Hwaro::Content::Processors::Markdown
Markdown processor implementation
Constants
Regex for matching h1-h6 tags with IDs to insert anchor links.
Attribute scans here and below are quote-aware (a > inside a
quoted value, e.g. title="a > b", is legal HTML5 and must not end
the tag) and the id key uses a (?<![\w-]) guard so data-id=
never counts as the element's id. Possessive, so a long unquoted
value (an inline data-x=…) does not exhaust the PCRE JIT stack:
the prefix stops only at an i that starts a non-empty id="…",
the first one the lazy (?:…)*?id="…" scan would have taken.
Apply emoji shortcode conversion to HTML text, skipping code, raw-text, math and mermaid elements (see EMOJI_SKIP_RE).
Scans by BYTE offset rather than char index. The tag/fence markers
('<', '>', '<code', '<pre', '', '') and the ':' shortcode
delimiters are all ASCII, so byte offsets land exactly on the same
boundaries even for UTF-8 text. Char-indexed scanning (html[pos],
html.index(_, pos)) is O(n) per access on any string containing a
multibyte codepoint, which turned this loop into O(n^2) — a single
accented/CJK character on a long page caused a ~1500x slowdown.
Regex for post_process_html — lightweight replacements for XML.parse_html Matches
…
through…
, capturing tag name, level digit, attributes, and inner HTML The inner group is.*?, not .+?: an EMPTY heading (## with no
text, or one whose only content was a stripped {#id} block) must
still match on its own. With .+? the empty <h2></h2> could not
match, so the scan slid on and paired that opening tag with the NEXT
heading's </h2> — handing the empty heading the following
heading's id and leaving the real one with none, which also broke
the render-hooks convergence invariant (HookedRenderer#heading gets
this right).
Extracts id="value" from an attribute string
Matches <img ...> tags that do NOT already have a loading= attribute
(the lookahead is quote-aware too, so a loading= sitting after a
quoted > is still seen, and data-loading= doesn't count).
Both scans are possessive, so a long unquoted value (an inline
src=data:…) does not exhaust the PCRE JIT stack: the lookahead
stops only at an l that starts loading=, and the capture stops
at the whitespace / / before the closing > as the lazy
(?:…)*?\s*\/?> did.
Known front-matter keys (shared between TOML, YAML, and JSON parsers). Using a Set for O(1) lookup instead of Array#includes? O(n).
Array-typed front matter keys that are NOT taxonomies. These are excluded from automatic taxonomy extraction.
Regex for TOML front matter
Regex for YAML front matter
A top-level key: line is what distinguishes broken front matter
(worth a hard error) from a document that merely opens with a ---
thematic break (whose first block may fail YAML parsing entirely).
\p{L} so non-ASCII keys (e.g. Korean 제목:) count as front
matter too — otherwise their invalid-YAML blocks silently render
as body text instead of erroring.
Instance methods
A front-matter value as page.extra stores it (see
extract_extra_value), for callers outside the parser.
Returns parsed metadata and content
Renders Markdown to HTML and generates a Table of Contents Returns {html_content, toc_headers} @param highlight - whether to enable syntax highlighting for code blocks @param safe - if true, raw HTML will not be passed through (replaced by comments) @param lazy_loading - if true, adds loading="lazy" to img tags @param emoji - if true, converts emoji shortcodes to emoji characters @param hooks - render-hook context; nil (the default) renders exactly as before this parameter existed.
Render with anchor links inserted into headings
The closest of candidates to key within Levenshtein distance 2
(but not key itself), or nil. Also the "did you mean" of the
[[content.schema]] strict unknown-key error.