From 2be2dec42a82fc71ca5d0e9a14fa65582ae3a5ba Mon Sep 17 00:00:00 2001 From: Yuzhong Zhang Date: Thu, 3 Sep 2026 23:36:04 +0000 Subject: [PATCH] fix: throw a readable error for out-of-range block annotations --- packages/codehike/src/code/lines.test.ts | 41 ++++++++++++++++++++++++ packages/codehike/src/code/lines.tsx | 7 ++++ 2 files changed, 48 insertions(+) create mode 100644 packages/codehike/src/code/lines.test.ts diff --git a/packages/codehike/src/code/lines.test.ts b/packages/codehike/src/code/lines.test.ts new file mode 100644 index 00000000..63c37ccb --- /dev/null +++ b/packages/codehike/src/code/lines.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from "vitest" +import { toLineGroups, toLines } from "./lines.js" +import { BlockAnnotation, Tokens } from "./types.js" + +function linesFromSource(source: string) { + const tokens: Tokens = [] + const rawLines = source.split("\n") + rawLines.forEach((line, i) => { + if (line.length) { + tokens.push([line]) + } + if (i < rawLines.length - 1) { + tokens.push("\n") + } + }) + return toLines(tokens) +} + +test("throws a readable error when a block annotation is out of range", () => { + const lines = linesFromSource( + [ + "const lorem = ipsum(dolor, sit)", + "const [amet, consectetur] = [0, 0]", + "lorem.adipiscing((sed, elit) => {", + " if (sed) {", + " amet += elit", + " }", + "})", + ].join("\n"), + ) + const annotation: BlockAnnotation = { + name: "mark", + query: "", + fromLineNumber: 100, + toLineNumber: 100, + } + + expect(() => toLineGroups(lines, [annotation])).toThrowError( + 'Cannot generate a valid range for the given code. Annotation "mark" targets lines 100-100, but the code only has 7 lines.', + ) +}) diff --git a/packages/codehike/src/code/lines.tsx b/packages/codehike/src/code/lines.tsx index 8dc83c23..149145c2 100644 --- a/packages/codehike/src/code/lines.tsx +++ b/packages/codehike/src/code/lines.tsx @@ -99,6 +99,13 @@ function applyBlockAnnotation( } }) + if (inside.length === 0) { + const lastLine = lines[lines.length - 1]?.range[1] ?? 0 + throw new Error( + `Cannot generate a valid range for the given code. Annotation "${annotation.name}" targets lines ${fromLineNumber}-${toLineNumber}, but the code only has ${lastLine} lines.`, + ) + } + return [ ...before, {