Skip to content

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_absent is now a non-fatal hint (read via quill.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 by QuillConfig::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-yaml opener 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 ~~~

- ~~~card-yaml
+ ~~~
  $quill: my_quill@1.0.0
  $kind: main
  title: Example
  ~~~

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 than card-yaml stays 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

  1. No edit is required for documents to keep parsing — ~~~card-yaml openers are still accepted.
  2. 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.
  3. 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

  1. Regenerate stored blueprint goldens — block openers change from ~~~card-yaml to ~~~.
  2. If a Quill.yaml body.example contains a literal ~~~-style code block, switch it to a backtick fence. Quill.yaml parsing now rejects a body.example line that opens a card-yaml block (a column-zero ~~~, a longer tilde run, or ~~~card-yaml), because it would corrupt the generated blueprint (diagnostic code quill::body_example_contains_fence).

Updating host code

  1. If you compare emitted markdown for equality or hash it, re-baseline against the bare ~~~ opener.
  2. No API changes: Document::from_markdown, to_markdown, and the typed accessors are unchanged.