Skip to content

Commit b0dacb1

Browse files
authored
New hash algorithm (#1920)
* feat: use base-62 full-width hash for atomic class names Replace the base-36, 4-char-truncated atomic class name hash with a base-62 encoding of the full 32-bit MurmurHash2 value. - hashBase62(): new encoder sharing the murmur2 core with hash(); fixed-width, zero-padded, byte-identical to atlaspack's to_base62 - atomicify-rules: group hash 6 chars, value hash 4 chars (11-char classes) - ax(): extract group key via className.length - 4 (fast fixed-offset slice); old (9-char) and new (11-char) classes are length-disjoint so they never falsely deduplicate during migration - unit tests incl. an atlaspack cross-implementation parity guard Eliminates the ~93K effective hash space and leading-character bias that caused class name collisions and silent style drops in large apps. test: collapse multi-line ax() calls in transform helper Longer atomic class names (11 chars under the base-62 hash scheme) can push ax([...]) calls past prettier's default printWidth in the test formatter, causing them to wrap onto multiple lines. This wrapping is purely a cosmetic artifact of the test helper — the real emitted code is single-line. Collapse multi-line ax([...]) calls back to a single line after formatting so generated-code assertions stay stable regardless of class-name length. test(keyframes): update fixtures for base-62 class names test(css-prop): update fixtures for base-62 class names test(styled): update fixtures for base-62 class names test(css-map): update fixtures for base-62 class names test(class-names, xcss-prop): update fixtures for base-62 class names fix(ac, compress): update group hash length for base-62 6-char groups ac() and compress-class-names-for-runtime.ts hardcoded the atomic group hash length as 4 chars (5 with the leading underscore). With the new base-62 hash, the group is 6 chars (7 with the leading underscore). - ac.ts: import ATOMIC_GROUP_HASH_LENGTH from @compiled/utils instead of hardcoding 5; update isCompressed check from charCodeAt(5) to charCodeAt(ATOMIC_GROUP_LENGTH) - compress-class-names-for-runtime.ts: import ATOMIC_GROUP_HASH_LENGTH and use it in slice(1, ATOMIC_GROUP_HASH_LENGTH + 1) instead of hardcoded slice(1, 5) - ac.test.ts: update synthetic test data from 4-char (_aaaa) to 6-char (_aaaaaa) group patterns to match new format test(babel-plugin): update compress and hash-prefix fixtures for base-62 test(babel-plugin): update remaining __tests__ fixtures for base-62 class names test(strip-runtime, vite-plugin, react, css): update fixtures for base-62 class names fix(ac): define ATOMIC_GROUP_HASH_LENGTH locally to avoid @compiled/utils runtime dependency test(react, vite-plugin): update fixtures for base-62 class names * feat: add collisionResistantHash option (default false) — dual-mechanism migration flag - Thread collisionResistantHash through babel-plugin types → transform.ts → atomicify-rules.ts - atomicClassName branches: false = legacy base-36 9-char (unchanged default), true = base-62 11-char - Default to collisionResistantHash:true in test helpers (babel-plugin test-utils, strip-runtime transform.ts, root babel.config.json, css/vite-plugin test helpers) so fixtures document the new output format while shipped default remains legacy - Add legacy regression suite to atomicify-rules.test.ts proving default=false emits exact 9-char base-36 names unchanged - Add collision-resistance test to hash.test.ts proving base-62 eliminates collisions - Remove atlaspack cross-impl parity assertions (not required for correctness) - Remove inaccurate '~93K effective hash space' claim (actual bias is more complex) - Downgrade changeset from major to minor (additive opt-in, no breaking change) * test(atomicify-rules): add real-world collision regression tests Documents a confirmed collision pair (scrollbar-width vs text-anchor, group _1fjg) found in large production CSS bundles. Tests assert: 1. Legacy hash DOES produce group collisions on real CSS properties (the confirmed bug) 2. Base-62 6-char hash eliminates those collisions (the fix) * test(ax, atomicify-rules): add parity tests and improve variable naming - ax: add legacy/new format dedup parity tests and cross-format no-dedup test to document correct behaviour during version-skew window. CLEANUP comments mark legacy-specific tests for removal when collisionResistantHash defaults to true. - atomicify-rules: rename cr -> collisionResistant, css -> cssDeclaration for clarity. Remove redundant third collision test case. * fix(ac, compress): derive atomic group length dynamically for legacy + new hash backward compat - ac() now locates the compression separator via indexOf and derives the uncompressed group via length - value hash, handling both the legacy 4-char group (9-char class) and the collision-resistant 6-char group (11-char class) - compress-class-names-for-runtime derives group length from the class instead of hardcoding it, keeping legacy class-name compression backward compatible - add legacy-format ac() cases and a dedicated compress helper unit test - remove migration-artifact comment; tighten vite extraction regex * test(react): migrate ax/style/perf fixtures to real base-62 class names * feat(babel-plugin, css): require @compiled/react >=1.0.0 as peer floor for new hash * docs: document collisionResistantHash option and migration guide
1 parent 71cb9b1 commit b0dacb1

49 files changed

Lines changed: 1509 additions & 978 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/new-hash-algorithm.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
'@compiled/babel-plugin': major
3+
'@compiled/css': major
4+
'@compiled/utils': minor
5+
---
6+
7+
Add an opt-in `collisionResistantHash` option that generates atomic class names using a base-62,
8+
full-width hash to eliminate hash collisions. **Default behaviour is unchanged** — you must opt in.
9+
10+
Atomic class names use a base-36 encoding truncated to 4 characters per hash segment
11+
(`_<group><value>`). This truncation has a severely constrained effective hash space due to leading-digit bias, and has a
12+
strong leading-character bias, causing class name collisions in large applications that can result
13+
in `ax()` silently dropping styles.
14+
15+
Setting `collisionResistantHash: true` (a babel plugin / transform option) switches to a base-62
16+
encoding of the full 32-bit MurmurHash2 value:
17+
18+
- **Group hash**: 6 characters (base-62 covers the full 32-bit space with no truncation)
19+
- **Value hash**: 4 characters (fixed width)
20+
- Atomic class names change from 9 characters (`_1e0c1ule`) to 11 characters (`_3iDTPbvLZJ`)
21+
22+
The option is a **migration flag**. It defaults to `false`, so the generated CSS is unchanged by
23+
default — existing output is byte-for-byte identical. Products can enable it incrementally (for
24+
example via an environment variable or feature gate in their build config), roll back instantly by
25+
turning it off and rebuilding, and a future major release will flip the default to `true` and remove
26+
the legacy branch.
27+
28+
**Breaking:** `@compiled/babel-plugin` and `@compiled/css` now declare `@compiled/react` `>=1.0.0`
29+
as a peer dependency. Because these packages can emit the new 11-character atomic class names, the
30+
consuming app must run a runtime whose `ax()` can parse them (older runtimes use a fixed slice
31+
offset and corrupt deduplication of 11-character classes). Declaring the floor makes this
32+
install-time enforced: adopting a plugin version capable of the new hash forces the consumer onto
33+
`@compiled/react@>=1.0.0`, preventing a new-hash-output / old-runtime mismatch. This is the primary
34+
guardrail for consumers outside AFM (inside AFM the floor is additionally guaranteed by the root
35+
`resolutions` + `alignedDependencies` pin).
36+
37+
Mixing legacy 9-character and new 11-character class names on a page is safe: the `>=1.0.0`
38+
runtime's `ax()` extracts the group key with `className.slice(0, className.length - 4)`, so the two
39+
formats produce different-length group keys, are structurally disjoint, and never falsely
40+
deduplicate each other (whether during the migration window or between pre-built dependency CSS and
41+
freshly compiled app CSS). This forward-compatible `ax()` behaviour already shipped in
42+
`@compiled/react@1.0.0` — which is exactly why it is the peer-dependency floor.
43+
44+
The new `hashBase62` encoding is byte-for-byte compatible with the atlaspack SWC transformer's
45+
`to_base62`, ensuring class names are identical across the babel plugin and SWC toolchains.

babel.config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"nonce": "\"k0Mp1lEd\"",
2121
"importReact": false,
2222
"optimizeCss": false,
23+
"collisionResistantHash": true,
2324
"importSources": [
2425
"./packages/react/src/create-strict-api/__tests__/__fixtures__/strict-api",
2526
"./packages/react/src/create-strict-api/__tests__/__fixtures__/strict-api-recursive",

packages/babel-plugin-strip-runtime/src/__tests__/extract-styles.test.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
4747
/*#__PURE__*/ React.createElement(
4848
'div',
4949
{
50-
className: ax(['_1wyb1fwx _syaz13q2']),
50+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
5151
},
5252
'hello world'
5353
);
@@ -56,7 +56,7 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
5656

5757
expect(writeFileSync).toBeCalledWith(
5858
expect.stringContaining('app.compiled.css'),
59-
'._1wyb1fwx{font-size:12px}\n._syaz13q2{color:blue}'
59+
'._1UtDYzynoA{color:blue}\n._4ya3eErjyG{font-size:12px}'
6060
);
6161
});
6262

