diff --git a/packages/happy-css-modules/src/locator/postcss.test.ts b/packages/happy-css-modules/src/locator/postcss.test.ts index 0cf9890..865a780 100644 --- a/packages/happy-css-modules/src/locator/postcss.test.ts +++ b/packages/happy-css-modules/src/locator/postcss.test.ts @@ -14,6 +14,7 @@ import { parseAtValue, parseComposesDeclarationWithFromUrl, collectNodes, + getOriginalLocationOfAtValue, } from './postcss.js'; describe('generateLocalTokenNames', () => { @@ -313,6 +314,17 @@ describe('getOriginalLocationOfClassSelector', () => { }); }); +test('getOriginalLocationOfAtValue', () => { + const [basic] = createAtValues( + createRoot(dedent` + @value basic: #000; + `), + ); + expect(getOriginalLocationOfAtValue(basic!)).toMatchInlineSnapshot( + `{ filePath: "/test/test.css", start: { line: 1, column: 1 }, end: { line: 1, column: 19 } }`, + ); +}); + test('collectNodes', () => { const ast = createRoot(dedent` @import; diff --git a/packages/happy-css-modules/src/locator/postcss.ts b/packages/happy-css-modules/src/locator/postcss.ts index f6bd13c..f652101 100644 --- a/packages/happy-css-modules/src/locator/postcss.ts +++ b/packages/happy-css-modules/src/locator/postcss.ts @@ -114,6 +114,32 @@ export function getOriginalLocationOfClassSelector(rule: Rule, classSelector: Cl }; } +/** + * Get the original location of `@value`. + * @param atValue The `@value` rule. + * @returns The location of the `@value` rule. + */ +export function getOriginalLocationOfAtValue(atValue: AtRule): Location { + // The node derived from `postcss.parse` always has `source` property. Therefore, this line is unreachable. + if (atValue.source === undefined) throw new Error('Node#source is undefined'); + // The node derived from `postcss.parse` always has `start` and `end` property. Therefore, this line is unreachable. + if (atValue.source.start === undefined) throw new Error('Node#start is undefined'); + if (atValue.source.end === undefined) throw new Error('Node#end is undefined'); + if (atValue.source.input.file === undefined) throw new Error('Node#input.file is undefined'); + + return { + filePath: atValue.source.input.file, + start: { + line: atValue.source.start.line, + column: atValue.source.start.column, + }, + end: { + line: atValue.source.end.line, + column: atValue.source.end.column, + }, + }; +} + function isAtRuleNode(node: Node): node is AtRule { return node.type === 'atrule'; }