module

Hwaro::Utils::FrontmatterScanner

Constants

TOML_FRONTMATTER_RE = /\A\+\+\+\s*\n(.*?\n?)^\+\+\+\s*$\n?/m

Front-matter block matchers shared by the read-only services (stats, validator, exporters, lister). Both capture the block body in group 1. The build's own parser (Processors::Markdown) uses its own variants that additionally capture the body.

YAML_FRONTMATTER_RE = /\A---\s*\n(.*?\n?)^---\s*$\n?/m
YAML_KEY_LINE_RE = /^[\p{L}_][\p{L}\p{N}_.-]*\s*:(\s|$)/

A top-level key: line — what separates broken YAML front matter from prose between two thematic breaks. Same pattern as Processors::Markdown::YAML_KEY_LINE_RE.

Instance methods

detect(content : String) : Tuple(Symbol, String) | Nil

The front-matter block at the top of content as {dialect, source}: {:toml, body} / {:yaml, body} (the text between the fences) or {:json, object} (the balanced {...} at byte 0), or nil when the file has none. Detection order TOML → YAML → JSON, the same as the build's parser, so every read-only tool agrees with the build about which dialect a file is in. Parsing (and its error policy) stays with the caller.

Source
find_json_end(content : String) : Int32 | Nil

Returns the end offset (exclusive) of the first balanced top-level JSON object at byte 0 of content, or nil if the input does not start with { or the braces never balance. Tracks string-literal state so braces inside quoted strings are ignored.

Source
json_start?(content : String) : Bool

True when content opens the way JSON front matter does: a { at byte 0 followed (after optional whitespace) by " (the first key) or } (an empty object). This is the build's own test (Processors::Markdown#json_front_matter_start?): a { also opens shortcodes ({{ … }}), Jinja tags ({% … %}) and attribute lists ({:.class}), which the build renders as body text. Treating those as front matter made the read-only tools disagree with the build — tool validate failed such a page with a JSON parse error.

Source
strip_frontmatter(content : String) : String

Strip front matter, if any. The TOML and YAML strips are mutually exclusive: chaining them would let the \A-anchored YAML pattern eat a body that opens with a thematic break (---\n…\n---) once the TOML front matter had already been removed, silently dropping the first block of the document.

A leading --- pair is only stripped when the build reads it as front matter (see yaml_front_matter?); a thematic break around prose stays part of the body, as it does in the build.

Source
yaml_front_matter?(block : String) : Bool

Whether the build treats the text between a leading --- pair as front matter (Processors::Markdown#parse): a mapping, an empty or comment-only block, or a block that fails to parse but carries a key: line (the build reports that as invalid front matter). Any other block — a list, a scalar, prose that is not valid YAML — is body text opening with a thematic break, and the build renders it.

Source
yaml_front_matter_like?(block : String) : Bool

True when a block that failed to parse as YAML still looks like front matter, so the failure is the author's broken front matter rather than prose after a thematic break.

Source