edytor 4.0.0 → 6.0.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/README.md +2 -2
- package/dist/block/block.svelte.js +6 -21
- package/dist/block/inlineBlock.svelte.js +4 -6
- package/dist/clipboard/moveText.js +6 -8
- package/dist/cloudflare/DocumentRoom.d.ts +10 -3
- package/dist/cloudflare/index.d.ts +1 -1
- package/dist/cloudflare/room/access.d.ts +8 -3
- package/dist/cloudflare/room/access.js +44 -20
- package/dist/cloudflare/room/admission.js +28 -5
- package/dist/cloudflare/room/comments.js +28 -1
- package/dist/cloudflare/room/context.d.ts +106 -109
- package/dist/cloudflare/room/context.js +10 -3
- package/dist/cloudflare/room/forged.d.ts +14 -0
- package/dist/cloudflare/room/forged.js +30 -2
- package/dist/cloudflare/room/frames.d.ts +4 -0
- package/dist/cloudflare/room/frames.js +5 -1
- package/dist/cloudflare/room/purge.js +2 -1
- package/dist/cloudflare/room/replicas.d.ts +4 -2
- package/dist/cloudflare/room/replicas.js +8 -3
- package/dist/cloudflare/room/suggest.d.ts +7 -0
- package/dist/cloudflare/room/suggest.js +143 -0
- package/dist/cloudflare/routeDocumentSocket.d.ts +10 -1
- package/dist/cloudflare/routeDocumentSocket.js +5 -3
- package/dist/components/Content.svelte +9 -1
- package/dist/crdt/anchors.js +3 -2
- package/dist/crdt/attribution/attribution.d.ts +3 -0
- package/dist/crdt/attribution/attribution.js +3 -3
- package/dist/crdt/doc/funnel.d.ts +1 -1
- package/dist/crdt/doc/funnel.js +5 -2
- package/dist/crdt/doc/gate.d.ts +1 -1
- package/dist/crdt/doc/history.d.ts +6 -0
- package/dist/crdt/doc/history.js +79 -59
- package/dist/crdt/doc/ops.d.ts +81 -0
- package/dist/crdt/doc/ops.js +1898 -0
- package/dist/crdt/doc/reads.d.ts +2 -2
- package/dist/crdt/doc/reads.js +18 -28
- package/dist/crdt/doc/suggest.d.ts +167 -0
- package/dist/crdt/doc/suggest.js +579 -0
- package/dist/crdt/document.d.ts +10 -1
- package/dist/crdt/document.js +19 -11
- package/dist/crdt/edytor-doc.d.ts +294 -272
- package/dist/crdt/edytor-doc.js +123 -108
- package/dist/crdt/engine-api.d.ts +8 -2
- package/dist/crdt/engine.d.ts +2 -1
- package/dist/crdt/engine.js +3 -1
- package/dist/crdt/flow.d.ts +5 -47
- package/dist/crdt/flow.js +3 -269
- package/dist/crdt/index.d.ts +102 -108
- package/dist/crdt/index.js +3 -0
- package/dist/crdt/operations.d.ts +13 -4
- package/dist/crdt/parts.d.ts +43 -0
- package/dist/crdt/parts.js +44 -0
- package/dist/crdt/placement/display.d.ts +1 -1
- package/dist/crdt/placement/display.js +3 -3
- package/dist/crdt/placement/keys.d.ts +5 -0
- package/dist/crdt/placement/keys.js +5 -0
- package/dist/crdt/placement/resolve.d.ts +1 -1
- package/dist/crdt/placement/resolve.js +2 -1
- package/dist/crdt/protocol.d.ts +1 -1
- package/dist/crdt/protocol.js +1 -1
- package/dist/crdt/protocols/auth.d.ts +11 -1
- package/dist/crdt/protocols/auth.js +17 -1
- package/dist/crdt/protocols/awareness.js +46 -81
- package/dist/crdt/protocols/comments.d.ts +16 -1
- package/dist/crdt/protocols/comments.js +9 -1
- package/dist/crdt/providers/index.d.ts +12 -22
- package/dist/crdt/providers/index.js +3 -1
- package/dist/crdt/providers/indexeddb.d.ts +6 -10
- package/dist/crdt/providers/indexeddb.js +10 -16
- package/dist/crdt/providers/room.d.ts +11 -0
- package/dist/crdt/providers/room.js +26 -12
- package/dist/crdt/providers/websocket.d.ts +8 -12
- package/dist/crdt/providers/websocket.js +17 -19
- package/dist/crdt/purge.d.ts +7 -1
- package/dist/crdt/purge.js +32 -2
- package/dist/crdt/rangeDelete.d.ts +2 -47
- package/dist/crdt/rangeDelete.js +1 -169
- package/dist/crdt/restore.d.ts +2 -1
- package/dist/crdt/restore.js +9 -0
- package/dist/crdt/schema.d.ts +9 -1
- package/dist/crdt/schema.js +13 -3
- package/dist/crdt/structs.d.ts +2 -0
- package/dist/crdt/structs.js +2 -0
- package/dist/crdt/text/index/build.d.ts +125 -0
- package/dist/crdt/text/index/build.js +2895 -0
- package/dist/crdt/text/index/shared.d.ts +2 -6
- package/dist/crdt/text/index/shared.js +19 -19
- package/dist/crdt/text/model.d.ts +10 -0
- package/dist/crdt/text/model.js +10 -4
- package/dist/crdt/text/runs.d.ts +43 -42
- package/dist/crdt/text/runs.js +2 -165
- package/dist/crdt/vendor/yjs/UPSTREAM.md +83 -0
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +6 -3
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +13 -2
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/Item.js +44 -5
- package/dist/crdt/vendor/yjs/src/ynode.js +29 -7
- package/dist/edytor.svelte.d.ts +1 -1
- package/dist/edytor.svelte.js +100 -75
- package/dist/events/beforeInputCommands.d.ts +2 -2
- package/dist/events/domTextOffset.d.ts +2 -0
- package/dist/events/domTextOffset.js +8 -0
- package/dist/events/nativeInteractiveControl.d.ts +11 -1
- package/dist/events/nativeInteractiveControl.js +41 -1
- package/dist/events/onBeforeInput.js +3 -3
- package/dist/events/onFocus.js +9 -11
- package/dist/export/forms.d.ts +75 -75
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/labels.d.ts +8 -0
- package/dist/labels.js +6 -1
- package/dist/plugins/comments/CommentsController.svelte.d.ts +5 -1
- package/dist/plugins/comments/CommentsController.svelte.js +14 -4
- package/dist/plugins/find/search.js +2 -2
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +63 -61
- package/dist/plugins/richtext/richTextOperations.js +26 -32
- package/dist/plugins/suggestions/SuggestionBars.svelte +40 -23
- package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +3 -1
- package/dist/plugins/suggestions/SuggestionRuns.svelte +77 -0
- package/dist/plugins/suggestions/SuggestionRuns.svelte.d.ts +9 -0
- package/dist/plugins/suggestions/shared.svelte.d.ts +58 -0
- package/dist/plugins/suggestions/shared.svelte.js +421 -0
- package/dist/plugins/suggestions/suggestionsPlugin.d.ts +15 -4
- package/dist/selection/domSelection.d.ts +2 -0
- package/dist/selection/domSelection.js +6 -2
- package/dist/selection/pointer.svelte.js +75 -48
- package/dist/selection/replaceSelection.js +2 -6
- package/dist/selection/selection.svelte.d.ts +3 -3
- package/dist/selection/selection.svelte.js +39 -32
- package/dist/selection/selection.utils.d.ts +14 -0
- package/dist/selection/selection.utils.js +33 -11
- package/dist/session/commands.js +21 -11
- package/dist/session/composition.svelte.d.ts +5 -3
- package/dist/session/composition.svelte.js +21 -17
- package/dist/session/handles.d.ts +4 -17
- package/dist/session/handles.js +14 -44
- package/dist/session/navigation.js +6 -9
- package/dist/session/selection.d.ts +11 -5
- package/dist/session/selection.js +14 -48
- package/dist/session/suggestions.svelte.d.ts +38 -9
- package/dist/session/suggestions.svelte.js +37 -18
- package/dist/session/virtual.d.ts +1 -1
- package/dist/surface/attributes.d.ts +5 -0
- package/dist/surface/attributes.js +2 -2
- package/dist/surface/cells.d.ts +2 -26
- package/dist/surface/cells.js +2 -33
- package/dist/surface/observer.svelte.d.ts +6 -1
- package/dist/surface/observer.svelte.js +143 -111
- package/dist/surface/pin.svelte.d.ts +9 -9
- package/dist/surface/pin.svelte.js +15 -22
- package/dist/surface/projector.svelte.js +10 -16
- package/dist/text/text.svelte.js +14 -19
- package/dist/themes/notion.css +29 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/package.json +3 -1
- package/dist/crdt/doc/capability.d.ts +0 -56
- package/dist/crdt/doc/capability.js +0 -211
- package/dist/crdt/doc/content.d.ts +0 -16
- package/dist/crdt/doc/content.js +0 -77
- package/dist/crdt/doc/delete.d.ts +0 -15
- package/dist/crdt/doc/delete.js +0 -84
- package/dist/crdt/doc/layout.d.ts +0 -9
- package/dist/crdt/doc/layout.js +0 -178
- package/dist/crdt/doc/meta.d.ts +0 -19
- package/dist/crdt/doc/meta.js +0 -199
- package/dist/crdt/doc/moves.d.ts +0 -21
- package/dist/crdt/doc/moves.js +0 -274
- package/dist/crdt/doc/split-merge.d.ts +0 -10
- package/dist/crdt/doc/split-merge.js +0 -179
- package/dist/crdt/doc/steps.d.ts +0 -65
- package/dist/crdt/doc/steps.js +0 -311
- package/dist/crdt/text/index/cache.d.ts +0 -16
- package/dist/crdt/text/index/cache.js +0 -175
- package/dist/crdt/text/index/claims.d.ts +0 -18
- package/dist/crdt/text/index/claims.js +0 -225
- package/dist/crdt/text/index/fold.d.ts +0 -21
- package/dist/crdt/text/index/fold.js +0 -656
- package/dist/crdt/text/index/layout.d.ts +0 -24
- package/dist/crdt/text/index/layout.js +0 -271
- package/dist/crdt/text/index/placement.d.ts +0 -47
- package/dist/crdt/text/index/placement.js +0 -741
- package/dist/crdt/text/index/records.d.ts +0 -13
- package/dist/crdt/text/index/records.js +0 -139
- package/dist/crdt/text/index/report.d.ts +0 -18
- package/dist/crdt/text/index/report.js +0 -337
- package/dist/crdt/text/index/state.d.ts +0 -197
- package/dist/crdt/text/index/state.js +0 -116
- package/dist/crdt/text/index/streams.d.ts +0 -25
- package/dist/crdt/text/index/streams.js +0 -248
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EngineNode } from '../../engine-api.js';
|
|
2
2
|
import type { BlockId, BlockRec } from '../../placement/model.js';
|
|
3
3
|
import type { ContentRun, DisplayRoles } from '../runs.js';
|
|
4
|
-
import type { SelfChecks } from './
|
|
4
|
+
import type { IndexFacts, SelfChecks } from './build.js';
|
|
5
5
|
/**
|
|
6
6
|
* The facet name of a block's registry entry itself (inserted or removed) —
|
|
7
7
|
* every other facet is named by the block attr it entered through.
|
|
@@ -65,12 +65,8 @@ export declare const sameShape: (roles: DisplayRoles, a: string, b: string) => b
|
|
|
65
65
|
*/
|
|
66
66
|
export declare const indexChecks: {
|
|
67
67
|
on: boolean;
|
|
68
|
-
of?: (
|
|
68
|
+
of?: (facts: IndexFacts) => SelfChecks;
|
|
69
69
|
};
|
|
70
|
-
/** `ix`'s checker ({@link indexChecks}), built on its first check. */
|
|
71
|
-
export declare const checksOf: (ix: {
|
|
72
|
-
checks: SelfChecks | null;
|
|
73
|
-
}) => SelfChecks;
|
|
74
70
|
/** Add `value` to `key`'s set in `index`. */
|
|
75
71
|
export declare const addTo: <K, V>(index: Map<K, Set<V>>, key: K, value: V) => void;
|
|
76
72
|
/** Remove `value` from `key`'s set in `index` (the set goes once empty). */
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { cloneJsonSafe } from '../../../utils/json.js';
|
|
7
7
|
import { CONTENT, DATA, DATA_LEAF_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../../schema.js';
|
|
8
|
+
import { getOr } from '../../../utils.js';
|
|
8
9
|
/**
|
|
9
10
|
* The facet name of a block's registry entry itself (inserted or removed) —
|
|
10
11
|
* every other facet is named by the block attr it entered through.
|
|
@@ -67,20 +68,23 @@ export const EMPTY_IDS = Object.freeze([]);
|
|
|
67
68
|
* its children.
|
|
68
69
|
*/
|
|
69
70
|
export const sameShape = (roles, a, b) => {
|
|
70
|
-
const lines =
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
const { lines, items, rows, cells } = roles.declared();
|
|
72
|
+
const shape = (t) => {
|
|
73
|
+
const k = roles.of(t);
|
|
74
|
+
return JSON.stringify([
|
|
75
|
+
k.childless,
|
|
76
|
+
k.island,
|
|
77
|
+
k.container,
|
|
78
|
+
k.line,
|
|
79
|
+
lines.has(t),
|
|
80
|
+
k.layout,
|
|
81
|
+
items.has(t),
|
|
82
|
+
k.table,
|
|
83
|
+
rows.has(t),
|
|
84
|
+
cells.has(t)
|
|
85
|
+
]);
|
|
86
|
+
};
|
|
87
|
+
return shape(a) === shape(b);
|
|
84
88
|
};
|
|
85
89
|
/**
|
|
86
90
|
* The index's self-checks, off in production: a test lane's setup installs
|
|
@@ -90,13 +94,9 @@ export const sameShape = (roles, a, b) => {
|
|
|
90
94
|
* difference; after every report, the published tree.
|
|
91
95
|
*/
|
|
92
96
|
export const indexChecks = { on: false };
|
|
93
|
-
/** `ix`'s checker ({@link indexChecks}), built on its first check. */
|
|
94
|
-
export const checksOf = (ix) => (ix.checks ??= indexChecks.of(ix));
|
|
95
97
|
/** Add `value` to `key`'s set in `index`. */
|
|
96
98
|
export const addTo = (index, key, value) => {
|
|
97
|
-
|
|
98
|
-
if (set === undefined)
|
|
99
|
-
index.set(key, (set = new Set()));
|
|
99
|
+
const set = getOr(index, key, () => new Set());
|
|
100
100
|
set.add(value);
|
|
101
101
|
};
|
|
102
102
|
/** Remove `value` from `key`'s set in `index` (the set goes once empty). */
|
|
@@ -277,6 +277,16 @@ export declare const insertIntoText: (doc: EngineDoc, blocks: unknown, own: Owne
|
|
|
277
277
|
* that step's undo still changes nothing.
|
|
278
278
|
*/
|
|
279
279
|
export declare const deleteRange: (doc: EngineDoc, blocks: unknown, own: Ownership, b: BlockId, offset: number, length: number) => void;
|
|
280
|
+
/**
|
|
281
|
+
* A suggestion's plan being written on a doc (`doc/suggest.ts`): its text
|
|
282
|
+
* deletes propose (fork patch YP32) into its record, `sort` telling each
|
|
283
|
+
* unit's lot (`1` its author's own: held; `2` proposed; `3` already
|
|
284
|
+
* proposed: stepped over).
|
|
285
|
+
*/
|
|
286
|
+
export declare const proposing: WeakMap<EngineDoc, {
|
|
287
|
+
into: EngineNode;
|
|
288
|
+
sort: (client: number, clock: number) => number;
|
|
289
|
+
}>;
|
|
280
290
|
export declare const formatRangeIn: (doc: EngineDoc, blocks: unknown, own: Ownership, b: BlockId, offset: number, length: number, formats: Record<string, unknown>) => void;
|
|
281
291
|
/**
|
|
282
292
|
* Delete the content of streams `streams` (the room's purge of a
|
package/dist/crdt/text/model.js
CHANGED
|
@@ -7,6 +7,7 @@ import { fitMarks, writeMarks } from './marks.js';
|
|
|
7
7
|
import { nodeStart } from './items.js';
|
|
8
8
|
import { readRange } from './ranges.js';
|
|
9
9
|
import { claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, rangesOf, removedKeys, scanText } from './streams.js';
|
|
10
|
+
import { getOr } from '../../utils.js';
|
|
10
11
|
export { isBoundary, isClaimItem, isRowMark, nodeStart } from './items.js';
|
|
11
12
|
export { canonKey, deepFreeze, inlineItemOf, protectItems, readRange } from './ranges.js';
|
|
12
13
|
export { byId, claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, removedKeys, scanText } from './streams.js';
|
|
@@ -107,9 +108,7 @@ export const readSegs = (segs, stats) => {
|
|
|
107
108
|
const out = [];
|
|
108
109
|
const cursors = new Map();
|
|
109
110
|
for (const seg of segs) {
|
|
110
|
-
|
|
111
|
-
if (cur === undefined)
|
|
112
|
-
cursors.set(seg.text, (cur = openRangeCursor(seg.text)));
|
|
111
|
+
const cur = getOr(cursors, seg.text, () => openRangeCursor(seg.text));
|
|
113
112
|
readRange(cur, seg.i0, seg.i1, stats, out);
|
|
114
113
|
}
|
|
115
114
|
return out;
|
|
@@ -198,8 +197,15 @@ export const deleteRange = (doc, blocks, own, b, offset, length) => {
|
|
|
198
197
|
const records = doc.get(TEXT_DELETES_ROOT);
|
|
199
198
|
const fresh = openInserts(doc);
|
|
200
199
|
for (const r of rangesOf(flatten(b, blocks, own), offset, offset + length))
|
|
201
|
-
r.text.delete(r.a, r.b - r.a, records, fresh);
|
|
200
|
+
r.text.delete(r.a, r.b - r.a, records, fresh, proposing.get(doc));
|
|
202
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* A suggestion's plan being written on a doc (`doc/suggest.ts`): its text
|
|
204
|
+
* deletes propose (fork patch YP32) into its record, `sort` telling each
|
|
205
|
+
* unit's lot (`1` its author's own: held; `2` proposed; `3` already
|
|
206
|
+
* proposed: stepped over).
|
|
207
|
+
*/
|
|
208
|
+
export const proposing = new WeakMap();
|
|
203
209
|
export const formatRangeIn = (doc, blocks, own, b, offset, length, formats) => {
|
|
204
210
|
for (const r of rangesOf(flatten(b, blocks, own), offset, offset + length))
|
|
205
211
|
writeMarks(doc, r.text, r.a, r.b - r.a, formats);
|
package/dist/crdt/text/runs.d.ts
CHANGED
|
@@ -53,17 +53,16 @@
|
|
|
53
53
|
* advancing the published tree in place (after a whole rebuild, the
|
|
54
54
|
* reachable tree is compared).
|
|
55
55
|
*
|
|
56
|
-
* The index is
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* the
|
|
60
|
-
*
|
|
61
|
-
* cache (`cache.ts`), the fold (`fold.ts`), the change report
|
|
62
|
-
* (`report.ts`); the self-checks a test lane installs are `indexChecks`. This module declares the
|
|
63
|
-
* index's types and wires the parts into the doc's one index.
|
|
56
|
+
* The index is one closure (`index/build.ts`) over its state: the claim
|
|
57
|
+
* graph, the stream table and each block's claims, the layout rules,
|
|
58
|
+
* placements and the children index, block records, the run cache, the fold
|
|
59
|
+
* and the change report; the self-checks a test lane installs are
|
|
60
|
+
* `indexChecks`. This module declares the index's types.
|
|
64
61
|
*/
|
|
65
|
-
import type { EngineApi
|
|
62
|
+
import type { EngineApi } from '../engine-api.js';
|
|
66
63
|
import type { BlockId, ContentItem, ModelView, ProjectedBlock } from '../placement/model.js';
|
|
64
|
+
import { indexOf } from './index/build.js';
|
|
65
|
+
export { indexOf };
|
|
67
66
|
export { CONTENT_ATTR, ENTRY_FACET, SEQ_FACET, indexChecks } from './index/shared.js';
|
|
68
67
|
/**
|
|
69
68
|
* One visible run of a block — the maintained form of `ContentItem`.
|
|
@@ -220,42 +219,44 @@ export type RunView = {
|
|
|
220
219
|
debug: RunViewDebug;
|
|
221
220
|
};
|
|
222
221
|
/**
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* `
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* kind that
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* layout
|
|
234
|
-
* `table`: a table
|
|
235
|
-
* the table's column order (`table.*`).
|
|
222
|
+
* A kind's answers, read once from its role (the one shape the display and
|
|
223
|
+
* every guard read). `childless`: displays no children (a void role) — a
|
|
224
|
+
* child of such a block displays in its slot. `island`: a block promoted
|
|
225
|
+
* out of one displays as `child` of its display parent's kind.
|
|
226
|
+
* `container`: renders no content and is neither void nor an island (a
|
|
227
|
+
* list) — a block promoted out of one follows like one promoted out of an
|
|
228
|
+
* island. `rendersContent`: no block that renders content ever shows as a
|
|
229
|
+
* kind that does not (its text would vanish). `child`: its default child
|
|
230
|
+
* (the document's default kind for the root, `null`). `line`: an island
|
|
231
|
+
* declared `lines` holds only lines of this kind, which hold no children.
|
|
232
|
+
* `layout`: a layout displays only items of this kind, and only two or
|
|
233
|
+
* more (`layout.*`). `table`: a table displays only rows of this kind, a
|
|
234
|
+
* row only its cells, in the table's column order (`table.*`).
|
|
236
235
|
*/
|
|
236
|
+
export type KindRole = {
|
|
237
|
+
childless: boolean;
|
|
238
|
+
island: boolean;
|
|
239
|
+
container: boolean;
|
|
240
|
+
rendersContent: boolean;
|
|
241
|
+
child: string;
|
|
242
|
+
line?: string;
|
|
243
|
+
layout?: string;
|
|
244
|
+
table?: string;
|
|
245
|
+
};
|
|
246
|
+
/** The kinds the roles declare: line kinds, layout kinds and their item kinds, table kinds and their row kinds (→ cell kind). */
|
|
247
|
+
export type DeclaredKinds = {
|
|
248
|
+
lines: ReadonlySet<string>;
|
|
249
|
+
layouts: readonly string[];
|
|
250
|
+
items: ReadonlySet<string>;
|
|
251
|
+
rows: ReadonlyMap<string, string>;
|
|
252
|
+
cells: ReadonlySet<string>;
|
|
253
|
+
};
|
|
254
|
+
/** The role table: each kind's {@link KindRole} and the declared kinds, both read once until the roles change. */
|
|
237
255
|
export type DisplayRoles = {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
container: (type: string) => boolean;
|
|
241
|
-
rendersContent: (type: string) => boolean;
|
|
242
|
-
defaultChild: (parentType: string | null) => string;
|
|
243
|
-
/** The line kind of an island kind declared `lines` (its `defaultChild`), if any. */
|
|
244
|
-
line: (islandType: string) => string | undefined;
|
|
245
|
-
/** Every line kind the roles declare, present in the document or not. */
|
|
246
|
-
lineKinds: () => Iterable<string>;
|
|
247
|
-
/** The item kind of a layout kind (its `defaultChild`), if `type` is one. */
|
|
248
|
-
layout: (type: string) => string | undefined;
|
|
249
|
-
/** Every layout kind the roles declare, present in the document or not. */
|
|
250
|
-
layoutKinds: () => Iterable<string>;
|
|
251
|
-
/** The row kind of a table kind (its `defaultChild`), if `type` is one (`table.*`). */
|
|
252
|
-
table: (type: string) => string | undefined;
|
|
253
|
-
/** Every table kind the roles declare, present in the document or not. */
|
|
254
|
-
tableKinds: () => Iterable<string>;
|
|
256
|
+
of: (type: string | null) => KindRole;
|
|
257
|
+
declared: () => DeclaredKinds;
|
|
255
258
|
};
|
|
256
|
-
/** The doc's index — built on first use, torn down when the doc is destroyed. */
|
|
257
|
-
export declare const indexOf: (doc: EngineDoc) => RunView;
|
|
258
259
|
/** The index binding (the public binding's `runs`): {@link indexOf}. */
|
|
259
260
|
export declare const bindRuns: (_Y: EngineApi) => {
|
|
260
|
-
attach: (doc: EngineDoc) => RunView;
|
|
261
|
+
attach: (doc: import("../engine-api.js").EngineDoc) => RunView;
|
|
261
262
|
};
|
package/dist/crdt/text/runs.js
CHANGED
|
@@ -1,168 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { indexState } from './index/state.js';
|
|
4
|
-
import { indexClaims } from './index/claims.js';
|
|
5
|
-
import { indexStreams } from './index/streams.js';
|
|
6
|
-
import { indexLayout } from './index/layout.js';
|
|
7
|
-
import { indexPlacement } from './index/placement.js';
|
|
8
|
-
import { indexRecords } from './index/records.js';
|
|
9
|
-
import { indexCache } from './index/cache.js';
|
|
10
|
-
import { indexFold } from './index/fold.js';
|
|
11
|
-
import { indexReporter } from './index/report.js';
|
|
1
|
+
import { indexOf } from './index/build.js';
|
|
2
|
+
export { indexOf };
|
|
12
3
|
export { CONTENT_ATTR, ENTRY_FACET, SEQ_FACET, indexChecks } from './index/shared.js';
|
|
13
|
-
/** One index per engine doc, shared by every binding (the doc's lifetime). */
|
|
14
|
-
const indexes = new WeakMap();
|
|
15
|
-
/** The doc's index — built on first use, torn down when the doc is destroyed. */
|
|
16
|
-
export const indexOf = (doc) => {
|
|
17
|
-
let index = indexes.get(doc);
|
|
18
|
-
if (index === undefined)
|
|
19
|
-
indexes.set(doc, (index = buildView(doc)));
|
|
20
|
-
return index;
|
|
21
|
-
};
|
|
22
4
|
/** The index binding (the public binding's `runs`): {@link indexOf}. */
|
|
23
5
|
export const bindRuns = (_Y) => ({ attach: indexOf });
|
|
24
|
-
const buildView = (doc) => {
|
|
25
|
-
// The index's parts, each over the state and the parts before it (`index/*`).
|
|
26
|
-
const ix0 = indexState(doc);
|
|
27
|
-
const ix1 = Object.assign(ix0, indexClaims(ix0));
|
|
28
|
-
const ix2 = Object.assign(ix1, indexStreams(ix1));
|
|
29
|
-
const ix4 = Object.assign(ix2, indexLayout(ix2));
|
|
30
|
-
const ix5 = Object.assign(ix4, indexPlacement(ix4));
|
|
31
|
-
const ix6 = Object.assign(ix5, indexRecords(ix5));
|
|
32
|
-
const ix7 = Object.assign(ix6, indexCache(ix6));
|
|
33
|
-
const ix8 = Object.assign(ix7, indexFold(ix7));
|
|
34
|
-
const ix = Object.assign(ix8, indexReporter(ix8));
|
|
35
|
-
const { registry, blocks, rows, homeOfText, shells, placementsMap, frames, displays, ownShim, ensurePlacements, typeOf, order, rebuildTable, scanRow, applyReclaims, updateBlockRec, syncIncarnations, intern, debug, runs, settle, syncPending, syncAll, openTx, onCommit, committed, itemsOf, projectBlock, publish, onUpdate, onReport, hasSubscribers } = ix;
|
|
36
|
-
const ctx = {
|
|
37
|
-
blocks,
|
|
38
|
-
own: ownShim,
|
|
39
|
-
get placements() {
|
|
40
|
-
ensurePlacements();
|
|
41
|
-
return placementsMap;
|
|
42
|
-
},
|
|
43
|
-
get kids() {
|
|
44
|
-
ensurePlacements();
|
|
45
|
-
return ix.kidsMap;
|
|
46
|
-
},
|
|
47
|
-
get order() {
|
|
48
|
-
ensurePlacements();
|
|
49
|
-
return order();
|
|
50
|
-
},
|
|
51
|
-
// The publication boundary shares THIS interner, so a payload
|
|
52
|
-
// emitted by `project()`/`contentItems()` is `===` the runs' one.
|
|
53
|
-
intern,
|
|
54
|
-
displays,
|
|
55
|
-
accepted: (id) => {
|
|
56
|
-
ensurePlacements();
|
|
57
|
-
return ix.rejected.has(id) ? null : (ix.edges.get(id) ?? null);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
// ── initial scan: index every existing block ────────────────────
|
|
61
|
-
registry.forEachAttr((v, id) => {
|
|
62
|
-
if (!isNodeLike(v))
|
|
63
|
-
return;
|
|
64
|
-
updateBlockRec(id);
|
|
65
|
-
for (const b of [id, ...syncIncarnations(id)]) {
|
|
66
|
-
const row = scanRow(b);
|
|
67
|
-
if (row !== undefined) {
|
|
68
|
-
rows.set(b, row);
|
|
69
|
-
homeOfText.set(row.text, b);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
rebuildTable(new Set());
|
|
74
|
-
applyReclaims(null);
|
|
75
|
-
settle(shells, null);
|
|
76
|
-
// Every commit folds once, before the document's `afterTransaction` listeners.
|
|
77
|
-
doc.on('commit', onCommit);
|
|
78
|
-
/** Derived state lives exactly as long as the doc. */
|
|
79
|
-
const teardown = () => {
|
|
80
|
-
doc.off('commit', onCommit);
|
|
81
|
-
doc.off('destroy', teardown);
|
|
82
|
-
doc.off('update', onUpdate);
|
|
83
|
-
indexes.delete(doc);
|
|
84
|
-
};
|
|
85
|
-
doc.on('destroy', teardown);
|
|
86
|
-
// ── public surface ───────────────────────────────────────────────
|
|
87
|
-
const view = {
|
|
88
|
-
version: () => {
|
|
89
|
-
syncAll();
|
|
90
|
-
return ix.version;
|
|
91
|
-
},
|
|
92
|
-
runs,
|
|
93
|
-
contentItems: (b) => {
|
|
94
|
-
syncAll();
|
|
95
|
-
return blocks.get(b)?.deleted === false ? itemsOf(b) : [];
|
|
96
|
-
},
|
|
97
|
-
// Inline atoms always carry `data` (`{}` when absent) — the public
|
|
98
|
-
// `JSONInlineBlock` shape of `edytor.value`.
|
|
99
|
-
contentJSON: (b) => runs(b).map((r) => r.kind === 'text'
|
|
100
|
-
? { text: r.text, ...(r.marks !== undefined && { marks: cloneJsonSafe(r.marks) }) }
|
|
101
|
-
: { id: r.id, type: r.type, data: r.data === undefined ? {} : cloneJsonSafe(r.data) }),
|
|
102
|
-
view: (tr) => {
|
|
103
|
-
syncAll();
|
|
104
|
-
if (tr !== undefined && !committed.has(tr))
|
|
105
|
-
syncPending(tr);
|
|
106
|
-
return ctx;
|
|
107
|
-
},
|
|
108
|
-
displayType: (id) => {
|
|
109
|
-
if (ix.roles === null)
|
|
110
|
-
return undefined;
|
|
111
|
-
syncAll();
|
|
112
|
-
ensurePlacements();
|
|
113
|
-
const shown = blocks.has(id) ? typeOf(id) : undefined;
|
|
114
|
-
return shown === blocks.get(id)?.type ? undefined : shown;
|
|
115
|
-
},
|
|
116
|
-
dissolved: (id) => {
|
|
117
|
-
syncAll();
|
|
118
|
-
ensurePlacements();
|
|
119
|
-
return ix.dissolved.has(id);
|
|
120
|
-
},
|
|
121
|
-
project: (root) => {
|
|
122
|
-
syncAll();
|
|
123
|
-
ensurePlacements();
|
|
124
|
-
return root === undefined
|
|
125
|
-
? (ix.kidsMap.get(null) ?? []).map((k) => projectBlock(k.id))
|
|
126
|
-
: [projectBlock(root)];
|
|
127
|
-
},
|
|
128
|
-
roles: (next) => {
|
|
129
|
-
ix.roles = next;
|
|
130
|
-
ix.placementFull = true;
|
|
131
|
-
ix.version++;
|
|
132
|
-
// No commit carries a role change: report it now (not inside a
|
|
133
|
-
// transaction, whose commit reports it), so every view follows.
|
|
134
|
-
if (hasSubscribers() && !openTx())
|
|
135
|
-
publish(null, false);
|
|
136
|
-
},
|
|
137
|
-
track: () => {
|
|
138
|
-
syncAll();
|
|
139
|
-
const f = { touched: new Map(), wrote: false };
|
|
140
|
-
frames.add(f);
|
|
141
|
-
return {
|
|
142
|
-
end: () => {
|
|
143
|
-
syncAll();
|
|
144
|
-
frames.delete(f);
|
|
145
|
-
return f;
|
|
146
|
-
},
|
|
147
|
-
quiet: (write) => {
|
|
148
|
-
syncAll();
|
|
149
|
-
const g = { touched: new Map(), wrote: false };
|
|
150
|
-
frames.delete(f);
|
|
151
|
-
frames.add(g);
|
|
152
|
-
try {
|
|
153
|
-
write();
|
|
154
|
-
syncAll();
|
|
155
|
-
}
|
|
156
|
-
finally {
|
|
157
|
-
frames.delete(g);
|
|
158
|
-
frames.add(f);
|
|
159
|
-
f.wrote ||= g.wrote;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
},
|
|
164
|
-
onReport,
|
|
165
|
-
debug
|
|
166
|
-
};
|
|
167
|
-
return view;
|
|
168
|
-
};
|
|
@@ -1515,6 +1515,89 @@ Oracle: `src/tests/crdt/attribution/first-write-binding.test.ts` (the first
|
|
|
1515
1515
|
local edit's one update carries the binding; a remote update writes none),
|
|
1516
1516
|
the upstream suite.
|
|
1517
1517
|
|
|
1518
|
+
### YP31 — a hold record inside a nested node holds nothing (`src/structs/Item.js`)
|
|
1519
|
+
|
|
1520
|
+
Reason: edytor's shared suggestions keep, inside each suggestion's record
|
|
1521
|
+
node, the id ranges it proposes to delete and the ranges its reviewers
|
|
1522
|
+
settled: lists of `client, clock, len` ranges that must hide nothing until a
|
|
1523
|
+
reviewer accepts. YP20's hold record is exactly that codec (one unit per
|
|
1524
|
+
range, a left id and a length, consecutive records of one writer merging
|
|
1525
|
+
as typed runs do), but it holds whatever it names wherever it integrates.
|
|
1526
|
+
The study's prototype added a sibling content type that held nothing
|
|
1527
|
+
(content ref 14, `ContentPropose`, a `YNode#propose` writer, about 0.3 KB);
|
|
1528
|
+
the rule here keeps one record type and one reader. Design:
|
|
1529
|
+
`docs/archive/shared-suggestions/design.md`. Edytor's schema generation 11
|
|
1530
|
+
is the cutover (no conversion: a generation-10 replica would hold what a
|
|
1531
|
+
proposal names).
|
|
1532
|
+
|
|
1533
|
+
Patch (new code delimited by `// YP31 begin` / `// YP31 end`, edits marked `// YP31`):
|
|
1534
|
+
|
|
1535
|
+
- **`holding(item)`**: a hold record holds what it names iff its item is an
|
|
1536
|
+
entry of a root's sequence (`item.parent._item === null`: the document's
|
|
1537
|
+
records list, `textdel`). `ContentHold#integrate` and `ContentHold#delete`
|
|
1538
|
+
hold and release only then; inside a nested node's sequence the record is
|
|
1539
|
+
a list of ids: it moves no length, waits in no `pendingHolds`, logs
|
|
1540
|
+
nothing in `transaction.holds`, and its delete (an undo, a reviewer's
|
|
1541
|
+
withdrawal, its node's delete) releases nothing. `YNode#hold(ids)` on a
|
|
1542
|
+
nested node appends one such list entry.
|
|
1543
|
+
|
|
1544
|
+
Plain deletes and the root records list (every upstream test, every YP20
|
|
1545
|
+
row) are untouched: no other code path writes a hold record into a nested
|
|
1546
|
+
node.
|
|
1547
|
+
|
|
1548
|
+
Edytor side: a suggestion's record node (root `suggest`) keeps its writer's
|
|
1549
|
+
proposed deletions and its reviewers' settled ranges as such entries
|
|
1550
|
+
(`crdt/doc/suggest.ts`); accepting a deletion writes a real hold record in
|
|
1551
|
+
the root list.
|
|
1552
|
+
|
|
1553
|
+
Oracle: `src/tests/crdt/yp31-id-lists.test.ts` (written, deleted, merged,
|
|
1554
|
+
split, synced, reloaded, received before the items it names, deleted with
|
|
1555
|
+
its node: nothing hidden or released; the root list still holds), the YP20
|
|
1556
|
+
rows and the shared-suggestion rows, the upstream suite unchanged
|
|
1557
|
+
(`encoding.tests.js` still pins 14 content refs).
|
|
1558
|
+
|
|
1559
|
+
### YP32 — a delete that proposes (`src/ynode.js`, `src/structs/Item.js`, `src/index.js`)
|
|
1560
|
+
|
|
1561
|
+
Reason: in suggesting mode a text delete writes nothing to the text: the
|
|
1562
|
+
units that are not the suggestion's author's own pending ones are named by
|
|
1563
|
+
an id list in the suggestion's record (YP31), and they stay shown. The
|
|
1564
|
+
plan that deleted them was prepared with them gone, so edytor carried a
|
|
1565
|
+
layer that re-read each later step's offsets over the units the plan had
|
|
1566
|
+
proposed, batched the steps around every proposal and mapped the caret
|
|
1567
|
+
back (`crdt/doc/suggest.ts` `apply`, about 1.4 KB minified). The fork's
|
|
1568
|
+
delete now proposes, and hides what it proposed until the plan ends: the
|
|
1569
|
+
plan's later steps read the offsets they were prepared with, and an
|
|
1570
|
+
insertion at a proposed deletion lands after it (at the end of the gap,
|
|
1571
|
+
as any insertion lands after deleted items). Design:
|
|
1572
|
+
`docs/archive/suggestions-in-engine/design.md`.
|
|
1573
|
+
|
|
1574
|
+
Patch (new code delimited by `// YP32 begin` / `// YP32 end`, edits marked `// YP32`):
|
|
1575
|
+
|
|
1576
|
+
- **`YNode#delete(index, length, into, fresh, propose)`**: with `propose`
|
|
1577
|
+
(`{ into, sort }`), each live unit the delete reaches is sorted by
|
|
1578
|
+
`sort(client, clock)`: `1` held by the record appended to `into` (the
|
|
1579
|
+
author's own pending text, YP20's path), `2` proposed (one id list
|
|
1580
|
+
appended to `propose.into`, the suggestion's record, which holds nothing
|
|
1581
|
+
there, YP31), `3` stepped over (already proposed). `fresh` units are
|
|
1582
|
+
removed as before. Proposed and stepped-over units are hidden
|
|
1583
|
+
(`hideIds`: a hold without a record, kept in `transaction.hidden`) until
|
|
1584
|
+
`unhide(transaction)`, which edytor calls when the plan is written.
|
|
1585
|
+
`deleteText` splits a run where the sort changes.
|
|
1586
|
+
- **`hideIds`, `unhide`** (`Item.js`, `unhide` exported): YP20's
|
|
1587
|
+
`holdIds` with no record, and its release.
|
|
1588
|
+
|
|
1589
|
+
Plain deletes (every upstream test, every YP20 row) are untouched: without
|
|
1590
|
+
`propose` the sort is not read and every changed path reduces to YP20's.
|
|
1591
|
+
|
|
1592
|
+
Edytor side: `crdt/text/model.ts` `deleteRange` passes the plan's
|
|
1593
|
+
`proposing` context; `crdt/doc/suggest.ts` writes a suggesting plan as one
|
|
1594
|
+
frame, its caret anchored before `unhide` and resolved after.
|
|
1595
|
+
|
|
1596
|
+
Oracle: the shared-suggestion rows (`src/tests/crdt/suggest/`, the random
|
|
1597
|
+
schedules with the index's self-checks on), `suggesting-input.test.tsx`
|
|
1598
|
+
(typing over a selection, a paste, Backspace and Delete over struck text),
|
|
1599
|
+
the YP20 rows, the upstream suite unchanged.
|
|
1600
|
+
|
|
1518
1601
|
## Generated declarations (`dts/`)
|
|
1519
1602
|
|
|
1520
1603
|
`svelte-package` copies JS verbatim but emits no `.d.ts` for JS inputs, so
|
|
@@ -17,4 +17,4 @@ export { idAtIndex, indexOfId } from "./utils/positions.js";
|
|
|
17
17
|
export { findIndexSS, getItemCleanStart, getItemCleanEnd, isKeptReplaced } from "./utils/transaction-helpers.js";
|
|
18
18
|
export { Transaction, transact } from "./utils/Transaction.js";
|
|
19
19
|
export { redoItem, keepItem } from "./utils/redo.js";
|
|
20
|
-
export { Item, followRedone, ContentBinary, ContentDeleted, ContentFormat, ContentAny, ContentString, ContentType, ContentMove } from "./structs/Item.js";
|
|
20
|
+
export { Item, followRedone, ContentBinary, ContentDeleted, ContentFormat, ContentAny, ContentString, ContentType, ContentMove, unhide } from "./structs/Item.js";
|
|
@@ -427,13 +427,14 @@ export class ContentHold {
|
|
|
427
427
|
mergeWith(right: ContentHold): boolean;
|
|
428
428
|
/**
|
|
429
429
|
* @param {Transaction} transaction
|
|
430
|
-
* @param {Item}
|
|
430
|
+
* @param {Item} item
|
|
431
431
|
*/
|
|
432
|
-
integrate(transaction: Transaction,
|
|
432
|
+
integrate(transaction: Transaction, item: Item): void;
|
|
433
433
|
/**
|
|
434
434
|
* @param {Transaction} transaction
|
|
435
|
+
* @param {Item} item
|
|
435
436
|
*/
|
|
436
|
-
delete(transaction: Transaction): void;
|
|
437
|
+
delete(transaction: Transaction, item: Item): void;
|
|
437
438
|
/**
|
|
438
439
|
* @param {Transaction} _tr
|
|
439
440
|
*/
|
|
@@ -449,6 +450,8 @@ export class ContentHold {
|
|
|
449
450
|
*/
|
|
450
451
|
getRef(): 11;
|
|
451
452
|
}
|
|
453
|
+
export function hideIds(tr: Transaction, ids: Array<number>): void;
|
|
454
|
+
export function unhide(tr: Transaction): void;
|
|
452
455
|
export function applyPending(tr: Transaction, clients: Array<number>): void;
|
|
453
456
|
/**
|
|
454
457
|
* A move record: one countable unit at its destination, naming the units
|
|
@@ -25,7 +25,7 @@ export class ItemTextListPosition {
|
|
|
25
25
|
advance(transaction: Transaction, length: number): void;
|
|
26
26
|
}
|
|
27
27
|
export function insertAtGapEndHelper(transaction: Transaction, parent: YNode, index: number, content: import("./structs/Item.js").AbstractContent): void;
|
|
28
|
-
export function deleteText(transaction: Transaction, currPos: ItemTextListPosition, length: number, held?: Array<number> | null, fresh?: import("./utils/ids.js").IdSet | null): ItemTextListPosition;
|
|
28
|
+
export function deleteText(transaction: Transaction, currPos: ItemTextListPosition, length: number, held?: Array<number> | null, fresh?: import("./utils/ids.js").IdSet | null, sort?: ((client: number, clock: number) => number) | null, proposed?: Array<number> | null, hidden?: Array<number> | null): ItemTextListPosition;
|
|
29
29
|
export class ArraySearchMarker {
|
|
30
30
|
/**
|
|
31
31
|
* @param {Item} p
|
|
@@ -193,12 +193,23 @@ export class YNode {
|
|
|
193
193
|
* which an undo of the record takes back), except those `fresh` names (the
|
|
194
194
|
* open undo step's inserts: removed, so that step's undo changes nothing).
|
|
195
195
|
*
|
|
196
|
+
* YP32: with `propose` (a suggestion's delete) each unit is sorted: held
|
|
197
|
+
* by the record in `into` (`1`: its author's own), proposed (`2`: an id
|
|
198
|
+
* list appended to `propose.into`, a suggestion's record, holding nothing)
|
|
199
|
+
* or stepped over (`3`: already proposed); proposed and stepped-over units
|
|
200
|
+
* read gone until `unhide`, so the rest of the plan reads the offsets it
|
|
201
|
+
* was prepared with.
|
|
202
|
+
*
|
|
196
203
|
* @param {number} index Index at which to start deleting elements
|
|
197
204
|
* @param {number} length The number of elements to remove. Defaults to 1.
|
|
198
205
|
* @param {YNode|null} [into]
|
|
199
206
|
* @param {import('./utils/ids.js').IdSet|null} [fresh]
|
|
207
|
+
* @param {{ into: YNode, sort: (client: number, clock: number) => number }|null} [propose]
|
|
200
208
|
*/
|
|
201
|
-
delete(index: number, length?: number, into?: YNode | null, fresh?: import("./utils/ids.js").IdSet | null
|
|
209
|
+
delete(index: number, length?: number, into?: YNode | null, fresh?: import("./utils/ids.js").IdSet | null, propose?: {
|
|
210
|
+
into: YNode;
|
|
211
|
+
sort: (client: number, clock: number) => number;
|
|
212
|
+
} | null): void;
|
|
202
213
|
/**
|
|
203
214
|
* YP20: append to this node (the document's records list) one hold record of
|
|
204
215
|
* the items `ids` names (`client, clock, len` triples): they read as deleted
|
|
@@ -19,7 +19,7 @@ export { RangeCursor } from './utils/RangeCursor.js'
|
|
|
19
19
|
export { YNode as Node } from './ynode.js'
|
|
20
20
|
export { AbstractStruct } from './structs/AbstractStruct.js'
|
|
21
21
|
export { GC } from './structs/GC.js'
|
|
22
|
-
export { Item, followRedone, ContentBinary, ContentDeleted, ContentFormat, ContentAny, ContentString, ContentType, ContentMove } from './structs/Item.js' // YP22: ContentMove
|
|
22
|
+
export { Item, followRedone, ContentBinary, ContentDeleted, ContentFormat, ContentAny, ContentString, ContentType, ContentMove, unhide } from './structs/Item.js' // YP22: ContentMove; YP32: unhide
|
|
23
23
|
export { Skip } from './structs/Skip.js'
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -1134,17 +1134,18 @@ export class ContentHold {
|
|
|
1134
1134
|
|
|
1135
1135
|
/**
|
|
1136
1136
|
* @param {Transaction} transaction
|
|
1137
|
-
* @param {Item}
|
|
1137
|
+
* @param {Item} item
|
|
1138
1138
|
*/
|
|
1139
|
-
integrate (transaction,
|
|
1140
|
-
holdIds(transaction, this.ids, 1)
|
|
1139
|
+
integrate (transaction, item) {
|
|
1140
|
+
if (holding(item)) holdIds(transaction, this.ids, 1) // YP31
|
|
1141
1141
|
}
|
|
1142
1142
|
|
|
1143
1143
|
/**
|
|
1144
1144
|
* @param {Transaction} transaction
|
|
1145
|
+
* @param {Item} item
|
|
1145
1146
|
*/
|
|
1146
|
-
delete (transaction) {
|
|
1147
|
-
holdIds(transaction, this.ids, -1)
|
|
1147
|
+
delete (transaction, item) {
|
|
1148
|
+
if (holding(item)) holdIds(transaction, this.ids, -1) // YP31
|
|
1148
1149
|
}
|
|
1149
1150
|
|
|
1150
1151
|
/**
|
|
@@ -1170,6 +1171,44 @@ export class ContentHold {
|
|
|
1170
1171
|
}
|
|
1171
1172
|
// YP20 end
|
|
1172
1173
|
|
|
1174
|
+
// YP31 begin (edytor fork: id lists — see UPSTREAM.md YP31)
|
|
1175
|
+
/**
|
|
1176
|
+
* Whether the hold record `item` holds what it names: one in a root's
|
|
1177
|
+
* sequence does (the document's records list, YP20); one in a nested node's
|
|
1178
|
+
* sequence is a list of ids, the same codec, that holds nothing.
|
|
1179
|
+
*
|
|
1180
|
+
* @param {Item} item
|
|
1181
|
+
* @return {boolean}
|
|
1182
|
+
*/
|
|
1183
|
+
const holding = item => /** @type {YNode} */ (item.parent)._item === null
|
|
1184
|
+
// YP31 end
|
|
1185
|
+
|
|
1186
|
+
// YP32 begin (edytor fork: a delete that proposes — see UPSTREAM.md YP32)
|
|
1187
|
+
/**
|
|
1188
|
+
* Hide the units `ids` names until `unhide` (a suggestion's proposed
|
|
1189
|
+
* deletion, which the rest of its plan reads gone): a hold without a
|
|
1190
|
+
* record, kept in `tr.hidden`.
|
|
1191
|
+
*
|
|
1192
|
+
* @param {Transaction} tr
|
|
1193
|
+
* @param {Array<number>} ids
|
|
1194
|
+
*/
|
|
1195
|
+
export const hideIds = (tr, ids) => {
|
|
1196
|
+
holdIds(tr, ids, 1)
|
|
1197
|
+
;/** @type {any} */ (tr).hidden = (/** @type {any} */ (tr).hidden ?? []).concat(ids)
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
/**
|
|
1201
|
+
* Show again what `hideIds` hid in `tr`.
|
|
1202
|
+
*
|
|
1203
|
+
* @param {Transaction} tr
|
|
1204
|
+
*/
|
|
1205
|
+
export const unhide = tr => {
|
|
1206
|
+
const hidden = /** @type {any} */ (tr).hidden
|
|
1207
|
+
if (hidden) holdIds(tr, hidden, -1)
|
|
1208
|
+
;/** @type {any} */ (tr).hidden = null
|
|
1209
|
+
}
|
|
1210
|
+
// YP32 end
|
|
1211
|
+
|
|
1173
1212
|
// YP22 begin (edytor fork: move records — see UPSTREAM.md YP22)
|
|
1174
1213
|
/**
|
|
1175
1214
|
* Whether move record `a` beats `b`: the greater `(priority, client, clock)`
|