@quillmark/wasm 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,175 @@
1
+ # Changelog
2
+
3
+ ## v0.87.0 - 2026-06-01
4
+
5
+ Arrays become first-class typed fields via a required `items` element
6
+ schema, datetime is unified under a single `type: datetime` accepting the
7
+ full YAML-1.1-style timestamp range (`FieldType::Date` is gone), and object
8
+ zero values are now shape-valid. This release tightens schema-load
9
+ validation in several places — empty `properties` maps and deeper array
10
+ nesting are now rejected — and consolidates the example/default conformance
11
+ checks behind one shared primitive. Documentation now ships from GitHub
12
+ Pages instead of Read the Docs.
13
+
14
+ ### Breaking changes
15
+
16
+ These are schema-load cutovers for `Quill.yaml` authors; full before/after
17
+ steps are in `docs/migrations/0.86-to-0.87.md`.
18
+
19
+ - **Array fields now require an `items` element schema** (#672). Arrays
20
+ previously carried a single untyped `Array` type; scalar arrays were
21
+ never coerced or validated element-wise and were always annotated
22
+ `array<string>`. Every array field must now declare `items`, and schema
23
+ load rejects arrays without it. The bare-`properties`-on-an-array form
24
+ (the old "typed table") is **removed** in favor of
25
+ `items: { type: object, properties: … }`. Migration for a typed table:
26
+
27
+ ```yaml
28
+ # before
29
+ rows:
30
+ type: array
31
+ properties: { name: { type: string }, qty: { type: integer } }
32
+ # after
33
+ rows:
34
+ type: array
35
+ items:
36
+ type: object
37
+ properties: { name: { type: string }, qty: { type: integer } }
38
+ ```
39
+
40
+ A scalar array adds `items` directly, e.g.
41
+ `counts: { type: array, items: { type: integer } }`. Elements now coerce
42
+ and validate against `items` (failing at the indexed path, e.g.
43
+ `counts[1]`), and blueprint annotations reflect the element type
44
+ (`array<integer>`, `array<markdown>`, …). Bundled quills and the
45
+ `usaf_memo` golden schema are migrated.
46
+ - **`FieldType::Date` removed; use `type: datetime`** (#679). `type: date`
47
+ no longer exists. `type: datetime` now accepts the full range from a bare
48
+ `YYYY-MM-DD` date through RFC 3339 with offset (seconds optional, `T` or
49
+ space separator). Datetime values gain calendar validation (e.g. Feb 30
50
+ is now rejected), and JSON Schema output emits `format: date-time` for
51
+ all datetime fields. The WASM `FieldType` union drops `"date"`. The
52
+ blueprint hint is now `datetime<YYYY-MM-DD[Thh:mm:ss]>`.
53
+ - **Empty `properties: {}` on an object field is rejected** (#678). An
54
+ empty properties map carries no information (the only conforming value is
55
+ `{}`) and is almost always a mistake. It is now treated like a missing
56
+ `properties` key and surfaces `quill::object_empty_properties`.
57
+ - **Deeper array nesting is rejected** (#673). The documented "one level of
58
+ nesting" contract is now enforced in a single recursive pass, closing a
59
+ gap where `array<object<array>>` and `object<array>` were silently
60
+ accepted. A typed table row and a typed dictionary may carry scalar
61
+ columns/properties only; deeper shapes fail with
62
+ `quill::nested_array_not_supported`.
63
+
64
+ ### Behavioral changes
65
+
66
+ - **Object zero values are now shape-valid** (#677). `zero_value` returned
67
+ a bare `{}` for every object field, which failed validation on any object
68
+ with `properties` (each absent property reported as `MustFillUnset`), so
69
+ the zero-filled render path broke for object fields. An object with
70
+ `properties` now recurses, zero-filling each property to its own
71
+ type-empty leaf. `{}` remains the zero only for the property-less edge
72
+ case.
73
+ - **`example:` values are now validated** (#680). The conformance check for
74
+ `example`/`default` literals recurses into array items and object
75
+ properties and validates datetime format — capabilities the old
76
+ load-time path lacked, so previously-unvalidated `example:` values are
77
+ now caught.
78
+
79
+ ### Documentation & infrastructure
80
+
81
+ - **Docs hosting moved from Read the Docs to GitHub Pages** (#671). A new
82
+ `docs.yml` workflow builds MkDocs (strict build as a PR check) and
83
+ deploys to Pages on a published release; RCs are skipped. `.readthedocs.yaml`
84
+ is removed and homepage/User Guide links point at the Pages URL.
85
+ - **Canon + docs: partial documents are first-class citizens** (#670). The
86
+ docs and binding READMEs no longer claim Must Fill fields must be supplied
87
+ before shipping. The only hard render gate is well-formedness (values
88
+ coerce, no surviving `<must-fill>` sentinel); completeness is a hint
89
+ surfaced by the form view. The `format-designer/` docs tree is renamed to
90
+ `quills/`.
91
+ - A Migration section overview page was added and wired into the nav (#674).
92
+
93
+ ### Internal
94
+
95
+ - Example/default validation is consolidated behind a single
96
+ `validate_schema_literal` conformance core shared by `quillmark-core`
97
+ config loading and the CLI `validate` command, with author-friendly
98
+ diagnostics preserved (#680).
99
+ - Array and markdown handling collapse into recursive passes over the
100
+ schema in both schema-shape validation and the Typst markdown transform
101
+ (#673).
102
+ - Doc/comment fixes from the array-items review (#675).
103
+
104
+
105
+ ## v0.86.0 - 2026-05-31
106
+
107
+ Documents now render even when incomplete, the canonical card-yaml fence
108
+ becomes a bare `~~~`, and the way placeholder/illustrative values are
109
+ produced is reworked. This release also fixes two markdown→Typst
110
+ conversion bugs and stamps a PDF `/Producer` field.
111
+
112
+ ### Breaking changes
113
+
114
+ - **Bare `~~~` is now the canonical card-yaml fence** (was `~~~card-yaml`)
115
+ (#662). Existing `~~~card-yaml` documents still parse, but `to_markdown`
116
+ re-emits the bare `~~~` form, so a document's canonical bytes change on
117
+ its first re-emit (relevant if you content-hash or byte-compare emitted
118
+ markdown, or store blueprint goldens). A side effect: a column-zero
119
+ `~~~` fence in a prose body is now read as a card-yaml block — use a
120
+ backtick fence or a non-`card-yaml` info string (e.g. `~~~rust`) for a
121
+ literal code block. Full details and corpus-migration steps:
122
+ `docs/migrations/0.85-to-0.86.md`.
123
+ - **`fill_blueprint()` removed** from `quillmark_core` and `quillmark`,
124
+ along with its re-exports (#657, #665). Callers no longer post-process a
125
+ blueprint string: fillable/illustrative documents come from
126
+ `QuillConfig::example()`, and the render path fills placeholders itself
127
+ (see below).
128
+
129
+ ### Behavioral changes
130
+
131
+ - **Incomplete documents render instead of erroring** (#665). An absent
132
+ Must Fill field is no longer a render error. On the render path each
133
+ schema field resolves to its authored value, else its `default:`, else a
134
+ type-empty zero value — applied to the plate projection only, never
135
+ persisted to the document. Only malformed input stays fatal: a surviving
136
+ `<must-fill>` sentinel, or a value that won't coerce/validate.
137
+ `quill.form(doc)` still reports completeness independently of the render
138
+ gate.
139
+ - **`default` vs `example` clarified** (#665, #663, #658). `default` is the
140
+ value most authors want and is interpolated when a field is omitted (an
141
+ authored value always wins); `example` documents a field's shape only and
142
+ never renders into output. Preview and illustrative fills now draw from a
143
+ field's `example:` when present, falling back to the leanest type-valid
144
+ value (`""`, `0`, `false`, `[]`, `{}`, first enum variant, empty body).
145
+
146
+ ### Markdown → Typst fixes (#661)
147
+
148
+ - Code is now emitted as `#raw(...)` with a string literal instead of a
149
+ backtick fence. This fixes fenced or inline code whose content contained
150
+ a run of three-or-more backticks, which previously closed the block early
151
+ and rendered as markup.
152
+ - Ordered-list start numbers are preserved — a list written `3.` / `4.` now
153
+ renders starting at 3 instead of restarting at 1.
154
+
155
+ ### New API
156
+
157
+ - `QuillConfig::example()`, plus `example` getters on the Python and WASM
158
+ bindings (#665).
159
+ - `quillmark_core::zero_value` — the single source of truth for a field's
160
+ type-minimal value, shared by blueprint emission and the render path
161
+ (#665).
162
+ - `RenderOptions.producer` on the core, WASM, and Python render APIs (#656)
163
+ — overrides the PDF `/Info` `/Producer` string, which now defaults to
164
+ `Quillmark <version>` on every Typst-rendered PDF.
165
+
166
+ ### Other fixes
167
+
168
+ - PDF rendering folds the `/Producer` stamp and the signature-field
169
+ AcroForm injection into a single incremental-update pass, preserving
170
+ Typst's `/Creator` (#656).
171
+ - `usaf_memo`: the signature widget is now overlaid at the 4.5in signature
172
+ block (AFH 33-337) instead of the 1in left margin, and no longer consumes
173
+ layout flow that could push the block out of position (#660); empty
174
+ signature fields no longer carry the `APPEND_ONLY` flag (#654).
175
+
package/README.md CHANGED
@@ -34,7 +34,7 @@ import { Document, Quillmark } from "@quillmark-test/wasm";
34
34
  const engine = new Quillmark();
35
35
  const quill = engine.quill(tree);
36
36
 
37
- const markdown = `~~~card-yaml
37
+ const markdown = `~~~
38
38
  $quill: my_quill
39
39
  $kind: main
40
40
  title: My Document
@@ -249,10 +249,11 @@ canvas.style.height = `${result.layoutHeight}px`;
249
249
  A field's *cell* is inferred from whether its schema declares a `default:`:
250
250
 
251
251
  - **Must Fill** (no `default:`) — `quill.blueprint` renders `<must-fill>`
252
- in the value cell, and `quill.render(doc)` throws with
253
- `validation::must_fill_absent` when the field is absent at
254
- validate time, or `validation::must_fill_sentinel` when the
255
- `<must-fill>` sentinel survives into the document.
252
+ in the value cell. An absent Must Fill field is a non-fatal signal
253
+ (`validation::must_fill_absent`) the render path zero-fills it
254
+ silently. A surviving `<must-fill>` sentinel is fatal
255
+ (`validation::must_fill_sentinel`). Partial documents are
256
+ first-class; `quill.render(doc)` only throws for malformed input.
256
257
  - **Endorsed** (with `default:`) — `quill.blueprint` renders the
257
258
  default value followed by a `; delete-ok` annotation, and the default
258
259
  is used when the document omits the field.
@@ -316,12 +317,19 @@ try {
316
317
 
317
318
  ## Notes
318
319
 
319
- - Parsed markdown requires a root `~~~card-yaml` block with a
320
- `$quill` system-metadata line. Empty input surfaces a dedicated
320
+ - Parsed markdown requires a root `~~~` block (a bare three-tilde fence;
321
+ the legacy `~~~card-yaml` opener is still accepted but non-canonical)
322
+ with a `$quill` system-metadata line. Empty input surfaces a dedicated
321
323
  "Empty markdown input cannot be parsed" message.
322
324
  - QUILL mismatch during `quill.render(parsed)` is a warning (`quill::ref_mismatch`), not an error.
323
325
  - Output schema APIs are no longer engine-level in WASM.
324
326
 
327
+ ## Changelog
328
+
329
+ See the [changelog](https://github.com/quillmark-org/quillmark/blob/main/CHANGELOG.md)
330
+ and the [GitHub Releases](https://github.com/quillmark-org/quillmark/releases) page for
331
+ release notes and version history.
332
+
325
333
  ## License
326
334
 
327
335
  Apache-2.0
package/bundler/wasm.d.ts CHANGED
@@ -113,10 +113,11 @@ export interface QuillCardBody {
113
113
  * without a `default` is **Must Fill** (the blueprint carries a
114
114
  * `<must-fill>` sentinel and validation reports
115
115
  * `validation::must_fill_absent` if the field is absent at validate
116
- * time). There is no separate `required` axis.
116
+ * time a non-fatal signal, since the render path zero-fills an absent
117
+ * field). There is no separate `required` axis.
117
118
  */
118
119
  export interface QuillFieldSchema {
119
- type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "markdown";
120
+ type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "datetime" | "markdown";
120
121
  description?: string;
121
122
  default?: unknown;
122
123
  example?: unknown;
@@ -234,6 +235,7 @@ export interface RenderOptions {
234
235
  format?: OutputFormat;
235
236
  ppi?: number;
236
237
  pages?: number[];
238
+ producer?: string;
237
239
  }
238
240
 
239
241
  export interface RenderResult {
@@ -427,6 +429,13 @@ export class Quill {
427
429
  */
428
430
  readonly backendId: string;
429
431
  readonly blueprint: string;
432
+ /**
433
+ * The `example` reference document — the illustrative "show me a
434
+ * filled-out one." Each field renders its `example:`, else its
435
+ * `default:`, else the type-empty zero value, with no `<must-fill>`
436
+ * sentinels. See `prose/canon/BLUEPRINT.md`.
437
+ */
438
+ readonly example: string;
430
439
  /**
431
440
  * Identity snapshot of the `quill:` section of `Quill.yaml`, plus
432
441
  * `supportedFormats` and any extra `quill:` keys.
@@ -664,6 +664,29 @@ export class Quill {
664
664
  wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
665
665
  }
666
666
  }
667
+ /**
668
+ * The `example` reference document — the illustrative "show me a
669
+ * filled-out one." Each field renders its `example:`, else its
670
+ * `default:`, else the type-empty zero value, with no `<must-fill>`
671
+ * sentinels. See `prose/canon/BLUEPRINT.md`.
672
+ * @returns {string}
673
+ */
674
+ get example() {
675
+ let deferred1_0;
676
+ let deferred1_1;
677
+ try {
678
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
679
+ wasm.quill_example(retptr, this.__wbg_ptr);
680
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
681
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
682
+ deferred1_0 = r0;
683
+ deferred1_1 = r1;
684
+ return getStringFromWasm0(r0, r1);
685
+ } finally {
686
+ wasm.__wbindgen_add_to_stack_pointer(16);
687
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
688
+ }
689
+ }
667
690
  /**
668
691
  * The schema-aware form view of `doc`. Read-only snapshot at call time;
669
692
  * subsequent edits to `doc` require calling `form` again.
Binary file
@@ -40,6 +40,7 @@ export const quill_backendId: (a: number, b: number) => void;
40
40
  export const quill_blankCard: (a: number, b: number, c: number, d: number) => void;
41
41
  export const quill_blankMain: (a: number, b: number) => void;
42
42
  export const quill_blueprint: (a: number, b: number) => void;
43
+ export const quill_example: (a: number, b: number) => void;
43
44
  export const quill_form: (a: number, b: number, c: number) => void;
44
45
  export const quill_metadata: (a: number) => number;
45
46
  export const quill_open: (a: number, b: number, c: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/wasm",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "description": "WebAssembly bindings for quillmark",
5
5
  "type": "module",
6
6
  "license": "MIT OR Apache-2.0",
@@ -16,7 +16,8 @@
16
16
  "bundler/wasm_bg.js",
17
17
  "bundler/wasm_bg.wasm.d.ts",
18
18
  "bundler/wasm.js",
19
- "bundler/wasm.d.ts"
19
+ "bundler/wasm.d.ts",
20
+ "CHANGELOG.md"
20
21
  ],
21
22
  "main": "./bundler/wasm.js",
22
23
  "module": "./bundler/wasm.js",