@@ -108,15 +108,15 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
108108
/*#__PURE__*/ React.createElement(
109109
'div',
110110
{
111-
className: ax(['_1wyb1fwx _syaz13q2']),
111+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
112112
},
113113
'hello world 2'
114114
);
115115
const Component2 = () =>
116116
/*#__PURE__*/ React.createElement(
117117
'div',
118118
{
119-
className: ax(['_1wyb1fwx _syaz32ev']),
119+
className: ax(['_4ya3eErjyG _1UtDYzy8mA']),
120120
},
121121
'hello world 2'
122122
);
@@ -156,8 +156,8 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
156156
import { ax, ix } from '@compiled/react/runtime';
157157
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
158158
const styles = {
159-
panel: '_ca0qftgi _u5f3ftgi _n3tdftgi _19bvftgi _syaz13q2',
160-
danger: '_syaz5scu',
159+
panel: '_0Of8r2Jg58 _1ZnuxbJg58 _1wydGWJg58 _2Zuz6QJg58 _1UtDYzynoA',
160+
danger: '_1UtDYzGowl',
161161
};
162162
const Component = ({ isDanger }) =>
163163
/*#__PURE__*/ _jsx('div', {
@@ -168,12 +168,12 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
168168

169169
// CSS output: atomic rules lexically sorted in the compiled.css file
170170
expect(getExtractedCss()).toMatchInlineSnapshot(`
171-
"._19bvftgi{padding-left:8px}
172-
._ca0qftgi{padding-top:8px}
173-
._n3tdftgi{padding-bottom:8px}
174-
._syaz13q2{color:blue}
175-
._syaz5scu{color:red}
176-
._u5f3ftgi{padding-right:8px}"
171+
"._0Of8r2Jg58{padding-top:8px}
172+
._1UtDYzGowl{color:red}
173+
._1UtDYzynoA{color:blue}
174+
._1ZnuxbJg58{padding-right:8px}
175+
._1wydGWJg58{padding-bottom:8px}
176+
._2Zuz6QJg58{padding-left:8px}"
177177
`);
178178
});
179179

