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
@@ -13,15 +13,21 @@
13
13
  * - It ends at the next delimiting boundary of the same text, or at the text
14
14
  * end. A boundary whose nonce matches no record is inert: skipped by reads,
15
15
  * never a delimiter.
16
- * - `display(b)` = `stream(b)`, then `display(m)` for each merge claim `{m}`
17
- * on `b`'s `claims` list whose max-stamp live claimer is `b`. Owner
18
- * resolution over claims (`claimGraph`: max-stamp claim, cycles, claims held
19
- * by deleted blocks are inert) is unchanged.
16
+ * - A merge writes one CLAIM ITEM `{m}` (one countable unit, never
17
+ * displayed) at the end of the gap at the end of the holder's stream (fork
18
+ * patch YP21: among the items of one origin it sorts after content and
19
+ * boundaries, so YATA decides which piece of a concurrent split keeps it).
20
+ * A block's claims are the claim items of its stream, in text order.
21
+ * - `display(b)` = `stream(b)`, then `display(m)` for each claim `{m}` of `b`
22
+ * whose max-stamp live claimer is `b`. Owner resolution over claims
23
+ * (`claimGraph`: max-stamp claim, cycles, claims held by deleted blocks are
24
+ * inert) is unchanged.
20
25
  *
21
26
  * Every position therefore lies in exactly one stream: the block that displays
22
27
  * it is a pure function of replicated items and is never repaired. Typing at a
23
28
  * stream's start inserts after its boundary, at its end before the next one;
24
- * the per-stream delete never removes a boundary; every read skips them.
29
+ * the per-stream delete never removes a boundary or a claim; every read skips
30
+ * them.
25
31
  *
26
32
  * Anchors are `{b, a}`: `b` the home block of the backing text, `a` an
27
33
  * engine relative position (`i` the bound item, `a` the side: `< 0` left). A
@@ -36,9 +42,9 @@
36
42
  */
37
43
  import type { EngineApi, EngineDoc, EngineNode } from '../engine-api.js';
38
44
  import { type IdSetOf } from '../structs.js';
39
- export { isBoundary, nodeStart } from './items.js';
45
+ export { isBoundary, isClaimItem, isRowMark, nodeStart } from './items.js';
40
46
  export { canonKey, deepFreeze, inlineItemOf, protectItems, readRange } from './ranges.js';
41
- export { byId, delimiters, displayOf, locate, ownedLength, pieces, placeText, scanText } from './streams.js';
47
+ export { byId, claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, removedKeys, scanText } from './streams.js';
42
48
  export type BlockId = string;
43
49
  /** A serialized relative position inside a backing text (`i: null`: a text end). */
44
50
  export type Anchor = {
@@ -48,26 +54,15 @@ export type Anchor = {
48
54
  } | null;
49
55
  a: number;
50
56
  };
51
- /** An engine item id as a claim payload stores it. */
52
- export type ItemRef = {
53
- c: number;
54
- k: number;
55
- };
56
57
  /**
57
- * Merge-claim payload: "this block's display continues with block `m`'s".
58
- * `a` and `r` (since 0.1.0-next.26, `merge.claim.anchor`) anchor it to the
59
- * end of the holder's stream as the claim's writer saw it: `a` the last
60
- * unit of that stream (its opening boundary when empty; absent at the start
61
- * of an own text) and `r` the item right after it (the next stream's
62
- * boundary; `null` at the text's end). A split the writer did not see moves
63
- * the claim to the piece that ends the region between them.
58
+ * A claim item's payload: "the display of the block whose stream holds me
59
+ * continues with block `m`'s" (`merge.claim.anchor`: YATA places it, so a
60
+ * split its writer did not see leaves it in the piece that ends the
61
+ * holder's region).
64
62
  */
65
63
  export type MergeClaim = {
66
64
  m: BlockId;
67
- a?: ItemRef;
68
- r?: ItemRef | null;
69
65
  };
70
- export declare const isMergeClaim: (v: unknown) => v is MergeClaim;
71
66
  /** Deterministic claim stamp = engine item id (client-major order). */
