edytor 3.0.0 → 5.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 +23 -12
- package/dist/cloudflare/DocumentRoom.js +10 -6
- 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 +139 -129
- package/dist/cloudflare/room/context.js +11 -4
- 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.d.ts +6 -3
- package/dist/cloudflare/room/purge.js +45 -19
- 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/room/updates.d.ts +3 -4
- package/dist/cloudflare/room/updates.js +6 -8
- 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 +34 -12
- package/dist/crdt/attribution/attribution.js +59 -21
- package/dist/crdt/attribution/block.d.ts +3 -3
- package/dist/crdt/attribution/block.js +7 -8
- package/dist/crdt/attribution/index.d.ts +1 -1
- package/dist/crdt/attribution/index.js +1 -1
- package/dist/crdt/data.d.ts +62 -31
- package/dist/crdt/data.js +211 -103
- package/dist/crdt/doc/capability.js +9 -13
- package/dist/crdt/doc/delete.d.ts +1 -1
- package/dist/crdt/doc/delete.js +13 -30
- package/dist/crdt/doc/funnel.d.ts +1 -1
- package/dist/crdt/doc/funnel.js +34 -26
- package/dist/crdt/doc/gate.d.ts +3 -3
- package/dist/crdt/doc/history.d.ts +31 -9
- package/dist/crdt/doc/history.js +204 -73
- package/dist/crdt/doc/layout.js +16 -27
- package/dist/crdt/doc/meta.js +17 -23
- package/dist/crdt/doc/moves.d.ts +1 -1
- package/dist/crdt/doc/moves.js +52 -32
- package/dist/crdt/doc/reads.d.ts +2 -2
- package/dist/crdt/doc/reads.js +20 -30
- package/dist/crdt/doc/seed.js +2 -2
- package/dist/crdt/doc/split-merge.js +12 -15
- package/dist/crdt/doc/steps.d.ts +25 -13
- package/dist/crdt/doc/steps.js +55 -125
- package/dist/crdt/doc/suggest.d.ts +167 -0
- package/dist/crdt/doc/suggest.js +579 -0
- package/dist/crdt/doc/types.d.ts +21 -9
- package/dist/crdt/document.d.ts +26 -6
- package/dist/crdt/document.js +40 -15
- package/dist/crdt/edytor-doc.d.ts +410 -390
- package/dist/crdt/edytor-doc.js +143 -95
- package/dist/crdt/engine-api.d.ts +39 -1
- package/dist/crdt/engine.d.ts +2 -2
- package/dist/crdt/engine.js +4 -5
- package/dist/crdt/flow.d.ts +2 -2
- package/dist/crdt/flow.js +29 -37
- package/dist/crdt/index.d.ts +134 -127
- package/dist/crdt/index.js +4 -1
- package/dist/crdt/operations.d.ts +12 -3
- package/dist/crdt/parts.d.ts +43 -0
- package/dist/crdt/parts.js +44 -0
- package/dist/crdt/placement/display.d.ts +6 -31
- package/dist/crdt/placement/display.js +41 -146
- package/dist/crdt/placement/keys.d.ts +63 -0
- package/dist/crdt/placement/keys.js +95 -0
- package/dist/crdt/placement/model.d.ts +119 -118
- package/dist/crdt/placement/model.js +242 -142
- package/dist/crdt/placement/resolve.d.ts +123 -35
- package/dist/crdt/placement/resolve.js +188 -153
- package/dist/crdt/placement/slots.d.ts +134 -0
- package/dist/crdt/placement/slots.js +152 -0
- 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/comments.d.ts +16 -1
- package/dist/crdt/protocols/comments.js +9 -1
- package/dist/crdt/providers/index.d.ts +6 -4
- package/dist/crdt/providers/index.js +3 -1
- package/dist/crdt/providers/room.d.ts +16 -2
- package/dist/crdt/providers/room.js +64 -17
- package/dist/crdt/providers/websocket.d.ts +6 -4
- package/dist/crdt/providers/websocket.js +14 -7
- package/dist/crdt/purge.d.ts +24 -9
- package/dist/crdt/purge.js +266 -126
- package/dist/crdt/restore.d.ts +4 -3
- package/dist/crdt/restore.js +27 -34
- package/dist/crdt/schema.d.ts +30 -21
- package/dist/crdt/schema.js +39 -23
- package/dist/crdt/storage.d.ts +1 -1
- package/dist/crdt/storage.js +1 -1
- package/dist/crdt/structs.d.ts +17 -15
- package/dist/crdt/structs.js +10 -22
- package/dist/crdt/text/index/cache.js +4 -0
- package/dist/crdt/text/index/claims.js +13 -23
- package/dist/crdt/text/index/fold.d.ts +2 -3
- package/dist/crdt/text/index/fold.js +194 -44
- package/dist/crdt/text/index/layout.d.ts +2 -4
- package/dist/crdt/text/index/layout.js +14 -30
- package/dist/crdt/text/index/placement.d.ts +26 -18
- package/dist/crdt/text/index/placement.js +420 -157
- package/dist/crdt/text/index/records.d.ts +3 -3
- package/dist/crdt/text/index/records.js +24 -31
- package/dist/crdt/text/index/shared.d.ts +11 -3
- package/dist/crdt/text/index/shared.js +29 -17
- package/dist/crdt/text/index/state.d.ts +21 -17
- package/dist/crdt/text/index/state.js +15 -17
- package/dist/crdt/text/index/streams.d.ts +10 -5
- package/dist/crdt/text/index/streams.js +78 -27
- package/dist/crdt/text/items.d.ts +10 -3
- package/dist/crdt/text/items.js +7 -0
- package/dist/crdt/text/model.d.ts +87 -62
- package/dist/crdt/text/model.js +91 -169
- package/dist/crdt/text/ranges.d.ts +1 -1
- package/dist/crdt/text/ranges.js +3 -3
- package/dist/crdt/text/rows.d.ts +13 -7
- package/dist/crdt/text/rows.js +24 -7
- package/dist/crdt/text/runs.d.ts +51 -42
- package/dist/crdt/text/runs.js +24 -7
- package/dist/crdt/text/streams.d.ts +26 -13
- package/dist/crdt/text/streams.js +41 -14
- package/dist/crdt/vendor/yjs/UPSTREAM.md +651 -21
- package/dist/crdt/vendor/yjs/dts/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +7 -0
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +197 -10
- package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +6 -3
- package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +5 -18
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +15 -1
- package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +14 -6
- package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +33 -6
- package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +1 -65
- package/dist/crdt/vendor/yjs/dts/utils/marks.d.ts +6 -1
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +54 -7
- package/dist/crdt/vendor/yjs/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +10 -0
- package/dist/crdt/vendor/yjs/src/structs/Item.js +649 -51
- package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +18 -9
- package/dist/crdt/vendor/yjs/src/utils/Doc.js +5 -3
- package/dist/crdt/vendor/yjs/src/utils/StructStore.js +5 -0
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +36 -13
- package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +88 -18
- package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +119 -32
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +13 -1
- package/dist/crdt/vendor/yjs/src/utils/ids.js +7 -7
- package/dist/crdt/vendor/yjs/src/utils/marks.js +193 -8
- package/dist/crdt/vendor/yjs/src/utils/redo.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/updates.js +3 -3
- package/dist/crdt/vendor/yjs/src/ynode.js +199 -12
- package/dist/edytor.svelte.d.ts +1 -1
- package/dist/edytor.svelte.js +103 -75
- package/dist/events/beforeInputCommands.d.ts +2 -2
- package/dist/events/beforeInputCommands.js +2 -2
- 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/events/onPageHide.d.ts +3 -0
- package/dist/events/onPageHide.js +16 -0
- package/dist/export/forms.d.ts +50 -50
- 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/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 +28 -3
- 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 +11 -37
- 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 +130 -83
- package/dist/surface/pin.svelte.d.ts +9 -9
- package/dist/surface/pin.svelte.js +15 -22
- package/dist/surface/projector.svelte.d.ts +15 -3
- package/dist/surface/projector.svelte.js +67 -22
- package/dist/text/text.svelte.js +14 -19
- package/dist/themes/notion.css +29 -0
- package/package.json +4 -2
- package/dist/crdt/placement/rank.d.ts +0 -87
- package/dist/crdt/placement/rank.js +0 -332
- package/dist/crdt/placement/source.d.ts +0 -43
- package/dist/crdt/placement/source.js +0 -66
- package/dist/crdt/text/delete-index.d.ts +0 -129
- package/dist/crdt/text/delete-index.js +0 -365
- package/dist/crdt/text/deletes.d.ts +0 -76
- package/dist/crdt/text/deletes.js +0 -362
- package/dist/crdt/text/index/anchored.d.ts +0 -17
- package/dist/crdt/text/index/anchored.js +0 -197
|
@@ -1,38 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Where a block displays: its display slot (read-time promotion out of a
|
|
3
3
|
* deleted, childless or passing parent, the line and layout rules), the
|
|
4
|
-
* children index and document order built from it,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* children index and document order built from it, liveness, and the
|
|
5
|
+
* inverse of the claim owners. Pure over replicated state and the
|
|
6
|
+
* ownership the caller passes. The order of a text's pieces is the slots'
|
|
7
|
+
* (`order.split.text`: a split-born slot's key, fork patch YP22).
|
|
7
8
|
*/
|
|
8
9
|
import { type Owner } from '../text/model.js';
|
|
9
|
-
import type { BlockId,
|
|
10
|
-
/**
|
|
11
|
-
* Split pieces in text order (`order.split.text`): the blocks whose streams lie in one
|
|
12
|
-
* backing text and that still stand where they were made (their winning
|
|
13
|
-
* placement is their first candidate, `1.<client>`: no move, outdent or
|
|
14
|
-
* lift since) under one parent show in their streams' order in that text —
|
|
15
|
-
* the order of the boundaries that delimit them, the same on every
|
|
16
|
-
* replica — at the ranks they hold between them: the i-th of them in the
|
|
17
|
-
* text takes the i-th smallest of their ranks. Ranks written at a split
|
|
18
|
-
* (`sourceRank`) are a guess made on one replica's text; the boundaries are
|
|
19
|
-
* the replicated fact, so two peers splitting one block at once keep the
|
|
20
|
-
* text's order whatever each saw (an unseen edit after one's own split
|
|
21
|
-
* point included). A block moved since stands where it was moved.
|
|
22
|
-
*
|
|
23
|
-
* `inText(home)`: the blocks of `home`'s text, in text order (segment 0's
|
|
24
|
-
* first). Memoized per (text, parent) until `forget(home)`.
|
|
25
|
-
*/
|
|
26
|
-
export declare const textRanker: (blocks: ReadonlyMap<BlockId, BlockRec>, placements: ReadonlyMap<BlockId, ResolvedPlacement>, homeOf: (b: BlockId) => BlockId | undefined, inText: (home: BlockId) => readonly BlockId[]) => {
|
|
27
|
-
rank: (id: BlockId, parent: BlockId | null, rank: string) => string;
|
|
28
|
-
/**
|
|
29
|
-
* Decide `home`'s text again (its segments or a member's placement
|
|
30
|
-
* changed); the blocks whose text-order rank changed.
|
|
31
|
-
*/
|
|
32
|
-
regroup: (home: BlockId) => Set<BlockId>;
|
|
33
|
-
/** Drop what was decided for `home`'s text (every one, without it). */
|
|
34
|
-
forget: (home?: BlockId) => void;
|
|
35
|
-
};
|
|
10
|
+
import type { BlockId, ChildSlot, DisplayOwnership, DocOrder, ModelView, ResolvedPlacement } from './model.js';
|
|
36
11
|
/**
|
|
37
12
|
* THE liveness answer: `id` carries no live delete mark, owns
|
|
38
13
|
* itself (`own.hidden` covers both: a delete-marked or unknown block owns
|
|
@@ -93,7 +68,7 @@ export declare const displayParentOf: (own: DisplayOwnership, pl: ResolvedPlacem
|
|
|
93
68
|
* promoted one ({@link displaySlotOf}).
|
|
94
69
|
*/
|
|
95
70
|
export declare const childrenIndex: (placements: Map<BlockId, ResolvedPlacement>, own: DisplayOwnership) => Map<BlockId | null, ChildSlot[]>;
|
|
96
|
-
/** The order of a children list: by rank, ties by id. */
|
|
71
|
+
/** The order of a children list: by rank, ties by id ({@link compareIds}). */
|
|
97
72
|
export declare const bySlot: (a: {
|
|
98
73
|
id: BlockId;
|
|
99
74
|
rank: string;
|
|
@@ -1,144 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Where a block displays: its display slot (read-time promotion out of a
|
|
3
3
|
* deleted, childless or passing parent, the line and layout rules), the
|
|
4
|
-
* children index and document order built from it,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* children index and document order built from it, liveness, and the
|
|
5
|
+
* inverse of the claim owners. Pure over replicated state and the
|
|
6
|
+
* ownership the caller passes. The order of a text's pieces is the slots'
|
|
7
|
+
* (`order.split.text`: a split-born slot's key, fork patch YP22).
|
|
7
8
|
*/
|
|
8
9
|
import { DEAD } from '../text/model.js';
|
|
9
|
-
import { promotedRank } from './
|
|
10
|
-
/**
|
|
11
|
-
* Split pieces in text order (`order.split.text`): the blocks whose streams lie in one
|
|
12
|
-
* backing text and that still stand where they were made (their winning
|
|
13
|
-
* placement is their first candidate, `1.<client>`: no move, outdent or
|
|
14
|
-
* lift since) under one parent show in their streams' order in that text —
|
|
15
|
-
* the order of the boundaries that delimit them, the same on every
|
|
16
|
-
* replica — at the ranks they hold between them: the i-th of them in the
|
|
17
|
-
* text takes the i-th smallest of their ranks. Ranks written at a split
|
|
18
|
-
* (`sourceRank`) are a guess made on one replica's text; the boundaries are
|
|
19
|
-
* the replicated fact, so two peers splitting one block at once keep the
|
|
20
|
-
* text's order whatever each saw (an unseen edit after one's own split
|
|
21
|
-
* point included). A block moved since stands where it was moved.
|
|
22
|
-
*
|
|
23
|
-
* `inText(home)`: the blocks of `home`'s text, in text order (segment 0's
|
|
24
|
-
* first). Memoized per (text, parent) until `forget(home)`.
|
|
25
|
-
*/
|
|
26
|
-
export const textRanker = (blocks, placements, homeOf, inText) => {
|
|
27
|
-
const memo = new Map();
|
|
28
|
-
const keysOf = new Map();
|
|
29
|
-
/** `b` stands where it was made: its placement is its first candidate's. */
|
|
30
|
-
const unmoved = (b) => {
|
|
31
|
-
const c = blocks.get(b)?.cands[0];
|
|
32
|
-
const pl = placements.get(b);
|
|
33
|
-
if (c === undefined || pl === undefined || c.seq !== 1 || c.r !== pl.rank)
|
|
34
|
-
return false;
|
|
35
|
-
return pl.parent === (c.p !== null && !blocks.has(c.p) ? null : c.p);
|
|
36
|
-
};
|
|
37
|
-
const group = (home, parent) => {
|
|
38
|
-
const members = [];
|
|
39
|
-
for (const b of inText(home))
|
|
40
|
-
if (placements.get(b)?.parent === parent && unmoved(b))
|
|
41
|
-
members.push(b);
|
|
42
|
-
const out = new Map();
|
|
43
|
-
if (members.length < 2)
|
|
44
|
-
return out;
|
|
45
|
-
const rankOf = (b) => placements.get(b).rank;
|
|
46
|
-
// One client's blocks keep its own order (it ranked them knowing each
|
|
47
|
-
// other); the text decides between different clients' (concurrent
|
|
48
|
-
// splits). Each client's members, sorted by rank, fill that client's
|
|
49
|
-
// places in the text order.
|
|
50
|
-
const byClient = new Map();
|
|
51
|
-
for (const b of members) {
|
|
52
|
-
const c = blocks.get(b).cands[0].client;
|
|
53
|
-
const list = byClient.get(c);
|
|
54
|
-
if (list === undefined)
|
|
55
|
-
byClient.set(c, [b]);
|
|
56
|
-
else
|
|
57
|
-
list.push(b);
|
|
58
|
-
}
|
|
59
|
-
if (byClient.size < 2)
|
|
60
|
-
return out;
|
|
61
|
-
for (const list of byClient.values())
|
|
62
|
-
list.sort((x, y) => bySlot({ id: x, rank: rankOf(x) }, { id: y, rank: rankOf(y) }));
|
|
63
|
-
const next = new Map();
|
|
64
|
-
const order = members.map((b) => {
|
|
65
|
-
const c = blocks.get(b).cands[0].client;
|
|
66
|
-
const i = next.get(c) ?? 0;
|
|
67
|
-
next.set(c, i + 1);
|
|
68
|
-
return byClient.get(c)[i];
|
|
69
|
-
});
|
|
70
|
-
const ranks = members.map(rankOf).sort();
|
|
71
|
-
order.forEach((b, i) => out.set(b, ranks[i]));
|
|
72
|
-
return out;
|
|
73
|
-
};
|
|
74
|
-
return {
|
|
75
|
-
rank: (id, parent, rank) => {
|
|
76
|
-
const home = homeOf(id);
|
|
77
|
-
// A text no other block shares (most blocks' own): nothing to order.
|
|
78
|
-
if (home === undefined || inText(home).length < 2)
|
|
79
|
-
return rank;
|
|
80
|
-
const key = `${home}\u0000${parent}`;
|
|
81
|
-
let ranks = memo.get(key);
|
|
82
|
-
if (ranks === undefined) {
|
|
83
|
-
memo.set(key, (ranks = group(home, parent)));
|
|
84
|
-
let keys = keysOf.get(home);
|
|
85
|
-
if (keys === undefined)
|
|
86
|
-
keysOf.set(home, (keys = new Set()));
|
|
87
|
-
keys.add(key);
|
|
88
|
-
}
|
|
89
|
-
return ranks.get(id) ?? rank;
|
|
90
|
-
},
|
|
91
|
-
/**
|
|
92
|
-
* Decide `home`'s text again (its segments or a member's placement
|
|
93
|
-
* changed); the blocks whose text-order rank changed.
|
|
94
|
-
*/
|
|
95
|
-
regroup: (home) => {
|
|
96
|
-
const before = new Map();
|
|
97
|
-
for (const key of keysOf.get(home) ?? [])
|
|
98
|
-
for (const [b, r] of memo.get(key) ?? [])
|
|
99
|
-
before.set(b, r);
|
|
100
|
-
for (const key of keysOf.get(home) ?? [])
|
|
101
|
-
memo.delete(key);
|
|
102
|
-
const keys = new Set();
|
|
103
|
-
keysOf.set(home, keys);
|
|
104
|
-
const changed = new Set();
|
|
105
|
-
const parents = new Set();
|
|
106
|
-
const row = inText(home);
|
|
107
|
-
if (row.length >= 2)
|
|
108
|
-
for (const b of row) {
|
|
109
|
-
const pl = placements.get(b);
|
|
110
|
-
if (pl !== undefined)
|
|
111
|
-
parents.add(pl.parent);
|
|
112
|
-
}
|
|
113
|
-
for (const parent of parents) {
|
|
114
|
-
const key = `${home}\u0000${parent}`;
|
|
115
|
-
const ranks = group(home, parent);
|
|
116
|
-
memo.set(key, ranks);
|
|
117
|
-
keys.add(key);
|
|
118
|
-
for (const [b, r] of ranks)
|
|
119
|
-
if (before.get(b) !== r)
|
|
120
|
-
changed.add(b);
|
|
121
|
-
}
|
|
122
|
-
for (const [b, r] of before) {
|
|
123
|
-
const now = memo.get(`${home}\u0000${placements.get(b)?.parent}`)?.get(b);
|
|
124
|
-
if (now !== r)
|
|
125
|
-
changed.add(b);
|
|
126
|
-
}
|
|
127
|
-
return changed;
|
|
128
|
-
},
|
|
129
|
-
/** Drop what was decided for `home`'s text (every one, without it). */
|
|
130
|
-
forget: (home) => {
|
|
131
|
-
if (home === undefined) {
|
|
132
|
-
memo.clear();
|
|
133
|
-
keysOf.clear();
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
for (const key of keysOf.get(home) ?? [])
|
|
137
|
-
memo.delete(key);
|
|
138
|
-
keysOf.delete(home);
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
};
|
|
10
|
+
import { claimedRank, compareIds, promotedRank } from './keys.js';
|
|
142
11
|
/**
|
|
143
12
|
* THE liveness answer: `id` carries no live delete mark, owns
|
|
144
13
|
* itself (`own.hidden` covers both: a delete-marked or unknown block owns
|
|
@@ -201,15 +70,13 @@ export const isLiveIn = (v, id) => {
|
|
|
201
70
|
*/
|
|
202
71
|
export const displaySlotOf = (own, placements, pl, id) => {
|
|
203
72
|
let { parent, rank } = pl;
|
|
204
|
-
// A
|
|
205
|
-
//
|
|
73
|
+
// A table's cell shown under its own placement's parent takes its column's rank
|
|
74
|
+
// (`table.columns`). Shown under its parent's claim owner (the parent merged away),
|
|
75
|
+
// it follows the owner's own children, by the claims down to its parent (`claimedRank`).
|
|
206
76
|
const direct = (owner) => {
|
|
207
77
|
if (owner !== pl.parent)
|
|
208
|
-
return rank;
|
|
209
|
-
|
|
210
|
-
if (ruled !== undefined)
|
|
211
|
-
return ruled;
|
|
212
|
-
return own.textRank === undefined ? rank : own.textRank(id, owner, rank);
|
|
78
|
+
return claimedRank(claimPath(own, owner, pl.parent), rank);
|
|
79
|
+
return (owner === null ? undefined : own.slotRank?.(owner, id, rank)) ?? rank;
|
|
213
80
|
};
|
|
214
81
|
let reset = null;
|
|
215
82
|
/** The first parent it is promoted out of (a deleted or childless one). */
|
|
@@ -240,8 +107,20 @@ export const displaySlotOf = (own, placements, pl, id) => {
|
|
|
240
107
|
// Promoted into a container: it shows as one of its items.
|
|
241
108
|
if (shows && reset === null && promoted !== null && own.container?.(owner) === true)
|
|
242
109
|
reset = promoted;
|
|
110
|
+
// Under its parent's claim owner — promoted there or not — it is keyed in the
|
|
111
|
+
// owner's claimed space: the keys are local to one index, so a key of
|
|
112
|
+
// `parent`'s sequence compares with the owner's own children's on no replica
|
|
113
|
+
// but this one.
|
|
243
114
|
if (shows)
|
|
244
|
-
return {
|
|
115
|
+
return {
|
|
116
|
+
parent: owner,
|
|
117
|
+
rank: owner !== parent
|
|
118
|
+
? claimedRank(claimPath(own, owner, parent), rank)
|
|
119
|
+
: hops === 0
|
|
120
|
+
? direct(owner)
|
|
121
|
+
: rank,
|
|
122
|
+
reset
|
|
123
|
+
};
|
|
245
124
|
promoted ??= out;
|
|
246
125
|
const up = placements.get(out);
|
|
247
126
|
if (up === undefined || hops > placements.size)
|
|
@@ -253,6 +132,22 @@ export const displaySlotOf = (own, placements, pl, id) => {
|
|
|
253
132
|
}
|
|
254
133
|
return { parent: null, rank: pl.parent === null ? direct(null) : rank, reset };
|
|
255
134
|
};
|
|
135
|
+
/**
|
|
136
|
+
* The claims from `owner` down to `parent` (a block it displays through
|
|
137
|
+
* merge claims), as each holder's claim index: the order the merged blocks'
|
|
138
|
+
* children take after the owner's own children.
|
|
139
|
+
*/
|
|
140
|
+
const claimPath = (own, owner, parent) => {
|
|
141
|
+
const path = [];
|
|
142
|
+
for (let cur = parent, hops = 0; cur !== null && cur !== owner && hops < 256; hops++) {
|
|
143
|
+
const holder = own.top(cur);
|
|
144
|
+
if (holder === undefined)
|
|
145
|
+
break;
|
|
146
|
+
path.unshift(Math.max(0, own.claimIndex(holder, cur)));
|
|
147
|
+
cur = holder;
|
|
148
|
+
}
|
|
149
|
+
return path;
|
|
150
|
+
};
|
|
256
151
|
/**
|
|
257
152
|
* The slot of `b` when it is a line — it displays (or, deleted, would
|
|
258
153
|
* display) directly under a `lines` island ({@link DisplayOwnership.lined}) — else
|
|
@@ -315,8 +210,8 @@ export const childrenIndex = (placements, own) => {
|
|
|
315
210
|
bucket.sort(bySlot);
|
|
316
211
|
return index;
|
|
317
212
|
};
|
|
318
|
-
/** The order of a children list: by rank, ties by id. */
|
|
319
|
-
export const bySlot = (a, b) => (a.rank === b.rank ? a.id
|
|
213
|
+
/** The order of a children list: by rank, ties by id ({@link compareIds}). */
|
|
214
|
+
export const bySlot = (a, b) => (a.rank === b.rank ? compareIds(a.id, b.id) : a.rank < b.rank ? -1 : 1);
|
|
320
215
|
export const documentOrder = (kids) => {
|
|
321
216
|
const ids = [];
|
|
322
217
|
const at = new Map();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Order keys — the in-memory keys the index sorts a parent's children by.
|
|
3
|
+
*
|
|
4
|
+
* A block's place is its slot in its parent's sequence (fork patch YP22:
|
|
5
|
+
* the engine orders slots and move records); nothing about the order is
|
|
6
|
+
* stored. The index still needs a comparable key per child, so that
|
|
7
|
+
* `displaySlotOf`'s promotion, the layout rules, `positionInView`'s binary
|
|
8
|
+
* search and `anchors.seam` keep working over `(rank, id)`-sorted lists:
|
|
9
|
+
* each child gets a key between its sequence neighbours' when it is placed
|
|
10
|
+
* (`keyBetween`), or a dense one when a whole sequence is read
|
|
11
|
+
* (`denseKey`). Keys are plain strings compared with `<`; they are local to
|
|
12
|
+
* one index and never leave it (two replicas may hold different keys for
|
|
13
|
+
* one order).
|
|
14
|
+
*
|
|
15
|
+
* Three key spaces compose with them:
|
|
16
|
+
*
|
|
17
|
+
* - a promoted child's key is its slot's key, {@link PROMOTED} and its own
|
|
18
|
+
* ({@link promotedRank}): `PROMOTED` sorts below every key character, so
|
|
19
|
+
* the promoted children follow the slot and precede the next sibling;
|
|
20
|
+
* - a merged-away block's children show after the owner's own children,
|
|
21
|
+
* by the owner's claim order ({@link claimedRank}): {@link CLAIMED} sorts
|
|
22
|
+
* above every key character;
|
|
23
|
+
* - a table's cells show in column order ({@link cellKey}).
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* The one order of two ids on a tie (a children list, the seam, the root's
|
|
27
|
+
* tail): their code units, the order every replica computes the same.
|
|
28
|
+
*/
|
|
29
|
+
export declare const compareIds: (a: string, b: string) => number;
|
|
30
|
+
/** Sorts below every key character: the separator of a promoted child's key. */
|
|
31
|
+
export declare const PROMOTED = "!";
|
|
32
|
+
/**
|
|
33
|
+
* A key strictly between `a` and `b` (`undefined`: no bound). Both bounds
|
|
34
|
+
* are keys of this alphabet with `a < b`: place by place, a digit halfway
|
|
35
|
+
* between theirs when one fits, else `a`'s digit and one place deeper
|
|
36
|
+
* (classic fractional indexing). A key never ends in the lowest digit
|
|
37
|
+
* (`denseKey` writes none), so a key fits between any two.
|
|
38
|
+
*/
|
|
39
|
+
export declare const keyBetween: (a: string | undefined, b: string | undefined) => string;
|
|
40
|
+
/** The `i`-th of a whole sequence's dense keys, in order (none ends in the lowest digit). */
|
|
41
|
+
export declare const denseKey: (i: number) => string;
|
|
42
|
+
/**
|
|
43
|
+
* The key of a block promoted into the slot keyed `slot` (read-time
|
|
44
|
+
* promotion, `del.blocks.promote`): after the slot, before every later key of
|
|
45
|
+
* the slot's list, in the promoted children's own order.
|
|
46
|
+
*/
|
|
47
|
+
export declare const promotedRank: (slot: string, rank: string) => string;
|
|
48
|
+
/**
|
|
49
|
+
* The key of a child of a merged-away block shown under its owner: after the
|
|
50
|
+
* owner's own children, by the owner's claims (`path`: the claim index at
|
|
51
|
+
* each hop down to the child's parent), then the child's own key.
|
|
52
|
+
*/
|
|
53
|
+
export declare const claimedRank: (path: readonly number[], rank: string) => string;
|
|
54
|
+
/**
|
|
55
|
+
* The key a table's cell displays at (`table.columns`): its column's
|
|
56
|
+
* position, before every unlisted column (`unlistedCellKey`) and the cells
|
|
57
|
+
* of no listed column (`LAST_CELL`).
|
|
58
|
+
*/
|
|
59
|
+
export declare const cellKey: (at: number) => string;
|
|
60
|
+
/** A withdrawn cell's column the table no longer lists: after the listed ones, by `unlistedRank`. */
|
|
61
|
+
export declare const unlistedCellKey: (hash: number) => string;
|
|
62
|
+
/** A cell of no listed column: last (it does not display, `table.cell`). */
|
|
63
|
+
export declare const LAST_CELL = "2";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Order keys — the in-memory keys the index sorts a parent's children by.
|
|
3
|
+
*
|
|
4
|
+
* A block's place is its slot in its parent's sequence (fork patch YP22:
|
|
5
|
+
* the engine orders slots and move records); nothing about the order is
|
|
6
|
+
* stored. The index still needs a comparable key per child, so that
|
|
7
|
+
* `displaySlotOf`'s promotion, the layout rules, `positionInView`'s binary
|
|
8
|
+
* search and `anchors.seam` keep working over `(rank, id)`-sorted lists:
|
|
9
|
+
* each child gets a key between its sequence neighbours' when it is placed
|
|
10
|
+
* (`keyBetween`), or a dense one when a whole sequence is read
|
|
11
|
+
* (`denseKey`). Keys are plain strings compared with `<`; they are local to
|
|
12
|
+
* one index and never leave it (two replicas may hold different keys for
|
|
13
|
+
* one order).
|
|
14
|
+
*
|
|
15
|
+
* Three key spaces compose with them:
|
|
16
|
+
*
|
|
17
|
+
* - a promoted child's key is its slot's key, {@link PROMOTED} and its own
|
|
18
|
+
* ({@link promotedRank}): `PROMOTED` sorts below every key character, so
|
|
19
|
+
* the promoted children follow the slot and precede the next sibling;
|
|
20
|
+
* - a merged-away block's children show after the owner's own children,
|
|
21
|
+
* by the owner's claim order ({@link claimedRank}): {@link CLAIMED} sorts
|
|
22
|
+
* above every key character;
|
|
23
|
+
* - a table's cells show in column order ({@link cellKey}).
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* The one order of two ids on a tie (a children list, the seam, the root's
|
|
27
|
+
* tail): their code units, the order every replica computes the same.
|
|
28
|
+
*/
|
|
29
|
+
export const compareIds = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
30
|
+
/**
|
|
31
|
+
* Order-preserving alphabet: charCode order equals numeric order (64
|
|
32
|
+
* characters, all safe inside a JSON string).
|
|
33
|
+
*/
|
|
34
|
+
const ALPHABET = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
|
|
35
|
+
const BASE = ALPHABET.length;
|
|
36
|
+
/** Sorts below every key character: the separator of a promoted child's key. */
|
|
37
|
+
export const PROMOTED = '!';
|
|
38
|
+
/** Sorts above every key character: the prefix of a merged-away block's children. */
|
|
39
|
+
const CLAIMED = '~';
|
|
40
|
+
/** The index of a key character in the alphabet (`-1`: none). */
|
|
41
|
+
const digit = (s, i) => (i < s.length ? ALPHABET.indexOf(s[i]) : -1);
|
|
42
|
+
/**
|
|
43
|
+
* A key strictly between `a` and `b` (`undefined`: no bound). Both bounds
|
|
44
|
+
* are keys of this alphabet with `a < b`: place by place, a digit halfway
|
|
45
|
+
* between theirs when one fits, else `a`'s digit and one place deeper
|
|
46
|
+
* (classic fractional indexing). A key never ends in the lowest digit
|
|
47
|
+
* (`denseKey` writes none), so a key fits between any two.
|
|
48
|
+
*/
|
|
49
|
+
export const keyBetween = (a, b) => {
|
|
50
|
+
let out = '';
|
|
51
|
+
for (let i = 0;; i++) {
|
|
52
|
+
// Past a bound's end: below every digit (`a`), above every digit (`b`).
|
|
53
|
+
const da = a !== undefined && i < a.length ? digit(a, i) : 0;
|
|
54
|
+
const db = b === undefined ? BASE : i < b.length ? digit(b, i) : 0;
|
|
55
|
+
if (db - da > 1)
|
|
56
|
+
return out + ALPHABET[da + ((db - da) >> 1)];
|
|
57
|
+
out += ALPHABET[da];
|
|
58
|
+
// Below `b` already at this place: it bounds the deeper places no more.
|
|
59
|
+
if (db - da === 1)
|
|
60
|
+
b = undefined;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/** The `i`-th of a whole sequence's dense keys, in order (none ends in the lowest digit). */
|
|
64
|
+
export const denseKey = (i) => {
|
|
65
|
+
// Four places of 63 digits (the lowest left out): 15M positions of one length.
|
|
66
|
+
let out = '';
|
|
67
|
+
let x = i;
|
|
68
|
+
for (let k = 0; k < 4; k++) {
|
|
69
|
+
out = ALPHABET[1 + (x % (BASE - 1))] + out;
|
|
70
|
+
x = Math.floor(x / (BASE - 1));
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The key of a block promoted into the slot keyed `slot` (read-time
|
|
76
|
+
* promotion, `del.blocks.promote`): after the slot, before every later key of
|
|
77
|
+
* the slot's list, in the promoted children's own order.
|
|
78
|
+
*/
|
|
79
|
+
export const promotedRank = (slot, rank) => slot + PROMOTED + rank;
|
|
80
|
+
/**
|
|
81
|
+
* The key of a child of a merged-away block shown under its owner: after the
|
|
82
|
+
* owner's own children, by the owner's claims (`path`: the claim index at
|
|
83
|
+
* each hop down to the child's parent), then the child's own key.
|
|
84
|
+
*/
|
|
85
|
+
export const claimedRank = (path, rank) => path.map((i) => CLAIMED + denseKey(i)).join('') + PROMOTED + rank;
|
|
86
|
+
/**
|
|
87
|
+
* The key a table's cell displays at (`table.columns`): its column's
|
|
88
|
+
* position, before every unlisted column (`unlistedCellKey`) and the cells
|
|
89
|
+
* of no listed column (`LAST_CELL`).
|
|
90
|
+
*/
|
|
91
|
+
export const cellKey = (at) => '0' + denseKey(at);
|
|
92
|
+
/** A withdrawn cell's column the table no longer lists: after the listed ones, by `unlistedRank`. */
|
|
93
|
+
export const unlistedCellKey = (hash) => '1' + denseKey(hash % 2 ** 24);
|
|
94
|
+
/** A cell of no listed column: last (it does not display, `table.cell`). */
|
|
95
|
+
export const LAST_CELL = '2';
|