@voithos-labs/aragonite 0.10.2 → 0.10.3

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 (255) hide show
  1. package/README.md +6 -21
  2. package/THIRD-PARTY-NOTICES.md +25 -0
  3. package/dist/a11y-strings.d.ts +18 -0
  4. package/dist/a11y-strings.js +18 -0
  5. package/dist/action-contracts.d.ts +7 -1
  6. package/dist/ambient/ambient-dom.js +5 -1
  7. package/dist/block-component.d.ts +14 -0
  8. package/dist/components/BlockDragHandle.svelte +35 -24
  9. package/dist/components/BlockHost.svelte +16 -9
  10. package/dist/components/Editor.svelte +381 -198
  11. package/dist/components/Editor.svelte.d.ts +1 -1
  12. package/dist/components/SelectionOverlay.svelte +17 -3
  13. package/dist/components/TailInsert.svelte +107 -0
  14. package/dist/components/TailInsert.svelte.d.ts +17 -0
  15. package/dist/components/block-content-selector.d.ts +6 -2
  16. package/dist/components/block-content-selector.js +6 -2
  17. package/dist/components/blocks/ThematicBreakBlock.svelte +19 -6
  18. package/dist/components/blocks/ThematicBreakBlock.svelte.d.ts +1 -0
  19. package/dist/components/blocks/code/CodeBlock.svelte +211 -30
  20. package/dist/components/blocks/code/CodeBlockRail.svelte +686 -0
  21. package/dist/components/blocks/code/CodeBlockRail.svelte.d.ts +26 -0
  22. package/dist/components/blocks/code/code-bootstrap.js +4 -0
  23. package/dist/components/blocks/code/code-context-actions.d.ts +1 -0
  24. package/dist/components/blocks/code/code-context-actions.js +24 -0
  25. package/dist/components/blocks/code/code-fence-exit.d.ts +15 -0
  26. package/dist/components/blocks/code/code-fence-exit.js +26 -0
  27. package/dist/components/blocks/code/code-languages.d.ts +6 -0
  28. package/dist/components/blocks/code/code-languages.js +11 -0
  29. package/dist/components/blocks/code/code-renderer.js +11 -0
  30. package/dist/components/blocks/directive/DirectiveContainerBlock.svelte +1 -1
  31. package/dist/components/blocks/editable-leaf.d.ts +37 -6
  32. package/dist/components/blocks/editable-leaf.js +243 -29
  33. package/dist/components/blocks/editable-surface.d.ts +9 -0
  34. package/dist/components/blocks/editable-surface.js +22 -3
  35. package/dist/components/blocks/list/ListItemBlock.svelte +3 -3
  36. package/dist/components/blocks/list/task-checkbox.d.ts +2 -0
  37. package/dist/components/blocks/list/task-checkbox.js +11 -2
  38. package/dist/components/blocks/surface-wiring.svelte.d.ts +4 -0
  39. package/dist/components/blocks/surface-wiring.svelte.js +8 -1
  40. package/dist/components/blocks/table/TableActionMenu.svelte +210 -86
  41. package/dist/components/blocks/table/TableActionMenu.svelte.d.ts +5 -0
  42. package/dist/components/blocks/table/TableBlock.svelte +205 -186
  43. package/dist/components/blocks/table/TableBlock.svelte.d.ts +1 -0
  44. package/dist/components/blocks/table/TableCellBlock.svelte +87 -22
  45. package/dist/components/blocks/table/TableRowBlock.svelte +4 -18
  46. package/dist/components/blocks/table/TableRowBlock.svelte.d.ts +0 -5
  47. package/dist/components/blocks/table/cell-clipboard.d.ts +10 -0
  48. package/dist/components/blocks/table/cell-clipboard.js +34 -1
  49. package/dist/components/blocks/table/cell-keydown-plan.d.ts +1 -1
  50. package/dist/components/blocks/table/cell-keydown-plan.js +3 -1
  51. package/dist/components/blocks/table/table-cell-paste.js +2 -1
  52. package/dist/components/blocks/table/table-menu-model.d.ts +35 -8
  53. package/dist/components/blocks/table/table-menu-model.js +36 -17
  54. package/dist/components/blocks/text/TextEditableBlock.svelte +58 -11
  55. package/dist/components/blocks/text/delimiter-autopair.d.ts +71 -0
  56. package/dist/components/blocks/text/delimiter-autopair.js +216 -0
  57. package/dist/components/blocks/text/edge-policy-dispatch.d.ts +4 -0
  58. package/dist/components/blocks/text/edge-policy-dispatch.js +56 -2
  59. package/dist/components/blocks/text/live-selection-edit.js +27 -0
  60. package/dist/components/blocks/text/text-keydown.d.ts +7 -1
  61. package/dist/components/blocks/text/text-keydown.js +11 -1
  62. package/dist/components/blocks/text/text-render.d.ts +1 -1
  63. package/dist/components/blocks/text/text-render.js +3 -1
  64. package/dist/components/blocks/text/widget-interaction.d.ts +3 -0
  65. package/dist/components/blocks/text/widget-interaction.js +144 -22
  66. package/dist/components/drag-handle.d.ts +35 -0
  67. package/dist/components/drag-handle.js +126 -0
  68. package/dist/components/editor-root-focus.d.ts +19 -0
  69. package/dist/components/editor-root-focus.js +67 -0
  70. package/dist/components/editor-root-geometry.d.ts +39 -0
  71. package/dist/components/editor-root-geometry.js +91 -0
  72. package/dist/components/editor-root-keydown.d.ts +1 -1
  73. package/dist/components/editor-root-keydown.js +12 -3
  74. package/dist/components/editor-root-listeners.d.ts +10 -6
  75. package/dist/components/editor-root-listeners.js +23 -22
  76. package/dist/components/editor-root-mode-flip.d.ts +36 -0
  77. package/dist/components/editor-root-mode-flip.js +92 -0
  78. package/dist/components/image/ImageOverlayHost.svelte +14 -6
  79. package/dist/components/image/ImageProperties.svelte +512 -70
  80. package/dist/components/image/ImageProperties.svelte.d.ts +6 -1
  81. package/dist/components/image/ImageResizeHandles.svelte +59 -34
  82. package/dist/components/image/image-crop.d.ts +39 -0
  83. package/dist/components/image/image-crop.js +74 -0
  84. package/dist/components/image/image-edit-commit.d.ts +1 -0
  85. package/dist/components/image/image-edit-commit.js +21 -5
  86. package/dist/components/image/image-source-bytes.js +10 -3
  87. package/dist/components/image/image-widget-editing.js +1 -0
  88. package/dist/components/image/widget-dom.js +5 -1
  89. package/dist/components/link-card/link-card-commit.js +1 -1
  90. package/dist/components/lrd-map-gate.js +1 -1
  91. package/dist/components/menu/BlockMenu.svelte +315 -0
  92. package/dist/components/menu/BlockMenu.svelte.d.ts +34 -0
  93. package/dist/components/menu/MenuIcon.svelte +153 -0
  94. package/dist/components/menu/MenuIcon.svelte.d.ts +51 -0
  95. package/dist/components/menu/clipboard-actions.d.ts +12 -0
  96. package/dist/components/menu/clipboard-actions.js +42 -0
  97. package/dist/components/menu/default-context-actions.d.ts +15 -0
  98. package/dist/components/menu/default-context-actions.js +76 -0
  99. package/dist/components/menu/flyout-placement.d.ts +6 -0
  100. package/dist/components/menu/flyout-placement.js +25 -0
  101. package/dist/core/inline/format-toggle.d.ts +12 -4
  102. package/dist/core/inline/format-toggle.js +94 -40
  103. package/dist/core/inline/image-dimensions.d.ts +3 -0
  104. package/dist/core/inline/image-dimensions.js +46 -10
  105. package/dist/core/inline/inline-widgets.d.ts +11 -0
  106. package/dist/core/inline/scan/brackets.js +1 -0
  107. package/dist/core/inline/scan/plugin-syntax.d.ts +8 -0
  108. package/dist/core/inline/scan/plugin-syntax.js +15 -1
  109. package/dist/core/inline-render.d.ts +6 -0
  110. package/dist/core/inline-render.js +32 -0
  111. package/dist/core/nodes.d.ts +14 -0
  112. package/dist/cursor/edge-affinity.js +2 -1
  113. package/dist/cursor/overlay-remeasure.js +8 -0
  114. package/dist/cursor/reveal-source.js +7 -2
  115. package/dist/cursor/widget-offset.d.ts +6 -0
  116. package/dist/cursor/widget-offset.js +61 -4
  117. package/dist/debug/interaction-trace.d.ts +4 -0
  118. package/dist/debug/interaction-trace.js +15 -0
  119. package/dist/decorations/decoration-state.svelte.js +1 -1
  120. package/dist/editor-actions/ancestry-folds.d.ts +2 -2
  121. package/dist/editor-actions/ancestry-folds.js +1 -1
  122. package/dist/editor-actions/block-edit-scope.js +1 -1
  123. package/dist/editor-actions/commit/text-batch.d.ts +3 -2
  124. package/dist/editor-actions/commit/text-batch.js +1 -1
  125. package/dist/editor-actions/commit/undo-controller.js +4 -2
  126. package/dist/editor-actions/container-edit.js +2 -1
  127. package/dist/editor-actions/enter-completion.d.ts +2 -0
  128. package/dist/editor-actions/enter-completion.js +23 -2
  129. package/dist/editor-actions/inline-range-commit.js +1 -1
  130. package/dist/editor-actions/reorder-action.js +19 -10
  131. package/dist/editor-actions/reorder-drag.js +29 -1
  132. package/dist/editor-actions/replacement-focus.d.ts +1 -1
  133. package/dist/editor-actions/replacement-focus.js +1 -1
  134. package/dist/editor-actions/search-replace.js +1 -1
  135. package/dist/editor-actions/table-context.d.ts +4 -1
  136. package/dist/editor-actions/table-context.js +57 -1
  137. package/dist/editor-events.d.ts +3 -0
  138. package/dist/editor-keys.d.ts +33 -0
  139. package/dist/editor-props.d.ts +21 -12
  140. package/dist/index.d.ts +1 -1
  141. package/dist/plugin.d.ts +6 -0
  142. package/dist/plugin.js +11 -0
  143. package/dist/plugins/latex/BlockMath.svelte +264 -29
  144. package/dist/plugins/latex/BlockMath.svelte.d.ts +2 -0
  145. package/dist/plugins/latex/index.d.ts +2 -1
  146. package/dist/plugins/latex/latex-kind.js +36 -3
  147. package/dist/plugins/latex/math-completion.js +4 -1
  148. package/dist/plugins/latex/math-layout.d.ts +15 -0
  149. package/dist/plugins/latex/math-layout.js +13 -0
  150. package/dist/plugins/latex/math-source.d.ts +19 -0
  151. package/dist/plugins/latex/math-source.js +97 -0
  152. package/dist/plugins/latex/register.d.ts +11 -2
  153. package/dist/plugins/latex/register.js +3 -1
  154. package/dist/plugins/latex/renderer.d.ts +3 -3
  155. package/dist/plugins/latex/renderer.js +13 -6
  156. package/dist/reactivity/list-windowing.svelte.d.ts +8 -8
  157. package/dist/reactivity/list-windowing.svelte.js +49 -24
  158. package/dist/schema/block-completions.d.ts +8 -0
  159. package/dist/schema/block-completions.js +11 -0
  160. package/dist/schema/context-actions.d.ts +31 -0
  161. package/dist/schema/context-actions.js +23 -0
  162. package/dist/schema/fenced-code-raw.js +31 -1
  163. package/dist/schema/operations.d.ts +8 -1
  164. package/dist/schema/reserved-chords.js +25 -4
  165. package/dist/schema/table-cell-raw.d.ts +1 -1
  166. package/dist/schema/table-cell-raw.js +1 -1
  167. package/dist/selection/block-hit-test.js +3 -2
  168. package/dist/selection/char-endpoint-snap.js +1 -1
  169. package/dist/selection/clipboard-text.js +6 -1
  170. package/dist/selection/covered-block.d.ts +10 -0
  171. package/dist/selection/covered-block.js +24 -0
  172. package/dist/selection/cross-block/dispatch.d.ts +3 -0
  173. package/dist/selection/cross-block/dispatch.js +13 -1
  174. package/dist/selection/cross-block/format-range.d.ts +1 -1
  175. package/dist/selection/cross-block/format-range.js +4 -15
  176. package/dist/selection/cross-block/format-toggle.js +1 -1
  177. package/dist/selection/cross-block/keydown.js +1 -1
  178. package/dist/selection/cross-block/ops.js +1 -1
  179. package/dist/selection/cross-block/paste.js +32 -30
  180. package/dist/selection/cross-block/type-replace.d.ts +3 -2
  181. package/dist/selection/cross-block/type-replace.js +62 -13
  182. package/dist/selection/dead-space-caret.d.ts +10 -0
  183. package/dist/selection/dead-space-caret.js +47 -1
  184. package/dist/selection/double-click-trim.d.ts +17 -0
  185. package/dist/selection/double-click-trim.js +57 -0
  186. package/dist/selection/drag-pointer.d.ts +7 -2
  187. package/dist/selection/drag-pointer.js +61 -2
  188. package/dist/selection/gap-caret.js +1 -1
  189. package/dist/selection/keyboard-extend.js +1 -1
  190. package/dist/selection/path-lookup.js +1 -1
  191. package/dist/selection/range-delete-ceremony.js +4 -2
  192. package/dist/selection/range-delete-chrome.js +2 -1
  193. package/dist/selection/range-delete-table-coverage.js +2 -1
  194. package/dist/selection/range-delete-table.js +3 -2
  195. package/dist/selection/range-delete.js +30 -2
  196. package/dist/selection/selection-restore.js +1 -1
  197. package/dist/selection/selection-state.svelte.d.ts +6 -0
  198. package/dist/selection/selection-state.svelte.js +36 -1
  199. package/dist/selection/table-endpoint-snap.js +1 -1
  200. package/dist/selection/table-rect-extend.js +1 -1
  201. package/dist/styles/editor-theme.css +57 -28
  202. package/dist/styles/editor.css +217 -18
  203. package/dist/testing/container-conformance.js +2 -2
  204. package/dist/testing/inline-conformance.js +2 -1
  205. package/dist/tree-operations/blockquote.js +1 -1
  206. package/dist/tree-operations/chain-rebuild.d.ts +63 -0
  207. package/dist/tree-operations/chain-rebuild.js +142 -0
  208. package/dist/tree-operations/children.d.ts +1 -1
  209. package/dist/tree-operations/children.js +1 -1
  210. package/dist/tree-operations/cleanup.js +1 -1
  211. package/dist/tree-operations/content-write.d.ts +50 -0
  212. package/dist/tree-operations/content-write.js +263 -0
  213. package/dist/tree-operations/index.d.ts +8 -3
  214. package/dist/tree-operations/index.js +6 -2
  215. package/dist/tree-operations/list/exit-replacement.js +1 -1
  216. package/dist/tree-operations/list/unwrap-merge.js +3 -3
  217. package/dist/tree-operations/node-ops.d.ts +17 -234
  218. package/dist/tree-operations/node-ops.js +47 -1113
  219. package/dist/tree-operations/node-primitives.d.ts +75 -0
  220. package/dist/tree-operations/node-primitives.js +117 -0
  221. package/dist/tree-operations/paste/apply.js +1 -1
  222. package/dist/tree-operations/paste/body-write.d.ts +1 -1
  223. package/dist/tree-operations/paste/body-write.js +2 -2
  224. package/dist/tree-operations/paste/container-match.js +4 -2
  225. package/dist/tree-operations/paste/dispatch.js +2 -1
  226. package/dist/tree-operations/paste/find-enclosing-list.js +1 -1
  227. package/dist/tree-operations/paste/focus-target.d.ts +1 -1
  228. package/dist/tree-operations/paste/list-absorb.js +1 -1
  229. package/dist/tree-operations/paste/list-break-out.js +1 -1
  230. package/dist/tree-operations/paste/parent-scope.js +1 -1
  231. package/dist/tree-operations/paste/paste-replacement.js +1 -1
  232. package/dist/tree-operations/paste/replace-block-at-parent.js +1 -1
  233. package/dist/tree-operations/path-mutate.d.ts +1 -1
  234. package/dist/tree-operations/path-mutate.js +2 -1
  235. package/dist/tree-operations/reorder-unit.js +1 -1
  236. package/dist/tree-operations/reorder.d.ts +5 -2
  237. package/dist/tree-operations/reorder.js +55 -2
  238. package/dist/tree-operations/settle.d.ts +105 -0
  239. package/dist/tree-operations/settle.js +660 -0
  240. package/dist/tree-operations/table-grid-clipboard.d.ts +21 -0
  241. package/dist/tree-operations/table-grid-clipboard.js +90 -0
  242. package/dist/tree-operations/unshare.d.ts +15 -77
  243. package/dist/tree-operations/unshare.js +15 -166
  244. package/docs/guide/consumer-guide.md +126 -96
  245. package/docs/guide/plugin-api.md +31 -3
  246. package/docs/guide/plugin-guide.md +26 -3
  247. package/package.json +4 -2
  248. package/dist/components/blocks/code/CodeLanguageChip.svelte +0 -127
  249. package/dist/components/blocks/code/CodeLanguageChip.svelte.d.ts +0 -14
  250. package/dist/components/blocks/table/TableGrip.svelte +0 -91
  251. package/dist/components/blocks/table/TableGrip.svelte.d.ts +0 -8
  252. package/dist/components/blocks/table/table-drop-target.d.ts +0 -1
  253. package/dist/components/blocks/table/table-drop-target.js +0 -16
  254. package/dist/components/blocks/table/table-reorder-drag.d.ts +0 -78
  255. package/dist/components/blocks/table/table-reorder-drag.js +0 -97
