edytor 2.0.0 → 4.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 (346) hide show
  1. package/README.md +19 -4
  2. package/dist/block/block.svelte.js +2 -4
  3. package/dist/clipboard/htmlFlow.d.ts +20 -7
  4. package/dist/clipboard/htmlFlow.js +23 -15
  5. package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
  6. package/dist/clipboard/serializeClipboardFragment.js +6 -4
  7. package/dist/clipboard/textBlocks.d.ts +8 -0
  8. package/dist/clipboard/textBlocks.js +6 -2
  9. package/dist/cloudflare/DocumentRoom.d.ts +13 -9
  10. package/dist/cloudflare/DocumentRoom.js +10 -6
  11. package/dist/cloudflare/room/admission.js +3 -3
  12. package/dist/cloudflare/room/context.d.ts +28 -27
  13. package/dist/cloudflare/room/context.js +2 -2
  14. package/dist/cloudflare/room/purge.d.ts +6 -3
  15. package/dist/cloudflare/room/purge.js +44 -19
  16. package/dist/cloudflare/room/updates.d.ts +3 -4
  17. package/dist/cloudflare/room/updates.js +6 -8
  18. package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
  19. package/dist/cloudflare/routeDocumentSocket.js +53 -0
  20. package/dist/collaboration/comments/client.d.ts +1 -1
  21. package/dist/collaboration/comments/client.js +1 -1
  22. package/dist/collaboration/remoteSelection.js +3 -3
  23. package/dist/components/Edytor.svelte +2 -10
  24. package/dist/components/Edytor.svelte.d.ts +1 -3
  25. package/dist/crdt/admission.d.ts +5 -10
  26. package/dist/crdt/admission.js +5 -11
  27. package/dist/crdt/attribution/attribution.d.ts +31 -12
  28. package/dist/crdt/attribution/attribution.js +56 -18
  29. package/dist/crdt/attribution/block.d.ts +3 -3
  30. package/dist/crdt/attribution/block.js +7 -8
  31. package/dist/crdt/attribution/index.d.ts +1 -1
  32. package/dist/crdt/attribution/index.js +1 -1
  33. package/dist/crdt/data.d.ts +62 -31
  34. package/dist/crdt/data.js +211 -103
  35. package/dist/crdt/doc/delete.d.ts +1 -1
  36. package/dist/crdt/doc/delete.js +13 -30
  37. package/dist/crdt/doc/funnel.d.ts +7 -6
  38. package/dist/crdt/doc/funnel.js +39 -33
  39. package/dist/crdt/doc/gate.d.ts +3 -20
  40. package/dist/crdt/doc/gate.js +2 -41
  41. package/dist/crdt/doc/history.d.ts +25 -9
  42. package/dist/crdt/doc/history.js +152 -42
  43. package/dist/crdt/doc/layout.js +11 -22
  44. package/dist/crdt/doc/meta.js +12 -17
  45. package/dist/crdt/doc/moves.d.ts +1 -1
  46. package/dist/crdt/doc/moves.js +52 -32
  47. package/dist/crdt/doc/reads.js +2 -2
  48. package/dist/crdt/doc/seed.js +2 -2
  49. package/dist/crdt/doc/split-merge.js +12 -15
  50. package/dist/crdt/doc/steps.d.ts +25 -13
  51. package/dist/crdt/doc/steps.js +52 -122
  52. package/dist/crdt/doc/types.d.ts +21 -9
  53. package/dist/crdt/document.d.ts +21 -19
  54. package/dist/crdt/document.js +26 -23
  55. package/dist/crdt/edytor-doc.d.ts +66 -68
  56. package/dist/crdt/edytor-doc.js +21 -20
  57. package/dist/crdt/engine-api.d.ts +33 -1
  58. package/dist/crdt/engine.d.ts +0 -1
  59. package/dist/crdt/engine.js +1 -4
  60. package/dist/crdt/flow.d.ts +1 -1
  61. package/dist/crdt/flow.js +25 -27
  62. package/dist/crdt/index.d.ts +29 -28
  63. package/dist/crdt/index.js +3 -3
  64. package/dist/crdt/placement/display.d.ts +5 -30
  65. package/dist/crdt/placement/display.js +39 -144
  66. package/dist/crdt/placement/keys.d.ts +58 -0
  67. package/dist/crdt/placement/keys.js +90 -0
  68. package/dist/crdt/placement/model.d.ts +119 -118
  69. package/dist/crdt/placement/model.js +242 -142
  70. package/dist/crdt/placement/resolve.d.ts +123 -35
  71. package/dist/crdt/placement/resolve.js +187 -153
  72. package/dist/crdt/placement/slots.d.ts +134 -0
  73. package/dist/crdt/placement/slots.js +152 -0
  74. package/dist/crdt/protocol.d.ts +2 -2
  75. package/dist/crdt/protocol.js +2 -2
  76. package/dist/crdt/providers/index.d.ts +1 -1
  77. package/dist/crdt/providers/room.d.ts +26 -11
  78. package/dist/crdt/providers/room.js +77 -27
  79. package/dist/crdt/providers/websocket.d.ts +1 -1
  80. package/dist/crdt/providers/websocket.js +33 -32
  81. package/dist/crdt/purge.d.ts +17 -8
  82. package/dist/crdt/purge.js +236 -126
  83. package/dist/crdt/restore.d.ts +2 -2
  84. package/dist/crdt/restore.js +18 -34
  85. package/dist/crdt/schema.d.ts +22 -21
  86. package/dist/crdt/schema.js +29 -23
  87. package/dist/crdt/semantics.js +3 -1
  88. package/dist/crdt/storage.d.ts +1 -1
  89. package/dist/crdt/storage.js +1 -1
  90. package/dist/crdt/structs.d.ts +15 -15
  91. package/dist/crdt/structs.js +8 -22
  92. package/dist/crdt/text/index/cache.js +4 -0
  93. package/dist/crdt/text/index/claims.js +12 -0
  94. package/dist/crdt/text/index/fold.d.ts +2 -3
  95. package/dist/crdt/text/index/fold.js +194 -44
  96. package/dist/crdt/text/index/layout.js +5 -8
  97. package/dist/crdt/text/index/placement.d.ts +26 -18
  98. package/dist/crdt/text/index/placement.js +404 -138
  99. package/dist/crdt/text/index/records.d.ts +3 -3
  100. package/dist/crdt/text/index/records.js +24 -31
  101. package/dist/crdt/text/index/shared.d.ts +11 -3
  102. package/dist/crdt/text/index/shared.js +12 -3
  103. package/dist/crdt/text/index/state.d.ts +21 -17
  104. package/dist/crdt/text/index/state.js +15 -17
  105. package/dist/crdt/text/index/streams.d.ts +10 -5
  106. package/dist/crdt/text/index/streams.js +78 -27
  107. package/dist/crdt/text/items.d.ts +10 -3
  108. package/dist/crdt/text/items.js +7 -0
  109. package/dist/crdt/text/model.d.ts +77 -62
  110. package/dist/crdt/text/model.js +84 -169
  111. package/dist/crdt/text/ranges.d.ts +1 -1
  112. package/dist/crdt/text/ranges.js +3 -3
  113. package/dist/crdt/text/rows.d.ts +13 -7
  114. package/dist/crdt/text/rows.js +24 -7
  115. package/dist/crdt/text/runs.d.ts +17 -12
  116. package/dist/crdt/text/runs.js +24 -7
  117. package/dist/crdt/text/streams.d.ts +26 -13
  118. package/dist/crdt/text/streams.js +41 -14
  119. package/dist/crdt/vendor/yjs/UPSTREAM.md +568 -21
  120. package/dist/crdt/vendor/yjs/dts/global.d.ts +2 -0
  121. package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
  122. package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +7 -0
  123. package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +194 -10
  124. package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +6 -3
  125. package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +5 -18
  126. package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +15 -1
  127. package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +14 -6
  128. package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +33 -6
  129. package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +1 -65
  130. package/dist/crdt/vendor/yjs/dts/utils/marks.d.ts +6 -1
  131. package/dist/crdt/vendor/yjs/dts/ynode.d.ts +43 -7
  132. package/dist/crdt/vendor/yjs/global.d.ts +2 -0
  133. package/dist/crdt/vendor/yjs/src/index.js +1 -1
  134. package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +10 -0
  135. package/dist/crdt/vendor/yjs/src/structs/Item.js +610 -51
  136. package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +18 -9
  137. package/dist/crdt/vendor/yjs/src/utils/Doc.js +5 -3
  138. package/dist/crdt/vendor/yjs/src/utils/StructStore.js +5 -0
  139. package/dist/crdt/vendor/yjs/src/utils/Transaction.js +36 -13
  140. package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +88 -18
  141. package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +119 -32
  142. package/dist/crdt/vendor/yjs/src/utils/encoding.js +13 -1
  143. package/dist/crdt/vendor/yjs/src/utils/ids.js +7 -7
  144. package/dist/crdt/vendor/yjs/src/utils/marks.js +193 -8
  145. package/dist/crdt/vendor/yjs/src/utils/redo.js +1 -1
  146. package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +1 -1
  147. package/dist/crdt/vendor/yjs/src/utils/updates.js +3 -3
  148. package/dist/crdt/vendor/yjs/src/ynode.js +177 -12
  149. package/dist/dnd/autoScroll.d.ts +15 -7
  150. package/dist/dnd/autoScroll.js +10 -15
  151. package/dist/dnd/dropIndicator.js +2 -5
  152. package/dist/dnd/external.d.ts +6 -0
  153. package/dist/dnd/external.js +17 -0
  154. package/dist/dnd/geometry.d.ts +2 -0
  155. package/dist/dnd/geometry.js +3 -4
  156. package/dist/dnd/placement.d.ts +1 -1
  157. package/dist/dnd/pragmatic.d.ts +3 -1
  158. package/dist/dnd/pragmatic.js +12 -2
  159. package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
  160. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
  161. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
  162. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
  163. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
  164. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
  165. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
  166. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
  167. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
  168. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
  169. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
  170. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
  171. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
  172. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
  173. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
  174. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
  175. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
  176. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +1 -1
  177. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
  178. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
  179. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
  180. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
  181. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
  182. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
  183. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
  184. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
  185. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
  186. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
  187. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
  188. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
  189. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
  190. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
  191. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
  192. package/dist/edytor.svelte.d.ts +2 -5
  193. package/dist/edytor.svelte.js +21 -32
  194. package/dist/events/beforeInputCommands.js +2 -2
  195. package/dist/events/onBeforeInput.js +1 -1
  196. package/dist/events/onDrop.d.ts +0 -6
  197. package/dist/events/onDrop.js +10 -23
  198. package/dist/events/onInput.d.ts +0 -12
  199. package/dist/events/onInput.js +1 -67
  200. package/dist/events/onPageHide.d.ts +3 -0
  201. package/dist/events/onPageHide.js +16 -0
  202. package/dist/export/forms.d.ts +627 -0
  203. package/dist/export/forms.js +749 -0
  204. package/dist/export/index.d.ts +170 -0
  205. package/dist/export/index.js +161 -0
  206. package/dist/export/markdown.d.ts +41 -0
  207. package/dist/export/markdown.js +585 -0
  208. package/dist/export/markdownWriter.d.ts +9 -0
  209. package/dist/export/markdownWriter.js +133 -0
  210. package/dist/export/mdx.d.ts +15 -0
  211. package/dist/export/mdx.js +33 -0
  212. package/dist/index.d.ts +3 -3
  213. package/dist/index.js +1 -1
  214. package/dist/kinds.js +1 -1
  215. package/dist/plugins/anchored.svelte.d.ts +21 -25
  216. package/dist/plugins/anchored.svelte.js +23 -39
  217. package/dist/plugins/blockHandles/BlockHandleController.svelte.js +24 -32
  218. package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
  219. package/dist/plugins/blockHandles/dragPreview.js +33 -0
  220. package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
  221. package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
  222. package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
  223. package/dist/plugins/chrome.d.ts +27 -5
  224. package/dist/plugins/chrome.js +24 -9
  225. package/dist/plugins/code/CodePlugin.svelte +12 -9
  226. package/dist/plugins/code/header.svelte.js +7 -11
  227. package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
  228. package/dist/plugins/code/languageMenu.svelte.js +13 -20
  229. package/dist/plugins/columns/ColumnsPlugin.svelte +7 -20
  230. package/dist/plugins/columns/resize.svelte.d.ts +2 -3
  231. package/dist/plugins/columns/resize.svelte.js +2 -5
  232. package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
  233. package/dist/plugins/comments/CommentsController.svelte.js +20 -0
  234. package/dist/plugins/equation/EquationPlugin.svelte +12 -22
  235. package/dist/plugins/equation/equation.svelte.d.ts +7 -15
  236. package/dist/plugins/equation/equation.svelte.js +13 -50
  237. package/dist/plugins/equation/tex.d.ts +17 -0
  238. package/dist/plugins/equation/tex.js +42 -0
  239. package/dist/plugins/fileDrop.d.ts +38 -23
  240. package/dist/plugins/fileDrop.js +82 -76
  241. package/dist/plugins/find/FindController.svelte.d.ts +5 -0
  242. package/dist/plugins/find/FindController.svelte.js +14 -14
  243. package/dist/plugins/find/findPlugin.js +1 -15
  244. package/dist/plugins/image/ImageChrome.svelte +8 -2
  245. package/dist/plugins/image/ImagePlugin.svelte +15 -52
  246. package/dist/plugins/image/controls.svelte.js +16 -2
  247. package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
  248. package/dist/plugins/image/toolbar.svelte.js +21 -31
  249. package/dist/plugins/index.d.ts +1 -1
  250. package/dist/plugins/list.svelte.d.ts +9 -0
  251. package/dist/plugins/list.svelte.js +18 -0
  252. package/dist/plugins/marquee/marqueePlugin.js +0 -4
  253. package/dist/plugins/media/AudioPlugin.svelte +1 -1
  254. package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
  255. package/dist/plugins/media/EmbedPlugin.svelte +5 -90
  256. package/dist/plugins/media/EmptySlot.svelte +36 -20
  257. package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
  258. package/dist/plugins/media/FilePlugin.svelte +1 -19
  259. package/dist/plugins/media/MediaEmpty.svelte +2 -55
  260. package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
  261. package/dist/plugins/media/SourceBlock.svelte +142 -52
  262. package/dist/plugins/media/SourceBlock.svelte.d.ts +10 -4
  263. package/dist/plugins/media/VideoPlugin.svelte +1 -1
  264. package/dist/plugins/media/empty.svelte.js +2 -7
  265. package/dist/plugins/media/media.d.ts +2 -63
  266. package/dist/plugins/media/media.js +1 -194
  267. package/dist/plugins/media/sources.d.ts +60 -0
  268. package/dist/plugins/media/sources.js +165 -0
  269. package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
  270. package/dist/plugins/media/urlPaste.svelte.js +12 -21
  271. package/dist/plugins/mention/MentionPlugin.svelte +8 -35
  272. package/dist/plugins/page/PagePlugin.svelte +2 -9
  273. package/dist/plugins/page/page.js +1 -1
  274. package/dist/plugins/pageLink/PageLinkPlugin.svelte +6 -13
  275. package/dist/plugins/richtext/RichTextPlugin.svelte +85 -197
  276. package/dist/plugins/richtext/body.js +1 -1
  277. package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
  278. package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
  279. package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
  280. package/dist/plugins/richtext/richTextOperations.js +3 -49
  281. package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
  282. package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
  283. package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
  284. package/dist/plugins/table/TableChrome.svelte +2 -3
  285. package/dist/plugins/table/TablePlugin.svelte +20 -54
  286. package/dist/plugins/table/chrome.svelte.d.ts +5 -2
  287. package/dist/plugins/table/chrome.svelte.js +30 -54
  288. package/dist/plugins/table/table.js +3 -3
  289. package/dist/plugins/toc/TocPlugin.svelte +2 -4
  290. package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
  291. package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
  292. package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
  293. package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
  294. package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
  295. package/dist/plugins/triggers/place.js +1 -2
  296. package/dist/plugins/triggers/triggers.d.ts +6 -1
  297. package/dist/plugins/triggers/triggers.js +12 -13
  298. package/dist/plugins/uploads.svelte.d.ts +5 -2
  299. package/dist/plugins/uploads.svelte.js +25 -15
  300. package/dist/plugins.d.ts +26 -0
  301. package/dist/plugins.js +0 -24
  302. package/dist/selection/replaceSelection.js +2 -2
  303. package/dist/selection/selection.svelte.d.ts +4 -10
  304. package/dist/selection/selection.svelte.js +7 -11
  305. package/dist/session/bindings.js +1 -1
  306. package/dist/session/commands.d.ts +7 -11
  307. package/dist/session/commands.js +13 -19
  308. package/dist/session/inputRules.js +1 -1
  309. package/dist/session/navigation.js +1 -1
  310. package/dist/session/suggestions.svelte.d.ts +0 -11
  311. package/dist/session/suggestions.svelte.js +15 -3
  312. package/dist/session/uploads.d.ts +8 -8
  313. package/dist/surface/lines.js +1 -3
  314. package/dist/surface/observer.svelte.d.ts +17 -1
  315. package/dist/surface/observer.svelte.js +74 -19
  316. package/dist/surface/overlay.d.ts +0 -14
  317. package/dist/surface/overlay.js +0 -25
  318. package/dist/surface/projector.svelte.d.ts +15 -3
  319. package/dist/surface/projector.svelte.js +60 -9
  320. package/dist/text/text.svelte.js +3 -13
  321. package/dist/utils/sanitize.d.ts +38 -0
  322. package/dist/utils/sanitize.js +82 -0
  323. package/dist/utils.d.ts +2 -0
  324. package/dist/utils.js +5 -0
  325. package/package.json +19 -2
  326. package/dist/crdt/placement/rank.d.ts +0 -87
  327. package/dist/crdt/placement/rank.js +0 -332
  328. package/dist/crdt/placement/source.d.ts +0 -43
  329. package/dist/crdt/placement/source.js +0 -66
  330. package/dist/crdt/text/delete-index.d.ts +0 -129
  331. package/dist/crdt/text/delete-index.js +0 -365
  332. package/dist/crdt/text/deletes.d.ts +0 -76
  333. package/dist/crdt/text/deletes.js +0 -362
  334. package/dist/crdt/text/index/anchored.d.ts +0 -17
  335. package/dist/crdt/text/index/anchored.js +0 -197
  336. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
  337. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
  338. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
  339. package/dist/plugins/code/LanguageMenu.svelte +0 -25
  340. package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
  341. package/dist/plugins/equation/EquationEditor.svelte +0 -27
  342. package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
  343. package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
  344. package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
  345. package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
  346. package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
