diff --git a/lib/nodes/inline-comment.js b/lib/nodes/inline-comment.js index b933949..6d4a461 100644 --- a/lib/nodes/inline-comment.js +++ b/lib/nodes/inline-comment.js @@ -45,7 +45,7 @@ module.exports = { // Replace tokenizer to retokenize the rest of the string // we need replace it after we added new token with inline comment because token position is calculated for old input (#145) if (remainingInput) { - this.input = new Input(remainingInput); + this.input = new Input(remainingInput, { from: this.input.file }); this.tokenizer = tokenizer(this.input); } diff --git a/test/parser/comments.test.js b/test/parser/comments.test.js index 6f7fdc1..952c472 100644 --- a/test/parser/comments.test.js +++ b/test/parser/comments.test.js @@ -212,3 +212,32 @@ test('handles single quotes in comments (#163)', (t) => { t.is(nodeToString(root), less); }); + +test('preserves source.input.file when retokenizing inline comments', (t) => { + const from = '/repro.less'; + // The quote in the inline comment, plus a later quote, makes the tokenizer run + // the string past the newline, which sends `isInlineComment` down the path that + // builds a replacement Input for the remainder of the file. + const less = `a {\n // it's\n color: red;\n}\nb { content: 'x'; }\n`; + + const root = parse(less, { from }); + + const nodes = []; + root.walk((node) => nodes.push(node)); + + // Nodes produced by the replacement tokenizer must keep the original path. + for (const node of nodes) { + t.is(node.source.input.file, from); + } + + // The position fix-up in lib/index.js still applies. + t.deepEqual(nodes.map((node) => [node.type, node.source.start.line]), [ + ['rule', 1], + ['comment', 2], + ['decl', 3], + ['rule', 5], + ['decl', 5] + ]); + + t.is(nodeToString(root), less); +});