@voithos-labs/aragonite 0.10.3 → 0.10.7

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 (1021) hide show
  1. package/README.md +2 -2
  2. package/dist/a11y-strings.d.ts +12 -5
  3. package/dist/a11y-strings.js +61 -5
  4. package/dist/action-contracts.d.ts +242 -155
  5. package/dist/action-contracts.js +2 -2
  6. package/dist/active-editor.d.ts +3 -3
  7. package/dist/active-editor.js +8 -9
  8. package/dist/ambient/ambient-dom.d.ts +2 -5
  9. package/dist/ambient/ambient-dom.js +16 -62
  10. package/dist/assert.js +6 -5
  11. package/dist/block-component.d.ts +135 -109
  12. package/dist/block-component.js +30 -22
  13. package/dist/block-id.d.ts +6 -10
  14. package/dist/block-id.js +25 -14
  15. package/dist/bounded-memo.d.ts +5 -5
  16. package/dist/bounded-memo.js +6 -6
  17. package/dist/components/BlockDragHandle.svelte +13 -20
  18. package/dist/components/BlockHost.svelte +56 -134
  19. package/dist/components/BlockList.svelte +22 -19
  20. package/dist/components/DecorationOverlay.svelte +9 -10
  21. package/dist/components/DecorationOverlay.svelte.d.ts +2 -2
  22. package/dist/components/Editor.svelte +619 -1089
  23. package/dist/components/Editor.svelte.d.ts +9 -20
  24. package/dist/components/GapCaret.svelte +26 -59
  25. package/dist/components/SelectionOverlay.svelte +36 -67
  26. package/dist/components/SelectionOverlay.svelte.d.ts +6 -4
  27. package/dist/components/TailInsert.svelte +8 -55
  28. package/dist/components/TailInsert.svelte.d.ts +4 -6
  29. package/dist/components/block-content-selector.d.ts +11 -11
  30. package/dist/components/block-content-selector.js +11 -11
  31. package/dist/components/block-el-lookup.d.ts +6 -0
  32. package/dist/components/block-el-lookup.js +27 -0
  33. package/dist/components/blocks/BlockquoteBlock.svelte +3 -3
  34. package/dist/components/blocks/ThematicBreakBlock.svelte +22 -63
  35. package/dist/components/blocks/ThematicBreakBlock.svelte.d.ts +0 -2
  36. package/dist/components/blocks/code/CodeBlock.svelte +255 -276
  37. package/dist/components/blocks/code/CodeBlock.svelte.d.ts +2 -3
  38. package/dist/components/blocks/code/CodeBlockRail.svelte +103 -100
  39. package/dist/components/blocks/code/CodeBlockRail.svelte.d.ts +9 -4
  40. package/dist/components/blocks/code/code-beforeinput.d.ts +1 -1
  41. package/dist/components/blocks/code/code-bootstrap.d.ts +3 -5
  42. package/dist/components/blocks/code/code-bootstrap.js +35 -28
  43. package/dist/components/blocks/code/code-context-actions.js +5 -4
  44. package/dist/components/blocks/code/code-enter.js +2 -2
  45. package/dist/components/blocks/code/code-fence-boundary.d.ts +29 -46
  46. package/dist/components/blocks/code/code-fence-boundary.js +40 -66
  47. package/dist/components/blocks/code/code-fence-exit.d.ts +6 -11
  48. package/dist/components/blocks/code/code-fence-exit.js +24 -25
  49. package/dist/components/blocks/code/code-indent.d.ts +2 -2
  50. package/dist/components/blocks/code/code-indent.js +4 -7
  51. package/dist/components/blocks/code/code-languages.d.ts +16 -12
  52. package/dist/components/blocks/code/code-languages.js +58 -32
  53. package/dist/components/blocks/code/code-paste-surface.d.ts +3 -2
  54. package/dist/components/blocks/code/code-paste-surface.js +9 -18
  55. package/dist/components/blocks/code/code-renderer.d.ts +21 -5
  56. package/dist/components/blocks/code/code-renderer.js +90 -125
  57. package/dist/components/blocks/directive/DirectiveContainerBlock.svelte +5 -8
  58. package/dist/components/blocks/directive/activate-directives.d.ts +4 -4
  59. package/dist/components/blocks/directive/activate-directives.js +18 -13
  60. package/dist/components/blocks/editable-leaf.d.ts +50 -74
  61. package/dist/components/blocks/editable-leaf.js +144 -202
  62. package/dist/components/blocks/editable-surface.d.ts +96 -100
  63. package/dist/components/blocks/editable-surface.js +101 -109
  64. package/dist/components/blocks/list/ListBlock.svelte +46 -90
  65. package/dist/components/blocks/list/ListItemBlock.svelte +99 -144
  66. package/dist/components/blocks/list/ListItemBlock.svelte.d.ts +3 -0
  67. package/dist/components/blocks/list/task-checkbox.d.ts +5 -2
  68. package/dist/components/blocks/list/task-checkbox.js +12 -7
  69. package/dist/components/blocks/plain-text-backend.d.ts +4 -20
  70. package/dist/components/blocks/plain-text-backend.js +9 -43
  71. package/dist/components/blocks/surface-wiring.svelte.d.ts +8 -9
  72. package/dist/components/blocks/surface-wiring.svelte.js +15 -34
  73. package/dist/components/blocks/table/TableActionMenu.svelte +19 -18
  74. package/dist/components/blocks/table/TableActionMenu.svelte.d.ts +3 -1
  75. package/dist/components/blocks/table/TableBlock.svelte +100 -165
  76. package/dist/components/blocks/table/TableBlock.svelte.d.ts +3 -3
  77. package/dist/components/blocks/table/TableCellBlock.svelte +307 -385
  78. package/dist/components/blocks/table/TableCellBlock.svelte.d.ts +1 -0
  79. package/dist/components/blocks/table/TableRowBlock.svelte +60 -104
  80. package/dist/components/blocks/table/TableRowBlock.svelte.d.ts +0 -1
  81. package/dist/components/blocks/table/cell-keydown-plan.d.ts +4 -9
  82. package/dist/components/blocks/table/cell-keydown-plan.js +8 -12
  83. package/dist/components/blocks/table/cell-pointer.d.ts +18 -23
  84. package/dist/components/blocks/table/cell-pointer.js +49 -71
  85. package/dist/components/blocks/table/cell-render.d.ts +24 -29
  86. package/dist/components/blocks/table/cell-render.js +29 -31
  87. package/dist/components/blocks/table/selected-cells.d.ts +7 -7
  88. package/dist/components/blocks/table/selected-cells.js +9 -13
  89. package/dist/components/blocks/table/table-caret-at-point.d.ts +4 -4
  90. package/dist/components/blocks/table/table-caret-at-point.js +5 -5
  91. package/dist/components/blocks/table/table-cell-paste.d.ts +5 -11
  92. package/dist/components/blocks/table/table-cell-paste.js +27 -43
  93. package/dist/components/blocks/table/table-drag-hit-test.js +2 -1
  94. package/dist/components/blocks/table/table-menu-model.d.ts +4 -8
  95. package/dist/components/blocks/table/table-menu-model.js +6 -10
  96. package/dist/components/blocks/table/table-navigation.js +2 -2
  97. package/dist/components/blocks/text/TextEditableBlock.svelte +392 -310
  98. package/dist/components/blocks/text/TextEditableBlock.svelte.d.ts +2 -1
  99. package/dist/components/blocks/text/auto-pair-record.d.ts +23 -0
  100. package/dist/components/blocks/text/auto-pair-record.js +51 -0
  101. package/dist/components/blocks/text/click-snap-guard.d.ts +9 -4
  102. package/dist/components/blocks/text/click-snap-guard.js +16 -5
  103. package/dist/components/blocks/text/composition-seat.d.ts +17 -14
  104. package/dist/components/blocks/text/composition-seat.js +11 -11
  105. package/dist/components/blocks/text/construct-edge-delete.d.ts +20 -20
  106. package/dist/components/blocks/text/construct-edge-delete.js +50 -65
  107. package/dist/components/blocks/text/construct-reveal.d.ts +16 -21
  108. package/dist/components/blocks/text/construct-reveal.js +13 -14
  109. package/dist/components/blocks/text/delimiter-autopair.d.ts +51 -34
  110. package/dist/components/blocks/text/delimiter-autopair.js +87 -103
  111. package/dist/components/blocks/text/edge-policy-dispatch.d.ts +44 -46
  112. package/dist/components/blocks/text/edge-policy-dispatch.js +164 -180
  113. package/dist/components/blocks/text/edge-seat.d.ts +17 -26
  114. package/dist/components/blocks/text/edge-seat.js +43 -70
  115. package/dist/components/blocks/text/link-at-point.d.ts +9 -9
  116. package/dist/components/blocks/text/link-at-point.js +12 -15
  117. package/dist/components/blocks/text/live-join-seam.d.ts +6 -9
  118. package/dist/components/blocks/text/live-join-seam.js +75 -112
  119. package/dist/components/blocks/text/live-selection-edit.d.ts +14 -43
  120. package/dist/components/blocks/text/live-selection-edit.js +32 -105
  121. package/dist/components/blocks/text/live-split-rebalance.d.ts +9 -13
  122. package/dist/components/blocks/text/live-split-rebalance.js +50 -67
  123. package/dist/components/blocks/text/marker-completion.d.ts +7 -12
  124. package/dist/components/blocks/text/marker-completion.js +17 -10
  125. package/dist/components/blocks/text/pending-mark-insert.d.ts +11 -18
  126. package/dist/components/blocks/text/pending-mark-insert.js +30 -49
  127. package/dist/components/blocks/text/screen-diff.d.ts +5 -15
  128. package/dist/components/blocks/text/screen-diff.js +5 -19
  129. package/dist/components/blocks/text/text-clipboard.d.ts +23 -32
  130. package/dist/components/blocks/text/text-clipboard.js +27 -32
  131. package/dist/components/blocks/text/text-keydown.d.ts +20 -30
  132. package/dist/components/blocks/text/text-keydown.js +54 -51
  133. package/dist/components/blocks/text/text-render.d.ts +25 -35
  134. package/dist/components/blocks/text/text-render.js +82 -61
  135. package/dist/components/blocks/text/widget-adjacency.d.ts +9 -9
  136. package/dist/components/blocks/text/widget-adjacency.js +17 -17
  137. package/dist/components/blocks/text/widget-interaction.d.ts +67 -43
  138. package/dist/components/blocks/text/widget-interaction.js +243 -208
  139. package/dist/components/blocks/widget-portal.d.ts +20 -29
  140. package/dist/components/blocks/widget-portal.js +16 -14
  141. package/dist/components/built-in-blocks.d.ts +3 -4
  142. package/dist/components/built-in-blocks.js +17 -18
  143. package/dist/components/drag-handle.d.ts +13 -30
  144. package/dist/components/drag-handle.js +25 -63
  145. package/dist/components/editor-built-ins.d.ts +1 -0
  146. package/dist/components/editor-built-ins.js +16 -0
  147. package/dist/components/editor-root-clipboard.d.ts +6 -6
  148. package/dist/components/editor-root-clipboard.js +16 -27
  149. package/dist/components/editor-root-document-swap.d.ts +49 -0
  150. package/dist/components/editor-root-document-swap.js +54 -0
  151. package/dist/components/editor-root-focus.d.ts +5 -4
  152. package/dist/components/editor-root-focus.js +51 -22
  153. package/dist/components/editor-root-focused-surface.d.ts +35 -0
  154. package/dist/components/editor-root-focused-surface.js +65 -0
  155. package/dist/components/editor-root-geometry.d.ts +15 -24
  156. package/dist/components/editor-root-geometry.js +27 -31
  157. package/dist/components/editor-root-gestures.d.ts +39 -0
  158. package/dist/components/editor-root-gestures.js +189 -0
  159. package/dist/components/editor-root-keydown.d.ts +10 -25
  160. package/dist/components/editor-root-keydown.js +19 -43
  161. package/dist/components/editor-root-listeners.d.ts +22 -31
  162. package/dist/components/editor-root-listeners.js +49 -46
  163. package/dist/components/editor-root-menus.d.ts +51 -0
  164. package/dist/components/editor-root-menus.js +147 -0
  165. package/dist/components/editor-root-mode-flip.d.ts +16 -11
  166. package/dist/components/editor-root-mode-flip.js +36 -34
  167. package/dist/components/editor-root-scroll-host.d.ts +22 -0
  168. package/dist/components/editor-root-scroll-host.js +34 -0
  169. package/dist/components/editor-root-test-surface.d.ts +48 -0
  170. package/dist/components/editor-root-test-surface.js +6 -0
  171. package/dist/components/image/ImageOverlayHost.svelte +44 -35
  172. package/dist/components/image/ImageOverlayHost.svelte.d.ts +5 -6
  173. package/dist/components/image/ImageProperties.svelte +37 -41
  174. package/dist/components/image/ImageProperties.svelte.d.ts +9 -4
  175. package/dist/components/image/ImageResizeHandles.svelte +26 -30
  176. package/dist/components/image/image-crop.d.ts +5 -11
  177. package/dist/components/image/image-crop.js +5 -11
  178. package/dist/components/image/image-edit-commit.d.ts +19 -16
  179. package/dist/components/image/image-edit-commit.js +74 -38
  180. package/dist/components/image/image-resize.d.ts +2 -5
  181. package/dist/components/image/image-resize.js +3 -6
  182. package/dist/components/image/image-widget-editing.d.ts +3 -3
  183. package/dist/components/image/image-widget-editing.js +9 -9
  184. package/dist/components/image/widget-dom.d.ts +2 -3
  185. package/dist/components/image/widget-dom.js +19 -24
  186. package/dist/components/image/widget-selection-state.svelte.d.ts +10 -11
  187. package/dist/components/image/widget-selection-state.svelte.js +26 -19
  188. package/dist/components/kind-cue.svelte.d.ts +21 -0
  189. package/dist/components/kind-cue.svelte.js +35 -0
  190. package/dist/components/link-card/LinkCard.svelte +115 -64
  191. package/dist/components/link-card/LinkCard.svelte.d.ts +7 -5
  192. package/dist/components/link-card/LinkCardHost.svelte +42 -33
  193. package/dist/components/link-card/LinkCardHost.svelte.d.ts +10 -8
  194. package/dist/components/link-card/link-card-commit.d.ts +16 -19
  195. package/dist/components/link-card/link-card-commit.js +21 -30
  196. package/dist/components/link-card/link-card-entry.d.ts +13 -23
  197. package/dist/components/link-card/link-card-entry.js +16 -24
  198. package/dist/components/link-card/link-card-state.svelte.d.ts +17 -21
  199. package/dist/components/link-card/link-card-state.svelte.js +2 -2
  200. package/dist/components/lrd-map-gate.d.ts +4 -11
  201. package/dist/components/lrd-map-gate.js +5 -11
  202. package/dist/components/menu/BlockMenu.svelte +20 -81
  203. package/dist/components/menu/BlockMenu.svelte.d.ts +11 -9
  204. package/dist/components/menu/InlineMenuHost.svelte +191 -0
  205. package/dist/components/menu/InlineMenuHost.svelte.d.ts +13 -0
  206. package/dist/components/menu/MenuIcon.svelte +3 -103
  207. package/dist/components/menu/MenuIcon.svelte.d.ts +2 -44
  208. package/dist/components/menu/SelectionToolbar.svelte +380 -0
  209. package/dist/components/menu/SelectionToolbar.svelte.d.ts +14 -0
  210. package/dist/components/menu/clipboard-actions.d.ts +3 -4
  211. package/dist/components/menu/clipboard-actions.js +3 -4
  212. package/dist/components/menu/default-context-actions.d.ts +4 -13
  213. package/dist/components/menu/default-context-actions.js +49 -67
  214. package/dist/components/menu/flyout-placement.d.ts +2 -2
  215. package/dist/components/menu/flyout-placement.js +2 -2
  216. package/dist/components/menu/menu-presence.svelte.d.ts +12 -0
  217. package/dist/components/menu/menu-presence.svelte.js +19 -0
  218. package/dist/components/paste-image-arm.d.ts +6 -11
  219. package/dist/components/paste-image-arm.js +11 -18
  220. package/dist/components/portal.d.ts +2 -5
  221. package/dist/components/portal.js +4 -7
  222. package/dist/core/directive/activate.d.ts +4 -5
  223. package/dist/core/directive/activate.js +8 -9
  224. package/dist/core/directive/container-opener.js +13 -12
  225. package/dist/core/directive/grammar.d.ts +2 -5
  226. package/dist/core/directive/grammar.js +10 -10
  227. package/dist/core/directive/kinds.d.ts +4 -7
  228. package/dist/core/directive/kinds.js +14 -16
  229. package/dist/core/directive/registry.d.ts +12 -9
  230. package/dist/core/directive/registry.js +19 -20
  231. package/dist/core/directive/text-recognizer.d.ts +3 -2
  232. package/dist/core/directive/text-recognizer.js +5 -9
  233. package/dist/core/escapable.d.ts +1 -5
  234. package/dist/core/escapable.js +1 -5
  235. package/dist/core/inline/backticks.d.ts +3 -4
  236. package/dist/core/inline/backticks.js +3 -4
  237. package/dist/core/inline/character-refs.js +2 -1
  238. package/dist/core/inline/destination-bytes.d.ts +6 -3
  239. package/dist/core/inline/destination-bytes.js +50 -8
  240. package/dist/core/inline/entity-widget.d.ts +4 -3
  241. package/dist/core/inline/entity-widget.js +6 -6
  242. package/dist/core/inline/format-toggle.d.ts +22 -28
  243. package/dist/core/inline/format-toggle.js +97 -129
  244. package/dist/core/inline/html-entities.d.ts +2 -3
  245. package/dist/core/inline/html-entities.js +2 -3
  246. package/dist/core/inline/html-tag-grammar.js +6 -2
  247. package/dist/core/inline/image-dimensions.d.ts +2 -0
  248. package/dist/core/inline/image-dimensions.js +19 -2
  249. package/dist/core/inline/image-source-bytes.d.ts +11 -0
  250. package/dist/core/inline/image-source-bytes.js +71 -0
  251. package/dist/core/inline/index.d.ts +28 -21
  252. package/dist/core/inline/index.js +56 -34
  253. package/dist/core/inline/inline-cache.d.ts +12 -15
  254. package/dist/core/inline/inline-cache.js +11 -14
  255. package/dist/core/inline/inline-widgets.d.ts +55 -68
  256. package/dist/core/inline/inline-widgets.js +55 -58
  257. package/dist/core/inline/link-destination.d.ts +31 -0
  258. package/dist/core/inline/link-destination.js +129 -0
  259. package/dist/core/inline/link-reference-resolver.d.ts +8 -6
  260. package/dist/core/inline/link-reference-resolver.js +10 -6
  261. package/dist/core/inline/link-source-bytes.d.ts +31 -0
  262. package/dist/{components/blocks/text → core/inline}/link-source-bytes.js +43 -54
  263. package/dist/core/inline/live-edit/read-back.d.ts +29 -0
  264. package/dist/core/inline/live-edit/read-back.js +50 -0
  265. package/dist/core/inline/picture.d.ts +10 -0
  266. package/dist/core/inline/picture.js +40 -0
  267. package/dist/core/inline/scan/autolinks.d.ts +7 -8
  268. package/dist/core/inline/scan/autolinks.js +80 -59
  269. package/dist/core/inline/scan/brackets.d.ts +2 -2
  270. package/dist/core/inline/scan/brackets.js +6 -103
  271. package/dist/core/inline/scan/code-spans.d.ts +4 -0
  272. package/dist/core/inline/scan/code-spans.js +8 -0
  273. package/dist/core/inline/scan/emphasis.js +10 -14
  274. package/dist/core/inline/scan/index.d.ts +3 -1
  275. package/dist/core/inline/scan/index.js +32 -33
  276. package/dist/core/inline/scan/plugin-syntax.d.ts +28 -36
  277. package/dist/core/inline/scan/plugin-syntax.js +75 -89
  278. package/dist/core/inline/scan/scan-state.d.ts +2 -0
  279. package/dist/core/inline/scan/scan-state.js +1 -0
  280. package/dist/core/inline/scan/simple-nodes.d.ts +2 -5
  281. package/dist/core/inline/scan/simple-nodes.js +2 -5
  282. package/dist/core/inline/scan/triggers.d.ts +17 -0
  283. package/dist/core/inline/scan/triggers.js +26 -0
  284. package/dist/core/inline/scan/url.js +8 -10
  285. package/dist/core/inline/transparency.d.ts +2 -1
  286. package/dist/core/inline/transparency.js +33 -17
  287. package/dist/core/inline/visibility.d.ts +30 -49
  288. package/dist/core/inline/visibility.js +31 -49
  289. package/dist/core/inline/walk.d.ts +4 -10
  290. package/dist/core/inline/walk.js +4 -10
  291. package/dist/core/inline-render.d.ts +22 -27
  292. package/dist/core/inline-render.js +51 -60
  293. package/dist/core/lines.d.ts +67 -26
  294. package/dist/core/lines.js +164 -33
  295. package/dist/core/metadata-parity.d.ts +9 -0
  296. package/dist/core/metadata-parity.js +25 -0
  297. package/dist/core/node-views.d.ts +7 -6
  298. package/dist/core/node-views.js +5 -5
  299. package/dist/core/nodes.d.ts +34 -44
  300. package/dist/core/nodes.js +4 -12
  301. package/dist/core/parser.d.ts +27 -34
  302. package/dist/core/parser.js +53 -67
  303. package/dist/core/parsers/blockquote.d.ts +5 -8
  304. package/dist/core/parsers/blockquote.js +11 -10
  305. package/dist/core/parsers/built-in-openers.d.ts +2 -5
  306. package/dist/core/parsers/built-in-openers.js +5 -8
  307. package/dist/core/parsers/fence-syntax.d.ts +36 -7
  308. package/dist/core/parsers/fence-syntax.js +61 -11
  309. package/dist/core/parsers/fenced-code.d.ts +16 -0
  310. package/dist/core/parsers/fenced-code.js +16 -15
  311. package/dist/core/parsers/heading.d.ts +19 -2
  312. package/dist/core/parsers/heading.js +50 -2
  313. package/dist/core/parsers/html-block.d.ts +3 -6
  314. package/dist/core/parsers/html-block.js +10 -11
  315. package/dist/core/parsers/indented-code.d.ts +1 -1
  316. package/dist/core/parsers/indented-code.js +2 -8
  317. package/dist/core/parsers/link-reference.d.ts +5 -3
  318. package/dist/core/parsers/link-reference.js +116 -120
  319. package/dist/core/parsers/list.d.ts +12 -5
  320. package/dist/core/parsers/list.js +53 -36
  321. package/dist/core/parsers/paragraph.d.ts +3 -3
  322. package/dist/core/parsers/paragraph.js +14 -5
  323. package/dist/core/parsers/table-completion.d.ts +2 -5
  324. package/dist/core/parsers/table-completion.js +7 -10
  325. package/dist/core/parsers/table.d.ts +8 -8
  326. package/dist/core/parsers/table.js +23 -26
  327. package/dist/core/parsers/thematic-break.js +15 -14
  328. package/dist/core/paths.d.ts +13 -0
  329. package/dist/core/paths.js +31 -0
  330. package/dist/core/terminator-escalation.d.ts +0 -7
  331. package/dist/core/terminator-escalation.js +5 -8
  332. package/dist/core/url-policy.d.ts +2 -5
  333. package/dist/core/url-policy.js +8 -12
  334. package/dist/cursor/caret-memory.d.ts +34 -0
  335. package/dist/cursor/caret-memory.js +82 -0
  336. package/dist/cursor/coordinate-spaces.d.ts +26 -19
  337. package/dist/cursor/coordinate-spaces.js +32 -20
  338. package/dist/cursor/dom-walk.d.ts +7 -13
  339. package/dist/cursor/dom-walk.js +7 -13
  340. package/dist/cursor/edge-affinity.d.ts +7 -35
  341. package/dist/cursor/edge-affinity.js +13 -44
  342. package/dist/cursor/focused-caret.d.ts +6 -8
  343. package/dist/cursor/focused-caret.js +7 -16
  344. package/dist/cursor/height-model.d.ts +3 -3
  345. package/dist/cursor/height-model.js +5 -5
  346. package/dist/cursor/height-oracle.d.ts +10 -7
  347. package/dist/cursor/height-oracle.js +26 -75
  348. package/dist/cursor/observe-resize.d.ts +13 -0
  349. package/dist/cursor/observe-resize.js +43 -0
  350. package/dist/cursor/overlay-rects.d.ts +2 -5
  351. package/dist/cursor/overlay-rects.js +2 -5
  352. package/dist/cursor/overlay-remeasure.d.ts +6 -7
  353. package/dist/cursor/overlay-remeasure.js +10 -14
  354. package/dist/cursor/pending-marks.d.ts +7 -9
  355. package/dist/cursor/pending-marks.js +6 -27
  356. package/dist/cursor/point-offset.d.ts +16 -10
  357. package/dist/cursor/point-offset.js +60 -25
  358. package/dist/cursor/reveal-source.d.ts +7 -11
  359. package/dist/cursor/reveal-source.js +10 -18
  360. package/dist/cursor/scroll-ancestors.d.ts +9 -20
  361. package/dist/cursor/scroll-ancestors.js +14 -26
  362. package/dist/cursor/scroll-owner.d.ts +92 -0
  363. package/dist/cursor/scroll-owner.js +283 -0
  364. package/dist/cursor/scrollport.d.ts +16 -8
  365. package/dist/cursor/scrollport.js +28 -5
  366. package/dist/cursor/sticky-column.d.ts +6 -29
  367. package/dist/cursor/sticky-column.js +6 -49
  368. package/dist/cursor/sticky-measure.d.ts +14 -9
  369. package/dist/cursor/sticky-measure.js +99 -49
  370. package/dist/cursor/surface-backend.d.ts +41 -0
  371. package/dist/cursor/surface-backend.js +78 -0
  372. package/dist/cursor/typography-estimates.d.ts +3 -3
  373. package/dist/cursor/typography-estimates.js +3 -3
  374. package/dist/cursor/visual-lines.d.ts +25 -13
  375. package/dist/cursor/visual-lines.js +72 -28
  376. package/dist/cursor/widget-edge-snap.d.ts +23 -0
  377. package/dist/cursor/widget-edge-snap.js +39 -0
  378. package/dist/cursor/widget-offset.d.ts +111 -102
  379. package/dist/cursor/widget-offset.js +352 -177
  380. package/dist/debug/diagnostics-report.d.ts +6 -6
  381. package/dist/debug/diagnostics-report.js +5 -5
  382. package/dist/debug/dump-tree.js +2 -2
  383. package/dist/debug/editor-diagnostics.d.ts +15 -0
  384. package/dist/debug/editor-diagnostics.js +33 -0
  385. package/dist/debug/inspect.d.ts +2 -2
  386. package/dist/debug/inspect.js +4 -4
  387. package/dist/debug/interaction-trace.d.ts +14 -15
  388. package/dist/debug/interaction-trace.js +19 -20
  389. package/dist/debug/operations-log.d.ts +1 -1
  390. package/dist/debug/operations-log.js +1 -1
  391. package/dist/decorations/buckets.d.ts +6 -12
  392. package/dist/decorations/buckets.js +4 -11
  393. package/dist/decorations/decoration-state.svelte.d.ts +2 -3
  394. package/dist/decorations/decoration-state.svelte.js +24 -26
  395. package/dist/decorations/island-dom.d.ts +10 -18
  396. package/dist/decorations/island-dom.js +25 -50
  397. package/dist/decorations/reserved-attrs.d.ts +6 -8
  398. package/dist/decorations/reserved-attrs.js +31 -17
  399. package/dist/decorations/types.d.ts +6 -7
  400. package/dist/decorations/types.js +2 -1
  401. package/dist/decorations/use-block-decorations.svelte.d.ts +19 -0
  402. package/dist/decorations/use-block-decorations.svelte.js +71 -0
  403. package/dist/decorations/widget-dom.d.ts +3 -3
  404. package/dist/decorations/widget-dom.js +5 -5
  405. package/dist/dev-warn.d.ts +5 -2
  406. package/dist/dev-warn.js +16 -4
  407. package/dist/editor-actions/ancestry-folds.d.ts +9 -14
  408. package/dist/editor-actions/ancestry-folds.js +13 -18
  409. package/dist/editor-actions/block-edit-core.d.ts +49 -22
  410. package/dist/editor-actions/block-edit-core.js +279 -151
  411. package/dist/editor-actions/block-edit-scope.d.ts +63 -50
  412. package/dist/editor-actions/block-edit-scope.js +100 -48
  413. package/dist/editor-actions/block-edit.d.ts +2 -3
  414. package/dist/editor-actions/block-edit.js +14 -90
  415. package/dist/editor-actions/commit/history.d.ts +4 -4
  416. package/dist/editor-actions/commit/history.js +33 -34
  417. package/dist/editor-actions/commit/reading-write-gate.d.ts +18 -0
  418. package/dist/editor-actions/commit/reading-write-gate.js +56 -0
  419. package/dist/editor-actions/commit/text-batch.d.ts +7 -11
  420. package/dist/editor-actions/commit/text-batch.js +6 -7
  421. package/dist/editor-actions/commit/undo-controller.d.ts +6 -4
  422. package/dist/editor-actions/commit/undo-controller.js +346 -216
  423. package/dist/editor-actions/container-block-component.d.ts +32 -51
  424. package/dist/editor-actions/container-block-component.js +66 -92
  425. package/dist/editor-actions/container-edit.d.ts +4 -2
  426. package/dist/editor-actions/container-edit.js +14 -44
  427. package/dist/editor-actions/container-exit-overrides.d.ts +6 -4
  428. package/dist/editor-actions/container-exit-overrides.js +19 -21
  429. package/dist/editor-actions/deps.d.ts +25 -32
  430. package/dist/editor-actions/enter-completion.d.ts +12 -15
  431. package/dist/editor-actions/enter-completion.js +49 -51
  432. package/dist/editor-actions/focus/focus-dispatch.d.ts +24 -25
  433. package/dist/editor-actions/focus/focus-dispatch.js +33 -52
  434. package/dist/editor-actions/focus/focus-landing.d.ts +11 -5
  435. package/dist/editor-actions/focus/focus-landing.js +29 -14
  436. package/dist/editor-actions/focus/focus.d.ts +3 -2
  437. package/dist/editor-actions/focus/focus.js +42 -59
  438. package/dist/editor-actions/index.d.ts +4 -3
  439. package/dist/editor-actions/index.js +5 -4
  440. package/dist/editor-actions/inline-range-commit.d.ts +18 -16
  441. package/dist/editor-actions/inline-range-commit.js +45 -54
  442. package/dist/editor-actions/leaf-write.d.ts +11 -0
  443. package/dist/editor-actions/leaf-write.js +102 -0
  444. package/dist/editor-actions/list-context.d.ts +9 -10
  445. package/dist/editor-actions/list-context.js +115 -110
  446. package/dist/editor-actions/list-overrides.d.ts +13 -5
  447. package/dist/editor-actions/list-overrides.js +36 -12
  448. package/dist/editor-actions/merge-fallback.d.ts +10 -16
  449. package/dist/editor-actions/merge-fallback.js +11 -22
  450. package/dist/editor-actions/nested/container-actions.d.ts +37 -0
  451. package/dist/editor-actions/nested/container-actions.js +42 -0
  452. package/dist/editor-actions/nested/emptied-container.d.ts +5 -0
  453. package/dist/editor-actions/nested/emptied-container.js +5 -0
  454. package/dist/editor-actions/nested/nested-actions.d.ts +22 -25
  455. package/dist/editor-actions/nested/nested-actions.js +17 -15
  456. package/dist/editor-actions/nested/nested-block-edit.d.ts +3 -4
  457. package/dist/editor-actions/nested/nested-block-edit.js +40 -134
  458. package/dist/editor-actions/nested/nested-focus.d.ts +2 -3
  459. package/dist/editor-actions/nested/nested-focus.js +33 -21
  460. package/dist/editor-actions/paste-coordinator.d.ts +3 -2
  461. package/dist/editor-actions/paste-coordinator.js +17 -13
  462. package/dist/editor-actions/plugin/chrome-leaf.d.ts +11 -9
  463. package/dist/editor-actions/plugin/chrome-leaf.js +14 -13
  464. package/dist/editor-actions/plugin/container.d.ts +55 -76
  465. package/dist/editor-actions/plugin/container.js +105 -186
  466. package/dist/editor-actions/plugin/directive-container.d.ts +4 -4
  467. package/dist/editor-actions/plugin/directive-container.js +7 -8
  468. package/dist/editor-actions/reorder-action.d.ts +7 -12
  469. package/dist/editor-actions/reorder-action.js +32 -48
  470. package/dist/editor-actions/reorder-drag.d.ts +12 -8
  471. package/dist/editor-actions/reorder-drag.js +45 -41
  472. package/dist/editor-actions/replacement-focus.d.ts +13 -21
  473. package/dist/editor-actions/replacement-focus.js +32 -33
  474. package/dist/editor-actions/search-replace.js +71 -67
  475. package/dist/editor-actions/stored-caret.d.ts +7 -0
  476. package/dist/editor-actions/stored-caret.js +10 -0
  477. package/dist/editor-actions/table-context.d.ts +9 -11
  478. package/dist/editor-actions/table-context.js +70 -93
  479. package/dist/editor-actions/unwrap-strategies.d.ts +4 -5
  480. package/dist/editor-actions/unwrap-strategies.js +52 -63
  481. package/dist/editor-actions/whole-block-focus-surface.d.ts +19 -28
  482. package/dist/editor-actions/whole-block-focus-surface.js +43 -53
  483. package/dist/editor-events.d.ts +25 -29
  484. package/dist/editor-events.js +17 -28
  485. package/dist/editor-keys.d.ts +96 -104
  486. package/dist/editor-keys.js +11 -24
  487. package/dist/editor-props.d.ts +91 -71
  488. package/dist/editor-rects.d.ts +23 -34
  489. package/dist/editor-rects.js +9 -77
  490. package/dist/env.d.ts +6 -4
  491. package/dist/env.js +8 -4
  492. package/dist/index.d.ts +6 -2
  493. package/dist/index.js +5 -2
  494. package/dist/inline-menu/inline-menu-session.d.ts +37 -0
  495. package/dist/inline-menu/inline-menu-session.js +98 -0
  496. package/dist/inline-menu/inline-menu-state.svelte.d.ts +63 -0
  497. package/dist/inline-menu/inline-menu-state.svelte.js +409 -0
  498. package/dist/inline-menu/types.d.ts +77 -0
  499. package/dist/inline-menu/types.js +7 -0
  500. package/dist/invariants/child-id-parity.d.ts +23 -0
  501. package/dist/invariants/child-id-parity.js +39 -0
  502. package/dist/invariants/commit-paths.d.ts +4 -4
  503. package/dist/invariants/commit-paths.js +4 -4
  504. package/dist/invariants/commit-scope.d.ts +4 -4
  505. package/dist/invariants/commit-scope.js +9 -8
  506. package/dist/invariants/context-keys.d.ts +2 -5
  507. package/dist/invariants/context-keys.js +3 -6
  508. package/dist/invariants/descriptor.d.ts +2 -6
  509. package/dist/invariants/descriptor.js +2 -6
  510. package/dist/invariants/inline-transitions.d.ts +9 -16
  511. package/dist/invariants/inline-transitions.js +10 -18
  512. package/dist/invariants/install.d.ts +18 -27
  513. package/dist/invariants/install.js +29 -30
  514. package/dist/invariants/keeps-a-block.d.ts +7 -0
  515. package/dist/invariants/keeps-a-block.js +14 -0
  516. package/dist/invariants/landable-caret.d.ts +5 -7
  517. package/dist/invariants/landable-caret.js +8 -11
  518. package/dist/invariants/landing-focus-scroll.d.ts +7 -0
  519. package/dist/invariants/landing-focus-scroll.js +13 -0
  520. package/dist/invariants/landing-value.d.ts +13 -0
  521. package/dist/invariants/landing-value.js +27 -0
  522. package/dist/invariants/marker-css-parity.d.ts +5 -6
  523. package/dist/invariants/marker-css-parity.js +11 -12
  524. package/dist/invariants/measures-in-own-list.d.ts +6 -0
  525. package/dist/invariants/measures-in-own-list.js +13 -0
  526. package/dist/invariants/node-shape.d.ts +18 -37
  527. package/dist/invariants/node-shape.js +123 -79
  528. package/dist/invariants/open-tail.d.ts +7 -0
  529. package/dist/invariants/open-tail.js +45 -0
  530. package/dist/invariants/placement-ends-widget.d.ts +8 -0
  531. package/dist/invariants/placement-ends-widget.js +13 -0
  532. package/dist/invariants/registry.d.ts +27 -66
  533. package/dist/invariants/registry.js +61 -137
  534. package/dist/invariants/render-fidelity.d.ts +4 -4
  535. package/dist/invariants/render-fidelity.js +5 -5
  536. package/dist/invariants/selection-endpoints.d.ts +6 -7
  537. package/dist/invariants/selection-endpoints.js +18 -16
  538. package/dist/invariants/single-node-sink.d.ts +4 -5
  539. package/dist/invariants/single-node-sink.js +4 -5
  540. package/dist/invariants/snapshot-integrity.d.ts +5 -6
  541. package/dist/invariants/snapshot-integrity.js +1 -1
  542. package/dist/invariants/structural-descriptor.d.ts +6 -15
  543. package/dist/invariants/structural-descriptor.js +6 -15
  544. package/dist/menu-icons.d.ts +47 -0
  545. package/dist/menu-icons.js +113 -0
  546. package/dist/perf/instruments.d.ts +20 -5
  547. package/dist/perf/instruments.js +35 -15
  548. package/dist/perf/use-mount-gauge.svelte.js +4 -4
  549. package/dist/plugin.d.ts +38 -8
  550. package/dist/plugin.js +102 -74
  551. package/dist/plugins/admonitions/AdmonitionBlock.svelte +14 -11
  552. package/dist/plugins/admonitions/admonition-kind.js +12 -10
  553. package/dist/plugins/admonitions/convert-document.d.ts +5 -5
  554. package/dist/plugins/admonitions/convert-document.js +8 -7
  555. package/dist/plugins/admonitions/gh-alert.d.ts +8 -1
  556. package/dist/plugins/admonitions/gh-alert.js +21 -22
  557. package/dist/plugins/admonitions/github-alert-kind.d.ts +5 -7
  558. package/dist/plugins/admonitions/github-alert-kind.js +28 -37
  559. package/dist/plugins/admonitions/index.js +2 -2
  560. package/dist/plugins/admonitions/kinds.d.ts +1 -1
  561. package/dist/plugins/admonitions/register.js +11 -2
  562. package/dist/plugins/details/DetailsBlock.svelte +20 -20
  563. package/dist/plugins/details/details-disclosure.svelte.d.ts +5 -6
  564. package/dist/plugins/details/details-disclosure.svelte.js +6 -7
  565. package/dist/plugins/details/details-kind.d.ts +6 -7
  566. package/dist/plugins/details/details-kind.js +44 -59
  567. package/dist/plugins/emoji/emoji-recognizer.d.ts +4 -7
  568. package/dist/plugins/emoji/emoji-recognizer.js +7 -14
  569. package/dist/plugins/footnotes/FootnoteDefinition.svelte +33 -16
  570. package/dist/plugins/footnotes/FootnoteReference.svelte +39 -19
  571. package/dist/plugins/footnotes/constants.d.ts +2 -0
  572. package/dist/plugins/footnotes/constants.js +3 -0
  573. package/dist/plugins/footnotes/footnote-definition.d.ts +8 -6
  574. package/dist/plugins/footnotes/footnote-definition.js +69 -45
  575. package/dist/plugins/footnotes/footnote-lookup.d.ts +3 -3
  576. package/dist/plugins/footnotes/footnote-lookup.js +14 -26
  577. package/dist/plugins/footnotes/footnote-numbering.d.ts +11 -11
  578. package/dist/plugins/footnotes/footnote-numbering.js +22 -31
  579. package/dist/plugins/footnotes/footnote-reference.d.ts +4 -4
  580. package/dist/plugins/footnotes/footnote-reference.js +8 -13
  581. package/dist/plugins/footnotes/index.js +2 -3
  582. package/dist/plugins/highlight-occurrences/highlight-occurrences-plugin.d.ts +5 -8
  583. package/dist/plugins/highlight-occurrences/highlight-occurrences-plugin.js +8 -3
  584. package/dist/plugins/highlight-occurrences/occurrence-source.d.ts +10 -12
  585. package/dist/plugins/highlight-occurrences/occurrence-source.js +21 -18
  586. package/dist/plugins/highlight-occurrences/occurrences.d.ts +11 -11
  587. package/dist/plugins/highlight-occurrences/occurrences.js +14 -36
  588. package/dist/plugins/highlight-occurrences/word-char.d.ts +1 -0
  589. package/dist/plugins/highlight-occurrences/word-char.js +4 -0
  590. package/dist/plugins/latex/BlockMath.svelte +58 -75
  591. package/dist/plugins/latex/BlockMath.svelte.d.ts +2 -4
  592. package/dist/plugins/latex/MathInline.svelte +10 -9
  593. package/dist/plugins/latex/flanking.d.ts +1 -0
  594. package/dist/plugins/latex/flanking.js +3 -0
  595. package/dist/plugins/latex/index.d.ts +1 -1
  596. package/dist/plugins/latex/latex-kind.d.ts +4 -4
  597. package/dist/plugins/latex/latex-kind.js +113 -85
  598. package/dist/plugins/latex/math-completion.d.ts +1 -1
  599. package/dist/plugins/latex/math-completion.js +5 -8
  600. package/dist/plugins/latex/math-layout.d.ts +2 -8
  601. package/dist/plugins/latex/math-layout.js +0 -9
  602. package/dist/plugins/latex/math-renderer.d.ts +17 -20
  603. package/dist/plugins/latex/math-renderer.js +21 -38
  604. package/dist/plugins/latex/math-source.d.ts +4 -8
  605. package/dist/plugins/latex/math-source.js +36 -75
  606. package/dist/plugins/latex/register.d.ts +10 -11
  607. package/dist/plugins/latex/register.js +24 -10
  608. package/dist/plugins/latex/renderer.d.ts +9 -10
  609. package/dist/plugins/latex/renderer.js +9 -24
  610. package/dist/plugins/mermaid/MermaidBlock.svelte +63 -47
  611. package/dist/plugins/mermaid/index.js +1 -1
  612. package/dist/plugins/mermaid/mermaid-kind.d.ts +4 -7
  613. package/dist/plugins/mermaid/mermaid-kind.js +30 -47
  614. package/dist/plugins/mermaid/mermaid-renderer.d.ts +9 -16
  615. package/dist/plugins/mermaid/mermaid-renderer.js +12 -31
  616. package/dist/plugins/mermaid/register.d.ts +3 -3
  617. package/dist/plugins/mermaid/register.js +5 -5
  618. package/dist/plugins/mermaid/renderer.d.ts +5 -5
  619. package/dist/plugins/mermaid/renderer.js +8 -11
  620. package/dist/plugins/parrot/ParrotBlock.svelte +18 -7
  621. package/dist/plugins/parrot/ParrotBlock.svelte.d.ts +2 -2
  622. package/dist/plugins/parrot/parrot-plugin.js +3 -3
  623. package/dist/plugins/slash-commands/filter.d.ts +23 -0
  624. package/dist/plugins/slash-commands/filter.js +31 -0
  625. package/dist/plugins/slash-commands/index.d.ts +2 -0
  626. package/dist/plugins/slash-commands/index.js +2 -0
  627. package/dist/plugins/slash-commands/slash-commands-plugin.d.ts +12 -0
  628. package/dist/plugins/slash-commands/slash-commands-plugin.js +40 -0
  629. package/dist/plugins/slash-commands/slash-source.d.ts +36 -0
  630. package/dist/plugins/slash-commands/slash-source.js +108 -0
  631. package/dist/plugins/toc/TocBlock.svelte +23 -22
  632. package/dist/plugins/toc/TocBlock.svelte.d.ts +2 -3
  633. package/dist/plugins/toc/heading-outline.d.ts +7 -12
  634. package/dist/plugins/toc/heading-outline.js +22 -36
  635. package/dist/plugins/toc/navigation-queue.d.ts +2 -4
  636. package/dist/plugins/toc/toc-plugin.d.ts +5 -5
  637. package/dist/plugins/toc/toc-plugin.js +20 -13
  638. package/dist/presentation-mode.d.ts +15 -23
  639. package/dist/presentation-mode.js +19 -25
  640. package/dist/reactivity/block-list-state.svelte.d.ts +9 -11
  641. package/dist/reactivity/block-list-state.svelte.js +8 -9
  642. package/dist/reactivity/block-window.svelte.d.ts +12 -6
  643. package/dist/reactivity/block-window.svelte.js +44 -17
  644. package/dist/reactivity/child-list.d.ts +34 -0
  645. package/dist/reactivity/child-list.js +48 -0
  646. package/dist/reactivity/content-version.svelte.d.ts +4 -7
  647. package/dist/reactivity/content-version.svelte.js +3 -5
  648. package/dist/reactivity/hold-across.d.ts +39 -0
  649. package/dist/reactivity/hold-across.js +57 -0
  650. package/dist/reactivity/layout-state.svelte.d.ts +27 -0
  651. package/dist/reactivity/layout-state.svelte.js +51 -0
  652. package/dist/reactivity/list-tree.d.ts +39 -0
  653. package/dist/reactivity/list-tree.js +132 -0
  654. package/dist/reactivity/list-windowing.svelte.d.ts +50 -71
  655. package/dist/reactivity/list-windowing.svelte.js +143 -292
  656. package/dist/reactivity/measure-batch.d.ts +6 -8
  657. package/dist/reactivity/measure-batch.js +5 -6
  658. package/dist/reactivity/publish-ref.svelte.d.ts +16 -41
  659. package/dist/reactivity/publish-ref.svelte.js +21 -85
  660. package/dist/reactivity/scope-geometry.d.ts +6 -13
  661. package/dist/reactivity/scope-geometry.js +7 -14
  662. package/dist/reactivity/state-registry.d.ts +5 -5
  663. package/dist/reactivity/state-registry.js +11 -15
  664. package/dist/reactivity/use-container-windowing.svelte.d.ts +13 -26
  665. package/dist/reactivity/use-container-windowing.svelte.js +64 -74
  666. package/dist/reactivity/use-measured-child.svelte.d.ts +10 -0
  667. package/dist/reactivity/use-measured-child.svelte.js +41 -0
  668. package/dist/reactivity/use-window-floor.svelte.d.ts +2 -0
  669. package/dist/reactivity/use-window-floor.svelte.js +27 -0
  670. package/dist/reactivity/window-slice.d.ts +4 -4
  671. package/dist/reactivity/window-slice.js +0 -2
  672. package/dist/renderer-slot.d.ts +48 -0
  673. package/dist/renderer-slot.js +85 -0
  674. package/dist/scan-index.d.ts +4 -4
  675. package/dist/scan-index.js +4 -4
  676. package/dist/schema/block-commands.d.ts +69 -54
  677. package/dist/schema/block-commands.js +91 -104
  678. package/dist/schema/block-completions.d.ts +16 -19
  679. package/dist/schema/block-completions.js +25 -32
  680. package/dist/schema/block-component-registry.d.ts +13 -14
  681. package/dist/schema/block-component-registry.js +19 -17
  682. package/dist/schema/block-kind-descriptor.d.ts +234 -168
  683. package/dist/schema/block-kind-descriptor.js +151 -66
  684. package/dist/schema/block-openers.d.ts +48 -39
  685. package/dist/schema/block-openers.js +73 -83
  686. package/dist/schema/built-in-descriptors.d.ts +3 -5
  687. package/dist/schema/built-in-descriptors.js +96 -80
  688. package/dist/schema/child-spans.d.ts +12 -10
  689. package/dist/schema/child-spans.js +68 -34
  690. package/dist/schema/closure.d.ts +18 -16
  691. package/dist/schema/closure.js +24 -14
  692. package/dist/schema/command-id.d.ts +6 -8
  693. package/dist/schema/command-id.js +20 -25
  694. package/dist/schema/commands.d.ts +79 -81
  695. package/dist/schema/commands.js +156 -116
  696. package/dist/schema/container-raw.d.ts +51 -11
  697. package/dist/schema/container-raw.js +143 -14
  698. package/dist/schema/container-rebuilders.d.ts +17 -15
  699. package/dist/schema/container-rebuilders.js +30 -22
  700. package/dist/schema/context-actions.d.ts +25 -13
  701. package/dist/schema/context-actions.js +32 -17
  702. package/dist/schema/define-plugin-block.d.ts +8 -6
  703. package/dist/schema/define-plugin-block.js +6 -4
  704. package/dist/schema/fenced-code-raw.d.ts +30 -17
  705. package/dist/schema/fenced-code-raw.js +155 -107
  706. package/dist/schema/global-commands.d.ts +6 -6
  707. package/dist/schema/global-commands.js +14 -22
  708. package/dist/schema/height-estimates.d.ts +31 -0
  709. package/dist/schema/height-estimates.js +64 -0
  710. package/dist/schema/inline-construct-policy.d.ts +42 -55
  711. package/dist/schema/inline-construct-policy.js +36 -35
  712. package/dist/schema/insert-catalogue.d.ts +30 -0
  713. package/dist/schema/insert-catalogue.js +95 -0
  714. package/dist/schema/keybinding-overrides.d.ts +9 -11
  715. package/dist/schema/keybinding-overrides.js +1 -1
  716. package/dist/schema/keybindings.d.ts +15 -7
  717. package/dist/schema/keybindings.js +21 -9
  718. package/dist/schema/merge-rules.d.ts +5 -7
  719. package/dist/schema/merge-rules.js +7 -9
  720. package/dist/schema/opener-priorities.d.ts +4 -4
  721. package/dist/schema/opener-priorities.js +4 -4
  722. package/dist/schema/operations.d.ts +9 -11
  723. package/dist/schema/operations.js +3 -3
  724. package/dist/schema/page-role.d.ts +14 -0
  725. package/dist/schema/page-role.js +19 -0
  726. package/dist/schema/plugin-activation.d.ts +4 -6
  727. package/dist/schema/plugin-activation.js +12 -10
  728. package/dist/schema/plugin-editor-context.d.ts +25 -10
  729. package/dist/schema/plugin-editor-context.js +40 -9
  730. package/dist/schema/plugin-install.d.ts +49 -17
  731. package/dist/schema/plugin-install.js +51 -25
  732. package/dist/schema/plugin-kind.d.ts +12 -8
  733. package/dist/schema/plugin-kind.js +35 -42
  734. package/dist/schema/plugin-name.js +3 -3
  735. package/dist/schema/plugin-registry.d.ts +54 -0
  736. package/dist/schema/plugin-registry.js +70 -0
  737. package/dist/schema/reading.d.ts +23 -0
  738. package/dist/schema/reading.js +7 -0
  739. package/dist/schema/register-once.d.ts +3 -5
  740. package/dist/schema/register-once.js +7 -16
  741. package/dist/schema/registration-checks.d.ts +12 -16
  742. package/dist/schema/registration-checks.js +35 -51
  743. package/dist/schema/registration-pairs.d.ts +54 -0
  744. package/dist/schema/registration-pairs.js +48 -0
  745. package/dist/schema/registration-pending.d.ts +8 -12
  746. package/dist/schema/registration-pending.js +9 -9
  747. package/dist/schema/registry-reset.d.ts +8 -4
  748. package/dist/schema/registry-reset.js +13 -26
  749. package/dist/schema/registry-view.d.ts +25 -13
  750. package/dist/schema/registry-view.js +26 -20
  751. package/dist/schema/reserved-chords.d.ts +9 -10
  752. package/dist/schema/reserved-chords.js +73 -78
  753. package/dist/schema/reserved-chrome.d.ts +12 -11
  754. package/dist/schema/reserved-chrome.js +15 -11
  755. package/dist/schema/setext-raw.d.ts +13 -0
  756. package/dist/schema/setext-raw.js +33 -0
  757. package/dist/schema/stored-as.d.ts +20 -0
  758. package/dist/schema/stored-as.js +6 -0
  759. package/dist/schema/table-cell-raw.d.ts +18 -7
  760. package/dist/schema/table-cell-raw.js +28 -7
  761. package/dist/schema/whole-block-unit.d.ts +5 -4
  762. package/dist/schema/whole-block-unit.js +5 -4
  763. package/dist/search/document-scan.d.ts +3 -3
  764. package/dist/search/document-scan.js +2 -2
  765. package/dist/search/matcher.d.ts +1 -1
  766. package/dist/search/regex-executor.d.ts +5 -6
  767. package/dist/search/regex-executor.js +6 -8
  768. package/dist/search/replace.d.ts +2 -5
  769. package/dist/search/replace.js +2 -5
  770. package/dist/search/search-state.svelte.d.ts +5 -5
  771. package/dist/search/search-state.svelte.js +12 -16
  772. package/dist/selection/autoscroll.d.ts +6 -9
  773. package/dist/selection/block-hit-test.d.ts +16 -24
  774. package/dist/selection/block-hit-test.js +29 -22
  775. package/dist/selection/caret-doors.d.ts +15 -14
  776. package/dist/selection/caret-doors.js +37 -26
  777. package/dist/selection/caret-landing.d.ts +62 -0
  778. package/dist/selection/caret-landing.js +157 -0
  779. package/dist/selection/caret-restore.d.ts +17 -10
  780. package/dist/selection/caret-restore.js +10 -22
  781. package/dist/selection/caret-target.d.ts +30 -0
  782. package/dist/selection/caret-target.js +84 -0
  783. package/dist/selection/char-endpoint-snap.d.ts +6 -10
  784. package/dist/selection/char-endpoint-snap.js +8 -14
  785. package/dist/selection/clipboard-text.d.ts +5 -12
  786. package/dist/selection/clipboard-text.js +69 -172
  787. package/dist/selection/covered-block.d.ts +6 -8
  788. package/dist/selection/covered-block.js +8 -19
  789. package/dist/selection/cross-block/clipboard.d.ts +3 -2
  790. package/dist/selection/cross-block/clipboard.js +13 -4
  791. package/dist/selection/cross-block/dispatch.d.ts +47 -43
  792. package/dist/selection/cross-block/dispatch.js +12 -23
  793. package/dist/selection/cross-block/format-range.d.ts +18 -21
  794. package/dist/selection/cross-block/format-range.js +104 -103
  795. package/dist/selection/cross-block/format-toggle.d.ts +10 -15
  796. package/dist/selection/cross-block/format-toggle.js +28 -33
  797. package/dist/selection/cross-block/keydown.d.ts +4 -4
  798. package/dist/selection/cross-block/keydown.js +93 -152
  799. package/dist/selection/cross-block/ops.d.ts +19 -34
  800. package/dist/selection/cross-block/ops.js +110 -95
  801. package/dist/selection/cross-block/paste.d.ts +2 -3
  802. package/dist/selection/cross-block/paste.js +61 -104
  803. package/dist/selection/cross-block/pointer.d.ts +17 -15
  804. package/dist/selection/cross-block/pointer.js +74 -25
  805. package/dist/selection/cross-block/type-replace.d.ts +4 -6
  806. package/dist/selection/cross-block/type-replace.js +53 -146
  807. package/dist/selection/dead-space-caret.d.ts +20 -28
  808. package/dist/selection/dead-space-caret.js +79 -87
  809. package/dist/selection/drag-pointer.d.ts +22 -5
  810. package/dist/selection/drag-pointer.js +63 -31
  811. package/dist/selection/gap-caret.d.ts +17 -28
  812. package/dist/selection/gap-caret.js +14 -26
  813. package/dist/selection/grid-selection.d.ts +12 -0
  814. package/dist/selection/grid-selection.js +22 -0
  815. package/dist/selection/keyboard-extend.d.ts +27 -39
  816. package/dist/selection/keyboard-extend.js +94 -116
  817. package/dist/selection/multi-click.d.ts +37 -0
  818. package/dist/selection/multi-click.js +197 -0
  819. package/dist/selection/native-bridge.d.ts +30 -37
  820. package/dist/selection/native-bridge.js +80 -100
  821. package/dist/selection/nearest-block.d.ts +17 -12
  822. package/dist/selection/nearest-block.js +37 -18
  823. package/dist/selection/path-lookup.d.ts +31 -14
  824. package/dist/selection/path-lookup.js +110 -20
  825. package/dist/selection/path-math.d.ts +9 -11
  826. package/dist/selection/path-math.js +5 -7
  827. package/dist/selection/pointer-gesture.d.ts +9 -0
  828. package/dist/selection/pointer-gesture.js +11 -0
  829. package/dist/selection/pointer-session.d.ts +10 -16
  830. package/dist/selection/pointer-session.js +6 -7
  831. package/dist/selection/primitives.d.ts +64 -33
  832. package/dist/selection/primitives.js +61 -53
  833. package/dist/selection/range-coverage.d.ts +94 -0
  834. package/dist/selection/range-coverage.js +365 -0
  835. package/dist/selection/range-delete-ceremony.d.ts +28 -74
  836. package/dist/selection/range-delete-ceremony.js +100 -141
  837. package/dist/selection/range-delete-chrome.d.ts +20 -33
  838. package/dist/selection/range-delete-chrome.js +53 -78
  839. package/dist/selection/range-delete-table-coverage.d.ts +11 -25
  840. package/dist/selection/range-delete-table-coverage.js +42 -112
  841. package/dist/selection/range-delete-table.d.ts +14 -12
  842. package/dist/selection/range-delete-table.js +106 -310
  843. package/dist/selection/range-delete.d.ts +18 -19
  844. package/dist/selection/range-delete.js +83 -123
  845. package/dist/selection/round-trip-restore.d.ts +18 -0
  846. package/dist/selection/round-trip-restore.js +19 -0
  847. package/dist/selection/selection-announcer.d.ts +17 -0
  848. package/dist/selection/selection-announcer.js +25 -0
  849. package/dist/selection/selection-description.d.ts +4 -3
  850. package/dist/selection/selection-description.js +5 -4
  851. package/dist/selection/selection-drop.d.ts +52 -0
  852. package/dist/selection/selection-drop.js +317 -0
  853. package/dist/selection/selection-restore.d.ts +20 -33
  854. package/dist/selection/selection-restore.js +21 -44
  855. package/dist/selection/selection-state.svelte.d.ts +50 -42
  856. package/dist/selection/selection-state.svelte.js +144 -98
  857. package/dist/selection/shared-keydown.d.ts +22 -27
  858. package/dist/selection/shared-keydown.js +25 -45
  859. package/dist/selection/table-endpoint-snap.d.ts +17 -41
  860. package/dist/selection/table-endpoint-snap.js +54 -80
  861. package/dist/selection/table-rect-extend.d.ts +3 -6
  862. package/dist/selection/table-rect-extend.js +19 -14
  863. package/dist/styles/editor-theme.css +75 -53
  864. package/dist/styles/editor.css +248 -139
  865. package/dist/testing/conformance-core.d.ts +50 -18
  866. package/dist/testing/conformance-core.js +88 -50
  867. package/dist/testing/container-conformance.d.ts +48 -84
  868. package/dist/testing/container-conformance.js +159 -285
  869. package/dist/testing/headless-actions.d.ts +34 -19
  870. package/dist/testing/headless-actions.js +116 -65
  871. package/dist/testing/headless-block-list.svelte.d.ts +16 -0
  872. package/dist/testing/headless-block-list.svelte.js +22 -0
  873. package/dist/testing/inline-conformance.d.ts +15 -22
  874. package/dist/testing/inline-conformance.js +131 -148
  875. package/dist/testing/kind-conformance.d.ts +19 -24
  876. package/dist/testing/kind-conformance.js +204 -117
  877. package/dist/testing/kit-reading.d.ts +7 -0
  878. package/dist/testing/kit-reading.js +16 -0
  879. package/dist/testing/mount-dom-stubs.d.ts +4 -5
  880. package/dist/testing/mount-dom-stubs.js +8 -5
  881. package/dist/testing/parse-convergence.d.ts +10 -10
  882. package/dist/testing/parse-convergence.js +14 -49
  883. package/dist/testing.d.ts +13 -9
  884. package/dist/testing.js +28 -38
  885. package/dist/tree-operations/blockquote.d.ts +8 -14
  886. package/dist/tree-operations/blockquote.js +25 -45
  887. package/dist/tree-operations/chain-rebuild.d.ts +34 -25
  888. package/dist/tree-operations/chain-rebuild.js +115 -52
  889. package/dist/tree-operations/children.d.ts +5 -9
  890. package/dist/tree-operations/children.js +7 -11
  891. package/dist/tree-operations/cleanup.d.ts +6 -7
  892. package/dist/tree-operations/cleanup.js +14 -11
  893. package/dist/tree-operations/clone.js +5 -4
  894. package/dist/tree-operations/container-lift.d.ts +10 -5
  895. package/dist/tree-operations/container-lift.js +20 -14
  896. package/dist/tree-operations/container-offsets.d.ts +22 -0
  897. package/dist/tree-operations/container-offsets.js +89 -0
  898. package/dist/tree-operations/content-write.d.ts +52 -29
  899. package/dist/tree-operations/content-write.js +155 -110
  900. package/dist/tree-operations/index.d.ts +4 -4
  901. package/dist/tree-operations/index.js +4 -4
  902. package/dist/tree-operations/keep-one-block.d.ts +10 -0
  903. package/dist/tree-operations/keep-one-block.js +19 -0
  904. package/dist/tree-operations/leaf-range.d.ts +33 -0
  905. package/dist/tree-operations/leaf-range.js +67 -0
  906. package/dist/tree-operations/list/empty-check.d.ts +2 -3
  907. package/dist/tree-operations/list/empty-check.js +4 -4
  908. package/dist/tree-operations/list/exit-replacement.d.ts +4 -6
  909. package/dist/tree-operations/list/exit-replacement.js +4 -9
  910. package/dist/tree-operations/list/item-partition.d.ts +2 -2
  911. package/dist/tree-operations/list/item-partition.js +2 -2
  912. package/dist/tree-operations/list/list-builders.d.ts +18 -16
  913. package/dist/tree-operations/list/list-builders.js +59 -30
  914. package/dist/tree-operations/list/ordered-markers.d.ts +7 -16
  915. package/dist/tree-operations/list/ordered-markers.js +7 -16
  916. package/dist/tree-operations/list/reconcile-task.d.ts +16 -7
  917. package/dist/tree-operations/list/reconcile-task.js +80 -23
  918. package/dist/tree-operations/list/sublist-separator.d.ts +7 -7
  919. package/dist/tree-operations/list/sublist-separator.js +20 -27
  920. package/dist/tree-operations/list/task-paragraph.d.ts +25 -0
  921. package/dist/tree-operations/list/task-paragraph.js +54 -0
  922. package/dist/tree-operations/list/unwrap-merge.d.ts +8 -16
  923. package/dist/tree-operations/list/unwrap-merge.js +44 -79
  924. package/dist/tree-operations/node-ops.d.ts +30 -52
  925. package/dist/tree-operations/node-ops.js +152 -218
  926. package/dist/tree-operations/node-primitives.d.ts +44 -31
  927. package/dist/tree-operations/node-primitives.js +84 -60
  928. package/dist/tree-operations/open-tail.d.ts +25 -0
  929. package/dist/tree-operations/open-tail.js +100 -0
  930. package/dist/tree-operations/parse-block.d.ts +15 -2
  931. package/dist/tree-operations/parse-block.js +19 -4
  932. package/dist/tree-operations/paste/apply.d.ts +7 -8
  933. package/dist/tree-operations/paste/apply.js +33 -63
  934. package/dist/tree-operations/paste/body-write.d.ts +8 -6
  935. package/dist/tree-operations/paste/body-write.js +13 -14
  936. package/dist/tree-operations/paste/container-match.d.ts +7 -10
  937. package/dist/tree-operations/paste/container-match.js +76 -58
  938. package/dist/tree-operations/paste/container-paste.d.ts +3 -3
  939. package/dist/tree-operations/paste/container-paste.js +3 -3
  940. package/dist/tree-operations/paste/dispatch.d.ts +26 -29
  941. package/dist/tree-operations/paste/dispatch.js +68 -53
  942. package/dist/tree-operations/paste/focus-target.d.ts +11 -14
  943. package/dist/tree-operations/paste/focus-target.js +13 -18
  944. package/dist/tree-operations/paste/hooks.d.ts +7 -12
  945. package/dist/tree-operations/paste/hooks.js +49 -46
  946. package/dist/tree-operations/paste/line-ending.d.ts +11 -0
  947. package/dist/tree-operations/paste/line-ending.js +32 -0
  948. package/dist/tree-operations/paste/list-absorb.d.ts +8 -11
  949. package/dist/tree-operations/paste/list-absorb.js +17 -19
  950. package/dist/tree-operations/paste/list-break-out.d.ts +12 -11
  951. package/dist/tree-operations/paste/list-break-out.js +24 -32
  952. package/dist/tree-operations/paste/parent-scope.d.ts +8 -12
  953. package/dist/tree-operations/paste/parent-scope.js +9 -16
  954. package/dist/tree-operations/paste/paste-deps.d.ts +14 -9
  955. package/dist/tree-operations/paste/paste-replacement.d.ts +20 -3
  956. package/dist/tree-operations/paste/paste-replacement.js +73 -42
  957. package/dist/tree-operations/paste/paste-transforms.d.ts +5 -7
  958. package/dist/tree-operations/paste/paste-transforms.js +18 -27
  959. package/dist/tree-operations/paste/replacement-parse.d.ts +19 -0
  960. package/dist/tree-operations/paste/replacement-parse.js +24 -0
  961. package/dist/tree-operations/paste/strategy.d.ts +1 -1
  962. package/dist/tree-operations/paste/strategy.js +1 -1
  963. package/dist/tree-operations/paste/table-slice.js +15 -10
  964. package/dist/tree-operations/paste-surfaces.d.ts +18 -29
  965. package/dist/tree-operations/paste-surfaces.js +14 -10
  966. package/dist/tree-operations/path-mutate.d.ts +7 -8
  967. package/dist/tree-operations/path-mutate.js +4 -4
  968. package/dist/tree-operations/reorder-unit.d.ts +4 -5
  969. package/dist/tree-operations/reorder-unit.js +5 -6
  970. package/dist/tree-operations/reorder.d.ts +7 -9
  971. package/dist/tree-operations/reorder.js +39 -40
  972. package/dist/tree-operations/settle.d.ts +42 -53
  973. package/dist/tree-operations/settle.js +241 -162
  974. package/dist/tree-operations/sharing.d.ts +5 -5
  975. package/dist/tree-operations/splice-many.d.ts +5 -5
  976. package/dist/tree-operations/splice-many.js +5 -5
  977. package/dist/tree-operations/stored-as.d.ts +13 -0
  978. package/dist/tree-operations/stored-as.js +48 -0
  979. package/dist/tree-operations/structural-change.d.ts +11 -15
  980. package/dist/tree-operations/structural-change.js +10 -14
  981. package/dist/tree-operations/structural-suffix.d.ts +22 -0
  982. package/dist/tree-operations/structural-suffix.js +61 -0
  983. package/dist/tree-operations/sub-table-copy.d.ts +7 -0
  984. package/dist/tree-operations/sub-table-copy.js +40 -36
  985. package/dist/tree-operations/table-grid-clipboard.d.ts +2 -7
  986. package/dist/tree-operations/table-grid-clipboard.js +11 -36
  987. package/dist/tree-operations/table-mutations.d.ts +7 -3
  988. package/dist/tree-operations/table-mutations.js +45 -9
  989. package/dist/tree-operations/unshare.d.ts +11 -15
  990. package/dist/tree-operations/unshare.js +15 -17
  991. package/dist/undo/manager.js +1 -1
  992. package/dist/undo/types.d.ts +2 -2
  993. package/docs/guide/consumer-guide.md +329 -205
  994. package/docs/guide/directives.md +7 -7
  995. package/docs/guide/plugin-api.md +267 -183
  996. package/docs/guide/plugin-guide.md +341 -235
  997. package/docs/guide/plugin-testing.md +96 -82
  998. package/package.json +17 -21
  999. package/dist/ambient/ambient-cursor.d.ts +0 -41
  1000. package/dist/ambient/ambient-cursor.js +0 -120
  1001. package/dist/components/blocks/code/code-paste.d.ts +0 -24
  1002. package/dist/components/blocks/code/code-paste.js +0 -21
  1003. package/dist/components/blocks/table/cell-clipboard.d.ts +0 -33
  1004. package/dist/components/blocks/table/cell-clipboard.js +0 -67
  1005. package/dist/components/blocks/text/hidden-suffix.d.ts +0 -10
  1006. package/dist/components/blocks/text/hidden-suffix.js +0 -15
  1007. package/dist/components/blocks/text/link-source-bytes.d.ts +0 -37
  1008. package/dist/components/image/image-source-bytes.d.ts +0 -15
  1009. package/dist/components/image/image-source-bytes.js +0 -80
  1010. package/dist/cursor/content-offsets.d.ts +0 -29
  1011. package/dist/cursor/content-offsets.js +0 -151
  1012. package/dist/cursor/reveal-anchor.d.ts +0 -30
  1013. package/dist/cursor/reveal-anchor.js +0 -31
  1014. package/dist/invariants/split-landing.d.ts +0 -8
  1015. package/dist/invariants/split-landing.js +0 -15
  1016. package/dist/selection/double-click-trim.d.ts +0 -17
  1017. package/dist/selection/double-click-trim.js +0 -57
  1018. package/dist/tree-operations/list/terminator.d.ts +0 -17
  1019. package/dist/tree-operations/list/terminator.js +0 -60
  1020. package/dist/tree-operations/paste/replace-block-at-parent.d.ts +0 -29
  1021. package/dist/tree-operations/paste/replace-block-at-parent.js +0 -75
