Skip to content

0.116 → 0.117 — example: and body.example leave the quill schema; a Quill.yaml declaring either fails to load; @latest is not a $quill selector; an empty or tagged version and a main card kind fail to load

The break no type checker reports: a Quill.yaml declaring example: fails to load. An example: on a field, a nested property, an array's items, a matrix column or a variant cell fails quill::field_parse_error, and a body.example on main or a card kind fails quill::invalid_body. Every document pinned to such a quill stops rendering until the quill is edited. quillmark validate <quill_dir> reports each field and body declaring one, in one pass.

The rule behind it: a slot declares one value, its default:. Its title and description are text, not values. See Migrating an example:.

Three more Quill.yaml shapes that loaded now fail: an empty version: "", a YAML-tagged version such as version: !!float 1.10, and a card kind named main. See Quill headers the load refuses.

A document break too: $quill: name@latest fails to parse. See @latest is not a selector.

And quillmark validate reads a file it ignored: an example.md at the quill root is the quill's example, and any diagnostic on it fails the quill. See The example document.

Break Surface Action
example: on a field declaration, at any depth, is an unknown key: the load fails quill::field_parse_error Quill.yaml Delete the key; fold a format hint into description
body.example is an unknown key: the load fails quill::invalid_body, hinting Valid keys under 'body' are: enabled. Quill.yaml Delete the key
quill::example_type_mismatch, example_not_in_enum, example_format_violation, example_on_namespace, example_over_max and body_example_contains_fence, and the warning quill::body_example_unused, are deleted diagnostics Drop the routes; the load fails on the key first
quill::richtext_example_import is quill::richtext_default_import: a richtext default: that fails to import diagnostics Route on the new code
The quill::optional_default hint reads Drop the `?` to always render the default, or drop the default to render `none`., and names no example: diagnostics None
The blueprint writes no # e.g. line above a field and no # body e.g. line closing a card's payload. A kind taking a body has no body line; one under body.enabled: false still closes with # no body blueprint A consumer reading an example off the blueprint reads the field's description line instead
A column-bearing matrix keeps its # e.g. line, the one left: each column shows its default:, else its container shape, else its type expression, where a column's example: came first blueprint None
schema(), schema.yaml, and WASM and Python quill.schema carry no example on a field or a card's body schema, WASM, Python Drop the read
QuillFieldSchema.example and QuillCardBody.example are deleted WASM Drop the read
FieldSchema::example and BodyCardSchema::example are deleted Rust Drop the read; a FieldSchema or BodyCardSchema literal drops the field

Migrating an example:

A sample value has no schema slot: delete it. A filled-in sample of the whole quill is its example document. A format hint becomes description text:

# 0.116
signer:
  type: string
  example: FIRST M. LAST, Capt, USAF

# 0.117
signer:
  type: string
  description: Name as signed, as in FIRST M. LAST, Capt, USAF.

A body declares no description. A rule for writing the body is the card's own description: text, which the blueprint prints on the card's $kind line. Starter text for a body goes in a template document's own body, or, for a card seed_card adds, in the main card's $seed.<kind>.$body.

The blueprint loses the lines the key fed:

# 0.116 blueprint
# The recipient's name and full mailing address.
# e.g. [Mr. John Doe, 123 Main St]
recipient: # array<string>
# body e.g. "Dear Dr. Smith,\n\nI am writing to..."
~~~

# 0.117 blueprint
# The recipient's name and full mailing address.
recipient: # array<string>
~~~

Seeding is unchanged: it committed no example: in 0.116 either.

Quill headers the load refuses

Each shape below loaded in 0.116 and fails in 0.117. None could hold what it seemed to: an empty version skipped the pin a document's $quill selector is checked against, a tagged number reached the loader as a float whose source text is gone (1.10 read as 1.1), and $kind: main never parses, so a main kind could hold no card.

