You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Emission-side sibling of #39. That fix made detection consult goldmark's per-line verdict; marker emission still assumes the configured spelling works in every context.
Repro (raw core; production is shielded by the render backstop)
The unchanged output is the render backstop absorbing the failure. What the raw core does: pass 1 detects the real <br> break, normalizes it to the configured spaces spelling, and emits "* [X] \n0" — but the task-list extension's taskListRegexp (^\[([\sxX])\]\s*) swallows the checkbox, the trailing spaces, and the line ending, so the emitted marker renders as a soft break: the hard break the source had is lost. Pass 2's detection (now AST-confirmed, #39) correctly reads the emitted line as soft and joins — single-pass idempotency and render preservation both violated in the raw core.
Only the spaces spelling is affected: a backslash marker survives (\s* stops at \, leaving "\\\n" to parse as a break with an empty flagged text node), and <br> is raw HTML in any context. Only reachable with --hard-breaks=spaces and a hard break whose cluster prose reduces to exactly the checkbox shape on the paragraph's first line of a task-list item.
Why no soak ever finds it
deriveOptions in fuzz_test.go derives only Mode and MaxWidth from the input hash; HardBreaks is always the zero value (HardBreakBr). The spaces and backslash styles are never fuzzed at all — a coverage gap worth noting alongside #24/#26 regardless of this bug.
Fix directions
Per-position fallback, mirroring the existing first-output-line <br>→backslash fallback in writeParagraph: when attaching a spaces marker to a paragraph-first output line whose prose is exactly a checkbox shape and the paragraph is a list item's first child (p.Node parent chain answers this), fall back to the backslash spelling — render-preserving, one narrow position, style deviation only where the configured style cannot work.
Emission-side sibling of #39. That fix made detection consult goldmark's per-line verdict; marker emission still assumes the configured spelling works in every context.
Repro (raw core; production is shielded by the render backstop)
The unchanged output is the render backstop absorbing the failure. What the raw core does: pass 1 detects the real
<br>break, normalizes it to the configured spaces spelling, and emits"* [X] \n0"— but the task-list extension'staskListRegexp(^\[([\sxX])\]\s*) swallows the checkbox, the trailing spaces, and the line ending, so the emitted marker renders as a soft break: the hard break the source had is lost. Pass 2's detection (now AST-confirmed, #39) correctly reads the emitted line as soft and joins — single-pass idempotency and render preservation both violated in the raw core.Only the spaces spelling is affected: a backslash marker survives (
\s*stops at\, leaving"\\\n"to parse as a break with an empty flagged text node), and<br>is raw HTML in any context. Only reachable with--hard-breaks=spacesand a hard break whose cluster prose reduces to exactly the checkbox shape on the paragraph's first line of a task-list item.Why no soak ever finds it
deriveOptionsin fuzz_test.go derives onlyModeandMaxWidthfrom the input hash;HardBreaksis always the zero value (HardBreakBr). The spaces and backslash styles are never fuzzed at all — a coverage gap worth noting alongside #24/#26 regardless of this bug.Fix directions
<br>→backslash fallback in writeParagraph: when attaching a spaces marker to a paragraph-first output line whose prose is exactly a checkbox shape and the paragraph is a list item's first child (p.Nodeparent chain answers this), fall back to the backslash spelling — render-preserving, one narrow position, style deviation only where the configured style cannot work.