@@ -1,30 +1,36 @@
1
1
  /**
2
- * The commit ceremony: snapshot capture, copy-path-on-write unshare, rollback.
3
- * Owns G1.9 — snapshot-shared nodes stay byte-readonly until this seam unshares
4
- * them. Keystroke batching is delegated to text-batch.ts.
2
+ * The commit sequence (`runCommitCeremony`): undo snapshot, copy before write, mutate,
3
+ * rollback on failure. A node shared with an undo snapshot stays read-only until the commit
4
+ * copies it (G1.9). Keystroke batching is in text-batch.ts.
5
5
  */
6
- import { DEV } from 'esm-env';
6
+ import { isDevChecks } from '../../env';
7
7
  import { tick } from 'svelte';
8
+ import { documentLineEnding } from '../../core/lines';
8
9
  import { digestDoc } from '../../invariants/snapshot-integrity';
9
10
  import { readCurrentSelection } from '../../selection/native-bridge';
10
11
  import { asDocPath, pathsEqual } from '../../selection/path-math';
11
12
  import { assertInvariant } from '../../assert';
13
+ import { checkLandingIsAValue, readCaretWhereabouts } from '../../invariants/landing-value';
14
+ import { docPathFrom } from '../../cursor/coordinate-spaces';
12
15
  import { beginCommit, endCommit } from '../../invariants/commit-scope';