72
67
  export type Stamp = {
73
68
  c: number;
@@ -75,19 +70,13 @@ export type Stamp = {
75
70
  };
76
71
  export declare const cmpStamp: (a: Stamp, b: Stamp) => number;
77
72
  /**
78
- * One live merge claim: `seqIndex` is its live index in the list that
79
- * stores it — its holder's, or `holder`'s when its anchor moved it to
80
- * another block (`merge.claim.anchor`); `-1` for an implicit claim, which
81
- * no list stores (`id.same.concurrent`). `a`/`r`: its anchor (see
82
- * {@link MergeClaim}).
73
+ * One live merge claim: its stamp is its claim item's id; an implicit
74
+ * claim, which no item stores (`id.same.concurrent`), stamps below every
75
+ * item (`stamp.c < 0`).
83
76
  */
84
77
  export type Claim = {
85
78
  m: BlockId;
86
79
  stamp: Stamp;
87
- seqIndex: number;
88
- a?: ItemRef;
89
- r?: ItemRef | null;
90
- holder?: BlockId;
91
80
  };
92
81
  /** Boundary-item payload in a backing text. */
93
82
  export type Boundary = {
@@ -111,8 +100,6 @@ export type SeqItem = {
111
100
  type?: EngineNode;
112
101
  };
113
102
  };
114
- /** The live merge claims of a `claims` list, with their stamps. */
115
- export declare const readClaims: (node: EngineNode | undefined) => Claim[];
116
103
  /** One emitted range-read element — the `ContentItem` shape. */
117
104
  export type RangeItem = {
118
105
  kind: 'text';
@@ -164,16 +151,10 @@ export type TextBlockRec = {
164
151
  n: unknown;
165
152
  /** The block's own backing text, when it has one. */
166
153
  content: EngineNode | undefined;
167
- /** The `claims` list node (write handle). */
168
- claimsNode: EngineNode | undefined;
169
- /**
170
- * Its effective merge claims (`merge.claim.anchor`): its list's claims
171
- * that stay with it, in list order, then those other holders' anchors
172
- * moved to it (each with its `holder`), by stamp.
173
- */
154
+ /** Its merge claims: its implicit ones, then the claim items of its stream, in text order. */
174
155
  claims: Claim[];
175
- /** Its list's live claims, in list order (absent: `claims` is the list). */
176
- listClaims?: Claim[];
156
+ /** Its implicit claims (`id.same.concurrent`), which no item stores. */
157
+ implicit?: Claim[];
177
158
  };
178
159
  /** The internal "no display owner" verdict — a symbol, never a block id. */
179
160
  export declare const DEAD: unique symbol;
@@ -191,12 +172,23 @@ export declare const claimGraph: (blocks: ReadonlyMap<BlockId, TextBlockRec>) =>
191
172
  };
192
173
  /** `owner(b)` for every block (see {@link claimGraph}). */
193
174
  export declare const computeOwners: (blocks: ReadonlyMap<BlockId, TextBlockRec>) => Map<BlockId, Owner>;
194
- /** A live boundary at live index `at` of its text; `key` is its item id. */
195
- export type Bound = Boundary & {
175
+ /**
176
+ * A unit a row tracks at live index `at` of its text (`key`: its item id): a
177
+ * live boundary, or a live claim item (`m`, with its stamp), which never
178
+ * delimits.
179
+ */
180
+ export type Bound = {
196
181
  at: number;
197
182
  key: string;
198
- };
199
- /** One scanned backing text: its live boundaries in order and its live length. */
183
+ } & ((Boundary & {
184
+ m?: undefined;
185
+ }) | {
186
+ m: BlockId;
187
+ stamp: Stamp;
188
+ s?: undefined;
189
+ n?: undefined;
190
+ });
191
+ /** One scanned backing text: its live boundaries and claim items in order, and its live length. */
200
192
  export type TextRow = {
201
193
  home: BlockId;
202
194
  text: EngineNode;
@@ -204,7 +196,7 @@ export type TextRow = {
204
196
  len: number;
205
197
  key: string;
206
198
  };
207
- /** One stream: `[start, end)` of `home`'s text, minus the inert boundaries at `inert`. */
199
+ /** One stream: `[start, end)` of `home`'s text, minus the inert boundaries and claim items at `inert`. */
208
200
  export type Stream = {
209
201
  block: BlockId;
210
202
  home: BlockId;
@@ -232,6 +224,8 @@ export type Ownership = {
232
224
  hidden: (b: BlockId) => boolean;
233
225
  /** The claimed block's max-stamp live claimer. */
234
226
  top: (m: BlockId) => BlockId | undefined;
227
+ /** The position of `m` among `holder`'s claims (`-1`: none): the order the claimed blocks' children show in. */
228
+ claimIndex: (holder: BlockId, m: BlockId) => number;
235
229
  streamOf: (b: BlockId) => Stream | undefined;
236
230
  /** The streams of `home`'s text, in text order. */
237
231
  streamsIn: (home: BlockId) => readonly Stream[];
@@ -239,8 +233,6 @@ export type Ownership = {
239
233
  streamAt: (home: BlockId, i: number) => Stream | undefined;
240
234
  /** `display(b)` as boundary-free pieces in reading order; `null` when hidden or dead. */
241
235
  display: (b: BlockId) => Seg[] | null;
242
- /** `b`'s effective claims (`merge.claim.anchor`), when the context computed them. */
243
- claimsOf?: (b: BlockId) => readonly Claim[];
244
236
  };
245
237
  /** Construct a detached v14 node, viewed through the structural interface. */
246
238
  export declare const newNode: (name: string) => EngineNode;
@@ -257,6 +249,11 @@ export declare const openRangeCursor: (text: EngineNode) => RangeCursor;
257
249
  export declare const itemsOfRange: (text: EngineNode, i0: number, i1: number) => RangeItem[];
258
250
  /** The items of `segs`, one cursor per backing text. */
259
251
  export declare const readSegs: (segs: readonly Seg[], stats?: RangeReadStats) => RangeItem[];
252
+ /**
253
+ * A from-scratch ownership context over `given` (every text scanned; the
254
+ * index's oracle): each block's claims are its implicit ones, then the claim
255
+ * items of its stream.
256
+ */
260
257
  export declare const computeOwnership: (doc: EngineDoc, given: ReadonlyMap<BlockId, TextBlockRec>) => Ownership;
261
258
  /** `b`'s display pieces (`[]` when hidden or streamless and claimless). */
262
259
  export declare const flatten: (b: BlockId, blocks: unknown, own: Ownership) => Seg[];
@@ -271,8 +268,25 @@ export declare const blockTextOf: (b: BlockId, blocks: unknown, own: Ownership)
271
268
  * `marks` (an operation for each mark its gap gave it otherwise).
272
269
  */
273
270
  export declare const insertIntoText: (doc: EngineDoc, blocks: unknown, own: Ownership, b: BlockId, offset: number, payload: string | EngineNode, marks?: Record<string, unknown>) => void;
274
- /** The per-stream delete: each range lies inside one stream's pieces, so no boundary is ever removed. */
271
+ /**
272
+ * The per-stream delete: each range lies inside one stream's pieces, so no
273
+ * boundary is ever removed. The text is held by this writer's record (fork
274
+ * patch YP20, root `textdel`, in the history's scope): an undo deletes the
275
+ * record and the text shows again where it was, unless another writer's
276
+ * record holds it. Text the open undo step inserted is removed instead, so
277
+ * that step's undo still changes nothing.
278
+ */
275
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
+ }>;
276
290
  export declare const formatRangeIn: (doc: EngineDoc, blocks: unknown, own: Ownership, b: BlockId, offset: number, length: number, formats: Record<string, unknown>) => void;
277
291
  /**
278
292
  * Delete the content of streams `streams` (the room's purge of a
@@ -290,19 +304,25 @@ export declare const findAtom: (own: Ownership, b: BlockId, inlineId: string) =>
290
304
  } | null;
291
305
  /**
292
306
  * Split `b`'s display at `offset` for the new block `newId` (incarnation
293
- * `n`): one boundary through fork patch YP7 at the end of the gap, and the claims that
294
- * follow the split point — every claim of the stream's own block, then each
295
- * holder's claims after the one that led down — returned for re-insertion
296
- * on the new block and deleted from their holders. No text is copied.
307
+ * `n`): one boundary through fork patch YP7 at the end of the gap. The
308
+ * claims that follow the split point — every claim of the stream's own
309
+ * block, then each holder's claims after the one that led down — are
310
+ * written again, in that order, at the end of the new block's stream, and
311
+ * their items deleted (an implicit claim is written on the new block, whose
312
+ * claim outranks it). No text is copied.
297
313
  */
298
- export declare const splitAt: (blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Ownership, b: BlockId, offset: number, newId: BlockId, n: number) => MergeClaim[];
314
+ export declare const splitAt: (doc: EngineDoc, blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Ownership, b: BlockId, offset: number, newId: BlockId, n: number) => void;
299
315
  /**
300
- * Append a merge claim `{m: from}` to `into`'s claims list, anchored to
301
- * the end of `into`'s stream (`merge.claim.anchor`): its last unit (its
302
- * opening boundary when empty; none at an own text's start) and the item
303
- * after it.
316
+ * Merge `from` into `into`: one claim item `{m: from}` at the end of the gap
317
+ * at the end of `into`'s stream (fork patch YP7; YP21 sorts it after the
318
+ * content and boundaries a concurrent writer puts at its origin, so a split
319
+ * the merge's writer did not see leaves it in the piece that ends `into`'s
320
+ * region: `merge.claim.anchor`). `into` has a stream: the caller gives a
321
+ * streamless block its own text first.
304
322
  */
305
- export declare const claimInto: (blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Pick<Ownership, "streamOf">, from: BlockId, into: BlockId) => void;
323
+ export declare const claimInto: (own: Pick<Ownership, "streamOf">, from: BlockId, into: BlockId) => void;
324
+ /** Delete the items of `claims` (an implicit claim has none). */
325
+ export declare const deleteClaims: (doc: EngineDoc, claims: readonly Claim[]) => void;
306
326
  /**
307
327
  * Give streamless block `rec` its own text and re-mint its nonce, so a late
308
328
  * copy of its old boundary is inert. Both writes carry a writer id
@@ -340,8 +360,8 @@ export declare const bindText: (_Y: EngineApi) => {
340
360
  at: number;
341
361
  node: EngineNode;
342
362
  } | null;
343
- splitAt: (blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Ownership, b: BlockId, offset: number, newId: BlockId, n: number) => MergeClaim[];
344
- claimInto: (blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Pick<Ownership, "streamOf">, from: BlockId, into: BlockId) => void;
363
+ splitAt: (doc: EngineDoc, blocks: ReadonlyMap<BlockId, TextBlockRec>, own: Ownership, b: BlockId, offset: number, newId: BlockId, n: number) => void;
364
+ claimInto: (own: Pick<Ownership, "streamOf">, from: BlockId, into: BlockId) => void;
345
365
  ownText: (doc: EngineDoc, rec: TextBlockRec) => {
346
366
  from: unknown;
347
367
  to: number;
@@ -353,4 +373,9 @@ export declare const bindText: (_Y: EngineApi) => {
353
373
  * typing and keeps the text every replica shares.
354
374
  */
355
375
  export declare const ownTextIds: WeakMap<EngineDoc, IdSetOf>;
376
+ /**
377
+ * Each history's open step on a doc (`doc/history.ts` registers them): what
378
+ * the step still capturing inserted, `null` when none is open.
379
+ */
380
+ export declare const openSteps: WeakMap<EngineDoc, Set<() => IdSetOf | null>>;
356
381
  export type TextEngine = ReturnType<typeof bindText>;
@@ -1,45 +1,16 @@
1
1
  import { Y } from '../engine.js';
2
2
  import { asYDoc, asYNode, attrItems, engineOps, newNode as makeNode, rangeCursorOf, storeOf } from '../structs.js';
3
- import { CONTENT, CONTENT_NODE, ID, NONCE, SCHEMA } from '../schema.js';
3
+ import { CONTENT, CONTENT_NODE, ID, NONCE, SCHEMA, TEXT_DELETES_ROOT } from '../schema.js';
4
4
  import { DEV } from 'esm-env';
5
5
  import { hash32, hash53 } from '../rand.js';
6
- import { bindDeletes } from './deletes.js';
7
6
  import { fitMarks, writeMarks } from './marks.js';
8
7
  import { nodeStart } from './items.js';
9
8
  import { readRange } from './ranges.js';
10
- import { delimiters, displayOf, locate, ownedLength, pieces, placeText, rangesOf, scanText } from './streams.js';
11
- export { isBoundary, nodeStart } from './items.js';
9
+ import { claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, rangesOf, removedKeys, scanText } from './streams.js';
10
+ export { isBoundary, isClaimItem, isRowMark, nodeStart } from './items.js';
12
11
  export { canonKey, deepFreeze, inlineItemOf, protectItems, readRange } from './ranges.js';
13
- export { byId, delimiters, displayOf, locate, ownedLength, pieces, placeText, scanText } from './streams.js';
14
- const isItemRef = (v) => v != null &&
15
- typeof v === 'object' &&
16
- Number.isInteger(v.c) &&
17
- Number.isInteger(v.k);
18
- export const isMergeClaim = (v) => v != null && typeof v === 'object' && typeof v.m === 'string';
12
+ export { byId, claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, removedKeys, scanText } from './streams.js';
19
13
  export const cmpStamp = (a, b) => a.c - b.c || a.k - b.k;
20
- /** The live merge claims of a `claims` list, with their stamps. */
21
- export const readClaims = (node) => {
22
- const out = [];
23
- let seqIndex = 0;
24
- for (let it = node ? nodeStart(node) : null; it !== null; it = it.right) {
25
- if (it.deleted || it.countable === false)
26
- continue;
27
- const arr = it.content.getContent();
28
- for (let j = 0; j < it.length; j++) {
29
- const p = arr[j];
30
- if (isMergeClaim(p)) {
31
- const claim = { m: p.m, stamp: { c: it.id.client, k: it.id.clock + j }, seqIndex };
32
- if (isItemRef(p.a)) {
33
- claim.a = p.a;
34
- claim.r = isItemRef(p.r) ? p.r : null;
35
- }
36
- out.push(claim);
37
- }
38
- seqIndex++;
39
- }
40
- }
41
- return out;
42
- };
43
14
  /** The internal "no display owner" verdict — a symbol, never a block id. */
44
15
  export const DEAD = Symbol('edytor.crdt.dead');
45
16
  /**
@@ -106,7 +77,6 @@ export const claimGraph = (blocks) => {
106
77
  };
107
78
  /** `owner(b)` for every block (see {@link claimGraph}). */
108
79
  export const computeOwners = (blocks) => claimGraph(blocks).owners;
109
- const D = bindDeletes(Y);
110
80
  const ops = engineOps(Y);
111
81
  /** Construct a detached v14 node, viewed through the structural interface. */
112
82
  export const newNode = (name) => makeNode(Y, name);
@@ -144,116 +114,44 @@ export const readSegs = (segs, stats) => {
144
114
  }
145
115
  return out;
146
116
  };
147
- /** A from-scratch ownership context over `blocks` (every text scanned). */
148
117
  /**
149
- * The effective claims of every block, from scratch (`merge.claim.anchor`;
150
- * the index keeps them incrementally, `text/runs.ts`): an anchored claim
151
- * goes to the block of the segment just before its `r` (the text's last
152
- * segment when `r` is null) in the row of its holder's stream, when that
153
- * segment is the holder's or a later one.
118
+ * A from-scratch ownership context over `given` (every text scanned; the
119
+ * index's oracle): each block's claims are its implicit ones, then the claim
120
+ * items of its stream.
154
121
  */
155
- const effectiveClaims = (doc, blocks, rows, delim, streams) => {
156
- /** Live index of unit `ref` (assoc 0) in `text`, or `null` when it is not `text`'s. */
157
- const indexIn = (text, ref) => {
158
- if (!text._item?.id)
159
- return null;
160
- const abs = Y.indexOfId(asYDoc(doc), Y.createID(ref.c, ref.k));
161
- return abs === null || abs.type !== text ? null : abs.index;
162
- };
163
- const targetOf = (holder, c) => {
164
- if (c.a === undefined)
165
- return holder;
166
- const s = streams.get(holder);
167
- const row = s && rows.get(s.text);
168
- if (row === undefined || indexIn(row.text, c.a) === null)
169
- return holder;
170
- const cuts = [];
171
- row.bounds.forEach((b, j) => {
172
- if (delim.get(b.s) === b.key)
173
- cuts.push(j);
174
- });
175
- const head = delim.has(row.home) ? null : row.home;
176
- // The gap before `r`: a live boundary's own index, else the boundaries before it.
177
- let gap = row.bounds.length;
178
- if (c.r != null) {
179
- const key = `${c.r.c}:${c.r.k}`;
180
- const at = row.bounds.findIndex((b) => b.key === key);
181
- if (at >= 0)
182
- gap = at;
183
- else {
184
- const p = indexIn(row.text, c.r);
185
- if (p === null)
186
- return holder;
187
- gap = row.bounds.filter((b) => b.at < p).length;
188
- }
189
- }
190
- const segment = (g) => cuts.filter((j) => j < g).length;
191
- const k = segment(gap);
192
- // The holder's own segment: the one its stream starts in.
193
- const k0 = segment(row.bounds.filter((b) => b.at < s.start).length);
194
- if (k < k0)
195
- return holder;
196
- return (k === 0 ? head : row.bounds[cuts[k - 1]].s) ?? holder;
197
- };
198
- const own = new Map();
199
- const moved = new Map();
200
- for (const [h, rec] of blocks) {
201
- const stays = [];
202
- for (const c of rec.listClaims ?? rec.claims) {
203
- const t = targetOf(h, c);
204
- if (t === h)
205
- stays.push(c);
206
- else {
207
- let into = moved.get(t);
208
- if (into === undefined)
209
- moved.set(t, (into = []));
210
- into.push({ ...c, holder: h });
211
- }
212
- }
213
- own.set(h, stays);
214
- }
215
- for (const [t, list] of moved) {
216
- if (!own.has(t))
217
- continue;
218
- list.sort((x, y) => cmpStamp(x.stamp, y.stamp));
219
- own.set(t, [...own.get(t), ...list]);
220
- }
221
- return own;
222
- };
223
122
  export const computeOwnership = (doc, given) => {
224
123
  const rows = [];
225
124
  for (const rec of given.values())
226
125
  if (rec.content)
227
126
  rows.push(scanText(rec.id, rec.content));
228
- const delim = delimiters(given, rows);
127
+ const delim = delimiters(given, rows, removedKeys(doc.get(SCHEMA.roots.registry)));
229
128
  const streams = new Map();
230
129
  const inText = new Map();
130
+ const rowOf = new Map();
231
131
  for (const row of rows) {
232
- const list = placeText(row, delim);
132
+ const list = placeText(row, delim, (s) => !given.has(s));
233
133
  inText.set(row.home, list);
134
+ rowOf.set(row.text, row);
234
135
  for (const s of list)
235
136
  streams.set(s.block, s);
236
137
  }
237
- // The records with their effective claims (`merge.claim.anchor`).
238
- const effective = effectiveClaims(doc, given, new Map(rows.map((row) => [row.text, row])), delim, streams);
239
138
  const blocks = new Map();
240
- for (const [id, rec] of given)
241
- blocks.set(id, {
242
- ...rec,
243
- listClaims: rec.listClaims ?? rec.claims,
244
- claims: effective.get(id) ?? rec.claims
245
- });
139
+ for (const [id, rec] of given) {
140
+ const s = streams.get(id);
141
+ const items = s === undefined ? [] : claimsIn(rowOf.get(s.text), s);
142
+ blocks.set(id, { ...rec, claims: [...(rec.implicit ?? []), ...items] });
143
+ }
246
144
  const { owners, top } = claimGraph(blocks);
247
145
  const ownerOf = (b) => owners.get(b) ?? DEAD;
248
146
  const own = {
249
147
  ownerOf,
250
148
  hidden: (b) => ownerOf(b) !== b,
251
149
  top: (m) => top.get(m),
150
+ claimIndex: (holder, m) => blocks.get(holder)?.claims.findIndex((c) => c.m === m) ?? -1,
252
151
  streamOf: (b) => streams.get(b),
253
152
  streamsIn: (home) => inText.get(home) ?? [],
254
153
  streamAt: (home, i) => (inText.get(home) ?? []).find((x) => x.start <= i && i <= x.end),
255
- display: (b) => displayOf(b, blocks, own),
256
- claimsOf: (b) => blocks.get(b)?.claims ?? []
154
+ display: (b) => displayOf(b, blocks, own)
257
155
  };
258
156
  return own;
259
157
  };
@@ -288,17 +186,27 @@ export const insertIntoText = (doc, blocks, own, b, offset, payload, marks) => {
288
186
  const have = at.find((p) => !p.deleted && p.len > 0)?.formats;
289
187
  fitMarks(doc, text, hit.idx, payload.length, have, marks);
290
188
  };
291
- /** The per-stream delete: each range lies inside one stream's pieces, so no boundary is ever removed. */
189
+ /**
190
+ * The per-stream delete: each range lies inside one stream's pieces, so no
191
+ * boundary is ever removed. The text is held by this writer's record (fork
192
+ * patch YP20, root `textdel`, in the history's scope): an undo deletes the
193
+ * record and the text shows again where it was, unless another writer's
194
+ * record holds it. Text the open undo step inserted is removed instead, so
195
+ * that step's undo still changes nothing.
196
+ */
292
197
  export const deleteRange = (doc, blocks, own, b, offset, length) => {
293
- const spans = [];
294
- for (const r of rangesOf(flatten(b, blocks, own), offset, offset + length)) {
295
- for (const p of openRangeCursor(r.text).read(r.a, r.b))
296
- if (!p.deleted && p.len > 0 && (p.content.str !== undefined || 'type' in p.content))
297
- spans.push({ c: p.id.client, k: p.id.clock, n: p.len });
298
- r.text.delete(r.a, r.b - r.a);
299
- }
300
- D.markDeleted(doc, spans);
198
+ const records = doc.get(TEXT_DELETES_ROOT);
199
+ const fresh = openInserts(doc);
200
+ for (const r of rangesOf(flatten(b, blocks, own), offset, offset + length))
201
+ r.text.delete(r.a, r.b - r.a, records, fresh, proposing.get(doc));
301
202
  };
203
+ /**
204
+ * A suggestion's plan being written on a doc (`doc/suggest.ts`): its text
205
+ * deletes propose (fork patch YP32) into its record, `sort` telling each
206
+ * unit's lot (`1` its author's own: held; `2` proposed; `3` already
207
+ * proposed: stepped over).
208
+ */
209
+ export const proposing = new WeakMap();
302
210
  export const formatRangeIn = (doc, blocks, own, b, offset, length, formats) => {
303
211
  for (const r of rangesOf(flatten(b, blocks, own), offset, offset + length))
304
212
  writeMarks(doc, r.text, r.a, r.b - r.a, formats);
@@ -337,60 +245,52 @@ export const findAtom = (own, b, inlineId) => {
337
245
  };
338
246
  /**
339
247
  * Split `b`'s display at `offset` for the new block `newId` (incarnation
340
- * `n`): one boundary through fork patch YP7 at the end of the gap, and the claims that
341
- * follow the split point — every claim of the stream's own block, then each
342
- * holder's claims after the one that led down — returned for re-insertion
343
- * on the new block and deleted from their holders. No text is copied.
248
+ * `n`): one boundary through fork patch YP7 at the end of the gap. The
249
+ * claims that follow the split point — every claim of the stream's own
250
+ * block, then each holder's claims after the one that led down — are
251
+ * written again, in that order, at the end of the new block's stream, and
252
+ * their items deleted (an implicit claim is written on the new block, whose
253
+ * claim outranks it). No text is copied.
344
254
  */
345
- export const splitAt = (blocks, own, b, offset, newId, n) => {
255
+ export const splitAt = (doc, blocks, own, b, offset, newId, n) => {
346
256
  const segs = flatten(b, blocks, own);
347
257
  const hit = locate(segs, Math.max(0, Math.min(offset, ownedLength(segs))));
348
258
  if (hit === null)
349
259
  throw new Error(`splitAt: "${b}" has no stream`);
350
260
  const { seg, idx } = hit;
351
- const moved = [];
352
- // A claim another block stores (its anchor moved it here) is deleted from that list.
353
- const after = (holder, from) => blocks
354
- .get(holder)
355
- .claims.slice(from)
356
- .forEach((c) => moved.push({ holder: c.holder ?? holder, claim: c }));
357
- after(seg.block, 0);
261
+ const moved = [...blocks.get(seg.block).claims];
358
262
  for (let i = seg.path.length - 1; i >= 0; i--)
359
- after(seg.path[i].holder, seg.path[i].entry + 1);
263
+ moved.push(...blocks.get(seg.path[i].holder).claims.slice(seg.path[i].entry + 1));
360
264
  const text = seg.text;
265
+ // The new block's stream ends where the source's did, one boundary later.
266
+ const end = own.streamOf(seg.block).end + 1;
361
267
  text.insertAtGapEnd(idx, [{ s: newId, n }]);
362
- const byHolder = new Map();
363
- // An implicit claim (a losing incarnation) has no list entry: it is
364
- // only written, explicitly, on the new block, whose claim outranks it.
365
- for (const { holder, claim } of moved)
366
- if (claim.seqIndex >= 0)
367
- byHolder.set(holder, [...(byHolder.get(holder) ?? []), claim.seqIndex]);
368
- for (const [holder, idxs] of byHolder) {
369
- const list = blocks.get(holder).claimsNode;
370
- for (const i of idxs.sort((x, y) => y - x))
371
- list.delete(i, 1);
372
- }
373
- // Re-inserted with their anchors: the region they end is the new block's now.
374
- return moved.map(({ claim: c }) => c.a === undefined ? { m: c.m } : { m: c.m, a: c.a, r: c.r ?? null });
268
+ if (moved.length === 0)
269
+ return;
270
+ text.insertAtGapEnd(end, moved.map((c) => ({ m: c.m })));
271
+ deleteClaims(doc, moved);
375
272
  };
376
273
  /**
377
- * Append a merge claim `{m: from}` to `into`'s claims list, anchored to
378
- * the end of `into`'s stream (`merge.claim.anchor`): its last unit (its
379
- * opening boundary when empty; none at an own text's start) and the item
380
- * after it.
274
+ * Merge `from` into `into`: one claim item `{m: from}` at the end of the gap
275
+ * at the end of `into`'s stream (fork patch YP7; YP21 sorts it after the
276
+ * content and boundaries a concurrent writer puts at its origin, so a split
277
+ * the merge's writer did not see leaves it in the piece that ends `into`'s
278
+ * region: `merge.claim.anchor`). `into` has a stream: the caller gives a
279
+ * streamless block its own text first.
381
280
  */
382
- export const claimInto = (blocks, own, from, into) => {
383
- const list = blocks.get(into).claimsNode;
384
- const claim = { m: from };
281
+ export const claimInto = (own, from, into) => {
385
282
  const s = own.streamOf(into);
386
- if (s !== undefined) {
387
- const a = anchorAt(s.text, s.end, -1).i;
388
- if (a !== null) {
389
- claim.a = a;
390
- claim.r = anchorAt(s.text, s.end, 0).i;
391
- }
283
+ s.text.insertAtGapEnd(s.end, [{ m: from }]);
284
+ };
285
+ /** Delete the items of `claims` (an implicit claim has none). */
286
+ export const deleteClaims = (doc, claims) => {
287
+ const store = storeOf(doc);
288
+ for (const { stamp } of claims) {
289
+ if (stamp.c < 0 || store.getItem({ client: stamp.c, clock: stamp.k }).deleted)
290
+ continue;
291
+ const at = Y.indexOfId(asYDoc(doc), Y.createID(stamp.c, stamp.k));
292
+ at.type.delete(at.index, 1);
392
293
  }
393
- list.insert(list.length, [claim]);
394
294
  };
395
295
  /**
396
296
  * Give streamless block `rec` its own text and re-mint its nonce, so a late
@@ -467,3 +367,25 @@ export const bindText = (_Y) => ({
467
367
  * typing and keeps the text every replica shares.
468
368
  */
469
369
  export const ownTextIds = new WeakMap();
370
+ /**
371
+ * Each history's open step on a doc (`doc/history.ts` registers them): what
372
+ * the step still capturing inserted, `null` when none is open.
373
+ */
374
+ export const openSteps = new WeakMap();
375
+ /**
376
+ * What this writer inserted in the open undo steps of `doc` (`null`: none):
377
+ * a history capturing a peer's frames (the room's validation) opens steps of
378
+ * that peer's writes, never fresh here.
379
+ */
380
+ const openInserts = (doc) => {
381
+ let fresh = null;
382
+ for (const open of openSteps.get(doc) ?? []) {
383
+ const ranges = open()?.clients.get(doc.clientID);
384
+ if (ranges === undefined)
385
+ continue;
386
+ fresh ??= ops.idSet();
387
+ for (const r of ranges.getIds())
388
+ fresh.add(doc.clientID, r.clock, r.len);
389
+ }
390
+ return fresh;
391
+ };
@@ -15,6 +15,6 @@ export declare const inlineItemOf: (entry: unknown) => RangeItem;
15
15
  /**
16
16
  * Read `[i0, i1)` through the cursor: text pieces as UTF-16 slices under their
17
17
  * folded marks (adjacent equal marks merge), inline atoms one item each.
18
- * Boundary items are skipped — the one read predicate stream ownership needs.
18
+ * Boundary and claim items are skipped — the one read predicate stream ownership needs.
19
19
  */
20
20
  export declare const readRange: (cur: RangeCursor, i0: number, i1: number, stats?: RangeReadStats, items?: RangeItem[]) => RangeItem[];
@@ -1,6 +1,6 @@
1
1
  import { ID, TYPE } from '../schema.js';
2
2
  import { readData } from '../data.js';
3
- import { isBoundary } from './items.js';
3
+ import { isRowMark } from './items.js';
4
4
  /** Canonical JSON key (sorted keys, recursive) — mark-set equality/interning. */
5
5
  export const canonKey = (v) => {
6
6
  if (v === null || typeof v !== 'object')
@@ -52,7 +52,7 @@ export const inlineItemOf = (entry) => {
52
52
  /**
53
53
  * Read `[i0, i1)` through the cursor: text pieces as UTF-16 slices under their
54
54
  * folded marks (adjacent equal marks merge), inline atoms one item each.
55
- * Boundary items are skipped — the one read predicate stream ownership needs.
55
+ * Boundary and claim items are skipped — the one read predicate stream ownership needs.
56
56
  */
57
57
  export const readRange = (cur, i0, i1, stats, items = []) => {
58
58
  for (const piece of cur.read(i0, i1, stats)) {
@@ -73,7 +73,7 @@ export const readRange = (cur, i0, i1, stats, items = []) => {
73
73
  else if (typeof c.getContent === 'function') {
74
74
  const arr = c.getContent();
75
75
  for (let k = piece.offset; k < piece.offset + piece.len; k++) {
76
- if (!isBoundary(arr[k]))
76
+ if (!isRowMark(arr[k]))
77
77
  items.push(inlineItemOf(arr[k]));
78
78
  }
79
79
  }