Skip to content

Commit d0a6685

Browse files
authored
Disallow non-JavaScript identifier @value (#221)
* disallow non-JavaScript identifier `@value` * add changelog
1 parent 61e053d commit d0a6685

3 files changed

Lines changed: 107 additions & 1 deletion

File tree

.changeset/twenty-windows-peel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@css-modules-kit/core': patch
3+
---
4+
5+
fix: disallow non-JavaScript identifier `@value`

packages/core/src/parser/at-value-parser.test.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,12 @@ describe('parseAtValue', () => {
412412
`);
413413
});
414414
test('invalid', () => {
415-
const [atValue1, atValue2] = fakeAtValues(
415+
const [atValue1, atValue2, atValue3, atValue4] = fakeAtValues(
416416
fakeRoot(dedent`
417417
@value;
418418
@value a,,b from "test.css";
419+
@value non-js-ident-1: #000;
420+
@value non-js-ident-1, non-js-ident-2 as alias_1, a as non-js-ident-3 from "test.css";
419421
`),
420422
);
421423
expect(parseAtValue(atValue1!)).toMatchInlineSnapshot(`
@@ -496,5 +498,70 @@ describe('parseAtValue', () => {
496498
],
497499
}
498500
`);
501+
expect(parseAtValue(atValue3!)).toMatchInlineSnapshot(`
502+
{
503+
"diagnostics": [
504+
{
505+
"category": "error",
506+
"length": 14,
507+
"start": {
508+
"column": 8,
509+
"line": 3,
510+
},
511+
"text": "css-modules-kit does not support non-JavaScript identifier as value names.",
512+
},
513+
],
514+
}
515+
`);
516+
expect(parseAtValue(atValue4!)).toMatchInlineSnapshot(`
517+
{
518+
"atValue": {
519+
"from": "test.css",
520+
"fromLoc": {
521+
"end": {
522+
"column": 85,
523+
"line": 4,
524+
"offset": 150,
525+
},
526+
"start": {
527+
"column": 77,
528+
"line": 4,
529+
"offset": 142,
530+
},
531+
},
532+
"type": "valueImportDeclaration",
533+
"values": [],
534+
},
535+
"diagnostics": [
536+
{
537+
"category": "error",
538+
"length": 14,
539+
"start": {
540+
"column": 8,
541+
"line": 4,
542+
},
543+
"text": "css-modules-kit does not support non-JavaScript identifier as value names.",
544+
},
545+
{
546+
"category": "error",
547+
"length": 14,
548+
"start": {
549+
"column": 24,
550+
"line": 4,
551+
},
552+
"text": "css-modules-kit does not support non-JavaScript identifier as value names.",
553+
},
554+
{
555+
"category": "error",
556+
"length": 14,
557+
"start": {
558+
"column": 56,
559+
"line": 4,
560+
},
561+
"text": "css-modules-kit does not support non-JavaScript identifier as value names.",
562+
},
563+
],
564+
}
565+
`);
499566
});
500567
});

packages/core/src/parser/at-value-parser.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { AtRule } from 'postcss';
22
import type { DiagnosticPosition, DiagnosticWithDetachedLocation, Location } from '../type.js';
3+
import { JS_IDENTIFIER_PATTERN } from '../util.js';
34

45
interface ValueDeclaration {
56
type: 'valueDeclaration';
@@ -83,6 +84,17 @@ export function parseAtValue(atValue: AtRule): ParseAtValueResult {
8384
column: start.column + name.length,
8485
offset: start.offset + name.length,
8586
};
87+
88+
if (!JS_IDENTIFIER_PATTERN.test(name)) {
89+
diagnostics.push({
90+
start: { line: start.line, column: start.column },
91+
length: name.length,
92+
text: `css-modules-kit does not support non-JavaScript identifier as value names.`,
93+
category: 'error',
94+
});
95+
continue;
96+
}
97+
8698
const result = { name, loc: { start, end } };
8799
if (localName === undefined) {
88100
values.push(result);
@@ -98,6 +110,17 @@ export function parseAtValue(atValue: AtRule): ParseAtValueResult {
98110
column: start.column + localName.length,
99111
offset: start.offset + localName.length,
100112
};
113+
114+
if (!JS_IDENTIFIER_PATTERN.test(localName)) {
115+
diagnostics.push({
116+
start: { line: start.line, column: start.column },
117+
length: localName.length,
118+
text: `css-modules-kit does not support non-JavaScript identifier as value names.`,
119+
category: 'error',
120+
});
121+
continue;
122+
}
123+
101124
values.push({ ...result, localName, localLoc: { start, end } });
102125
}
103126
} else {
@@ -154,6 +177,17 @@ export function parseAtValue(atValue: AtRule): ParseAtValueResult {
154177
column: start.column + name.length,
155178
offset: start.offset + name.length,
156179
};
180+
181+
if (!JS_IDENTIFIER_PATTERN.test(name)) {
182+
diagnostics.push({
183+
start: { line: start.line, column: start.column },
184+
length: name.length,
185+
text: `css-modules-kit does not support non-JavaScript identifier as value names.`,
186+
category: 'error',
187+
});
188+
return { diagnostics };
189+
}
190+
157191
const parsedAtValue: ValueDeclaration = {
158192
type: 'valueDeclaration',
159193
name,

0 commit comments

Comments
 (0)