Break Surface Action
version: "" fails quill::invalid_version Quill.yaml Write the version, MAJOR.MINOR or MAJOR.MINOR.PATCH
A tagged version (version: !!float 1.10) fails quill::invalid_version, hinting Write the version as untagged text in semver format: '1.0' or '1.0.0'. Quill.yaml Drop the tag; quote the version if in doubt
A card kind named main under card_kinds: fails quill::invalid_card_name Quill.yaml Rename the kind; fields for the document root go under the top-level main:

Two document-side changes ride with them:

Change Surface Action
A title key on a matrix member (qualifications: { flight_cc: { held: true, title: X } }) warns validation::unknown_field at <field>.<member>.title. The plate reads the roster's title either way, as in 0.116; quillmark check --strict now fails such a document markdown, diagnostics Remove the key: the member's title is the quill's
quillmark check locates a diagnostic in the file it came from, where every location read input.md, and a missing path draws cli::unreadable_document and the remaining paths are still checked CLI A script matching input.md in check output matches the document's path

The example document

example.md at the quill root, beside Quill.yaml, is the quill's example: a filled-in page whose values are made up. Quill.yaml declares nothing about it, and the load never reads it. Quill::example_document(), WASM Quill.exampleDocument() and Python Quill.example_document() hand it out pinned to the quill's name@version; None / undefined means the quill has none.

Change Surface Action
quillmark validate reads, validates and renders a root example.md, and fails the quill on any diagnostic it carries, a warning included (cli::example_not_clean, then cli::example_render_failed for a render that fails) CLI A quill keeping a root example.md for another purpose renames it
An example whose $quill is not the quill's bare name (name@1, another quill) fails quill::example_reference diagnostics Write $quill: <name> with no selector: the quill pins it

@latest is not a selector

$quill: name@latest fails as parse::invalid_quill_reference. It was a second spelling of the bare name: both matched any version, and to_markdown wrote either back as name. A selector is MAJOR, MAJOR.MINOR or MAJOR.MINOR.PATCH, digits only, the grammar @quillmark/quiver's parseQuillRef already enforces.

The fix is to delete @latest. It changes no pairing: the bare name matches every version @latest did.

Break Surface Action
A $quill reference ending @latest fails as parse::invalid_quill_reference, from markdown, a card wire's quill and a stored row's $quill markdown, stored documents, diagnostics Write name for name@latest. No row the engine stored carries @latest: it wrote the bare name
VersionSelector::Latest is VersionSelector::Any, and QuillReference::latest(name) is deleted Rust Rename the arm; build with QuillReference::new(name, VersionSelector::Any)
VersionSelector no longer implements Display: Latest displayed @latest, and Any has no written form outside a reference Rust None for QuillReference, whose Display still writes name or name@selector. A caller formatting a lone selector matches on it and words Any itself
quill_ref_hint(), WASM Document.quillRefHint() and Python Document.quill_ref_hint() drop @latest from the grammar they state WASM, Python, diagnostics None

To find and fix it:

grep -rlE '^\$quill:[[:space:]]*["'"'"']?[a-z_][a-z0-9_]*@latest' .
sed -i -E 's/^(\$quill:[[:space:]]*["'"'"']?[a-z_][a-z0-9_]*)@latest/\1/' <file>

The embedded font

A quill shipping no fonts renders in Roboto, where it rendered in Figtree. Figtree has no prime, so a " or ' after a digit in richtext, which Typst's smart quotes draw as ″ or ′, rendered as an empty box.

Change Surface Action
A quill with no .ttf or .otf under assets/fonts/ or packages/ renders in variable Roboto, upright and italic, at any weight from 100 to 900. Its text reflows, and bold italic is a true face rendered output A quill that must keep Figtree ships its faces under assets/fonts/
A plate naming "Figtree" without shipping it draws Typst's unknown font family warning and renders in Roboto Typst, diagnostics Ship Figtree, or drop the name
quillmark workspace exports fonts/Roboto.ttf and fonts/Roboto-Italic.ttf for such a quill, where it exported fonts/Figtree-*.ttf CLI None