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,36 +1,48 @@
1
1
  import { Edytor } from '../edytor.svelte.js';
2
- import * as Y from 'yjs';
3
- import { type JSONText, type SerializableContent } from '../utils/json.js';
2
+ import { type JSONText } from '../utils/json.js';
4
3
  import { Block } from '../block/block.svelte.js';
5
- import { type JSONDelta } from './deltas.js';
4
+ /**
5
+ * An id-only text handle (§2.4 "Handles", R4): the `ordinal`-th text segment
6
+ * of block `blockId` — no identity across commits beyond that position (K5).
7
+ * Getters read the document index; mutators write through the block's model.
8
+ * `node` is the element that renders the segment (a Surface fact).
9
+ */
6
10
  export declare class Text {
7
11
  #private;
8
12
  readonly: boolean;
9
- parent: Block;
10
- yText: Y.Text;
11
- edytor: Edytor;
12
- stringContent: string;
13
- index: number;
13
+ readonly edytor: Edytor;
14
+ readonly blockId: string;
15
+ /** The segment's position among its block's text segments. */
16
+ readonly ordinal: number;
17
+ readonly id: string;
14
18
  node: HTMLElement | undefined;
15
- isEmpty: boolean;
16
- endsWithNewline: boolean;
17
- markOnNextInsert: undefined | Record<string, SerializableContent | null>;
18
- id: string;
19
+ constructor(edytor: Edytor, blockId: string, ordinal: number);
20
+ get parent(): Block;
21
+ /** Position among the block's content parts. */
22
+ get index(): number;
19
23
  get value(): JSONText[];
24
+ /** The segment's text. */
25
+ get stringContent(): string;
26
+ get isEmpty(): boolean;
27
+ get endsWithNewline(): boolean;
20
28
  get length(): number;
21
- get children(): JSONDelta[];
22
- set children(value: JSONDelta[]);
23
- private setChildren;
24
- private observeText;
25
- constructor({ parent, content, yText }: {
26
- parent: Block;
27
- } & ({
28
- yText?: undefined;
29
- content: string | JSONText[];
30
- } | {
31
- yText: Y.Text;
32
- content?: undefined;
33
- }));
29
+ /** Display offset of this segment inside its block's content (atoms count 1). */
30
+ get segStart(): number;
31
+ /** The segment is shown by a live block. */
32
+ get isInDocument(): boolean;
33
+ /**
34
+ * Re-create this block's text elements from its cell — the repair of a
35
+ * DOM the browser or a foreign script changed (typing and model commits
36
+ * never remount). Never while the IME owns the element. A remount under
37
+ * the caret is a render the projector displays after (`mounted`).
38
+ */
39
+ refreshFromModel: () => void;
40
+ /** Insert `text` (optionally marked) at segment-local `offset`. */
41
+ insertAt: (offset: number, text: string, marks?: Record<string, unknown> | null) => boolean;
42
+ /** Delete `length` atoms at segment-local `offset`. */
43
+ deleteAt: (offset: number, length: number) => boolean;
44
+ /** Multi-mark format over `[offset, offset+length)` — `null` values remove the mark. */
45
+ formatAt: (offset: number, length: number, attributes: Record<string, unknown>) => boolean;
34
46
  private batch;
35
47
  getMarksAtRange: (yStart: number, yEnd: number) => JSONText[];
36
48
  insertText: (args_0: {
@@ -38,12 +50,15 @@ export declare class Text {
38
50
  isAutoDot?: boolean;
39
51
  start?: number;
40
52
  end?: number;
41
- marks?: Record<string, SerializableContent | null>;
53
+ marks?: Record<string, import("../utils/json.js").SerializableContent | null>;
42
54
  }) => void;
43
55
  deleteText: (args_0: {
44
56
  direction: "BACKWARD" | "FORWARD";
45
57
  length: number;
46
- }) => void;
58
+ }) => {
59
+ start: number;
60
+ end: number;
61
+ } | undefined;
47
62
  splitText: (args_0: {
48
63
  index?: number;
49
64
  }) => JSONText[];
