0.85.0 → 0.86.0 — Partial documents, bare ~~~ fence, zero-fill render¶
0.86.0 ships two significant behavioural changes: incomplete documents now render without error, and the canonical card-yaml fence changes to bare ~~~.
Partial documents are first-class (zero-filled render)¶
An absent Must Fill field is no longer a render error. On every render, each absent schema field resolves by precedence: authored value → schema default: → type-empty zero value. This fill lives only in the plate-JSON projection and is never persisted.
validation::must_fill_absentis now a non-fatal hint (read viaquill.form(doc)for doneness), not a render gate.- A surviving
<must-fill>sentinel is still fatal (validation::must_fill_sentinel). fill_blueprint()is removed — it is superseded byQuillConfig::example()and the render path itself.
No migration is required if your code simply calls render() — incomplete documents that previously errored now succeed. If you used validation::must_fill_absent as a render gate (e.g. by catching it and blocking output), switch to quill.form(doc) and inspect fields with source === "missing" / source == "missing".
Bare ~~~ is the canonical card-yaml fence¶
0.86.0 makes the card-yaml info string optional and non-canonical. The
canonical block opener is now a bare ~~~ (three tildes, no info string),
matching the closer. The legacy ~~~card-yaml opener is still accepted on
input, so existing documents keep parsing — but toMarkdown now emits the
bare ~~~ form, and authoring surfaces (blueprints, FORMAT_RULES,
examples) advertise only ~~~.
This is a behavioural change for:
- Anyone who content-hashes, content-addresses, or byte-compares
emitted markdown — a document with a
~~~card-yamlopener re-emits with a bare~~~opener, so its canonical bytes change on first re-emit. - Stored blueprint goldens — generated blueprints now open blocks with
~~~instead of~~~card-yaml. - Authors who use bare
~~~fenced code blocks in prose bodies (see below).
It is not a breaking change for parsing: every ~~~card-yaml document
from 0.85 still parses, and the typed Document model is unchanged.
What changed¶
Canonical opener is bare ~~~¶
Both forms parse to the same Document. The legacy ~~~card-yaml opener
converges to bare ~~~ on the first toMarkdown round-trip (the same
"accept, don't emit" treatment already given to the --- root-block
alias).
A bare ~~~ block is now a card-yaml block¶
A column-zero ~~~ fence (three or more tildes, with a blank line above
it and a matching closer) opens a card-yaml block. This is a declared
deviation from CommonMark, in the same spirit as the --- root-block alias.
The canonical opener is three tildes; a longer run is accepted and re-emits
as ~~~ (its closer must be at least as long, per CommonMark).
The consequence: a ~~~-fenced code block in a prose body is now
interpreted as a card-yaml block instead of a code block — and adding more
tildes does not escape it. To write a literal fenced code block, use:
- a backtick fence —
``` … ```(the escape hatch) - a language info string —
~~~rust … ~~~(a~~~fence whose info string is anything other thancard-yamlstays an ordinary code block)
Backtick fences and language-tagged ~~~ fences are unaffected. An indented
~~~ (1–3 leading spaces) also stays an ordinary code block — card openers
are at column zero.
Updating a document corpus¶
- No edit is required for documents to keep parsing —
~~~card-yamlopeners are still accepted. - To converge a corpus onto the canonical form, parse and re-emit each
document (
Document::from_markdown(src).to_markdown()); the opener normalises to bare~~~automatically. - Search prose bodies for
~~~code fences and convert them to backtick fences. A column-zero~~~block with a blank line above it will otherwise be parsed as a card-yaml block (adding more tildes does not help — only backticks or a language info string do).
Updating a quill bundle¶
- Regenerate stored blueprint goldens — block openers change from
~~~card-yamlto~~~. - If a
Quill.yamlbody.examplecontains a literal~~~-style code block, switch it to a backtick fence.Quill.yamlparsing now rejects abody.exampleline that opens a card-yaml block (a column-zero~~~, a longer tilde run, or~~~card-yaml), because it would corrupt the generated blueprint (diagnostic codequill::body_example_contains_fence).
Updating host code¶
- If you compare emitted markdown for equality or hash it, re-baseline
against the bare
~~~opener. - No API changes:
Document::from_markdown,to_markdown, and the typed accessors are unchanged.