@quillmark/wasm 0.123.0 → 0.124.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 +142 -0
- package/README.md +15 -10
- package/core/wasm.d.ts +109 -27
- package/core/wasm.js +105 -30
- package/core/wasm_bg.wasm +0 -0
- package/core/wasm_bg.wasm.d.ts +2 -0
- package/package.json +1 -1
- package/render/wasm.d.ts +114 -30
- package/render/wasm.js +110 -33
- package/render/wasm_bg.wasm +0 -0
- package/render/wasm_bg.wasm.d.ts +2 -0
- package/runtime/runtime.d.ts +40 -18
- package/runtime/runtime.js +69 -37
package/render/wasm.js
CHANGED
|
@@ -26,11 +26,14 @@ export class Document {
|
|
|
26
26
|
* leaves the document untouched. Field errors throw the same per-field
|
|
27
27
|
* bundle as [`commitFields`](Self::commit_fields); an invalid kind or body,
|
|
28
28
|
* or a bad position, throws a single-entry bundle keyed `$kind` / `$body`.
|
|
29
|
+
* Returns the body import's `parse::dropped_construct` warnings, anchored
|
|
30
|
+
* at the placed card's body.
|
|
29
31
|
* @param {Quill} quill
|
|
30
32
|
* @param {string} kind
|
|
31
33
|
* @param {Record<string, unknown>} [fields]
|
|
32
34
|
* @param {string} [body]
|
|
33
35
|
* @param {number} [at]
|
|
36
|
+
* @returns {Diagnostic[]}
|
|
34
37
|
*/
|
|
35
38
|
_addCard(quill, kind, fields, body, at) {
|
|
36
39
|
try {
|
|
@@ -43,9 +46,11 @@ export class Document {
|
|
|
43
46
|
wasm.document__addCard(retptr, this.__wbg_ptr, quill.__wbg_ptr, ptr0, len0, isLikeNone(fields) ? 0 : addHeapObject(fields), ptr1, len1, isLikeNone(at) ? Number.MAX_SAFE_INTEGER : (at) >>> 0);
|
|
44
47
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
45
48
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
50
|
+
if (r2) {
|
|
51
|
+
throw takeObject(r1);
|
|
48
52
|
}
|
|
53
|
+
return takeObject(r0);
|
|
49
54
|
} finally {
|
|
50
55
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
51
56
|
}
|
|
@@ -228,14 +233,40 @@ export class Document {
|
|
|
228
233
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
229
234
|
}
|
|
230
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* The ABI under `writer.reviseDocument`: a whole-document revise, then
|
|
238
|
+
* conform against `quill`. Throws when `markdown` declares a `$quill` this quill
|
|
239
|
+
* does not answer to, before any mutation.
|
|
240
|
+
* @param {Quill} quill
|
|
241
|
+
* @param {string} markdown
|
|
242
|
+
* @returns {DocumentRevised}
|
|
243
|
+
*/
|
|
244
|
+
_reviseDocument(quill, markdown) {
|
|
245
|
+
try {
|
|
246
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
247
|
+
_assertClass(quill, Quill);
|
|
248
|
+
const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
249
|
+
const len0 = WASM_VECTOR_LEN;
|
|
250
|
+
wasm.document__reviseDocument(retptr, this.__wbg_ptr, quill.__wbg_ptr, ptr0, len0);
|
|
251
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
252
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
253
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
254
|
+
if (r2) {
|
|
255
|
+
throw takeObject(r1);
|
|
256
|
+
}
|
|
257
|
+
return takeObject(r0);
|
|
258
|
+
} finally {
|
|
259
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
231
262
|
/**
|
|
232
263
|
* Revise the content field at `addr` from authored text, typed *and*
|
|
233
264
|
* anchor-preserving: the ABI under `writer.reviseField`. Surviving anchors
|
|
234
265
|
* rebase as in [`revise`](Self::revise), then the diffed result is
|
|
235
266
|
* schema-conformed, so a `richtext(inline)` field rejects a multi-block
|
|
236
|
-
* result with `edit::field_not_inline`. Returns the
|
|
237
|
-
* is the declared type's:
|
|
238
|
-
* text.
|
|
267
|
+
* result with `edit::field_not_inline`. Returns the `Revised` receipt, its
|
|
268
|
+
* warnings anchored at the field. The codec is the declared type's:
|
|
269
|
+
* `richtext` diffs markdown, `plaintext` literal text, which drops nothing.
|
|
239
270
|
*
|
|
240
271
|
* `addr` must name a field; a body address throws, since a body carries no
|
|
241
272
|
* field schema (use [`revise`](Self::revise)). An undeclared name throws
|
|
@@ -243,7 +274,7 @@ export class Document {
|
|
|
243
274
|
* @param {Quill} quill
|
|
244
275
|
* @param {Addr | string} addr
|
|
245
276
|
* @param {string} text
|
|
246
|
-
* @returns {
|
|
277
|
+
* @returns {Revised}
|
|
247
278
|
*/
|
|
248
279
|
_reviseField(quill, addr, text) {
|
|
249
280
|
try {
|
|
@@ -861,16 +892,18 @@ export class Document {
|
|
|
861
892
|
/**
|
|
862
893
|
* **Revise** the richtext value at `addr` from a markdown string: the
|
|
863
894
|
* default write path. Imports the markdown, diffs it against the current
|
|
864
|
-
* value, rebases surviving identity anchors, and returns the
|
|
865
|
-
* editor bridge maps its own positions through
|
|
866
|
-
* `
|
|
867
|
-
*
|
|
895
|
+
* value, rebases surviving identity anchors, and returns the `Revised`
|
|
896
|
+
* receipt: the text `delta` an editor bridge maps its own positions through
|
|
897
|
+
* (`mapPos`), and a `parse::dropped_construct` warning per construct the
|
|
898
|
+
* import dropped, its `path` the address written. An absent `addr.field`
|
|
899
|
+
* targets the body, an absent `addr.card` the main card; an absent field
|
|
900
|
+
* cold-imports from empty.
|
|
868
901
|
*
|
|
869
902
|
* Throws on an out-of-range card, a malformed field name, a present
|
|
870
903
|
* non-content field value, or an over-nested markdown input.
|
|
871
904
|
* @param {Addr | string} addr
|
|
872
905
|
* @param {string} markdown
|
|
873
|
-
* @returns {
|
|
906
|
+
* @returns {Revised}
|
|
874
907
|
*/
|
|
875
908
|
revise(addr, markdown) {
|
|
876
909
|
try {
|
|
@@ -1051,8 +1084,33 @@ export class Document {
|
|
|
1051
1084
|
}
|
|
1052
1085
|
}
|
|
1053
1086
|
/**
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1087
|
+
* `toMarkdown` with each prose anchor of every body and content field
|
|
1088
|
+
* spelled read-only at its start where its line can hold the tag, and
|
|
1089
|
+
* listed with its field's path and line either way. An import drops every
|
|
1090
|
+
* tag, so `writer.reviseDocument` with the markdown keeps the anchors it keeps
|
|
1091
|
+
* with `toMarkdown`'s.
|
|
1092
|
+
* @returns {AnnotatedMarkdown}
|
|
1093
|
+
*/
|
|
1094
|
+
toAnnotatedMarkdown() {
|
|
1095
|
+
try {
|
|
1096
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1097
|
+
wasm.document_toAnnotatedMarkdown(retptr, this.__wbg_ptr);
|
|
1098
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1099
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1100
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1101
|
+
if (r2) {
|
|
1102
|
+
throw takeObject(r1);
|
|
1103
|
+
}
|
|
1104
|
+
return takeObject(r0);
|
|
1105
|
+
} finally {
|
|
1106
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Emit canonical Quillmark Markdown. Re-parsing the result produces a
|
|
1111
|
+
* `Document` equal to `self` by value and by type, but for content: a body
|
|
1112
|
+
* or content field holds what its markdown spells, so its anchors drop and
|
|
1113
|
+
* its island ids re-mint. `toStored` keeps both.
|
|
1056
1114
|
* @returns {string}
|
|
1057
1115
|
*/
|
|
1058
1116
|
toMarkdown() {
|
|
@@ -1098,7 +1156,7 @@ export class Document {
|
|
|
1098
1156
|
* The non-fatal diagnostics of the load that produced this document: parse
|
|
1099
1157
|
* warnings, plus `conform::*` warnings when it came through `quill.parse`.
|
|
1100
1158
|
* Session state, not document value: `equals` and the storage DTO exclude
|
|
1101
|
-
* it, and `fromStored` / `loadStored` clear it.
|
|
1159
|
+
* it, and `fromStored` / `loadStored` / `writer.reviseDocument` clear it.
|
|
1102
1160
|
* @returns {Diagnostic[]}
|
|
1103
1161
|
*/
|
|
1104
1162
|
get warnings() {
|
|
@@ -1763,8 +1821,8 @@ export class Quill {
|
|
|
1763
1821
|
return takeObject(ret);
|
|
1764
1822
|
}
|
|
1765
1823
|
/**
|
|
1766
|
-
* Validate `doc` against this quill's schema, returning every diagnostic
|
|
1767
|
-
*
|
|
1824
|
+
* Validate `doc` against this quill's schema, returning every diagnostic:
|
|
1825
|
+
* an error blocks a render, a warning does not. Forwards the canonical
|
|
1768
1826
|
* `validation::*` diagnostics the engine emits.
|
|
1769
1827
|
* @param {Document} doc
|
|
1770
1828
|
* @returns {Diagnostic[]}
|
|
@@ -1859,9 +1917,11 @@ export class Quillmark {
|
|
|
1859
1917
|
}
|
|
1860
1918
|
/**
|
|
1861
1919
|
* Render `doc` against `quill` in one shot: `open` + `LiveSession.render`,
|
|
1862
|
-
* with
|
|
1863
|
-
*
|
|
1864
|
-
*
|
|
1920
|
+
* with every `quill.validate` warning but `validation::declined_construct`,
|
|
1921
|
+
* which the compile raises as `backend::declined_construct`, ahead of the
|
|
1922
|
+
* compile's in `warnings`; the load's stay on `doc.warnings`. An unset
|
|
1923
|
+
* `output_format` falls back to the backend's first supported format.
|
|
1924
|
+
* `today` reads as on `open`.
|
|
1865
1925
|
* @param {Quill} quill
|
|
1866
1926
|
* @param {Document} doc
|
|
1867
1927
|
* @param {RenderOptions | null} [opts]
|
|
@@ -1983,7 +2043,7 @@ export function formatDiagnostic(diagnostic) {
|
|
|
1983
2043
|
}
|
|
1984
2044
|
|
|
1985
2045
|
/**
|
|
1986
|
-
* Serialize structured
|
|
2046
|
+
* Serialize structured `DocPathSeg` segments back to the canonical path
|
|
1987
2047
|
* string: the inverse of `parseDocPath`. Throws on a segment array the
|
|
1988
2048
|
* deserializer rejects, and on an empty one.
|
|
1989
2049
|
* @param {DocPathSeg[]} segs
|
|
@@ -2015,11 +2075,13 @@ export function formatDocPath(segs) {
|
|
|
2015
2075
|
}
|
|
2016
2076
|
|
|
2017
2077
|
/**
|
|
2018
|
-
* Import a markdown string
|
|
2019
|
-
*
|
|
2020
|
-
*
|
|
2078
|
+
* Import a markdown string: the pure, document-free codec. Returns the
|
|
2079
|
+
* canonical `content` and a `parse::dropped_construct` warning per construct
|
|
2080
|
+
* the import dropped, with no `path`. `overwrite(addr, importMarkdown(md).content)`
|
|
2081
|
+
* spells the cold, anchor-losing write; prefer `revise` for edit semantics.
|
|
2082
|
+
* Throws on an over-nested input.
|
|
2021
2083
|
* @param {string} markdown
|
|
2022
|
-
* @returns {
|
|
2084
|
+
* @returns {Imported}
|
|
2023
2085
|
*/
|
|
2024
2086
|
export function importMarkdown(markdown) {
|
|
2025
2087
|
try {
|
|
@@ -2152,7 +2214,7 @@ export function mapPos(delta, pos, assoc) {
|
|
|
2152
2214
|
|
|
2153
2215
|
/**
|
|
2154
2216
|
* Parse a canonical document-model `Diagnostic.path` (`cards.<kind>[<i>].<field>`,
|
|
2155
|
-
* `main.body`, `recipients[0].name`) into structured
|
|
2217
|
+
* `main.body`, `recipients[0].name`) into structured `DocPathSeg` segments, so
|
|
2156
2218
|
* a consumer routes on segments instead of regexing the string. Throws on a
|
|
2157
2219
|
* malformed path.
|
|
2158
2220
|
* @param {string} path
|
|
@@ -2178,12 +2240,13 @@ export function parseDocPath(path) {
|
|
|
2178
2240
|
|
|
2179
2241
|
/**
|
|
2180
2242
|
* Rebase `markdown` onto a `base` content: the document-free twin of `revise`,
|
|
2181
|
-
* returning the new `content
|
|
2182
|
-
* `Content.text`, surviving anchors rebased)
|
|
2183
|
-
*
|
|
2243
|
+
* returning the new `content`, the text `delta` (offsets are USV indices into
|
|
2244
|
+
* `Content.text`, surviving anchors rebased), and the import's
|
|
2245
|
+
* `parse::dropped_construct` warnings, with no `path`. Throws on an
|
|
2246
|
+
* over-nested markdown input or a non-content `base`.
|
|
2184
2247
|
* @param {Content} base
|
|
2185
2248
|
* @param {string} markdown
|
|
2186
|
-
* @returns {{ content: Content; delta: Delta }}
|
|
2249
|
+
* @returns {{ content: Content; delta: Delta; warnings: Diagnostic[] }}
|
|
2187
2250
|
*/
|
|
2188
2251
|
export function rebase(base, markdown) {
|
|
2189
2252
|
try {
|
|
@@ -2352,10 +2415,6 @@ function __wbg_get_imports() {
|
|
|
2352
2415
|
const ret = getObject(arg0).getMonth();
|
|
2353
2416
|
return ret;
|
|
2354
2417
|
},
|
|
2355
|
-
__wbg_getOwnPropertyNames_f8299644de14134c: function(arg0) {
|
|
2356
|
-
const ret = Object.getOwnPropertyNames(getObject(arg0));
|
|
2357
|
-
return addHeapObject(ret);
|
|
2358
|
-
},
|
|
2359
2418
|
__wbg_getPrototypeOf_4e7d85b5bf38d546: function() { return handleError(function (arg0) {
|
|
2360
2419
|
const ret = Reflect.getPrototypeOf(getObject(arg0));
|
|
2361
2420
|
return addHeapObject(ret);
|
|
@@ -2396,6 +2455,16 @@ function __wbg_get_imports() {
|
|
|
2396
2455
|
const ret = result;
|
|
2397
2456
|
return ret;
|
|
2398
2457
|
},
|
|
2458
|
+
__wbg_instanceof_Error_80a725f81f2e102d: function(arg0) {
|
|
2459
|
+
let result;
|
|
2460
|
+
try {
|
|
2461
|
+
result = getObject(arg0) instanceof Error;
|
|
2462
|
+
} catch (_) {
|
|
2463
|
+
result = false;
|
|
2464
|
+
}
|
|
2465
|
+
const ret = result;
|
|
2466
|
+
return ret;
|
|
2467
|
+
},
|
|
2399
2468
|
__wbg_instanceof_Map_b2611749102d7ba3: function(arg0) {
|
|
2400
2469
|
let result;
|
|
2401
2470
|
try {
|
|
@@ -2446,6 +2515,10 @@ function __wbg_get_imports() {
|
|
|
2446
2515
|
const ret = getObject(arg0).length;
|
|
2447
2516
|
return ret;
|
|
2448
2517
|
},
|
|
2518
|
+
__wbg_message_5f8387f0c32b90a7: function(arg0) {
|
|
2519
|
+
const ret = getObject(arg0).message;
|
|
2520
|
+
return addHeapObject(ret);
|
|
2521
|
+
},
|
|
2449
2522
|
__wbg_new_0_72d020f0c63443d4: function() {
|
|
2450
2523
|
const ret = new Date();
|
|
2451
2524
|
return addHeapObject(ret);
|
|
@@ -2490,6 +2563,10 @@ function __wbg_get_imports() {
|
|
|
2490
2563
|
const ret = getObject(arg0).next();
|
|
2491
2564
|
return addHeapObject(ret);
|
|
2492
2565
|
}, arguments); },
|
|
2566
|
+
__wbg_ownKeys_7f46b96dc7311fe8: function() { return handleError(function (arg0) {
|
|
2567
|
+
const ret = Reflect.ownKeys(getObject(arg0));
|
|
2568
|
+
return addHeapObject(ret);
|
|
2569
|
+
}, arguments); },
|
|
2493
2570
|
__wbg_prototypesetcall_bc27214492979395: function(arg0, arg1, arg2) {
|
|
2494
2571
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
|
|
2495
2572
|
},
|
package/render/wasm_bg.wasm
CHANGED
|
Binary file
|
package/render/wasm_bg.wasm.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export const document__commitFields: (a: number, b: number, c: number, d: number
|
|
|
11
11
|
export const document__readerGet: (a: number, b: number, c: number, d: number) => void;
|
|
12
12
|
export const document__readerGetContent: (a: number, b: number, c: number, d: number) => void;
|
|
13
13
|
export const document__readerGetContentAt: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
14
|
+
export const document__reviseDocument: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
14
15
|
export const document__reviseField: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
15
16
|
export const document_applyChange: (a: number, b: number, c: number, d: number) => void;
|
|
16
17
|
export const document_bodyMarkdown: (a: number, b: number, c: number) => void;
|
|
@@ -47,6 +48,7 @@ export const document_storeExt: (a: number, b: number, c: number, d: number) =>
|
|
|
47
48
|
export const document_storeField: (a: number, b: number, c: number, d: number) => void;
|
|
48
49
|
export const document_storeFields: (a: number, b: number, c: number, d: number) => void;
|
|
49
50
|
export const document_storeSeedOverlay: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
51
|
+
export const document_toAnnotatedMarkdown: (a: number, b: number) => void;
|
|
50
52
|
export const document_toMarkdown: (a: number, b: number) => void;
|
|
51
53
|
export const document_toStored: (a: number, b: number) => void;
|
|
52
54
|
export const document_warnings: (a: number, b: number) => void;
|
package/runtime/runtime.d.ts
CHANGED
|
@@ -117,7 +117,7 @@ export type {
|
|
|
117
117
|
} from '../core/wasm.js';
|
|
118
118
|
|
|
119
119
|
// Content edit vocabulary: the op-grained content model `Document`'s methods
|
|
120
|
-
// speak (`applyChange(addr, bundle)`, `overwrite(addr, rt)`, `revise(…) =>
|
|
120
|
+
// speak (`applyChange(addr, bundle)`, `overwrite(addr, rt)`, `revise(…) => Revised`).
|
|
121
121
|
// `ContentLineKind` is the shared half of `ContentLine` and `setKind`, and
|
|
122
122
|
// `ContentMarkKind` of `ContentMark` and a mark op's `add` / `remove`: lifting a
|
|
123
123
|
// read value's kind whole — destructure off the envelope, spread the rest into
|
|
@@ -139,6 +139,10 @@ export type {
|
|
|
139
139
|
Addr,
|
|
140
140
|
CardAddr,
|
|
141
141
|
Delta,
|
|
142
|
+
Revised,
|
|
143
|
+
DocumentRevised,
|
|
144
|
+
AnnotatedMarkdown,
|
|
145
|
+
Imported,
|
|
142
146
|
Assoc,
|
|
143
147
|
IslandOp,
|
|
144
148
|
LineOp,
|
|
@@ -410,11 +414,12 @@ export declare class Engine {
|
|
|
410
414
|
* synchronously before the first await, so the caller may `free()` them as
|
|
411
415
|
* soon as this call returns.
|
|
412
416
|
*
|
|
413
|
-
* {@link RenderResult.warnings} carries
|
|
414
|
-
* `
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
* compile's alone: read
|
|
417
|
+
* {@link RenderResult.warnings} carries every `quill.validate(doc)` warning
|
|
418
|
+
* but `validation::declined_construct`, which the compile raises as
|
|
419
|
+
* `backend::declined_construct`, then the compile's own. The load's (parse
|
|
420
|
+
* and `conform::*`) stay on `doc.warnings`, and a revise's on its receipt.
|
|
421
|
+
* A {@link LiveSession} carries the compile's alone: read
|
|
422
|
+
* `quill.validate(doc)` beside it.
|
|
418
423
|
*
|
|
419
424
|
* `today` reads as on {@link open}. An `options` key outside
|
|
420
425
|
* {@link RenderOptions} rejects, `today` among them.
|
|
@@ -591,7 +596,7 @@ declare module '../core/wasm.js' {
|
|
|
591
596
|
}
|
|
592
597
|
}
|
|
593
598
|
|
|
594
|
-
import type { Addr, Content,
|
|
599
|
+
import type { Addr, Content, DocumentRevised, PathStep, Resolved, Revised } from '../core/wasm.js';
|
|
595
600
|
|
|
596
601
|
/**
|
|
597
602
|
* A `Document` bound to its `Quill` for typed writes, from {@link Quill.writer}.
|
|
@@ -621,30 +626,44 @@ export declare class DocumentWriter {
|
|
|
621
626
|
*/
|
|
622
627
|
setAll(fields: Record<string, unknown>): void;
|
|
623
628
|
/**
|
|
624
|
-
* Revise the main body from markdown; anchors rebase. Returns the
|
|
625
|
-
* `
|
|
626
|
-
* content lane's `revise` reached
|
|
629
|
+
* Revise the main body from markdown; anchors rebase. Returns the
|
|
630
|
+
* `Revised` receipt, its warnings at `main.body`: a body carries no field
|
|
631
|
+
* schema to type against, so this is the content lane's `revise` reached
|
|
632
|
+
* through the writer.
|
|
627
633
|
*/
|
|
628
|
-
reviseBody(markdown: string):
|
|
634
|
+
reviseBody(markdown: string): Revised;
|
|
629
635
|
/**
|
|
630
636
|
* Revise the content main-card field `name` from authored text: typed *and*
|
|
631
637
|
* anchor-preserving. Surviving anchors rebase, then the diffed result is
|
|
632
638
|
* schema-conformed (`richtext(inline)` rejects a multi-block result). Throws
|
|
633
|
-
* `UnknownField` for a name the schema does not declare. Returns the
|
|
639
|
+
* `UnknownField` for a name the schema does not declare. Returns the
|
|
640
|
+
* `Revised` receipt, its warnings at the field.
|
|
634
641
|
*
|
|
635
642
|
* The codec comes from the declared type: `richtext` diffs markdown, while
|
|
636
643
|
* `plaintext` diffs the literal text and never imports markdown, so a
|
|
637
644
|
* byte-identical revise of a value carrying escapes is a byte no-op.
|
|
638
645
|
*/
|
|
639
|
-
reviseField(name: string, text: string):
|
|
646
|
+
reviseField(name: string, text: string): Revised;
|
|
647
|
+
/**
|
|
648
|
+
* Replace the bound document with `markdown`, then conform it. Composable
|
|
649
|
+
* cards align to the stored ones by `$kind` and text similarity, an aligned
|
|
650
|
+
* card's body and stored content fields revise, their anchors rebasing as
|
|
651
|
+
* {@link reviseBody}'s do, and every declared content field lands at rest.
|
|
652
|
+
* Returns the `DocumentRevised` receipt, its `warnings` ending with the
|
|
653
|
+
* `conform::*` ones, and clears `doc.warnings`. Throws when `markdown`
|
|
654
|
+
* declares a `$quill` this quill does not answer to, or does not parse,
|
|
655
|
+
* leaving the document unchanged.
|
|
656
|
+
*/
|
|
657
|
+
reviseDocument(markdown: string): DocumentRevised;
|
|
640
658
|
/**
|
|
641
659
|
* Build a composable card of `kind`, typed-commit `fields` onto it, set its
|
|
642
660
|
* body from optional markdown, and place it. `at` omitted appends, a number
|
|
643
661
|
* inserts at that index. Transactional: a rejected field (throwing a per-field
|
|
644
662
|
* diagnostic bundle) or an invalid kind, body, or position leaves the document
|
|
645
|
-
* untouched.
|
|
663
|
+
* untouched. Returns the body import's `parse::dropped_construct` warnings,
|
|
664
|
+
* anchored at the placed card's body.
|
|
646
665
|
*/
|
|
647
|
-
addCard(kind: string, fields?: Record<string, unknown>, body?: string, at?: number):
|
|
666
|
+
addCard(kind: string, fields?: Record<string, unknown>, body?: string, at?: number): Diagnostic[];
|
|
648
667
|
/** Remove the composable card at `index`, returning it (or `undefined`). */
|
|
649
668
|
removeCard(index: number): Card | undefined;
|
|
650
669
|
/**
|
|
@@ -674,13 +693,16 @@ export declare class CardWriter {
|
|
|
674
693
|
readonly kind: string;
|
|
675
694
|
set(name: string, value: unknown): void;
|
|
676
695
|
setAll(fields: Record<string, unknown>): void;
|
|
677
|
-
/**
|
|
678
|
-
|
|
696
|
+
/**
|
|
697
|
+
* Revise this card's body from markdown (edit semantics), returning the
|
|
698
|
+
* `Revised` receipt, its warnings at the card's body.
|
|
699
|
+
*/
|
|
700
|
+
reviseBody(markdown: string): Revised;
|
|
679
701
|
/**
|
|
680
702
|
* The card twin of {@link DocumentWriter.reviseField}. Throws `UnknownField`
|
|
681
703
|
* for an undeclared name and `IndexOutOfRange` for a bad bound index.
|
|
682
704
|
*/
|
|
683
|
-
reviseField(name: string, text: string):
|
|
705
|
+
reviseField(name: string, text: string): Revised;
|
|
684
706
|
}
|
|
685
707
|
|
|
686
708
|
/**
|
package/runtime/runtime.js
CHANGED
|
@@ -162,11 +162,11 @@ function quillmarkError(code, message, hint) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
/**
|
|
165
|
-
* Throw on options that are not a plain object, or on
|
|
166
|
-
* outside `known`. The JS twin of the
|
|
167
|
-
* uncoded shape it throws: a misspelled
|
|
168
|
-
* absent, and a read reaches a key up the
|
|
169
|
-
* sees.
|
|
165
|
+
* Throw on options that are not a plain object, or on a key of them, or of a
|
|
166
|
+
* null-prototype object they inherit from, outside `known`. The JS twin of the
|
|
167
|
+
* binding's `reject_unknown_keys`, in the uncoded shape it throws: a misspelled
|
|
168
|
+
* optional key would otherwise read as absent, and a read reaches a key up the
|
|
169
|
+
* prototype chain that no own-key walk sees.
|
|
170
170
|
* @param {unknown} options
|
|
171
171
|
* @param {string[]} known
|
|
172
172
|
* @param {string} what the options' name, for the message
|
|
@@ -174,8 +174,28 @@ function quillmarkError(code, message, hint) {
|
|
|
174
174
|
*/
|
|
175
175
|
function rejectUnknownKeys(options, known, what) {
|
|
176
176
|
if (options == null) return;
|
|
177
|
-
const proto = Object.getPrototypeOf(options);
|
|
178
177
|
let message;
|
|
178
|
+
try {
|
|
179
|
+
message = unknownKeyRefusal(options, known, what);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
const cause = e instanceof Error ? e.message : String(e);
|
|
182
|
+
message = `${what} must be a plain object, not one whose read throws: ${cause}`;
|
|
183
|
+
}
|
|
184
|
+
if (message === undefined) return;
|
|
185
|
+
const err = /** @type {any} */ (new Error(message));
|
|
186
|
+
err.diagnostics = [{ severity: 'error', message }];
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The refusal `rejectUnknownKeys` throws, if any. A `Proxy` trap may throw.
|
|
192
|
+
* @param {unknown} options
|
|
193
|
+
* @param {string[]} known
|
|
194
|
+
* @param {string} what
|
|
195
|
+
* @returns {string | undefined}
|
|
196
|
+
*/
|
|
197
|
+
function unknownKeyRefusal(options, known, what) {
|
|
198
|
+
const proto = Object.getPrototypeOf(options);
|
|
179
199
|
if (proto !== null && Object.getPrototypeOf(proto) !== null) {
|
|
180
200
|
const passed =
|
|
181
201
|
options instanceof Map
|
|
@@ -183,15 +203,16 @@ function rejectUnknownKeys(options, known, what) {
|
|
|
183
203
|
: typeof options === 'object'
|
|
184
204
|
? 'one inheriting from another object'
|
|
185
205
|
: `a ${typeof options}`;
|
|
186
|
-
|
|
187
|
-
} else {
|
|
188
|
-
const key = Object.getOwnPropertyNames(options).find((k) => !known.includes(k));
|
|
189
|
-
if (key === undefined) return;
|
|
190
|
-
message = `${what} have unknown key \`${key}\`; ${what} take only \`${known.join('`, `')}\``;
|
|
206
|
+
return `${what} must be a plain object, not ${passed}`;
|
|
191
207
|
}
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
208
|
+
const keys = Object.getOwnPropertyNames(options);
|
|
209
|
+
if (proto !== null) {
|
|
210
|
+
const builtin = Object.getOwnPropertyNames(Object.prototype);
|
|
211
|
+
keys.push(...Object.getOwnPropertyNames(proto).filter((k) => !builtin.includes(k)));
|
|
212
|
+
}
|
|
213
|
+
const key = keys.find((k) => !known.includes(k));
|
|
214
|
+
if (key === undefined) return undefined;
|
|
215
|
+
return `${what} have unknown key \`${key}\`; ${what} take only \`${known.join('`, `')}\``;
|
|
195
216
|
}
|
|
196
217
|
|
|
197
218
|
// These checks deliver the ERROR, not the rejection, at the seams that cross
|
|
@@ -263,9 +284,10 @@ function requireLocalQuill(quill, method) {
|
|
|
263
284
|
// `runtime.test.js` § "container run boundaries" stamps a pair and re-imports
|
|
264
285
|
// it, where `Content::normalize` re-mints against the Rust predicate. A tag the
|
|
265
286
|
// table omits welds with nothing, so `tests/known_names_drift.rs` pins that
|
|
266
|
-
// every container has an entry.
|
|
287
|
+
// every container has an entry. An entry of `'*'` welds on the whole bag: an
|
|
288
|
+
// element's attributes are open, its name among them.
|
|
267
289
|
|
|
268
|
-
const WELD_KEYS = { list_item: ['ordered'], quote: [] };
|
|
290
|
+
const WELD_KEYS = { list_item: ['ordered'], quote: [], element: '*' };
|
|
269
291
|
|
|
270
292
|
/**
|
|
271
293
|
* @param {import('../core/wasm.js').ContentContainer} a
|
|
@@ -278,7 +300,20 @@ function weldsWith(a, b) {
|
|
|
278
300
|
// `hasOwn`, so a tag colliding with an `Object.prototype` member answers
|
|
279
301
|
// `false` rather than reaching a function.
|
|
280
302
|
if (!Object.hasOwn(WELD_KEYS, a.container)) return false;
|
|
281
|
-
|
|
303
|
+
const keys = WELD_KEYS[a.container];
|
|
304
|
+
if (keys === '*') return sameBag(a.attrs, b.attrs);
|
|
305
|
+
return keys.every((k) => a.attrs?.[k] === b.attrs?.[k]);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @param {Record<string, unknown> | undefined} a
|
|
310
|
+
* @param {Record<string, unknown> | undefined} b
|
|
311
|
+
* @returns {boolean}
|
|
312
|
+
*/
|
|
313
|
+
function sameBag(a, b) {
|
|
314
|
+
const [x, y] = [a ?? {}, b ?? {}];
|
|
315
|
+
const keys = Object.keys(x);
|
|
316
|
+
return keys.length === Object.keys(y).length && keys.every((k) => Object.hasOwn(y, k) && x[k] === y[k]);
|
|
282
317
|
}
|
|
283
318
|
|
|
284
319
|
/**
|
|
@@ -510,16 +545,11 @@ export class Engine {
|
|
|
510
545
|
* memory and run `fn` against the backend engine. Only `render`/`open` call
|
|
511
546
|
* this, so `doc` is always present.
|
|
512
547
|
*
|
|
513
|
-
* OWNERSHIP WINDOW: both caller handles are snapshotted (`doc.toStored()
|
|
514
|
-
*
|
|
515
|
-
* await. The backend load below is a real suspension point, so reading the
|
|
548
|
+
* OWNERSHIP WINDOW: both caller handles are snapshotted (`doc.toStored()`,
|
|
549
|
+
* and `quill.toTree()` on a clone-cache miss) BEFORE the first await. The backend load below is a real suspension point, so reading the
|
|
516
550
|
* handles after it would race a caller that `free()`s them as soon as this
|
|
517
551
|
* call returns its promise ("null pointer passed to rust").
|
|
518
552
|
*
|
|
519
|
-
* `docWarnings` rides the context because the storage DTO does not carry
|
|
520
|
-
* them: `fromStored` clears the load's warnings, so the backend clone knows
|
|
521
|
-
* nothing of them and `render` splices the snapshot back in.
|
|
522
|
-
*
|
|
523
553
|
* Clone lifetimes differ by design: the `doc` clone is TRANSIENT, freed in
|
|
524
554
|
* the `finally` of every call, while the `quill` clone is CACHED and is not
|
|
525
555
|
* freed here — a `Quill` instance's contents never change after
|
|
@@ -528,13 +558,12 @@ export class Engine {
|
|
|
528
558
|
* @param {string} method the caller's name, for the rejection message
|
|
529
559
|
* @param {Quill} quill
|
|
530
560
|
* @param {Document} doc
|
|
531
|
-
* @param {(ctx: { mod: any, engine: any, quill: any, doc: any
|
|
561
|
+
* @param {(ctx: { mod: any, engine: any, quill: any, doc: any }) => any} fn
|
|
532
562
|
*/
|
|
533
563
|
async #withClones(method, quill, doc, fn) {
|
|
534
564
|
const backendId = this.#backendOf(quill, method);
|
|
535
565
|
requireLocalDoc(doc, method);
|
|
536
566
|
const docJson = doc.toStored();
|
|
537
|
-
const docWarnings = doc.warnings;
|
|
538
567
|
const quillTree = this.#quillClones.get(this.#descriptorFor(backendId).load)?.has(quill)
|
|
539
568
|
? null
|
|
540
569
|
: quill.toTree();
|
|
@@ -546,7 +575,7 @@ export class Engine {
|
|
|
546
575
|
let backendDoc = null;
|
|
547
576
|
try {
|
|
548
577
|
backendDoc = mod.Document.fromStored(docJson);
|
|
549
|
-
return fn({ mod, engine, quill: backendQuill, doc: backendDoc
|
|
578
|
+
return fn({ mod, engine, quill: backendQuill, doc: backendDoc });
|
|
550
579
|
} finally {
|
|
551
580
|
backendDoc?.free();
|
|
552
581
|
}
|
|
@@ -564,11 +593,7 @@ export class Engine {
|
|
|
564
593
|
'engine.render(quill, doc)',
|
|
565
594
|
quill,
|
|
566
595
|
doc,
|
|
567
|
-
({ engine, quill: q, doc: d
|
|
568
|
-
const result = engine.render(q, d, options ?? undefined, today);
|
|
569
|
-
result.warnings = docWarnings.concat(result.warnings);
|
|
570
|
-
return result;
|
|
571
|
-
}
|
|
596
|
+
({ engine, quill: q, doc: d }) => engine.render(q, d, options ?? undefined, today)
|
|
572
597
|
);
|
|
573
598
|
}
|
|
574
599
|
|
|
@@ -756,7 +781,7 @@ export class DocumentWriter {
|
|
|
756
781
|
}
|
|
757
782
|
/**
|
|
758
783
|
* @param {string} markdown
|
|
759
|
-
* @returns {import('../core/wasm.js').
|
|
784
|
+
* @returns {import('../core/wasm.js').Revised}
|
|
760
785
|
*/
|
|
761
786
|
reviseBody(markdown) {
|
|
762
787
|
return this.#doc.revise({}, markdown);
|
|
@@ -764,17 +789,24 @@ export class DocumentWriter {
|
|
|
764
789
|
/**
|
|
765
790
|
* @param {string} name
|
|
766
791
|
* @param {string} text
|
|
767
|
-
* @returns {import('../core/wasm.js').
|
|
792
|
+
* @returns {import('../core/wasm.js').Revised}
|
|
768
793
|
*/
|
|
769
794
|
reviseField(name, text) {
|
|
770
795
|
return this.#doc._reviseField(this.#quill, name, text);
|
|
771
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* @param {string} markdown
|
|
799
|
+
* @returns {import('../core/wasm.js').DocumentRevised}
|
|
800
|
+
*/
|
|
801
|
+
reviseDocument(markdown) {
|
|
802
|
+
return this.#doc._reviseDocument(this.#quill, markdown);
|
|
803
|
+
}
|
|
772
804
|
/**
|
|
773
805
|
* @param {string} kind
|
|
774
806
|
* @param {Record<string, unknown>} [fields]
|
|
775
807
|
* @param {string} [body]
|
|
776
808
|
* @param {number} [at] insertion index; appends when omitted
|
|
777
|
-
* @returns {
|
|
809
|
+
* @returns {import('../core/wasm.js').Diagnostic[]}
|
|
778
810
|
*/
|
|
779
811
|
addCard(kind, fields, body, at) {
|
|
780
812
|
return this.#doc._addCard(this.#quill, kind, fields, body, at);
|
|
@@ -837,7 +869,7 @@ export class CardWriter {
|
|
|
837
869
|
}
|
|
838
870
|
/**
|
|
839
871
|
* @param {string} markdown
|
|
840
|
-
* @returns {import('../core/wasm.js').
|
|
872
|
+
* @returns {import('../core/wasm.js').Revised}
|
|
841
873
|
*/
|
|
842
874
|
reviseBody(markdown) {
|
|
843
875
|
return this.#doc.revise({ card: this.#index }, markdown);
|
|
@@ -845,7 +877,7 @@ export class CardWriter {
|
|
|
845
877
|
/**
|
|
846
878
|
* @param {string} name
|
|
847
879
|
* @param {string} text
|
|
848
|
-
* @returns {import('../core/wasm.js').
|
|
880
|
+
* @returns {import('../core/wasm.js').Revised}
|
|
849
881
|
*/
|
|
850
882
|
reviseField(name, text) {
|
|
851
883
|
return this.#doc._reviseField(this.#quill, { card: this.#index, field: name }, text);
|