blockmap: a lazy-continuation admonition keeps its marker and its indent - #31
Conversation
MkDocs and Python-Markdown accept an admonition whose body follows the marker with no blank line between them. That spelling is one paragraph to CommonMark: the indented body is a lazy continuation, not the indented code block the blank-line spelling produces, so it never reaches the dialect recognition added for the latter. Reflowed as ordinary prose it stops being a callout. The marker joins the body, and even with the marker pinned the body loses the 4-space indent the extension requires, so the whole thing renders as a paragraph beginning with a literal "!!! tip". build already has this exact shape for a footnote definition: a marker first line whose body must stay indented, handled by appending to ContPrefix. An admonition needs that plus an immovable marker, so it gets both. Found by diffing a rendered mkdocs site before and after adopting sentence-per-line across a 263-file docset: 7 of 17 callouts were being destroyed, and no existing gate saw it, since the output is still valid Markdown that builds.
|
Merged (rebased onto the fresh v0.1.5 — your CHANGELOG entry moved to the new Unreleased section with a #31 reference). Took it ungated after weighing the dialect question: boundary-protection for dialect markers is the always-on posture here (GitHub alerts, Docusaurus fences, Hugo shortcodes all get it regardless of dialect), and this is render-preserving under goldmark, so it belongs in that family rather than behind --dialect mkdocs, which stays reserved for render-changing recognition. The 7→0 mkdocs-build verification is the kind of evidence that makes these easy to take. Your idempotency find is filed as #32 with credit — confirmed pre-existing, confirmed backstop-absorbed for users, and flagged as the second ::: -neighborhood find in a day. It's first in line for v0.1.6, which at the current rate you're setting will be soon. |
) A list item whose marker line has an empty body carries its prose on a later, indented physical line, so writeParagraph's firstLinePrefix — the joint context the thematic-break escape needs — is that line's own leading whitespace, pure container indentation goldmark consumes before the block scan. It was normalized for blockquote markers but not for that indent, and a leading tab left in place disqualified the whole line from isThematicBreak (which counts only spaces as separators). So when the body "**"/"**" reflowed to "** **" — four asterisks, a thematic break — the tab hid it from the escape, and the join silently ended the list and dropped the following ::: paragraph out of it. A render change; the render backstop was reverting it, which is why public Format looked idempotent on the shape. firstLinePrefix now strips leading spaces/tabs after the blockquote strip: a bare-indent prefix contributes "" to the joint spelling, while a "* "/"- " marker char (itself part of a thematic-break run) still survives. The body is escaped and reflows normally. Found by @karlkfi fuzzing the #31 branch on "*\n\t**\n**\n:::\n0"; seed checked in. Second find in the ::: boundary neighborhood after cf1a42a. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up to #19, which only covered half the construct. This is the half that was silently destroying callouts.
Problem
MkDocs and Python-Markdown accept both of these:
The first is a paragraph plus an indented code block, which #19 recognizes. The second is a single paragraph to CommonMark, because the indented body is a lazy continuation rather than a code block, so it never reaches that recognition and reflows as ordinary prose:
MkDocs then renders that as a paragraph beginning with a literal
!!! tip. The callout is gone.Why the marker alone is not enough
I tried the obvious fix first, a
lineBoundarydialect rule like the GitHub alert marker. The marker survives, but the body loses its indent:Python-Markdown needs the 4-space indent, so that is still not a callout. The alert case works only because
>is the paragraph's container prefix and gets reproduced; an admonition's indent is not a container prefix.Proposal
buildalready handles exactly this shape for a footnote definition: a marker first line whose body must stay indented, done by appending toContPrefix. An admonition needs the same plus an immovable marker line.Result:
Marker preserved, body reflowed, indent intact. No skip, and the body still gets sentence-per-line.
Verification
go test ./...green, plus a table case asserting both the boundary and the prefix.!!!is untouched (the marker pattern requires a type word), a marker with no title works, and one nested in a list item keeps its container prefix.mkdocs buildover the 263-file docset this was found on, before and after: structural page differences went from 7 to 0.The two pages that still differ structurally are the reflow fixing latent bugs in that source, not regressions: a sentence wrapped so
10.landed at line start had been rendering as a stray<li>, and a heading that was missing from the page nav now appears.Unrelated pre-existing failure, for your awareness
Fuzzing this branch surfaced an idempotency failure on
"*\n\t**\n**\n:::\n0". It reproduces on unmodified main with the same seed, so it is not from this change and I have not tried to fix it. Happy to file it separately if it is not already known.