13
16
  import { assignIds } from '../../block-id';
14
17
  import { replaceRefs } from '../../reactivity/publish-ref.svelte';
15
- import { nodeAt } from '../../tree-operations/node-primitives';
18
+ import { blockNodeAt, documentBody, nodeAt } from '../../tree-operations/node-primitives';
16
19
  import { settleSeparator } from '../../tree-operations/settle';
17
- import { ensureUnsharedPath } from '../../tree-operations/unshare';
18
- import { attachedChainPrefix, rebuildUnsharedChain } from '../../tree-operations/chain-rebuild';
20
+ import { endsOpen, endWindowLines, keepOpenTail } from '../../tree-operations/open-tail';
21
+ import { keepOneBlock } from '../../tree-operations/keep-one-block';
22
+ import { ensureUnsharedPath, rebuildOwnedContainer } from '../../tree-operations/unshare';
23
+ import { attachedChainPrefix, rebuildUnsharedChain, sharedChainLevels } from '../../tree-operations/chain-rebuild';
19
24
  import { foldLandingFor, publishAncestryFolds } from '../ancestry-folds';
20
25
  import { createTextBatch } from './text-batch';
26
+ import { admitsSnapshot, admitsWrite } from './reading-write-gate';
21
27
  import { toEditEvent } from '../../editor-events';
