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.
Files changed (231) hide show
  1. package/README.md +2 -2
  2. package/dist/block/block.svelte.js +6 -21
  3. package/dist/block/inlineBlock.svelte.js +4 -6
  4. package/dist/clipboard/moveText.js +6 -8
  5. package/dist/cloudflare/DocumentRoom.d.ts +23 -12
  6. package/dist/cloudflare/DocumentRoom.js +10 -6
  7. package/dist/cloudflare/index.d.ts +1 -1
  8. package/dist/cloudflare/room/access.d.ts +8 -3
  9. package/dist/cloudflare/room/access.js +44 -20
  10. package/dist/cloudflare/room/admission.js +28 -5
  11. package/dist/cloudflare/room/comments.js +28 -1
  12. package/dist/cloudflare/room/context.d.ts +139 -129
  13. package/dist/cloudflare/room/context.js +11 -4
  14. package/dist/cloudflare/room/forged.d.ts +14 -0
  15. package/dist/cloudflare/room/forged.js +30 -2
  16. package/dist/cloudflare/room/frames.d.ts +4 -0
  17. package/dist/cloudflare/room/frames.js +5 -1
  18. package/dist/cloudflare/room/purge.d.ts +6 -3
  19. package/dist/cloudflare/room/purge.js +45 -19
  20. package/dist/cloudflare/room/replicas.d.ts +4 -2
  21. package/dist/cloudflare/room/replicas.js +8 -3
  22. package/dist/cloudflare/room/suggest.d.ts +7 -0
  23. package/dist/cloudflare/room/suggest.js +143 -0
  24. package/dist/cloudflare/room/updates.d.ts +3 -4
  25. package/dist/cloudflare/room/updates.js +6 -8
  26. package/dist/cloudflare/routeDocumentSocket.d.ts +10 -1
  27. package/dist/cloudflare/routeDocumentSocket.js +5 -3
  28. package/dist/components/Content.svelte +9 -1
  29. package/dist/crdt/anchors.js +3 -2
  30. package/dist/crdt/attribution/attribution.d.ts +34 -12
  31. package/dist/crdt/attribution/attribution.js +59 -21
  32. package/dist/crdt/attribution/block.d.ts +3 -3
  33. package/dist/crdt/attribution/block.js +7 -8
  34. package/dist/crdt/attribution/index.d.ts +1 -1
  35. package/dist/crdt/attribution/index.js +1 -1
  36. package/dist/crdt/data.d.ts +62 -31
  37. package/dist/crdt/data.js +211 -103
  38. package/dist/crdt/doc/capability.js +9 -13
  39. package/dist/crdt/doc/delete.d.ts +1 -1
  40. package/dist/crdt/doc/delete.js +13 -30
  41. package/dist/crdt/doc/funnel.d.ts +1 -1
  42. package/dist/crdt/doc/funnel.js +34 -26
  43. package/dist/crdt/doc/gate.d.ts +3 -3
  44. package/dist/crdt/doc/history.d.ts +31 -9
  45. package/dist/crdt/doc/history.js +204 -73
  46. package/dist/crdt/doc/layout.js +16 -27
  47. package/dist/crdt/doc/meta.js +17 -23
  48. package/dist/crdt/doc/moves.d.ts +1 -1
  49. package/dist/crdt/doc/moves.js +52 -32
  50. package/dist/crdt/doc/reads.d.ts +2 -2
  51. package/dist/crdt/doc/reads.js +20 -30
  52. package/dist/crdt/doc/seed.js +2 -2
  53. package/dist/crdt/doc/split-merge.js +12 -15
  54. package/dist/crdt/doc/steps.d.ts +25 -13
  55. package/dist/crdt/doc/steps.js +55 -125
  56. package/dist/crdt/doc/suggest.d.ts +167 -0
  57. package/dist/crdt/doc/suggest.js +579 -0
  58. package/dist/crdt/doc/types.d.ts +21 -9
  59. package/dist/crdt/document.d.ts +26 -6
  60. package/dist/crdt/document.js +40 -15
  61. package/dist/crdt/edytor-doc.d.ts +410 -390
  62. package/dist/crdt/edytor-doc.js +143 -95
  63. package/dist/crdt/engine-api.d.ts +39 -1
  64. package/dist/crdt/engine.d.ts +2 -2
  65. package/dist/crdt/engine.js +4 -5
  66. package/dist/crdt/flow.d.ts +2 -2
  67. package/dist/crdt/flow.js +29 -37
  68. package/dist/crdt/index.d.ts +134 -127
  69. package/dist/crdt/index.js +4 -1
  70. package/dist/crdt/operations.d.ts +12 -3
  71. package/dist/crdt/parts.d.ts +43 -0
  72. package/dist/crdt/parts.js +44 -0
  73. package/dist/crdt/placement/display.d.ts +6 -31
  74. package/dist/crdt/placement/display.js +41 -146
  75. package/dist/crdt/placement/keys.d.ts +63 -0
  76. package/dist/crdt/placement/keys.js +95 -0
  77. package/dist/crdt/placement/model.d.ts +119 -118
  78. package/dist/crdt/placement/model.js +242 -142
  79. package/dist/crdt/placement/resolve.d.ts +123 -35
  80. package/dist/crdt/placement/resolve.js +188 -153
  81. package/dist/crdt/placement/slots.d.ts +134 -0
  82. package/dist/crdt/placement/slots.js +152 -0
  83. package/dist/crdt/protocol.d.ts +1 -1
  84. package/dist/crdt/protocol.js +1 -1
  85. package/dist/crdt/protocols/auth.d.ts +11 -1
  86. package/dist/crdt/protocols/auth.js +17 -1
  87. package/dist/crdt/protocols/comments.d.ts +16 -1
  88. package/dist/crdt/protocols/comments.js +9 -1
  89. package/dist/crdt/providers/index.d.ts +6 -4
  90. package/dist/crdt/providers/index.js +3 -1
  91. package/dist/crdt/providers/room.d.ts +16 -2
  92. package/dist/crdt/providers/room.js +64 -17
  93. package/dist/crdt/providers/websocket.d.ts +6 -4
  94. package/dist/crdt/providers/websocket.js +14 -7
  95. package/dist/crdt/purge.d.ts +24 -9
  96. package/dist/crdt/purge.js +266 -126
  97. package/dist/crdt/restore.d.ts +4 -3
  98. package/dist/crdt/restore.js +27 -34
  99. package/dist/crdt/schema.d.ts +30 -21
  100. package/dist/crdt/schema.js +39 -23
  101. package/dist/crdt/storage.d.ts +1 -1
  102. package/dist/crdt/storage.js +1 -1
  103. package/dist/crdt/structs.d.ts +17 -15
  104. package/dist/crdt/structs.js +10 -22
  105. package/dist/crdt/text/index/cache.js +4 -0
  106. package/dist/crdt/text/index/claims.js +13 -23
  107. package/dist/crdt/text/index/fold.d.ts +2 -3
  108. package/dist/crdt/text/index/fold.js +194 -44
  109. package/dist/crdt/text/index/layout.d.ts +2 -4
  110. package/dist/crdt/text/index/layout.js +14 -30
  111. package/dist/crdt/text/index/placement.d.ts +26 -18
  112. package/dist/crdt/text/index/placement.js +420 -157
  113. package/dist/crdt/text/index/records.d.ts +3 -3
  114. package/dist/crdt/text/index/records.js +24 -31
  115. package/dist/crdt/text/index/shared.d.ts +11 -3
  116. package/dist/crdt/text/index/shared.js +29 -17
  117. package/dist/crdt/text/index/state.d.ts +21 -17
  118. package/dist/crdt/text/index/state.js +15 -17
  119. package/dist/crdt/text/index/streams.d.ts +10 -5
  120. package/dist/crdt/text/index/streams.js +78 -27
  121. package/dist/crdt/text/items.d.ts +10 -3
  122. package/dist/crdt/text/items.js +7 -0
  123. package/dist/crdt/text/model.d.ts +87 -62
  124. package/dist/crdt/text/model.js +91 -169
  125. package/dist/crdt/text/ranges.d.ts +1 -1
  126. package/dist/crdt/text/ranges.js +3 -3
  127. package/dist/crdt/text/rows.d.ts +13 -7
  128. package/dist/crdt/text/rows.js +24 -7
  129. package/dist/crdt/text/runs.d.ts +51 -42
  130. package/dist/crdt/text/runs.js +24 -7
  131. package/dist/crdt/text/streams.d.ts +26 -13
  132. package/dist/crdt/text/streams.js +41 -14
  133. package/dist/crdt/vendor/yjs/UPSTREAM.md +651 -21
  134. package/dist/crdt/vendor/yjs/dts/global.d.ts +2 -0
  135. package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
  136. package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +7 -0
  137. package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +197 -10
  138. package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +6 -3
  139. package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +5 -18
  140. package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +15 -1
  141. package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +14 -6
  142. package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +33 -6
  143. package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +1 -65
  144. package/dist/crdt/vendor/yjs/dts/utils/marks.d.ts +6 -1
  145. package/dist/crdt/vendor/yjs/dts/ynode.d.ts +54 -7
  146. package/dist/crdt/vendor/yjs/global.d.ts +2 -0
  147. package/dist/crdt/vendor/yjs/src/index.js +1 -1
  148. package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +10 -0
  149. package/dist/crdt/vendor/yjs/src/structs/Item.js +649 -51
  150. package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +18 -9
  151. package/dist/crdt/vendor/yjs/src/utils/Doc.js +5 -3
  152. package/dist/crdt/vendor/yjs/src/utils/StructStore.js +5 -0
  153. package/dist/crdt/vendor/yjs/src/utils/Transaction.js +36 -13
  154. package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +88 -18
  155. package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +119 -32
  156. package/dist/crdt/vendor/yjs/src/utils/encoding.js +13 -1
  157. package/dist/crdt/vendor/yjs/src/utils/ids.js +7 -7
  158. package/dist/crdt/vendor/yjs/src/utils/marks.js +193 -8
  159. package/dist/crdt/vendor/yjs/src/utils/redo.js +1 -1
  160. package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +1 -1
  161. package/dist/crdt/vendor/yjs/src/utils/updates.js +3 -3
  162. package/dist/crdt/vendor/yjs/src/ynode.js +199 -12
  163. package/dist/edytor.svelte.d.ts +1 -1
  164. package/dist/edytor.svelte.js +103 -75
  165. package/dist/events/beforeInputCommands.d.ts +2 -2
  166. package/dist/events/beforeInputCommands.js +2 -2
  167. package/dist/events/nativeInteractiveControl.d.ts +11 -1
  168. package/dist/events/nativeInteractiveControl.js +41 -1
  169. package/dist/events/onBeforeInput.js +3 -3
  170. package/dist/events/onFocus.js +9 -11
  171. package/dist/events/onPageHide.d.ts +3 -0
  172. package/dist/events/onPageHide.js +16 -0
  173. package/dist/export/forms.d.ts +50 -50
  174. package/dist/index.d.ts +4 -2
  175. package/dist/index.js +1 -1
  176. package/dist/labels.d.ts +8 -0
  177. package/dist/labels.js +6 -1
  178. package/dist/plugins/comments/CommentsController.svelte.d.ts +5 -1
  179. package/dist/plugins/comments/CommentsController.svelte.js +14 -4
  180. package/dist/plugins/find/search.js +2 -2
  181. package/dist/plugins/index.d.ts +1 -0
  182. package/dist/plugins/index.js +1 -0
  183. package/dist/plugins/suggestions/SuggestionBars.svelte +40 -23
  184. package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +3 -1
  185. package/dist/plugins/suggestions/SuggestionRuns.svelte +77 -0
  186. package/dist/plugins/suggestions/SuggestionRuns.svelte.d.ts +9 -0
  187. package/dist/plugins/suggestions/shared.svelte.d.ts +58 -0
  188. package/dist/plugins/suggestions/shared.svelte.js +421 -0
  189. package/dist/plugins/suggestions/suggestionsPlugin.d.ts +15 -4
  190. package/dist/selection/domSelection.d.ts +2 -0
  191. package/dist/selection/domSelection.js +6 -2
  192. package/dist/selection/pointer.svelte.js +75 -48
  193. package/dist/selection/replaceSelection.js +2 -6
  194. package/dist/selection/selection.svelte.d.ts +3 -3
  195. package/dist/selection/selection.svelte.js +39 -32
  196. package/dist/selection/selection.utils.d.ts +14 -0
  197. package/dist/selection/selection.utils.js +28 -3
  198. package/dist/session/commands.js +21 -11
  199. package/dist/session/composition.svelte.d.ts +5 -3
  200. package/dist/session/composition.svelte.js +21 -17
  201. package/dist/session/handles.d.ts +4 -17
  202. package/dist/session/handles.js +11 -37
  203. package/dist/session/navigation.js +6 -9
  204. package/dist/session/selection.d.ts +11 -5
  205. package/dist/session/selection.js +14 -48
  206. package/dist/session/suggestions.svelte.d.ts +38 -9
  207. package/dist/session/suggestions.svelte.js +37 -18
  208. package/dist/session/virtual.d.ts +1 -1
  209. package/dist/surface/attributes.d.ts +5 -0
  210. package/dist/surface/attributes.js +2 -2
  211. package/dist/surface/cells.d.ts +2 -26
  212. package/dist/surface/cells.js +2 -33
  213. package/dist/surface/observer.svelte.d.ts +6 -1
  214. package/dist/surface/observer.svelte.js +130 -83
  215. package/dist/surface/pin.svelte.d.ts +9 -9
  216. package/dist/surface/pin.svelte.js +15 -22
  217. package/dist/surface/projector.svelte.d.ts +15 -3
  218. package/dist/surface/projector.svelte.js +67 -22
  219. package/dist/text/text.svelte.js +14 -19
  220. package/dist/themes/notion.css +29 -0
  221. package/package.json +4 -2
  222. package/dist/crdt/placement/rank.d.ts +0 -87
  223. package/dist/crdt/placement/rank.js +0 -332
  224. package/dist/crdt/placement/source.d.ts +0 -43
  225. package/dist/crdt/placement/source.js +0 -66
  226. package/dist/crdt/text/delete-index.d.ts +0 -129
  227. package/dist/crdt/text/delete-index.js +0 -365
  228. package/dist/crdt/text/deletes.d.ts +0 -76
  229. package/dist/crdt/text/deletes.js +0 -362
  230. package/dist/crdt/text/index/anchored.d.ts +0 -17
  231. 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, the text order of a
5
- * text's pieces (`textRanker`), liveness, and the inverse of the claim
6
- * owners. Pure over replicated state and the ownership the caller passes.
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, BlockRec, ChildSlot, DisplayOwnership, DocOrder, ModelView, ResolvedPlacement } from './model.js';
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, the text order of a
5
- * text's pieces (`textRanker`), liveness, and the inverse of the claim
6
- * owners. Pure over replicated state and the ownership the caller passes.
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 './source.js';
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 piece of a text shown under its own placement's parent takes its text-order rank;
205
- // a table's cell its column's (`table.columns`).
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
- const ruled = owner === null ? undefined : own.slotRank?.(owner, id, rank);
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 { parent: owner, rank: hops === 0 ? direct(owner) : rank, reset };
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.localeCompare(b.id) : a.rank < b.rank ? -1 : 1);
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';