Skip to content

Commit 10beb3d

Browse files
committed
Fix underscore-prefixed column names being treated as LaTeX subscript prefix
1 parent a658055 commit 10beb3d

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

src/ra-engine/raHighlight.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,34 @@ describe("RA preview", () => {
171171
const opMatches = html.match(/ra-prev-op/g);
172172
expect(opMatches!.length).toBeGreaterThanOrEqual(2);
173173
});
174+
175+
it("should not treat underscore-prefixed column names as LaTeX subscript", () => {
176+
const html = renderRAPreview("PI _name, person_id Person");
177+
// _name should not be split — the underscore is part of the column name
178+
expect(html).toMatch(/<sub[^>]*>.*_name.*person_id.*<\/sub>/);
179+
expect(html).not.toMatch(/opacity/); // no faint bracket styling for _
180+
});
181+
});
182+
183+
describe("RA highlighter character preservation with underscore columns", () => {
184+
it("should preserve character count with underscore-prefixed columns", () => {
185+
const input = "PI _name, person_id (Person)";
186+
const html = highlightRA(input);
187+
const textOnly = html
188+
.replace(/<[^>]+>/g, "")
189+
.replace(/&lt;/g, "<").replace(/&gt;/g, ">")
190+
.replace(/&amp;/g, "&").replace(/&quot;/g, '"');
191+
expect(textOnly).toBe(input);
192+
});
193+
194+
it("should still handle real _{} LaTeX notation with Unicode symbol", () => {
195+
const input = "σ_{age > 20}(Person)";
196+
const html = highlightRA(input);
197+
const textOnly = html
198+
.replace(/<[^>]+>/g, "")
199+
.replace(/&lt;/g, "<").replace(/&gt;/g, ">")
200+
.replace(/&amp;/g, "&").replace(/&quot;/g, '"');
201+
expect(textOnly).toBe(input);
202+
expect(html).toContain("opacity: 0.5"); // _ rendered as faint bracket
203+
});
174204
});

src/ra-engine/raHighlight.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,14 @@ function renderSubscript(code: string, i: number, result: string[]): number {
197197
return i;
198198
}
199199

200-
// Handle _{ or _[ (LaTeX-style)
200+
// Handle _{ or _[ (LaTeX-style) — only if followed by a bracket
201201
if (code[i] === "_") {
202-
result.push(`<span style="${S.bracket}">${esc("_")}</span>`);
203-
i++;
204-
i = skipWs(code, i);
202+
const afterUnderscore = skipWs(code, i + 1);
203+
if (afterUnderscore < code.length && (code[afterUnderscore] === "{" || code[afterUnderscore] === "[")) {
204+
result.push(`<span style="${S.bracket}">${esc("_")}</span>`);
205+
i++;
206+
i = skipWs(code, i);
207+
}
205208
}
206209

207210
// Try bracket content

src/ra-engine/raShared.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,12 @@ export function extractBracketContent(code: string, startI: number): [number, st
152152
let i = skipWs(code, startI);
153153
if (i >= code.length) return [startI, null];
154154

155-
// Handle _{ or _[ prefix
155+
// Handle _{ or _[ prefix — only if followed by a bracket
156156
if (code[i] === "_") {
157-
i++;
158-
i = skipWs(code, i);
157+
const afterUnderscore = skipWs(code, i + 1);
158+
if (afterUnderscore < code.length && (code[afterUnderscore] === "{" || code[afterUnderscore] === "[")) {
159+
i = afterUnderscore;
160+
}
159161
}
160162

161163
if (code[i] === "[" || code[i] === "{") {

0 commit comments

Comments
 (0)