/** * Fenced-code tracker — THE definition of "am I inside a code fence". * Server-safe: no React, no DOM. * * Lives in its own module because it is a GENERAL CommonMark fence machine * with two unrelated consumers: the heading scanner * (`utils/markdown-heading-id`) and the streaming block splitter * (`components/ui/markdown/streaming`). It used to live inside * `markdown-heading-id`, which meant a streaming renderer imported its fence * state machine from a module named after heading slugs. `markdown-heading-id` * re-exports these names so the public `utils` surface is unchanged. */ /** * CommonMark fenced-code opener/closer. Fence indent is capped at 3 spaces * (4+ is an indented code block, whose backticks are literal content), and the * run length is captured so a closer can be required to be at least as long as * its opener. Matched on the RAW line — `trimStart()` would let a fence inside * 4-space-indented code toggle the state. * * `\r`-TOLERANT BY CONSTRUCTION. The previous spelling ended `(.*)$`, and `.` * excludes `\r` while `$` (no `m` flag) anchors at end of input — so on a CRLF * document, split on `\n`, NO line ever matched and the tracker was completely * fence-blind: `['```js\r','const a = 1\r','```\r','after\r']` classified as * four `text` lines where the LF spelling gives `open/inside/close/text`. The * sanitizer's closer haystack then never blanked the fenced region, so a * `` written as a CRLF code sample satisfied `hasLaterCloser` and a * prose `