Skip to content

Commit 10543f1

Browse files
committed
feat(core, ts-plugin): support non-JavaScript identifier token in named export
1 parent 506782f commit 10543f1

13 files changed

Lines changed: 513 additions & 586 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@css-modules-kit/core': minor
3+
'@css-modules-kit/ts-plugin': minor
4+
---
5+
6+
feat(core, ts-plugin): support non-JavaScript identifier token in named export
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// @ts-nocheck
2-
export var a_1: string;
3-
export var a_2: string;
4-
export var a_2: string;
5-
export var a_3: string;
2+
var _token_0: string;
3+
export { _token_0 as 'a_1' };
4+
var _token_1: string;
5+
var _token_1: string;
6+
export { _token_1 as 'a_2' };
7+
var _token_2: string;
8+
export { _token_2 as 'a_3' };
69
export * from './b.module.css';
710
export {
8-
c_1,
9-
c_2 as c_alias,
11+
'c_1' as 'c_1',
12+
'c_2' as 'c_alias',
1013
} from './c.module.css';
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
// @ts-nocheck
2-
export var b_1: string;
2+
var _token_0: string;
3+
export { _token_0 as 'b_1' };
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
// @ts-nocheck
2-
export var c_1: string;
3-
export var c_2: string;
2+
var _token_0: string;
3+
export { _token_0 as 'c_1' };
4+
var _token_1: string;
5+
export { _token_1 as 'c_2' };

packages/core/src/checker.test.ts

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

3838
describe('checkCSSModule', () => {
39-
test('do not report diagnostics for invalid name as js identifier when namedExports is false', async () => {
40-
const iff = await createIFF({
41-
'a.module.css': dedent`
42-
.a-1 { color: red; }
43-
@value b-1, b-2 as a-2 from './b.module.css';
44-
`,
45-
'b.module.css': dedent`
46-
@value b-1: red;
47-
@value b-2: red;
48-
`,
49-
});
50-
const check = prepareChecker();
51-
const diagnostics = check(readAndParseCSSModule(iff.paths['a.module.css'])!);
52-
expect(formatDiagnostics(diagnostics, iff.rootDir)).toMatchInlineSnapshot(`[]`);
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 }) });
66-
const diagnostics = check(readAndParseCSSModule(iff.paths['a.module.css'])!);
67-
expect(formatDiagnostics(diagnostics, iff.rootDir)).toMatchInlineSnapshot(`
68-
[
69-
{
70-
"category": "error",
71-
"fileName": "<rootDir>/a.module.css",
72-
"length": 3,
73-
"start": {
74-
"column": 2,
75-
"line": 1,
76-
},
77-
"text": "Token names must be valid JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
78-
},
79-
{
80-
"category": "error",
81-
"fileName": "<rootDir>/a.module.css",
82-
"length": 3,
83-
"start": {
84-
"column": 8,
85-
"line": 2,
86-
},
87-
"text": "Token names must be valid JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
88-
},
89-
{
90-
"category": "error",
91-
"fileName": "<rootDir>/a.module.css",
92-
"length": 3,
93-
"start": {
94-
"column": 13,
95-
"line": 2,
96-
},
97-
"text": "Token names must be valid JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
98-
},
99-
{
100-
"category": "error",
101-
"fileName": "<rootDir>/a.module.css",
102-
"length": 3,
103-
"start": {
104-
"column": 20,
105-
"line": 2,
106-
},
107-
"text": "Token names must be valid JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.",
108-
},
109-
]
110-
`);
111-
});
11239
test('report diagnostics for "__proto__" name', async () => {
11340
const iff = await createIFF({
11441
'a.module.css': dedent`
@@ -205,7 +132,7 @@ describe('checkCSSModule', () => {
205132
]
206133
`);
207134
});
208-
test('report diagnostics for backslash in name when namedExports is false', async () => {
135+
test('report diagnostics for backslash in name', async () => {
209136
// NOTE: The backslash is valid syntax in class selectors, but it is invalid syntax in `@value`.
210137
// Therefore, it is sufficient for diagnostics to be reported only for class selectors.
211138
const iff = await createIFF({
@@ -225,7 +152,7 @@ describe('checkCSSModule', () => {
225152
"column": 2,
226153
"line": 1,
227154
},
228-
"text": "Backslash (\\) is not allowed in names when \`cmkOptions.namedExports\` is set to \`false\`.",
155+
"text": "Backslash (\\) is not allowed in names.",
229156
},
230157
]
231158
`);

packages/core/src/checker.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,14 @@ export function checkCSSModule(cssModule: CSSModule, args: CheckerArgs): Diagnos
6868
function createTokenNameDiagnostic(cssModule: CSSModule, loc: Location, violation: TokenNameViolation): Diagnostic {
6969
let text: string;
7070
switch (violation) {
71-
case 'invalid-js-identifier':
72-
text = `Token names must be valid JavaScript identifiers when \`cmkOptions.namedExports\` is set to \`true\`.`;
73-
break;
7471
case 'proto-not-allowed':
7572
text = `\`__proto__\` is not allowed as names.`;
7673
break;
7774
case 'default-not-allowed':
7875
text = `\`default\` is not allowed as names when \`cmkOptions.namedExports\` is set to \`true\`.`;
7976
break;
8077
case 'backslash-not-allowed':
81-
text = `Backslash (\\) is not allowed in names when \`cmkOptions.namedExports\` is set to \`false\`.`;
78+
text = `Backslash (\\) is not allowed in names.`;
8279
break;
8380
default:
8481
throw new Error('unreachable: unknown TokenNameViolation');

packages/core/src/dts-generator.test.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,26 @@ describe('generateDts', () => {
9595
'test.module.css': dedent`
9696
.local1 { color: red; }
9797
.local2 { color: red; }
98+
.local2 { color: red; }
9899
@import './a.module.css';
99100
@value imported1, imported2 as aliasedImported2 from './b.module.css';
100101
`,
101102
});
102103
expect(generateDts(readAndParseCSSModule(iff.paths['test.module.css'])!, { ...options, namedExports: true }).text)
103104
.toMatchInlineSnapshot(`
104-
"// @ts-nocheck
105-
export var local1: string;
106-
export var local2: string;
107-
export * from './a.module.css';
108-
export {
109-
imported1,
110-
imported2 as aliasedImported2,
111-
} from './b.module.css';
112-
"
113-
`);
105+
"// @ts-nocheck
106+
var _token_0: string;
107+
export { _token_0 as 'local1' };
108+
var _token_1: string;
109+
var _token_1: string;
110+
export { _token_1 as 'local2' };
111+
export * from './a.module.css';
112+
export {
113+
'imported1' as 'imported1',
114+
'imported2' as 'aliasedImported2',
115+
} from './b.module.css';
116+
"
117+
`);
114118
});
115119
test('exports styles as default when `namedExports` and `forTsPlugin` are true, but `prioritizeNamedImports` is false', async () => {
116120
const iff = await createIFF({
@@ -125,7 +129,8 @@ describe('generateDts', () => {
125129
}).text,
126130
).toMatchInlineSnapshot(`
127131
"// @ts-nocheck
128-
export var local1: string;
132+
var _token_0: string;
133+
export { _token_0 as 'local1' };
129134
declare const styles: {};
130135
export default styles;
131136
"

0 commit comments

Comments
 (0)