@@ -168,6 +168,29 @@
168
168
  max-width: 100%;
169
169
  height: auto;
170
170
  display: block;
171
+ /* Enough to take the hard corner off a photo sitting in prose, not enough to read as a
172
+ card: half the surface radius the block chrome uses. */
173
+ border-radius: 4px;
174
+ }
175
+
176
+ /* A cropped image: the widget is the frame (width and aspect set inline from the `|WxH` hint,
177
+ capped to the column) and the image pans inside it, sized and offset by `image-crop.ts`. */
178
+ :where(.editor) .md-image-widget.md-image-cropped {
179
+ overflow: hidden;
180
+ max-width: 100%;
181
+ /* The frame clips the picture, so the rounding belongs to it; the picture inside is square
182
+ again or its own corners would cut inside the frame's. */
183
+ border-radius: 4px;
184
+ }
185
+
186
+ :where(.editor) .md-image-widget.md-image-cropped img {
187
+ border-radius: 0;
188
+ }
189
+
190
+ :where(.editor) .md-image-widget.md-image-cropped img {
191
+ position: absolute;
192
+ max-width: none;
193
+ object-fit: cover;
171
194
  }
172
195
 
173
196
  /* Image-bearing list-item / blockquote paragraph: the ambient marker sits at the image's
@@ -249,6 +272,12 @@
249
272
  pointer-events: none;
250
273
  }
251
274
 
275
+ /* The tint IS the widget's selection paint: native `::selection` on the text inside it (a KaTeX
276
+ box is text) would stack a second wash on the same pixels. */
277
+ :where(.editor) [data-inline-widget].md-widget-selected ::selection {
278
+ background: transparent;
279
+ }
280
+
252
281
  /* Synthetic caret on the snap-target edge — Chromium doesn't reliably render
253
282
  the live caret adjacent to a contenteditable=false neighbor. */
