Skip to content

markdown_parser: unclosed <u> markers pair via the emphasis algorithm and delete surrounding text #12863

Description

@tkshsbcue

Summary

parse_markdown silently deletes text when a <u> underline marker is left unclosed and another <u> appears later in the same line. The two <u> markers are matched against each other as an emphasis pair and consumed, taking the text around them with them.

Reproduction (against the real parser)

Input Expected (literal round-trip, like an unclosed *) Actual
<u><u> <u><u> empty line — all text gone
<u>a<u> <u>a<u> a (both <u> deleted)
a <u>word<u> b a <u>word<u> b a word b (both <u> deleted)
assert_eq!(parse_markdown("<u><u>").unwrap().raw_text(), "<u><u>\n"); // fails: left is "\n"

Root cause

<u> is tokenized as an UnderlineStart delimiter (crates/markdown_parser/src/markdown_parser.rs, the InlineToken::Delimiter arm) and pushed onto the shared delimiter stack with can_close set from the right-flanking rules (Delimiter::new). As a result process_emphasis sees two <u> markers as a matchable opener/closer pair — can_open_for passes because they share kind == DelimiterKind::UnderlineStart — and the opener.kind == UnderlineStart branch in process_emphasis consumes both markers and removes their text nodes.

Underline is only ever supposed to be closed by an explicit </u>, which is handled separately by parse_underline (it never goes through can_open_for). So pairing two <u> openers through the emphasis path is always wrong; an unclosed <u> should round-trip to literal text, exactly like an unclosed *.

Impact

parse_markdown is the main renderer for agent output and markdown-viewer content, so a partial/streamed <u> or two <u> tags silently drop the literal text. This is data loss in rendered output, not a crash.

Notes

  • Crate-scoped and reproducible with a pure unit test (no UI needed).
  • I have a small fix ready (make can_open_for reject UnderlineStart; ~8 lines) with regression tests for the cases above, and all existing markdown_parser tests still pass. Happy to open a PR once this is labeled ready-to-implement.

Operating system

All (platform-independent parser logic)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:editor-notebooksEditors, notebooks, markdown rendering, LSP, and code display.bugSomething isn't working.ready-to-implementThe issue is ready for implementation work.repro:highThe report includes enough evidence that the issue appears highly reproducible.triagedIssue has received an initial automated triage pass.warp:auto-triage-review

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions