fix(lexer): don't split table cells on | inside links/code
The table-row lexer collected every `|` as a cell separator, so a pipe
inside a `[[url|title]]` wikilink (or `{{…}}` transclusion / `` `…` ``
inline code) was mistaken for a column boundary — mangling the link and
adding a phantom column in the AST and HTML export.
Replace the naive scan in `try_lex_table_row` with `cell_bar_positions`,
which skips pipes inside those constructs (matching the regions
`lex_inline` tokenises as a unit). Unclosed constructs fall back to
literal openers so a malformed cell can't swallow the rest of the row,
and the scan only slices at ASCII openers to stay UTF-8 safe.
Backslash-escaped `\|` is intentionally left unhandled: the inline lexer
has no escape handling, so honouring it here would leave a stray
backslash in the output. Documented as a matched follow-up.
Adds lexer + HTML-export regression tests.
Closes #1
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lzhq43v1qpkZczN65dqXa3
This commit is contained in:
@@ -454,6 +454,48 @@ fn table_col_and_row_span_cells() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_cell_with_wikilink_pipe_is_not_split() {
|
||||
// The `|` inside `[[url|title]]` is part of the link, not a cell
|
||||
// boundary: the row must lex to exactly two cells (three TableSeps).
|
||||
assert_eq!(
|
||||
lex("| foo | [[https://example.com|My Site]] |\n"),
|
||||
vec![
|
||||
TableSep,
|
||||
text(" foo "),
|
||||
TableSep,
|
||||
text(" "),
|
||||
WikiLinkOpen,
|
||||
text("https://example.com"),
|
||||
WikiLinkSep,
|
||||
text("My Site"),
|
||||
WikiLinkClose,
|
||||
text(" "),
|
||||
TableSep,
|
||||
Newline,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_cell_with_transclusion_and_code_pipes_are_not_split() {
|
||||
// `|` inside `{{…}}` and inside `` `…` `` are both literal.
|
||||
let lexed = lex("| {{a|b}} | `x|y` |\n");
|
||||
let seps = lexed.iter().filter(|t| matches!(t, TableSep)).count();
|
||||
assert_eq!(seps, 3, "expected 2 cells: {lexed:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_cell_with_unclosed_wikilink_falls_back_to_pipe_split() {
|
||||
// A malformed, unclosed `[[` must not swallow the rest of the row —
|
||||
// the pipes still delimit cells.
|
||||
let seps = lex("| [[oops | tail |\n")
|
||||
.iter()
|
||||
.filter(|t| matches!(t, TableSep))
|
||||
.count();
|
||||
assert_eq!(seps, 3);
|
||||
}
|
||||
|
||||
// ===== Definition list =====
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user