Skip to content

Commit

Permalink
fix(core): trim ">" selector (#435)
Browse files Browse the repository at this point in the history
* fix(core): trim ">" selector

* Change files
  • Loading branch information
layershifter authored Sep 20, 2023
1 parent eed56ee commit 480aba5
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "fix(core): trim \">\" selector",
"packageName": "@griffel/core",
"email": "[email protected]",
"dependentChangeType": "patch"
}
27 changes: 25 additions & 2 deletions packages/core/src/runtime/resolveStyleRules.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,29 @@ describe('resolveStyleRules', () => {
`);
});

it('trims ">" selectors to generate the same classes', () => {
const resultA = resolveStyleRules({ '> div': { color: 'blue' } });
const resultB = resolveStyleRules({ '>div': { color: 'blue' } });

expect(resultA[0]).toEqual(resultB[0]);
expect(resultA[0]).toMatchInlineSnapshot(`
Object {
"B9q554f": "f1plvi8r",
}
`);

expect(resultA).toMatchInlineSnapshot(`
.f1plvi8r > div {
color: blue;
}
`);
expect(resultB).toMatchInlineSnapshot(`
.f1plvi8r > div {
color: blue;
}
`);
});

it('hyphenates camelcased CSS properties', () => {
expect(
resolveStyleRules({
Expand Down Expand Up @@ -362,7 +385,7 @@ describe('resolveStyleRules', () => {
`);

expect(resolveStyleRules({ '> div': { color: 'green' } })).toMatchInlineSnapshot(`
.f18wx08q > div {
.f1fdorc0 > div {
color: green;
}
`);
Expand Down Expand Up @@ -392,7 +415,7 @@ describe('resolveStyleRules', () => {

it('handles complex nested selectors', () => {
expect(resolveStyleRules({ '& > :first-child': { '& svg': { color: 'red' } } })).toMatchInlineSnapshot(`
.fxfx2ih > :first-child svg {
.fkngkdt > :first-child svg {
color: red;
}
`);
Expand Down
17 changes: 11 additions & 6 deletions packages/core/src/runtime/resolveStyleRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { isObject } from './utils/isObject';
import { getStyleBucketName } from './getStyleBucketName';
import { hashClassName } from './utils/hashClassName';
import { hashPropertyKey } from './utils/hashPropertyKey';
import { trimSelector } from './utils/trimSelector';
import { warnAboutUnresolvedRule } from './warnings/warnAboutUnresolvedRule';
import { warnAboutUnsupportedProperties } from './warnings/warnAboutUnsupportedProperties';

Expand Down Expand Up @@ -92,15 +93,17 @@ export function resolveStyleRules(
}

if (typeof value === 'string' || typeof value === 'number') {
const selector = trimSelector(selectors.join(''));

// uniq key based on a hash of property & selector, used for merging later
const key = hashPropertyKey(selectors, container, media, support, property);
const key = hashPropertyKey(selector, container, media, support, property);
const className = hashClassName({
container,
media,
layer,
value: value.toString(),
support,
selectors,
selector,
property,
});

Expand All @@ -112,7 +115,7 @@ export function resolveStyleRules(
container,
value: rtlDefinition.value.toString(),
property: rtlDefinition.key,
selectors,
selector,
media,
layer,
support,
Expand Down Expand Up @@ -202,14 +205,16 @@ export function resolveStyleRules(
continue;
}

const key = hashPropertyKey(selectors, container, media, support, property);
const selector = trimSelector(selectors.join(''));

const key = hashPropertyKey(selector, container, media, support, property);
const className = hashClassName({
container,
media,
layer,
value: value.map(v => (v ?? '').toString()).join(';'),
support,
selectors,
selector,
property,
});

Expand All @@ -233,7 +238,7 @@ export function resolveStyleRules(
container,
value: rtlDefinitions.map(v => (v?.value ?? '').toString()).join(';'),
property: rtlDefinitions[0].key,
selectors,
selector,
layer,
media,
support,
Expand Down
16 changes: 12 additions & 4 deletions packages/core/src/runtime/utils/hashClassName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HASH_PREFIX } from '../../constants';
interface HashedClassNameParts {
property: string;
value: string;
selectors: string[];
selector: string;
media: string;
layer: string;
support: string;
Expand All @@ -16,12 +16,20 @@ export function hashClassName({
media,
layer,
property,
selectors,
selector,
support,
value,
}: HashedClassNameParts): string {
// Trimming of value is required to generate consistent hashes
const classNameHash = hashString(selectors.join('') + container + media + layer + support + property + value.trim());
const classNameHash = hashString(
selector +
container +
media +
layer +
support +
property +
// Trimming of value is required to generate consistent hashes
value.trim(),
);

return HASH_PREFIX + classNameHash;
}
8 changes: 4 additions & 4 deletions packages/core/src/runtime/utils/hashPropertyKey.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { hashPropertyKey } from './hashPropertyKey';

describe('hashPropertyKey', () => {
it('generates hashes that always start with letters', () => {
expect(hashPropertyKey([''], '', '', '', 'color')).toBe('sj55zd');
expect(hashPropertyKey([''], '', '', '', 'display')).toBe('mc9l5x');
expect(hashPropertyKey('', '', '', '', 'color')).toBe('sj55zd');
expect(hashPropertyKey('', '', '', '', 'display')).toBe('mc9l5x');

expect(hashPropertyKey([''], '', '', '', 'backgroundColor')).toBe('De3pzq');
expect(hashPropertyKey([':hover'], '', '', '', 'color')).toBe('Bi91k9c');
expect(hashPropertyKey('', '', '', '', 'backgroundColor')).toBe('De3pzq');
expect(hashPropertyKey(':hover', '', '', '', 'color')).toBe('Bi91k9c');
});
});
6 changes: 3 additions & 3 deletions packages/core/src/runtime/utils/hashPropertyKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import hash from '@emotion/hash';
import { PropertyHash } from '../../types';

export function hashPropertyKey(
selectors: string[],
selector: string,
container: string,
media: string,
support: string,
property: string,
): PropertyHash {
// uniq key based on property & selector, used for merging later
const computedKey = selectors.join('') + container + media + support + property;
const computedKey = selector + container + media + support + property;

// "key" can be really long as it includes selectors, we use hashes to reduce sizes of keys
// ".foo :hover" => "abcd"
Expand All @@ -25,7 +25,7 @@ export function hashPropertyKey(
const startsWithNumber = firstCharCode >= 48 && firstCharCode <= 57;

if (startsWithNumber) {
return String.fromCharCode(firstCharCode + 17) + hashedKey.substr(1);
return String.fromCharCode(firstCharCode + 17) + hashedKey.slice(1);
}

return hashedKey;
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/runtime/utils/trimSelector.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { trimSelector } from './trimSelector';

describe('trimSelector', () => {
it('trims ">"', () => {
expect(trimSelector('>.foo')).toBe('>.foo');
expect(trimSelector('> .foo')).toBe('>.foo');
expect(trimSelector('> .foo')).toBe('>.foo');

expect(trimSelector('> .foo > .bar')).toBe('>.foo >.bar');
});
});
6 changes: 6 additions & 0 deletions packages/core/src/runtime/utils/trimSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Trims selectors to generate consistent hashes.
*/
export function trimSelector(selector: string): string {
return selector.replace(/>\s+/g, '>');
}

0 comments on commit 480aba5

Please sign in to comment.