@@ -208,7 +208,7 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
208208
import { ax, ix } from '@compiled/react/runtime';
209209
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
210210
const atomicStyles = {
211-
base: '_syaz13q2',
211+
base: '_1UtDYzynoA',
212212
};
213213
const scopedStyles = {
214214
panel: 'cc-1m0qvev',
@@ -346,12 +346,12 @@ describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesTo
346346
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
347347
const Component = () =>
348348
/*#__PURE__*/ _jsx('div', {
349-
className: ax(['_1wyb1fwx _syaz13q2']),
349+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
350350
children: 'hello world 2',
351351
});
352352
const Component2 = () =>
353353
/*#__PURE__*/ _jsx('div', {
354-
className: ax(['_1wyb1fwx _syaz32ev']),
354+
className: ax(['_4ya3eErjyG _1UtDYzy8mA']),
355355
children: 'hello world 2',
356356
});
357357
"

packages/babel-plugin-strip-runtime/src/__tests__/strip-runtime-source-code.test.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
3333
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
3434
const Component = () =>
3535
/*#__PURE__*/ _jsx('div', {
36-
className: ax(['_1wyb1fwx _syaz13q2']),
36+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
3737
children: 'hello world',
3838
});
3939
"
@@ -48,8 +48,8 @@ describe('babel-plugin-strip-runtime using source code', () => {
4848
});
4949

5050
expect(actual.match(regexToFindRequireStatements)).toEqual([
51-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
52-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
51+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
52+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
5353
]);
5454
});
5555

@@ -75,7 +75,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
7575
const metadata = actual?.metadata as BabelFileMetadata;
7676

