Skip to content

Commit

Permalink
fix: Maintain nesting order of pseudo elements vs pseudo classes (#740)
Browse files Browse the repository at this point in the history
  • Loading branch information
nmn authored Oct 10, 2024
1 parent ed0c7fe commit 41fa0fa
Show file tree
Hide file tree
Showing 3 changed files with 347 additions and 1 deletion.
133 changes: 133 additions & 0 deletions packages/babel-plugin/__tests__/stylex-transform-create-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,139 @@ describe('@stylexjs/babel-plugin', () => {
_inject2(".x1en94km::-webkit-slider-thumb, .x1en94km::-moz-range-thumb, .x1en94km::-ms-thumb{width:16px}", 9000);"
`);
});

test('transforms pseudo class within a pseudo element', () => {
expect(
transform(`
import stylex from 'stylex';
export const styles = stylex.create({
foo: {
'::before': {
color: {
default: 'red',
':hover': 'blue',
}
},
},
});
`),
).toMatchInlineSnapshot(`
"import _inject from "@stylexjs/stylex/lib/stylex-inject";
var _inject2 = _inject;
import stylex from 'stylex';
_inject2(".x16oeupf::before{color:red}", 8000);
_inject2(".xeb2lg0::before:hover{color:blue}", 8130);
export const styles = {
foo: {
"::before_color": "x16oeupf xeb2lg0",
$$css: true
}
};"
`);
});

test('transforms legacy pseudo class within a pseudo element', () => {
expect(
transform(`
import stylex from 'stylex';
export const styles = stylex.create({
foo: {
'::before': {
color: 'red',
':hover': {
color: 'blue',
},
},
},
});
`),
).toMatchInlineSnapshot(`
"import _inject from "@stylexjs/stylex/lib/stylex-inject";
var _inject2 = _inject;
import stylex from 'stylex';
_inject2(".x16oeupf::before{color:red}", 8000);
_inject2(".xeb2lg0::before:hover{color:blue}", 8130);
export const styles = {
foo: {
"::before_color": "x16oeupf",
"::before_:hover_color": "xeb2lg0",
$$css: true
}
};"
`);
});

test('transforms pseudo elements within legeacy pseudo class', () => {
expect(
transform(`
import stylex from 'stylex';
export const styles = stylex.create({
foo: {
'::before': {
color: 'red',
},
':hover': {
'::before': {
color: 'blue',
},
},
},
});
`),
).toMatchInlineSnapshot(`
"import _inject from "@stylexjs/stylex/lib/stylex-inject";
var _inject2 = _inject;
import stylex from 'stylex';
_inject2(".x16oeupf::before{color:red}", 8000);
_inject2(".xeb2lg0:hover::before{color:blue}", 8130);
export const styles = {
foo: {
"::before_color": "x16oeupf",
":hover_::before_color": "xeb2lg0",
$$css: true
}
};"
`);
});

test('transforms pseudo elements sandwiched within pseudo classes', () => {
expect(
transform(`
import stylex from 'stylex';
export const styles = stylex.create({
foo: {
'::before': {
color: 'red',
},
':hover': {
'::before': {
color: {
default: 'blue',
':hover': 'green',
':active': 'purple',
},
},
},
},
});
`),
).toMatchInlineSnapshot(`
"import _inject from "@stylexjs/stylex/lib/stylex-inject";
var _inject2 = _inject;
import stylex from 'stylex';
_inject2(".x16oeupf::before{color:red}", 8000);
_inject2(".xeb2lg0:hover::before{color:blue}", 8130);
_inject2(".x18ezmze:hover::before:hover{color:green}", 8260);
_inject2(".xnj3kot:hover::before:active{color:purple}", 8300);
export const styles = {
foo: {
"::before_color": "x16oeupf",
":hover_::before_color": "xeb2lg0 x18ezmze xnj3kot",
$$css: true
}
};"
`);
});
});

describe('queries', () => {
Expand Down
179 changes: 179 additions & 0 deletions packages/shared/__tests__/stylex-create-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,185 @@ describe('stylex-create-test', () => {
`);
});

