edytor 0.0.11 → 0.1.0-next.16

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 (371) hide show
  1. package/README.md +77 -197
  2. package/dist/block/block.svelte.d.ts +156 -69
  3. package/dist/block/block.svelte.js +324 -355
  4. package/dist/block/block.utils.d.ts +191 -24
  5. package/dist/block/block.utils.js +327 -460
  6. package/dist/block/contentRange.d.ts +4 -0
  7. package/dist/block/contentRange.js +20 -0
  8. package/dist/block/inlineBlock.svelte.d.ts +26 -19
  9. package/dist/block/inlineBlock.svelte.js +91 -39
  10. package/dist/clipboard/clipboard.d.ts +4 -0
  11. package/dist/clipboard/clipboard.js +4 -0
  12. package/dist/clipboard/createClipboardFragment.d.ts +3 -0
  13. package/dist/clipboard/createClipboardFragment.js +103 -0
  14. package/dist/clipboard/fragmentData.d.ts +6 -0
  15. package/dist/clipboard/fragmentData.js +74 -0
  16. package/dist/clipboard/htmlFlow.d.ts +22 -0
  17. package/dist/clipboard/htmlFlow.js +167 -0
  18. package/dist/clipboard/insertClipboardFragment.d.ts +18 -0
  19. package/dist/clipboard/insertClipboardFragment.js +48 -0
  20. package/dist/clipboard/serializeClipboardFragment.d.ts +7 -0
  21. package/dist/clipboard/serializeClipboardFragment.js +53 -0
  22. package/dist/clipboard/textBlocks.d.ts +23 -0
  23. package/dist/clipboard/textBlocks.js +103 -0
  24. package/dist/clipboard/types.d.ts +20 -0
  25. package/dist/clipboard/types.js +2 -0
  26. package/dist/cloudflare/DocumentRoom.d.ts +586 -0
  27. package/dist/cloudflare/DocumentRoom.js +1706 -0
  28. package/dist/cloudflare/index.d.ts +8 -0
  29. package/dist/cloudflare/index.js +8 -0
  30. package/dist/cloudflare/routeDocumentSocket.d.ts +33 -0
  31. package/dist/cloudflare/routeDocumentSocket.js +51 -0
  32. package/dist/collaboration/RemoteSelections.svelte +94 -0
  33. package/dist/collaboration/RemoteSelections.svelte.d.ts +7 -0
  34. package/dist/collaboration/awarenessSelection.d.ts +127 -0
  35. package/dist/collaboration/awarenessSelection.js +199 -0
  36. package/dist/collaboration/documentSync.d.ts +20 -0
  37. package/dist/collaboration/documentSync.js +13 -0
  38. package/dist/collaboration/index.d.ts +3 -0
  39. package/dist/collaboration/index.js +3 -0
  40. package/dist/collaboration/providers.d.ts +13 -0
  41. package/dist/collaboration/providers.js +21 -0
  42. package/dist/collaboration/remoteSelection.d.ts +21 -0
  43. package/dist/collaboration/remoteSelection.js +159 -0
  44. package/dist/components/Block.svelte +223 -15
  45. package/dist/components/Block.svelte.d.ts +4 -2
  46. package/dist/components/Content.svelte +128 -32
  47. package/dist/components/Content.svelte.d.ts +6 -2
  48. package/dist/components/Edytor.svelte +308 -110
  49. package/dist/components/Edytor.svelte.d.ts +64 -20
  50. package/dist/components/InlineBlock.svelte +38 -7
  51. package/dist/components/InlineBlock.svelte.d.ts +5 -2
  52. package/dist/components/Mark.svelte +29 -13
  53. package/dist/components/Mark.svelte.d.ts +4 -4
  54. package/dist/components/Suggestion.svelte +48 -0
  55. package/dist/components/Suggestion.svelte.d.ts +7 -0
  56. package/dist/components/SuggestionRanges.svelte +58 -0
  57. package/dist/components/SuggestionRanges.svelte.d.ts +7 -0
  58. package/dist/components/Text.svelte +107 -14
  59. package/dist/components/Text.svelte.d.ts +8 -1
  60. package/dist/constants.d.ts +0 -2
  61. package/dist/constants.js +0 -2
  62. package/dist/crdt/admission.d.ts +141 -0
  63. package/dist/crdt/admission.js +147 -0
  64. package/dist/crdt/anchors.d.ts +47 -0
  65. package/dist/crdt/anchors.js +42 -0
  66. package/dist/crdt/attribution/attribution.d.ts +169 -0
  67. package/dist/crdt/attribution/attribution.js +136 -0
  68. package/dist/crdt/attribution/block.d.ts +200 -0
  69. package/dist/crdt/attribution/block.js +327 -0
  70. package/dist/crdt/attribution/index.d.ts +9 -0
  71. package/dist/crdt/attribution/index.js +9 -0
  72. package/dist/crdt/data.d.ts +81 -0
  73. package/dist/crdt/data.js +383 -0
  74. package/dist/crdt/document.d.ts +590 -0
  75. package/dist/crdt/document.js +1160 -0
  76. package/dist/crdt/edytor-doc.d.ts +752 -0
  77. package/dist/crdt/edytor-doc.js +2382 -0
  78. package/dist/crdt/engine-api.d.ts +153 -0
  79. package/dist/crdt/engine.d.ts +37 -0
  80. package/dist/crdt/engine.js +50 -0
  81. package/dist/crdt/flow.d.ts +104 -0
  82. package/dist/crdt/flow.js +229 -0
  83. package/dist/crdt/index.d.ts +630 -0
  84. package/dist/crdt/index.js +168 -0
  85. package/dist/crdt/migration/legacy-schema.d.ts +61 -0
  86. package/dist/crdt/migration/legacy-schema.js +149 -0
  87. package/dist/crdt/migration/migrate.d.ts +67 -0
  88. package/dist/crdt/migration/migrate.js +219 -0
  89. package/dist/crdt/nodes.d.ts +120 -0
  90. package/dist/crdt/nodes.js +56 -0
  91. package/dist/crdt/placement/model.d.ts +383 -0
  92. package/dist/crdt/placement/model.js +811 -0
  93. package/dist/crdt/placement/rank.d.ts +57 -0
  94. package/dist/crdt/placement/rank.js +209 -0
  95. package/dist/crdt/protocols/auth.d.ts +28 -0
  96. package/dist/crdt/protocols/auth.js +43 -0
  97. package/dist/crdt/protocols/awareness.d.ts +87 -0
  98. package/dist/crdt/protocols/awareness.js +271 -0
  99. package/dist/crdt/protocols/envelope.d.ts +75 -0
  100. package/dist/crdt/protocols/envelope.js +89 -0
  101. package/dist/crdt/protocols/observable.d.ts +19 -0
  102. package/dist/crdt/protocols/observable.js +26 -0
  103. package/dist/crdt/protocols/sync.d.ts +82 -0
  104. package/dist/crdt/protocols/sync.js +288 -0
  105. package/dist/crdt/providers/container.d.ts +23 -0
  106. package/dist/crdt/providers/container.js +64 -0
  107. package/dist/crdt/providers/index.d.ts +282 -0
  108. package/dist/crdt/providers/index.js +118 -0
  109. package/dist/crdt/providers/indexeddb.d.ts +196 -0
  110. package/dist/crdt/providers/indexeddb.js +332 -0
  111. package/dist/crdt/providers/room.d.ts +193 -0
  112. package/dist/crdt/providers/room.js +444 -0
  113. package/dist/crdt/providers/websocket.d.ts +223 -0
  114. package/dist/crdt/providers/websocket.js +601 -0
  115. package/dist/crdt/rand.d.ts +22 -0
  116. package/dist/crdt/rand.js +22 -0
  117. package/dist/crdt/rangeDelete.d.ts +85 -0
  118. package/dist/crdt/rangeDelete.js +126 -0
  119. package/dist/crdt/schema.d.ts +96 -0
  120. package/dist/crdt/schema.js +79 -0
  121. package/dist/crdt/semantics.d.ts +81 -0
  122. package/dist/crdt/semantics.js +57 -0
  123. package/dist/crdt/structs.d.ts +106 -0
  124. package/dist/crdt/structs.js +119 -0
  125. package/dist/crdt/text/deletes.d.ts +23 -0
  126. package/dist/crdt/text/deletes.js +608 -0
  127. package/dist/crdt/text/model.d.ts +280 -0
  128. package/dist/crdt/text/model.js +554 -0
  129. package/dist/crdt/text/runs.d.ts +212 -0
  130. package/dist/crdt/text/runs.js +1142 -0
  131. package/dist/crdt/vendor/yjs/API-NOTES.md +59 -0
  132. package/dist/crdt/vendor/yjs/LICENSE +23 -0
  133. package/dist/crdt/vendor/yjs/UPSTREAM.md +653 -0
  134. package/dist/crdt/vendor/yjs/dts/global.d.ts +52 -0
  135. package/dist/crdt/vendor/yjs/dts/index.d.ts +25 -0
  136. package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +38 -0
  137. package/dist/crdt/vendor/yjs/dts/structs/GC.d.ts +25 -0
  138. package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +748 -0
  139. package/dist/crdt/vendor/yjs/dts/structs/Skip.d.ts +30 -0
  140. package/dist/crdt/vendor/yjs/dts/utils/BlockSet.d.ts +34 -0
  141. package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +198 -0
  142. package/dist/crdt/vendor/yjs/dts/utils/EventHandler.d.ts +17 -0
  143. package/dist/crdt/vendor/yjs/dts/utils/ID.d.ts +20 -0
  144. package/dist/crdt/vendor/yjs/dts/utils/RangeCursor.d.ts +198 -0
  145. package/dist/crdt/vendor/yjs/dts/utils/RelativePosition.d.ts +80 -0
  146. package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +61 -0
  147. package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +129 -0
  148. package/dist/crdt/vendor/yjs/dts/utils/UndoManager.d.ts +205 -0
  149. package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +170 -0
  150. package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +164 -0
  151. package/dist/crdt/vendor/yjs/dts/utils/YEvent.d.ts +93 -0
  152. package/dist/crdt/vendor/yjs/dts/utils/content-helper.d.ts +1 -0
  153. package/dist/crdt/vendor/yjs/dts/utils/encoding-helpers.d.ts +5 -0
  154. package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +26 -0
  155. package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +407 -0
  156. package/dist/crdt/vendor/yjs/dts/utils/isParentOf.d.ts +1 -0
  157. package/dist/crdt/vendor/yjs/dts/utils/meta.d.ts +25 -0
  158. package/dist/crdt/vendor/yjs/dts/utils/renderer-helpers.d.ts +98 -0
  159. package/dist/crdt/vendor/yjs/dts/utils/schemas.d.ts +2 -0
  160. package/dist/crdt/vendor/yjs/dts/utils/transaction-helpers.d.ts +15 -0
  161. package/dist/crdt/vendor/yjs/dts/utils/updates.d.ts +70 -0
  162. package/dist/crdt/vendor/yjs/dts/ynode.d.ts +655 -0
  163. package/dist/crdt/vendor/yjs/global.d.ts +52 -0
  164. package/dist/crdt/vendor/yjs/src/index.js +64 -0
  165. package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +64 -0
  166. package/dist/crdt/vendor/yjs/src/structs/GC.js +75 -0
  167. package/dist/crdt/vendor/yjs/src/structs/Item.js +1538 -0
  168. package/dist/crdt/vendor/yjs/src/structs/Skip.js +72 -0
  169. package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +291 -0
  170. package/dist/crdt/vendor/yjs/src/utils/Doc.js +255 -0
  171. package/dist/crdt/vendor/yjs/src/utils/EventHandler.js +75 -0
  172. package/dist/crdt/vendor/yjs/src/utils/ID.js +59 -0
  173. package/dist/crdt/vendor/yjs/src/utils/RangeCursor.js +407 -0
  174. package/dist/crdt/vendor/yjs/src/utils/RelativePosition.js +301 -0
  175. package/dist/crdt/vendor/yjs/src/utils/StructStore.js +134 -0
  176. package/dist/crdt/vendor/yjs/src/utils/Transaction.js +458 -0
  177. package/dist/crdt/vendor/yjs/src/utils/UndoManager.js +554 -0
  178. package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +284 -0
  179. package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +323 -0
  180. package/dist/crdt/vendor/yjs/src/utils/YEvent.js +158 -0
  181. package/dist/crdt/vendor/yjs/src/utils/content-helper.js +0 -0
  182. package/dist/crdt/vendor/yjs/src/utils/encoding-helpers.js +110 -0
  183. package/dist/crdt/vendor/yjs/src/utils/encoding.js +662 -0
  184. package/dist/crdt/vendor/yjs/src/utils/ids.js +1504 -0
  185. package/dist/crdt/vendor/yjs/src/utils/isParentOf.js +19 -0
  186. package/dist/crdt/vendor/yjs/src/utils/meta.js +74 -0
  187. package/dist/crdt/vendor/yjs/src/utils/renderer-helpers.js +186 -0
  188. package/dist/crdt/vendor/yjs/src/utils/schemas.js +3 -0
  189. package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +391 -0
  190. package/dist/crdt/vendor/yjs/src/utils/updates.js +264 -0
  191. package/dist/crdt/vendor/yjs/src/ynode.js +2897 -0
  192. package/dist/dnd/pragmatic.d.ts +22 -0
  193. package/dist/dnd/pragmatic.js +26 -0
  194. package/dist/edytor.svelte.d.ts +323 -54
  195. package/dist/edytor.svelte.js +771 -197
  196. package/dist/edytor.utils.d.ts +49 -2
  197. package/dist/edytor.utils.js +65 -76
  198. package/dist/events/beforeInputCommands.d.ts +21 -0
  199. package/dist/events/beforeInputCommands.js +328 -0
  200. package/dist/events/beforeInputDeleteCommands.d.ts +3 -0
  201. package/dist/events/beforeInputDeleteCommands.js +245 -0
  202. package/dist/events/dataTransferPayload.d.ts +6 -0
  203. package/dist/events/dataTransferPayload.js +9 -0
  204. package/dist/events/domTextOffset.d.ts +12 -0
  205. package/dist/events/domTextOffset.js +52 -0
  206. package/dist/events/events.utils.d.ts +3 -0
  207. package/dist/events/events.utils.js +13 -0
  208. package/dist/events/nativeInteractiveControl.d.ts +31 -0
  209. package/dist/events/nativeInteractiveControl.js +98 -0
  210. package/dist/events/onBeforeInput.d.ts +10 -1
  211. package/dist/events/onBeforeInput.js +449 -330
  212. package/dist/events/onCopy.d.ts +7 -0
  213. package/dist/events/onCopy.js +30 -0
  214. package/dist/events/onCut.d.ts +8 -0
  215. package/dist/events/onCut.js +13 -0
  216. package/dist/events/onDrop.d.ts +16 -0
  217. package/dist/events/onDrop.js +158 -0
  218. package/dist/events/onFocus.d.ts +4 -0
  219. package/dist/events/onFocus.js +166 -0
  220. package/dist/events/onInput.d.ts +20 -0
  221. package/dist/events/onInput.js +249 -0
  222. package/dist/events/onKeyDown.js +191 -11
  223. package/dist/events/onPaste.d.ts +3 -0
  224. package/dist/events/onPaste.js +108 -0
  225. package/dist/events/wordBoundary.d.ts +2 -0
  226. package/dist/events/wordBoundary.js +58 -0
  227. package/dist/index.d.ts +38 -1
  228. package/dist/index.js +36 -1
  229. package/dist/kinds.d.ts +100 -0
  230. package/dist/kinds.js +198 -0
  231. package/dist/plugins/arrowMove/arrowMove.d.ts +1 -1
  232. package/dist/plugins/arrowMove/arrowMove.js +30 -65
  233. package/dist/plugins/blockHandles/BlockHandle.svelte +152 -0
  234. package/dist/plugins/blockHandles/BlockHandle.svelte.d.ts +12 -0
  235. package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +208 -0
  236. package/dist/plugins/blockHandles/BlockHandleController.svelte.js +823 -0
  237. package/dist/plugins/blockHandles/BlockHandles.svelte +151 -0
  238. package/dist/plugins/blockHandles/BlockHandles.svelte.d.ts +20 -0
  239. package/dist/plugins/blockHandles/autoScroll.d.ts +8 -0
  240. package/dist/plugins/blockHandles/autoScroll.js +25 -0
  241. package/dist/plugins/blockHandles/blockHandlesPlugin.d.ts +37 -0
  242. package/dist/plugins/blockHandles/blockHandlesPlugin.js +100 -0
  243. package/dist/plugins/blockHandles/dragPreview.d.ts +33 -0
  244. package/dist/plugins/blockHandles/dragPreview.js +228 -0
  245. package/dist/plugins/blockMenu/BlockMenu.svelte +301 -0
  246. package/dist/plugins/blockMenu/BlockMenu.svelte.d.ts +9 -0
  247. package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +102 -0
  248. package/dist/plugins/blockMenu/BlockMenuController.svelte.js +245 -0
  249. package/dist/plugins/blockMenu/blockMenuPlugin.d.ts +11 -0
  250. package/dist/plugins/blockMenu/blockMenuPlugin.js +89 -0
  251. package/dist/plugins/code/CodePlugin.svelte +210 -163
  252. package/dist/plugins/code/CodePlugin.svelte.d.ts +1 -3
  253. package/dist/plugins/code/code.css +92 -0
  254. package/dist/plugins/icons.d.ts +2 -0
  255. package/dist/plugins/icons.js +31 -0
  256. package/dist/plugins/image/ImageEmpty.svelte +69 -0
  257. package/dist/plugins/image/ImageEmpty.svelte.d.ts +8 -0
  258. package/dist/plugins/image/ImagePlugin.svelte +74 -12
  259. package/dist/plugins/image/ImagePlugin.svelte.d.ts +15 -0
  260. package/dist/plugins/image/image.d.ts +2 -0
  261. package/dist/plugins/image/image.js +7 -0
  262. package/dist/plugins/index.d.ts +14 -1
  263. package/dist/plugins/index.js +10 -1
  264. package/dist/plugins/keepInView.d.ts +4 -0
  265. package/dist/plugins/keepInView.js +6 -0
  266. package/dist/plugins/markdownShortcuts.d.ts +3 -0
  267. package/dist/plugins/markdownShortcuts.js +104 -0
  268. package/dist/plugins/mention/MentionPlugin.svelte +28 -31
  269. package/dist/plugins/richtext/RichTextPlugin.svelte +411 -200
  270. package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +8 -7
  271. package/dist/plugins/richtext/richTextOperations.d.ts +53 -0
  272. package/dist/plugins/richtext/richTextOperations.js +200 -0
  273. package/dist/plugins/slashMenu/SlashMenu.svelte +297 -0
  274. package/dist/plugins/slashMenu/SlashMenu.svelte.d.ts +11 -0
  275. package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +56 -0
  276. package/dist/plugins/slashMenu/SlashMenuController.svelte.js +275 -0
  277. package/dist/plugins/slashMenu/slashMenuPlugin.d.ts +25 -0
  278. package/dist/plugins/slashMenu/slashMenuPlugin.js +105 -0
  279. package/dist/plugins/suggestions/SuggestionBars.svelte +142 -0
  280. package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +10 -0
  281. package/dist/plugins/suggestions/suggestionsPlugin.d.ts +28 -0
  282. package/dist/plugins/suggestions/suggestionsPlugin.js +53 -0
  283. package/dist/plugins/toolbar/Toolbar.svelte +341 -0
  284. package/dist/plugins/toolbar/Toolbar.svelte.d.ts +9 -0
  285. package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +85 -0
  286. package/dist/plugins/toolbar/ToolbarController.svelte.js +150 -0
  287. package/dist/plugins/toolbar/toolbarPlugin.d.ts +16 -0
  288. package/dist/plugins/toolbar/toolbarPlugin.js +40 -0
  289. package/dist/plugins.d.ts +249 -40
  290. package/dist/plugins.js +11 -5
  291. package/dist/selection/domSelection.d.ts +29 -0
  292. package/dist/selection/domSelection.js +230 -0
  293. package/dist/selection/replaceSelection.d.ts +143 -0
  294. package/dist/selection/replaceSelection.js +316 -0
  295. package/dist/selection/selection.svelte.d.ts +275 -37
  296. package/dist/selection/selection.svelte.js +1162 -331
  297. package/dist/selection/selection.utils.d.ts +35 -4
  298. package/dist/selection/selection.utils.js +309 -100
  299. package/dist/selection/visibility.d.ts +88 -0
  300. package/dist/selection/visibility.js +140 -0
  301. package/dist/session/attempt.d.ts +190 -0
  302. package/dist/session/attempt.js +188 -0
  303. package/dist/session/bindings.d.ts +16 -0
  304. package/dist/session/bindings.js +262 -0
  305. package/dist/session/commands.d.ts +158 -0
  306. package/dist/session/commands.js +601 -0
  307. package/dist/session/composition.svelte.d.ts +114 -0
  308. package/dist/session/composition.svelte.js +489 -0
  309. package/dist/session/editing/text.d.ts +33 -0
  310. package/dist/session/editing/text.js +36 -0
  311. package/dist/session/handles.d.ts +63 -0
  312. package/dist/session/handles.js +123 -0
  313. package/dist/session/history.d.ts +49 -0
  314. package/dist/session/history.js +131 -0
  315. package/dist/session/keymap.d.ts +42 -0
  316. package/dist/session/keymap.js +144 -0
  317. package/dist/session/moves.d.ts +32 -0
  318. package/dist/session/moves.js +116 -0
  319. package/dist/session/navigation.d.ts +51 -0
  320. package/dist/session/navigation.js +312 -0
  321. package/dist/session/props.d.ts +28 -0
  322. package/dist/session/props.js +162 -0
  323. package/dist/session/selection.d.ts +126 -0
  324. package/dist/session/selection.js +227 -0
  325. package/dist/session/suggestions.svelte.d.ts +125 -0
  326. package/dist/session/suggestions.svelte.js +329 -0
  327. package/dist/session/virtual.d.ts +33 -0
  328. package/dist/session/virtual.js +182 -0
  329. package/dist/surface/attributes.d.ts +36 -0
  330. package/dist/surface/attributes.js +143 -0
  331. package/dist/surface/cells.d.ts +103 -0
  332. package/dist/surface/cells.js +215 -0
  333. package/dist/surface/observer.svelte.d.ts +70 -0
  334. package/dist/surface/observer.svelte.js +969 -0
  335. package/dist/surface/overlay.d.ts +33 -0
  336. package/dist/surface/overlay.js +91 -0
  337. package/dist/surface/pin.svelte.d.ts +56 -0
  338. package/dist/surface/pin.svelte.js +108 -0
  339. package/dist/surface/projector.svelte.d.ts +69 -0
  340. package/dist/surface/projector.svelte.js +486 -0
  341. package/dist/text/deltas.d.ts +14 -3
  342. package/dist/text/deltas.js +27 -90
  343. package/dist/text/text.svelte.d.ts +43 -31
  344. package/dist/text/text.svelte.js +88 -69
  345. package/dist/text/text.utils.d.ts +7 -2
  346. package/dist/text/text.utils.js +121 -97
  347. package/dist/themes/notion.css +473 -0
  348. package/dist/utils/diffText.d.ts +15 -0
  349. package/dist/utils/diffText.js +26 -0
  350. package/dist/utils/json.d.ts +90 -3
  351. package/dist/utils/json.js +369 -2
  352. package/dist/utils.d.ts +3 -1
  353. package/dist/utils.js +2 -0
  354. package/package.json +112 -50
  355. package/dist/block/content.svelte.d.ts +0 -14
  356. package/dist/block/content.svelte.js +0 -40
  357. package/dist/components/ReadonlyEditor.svelte +0 -46
  358. package/dist/components/ReadonlyEditor.svelte.d.ts +0 -4
  359. package/dist/components/readonlyElements.svelte.d.ts +0 -82
  360. package/dist/components/readonlyElements.svelte.js +0 -144
  361. package/dist/dnd.svelte.d.ts +0 -17
  362. package/dist/dnd.svelte.js +0 -125
  363. package/dist/hotkeys.d.ts +0 -27
  364. package/dist/hotkeys.js +0 -282
  365. package/dist/localProvider.d.ts +0 -82
  366. package/dist/localProvider.js +0 -267
  367. package/dist/plugins/code/prism.css +0 -141
  368. package/dist/utils/jsx.d.ts +0 -25
  369. package/dist/utils/jsx.js +0 -66
  370. package/dist/utils/serialize.js +0 -1
  371. /package/dist/{utils/serialize.d.ts → crdt/engine-api.js} +0 -0
