Skip to content

Code-region protection in markdown preprocessing is desynchronized by longer backtick runs (nonlocal corruption) #227

Description

@PathGao

The five source-level rewrites in `src-tauri/src/lib.rs` (`![[embeds]]`, `[[#wikilinks]]`, `^block-ids`, `==highlight==`, `^[inline footnotes]`) protect code regions with the regex alternation:

(?s)```.*?```|`.*?`|<the actual pattern>

That alternation cannot express CommonMark's pairing rules, and a single unusual-but-legal construct desynchronizes protection for the entire rest of the document.

Two independent rupture modes

1. Longer backtick runs. CommonMark pairs code spans by equal-length backtick runs, and closes fences only on a run at least as long as the opener. The lazy ```.*?``` knows neither rule. Minimal repro:

```` ```mermaid ```` fence sample

later, some inline code: `![[not-an-embed.md]]`

The 4-backtick inline sample mispairs with the next run, and from that point on the "is this inside code?" bookkeeping is shifted for the whole document: the second line's inline code gets rewritten into <img src="not-an-embed.md" …>. In a real document we observed collateral damage in blocks far away from the trigger (a callout rendered with a huge empty area) — the corruption is nonlocal, which makes it very hard for users to connect symptom to cause.

2. Non-backtick fences. The pattern only knows ``` fences. ~~~ fences and indented code blocks are not protected at all, so an `![[x]]` inside a `~~~` block is rewritten today, no exotic trigger needed.

Why the regex cannot be fixed in place

Equal-length run pairing needs backreferences; the regex crate deliberately doesn't support them (linear-time guarantee). PR # replaces the alternation with a ~60-line scanner that walks fences and backtick runs by the CommonMark rules and skips any rewrite starting inside a protected range — no new dependencies, behavior otherwise unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions