@quillmark/wasm 0.102.0 → 0.104.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 +170 -0
- package/README.md +40 -27
- package/backends/pdfform/wasm.d.ts +60 -6
- package/backends/pdfform/wasm.js +75 -4
- package/backends/pdfform/wasm_bg.wasm +0 -0
- package/backends/pdfform/wasm_bg.wasm.d.ts +2 -0
- package/backends/typst/wasm.d.ts +60 -6
- package/backends/typst/wasm.js +75 -4
- package/backends/typst/wasm_bg.wasm +0 -0
- package/backends/typst/wasm_bg.wasm.d.ts +2 -0
- package/core/wasm.d.ts +59 -5
- package/core/wasm.js +75 -4
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +2 -0
- package/package.json +2 -2
- package/runtime/runtime.d.ts +68 -34
- package/runtime/runtime.js +131 -66
- package/runtime/uninit.js +0 -57
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,175 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.104.0 - 2026-08-13
|
|
4
|
+
|
|
5
|
+
- feat(core,wasm): a quill declares, per body, the block constructs its plate
|
|
6
|
+
does not typeset (`main.body.unsupported`, `card_kinds.<k>.body.unsupported`;
|
|
7
|
+
names from `heading`, `rule`, `code`, `list`, `quote`, `table`, `image`).
|
|
8
|
+
A body holding one anyway draws the non-fatal `plate::unsupported_construct`,
|
|
9
|
+
a fifth warning family, on the pre-render walk `Quill::parse` runs beside
|
|
10
|
+
`conform`: one diagnostic per (body, construct) carrying the count in `args`
|
|
11
|
+
and the body's path, so occurrences collapse rather than scatter. The
|
|
12
|
+
declaration also rides `QuillConfig::schema()` to the editor, which is the
|
|
13
|
+
half a render-time warning could not serve: it answers before the gesture.
|
|
14
|
+
Nothing verifies a declaration — a plate that drops an undeclared construct
|
|
15
|
+
stays as silent as before. `usaf_memo` declares `rule`; empty everywhere
|
|
16
|
+
else, so no existing quill's schema or warnings change.
|
|
17
|
+
- fix(fixtures): `usaf_memo`'s `render-body` drained its heading buffer in the
|
|
18
|
+
three shapes that used to discard it. A heading with nothing after it (the
|
|
19
|
+
buffer died with the loop, taking a list item's bullet with it), a heading
|
|
20
|
+
whose next element opened a *different* list item (its text was delivered
|
|
21
|
+
into that item), and a heading following a heading (the assignment overwrote
|
|
22
|
+
the earlier one) each lost their text with nothing in the render to say so.
|
|
23
|
+
The run-in style is unchanged where it was right: a heading joins the next
|
|
24
|
+
block of its own item, or the next paragraph at top level.
|
|
25
|
+
- fix(content)!: `to_markdown` writes `***` for a thematic break, not `---`.
|
|
26
|
+
`- ` + `---` is four dashes separated by spaces, which re-imports as a
|
|
27
|
+
top-level break, so a rule as a bullet item's first block lost its item on
|
|
28
|
+
every markdown round-trip. The canonical spelling is now the one with the
|
|
29
|
+
fewest other readings (`---` is also a setext underline and the root-block
|
|
30
|
+
front-matter opener). Exported markdown changes for documents holding a
|
|
31
|
+
rule; the content model, wire data and rendered output do not.
|
|
32
|
+
- refactor(core,pdfform,cli,wasm)!: the `enum:` modifier on `type: string`
|
|
33
|
+
retires. `type: enum` with a `values:` list is the one spelling of a finite
|
|
34
|
+
string domain; `enum:` on any type is now `quill::field_parse_error`, whose
|
|
35
|
+
message names the replacement — it is the only diagnostic a quill written
|
|
36
|
+
against the modifier ever received, since the deprecation shipped in 0.94
|
|
37
|
+
with no warning code behind it. `QuillConfig::schema()` re-emits every
|
|
38
|
+
domain as `values:`, so a consumer reading `enum:` off the schema echo (the
|
|
39
|
+
wasm `QuillFieldSchema.enum`, dropped here) reads `values:` instead. The
|
|
40
|
+
`usaf_memo` and `sample_form` fixtures migrate; wire data and rendered
|
|
41
|
+
output are unchanged, the projections being domain-keyed already.
|
|
42
|
+
- fix(core): `build_transform_schema` keys a field's finite domain on the
|
|
43
|
+
domain itself rather than the `Enum` token, joining the render floor, the
|
|
44
|
+
pdfform widget kind and the blueprint annotation. Under the retired
|
|
45
|
+
spelling every `usaf_memo` enum — `classification`, `format`, `action` —
|
|
46
|
+
projected as a bare `{"type":"string"}`, so a consumer building a
|
|
47
|
+
JSON-Schema validator from the transform schema accepted
|
|
48
|
+
`classification: "banana"` while pdfform drew the six-option dropdown for
|
|
49
|
+
the same field and `QuillConfig` rejected the value at coercion (#1237)
|
|
50
|
+
- fix(core)!: geometry addresses parse segment-wise, so `locate` and
|
|
51
|
+
`fieldBoxes` answer for an address deeper than one segment. The translation
|
|
52
|
+
boundary folded a plate address's whole tail into one `Field`, so
|
|
53
|
+
`references.0` minted `main.references.0` — a string that reparses as a field
|
|
54
|
+
literally named `0`, and that the reverse direction refused outright. Both
|
|
55
|
+
spellings returned `None`, leaving caret placement and whole-field highlight
|
|
56
|
+
dead for **every** `array<richtext>` element (the flagship memo's
|
|
57
|
+
`references` among them) and for every nested key a pdfform widget binds
|
|
58
|
+
(`address.city`). `region.rs` now reads and renders a plate tail one segment
|
|
59
|
+
at a time: an all-digit segment is an array index, `$body` the body terminal,
|
|
60
|
+
anything else a field or map key.
|
|
61
|
+
- change(wasm, python)!: `RenderedRegion.field`, `FieldRegion.field` and
|
|
62
|
+
`ContentHit.field` spell an array element bracketed — `main.references.0`
|
|
63
|
+
becomes `main.references[0]` — on `regions()`, `fieldAt`, `positionAt` and
|
|
64
|
+
`RenderResult.regions`. This is the spelling schema validation already emits,
|
|
65
|
+
so a `Diagnostic.path` and the geometry address for one place are now the same
|
|
66
|
+
string. A consumer finding an address's children by prefix (`startsWith(`${field}.`)`)
|
|
67
|
+
needs the `[` opener too, and any heuristic reading a trailing all-digit field
|
|
68
|
+
name as a lost index is dead.
|
|
69
|
+
- feat(wasm): `doc.pathFor(addr)` mints an `Addr` as the canonical `DocPath`
|
|
70
|
+
string `Diagnostic.path` carries and `session.locate` / `session.fieldBoxes`
|
|
71
|
+
take; `doc.cardPath(i)` is the card's own root. `Document` computed the
|
|
72
|
+
kind-qualified root for every addressed write and did not hand it out, so a
|
|
73
|
+
consumer building a path restated the kind lookup, the `Addr` defaults and the
|
|
74
|
+
range guard — and a wrong-kind path is compared as a string, matching nothing
|
|
75
|
+
and drawing no highlight without throwing. Both are quill-free (the stored
|
|
76
|
+
`$kind` verbatim) and total on the index axis: a path is an anchor, not a
|
|
77
|
+
read, so a per-keystroke call needs no `try` (#1225)
|
|
78
|
+
- change(wasm)!: `@quillmark/wasm` declares `engines: { node: ">=24" }`, the
|
|
79
|
+
tier CI builds and tests the bindings on and the one both devcontainers hand a
|
|
80
|
+
contributor. Nothing in the package requires it at runtime, so a Node 22
|
|
81
|
+
install fails `engines` checking without failing at import.
|
|
82
|
+
- docs: `docs/migrations/0.103-to-0.104.md` carries the four breaks — the
|
|
83
|
+
retired `enum:` modifier, the bracketed index spelling, the `***` thematic
|
|
84
|
+
break and the Node floor — with the prefix-match, trailing-digit and stored
|
|
85
|
+
-markdown shapes a consumer has to fix, and the two additive surfaces
|
|
86
|
+
(`pathFor` / `cardPath`, and the `plate::unsupported_construct` family a
|
|
87
|
+
code-routing consumer gains an arm for).
|
|
88
|
+
- test(core): three characterization tests pin the render floor's two
|
|
89
|
+
type-domain edges (a defaultless enum, top-level and nested in a typed
|
|
90
|
+
dictionary) and an authored empty `date` beside an empty `string`, so the
|
|
91
|
+
coercion difference between the two is one test's diff. Every shipped quill
|
|
92
|
+
declares a `default:` on every enum and none authors an empty `date`, so the
|
|
93
|
+
fixture suite reached neither path. A fourth carries a `!must_fill` tag on two
|
|
94
|
+
example-seeded cells through seed → store → load → conform. Refs #1234
|
|
95
|
+
|
|
96
|
+
<!-- seed: commits since v0.103.0, confirm the entries above cover them, then delete this comment
|
|
97
|
+
- Carry the thematic-break and unsupported-construct work into the guide
|
|
98
|
+
- Dense-prose pass over the new comments and docs
|
|
99
|
+
- Let a quill declare the constructs its plate does not typeset
|
|
100
|
+
- Drain the memo's heading buffer instead of dropping it
|
|
101
|
+
- Canonicalize a thematic break to `***`
|
|
102
|
+
- Close the 0.104 release gaps: the migration guide, and four changelog entries
|
|
103
|
+
- Retire the enum: modifier; project a field's domain by capability
|
|
104
|
+
- Pin the render floor's two type-domain edges and the seeded fill tag
|
|
105
|
+
- Raise the Node floor to 24
|
|
106
|
+
- dense-prose pass over the added prose
|
|
107
|
+
- docs: dense-prose pass on the text-type sections
|
|
108
|
+
- docs: give the text-type choice a decision procedure
|
|
109
|
+
- docs: state the backend seam's scope and reserve its namespaces
|
|
110
|
+
- docs: drop the private intra-doc link from pathFor
|
|
111
|
+
- fix(core): state the unspellable-tail conditions instead of linking a private fn
|
|
112
|
+
- chore(wasm): density pass, and gate a core-build dead function
|
|
113
|
+
- docs: dense-prose pass over the geometry-address translation
|
|
114
|
+
- docs: dense-prose pass over the pathFor / cardPath prose
|
|
115
|
+
- test(wasm): execute the static-export exemption instead of listing it
|
|
116
|
+
- feat(wasm): mint a DocPath from an Addr (#1225)
|
|
117
|
+
- fix(core)!: parse geometry addresses segment-wise (#1223)
|
|
118
|
+
- docs: carry the 0.103 CLI break, and the init gate into the quickstart (#1222)
|
|
119
|
+
- SCHEMAS.md: a declared type change rewrites stored values (#1221)
|
|
120
|
+
-->
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## v0.103.0 - 2026-08-09
|
|
124
|
+
|
|
125
|
+
- docs: `docs/integration/operations.md`, carrying what the other integration
|
|
126
|
+
pages leave unsaid: that **render is not bounded** — no deadline, no
|
|
127
|
+
cancellation, and the parse limits do not carry through — with the
|
|
128
|
+
worker-termination recipe that is the only abort a browser has; that
|
|
129
|
+
`Quillmark`, `Quill` and `Document` are `Send + Sync`, pinned by a test rather
|
|
130
|
+
than asserted; `comemo` eviction as what a long-lived process's memory tracks;
|
|
131
|
+
the no-network, no-ambient-filesystem isolation properties; and that a panic
|
|
132
|
+
is terminal on every surface.
|
|
133
|
+
- docs: `parse::input_too_large` carries four of the five §8 caps, separable
|
|
134
|
+
only by its `max` arg, which `error-handling.md` now says where it names the
|
|
135
|
+
code.
|
|
136
|
+
- test(cli): `quillmark-cli` gets its first tests. The bin carries
|
|
137
|
+
`test = false`, so twelve cases drive the built executable instead — every
|
|
138
|
+
subcommand, `-o` and `--stdout`, PDF and SVG output, and the error paths,
|
|
139
|
+
which must exit 1 rather than panic. The crate had no `[dev-dependencies]`
|
|
140
|
+
and no workflow invoked it (#1068).
|
|
141
|
+
- fix(cli)!: `render --verbose` writes its progress lines to stderr, as the
|
|
142
|
+
warning printer already did. Under `--stdout` they went to stdout ahead of and
|
|
143
|
+
after the artifact, so `quillmark render q --stdout --verbose > out.pdf`
|
|
144
|
+
produced a PDF with `Loading quill from: …` before its header and
|
|
145
|
+
`Rendering completed successfully` past its trailer. A script that parses
|
|
146
|
+
`--verbose` output from stdout reads it from stderr now.
|
|
147
|
+
- test(fuzz): `pdf_fuzz` covers the AcroForm stamp spine's byte-level reads,
|
|
148
|
+
the one hand-rolled parser with no fuzz target. Arbitrary bytes, and a real
|
|
149
|
+
form truncated, single-byte-corrupted, or spliced, all through
|
|
150
|
+
`page_media_boxes` / `PdfUpdate::begin` / `stamp`. The oracle is no panic:
|
|
151
|
+
nothing in the workspace catches unwind, so a panic there kills the CLI and
|
|
152
|
+
the Python extension and poisons the WASM module. No failures found.
|
|
153
|
+
- fix(core): `MAX_FIELD_COUNT`'s rustdoc said "per document"; the check is per
|
|
154
|
+
card-yaml block, counted after `$`-key extraction.
|
|
155
|
+
- refactor(wasm)!: `init()` resolves to the core surface, and it is the only way
|
|
156
|
+
to reach one. `Quill`, `Document`, `importMarkdown`, `exportMarkdown`,
|
|
157
|
+
`rebase`, `mapPos`, `parseDocPath` and `formatDocPath` leave the static
|
|
158
|
+
exports of `@quillmark/wasm`: `const { Quill, Document } = await init()`
|
|
159
|
+
replaces the value import. The precondition was carried entirely by
|
|
160
|
+
`init`'s signature, and a floating promise is an ESLint rule rather than a
|
|
161
|
+
`tsc` diagnostic, so a call site that skipped the await type-checked and then
|
|
162
|
+
passed or failed by load order. It now has no name to call. `Engine`,
|
|
163
|
+
`MAIN_CARD_ADDR`, `isQuillmarkError`, the open-set guards and the
|
|
164
|
+
writer/reader classes are unchanged, needing no instance or gated by their
|
|
165
|
+
arguments; the `Quill` / `Document` **type** exports are unchanged, so
|
|
166
|
+
annotations and `import type` compile as before. Class identity is untouched:
|
|
167
|
+
the gate hands out the core build's classes verbatim, and `instanceof` stays
|
|
168
|
+
the whole membership test. `runtime::not_initialized` and the build-time
|
|
169
|
+
sentinel that raised it retire with the door they guarded. Rust, Python,
|
|
170
|
+
documents and stored blobs are unaffected. See
|
|
171
|
+
`docs/migrations/0.102-to-0.103.md`
|
|
172
|
+
|
|
3
173
|
## v0.102.0 - 2026-08-04
|
|
4
174
|
|
|
5
175
|
The pre-1.0 vocabulary reset. Verbs, diagnostic codes, and two words that meant
|
package/README.md
CHANGED
|
@@ -10,11 +10,11 @@ Use Quillmark in browsers/Node.js with explicit in-memory trees (`Map<string, Ui
|
|
|
10
10
|
|
|
11
11
|
The package exposes **one import surface**:
|
|
12
12
|
|
|
13
|
-
- `@quillmark/wasm` (the root), the **canonical API**: `
|
|
14
|
-
an `Engine` that renders them.
|
|
13
|
+
- `@quillmark/wasm` (the root), the **canonical API**: `init`, resolving to
|
|
14
|
+
`Quill` and `Document`, and an `Engine` that renders them.
|
|
15
15
|
|
|
16
|
-
`Quill` and `Document` are
|
|
17
|
-
|
|
16
|
+
`Quill` and `Document` are the internal Typst-less core build's own classes,
|
|
17
|
+
handed out verbatim by `init`, so editor/validation code (`Quill.fromTree`,
|
|
18
18
|
`Document.fromMarkdown`) loads only that small core binary: no backend is
|
|
19
19
|
loaded until you render. The `Engine` hides everything else: each backend
|
|
20
20
|
(`typst`, `pdfform`) is a separate, private WASM binary with its own linear
|
|
@@ -31,9 +31,8 @@ bash scripts/build-wasm.sh
|
|
|
31
31
|
The script builds three variants: the core (no backend), the Typst backend
|
|
32
32
|
(default features), and the Typst-free pdfform backend (`pdfform` feature):
|
|
33
33
|
each with `--target web` and `--weak-refs` enabled (see
|
|
34
|
-
[Initialization](#initialization) and [Lifecycle](#lifecycle)). It then
|
|
35
|
-
|
|
36
|
-
asserts none of them carries a `.wasm` ESM import or a top-level await.
|
|
34
|
+
[Initialization](#initialization) and [Lifecycle](#lifecycle)). It then asserts
|
|
35
|
+
none of them carries a `.wasm` ESM import or a top-level await.
|
|
37
36
|
|
|
38
37
|
## Test
|
|
39
38
|
|
|
@@ -47,9 +46,9 @@ npm test
|
|
|
47
46
|
## Usage
|
|
48
47
|
|
|
49
48
|
```ts
|
|
50
|
-
import { init,
|
|
49
|
+
import { init, Engine } from "@quillmark/wasm";
|
|
51
50
|
|
|
52
|
-
await init();
|
|
51
|
+
const { Quill, Document } = await init(); // see Initialization
|
|
53
52
|
|
|
54
53
|
const quill = Quill.fromTree(tree); // no engine needed: build + validate
|
|
55
54
|
const engine = new Engine(); // loads a backend lazily on first render
|
|
@@ -68,12 +67,13 @@ const result = await engine.render(quill, parsed, { format: "pdf" });
|
|
|
68
67
|
|
|
69
68
|
## Initialization
|
|
70
69
|
|
|
71
|
-
`
|
|
72
|
-
after
|
|
70
|
+
`init` resolves to the core surface: `Quill`, `Document`, and the free
|
|
71
|
+
functions. Everything after the await is the synchronous surface the rest of
|
|
72
|
+
this README describes.
|
|
73
73
|
|
|
74
74
|
```js
|
|
75
|
-
import { init,
|
|
76
|
-
await init();
|
|
75
|
+
import { init, Engine } from "@quillmark/wasm";
|
|
76
|
+
const { Quill, Document } = await init();
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
The same line works everywhere: the binary streams from a URL in a browser and
|
|
@@ -83,10 +83,11 @@ the builds are `--target web`, so nothing in the package graph imports a `.wasm`
|
|
|
83
83
|
module or carries a top-level await, and a static `import` of this package is
|
|
84
84
|
safe anywhere, SSR included.
|
|
85
85
|
|
|
86
|
-
`init` is idempotent and concurrency-safe: every call returns
|
|
87
|
-
so several entry points may each `await init()` for one
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
`init` is idempotent and concurrency-safe: every non-conflicting call returns
|
|
87
|
+
the same promise, so several entry points may each `await init()` for one
|
|
88
|
+
instantiation. Destructure at **every** entry point (route loader, hydration
|
|
89
|
+
path, worker) rather than threading one result around. A failed init clears the
|
|
90
|
+
memo, so a retry works. Each realm initializes its own copy, a Worker included.
|
|
90
91
|
|
|
91
92
|
**Backends need nothing.** `Engine` instantiates a backend inside its lazy load,
|
|
92
93
|
on the first render against it.
|
|
@@ -94,13 +95,17 @@ on the first render against it.
|
|
|
94
95
|
**Overriding the source.** `init(source)` accepts bytes, a `Response`, a
|
|
95
96
|
`WebAssembly.Module`, or a URL, for hosts that route assets themselves or embed
|
|
96
97
|
the binary. Pass it on the first call; a later call passing a *different* source
|
|
97
|
-
|
|
98
|
-
same value again is fine, so several entry points may each
|
|
99
|
-
against one constant.
|
|
98
|
+
rejects with `runtime::init_conflict` rather than silently ignoring it. Passing
|
|
99
|
+
the same value again is fine, so several entry points may each
|
|
100
|
+
`await init(BYTES)` against one constant.
|
|
100
101
|
|
|
101
|
-
**
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
**Both failures reject.** `runtime::init_conflict` and `runtime::init_failed`
|
|
103
|
+
alike ride the returned promise, so one `catch` around `await init(...)` covers
|
|
104
|
+
the gate. See [Errors](#errors) for the rule this follows.
|
|
105
|
+
|
|
106
|
+
**You cannot forget.** The core surface has no static export, so a call site
|
|
107
|
+
that skips the await has no name to call. The precondition is structural rather
|
|
108
|
+
than a convention: no load order can make one entry point pass and another fail.
|
|
104
109
|
|
|
105
110
|
**Vite's dev server** pre-bundles dependencies, which moves the package away
|
|
106
111
|
from its binary. Exclude it:
|
|
@@ -547,6 +552,14 @@ try {
|
|
|
547
552
|
}
|
|
548
553
|
```
|
|
549
554
|
|
|
555
|
+
**Delivery follows the function, not the failure.** A synchronous method throws;
|
|
556
|
+
a promise-returning one rejects. The promise-returning surface is `init` and the
|
|
557
|
+
four `Engine` verbs (`render`, `open`, `supportedFormats`, `supportsCanvas`), so
|
|
558
|
+
a programming error reached through one of them (a foreign handle, an
|
|
559
|
+
unregistered backend) rejects like any other failure. Nothing here both returns
|
|
560
|
+
a promise and throws, so a `.catch` on a promise-returning call is a whole
|
|
561
|
+
guard.
|
|
562
|
+
|
|
550
563
|
`QuillmarkError` is a **structural interface, not a class**: the WASM layer
|
|
551
564
|
throws a real `Error` and attaches the property, so there is no constructor to
|
|
552
565
|
`instanceof` against; narrow with `isQuillmarkError` (which also works on
|
|
@@ -591,11 +604,11 @@ call returns: `try { return engine.render(quill, doc); } finally
|
|
|
591
604
|
{ doc.free(); }`: is safe even on the first render, while the backend
|
|
592
605
|
binary is still loading.
|
|
593
606
|
|
|
594
|
-
The package floor is Node
|
|
607
|
+
The package floor is Node 24+ (`engines: { node: ">=24" }`) and current
|
|
595
608
|
evergreen browsers; `--weak-refs` itself only needs Node 14.6+. The `using`
|
|
596
|
-
sugar ([explicit resource management][erm])
|
|
597
|
-
|
|
598
|
-
|
|
609
|
+
sugar ([explicit resource management][erm]) is on that floor and optional;
|
|
610
|
+
an explicit `try` / `finally` is the equivalent, and the form that also runs
|
|
611
|
+
in a browser that hasn't shipped it:
|
|
599
612
|
|
|
600
613
|
```ts
|
|
601
614
|
const session = await engine.open(quill, doc);
|
|
@@ -181,6 +181,11 @@ export type ContentIsland = {
|
|
|
181
181
|
* (`doc.storeField("qty", 3)`, `doc.revise("intro", md)`) the one coercion
|
|
182
182
|
* rule. A bare number is *not* an addr (`{ card: 2 }` is the self-documenting
|
|
183
183
|
* spelling), so no third navigation idiom re-fragments the surface.
|
|
184
|
+
*
|
|
185
|
+
* `doc.pathFor(addr)` mints the address as its canonical `DocPath` string, the
|
|
186
|
+
* anchor `Diagnostic.path` carries and `session.locate` / `session.fieldBoxes`
|
|
187
|
+
* take: a card path is kind-qualified, so building one by hand needs the card's
|
|
188
|
+
* `$kind`, and a wrong-kind path matches nothing silently.
|
|
184
189
|
*/
|
|
185
190
|
export interface Addr {
|
|
186
191
|
card?: number;
|
|
@@ -479,12 +484,32 @@ export interface QuillCardUi {
|
|
|
479
484
|
groups?: Record<string, QuillGroupUi>;
|
|
480
485
|
}
|
|
481
486
|
|
|
487
|
+
/** A block construct a body can hold. `paragraph` is absent on purpose: it is
|
|
488
|
+
* the floor and cannot be declined. */
|
|
489
|
+
export type QuillBlockConstruct =
|
|
490
|
+
| "heading"
|
|
491
|
+
| "rule"
|
|
492
|
+
| "code"
|
|
493
|
+
| "list"
|
|
494
|
+
| "quote"
|
|
495
|
+
| "table"
|
|
496
|
+
| "image";
|
|
497
|
+
|
|
482
498
|
/** Body namespace for a card (main or named card kind). */
|
|
483
499
|
export interface QuillCardBody {
|
|
484
500
|
/** When false, consumers must not accept or store body content for this card kind. Defaults to true. */
|
|
485
501
|
enabled?: boolean;
|
|
486
502
|
/** Example body content embedded verbatim in the blueprint body region. Fallback is "Write <card> body here." */
|
|
487
503
|
example?: string;
|
|
504
|
+
/** Block constructs this quill's plate does not typeset in this body.
|
|
505
|
+
*
|
|
506
|
+
* Absent or empty means it declines nothing, which is the default. An
|
|
507
|
+
* editor reads this to decline a gesture before the author makes it; a body
|
|
508
|
+
* that holds one anyway draws a non-fatal `plate::unsupported_construct`
|
|
509
|
+
* warning carrying the construct and a count. It is the quill's claim about
|
|
510
|
+
* its own plate, and nothing verifies it: a construct absent from this list
|
|
511
|
+
* is not a promise that the plate typesets it. */
|
|
512
|
+
unsupported?: QuillBlockConstruct[];
|
|
488
513
|
}
|
|
489
514
|
|
|
490
515
|
/** Schema entry for a single field declared in a quill's `Quill.yaml`.
|
|
@@ -501,11 +526,8 @@ export interface QuillFieldSchema {
|
|
|
501
526
|
description?: string;
|
|
502
527
|
default?: unknown;
|
|
503
528
|
example?: unknown;
|
|
504
|
-
/**
|
|
505
|
-
*
|
|
506
|
-
* release. Both round-trip through this field. */
|
|
507
|
-
enum?: string[];
|
|
508
|
-
/** Required on `type: "enum"`: the closed set of allowed string values. */
|
|
529
|
+
/** Required on `type: "enum"`, and valid nowhere else: the closed set of
|
|
530
|
+
* allowed string values. */
|
|
509
531
|
values?: string[];
|
|
510
532
|
ui?: QuillFieldUi;
|
|
511
533
|
properties?: Record<string, QuillFieldSchema>;
|
|
@@ -752,7 +774,7 @@ export interface Location {
|
|
|
752
774
|
}
|
|
753
775
|
|
|
754
776
|
/**
|
|
755
|
-
* What a committed `LiveSession.
|
|
777
|
+
* What a committed `LiveSession.update` changed. `dirtyPages` lists the pages
|
|
756
778
|
* whose rendered content differs from the previous compile, including pages
|
|
757
779
|
* the edit added; removed pages are implied by `pageCount`. A preview
|
|
758
780
|
* repaints `dirty ∩ visible` and nothing else.
|
|
@@ -812,6 +834,13 @@ export class Document {
|
|
|
812
834
|
* verbs.
|
|
813
835
|
*/
|
|
814
836
|
card(index: number): Card;
|
|
837
|
+
/**
|
|
838
|
+
* The composable card's own path, `cards.<kind>[index]`: the whole-card
|
|
839
|
+
* root [`pathFor`](Self::path_for) extends, for a consumer anchoring the
|
|
840
|
+
* card rather than one of its fields. Total on the index axis for the same
|
|
841
|
+
* reason, out of range renders `cards[index]`.
|
|
842
|
+
*/
|
|
843
|
+
cardPath(index: number): string;
|
|
815
844
|
clone(): Document;
|
|
816
845
|
/**
|
|
817
846
|
* Storage version this build writes via [`toJson`](Document::to_json).
|
|
@@ -959,6 +988,29 @@ export class Document {
|
|
|
959
988
|
* not a canonical content object.
|
|
960
989
|
*/
|
|
961
990
|
overwrite(addr: Addr | string, rt: Content): void;
|
|
991
|
+
/**
|
|
992
|
+
* `addr`'s canonical `DocPath` string, the anchor `Diagnostic.path`
|
|
993
|
+
* carries: `pathFor()` is `main.body`, `pathFor("intro")` `main.intro`,
|
|
994
|
+
* `pathFor({card: 2})` `cards.<kind>[2].body`. A consumer holding an
|
|
995
|
+
* `Addr` mints one without restating the kind lookup, the `Addr` defaults
|
|
996
|
+
* or the range guard.
|
|
997
|
+
*
|
|
998
|
+
* The kind is the card's stored `$kind` verbatim, the quill-free rule the
|
|
999
|
+
* addressed mutators anchor with and the geometry translation uses, not
|
|
1000
|
+
* `validate`'s declared-kind filter: a `Document` holds a `$quill`
|
|
1001
|
+
* reference and no schema. That is the one edge where this path and a
|
|
1002
|
+
* `validate` diagnostic path differ for the same card.
|
|
1003
|
+
*
|
|
1004
|
+
* **Total on the index axis**, unlike the `Addr` reads (`getStored`,
|
|
1005
|
+
* `isFill`, `bodyMarkdown`), which throw there: a path is an anchor, not
|
|
1006
|
+
* a read. An out-of-range `{card: 7, field: "from"}` extends the
|
|
1007
|
+
* unknown-kind root `edit::index_out_of_range` anchors at, rendering
|
|
1008
|
+
* `cards[7].from`, which parses back and resolves to nothing rather than
|
|
1009
|
+
* mis-targeting. So a per-keystroke call needs no `try`; a caller wanting
|
|
1010
|
+
* a drop-it guard has [`cardCount`](Self::card_count). Only a malformed
|
|
1011
|
+
* address throws.
|
|
1012
|
+
*/
|
|
1013
|
+
pathFor(addr: Addr | string): string;
|
|
962
1014
|
/**
|
|
963
1015
|
* The canonical `$quill` reference grammar as author-facing text. Core is
|
|
964
1016
|
* the single source of truth: drive schema `describe` and validation
|
|
@@ -1513,6 +1565,7 @@ export interface InitOutput {
|
|
|
1513
1565
|
readonly document_bodyMarkdown: (a: number, b: number, c: number) => void;
|
|
1514
1566
|
readonly document_card: (a: number, b: number, c: number) => void;
|
|
1515
1567
|
readonly document_cardCount: (a: number) => number;
|
|
1568
|
+
readonly document_cardPath: (a: number, b: number, c: number) => void;
|
|
1516
1569
|
readonly document_cards: (a: number, b: number) => void;
|
|
1517
1570
|
readonly document_clone: (a: number) => number;
|
|
1518
1571
|
readonly document_currentStorageVersion: (a: number) => void;
|
|
@@ -1532,6 +1585,7 @@ export interface InitOutput {
|
|
|
1532
1585
|
readonly document_moveCard: (a: number, b: number, c: number, d: number) => void;
|
|
1533
1586
|
readonly document_new: (a: number, b: number, c: number) => void;
|
|
1534
1587
|
readonly document_overwrite: (a: number, b: number, c: number, d: number) => void;
|
|
1588
|
+
readonly document_pathFor: (a: number, b: number, c: number) => void;
|
|
1535
1589
|
readonly document_quillRef: (a: number, b: number) => void;
|
|
1536
1590
|
readonly document_quillRefHint: (a: number) => void;
|
|
1537
1591
|
readonly document_removeCard: (a: number, b: number, c: number) => void;
|
package/backends/pdfform/wasm.js
CHANGED
|
@@ -368,6 +368,30 @@ export class Document {
|
|
|
368
368
|
const ret = wasm.document_cardCount(this.__wbg_ptr);
|
|
369
369
|
return ret >>> 0;
|
|
370
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* The composable card's own path, `cards.<kind>[index]`: the whole-card
|
|
373
|
+
* root [`pathFor`](Self::path_for) extends, for a consumer anchoring the
|
|
374
|
+
* card rather than one of its fields. Total on the index axis for the same
|
|
375
|
+
* reason, out of range renders `cards[index]`.
|
|
376
|
+
* @param {number} index
|
|
377
|
+
* @returns {string}
|
|
378
|
+
*/
|
|
379
|
+
cardPath(index) {
|
|
380
|
+
let deferred1_0;
|
|
381
|
+
let deferred1_1;
|
|
382
|
+
try {
|
|
383
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
384
|
+
wasm.document_cardPath(retptr, this.__wbg_ptr, index);
|
|
385
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
386
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
387
|
+
deferred1_0 = r0;
|
|
388
|
+
deferred1_1 = r1;
|
|
389
|
+
return getStringFromWasm0(r0, r1);
|
|
390
|
+
} finally {
|
|
391
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
392
|
+
wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
371
395
|
/**
|
|
372
396
|
* @returns {Card[]}
|
|
373
397
|
*/
|
|
@@ -815,6 +839,54 @@ export class Document {
|
|
|
815
839
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
816
840
|
}
|
|
817
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* `addr`'s canonical `DocPath` string, the anchor `Diagnostic.path`
|
|
844
|
+
* carries: `pathFor()` is `main.body`, `pathFor("intro")` `main.intro`,
|
|
845
|
+
* `pathFor({card: 2})` `cards.<kind>[2].body`. A consumer holding an
|
|
846
|
+
* `Addr` mints one without restating the kind lookup, the `Addr` defaults
|
|
847
|
+
* or the range guard.
|
|
848
|
+
*
|
|
849
|
+
* The kind is the card's stored `$kind` verbatim, the quill-free rule the
|
|
850
|
+
* addressed mutators anchor with and the geometry translation uses, not
|
|
851
|
+
* `validate`'s declared-kind filter: a `Document` holds a `$quill`
|
|
852
|
+
* reference and no schema. That is the one edge where this path and a
|
|
853
|
+
* `validate` diagnostic path differ for the same card.
|
|
854
|
+
*
|
|
855
|
+
* **Total on the index axis**, unlike the `Addr` reads (`getStored`,
|
|
856
|
+
* `isFill`, `bodyMarkdown`), which throw there: a path is an anchor, not
|
|
857
|
+
* a read. An out-of-range `{card: 7, field: "from"}` extends the
|
|
858
|
+
* unknown-kind root `edit::index_out_of_range` anchors at, rendering
|
|
859
|
+
* `cards[7].from`, which parses back and resolves to nothing rather than
|
|
860
|
+
* mis-targeting. So a per-keystroke call needs no `try`; a caller wanting
|
|
861
|
+
* a drop-it guard has [`cardCount`](Self::card_count). Only a malformed
|
|
862
|
+
* address throws.
|
|
863
|
+
* @param {Addr | string} addr
|
|
864
|
+
* @returns {string}
|
|
865
|
+
*/
|
|
866
|
+
pathFor(addr) {
|
|
867
|
+
let deferred2_0;
|
|
868
|
+
let deferred2_1;
|
|
869
|
+
try {
|
|
870
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
871
|
+
wasm.document_pathFor(retptr, this.__wbg_ptr, addHeapObject(addr));
|
|
872
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
873
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
874
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
875
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
876
|
+
var ptr1 = r0;
|
|
877
|
+
var len1 = r1;
|
|
878
|
+
if (r3) {
|
|
879
|
+
ptr1 = 0; len1 = 0;
|
|
880
|
+
throw takeObject(r2);
|
|
881
|
+
}
|
|
882
|
+
deferred2_0 = ptr1;
|
|
883
|
+
deferred2_1 = len1;
|
|
884
|
+
return getStringFromWasm0(ptr1, len1);
|
|
885
|
+
} finally {
|
|
886
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
887
|
+
wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
818
890
|
/**
|
|
819
891
|
* @returns {string}
|
|
820
892
|
*/
|
|
@@ -2885,8 +2957,7 @@ if (!('encodeInto' in cachedTextEncoder)) {
|
|
|
2885
2957
|
|
|
2886
2958
|
let WASM_VECTOR_LEN = 0;
|
|
2887
2959
|
|
|
2888
|
-
|
|
2889
|
-
let wasmModule, wasm = uninitSentinel("@quillmark/wasm internal error: the 'pdfform' backend was used before instantiation.", "This is a bug in @quillmark/wasm, not in your code. Please report it.");
|
|
2960
|
+
let wasmModule, wasm;
|
|
2890
2961
|
function __wbg_finalize_init(instance, module) {
|
|
2891
2962
|
wasm = instance.exports;
|
|
2892
2963
|
wasmModule = module;
|
|
@@ -2933,7 +3004,7 @@ async function __wbg_load(module, imports) {
|
|
|
2933
3004
|
}
|
|
2934
3005
|
|
|
2935
3006
|
function initSync(module) {
|
|
2936
|
-
if (wasm !== undefined
|
|
3007
|
+
if (wasm !== undefined) return wasm;
|
|
2937
3008
|
|
|
2938
3009
|
|
|
2939
3010
|
if (module !== undefined) {
|
|
@@ -2953,7 +3024,7 @@ function initSync(module) {
|
|
|
2953
3024
|
}
|
|
2954
3025
|
|
|
2955
3026
|
async function __wbg_init(module_or_path) {
|
|
2956
|
-
if (wasm !== undefined
|
|
3027
|
+
if (wasm !== undefined) return wasm;
|
|
2957
3028
|
|
|
2958
3029
|
|
|
2959
3030
|
if (module_or_path !== undefined) {
|
|
Binary file
|
|
@@ -16,6 +16,7 @@ export const document_blueprintInstruction: (a: number, b: number, c: number) =>
|
|
|
16
16
|
export const document_bodyMarkdown: (a: number, b: number, c: number) => void;
|
|
17
17
|
export const document_card: (a: number, b: number, c: number) => void;
|
|
18
18
|
export const document_cardCount: (a: number) => number;
|
|
19
|
+
export const document_cardPath: (a: number, b: number, c: number) => void;
|
|
19
20
|
export const document_cards: (a: number, b: number) => void;
|
|
20
21
|
export const document_clone: (a: number) => number;
|
|
21
22
|
export const document_currentStorageVersion: (a: number) => void;
|
|
@@ -35,6 +36,7 @@ export const document_makeCard: (a: number, b: number, c: number, d: number, e:
|
|
|
35
36
|
export const document_moveCard: (a: number, b: number, c: number, d: number) => void;
|
|
36
37
|
export const document_new: (a: number, b: number, c: number) => void;
|
|
37
38
|
export const document_overwrite: (a: number, b: number, c: number, d: number) => void;
|
|
39
|
+
export const document_pathFor: (a: number, b: number, c: number) => void;
|
|
38
40
|
export const document_quillRef: (a: number, b: number) => void;
|
|
39
41
|
export const document_quillRefHint: (a: number) => void;
|
|
40
42
|
export const document_removeCard: (a: number, b: number, c: number) => void;
|