Hwaro::Content::Processors::FenceTracker
CommonMark-faithful fence state machine:
- An opener is a run of 3+ backticks or tildes indented at most 3 spaces. A backtick fence's info string may not contain a backtick (CommonMark treats such a line as inline code, not a fence).
- The closer must use the same character, be at least as long as the
opener, and carry nothing but whitespace after the run. A shorter
run, the other character, or trailing text is fence content —
this is what keeps
examples nested inside ```` fences (and "ruby" lines inside an open fence) verbatim. - Lines indented 4+ spaces (or starting with a tab) are indented-code context where ```/~~~ is literal text, never a delimiter. Whole indented-code runs are tracked as verbatim too: a 4+-indented non-blank line opens a run when nothing before it can absorb the indent — after a blank line, or directly after an ATX heading, which CommonMark (and Markd) let indented code follow with no blank line in between. Inside a list item the run opens only four columns beyond the item's content column (tabs expanded to 4-column stops), and it survives blanks until the first non-blank line back under that column.
- List items are tracked as a stack of content columns, one entry
per open item, at ANY indentation: a nested
- bsits wherever its parent's content puts it, four spaces or a tab included. The stack errs toward keeping items open — a marker always pushes, an item is only popped by a marker left of its content or by a non-blank line left of its content after a blank line (the one case where Markd certainly closes it). A stale item can only make a line look less like code (today's under-protective behaviour); a missed one would make real list content look like code and silently skip every extension on it. Items are keyed by blockquote depth, so a quote inside an item never pops the item, while a>marker left of an item's content closes it. Column arithmetic mirrors Markd, including its quirks (tabs after a list marker and after>are measured from Markd's own column, not the true one). Lines inside a generic HTML block (<div>… blank line,<!--…-->) never open indented code, since Markd passes them through as raw HTML; the block ends where Markd's does, including when its list item or quote ends. Walkers built withraw_html_code: falseskip this, like raw code blocks. Known limit: a fence closer followed directly by indented code opens no run. - Fences inside blockquotes (
> ```) are tracked too: the leading>markers are stripped before the opener/closer rules apply, and the marker depth is remembered. Because CommonMark gives fenced code no lazy continuation, a line missing the fence's markers ends the quote — and the fence with it — and is re-evaluated as a potential new opener. Inside an open fence, only the fence's own marker depth is stripped, so a> ```' line stays literal content of a top-level fence. Known limits: fences at 4+ absolute indent inside list items are still invisible, and tab-formed>markers (>\t) are not recognized.
Constants
An ATX heading at up to 3 spaces indent: 1-6 # followed by a
space/tab or nothing but the line ending. Only used to let an
indented-code run open on the line right after a heading — the
blank line the run otherwise needs is what CommonMark requires to
keep indented code from interrupting a paragraph, and a heading
is not a paragraph. Markd opens the code block there, so without
this the walkers transformed lines Markd renders verbatim (a
shortcode expanded on such a line left an escaped placeholder
comment stranded inside <pre><code>). The other paragraph-ending
blocks (setext underlines, thematic breaks, HTML blocks) are not
recognized here: they are ambiguous line-locally, and missing them
only keeps today's under-protective behavior.
What ends the HTML blocks that run to a marker, not a blank line
(CommonMark types 2-5), keyed by @html_block.
Starts of CommonMark HTML blocks that run to a blank line (Markd's HTML_BLOCK_OPEN types 6 and 7, the latter with possessive quantifiers so a long line cannot exhaust the PCRE JIT stack).
A bullet or ordered-list marker, matched after the line's leading
whitespace (so at any indentation — which list it belongs to is
decided by the item stack), followed by a space/tab or nothing
(CommonMark's empty item). Over-matching (a * * * thematic break,
a 2. that cannot interrupt a paragraph) only pushes a stale item,
which errs toward "not code".
These CommonMark raw HTML blocks (type 1) leave their contents
uninterpreted. Preprocessors must treat them like code so math,
footnotes, and inline markup do not rewrite script/style or
preformatted text. The tag name must end at whitespace, > or the
line end — <style-guide> or <pre-view> is an ordinary element —
and the block ends at the first line containing ANY of the closing
tags, whichever element opened it.
Constructors
raw_html_code: false turns off raw-HTML code-block tracking and
generic HTML-block tracking.
Only the Markdown-extension walkers treat <pre>/<script>/
<style>/<textarea> blocks as opaque; shortcode expansion (and
the checks that must agree with it) keeps its long-standing
behaviour of seeing inside. html_blocks: false keeps the raw
code blocks opaque but turns generic HTML-block tracking off
(definition-list extraction, which escapes raw-HTML term lines).
Instance methods
Feed the next line (with or without its trailing newline). Returns true when the line must pass through verbatim: a fence delimiter or any line inside an open fence.
The last line fed was raw HTML to Markd: it opened or continued a generic HTML block (no inline parsing happens there).
The last line fed opened a list item that Markd starts: a list marker, unless it sits in the open paragraph's container and is an item CommonMark forbids from interrupting a paragraph (an empty one, or an ordered one not starting at 1), which is continuation text.