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 |