7777
expect(metadata).toEqual({
78-
styleRules: ['._1wyb1fwx{font-size:12px}', '._syaz13q2{color:blue}'],
78+
styleRules: ['._4ya3eErjyG{font-size:12px}', '._1UtDYzynoA{color:blue}'],
7979
});
8080
});
8181
});
@@ -94,7 +94,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
9494
/*#__PURE__*/ React.createElement(
9595
'div',
9696
{
97-
className: ax(['_1wyb1fwx _syaz13q2']),
97+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
9898
},
9999
'hello world'
100100
);
@@ -110,8 +110,8 @@ describe('babel-plugin-strip-runtime using source code', () => {
110110
});
111111

112112
expect(actual.match(regexToFindRequireStatements)).toEqual([
113-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
114-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
113+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
114+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
115115
]);
116116
});
117117

@@ -137,7 +137,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
137137
const metadata = actual?.metadata as BabelFileMetadata;
138138

139139
expect(metadata).toEqual({
140-
styleRules: ['._1wyb1fwx{font-size:12px}', '._syaz13q2{color:blue}'],
140+
styleRules: ['._4ya3eErjyG{font-size:12px}', '._1UtDYzynoA{color:blue}'],
141141
});
142142
});
143143
});
@@ -157,7 +157,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
157157
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
158158
const Component = () =>
159159
/*#__PURE__*/ _jsx('div', {
160-
className: ax(['_1wyb1fwx _syaz13q2']),
160+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
161161
children: 'hello world',
162162
});
163163
"
@@ -173,8 +173,8 @@ describe('babel-plugin-strip-runtime using source code', () => {
173173
});
174174

175175
expect(actual.match(regexToFindRequireStatements)).toEqual([
176-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
177-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
176+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
177+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
178178
]);
179179
});
180180

@@ -202,7 +202,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
202202
const metadata = actual?.metadata as BabelFileMetadata;
203203

204204
expect(metadata).toEqual({
205-
styleRules: ['._1wyb1fwx{font-size:12px}', '._syaz13q2{color:blue}'],
205+
styleRules: ['._4ya3eErjyG{font-size:12px}', '._1UtDYzynoA{color:blue}'],
206206
});
207207
});
208208
});
@@ -222,7 +222,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
222222
/*#__PURE__*/ React.createElement(
223223
'div',
224224
{
225-
className: ax(['_1wyb1fwx _syaz13q2']),
225+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
226226
},
227227
'hello world'
228228
);
@@ -239,8 +239,8 @@ describe('babel-plugin-strip-runtime using source code', () => {
239239
});
240240

241241
expect(actual.match(regexToFindRequireStatements)).toEqual([
242-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
243-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
242+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
243+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
244244
]);
245245
});
246246

@@ -268,7 +268,7 @@ describe('babel-plugin-strip-runtime using source code', () => {
268268
const metadata = actual?.metadata as BabelFileMetadata;
269269

270270
expect(metadata).toEqual({
271-
styleRules: ['._1wyb1fwx{font-size:12px}', '._syaz13q2{color:blue}'],
271+
styleRules: ['._4ya3eErjyG{font-size:12px}', '._1UtDYzynoA{color:blue}'],
272272
});
273273
});
274274
});

packages/babel-plugin-strip-runtime/src/__tests__/strip-runtime-transpiled-code.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const transform = (
2828
babelrc: false,
2929
configFile: false,
3030
filename,
31-
plugins: [[compiledBabelPlugin, { optimizeCss: false }]],
31+
plugins: [[compiledBabelPlugin, { optimizeCss: false, collisionResistantHash: true }]],
3232
presets: [
3333
['@babel/preset-env', { targets: { esmodules: true }, modules: modules ?? 'auto' }],
3434
'@babel/preset-typescript',
@@ -76,8 +76,8 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
7676
const actual = transform(code, { styleSheetPath: testStyleSheetPath, runtime });
7777

7878
expect(actual.match(regexToFindRequireStatements)).toEqual([
79-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
80-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
79+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
80+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
8181
]);
8282
});
8383

