Skip to content

Mark front matter entries of unknown value in YamlParser instead of inferring them in markanywhere-html #85

Description

@morisil

Follow-up to #82.

Problem

Whether a front matter entry's value is known is a fact of the YAML parse,
yet markanywhere-html rebuilds it from the shape of the event stream in FrontMatterEntryReader:
text at the frontmatter root that starts with indentation continues the entry before it,
text inside an entry is its scalar value,
and a verbatim line opening with a key defines an entry.

The shape is ambiguous, so every new verbatim shape needs another special case there and in EnsureFrontmatterTitle (opensWithVerbatimLine, keepingFirstSlot).
Several review rounds on #82 kept finding new shapes rather than new classes of bug.

Proposed fix

Have YamlParser mark an entry whose value is incomplete or verbatim
(e.g. an attribute on the entry mark),
so FrontMatterEntry.isHeadMetadata becomes a plain check and the html module stops guessing.

Symptoms (on the #82 branch)

The PR for #82 closes 1–3 conservatively:
the reader treats such an entry's value as unknown (no <title> / <meta>, kept as content by ensureFrontmatterTitle) instead of reading a wrong one.
The heuristic is "text inside an entry that starts with indentation and ends with \n", so a quoted scalar of that exact shape (k: " x\n") is also read as unknown.

  1. A plain scalar continued on indented lines was read as its first line only:
    title: A long\n title → <title>A long</title> (readers: "A long title").
  2. A verbatim line under a bare key: was read as the value:
    title:\n [a:, b] → <title>[a:, b]</title> (readers disagree on this shape).
  3. Indented verbatim lines under a bare key: leaked their indentation into the value:
    description:\n first line\n second → content=" first line\n second\n".
  4. Still open: the reader assumes one text event per YAML line.
    After mergeAdjacentText a verbatim title: line merged into a preceding verbatim line is missed,
    so ensureFrontmatterTitle derives a second title: — a duplicate key js-yaml (Eleventy, Astro, Gatsby) rejects, losing the whole front matter.

Other known gaps (smaller, same area)

  1. opensWithVerbatimLine treats any verbatim line as blocking front matter detection, including a key-shaped one isYamlKeyLine accepts,
    so ---\nTitle:\nbar: [a:, b]\n--- keeps the empty Title: for no reason.
  2. keepingFirstSlot can move an entry left unclosed (stream truncated inside the frontmatter) to the first slot;
    closed() then balances by count, nesting the following entries inside it.
  3. closed() pops its open-mark stack on any Unmark without checking the name,
    so a crossed upstream stream (mark h1, mark em, unmark strong) gets the wrong closers appended.
  4. !opensWithVerbatimLine(emptyMap(), emptyList()) recomputes a property of the closed frontmatter on every flush;
    computing it once in judgeFrontmatter would also make the rewrite condition easier to follow.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions