@quillmark/wasm 0.94.0 → 0.96.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 +71 -318
- package/README.md +60 -43
- package/backends/pdfform/wasm.d.ts +361 -256
- package/backends/pdfform/wasm.js +1 -1
- package/backends/pdfform/wasm_bg.js +532 -458
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +25 -25
- package/backends/typst/wasm.d.ts +361 -256
- package/backends/typst/wasm.js +1 -1
- package/backends/typst/wasm_bg.js +532 -458
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +25 -25
- package/core/wasm.d.ts +346 -242
- package/core/wasm.js +1 -1
- package/core/wasm_bg.js +518 -445
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +25 -25
- package/package.json +1 -1
- package/runtime/runtime.d.ts +205 -37
- package/runtime/runtime.js +214 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,324 +1,71 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v0.
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- core:
|
|
10
|
-
- core
|
|
11
|
-
-
|
|
12
|
-
- core
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- Reject
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
- feat(wasm): setCardBody — corpus writer for a non-main card body (#892)
|
|
68
|
-
- remove(core,richtext,wasm)!: delete the incremental-edit surface (#886)
|
|
69
|
-
- test(wasm): fix two applyFieldDelta tests left stale by the #881 un-gate
|
|
70
|
-
- feat(regions): field_boxes helper + CorpusHit granularity signal (#884)
|
|
71
|
-
- fix(core,wasm): resolve lint CI failure + re-sync applyFieldDelta type after merge
|
|
72
|
-
- wasm/canvas: report clamp on PaintResult; document paint compositing constraints
|
|
73
|
-
- fix(wasm): make applyFieldDelta and supportsCanvas types honest about their domain
|
|
74
|
-
- docs: migration guide for the richtext field write-surface unification (#881)
|
|
75
|
-
- richtext: un-gate applyFieldDelta to richtext fields (step 6)
|
|
76
|
-
- wasm: setRichtextField / updateCardRichtextField + per-field markdown getter (step 5)
|
|
77
|
-
- richtext: emit projects corpus fields to markdown; wire/DTO lossless (steps 2-4)
|
|
78
|
-
- richtext: Card::set_field_richtext writer + corpus read-back (step 1)
|
|
79
|
-
- fixtures: table_demo Quill + end-to-end table render test; document pdfform limit
|
|
80
|
-
- richtext: property-test structured tables through normalize + round-trip
|
|
81
|
-
- richtext: in-cell images degrade honestly instead of silent-Lossless
|
|
82
|
-
- richtext: canonical table shape — validate invariants, repair in normalize
|
|
83
|
-
- test: drop two redundant inline tests; dense-prose the runtime edit-surface note
|
|
84
|
-
- Prune landed simplification entries from the backlog
|
|
85
|
-
- Silence clippy nits in span_scan walk refactor
|
|
86
|
-
- test(wasm): keep runtime edit-surface guard focused on the #876 methods
|
|
87
|
-
- docs: fix rustdoc intra-doc links to satisfy the -Dwarnings lint gate
|
|
88
|
-
- Filter locate's glyph walk to the target segment
|
|
89
|
-
- Share frame-walk geometry between region scan and corpus walk
|
|
90
|
-
- feat(wasm): expose incremental editor edit surface through runtime (#876)
|
|
91
|
-
- Skip props re-clone in normalize when already key-sorted; document R2 hazard
|
|
92
|
-
- Carry the <u>/Strong distinction instead of re-sniffing source
|
|
93
|
-
- feat(typst): add plaintext(field) projection helper + document richtext migration hazard (#873)
|
|
94
|
-
- Lift island mark-dispatch out of model into serial
|
|
95
|
-
- Build canonical richtext tree once via move-based key sort
|
|
96
|
-
- feat(wasm): add setBody(corpus) mutator on Document (#874)
|
|
97
|
-
- Dedup emit_inline mark partition into wraps_and_codes
|
|
98
|
-
- fix(typst): lower richtext(inline) fields to inline content (#872); fix wasm TS types (#875)
|
|
99
|
-
- Remove unused ChangeLog/session forward surface
|
|
100
|
-
- Cut over-engineered simplification findings; refresh drifted citations
|
|
101
|
-
- docs(simplifications): remove the addressed findings
|
|
102
|
-
- docs(simplifications): record the sync-twins deferral rationale
|
|
103
|
-
- refactor(typst,richtext): dedup container dispatch and the #846 clip
|
|
104
|
-
- refactor(core): one shared decoder for the dual-shape richtext seam
|
|
105
|
-
- refactor(richtext): make apply_field_change all-or-nothing
|
|
106
|
-
- refactor(core): single carrier for the richtext inline flag
|
|
107
|
-
- refactor(richtext): drop unused usv UTF-16 helpers and content_key alias
|
|
108
|
-
- refactor: apply low-risk simplifications from prose/simplifications
|
|
109
|
-
- docs: record simplification-review findings in prose/simplifications/
|
|
110
|
-
- fix(richtext): apply a short field delta leniently (auto-append remainder)
|
|
111
|
-
- Trim unused test-only public methods from core
|
|
112
|
-
- docs(core,typst): dense-prose pass on comments
|
|
113
|
-
- docs(richtext): dense-prose pass on comments
|
|
114
|
-
- docs(core): update QuillValue fill-setter reference after set_fill removal
|
|
115
|
-
- Remove more dead/redundant logic
|
|
116
|
-
- docs: remove stale info across canon, docs, and comments
|
|
117
|
-
- test: remove redundant and low-value tests across the workspace
|
|
118
|
-
- Remove dead and redundant logic
|
|
119
|
-
- fix(docs): resolve broken intra-doc links (cargo doc -Dwarnings)
|
|
120
|
-
- typst/richtext: address #855 cleanup findings
|
|
121
|
-
- Fix #851 follow-up: transactional applyFieldDelta and fail-closed invalidation
|
|
122
|
-
- richtext: fix issue #854 cleanup findings
|
|
123
|
-
- fix(session): close the three delta-protocol lifecycle gaps (#851)
|
|
124
|
-
- Fix low-risk API-surface findings from #856
|
|
125
|
-
- fix(wasm): strip unreachable delta-API types from public runtime.d.ts (#850)
|
|
126
|
-
- chore: ignore dist/, .vite/, test-results/ to prevent build-artifact commits
|
|
127
|
-
- fix(richtext): cap single-line char diff to avoid quadratic blowup (#849)
|
|
128
|
-
- fix(richtext): balance markdown export for overlap, escape `&` and trailing heading `#` (#848)
|
|
129
|
-
- docs: fix richtext drift found in #853
|
|
130
|
-
- fix(richtext): keep islands in sync on text-channel edits (#847)
|
|
131
|
-
- fix(typst): balance markup for overlapping wrap+code marks (#846)
|
|
132
|
-
- Render thematic breaks (---/***/___) instead of dropping them
|
|
133
|
-
- fix(richtext): correct ChangeLog::map_pos staleness and future-revision handling
|
|
134
|
-
- chore(richtext): drop richtext-spikes from integration branch
|
|
135
|
-
- Move richtext inline shape to `inline: true` schema field.
|
|
136
|
-
- feat(richtext): PR-H findings — fixture, runtime nav, docs (PR-H)
|
|
137
|
-
- cargo fmt
|
|
138
|
-
- feat(richtext): preview revision stamp + WASM session delta API (PR-F/PR-G)
|
|
139
|
-
- feat(richtext): fallible document body mutators (PR-E)
|
|
140
|
-
- docs(richtext): drop .qmd and Quill-Delta from phase-3 plan
|
|
141
|
-
- docs(richtext): record PR-C/D landing in phase-3 plan
|
|
142
|
-
- feat(richtext): add mark/line op channels and apply bundle (PR-D)
|
|
143
|
-
- feat(richtext): add revision counter and bounded change log (PR-C)
|
|
144
|
-
- feat(richtext): replace coarse delta::diff with Myers/LCS (PR-B)
|
|
145
|
-
- Remove husky pre-commit hook
|
|
146
|
-
- cargo fmt
|
|
147
|
-
- docs(richtext): record phase-3 spike findings on integration branch
|
|
148
|
-
- docs(richtext): align canon + code comments to PR-G, wrap up phase 2
|
|
149
|
-
- fix(wasm): add span to canonical FieldRegion contract
|
|
150
|
-
- richtext PR-G: richtext(inline), load-time example cache, alias cutover
|
|
151
|
-
- Delete prose/review directory
|
|
152
|
-
- docs(richtext): trim phase plans to landed reality, fold spike findings
|
|
153
|
-
- test(richtext): wasm binding test for positionAt/locate round-trip (#829)
|
|
154
|
-
- PR-F: regions + navigation — two-tier segment scan, position_at/locate (#829)
|
|
155
|
-
- spike(richtext): PR-F de-risking — run-machine transparency + glyph.span.1 precision
|
|
156
|
-
- fix(richtext): accept bodyMarkdown in the wasm card field allowlist
|
|
157
|
-
- feat(richtext): phase-2 PR-E — bindings expose corpus body + bodyMarkdown
|
|
158
|
-
- docs(richtext): clarify hard vs soft break in the CONVERT lowering table
|
|
159
|
-
- docs(richtext): phase-2 PR-E canon rework for the corpus seam
|
|
160
|
-
- feat(richtext): phase-2 PR-E — pdfform lowers richtext to plaintext + fixture
|
|
161
|
-
- feat(richtext): phase-2 PR-E part 2 — delete the markdown oracle
|
|
162
|
-
- feat(richtext): phase-2 PR-E part 1 — seam flip + typst consumes corpus
|
|
163
|
-
- docs(richtext): reconcile Typst-emit section with structured cells
|
|
164
|
-
- docs(richtext): PR-E handover + phase-2 status refresh
|
|
165
|
-
- docs(richtext): remove the .qmd file-extension concept
|
|
166
|
-
- feat(richtext): structured table cells — markdown a pure projection
|
|
167
|
-
- feat(richtext): phase-2 PR-D — typst corpus emitter + segment source maps
|
|
168
|
-
- feat(richtext): phase-2 PR-C — storage cutover to quillmark/document@0.93.0
|
|
169
|
-
- fix(richtext): resolve broken RichText::validate intra-doc link
|
|
170
|
-
- fix(core): quote payload scalars that would re-parse as a non-string
|
|
171
|
-
- docs(richtext): PR-B landing log + PR-C handover on the phase-2 plan
|
|
172
|
-
- fix(richtext): clear rustdoc -Dwarnings lint on phase-2 PR-B docs
|
|
173
|
-
- test(bindings): update body expectations for corpus canonicalization
|
|
174
|
-
- feat(richtext): phase-2 PR-B — Card.body is RichText, markdown a projection
|
|
175
|
-
- docs(richtext): lock separate-crate topology + retire Quill-Delta framing in plan
|
|
176
|
-
- refactor(richtext): make quillmark-richtext a leaf crate core depends on
|
|
177
|
-
- docs(richtext): phase-2 plan — engine consumes RichText, delivers #829
|
|
178
|
-
- docs(richtext): note block-quote emit decision for phase-2 handover
|
|
179
|
-
- docs(richtext): phase-1 handover doc + integration HQ updates
|
|
180
|
-
- fix(richtext): address phase-1 review — freeze determinism, codecs, anchors
|
|
181
|
-
- feat(richtext): phase 1 — RichText corpus model, codecs, canonical serialization
|
|
182
|
-
- docs(richtext): land phase-0 spike findings on the integration HQ
|
|
183
|
-
- docs(richtext): make integration HQ canonical, self-contained
|
|
184
|
-
- docs(richtext): open integration HQ plan for the content-model rework
|
|
185
|
-
- Sync usaf_memo/0.2.0 fixture with airmark-quiver template
|
|
186
|
-
- #824: dedup bindings tests + add two coverage guards
|
|
187
|
-
- #823 items 2-9: dedup core + integration tests
|
|
188
|
-
- #821 follow-up: fix rustdoc private-intra-doc-link in winansi_encode
|
|
189
|
-
- #822: dedup typst backend + PDF crate tests (~280 lines)
|
|
190
|
-
- #825: cache only the wasm cargo build dir, always regenerate pkg/
|
|
191
|
-
- #806: resolve overlapping widget field_at by paint order, not name
|
|
192
|
-
- Dead-code sweep from minimize-0.92.1-main review (#817–#821, #823, #825)
|
|
193
|
-
- Ground #809/#810: memoize page checks, unify dict-splice + field-name filters (#816)
|
|
194
|
-
- Tidy deferred backlog: dedup error-summary, pdfform flatten-limit docs, cleanup (#804, #807, #810, #812) (#815)
|
|
195
|
-
- Fix silent-data-loss regression and blueprint/error/docs gaps (#803, #805, #808, #811) (#814)
|
|
196
|
-
- Land LiveSession.fieldAt delegation; harden page_hashes against source spans (#801) (#813)
|
|
197
|
-
- Helper codegen v2: markup blocks + generated data literal, retiring eval() and json() (#800)
|
|
198
|
-
- Disable clippy in lint CI job (#798)
|
|
199
|
-
- Satisfy clippy's manual_contains in the scalar-window walker
|
|
200
|
-
- Drop the #797 spike modules from the branch
|
|
201
|
-
- Harden the span scan against the review findings
|
|
202
|
-
- Delete .claude/skills/simplification-cascades directory
|
|
203
|
-
- Spike: generated data literal is Typst-equal to the json() blob
|
|
204
|
-
- Spike: content fields as markup blocks resolve with per-node spans
|
|
205
|
-
- Document the span-based region contract across canon, core, and the migration guide
|
|
206
|
-
- Expose fieldAt on the WASM session; align binding docs with the span contract
|
|
207
|
-
- Migrate usaf_memo off tagged(); rewrite region tests for the span contract
|
|
208
|
-
- Span-based region tracking: codegen'd eval windows + glyph-span scan
|
|
209
|
-
- Omit $body from the transform schema for body-disabled kinds
|
|
210
|
-
- feat(regions): any array is element-addressable; SchemaMeta drops its unreachable Option
|
|
211
|
-
- test(typst): own the widget-region test's schema instead of borrowing the fixture's
|
|
212
|
-
- refactor(typst): collapse SchemaMeta per-kind table boilerplate, test-owned widget width
|
|
213
|
-
- docs(migrations): document the compile-time region-binding validation in the working guide
|
|
214
|
-
- fix(ci): hash every pkg/ input in the wasm cache key, check key sets in the drift guard
|
|
215
|
-
- fix(wasm): sync canonical runtime.d.ts with the regions sidecar, wire typecheck into CI
|
|
216
|
-
- feat(regions): validate form-field paths, reject scalar index-tagging, cache schema meta
|
|
217
|
-
- docs(migrations): fix stale region-uniqueness line in 0.92→0.93 guide
|
|
218
|
-
- Reconcile canon and migration guide with the reworked error system
|
|
219
|
-
- Update binding surfaces to the current-compile warnings contract
|
|
220
|
-
- Thread Typst compile warnings through the session as current-compile state
|
|
221
|
-
- Collapse RenderError to a single diagnostics-carrying struct; drop Severity::Note
|
|
222
|
-
- Amend error-rework proposal per adversarial review
|
|
223
|
-
- Propose error system rework: one failure type, warnings on the compile seam
|
|
224
|
-
- dense-prose: drop issue reference and history narration from regions test
|
|
225
|
-
- feat(regions): tag the usaf_memo plate; canon + migration guide for the new region contract
|
|
226
|
-
- feat(regions): per-placement regions, public tagged() helper, one-shot sidecar
|
|
227
|
-
- docs: accuracy pass + dense-prose sweep across docs/, prose/canon/, comments, READMEs
|
|
228
|
-
- build-wasm.sh: dev builds stamp next-patch -dev.<sha>, releases stamp verbatim
|
|
229
|
-
- wasm runtime: snapshot caller handles before the first await
|
|
230
|
-
- ci: enable the Clippy lint gate
|
|
231
|
-
- Python: batched-error message embeds the first diagnostic
|
|
232
|
-
- docs(core): note apply's $quill-check boundary on LiveSession::apply (#778)
|
|
233
|
-
- perf(wasm): LiveSession retains QuillConfig, not the whole Quill (#778)
|
|
234
|
-
- docs: canonize LiveSession — live preview owns apply/ChangeSet (#778)
|
|
235
|
-
- feat(wasm): LiveSession.apply(doc) -> ChangeSet (#778)
|
|
236
|
-
- Canon: endorse programmatic document construction
|
|
237
|
-
- refactor!: collapse RenderSession into LiveSession (#778)
|
|
238
|
-
- Add blank-canvas Document constructor in core and all bindings
|
|
239
|
-
- feat: transactional apply() + ChangeSet on the render session (#778)
|
|
240
|
-
- Add scalar From impls for QuillValue; mutators take Into<QuillValue>
|
|
241
|
-
- Expose batched set_fields across Python, WASM, and .NET bindings
|
|
242
|
-
- feat(typst): persist the World in the session; evict comemo after each compile (#778)
|
|
243
|
-
- Add atomic batched Card::set_fields
|
|
244
|
-
- remove(dotnet)!: drop the .NET binding entirely
|
|
245
|
-
- Update README.md
|
|
246
|
-
- Update README.md
|
|
247
|
-
- Update README.md
|
|
248
|
-
- Update README.md
|
|
249
|
-
- Update README.md
|
|
250
|
-
- Update README.md
|
|
251
|
-
- Update README.md
|
|
252
|
-
- fix: update WASM region test for content auto-tag; fix doc links
|
|
253
|
-
- docs(region): tighten regions() doc per dense-prose
|
|
254
|
-
- feat(region): one region per logical schema field
|
|
255
|
-
- docs(region): fix grouping guidance and note blank/empty no-region case
|
|
256
|
-
- refactor(typst): expose a region only for schema-addressable fields
|
|
257
|
-
- feat(typst): auto-region tagging for content fields (#775)
|
|
258
|
-
- refactor(core)!: move field regions from RenderResult to RenderSession::regions()
|
|
259
|
-
- refactor(core)!: key regions on the quill schema field, not the backend widget
|
|
260
|
-
- docs: fold prune-evolutionary-info into dense-prose
|
|
261
|
-
- docs: canonize comment/doc style as the dense-prose skill
|
|
262
|
-
- refactor(test): drop dangling BACKLOG.md reference
|
|
263
|
-
- refactor(core): tighten doc-comments, prune evolutionary phrasing
|
|
264
|
-
- refactor(bindings): neutralize marketing and reframe legacy phrasing
|
|
265
|
-
- refactor(quillmark,cli,fuzz): tighten comments, drop bug-history narration
|
|
266
|
-
- refactor(typst): tighten module and item doc-comments
|
|
267
|
-
- docs(canon): prune evolutionary and marketing phrasing
|
|
268
|
-
- docs: neutralize marketing and reframe legacy aliases in consumer docs
|
|
269
|
-
- feat(pdfform): export PNG and SVG; remove the preview feature gate
|
|
270
|
-
- fix(ci): resolve lint and docs CI failures on pdfform branch
|
|
271
|
-
- fix(quillmark-pdf): make find_dict_value key/value-position aware
|
|
272
|
-
- Make the plate a Typst-backend concern, not a universal one
|
|
273
|
-
- Address branch-review findings: spine robustness, coercion parity, doc accuracy
|
|
274
|
-
- Prune resolved review items 01–06; trim 07 to remaining gaps
|
|
275
|
-
- Rework item 2: derive canvas capability, delete supports_canvas flag
|
|
276
|
-
- Address branch-review item 3: total FieldRegion round-trip
|
|
277
|
-
- Address branch-review items 1, 2, 4, 5, 6, 7
|
|
278
|
-
- docs(review): write up unaddressed branch-review items for discussion
|
|
279
|
-
- test(pdfform): restore flatten byte-level coverage at the unit level (preview-gated)
|
|
280
|
-
- refactor(pdfform): PDF output always AcroForm; remove the public flatten knob
|
|
281
|
-
- Update sample_form PDF title and field labels
|
|
282
|
-
- Make pdfform framing industry-neutral
|
|
283
|
-
- docs: add PDF Form backend page under quills section
|
|
284
|
-
- refactor(pdfform): remove the form.json -> Quill.yaml scaffold
|
|
285
|
-
- refactor(pdf): extract the incremental-update envelope into PdfUpdate
|
|
286
|
-
- pdfform: WinAnsi flatten encoding, value clipping, shared PDF writer
|
|
287
|
-
- review: resolve low-risk findings from pdfform branch review
|
|
288
|
-
- Update README.md
|
|
289
|
-
- Remove qualification layer and page composition: pdfform fills static forms only
|
|
290
|
-
- feat(quillmark-pdf): page-merge primitive + continuation foundation (#757)
|
|
291
|
-
- refactor(pdfform): centralize flatten value typography as one source of truth (#752)
|
|
292
|
-
- feat(wasm): ship pdfform canvas + make the per-backend canvas contract explicit (#755)
|
|
293
|
-
- feat(typst): generalize the plate API to arbitrary form-field(...) (#758)
|
|
294
|
-
- feat(pdfform): card-instance value addressing in the resolver (#757)
|
|
295
|
-
- feat(qualify): add quillmark-qualify — AcroForm PDF → form.pdf + form.json (#753)
|
|
296
|
-
- chore(fmt): apply rustfmt line-wrapping to pre-existing drift
|
|
297
|
-
- feat(pdfform,cli): scaffold Quill.yaml from a form.json field spec (#756)
|
|
298
|
-
- fix(pdfform): build the preview feature against hayro's vello_cpu re-export
|
|
299
|
-
- Expose form-field regions from stamped AcroForm backends (#759)
|
|
300
|
-
- Implement `pdfform` backend + shared `quillmark-pdf` stamping spine (V1) (#750)
|
|
301
|
-
- docs(proposal): design for pdfform backend + shared AcroForm spine (#744) (#748)
|
|
302
|
-
- fix(python): count container levels, not the scalar leaf, in depth bound (#742) (#746)
|
|
303
|
-
- Add generic hint for unresolvable Typst eval errors (issue #745) (#747)
|
|
304
|
-
- docs: fix prose/canon, docs, and code-comment consistency drift (#743)
|
|
305
|
-
- fix(core): count empty containers in json_depth_exceeds (#741)
|
|
306
|
-
- Update README.md
|
|
307
|
-
- docs: position Quillmark as a "schema-driven document engine" (#739) (#740)
|
|
308
|
-
- review(0.93.0): fix stale comments, document scalar coercion, cover card markers (#738)
|
|
309
|
-
- Unify blueprint emission on Document::to_markdown (#737)
|
|
310
|
-
- docs(blueprint): fix $-line comment inaccuracies in canon (#735)
|
|
311
|
-
- core: graciously coerce bare scalars into string fields (#733)
|
|
312
|
-
- docs(spike): propose unifying blueprint placeholder on the !must_fill tag (#732)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
## v0.92.1 - 2026-06-22
|
|
316
|
-
|
|
317
|
-
- Accept uppercase field names; reserve only `$`-prefixed keys (#730)
|
|
318
|
-
- docs: canonize $ext.editor.title as per-card display name slot (#729)
|
|
3
|
+
## v0.96.0 - 2026-07-23
|
|
4
|
+
|
|
5
|
+
- docs(spec): keep plate JSON out of the markdown spec
|
|
6
|
+
- docs(core): fix doc-lint and mkdocs-strict CI failures
|
|
7
|
+
- core: gate plate $body at construction, not post-hoc strip
|
|
8
|
+
- docs(core): trim duplicated $kind comment in to_plate_json
|
|
9
|
+
- core: plate $body/$kind absent on undefined (#1030)
|
|
10
|
+
- core: compile_data conforms once — ladder consumes the gate's coerced output
|
|
11
|
+
- rename: view()→reader(), fieldStates()→resolve() across core and bindings
|
|
12
|
+
- core: one shared resolver behind compile_data and field_states
|
|
13
|
+
- content: dense-prose + simplify pass on the #1002 decision
|
|
14
|
+
- content: decide island-id ↔ content-hash determinism (#1002)
|
|
15
|
+
- Re-key runtime.d.ts geometry docs onto the canonical DocPath form
|
|
16
|
+
- Canon lint cleanup: dedup spine restatements, fold CI job, shape-based anchor check
|
|
17
|
+
- Canon docs infra: single-source the spine in prose/README.md, enforce in CI
|
|
18
|
+
- release: strip the seed coverage comment by construction; fix blank-notes fallback
|
|
19
|
+
- Reject signed years in date/datetime grammar (#1008)
|
|
20
|
+
- core: silence unused_must_use on Payload::insert in tests
|
|
21
|
+
- DocPath: root every main-field address at `main`
|
|
22
|
+
- fieldStates: ordered rows carrying `name`, body as a sibling (drop `$body`)
|
|
23
|
+
- Descope phase 5: cut the conformance suite, contractVersion, and phase-plan docs
|
|
24
|
+
- Contract phase 5 — conformance suite + contractVersion
|
|
25
|
+
- Contract phase 4 — typed-surface completion: QuillCardUi.groups + island props
|
|
26
|
+
- Phase 3 doc: separate tested value-parity from structural source-rung claim
|
|
27
|
+
- Fix rustdoc intra-doc links on EditError::doc_path / RenderedRegion.field
|
|
28
|
+
- simplify pass: hoist kinds vec, unify render-sidecar addressing, merge doc_path arms
|
|
29
|
+
- Contract phases 2–3: geometry DocPath unification, mutator paths, lean fieldStates
|
|
30
|
+
- Repivot the contract rework around consumer evidence (phase-doc rewrite)
|
|
31
|
+
- Qualify card fill diagnostics by schema-declared kind only (#1014)
|
|
32
|
+
- Contract phase 2 — canonical DocPath (+ phase 1 wasm test fix) (#1012)
|
|
33
|
+
- edit:: diagnostic codes on mutator failures (contract phase 1) (#1006)
|
|
34
|
+
- Add document-contract rework phase plan (#1005)
|
|
35
|
+
- content: centralize island type dispatch behind KnownIslandType (#985) (#1001)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## v0.95.1 - 2026-07-19
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## v0.95.0 - 2026-07-19
|
|
43
|
+
|
|
44
|
+
- release: re-cut to finish binding dists after the first publish run cancelled mid-flight
|
|
45
|
+
- **breaking** typst: a present `date` / `datetime` field lowers to a click-to-edit value-object — `(value: datetime(..), display: (..args) => text(value.display(..args)))` — instead of a bare Typst `datetime`, so the rendered glyphs are born at a generated `text(..)` node carrying a region keyed on the field's schema path: a date placed by a vendored package, or a card's date riding a shared loop variable, is click-to-edit. A blank date stays `none`, so `!= none` guards hold. Plates migrate two shapes: `(data.f.display)("…")` (paren form — the stored `display` is a closure on a dict, not a method) and `data.f.value` for anything native (comparison, `.year()`-family components, datetime-consuming packages). The tonguetoquill flagship quills' `display-date` dispatches on `type(date)`, since their `datetime.today()` blank-date fallback stays a native datetime (#990)
|
|
46
|
+
- **breaking** core,typst,pdfform: split the `datetime` field type into strict `date` and `datetime` (#717/#799 resolved) — `date` accepts a bare `YYYY-MM-DD` and rejects any time component; `datetime` accepts offset-less wall-clock `YYYY-MM-DDThh:mm[:ss]` (seconds zero-filled) and rejects timezone offsets, the space separator, fractional seconds, and bare dates. Offsets are rejected, never dropped (the engine does no zone math); storage stays verbatim; no truncation in either direction. A `date` lowers to the three-component Typst `datetime(year:, month:, day:)` (unchanged emission) and a `datetime` to the six-component constructor, carrying the wall-clock time. The transform schema marks `date` as `format: "date"` (keeping `format: "date-time"` for `datetime`), and the blueprint reads `date<YYYY-MM-DD>` / `datetime<YYYY-MM-DDThh:mm[:ss]>`. Most deployed `datetime` fields hold a bare date and migrate to `type: date` with byte-identical data; the fixtures (usaf_memo, cmu_letter) do so. No deprecation alias — `datetime` rejecting a bare date is the decided end-state (#991)
|
|
47
|
+
- **breaking** python: the binding commits to the typed lanes — field I/O flows through `quill.writer(doc)` / `quill.view(doc)` exclusively and `Document` is quill-free data and structure. Removed (WASM-only by scope, not lag — their audience is not a Python audience): the opaque field store (`store_field` / `store_fields` / `store_fill` and card twins), the content lane (`install` / `revise` / `apply_change`), the quill-free field reads (`get` / `get_card_field`), and the module codec fns (`import_markdown` / `export_markdown` / `rebase` / `map_pos`). The composable `$ext` / field-remove card twins fold onto a trailing `card=None` selector and `push_card` folds into `insert_card(card, at=None)`. Mirrored additions: `writer.revise_field` (the `Delta` receipt is not surfaced), `writer.add_card(kind, fields=None, body=None, at=None)`, `writer.card(i).kind`, and the `Writer` / `CardWriter` / `View` / `CardView` handle classes exported from the package (#970)
|
|
48
|
+
- **breaking** core,wasm,python: complete the `RichText` → `Content` residual sweep (#976 folds into #982) — retire the last informal-`corpus` / model-`RichText` *identifiers* the mechanical rename missed: `CorpusHit` → `ContentHit`, `EditError::CorpusApply` → `EditError::ContentApply`, `RichtextDecodeError::NotCorpus` → `NotContent` (the codec-specific `RichtextDecodeError` type itself is kept), storage DTO `CanonicalRichText` → `CanonicalContent` (serde is unchanged — no wire migration), and the model-generic Typst emitter `emit_richtext` / `emit_richtext_inline` → `emit_content` / `emit_content_inline` (they lower any `Content`, richtext *or* plaintext). Also fixes the `ParseError` display strings `richtext json …` → `content json …`, the doubled-word find-replace debris (`content content model` → `content model`), and stale prose/comments across canon and rustdoc. Schema/codec names are untouched — `richtext` / `plaintext` tokens, `FieldType::{RichText,PlainText}`, `field_richtext` / `FieldRichtext*` / `apply_field_richtext_change`, `richtext(inline)` — they name codecs, not the model. "corpus" is purged from the tree entirely, including the ordinary-English test-set names that meant a *collection* of fixtures (`fixture_corpus` → `fixtures`, `synthetic_corpus` → `synthetic_inputs`) (#982)
|
|
49
|
+
- **breaking** core,wasm,python: a schema-bound read view — `Quill::view(&doc)` / `quill.view(doc)`, the read twin of `quill.writer(doc)`. `view.get(addr)` interprets each field by its declared type (a `richtext` field → markdown, a `plaintext` field → its literal text via the plaintext codec, every other type → its canonical value verbatim), returns absent as `undefined` / `None`, and — the authority the quill-free `getMarkdown` lacks — throws `UnknownField` for a name the schema does not declare and `FieldRichtextDecode` for a content field holding an undecodable value. Core `TypedReader::get` returns a `ReadValue` (`Markdown`/`Plaintext`/`Value`); `view.card(i)` is the card cursor; core adds `Card::field_plaintext` (the `to_plaintext` twin of `field_markdown`). **`getMarkdown`'s field half retires**: `getMarkdown` / `get_markdown` / `get_card_markdown` are now body-only (WASM `getMarkdown` takes a `CardAddr`, a present `field` throws; Python drops the `name` parameter) — a field's markdown is read through `view.get`. The quill-free body projection stays on `Document` (#978)
|
|
50
|
+
- **breaking** content: one delta-application contract — implicit trailing retain is `try_apply`'s semantics (a short delta retains the untouched remainder; the error is over-consumption only), `apply` panics on an over-long delta instead of clamping (clamping is silent corruption), and `extend_to_base` is removed. `split_line` / `join_line` rebase marks through their one-char `\n` splice with `map_pos` — the same mapping the text-delta channel uses — so marks no longer drift across line ops and `apply_field_change` canonicalizes once (a single terminal normalize instead of one per stage); line sync rebuilds in one forward pass instead of per-`\n` `Vec` splices. Mark ops are specified in final-text coordinates (post-delta, post-line-op — the frame they validate against) (#926, #987)
|
|
51
|
+
- **breaking** core: storage blobs tagged `@0.81.0` / `@0.82.0` fail as an unknown schema version — the read-only `V0_81_0` / `V0_82_0` DTO trees and their forward migrations are retired (nothing persisted on this lineage predates `@0.92.0`; `0.82.0` was yanked). `V0_92_0` stays the oldest shape read, and its payload types back the current write path. DOCUMENT_STORAGE.md records variant retirement as the policy when no stored population remains (#929)
|
|
52
|
+
- **breaking** core,wasm,python: the markdown projection stops appending a trailing newline — `to_markdown` projects a *value*, not a file, so `field_markdown` / `body_markdown` (WASM `getMarkdown` / `exportMarkdown`, Python `export_markdown` / `get_markdown`) no longer grow a `\n`; `writer.set("subject", "Hello")` reads back as `"Hello"`, not `"Hello\n"`. `.qmd` files still end in one newline (owned by `Document::to_markdown`, the file writer) and the content fixed point is unchanged (import is newline-insensitive) (#965)
|
|
53
|
+
- **breaking** all: rename the content genus off its codec's name — crate `quillmark-richtext` → `quillmark-content`, type `RichText` → `Content` (and `RichTextLine`/`RichTextContainer`/`RichTextMark`/`RichTextIsland` → `ContentLine`/…), const `RICHTEXT_MEDIA_TYPE` → `CONTENT_MEDIA_TYPE` and its wire string `application/quillmark-richtext+json` → `application/quillmark-content+json`, `#[serde(skip)]` companion caches `FieldSchema::{default,example}_corpus` → `_content`, `SegmentMap.corpus: Range<usize>` → `.content`, Typst-emitter `EmittedContent` → `Emission` (it is markup + source map, not a Typst `content` value). Schema tokens `richtext` / `plaintext`, `FieldType::{RichText,PlainText}` variants, and the codec-specific `field_richtext` / `FieldRichtext*` / `apply_field_richtext_change` / `richtext(inline)` surface are unchanged — those name codecs, not the model. Canonical body JSON is nameless, so stored documents don't migrate; `contentMediaType` consumers pin to the new spelling. Retires the informal "corpus" noun to end the code/prose split (#976)
|
|
54
|
+
- **breaking** core,wasm,python: `getMarkdown` / `get_markdown` / `get_card_markdown` stop conflating an absent field with a present-but-not-richtext one — a present field that does not decode as richtext (a scalar/array/object a `storeField` wrote) now throws `FieldRichtextDecode` instead of reading back `undefined` / `""`; absence still returns the absent shape. Core `Card::field_markdown` becomes `Option<Result<String, RichtextDecodeError>>` (the projection twin of `field_richtext`). Rule: absence returns, mismatch raises; read the raw value with `get` (#968)
|
|
55
|
+
- feat(core,wasm): typed, anchor-preserving field revise — `TypedWriter::revise_field` / `CardWriter::revise_field` and `writer.reviseField` / `writer.card(i).reviseField` wrap core `Card::revise_field_checked` (diff-rebase surviving anchors, then schema-conform the result); the schema-bound verb lives on the writer, where the schema is (#957, #966)
|
|
56
|
+
- **breaking** wasm: the quill-taking `Document` methods become the hidden ABI under the writer — `commitField` / `commitFields` / `addCard` → `_commitField` / `_commitFields` / `_addCard`, dropped from the `.d.ts`; remove `doc.reviseChecked` (no runtime consumer — use `writer.reviseField`). The visible `Document` class then carries zero quill-taking methods (#966)
|
|
57
|
+
- **breaking** core: rename `EditError::BodyImport` → `EditError::Import` (message `body import failed:` → `markdown import failed:`) — the variant also fires on field-path imports (`revise_field`), where "body" misnamed it (#966)
|
|
58
|
+
- **breaking** wasm: fold `pushCard` into `insertCard(card, at?)` — one insertion verb per lane, absent `at` appends; `insertCard`'s parameters reorder to `(card, at?)`. Delete the deprecated `replaceBody` alias (use `revise({}, md)` or `writer.setBody`) (#961)
|
|
59
|
+
- feat(core,wasm): positioned card insert — `TypedWriter::add_card` / `writer.addCard` and the `addCard` ABI take an `at` position, so a positioned typed insert is one atomic call instead of `addCard` + `moveCard`; add `TypedWriter::remove_card` (mirrors JS `writer.removeCard`) and a JS `CardWriter.kind` getter (mirrors core `CardWriter::kind()`) (#961)
|
|
60
|
+
- **breaking** core: `Payload::insert` / `insert_fill` now validate the field-name and value-depth invariant at the boundary and return `Result<_, FieldViolation>`, closing the `payload_mut().insert(...)` hole that let a direct caller build an invalid document; pre-validated internal callers use the new `pub(crate)` `insert_unchecked` / `insert_fill_unchecked` (#958)
|
|
61
|
+
- feat(wasm,core): single-card reads — `doc.card(i)` (throws out of range), `doc.cardIndexById(id)` (first match; `$id` is non-unique), and `doc.seedOverlay(kind)`, backed by core `Document::card(i)` / `find_card(id)`. Reading one card, resolving a `$id`, or fetching a `$seed` overlay no longer serializes the whole `cards` array or main card (#956)
|
|
62
|
+
- **breaking** core: parse warnings live only on `ParseOutput` — the redundant `Document::warnings` field + `warnings()` getter are dropped and `Document::from_main_and_cards` no longer takes a `warnings` param (`Document` `PartialEq` is now a plain derive) (#959)
|
|
63
|
+
- **breaking** core: collapse the two parse functions into one entry — `Document::from_markdown` and `Document::from_markdown_with_warnings` are removed in favor of `Document::parse(md) -> Result<Parsed, ParseError>`, and `ParseOutput` is renamed `Parsed`. A document-only caller writes `parse(md)?.document`. Bindings are unaffected: WASM `Document.fromMarkdown` / Python `Document.from_markdown` keep their names and their `doc.warnings` getter (#964)
|
|
64
|
+
- feat(wasm,python): keyed card reads `getCardField(index, name)` / `getCardMarkdown(index, name?)` (py `get_card_field` / `get_card_markdown`) — the card-indexed twins of `get` / `getMarkdown`, mirroring the `commitCardField` / `setCardField` write verbs so card reads no longer require a `payloadItems` walk (#953)
|
|
65
|
+
- feat(content,wasm,python): `LineOp::SetContinues { line, continues }` — hard breaks lower op-wise. Split, join, and a text-delta `\n` all mint `continues: false` lines, so a within-block hard break (a paragraph hard break, a code fence's interior line) had no op and fell back to a whole-install, losing that edit's identity anchors. Threaded through the wire codec into WASM `applyChange` (TS union updated) and Python; `continues: true` on line 0 is rejected with `ApplyError::FirstLineContinues` before the write, leaving the content untouched (#949)
|
|
66
|
+
- feat(wasm): the runtime root re-exports the edit vocabulary its own signatures reference — `Content` / `ContentLine` / `ContentContainer` / `ContentMark` / `ContentIsland`, `Addr` / `Delta` / `Assoc` / `LineOp` / `MarkOp` / `ChangeBundle`, `CardInput` / `PathStep` — as type-only exports (single entry point preserved; no `/core` subpath), with a presence guard so a dropped re-export fails `npm run typecheck` (#948)
|
|
319
67
|
|
|
320
|
-
|
|
321
|
-
## Unreleased
|
|
68
|
+
## v0.94.0 - 2026-07-15
|
|
322
69
|
|
|
323
70
|
These notes cover everything since v0.92.1. No 0.93.x was separately
|
|
324
71
|
published — the 0.93 milestone folds into this release, so the upgrade path
|
|
@@ -546,6 +293,12 @@ from 0.92.1 is the `0.92-to-0.93` and `0.93-to-0.94` guides read in sequence.
|
|
|
546
293
|
`--features typst` where they used `--features render`; the published JS API is
|
|
547
294
|
unchanged. See `docs/migrations/0.92-to-0.93.md`
|
|
548
295
|
|
|
296
|
+
## v0.92.1 - 2026-06-22
|
|
297
|
+
|
|
298
|
+
- Accept uppercase field names; reserve only `$`-prefixed keys (#730)
|
|
299
|
+
- docs: canonize $ext.editor.title as per-card display name slot (#729)
|
|
300
|
+
|
|
301
|
+
|
|
549
302
|
## v0.92.0 - 2026-06-22
|
|
550
303
|
|
|
551
304
|
- 0.92 technical-debt sweep: correctness, $seed hardening, de-duplication (#727)
|
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ is resolved at render time, not here. Loads no backend binary.
|
|
|
89
89
|
A blank document: a main card carrying only `$quill`, an empty body, and no
|
|
90
90
|
composable cards — the programmatic blank canvas. Absent fields resolve at
|
|
91
91
|
render time (schema `default`, else type-empty zero), so nothing the caller
|
|
92
|
-
did not set reaches the output. Build it up with `
|
|
92
|
+
did not set reaches the output. Build it up with `storeFields` / `insertCard`.
|
|
93
93
|
For an example-filled starter use `quill.seedDocument()`. Throws on an
|
|
94
94
|
invalid quill reference.
|
|
95
95
|
|
|
@@ -197,7 +197,7 @@ and compare instead of re-parsing on every keystroke.
|
|
|
197
197
|
### `doc.cardCount`
|
|
198
198
|
O(1) getter for the number of composable cards (excluding the main card).
|
|
199
199
|
Use this to validate indices before calling card mutators (`removeCard`,
|
|
200
|
-
`
|
|
200
|
+
`storeField({ card, field }, …)`, etc.) without allocating the full `cards` array.
|
|
201
201
|
|
|
202
202
|
### `quill.validate(doc)`
|
|
203
203
|
|
|
@@ -233,47 +233,64 @@ const markdown = doc.toMarkdown();
|
|
|
233
233
|
For per-card seeding, `quill.seedMain()` returns just the `$kind: main` card
|
|
234
234
|
and `quill.seedCard(kind)` returns a starter composable card (or `undefined`
|
|
235
235
|
if the kind is not declared). Both return the read `Card` shape of
|
|
236
|
-
`doc.main` / `doc.cards`, which `doc.
|
|
237
|
-
directly:
|
|
236
|
+
`doc.main` / `doc.cards`, which `doc.insertCard` accepts directly:
|
|
238
237
|
|
|
239
238
|
```ts
|
|
240
|
-
doc.
|
|
241
|
-
doc.
|
|
242
|
-
doc.
|
|
239
|
+
doc.insertCard(quill.seedCard("note")); // seed → append
|
|
240
|
+
doc.insertCard(Document.makeCard("note", { x: 1 })); // build from a flat map
|
|
241
|
+
doc.insertCard({ kind: "note", body: "Plain **markdown**." }); // bare inline
|
|
242
|
+
doc.insertCard({ kind: "note" }, 0); // insert at index 0
|
|
243
243
|
```
|
|
244
244
|
|
|
245
245
|
Reads and writes are two aligned shapes. A read `Card` always has `body:
|
|
246
|
-
|
|
246
|
+
Content` (canonical content, never a raw string) — no narrowing, no guessing
|
|
247
247
|
whether the body was normalized. The write shape `CardInput` widens `body` to
|
|
248
|
-
`
|
|
249
|
-
field but `kind` optional. Every `Card` is a valid `CardInput`, so `
|
|
250
|
-
|
|
248
|
+
`Content | string` (a markdown string imports to the content) and makes every
|
|
249
|
+
field but `kind` optional. Every `Card` is a valid `CardInput`, so `insertCard`
|
|
250
|
+
still takes exactly what `cards` / `removeCard` / `seedCard` return.
|
|
251
251
|
Build a fresh card from a flat field map with
|
|
252
252
|
`Document.makeCard(kind, fields?, body?)`.
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
**One address for the whole surface.** Reads and writes navigate by an `Addr` —
|
|
255
|
+
`{ card?, field? }`, absent `card` = main, absent `field` = body — and a bare
|
|
256
|
+
string is shorthand for `{ field }`. So `doc.storeField("qty", 3)` targets the
|
|
257
|
+
main card's `qty`, `doc.storeField({ card: 2, field: "qty" }, 3)` a composable
|
|
258
|
+
card's. Reads are total over the field axis (`get` → `undefined`, `isFill` → `false` for
|
|
259
|
+
an absent field; only an out-of-range card throws); field writes throw on a body
|
|
260
|
+
address. `getMarkdown` is the body markdown read (a `CardAddr`; a field's
|
|
261
|
+
markdown is read through `quill.reader(doc).get(field)`). Card-scoped verbs take a
|
|
262
|
+
`CardAddr` (`{ card? }`) first: `doc.getExt({ card: 2 })`, and the batch below.
|
|
263
|
+
|
|
264
|
+
Batch mutation: `doc.storeFields({}, {...})` / `doc.storeFields({ card: index }, {...})`
|
|
255
265
|
apply a whole object atomically — on any invalid field nothing is applied and
|
|
256
266
|
the thrown error carries one diagnostic per offending field (`path` = field
|
|
257
|
-
name).
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
267
|
+
name). The address is first (never shape-overloaded, since `card` is a legal
|
|
268
|
+
field name), and parses strictly — a stray key throws rather than silently
|
|
269
|
+
reading as `{}`. The main card is `{}`, or **`MAIN_CARD_ADDR`** (from
|
|
270
|
+
`@quillmark/wasm/runtime`), a frozen alias that spells the intent:
|
|
271
|
+
`doc.storeFields(MAIN_CARD_ADDR, {...})`.
|
|
272
|
+
|
|
273
|
+
### Typed writes: `commit*` is the default, `store*` is the quill-free primitive
|
|
274
|
+
|
|
275
|
+
A `Document` holds only a `$quill` *reference*, not the resolved schema, so typed
|
|
276
|
+
writes go through the schema-bound writer while the quill-free opaque store sits
|
|
277
|
+
on `Document` itself (**store** = verbatim, **set** = typed):
|
|
278
|
+
|
|
279
|
+
- **`quill.writer(doc)` — the typed door whenever a quill is in hand.** Bind the
|
|
280
|
+
schema once and issue bare `set` / `setAll` / `setBody` / `reviseField` /
|
|
281
|
+
`addCard` / `card(i)`. Each resolves the field's schema `type`, coerces the
|
|
282
|
+
value to its canonical form (`"3"` → `3`, a markdown string → a richtext
|
|
283
|
+
content), and **fails now** on a mismatch instead of at render. A name the schema
|
|
284
|
+
does not declare throws `UnknownField` rather than falling to the opaque store —
|
|
285
|
+
on the typed path an undeclared name is a typo, not a fallback. The batch form
|
|
286
|
+
(`setAll`) is all-or-nothing: an undeclared name aborts the whole write and its
|
|
287
|
+
per-field diagnostics name every offending field, so a whole-form submit
|
|
288
|
+
surfaces every typo `storeFields` would silently absorb. (The raw wasm class
|
|
289
|
+
carries the quill-taking `_commitField` / `_commitFields` / `_addCard` /
|
|
290
|
+
`_reviseField` ABI the writer delegates to, hidden from the `.d.ts`.)
|
|
291
|
+
|
|
292
|
+
- **`store*` — the deliberate quill-free primitive.** `doc.storeField(addr, value)`
|
|
293
|
+
/ `doc.storeFields(cardAddr, {...})` (and `storeFill`) validate only the field
|
|
277
294
|
name/depth/kind and store the value verbatim, no quill required. Reach for it
|
|
278
295
|
on purpose when you *want* the opaque store: quill-agnostic storage/migration
|
|
279
296
|
infra that has no bundle and must write regardless of a drifted schema;
|
|
@@ -283,21 +300,20 @@ mutates through two layers:
|
|
|
283
300
|
and only surfaces at `quill.validate` / render.
|
|
284
301
|
|
|
285
302
|
Per-keystroke cost is the same either way (both mutate the in-memory `Document`
|
|
286
|
-
in place; no seam is crossed), so steering to
|
|
303
|
+
in place; no seam is crossed), so steering to the writer buys the type check for
|
|
287
304
|
free.
|
|
288
305
|
|
|
289
306
|
#### `DocumentWriter` / `CardWriter` — bind the quill once
|
|
290
307
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
308
|
+
`quill.writer(doc)` binds the quill's schema to the document once, so a form
|
|
309
|
+
editor or MCP writer that holds both issues bare verbs (the writer forwards to
|
|
310
|
+
the per-call `_commit*` ABI):
|
|
294
311
|
|
|
295
312
|
```ts
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const ed = new DocumentWriter(quill, doc); // JS twin of Rust `quill.writer(doc)`
|
|
313
|
+
const ed = quill.writer(doc); // Rust `quill.writer(doc)` twin; new DocumentWriter(quill, doc) also works
|
|
299
314
|
ed.set("subject", "Q3 results"); // strict-committed to the schema type
|
|
300
315
|
ed.setAll({ qty: "3", subject: "Q3" }); // all-or-nothing batch
|
|
316
|
+
ed.reviseField("subject", "Q3 **results**"); // typed AND anchor-preserving; returns a Delta
|
|
301
317
|
ed.set("titel", "x"); // throws UnknownField — a typo, not a fallback
|
|
302
318
|
ed.card(2).set("body", "**note**"); // composable card, resolved by its $kind
|
|
303
319
|
```
|
|
@@ -446,10 +462,11 @@ compilation failures. The same shape applies to every throw site:
|
|
|
446
462
|
|
|
447
463
|
- `Document.fromMarkdown` — parse errors (missing root `$quill` metadata, YAML
|
|
448
464
|
errors, `parse::input_too_large` for inputs > 10 MB).
|
|
449
|
-
- `Document` mutators (`
|
|
450
|
-
|
|
451
|
-
`
|
|
452
|
-
|
|
465
|
+
- `Document` mutators (`storeField`, the writer's `set`, etc.) — mutator
|
|
466
|
+
failures carry a namespaced `edit::*` `code` on `diagnostics[0]`
|
|
467
|
+
(`edit::invalid_field_name`, `edit::unknown_field`, `edit::index_out_of_range`,
|
|
468
|
+
`edit::field_conform`, …). Route on `diagnostics[0].code`, never on message
|
|
469
|
+
text.
|
|
453
470
|
- `engine.render` / `session.render` — backend compilation failures and
|
|
454
471
|
validation errors.
|
|
455
472
|
|