@@ -1,11 +1,25 @@
1
- import { view as modelView } from './placement/model.js';
2
- import { purgeStreams } from './text/model.js';
3
- import { AT, BLOCK_ATTR_ROOT, DATA, DATA_LEAF_PREFIX, DEL_PREFIX, HORIZON_ATTR, HORIZON_ROOT, isNodeLike, REC_PREFIX, REGISTRY_KEY, WITHDRAW_PREFIX } from './schema.js';
4
- import { bindDeletes } from './text/deletes.js';
5
- import { deleteIndex } from './text/delete-index.js';
1
+ import { recordsOf, registryOf, view as modelView } from './placement/model.js';
2
+ import { removeUnit, unitOf } from './placement/slots.js';
3
+ import { deleteClaims, purgeStreams, scanText } from './text/model.js';
4
+ import { BLOCK_ATTR_ROOT, DATA, DATA_LEAF_PREFIX, DEL_PREFIX, HORIZON_ATTR, HORIZON_ROOT, REGISTRY_KEY, RELEASE_ROOT, TEXT_DELETES_ROOT, WITHDRAW_PREFIX } from './schema.js';
6
5
  import { baseIdOf, isIncarnationId } from './incarnations.js';
7
- import { attrItems, firstItem } from './structs.js';
6
+ import { attrItems, dropSearchMarkers, engineOps, firstItem, holdsIds } from './structs.js';
8
7
  const mapOf = (node) => attrItems(node);