@@ -1,102 +1,146 @@
1
1
  import { Text } from '../text/text.svelte.js';
2
2
  import { Edytor } from '../edytor.svelte.js';
3
- import {} from '../utils/json.js';
4
- import * as Y from 'yjs';
5
- import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, pushContentIntoBlock, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, addChildBlocks, unNestBlock, moveBlock, normalizeContent, groupContent, addInlineBlock, acceptSuggestedText, suggestText, deleteContentAtRange } from './block.utils.js';
6
- import { id } from '../utils.js';
7
- import { climb } from '../selection/selection.utils.js';
3
+ import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, prepareSplit, duplicateBlock, prepareDuplicate, prepareSet, prepareMove, prepareMoves, prepareInsertAfter, prepareInsertBefore, prepareRemove, prepareMergeBackward, prepareMergeForward, prepareUnNest, prepareNest, prepareRemoveInline, preparePatch, patchData, prepareDeleteRange, addChildBlocks, pushContentIntoBlock, unNestBlock, moveBlock, moveBlocks, normalizeContent, addInlineBlock, textAfterAtom, blockOf, acceptSuggestedText, suggestText, deleteContentAtRange, normalizeChildren } from './block.utils.js';
4
+ import { jsonBlockToSpec, jsonContentToItems } from '../utils/json.js';
8
5
  import { InlineBlock } from './inlineBlock.svelte.js';
