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,26 +1,21 @@
1
- /**
2
- * The write funnel: every facade write goes through `write` (disposal and the
3
- * document's writable guard), and every prepared plan through `apply` — one
4
- * transaction, its result read from what the transaction wrote, and the
5
- * frame's one attribution pass.
6
- */
7
- import { blockNodeOf, buildInline, materializeSpec, ownText, view as modelView, writePlacement, writeSplit } from '../placement/model.js';
8
- import { ENTRY_FACET } from '../text/runs.js';
9
- import { AT, DEL_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
10
- import { writeLeaves } from '../data.js';
1
+ import { blockNodeOf, buildInline, insertSpecsAt, moveBlocksTo, ownText, view as modelView, writeSplit } from '../placement/model.js';
2
+ import { ENTRY_FACET, SEQ_FACET } from '../text/runs.js';
3
+ import { DEL_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
4
+ import { writeData } from '../data.js';
11
5
  import { NOOP } from './plan.js';
12
6
  import { claimInto, deleteRange, formatRangeIn, insertIntoText } from '../text/model.js';
13
7
  /**
14
- * Raised when a mutating facade op runs after `dispose()` — disposal is
15
- * terminal for writes (reads stay dead-safe: a stale handle may still be
16
- * inspected while its document outlives the facade). The facade-level
17
- * counterpart of `DocumentDestroyedError` — kept in this module because a
18
- * bare `bindEdytorDoc` facade has no document layer above it.
8
+ * Raised when an operation runs against a torn-down document: every attach
9
+ * reference released, or its facade disposed (terminal for writes; reads
10
+ * stay dead-safe: a stale handle may still be inspected). Distinct from
11
+ * `DocumentNotReadyError`: destroyed is terminal, pending may still resolve.
12
+ * Kept in this module because a bare `bindEdytorDoc` facade has no document
13
+ * layer above it.
19
14
  */
20
- export class EdytorDocDisposedError extends Error {
15
+ export class DocumentDestroyedError extends Error {
21
16
  constructor(service) {
22
- super(`EdytorDoc${service ? `.${service}` : ''}: facade is disposed.`);
23
- this.name = 'EdytorDocDisposedError';
17
+ super(`${service ?? 'document'}: the document is destroyed`);
18
+ this.name = 'DocumentDestroyedError';
24
19
  }
25
20
  }
26
21
  /** The write funnel of one facade. */
@@ -37,7 +32,7 @@ export const writeFunnel = (c) => {
37
32
  /** Mutation boundary — every facade write funnels through `write`. */
38
33
  const write = (fn) => {
39
34
  if (disposed) {
40
- throw new EdytorDocDisposedError();
35
+ throw new DocumentDestroyedError();
41
36
  }
42
37
  config.assertWritable?.();
43
38
  return fn();
@@ -54,8 +49,8 @@ export const writeFunnel = (c) => {
54
49
  // Each apply opens a frame that tracks the index's folds. When it
55
50
  // closes, ONE pass over the facets the fold saw stamps attribution: a
56
51
  // block whose registry entry was created gets its `createdBy` record; a block whose content, claims, type or data
57
- // changed gets a contributor stamp; moves and delete marks stamp
58
- // nothing. Two intents the effects cannot name are recorded by their
52
+ // changed gets a contributor stamp; moves (a record or a slot in a
53
+ // block's sequence) and delete marks stamp nothing. Two intents the effects cannot name are recorded by their
59
54
  // steps: a split-born block inherits its source's contributors, and a
60
55
  // merge survivor unions the absorbed block's. With no configured
61
56
  // `actor` the funnel writes no attribution at all.
@@ -73,9 +68,12 @@ export const writeFunnel = (c) => {
73
68
  else
74
69
  for (const facet of facets)
75
70
  if (!facet.startsWith(DEL_PREFIX) &&
76
- ![ENTRY_FACET, AT, ID, LAST_CHANGED_ATTR].includes(facet))
71
+ ![ENTRY_FACET, SEQ_FACET, ID, LAST_CHANGED_ATTR].includes(facet))
77
72
  changed.add(id);
78
73
  }
74
+ // A merge changed its survivor (its claim item, written quietly, is no edit of the text holding it).
75
+ for (const [into] of f.unions)
76
+ changed.add(into);
79
77
  for (const id of created) {
80
78
  const node = blockNodeOf(doc, id);
81
79
  if (node !== null)
@@ -92,38 +90,46 @@ export const writeFunnel = (c) => {
92
90
  /**
93
91
  * A streamless block gets its own text before the first write that
94
92
  * needs a stream (`ownText`: a writer derived from its dead
95
- * incarnation); its attribution record follows the re-minted nonce.
93
+ * incarnation); its attribution record follows the re-minted nonce. A
94
+ * claim item needs the block's own stream (`claim`); text, any piece of
95
+ * its display.
96
96
  */
97
- const needStream = (id) => {
98
- if ((modelView(doc).own.display(id) ?? []).length > 0)
97
+ const needStream = (id, claim = false) => {
98
+ const { own } = modelView(doc);
99
+ if (claim ? own.streamOf(id) !== undefined : (own.display(id) ?? []).length > 0)
99
100
  return;
100
101
  const { from, to } = ownText(doc, id);
101
102
  BA.retarget(doc, id, from, to);
102
103
  };
103
104
  /** One planned step, written (the plan decided it; writers never refuse). */
104
105
  const writeStep = (w, f) => {
105
- // Structural steps need no view: delete marks and placements write one node.
106
+ // Delete marks need no view: they write one node.
106
107
  if (w.op === 'deleteBlock')
107
108
  return w.marks.forEach((id) => blockNodeOf(doc, id).setAttr(DEL_PREFIX + doc.clientID, true));
108
109
  if (w.op === 'splitBlock' || w.op === 'insertText' || w.op === 'insertInline')
109
110
  needStream(w.id);
110
- const { blocks, own } = modelView(doc);
111
+ // A claim item goes at the end of the stream of the block merged into.
112
+ if (w.op === 'mergeBlocks')
113
+ needStream(w.into, true);
114
+ const v = modelView(doc);
115
+ const { blocks, own } = v;
111
116
  const node = (id) => blockNodeOf(doc, id);
112
117
  switch (w.op) {
113
118
  case 'insertBlocks':
114
- return w.specs.forEach((sp, i) => materializeSpec(doc, sp, w.parent, w.ranks[i]));
119
+ return insertSpecsAt(doc, v, w.parent, w.index, w.specs, w.split === undefined ? null : (f.bounds.get(w.split) ?? null));
115
120
  case 'moveBlocks':
116
- return w.ids.forEach((id, i) => writePlacement(doc, node(id), w.parent, w.ranks[i]));
121
+ return moveBlocksTo(doc, v, w.ids, w.parent, w.index, w.side ?? 0, w.part ?? 0, w.at ?? null);
117
122
  case 'splitBlock':
118
123
  f.inherit.set(w.newId, w.id);
119
- return writeSplit(doc, w.id, w.offset, w.newId, w.tail, { p: w.parent, r: w.rank });
124
+ f.bounds.set(w.newId, writeSplit(doc, w.id, w.offset, w.newId, w.tail, w.parent, w.index));
125
+ return;
120
126
  case 'mergeBlocks':
121
127
  f.unions.push([w.into, w.from]);
122
- return claimInto(blocks, own, w.from, w.into);
128
+ return f.quiet(() => claimInto(own, w.from, w.into));
123
129
  case 'setBlockType':
124
130
  return void node(w.id).setAttr(TYPE, w.type);
125
131
  case 'patchData':
126
- return writeLeaves(dataNode(w.id, w.inlineId), w.leaves);
132
+ return writeData(dataNode(w.id, w.inlineId), w.writes);
127
133
  case 'insertText':
128
134
  return insertIntoText(doc, blocks, own, w.id, w.offset, w.text, w.marks);
129
135
  case 'insertInline':
@@ -149,7 +155,7 @@ export const writeFunnel = (c) => {
149
155
  }
150
156
  return write(() => doc.transact(() => {
151
157
  const frame = runsView.track();
152
- const f = { inherit: new Map(), unions: [] };
158
+ const f = { inherit: new Map(), bounds: new Map(), unions: [], quiet: frame.quiet };
153
159
  try {
154
160
  for (const w of p.writes)
155
161
  writeStep(w, f);
@@ -17,15 +17,15 @@
17
17
  *
18
18
  * ```
19
19
  * doc.get('blocks') registry — flat map, blockId → node('block')
20
- * └ <blockId> id/n/type/data/del + content/claims/at
21
- * (n: incarnation nonce)
20
+ * └ <blockId> n/type/d/…/del./wd./l + content
21
+ * (n: incarnation nonce; the id is the key)
22
22
  * doc.get('meta') version record root
23
23
  * ├ v : number SCHEMA_VERSION (LWW attr — concurrent init converges)
24
24
  * └ schema : 'edytor-doc' SCHEMA_NAME
25
25
  * ```
26
26
  */
27
27
  import type { EngineDoc } from '../engine-api.js';
28
- export declare const SCHEMA_VERSION: 6;
28
+ export declare const SCHEMA_VERSION: 10;
29
29
  export declare const SCHEMA_NAME: "edytor-doc";
30
30
  export declare const META_KEY: "meta";
31
31
  /**
@@ -86,20 +86,3 @@ export declare class SchemaMismatchError extends Error {
86
86
  * mutating a synced document.
87
87
  */
88
88
  export declare const assertSchema: (doc: EngineDoc, docName?: string) => void;
89
- /**
90
- * Error raised by {@link assertUsableDoc} — the doc cannot host a v14 facade:
91
- * a foreign engine object (a v13 `yjs` Doc — a different CRDT implementation
92
- * entirely).
93
- */
94
- export declare class UnsupportedDocError extends Error {
95
- readonly kind: 'foreign';
96
- constructor(kind: 'foreign');
97
- }
98
- /**
99
- * Document-boundary guard run by {@link EdytorDocBinding.create} before the
100
- * runs view attaches. The facade only speaks the v14 unified-node surface —
101
- * without this gate a foreign doc dies obscurely inside `buildView`
102
- * (`registry.forEachAttr is not a function`); it fails fast with an
103
- * actionable error instead.
104
- */
105
- export declare const assertUsableDoc: (doc: EngineDoc) => void;
@@ -1,4 +1,4 @@
1
- import { isNodeLike, SCHEMA } from '../schema.js';
1
+ import { SCHEMA } from '../schema.js';
2
2
  export const SCHEMA_VERSION = SCHEMA.version;
3
3
  export const SCHEMA_NAME = SCHEMA.name;
4
4
  export const META_KEY = SCHEMA.roots.meta;
@@ -51,13 +51,7 @@ export class SchemaMismatchError extends Error {
51
51
  docName;
52
52
  problem;
53
53
  constructor(docName, problem) {
54
- super(problem.kind === 'unversioned'
55
- ? `Document "${docName}" carries replicated registry state but no meta.v schema version — refusing to treat it as initialized.`
56
- : problem.kind === 'unsupported'
57
- ? `Document "${docName}" claims unsupported schema version ${problem.version} (this build speaks ${SCHEMA_VERSION}).`
58
- : problem.schema === undefined
59
- ? `Document "${docName}" carries meta.v=${problem.version} but no meta.schema manifest name — refusing it as an "${SCHEMA_NAME}" document.`
60
- : `Document "${docName}" claims foreign schema "${String(problem.schema)}" (this build speaks "${SCHEMA_NAME}").`);
54
+ super(`${docName}: ${problem.kind} schema version ${problem.version} "${String(problem.schema)}" (this build speaks ${SCHEMA_VERSION} "${SCHEMA_NAME}")`);
61
55
  this.docName = docName;
62
56
  this.problem = problem;
63
57
  this.name = 'SchemaMismatchError';
@@ -73,36 +67,3 @@ export const assertSchema = (doc, docName = 'doc') => {
73
67
  if (problem !== null)
74
68
  throw new SchemaMismatchError(docName, problem);
75
69
  };
76
- /**
77
- * Error raised by {@link assertUsableDoc} — the doc cannot host a v14 facade:
78
- * a foreign engine object (a v13 `yjs` Doc — a different CRDT implementation
79
- * entirely).
80
- */
81
- export class UnsupportedDocError extends Error {
82
- kind;
83
- constructor(kind) {
84
- super('Document is not a v14 engine doc — the `blocks` registry is not a ' +
85
- 'unified Y.Node. Use `crdt.createDoc()` (or `new Y.Doc()` from `edytor/crdt`).');
86
- this.kind = kind;
87
- this.name = 'UnsupportedDocError';
88
- }
89
- }
90
- /**
91
- * Document-boundary guard run by {@link EdytorDocBinding.create} before the
92
- * runs view attaches. The facade only speaks the v14 unified-node surface —
93
- * without this gate a foreign doc dies obscurely inside `buildView`
94
- * (`registry.forEachAttr is not a function`); it fails fast with an
95
- * actionable error instead.
96
- */
97
- export const assertUsableDoc = (doc) => {
98
- let registry;
99
- try {
100
- registry = typeof doc?.get === 'function' ? doc.get(SCHEMA.roots.registry) : undefined;
101
- }
102
- catch {
103
- registry = undefined;
104
- }
105
- if (!isNodeLike(registry) || typeof registry.forEachAttr !== 'function') {
106
- throw new UnsupportedDocError('foreign');
107
- }
108
- };
@@ -1,5 +1,4 @@
1
1
  import type { EngineApi, EngineDoc, EngineNode } from '../engine-api.js';
2
- import type { TextDeletes } from '../text/deletes.js';
3
2
  import { type IdSetOf, type StoreStruct } from '../structs.js';
4
3
  import { type WriteFunnel } from './funnel.js';
5
4
  import type { DocBase } from './reads.js';
@@ -33,15 +32,12 @@ export type HistoryOptions = {
33
32
  }) => boolean;
34
33
  };
35
34
  /** What a history is made over: the document and the rules of its replay. */
36
- type Rules = {
35
+ export type Rules = {
37
36
  Y: EngineApi;
38
37
  doc: EngineDoc;
39
38
  scope: EngineNode[];
40
- /** The text delete marks' restore and apply rules (`text/deletes.ts`). */
41
- marks: {
42
- restoreFilter(item: unknown): boolean;
43
- onApply(tr: unknown, step: StackItem): void;
44
- };
39
+ /** The records list a replay's text holds go to (fork patch YP20). */
40
+ records: EngineNode;
45
41
  /** Whether an item a replay would delete is withdrawn instead (`hist.undo.withdraw`). */
46
42
  withdraw(item: StoreStruct, step: StackItem): boolean;
47
43
  /** Repair the attrs a replay left undefined. */
@@ -85,16 +81,36 @@ export declare class UndoManager {
85
81
  redo(): StackItem | null;
86
82
  /** Drop every step (undo and redo) and release what they kept for their replay. */
87
83
  clear(): void;
84
+ /**
85
+ * The session ends: its page left for good (`hist.release.end`). Every
86
+ * step is dropped and released as a dropped step is (`#release`: what
87
+ * they kept is collected, the text this writer's records hold is
88
+ * deleted for good), in one transaction that, when a step marked a block
89
+ * deleted or withdrawn, also appends one release record (the
90
+ * {@link RELEASE_ROOT} list): its id names this writer and the clock the
91
+ * history ended at, so the room's purge removes what those marks hide at
92
+ * its next tick, past the horizon or not. Then the manager stops
93
+ * capturing (it is destroyed; the document attaches a fresh one if asked).
94
+ * A history that captured nothing writes nothing. Only for a page that
95
+ * cannot come back: a page the back/forward cache keeps, or one that
96
+ * only lost its connection, keeps its history.
97
+ */
98
+ end(): void;
88
99
  destroy: () => void;
89
100
  }
90
101
  /** What a facade's history is made over: its doc, the write funnel and the bound engine layers. */
91
102
  export type HistoryContext = DocBase & Pick<WriteFunnel, 'write' | 'disposed'> & {
92
- D: TextDeletes;
93
103
  /** Stamp the version record before the history attaches. */
94
104
  init: (doc: EngineDoc) => void;
95
105
  };
106
+ /**
107
+ * The document's history rules over `doc` (the one set every history of an
108
+ * edytor document runs): its scope (the block registry, the text hold
109
+ * records, the document's data), the records a replay's text holds go to,
110
+ * the withdraw rule (`hist.undo.withdraw`) and the attr repair below.
111
+ */
112
+ export declare const historyRules: (Y: EngineApi, doc: EngineDoc) => Rules;
96
113
  /** The history factory of one facade. */
97
114
  export declare const docHistory: (c: HistoryContext) => {
98
115
  createUndoManager: (options?: HistoryOptions) => UndoManager;
99
116
  };
100
- export {};
@@ -1,21 +1,24 @@
1
1
  /**
2
2
  * The document's history: the one undo manager (fork patch YP18 removed the
3
3
  * engine's). It captures the tracked local transactions that write in its
4
- * scope (the block registry, the text delete marks, the document's data)
4
+ * scope (the block registry, the text hold records, the document's data)
5
5
  * into steps, and an undo or a redo replays a step in one transaction over
6
- * the engine's struct primitives (`redoItem`, `keepItem`). Its rules: text
7
- * comes back as the delete marks allow (`hist.undo.restore`), an undone
6
+ * the engine's struct primitives (`redoItem`, `keepItem`). Its rules: a text
7
+ * delete is a hold record (fork patch YP20), so undoing it deletes the record
8
+ * and the text shows again unless another writer's record holds it
9
+ * (`hist.undo.restore`); undoing typing holds the typed text; an undone
8
10
  * creation is withdrawn (`hist.undo.withdraw`), an overwritten attr is
9
- * repaired, the stack keeps `limit` steps, and the purge horizon drops the
10
- * steps below it (`hist.purge.horizon`).
11
+ * repaired, the stack keeps `limit` steps, the purge horizon drops the
12
+ * steps below it (`hist.purge.horizon`), and a session's end releases them
13
+ * all (`hist.release.end`).
11
14
  */
12
15
  import { getUnixTime } from 'lib0-v14/time';
13
- import { ownTextIds } from '../text/model.js';
16
+ import { openSteps, ownTextIds } from '../text/model.js';
14
17
  import { readHorizon } from '../purge.js';
15
- import { BLOCK_NODE, DATA_LEAF_PREFIX, DOC_DATA_ROOT, HORIZON_ROOT, INLINE_NODE, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
18
+ import { BLOCK_NODE, CONTENT_NODE, DATA_LEAF_PREFIX, DEL_PREFIX, DOC_DATA_ROOT, HORIZON_ROOT, INLINE_NODE, LAST_CHANGED_ATTR, RELEASE_ROOT, TEXT_DELETES_ROOT, TYPE, WITHDRAW_PREFIX } from '../schema.js';
16
19
  import { changedUnder, collectable, collectNow, collects, dropSearchMarkers, engineOps, walkIdSet } from '../structs.js';
17
20
  import { isInitialized } from './gate.js';
18
- import { EdytorDocDisposedError } from './funnel.js';
21
+ import { DocumentDestroyedError } from './funnel.js';
19
22
  import { registryOf, withdrawOnUndo } from '../placement/model.js';
20
23
  /** The undo steps a document's history keeps by default: older ones are released. */
21
24
  export const DEFAULT_HISTORY_LIMIT = 200;
@@ -37,6 +40,13 @@ const REPAIRED = {
37
40
  [BLOCK_NODE]: [TYPE, LAST_CHANGED_ATTR],
38
41
  [INLINE_NODE]: [TYPE]
39
42
  };
43
+ /** A unit of a block's text: a character or an inline atom (what a hold record holds). */
44
+ const isUnit = (it) => {
45
+ const content = it.content;
46
+ return (it.parentSub === null &&
47
+ it.parent?.name === CONTENT_NODE &&
48
+ (typeof content?.str === 'string' || content?.type?.name === INLINE_NODE));
49
+ };
40
50
  /**
41
51
  * A document's undo manager: the undo and redo stacks of the tracked local
42
52
  * transactions in its scope. `undo()`/`redo()` replay the top step and
@@ -64,6 +74,10 @@ export class UndoManager {
64
74
  /** What dropped steps released (an item is released once every step that deleted it is gone). */
65
75
  #released;
66
76
  #horizon;
77
+ /** A captured step wrote a block's delete or withdraw mark: the session's end records its release. */
78
+ #marked = false;
79
+ /** The session ended (`end()`): nothing more is released. */
80
+ #ended = false;
67
81
  constructor(rules, options = {}) {
68
82
  this.#rules = rules;
69
83
  this.#ops = engineOps(rules.Y);
@@ -78,7 +92,19 @@ export class UndoManager {
78
92
  this.trackedOrigins.add(this);
79
93
  this.#ops.on(rules.doc, 'afterTransaction', this.#afterTransaction);
80
94
  this.#ops.on(rules.doc, 'destroy', this.destroy);
95
+ const open = openSteps.get(rules.doc) ?? new Set();
96
+ openSteps.set(rules.doc, open.add(this.#open));
81
97
  }
98
+ /** What the step still capturing inserted (`null`: none is open): a text delete there removes. */
99
+ #open = () => {
100
+ const top = this.undoStack.at(-1);
101
+ const open = top !== undefined &&
102
+ !this.undoing &&
103
+ !this.redoing &&
104
+ this.lastChange > 0 &&
105
+ getUnixTime() - this.lastChange < this.captureTimeout;
106
+ return open ? top.inserts : null;
107
+ };
82
108
  /** Be told of every step taken into a stack (added, or the open one updated). Returns the unsubscribe. */
83
109
  observe(f) {
84
110
  this.#observers.add(f);
@@ -118,8 +144,39 @@ export class UndoManager {
118
144
  clear() {
119
145
  this.#release([...this.undoStack.splice(0), ...this.redoStack.splice(0)]);
120
146
  }
147
+ /**
148
+ * The session ends: its page left for good (`hist.release.end`). Every
149
+ * step is dropped and released as a dropped step is (`#release`: what
150
+ * they kept is collected, the text this writer's records hold is
151
+ * deleted for good), in one transaction that, when a step marked a block
152
+ * deleted or withdrawn, also appends one release record (the
153
+ * {@link RELEASE_ROOT} list): its id names this writer and the clock the
154
+ * history ended at, so the room's purge removes what those marks hide at
155
+ * its next tick, past the horizon or not. Then the manager stops
156
+ * capturing (it is destroyed; the document attaches a fresh one if asked).
157
+ * A history that captured nothing writes nothing. Only for a page that
158
+ * cannot come back: a page the back/forward cache keeps, or one that
159
+ * only lost its connection, keeps its history.
160
+ */
161
+ end() {
162
+ if (this.#ended)
163
+ return;
164
+ this.#ended = true;
165
+ const dropped = [...this.undoStack.splice(0), ...this.redoStack.splice(0)];
166
+ const marked = this.#marked;
167
+ if (dropped.length > 0 || marked)
168
+ this.doc.transact(() => {
169
+ this.#release(dropped);
170
+ if (marked) {
171
+ const records = this.doc.get(RELEASE_ROOT);
172
+ records.insert(records.length, [true]);
173
+ }
174
+ }, HISTORY_TRIM);
175
+ this.destroy();
176
+ }
121
177
  destroy = () => {
122
178
  this.trackedOrigins.delete(this);
179
+ openSteps.get(this.doc)?.delete(this.#open);
123
180
  this.#ops.off(this.doc, 'afterTransaction', this.#afterTransaction);
124
181
  this.#ops.off(this.doc, 'destroy', this.destroy);
125
182
  this.#observers.clear();
@@ -164,6 +221,14 @@ export class UndoManager {
164
221
  stack.push(new StackItem(tr.insertSet, tr.deleteSet));
165
222
  if (!undoing && !redoing)
166
223
  this.lastChange = now;
224
+ // A block's delete or withdraw mark: what it hides waits for this
225
+ // history (its end releases it to the purge, `end()`).
226
+ if (!this.#marked)
227
+ for (const keys of tr.changed.values())
228
+ for (const key of keys)
229
+ if (typeof key === 'string' &&
230
+ (key.startsWith(DEL_PREFIX) || key.startsWith(WITHDRAW_PREFIX)))
231
+ this.#marked = true;
167
232
  // What the step deleted is kept from collection while a step may bring it back.
168
233
  ops.iterate(tr, tr.deleteSet, (item) => {
169
234
  if (ops.isItem(item) && this.#inScope(item))
@@ -190,13 +255,14 @@ export class UndoManager {
190
255
  }
191
256
  /**
192
257
  * Replay the top step of `stack` in one transaction (origin: this
193
- * manager): what it inserted is deleted (or withdrawn), what it deleted
194
- * comes back (text as its delete marks allow), the overwritten attrs are
258
+ * manager): what it inserted is deleted (text: held by a record of this
259
+ * writer; a block: withdrawn), what it deleted comes back (a text delete
260
+ * was a record: deleting it shows the text), the overwritten attrs are
195
261
  * repaired. A step that changes nothing is skipped for the one below.
196
262
  */
197
263
  #pop(stack) {
198
264
  const ops = this.#ops;
199
- const { marks, withdraw, repair } = this.#rules;
265
+ const { records, withdraw, repair } = this.#rules;
200
266
  const deletedByHistory = (id) => [this.undoStack, this.redoStack].some((s) => s.some((step) => step.deletes.has(id.client, id.clock)));
201
267
  this.doc.transact((transaction) => {
202
268
  const tr = transaction;
@@ -204,11 +270,18 @@ export class UndoManager {
204
270
  const step = stack.pop();
205
271
  const restore = new Set();
206
272
  const remove = [];
273
+ const held = [];
207
274
  let changed = false;
208
275
  ops.iterate(tr, step.inserts, (struct) => {
209
276
  if (!ops.isItem(struct))
210
277
  return;
211
278
  const item = ops.latest(tr, struct);
279
+ // An atom the step inserted is held whole: its attrs stay with it.
280
+ const atom = item.parent?._item;
281
+ if (atom?.id &&
282
+ isUnit(atom) &&
283
+ step.inserts.has(atom.id.client, atom.id.clock))
284
+ return;
212
285
  if (!item.deleted && this.#inScope(item))
213
286
  remove.push(item);
214
287
  });
@@ -218,25 +291,27 @@ export class UndoManager {
218
291
  // Created and deleted within the step: nothing to bring back.
219
292
  if (step.inserts.has(struct.id.client, struct.id.clock))
220
293
  return;
221
- // Text comes back through the delete marks (`onApply`): withheld here.
222
- if (!marks.restoreFilter(struct))
223
- changed = true;
224
- else
225
- restore.add(struct);
294
+ // Text a record holds stays hidden: the record decides (removed with its node).
295
+ if ((struct.holds ?? 0) > 0)
296
+ return;
297
+ restore.add(struct);
226
298
  });
227
299
  for (const item of restore)
228
300
  changed = ops.redo(tr, item, restore, step.inserts, deletedByHistory) !== null || changed;
229
301
  // Children before parents: more is known when an item is judged.
230
302
  for (let i = remove.length - 1; i >= 0; i--) {
231
- if (!withdraw(remove[i], step))
232
- ops.remove(tr, remove[i]);
303
+ const item = remove[i];
304
+ // Text the step wrote is held, never removed: a redo shows it again where it was.
305
+ if (isUnit(item))
306
+ held.push(item.id.client, item.id.clock, item.length);
307
+ else if (!withdraw(item, step))
308
+ ops.remove(tr, item);
233
309
  changed = true;
234
310
  }
311
+ records.hold(held);
235
312
  this.currStackItem = changed ? step : null;
236
- if (changed) {
237
- marks.onApply(tr, step);
313
+ if (changed)
238
314
  repair(step);
239
- }
240
315
  }
241
316
  tr.changed.forEach((keys, node) => {
242
317
  if (keys.has(null))
@@ -250,8 +325,8 @@ export class UndoManager {
250
325
  /**
251
326
  * Release what dropped steps kept for their replay: the engine collects
252
327
  * that content now, as it would have at the delete without a history
253
- * (the doc's `gcFilter` still decides: a text copy another replica may
254
- * have to copy again stays, `text/deletes.ts`). An item is released only
328
+ * (the doc's `gcFilter` still decides), and the text their hold records
329
+ * hold is deleted for good. An item is released only
255
330
  * once every step that deleted part of it was dropped (the engine merges
256
331
  * deleted items across steps): never split, so the store keeps its
257
332
  * merged items. Only the items themselves are released: a kept
@@ -269,6 +344,8 @@ export class UndoManager {
269
344
  return (released.clients.get(st.id.client)?.getIds() ?? []).some((r) => r.clock <= st.id.clock && end <= r.clock + r.len);
270
345
  };
271
346
  const gc = collects(doc);
347
+ const ops = this.#ops;
348
+ const { records } = this.#rules;
272
349
  doc.transact((tr) => {
273
350
  for (const step of dropped)
274
351
  walkIdSet(Y, doc, step.deletes, (st) => {
@@ -279,6 +356,32 @@ export class UndoManager {
279
356
  if (gc && it.deleted && collectable(doc, it))
280
357
  collectNow(it, tr);
281
358
  });
359
+ // A dropped step's text deletes can never be undone here: what this
360
+ // writer's live records hold is deleted for good, as the purge does,
361
+ // and the engine collects it (`hist.delete-marks.release`). A record
362
+ // a captured remote frame wrote (the room's validation) is its
363
+ // writer's to take back.
364
+ const own = ops.idSet();
365
+ for (const step of dropped)
366
+ walkIdSet(Y, doc, step.inserts, (st, from, to) => {
367
+ if (st.parent === records && !st.deleted && st.id.client === doc.clientID)
368
+ own.add(st.id.client, from, to - from);
369
+ });
370
+ const held = ops.idSet();
371
+ ops.iterate(tr, own, (st) => {
372
+ const ids = st.content?.ids;
373
+ if (st.deleted || ids === undefined)
374
+ return;
375
+ for (let i = 0; i < ids.length; i += 3)
376
+ held.add(ids[i], ids[i + 1], ids[i + 2]);
377
+ ops.remove(tr, st);
378
+ });
379
+ ops.iterate(tr, held, (it) => {
380
+ if (it.removed !== false)
381
+ return;
382
+ ops.remove(tr, it);
383
+ dropSearchMarkers(it.parent);
384
+ });
282
385
  }, HISTORY_TRIM);
283
386
  }
284
387
  /**
@@ -310,9 +413,13 @@ export class UndoManager {
310
413
  this.#release(dropped);
311
414
  }
312
415
  }
313
- /** The history factory of one facade. */
314
- export const docHistory = (c) => {
315
- const { Y, doc, D, init, write, disposed } = c;
416
+ /**
417
+ * The document's history rules over `doc` (the one set every history of an
418
+ * edytor document runs): its scope (the block registry, the text hold
419
+ * records, the document's data), the records a replay's text holds go to,
420
+ * the withdraw rule (`hist.undo.withdraw`) and the attr repair below.
421
+ */
422
+ export const historyRules = (Y, doc) => {
316
423
  /**
317
424
  * Undo repair, inside the replay's transaction. A replayed step
318
425
  * deletes its own attr write and re-creates the value that write
@@ -350,9 +457,25 @@ export const docHistory = (c) => {
350
457
  node.setAttr(key, value);
351
458
  }
352
459
  };
460
+ // The text hold records are in scope (an undo deletes the undoer's
461
+ // own, fork patch YP20). An undone creation withdraws the block instead
462
+ // of deleting it (`hist.undo.withdraw`).
463
+ const records = doc.get(TEXT_DELETES_ROOT);
464
+ return {
465
+ Y,
466
+ doc,
467
+ scope: [registryOf(doc), records, doc.get(DOC_DATA_ROOT)],
468
+ records,
469
+ withdraw: withdrawOnUndo(doc),
470
+ repair: repairAttrs
471
+ };
472
+ };
473
+ /** The history factory of one facade. */
474
+ export const docHistory = (c) => {
475
+ const { Y, doc, init, write, disposed } = c;
353
476
  /**
354
477
  * The document's undo manager, SCOPED TO THE BLOCK REGISTRY (with the
355
- * text delete marks and the document's data), attached only after the
478
+ * text hold records and the document's data), attached only after the
356
479
  * doc carries the schema version record:
357
480
  *
358
481
  * - the `meta` root (version stamp, schema name) is outside the scope,
@@ -367,26 +490,13 @@ export const docHistory = (c) => {
367
490
  */
368
491
  const createUndoManager = (options = {}) => {
369
492
  if (disposed()) {
370
- throw new EdytorDocDisposedError('createUndoManager');
493
+ throw new DocumentDestroyedError('createUndoManager');
371
494
  }
372
495
  write(() => {
373
496
  if (!isInitialized(doc))
374
497
  init(doc);
375
498
  });
376
- // Text delete marks (`text/deletes.ts`): the marks are in scope (an undo
377
- // removes the undoer's own), and the history restores text only as the
378
- // marks allow. An undone creation withdraws the block instead of
379
- // deleting it (`hist.undo.withdraw`).
380
- const marks = D.history(doc, () => um);
381
- const um = new UndoManager({
382
- Y,
383
- doc,
384
- scope: [registryOf(doc), D.scope(doc), doc.get(DOC_DATA_ROOT)],
385
- marks,
386
- withdraw: withdrawOnUndo(doc),
387
- repair: repairAttrs
388
- }, options);
389
- return um;
499
+ return new UndoManager(historyRules(Y, doc), options);
390
500
  };
391
501
  return { createUndoManager };
392
502
  };