test('transforms nested pseudo-classes within pseudo elements', () => {
expect(
styleXCreate({
default: {
'::before': {
color: {
default: 'red',
':hover': 'blue',
},
},
},
}),
).toMatchInlineSnapshot(`
[
{
"default": {
"$$css": true,
"::before_color": "x16oeupf xeb2lg0",
},
},
{
"x16oeupf": {
"ltr": ".x16oeupf::before{color:red}",
"priority": 8000,
"rtl": null,
},
"xeb2lg0": {
"ltr": ".xeb2lg0::before:hover{color:blue}",
"priority": 8130,
"rtl": null,
},
},
{
"default": {
"x16oeupf": [
"::before",
"default",
"color",
],
"xeb2lg0": [
"::before",
":hover",
"color",
],
},
},
]
`);
});

test('transforms nested legacy pseudo-classes within pseudo elements', () => {
expect(
styleXCreate({
default: {
'::before': {
color: 'red',
':hover': {
color: 'blue',
},
},
},
}),
).toMatchInlineSnapshot(`
[
{
"default": {
"$$css": true,
"::before_:hover_color": "xeb2lg0",
"::before_color": "x16oeupf",
},
},
{
"x16oeupf": {
"ltr": ".x16oeupf::before{color:red}",
"priority": 8000,
"rtl": null,
},
"xeb2lg0": {
"ltr": ".xeb2lg0::before:hover{color:blue}",
"priority": 8130,
"rtl": null,
},
},
{
"default": {
"x16oeupf": [
"::before",
"color",
],
"xeb2lg0": [
"::before",
":hover",
"color",
],
},
},
]
`);
});

test('transforms nested pseudo-element within legacy pseudo class', () => {
expect(
styleXCreate({
default: {
'::before': {
color: 'blue',
},
':hover': {
'::before': {
color: {
default: 'red',
':hover': 'green',
':active': 'yellow',
},
},
},
},
}),
).toMatchInlineSnapshot(`
[
{
"default": {
"$$css": true,
"::before_color": "xvg9oe5",
":hover_::before_color": "x1qdmp1q x18ezmze x14o3fp0",
},
},
{
"x14o3fp0": {
"ltr": ".x14o3fp0:hover::before:active{color:yellow}",
"priority": 8300,
"rtl": null,
},
"x18ezmze": {
"ltr": ".x18ezmze:hover::before:hover{color:green}",
"priority": 8260,
"rtl": null,
},
"x1qdmp1q": {
"ltr": ".x1qdmp1q:hover::before{color:red}",
"priority": 8130,
"rtl": null,
},
"xvg9oe5": {
"ltr": ".xvg9oe5::before{color:blue}",
"priority": 8000,
"rtl": null,
},
},
{
"default": {
"x14o3fp0": [
":hover",
"::before",
":active",
"color",
],
"x18ezmze": [
":hover",
"::before",
":hover",
"color",
],
"x1qdmp1q": [
":hover",
"::before",
"default",
"color",
],
"xvg9oe5": [
"::before",
"color",
],
},
},
]
`);
});

// This API will not launch as an array, but internally we can continue to use arrays
test('transforms array values as fallbacks', () => {
expect(
Expand Down
36 changes: 35 additions & 1 deletion packages/shared/src/preprocess-rules/PreRule.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,38 @@ const stringComparator = (a: string, b: string): number => {
return a.localeCompare(b);
};

const sortPseudos = (
pseudos: $ReadOnlyArray<string>,
): $ReadOnlyArray<string> => {
if (pseudos.length < 2) {
return pseudos;
}

return pseudos
.reduce(
(acc, pseudo) => {
if (pseudo.startsWith('::')) {
return [...acc, pseudo];
}

const lastElement = acc[acc.length - 1];
const allButLast = acc.slice(0, acc.length - 1);
if (Array.isArray(lastElement)) {
return [...allButLast, [...lastElement, pseudo]];
} else {
return [...allButLast, lastElement, [pseudo]].filter(Boolean);
}
},
[] as $ReadOnlyArray<string | $ReadOnlyArray<string>>,
)
.flatMap((pseudo) => {
if (Array.isArray(pseudo)) {
return arraySort(pseudo, stringComparator);
}
return [pseudo];
});
};

export class PreRule implements IPreRule {
+property: string;
+value: string | number | $ReadOnlyArray<string | number>;
Expand All @@ -94,7 +126,9 @@ export class PreRule implements IPreRule {

get pseudos(): $ReadOnlyArray<string> {
const unsortedPseudos = this.keyPath.filter((key) => key.startsWith(':'));
return arraySort(unsortedPseudos, stringComparator);

return sortPseudos(unsortedPseudos);
// return arraySort(unsortedPseudos, stringComparator);
}

get atRules(): $ReadOnlyArray<string> {
Expand Down

0 comments on commit 41fa0fa

Please sign in to comment.