@quillmark/wasm 0.125.0 → 0.126.1
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 +329 -0
- package/LICENSE +198 -10
- package/NOTICE +8 -0
- package/README.md +40 -28
- package/THIRD_PARTY_LICENSES.md +10629 -0
- package/core/wasm.d.ts +25 -18
- package/core/wasm.js +14 -13
- package/core/wasm_bg.wasm +0 -0
- package/package.json +19 -2
- package/render/wasm.d.ts +25 -18
- package/render/wasm.js +14 -13
- package/render/wasm_bg.wasm +0 -0
- package/runtime/runtime.d.ts +10 -3
- package/runtime/runtime.js +69 -16
- package/sbom.cdx.json +631 -62
package/core/wasm.d.ts
CHANGED
|
@@ -446,11 +446,10 @@ export interface Resolved {
|
|
|
446
446
|
/** UI layout hints for a single field. Display order is not a hint: key order
|
|
447
447
|
* in the schema's `fields`/`properties` objects is the ordering contract. */
|
|
448
448
|
export interface QuillFieldUi {
|
|
449
|
-
/** The id of the card
|
|
449
|
+
/** The id of the card group holding the field, a key of the card's
|
|
450
450
|
* `ui.groups`. */
|
|
451
451
|
group?: string;
|
|
452
452
|
compact?: boolean;
|
|
453
|
-
multiline?: boolean;
|
|
454
453
|
/** Label for an `enum`'s blank option. Absent, the consumer supplies a
|
|
455
454
|
* conventional label of its own. */
|
|
456
455
|
blank_title?: string;
|
|
@@ -464,8 +463,8 @@ export interface QuillFieldUi {
|
|
|
464
463
|
layout?: "table" | "flat";
|
|
465
464
|
}
|
|
466
465
|
|
|
467
|
-
/** One
|
|
468
|
-
*
|
|
466
|
+
/** One group in a card's `ui.groups`: a display-label override for the
|
|
467
|
+
* group id (the map key). An empty object carries no override, and the
|
|
469
468
|
* consumer derives the label from the id (`memo_for` → "Memo For"). */
|
|
470
469
|
export interface QuillGroupUi {
|
|
471
470
|
title?: string;
|
|
@@ -473,9 +472,9 @@ export interface QuillGroupUi {
|
|
|
473
472
|
|
|
474
473
|
/** UI layout hints for a card (main or named card kind). */
|
|
475
474
|
export interface QuillCardUi {
|
|
476
|
-
/** The card's
|
|
475
|
+
/** The card's groups keyed by id, each holding at least one field, which
|
|
477
476
|
* names it in its `ui.group`. Key order is the display-order contract, as
|
|
478
|
-
* with `fields`. Absent when the card declares no
|
|
477
|
+
* with `fields`. Absent when the card declares no groups. */
|
|
479
478
|
groups?: Record<string, QuillGroupUi>;
|
|
480
479
|
}
|
|
481
480
|
|
|
@@ -485,7 +484,7 @@ export interface QuillCardBody {
|
|
|
485
484
|
enabled?: boolean;
|
|
486
485
|
}
|
|
487
486
|
|
|
488
|
-
export type QuillFieldType = "
|
|
487
|
+
export type QuillFieldType = "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "text" | "richtext" | "enum" | "matrix";
|
|
489
488
|
|
|
490
489
|
/** Schema entry for a single field declared in a quill's `Quill.yaml`.
|
|
491
490
|
*
|
|
@@ -530,9 +529,12 @@ export interface QuillFieldSchema {
|
|
|
530
529
|
* out on. Valid only on an `array`. Never gates render: a document over
|
|
531
530
|
* the cap warns `validation::cardinality` and renders. */
|
|
532
531
|
max?: number;
|
|
533
|
-
/**
|
|
534
|
-
*
|
|
535
|
-
|
|
532
|
+
/** The line shape of a `text` or `richtext` field, valid nowhere else.
|
|
533
|
+
* Absent or `false`, the field is one line (`text`) or one paragraph with
|
|
534
|
+
* no container or island (`richtext`); `true` admits line breaks
|
|
535
|
+
* (`text`) or block structure (`richtext`). A `richtext` always carries
|
|
536
|
+
* it. */
|
|
537
|
+
multiline?: boolean;
|
|
536
538
|
}
|
|
537
539
|
|
|
538
540
|
/** Schema entry for the main card or a named card kind. */
|
|
@@ -572,6 +574,10 @@ export interface QuillMetadata {
|
|
|
572
574
|
backend: string;
|
|
573
575
|
author: string;
|
|
574
576
|
description: string;
|
|
577
|
+
/** An SPDX license expression; absent when the quill declares none. */
|
|
578
|
+
license?: string;
|
|
579
|
+
/** An absolute `http(s)` URL; absent when the quill declares none. */
|
|
580
|
+
homepage?: string;
|
|
575
581
|
}
|
|
576
582
|
|
|
577
583
|
|
|
@@ -686,7 +692,7 @@ export class Document {
|
|
|
686
692
|
* `edit::index_out_of_range`.
|
|
687
693
|
*
|
|
688
694
|
* A content field at rest has one stored form per codec: a `richtext` field
|
|
689
|
-
* holds the canonical content object, a `
|
|
695
|
+
* holds the canonical content object, a `text` field its literal
|
|
690
696
|
* string. A document from the bound door (`quill.parse` / `quill.conform`)
|
|
691
697
|
* is at rest; one from the transport door may rest as authored until it is
|
|
692
698
|
* conformed, and this read reports what is there. For the `Content` either
|
|
@@ -699,8 +705,9 @@ export class Document {
|
|
|
699
705
|
/**
|
|
700
706
|
* Insert a card: `at` absent appends, a number inserts at that index (in
|
|
701
707
|
* `0..=cards.length`). Accepts any `CardInput`, including a card read back
|
|
702
|
-
* out of a document. Throws if `card.kind` is not a valid kind name,
|
|
703
|
-
* `at` is out of range
|
|
708
|
+
* out of a document. Throws if `card.kind` is not a valid kind name, if
|
|
709
|
+
* `at` is out of range, or `edit::too_many_cards` if the document holds
|
|
710
|
+
* 1,000 cards.
|
|
704
711
|
*/
|
|
705
712
|
insertCard(card: CardInput, at?: number): void;
|
|
706
713
|
/**
|
|
@@ -913,7 +920,7 @@ export class Quill {
|
|
|
913
920
|
* The quill's example document, `undefined` when the quill has no
|
|
914
921
|
* `example.md` at its root: a filled-in page whose values are made up to show the
|
|
915
922
|
* quill in use, never kept. It comes back pinned to this quill's
|
|
916
|
-
* `name@
|
|
923
|
+
* `name@MAJOR.MINOR` and conformed as `parse` conforms, its parse and
|
|
917
924
|
* `conform::*` warnings on `doc.warnings`. Throws when the file does not
|
|
918
925
|
* parse or its `$quill` is not this quill's bare name.
|
|
919
926
|
*/
|
|
@@ -928,7 +935,7 @@ export class Quill {
|
|
|
928
935
|
* Parse `markdown` and conform it against this quill: the primary ingestion
|
|
929
936
|
* path, and the bound twin of the schema-free `Document.fromMarkdown`. The
|
|
930
937
|
* returned document rests at its canonical form (a `richtext` field as a
|
|
931
|
-
* content object, a `
|
|
938
|
+
* content object, a `text` field as its literal string), so `getStored`
|
|
932
939
|
* answers by the field's declared codec, not by how the document was built.
|
|
933
940
|
*
|
|
934
941
|
* Parse warnings and the `conform::*` diagnostics both land on
|
|
@@ -1039,15 +1046,15 @@ export function formatDocPath(segs: DocPathSeg[]): string;
|
|
|
1039
1046
|
export function importMarkdown(markdown: string): Imported;
|
|
1040
1047
|
|
|
1041
1048
|
/**
|
|
1042
|
-
* Whether `content` satisfies the
|
|
1043
|
-
* `
|
|
1049
|
+
* Whether `content` satisfies the one-line constraint of `text` and
|
|
1050
|
+
* `richtext`: one `Para` line, in no container, with no islands. Judged on
|
|
1044
1051
|
* the normalized content, which is what a write stores. Throws if `content` is
|
|
1045
1052
|
* not canonical content.
|
|
1046
1053
|
*/
|
|
1047
1054
|
export function isInline(content: Content): boolean;
|
|
1048
1055
|
|
|
1049
1056
|
/**
|
|
1050
|
-
* Whether `content` satisfies the `
|
|
1057
|
+
* Whether `content` satisfies the `text` constraint: no marks, no
|
|
1051
1058
|
* islands, every line a `Para` in no container. Judged on the normalized
|
|
1052
1059
|
* content, which is what a write stores. Throws if `content` is not canonical
|
|
1053
1060
|
* content.
|
package/core/wasm.js
CHANGED
|
@@ -58,7 +58,7 @@ export class Document {
|
|
|
58
58
|
/**
|
|
59
59
|
* Typed field write at `addr`, resolving the field's schema `type` from
|
|
60
60
|
* `quill`: the stable ABI under the runtime `writer.set`. One verb for every
|
|
61
|
-
* field type; the schema carries the
|
|
61
|
+
* field type; the schema carries the one-line constraint, so no type token
|
|
62
62
|
* is passed.
|
|
63
63
|
*
|
|
64
64
|
* A bare string is `Addr` shorthand for `{ field }`. A body address throws,
|
|
@@ -67,7 +67,7 @@ export class Document {
|
|
|
67
67
|
* `edit::unknown_field` rather than falling to the opaque store — use
|
|
68
68
|
* [`storeField`](Document::store_field) for that. Also throws
|
|
69
69
|
* `edit::field_coercion_failed` / `edit::field_decode` /
|
|
70
|
-
* `edit::
|
|
70
|
+
* `edit::field_not_single_line` on a typed mismatch,
|
|
71
71
|
* `edit::invalid_field_name` on a malformed name, and
|
|
72
72
|
* `edit::index_out_of_range` on an out-of-range card.
|
|
73
73
|
*
|
|
@@ -273,10 +273,10 @@ export class Document {
|
|
|
273
273
|
* Revise the content field at `addr` from authored text, typed *and*
|
|
274
274
|
* anchor-preserving: the ABI under `writer.reviseField`. Surviving anchors
|
|
275
275
|
* rebase as in [`revise`](Self::revise), then the diffed result is
|
|
276
|
-
* schema-conformed, so a `richtext
|
|
277
|
-
* result with `edit::
|
|
276
|
+
* schema-conformed, so a one-paragraph `richtext` field rejects a multi-block
|
|
277
|
+
* result with `edit::field_not_single_line`. Returns the `Revised` receipt, its
|
|
278
278
|
* warnings anchored at the field. The codec is the declared type's:
|
|
279
|
-
* `richtext` diffs markdown, `
|
|
279
|
+
* `richtext` diffs markdown, `text` literal text, which drops nothing.
|
|
280
280
|
*
|
|
281
281
|
* `addr` must name a field; a body address throws, since a body carries no
|
|
282
282
|
* field schema (use [`revise`](Self::revise)). An undeclared name throws
|
|
@@ -551,7 +551,7 @@ export class Document {
|
|
|
551
551
|
* `edit::index_out_of_range`.
|
|
552
552
|
*
|
|
553
553
|
* A content field at rest has one stored form per codec: a `richtext` field
|
|
554
|
-
* holds the canonical content object, a `
|
|
554
|
+
* holds the canonical content object, a `text` field its literal
|
|
555
555
|
* string. A document from the bound door (`quill.parse` / `quill.conform`)
|
|
556
556
|
* is at rest; one from the transport door may rest as authored until it is
|
|
557
557
|
* conformed, and this read reports what is there. For the `Content` either
|
|
@@ -580,8 +580,9 @@ export class Document {
|
|
|
580
580
|
/**
|
|
581
581
|
* Insert a card: `at` absent appends, a number inserts at that index (in
|
|
582
582
|
* `0..=cards.length`). Accepts any `CardInput`, including a card read back
|
|
583
|
-
* out of a document. Throws if `card.kind` is not a valid kind name,
|
|
584
|
-
* `at` is out of range
|
|
583
|
+
* out of a document. Throws if `card.kind` is not a valid kind name, if
|
|
584
|
+
* `at` is out of range, or `edit::too_many_cards` if the document holds
|
|
585
|
+
* 1,000 cards.
|
|
585
586
|
* @param {CardInput} card
|
|
586
587
|
* @param {number} [at]
|
|
587
588
|
*/
|
|
@@ -1318,7 +1319,7 @@ export class Quill {
|
|
|
1318
1319
|
* The quill's example document, `undefined` when the quill has no
|
|
1319
1320
|
* `example.md` at its root: a filled-in page whose values are made up to show the
|
|
1320
1321
|
* quill in use, never kept. It comes back pinned to this quill's
|
|
1321
|
-
* `name@
|
|
1322
|
+
* `name@MAJOR.MINOR` and conformed as `parse` conforms, its parse and
|
|
1322
1323
|
* `conform::*` warnings on `doc.warnings`. Throws when the file does not
|
|
1323
1324
|
* parse or its `$quill` is not this quill's bare name.
|
|
1324
1325
|
* @returns {Document | undefined}
|
|
@@ -1385,7 +1386,7 @@ export class Quill {
|
|
|
1385
1386
|
* Parse `markdown` and conform it against this quill: the primary ingestion
|
|
1386
1387
|
* path, and the bound twin of the schema-free `Document.fromMarkdown`. The
|
|
1387
1388
|
* returned document rests at its canonical form (a `richtext` field as a
|
|
1388
|
-
* content object, a `
|
|
1389
|
+
* content object, a `text` field as its literal string), so `getStored`
|
|
1389
1390
|
* answers by the field's declared codec, not by how the document was built.
|
|
1390
1391
|
*
|
|
1391
1392
|
* Parse warnings and the `conform::*` diagnostics both land on
|
|
@@ -1685,8 +1686,8 @@ export function importMarkdown(markdown) {
|
|
|
1685
1686
|
}
|
|
1686
1687
|
|
|
1687
1688
|
/**
|
|
1688
|
-
* Whether `content` satisfies the
|
|
1689
|
-
* `
|
|
1689
|
+
* Whether `content` satisfies the one-line constraint of `text` and
|
|
1690
|
+
* `richtext`: one `Para` line, in no container, with no islands. Judged on
|
|
1690
1691
|
* the normalized content, which is what a write stores. Throws if `content` is
|
|
1691
1692
|
* not canonical content.
|
|
1692
1693
|
* @param {Content} content
|
|
@@ -1709,7 +1710,7 @@ export function isInline(content) {
|
|
|
1709
1710
|
}
|
|
1710
1711
|
|
|
1711
1712
|
/**
|
|
1712
|
-
* Whether `content` satisfies the `
|
|
1713
|
+
* Whether `content` satisfies the `text` constraint: no marks, no
|
|
1713
1714
|
* islands, every line a `Para` in no container. Judged on the normalized
|
|
1714
1715
|
* content, which is what a write stores. Throws if `content` is not canonical
|
|
1715
1716
|
* content.
|
package/core/wasm_bg.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quillmark/wasm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.126.1",
|
|
4
4
|
"description": "WebAssembly bindings for Quillmark, a schema-driven document engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
+
"author": "Quillmark Contributors",
|
|
8
|
+
"homepage": "https://quillmark.dev/",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/borb-sh/quillmark/issues"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"markdown",
|
|
14
|
+
"pdf",
|
|
15
|
+
"typst",
|
|
16
|
+
"document",
|
|
17
|
+
"template",
|
|
18
|
+
"schema",
|
|
19
|
+
"forms",
|
|
20
|
+
"wasm"
|
|
21
|
+
],
|
|
7
22
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
23
|
+
"node": ">=22"
|
|
9
24
|
},
|
|
10
25
|
"repository": {
|
|
11
26
|
"type": "git",
|
|
@@ -16,6 +31,8 @@
|
|
|
16
31
|
"render",
|
|
17
32
|
"runtime",
|
|
18
33
|
"CHANGELOG.md",
|
|
34
|
+
"NOTICE",
|
|
35
|
+
"THIRD_PARTY_LICENSES.md",
|
|
19
36
|
"sbom.cdx.json"
|
|
20
37
|
],
|
|
21
38
|
"main": "./runtime/runtime.js",
|
package/render/wasm.d.ts
CHANGED
|
@@ -457,11 +457,10 @@ export interface Resolved {
|
|
|
457
457
|
/** UI layout hints for a single field. Display order is not a hint: key order
|
|
458
458
|
* in the schema's `fields`/`properties` objects is the ordering contract. */
|
|
459
459
|
export interface QuillFieldUi {
|
|
460
|
-
/** The id of the card
|
|
460
|
+
/** The id of the card group holding the field, a key of the card's
|
|
461
461
|
* `ui.groups`. */
|
|
462
462
|
group?: string;
|
|
463
463
|
compact?: boolean;
|
|
464
|
-
multiline?: boolean;
|
|
465
464
|
/** Label for an `enum`'s blank option. Absent, the consumer supplies a
|
|
466
465
|
* conventional label of its own. */
|
|
467
466
|
blank_title?: string;
|
|
@@ -475,8 +474,8 @@ export interface QuillFieldUi {
|
|
|
475
474
|
layout?: "table" | "flat";
|
|
476
475
|
}
|
|
477
476
|
|
|
478
|
-
/** One
|
|
479
|
-
*
|
|
477
|
+
/** One group in a card's `ui.groups`: a display-label override for the
|
|
478
|
+
* group id (the map key). An empty object carries no override, and the
|
|
480
479
|
* consumer derives the label from the id (`memo_for` → "Memo For"). */
|
|
481
480
|
export interface QuillGroupUi {
|
|
482
481
|
title?: string;
|
|
@@ -484,9 +483,9 @@ export interface QuillGroupUi {
|
|
|
484
483
|
|
|
485
484
|
/** UI layout hints for a card (main or named card kind). */
|
|
486
485
|
export interface QuillCardUi {
|
|
487
|
-
/** The card's
|
|
486
|
+
/** The card's groups keyed by id, each holding at least one field, which
|
|
488
487
|
* names it in its `ui.group`. Key order is the display-order contract, as
|
|
489
|
-
* with `fields`. Absent when the card declares no
|
|
488
|
+
* with `fields`. Absent when the card declares no groups. */
|
|
490
489
|
groups?: Record<string, QuillGroupUi>;
|
|
491
490
|
}
|
|
492
491
|
|
|
@@ -496,7 +495,7 @@ export interface QuillCardBody {
|
|
|
496
495
|
enabled?: boolean;
|
|
497
496
|
}
|
|
498
497
|
|
|
499
|
-
export type QuillFieldType = "
|
|
498
|
+
export type QuillFieldType = "number" | "integer" | "boolean" | "array" | "object" | "date" | "datetime" | "text" | "richtext" | "enum" | "matrix";
|
|
500
499
|
|
|
501
500
|
/** Schema entry for a single field declared in a quill's `Quill.yaml`.
|
|
502
501
|
*
|
|
@@ -541,9 +540,12 @@ export interface QuillFieldSchema {
|
|
|
541
540
|
* out on. Valid only on an `array`. Never gates render: a document over
|
|
542
541
|
* the cap warns `validation::cardinality` and renders. */
|
|
543
542
|
max?: number;
|
|
544
|
-
/**
|
|
545
|
-
*
|
|
546
|
-
|
|
543
|
+
/** The line shape of a `text` or `richtext` field, valid nowhere else.
|
|
544
|
+
* Absent or `false`, the field is one line (`text`) or one paragraph with
|
|
545
|
+
* no container or island (`richtext`); `true` admits line breaks
|
|
546
|
+
* (`text`) or block structure (`richtext`). A `richtext` always carries
|
|
547
|
+
* it. */
|
|
548
|
+
multiline?: boolean;
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
/** Schema entry for the main card or a named card kind. */
|
|
@@ -583,6 +585,10 @@ export interface QuillMetadata {
|
|
|
583
585
|
backend: string;
|
|
584
586
|
author: string;
|
|
585
587
|
description: string;
|
|
588
|
+
/** An SPDX license expression; absent when the quill declares none. */
|
|
589
|
+
license?: string;
|
|
590
|
+
/** An absolute `http(s)` URL; absent when the quill declares none. */
|
|
591
|
+
homepage?: string;
|
|
586
592
|
}
|
|
587
593
|
|
|
588
594
|
|
|
@@ -824,7 +830,7 @@ export class Document {
|
|
|
824
830
|
* `edit::index_out_of_range`.
|
|
825
831
|
*
|
|
826
832
|
* A content field at rest has one stored form per codec: a `richtext` field
|
|
827
|
-
* holds the canonical content object, a `
|
|
833
|
+
* holds the canonical content object, a `text` field its literal
|
|
828
834
|
* string. A document from the bound door (`quill.parse` / `quill.conform`)
|
|
829
835
|
* is at rest; one from the transport door may rest as authored until it is
|
|
830
836
|
* conformed, and this read reports what is there. For the `Content` either
|
|
@@ -837,8 +843,9 @@ export class Document {
|
|
|
837
843
|
/**
|
|
838
844
|
* Insert a card: `at` absent appends, a number inserts at that index (in
|
|
839
845
|
* `0..=cards.length`). Accepts any `CardInput`, including a card read back
|
|
840
|
-
* out of a document. Throws if `card.kind` is not a valid kind name,
|
|
841
|
-
* `at` is out of range
|
|
846
|
+
* out of a document. Throws if `card.kind` is not a valid kind name, if
|
|
847
|
+
* `at` is out of range, or `edit::too_many_cards` if the document holds
|
|
848
|
+
* 1,000 cards.
|
|
842
849
|
*/
|
|
843
850
|
insertCard(card: CardInput, at?: number): void;
|
|
844
851
|
/**
|
|
@@ -1172,7 +1179,7 @@ export class Quill {
|
|
|
1172
1179
|
* The quill's example document, `undefined` when the quill has no
|
|
1173
1180
|
* `example.md` at its root: a filled-in page whose values are made up to show the
|
|
1174
1181
|
* quill in use, never kept. It comes back pinned to this quill's
|
|
1175
|
-
* `name@
|
|
1182
|
+
* `name@MAJOR.MINOR` and conformed as `parse` conforms, its parse and
|
|
1176
1183
|
* `conform::*` warnings on `doc.warnings`. Throws when the file does not
|
|
1177
1184
|
* parse or its `$quill` is not this quill's bare name.
|
|
1178
1185
|
*/
|
|
@@ -1187,7 +1194,7 @@ export class Quill {
|
|
|
1187
1194
|
* Parse `markdown` and conform it against this quill: the primary ingestion
|
|
1188
1195
|
* path, and the bound twin of the schema-free `Document.fromMarkdown`. The
|
|
1189
1196
|
* returned document rests at its canonical form (a `richtext` field as a
|
|
1190
|
-
* content object, a `
|
|
1197
|
+
* content object, a `text` field as its literal string), so `getStored`
|
|
1191
1198
|
* answers by the field's declared codec, not by how the document was built.
|
|
1192
1199
|
*
|
|
1193
1200
|
* Parse warnings and the `conform::*` diagnostics both land on
|
|
@@ -1327,15 +1334,15 @@ export function formatDocPath(segs: DocPathSeg[]): string;
|
|
|
1327
1334
|
export function importMarkdown(markdown: string): Imported;
|
|
1328
1335
|
|
|
1329
1336
|
/**
|
|
1330
|
-
* Whether `content` satisfies the
|
|
1331
|
-
* `
|
|
1337
|
+
* Whether `content` satisfies the one-line constraint of `text` and
|
|
1338
|
+
* `richtext`: one `Para` line, in no container, with no islands. Judged on
|
|
1332
1339
|
* the normalized content, which is what a write stores. Throws if `content` is
|
|
1333
1340
|
* not canonical content.
|
|
1334
1341
|
*/
|
|
1335
1342
|
export function isInline(content: Content): boolean;
|
|
1336
1343
|
|
|
1337
1344
|
/**
|
|
1338
|
-
* Whether `content` satisfies the `
|
|
1345
|
+
* Whether `content` satisfies the `text` constraint: no marks, no
|
|
1339
1346
|
* islands, every line a `Para` in no container. Judged on the normalized
|
|
1340
1347
|
* content, which is what a write stores. Throws if `content` is not canonical
|
|
1341
1348
|
* content.
|
package/render/wasm.js
CHANGED
|
@@ -58,7 +58,7 @@ export class Document {
|
|
|
58
58
|
/**
|
|
59
59
|
* Typed field write at `addr`, resolving the field's schema `type` from
|
|
60
60
|
* `quill`: the stable ABI under the runtime `writer.set`. One verb for every
|
|
61
|
-
* field type; the schema carries the
|
|
61
|
+
* field type; the schema carries the one-line constraint, so no type token
|
|
62
62
|
* is passed.
|
|
63
63
|
*
|
|
64
64
|
* A bare string is `Addr` shorthand for `{ field }`. A body address throws,
|
|
@@ -67,7 +67,7 @@ export class Document {
|
|
|
67
67
|
* `edit::unknown_field` rather than falling to the opaque store — use
|
|
68
68
|
* [`storeField`](Document::store_field) for that. Also throws
|
|
69
69
|
* `edit::field_coercion_failed` / `edit::field_decode` /
|
|
70
|
-
* `edit::
|
|
70
|
+
* `edit::field_not_single_line` on a typed mismatch,
|
|
71
71
|
* `edit::invalid_field_name` on a malformed name, and
|
|
72
72
|
* `edit::index_out_of_range` on an out-of-range card.
|
|
73
73
|
*
|
|
@@ -273,10 +273,10 @@ export class Document {
|
|
|
273
273
|
* Revise the content field at `addr` from authored text, typed *and*
|
|
274
274
|
* anchor-preserving: the ABI under `writer.reviseField`. Surviving anchors
|
|
275
275
|
* rebase as in [`revise`](Self::revise), then the diffed result is
|
|
276
|
-
* schema-conformed, so a `richtext
|
|
277
|
-
* result with `edit::
|
|
276
|
+
* schema-conformed, so a one-paragraph `richtext` field rejects a multi-block
|
|
277
|
+
* result with `edit::field_not_single_line`. Returns the `Revised` receipt, its
|
|
278
278
|
* warnings anchored at the field. The codec is the declared type's:
|
|
279
|
-
* `richtext` diffs markdown, `
|
|
279
|
+
* `richtext` diffs markdown, `text` literal text, which drops nothing.
|
|
280
280
|
*
|
|
281
281
|
* `addr` must name a field; a body address throws, since a body carries no
|
|
282
282
|
* field schema (use [`revise`](Self::revise)). An undeclared name throws
|
|
@@ -551,7 +551,7 @@ export class Document {
|
|
|
551
551
|
* `edit::index_out_of_range`.
|
|
552
552
|
*
|
|
553
553
|
* A content field at rest has one stored form per codec: a `richtext` field
|
|
554
|
-
* holds the canonical content object, a `
|
|
554
|
+
* holds the canonical content object, a `text` field its literal
|
|
555
555
|
* string. A document from the bound door (`quill.parse` / `quill.conform`)
|
|
556
556
|
* is at rest; one from the transport door may rest as authored until it is
|
|
557
557
|
* conformed, and this read reports what is there. For the `Content` either
|
|
@@ -580,8 +580,9 @@ export class Document {
|
|
|
580
580
|
/**
|
|
581
581
|
* Insert a card: `at` absent appends, a number inserts at that index (in
|
|
582
582
|
* `0..=cards.length`). Accepts any `CardInput`, including a card read back
|
|
583
|
-
* out of a document. Throws if `card.kind` is not a valid kind name,
|
|
584
|
-
* `at` is out of range
|
|
583
|
+
* out of a document. Throws if `card.kind` is not a valid kind name, if
|
|
584
|
+
* `at` is out of range, or `edit::too_many_cards` if the document holds
|
|
585
|
+
* 1,000 cards.
|
|
585
586
|
* @param {CardInput} card
|
|
586
587
|
* @param {number} [at]
|
|
587
588
|
*/
|
|
@@ -1662,7 +1663,7 @@ export class Quill {
|
|
|
1662
1663
|
* The quill's example document, `undefined` when the quill has no
|
|
1663
1664
|
* `example.md` at its root: a filled-in page whose values are made up to show the
|
|
1664
1665
|
* quill in use, never kept. It comes back pinned to this quill's
|
|
1665
|
-
* `name@
|
|
1666
|
+
* `name@MAJOR.MINOR` and conformed as `parse` conforms, its parse and
|
|
1666
1667
|
* `conform::*` warnings on `doc.warnings`. Throws when the file does not
|
|
1667
1668
|
* parse or its `$quill` is not this quill's bare name.
|
|
1668
1669
|
* @returns {Document | undefined}
|
|
@@ -1729,7 +1730,7 @@ export class Quill {
|
|
|
1729
1730
|
* Parse `markdown` and conform it against this quill: the primary ingestion
|
|
1730
1731
|
* path, and the bound twin of the schema-free `Document.fromMarkdown`. The
|
|
1731
1732
|
* returned document rests at its canonical form (a `richtext` field as a
|
|
1732
|
-
* content object, a `
|
|
1733
|
+
* content object, a `text` field as its literal string), so `getStored`
|
|
1733
1734
|
* answers by the field's declared codec, not by how the document was built.
|
|
1734
1735
|
*
|
|
1735
1736
|
* Parse warnings and the `conform::*` diagnostics both land on
|
|
@@ -2134,8 +2135,8 @@ export function importMarkdown(markdown) {
|
|
|
2134
2135
|
}
|
|
2135
2136
|
|
|
2136
2137
|
/**
|
|
2137
|
-
* Whether `content` satisfies the
|
|
2138
|
-
* `
|
|
2138
|
+
* Whether `content` satisfies the one-line constraint of `text` and
|
|
2139
|
+
* `richtext`: one `Para` line, in no container, with no islands. Judged on
|
|
2139
2140
|
* the normalized content, which is what a write stores. Throws if `content` is
|
|
2140
2141
|
* not canonical content.
|
|
2141
2142
|
* @param {Content} content
|
|
@@ -2158,7 +2159,7 @@ export function isInline(content) {
|
|
|
2158
2159
|
}
|
|
2159
2160
|
|
|
2160
2161
|
/**
|
|
2161
|
-
* Whether `content` satisfies the `
|
|
2162
|
+
* Whether `content` satisfies the `text` constraint: no marks, no
|
|
2162
2163
|
* islands, every line a `Para` in no container. Judged on the normalized
|
|
2163
2164
|
* content, which is what a write stores. Throws if `content` is not canonical
|
|
2164
2165
|
* content.
|
package/render/wasm_bg.wasm
CHANGED
|
Binary file
|
package/runtime/runtime.d.ts
CHANGED
|
@@ -440,6 +440,13 @@ export declare class Engine {
|
|
|
440
440
|
*
|
|
441
441
|
* `today` reads as on {@link open}. An `options` key outside
|
|
442
442
|
* {@link RenderOptions} rejects, `today` among them.
|
|
443
|
+
*
|
|
444
|
+
* A compile that traps (out of memory, a panic) rejects as
|
|
445
|
+
* `runtime::backend_trapped`, the `WebAssembly.RuntimeError` on `cause`, as
|
|
446
|
+
* does a trap in {@link LiveSession}'s `update` / `render` / `paint`, and a
|
|
447
|
+
* `RangeError` or Firefox's `InternalError` for stack or memory exhaustion,
|
|
448
|
+
* which engines raise for a stack overflow inside wasm. The build's state is then undefined: discard the
|
|
449
|
+
* realm.
|
|
443
450
|
*/
|
|
444
451
|
render(quill: Quill, doc: Document, options?: RenderOptions, today?: string): Promise<RenderResult>;
|
|
445
452
|
|
|
@@ -660,12 +667,12 @@ export declare class DocumentWriter {
|
|
|
660
667
|
/**
|
|
661
668
|
* Revise the content main-card field `name` from authored text: typed *and*
|
|
662
669
|
* anchor-preserving. Surviving anchors rebase, then the diffed result is
|
|
663
|
-
* schema-conformed (`richtext
|
|
670
|
+
* schema-conformed (a one-paragraph `richtext` rejects a multi-block result). Throws
|
|
664
671
|
* `UnknownField` for a name the schema does not declare. Returns the
|
|
665
672
|
* `Revised` receipt, its warnings at the field.
|
|
666
673
|
*
|
|
667
674
|
* The codec comes from the declared type: `richtext` diffs markdown, while
|
|
668
|
-
* `
|
|
675
|
+
* `text` diffs the literal text and never imports markdown, so a
|
|
669
676
|
* byte-identical revise of a value carrying escapes is a byte no-op.
|
|
670
677
|
*/
|
|
671
678
|
reviseField(name: string, text: string): Revised;
|
|
@@ -734,7 +741,7 @@ export declare class CardWriter {
|
|
|
734
741
|
* A `Document` bound to its `Quill` for interpreted reads, from
|
|
735
742
|
* {@link Quill.reader}: the read twin of {@link DocumentWriter}. One `get` reads
|
|
736
743
|
* each field by its declared type — a richtext field to its markdown projection,
|
|
737
|
-
* a
|
|
744
|
+
* a text field to its literal text, every other type verbatim.
|
|
738
745
|
*
|
|
739
746
|
* The schema authority is the point: unlike the quill-free `Document.getStored`,
|
|
740
747
|
* an undeclared name throws `UnknownField` rather than reading back `undefined`,
|
package/runtime/runtime.js
CHANGED
|
@@ -161,6 +161,53 @@ function quillmarkError(code, message, hint) {
|
|
|
161
161
|
return err;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* `err` as `runtime::backend_trapped` when it is a `WebAssembly.RuntimeError`,
|
|
166
|
+
* or a `RangeError` (V8, JavaScriptCore) or `InternalError` (SpiderMonkey) for
|
|
167
|
+
* stack or memory exhaustion, which those engines raise for native stack
|
|
168
|
+
* overflow inside wasm; else unchanged.
|
|
169
|
+
* @param {unknown} err
|
|
170
|
+
* @returns {unknown}
|
|
171
|
+
*/
|
|
172
|
+
function backendTrap(err) {
|
|
173
|
+
const exhausted =
|
|
174
|
+
(err instanceof RangeError || (err instanceof Error && err.name === 'InternalError')) &&
|
|
175
|
+
/Maximum call stack|stack overflow|too much recursion|out of memory/i.test(err.message);
|
|
176
|
+
if (!(err instanceof WebAssembly.RuntimeError) && !exhausted) return err;
|
|
177
|
+
return Object.assign(
|
|
178
|
+
quillmarkError(
|
|
179
|
+
'runtime::backend_trapped',
|
|
180
|
+
`The backend build trapped (${err.message}); its state is now undefined.`,
|
|
181
|
+
'A render ran out of memory or stack, or panicked. Discard the realm before rendering again: terminate the Worker or restart the process. For untrusted input, cap the document size.'
|
|
182
|
+
),
|
|
183
|
+
{ cause: err }
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Run `fn` on a transient clone of `docJson` in `mod`'s memory, then free it. A
|
|
189
|
+
* call that throws can leave the clone borrowed, so its `free()` throws too, and
|
|
190
|
+
* the error in flight is the one that propagates.
|
|
191
|
+
* @param {any} mod
|
|
192
|
+
* @param {string} docJson
|
|
193
|
+
* @param {(doc: any) => any} fn
|
|
194
|
+
* @returns {any}
|
|
195
|
+
*/
|
|
196
|
+
function withDocClone(mod, docJson, fn) {
|
|
197
|
+
const backendDoc = mod.Document.fromStored(docJson);
|
|
198
|
+
let result;
|
|
199
|
+
try {
|
|
200
|
+
result = fn(backendDoc);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
try {
|
|
203
|
+
backendDoc.free();
|
|
204
|
+
} catch {}
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
backendDoc.free();
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
|
|
164
211
|
/**
|
|
165
212
|
* Throw on options that are not a plain object, or on a key of them, or of a
|
|
166
213
|
* null-prototype object they inherit from, outside `known`. The JS twin of the
|
|
@@ -568,16 +615,15 @@ export class Engine {
|
|
|
568
615
|
? null
|
|
569
616
|
: quill.toTree();
|
|
570
617
|
const { mod, engine } = await this.#resolveBackend(backendId);
|
|
571
|
-
// The
|
|
572
|
-
//
|
|
573
|
-
// `fn` MUST be synchronous: an async one would run against a freed clone.
|
|
574
|
-
const backendQuill = this.#cachedQuillClone(mod, backendId, quill, quillTree);
|
|
575
|
-
let backendDoc = null;
|
|
618
|
+
// The cached quill clone is intentionally not freed. `fn` MUST be
|
|
619
|
+
// synchronous: an async one would run against a freed doc clone.
|
|
576
620
|
try {
|
|
577
|
-
|
|
578
|
-
return
|
|
579
|
-
|
|
580
|
-
|
|
621
|
+
const backendQuill = this.#cachedQuillClone(mod, backendId, quill, quillTree);
|
|
622
|
+
return withDocClone(mod, docJson, (backendDoc) =>
|
|
623
|
+
fn({ mod, engine, quill: backendQuill, doc: backendDoc })
|
|
624
|
+
);
|
|
625
|
+
} catch (err) {
|
|
626
|
+
throw backendTrap(err);
|
|
581
627
|
}
|
|
582
628
|
}
|
|
583
629
|
|
|
@@ -654,12 +700,11 @@ export class LiveSession {
|
|
|
654
700
|
*/
|
|
655
701
|
update(doc) {
|
|
656
702
|
requireLocalDoc(doc, 'session.update(doc)');
|
|
657
|
-
|
|
703
|
+
const docJson = doc.toStored();
|
|
658
704
|
try {
|
|
659
|
-
backendDoc
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
backendDoc?.free();
|
|
705
|
+
return withDocClone(this.#mod, docJson, (backendDoc) => this.#inner.update(backendDoc));
|
|
706
|
+
} catch (err) {
|
|
707
|
+
throw backendTrap(err);
|
|
663
708
|
}
|
|
664
709
|
}
|
|
665
710
|
|
|
@@ -675,7 +720,11 @@ export class LiveSession {
|
|
|
675
720
|
|
|
676
721
|
/** @param {object} [options] */
|
|
677
722
|
render(options) {
|
|
678
|
-
|
|
723
|
+
try {
|
|
724
|
+
return this.#inner.render(options ?? undefined);
|
|
725
|
+
} catch (err) {
|
|
726
|
+
throw backendTrap(err);
|
|
727
|
+
}
|
|
679
728
|
}
|
|
680
729
|
|
|
681
730
|
/**
|
|
@@ -742,7 +791,11 @@ export class LiveSession {
|
|
|
742
791
|
* @param {number} scale
|
|
743
792
|
*/
|
|
744
793
|
paint(ctx, page, scale) {
|
|
745
|
-
|
|
794
|
+
try {
|
|
795
|
+
this.#inner.paint(ctx, page, scale);
|
|
796
|
+
} catch (err) {
|
|
797
|
+
throw backendTrap(err);
|
|
798
|
+
}
|
|
746
799
|
}
|
|
747
800
|
|
|
748
801
|
free() {
|