254
283
  :where(.editor) [data-inline-widget].md-snap-after::before,
@@ -263,12 +292,14 @@
263
292
  pointer-events: none;
264
293
  }
265
294
 
295
+ /* Clear of the widget's own edge: against a picture, a caret drawn tight to the frame reads as
296
+ part of the border rather than as a caret waiting for the next character. */
266
297
  :where(.editor) [data-inline-widget].md-snap-after::before {
267
- right: -2px;
298
+ right: -4px;
268
299
  }
269
300
 
270
301
  :where(.editor) [data-inline-widget].md-snap-before::before {
271
- left: -2px;
302
+ left: -4px;
272
303
  }
273
304
 
274
305
  @keyframes md-snap-caret-blink {
@@ -350,7 +381,7 @@
350
381
  /* Dimmed monospace gives inline raw HTML a code-ish feel without becoming a code span. */
351
382
  :where(.editor) .md-raw-html {
352
383
  color: var(--md-raw-html-color, rgba(120, 120, 120, 0.85));
353
- font-family: var(--font-editor, ui-monospace, monospace);
384
+ font-family: var(--font-code, ui-monospace, monospace);
354
385
  font-size: 0.92em;
355
386
  }
356
387
 
@@ -367,7 +398,7 @@
367
398
  width: 100%;
368
399
  box-sizing: border-box;
369
400
  min-height: 1.4em;
370
- font-family: var(--font-editor, ui-monospace, monospace);
401
+ font-family: var(--font-code, ui-monospace, monospace);
371
402
  font-size: 0.9em;
372
403
  line-height: 1.5;
373
404
  color: inherit;
@@ -394,6 +425,13 @@
394
425
  color: var(--syntax-code, currentColor);
395
426
  }