22
28
  import { applyStructuralChangeToIdsRefs } from '../../tree-operations/structural-change';
23
- import { assertCommitPaths, assertCommittedNodes, assertIdsInLockstep, assertUndoTopIntegrity } from '../../invariants/install';
29
+ import { assertCommitPaths, assertCommittedNodes, assertIdsInLockstep, assertKeepsABlock, assertLastLineKept, assertUndoTopIntegrity } from '../../invariants/install';
24
30
  import { tryGetBlockKindDescriptor } from '../../schema/block-kind-descriptor';
25
31
  import { dropChildSpans } from '../../schema/child-spans';
26
32
  import { docByteLength, perfEnabled, recordSnapshotClone, setUndoGauge } from '../../perf/instruments';
27
- // ── Dev invariant scoping (DEV-only paths) ────────────────────────────────────
33
+ // ── Dev invariant scoping (dev-only paths) ────────────────────────────────────
28
34
  /** A `noop` change names no new positions, so the caller passes its leaf via `explicit`. */
29
35
  function touchedFromChange(change, children, explicit) {
30
36
  if (change.op === 'insert')
@@ -33,7 +39,7 @@ function touchedFromChange(change, children, explicit) {
33
39
  return children.slice(change.at, change.at + change.newCount);
34
40
  return explicit ?? [];
35
41
  }
36
- /** Direct children ride along: a strip rebuild concatenates them into the container. */
42
+ /** Direct children go along: a container's rebuild concatenates them into its raw. */
37
43
  function touchedContainersWithChildren(containers) {
38
44
  if (!containers)
39
45
  return [];
@@ -46,25 +52,10 @@ function touchedContainersWithChildren(containers) {
46
52
  }
47
53
  return out;
48
54
  }
49
- export function createUndoController(deps) {
55
+ /** `announceEdit` speaks a commit's announcement in the editor's edit live region; only the
56
+ * controller holds it, so nothing but a commit that wrote can speak there. Silent by default. */
57
+ export function createUndoController(deps, announceEdit = () => { }) {
50
58
  // ── Selection helpers ─────────────────────────────────────────────────────
51
- /**
52
- * The document as the settle's parent, over the mutate's working array. The suffix rides as
53
- * accessors: a tail settle spends the live document's folded line, and the rollback frame
54
- * restores it.
55
- */
56
- function docSettleParent(children) {
57
- return {
58
- kind: 'document',
59
- children,
60
- get suffix() {
61
- return deps.doc.suffix;
62
- },
63
- set suffix(value) {
64
- deps.doc.suffix = value;
65
- }
66
- };
67
- }
68
59
  function collapsedSelectionAt(blockIndex, offset) {
69
60
  const point = { path: [blockIndex], offset };
70
61
  return { anchor: point, focus: point };
@@ -74,10 +65,8 @@ export function createUndoController(deps) {
74
65
  return { anchor: point, focus: point };
75
66
  }
76
67
  // ── Snapshot pushers ─────────────────────────────────────────────────────
77
- /**
78
- * Snapshots share the live tree's nodes; only the top-level children array is
79
- * copied. G1.9: mutations copy-path-on-write first (`tree-operations/unshare.ts`).
80
- */
68
+ /** Snapshots share the live tree's nodes and copy only the top-level children array, so an
69
+ * edit copies the path it writes first (G1.9, `tree-operations/unshare.ts`). */
81
70
  function shareSnapshot() {
82
71
  deps.sharing.markSnapshotTaken();
83
72
  const snapshot = {
@@ -86,7 +75,7 @@ export function createUndoController(deps) {
86
75
  children: [...deps.doc.children],
87
76
  suffix: deps.doc.suffix
88
77
  };
89
- return { snapshot, integrity: DEV ? digestDoc(snapshot) : undefined };
78
+ return { snapshot, integrity: isDevChecks() ? digestDoc(snapshot) : undefined };
90
79
  }
91
80
  function recordSnapshotPerf() {
92
81
  if (!perfEnabled())
@@ -98,47 +87,121 @@ export function createUndoController(deps) {
98
87
  liveBytes += docByteLength(entry.snapshot);
99
88
  setUndoGauge(liveBytes, undo.length);
100
89
  }
90
+ const readLive = () => readCurrentSelection(deps.selectionState, deps.blockRefs);
101
91
  /**
102
- * What an entry records as "where the caret was". The gap outranks the caller's declared
103
- * coordinate and not the live caret: it IS a live caret, but no block ref can report it,
104
- * so it would otherwise fall through to a fallback naming a block it isn't in.
92
+ * What an entry records as "where the caret was". The gap caret outranks only the caller's
93
+ * fallback, since no block ref reports it.
105
94
  */
106
95
  function entrySelection(fallback) {
107
- const live = readCurrentSelection(deps.selectionState, deps.blockRefs);
96
+ const live = readLive();
108
97
  if (live)
109
98
  return live;
110
99
  const gap = deps.selectionState.gapCaret;
111
100
  return gap ? { gapCaret: gap } : fallback();
112
101
  }
113
- function pushUndoSnapshotPath(fallbackPath, offset) {
114
- deps.undoManager.push({
115
- ...shareSnapshot(),
116
- blockIds: [...deps.blockIds],
117
- selection: entrySelection(() => collapsedSelectionAtPath(fallbackPath, offset))
118
- });
102
+ // ── Undo steps ───────────────────────────────────────────────────────────
103
+ // The outermost open step owns these; a step inside a step adds only depth. The entry is held
104
+ // by identity: a first write that rolls back removes it, and the next write opens it again.
105
+ let stepDepth = 0;
106
+ let stepEntry = null;
107
+ // Read when the step opens, since a gesture may collapse its range before its first write.
108
+ let stepSelection = null;
109
+ let stepPushed = false;
110
+ // Set by the author's input while a step is open; until it closes, writes push alone.
111
+ let stepEnded = false;
112
+ // The entry the typing batch's first keystroke went into, and whether a keystroke's own
113
+ // commit is being called, which joins it.
114
+ let typingEntry = null;
115
+ let joiningTyping = false;
116
+ const inOpenStep = () => stepDepth > 0 && !stepEnded;
117
+ const isTop = (entry) => entry !== null && deps.undoManager.peekUndo() === entry;
118
+ const joinsStep = () => inOpenStep() && isTop(stepEntry);
119
+ const isJoinedPush = () => (joiningTyping && isTop(typingEntry)) || joinsStep();
120
+ function pushEntry(entry) {
121
+ deps.undoManager.push(entry);
122
+ if (inOpenStep()) {
123
+ stepEntry = entry;
124
+ stepPushed = true;
125
+ }
119
126
  recordSnapshotPerf();
120
127
  }
121
- // Top-level only: a deep-path caller must route through pushUndoSnapshotPath, or its
122
- // no-caret fallback restores to the top-level block instead of the edited leaf.
123
- function pushUndoSnapshot(blockIndex, offset) {
124
- pushUndoSnapshotPath([blockIndex], offset);
128
+ /** The selection a push records: the open step's, else the push's own. */
129
+ function selectionFor(own) {
130
+ return inOpenStep() && stepSelection ? stepSelection : own();
125
131
  }
126
- // Path from the live focused leaf, offset from the caller: the live cursor is
127
- // post-edit, but its path still points at the same leaf.
128
- function pushTypingSnapshot(leafPath, offset) {
129
- const live = readCurrentSelection(deps.selectionState, deps.blockRefs);
130
- const liveIsCollapsed = !!live &&
131
- pathsEqual(live.anchor.path, live.focus.path) &&
132
- live.anchor.offset === live.focus.offset;
133
- const selection = liveIsCollapsed
134
- ? collapsedSelectionAtPath(live.anchor.path, offset)
135
- : collapsedSelectionAtPath(leafPath, offset);
136
- deps.undoManager.push({
132
+ async function undoStep(seed, run) {
133
+ // A step opened after the author's input is a new gesture, so it groups its own writes.
134
+ if (stepDepth === 0 || stepEnded) {
135
+ stepEntry = null;
136
+ stepSelection = entrySelection(() => collapsedSelectionAtPath(seed.path, seed.offset));
137
+ stepEnded = false;
138
+ }
139
+ stepDepth++;
140
+ try {
141
+ await run();
142
+ }
143
+ finally {
144
+ stepDepth--;
145
+ if (stepDepth === 0) {
146
+ // The next keystroke starts its own entry rather than joining the gesture's.
147
+ if (stepPushed && !stepEnded)
148
+ textBatch.interrupt();
149
+ stepEntry = null;
150
+ stepSelection = null;
151
+ stepPushed = false;
152
+ stepEnded = false;
153
+ }
154
+ }
155
+ }
156
+ // Synchronous: a commit pushes as it is called, so this covers the call, not the awaited tail.
157
+ // Safe because `updateBlockContent` pushes the keystroke's batch entry before its commit.
158
+ function joinTypingBatch(write) {
159
+ const outer = joiningTyping;
160
+ joiningTyping = true;
161
+ try {
162
+ return write();
163
+ }
164
+ finally {
165
+ joiningTyping = outer;
166
+ }
167
+ }
168
+ function endUndoStep() {
169
+ if (stepDepth === 0)
170
+ return;
171
+ stepEnded = true;
172
+ stepEntry = null;
173
+ }
174
+ // ── Entry pushes ─────────────────────────────────────────────────────────
175
+ // A push inside a step after its first returns before the snapshot, so it neither marks the
176
+ // tree shared nor clears the redo stack.
177
+ function pushCommitSnapshot(fallbackPath, offset) {
178
+ if (isJoinedPush() || !admitsSnapshot(deps.reading))
179
+ return;
180
+ pushEntry({
137
181
  ...shareSnapshot(),
138
182
  blockIds: [...deps.blockIds],
139
- selection
183
+ selection: selectionFor(() => entrySelection(() => collapsedSelectionAtPath(fallbackPath, offset)))
140
184
  });
141
- recordSnapshotPerf();
185
+ }
186
+ // Path from the live focused leaf, offset from the caller: the live caret is already
187
+ // past the edit, but its path still points at the same leaf.
188
+ function pushTypingSnapshot(leafPath, offset) {
189
+ if (joinsStep()) {
190
+ typingEntry = stepEntry;
191
+ return;
192
+ }
193
+ const selection = selectionFor(() => {
194
+ const live = readLive();
195
+ const liveIsCollapsed = !!live &&
196
+ pathsEqual(live.anchor.path, live.focus.path) &&
197
+ live.anchor.offset === live.focus.offset;
198
+ return liveIsCollapsed
199
+ ? collapsedSelectionAtPath(live.anchor.path, offset)
200
+ : collapsedSelectionAtPath(leafPath, offset);
201
+ });
202
+ const entry = { ...shareSnapshot(), blockIds: [...deps.blockIds], selection };
203
+ pushEntry(entry);
204
+ typingEntry = entry;
142
205
  }
143
206
  const textBatch = createTextBatch({
144
207
  pushSnapshot: pushTypingSnapshot,
@@ -149,23 +212,20 @@ export function createUndoController(deps) {
149
212
  timestamp: Date.now()
150
213
  })
151
214
  });
152
- /**
153
- * Every register a throwing or discardIfNoop-bailing commit rolls back, in one
154
- * place. Container per-scope registers aren't minted until `mutate` unshares, so
155
- * restore() delegates those to the `rollback` thunk.
156
- */
157
- function captureRollbackFrame(args) {
158
- // Wholesale restore, not a pop: the push may evict the oldest at cap.
159
- const savedStacks = args.snapshot !== 'skip' ? deps.undoManager.getStacks() : null;
160
- // The container branch mutates the live tree in place; the document branch
161
- // publishes children only on success, but its tail settle can spend the live
162
- // document's suffix, so that register restores in both branches.
215
+ /** Everything a commit that throws or bails on discardIfNoop restores; a container's per-scope
216
+ * state exists only once `mutate` has copied it, so restore() hands those to `rollback`. */
217
+ function captureRollbackFrame(args, pushes) {
218
+ // A whole-stack restore, not a pop: the push may evict the oldest entry at the cap. A
219
+ // commit that joins its step's entry pushes nothing, so it has no stacks to restore.
220
+ const savedStacks = pushes ? deps.undoManager.getStacks() : null;
221
+ // The container branch mutates the live tree in place, and the document branch's
222
+ // trailing-line fix-up can consume the live document's suffix, so both restore the suffix.
163
223
  const savedDocChildren = args.kind === 'container' ? [...deps.doc.children] : null;
164
224
  const savedDocSuffix = deps.doc.suffix;
165
225
  return {
166
226
  restore() {
167
- // Top-down: stacks, top-level array, then the thunk for the in-place splices
168
- // the array swap can't reach.
227
+ // Top down: the stacks, the top-level array, then the function for the in-place
228
+ // splices the array swap cannot reach.
169
229
  if (savedStacks)
170
230
  deps.undoManager.restoreStacks(savedStacks);
171
231
  if (savedDocChildren)
@@ -176,7 +236,7 @@ export function createUndoController(deps) {
176
236
  }
177
237
  };
178
238
  }
179
- /** The one door to the `error` channel, so every throw site attributes alike (editor.md §12). */
239
+ /** The one path to the `error` event, so every throw site reports alike (`docs/design/editor.md` § The event channel). */
180
240
  function reportCommitError(args, error) {
181
241
  deps.events.emit('error', {
182
242
  origin: 'commit',
@@ -185,34 +245,39 @@ export function createUndoController(deps) {
185
245
  });
186
246
  }
187
247
  function runCommitCeremony(args) {
188
- deps.stickyColumn.reset();
189
- deps.edgeAffinity.reset();
248
+ deps.caretMemory.forget();
190
249
  textBatch.interrupt();
191
- if (DEV) {
192
- // Both declared coordinates must be doc-absolute; `invariants` stays a runtime
193
- // leaf, so the number[]→DocPath mint lives here at the ceremony.
194
- assertCommitPaths(deps.doc, args.snapshot === 'skip' ? null : asDocPath(args.snapshot.path), args.op?.eventPath ? asDocPath(args.op.eventPath) : null);
250
+ if (isDevChecks()) {
251
+ // Both declared paths must be document-absolute; `invariants` imports nothing at
252
+ // runtime, so the number[] to DocPath conversion lives here.
253
+ assertCommitPaths(deps.doc, asDocPath(args.snapshot.path), args.op?.eventPath ? asDocPath(args.op.eventPath) : null);
195
254
  }
196
- // Outside the try: the stack registers must be read BEFORE the push below.
197
- const rollback = captureRollbackFrame(args);
198
- // A `discardIfNoop` op that changed nothing takes the throw path's restore minus
199
- // the error emit. afterTick still runs.
255
+ // Outside the try: the stacks must be saved before the push below.
256
+ const rollback = captureRollbackFrame(args, !isJoinedPush());
257
+ // A `discardIfNoop` commit that changed nothing takes the throw path's restore minus
258
+ // the error event.
200
259
  let discarded = false;
201
260
  try {
202
- if (args.snapshot !== 'skip') {
203
- // Inside the try: readCurrentSelection walks live block refs, plugin leaves
204
- // included, so it throws like every other ceremony site.
205
- pushUndoSnapshotPath(args.snapshot.path, args.snapshot.offset);
206
- }
261
+ // Inside the try: readCurrentSelection walks live block refs, plugin leaves included,
262
+ // so it can throw like every other step.
263
+ pushCommitSnapshot(args.snapshot.path, args.snapshot.offset);
264
+ const wasOpen = endsOpen(deps.doc);
207
265
  if (args.kind === 'document') {
208
266
  const childrenCopy = [...deps.doc.children];
209
267
  const idsCopy = [...deps.blockIds];
210
268
  const refsCopy = [...deps.blockRefs];
269
+ const body = documentBody(deps.doc, childrenCopy);
270
+ const mutated = args.mutate(childrenCopy);
271
+ endWindowLines(body, mutated, deps.sharing, deps.reading.grammar);
211
272
  // `deps.doc.children` is still the pre-mutate array here (`publish` swaps it),
212
- // so the settle reads was-blank off it with no caller threading any facts.
213
- const change = settleSeparator(docSettleParent(childrenCopy), deps.doc.children, args.mutate(childrenCopy), deps.sharing);
273
+ // so the blank-line fix-up reads which blocks were blank off it directly.
274
+ const settled = settleSeparator(body, deps.doc.children, mutated, deps.reading.grammar, deps.sharing, args.trackCaret);
275
+ // Before the tail step, which reads the block now last; the empty paragraph is blank, so
276
+ // that step leaves its line ending as it is.
277
+ const change = keepOneBlock(body, settled, deps.sharing);
278
+ keepOpenTail(body, wasOpen, deps.sharing, deps.reading.grammar);
214
279
  if (args.discardIfNoop && change.op === 'noop') {
215
- // Document branch never published; the frame restores only the stacks here.
280
+ // The document branch installed nothing; only the stacks are restored here.
216
281
  rollback.restore();
217
282
  discarded = true;
218
283
  }
@@ -220,85 +285,124 @@ export function createUndoController(deps) {
220
285
  applyStructuralChangeToIdsRefs(change, idsCopy, refsCopy);
221
286
  assertIdsInLockstep('commitStructural', idsCopy.length, childrenCopy.length);
222
287
  args.publish(childrenCopy, idsCopy, refsCopy);
223
- if (DEV) {
224
- assertCommittedNodes(touchedFromChange(change, childrenCopy, args.touchedNodes));
288
+ if (isDevChecks()) {
289
+ const touched = touchedFromChange(change, childrenCopy, args.touchedNodes);
290
+ assertCommittedNodes(touched, deps.reading.grammar);
291
+ assertLastLineKept(deps.doc, wasOpen);
292
+ assertKeepsABlock(deps.doc, touched);
225
293
  }
226
294
  }
227
295
  }
228
296
  else {
229
- const changed = args.mutate();
297
+ const changed = args.mutate(wasOpen);
230
298
  if (args.discardIfNoop && !changed) {
231
- // The in-place mutation ran but every scope no-op'd — unwind as a throw would.
299
+ // The in-place mutation ran but no scope changed: unwind as a throw would.
232
300
  rollback.restore();
233
301
  discarded = true;
234
302
  }
235
303
  else {
236
304
  args.publish();
237
- if (DEV) {
238
- assertCommittedNodes(touchedContainersWithChildren(args.touchedNodes?.()));
305
+ if (isDevChecks()) {
306
+ const touched = touchedContainersWithChildren(args.touchedNodes?.());
307
+ assertCommittedNodes(touched, deps.reading.grammar);
308
+ assertLastLineKept(deps.doc, wasOpen);
309
+ assertKeepsABlock(deps.doc, touched);
239
310
  }
240
311
  }
241
312
  }
242
- if (!discarded && DEV) {
243
- // G1.9 commit seam: a missed copy-path-on-write here corrupts the freshest
244
- // entry — catch it at the commit, not at some distant undo. Never throws.
313
+ if (!discarded && isDevChecks()) {
314
+ // A missed copy before write corrupts the newest undo entry, so the commit catches it
315
+ // rather than some distant undo (G1.9). Never throws.
245
316
  assertUndoTopIntegrity(deps.undoManager.peekUndo() ?? undefined);
246
317
  }
247
318
  }
248
319
  catch (err) {
249
320
  rollback.restore();
250
321
  reportCommitError(args, err);
251
- // Loud in dev; production swallows so one failed mutation doesn't kill the
252
- // editor. The tree is intact either way: rolled back, or never published.
253
- if (DEV)
322
+ // Loud in dev; production swallows it so one failed edit does not kill the editor.
323
+ // The tree is intact either way: rolled back, or never installed.
324
+ if (isDevChecks())
254
325
  throw err;
255
- return false;
326
+ return 'failed';
256
327
  }
257
328
  if (!discarded) {
258
- // After both publish arms, so nothing can memoize the new key against a tree the
259
- // ceremony has not finished handing over. A discarded commit rolled its own
260
- // mutation back, and announcing it would claim bytes that never moved.
329
+ // After both branches installed their result, so nothing caches the new version against
330
+ // a half-installed tree; a discarded commit rolled back, so it announces nothing.
261
331
  deps.bumpContentVersion();
262
- // The gap names a BOUNDARY INDEX, and a commit moves what that index names. Ended
263
- // here rather than remapped: no arm can say which boundary the user meant afterwards.
264
- // After the push above, so the entry this commit stored keeps the gap it was taken at.
332
+ // A commit moves what the gap caret's boundary index names, and nothing can say which
333
+ // boundary the user meant; after the push, so the stored entry keeps the gap.
265
334
  deps.selectionState.clearGapCaret();
266
335
  }
267
336
  if (!discarded && args.op) {
268
337
  deps.events.emit('edit', toEditEvent(args.op, args.op.eventPath, Date.now()));
269
338
  }
270
- return true;
339
+ return discarded ? 'discarded' : 'written';
271
340
  }
272
- // Bracket the synchronous ceremony so the decoration engine keeps a source off a
273
- // half-applied commit. Cleared before the first await.
341
+ /** The commit's landing, checked in dev to have moved no caret while it was read. */
342
+ function readLanding(landing) {
343
+ if (!landing)
344
+ return null;
345
+ if (!isDevChecks())
346
+ return landing();
347
+ const before = readCaretWhereabouts();
348
+ const value = landing();
349
+ assertInvariant('landing-is-a-value', () => checkLandingIsAValue(before, readCaretWhereabouts()));
350
+ return value;
351
+ }
352
+ // Bracket the synchronous commit so the decorations never read a half-applied tree.
353
+ // Cleared before the first await. Resolves to whether bytes landed.
274
354
  async function __commit(args) {
355
+ const op = args.op?.kind ?? (args.kind === 'document' ? 'commitStructural' : 'commitMultiScope');
356
+ const target = args.op?.eventPath ?? args.snapshot.path;
357
+ // A refused write lands nothing, while a discarded no-op still lands: whether a commit
358
+ // lands is its own question, not whether it wrote.
359
+ if (!admitsWrite(deps.reading, op, () => blockNodeAt(deps.doc, target)?.kind))
360
+ return false;
361
+ // Read before any await, so an undo or swap during the landing's mount makes it give up.
362
+ const stamp = deps.caretLanding.generation();
275
363
  beginCommit();
276
- let committed;
364
+ let outcome;
277
365
  try {
278
- committed = runCommitCeremony(args);
366
+ outcome = runCommitCeremony(args);
279
367
  }
280
368
  finally {
281
369
  endCommit();
282
370
  }
283
- if (!committed)
284
- return;
371
+ if (outcome === 'failed')
372
+ return false;
285
373
  await tick();
374
+ // Awaited, so the promise every caller holds means "the caret is placed". No rollback on a
375
+ // throw: the commit succeeded and the tree is correct, so it is reported and the next runs.
286
376
  try {
287
- // Awaited: a landing that reveals an off-window target is async, and this
288
- // promise is what every caller treats as "the caret has settled".
289
377
  await args.afterTick?.();
290
378
  }
291
379
  catch (err) {
292
- // No rollback: the commit succeeded and the tree is correct. Contained so a
293
- // plugin's afterTick is a reported no-op, not an unhandled rejection.
294
380
  reportCommitError(args, err);
295
381
  }
382
+ try {
383
+ const landing = readLanding(args.landing);
384
+ if (landing)
385
+ await landOrRestore(landing, { stamp, reveal: args.reveal });
386
+ }
387
+ catch (err) {
388
+ reportCommitError(args, err);
389
+ }
390
+ if (outcome !== 'written')
391
+ return false;
392
+ if (args.announce)
393
+ announceEdit(args.announce());
394
+ return true;
395
+ }
396
+ async function landOrRestore(landing, opts) {
397
+ if ('anchor' in landing)
398
+ await deps.caretLanding.restore(landing, opts);
399
+ else
400
+ await deps.caretLanding.land(landing, opts);
296
401
  }
297
- // ── Structural-mutation ceremony ─────────────────────────────────────────
298
- /** `snapshot: 'skip'` lets composite operations share a single undo entry. */
299
- async function commitStructural(args) {
300
- const { snapshot, mutate, op, afterTick, touchedNodes, discardIfNoop } = args;
301
- await __commit({
402
+ // ── Structural-mutation commit ───────────────────────────────────────────
403
+ function commitStructural(args) {
404
+ const { snapshot, mutate, op, afterTick, landing, announce, touchedNodes, discardIfNoop } = args;
405
+ return __commit({
302
406
  kind: 'document',
303
407
  snapshot,
304
408
  mutate,
@@ -309,36 +413,43 @@ export function createUndoController(deps) {
309
413
  },
310
414
  op,
311
415
  afterTick,
416
+ landing,
417
+ reveal: args.reveal,
418
+ announce,
312
419
  touchedNodes,
313
- discardIfNoop
420
+ discardIfNoop,
421
+ trackCaret: args.trackCaret
314
422
  });
315
423
  }
316
- async function commitContainerStructural(args) {
424
+ function commitContainerStructural(args) {
317
425
  const { containerNode, path, state, snapshot, mutate, op, afterTick, discardIfNoop } = args;
318
- await commitMultiScope({
426
+ return commitMultiScope({
319
427
  scopes: [{ node: containerNode, state, path }],
320
428
  snapshot,
321
429
  mutate: ([scope]) => [mutate(scope)],
322
430
  op,
323
431
  afterTick,
324
- discardIfNoop
432
+ landing: args.landing,
433
+ reveal: args.reveal,
434
+ announce: args.announce,
435
+ discardIfNoop,
436
+ trackCaret: [args.trackCaret]
325
437
  });
326
438
  }
327
- /** Bytes at risk: the unshared spine plus direct children — `savedChildren`'s granularity. */
439
+ /** The bytes at risk, with the metadata a rebuild re-reads from them: the copied ancestors plus
440
+ * direct children, matching `savedChildren`. */
328
441
  function captureScopeRaws(chain, owned) {
329
- const saved = chain.map((node) => ({ node, raw: node.raw }));
330
- for (const child of owned.children ?? [])
331
- saved.push({ node: child, raw: child.raw });
332
- return saved;
442
+ const save = (node) => ({ node, raw: node.raw, metadata: node.metadata });
443
+ return [...chain.map(save), ...(owned.children ?? []).map(save)];
333
444
  }
334
445
  /**
335
- * Runs over ALL scopes BEFORE any spine is unshared: preparing an earlier scope
336
- * copies nodes a later, overlapping scope still points at.
446
+ * Runs over all scopes before any is copied: preparing an earlier scope copies nodes a
447
+ * later, overlapping scope still points at.
337
448
  */
338
449
  function assertScopeIdentity(s) {
339
450
  if (s.node === deps.doc)
340
451
  return;
341
- // A stale-but-in-range path would unshare and rebuild the wrong spine.
452
+ // A stale path that is still in range would copy and rebuild the wrong ancestors.
342
453
  assertInvariant('multi-scope-commit-path', () => nodeAt(deps.doc, s.path) === s.node
343
454
  ? null
344
455
  : {
@@ -346,14 +457,13 @@ export function createUndoController(deps) {
346
457
  message: `commit: path [${s.path.join(',')}] does not resolve to scope node (${s.node.kind})`
347
458
  });
348
459
  }
349
- /** Unshares the spine and attaches a working children array (`tree-operations/unshare.ts`). */
460
+ /** Copies the scope's ancestors and attaches a working children array (`tree-operations/unshare.ts`). */
350
461
  function prepareScopeView(s) {
351
462
  const isDoc = s.node === deps.doc;
352
463
  const chain = isDoc ? [] : ensureUnsharedPath(deps.doc, s.path, deps.sharing);
353
464
  if (!isDoc && chain.length !== s.path.length) {
354
- // Falling back to the caller's still-shared node would silently corrupt the
355
- // snapshot entry sharing it (G1.9); G1.19/G1.22 are dev-only. This door throws;
356
- // its sibling (`withUnsharedSpine`, G1.20) rebuilds what the walk did reach.
465
+ // A short chain leaves the container node shared with an undo entry, and writing it
466
+ // would corrupt that entry (G1.9), so the commit throws rather than write it.
357
467
  const message = `commitMultiScope: unshared chain depth ${chain.length} != scope path depth ${s.path.length} (path [${s.path.join(',')}])`;
358
468
  assertInvariant('multi-scope-scope-depth', () => ({
359
469
  code: 'multi-scope-scope-depth',
@@ -361,11 +471,11 @@ export function createUndoController(deps) {
361
471
  }));
362
472
  throw new Error(message);
363
473
  }
364
- // The ceremony's view→mutable door (core/node-views.ts): the unshared chain owns
365
- // the scope node, and the doc scope owns the root by construction.
474
+ // Where the commit turns a read-only view into a mutable node (core/node-views.ts):
475
+ // the copied chain owns the scope node, and the document scope owns the root.
366
476
  const owned = isDoc ? s.node : chain[chain.length - 1];
367
- // A container that never mounted has NO ids, which is not an empty list: seeding `[]`
368
- // publishes one id per structural change against N children, and nothing reconciles it.
477
+ // A container that never mounted has no ids, which is not an empty list: starting from
478
+ // `[]` writes one id per structural change against N children, and nothing fixes it.
369
479
  const ids = isDoc
370
480
  ? [...s.state.innerBlockIds]
371
481
  : [...(owned.childIds ?? assignIds(owned.children ?? []))];
@@ -377,12 +487,31 @@ export function createUndoController(deps) {
377
487
  const savedChildIds = owned.childIds;
378
488
  const savedRaws = captureScopeRaws(chain, owned);
379
489
  owned.children = [...(owned.children ?? [])];
490
+ const lineEnding = documentLineEnding(deps.doc);
380
491
  return {
381
492
  target: s,
382
493
  isDoc,
383
494
  chain,
384
495
  owned,
385
- view: { node: owned, children: owned.children, sharing: deps.sharing },
496
+ view: {
497
+ node: owned,
498
+ children: owned.children,
499
+ sharing: deps.sharing,
500
+ lineEnding,
501
+ body: isDoc
502
+ ? documentBody(deps.doc, owned.children)
503
+ : { children: owned.children, owner: owned, lineEnding },
504
+ rebuild: (node) => {
505
+ // The commit rebuilds the scope's own chain, and a shared node is an undo entry's.
506
+ assertInvariant('scope-rebuild-off-chain', () => node === owned || chain.includes(node) || deps.sharing.isShared(node)
507
+ ? {
508
+ code: 'scope-rebuild-off-chain',
509
+ message: `ContainerScope.rebuild: a ${node.kind} on the commit's chain or shared`
510
+ }
511
+ : null);
512
+ rebuildOwnedContainer(node, deps.sharing);
513
+ }
514
+ },
386
515
  ids,
387
516
  refs,
388
517
  savedChildren,
@@ -393,8 +522,8 @@ export function createUndoController(deps) {
393
522
  };
394
523
  }
395
524
  /**
396
- * Doc-scope ids route through deps setters; container ids live on the owned node,
397
- * because the state bundle's setter would write the stale shared node prop.
525
+ * Document-scope ids go through the deps setters; container ids live on the copied node,
526
+ * because the state's setter would write the stale shared node's property.
398
527
  */
399
528
  function publishScopeView(p, change) {
400
529
  applyStructuralChangeToIdsRefs(change, p.ids, p.refs);
@@ -407,75 +536,79 @@ export function createUndoController(deps) {
407
536
  }
408
537
  replaceRefs(p.target.state.innerBlockRefs, p.refs);
409
538
  }
410
- /**
411
- * Atomic structural commit across container scopes — one undo snapshot, one edit
412
- * event. Each spine is unshared before `mutate` and raw-rebuilt after, deepest
413
- * first. Mutate through the provided scope views, never pre-commit captures.
414
- */
539
+ /** One structural commit across several containers: one undo snapshot, one edit event. Mutate
540
+ * through the provided scope views, never nodes read before the commit. */
415
541
  async function commitMultiScope(args) {
416
- const { scopes, snapshot, mutate, op, afterTick, discardIfNoop, trackCaret } = args;
542
+ const { scopes, snapshot, mutate, op, discardIfNoop, trackCaret } = args;
417
543
  const prepared = [];
418
- // Container slots the chain rebuild re-kinded: the replacements are what the DEV
419
- // probes check, and the slot is what an unwind restores.
544
+ // Containers whose kind the chain rebuild changed: the replacements are what the dev
545
+ // checks read, and the index is what an unwind restores.
420
546
  const reclassified = [];
421
- // Parent-scope folds the ancestry settle spliced, with the caret landing they owe: the
422
- // fold re-mints every block in its window, so a scope it ate has no ref left to focus.
547
+ // Containers the ancestor rebuild collapsed into their parent, with where the caret goes: a
548
+ // collapse recreates every block in its range, so a swallowed scope has no ref to focus.
423
549
  const folds = [];
424
- let landing = null;
550
+ let foldLanding = null;
425
551
  let unwindFolds = null;
426
- await __commit({
552
+ return __commit({
427
553
  kind: 'container',
428
554
  snapshot,
429
- mutate: () => {
555
+ mutate: (wasOpen) => {
430
556
  for (const s of scopes)
431
557
  assertScopeIdentity(s);
432
558
  // Pushed as each resolves, so a scope that fails to prepare still leaves the
433
- // frame holding the registers of the scopes prepared before it.
559
+ // rollback holding the state of the scopes prepared before it.
434
560
  for (const s of scopes)
435
561
  prepared.push(prepareScopeView(s));
436
562
  const changes = mutate(prepared.map((p) => p.view));
437
- // Dynamically-built scope arrays degrade to array typing, so this runtime
438
- // check backstops the tuple types.
563
+ // A scope array built at runtime loses the tuple type, so this runtime check
564
+ // backs up the types.
439
565
  const changeList = [...changes];
440
566
  if (changeList.length !== scopes.length) {
441
567
  throw new Error(`commitMultiScope: mutate returned ${changeList.length} changes for ${scopes.length} scopes`);
442
568
  }
443
569
  for (let i = 0; i < prepared.length; i++) {
444
- // `savedChildren` is the pre-mutate array the scope prep swapped out, so the
445
- // settle reads was-blank off it (`prepareScopeView`).
446
- changeList[i] = settleSeparator(prepared[i].owned, prepared[i].savedChildren ?? [], changeList[i], deps.sharing, trackCaret?.[i]);
570
+ endWindowLines(prepared[i].view.body, changeList[i], deps.sharing, deps.reading.grammar);
571
+ }
572
+ for (let i = 0; i < prepared.length; i++) {
573
+ // `savedChildren` is the pre-mutate array `prepareScopeView` swapped out, so
574
+ // the blank-line fix-up reads which blocks were blank off it.
575
+ changeList[i] = settleSeparator(prepared[i].view.body, prepared[i].savedChildren ?? [], changeList[i], deps.reading.grammar, deps.sharing, trackCaret?.[i]);
576
+ if (prepared[i].isDoc) {
577
+ changeList[i] = keepOneBlock(prepared[i].view.body, changeList[i], deps.sharing);
578
+ }
447
579
  publishScopeView(prepared[i], changeList[i]);
448
580
  }
449
- // Deepest chains first: an inner scope's raw must be current before an outer
450
- // chain concatenates it. Truncating to the attached prefix keeps a
451
- // spliced-out scope from being rebuilt off its emptied children.
452
- for (const p of [...prepared].sort((a, b) => b.chain.length - a.chain.length)) {
581
+ // Deepest first, so an outer chain concatenates current inner raws; the attached prefix
582
+ // keeps a scope spliced out of the tree from being rebuilt off its emptied children.
583
+ const order = [...prepared].sort((a, b) => b.chain.length - a.chain.length);
584
+ // An ancestor several scopes share is rebuilt once, by the last chain holding it.
585
+ const levels = sharedChainLevels(order.map((p) => p.chain));
586
+ order.forEach((p, i) => {
453
587
  const before = folds.length;
454
- reclassified.push(...rebuildUnsharedChain(deps.doc, attachedChainPrefix(deps.doc, p.chain), deps.sharing, folds, deps.grammar));
455
- landing = foldLandingFor(folds.slice(before), p.target.path) ?? landing;
456
- }
588
+ reclassified.push(...rebuildUnsharedChain(deps.doc, attachedChainPrefix(deps.doc, p.chain), deps.sharing, folds, deps.reading.grammar, undefined, levels[i]));
589
+ foldLanding = foldLandingFor(folds.slice(before), p.target.path) ?? foldLanding;
590
+ });
457
591
  unwindFolds = publishAncestryFolds(deps, folds);
592
+ // The document commit above runs the same two steps until the two branches merge.
593
+ keepOpenTail(deps.doc, wasOpen, deps.sharing, deps.reading.grammar);
458
594
  return changeList.some((c) => c.op !== 'noop') || folds.length > 0;
459
595
  },
460
596
  publish: () => {
461
- // Nudge top-level reactivity so ancestor-raw mutations propagate.
597
+ // Nudge top-level reactivity so the rewritten ancestor raws propagate.
462
598
  deps.doc.children = [...deps.doc.children];
463
599
  },
464
600
  op,
465
- afterTick: async () => {
466
- try {
467
- await afterTick?.();
468
- }
469
- finally {
470
- // After the caller's landing and regardless of it: the fold ate the scope that
471
- // landing addressed, so it resolved no ref — or read through a detached node.
472
- if (landing)
473
- (await deps.revealPath(landing.path))?.focus(landing.offset);
474
- }
475
- },
601
+ afterTick: args.afterTick,
602
+ // A collapsed container recreated every block in its range, so its position replaces the
603
+ // caller's rather than following it.
604
+ landing: () => foldLanding
605
+ ? { path: docPathFrom(foldLanding.path), offset: foldLanding.offset }
606
+ : (args.landing?.() ?? null),
607
+ reveal: args.reveal,
608
+ announce: args.announce,
476
609
  discardIfNoop,
477
- // Detached scopes are no longer committed tree state — checking one would fire
478
- // stale-raw on a node the document no longer contains.
610
+ // A detached scope is outside the tree, and checking it would fire stale-raw on a node
611
+ // the document does not contain.
479
612
  touchedNodes: () => [
480
613
  ...prepared
481
614
  .filter((p) => attachedChainPrefix(deps.doc, p.chain).length === p.chain.length)
@@ -483,11 +616,11 @@ export function createUndoController(deps) {
483
616
  ...reclassified.map((r) => r.replacement)
484
617
  ].filter((n) => tryGetBlockKindDescriptor(n.kind) !== undefined),
485
618
  rollback: () => {
486
- // Folds unwind first: each restores a whole parent array, which the
487
- // reclassification registers below then correct slot by slot.
619
+ // Collapses unwind first: each restores a whole parent array, which the kind
620
+ // changes below then correct index by index.
488
621
  unwindFolds?.();
489
- // Reverse of the landing order, so a slot is never restored under a node the
490
- // next restore is about to replace.
622
+ // The reverse of the order they happened in, so an index is never restored
623
+ // under a node the next restore is about to replace.
491
624
  for (let i = reclassified.length - 1; i >= 0; i--) {
492
625
  const { siblings, index, previous } = reclassified[i];
493
626
  siblings[index] = previous;
@@ -495,13 +628,14 @@ export function createUndoController(deps) {
495
628
  for (const p of prepared) {
496
629
  p.owned.children = p.savedChildren;
497
630
  p.owned.childIds = p.savedChildIds;
498
- // Bytes as well as shape: the chain rebuild dispatches into plugin
499
- // `rebuildRaw`, so an unwind leaves raws the children no longer justify.
500
- for (const { node, raw } of p.savedRaws) {
631
+ // The chain rebuild rewrote these bytes and the metadata it read from them, and both have
632
+ // to match the children restored above.
633
+ for (const { node, raw, metadata } of p.savedRaws) {
501
634
  node.raw = raw;
635
+ node.metadata = metadata;
502
636
  dropChildSpans(node);
503
637
  }
504
- // Without this, ids/refs published before the throw keep reflecting it.
638
+ // Without this, the ids and refs written before the throw keep reflecting it.
505
639
  if (p.isDoc)
506
640
  p.target.state.innerBlockIds = p.savedStateIds;
507
641
  replaceRefs(p.target.state.innerBlockRefs, p.savedStateRefs);
@@ -511,7 +645,7 @@ export function createUndoController(deps) {
511
645
  }
512
646
  // ── Doc scope adapter ────────────────────────────────────────────────────
513
647
  /** Forwards top-level ids through the deps setter, so the write reaches the `$state`
514
- * proxy; refs are the editor's own array, which every publish mutates in place. */
648
+ * proxy; refs are the editor's own array, which every write mutates in place. */
515
649
  function createDocScopeAdapter() {
516
650
  return {
517
651
  get innerBlockIds() {
@@ -526,44 +660,40 @@ export function createUndoController(deps) {
526
660
  refSlots: deps.blockRefSlots
527
661
  };
528
662
  }
529
- /** The document root as a MultiScopeTarget, for cross-scope ops whose LCA is doc level. */
663
+ /** The document root as a MultiScopeTarget, for edits whose common ancestor is the document. */
530
664
  function getDocScope() {
531
665
  return { node: deps.doc, path: [], state: createDocScopeAdapter() };
532
666
  }
533
667
  // ── State capture / checkpoint control ──────────────────────────────────
534
- // Every history swap replaces the whole tree, so a landing that awaited across one is
535
- // aimed at content that no longer exists. Monotonic and never reset: a landing compares
536
- // stamps, it never reads the value.
537
- let historyGeneration = 0;
538
668
  function captureCurrentState() {
539
- // Same three-tier read as the snapshot pushers — this is the entry a history swap
540
- // pushes onto the opposite stack, so a gap live at the swap must survive the return.
669
+ // The same selection read as the snapshot pushes: this is the entry an undo or redo
670
+ // pushes onto the opposite stack, so a gap caret or a selected image's caret survives.
541
671
  return {
542
672
  ...shareSnapshot(),
543
673
  blockIds: [...deps.blockIds],
544
- // Fallback for unfocused-at-capture (headless harness, programmatic capture).
674
+ // Fallback when nothing is focused (a headless harness, a programmatic capture).
545
675
  selection: entrySelection(() => collapsedSelectionAt(0, 0))
546
676
  };
547
677
  }
548
678
  return {
549
679
  sharing: deps.sharing,
550
- pushUndoSnapshot,
551
- pushUndoSnapshotPath,
552
- pushUndoSnapshotDebounced: textBatch.keystroke,
680
+ pushUndoSnapshotDebounced: (leafPath, offset, batchKey) => {
681
+ if (admitsSnapshot(deps.reading))
682
+ textBatch.keystroke(leafPath, offset, batchKey);
683
+ },
553
684
  armUndoPause: textBatch.armPause,
554
685
  commitStructural,
555
686
  commitContainerStructural,
556
687
  commitMultiScope,
557
688
  getDocScope,
558
689
  captureCurrentState,
559
- historyGeneration: () => historyGeneration,
560
- noteHistorySwap: () => {
561
- historyGeneration++;
562
- },
563
690
  flushDebouncedCheckpoint: textBatch.interrupt,
691
+ undoStep,
692
+ joinTypingBatch,
693
+ endUndoStep,
564
694
  isolateUndoEntry: (write) => {
565
- // Both sides: the leading break makes the write push its own snapshot instead of
566
- // joining the burst before it, the trailing one keeps the next keystroke out of it.
695
+ // Both sides: the first break makes the write push its own snapshot instead of
696
+ // joining the burst before it, the second keeps the next keystroke out of it.
567
697
  textBatch.interrupt();
568
698
  write();
569
699
  textBatch.interrupt();