Skip to content

Commit 96d2d6f

Browse files
committed
feat: support non identifier classnames
1 parent 44c1dbf commit 96d2d6f

19 files changed

Lines changed: 457 additions & 205 deletions
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// @ts-nocheck
22
function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;
33
declare const styles = {
4-
a_1: '' as readonly string,
5-
a_2: '' as readonly string,
6-
a_2: '' as readonly string,
7-
a_3: '' as readonly string,
8-
a_4: '' as readonly string,
4+
'a_1': '' as readonly string,
5+
'a_2': '' as readonly string,
6+
'a_2': '' as readonly string,
7+
'a_3': '' as readonly string,
8+
'a_4': '' as readonly string,
9+
'a-1': '' as readonly string,
910
...blockErrorType((await import('./b.module.css')).default),
10-
c_1: (await import('./c.module.css')).default.c_1,
11-
c_alias: (await import('./c.module.css')).default.c_2,
11+
'c_1': (await import('./c.module.css')).default['c_1'],
12+
'c_alias': (await import('./c.module.css')).default['c_2'],
1213
};
1314
export default styles;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-nocheck
22
declare const styles = {
3-
b_1: '' as readonly string,
4-
b_2: '' as readonly string,
3+
'b_1': '' as readonly string,
4+
'b_2': '' as readonly string,
55
};
66
export default styles;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-nocheck
22
declare const styles = {
3-
c_1: '' as readonly string,
4-
c_2: '' as readonly string,
3+
'c_1': '' as readonly string,
4+
'c_2': '' as readonly string,
55
};
66
export default styles;

examples/1-basic/src/a.module.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@
77
100% { transform: translateY(-100%); }
88
}
99

10+
.a-1 {color: red;}
11+
1012
@import './b.module.css';
1113
@value c_1, c_2 as c_alias from './c.module.css';

examples/1-basic/src/a.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ styles.b_1;
88
styles.b_2;
99
styles.c_1;
1010
styles.c_alias;
11+
styles['a-1'];
1112
styles.unknown; // Expected TS2339 error
1213

