postcss-less
postcss-less copied to clipboard
Reports incorrect node locations for files with comments containing single quote
I originally reported this problem in stylelint (https://github.com/stylelint/stylelint/issues/5438), but eventually determined it was caused by postcss-less
.
- Node Version: 14.17.0
- NPM Version: 6.14.13
- postcss Version: 8.3.5
- postcss-less Version: master
LESS
This example may look kind of contrived, but it's based on many real-world examples in our code (long, rambling explanations that happen to single quotes). This is as simplified as I could get it.
a {
// '
color: pink;
}
/** ' */
JavaScript
Here is the test I added to test/parser/comments.test.js
to reproduce the problem:
test('handles single quotes in comments', (t) => {
const less = `a {\n // '\n color: pink;\n}\n\n/** ' */`;
const root = parse(less);
const [ruleNode, commentNode] = root.nodes;
t.is(ruleNode.type, 'rule');
t.is(commentNode.type, 'comment');
const [innerCommentNode, declarationNode] = ruleNode.nodes;
t.is(innerCommentNode.type, 'comment');
t.is(declarationNode.type, 'decl');
t.is(declarationNode.source.start.line, 3);
t.is(declarationNode.source.start.column, 3);
t.is(declarationNode.source.end.line, 3);
t.is(declarationNode.source.end.column, 14);
t.is(nodeToString(root), less);
});
All assertions about declarationNode.source.*.line
fail.
Expected Behavior
I would expect that the declaration node for color: pink
to be marked as starting and ending on line 3.
Actual Behavior
The declaration node for color: pink
is marked as starting and ending on line 2. As you can see from the original LESS document, this is incorrect; line 2 is a comment.
How can we reproduce the behavior?
If you add the above test to test/parser/comments.test.js
and run npm run test -- test/parser/comments.test.js
, you can observe the test failing:
> ava "test/parser/comments.test.js"
handles single quotes in comments
test/parser/comments.test.js:198
197:
198: t.is(declarationNode.source.start.line, 3);
199: t.is(declarationNode.source.start.column, 3);
Difference:
- 2
+ 3
› test/parser/comments.test.js:198:5
─
1 test failed
Potential fix
I spent a good deal of time trying to develop a fix for this, but I haven't yet figured out a way to work around the fact that the inline-comment
node creates a new tokenizer in the middle of parsing (source). My current thinking is to try to do some kind of post-processing on the tree in the parse
function - does that seem like a reasonable approach to you?