@@ -97,7 +97,7 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
9797
expect(actual.split('var Component = ')[1]).toMatchInlineSnapshot(`
9898
"() =>
9999
/*#__PURE__*/ (0, _jsxRuntime.jsx)('div', {
100-
className: (0, _runtime.ax)(['_1wyb1fwx _syaz13q2']),
100+
className: (0, _runtime.ax)(['_4ya3eErjyG _1UtDYzynoA']),
101101
children: 'hello world',
102102
});
103103
"
@@ -114,7 +114,7 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
114114
import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
115115
var Component = () =>
116116
/*#__PURE__*/ _jsx('div', {
117-
className: ax(['_1wyb1fwx _syaz13q2']),
117+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
118118
children: 'hello world',
119119
});
120120
"
@@ -129,8 +129,8 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
129129
const actual = transform(code, { styleSheetPath: testStyleSheetPath, runtime });
130130

131131
expect(actual.match(regexToFindRequireStatements)).toEqual([
132-
`require('${testStyleSheetPath}?style=._1wyb1fwx%7Bfont-size%3A12px%7D');`,
133-
`require('${testStyleSheetPath}?style=._syaz13q2%7Bcolor%3Ablue%7D');`,
132+
`require('${testStyleSheetPath}?style=._4ya3eErjyG%7Bfont-size%3A12px%7D');`,
133+
`require('${testStyleSheetPath}?style=._1UtDYzynoA%7Bcolor%3Ablue%7D');`,
134134
]);
135135
});
136136

@@ -152,7 +152,7 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
152152
/*#__PURE__*/ React.createElement(
153153
'div',
154154
{
155-
className: (0, _runtime.ax)(['_1wyb1fwx _syaz13q2']),
155+
className: (0, _runtime.ax)(['_4ya3eErjyG _1UtDYzynoA']),
156156
},
157157
'hello world'
158158
);
@@ -171,7 +171,7 @@ describe('babel-plugin-strip-runtime using transpiled code', () => {
171171
/*#__PURE__*/ React.createElement(
172172
'div',
173173
{
174-
className: ax(['_1wyb1fwx _syaz13q2']),
174+
className: ax(['_4ya3eErjyG _1UtDYzynoA']),
175175
},
176176
'hello world'
177177
);

packages/babel-plugin-strip-runtime/src/__tests__/transform.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,18 @@ export const transformSync = (code: string, opts: TransformOptions): BabelFileRe
2929
},
3030
plugins: [
3131
...(bake
32-
? [[compiledBabelPlugin, { importReact: runtime === 'classic', optimizeCss: false }]]
32+
? [
33+
[
34+
compiledBabelPlugin,
35+
{
36+
importReact: runtime === 'classic',
37+
optimizeCss: false,
38+
// Tests assert the collision-resistant (base-62, 11-char) output.
39+
// Shipped default is legacy 9-char — see atomicify-rules legacy suite.
40+
collisionResistantHash: true,
41+
},
42+
],
43+
]
3344
: []),
3445
...(extract
3546
? [

packages/babel-plugin/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@
4343
"prettier": "^2.8.8",
4444
"ts-node": "^10.9.2",
4545
"tsconfig-paths": "^4.1.2"
46+
},
47+
"peerDependencies": {
48+
"@compiled/react": ">=1.0.0"
4649
}
4750
}

packages/babel-plugin/src/__tests__/css-builder.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('css builder', () => {
109109
<div css={{ '@media screen': { color: 'red', fontSize: 20 } }} />
110110
`);
111111

112-
expect(actual).toInclude('@media screen{._43475scu{color:red}._1yzygktf{font-size:20px}}');
112+
expect(actual).toInclude('@media screen{._0gIO46Gowl{color:red}._4Gx609SPN1{font-size:20px}}');
113113
});
114114

115115
it('generates the correct style prop for shadowed runtime identifiers', () => {
@@ -131,15 +131,15 @@ describe('css builder', () => {
131131
expect(actual).toMatchInlineSnapshot(`
132132
"import * as React from "react";
133133
import { ax, ix, CC, CS } from "@compiled/react/runtime";
134-
const _2 = "._syaz1aj3{color:var(--_1ylxx6h)}";
135-
const _ = "._bfhk8ruw{background-color:var(--_agotg1)}";
134+
const _2 = "._1UtDYzpjc8{color:var(--_1ylxx6h)}";
135+
const _ = "._0KLXruU0IR{background-color:var(--_agotg1)}";
136136
const getBackgroundColor = (color) => color;
137137
const color = baseColor;
138138
<CC>
139139
<CS>{[_, _2]}</CS>
140140
{
141141
<div
142-
className={ax(["_bfhk8ruw _syaz1aj3"])}
142+
className={ax(["_0KLXruU0IR _1UtDYzpjc8"])}
143143
style={{
144144
"--_agotg1": ix(getBackgroundColor(customBackgroundColor)),
145145
"--_1ylxx6h": ix(color),

0 commit comments

Comments
 (0)