1314
const jsx = (

packages/codegen/e2e-test/index.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ test('generates .d.ts', async () => {
4848
"// @ts-nocheck
4949
function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;
5050
declare const styles = {
51-
a1: '' as readonly string,
51+
'a1': '' as readonly string,
5252
...blockErrorType((await import('./b.module.css')).default),
5353
...blockErrorType((await import('./unmatched.module.css')).default),
5454
};
@@ -58,15 +58,15 @@ test('generates .d.ts', async () => {
5858
expect(await iff.readFile('generated/src/b.module.css.d.ts')).toMatchInlineSnapshot(`
5959
"// @ts-nocheck
6060
declare const styles = {
61-
b1: '' as readonly string,
61+
'b1': '' as readonly string,
6262
};
6363
export default styles;
6464
"
6565
`);
6666
expect(await iff.readFile('generated/src/c.module.css.d.ts')).toMatchInlineSnapshot(`
6767
"// @ts-nocheck
6868
declare const styles = {
69-
c1: '' as readonly string,
69+
'c1': '' as readonly string,
7070
};
7171
export default styles;
7272
"
@@ -158,7 +158,7 @@ test('generates .d.ts with circular import', async () => {
158158
"// @ts-nocheck
159159
function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;
160160
declare const styles = {
161-
a1: '' as readonly string,
161+
'a1': '' as readonly string,
162162
...blockErrorType((await import('./b.module.css')).default),
163163
};
164164
export default styles;
@@ -168,7 +168,7 @@ test('generates .d.ts with circular import', async () => {
168168
"// @ts-nocheck
169169
function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;
170170
declare const styles = {
171-
b1: '' as readonly string,
171+
'b1': '' as readonly string,
172172
...blockErrorType((await import('./a.module.css')).default),
173173
};
174174
export default styles;
@@ -178,7 +178,7 @@ test('generates .d.ts with circular import', async () => {
178178
"// @ts-nocheck
179179
function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;
180180
declare const styles = {
181-
c1: '' as readonly string,
181+
'c1': '' as readonly string,
182182
...blockErrorType((await import('./c.module.css')).default),
183183
};
184184
export default styles;

packages/codegen/src/project.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ describe('updateFile', () => {
197197
expect(await iff.readFile('generated/src/a.module.css.d.ts')).toMatchInlineSnapshot(`
198198
"// @ts-nocheck
199199
declare const styles = {
200-
a_1: '' as readonly string,
200+
'a_1': '' as readonly string,
201201
};
202202
export default styles;
203203
"
@@ -537,15 +537,15 @@ describe('emitDtsFiles', () => {
537537
expect(await iff.readFile('generated/src/a.module.css.d.ts')).toMatchInlineSnapshot(`
538538
"// @ts-nocheck
539539
declare const styles = {
540-
a1: '' as readonly string,
540+
'a1': '' as readonly string,
541541
};
542542
export default styles;
543543
"
544544
`);
545545
expect(await iff.readFile('generated/src/b.module.css.d.ts')).toMatchInlineSnapshot(`
546546
"// @ts-nocheck
547547
declare const styles = {
548-
b1: '' as readonly string,
548+
'b1': '' as readonly string,
549549
};
550550
export default styles;
551551
"
@@ -562,7 +562,7 @@ describe('emitDtsFiles', () => {
562562
expect(await iff.readFile('generated/src/a.module.css.d.ts')).toMatchInlineSnapshot(`
563563
"// @ts-nocheck
564564
declare const styles = {
565-
a1: '' as readonly string,
565+
'a1': '' as readonly string,
566566
};
567567
export default styles;
568568
"

packages/codegen/src/runner.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ describe('runCMK', () => {
3030
expect(await iff.readFile('generated/src/a.module.css.d.ts')).toMatchInlineSnapshot(`
3131
"// @ts-nocheck
3232
declare const styles = {
33-
a_1: '' as readonly string,
33+
'a_1': '' as readonly string,
3434
};
3535
export default styles;
3636
"
3737
`);
3838
expect(await iff.readFile('generated/src/b.module.css.d.ts')).toMatchInlineSnapshot(`
3939
"// @ts-nocheck
4040
declare const styles = {
41-
b_1: '' as readonly string,
41+
'b_1': '' as readonly string,
4242
};
4343
export default styles;
4444
"
@@ -133,15 +133,15 @@ describe('runCMKInWatchMode', () => {
133133
expect(await iff.readFile('generated/src/a.module.css.d.ts')).toMatchInlineSnapshot(`
134134
"// @ts-nocheck
135135
declare const styles = {
136-
a_1: '' as readonly string,
136+
'a_1': '' as readonly string,
137137
};
138138
export default styles;
139139
"
140140
`);
141141
expect(await iff.readFile('generated/src/b.module.css.d.ts')).toMatchInlineSnapshot(`
142142
"// @ts-nocheck
143143
declare const styles = {
144-
b_1: '' as readonly string,
144+
'b_1': '' as readonly string,
145145
};
146146
export default styles;
147147
"

packages/core/src/checker.test.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function prepareChecker(args?: Partial<CheckerArgs>): Checker {
3636
}
3737

3838
describe('checkCSSModule', () => {
39-
test('report diagnostics for invalid name as js identifier', async () => {
39+
test('do not report diagnostics for invalid name as js identifier when namedExports is false', async () => {
4040
const iff = await createIFF({
4141
'a.module.css': dedent`
4242
.a-1 { color: red; }
@@ -47,7 +47,22 @@ describe('checkCSSModule', () => {
4747
@value b-2: red;
4848
`,
4949
});
50-
const check = prepareChecker();
50+
const check = prepareChecker({ config: fakeConfig({ namedExports: false }) });
51+
const diagnostics = check(readAndParseCSSModule(iff.paths['a.module.css'])!);
52+
expect(diagnostics).toEqual([]);
53+
});
54+
test('report diagnostics for invalid name as js identifier when namedExports is true', async () => {
55+
const iff = await createIFF({
56+
'a.module.css': dedent`
57+
.a-1 { color: red; }
58+
@value b-1, b-2 as a-2 from './b.module.css';
59+
`,
60+
'b.module.css': dedent`
61+
@value b-1: red;
62+
@value b-2: red;
63+
`,
64+
});
65+
const check = prepareChecker({ config: fakeConfig({ namedExports: true }) });
5166
const diagnostics = check(readAndParseCSSModule(iff.paths['a.module.css'])!);
5267
expect(formatDiagnostics(diagnostics, iff.rootDir)).toMatchInlineSnapshot(`
5368
[
@@ -59,7 +74,7 @@ describe('checkCSSModule', () => {
5974
"column": 2,
6075
"line": 1,
6176
},
62-
"text": "css-modules-kit does not support invalid names as JavaScript identifiers.",
77+
"text": "css-modules-kit does not support invalid names as JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
6378
},
6479
{
6580
"category": "error",
@@ -69,7 +84,7 @@ describe('checkCSSModule', () => {
6984
"column": 8,
7085
"line": 2,
7186
},
72-
"text": "css-modules-kit does not support invalid names as JavaScript identifiers.",
87+
"text": "css-modules-kit does not support invalid names as JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
7388
},
7489
{
7590
"category": "error",
@@ -79,7 +94,7 @@ describe('checkCSSModule', () => {
7994
"column": 13,
8095
"line": 2,
8196
},
82-
"text": "css-modules-kit does not support invalid names as JavaScript identifiers.",
97+
"text": "css-modules-kit does not support invalid names as JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
8398
},
8499
{
85100
"category": "error",
@@ -89,7 +104,7 @@ describe('checkCSSModule', () => {
89104
"column": 20,
90105
"line": 2,
91106
},
92-
"text": "css-modules-kit does not support invalid names as JavaScript identifiers.",
107+
"text": "css-modules-kit does not support invalid names as JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
93108
},
94109
]
95110
`);

packages/core/src/checker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function checkCSSModule(cssModule: CSSModule, args: CheckerArgs): Diagnos
2626

2727
for (const token of cssModule.localTokens) {
2828
// Reject special names as they may break .d.ts files
29-
if (!isValidAsJSIdentifier(token.name)) {
29+
if (config.namedExports && !isValidAsJSIdentifier(token.name)) {
3030
diagnostics.push(createInvalidNameAsJSIdentifiersDiagnostic(cssModule, token.loc));
3131
}
3232
if (token.name === '__proto__') {
@@ -54,10 +54,10 @@ export function checkCSSModule(cssModule: CSSModule, args: CheckerArgs): Diagnos
5454
if (!exportRecord.allTokens.includes(value.name)) {
5555
diagnostics.push(createModuleHasNoExportedTokenDiagnostic(cssModule, tokenImporter, value));
5656
}
57-
if (!isValidAsJSIdentifier(value.name)) {
57+
if (config.namedExports && !isValidAsJSIdentifier(value.name)) {
5858
diagnostics.push(createInvalidNameAsJSIdentifiersDiagnostic(cssModule, value.loc));
5959
}
60-
if (value.localName && !isValidAsJSIdentifier(value.localName)) {
60+
if (value.localName && config.namedExports && !isValidAsJSIdentifier(value.localName)) {
6161
diagnostics.push(createInvalidNameAsJSIdentifiersDiagnostic(cssModule, value.localLoc!));
6262
}
6363
if (value.name === '__proto__') {
@@ -106,7 +106,7 @@ function createModuleHasNoExportedTokenDiagnostic(
106106

107107
function createInvalidNameAsJSIdentifiersDiagnostic(cssModule: CSSModule, loc: Location): Diagnostic {
108108
return {
109-
text: `css-modules-kit does not support invalid names as JavaScript identifiers.`,
109+
text: `css-modules-kit does not support invalid names as JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.`,
110110
category: 'error',
111111
file: { fileName: cssModule.fileName, text: cssModule.text },
112112
start: { line: loc.start.line, column: loc.start.column },

0 commit comments

Comments
 (0)