Skip to content

fix(markdown): keep indented bare-fence lines as content in numeric lists - #248

Open
detail-app[bot] wants to merge 1 commit into
devfrom
detail/bug-fix/fix-markdown-keep-indented-bare-fence-lines-as-con-93a0d7
Open

detail-app[bot] wants to merge 1 commit into
devfrom
detail/bug-fix/fix-markdown-keep-indented-bare-fence-lines-as-con-93a0d7

Conversation

@detail-app

@detail-app detail-app Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Detail bug report: View on Detail

Bug

nestNumericListFences re-indents fenced code blocks so CommonMark attaches them to a preceding numeric list item (parseMarkdown runs this on every message before lexing). In commit 724c810e the closing-fence cutoff in the open-fence pass lost its bodyIndentation.length term, widening it from openingSourceIndentation + 3 to awaitedContinuationIndentation + 3.

As a result, a bare ```/~~~ line used as code content inside a reparented fence was misclassified as the closing fence whenever its source indentation landed in that gap. The block closed early, the inner fence line and everything after it were dropped/repurposed, and trailing content leaked out of the list item as a sibling <p> plus a stray empty <pre><code>. The window grows with the numeric marker width (e.g. 14., 123.), so even moderately indented nested-fence demos lost content. This contradicts plain marked@15.0.12 on the un-preprocessed source, which keeps those lines as content (closing fences may be at most 3 columns past the opening fence's column).

Closes #244

Fix

Restore the body-indentation correction so closing-fence detection stays relative to the (possibly re-indented) opening fence's source column, per CommonMark §4.5:

maximumSourceIndentation =
  awaitedContinuationIndentation +
  COMMONMARK_MAX_FENCE_INDENTATION -
  bodyIndentation.length;

This is the pre-724c810e formula and the idiomatic single-line fix: nestNumericListFences is a structural reparenting transform, so it must preserve the content boundaries the source already establishes rather than reinterpret them. No lookahead/disambiguation is needed — a bare fence more than 3 columns past the opener is unambiguously content in the source frame.

Updated the test added in 724c810e (which codified the widened, non-CommonMark cutoff) to expect bare fences at columns 4–7 to be preserved as content, matching plain marked@15.0.12. Added regression tests for the reported reproducer, for deep numeric markers (14., 123.) — confirming the cutoff tracks the opening fence rather than the marker width — and a positive-direction test confirming valid closers at columns 0–3 still close (guards against over-tightening).

Testing

  • Unit tests (numericListFenceNesting.test.ts, markdown.test.ts) and the full frontend Vitest suite (356 tests) pass.
  • Inverted the fix temporarily: the new/updated content-preservation tests fail without the fix (4 fail / 8 pass), confirming they catch the regression; the positive-direction test and pre-existing tests still pass without it, confirming the fix only tightens the cutoff.
  • Verified empirically that the fixed parseMarkdown output's code-block content matches plain marked@15.0.12 byte-for-byte for the 1., 14., and 123. openers (and tilde fences), with the block additionally nested under the list item and no leaked <p>/stray <pre> (ran as a temporary jsdom-backed Vitest cross-check, then removed per the no-probes rule).
  • End-to-end browser verification in headless Chromium: wrote a temporary Playwright spec that mocks the chat SSE stream with the reproducer markdown and asserts the rendered assistant bubble keeps ```\nmore inside exactly one nested ol > li pre > code, with no stray top-level <pre> or <p> — for both the 1. and 14. markers. Both passed; the pre-existing accessibility e2e suite still passes (no regression). The temporary spec was removed (browser lane is CI-owned).
  • Typecheck (svelte-check), format check (oxfmt), lint (oxlint + eslint type-aware + ast-grep), and production build all pass clean.

Automatic Fixes PRs can be configured here.

…ists

Restore the body-indentation correction in the numeric-list fence nesting open-fence pass so the closing-fence cutoff stays relative to the opening fence's source column (CommonMark §4.5). A bare ```/~~~ line used as code content inside a reparented fence was misclassified as the closing fence when its indentation fell in the widened cutoff window, dropping the rest of the block out of the list item.
@detail-app
detail-app Bot requested a review from WilliamAGH September 8, 2026 16:08
@detail-app detail-app Bot added the bug Something isn't working label Sep 8, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Detail Bug] Markdown: Fenced code blocks in numeric lists can close early, dropping content after an indented ``` line

1 participant