@quillmark/svelte 0.27.0 → 0.28.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/NOTICE +4 -4
- package/README.md +26 -8
- package/THEMING.md +10 -8
- package/dist/core/address.d.ts +35 -64
- package/dist/core/address.js +35 -55
- package/dist/core/bloom.d.ts +4 -10
- package/dist/core/bloom.js +14 -27
- package/dist/core/codec/blocks.d.ts +41 -43
- package/dist/core/codec/blocks.js +97 -130
- package/dist/core/codec/code.d.ts +7 -10
- package/dist/core/codec/code.js +37 -46
- package/dist/core/codec/decode.d.ts +19 -23
- package/dist/core/codec/decode.js +76 -111
- package/dist/core/codec/encode.d.ts +11 -15
- package/dist/core/codec/encode.js +60 -67
- package/dist/core/codec/field.d.ts +62 -95
- package/dist/core/codec/field.js +107 -179
- package/dist/core/codec/islands.d.ts +33 -41
- package/dist/core/codec/islands.js +76 -86
- package/dist/core/codec/lists.d.ts +17 -26
- package/dist/core/codec/lists.js +117 -157
- package/dist/core/codec/marks.d.ts +4 -3
- package/dist/core/codec/marks.js +8 -3
- package/dist/core/codec/prose.css +84 -46
- package/dist/core/codec/schema.d.ts +18 -23
- package/dist/core/codec/schema.js +84 -76
- package/dist/core/codec/slash.d.ts +42 -48
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-copy.d.ts +4 -3
- package/dist/core/codec/table-copy.js +25 -7
- package/dist/core/codec/table-view.d.ts +12 -12
- package/dist/core/codec/table-view.js +460 -383
- package/dist/core/codec/table.d.ts +94 -61
- package/dist/core/codec/table.js +331 -83
- package/dist/core/codec/tasks.d.ts +6 -0
- package/dist/core/codec/tasks.js +30 -3
- package/dist/core/errors.d.ts +15 -30
- package/dist/core/errors.js +2 -6
- package/dist/core/index.js +7 -12
- package/dist/core/lifecycle.d.ts +7 -16
- package/dist/core/lifecycle.js +10 -21
- package/dist/core/rebind.svelte.d.ts +10 -20
- package/dist/core/rebind.svelte.js +15 -27
- package/dist/core/rungs.d.ts +14 -11
- package/dist/core/rungs.js +17 -19
- package/dist/core/teardown.d.ts +4 -6
- package/dist/core/teardown.js +7 -10
- package/dist/core/theme.css +74 -54
- package/dist/index.js +3 -8
- package/dist/preset/app.css +3 -1
- package/dist/preset/index.css +6 -8
- package/dist/preset/recipes.css +12 -15
- package/dist/preset/scale.css +18 -17
- package/dist/preset/shell.css +10 -0
- package/dist/preview/bridge.d.ts +18 -22
- package/dist/preview/bridge.js +29 -58
- package/dist/preview/controller.d.ts +21 -29
- package/dist/preview/controller.js +14 -39
- package/dist/preview/geometry.d.ts +13 -34
- package/dist/preview/geometry.js +13 -34
- package/dist/preview/index.js +4 -16
- package/dist/preview/paint.d.ts +3 -3
- package/dist/preview/paint.js +28 -68
- package/dist/preview/strings.d.ts +1 -1
- package/dist/preview/strings.js +2 -14
- package/dist/preview/zoom.d.ts +18 -23
- package/dist/preview/zoom.js +28 -27
- package/dist/visual/ArrayField.svelte +77 -16
- package/dist/visual/BooleanField.svelte +27 -14
- package/dist/visual/Card.svelte +61 -48
- package/dist/visual/CardControls.svelte +5 -11
- package/dist/visual/DateField.svelte +20 -4
- package/dist/visual/EnumField.svelte +3 -0
- package/dist/visual/FieldHint.svelte +2 -1
- package/dist/visual/FormatPopover.svelte +82 -15
- package/dist/visual/FormatPopover.svelte.d.ts +4 -0
- package/dist/visual/MatrixAdd.svelte +30 -12
- package/dist/visual/MatrixField.svelte +24 -16
- package/dist/visual/NumberField.svelte +7 -0
- package/dist/visual/ObjectField.svelte +4 -4
- package/dist/visual/ProseField.svelte +0 -5
- package/dist/visual/TipsCard.svelte +11 -10
- package/dist/visual/VariantField.svelte +3 -1
- package/dist/visual/VisualEditorInner.svelte +19 -3
- package/dist/visual/controls.css +7 -2
- package/dist/visual/fonts.d.ts +18 -0
- package/dist/visual/fonts.js +59 -0
- package/dist/visual/icons/nodes.d.ts +0 -5
- package/dist/visual/icons/nodes.js +0 -4
- package/dist/visual/props.d.ts +14 -1
- package/dist/visual/strings.d.ts +7 -0
- package/dist/visual/strings.js +5 -2
- package/dist/visual/structure.d.ts +43 -87
- package/dist/visual/structure.js +42 -83
- package/package.json +2 -2
|
@@ -9,9 +9,8 @@ function appendText(acc, s) {
|
|
|
9
9
|
acc.usvEnd += usvLength(s);
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Walk a PM document once, producing the content projection and the position-map
|
|
13
|
-
*
|
|
14
|
-
* source both `pmToContent` and the position map draw from.
|
|
12
|
+
* Walk a PM document once, producing the content projection and the position-map runs; sharing the
|
|
13
|
+
* traversal means they cannot disagree.
|
|
15
14
|
*/
|
|
16
15
|
export function scanDoc(doc) {
|
|
17
16
|
const acc = {
|
|
@@ -28,8 +27,10 @@ export function scanDoc(doc) {
|
|
|
28
27
|
acc.marks = mergeMarks(acc.rawMarks);
|
|
29
28
|
return acc;
|
|
30
29
|
}
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
30
|
+
/**
|
|
31
|
+
* The content projection a scan carries, for a caller holding a `Scan` that would otherwise walk
|
|
32
|
+
* again.
|
|
33
|
+
*/
|
|
33
34
|
export function scanContent(s) {
|
|
34
35
|
const { text, lines, marks, islands } = s;
|
|
35
36
|
return { text, lines, marks, islands };
|
|
@@ -38,11 +39,12 @@ export function scanContent(s) {
|
|
|
38
39
|
export function pmToContent(doc) {
|
|
39
40
|
return scanContent(scanDoc(doc));
|
|
40
41
|
}
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* `instance` against the sibling before it
|
|
45
|
-
*
|
|
42
|
+
/**
|
|
43
|
+
* Walk a block-content fragment; `contentStart` is the PM pos before its first child. Two container
|
|
44
|
+
* siblings of one run shape read as a single container (contiguity plus an equal path is the
|
|
45
|
+
* store's "same one"), so each alternates its `instance` against the sibling before it; a container
|
|
46
|
+
* one level in already differs in path above it.
|
|
47
|
+
*/
|
|
46
48
|
function scanBlocks(acc, parent, contentStart, containers) {
|
|
47
49
|
let pm = contentStart;
|
|
48
50
|
let prevShape = null;
|
|
@@ -55,9 +57,10 @@ function scanBlocks(acc, parent, contentStart, containers) {
|
|
|
55
57
|
pm += child.nodeSize;
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
* there.
|
|
60
|
+
/**
|
|
61
|
+
* A block's container run shape, `ordinal` and `instance` aside; null where it opens no container.
|
|
62
|
+
* A list's `start` is not in it: the store welds two runs differing only there.
|
|
63
|
+
*/
|
|
61
64
|
function runShape(node) {
|
|
62
65
|
switch (node.type.name) {
|
|
63
66
|
case 'blockquote':
|
|
@@ -145,9 +148,10 @@ function textblockKind(node) {
|
|
|
145
148
|
return { kind: 'heading', attrs: { level: node.attrs.level } };
|
|
146
149
|
return { kind: 'para' };
|
|
147
150
|
}
|
|
148
|
-
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
+
/**
|
|
152
|
+
* A container with its run `instance`, spelled only where it is not the zero a canonical read
|
|
153
|
+
* omits, so the projection and `lineMetaEqual` spell one container one way.
|
|
154
|
+
*/
|
|
151
155
|
function withInstance(container, instance) {
|
|
152
156
|
return instance === 0 ? container : { ...container, instance };
|
|
153
157
|
}
|
|
@@ -171,11 +175,9 @@ function scanInline(acc, block, contentStart, containers, kind) {
|
|
|
171
175
|
if (child.isText) {
|
|
172
176
|
const text = child.text ?? '';
|
|
173
177
|
emitText(acc, text, pm, child.marks);
|
|
174
|
-
// A `\n` in a textblock that is not `whitespace: 'pre'` is the same line
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
// `clearIncompatible` nor `replaceNewlines` — leaves one. It rides the text
|
|
178
|
-
// run, where PM and USV advance together.
|
|
178
|
+
// A `\n` in a textblock that is not `whitespace: 'pre'` is the same line boundary a
|
|
179
|
+
// hard break is: `joinTextblocksAround` (a bare `replaceStep`) leaves one. It rides the
|
|
180
|
+
// text run, where PM and USV advance together.
|
|
179
181
|
const breaks = text.split('\n').length - 1;
|
|
180
182
|
for (let i = 0; i < breaks; i++)
|
|
181
183
|
acc.lines.push({ containers, continues: true, ...kind });
|
|
@@ -206,10 +208,8 @@ function emitText(acc, s, pmStart, marks) {
|
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
/**
|
|
209
|
-
* Merge adjacent/overlapping same-descriptor marks into maximal ranges
|
|
210
|
-
*
|
|
211
|
-
* Same two primitives the mark diff runs on (`groupFormatting` + `union`), so the
|
|
212
|
-
* projection and the diff group and merge by one rule.
|
|
211
|
+
* Merge adjacent/overlapping same-descriptor marks into maximal ranges, by the same primitives the
|
|
212
|
+
* mark diff runs on (`groupFormatting` + `union`).
|
|
213
213
|
*/
|
|
214
214
|
function mergeMarks(raw) {
|
|
215
215
|
const out = [];
|
|
@@ -271,12 +271,10 @@ function diffText(oldText, newText) {
|
|
|
271
271
|
return { ops };
|
|
272
272
|
}
|
|
273
273
|
/**
|
|
274
|
-
* Whether the splice moves a line boundary
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
* says nothing about it: one splice that both joins a boundary and opens another
|
|
279
|
-
* leaves the line count and the metadata array unchanged while the kinds slide.
|
|
274
|
+
* Whether the splice moves a line boundary (a `\n` deleted or inserted). Where it does not, equal
|
|
275
|
+
* metadata on both sides is the whole story. Where it does, the store's split/join inheritance
|
|
276
|
+
* decides what each line carries: one splice that joins a boundary and opens another leaves the
|
|
277
|
+
* line count and metadata array unchanged while the kinds slide.
|
|
280
278
|
*/
|
|
281
279
|
function movesBoundary(oldText, delta) {
|
|
282
280
|
if (!delta)
|
|
@@ -305,11 +303,8 @@ function diffLines(oldRt, newRt, delta) {
|
|
|
305
303
|
if (!movesBoundary(oldRt.text, delta) && lineMetaEqual(oldRt.lines, newRt.lines))
|
|
306
304
|
return [];
|
|
307
305
|
const ops = [];
|
|
308
|
-
// Force every new line's metadata
|
|
309
|
-
// so
|
|
310
|
-
// the intermediate metadata. `continues` is a boundary property of the `\n`
|
|
311
|
-
// preceding a line: line 0 has no predecessor, never carries it, and the op
|
|
312
|
-
// rejects it there, so it's set only for lines ≥ 1.
|
|
306
|
+
// Force every new line's metadata; redundant ops are safe no-ops. `continues` is a property of
|
|
307
|
+
// the `\n` preceding a line, so line 0 never carries it and it is set only for lines ≥ 1.
|
|
313
308
|
for (let i = 0; i < newRt.lines.length; i++) {
|
|
314
309
|
const l = newRt.lines[i];
|
|
315
310
|
ops.push({ op: 'setContainers', line: i, containers: l.containers });
|
|
@@ -319,9 +314,10 @@ function diffLines(oldRt, newRt, delta) {
|
|
|
319
314
|
}
|
|
320
315
|
return ops;
|
|
321
316
|
}
|
|
322
|
-
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
317
|
+
/**
|
|
318
|
+
* A line minus its `containers` / `continues` envelope: exactly `setKind`'s payload
|
|
319
|
+
* (`ContentLineKind`). Lifted whole, so an arm added upstream reaches the op by construction.
|
|
320
|
+
*/
|
|
325
321
|
function kindPart(l) {
|
|
326
322
|
const { containers: _containers, continues: _continues, ...kind } = l;
|
|
327
323
|
return kind;
|
|
@@ -342,28 +338,23 @@ function lineMetaEqual(a, b) {
|
|
|
342
338
|
}
|
|
343
339
|
return true;
|
|
344
340
|
}
|
|
345
|
-
/**
|
|
346
|
-
*
|
|
347
|
-
* nested `attrs` bag.
|
|
341
|
+
/**
|
|
342
|
+
* A line kind's comparison key, key-order-insensitive at every depth: the sides come from different
|
|
343
|
+
* producers (a WASM read and this scan) and a kind carries a nested `attrs` bag.
|
|
344
|
+
*/
|
|
348
345
|
function kindKey(l) {
|
|
349
346
|
return canonicalJson(kindPart(l));
|
|
350
347
|
}
|
|
351
348
|
/**
|
|
352
|
-
* Split the edit's islands off the text splice. `applyChange` throws
|
|
353
|
-
* `
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
* op
|
|
357
|
-
* addressed by the id both sides carry. A deleted island needs no op at all: the
|
|
358
|
-
* delta that removes its slot drops the entry.
|
|
359
|
-
*
|
|
360
|
-
* `at` is the slot's position in the final text: inserts apply left to right, so
|
|
361
|
-
* by the time the k-th lands, the k slots before it are back in place.
|
|
349
|
+
* Split the edit's islands off the text splice. `applyChange` throws `IslandSlotInInsert` on a
|
|
350
|
+
* `delta` that types a slot, so every slot inside the splice's inserted region is stripped from it
|
|
351
|
+
* and placed by `{ op: 'insert', at }`, which carries the backing entry. Every other island kept
|
|
352
|
+
* its slot, so a changed payload is `{ op: 'set' }` by the id both sides carry. A deleted island
|
|
353
|
+
* needs no op: the delta that removes its slot drops the entry.
|
|
362
354
|
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
* it is unreachable.
|
|
355
|
+
* `at` is the slot's position in the final text: inserts apply left to right, so by the k-th, the k
|
|
356
|
+
* slots before it are in place. An id the store does not carry emits nothing (it would throw
|
|
357
|
+
* `UnknownIslandId`); nothing mints or renames an island id, so that is unreachable.
|
|
367
358
|
*/
|
|
368
359
|
function splitIslands(edit) {
|
|
369
360
|
const { oldRt, newRt, delta } = edit;
|
|
@@ -386,8 +377,7 @@ function splitIslands(edit) {
|
|
|
386
377
|
});
|
|
387
378
|
return { delta: inserts && delta ? withoutSlots(delta) : delta, islandOps };
|
|
388
379
|
}
|
|
389
|
-
/** The USV positions of `text`'s island slots, in document order: the i-th is the
|
|
390
|
-
* i-th island's, since the scan appends an entry per slot it writes. */
|
|
380
|
+
/** The USV positions of `text`'s island slots, in document order: the i-th is the i-th island's. */
|
|
391
381
|
function slotPositions(text) {
|
|
392
382
|
const out = [];
|
|
393
383
|
let usv = 0;
|
|
@@ -398,9 +388,10 @@ function slotPositions(text) {
|
|
|
398
388
|
}
|
|
399
389
|
return out;
|
|
400
390
|
}
|
|
401
|
-
/**
|
|
402
|
-
*
|
|
403
|
-
*
|
|
391
|
+
/**
|
|
392
|
+
* The splice's inserted region `[start, end)` in final coords: `diffText` emits one
|
|
393
|
+
* `[retain?][delete?][insert?][retain?]`, so the leading retain is where the insert lands.
|
|
394
|
+
*/
|
|
404
395
|
function insertedRegion(delta) {
|
|
405
396
|
if (!delta)
|
|
406
397
|
return { start: 0, end: 0 };
|
|
@@ -409,9 +400,10 @@ function insertedRegion(delta) {
|
|
|
409
400
|
const insert = delta.ops.find((op) => 'insert' in op);
|
|
410
401
|
return { start, end: start + (insert ? usvLength(insert.insert) : 0) };
|
|
411
402
|
}
|
|
412
|
-
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
403
|
+
/**
|
|
404
|
+
* The delta with every island slot removed from its insert, or `undefined` when only retains
|
|
405
|
+
* remain.
|
|
406
|
+
*/
|
|
415
407
|
function withoutSlots(delta) {
|
|
416
408
|
const ops = [];
|
|
417
409
|
let splices = false;
|
|
@@ -431,9 +423,10 @@ function withoutSlots(delta) {
|
|
|
431
423
|
}
|
|
432
424
|
return splices ? { ops } : undefined;
|
|
433
425
|
}
|
|
434
|
-
/**
|
|
435
|
-
*
|
|
436
|
-
* the wire's `attrs` spelling is the one a checker admits.
|
|
426
|
+
/**
|
|
427
|
+
* Formatting marks → add/remove ops; anchors → add/removeAnchor by id. A descriptor spreads in
|
|
428
|
+
* whole, so the wire's `attrs` spelling is the one a checker admits.
|
|
429
|
+
*/
|
|
437
430
|
function diffMarks(oldRt, newRt, moved, opts) {
|
|
438
431
|
const ops = [];
|
|
439
432
|
// The store's answer for where `moved`'s text channels leave the field's marks;
|
|
@@ -9,9 +9,10 @@ import { type SlashState, type SlashStrings } from './slash.js';
|
|
|
9
9
|
/** Options for {@link createField}. */
|
|
10
10
|
export interface CreateFieldOpts {
|
|
11
11
|
doc: Document;
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
/**
|
|
13
|
+
* The schema the leaf reads through: the declared type decides whether a stored string is
|
|
14
|
+
* markdown or literal text.
|
|
15
|
+
*/
|
|
15
16
|
quill: Quill;
|
|
16
17
|
addr: Addr;
|
|
17
18
|
container: HTMLElement;
|
|
@@ -24,53 +25,44 @@ export interface CreateFieldOpts {
|
|
|
24
25
|
* `aria-describedby` while it holds. */
|
|
25
26
|
heldNoteId?: string;
|
|
26
27
|
/**
|
|
27
|
-
* Fired when the leaf holds or releases, and at mount when it mounts held. A one-line
|
|
28
|
-
* leaf
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* its content on the block schema, read-only, and commits nothing. Judged of the value
|
|
34
|
-
* each mount and re-hydrate reads, so {@link FieldController.applyExternal} is what
|
|
35
|
-
* re-evaluates it.
|
|
28
|
+
* Fired when the leaf holds or releases, and at mount when it mounts held. A one-line or `text`
|
|
29
|
+
* leaf is held over a value its schema cannot hold (`fitsLeaf`): the decode would join lines
|
|
30
|
+
* and drop containers and islands. Any leaf is held over what is read and not edited: a font
|
|
31
|
+
* family, a footnote, an equation (CODEC §Decode). A held leaf draws on the block schema,
|
|
32
|
+
* read-only, and commits nothing. Judged on each mount and re-hydrate ({@link
|
|
33
|
+
* FieldController.applyExternal}).
|
|
36
34
|
*/
|
|
37
35
|
onHold?(held: boolean): void;
|
|
38
36
|
/** Suppress the markdown-shorthand input rules. */
|
|
39
37
|
noInputRules?: boolean;
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
38
|
+
/**
|
|
39
|
+
* The island chrome's wording, read live so a locale swap re-renders. Absent leaves the
|
|
40
|
+
* package's English.
|
|
41
|
+
*/
|
|
43
42
|
tableStrings?: () => TableChromeStrings;
|
|
44
43
|
/**
|
|
45
|
-
* The slash menu's live state, or `undefined` when it is closed: the channel the
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* leaf's, but a surface only a keyboard can reach (claiming Enter, Escape and the
|
|
50
|
-
* arrows with nothing on screen) is worse than no surface, so the door exists
|
|
51
|
-
* exactly where something can draw it. A constrained inline leaf never has one:
|
|
52
|
-
* it holds no island and no block to convert.
|
|
44
|
+
* The slash menu's live state, or `undefined` when it is closed: the channel the chrome draws
|
|
45
|
+
* from (`visual/SlashMenu.svelte`). Its presence is what mounts the menu, so the keys never
|
|
46
|
+
* claim Enter, Escape and the arrows with nothing on screen. A constrained inline leaf never
|
|
47
|
+
* has one.
|
|
53
48
|
*/
|
|
54
49
|
onSlash?(state: SlashState | undefined): void;
|
|
55
|
-
/** The slash surface's wording, read per decoration pass
|
|
56
|
-
* package's English; read only beside {@link onSlash}, the hint being the menu's. */
|
|
50
|
+
/** The slash surface's wording, read per decoration pass; read only beside {@link onSlash}. */
|
|
57
51
|
slashStrings?: () => SlashStrings;
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Accessible name → `aria-label` on the `contenteditable`, for a leaf nothing else names (an
|
|
54
|
+
* array element, the card body). A leaf with a field label takes `labelledBy` instead: `for`
|
|
55
|
+
* cannot reach a `contenteditable`.
|
|
56
|
+
*/
|
|
63
57
|
label?: string;
|
|
64
58
|
/** The field label's own id → `aria-labelledby`, which supersedes `label`. */
|
|
65
59
|
labelledBy?: string;
|
|
66
60
|
/** The parked `description` → `aria-describedby`; announced after the name. */
|
|
67
61
|
describedBy?: string;
|
|
68
62
|
/**
|
|
69
|
-
* The resolved `default:` where it prints: the content an unset field's leaf holds,
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* the edit in it. The initial value; {@link FieldController.setFallback} moves it
|
|
73
|
-
* after mount.
|
|
63
|
+
* The resolved `default:` where it prints: the content an unset field's leaf holds, marked
|
|
64
|
+
* `data-default`. Nothing is written until an edit, which commits the whole leaf with the edit
|
|
65
|
+
* in it. Initial value; {@link FieldController.setFallback} moves it.
|
|
74
66
|
*/
|
|
75
67
|
fallback?: Content;
|
|
76
68
|
/** Ghost text shown on the empty leaf: the `none` an unset optional field prints, or
|
|
@@ -91,15 +83,10 @@ export interface CreateFieldOpts {
|
|
|
91
83
|
/** Fired with the new USV caret after an edit or a selection move. */
|
|
92
84
|
onCaretMove?(addr: Addr, pos: number): void;
|
|
93
85
|
/**
|
|
94
|
-
* Fired after an edit committed to the document: the leaf's change signal
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* Fires for every commit regardless of which branch it took (`applyChange`, the
|
|
99
|
-
* first-edit `overwrite`, the fallback `overwrite`, a `text` leaf's typed write)
|
|
100
|
-
* and for an anchor mutation,
|
|
101
|
-
* which changes no text. A commit that failed outright (`commit-lost`) does not
|
|
102
|
-
* fire it: nothing landed.
|
|
86
|
+
* Fired after an edit committed to the document: the leaf's change signal. Unlike `onCaretMove`
|
|
87
|
+
* it does not fire on a bare selection move. Fires for every commit branch and for an anchor
|
|
88
|
+
* mutation (which changes no text); a commit that failed outright (`commit-lost`) does not fire
|
|
89
|
+
* it.
|
|
103
90
|
*/
|
|
104
91
|
onChange?(addr: Addr): void;
|
|
105
92
|
/** Recovered failures on the commit path ({@link EditorErrorHandler}). */
|
|
@@ -116,12 +103,9 @@ export interface FieldController {
|
|
|
116
103
|
* re-evaluate its hold against the value now stored. */
|
|
117
104
|
applyExternal(): void;
|
|
118
105
|
/**
|
|
119
|
-
* Move the empty-leaf ghost after mount
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* Refreshes the decoration without a transaction: a placeholder is chrome, and
|
|
124
|
-
* a transaction would fire `onCaretMove` at a moment the caret did not move.
|
|
106
|
+
* Move the empty-leaf ghost after mount (a card retyped to another kind takes its new wording;
|
|
107
|
+
* a remount would cost the caret). Refreshes the decoration without a transaction, which would
|
|
108
|
+
* fire `onCaretMove` with no caret move.
|
|
125
109
|
*/
|
|
126
110
|
setPlaceholder(text: string | undefined): void;
|
|
127
111
|
/** Move the default an unset leaf holds after mount: a retype or a quill swap
|
|
@@ -131,11 +115,9 @@ export interface FieldController {
|
|
|
131
115
|
/** The current stored content for this addr (for tests / reconcile). */
|
|
132
116
|
getContent(): Content;
|
|
133
117
|
/**
|
|
134
|
-
* Insert an identity anchor `id` at USV `pos
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* survives later edits like any anchor. The id is caller-supplied and must be
|
|
138
|
-
* unique + invariant (the 0.97 anchor-id policy); a duplicate id is a no-op.
|
|
118
|
+
* Insert an identity anchor `id` at USV `pos`. Zero-width; it folds into the plugin's position
|
|
119
|
+
* set and commits through the mark-diff `anchor` op. The id is caller-supplied and must be
|
|
120
|
+
* unique and invariant; a duplicate id is a no-op.
|
|
139
121
|
*/
|
|
140
122
|
insertAnchor(id: string, pos: number): void;
|
|
141
123
|
/** Remove the identity anchor `id` (the inverse of {@link insertAnchor}); a no-op if absent. */
|
|
@@ -143,9 +125,8 @@ export interface FieldController {
|
|
|
143
125
|
/** Ids of the anchors within USV range `[from, to]`: a selection's anchor state. */
|
|
144
126
|
anchorsInRange(from: number, to: number): string[];
|
|
145
127
|
/**
|
|
146
|
-
* Move the slash menu's cursor onto the command `name
|
|
147
|
-
*
|
|
148
|
-
* chrome moves the one the keys already drive rather than painting a second.
|
|
128
|
+
* Move the slash menu's cursor onto the command `name` (a pointer entering an item): the
|
|
129
|
+
* keyboard cursor and the pointer highlight are one state.
|
|
149
130
|
*/
|
|
150
131
|
slashFocus(name: string): void;
|
|
151
132
|
/** Run the command `name` (a click on its item): the same path Enter takes. A no-op
|
|
@@ -159,13 +140,11 @@ export interface FieldController {
|
|
|
159
140
|
destroy(): void;
|
|
160
141
|
}
|
|
161
142
|
/**
|
|
162
|
-
* The ProseMirror handles a chrome surface reaches a mounted leaf through
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* `view`
|
|
166
|
-
*
|
|
167
|
-
* The two being different is exactly what tells the popover to withhold its
|
|
168
|
-
* `anchor` button: an anchor is the field's coordinate space, and a cell is not in it.
|
|
143
|
+
* The ProseMirror handles a chrome surface reaches a mounted leaf through; not part of {@link
|
|
144
|
+
* FieldController}. The format popover needs both: `view` names the leaf's own document,
|
|
145
|
+
* `focusedView` acts wherever the caret is, which inside a table island is a nested cell view
|
|
146
|
+
* (`table-view.ts`). Their differing is what tells the popover to withhold its `anchor` button: a
|
|
147
|
+
* cell is not in the field's coordinate space.
|
|
169
148
|
*/
|
|
170
149
|
export interface LeafViews {
|
|
171
150
|
view: EditorView;
|
|
@@ -173,17 +152,15 @@ export interface LeafViews {
|
|
|
173
152
|
/** Every view nested inside this leaf, in mount order: one per table cell. */
|
|
174
153
|
nestedViews(): EditorView[];
|
|
175
154
|
}
|
|
176
|
-
/** The canonical empty `Content`: one empty `para` line.
|
|
177
|
-
* leaf (or an array's prose element) seeds from. */
|
|
155
|
+
/** The canonical empty `Content`: one empty `para` line. */
|
|
178
156
|
export declare function emptyContent(): Content;
|
|
179
157
|
/** Whether `rt` is the empty leaf: {@link emptyContent}, nothing typed and no shape left. */
|
|
180
158
|
export declare function isEmptyContent(rt: Content): boolean;
|
|
181
|
-
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
|
|
186
|
-
* the absence, not an empty object. */
|
|
159
|
+
/**
|
|
160
|
+
* The naming attributes for the `contenteditable`, shared with `ProseValue`. `aria-labelledby`
|
|
161
|
+
* supersedes `aria-label`, and `undefined` is returned whole when a leaf takes neither, since
|
|
162
|
+
* ProseMirror reads the absence.
|
|
163
|
+
*/
|
|
187
164
|
export declare function proseAttributes(opts: {
|
|
188
165
|
label?: string;
|
|
189
166
|
labelledBy?: string;
|
|
@@ -198,36 +175,26 @@ export declare function heldAttributes(opts: {
|
|
|
198
175
|
}, noteId: string | undefined): Record<string, string>;
|
|
199
176
|
export declare function createField(opts: CreateFieldOpts): FieldController;
|
|
200
177
|
/**
|
|
201
|
-
* The prose-leaf plugin stack (VISUAL_EDITOR §Surface)
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* that links a selection (`link-paste.ts`), and last the ones that answer to a block
|
|
210
|
-
* leaf's own shapes: the gap cursor, {@link pastAtomPlugin}, the island paste pass
|
|
211
|
-
* (`islands.ts`), the table paste (`table-paste.ts`), the markdown paste
|
|
212
|
-
* (`markdown-paste.ts`) and the task item's checkbox (`tasks.ts`). A one-line leaf's
|
|
213
|
-
* paste joins its lines (`line-paste.ts`).
|
|
178
|
+
* The prose-leaf plugin stack (VISUAL_EDITOR §Surface), shared by {@link createField} and
|
|
179
|
+
* `ProseValue` so the two never fork the plugin ordering. History first with the step-splitting
|
|
180
|
+
* plugin (`undo.ts`), then `afterHistory` plugins (the addressed leaf's anchor plugin), {@link
|
|
181
|
+
* linebreakPlugin}, the markdown-shorthand input rules and their Backspace, the field keymap over
|
|
182
|
+
* the base keymap, the URL paste that links a selection (`link-paste.ts`), and last the block
|
|
183
|
+
* leaf's own shapes: the gap cursor, {@link pastAtomPlugin}, the island paste (`islands.ts`), table
|
|
184
|
+
* paste (`table-paste.ts`), markdown paste (`markdown-paste.ts`) and the task checkbox
|
|
185
|
+
* (`tasks.ts`). A one-line leaf's paste joins its lines (`line-paste.ts`).
|
|
214
186
|
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* toggles bind no key and a pasted URL stays text, so a `**bold**` keeps the delimiters
|
|
218
|
-
* its author typed without a second rule saying so.
|
|
187
|
+
* Mark-shaped plugins read the schema rather than a flag: over a mark-free schema the shorthand
|
|
188
|
+
* rules build nothing, the toggles bind no key and a pasted URL stays text.
|
|
219
189
|
*/
|
|
220
190
|
export declare function proseLeafPlugins(schema: Schema, opts: {
|
|
221
191
|
inline: boolean;
|
|
222
|
-
/** The slash menu's report channel; absent mounts no menu
|
|
223
|
-
* Enter/Escape/the arrows to the links below (`keymap.ts`). */
|
|
192
|
+
/** The slash menu's report channel; absent mounts no menu (`keymap.ts`). */
|
|
224
193
|
slash?: (state: SlashState | undefined) => void;
|
|
225
194
|
/** The empty line's hint, read live; drawn only beside `slash`. */
|
|
226
195
|
slashHint?: () => string | undefined;
|
|
227
196
|
noInputRules?: boolean;
|
|
228
|
-
/** Read live
|
|
229
|
-
* ({@link FieldController.setPlaceholder}), and a re-hydration rebuilds this
|
|
230
|
-
* stack, so the plugin must ask rather than hold. */
|
|
197
|
+
/** Read live: the ghost can move after mount and a re-hydration rebuilds this stack. */
|
|
231
198
|
placeholder?: () => string | undefined;
|
|
232
199
|
/** {@link CreateFieldOpts.placeholderUntilEdit}. */
|
|
233
200
|
placeholderUntilEdit?: boolean;
|