396
427
 
428
+ /* An inline widget's source while it is revealed for editing (`$x$`, a footnote ref): the
429
+ inline-code wash, so the span being edited reads as a span, in the prose face so the line
430
+ does not reflow around it. */
431
+ ::highlight(md-inline-reveal) {
432
+ background-color: var(--color-bg-secondary, rgba(128, 128, 128, 0.12));
433
+ }
434
+
397
435
  /* Raw-HTML block source text; inline raw HTML keeps --md-raw-html-color above. */
398
436
  :where(.editor) .text-editable-block.raw-block {
399
437
  color: var(--syntax-comment, currentColor);
@@ -404,7 +442,7 @@
404
442
  }
405
443
 
406
444
  :where(.editor) .thematic-break-rule[role='separator'] > hr {
407
- border-top-color: var(--syntax-separator, var(--color-ui-muted, #a4a4a4));
445
+ border-top-color: var(--syntax-separator, var(--color-border, #3e3e3b));
408
446
  }
409
447
 
410
448
  /* The [contenteditable='false'] qualifier scopes to the structurally-injected ambient
@@ -417,12 +455,69 @@
417
455
  color: var(--syntax-task, currentColor);
418
456
  }
419
457
 
420
- /* Table grips reveal on table hover, in pure CSS with no per-grip reactive state. The grip's
421
- own <style> holds the at-rest state, so it never intercepts a caret click until then. */
422
- :where(.editor) [role='table']:hover [data-table-col-grip],
423
- :where(.editor) [role='table']:hover [data-table-row-grip] {
424
- opacity: 1;
425
- pointer-events: auto;
458
+ /* ── Menus ──────────────────────────────────────────────────────────────────
459
+ One surface for every menu the editor opens (the table's context menu, the code rail's
460
+ picker and overflow), copied from the host app's context menu value for value and reading
461
+ the same tokens, so a menu here is indistinguishable from one of the host's. */
462
+ :where(.editor) .md-menu {
463
+ position: fixed;
464
+ z-index: 2000;
465
+ min-width: 168px;
466
+ padding: 4px;
467
+ background: var(--color-bg, #2c2c2a);
468
+ border: 1px solid var(--color-border, #3e3e3b);
469
+ border-radius: 8px;
470
+ box-shadow: var(--menu-shadow, 0 12px 32px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.35));
471
+ font-family: var(--font-ui, system-ui, sans-serif);
472
+ font-size: 13px;
473
+ line-height: 1.4;
474
+ color: var(--color-text-primary, #e8e8e5);
475
+ user-select: none;
476
+ }
477
+
478
+ :where(.editor) .md-menu-item {
479
+ display: flex;
480
+ align-items: center;
481
+ gap: 9px;
482
+ width: 100%;
483
+ padding: 7px 10px;
484
+ border: none;
485
+ border-radius: 5px;
486
+ background: transparent;
487
+ color: inherit;
488
+ font: inherit;
489
+ text-align: left;
490
+ cursor: pointer;
491
+ }
492
+
493
+ :where(.editor) .md-menu-item:hover,
494
+ :where(.editor) .md-menu-item:focus-visible,
495
+ :where(.editor) .md-menu-item[aria-pressed='true'],
496
+ :where(.editor) .md-menu-item[data-active='true'] {
497
+ background: var(--menu-item-hover, rgba(255, 255, 255, 0.07));
498
+ outline: none;
499
+ }
500
+
501
+ :where(.editor) .md-menu-item:disabled {
502
+ opacity: 0.4;
503
+ cursor: default;
504
+ }
505
+
506
+ :where(.editor) .md-menu-item:disabled:hover {
507
+ background: transparent;
508
+ }
509
+
510
+ :where(.editor) .md-menu-icon {
511
+ display: inline-flex;
512
+ align-items: center;
513
+ flex-shrink: 0;
514
+ color: var(--color-ui-muted, #8f8f89);
515
+ }
516
+
517
+ :where(.editor) .md-menu-divider {
518
+ height: 1px;
519
+ margin: 4px 6px;
520
+ background: var(--color-border, #3e3e3b);
426
521
  }
427
522
 
428
523
  /* ── Rendered chrome, shared by every marker-hiding mode ──────────────────────
@@ -450,17 +545,33 @@
450
545
  }
451
546
 
452
547
  /* Chrome with nothing behind it has nowhere to hide: a construct whose only bytes are its own
453
- markers would paint as an empty line with no caret position, so an editable rung shows them
454
- dimmed exactly as source does. Mirrored in `cursor/widget-offset.ts` (same two modes, same
455
- two families); reading takes no keystrokes and keeps its silence. The `[contenteditable]`
456
- qualifier scopes the stamp to the walk containers its JS twin reads, which is what a block
457
- decoration spelling `data-content-empty` onto the block host cannot reach. */
548
+ markers has no caret position, so an editable rung shows them dimmed as source does — but
549
+ only while the surface holds focus, since the seat is for a caret and a block nobody is in
550
+ reads as the empty construct it is. Mirrored in `cursor/widget-offset.ts` (same modes, same
551
+ families); reading keeps its silence. `[contenteditable]` scopes the stamp to the walk
552
+ containers its JS twin reads, which a decoration on the block host cannot reach. */
458
553
  :where(.editor):is([data-presentation^='preview-'], [data-presentation='live'])
459
- [contenteditable][data-content-empty]
554
+ [contenteditable][data-content-empty]:focus-within
460
555
  :is(.md-marker:not([contenteditable='false']), .md-fence-line) {
461
556
  display: inline;
462
557
  }
463
558
 
559
+ /* A code block or table is a box, and prose gives it nothing to stand off from: blocks stack flush,
560
+ with only a text line's own leading between them. The box brings its own breathing room —
561
+ about a text line's leading each side, so code-to-code and code-to-prose match. Padding,
562
+ not margin: the height model measures the host's border box. */
563
+ :where(.editor) .block-host:is([data-block-kind='fencedCode'], [data-block-kind='table']) {
564
+ padding-block: 6px;
565
+ }
566
+
567
+ /* Room for the add strips (`TableBlock.svelte`) INSIDE the host's box: on the right so a
568
+ full-width table still leaves the column strip inside the editor's scroll box, and below so
569
+ the row strip never lies over whatever follows the table (the trailing insert row, a block). */
570
+ :where(.editor) .block-host[data-block-kind='table'] {
571
+ padding-right: 30px;
572
+ padding-bottom: 24px;
573
+ }
574
+
464
575
  /* Ambient list markers own the hanging indent (padding/text-indent are keyed to the span's
465
576
  ch width), so they keep their box: visibility, not display. */
466
577
  :where(.editor):is(
@@ -498,7 +609,21 @@
498
609
  visibility: visible;
499
610
  }
500
611
 
501
- /* GitHub task lists carry no bullet, so the `- ` prefix hides and the checkbox stays. */
612
+ /* GitHub task lists: no bullet, the box at the margin, the text one gap after it. The `- `
613
+ marker collapses to nothing (its bytes stay for the walk), the `[ ]` span becomes a fixed
614
+ slot so checked and unchecked are the same width, and the box paints in that slot. */
615
+ :where(.editor):is(
616
+ [data-presentation='reading'],
617
+ [data-presentation^='preview-'],
618
+ [data-presentation='live']
619
+ )
620
+ .list-item-block[data-list-marker='task']
621
+ .task-list-marker {
622
+ display: inline-block;
623
+ width: 0;
624
+ overflow: hidden;
625
+ }
626
+
502
627
  :where(.editor):is(
503
628
  [data-presentation='reading'],
504
629
  [data-presentation^='preview-'],
@@ -506,7 +631,72 @@
506
631
  )
507
632
  .list-item-block[data-list-marker='task']
508
633
  .task-checkbox {
634
+ /* Visible inside the hidden ambient marker, its `[ ]` bytes gone by colour: a hidden span
635
+ leaves the accessibility tree and the hit-test, and the pseudo-elements draw the box. */
509
636
  visibility: visible;
637
+ color: transparent;
638
+ position: relative;
639
+ display: inline-block;
640
+ /* Slot + gap; `TASK_HANGING_INDENT` in task-checkbox.ts is these plus the trailing space. */
641
+ width: 1.2em;
642
+ margin-right: 0.65em;
643
+ vertical-align: baseline;
644
+ }
645
+
646
+ :where(.editor):is(
647
+ [data-presentation='reading'],
648
+ [data-presentation^='preview-'],
649
+ [data-presentation='live']
650
+ )
651
+ .list-item-block[data-list-marker='task']
652
+ .task-checkbox::before {
653
+ content: '';
654
+ visibility: visible;
655
+ position: absolute;
656
+ left: 50%;
657
+ top: 50%;
658
+ width: 1.2em;
659
+ height: 1.2em;
660
+ transform: translate(-50%, -50%);
661
+ box-sizing: border-box;
662
+ border: 1.5px solid var(--color-ui-muted, #8f8f89);
663
+ border-radius: 0.28em;
664
+ background: transparent;
665
+ }
666
+
667
+ /* Checked: the box fills with the text colour and the tick is cut from it in the page's
668
+ background — two borders of a rotated box, so it needs no glyph and scales with the type. */
669
+ :where(.editor):is(
670
+ [data-presentation='reading'],
671
+ [data-presentation^='preview-'],
672
+ [data-presentation='live']
673
+ )
674
+ .list-item-block[data-task-checked='true']
675
+ .task-checkbox::before {
676
+ background: var(--color-text-primary, currentColor);
677
+ border-color: var(--color-text-primary, currentColor);
678
+ }
679
+
680
+ :where(.editor):is(
681
+ [data-presentation='reading'],
682
+ [data-presentation^='preview-'],
683
+ [data-presentation='live']
684
+ )
685
+ .list-item-block[data-task-checked='true']
686
+ .task-checkbox::after {
687
+ content: '';
688
+ visibility: visible;
689
+ position: absolute;
690
+ /* The slot's centre, nudged up and right: the visible strokes are the L's right and
691
+ bottom edges, which rotation swings down and left. */
692
+ left: 53%;
693
+ top: 45%;
694
+ width: 0.32em;
695
+ height: 0.6em;
696
+ box-sizing: border-box;
697
+ border: solid var(--color-bg, #2c2c2a);
698
+ border-width: 0 0.15em 0.15em 0;
699
+ transform: translate(-50%, -50%) rotate(45deg);
510
700
  }
511
701
 
512
702
  /* ── Reading mode ─────────────────────────────────────────────────────────────
@@ -550,6 +740,15 @@
550
740
  display: inline;
551
741
  }
552
742
 
743
+ /* The body's caret anchor stands in for the closer line while that line hides (see
744
+ `code-renderer.ts`); wherever the closer paints it would add a blank line instead. */
745
+ :where(.editor):not([data-presentation]) br[data-caret-anchor='closer'],
746
+ :where(.editor)[data-presentation^='preview-']
747
+ .block-host[data-focused]
748
+ br[data-caret-anchor='closer'] {
749
+ display: none;
750
+ }
751
+
553
752
  /* Reference labels reveal on the focused block under preview-block. */
554
753
  :where(.editor)[data-presentation='preview-block'] .block-host[data-focused] .md-ref-label {
555
754
  display: inline;
@@ -19,7 +19,7 @@ import { isBlockOpenerRegistered } from '../schema/block-openers';
19
19
  import { getBlockKindDescriptor } from '../schema/block-kind-descriptor';
20
20
  import { rebuildContainerRawIfContainer } from '../schema/container-raw';
21
21
  import { createSharingState } from '../tree-operations/sharing';
22
- import { rebuildUnsharedAncestry } from '../tree-operations/unshare';
22
+ import { rebuildUnsharedAncestry } from '../tree-operations/chain-rebuild';
23
23
  import { assertParseConverged } from './parse-convergence';
24
24
  import { createHeadlessActions, mountBlockListState, recordingFocus, stubBlockEdit, stubStickyColumn } from './headless-actions';
25
25
  import { assert, assertExemptionDocumented, assertIndices, assertIs, assertRebuildIsParseCanonical, assertReasonDocumented, fail, findFirstOfKind, firstChildOfKind, nodeAtPath, pathPassesThroughKind } from './conformance-core';
@@ -487,7 +487,7 @@ function assertContentStartSpaceIsRebuilt(kind, descriptor) {
487
487
  /**
488
488
  * `container.bodyWrap` is probed, never trusted: the separator settle reads it to decide whether
489
489
  * a freed blank line belongs to the wrap, and a kind whose parse disagrees loses its body head
490
- * on reload (`tree-operations/node-ops.clearRedundantSeparator`).
490
+ * on reload (`tree-operations/settle.clearRedundantSeparator`).
491
491
  */
492
492
  function assertBodyWrapMatchesParse(kind, descriptor) {
493
493
  if (descriptor.containerContract === 'grid')
@@ -379,7 +379,8 @@ function assertRewriteReproducesSource(fixture, node, rung) {
379
379
  ...(node.title !== undefined ? { title: node.title } : {}),
380
380
  ...(node.label !== undefined ? { label: node.label } : {}),
381
381
  ...(node.width !== undefined ? { width: node.width } : {}),
382
- ...(node.height !== undefined ? { height: node.height } : {})
382
+ ...(node.height !== undefined ? { height: node.height } : {}),
383
+ ...(node.crop !== undefined ? { crop: node.crop } : {})
383
384
  };
384
385
  assertIs(rung.rewriteImage(source, fields), source, `rewriteImage re-emits ${JSON.stringify(source)} from the fields the scan read out of it`);
385
386
  }
@@ -2,7 +2,7 @@ import { cloneMetadata, cloneNode } from './clone';
2
2
  import { rebuildBlockquoteRaw } from '../schema/container-rebuilders';
3
3
  import { rebuildContainerRaw } from '../schema/container-raw';
4
4
  import { assignIds } from '../block-id';
5
- import { emptyParagraph } from './node-ops';
5
+ import { emptyParagraph } from './node-primitives';
6
6
  import { trailingLineEnding } from '../core/lines';
7
7
  /**
8
8
  * Unwrap a quote-shaped container's first child (Rule U2), returning fresh clones without
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The ancestry rebuild: raws re-derived along an owned spine chain innermost-first, each
3
+ * container's kind re-derived and the seam at its own slot asked on the way out (editor.md § 9).
4
+ */
5
+ import type { CstNode } from '../core/nodes';
6
+ import type { SharingState } from './sharing';
7
+ import type { NodeParent } from './node-primitives';
8
+ import type { StructuralChange } from './structural-change';
9
+ import type { GrammarView } from '../schema/block-openers';
10
+ import { type TrackedPosition } from './settle';
11
+ /**
12
+ * Longest prefix of `chain` still attached under `root`, identity-checked level by level. A
13
+ * commit mutation can splice a node out mid-ceremony, and rebuilding the detached node's raw
14
+ * against its emptied children writes `raw: ''`; ancestors above the detachment still rebuild.
15
+ */
16
+ export declare function attachedChainPrefix(root: NodeParent, chain: CstNode[]): CstNode[];
17
+ /**
18
+ * One container slot a rebuild re-kinded. `previous` is the rollback register: a commit
19
+ * unwinding after the swap has already published `replacement` into a live children array.
20
+ */
21
+ export interface ContainerReclassification {
22
+ siblings: CstNode[];
23
+ index: number;
24
+ previous: CstNode;
25
+ replacement: CstNode;
26
+ }
27
+ /**
28
+ * A fold the rebuilt container's own slot owed: its bytes stopped interrupting a neighbour, so
29
+ * the parent's array reloads as fewer blocks. `before` is the pre-splice array, the rollback
30
+ * register, since the splice lands in an array no commit descriptor covers.
31
+ */
32
+ export interface AncestrySeamFold {
33
+ /** Chain level of the folded container, so a caller composes the owner's path from its own. */
34
+ depth: number;
35
+ siblings: CstNode[];
36
+ /** The chain node owning `siblings`, or null when they are the rebuild root's children. */
37
+ owner: CstNode | null;
38
+ change: StructuralChange;
39
+ before: CstNode[];
40
+ landing: TrackedPosition;
41
+ }
42
+ /**
43
+ * What the typing door knows and a bare chain does not: where the chain sits in the document,
44
+ * and the bytes its leaf carried before the write. Both are guesses the rebuild identity-checks.
45
+ */
46
+ export interface ChainWriteHint {
47
+ path: number[];
48
+ leafPreviousRaw: string;
49
+ }
50
+ /**
51
+ * Rebuild raws along an owned spine chain innermost-first, re-deriving each container's kind and
52
+ * settling the seams at its own slot; chain- rather than path-based so it survives index shifts.
53
+ * Both passes gate on a boundary line of the rebuilt raw moving. `folds` is required-nullable: a
54
+ * fold splices the PARENT's array, so only a caller that reconciles that scope's ids/refs passes
55
+ * a sink.
56
+ */
57
+ export declare function rebuildUnsharedChain(root: NodeParent | CstNode, chain: CstNode[], sharing: SharingState, folds: AncestrySeamFold[] | null, grammar: GrammarView | undefined, hint?: ChainWriteHint): ContainerReclassification[];
58
+ /**
59
+ * Unshare the spine to `path` and rebuild it innermost-first, tolerating paths that ran out of
60
+ * range mid-walk (post-delete rebuild passes). Prefer `rebuildUnsharedChain` when indices may
61
+ * have shifted since the unshare.
62
+ */
63
+ export declare function rebuildUnsharedAncestry(root: NodeParent, path: number[], sharing: SharingState, folds: AncestrySeamFold[] | null, grammar: GrammarView | undefined): ContainerReclassification[];
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The ancestry rebuild: raws re-derived along an owned spine chain innermost-first, each
3
+ * container's kind re-derived and the seam at its own slot asked on the way out (editor.md § 9).
4
+ */
5
+ import { dropChildSpans } from '../schema/child-spans';
6
+ import { trimTrailingLineEnding } from '../core/lines';
7
+ import { perfEnabled, recordRebuildDepth } from '../perf/instruments';
8
+ import { rebuildOwnedContainer, walkUnsharing } from './unshare';
9
+ import { absorbWindowSeams } from './settle';
10
+ import { lineOpensAs, reclassifyContainer } from './content-write';
11
+ import { settleSublistSeparator } from './list/sublist-separator';
12
+ /**
13
+ * Longest prefix of `chain` still attached under `root`, identity-checked level by level. A
14
+ * commit mutation can splice a node out mid-ceremony, and rebuilding the detached node's raw
15
+ * against its emptied children writes `raw: ''`; ancestors above the detachment still rebuild.
16
+ */
17
+ export function attachedChainPrefix(root, chain) {
18
+ let parentChildren = root.children;
19
+ for (let i = 0; i < chain.length; i++) {
20
+ if (!parentChildren.includes(chain[i]))
21
+ return chain.slice(0, i);
22
+ parentChildren = chain[i].children ?? [];
23
+ }
24
+ return chain;
25
+ }
26
+ /**
27
+ * Rebuild raws along an owned spine chain innermost-first, re-deriving each container's kind and
28
+ * settling the seams at its own slot; chain- rather than path-based so it survives index shifts.
29
+ * Both passes gate on a boundary line of the rebuilt raw moving. `folds` is required-nullable: a
30
+ * fold splices the PARENT's array, so only a caller that reconciles that scope's ids/refs passes
31
+ * a sink.
32
+ */
33
+ export function rebuildUnsharedChain(root, chain, sharing, folds, grammar, hint) {
34
+ const reclassified = [];
35
+ // The bytes chain[i + 1] held before this pass. It rides up only from a door that named the
36
+ // leaf's own: a caller passing no hint re-derives at every level (editor.md § 9).
37
+ let childPreviousRaw;
38
+ for (let i = chain.length - 1; i >= 0; i--) {
39
+ const node = chain[i];
40
+ const rawBefore = node.raw;
41
+ const child = chain[i + 1];
42
+ rebuildOwnedContainer(node, sharing, child && childPreviousRaw !== undefined
43
+ ? childRawChange(node, child, childPreviousRaw, hint?.path[i + 1])
44
+ : undefined);
45
+ if (hint)
46
+ childPreviousRaw = i === chain.length - 1 ? hint.leafPreviousRaw : rawBefore;
47
+ const openerMoved = firstLine(rawBefore) !== firstLine(node.raw);
48
+ const closerMoved = lastLine(rawBefore) !== lastLine(node.raw);
49
+ if (!openerMoved && !closerMoved)
50
+ continue;
51
+ const owner = i === 0 ? null : chain[i - 1];
52
+ const siblings = (owner ?? root).children;
53
+ const index = siblings ? childIndexOf(siblings, node, hint?.path[i]) : -1;
54
+ if (!siblings || index < 0)
55
+ continue;
56
+ if (openerMoved && lineOpensAs(firstLine(node.raw), grammar) !== node.kind) {
57
+ const replacement = reclassifyContainer({ children: siblings }, index, grammar);
58
+ if (replacement) {
59
+ sharing.stamp(replacement);
60
+ reclassified.push({ siblings, index, previous: node, replacement });
61
+ }
62
+ }
63
+ // Ahead of the seam ask, which then reads the settled bytes: a list rebuilt down to an
64
+ // empty marker owes the paragraph above it a separating line.
65
+ if (openerMoved)
66
+ settleSublistSeparator(siblings, index);
67
+ // After the re-derive: the seam reads whatever occupies the slot now.
68
+ if (folds) {
69
+ const before = folds.length;
70
+ settleSlotSeams({ siblings, owner, depth: i, index, openerMoved, closerMoved }, sharing, folds);
71
+ // A fold re-tiled the owner's children, so its spans describe a shape that is gone.
72
+ if (folds.length > before && owner)
73
+ dropChildSpans(owner);
74
+ }
75
+ }
76
+ if (perfEnabled())
77
+ recordRebuildDepth(chain.length);
78
+ return reclassified;
79
+ }
80
+ /**
81
+ * The changed-child hint for `node`, or undefined when `child` cannot be placed in it. The path
82
+ * index is a guess; an identity match is what makes it an answer.
83
+ */
84
+ function childRawChange(node, child, previousRaw, guess) {
85
+ const siblings = node.children;
86
+ if (!siblings)
87
+ return undefined;
88
+ const index = childIndexOf(siblings, child, guess);
89
+ return index < 0 ? undefined : { index, previousRaw };
90
+ }
91
+ /** `indexOf` with a guess first: the scan is O(children) through the `$state` proxy. */
92
+ function childIndexOf(siblings, child, guess) {
93
+ if (guess !== undefined && siblings[guess] === child)
94
+ return guess;
95
+ return siblings.indexOf(child);
96
+ }
97
+ /**
98
+ * Ask the joins at a rebuilt container's slot, since its new bytes can stop interrupting a
99
+ * neighbour. `absorbWindowSeams` walks `at - 1 … at + added - 1`, so the two arguments below
100
+ * name exactly the sides whose line moved.
101
+ */
102
+ function settleSlotSeams(slot, sharing, folds) {
103
+ const { siblings, index, openerMoved, closerMoved } = slot;
104
+ // The rollback snapshot is captured only once a fold is certain: an eager copy here cost
105
+ // O(children) reactive reads on every keystroke inside a large container.
106
+ let before = null;
107
+ const landing = { index, offset: 0 };
108
+ const settled = absorbWindowSeams({ children: siblings }, openerMoved ? index : index + 1, openerMoved && closerMoved ? 1 : 0, index, { op: 'noop' }, sharing, landing, index, () => {
109
+ before ??= siblings.slice();
110
+ });
111
+ if (settled.change.op === 'noop')
112
+ return;
113
+ folds.push({
114
+ depth: slot.depth,
115
+ siblings,
116
+ owner: slot.owner,
117
+ change: settled.change,
118
+ // A non-noop change means a splice ran, so the capture ran first.
119
+ before: before,
120
+ landing
121
+ });
122
+ }
123
+ /** The container's opener line. */
124
+ function firstLine(raw) {
125
+ const nl = raw.indexOf('\n');
126
+ return nl < 0 ? raw : raw.slice(0, nl);
127
+ }
128
+ /** The container's closing line: its last line carrying bytes, without the ending. */
129
+ function lastLine(raw) {
130
+ const body = trimTrailingLineEnding(raw);
131
+ const nl = body.lastIndexOf('\n');
132
+ return nl < 0 ? body : body.slice(nl + 1);
133
+ }
134
+ /**
135
+ * Unshare the spine to `path` and rebuild it innermost-first, tolerating paths that ran out of
136
+ * range mid-walk (post-delete rebuild passes). Prefer `rebuildUnsharedChain` when indices may
137
+ * have shifted since the unshare.
138
+ */
139
+ export function rebuildUnsharedAncestry(root, path, sharing, folds, grammar) {
140
+ const chain = walkUnsharing(root, path, sharing, false);
141
+ return rebuildUnsharedChain(root, chain, sharing, folds, grammar);
142
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Container children mutations that keep `childIds` in lockstep, for out-of-commit-scope
3
- * writes (discovered descendants/ancestors — see the `node-ops.ts` header). Inside a
3
+ * writes (discovered descendants/ancestors — see the `node-primitives.ts` header). Inside a
4
4
  * commit scope the StructuralChange descriptor owns id/ref sync; here a hand-rolled
5
5
  * splice would let the parallel id array drift and break Svelte's keyed-each rendering.
6
6
  * The same shape change invalidates `childSpans`, so both parallel arrays settle here.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Container children mutations that keep `childIds` in lockstep, for out-of-commit-scope
3
- * writes (discovered descendants/ancestors — see the `node-ops.ts` header). Inside a
3
+ * writes (discovered descendants/ancestors — see the `node-primitives.ts` header). Inside a
4
4
  * commit scope the StructuralChange descriptor owns id/ref sync; here a hand-rolled
5
5
  * splice would let the parallel id array drift and break Svelte's keyed-each rendering.
6
6
  * The same shape change invalidates `childSpans`, so both parallel arrays settle here.
@@ -1,4 +1,4 @@
1
- import { spliceChildrenSettled } from './node-ops';
1
+ import { spliceChildrenSettled } from './settle';
2
2
  import { ensureUnsharedPath } from './unshare';
3
3
  /**
4
4
  * Walk up from `deletedPath`'s parent, removing containers emptied by the cleanup. Stops
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The content write: every byte that enters a node crosses `updateNodeContent`, the sole
3
+ * re-parse transfer funnel (editor.md § 6, § 8), and the container twin that re-derives a
4
+ * container's kind from its rebuilt raw.
5
+ */
6
+ import type { AnyBlockKind, CstNode } from '../core/nodes';
7
+ import type { NodeView } from '../core/node-views';
8
+ import { type GrammarView } from '../schema/block-openers';
9
+ import type { SharingState } from './sharing';
10
+ import { type StructuralChange } from './structural-change';
11
+ import { type BodyParentArg, type NodeParent } from './node-primitives';
12
+ /** What a content write settled: its change widened by every fold, and the offset the written
13
+ * text starts at inside that change's window (nonzero once a fold above absorbed it). */
14
+ export interface SettledContent {
15
+ change: StructuralChange;
16
+ textStart: number;
17
+ }
18
+ /**
19
+ * Update raw and re-parse. A kind change mints the reparsed block into the slot rather than
20
+ * reassigning `kind` in place, and multi-block text mints every parsed block; only a same-kind
21
+ * single-block edit writes in place, so routine typing keeps the node's object identity.
22
+ */
23
+ export declare function updateNodeContent(parent: BodyParentArg, blockIndex: number, text: string, grammar?: GrammarView, sharing?: SharingState): SettledContent;
24
+ /**
25
+ * Refresh a node in place from its own reparse, keeping its object identity. The id resync is
26
+ * unconditional: the reparse can change the child count while the caller reports `noop`.
27
+ */
28
+ export declare function adoptReparsedFields(target: CstNode, parsed: CstNode | undefined): void;
29
+ /**
30
+ * What the grammar opens `line` as, read in isolation: asked of the opener registry and never
31
+ * a kind list, so a kind registered later is covered the day it registers.
32
+ */
33
+ export declare function lineOpensAs(line: string, grammar?: GrammarView): AnyBlockKind;
34
+ /** Whether the ambient grammar still leaves `NEXT_PROSE_LINE` an ordinary paragraph. */
35
+ export declare function probeLineOpensAsProse(grammar?: GrammarView): boolean;
36
+ /**
37
+ * Re-derive the container at `index` from its own (already rebuilt) raw, replacing it in the
38
+ * slot when that raw now opens as a different kind (editor.md § 8). Eligibility is the opener
39
+ * registry: registering an opener is exactly the claim that `parse(raw)` reproduces the kind.
40
+ */
41
+ export declare function reclassifyContainer(parent: NodeParent, index: number, grammar?: GrammarView): CstNode | null;
42
+ /**
43
+ * Where a caret at `offset` in the written text lands once {@link updateNodeContent}'s folds
44
+ * settled: an absorb ABOVE leaves the predecessor holding the bytes, so the slot the gesture
45
+ * named is gone and the offset carries what that predecessor put in front of it.
46
+ */
47
+ export declare function settledCaretTarget(settled: SettledContent, at: number, offset: number, children: readonly NodeView[]): {
48
+ index: number;
49
+ offset: number;
50
+ };