8
+ /**
9
+ * The ended histories a document holds (`hist.release.end`): per writer,
10
+ * the clock its latest live release record ended at (what it wrote below
11
+ * it is released).
12
+ */
13
+ export const releasesOf = (doc) => {
14
+ const out = new Map();
15
+ for (let it = firstItem(doc.get(RELEASE_ROOT)); it; it = it.right) {
16
+ if (it.deleted)
17
+ continue;
18
+ const { client, clock } = it.id;
19
+ out.set(client, Math.max(out.get(client) ?? 0, clock + it.length - 1));
20
+ }
21
+ return out;
22
+ };
9
23
  /** The horizon a document holds (`null`: never purged). */
10
24
  export const readHorizon = (doc) => {
11
25
  const h = doc.get(HORIZON_ROOT).getAttr(HORIZON_ATTR);
@@ -14,73 +28,76 @@ export const readHorizon = (doc) => {
14
28
  : null;
15
29
  };
16
30
  export const bindPurge = (Y) => {
17
- const D = bindDeletes(Y);
18
- const { rootSpans, holders, dropMarks, recordsIn, copiesOf, liveRoots, forget, collect } = deleteIndex(Y);
31
+ const ops = engineOps(Y);
32
+ /** The live hold records of `doc`, one per held range. */
33
+ const holdsOf = (doc) => {
34
+ const out = [];
35
+ for (let it = firstItem(doc.get(TEXT_DELETES_ROOT)); it; it = it.right) {
36
+ const ids = it.content.ids;
37
+ if (it.deleted || ids === undefined)
38
+ continue;
39
+ for (let j = 0; j < ids.length; j += 3)
40
+ out.push({
41
+ client: it.id.client,
42
+ clock: it.id.clock + j / 3,
43
+ c: ids[j],
44
+ k: ids[j + 1],
45
+ n: ids[j + 2]
46
+ });
47
+ }
48
+ return out;
49
+ };
19
50
  /**
20
- * Whether every live mark holding a character of `spans` was written
21
- * where `old` says (a withdrawn block's content was deleted
22
- * before the horizon). Characters no mark holds count as old.
51
+ * Whether every live record holding an item of `spans` was written where
52
+ * `old` says (a withdrawn block's content was deleted before the
53
+ * horizon). Items no record holds count as old.
23
54
  */
24
- const heldBefore = (doc, spans, old) => {
25
- const s = D.state(doc);
26
- return spans
27
- .flatMap((sp) => rootSpans(s, sp))
28
- .every((r) => holders(s, r).every((mark) => old(mark.client, mark.clock)));
29
- };
55
+ const heldBefore = (holds, spans, old) => holds.every((h) => old(h.client, h.clock) ||
56
+ !spans.some((sp) => sp.c === h.c && sp.k < h.k + h.n && h.k < sp.k + sp.n));
30
57
  /**
31
- * The text's part (`room.purge.what`), inside the purge
32
- * transaction: delete every text delete mark record `old` names, and
33
- * every restoration record `old` names whose copies are all deleted
34
- * and that no remaining mark holds; its copies are forgotten (the
35
- * `gcFilter` no longer keeps them) and collected. Writes no mark.
58
+ * The text's part (`room.purge.what`), inside the purge transaction:
59
+ * every hold record `old` names is deleted with what it holds (a real
60
+ * delete: the engine collects it everywhere; a newer record holding the
61
+ * same text has nothing to show again, the older delete is past the
62
+ * horizon). A record whose text the room lacks (lost, coming back with
63
+ * its author) is kept: it holds that text when it returns.
36
64
  */
37
65
  const purgeText = (doc, old) => {
38
- const s = D.state(doc);
39
- const tr = s.doc._transaction;
40
- if (tr === null)
66
+ const tr = doc._transaction;
67
+ if (tr == null)
41
68
  throw new Error('purge: outside a transaction');
42
- const spans = [];
43
- const dropped = [];
44
- for (let it = firstItem(s.marks); it; it = it.right)
45
- if (!it.deleted)
46
- for (let j = 0; j < it.length; j++) {
47
- const r = { client: it.id.client, clock: it.id.clock + j };
48
- if (!old(r.client, r.clock))
49
- continue;
50
- dropped.push(r);
51
- const last = spans[spans.length - 1];
52
- if (last !== undefined && last.c === r.client && last.k + last.n === r.clock)
53
- last.n++;
54
- else
55
- spans.push({ c: r.client, k: r.clock, n: 1 });
56
- }
57
- dropMarks(s, dropped);
58
- const marks = dropped.length;
59
- D.remove(tr, spans);
60
- const doomed = [];
61
- attrItems(s.restored).forEach((it, key) => {
62
- if (it.deleted || !old(it.id.client, it.id.clock))
63
- return;
64
- const [record, bytes] = recordsIn(it, null)[0] ?? [];
65
- if (bytes === undefined)
69
+ const doomed = holdsOf(doc).filter((h) => old(h.client, h.clock) && holdsIds(doc, h.c, h.k, h.n));
70
+ const ids = (spans) => {
71
+ const set = ops.idSet();
72
+ for (const sp of spans)
73
+ set.add(sp.c, sp.k, sp.n);
74
+ return set;
75
+ };
76
+ ops.iterate(tr, ids(doomed), (it) => {
77
+ if (it.removed !== false)
66
78
  return;
67
- const copies = copiesOf(record, bytes);
68
- const dead = copies.every((e) => liveRoots(s, { c: e.c, k: e.k, n: e.n, rk: e.k }).length === 0 &&
69
- holders(s, { c: e.rc, k: e.rk, n: e.n }).length === 0);
70
- if (dead)
71
- doomed.push({ key, copies });
79
+ it.delete(tr);
80
+ dropSearchMarkers(it.parent);
72
81
  });
73
- for (const { key, copies } of doomed) {
74
- s.restored.deleteAttr(key);
75
- forget(s, copies);
76
- collect(s, tr, copies);
77
- }
78
- return { marks, records: doomed.length };
82
+ // The records are read first and deleted after: deleting one releases
83
+ // its holds, which can split items of the store the walk is reading
84
+ // (its writer's own text), and the walk would then visit the structs
85
+ // written before the record (a delete mark beside it) as if they were it.
86
+ const records = [];
87
+ ops.iterate(tr, ids(doomed.map((h) => ({ c: h.client, k: h.clock, n: 1 }))), (it) => {
88
+ records.push(it);
89
+ });
90
+ for (const it of records)
91
+ it.delete(tr);
92
+ return doomed.length;
79
93
  };
80
94
  /**
81
95
  * Purge from `doc` (through `facade`, the facade over it) what was
82
- * deleted before `horizon`, and write the horizon record. Runs inside the
83
- * caller's transaction.
96
+ * deleted before `horizon`, and what the sessions whose history ended
97
+ * deleted (`hist.release.end`), and write the horizon record. With no
98
+ * horizon (`null`: the room's tick found none due), only the ended
99
+ * sessions' deletes go, and the horizon record is left as it is. Runs
100
+ * inside the caller's transaction.
84
101
  */
85
102
  const purge = (doc, facade, horizon) => {
86
103
  const report = {
@@ -88,13 +105,18 @@ export const bindPurge = (Y) => {
88
105
  emptied: 0,
89
106
  marks: 0,
90
107
  records: 0,
91
- candidates: 0,
92
108
  claims: 0,
93
- merged: 0
109
+ merged: 0,
110
+ released: 0
94
111
  };
95
- const vector = Y.decodeStateVector(horizon.sv);
112
+ const vector = horizon === null
113
+ ? new Map()
114
+ : Y.decodeStateVector(horizon.sv);
96
115
  const old = (client, clock) => clock < (vector.get(client) ?? 0);
97
- const oldItem = (item) => item !== undefined && !item.deleted && old(item.id.client, item.id.clock);
116
+ // A delete of an ended session is past the horizon (`hist.release.end`).
117
+ const releases = releasesOf(doc);
118
+ const freed = (client, clock) => old(client, clock) || clock < (releases.get(client) ?? 0);
119
+ const oldItem = (item) => item !== undefined && !item.deleted && freed(item.id.client, item.id.clock);
98
120
  const view = modelView(doc);
99
121
  const { blocks, own, placements } = view;
100
122
  const marks = (node, prefix) => [...node.attrKeys()]
@@ -120,6 +142,35 @@ export const bindPurge = (Y) => {
120
142
  }
121
143
  return out;
122
144
  };
145
+ /** The paired mark items of `s`'s region whose start and end both lie in it. */
146
+ const regionMarks = (s) => {
147
+ const opened = new Map();
148
+ const out = [];
149
+ let at = 0;
150
+ let inside = s.start === 0;
151
+ for (let it = firstItem(s.text); it !== null; it = it.right) {
152
+ const live = !it.deleted && it.countable !== false;
153
+ if (live && at >= s.end)
154
+ break;
155
+ const { key, value } = it.content;
156
+ if (inside && !it.deleted && typeof key === 'string' && Array.isArray(value)) {
157
+ const role = key.charCodeAt(0);
158
+ if (role === 1)
159
+ opened.set(`${value[2]}:${value[3]}`, it);
160
+ else if (role === 2) {
161
+ const start = opened.get(`${value[0]}:${value[1]}`);
162
+ if (start !== undefined)
163
+ out.push(start, it);
164
+ }
165
+ }
166
+ if (live) {
167
+ at += it.length;
168
+ if (at === s.start)
169
+ inside = true;
170
+ }
171
+ }
172
+ return out;
173
+ };
123
174
  const dead = new Set();
124
175
  const shells = [];
125
176
  for (const [id, rec] of blocks) {
@@ -136,7 +187,8 @@ export const bindPurge = (Y) => {
136
187
  shells.push(id);
137
188
  }
138
189
  // A withdrawn block is hidden since it last held something: what its
139
- // stream held was deleted, and its children left, before the horizon.
190
+ // stream held was deleted, and its children left (the move that took
191
+ // them is old), before the horizon.
140
192
  const children = new Map();
141
193
  const add = (map, key, id) => {
142
194
  const list = map.get(key);
@@ -145,23 +197,27 @@ export const bindPurge = (Y) => {
145
197
  else
146
198
  list.push(id);
147
199
  };
148
- for (const [id, rec] of blocks)
149
- for (const c of rec.cands)
150
- if (typeof c.p === 'string')
151
- add(children, c.p, id);
152
- const winnerOld = (rec) => oldItem(mapOf(rec.node.getAttr(AT))?.get(rec.cands[0]?.key));
200
+ for (const [id, rec] of blocks) {
201
+ const p = rec.home?.parent;
202
+ if (typeof p === 'string')
203
+ add(children, p, id);
204
+ }
205
+ /** The block's display edge is old: it shows at its home slot (written with the block), or at an old record. */
206
+ const edgeOld = (id) => {
207
+ const home = blocks.get(id)?.home;
208
+ const r = home ? (unitOf(doc, home)?.item.mover ?? null) : null;
209
+ return r === null ? true : old(r.id.client, r.id.clock);
210
+ };
211
+ const holds = shells.length > 0 ? holdsOf(doc) : [];
153
212
  for (let grew = true; grew;) {
154
213
  grew = false;
155
214
  for (const id of shells) {
156
215
  if (dead.has(id))
157
216
  continue;
158
217
  const s = own.streamOf(id);
159
- if (s !== undefined && !heldBefore(doc, regionSpans(s), old))
218
+ if (s !== undefined && !heldBefore(holds, regionSpans(s), freed))
160
219
  continue;
161
- const left = (children.get(id) ?? []).every((child) => {
162
- const rec = blocks.get(child);
163
- return rec.cands[0]?.p === id ? dead.has(child) : winnerOld(rec);
164
- });
220
+ const left = (children.get(id) ?? []).every((child) => placements.get(child)?.parent === id ? dead.has(child) : edgeOld(child));
165
221
  if (!left)
166
222
  continue;
167
223
  dead.add(id);
@@ -174,8 +230,11 @@ export const bindPurge = (Y) => {
174
230
  dead.add(id);
175
231
  // ── Which of them go whole ────────────────────────────────────────
176
232
  // A text family: the blocks with a stream in one backing text, and the
177
- // block owning it. It goes whole or not at all: a stream whose
178
- // delimiting block went would join the stream before it.
233
+ // block owning it. The block owning a text goes only with every block
234
+ // streaming in it (its text goes with its node). A block streaming in
235
+ // another's text, owning none, goes alone when one boundary names it:
236
+ // that boundary stays and delimits the stream the purge empties, which
237
+ // nobody shows (a removed key's, `text/streams.ts` `removedKeys`).
179
238
  const parent = new Map();
180
239
  const root = (id) => {
181
240
  let r = id;
@@ -205,32 +264,71 @@ export const bindPurge = (Y) => {
205
264
  if (family.every((id) => dead.has(id)))
206
265
  for (const id of family)
207
266
  removable.add(id);
208
- // Nothing that stays may be placed under a block that goes.
267
+ // The live boundaries naming each block, and the keys with losing incarnations.
268
+ const naming = new Map();
269
+ for (const rec of blocks.values())
270
+ if (rec.content)
271
+ for (const b of scanText(rec.id, rec.content).bounds)
272
+ if (b.m === undefined)
273
+ naming.set(b.s, (naming.get(b.s) ?? 0) + 1);
274
+ const incarnated = new Set();
275
+ for (const id of blocks.keys())
276
+ if (isIncarnationId(id))
277
+ incarnated.add(baseIdOf(id));
278
+ const lone = new Set();
279
+ for (const id of dead) {
280
+ if (removable.has(id) || isIncarnationId(id) || incarnated.has(id))
281
+ continue;
282
+ const s = own.streamOf(id);
283
+ if (s === undefined || s.home === id || blocks.get(id).content !== undefined)
284
+ continue;
285
+ if (naming.get(id) !== 1)
286
+ continue;
287
+ lone.add(id);
288
+ removable.add(id);
289
+ }
290
+ // Nothing that stays may be placed under a block that goes, or keep its
291
+ // home slot in the sequence of one (the slot goes with the node).
209
292
  for (let shrank = true; shrank;) {
210
293
  shrank = false;
211
- for (const [id, pl] of placements) {
212
- if (removable.has(id) || typeof pl.parent !== 'string' || !removable.has(pl.parent))
294
+ for (const [id, rec] of blocks) {
295
+ if (removable.has(id))
213
296
  continue;
214
- for (const member of families.get(root(pl.parent)) ?? [])
215
- removable.delete(member);
216
- shrank = true;
297
+ for (const p of [placements.get(id)?.parent, rec.home?.parent]) {
298
+ if (typeof p !== 'string' || !removable.has(p))
299
+ continue;
300
+ for (const member of lone.has(p) ? [p] : (families.get(root(p)) ?? [])) {
301
+ removable.delete(member);
302
+ lone.delete(member);
303
+ }
304
+ shrank = true;
305
+ }
217
306
  }
218
307
  }
219
308
  // ── The writes ────────────────────────────────────────────────────
220
309
  // A deleted block that stays: its stream's text (boundaries kept), its
221
- // data leaves and its claims.
310
+ // data leaves and its claims; a block that goes alone: its stream's
311
+ // text and its claims (the rest goes with its node).
222
312
  const emptied = [...dead].filter((id) => !removable.has(id));
223
- purgeStreams(emptied.flatMap((id) => {
313
+ const purged = [...emptied, ...lone].flatMap((id) => {
224
314
  const s = own.streamOf(id);
225
- return s === undefined || s.end - s.start <= s.inert.length ? [] : [s];
226
- }));
315
+ return s === undefined ? [] : [s];
316
+ });
317
+ // Their marks format nothing any reader shows: each pair whose start and
318
+ // end lie in one of these streams goes (collected, it keeps its class).
319
+ const tr = doc._transaction;
320
+ for (const s of purged)
321
+ for (const item of regionMarks(s))
322
+ item.delete(tr);
323
+ purgeStreams(purged.filter((s) => s.end - s.start > s.inert.length));
324
+ for (const id of lone)
325
+ deleteClaims(doc, blocks.get(id).claims);
227
326
  for (const id of emptied) {
228
327
  const rec = blocks.get(id);
229
328
  for (const key of [...rec.node.attrKeys()])
230
329
  if (key === DATA || key.startsWith(DATA_LEAF_PREFIX))
231
330
  rec.node.deleteAttr(key);
232
- if (rec.claimsNode !== undefined && rec.claimsNode.length > 0)
233
- rec.claimsNode.delete(0, rec.claimsNode.length);
331
+ deleteClaims(doc, rec.claims);
234
332
  report.emptied++;
235
333
  }
236
334
  // The blocks that go whole: their entries, attribution records and the claims naming them.
@@ -238,18 +336,17 @@ export const bindPurge = (Y) => {
238
336
  const attribution = doc.get(BLOCK_ATTR_ROOT);
239
337
  for (const [id, rec] of blocks) {
240
338
  // An emptied block's claims are gone already (above).
241
- if (removable.has(id) || dead.has(id) || rec.claimsNode === undefined)
339
+ if (removable.has(id) || dead.has(id))
242
340
  continue;
243
- // The claims its list stores (an anchor may show one in another block).
244
- const named = (rec.listClaims ?? rec.claims)
245
- .filter((c) => removable.has(c.m))
246
- .map((c) => c.seqIndex)
247
- .filter((at) => at >= 0);
248
- for (const at of named.sort((a, b) => b - a))
249
- rec.claimsNode.delete(at, 1);
341
+ const named = rec.claims.filter((c) => c.stamp.c >= 0 && removable.has(c.m));
342
+ deleteClaims(doc, named);
250
343
  report.claims += named.length;
251
344
  }
252
345
  for (const id of removable) {
346
+ // Its home slot goes with it: nothing shows it any more.
347
+ const home = blocks.get(id)?.home;
348
+ if (home)
349
+ removeUnit(doc, home);
253
350
  if (isIncarnationId(id)) {
254
351
  // A losing incarnation is no registry value: its subtree goes.
255
352
  // Its node is a deleted value, which the node API writes nothing to:
@@ -264,8 +361,8 @@ export const bindPurge = (Y) => {
264
361
  continue;
265
362
  }
266
363
  registry.deleteAttr(id);
267
- if (attribution.getAttr(`${REC_PREFIX}${id}`) !== undefined)
268
- attribution.deleteAttr(`${REC_PREFIX}${id}`);
364
+ if (attribution.getAttr(id) !== undefined)
365
+ attribution.deleteAttr(id);
269
366
  report.removed++;
270
367
  }
271
368
  // Blocks merged away before the horizon (`room.purge.merged`): live,
@@ -273,10 +370,10 @@ export const bindPurge = (Y) => {
273
370
  // own attribution records go (no history reaches a step below the
274
371
  // horizon to split them out again); their registry entries stay.
275
372
  const claimsOn = new Map();
276
- for (const [holder, rec] of blocks) {
373
+ for (const rec of blocks.values()) {
277
374
  if (rec.deleted)
278
375
  continue;
279
- for (const c of own.claimsOf?.(holder) ?? rec.claims) {
376
+ for (const c of rec.claims) {
280
377
  const list = claimsOn.get(c.m);
281
378
  if (list === undefined)
282
379
  claimsOn.set(c.m, [c]);
@@ -284,40 +381,53 @@ export const bindPurge = (Y) => {
284
381
  list.push(c);
285
382
  }
286
383
  }
287
- const claimedOld = (id) => (claimsOn.get(id) ?? []).every((c) => c.seqIndex >= 0 && old(c.stamp.c, c.stamp.k));
384
+ const claimedOld = (id) => (claimsOn.get(id) ?? []).every((c) => c.stamp.c >= 0 && old(c.stamp.c, c.stamp.k));
288
385
  for (const [id, rec] of blocks) {
289
386
  if (rec.deleted || removable.has(id) || dead.has(id) || isIncarnationId(id))
290
387
  continue;
291
388
  const owner = own.ownerOf(id);
292
389
  if (owner === id || typeof owner !== 'string' || !claimedOld(id))
293
390
  continue;
294
- if (attribution.getAttr(`${REC_PREFIX}${id}`) === undefined)
391
+ if (attribution.getAttr(id) === undefined)
295
392
  continue;
296
- attribution.deleteAttr(`${REC_PREFIX}${id}`);
393
+ attribution.deleteAttr(id);
297
394
  report.merged++;
298
395
  }
299
- // Runner-up candidates of an old winner that stands.
300
- for (const [id, rec] of blocks) {
301
- if (removable.has(id) || rec.cands.length < 2)
302
- continue;
303
- const winner = rec.cands[0];
304
- const at = rec.node.getAttr(AT);
305
- if (!isNodeLike(at) || !oldItem(mapOf(at).get(winner.key)))
306
- continue;
307
- const pl = placements.get(id);
308
- const p = winner.p !== null && !blocks.has(winner.p) ? null : winner.p;
309
- if (pl === undefined || pl.parent !== p || pl.rank !== winner.r)
310
- continue;
311
- for (const c of rec.cands.slice(1))
312
- at.deleteAttr(c.key);
313
- report.candidates += rec.cands.length - 1;
396
+ // Old move records no block shows at (lost to a newer move, or their blocks
397
+ // removed): no undo below the horizon can make them movers again.
398
+ const sequences = [registryOf(doc)];
399
+ for (const [id, rec] of blocks)
400
+ if (!removable.has(id))
401
+ sequences.push(rec.node);
402
+ // A record a block shows at stays, though it is no unit's mover (a cycle
403
+ // sent the block back to it): it is read before any record goes.
404
+ const shownNow = modelView(doc);
405
+ const listed = sequences.map((node) => [node, recordsOf(doc, node, shownNow)]);
406
+ doc.transact((tr) => {
407
+ for (const [node, records] of listed)
408
+ for (const r of records) {
409
+ if (r.wins || !old(r.item.id.client, r.item.id.clock))
410
+ continue;
411
+ ops.remove(tr, r.item);
412
+ dropSearchMarkers(node);
413
+ report.records++;
414
+ }
415
+ });
416
+ // Text hold records past the horizon, with what they hold.
417
+ report.marks = purgeText(doc, freed);
418
+ // Release records the horizon covers: what they released is past it.
419
+ {
420
+ const tr = doc._transaction;
421
+ for (let it = firstItem(doc.get(RELEASE_ROOT)); it; it = it.right) {
422
+ if (it.deleted || !old(it.id.client, it.id.clock + it.length - 1))
423
+ continue;
424
+ it.delete(tr);
425
+ report.released++;
426
+ }
314
427
  }
315
- // Text delete marks and restoration records past the horizon.
316
- const text = purgeText(doc, old);
317
- report.marks = text.marks;
318
- report.records = text.records;
319
428
  // The horizon record, last.
320
- doc.get(HORIZON_ROOT).setAttr(HORIZON_ATTR, { at: horizon.at, sv: horizon.sv });
429
+ if (horizon !== null)
430
+ doc.get(HORIZON_ROOT).setAttr(HORIZON_ATTR, { at: horizon.at, sv: horizon.sv });
321
431
  return report;
322
432
  };
323
433
  return { purge };
@@ -14,8 +14,8 @@
14
14
  * 2. its type and data, per leaf, where they differ;
15
15
  * 3. its place: under its snapshot parent, in the snapshot's order (the
16
16
  * longest run of that parent's children already in order stays; each
17
- * other block gets a placement candidate between its neighbours); a
18
- * snapshot block the registry no longer holds is created there;
17
+ * other block is moved after the one before it); a snapshot block the
18
+ * registry no longer holds is created there;
19
19
  * 4. its content, where it differs: its own claims removed, then its
20
20
  * stream's text replaced through the facade's per-stream delete and
21
21
  * insert, the common prefix and suffix kept;
@@ -1,7 +1,7 @@
1
- import { blockNodeOf, materializeSpec, ranksAt, view as modelView, writePlacement } from './placement/model.js';
1
+ import { blockNodeOf, insertSpecsAt, moveBlocksTo, view as modelView } from './placement/model.js';
2
2
  import { DEL_PREFIX, TYPE, WITHDRAW_PREFIX } from './schema.js';
3
- import { common, patchWrites, writeLeaves } from './data.js';
4
- import { canonKey } from './text/model.js';
3
+ import { common, patchWrites, writeData } from './data.js';
4
+ import { canonKey, deleteClaims } from './text/model.js';
5
5
  import { randOf } from './rand.js';
6
6
  import { toBlockSpec } from '../utils/json.js';
7
7
  /** `items` one unit each (a character with its marks, or an atom), keyed for comparison. */
@@ -117,15 +117,8 @@ export const restoreDocument = (doc, facade, json) => {
117
117
  const { blocks } = modelView(doc);
118
118
  for (const rec of blocks.values()) {
119
119
  // A deleted holder's claims are void (and stay so): only the others.
120
- if (rec.deleted || rec.claimsNode === undefined)
121
- continue;
122
- // The claims its list stores (an anchor may show one in another block).
123
- const named = (rec.listClaims ?? rec.claims)
124
- .filter((claim) => all.has(claim.m))
125
- .map((c) => c.seqIndex)
126
- .filter((at) => at >= 0);
127
- for (const at of named.sort((a, b) => b - a))
128
- rec.claimsNode.delete(at, 1);
120
+ if (!rec.deleted)
121
+ deleteClaims(doc, rec.claims.filter((claim) => all.has(claim.m)));
129
122
  }
130
123
  }
131
124
  // 2 · Type and data, per leaf, where they differ.
@@ -135,7 +128,7 @@ export const restoreDocument = (doc, facade, json) => {
135
128
  continue;
136
129
  if (n.getAttr(TYPE) !== spec.type)
137
130
  n.setAttr(TYPE, spec.type);
138
- writeLeaves(n, patchWrites(n, [{ path: [], value: spec.data ?? {} }], doc.clientID, randOf(doc)) ?? []);
131
+ writeData(n, patchWrites(n, [{ path: [], value: spec.data ?? {} }], doc.clientID, randOf(doc)) ?? []);
139
132
  }
140
133
  // 3 · Places, parent by parent in snapshot order (the root first).
141
134
  const parents = [[null, specs]];
@@ -145,36 +138,28 @@ export const restoreDocument = (doc, facade, json) => {
145
138
  if (list.length === 0)
146
139
  continue;
147
140
  const slots = facade.childSlots(parent);
148
- const index = new Map(slots.map((slot, i) => [slot.id, i]));
149
141
  // What a longest common run of the two orders keeps stays where it is.
150
142
  const kept = new Set(common(slots.map((slot) => slot.id), list.map((spec) => spec.id)).map(([, j]) => j));
151
- let prev;
143
+ let prev = null;
152
144
  list.forEach((spec, i) => {
153
145
  if (kept.has(i)) {
154
- prev = slots[index.get(spec.id)].rank;
146
+ prev = spec.id;
155
147
  return;
156
148
  }
157
- let next;
158
- for (let j = i + 1; j < list.length; j++)
159
- if (kept.has(j)) {
160
- next = slots[index.get(list[j].id)].rank;
161
- break;
162
- }
163
- const bounds = [
164
- ...(prev === undefined ? [] : [{ rank: prev }]),
165
- ...(next === undefined ? [] : [{ rank: next }])
166
- ];
167
- const [rank] = ranksAt(bounds, prev === undefined ? 0 : 1, 1, doc.clientID, randOf(doc));
149
+ const v = modelView(doc);
150
+ // Right after the block before it in the snapshot (the list as it stands, the block itself left out).
151
+ const shown = (v.kids.get(parent) ?? []).map((k) => k.id).filter((id) => id !== spec.id);
152
+ const at = prev === null ? 0 : shown.indexOf(prev) + 1;
168
153
  const n = node(spec.id);
169
154
  if (n === null) {
170
- materializeSpec(doc, { ...spec, children: [] }, parent, rank);
155
+ insertSpecsAt(doc, v, parent, at, [{ ...spec, children: [] }]);
171
156
  report.created++;
172
157
  }
173
158
  else {
174
- writePlacement(doc, n, parent, rank);
159
+ moveBlocksTo(doc, v, [spec.id], parent, at);
175
160
  report.moved++;
176
161
  }
177
- prev = rank;
162
+ prev = spec.id;
178
163
  });
179
164
  }
180
165
  // 4 · Content, where it differs: own claims removed, the stream rewritten.
@@ -183,10 +168,9 @@ export const restoreDocument = (doc, facade, json) => {
183
168
  let have = unitsOf(facade.contentItems(id));
184
169
  if (have.length === want.length && have.every((u, i) => u.key === want[i].key))
185
170
  continue;
186
- const rec = modelView(doc).blocks.get(id);
187
- const claims = rec?.claimsNode;
188
- if (claims !== undefined && claims.length > 0) {
189
- claims.delete(0, claims.length);
171
+ const claims = modelView(doc).blocks.get(id)?.claims ?? [];
172
+ if (claims.some((c) => c.stamp.c >= 0)) {
173
+ deleteClaims(doc, claims);
190
174
  have = unitsOf(facade.contentItems(id));
191
175
  }
192
176
  rewriteContent(facade, id, have, want);