9
- import { createReadonlyText } from '../components/readonlyElements.svelte.js';
10
- import { createReadonlyInlineBlock } from '../components/readonlyElements.svelte.js';
11
- export const getSetArray = (yBlock, key = 'children') => {
12
- let yChildren = yBlock.get(key);
13
- if (!yChildren) {
14
- yChildren = new Y.Array();
15
- yBlock.set(key, yChildren);
16
- }
17
- return yChildren;
18
- };
19
- export const getSetText = (yBlock) => {
20
- let yText = yBlock.get('content');
21
- if (!yText) {
22
- yText = new Y.Text();
23
- yBlock.set('content', yText);
24
- }
25
- return yText;
6
+ import { revealed } from '../selection/replaceSelection.js';
7
+ import { propsProxy } from '../session/props.js';
8
+ /**
9
+ * An id-only block handle (§2.4 "Handles", R4): every getter reads the
10
+ * document index (transaction-aware), every mutator issues a command. The
11
+ * view keeps one per id (`edytor.idToBlock`); `node` is the element the core
12
+ * renders for it (O45).
13
+ */
14
+ /** Mark an element inside a block's markup as non-editable chrome (`block.void`, a preview's too). */
15
+ export const voidChrome = (node) => {
16
+ node.setAttribute('data-edytor-void', `true`);
17
+ node.style.userSelect = 'none';
18
+ node.setAttribute('contenteditable', 'false');
26
19
  };
27
20
  export class Block {
28
21
  readonly = false;
29
22
  edytor;
30
- yBlock;
31
- parent;
32
- yChildren;
33
- yContent;
34
- children = $state([]);
35
- content = $state([]);
36
- id = $state(id('b'));
37
- data = $state({});
23
+ id;
38
24
  node;
39
- definition = $state({});
25
+ constructor(edytor, id) {
26
+ this.edytor = edytor;
27
+ this.id = id;
28
+ }
29
+ get isRoot() {
30
+ return this.id === 'root';
31
+ }
32
+ /** The typed document node — `null` for the root. */
33
+ get model() {
34
+ return this.isRoot ? null : this.edytor.facade.block(this.id);
35
+ }
36
+ /** The display parent (the root for a top-level block); none for the root or a dead block. */
37
+ get parent() {
38
+ const at = this.isRoot ? null : this.edytor.facade.positionOf(this.id);
39
+ return at ? this.edytor.idToBlock.block(at.parent ?? 'root') : undefined;
40
+ }
41
+ get children() {
42
+ const { facade, idToBlock } = this.edytor;
43
+ return facade.childrenIds(this.isRoot ? null : this.id).map(idToBlock.block);
44
+ }
45
+ /** Text segments and inline atoms, alternating, starting and ending with a text. */
46
+ get content() {
47
+ const handles = this.edytor.idToBlock;
48
+ let ordinal = 0;
49
+ return handles
50
+ .parts(this.id)
51
+ .map((part) => part.kind === 'text'
52
+ ? handles.text(this.id, ordinal++)
53
+ : handles.atom(this.id, part.item.id));
54
+ }
55
+ get type() {
56
+ return this.isRoot ? 'root' : (this.edytor.facade.blockTypeOf(this.id) ?? '');
57
+ }
58
+ /** Retype the block — the `setBlock` command (readonly, hooks, `dispatcher.last`). */
59
+ set type(value) {
60
+ this.setBlock({ value: { type: value } });
61
+ }
62
+ #data;
63
+ #props;
64
+ /**
65
+ * The block's `data` as a live proxy (`session/props.ts`): reads follow the
66
+ * document (reactive through the block's cell), writes are `patchData`
67
+ * commands. The root's is the document's data (`edytor.data`).
68
+ */
69
+ get data() {
70
+ return (this.#props ??= propsProxy(() => (this.isRoot ? this.edytor.docData() : this.#current()), (ops) => this.patchData({ ops }), (path) => this.edytor.facade.dataItemIds(this.isRoot ? null : this.id, path)));
71
+ }
72
+ #current() {
73
+ const { facade, cells } = this.edytor;
74
+ cells?.get(this.id);
75
+ const version = facade.version;
76
+ if (this.#data?.version !== version)
77
+ this.#data = { version, value: facade.blockDataOf(this.id) ?? {} };
78
+ return this.#data.value;
79
+ }
80
+ get definition() {
81
+ return this.edytor.definitionOf(this.type);
82
+ }
83
+ /**
84
+ * Replace the block's `data` — a `patchData` command of its root (readonly,
85
+ * hooks, `dispatcher.last`); `block.model.setData` is the raw document write.
86
+ */
87
+ setData = (data) => {
88
+ // Non-JSON values are coerced at the document boundary (`sanitizeWireJson`).
89
+ this.patchData({ ops: [{ path: [], value: data }] });
90
+ };
40
91
  get selected() {
41
- this.yBlock._item?.id;
42
- return this.edytor.selection.selectedBlocks.has(this) || this.edytor.selection.hasSelectedAll;
92
+ return this.edytor.selection.selectedBlocks.has(this);
43
93
  }
44
94
  get focused() {
45
95
  return this.edytor.selection.focusedBlocks.has(this) && !this.selected;
46
96
  }
47
- get insideIsland() {
48
- let insideIslands = false;
49
- climb(this.parent, (block) => {
50
- if (block.definition?.island) {
51
- insideIslands = true;
52
- return true;
53
- }
54
- });
55
- return insideIslands;
97
+ /** May this block move at all — R5 `canPlace` without a destination (drag handles). */
98
+ get movable() {
99
+ return this.edytor.facade.canPlace([this.id]);
100
+ }
101
+ /**
102
+ * May text-level structural commands (convert, markdown shortcut, slash
103
+ * menu) apply: the block is movable — or the virtual paragraph of an
104
+ * emptied document, which a conversion creates with its kind
105
+ * (SW10-lists-3) — has no role of its own and renders its own content —
106
+ * a container (a list) is never converted, its items are (ZW-02).
107
+ */
108
+ get convertible() {
109
+ const { facade } = this.edytor;
110
+ const placeable = this.movable || facade.virtual() === this.id;
111
+ return placeable && this.rendersContent && !facade.isVoid(this.id) && !facade.isIsland(this.id);
56
112
  }
57
113
  get firstEditableText() {
58
- if (this.content.length && this.content.some((part) => part instanceof Text && part.node)) {
59
- return this.content.find((part) => part instanceof Text);
114
+ // Only a RENDERED text part is editable — a container's phantom
115
+ // content slot holds a Text with no `node`. Scan ALL children: the
116
+ // first child can be noneditable (a void divider) while a later
117
+ // child owns the text the caret must land in.
118
+ const own = this.content.find((part) => part instanceof Text && part.node != null);
119
+ if (own)
120
+ return own;
121
+ for (const child of this.children) {
122
+ const text = child.firstEditableText;
123
+ if (text)
124
+ return text;
60
125
  }
61
- return this.children.at(0)?.firstEditableText;
126
+ return undefined;
62
127
  }
63
128
  get lastEditableText() {
64
- if (this.content.length && this.content.some((part) => part instanceof Text && part.node)) {
65
- return this.content.findLast((part) => part instanceof Text);
129
+ const own = this.content.findLast((part) => part instanceof Text && part.node != null);
130
+ if (own)
131
+ return own;
132
+ for (let i = this.children.length - 1; i >= 0; i--) {
133
+ const text = this.children[i].lastEditableText;
134
+ if (text)
135
+ return text;
66
136
  }
67
- return this.children.at(-1)?.lastEditableText;
137
+ return undefined;
68
138
  }
69
- #index = $state(null);
70
139
  get index() {
71
- if (!this.parent) {
72
- return 0;
73
- }
74
- if (this.#index === null) {
75
- return this.parent.children.indexOf(this);
76
- }
77
- return this.#index;
78
- }
79
- set index(value) {
80
- this.#index = value;
81
- }
82
- #type = $state('paragraph');
83
- get type() {
84
- return this.#type;
85
- }
86
- set type(value) {
87
- this.yBlock.set('type', value);
88
- this.#type = value;
89
- this.definition = this.edytor.getBlockDefinition('block', value);
140
+ return (!this.isRoot && this.edytor.facade.positionOf(this.id)?.index) || 0;
90
141
  }
91
- #depth = $state(null);
92
142
  get depth() {
93
- if (!this.parent) {
94
- return 0;
95
- }
96
- if (this.#depth === null) {
97
- return this.parent.depth + 1;
98
- }
99
- return this.#depth;
143
+ return this.parent ? this.parent.depth + 1 : 0;
100
144
  }
101
145
  get path() {
102
146
  const start = [this.index];
@@ -107,324 +151,249 @@ export class Block {
107
151
  }
108
152
  return start.toReversed();
109
153
  }
110
- get isRoot() {
111
- return this === this.edytor.root;
154
+ /** The block is visible in the document (a dead handle answers false). */
155
+ get isInTree() {
156
+ return this.isRoot || this.edytor.facade.isVisibleBlock(this.id);
112
157
  }
113
- #suggestions = $state(null);
158
+ /**
159
+ * @deprecated `edytor.suggestions` with `{ end: block.id }`. The content of
160
+ * this block's latest `end` suggestion, as parts (a text's runs, or an
161
+ * atom); setting it replaces this block's `end` suggestions, `null` drops them.
162
+ */
114
163
  get suggestions() {
115
- if (!this.#suggestions) {
164
+ const content = this.edytor.suggestions?.at(this.id).end.at(-1)?.content[0]?.content;
165
+ if (!content?.length)
116
166
  return null;
117
- }
118
- return this.#suggestions.map((suggestion) => {
119
- if ('type' in suggestion) {
120
- return createReadonlyInlineBlock({
121
- block: suggestion,
122
- edytor: this.edytor,
123
- parent: this
124
- });
125
- }
126
- else {
127
- return createReadonlyText({
128
- value: suggestion,
129
- parent: this,
130
- edytor: this.edytor
131
- });
132
- }
133
- });
167
+ const parts = [];
168
+ for (const part of content)
169
+ if ('type' in part)
170
+ parts.push(part);
171
+ else if (Array.isArray(parts.at(-1)))
172
+ parts.at(-1).push(part);
173
+ else
174
+ parts.push([part]);
175
+ return parts;
134
176
  }
135
177
  set suggestions(value) {
136
- this.#suggestions = value;
178
+ const { suggestions } = this.edytor;
179
+ for (const suggestion of suggestions.at(this.id).end)
180
+ suggestion.discard();
181
+ if (value)
182
+ suggestions.add({ end: this.id }, [{ type: this.type, content: value.flat() }]);
137
183
  }
138
184
  get nextBlock() {
139
- if (!this.parent) {
140
- return null;
141
- }
142
- return this.parent.children[this.index + 1];
185
+ return this.parent ? this.parent.children[this.index + 1] : null;
143
186
  }
144
187
  get previousBlock() {
145
- if (!this.parent) {
146
- return null;
147
- }
148
- return this.parent.children[this.index - 1];
188
+ return this.parent ? this.parent.children[this.index - 1] : null;
149
189
  }
150
190
  get closestPreviousBlock() {
151
- const previousBlock = this.previousBlock;
152
- if (this.index === 0) {
153
- return this.parent instanceof Block ? this.parent : null;
154
- }
155
- else if (previousBlock) {
156
- if (previousBlock?.children.length > 0) {
157
- let closestPreviousBlock = previousBlock.children.at(-1) || null;
158
- while (closestPreviousBlock && closestPreviousBlock?.children.length > 0) {
159
- closestPreviousBlock = closestPreviousBlock.children.at(-1) || null;
160
- }
161
- return closestPreviousBlock || null;
162
- }
163
- else {
164
- return this.previousBlock;
165
- }
166
- }
167
- return null;
191
+ return this.edytor.blockBefore(this);
168
192
  }
169
193
  get closestNextBlock() {
170
- if (this.hasChildren) {
171
- return this.children.at(0) || null;
172
- }
173
- if (this.nextBlock || this.definition.island || this.definition.void) {
174
- return this.nextBlock;
175
- }
176
- else {
177
- if (this.parent instanceof Block) {
178
- let parent = this.parent;
179
- let nextBlock = parent.nextBlock;
180
- while (!nextBlock && parent instanceof Block) {
181
- if (parent.parent instanceof Block) {
182
- parent = parent.parent;
183
- nextBlock = parent.nextBlock;
184
- }
185
- else {
186
- return null;
187
- }
188
- }
189
- return nextBlock;
190
- }
191
- else {
192
- return null;
193
- }
194
- }
195
- }
196
- get deepestChild() {
197
- if (this.children.length) {
198
- return this.children.at(-1).deepestChild;
199
- }
200
- return this;
194
+ return this.edytor.blockAfter(this);
201
195
  }
202
196
  get hasChildren() {
203
197
  return this.children.length > 0;
204
198
  }
199
+ /** It shows content: text or an inline atom (a block holding only a mention is not empty). */
205
200
  get hasContent() {
206
- return (this.content.length > 0 && this.content.some((part) => part instanceof Text && !part.isEmpty));
201
+ return this.content.some((part) => !(part instanceof Text) || !part.isEmpty);
207
202
  }
203
+ /** It holds nothing: no content and no children (the emptiness Turn into reads, `holdsNothing`). */
208
204
  get isEmpty() {
209
205
  return !this.hasContent && !this.hasChildren;
210
206
  }
207
+ get isNested() {
208
+ return (this.parent && this.parent.type !== 'root') || false;
209
+ }
210
+ /** This block's JSON — the document's one serializer (`facade.blockJSON`, L14). */
211
211
  get value() {
212
- const children = this.children.map((child) => child.value);
213
- const content = this.content.map((part) => part.value).flat();
214
- const value = {
215
- type: this.type,
216
- id: this.id,
217
- children,
218
- content
219
- };
220
- if (Object.keys(this.data).length > 0) {
221
- value.data = this.data;
222
- }
223
- if (!children.length) {
224
- delete value.children;
225
- }
226
- if (!content.length) {
227
- delete value.content;
228
- }
229
- return value;
212
+ if (!this.isRoot)
213
+ return this.edytor.facade.blockJSON(this.id);
214
+ const { data = {}, children } = this.edytor.facade.toJSON();
215
+ return { type: 'root', id: 'root', data, ...(children.length > 0 && { children }) };
216
+ }
217
+ isChildOf(block) {
218
+ for (let parent = this.parent; parent; parent = parent.parent)
219
+ if (parent === block)
220
+ return true;
221
+ return false;
222
+ }
223
+ /** Whether this kind renders its own content slot — the adopted capability (R5, O22). */
224
+ get rendersContent() {
225
+ return this.edytor.document.rendersContent(this.type);
226
+ }
227
+ /**
228
+ * A container: it shows only its children (a list), neither void nor an
229
+ * island — the document's container rule (YW-02). Its items hold what it
230
+ * shows; it is never converted (`convertible`).
231
+ */
232
+ get isContainer() {
233
+ const { facade } = this.edytor;
234
+ return !this.rendersContent && !facade.isVoid(this.id) && !facade.isIsland(this.id);
230
235
  }
236
+ /**
237
+ * An item of a list: its parent is a container whose items are a kind of
238
+ * their own (a `list-item` in an `unordered-list`), not the document's
239
+ * default — a column of paragraphs is no list. Turned into another kind,
240
+ * an item leaves its list; <kbd>Enter</kbd> in an empty one ends it.
241
+ */
242
+ get isListItem() {
243
+ const { parent, edytor } = this;
244
+ if (!parent?.isContainer)
245
+ return false;
246
+ const item = edytor.defaultChild(parent);
247
+ return this.type === item && item !== edytor.document.defaultChild(null);
248
+ }
249
+ /**
250
+ * The list this block shows in: its container when it is an item
251
+ * (`isListItem`), or — an item outdented out of a nested list into the
252
+ * item holding it (SW8-roles-4) — the list of the items of its kind it
253
+ * sits under. <kbd>Enter</kbd> in an empty one outdents it; the menus
254
+ * name it by the list's `itemKind`.
255
+ */
256
+ get list() {
257
+ if (this.isListItem)
258
+ return this.parent ?? undefined;
259
+ return this.parent?.type === this.type ? this.parent.list : undefined;
260
+ }
261
+ /**
262
+ * The first text of this block's own content — none for a kind that
263
+ * does not render its content (a list container, a divider): its slot
264
+ * is never displayed, so no caret or endpoint may land there. A block
265
+ * without a content slot (the root) answers with its first child's.
266
+ */
231
267
  get firstText() {
232
- if (this.content.length) {
233
- return this.content.find((part) => part instanceof Text);
234
- }
235
- return this.children.at(0)?.firstText;
268
+ if (!this.content.length)
269
+ return this.children.at(0)?.firstText;
270
+ return this.rendersContent ? this.content.find((p) => p instanceof Text) : undefined;
236
271
  }
272
+ /** The last text of this block's own content (see {@link firstText}). */
237
273
  get lastText() {
238
- if (this.content.length) {
239
- return this.content.findLast((part) => part instanceof Text);
240
- }
241
- return this.children.at(0).lastText;
242
- }
243
- observeContent = observeContent.bind(this);
244
- observeChildren = observeChildren.bind(this);
245
- batch = batch.bind(this);
246
- addChildBlock = this.batch('addChildBlock', addChildBlock.bind(this));
247
- addChildBlocks = this.batch('addChildBlocks', addChildBlocks.bind(this));
248
- insertBlockAfter = this.batch('insertBlockAfter', insertBlockAfter.bind(this));
249
- insertBlockBefore = this.batch('insertBlockBefore', insertBlockBefore.bind(this));
250
- splitBlock = this.batch('splitBlock', splitBlock.bind(this));
251
- removeBlock = this.batch('removeBlock', removeBlock.bind(this));
252
- unNestBlock = this.batch('unNestBlock', unNestBlock.bind(this));
253
- mergeBlockBackward = this.batch('mergeBlockBackward', mergeBlockBackward.bind(this));
254
- mergeBlockForward = this.batch('mergeBlockForward', mergeBlockForward.bind(this));
255
- nestBlock = this.batch('nestBlock', nestBlock.bind(this));
256
- setBlock = this.batch('setBlock', setBlock.bind(this));
257
- moveBlock = this.batch('moveBlock', moveBlock.bind(this));
258
- pushContentIntoBlock = this.batch('pushContentIntoBlock', pushContentIntoBlock.bind(this));
259
- removeInlineBlock = this.batch('removeInlineBlock', removeInlineBlock.bind(this));
260
- addInlineBlock = this.batch('addInlineBlock', addInlineBlock.bind(this));
261
- normalizeContent = this.batch('normalizeContent', normalizeContent.bind(this));
262
- suggestText = this.batch('suggestText', suggestText.bind(this));
263
- acceptSuggestedText = this.batch('acceptSuggestedText', acceptSuggestedText.bind(this));
264
- deleteContentAtRange = this.batch('deleteContentAtRange', deleteContentAtRange.bind(this));
265
- void = (node) => {
266
- node.setAttribute('data-edytor-void', `true`);
267
- node.style.userSelect = 'none';
268
- node.contentEditable = 'false';
269
- };
270
- constructor({ parent, block, yBlock, edytor }) {
271
- this.parent = parent;
272
- this.edytor = edytor;
273
- this.id = (yBlock?.doc && yBlock?.get('id')) || id('b');
274
- if (block !== undefined) {
275
- this.#type = block.type;
276
- this.data = block.data || {};
277
- // Initialize children
278
- this.children = (block.children || []).map((child, index) => {
279
- const block = new Block({ parent: this, edytor, block: child });
280
- block.index = index;
281
- return block;
282
- });
283
- const groupedContent = groupContent(block.content);
284
- if (!groupedContent.length) {
285
- groupedContent.push([{ text: '' }]);
274
+ if (!this.content.length)
275
+ return this.children.at(-1)?.lastText;
276
+ return this.rendersContent ? this.content.findLast((p) => p instanceof Text) : undefined;
277
+ }
278
+ addChildBlock = batch('addChildBlock', addChildBlock);
279
+ addChildBlocks = batch('addChildBlocks', addChildBlocks);
280
+ insertBlockAfter = batch('insertBlockAfter', insertBlockAfter, prepareInsertAfter, blockOf);
281
+ insertBlockBefore = batch('insertBlockBefore', insertBlockBefore, prepareInsertBefore, blockOf);
282
+ splitBlock = batch('splitBlock', splitBlock, prepareSplit, blockOf);
283
+ duplicateBlock = batch('duplicateBlock', duplicateBlock, prepareDuplicate, blockOf);
284
+ removeBlock = batch('removeBlock', removeBlock, prepareRemove);
285
+ unNestBlock = revealed(batch('unNestBlock', unNestBlock, prepareUnNest));
286
+ mergeBlockBackward = batch('mergeBlockBackward', mergeBlockBackward, prepareMergeBackward, blockOf);
287
+ mergeBlockForward = batch('mergeBlockForward', mergeBlockForward, prepareMergeForward, blockOf);
288
+ nestBlock = revealed(batch('nestBlock', nestBlock, prepareNest));
289
+ setBlock = batch('setBlock', setBlock, prepareSet);
290
+ moveBlock = revealed(batch('moveBlock', moveBlock, prepareMove));
291
+ moveBlocks = revealed(batch('moveBlocks', moveBlocks, prepareMoves));
292
+ pushContentIntoBlock = batch('pushContentIntoBlock', pushContentIntoBlock);
293
+ removeInlineBlock = batch('removeInlineBlock', removeInlineBlock, prepareRemoveInline);
294
+ patchData = batch('patchData', patchData, preparePatch);
295
+ addInlineBlock = batch('addInlineBlock', addInlineBlock, undefined, textAfterAtom);
296
+ normalizeContent = batch('normalizeContent', normalizeContent);
297
+ normalizeChildren = batch('normalizeChildren', normalizeChildren);
298
+ /** @deprecated `edytor.suggestions.add({ end: block.id }, …)`. */
299
+ suggestText = (payload) => suggestText.call(this, payload);
300
+ /** @deprecated `suggestion.accept()`. */
301
+ acceptSuggestedText = () => acceptSuggestedText.call(this);
302
+ deleteContentAtRange = batch('deleteContentAtRange', deleteContentAtRange, prepareDeleteRange);
303
+ /** Mark an element inside the block's markup as non-editable chrome (a header, a caption bar). */
304
+ void = voidChrome;
305
+ /**
306
+ * The text segment that displays block offset `offset`, and the offset in
307
+ * it — the one offset → segment mapper over the committed parts (a
308
+ * boundary before an atom reads the text before it; past the end, the
309
+ * last text's end).
310
+ */
311
+ textAtOffset = (offset) => {
312
+ let at = 0;
313
+ let hit = null;
314
+ for (const part of this.content) {
315
+ if (!(part instanceof Text)) {
316
+ if (offset <= at)
317
+ return hit;
318
+ at += 1;
286
319
  }
287
- this.content = groupedContent.map((part, index) => {
288
- const isInlineBlock = 'type' in part;
289
- if (isInlineBlock) {
290
- const block = new InlineBlock({ parent: this, block: part });
291
- block.index = index;
292
- return block;
293
- }
294
- else {
295
- const text = new Text({ parent: this, content: part });
296
- text.index = index;
297
- return text;
298
- }
299
- });
300
- this.yChildren = Y.Array.from(this.children.map((child) => child.yBlock));
301
- this.yContent = Y.Array.from(this.content.map((part) => (part instanceof Text ? part.yText : part.yBlock)));
302
- // If the block is a root block we need to set the yBlock to the yRootBlock
303
- if (block.type === 'root') {
304
- this.yBlock = yBlock;
305
- this.yBlock.set('id', this.id);
306
- this.yBlock.set('type', block.type);
307
- this.yBlock.set('data', this.data);
308
- this.yBlock.set('children', this.yChildren);
309
- this.yBlock.set('content', this.yContent);
320
+ else if (offset <= at + part.length) {
321
+ return { text: part, offset: Math.max(0, offset - at) };
310
322
  }
311
323
  else {
312
- this.yBlock = new Y.Map(Object.entries({
313
- type: block.type,
314
- id: this.id,
315
- data: this.data,
316
- children: this.yChildren,
317
- content: this.yContent
318
- }));
324
+ hit = { text: part, offset: part.length };
325
+ at += part.length;
319
326
  }
320
327
  }
321
- else {
322
- this.yBlock = yBlock;
323
- this.#type = this.yBlock.get('type') || this.edytor.getDefaultBlock(parent);
324
- this.data = this.yBlock.get('data') || {};
325
- this.yChildren = getSetArray(this.yBlock);
326
- this.yContent = getSetArray(this.yBlock, 'content');
327
- this.children = this.yChildren.map((child, index) => {
328
- const block = new Block({ parent: this, edytor, yBlock: child });
329
- block.index = index;
330
- return block;
331
- });
332
- this.normalizeContent();
333
- this.content = this.yContent.map((part, index) => {
334
- if (part instanceof Y.Map) {
335
- const block = new InlineBlock({ parent: this, yBlock: part });
336
- block.index = index;
337
- return block;
338
- }
339
- else {
340
- const text = new Text({ parent: this, yText: part });
341
- text.index = index;
342
- return text;
343
- }
344
- });
345
- }
346
- this.definition = this.edytor.getBlockDefinition('block', this.#type);
347
- this.edytor.idToBlock.set(this.id, this);
348
- if (!this.edytor.readonly) {
349
- this.yChildren.observe(this.observeChildren);
350
- this.yContent.observe(this.observeContent);
328
+ return hit;
329
+ };
330
+ // ── JSON insertion (K5: specs are data; `new Block({block})` is gone) ──
331
+ /**
332
+ * Insert children at `index`: a JSON spec is created (its id kept, minted
333
+ * when missing); a block handle moves there with its identity.
334
+ */
335
+ insertChildren = (index, blocks) => {
336
+ const { facade } = this.edytor;
337
+ const parent = this.isRoot ? null : this.id;
338
+ blocks.forEach((block, k) => {
339
+ if (block instanceof Block)
340
+ block.model?.moveTo({ parent: this.model, index: index + k });
341
+ else
342
+ facade.insertBlock({ parent, index: index + k }, jsonBlockToSpec(block));
343
+ });
344
+ };
345
+ /** Delete `length` visible children from `index`, each with its subtree (a document delete). */
346
+ deleteChildren = (index, length = 1) => {
347
+ const ids = this.edytor.facade.childrenIds(this.isRoot ? null : this.id);
348
+ for (const id of ids.slice(index, index + length).reverse())
349
+ this.edytor.facade.block(id).delete({ keepChildren: false });
350
+ };
351
+ /**
352
+ * Insert content before part `index` (a text segment or an inline atom):
353
+ * each entry is a text's runs or an atom, as JSON.
354
+ */
355
+ insertParts = (index, parts) => {
356
+ const model = this.model;
357
+ if (!model)
358
+ return;
359
+ const all = this.edytor.idToBlock.parts(this.id);
360
+ let at = all[index]?.start ?? model.length;
361
+ for (const item of jsonContentToItems(parts.flat())) {
362
+ if (item.kind === 'inline')
363
+ model.insertInline(at++, item);
364
+ else if (item.text) {
365
+ model.insertText(at, item.text, item.marks);
366
+ at += item.text.length;
367
+ }
351
368
  }
352
- }
369
+ };
370
+ /** The declared view state (`open` on a `details`) the block's last element held. */
371
+ #viewState = [];
372
+ /**
373
+ * Register the element the core rendered for this block (O45) and run the
374
+ * attach hooks. A re-rendered block (moved, re-parented) keeps its declared
375
+ * view state (R11): an open toggle stays open.
376
+ */
353
377
  attach = (node) => {
378
+ const names = this.definition.viewState ?? [];
379
+ const read = (from) => names.flatMap((name) => (from.hasAttribute(name) ? [[name, from.getAttribute(name)]] : []));
380
+ for (const [name, value] of this.node ? read(this.node) : this.#viewState)
381
+ if (names.includes(name))
382
+ node.setAttribute(name, value);
354
383
  this.node = node;
355
- node.setAttribute('data-edytor-id', `${this.id}`);
356
- node.setAttribute('data-edytor-block', `true`);
357
- node.setAttribute('data-edytor-type', `${this.#type}`);
358
- const pluginDestroy = this.edytor.plugins.reduce((acc, plugin) => {
384
+ const release = this.edytor.surface.register(node, 'block', this.id);
385
+ const onDestroy = this.edytor.plugins.flatMap((plugin) => {
359
386
  const action = plugin.onBlockAttached?.({ node, block: this });
360
- action && acc.push(action);
361
- return acc;
362
- }, []);
363
- if (this.definition.void) {
364
- this.void(node);
365
- }
387
+ return typeof action === 'function' ? [action] : [];
388
+ });
366
389
  return {
367
390
  destroy: () => {
368
- this.yChildren.unobserve(this.observeChildren);
369
- this.yContent.unobserve(this.observeContent);
370
- this.edytor.idToBlock.delete(this.id);
371
- pluginDestroy.forEach((destroy) => destroy());
391
+ this.#viewState = read(node);
392
+ if (this.node === node)
393
+ this.node = undefined;
394
+ release();
395
+ onDestroy.forEach((destroy) => destroy());
372
396
  }
373
397
  };
374
398
  };
375
399
  }
376
- export function observeChildren(event) {
377
- let start = 0;
378
- event.delta.forEach(({ retain, delete: _delete, insert }) => {
379
- if (retain) {
380
- start += retain;
381
- }
382
- if (_delete) {
383
- this.children.splice(start, _delete);
384
- }
385
- if (Array.isArray(insert)) {
386
- for (let i = 0; i < insert.length; i++) {
387
- const yBlock = insert[i];
388
- const block = this.edytor.idToBlock.get(yBlock.get('id')) ||
389
- new Block({
390
- parent: this,
391
- edytor: this.edytor,
392
- yBlock
393
- });
394
- this.children.splice(start, 0, block);
395
- start += 1;
396
- }
397
- }
398
- });
399
- this.children.forEach((child, index) => {
400
- child.index = index;
401
- });
402
- }
403
- export function observeContent(event) {
404
- let start = 0;
405
- event.delta.forEach(({ retain, delete: _delete, insert }) => {
406
- if (retain) {
407
- start += retain;
408
- }
409
- if (_delete) {
410
- this.content.splice(start, _delete);
411
- }
412
- if (Array.isArray(insert)) {
413
- for (let i = 0; i < insert.length; i++) {
414
- const yElement = insert[i];
415
- if (yElement instanceof Y.Text) {
416
- const text = new Text({ parent: this, yText: yElement });
417
- this.content.splice(start, 0, text);
418
- }
419
- else {
420
- const inlineBlock = new InlineBlock({ parent: this, yBlock: yElement });
421
- this.content.splice(start, 0, inlineBlock);
422
- }
423
- start += 1;
424
- }
425
- }
426
- });
427
- this.content.forEach((part, index) => {
428
- part.index = index;
429
- });
430
- }