fix(markdown-table): handle escaped backslashes before pipe separators; use @/ alias in test import

- Rewrite parseRow to count consecutive backslashes before each pipe so
  that `\\|` (escaped backslash + unescaped pipe) is correctly treated as
  a column separator. The previous lookbehind regex (?<!\\)| only checked
  the single character immediately before the pipe, causing it to fail for
  an even number of preceding backslashes.
- Update test file import from relative `./markdown-table` to the project
  alias `@/utils/markdown-table` for consistency with frontend conventions.
This commit is contained in:
milvasic 2026-03-23 19:47:39 +01:00
parent aa0f072c42
commit 26dec86b70
2 changed files with 26 additions and 3 deletions

View File

@ -6,7 +6,7 @@ import {
replaceNthTable,
serializeMarkdownTable,
type TableData,
} from "./markdown-table";
} from "@/utils/markdown-table";
// ---------------------------------------------------------------------------
// parseMarkdownTable

View File

@ -37,11 +37,34 @@ export function parseMarkdownTable(md: string): TableData | null {
if (lines.length < 2) return null;
const parseRow = (line: string): string[] => {
// Strip leading/trailing pipes and split by unescaped pipe.
// Strip leading/trailing pipes and split by pipes preceded by an even number
// of backslashes (0, 2, 4, …). A pipe preceded by an odd number of
// backslashes is an escaped pipe and must not be treated as a column
// separator. The simpler regex (?<!\\)\| fails for "\\|" (escaped
// backslash + unescaped pipe) because the lookbehind only checks the single
// character immediately before the pipe.
let trimmed = line;
if (trimmed.startsWith("|")) trimmed = trimmed.slice(1);
if (trimmed.endsWith("|")) trimmed = trimmed.slice(0, -1);
return trimmed.split(/(?<!\\)\|/).map((cell) => cell.trim().replace(/\\\|/g, "|"));
const cells: string[] = [];
let cellStart = 0;
for (let i = 0; i < trimmed.length; i++) {
if (trimmed[i] === "|") {
let backslashes = 0;
let j = i - 1;
while (j >= 0 && trimmed[j] === "\\") {
backslashes++;
j--;
}
if (backslashes % 2 === 0) {
cells.push(trimmed.slice(cellStart, i).trim().replace(/\\\|/g, "|"));
cellStart = i + 1;
}
}
}
cells.push(trimmed.slice(cellStart).trim().replace(/\\\|/g, "|"));
return cells;
};
const headers = parseRow(lines[0]);