@@ -54,15 +69,12 @@ export declare class Text {
54
69
  mark: string;
55
70
  start?: number;
56
71
  end?: number;
57
- value?: SerializableContent | null;
72
+ value?: import("../utils/json.js").SerializableContent | null;
58
73
  toggle?: boolean;
59
74
  }) => void;
60
75
  removeMarksFromText: (args_0: {
61
- mark: string;
62
76
  start?: number;
63
77
  end?: number;
64
- value?: SerializableContent | null;
65
- toggle?: boolean;
66
78
  }) => void;
67
79
  attach: (node: HTMLElement) => {
68
80
  destroy: () => void;
@@ -1,84 +1,96 @@
1
1
  import { Edytor } from '../edytor.svelte.js';
2
- import * as Y from 'yjs';
3
2
  import {} from '../utils/json.js';
4
3
  import { Block } from '../block/block.svelte.js';
5
4
  import { batch, deleteText, removeMarksFromText, getMarksAtRange, insertText, markText, setText, splitText } from './text.utils.js';
6
- import { deltaToJson, jsonToDelta, toDeltas } from './deltas.js';
7
- import { id } from '../utils.js';
5
+ import { deltaToJson, runsToDeltas } from './deltas.js';
8
6
  import { climb } from '../selection/selection.utils.js';
7
+ /** A write through the block's model that the document did not refuse. */
8
+ const accepted = (r) => r !== undefined && r.status !== 'refused';
9
+ /**
10
+ * An id-only text handle (§2.4 "Handles", R4): the `ordinal`-th text segment
11
+ * of block `blockId` — no identity across commits beyond that position (K5).
12
+ * Getters read the document index; mutators write through the block's model.
13
+ * `node` is the element that renders the segment (a Surface fact).
14
+ */
9
15
  export class Text {
10
16
  readonly = false;
11
- parent;
12
- yText;
13
17
  edytor;
14
- stringContent = $state('');
15
- index = $state(0);
16
- node;
17
- // Used to add en empty string in the DOM if the text is empty in order to be abble to focus on it.
18
- isEmpty = $state(false);
19
- // Used to add en empty string at the end of the text if it ends with a newline in order to visually render the newline.
20
- endsWithNewline = $state(false);
21
- // Used when user toggles mark without selection range.
22
- markOnNextInsert = undefined;
18
+ blockId;
19
+ /** The segment's position among its block's text segments. */
20
+ ordinal;
23
21
  id;
24
- #children = $state([]);
22
+ node;
23
+ constructor(edytor, blockId, ordinal) {
24
+ this.edytor = edytor;
25
+ this.blockId = blockId;
26
+ this.ordinal = ordinal;
27
+ this.id = `t:${blockId}:${ordinal}`;
28
+ }
29
+ get parent() {
30
+ return this.edytor.idToBlock.block(this.blockId);
31
+ }
32
+ /** This segment in its block's parts, and its position among them. */
33
+ get #at() {
34
+ const parts = this.edytor.idToBlock.parts(this.blockId);
35
+ for (let index = 0, k = 0; index < parts.length; index++) {
36
+ const part = parts[index];
37
+ if (part.kind === 'text' && k++ === this.ordinal)
38
+ return { part, index };
39
+ }
40
+ return { index: -1 };
41
+ }
42
+ /** Position among the block's content parts. */
43
+ get index() {
44
+ return this.#at.index;
45
+ }
25
46
  get value() {
26
- return deltaToJson(this.#children);
47
+ return deltaToJson(runsToDeltas(this.#at.part?.items ?? [])[0]);
48
+ }
49
+ /** The segment's text. */
50
+ get stringContent() {
51
+ return this.#at.part?.items.map((item) => item.text).join('') ?? '';
52
+ }
53
+ get isEmpty() {
54
+ return this.length === 0;
55
+ }
56
+ get endsWithNewline() {
57
+ return this.stringContent.endsWith('\n');
27
58
  }
28
59
  get length() {
29
- return this.yText.length;
60
+ return this.#at.part?.length ?? 0;
30
61
  }
31
- get children() {
32
- const transformer = this.parent.definition.transformText;
33
- return transformer
34
- ? jsonToDelta(transformer({ text: this, block: this.parent, content: this.value }))
35
- : this.#children;
62
+ /** Display offset of this segment inside its block's content (atoms count 1). */
63
+ get segStart() {
64
+ return this.#at.part?.start ?? 0;
36
65
  }
37
- set children(value) {
38
- this.#children = value;
66
+ /** The segment is shown by a live block. */
67
+ get isInDocument() {
68
+ return this.parent.isInTree && this.#at.part !== undefined;
39
69
  }
40
- setChildren = (text) => {
41
- this.stringContent = this.yText.toJSON();
42
- [this.children, this.isEmpty] = toDeltas(text || this.yText);
43
- this.endsWithNewline = this.stringContent.endsWith('\n');
44
- };
45
- observeText = (event, transaction) => {
46
- if (transaction.origin !== this.edytor.transaction) {
47
- // If the transaction is not from the edytor, we need to restore the selection
48
- // If the current text is not focused, this action will be ignored
49
- this.edytor.selection.restoreRelativePosition(this);
50
- }
51
- this.setChildren(event.target);
70
+ /**
71
+ * Re-create this block's text elements from its cell — the repair of a
72
+ * DOM the browser or a foreign script changed (typing and model commits
73
+ * never remount). Never while the IME owns the element. A remount under
74
+ * the caret is a render the projector displays after (`mounted`).
75
+ */
76
+ refreshFromModel = () => {
77
+ if (this.edytor.pin.owns(this.node))
78
+ return;
79
+ this.edytor.cells?.remount(this.parent.id);
52
80
  };
53
- constructor({ parent, content, yText }) {
54
- this.parent = parent;
55
- this.edytor = parent.edytor;
56
- this.yText = yText || new Y.Text();
57
- this.id = this.yText.doc ? this.yText.getAttribute('id') : id('t');
58
- if (content !== undefined) {
59
- // If content is provided we need to initialize the text with the content
60
- this.yText._pending?.push(() => {
61
- this.yText.setAttribute('id', this.id);
62
- if (typeof content === 'string') {
63
- this.yText.insert(0, content);
64
- }
65
- else {
66
- this.yText.applyDelta(content.map((part) => ({
67
- insert: part.text,
68
- attributes: part.marks
69
- })));
70
- }
71
- this.setChildren();
72
- });
73
- }
74
- else {
75
- this.setChildren();
76
- }
77
- this.edytor.idToText.set(this.id, this);
78
- if (!this.edytor.readonly) {
79
- this.yText.observe(this.observeText);
80
- }
81
- }
81
+ // ── segment writes ───────────────────────────────────────────────────
82
+ //
83
+ // `insertAt`/`deleteAt`/`formatAt` are the offset-based primitives the
84
+ // operation layer (`text.utils`), event handlers and plugins call. Offsets
85
+ // are SEGMENT-LOCAL display atoms (UTF-16 units); `segStart` maps them into
86
+ // the block's display space (read from the index, so a write after another
87
+ // in the same transaction lands right).
88
+ /** Insert `text` (optionally marked) at segment-local `offset`. */
89
+ insertAt = (offset, text, marks) => accepted(this.parent.model?.insertText(this.segStart + offset, text, marks ?? undefined));
90
+ /** Delete `length` atoms at segment-local `offset`. */
91
+ deleteAt = (offset, length) => accepted(this.parent.model?.deleteText(this.segStart + offset, length));
92
+ /** Multi-mark format over `[offset, offset+length)` — `null` values remove the mark. */
93
+ formatAt = (offset, length, attributes) => accepted(this.parent.model?.format(this.segStart + offset, length, attributes));
82
94
  batch = batch.bind(this);
83
95
  getMarksAtRange = getMarksAtRange.bind(this);
84
96
  insertText = this.batch('insertText', insertText.bind(this));
@@ -90,11 +102,13 @@ export class Text {
90
102
  attach = (node) => {
91
103
  this.node = node;
92
104
  this.edytor.nodeToText.set(node, this);
105
+ const release = this.edytor.surface.register(node, 'text', this.parent.id);
93
106
  node.setAttribute('data-edytor-id', `${this.id}`);
94
107
  node.setAttribute('data-edytor-text', `true`);
95
108
  let pluginDestroy = this.edytor.plugins.reduce((acc, plugin) => {
96
109
  const action = plugin.onTextAttached?.({ node, text: this });
97
- action && acc.push(action);
110
+ if (typeof action === 'function')
111
+ acc.push(action);
98
112
  return acc;
99
113
  }, []);
100
114
  let insideVoid = this.parent.definition.void;
@@ -105,13 +119,18 @@ export class Text {
105
119
  }
106
120
  });
107
121
  if (insideVoid) {
108
- node.contentEditable = 'true';
122
+ node.setAttribute('contenteditable', 'true');
109
123
  node.style.outline = 'none';
110
124
  }
125
+ // A display that waited for a mounted destination runs in the next pass.
126
+ this.edytor.projector?.mounted(this);
111
127
  return {
112
128
  destroy: () => {
113
- this.yText?.unobserve(this.observeText);
114
- this.edytor.idToText.delete(this.id);
129
+ if (this.node === node)
130
+ this.node = undefined;
131
+ if (this.edytor.nodeToText.get(node) === this)
132
+ this.edytor.nodeToText.delete(node);
133
+ release();
115
134
  pluginDestroy.forEach((destroy) => destroy());
116
135
  }
117
136
  };
@@ -33,8 +33,13 @@ export type TextOperations = {
33
33
  export declare function batch<T extends (...args: any[]) => any, O extends keyof TextOperations>(operation: O, func: T): T;
34
34
  export declare function insertText(this: Text, { value, isAutoDot, start, end, marks }: TextOperations['insertText']): void;
35
35
  export declare function getMarksAtRange(this: Text, yStart: number, yEnd: number): JSONText[];
36
- export declare function deleteText(this: Text, { direction, length }: TextOperations['deleteText']): void;
37
- export declare function removeMarksFromText(this: Text, { start, end }: TextOperations['markText']): void;
36
+ export declare const getPreviousGraphemeStart: (value: string, offset: number) => number;
37
+ export declare const getNextGraphemeEnd: (value: string, offset: number) => number;
38
+ export declare function deleteText(this: Text, { direction, length }: TextOperations['deleteText']): {
39
+ start: number;
40
+ end: number;
41
+ } | undefined;
42
+ export declare function removeMarksFromText(this: Text, { start, end }: TextOperations['removeMarksFromText']): void;
38
43
  export declare function markText(this: Text, { mark, value, toggle, start, end }: TextOperations['markText']): void;
39
44
  export declare function splitText(this: Text, { index }: TextOperations['splitText']): JSONText[];
40
45
  export declare function setText(this: Text, { value }: TextOperations['setText']): void;
@@ -1,62 +1,50 @@
1
- import { prevent } from '../utils.js';
1
+ import { marksForInsertion } from '../session/editing/text.js';
2
2
  export function batch(operation, func) {
3
3
  return function (payload) {
4
- let finalPayload = payload;
5
- for (const plugin of this.edytor.plugins) {
6
- // @ts-expect-error
7
- const normalizedPayload = plugin.onBeforeOperation?.({
8
- operation,
9
- payload,
10
- text: this,
11
- block: this.parent,
12
- prevent
13
- });
14
- if (normalizedPayload) {
15
- finalPayload = normalizedPayload;
16
- break;
17
- }
18
- }
19
- const result = this.edytor.transact(() => func.bind(this)(finalPayload));
20
- for (const plugin of this.edytor.plugins) {
21
- plugin.onAfterOperation?.({
22
- operation,
23
- payload,
24
- text: this,
25
- block: this.parent
26
- });
27
- }
28
- return result;
4
+ // Dispatched like block operations (`session/commands.ts`): plugins see
5
+ // `block: this.parent` + `text: this`, the text arm of `ChangePayload`.
6
+ return this.edytor.dispatcher.dispatch(operation, payload, { block: this.parent, text: this }, func);
29
7
  };
30
8
  }
31
- export function insertText({ value, isAutoDot, start = this.edytor.selection.state.yStart, end = this.edytor.selection.state.yEnd, marks = this.markOnNextInsert }) {
9
+ export function insertText({ value, isAutoDot, start = this.edytor.selection.state.yStart, end = this.edytor.selection.state.yEnd, marks }) {
32
10
  const isCollapsed = start === end || !end;
33
- // const attributes = this.getAttributesAtPosition(yStart);
34
- const deltas = [{ retain: start }, { insert: value, attributes: marks }];
35
- if (isAutoDot) {
36
- deltas[0].retain = start - 1;
37
- deltas.splice(1, 0, { delete: 1 });
38
- }
39
- if (!isCollapsed) {
40
- deltas.splice(1, 0, { delete: end - start });
41
- }
42
- this.edytor.doc.transact(() => {
43
- if (isAutoDot || !isCollapsed) {
44
- this.yText.applyDelta(deltas);
11
+ // The caret's pending marks (L4) apply to an insertion at the caret, which consumes them.
12
+ const { selection } = this.edytor;
13
+ const { startText, yStart } = selection.state;
14
+ const pending = startText === this && yStart === start ? selection.pending : undefined;
15
+ marks ??= marksForInsertion(this, start, {
16
+ replaced: isCollapsed ? undefined : this.getMarksAtRange(start, end),
17
+ pending
18
+ });
19
+ this.edytor.transact(() => {
20
+ if (isAutoDot) {
21
+ // Replace the previous char with the inserted value (autocorrect).
22
+ this.deleteAt(start - 1, 1);
23
+ this.insertAt(start - 1, value, marks);
24
+ }
25
+ else if (!isCollapsed) {
26
+ this.deleteAt(start, end - start);
27
+ this.insertAt(start, value, marks);
45
28
  }
46
29
  else {
47
- this.yText.insert(start, value, marks);
30
+ this.insertAt(start, value, marks);
48
31
  }
49
32
  });
50
- if (this.markOnNextInsert) {
51
- this.markOnNextInsert = undefined;
52
- }
33
+ if (pending)
34
+ selection.stage(undefined);
53
35
  }
54
36
  export function getMarksAtRange(yStart, yEnd) {
55
37
  const result = [];
56
38
  let offset = 0;
57
39
  let entered = false;
58
- for (let i = 0; i < this.children.length; i++) {
59
- const { text, marks } = this.children[i];
40
+ // Iterate the MODEL runs (`this.value`), never `this.children` — the
41
+ // children getter applies the block's `transformText` (e.g. code
42
+ // tokens), whose marks are local decorations. Reading them here leaked
43
+ // `codeToken` into persisted marks: typed/composed text inside a code
44
+ // line inherited the decoration, splitting the serialized content.
45
+ const parts = this.value;
46
+ for (let i = 0; i < parts.length; i++) {
47
+ const { text, marks } = parts[i];
60
48
  const length = text.length;
61
49
  const end = offset + length;
62
50
  if (yStart >= offset && yStart < end) {
@@ -66,14 +54,14 @@ export function getMarksAtRange(yStart, yEnd) {
66
54
  const endOffset = Math.min(length, yEnd - offset);
67
55
  result.push({
68
56
  text: text.slice(startOffset, endOffset),
69
- marks: Object.fromEntries(marks)
57
+ marks: { ...(marks ?? {}) }
70
58
  });
71
59
  }
72
60
  else if (entered && end <= yEnd) {
73
61
  // Middle of range
74
62
  result.push({
75
63
  text,
76
- marks: Object.fromEntries(marks)
64
+ marks: { ...(marks ?? {}) }
77
65
  });
78
66
  }
79
67
  else if (entered && offset < yEnd && yEnd <= end) {
@@ -81,7 +69,7 @@ export function getMarksAtRange(yStart, yEnd) {
81
69
  const endOffset = yEnd - offset;
82
70
  result.push({
83
71
  text: text.slice(0, endOffset),
84
- marks: Object.fromEntries(marks)
72
+ marks: { ...(marks ?? {}) }
85
73
  });
86
74
  break;
87
75
  }
@@ -89,57 +77,89 @@ export function getMarksAtRange(yStart, yEnd) {
89
77
  }
90
78
  return result;
91
79
  }
80
+ const getGraphemeBoundaries = (value) => {
81
+ const Segmenter = Intl.Segmenter;
82
+ if (Segmenter) {
83
+ return Array.from(new Segmenter(undefined, { granularity: 'grapheme' }).segment(value)).map(({ index, segment }) => ({
84
+ start: index,
85
+ end: index + segment.length
86
+ }));
87
+ }
88
+ let index = 0;
89
+ return Array.from(value).map((segment) => {
90
+ const start = index;
91
+ index += segment.length;
92
+ return {
93
+ start,
94
+ end: index
95
+ };
96
+ });
97
+ };
98
+ export const getPreviousGraphemeStart = (value, offset) => {
99
+ const clampedOffset = Math.min(Math.max(offset, 0), value.length);
100
+ let previousStart = 0;
101
+ for (const boundary of getGraphemeBoundaries(value)) {
102
+ if (boundary.end >= clampedOffset) {
103
+ return boundary.start < clampedOffset ? boundary.start : previousStart;
104
+ }
105
+ previousStart = boundary.start;
106
+ }
107
+ return previousStart;
108
+ };
109
+ export const getNextGraphemeEnd = (value, offset) => {
110
+ const clampedOffset = Math.min(Math.max(offset, 0), value.length);
111
+ for (const boundary of getGraphemeBoundaries(value)) {
112
+ if (boundary.end > clampedOffset) {
113
+ return boundary.end;
114
+ }
115
+ }
116
+ return clampedOffset;
117
+ };
92
118
  export function deleteText({ direction, length = 1 }) {
93
119
  const { yStart, isCollapsed } = this.edytor.selection.state;
94
- const deltas = direction === 'BACKWARD'
95
- ? [{ retain: isCollapsed ? yStart - 1 : yStart }, { delete: isCollapsed ? 1 : length }]
96
- : [{ retain: isCollapsed ? yStart : yStart }, { delete: isCollapsed ? 1 : length }];
97
- this.yText.applyDelta(deltas);
120
+ const requestedLength = Math.max(0, length);
121
+ const textLength = this.length;
122
+ if (requestedLength === 0 || textLength === 0) {
123
+ return;
124
+ }
125
+ const shouldDeleteSingleGrapheme = isCollapsed && requestedLength === 1;
126
+ const start = shouldDeleteSingleGrapheme && direction === 'BACKWARD'
127
+ ? getPreviousGraphemeStart(this.stringContent, yStart)
128
+ : direction === 'BACKWARD' && isCollapsed
129
+ ? Math.max(0, yStart - requestedLength)
130
+ : Math.max(0, yStart);
131
+ const end = shouldDeleteSingleGrapheme && direction === 'FORWARD'
132
+ ? getNextGraphemeEnd(this.stringContent, yStart)
133
+ : direction === 'BACKWARD' && isCollapsed
134
+ ? Math.min(textLength, yStart)
135
+ : Math.min(textLength, start + requestedLength);
136
+ const deleteLength = end - start;
137
+ if (deleteLength <= 0) {
138
+ return;
139
+ }
140
+ this.deleteAt(start, deleteLength);
141
+ return { start, end };
98
142
  }
99
- export function removeMarksFromText({ start = this.edytor.selection.state.yStart || 0, end = this.edytor.selection.state.yEnd || this.yText.length }) {
100
- const marksAtRange = this.getMarksAtRange(start, end);
101
- const attributes = marksAtRange.reduce((acc, { marks }) => {
102
- Object.entries(marks || {}).forEach(([key, value]) => {
103
- if (value === null) {
104
- Object.assign({ key: null });
105
- }
106
- });
107
- return acc;
108
- }, {});
109
- this.yText.format(start, end, attributes);
143
+ export function removeMarksFromText({ start = this.edytor.selection.state.yStart || 0, end = this.edytor.selection.state.yEnd || this.length }) {
144
+ // Persisted mark changes delegate to the document: `clearMarks` discovers
145
+ // every mark name present in the range and unsets them; `segStart` maps
146
+ // the segment-local range into the block's display offsets.
147
+ this.parent.model?.clearMarks(this.segStart + start, end - start);
110
148
  }
111
149
  export function markText({ mark, value = true, toggle = false, start = this.edytor.selection.state.yStart, end = this.edytor.selection.state.yEnd }) {
112
- const length = end - start;
113
- const isCollasped = end - start === 0;
114
- const marksAtRange = this.getMarksAtRange(isCollasped ? start - 1 : start, end);
115
- const isNextActiveMark = isCollasped && this.markOnNextInsert && mark in this.markOnNextInsert;
116
- const spreadOnAllRange = marksAtRange.every(({ marks }) => marks && mark in marks);
117
- const markValue = (spreadOnAllRange || isNextActiveMark) && toggle ? null : value;
118
- if (isCollasped) {
119
- const activeMarks = marksAtRange.reduce((acc, { marks }) => {
120
- Object.entries(marks || {}).forEach(([key, value]) => {
121
- if (value === true) {
122
- Object.assign(acc, { [key]: true });
123
- }
124
- });
125
- return acc;
126
- }, {});
127
- if (isNextActiveMark && markValue === null) {
128
- delete this.markOnNextInsert[mark];
129
- }
130
- else {
131
- this.markOnNextInsert = {
132
- ...(this.markOnNextInsert || {}),
133
- ...activeMarks,
134
- [mark]: markValue
135
- };
136
- }
137
- }
138
- else {
139
- this.yText.format(start, length, {
140
- [mark]: markValue
150
+ if (start === end) {
151
+ // A caret stages the full set the next insertion carries (values kept).
152
+ const { selection } = this.edytor;
153
+ const { [mark]: current = null, ...rest } = marksForInsertion(this, start, {
154
+ pending: selection.pending
141
155
  });
156
+ const next = current !== null && toggle ? null : value;
157
+ selection.stage(next === null ? rest : { ...rest, [mark]: next });
158
+ return;
142
159
  }
160
+ const marksAtRange = this.getMarksAtRange(start, end);
161
+ const spreadOnAllRange = marksAtRange.length > 0 && marksAtRange.every(({ marks }) => marks && mark in marks);
162
+ this.formatAt(start, end - start, { [mark]: spreadOnAllRange && toggle ? null : value });
143
163
  }
144
164
  // This function split a Y.Text at an index, delete what is after the index and returns the deleted content as a JSONText[]
145
165
  export function splitText({ index = this.edytor.selection.state.yStart }) {
@@ -163,12 +183,16 @@ export function splitText({ index = this.edytor.selection.state.yStart }) {
163
183
  }
164
184
  offset = nextOffset;
165
185
  }
166
- this.yText.delete(index, this.yText.length - index);
186
+ this.deleteAt(index, this.length - index);
167
187
  return content;
168
188
  }
169
189
  export function setText({ value }) {
170
- this.yText.applyDelta([
171
- { delete: this.yText.length },
172
- ...value.map((part) => ({ insert: part.text, attributes: part.marks }))
173
- ]);
190
+ this.deleteAt(0, this.length);
191
+ let offset = 0;
192
+ for (const part of value) {
193
+ if (part.text.length) {
194
+ this.insertAt(offset, part.text, part.marks);
195
+ offset += part.text.length;
196
+ }
197
+ }
174
198
  }