diff --git a/.changeset/calm-comments-stay.md b/.changeset/calm-comments-stay.md new file mode 100644 index 000000000..76c372132 --- /dev/null +++ b/.changeset/calm-comments-stay.md @@ -0,0 +1,7 @@ +--- +'@linaria/postcss-linaria': patch +--- + +Keep comment indentation stable through `stylelint --fix` + +Indented templates no longer add their base indentation before trailing comments or remove it from continuation lines inside multi-line comments. Repeated parse/stringify passes now preserve both forms byte-for-byte (#1502). diff --git a/packages/postcss-linaria/__tests__/stringify.test.ts b/packages/postcss-linaria/__tests__/stringify.test.ts index 17ef76ecd..116326d9d 100644 --- a/packages/postcss-linaria/__tests__/stringify.test.ts +++ b/packages/postcss-linaria/__tests__/stringify.test.ts @@ -298,6 +298,44 @@ describe('stringify', () => { expect(output).toEqual(source); }); + // https://github.com/callstack/linaria/issues/1502. The whitespace before a + // trailing comment is not line indentation and must not grow on each pass. + it('should keep whitespace before a trailing comment unchanged', () => { + const source = ` +export const style = { + a: css\` + color: red; /* c */ + \`, +}; +`; + + let current = source; + for (let pass = 0; pass < 3; pass += 1) { + const { ast } = createTestAst(current); + current = ast.toString(syntax); + expect(current).toEqual(source); + } + }); + + it('should keep indentation inside a multi-line comment unchanged', () => { + const source = ` +export const style = { + a: css\` + /* first line + second line */ + color: red; + \`, +}; +`; + + let current = source; + for (let pass = 0; pass < 3; pass += 1) { + const { ast } = createTestAst(current); + current = ast.toString(syntax); + expect(current).toEqual(source); + } + }); + // Not the same as the placeholder cases above: these have no interpolations. it('should keep a comment inside a multi-line selector', () => { const { source, ast } = createTestAst(` diff --git a/packages/postcss-linaria/src/locationCorrection.ts b/packages/postcss-linaria/src/locationCorrection.ts index 20a5dd5e2..aaf88c9a0 100644 --- a/packages/postcss-linaria/src/locationCorrection.ts +++ b/packages/postcss-linaria/src/locationCorrection.ts @@ -178,20 +178,37 @@ function computeBeforeAfter( node: Document | Root | ChildNode, baseIndentations: Map ): void { + const { before } = node.raws; if ( - node.raws.before && - (node.raws.before.includes('\n') || node.parent?.type === 'root') && + before && + (before.includes('\n') || + (node.parent?.type === 'root' && + node.source?.start && + node.source.start.column === before.length + 1)) && node.source?.start ) { - const numBeforeLines = node.raws.before.split('\n').length - 1; + const numBeforeLines = before.split('\n').length - 1; const corrected = computeCorrectedString( - node.raws.before, + before, node.source.start.line - numBeforeLines, baseIndentations ); node.raws.linariaBefore = corrected; } + if ( + node.type === 'comment' && + node.text.includes('\n') && + node.source?.start + ) { + const corrected = computeCorrectedString( + node.text, + node.source.start.line, + baseIndentations + ); + node.raws.linariaText = corrected; + } + if ( node.raws.after && node.raws.after.includes('\n') && diff --git a/packages/postcss-linaria/src/stringify.ts b/packages/postcss-linaria/src/stringify.ts index 41ae8b211..ba56cbdab 100644 --- a/packages/postcss-linaria/src/stringify.ts +++ b/packages/postcss-linaria/src/stringify.ts @@ -174,7 +174,14 @@ class LinariaStringifier extends Stringifier { 'left', this.raw(node, 'left', 'commentLeft') ); - const text = escapeNodeField(node, 'text', node.text); + const text = escapeNodeField( + node, + 'text', + typeof node.raws.linariaText === 'string' && + isOriginalField(node, 'text', node.text) + ? node.raws.linariaText + : node.text + ); const right = escapeRawField( node, 'right',