From 7b11acde6c2826af5c51ca67802f20ad3592ad1d Mon Sep 17 00:00:00 2001 From: Sarath Francis Date: Mon, 1 Jun 2026 22:38:21 -0400 Subject: [PATCH] Fix Node#rangeBy() ignoring index 0 When calling Node#rangeBy() (and therefore Node#error() and Node#warn()) with index 0, the resulting range covered the whole node instead of a single character at offset 0. The end-of-range branch used a truthy check on opts.index, so an index of 0 fell through and left the end position at the node's end. This is the same off-by-zero issue that was previously fixed for endIndex; the index branches were missed. Switch both index checks to a numeric type check, matching the existing endIndex handling. index 0 now produces a single-character range, consistent with every other index value. --- lib/node.js | 4 ++-- test/node.test.ts | 10 ++++++++++ test/warning.test.ts | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/node.js b/lib/node.js index b403b7136..cfddbbefa 100644 --- a/lib/node.js +++ b/lib/node.js @@ -298,7 +298,7 @@ class Node { line: opts.start.line, offset: sourceOffset(inputString, opts.start) } - } else if (opts.index) { + } else if (typeof opts.index === 'number') { start = this.positionInside(opts.index) } @@ -310,7 +310,7 @@ class Node { } } else if (typeof opts.endIndex === 'number') { end = this.positionInside(opts.endIndex) - } else if (opts.index) { + } else if (typeof opts.index === 'number') { end = this.positionInside(opts.index + 1) } } diff --git a/test/node.test.ts b/test/node.test.ts index 41b0ac7b7..1a2f33655 100755 --- a/test/node.test.ts +++ b/test/node.test.ts @@ -849,6 +849,16 @@ test('rangeBy() returns range for index and endIndex', () => { }) }) +test('rangeBy() returns range for index 0', () => { + let css = parse('a { one: X }') + let a = css.first as Rule + let one = a.first as Declaration + equal(one.rangeBy({ index: 0 }), { + end: { column: 7, line: 1, offset: 6 }, + start: { column: 6, line: 1, offset: 5 } + }) +}) + test('rangeBy() returns range for index and endIndex when offsets are missing', () => { let css = parse('a { one: X }') let a = css.first as Rule diff --git a/test/warning.test.ts b/test/warning.test.ts index 609b056aa..4075f8a7a 100644 --- a/test/warning.test.ts +++ b/test/warning.test.ts @@ -121,6 +121,15 @@ test('gets range from index', () => { is(warning.endColumn, 4) }) +test('gets range from index 0', () => { + let root = parse('a b{}') + let warning = new Warning('text', { index: 0, node: root.first }) + is(warning.line, 1) + is(warning.column, 1) + is(warning.endLine, 1) + is(warning.endColumn, 2) +}) + test('gets range from index and endIndex', () => { let root = parse('a b{}') let warning = new Warning('text', { endIndex: 3, index: 2, node: root.first })