@notectl/core 2.2.6 → 2.3.1
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.
- package/dist/chunks/{AlignmentPlugin-DeD4C4EP.mjs → AlignmentPlugin--xAFlRqE.mjs} +2 -2
- package/dist/chunks/{AlignmentPlugin-DeD4C4EP.mjs.map → AlignmentPlugin--xAFlRqE.mjs.map} +1 -1
- package/dist/chunks/{AttrRegistry-DcDVyzLm.mjs → AttrRegistry-B3zB02z9.mjs} +2 -2
- package/dist/chunks/AttrRegistry-B3zB02z9.mjs.map +1 -0
- package/dist/chunks/{AttributedMarkCommands-D4W2Jgpj.mjs → AttributedMarkCommands-bagbH8Qt.mjs} +2 -2
- package/dist/chunks/{AttributedMarkCommands-D4W2Jgpj.mjs.map → AttributedMarkCommands-bagbH8Qt.mjs.map} +1 -1
- package/dist/chunks/{BidiIsolationPlugin-BddRbDCN.mjs → BidiIsolationPlugin-DBXyXpgm.mjs} +2 -2
- package/dist/chunks/{BidiIsolationPlugin-BddRbDCN.mjs.map → BidiIsolationPlugin-DBXyXpgm.mjs.map} +1 -1
- package/dist/chunks/BlockInsertion-CJusvrDL.mjs +2 -0
- package/dist/chunks/BlockInsertion-CJusvrDL.mjs.map +1 -0
- package/dist/chunks/BlockquotePlugin-Bz2glHwX.mjs +2 -0
- package/dist/chunks/{BlockquotePlugin-4V7KV_Sb.mjs.map → BlockquotePlugin-Bz2glHwX.mjs.map} +1 -1
- package/dist/chunks/{CaretNavigationPlugin-C6XBwp0N.mjs → CaretNavigationPlugin-CNsT0eb4.mjs} +2 -2
- package/dist/chunks/{CaretNavigationPlugin-C6XBwp0N.mjs.map → CaretNavigationPlugin-CNsT0eb4.mjs.map} +1 -1
- package/dist/chunks/CodeBlockPlugin-C1hrdbSZ.mjs +2 -0
- package/dist/chunks/CodeBlockPlugin-C1hrdbSZ.mjs.map +1 -0
- package/dist/chunks/{ColorGrid-DPNiXxpD.mjs → ColorGrid-C9RQoEWF.mjs} +2 -2
- package/dist/chunks/{ColorGrid-DPNiXxpD.mjs.map → ColorGrid-C9RQoEWF.mjs.map} +1 -1
- package/dist/chunks/ColorPickerPopup-DiA68Pzz.mjs +2 -0
- package/dist/chunks/{ColorPickerPopup-lcf3jS6G.mjs.map → ColorPickerPopup-DiA68Pzz.mjs.map} +1 -1
- package/dist/chunks/Commands-1dFFldi7.mjs +2 -0
- package/dist/chunks/Commands-1dFFldi7.mjs.map +1 -0
- package/dist/chunks/ContentModel-NpAj7vGW.mjs +2 -0
- package/dist/chunks/ContentModel-NpAj7vGW.mjs.map +1 -0
- package/dist/chunks/Decoration-BpoEOANl.mjs +2 -0
- package/dist/chunks/Decoration-BpoEOANl.mjs.map +1 -0
- package/dist/chunks/{DirectionDetection-C7XE0nxW.mjs → DirectionDetection-CDVSEWQ6.mjs} +2 -2
- package/dist/chunks/{DirectionDetection-C7XE0nxW.mjs.map → DirectionDetection-CDVSEWQ6.mjs.map} +1 -1
- package/dist/chunks/Document-827l3P80.mjs +2 -0
- package/dist/chunks/Document-827l3P80.mjs.map +1 -0
- package/dist/chunks/DocumentParser-D2tr3ZKn.mjs +2 -0
- package/dist/chunks/DocumentParser-D2tr3ZKn.mjs.map +1 -0
- package/dist/chunks/EditorEventBoundary-zpYRxryo.mjs +2 -0
- package/dist/chunks/EditorEventBoundary-zpYRxryo.mjs.map +1 -0
- package/dist/chunks/{FontPlugin-DQMj65Bc.mjs → FontPlugin-By-TGrQo.mjs} +2 -2
- package/dist/chunks/{FontPlugin-DQMj65Bc.mjs.map → FontPlugin-By-TGrQo.mjs.map} +1 -1
- package/dist/chunks/{FontSizePlugin-9StCjEfN.mjs → FontSizePlugin-Dln-tYXV.mjs} +2 -2
- package/dist/chunks/FontSizePlugin-Dln-tYXV.mjs.map +1 -0
- package/dist/chunks/FormulaPlugin-By1befrR.mjs +2 -0
- package/dist/chunks/FormulaPlugin-By1befrR.mjs.map +1 -0
- package/dist/chunks/GapCursorNavigation-BuXngVu-.mjs +2 -0
- package/dist/chunks/{GapCursorNavigation-ycNzuQVH.mjs.map → GapCursorNavigation-BuXngVu-.mjs.map} +1 -1
- package/dist/chunks/{GapCursorPlugin-Zvxjnr82.mjs → GapCursorPlugin-DAxVzXRs.mjs} +2 -2
- package/dist/chunks/{GapCursorPlugin-Zvxjnr82.mjs.map → GapCursorPlugin-DAxVzXRs.mjs.map} +1 -1
- package/dist/chunks/HTMLUtils-Bhg3_P8B.mjs +2 -0
- package/dist/chunks/HTMLUtils-Bhg3_P8B.mjs.map +1 -0
- package/dist/chunks/{HardBreakPlugin-9DOyCyyM.mjs → HardBreakPlugin-DlbSlrdq.mjs} +2 -2
- package/dist/chunks/{HardBreakPlugin-9DOyCyyM.mjs.map → HardBreakPlugin-DlbSlrdq.mjs.map} +1 -1
- package/dist/chunks/HeadingPlugin-uMAjPOk5.mjs +2 -0
- package/dist/chunks/{HeadingPlugin-BuGoM9Rz.mjs.map → HeadingPlugin-uMAjPOk5.mjs.map} +1 -1
- package/dist/chunks/{HighlightPlugin-C6pHifVz.mjs → HighlightPlugin-Bj7FPkIQ.mjs} +2 -2
- package/dist/chunks/{HighlightPlugin-C6pHifVz.mjs.map → HighlightPlugin-Bj7FPkIQ.mjs.map} +1 -1
- package/dist/chunks/HorizontalRulePlugin-DUVmTQpX.mjs +2 -0
- package/dist/chunks/HorizontalRulePlugin-DUVmTQpX.mjs.map +1 -0
- package/dist/chunks/ImagePlugin-FToCOjd5.mjs +2 -0
- package/dist/chunks/{ImagePlugin-KpkuE2LH.mjs.map → ImagePlugin-FToCOjd5.mjs.map} +1 -1
- package/dist/chunks/{InlineCodePlugin-DMr4O7c7.mjs → InlineCodePlugin-pISIoGQE.mjs} +2 -2
- package/dist/chunks/InlineCodePlugin-pISIoGQE.mjs.map +1 -0
- package/dist/chunks/InlineStyleMarkSpec-CjSRj4f_.mjs +2 -0
- package/dist/chunks/{InlineStyleMarkSpec-C6LJT7kp.mjs.map → InlineStyleMarkSpec-CjSRj4f_.mjs.map} +1 -1
- package/dist/chunks/LinkPlugin-Ct5Z180S.mjs +2 -0
- package/dist/chunks/LinkPlugin-Ct5Z180S.mjs.map +1 -0
- package/dist/chunks/ListPlugin-DAY5ezNs.mjs +2 -0
- package/dist/chunks/ListPlugin-DAY5ezNs.mjs.map +1 -0
- package/dist/chunks/MarkInputRule-Bdi8KPus.mjs +2 -0
- package/dist/chunks/MarkInputRule-Bdi8KPus.mjs.map +1 -0
- package/dist/chunks/MarkdownHTMLRegistry-CKEx7LkR.mjs +2 -0
- package/dist/chunks/MarkdownHTMLRegistry-CKEx7LkR.mjs.map +1 -0
- package/dist/chunks/MarkdownParser-CWt3M6jR.mjs +2 -0
- package/dist/chunks/MarkdownParser-CWt3M6jR.mjs.map +1 -0
- package/dist/chunks/MarkdownSerializer-J-i28out.mjs +2 -0
- package/dist/chunks/MarkdownSerializer-J-i28out.mjs.map +1 -0
- package/dist/chunks/{NodeResolver-ChgLF_IP.mjs → NodeResolver-Dleih-8R.mjs} +2 -2
- package/dist/chunks/{NodeResolver-ChgLF_IP.mjs.map → NodeResolver-Dleih-8R.mjs.map} +1 -1
- package/dist/chunks/NodeSelectionCommands-1PjwUDTJ.mjs +2 -0
- package/dist/chunks/{NodeSelectionCommands-Dj4VxLdD.mjs.map → NodeSelectionCommands-1PjwUDTJ.mjs.map} +1 -1
- package/dist/chunks/PluginHelpers-Dx_0hfDe.mjs +2 -0
- package/dist/chunks/{PluginHelpers-KDuTlmXm.mjs.map → PluginHelpers-Dx_0hfDe.mjs.map} +1 -1
- package/dist/chunks/{PopupManager-DUtaK3WX.mjs → PopupManager-CT-fMZJn.mjs} +2 -2
- package/dist/chunks/{PopupManager-DUtaK3WX.mjs.map → PopupManager-CT-fMZJn.mjs.map} +1 -1
- package/dist/chunks/PopupPositioning-BFh6Ed1D.mjs +2 -0
- package/dist/chunks/{PopupPositioning-BB97-__N.mjs.map → PopupPositioning-BFh6Ed1D.mjs.map} +1 -1
- package/dist/chunks/PrintPlugin-7zz9mhhU.mjs +2 -0
- package/dist/chunks/PrintPlugin-7zz9mhhU.mjs.map +1 -0
- package/dist/chunks/{RangeIterator-o8v3msQe.mjs → RangeIterator-DP7Ud3Gp.mjs} +2 -2
- package/dist/chunks/{RangeIterator-o8v3msQe.mjs.map → RangeIterator-DP7Ud3Gp.mjs.map} +1 -1
- package/dist/chunks/SchemaRegistry-CkBN-1yW.mjs +2 -0
- package/dist/chunks/SchemaRegistry-CkBN-1yW.mjs.map +1 -0
- package/dist/chunks/{SimpleMark-CaQtFAau.mjs → SimpleMark-7CQcA4RK.mjs} +2 -2
- package/dist/chunks/{SimpleMark-CaQtFAau.mjs.map → SimpleMark-7CQcA4RK.mjs.map} +1 -1
- package/dist/chunks/{SmartPastePlugin-Bi_wpTCV.mjs → SmartPastePlugin-CYa_nD9v.mjs} +2 -2
- package/dist/chunks/{SmartPastePlugin-Bi_wpTCV.mjs.map → SmartPastePlugin-CYa_nD9v.mjs.map} +1 -1
- package/dist/chunks/StrikethroughPlugin-C2oWvGc3.mjs +2 -0
- package/dist/chunks/StrikethroughPlugin-C2oWvGc3.mjs.map +1 -0
- package/dist/chunks/StyleRuntime-DW6omotc.mjs +2 -0
- package/dist/chunks/StyleRuntime-DW6omotc.mjs.map +1 -0
- package/dist/chunks/{SuperSubPlugin-DVP7VnIz.mjs → SuperSubPlugin-D1xaKrSu.mjs} +2 -2
- package/dist/chunks/{SuperSubPlugin-DVP7VnIz.mjs.map → SuperSubPlugin-D1xaKrSu.mjs.map} +1 -1
- package/dist/chunks/TableDimensions-BBhjHNjQ.mjs +2 -0
- package/dist/chunks/TableDimensions-BBhjHNjQ.mjs.map +1 -0
- package/dist/chunks/TablePlugin-PJe3zwr-.mjs +2 -0
- package/dist/chunks/TablePlugin-PJe3zwr-.mjs.map +1 -0
- package/dist/chunks/TextColorPlugin-CTd9tfeG.mjs +2 -0
- package/dist/chunks/{TextColorPlugin-CEfZQ6Md.mjs.map → TextColorPlugin-CTd9tfeG.mjs.map} +1 -1
- package/dist/chunks/TextDirectionAutoPlugin-CPnKVVuI.mjs +2 -0
- package/dist/chunks/{TextDirectionAutoPlugin-CzWJjrvG.mjs.map → TextDirectionAutoPlugin-CPnKVVuI.mjs.map} +1 -1
- package/dist/chunks/{TextDirectionPlugin-DHB88HKf.mjs → TextDirectionPlugin-Bns_03vL.mjs} +2 -2
- package/dist/chunks/{TextDirectionPlugin-DHB88HKf.mjs.map → TextDirectionPlugin-Bns_03vL.mjs.map} +1 -1
- package/dist/chunks/TextDirectionService-BcX07mw2.mjs +2 -0
- package/dist/chunks/{TextDirectionService-OFOU6r_s.mjs.map → TextDirectionService-BcX07mw2.mjs.map} +1 -1
- package/dist/chunks/TextFormattingPlugin-DBVlePqj.mjs +2 -0
- package/dist/chunks/TextFormattingPlugin-DBVlePqj.mjs.map +1 -0
- package/dist/chunks/{ToolbarPlugin-DVGrFf8v.mjs → ToolbarPlugin-DtfGTO_V.mjs} +2 -2
- package/dist/chunks/{ToolbarPlugin-DVGrFf8v.mjs.map → ToolbarPlugin-DtfGTO_V.mjs.map} +1 -1
- package/dist/chunks/VideoPlugin-BrR8g6Rz.mjs +2 -0
- package/dist/chunks/VideoPlugin-BrR8g6Rz.mjs.map +1 -0
- package/dist/chunks/WordBoundary-CFpIJDNP.mjs +2 -0
- package/dist/chunks/{WordBoundary-DxeMBRyP.mjs.map → WordBoundary-CFpIJDNP.mjs.map} +1 -1
- package/dist/chunks/ar-Dg9PdDet.mjs +2 -0
- package/dist/chunks/ar-Dg9PdDet.mjs.map +1 -0
- package/dist/chunks/ar-eOA3UmiE.mjs +2 -0
- package/dist/chunks/{ar-BTShmP2E.mjs.map → ar-eOA3UmiE.mjs.map} +1 -1
- package/dist/chunks/de-DJ5EkXQo.mjs +2 -0
- package/dist/chunks/de-DJ5EkXQo.mjs.map +1 -0
- package/dist/chunks/{de-C--bRmjW.mjs → de-DRbhnS4T.mjs} +2 -2
- package/dist/chunks/{de-C--bRmjW.mjs.map → de-DRbhnS4T.mjs.map} +1 -1
- package/dist/chunks/{es-DFUVd7eO.mjs → es-BQ9dox_E.mjs} +2 -2
- package/dist/chunks/{es-DFUVd7eO.mjs.map → es-BQ9dox_E.mjs.map} +1 -1
- package/dist/chunks/es-CEAJj7aB.mjs +2 -0
- package/dist/chunks/es-CEAJj7aB.mjs.map +1 -0
- package/dist/chunks/fr-DhWQzZy3.mjs +2 -0
- package/dist/chunks/fr-DhWQzZy3.mjs.map +1 -0
- package/dist/chunks/{fr-BaXKyPmX.mjs → fr-NVOinLyF.mjs} +2 -2
- package/dist/chunks/{fr-BaXKyPmX.mjs.map → fr-NVOinLyF.mjs.map} +1 -1
- package/dist/chunks/full-DSWM4cKQ.mjs +2 -0
- package/dist/chunks/{full-BBl7mvwH.mjs.map → full-DSWM4cKQ.mjs.map} +1 -1
- package/dist/chunks/hi-BsZzSMfL.mjs +2 -0
- package/dist/chunks/hi-BsZzSMfL.mjs.map +1 -0
- package/dist/chunks/{hi-aH9HZG23.mjs → hi-DrC2H81d.mjs} +2 -2
- package/dist/chunks/{hi-aH9HZG23.mjs.map → hi-DrC2H81d.mjs.map} +1 -1
- package/dist/chunks/minimal-CFkkPXef.mjs +2 -0
- package/dist/chunks/{minimal-CtnR4dqp.mjs.map → minimal-CFkkPXef.mjs.map} +1 -1
- package/dist/chunks/pt-BuZ7acHF.mjs +2 -0
- package/dist/chunks/pt-BuZ7acHF.mjs.map +1 -0
- package/dist/chunks/{pt-Hy-0Xnnc.mjs → pt-CFrcl1v_.mjs} +2 -2
- package/dist/chunks/{pt-Hy-0Xnnc.mjs.map → pt-CFrcl1v_.mjs.map} +1 -1
- package/dist/chunks/rolldown-runtime-H_PjY6_i.mjs +1 -0
- package/dist/chunks/ru-CsP6mLxp.mjs +2 -0
- package/dist/chunks/ru-CsP6mLxp.mjs.map +1 -0
- package/dist/chunks/{ru-BFpEOrVp.mjs → ru-gxbzqLL8.mjs} +2 -2
- package/dist/chunks/{ru-BFpEOrVp.mjs.map → ru-gxbzqLL8.mjs.map} +1 -1
- package/dist/chunks/src-DiAOfuOT.mjs +2 -0
- package/dist/chunks/src-DiAOfuOT.mjs.map +1 -0
- package/dist/chunks/zh-BFZOM3lF.mjs +2 -0
- package/dist/chunks/{zh-BjoyjClN.mjs.map → zh-BFZOM3lF.mjs.map} +1 -1
- package/dist/chunks/zh-CiIyOm6U.mjs +2 -0
- package/dist/chunks/zh-CiIyOm6U.mjs.map +1 -0
- package/dist/commands/BlockInsertion.d.ts +5 -3
- package/dist/commands/BlockInsertion.d.ts.map +1 -1
- package/dist/commands/SelectionDeletion.d.ts +13 -2
- package/dist/commands/SelectionDeletion.d.ts.map +1 -1
- package/dist/editor/ContentSerializer.d.ts +21 -0
- package/dist/editor/ContentSerializer.d.ts.map +1 -1
- package/dist/editor/EditorConfig.d.ts +17 -0
- package/dist/editor/EditorConfig.d.ts.map +1 -1
- package/dist/editor/EditorConfigController.d.ts +10 -0
- package/dist/editor/EditorConfigController.d.ts.map +1 -1
- package/dist/editor/EditorInitializer.d.ts +4 -0
- package/dist/editor/EditorInitializer.d.ts.map +1 -1
- package/dist/editor/EditorLocale.d.ts +2 -0
- package/dist/editor/EditorLocale.d.ts.map +1 -1
- package/dist/editor/MarkdownMode.d.ts +46 -0
- package/dist/editor/MarkdownMode.d.ts.map +1 -0
- package/dist/editor/NotectlEditor.d.ts +24 -0
- package/dist/editor/NotectlEditor.d.ts.map +1 -1
- package/dist/editor/locales/ar.d.ts.map +1 -1
- package/dist/editor/locales/de.d.ts.map +1 -1
- package/dist/editor/locales/es.d.ts.map +1 -1
- package/dist/editor/locales/fr.d.ts.map +1 -1
- package/dist/editor/locales/hi.d.ts.map +1 -1
- package/dist/editor/locales/pt.d.ts.map +1 -1
- package/dist/editor/locales/ru.d.ts.map +1 -1
- package/dist/editor/locales/zh.d.ts.map +1 -1
- package/dist/editor/styles/list.d.ts +1 -1
- package/dist/editor/styles/list.d.ts.map +1 -1
- package/dist/editor/styles/table.d.ts +1 -1
- package/dist/editor/styles/table.d.ts.map +1 -1
- package/dist/full.mjs +1 -1
- package/dist/html.d.ts +1 -0
- package/dist/html.d.ts.map +1 -1
- package/dist/html.mjs +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/input/ClipboardHandler.d.ts +2 -0
- package/dist/input/ClipboardHandler.d.ts.map +1 -1
- package/dist/input/InputHandler.d.ts +7 -0
- package/dist/input/InputHandler.d.ts.map +1 -1
- package/dist/input/InputManager.d.ts +10 -0
- package/dist/input/InputManager.d.ts.map +1 -1
- package/dist/input/KeyboardHandler.d.ts.map +1 -1
- package/dist/input/MarkdownPasteDetector.d.ts +26 -0
- package/dist/input/MarkdownPasteDetector.d.ts.map +1 -0
- package/dist/input/PasteHTMLHandler.d.ts +18 -1
- package/dist/input/PasteHTMLHandler.d.ts.map +1 -1
- package/dist/input/PasteHandler.d.ts +30 -0
- package/dist/input/PasteHandler.d.ts.map +1 -1
- package/dist/input/PasteRichBlockHandler.d.ts.map +1 -1
- package/dist/input/SelectionDocument.d.ts +2 -1
- package/dist/input/SelectionDocument.d.ts.map +1 -1
- package/dist/markdown.d.ts +17 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.mjs +1 -0
- package/dist/model/AttrRegistry.d.ts +2 -2
- package/dist/model/AttrRegistry.d.ts.map +1 -1
- package/dist/model/ContentModel.d.ts +12 -0
- package/dist/model/ContentModel.d.ts.map +1 -1
- package/dist/model/Document.d.ts +28 -3
- package/dist/model/Document.d.ts.map +1 -1
- package/dist/model/HTMLUtils.d.ts +15 -0
- package/dist/model/HTMLUtils.d.ts.map +1 -1
- package/dist/model/InlineNodeSpec.d.ts +7 -1
- package/dist/model/InlineNodeSpec.d.ts.map +1 -1
- package/dist/model/InputRule.d.ts +11 -0
- package/dist/model/InputRule.d.ts.map +1 -1
- package/dist/model/MarkSpec.d.ts +7 -1
- package/dist/model/MarkSpec.d.ts.map +1 -1
- package/dist/model/MarkdownSyntaxRegistry.d.ts +51 -0
- package/dist/model/MarkdownSyntaxRegistry.d.ts.map +1 -0
- package/dist/model/NodeSpec.d.ts +47 -1
- package/dist/model/NodeSpec.d.ts.map +1 -1
- package/dist/model/RichBlockData.d.ts +2 -0
- package/dist/model/RichBlockData.d.ts.map +1 -1
- package/dist/model/SchemaRegistry.d.ts.map +1 -1
- package/dist/model/TableDimensions.d.ts +11 -0
- package/dist/model/TableDimensions.d.ts.map +1 -0
- package/dist/notectl-core.mjs +1 -1
- package/dist/notectl-core.umd.js +1 -1
- package/dist/notectl-core.umd.js.map +1 -1
- package/dist/platform/EditorEventBoundary.d.ts +12 -0
- package/dist/platform/EditorEventBoundary.d.ts.map +1 -0
- package/dist/plugins/Plugin.d.ts +7 -0
- package/dist/plugins/Plugin.d.ts.map +1 -1
- package/dist/plugins/PluginContextFactory.d.ts +2 -0
- package/dist/plugins/PluginContextFactory.d.ts.map +1 -1
- package/dist/plugins/PluginManager.d.ts +2 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -1
- package/dist/plugins/alignment.mjs +1 -1
- package/dist/plugins/bidi-isolation.mjs +1 -1
- package/dist/plugins/blockquote/BlockquotePlugin.d.ts +2 -0
- package/dist/plugins/blockquote/BlockquotePlugin.d.ts.map +1 -1
- package/dist/plugins/blockquote.mjs +1 -1
- package/dist/plugins/caret-navigation.mjs +1 -1
- package/dist/plugins/code-block/CodeBlockTypes.d.ts +2 -0
- package/dist/plugins/code-block/CodeBlockTypes.d.ts.map +1 -1
- package/dist/plugins/code-block.mjs +1 -1
- package/dist/plugins/font-size/FontSizeOperations.d.ts.map +1 -1
- package/dist/plugins/font-size.mjs +1 -1
- package/dist/plugins/font.mjs +1 -1
- package/dist/plugins/formula/DisplayMathNodeSpec.d.ts.map +1 -1
- package/dist/plugins/formula/FormulaInputRules.d.ts.map +1 -1
- package/dist/plugins/formula/FormulaMarkdownSyntax.d.ts +4 -0
- package/dist/plugins/formula/FormulaMarkdownSyntax.d.ts.map +1 -0
- package/dist/plugins/formula/FormulaPlugin.d.ts.map +1 -1
- package/dist/plugins/formula/FormulaTypes.d.ts +2 -0
- package/dist/plugins/formula/FormulaTypes.d.ts.map +1 -1
- package/dist/plugins/formula/InlineMathNodeSpec.d.ts.map +1 -1
- package/dist/plugins/formula.mjs +1 -1
- package/dist/plugins/gap-cursor.mjs +1 -1
- package/dist/plugins/hard-break.mjs +1 -1
- package/dist/plugins/heading/HeadingPlugin.d.ts +2 -0
- package/dist/plugins/heading/HeadingPlugin.d.ts.map +1 -1
- package/dist/plugins/heading.mjs +1 -1
- package/dist/plugins/highlight.mjs +1 -1
- package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts +2 -0
- package/dist/plugins/horizontal-rule/HorizontalRulePlugin.d.ts.map +1 -1
- package/dist/plugins/horizontal-rule.mjs +1 -1
- package/dist/plugins/image/ImagePlugin.d.ts +14 -0
- package/dist/plugins/image/ImagePlugin.d.ts.map +1 -1
- package/dist/plugins/image.mjs +1 -1
- package/dist/plugins/inline-code/InlineCodePlugin.d.ts.map +1 -1
- package/dist/plugins/inline-code.mjs +1 -1
- package/dist/plugins/link/LinkPlugin.d.ts +14 -0
- package/dist/plugins/link/LinkPlugin.d.ts.map +1 -1
- package/dist/plugins/link.mjs +1 -1
- package/dist/plugins/list/ListCommands.d.ts +5 -1
- package/dist/plugins/list/ListCommands.d.ts.map +1 -1
- package/dist/plugins/list/ListInputRules.d.ts.map +1 -1
- package/dist/plugins/list/ListItemContext.d.ts +27 -0
- package/dist/plugins/list/ListItemContext.d.ts.map +1 -0
- package/dist/plugins/list/ListKeyboardHandlers.d.ts.map +1 -1
- package/dist/plugins/list/ListPlugin.d.ts +2 -0
- package/dist/plugins/list/ListPlugin.d.ts.map +1 -1
- package/dist/plugins/list/ListToolbarItems.d.ts.map +1 -1
- package/dist/plugins/list.mjs +1 -1
- package/dist/plugins/print/PrintContentPreparer.d.ts.map +1 -1
- package/dist/plugins/print/PrintDestinationBridge.d.ts +23 -0
- package/dist/plugins/print/PrintDestinationBridge.d.ts.map +1 -0
- package/dist/plugins/print/PrintHostStyles.d.ts.map +1 -1
- package/dist/plugins/print/PrintServiceImpl.d.ts +5 -1
- package/dist/plugins/print/PrintServiceImpl.d.ts.map +1 -1
- package/dist/plugins/print/PrintStyleCollector.d.ts.map +1 -1
- package/dist/plugins/print.mjs +1 -1
- package/dist/plugins/shared/MarkInputRule.d.ts +9 -0
- package/dist/plugins/shared/MarkInputRule.d.ts.map +1 -0
- package/dist/plugins/shared/PopupPositioning.d.ts +2 -0
- package/dist/plugins/shared/PopupPositioning.d.ts.map +1 -1
- package/dist/plugins/shared/index.d.ts +1 -0
- package/dist/plugins/shared/index.d.ts.map +1 -1
- package/dist/plugins/shared.mjs +1 -1
- package/dist/plugins/smart-paste.mjs +1 -1
- package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts +2 -0
- package/dist/plugins/strikethrough/StrikethroughPlugin.d.ts.map +1 -1
- package/dist/plugins/strikethrough.mjs +1 -1
- package/dist/plugins/super-sub.mjs +1 -1
- package/dist/plugins/table/TableClipboard.d.ts +8 -0
- package/dist/plugins/table/TableClipboard.d.ts.map +1 -0
- package/dist/plugins/table/TableCommands.d.ts.map +1 -1
- package/dist/plugins/table/TableContextMenu.d.ts +11 -1
- package/dist/plugins/table/TableContextMenu.d.ts.map +1 -1
- package/dist/plugins/table/TableControls.d.ts +6 -1
- package/dist/plugins/table/TableControls.d.ts.map +1 -1
- package/dist/plugins/table/TableControlsDOM.d.ts +11 -2
- package/dist/plugins/table/TableControlsDOM.d.ts.map +1 -1
- package/dist/plugins/table/TableControlsLayout.d.ts +12 -3
- package/dist/plugins/table/TableControlsLayout.d.ts.map +1 -1
- package/dist/plugins/table/TableGrid.d.ts +57 -0
- package/dist/plugins/table/TableGrid.d.ts.map +1 -0
- package/dist/plugins/table/TableHelpers.d.ts +4 -0
- package/dist/plugins/table/TableHelpers.d.ts.map +1 -1
- package/dist/plugins/table/TableLocale.d.ts +30 -0
- package/dist/plugins/table/TableLocale.d.ts.map +1 -1
- package/dist/plugins/table/TableNavigation.d.ts +5 -1
- package/dist/plugins/table/TableNavigation.d.ts.map +1 -1
- package/dist/plugins/table/TableNodeViews.d.ts +13 -1
- package/dist/plugins/table/TableNodeViews.d.ts.map +1 -1
- package/dist/plugins/table/TablePlugin.d.ts +21 -1
- package/dist/plugins/table/TablePlugin.d.ts.map +1 -1
- package/dist/plugins/table/TableSelection.d.ts.map +1 -1
- package/dist/plugins/table/TableSizeEditor.d.ts +11 -0
- package/dist/plugins/table/TableSizeEditor.d.ts.map +1 -0
- package/dist/plugins/table/TableSizing.d.ts +70 -0
- package/dist/plugins/table/TableSizing.d.ts.map +1 -0
- package/dist/plugins/table/index.d.ts +3 -1
- package/dist/plugins/table/index.d.ts.map +1 -1
- package/dist/plugins/table/locales/ar.d.ts.map +1 -1
- package/dist/plugins/table/locales/de.d.ts.map +1 -1
- package/dist/plugins/table/locales/es.d.ts.map +1 -1
- package/dist/plugins/table/locales/fr.d.ts.map +1 -1
- package/dist/plugins/table/locales/hi.d.ts.map +1 -1
- package/dist/plugins/table/locales/pt.d.ts.map +1 -1
- package/dist/plugins/table/locales/ru.d.ts.map +1 -1
- package/dist/plugins/table/locales/zh.d.ts.map +1 -1
- package/dist/plugins/table.mjs +1 -1
- package/dist/plugins/text-color.mjs +1 -1
- package/dist/plugins/text-direction-auto.mjs +1 -1
- package/dist/plugins/text-direction.mjs +1 -1
- package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts +9 -0
- package/dist/plugins/text-formatting/TextFormattingPlugin.d.ts.map +1 -1
- package/dist/plugins/text-formatting.mjs +1 -1
- package/dist/plugins/toolbar.mjs +1 -1
- package/dist/plugins/video/VideoCommands.d.ts.map +1 -1
- package/dist/plugins/video.mjs +1 -1
- package/dist/presets/full.mjs +1 -1
- package/dist/presets/minimal.mjs +1 -1
- package/dist/presets.mjs +1 -1
- package/dist/serialization/DocumentParser.d.ts.map +1 -1
- package/dist/serialization/DocumentSerializer.d.ts +2 -0
- package/dist/serialization/DocumentSerializer.d.ts.map +1 -1
- package/dist/serialization/HTMLSanitization.d.ts +15 -0
- package/dist/serialization/HTMLSanitization.d.ts.map +1 -0
- package/dist/serialization/MarkSerializer.d.ts +12 -0
- package/dist/serialization/MarkSerializer.d.ts.map +1 -1
- package/dist/serialization/MarkdownParser.d.ts +6 -0
- package/dist/serialization/MarkdownParser.d.ts.map +1 -0
- package/dist/serialization/MarkdownSerializer.d.ts +12 -0
- package/dist/serialization/MarkdownSerializer.d.ts.map +1 -0
- package/dist/serialization/MarkdownTypes.d.ts +59 -0
- package/dist/serialization/MarkdownTypes.d.ts.map +1 -0
- package/dist/serialization/TableDimensions.d.ts +37 -0
- package/dist/serialization/TableDimensions.d.ts.map +1 -0
- package/dist/serialization/markdown/BlockSerializers.d.ts +7 -0
- package/dist/serialization/markdown/BlockSerializers.d.ts.map +1 -0
- package/dist/serialization/markdown/BlockTokenizer.d.ts +54 -0
- package/dist/serialization/markdown/BlockTokenizer.d.ts.map +1 -0
- package/dist/serialization/markdown/GfmAutolink.d.ts +20 -0
- package/dist/serialization/markdown/GfmAutolink.d.ts.map +1 -0
- package/dist/serialization/markdown/GfmTableParser.d.ts +26 -0
- package/dist/serialization/markdown/GfmTableParser.d.ts.map +1 -0
- package/dist/serialization/markdown/InlineAst.d.ts +34 -0
- package/dist/serialization/markdown/InlineAst.d.ts.map +1 -0
- package/dist/serialization/markdown/InlineSerializers.d.ts +5 -0
- package/dist/serialization/markdown/InlineSerializers.d.ts.map +1 -0
- package/dist/serialization/markdown/InlineTokenizer.d.ts +5 -0
- package/dist/serialization/markdown/InlineTokenizer.d.ts.map +1 -0
- package/dist/serialization/markdown/LinkReferenceExtractor.d.ts +37 -0
- package/dist/serialization/markdown/LinkReferenceExtractor.d.ts.map +1 -0
- package/dist/serialization/markdown/MarkdownContext.d.ts +32 -0
- package/dist/serialization/markdown/MarkdownContext.d.ts.map +1 -0
- package/dist/serialization/markdown/MarkdownEntities.d.ts +33 -0
- package/dist/serialization/markdown/MarkdownEntities.d.ts.map +1 -0
- package/dist/serialization/markdown/MarkdownEscape.d.ts +33 -0
- package/dist/serialization/markdown/MarkdownEscape.d.ts.map +1 -0
- package/dist/serialization/markdown/MarkdownHTMLRegistry.d.ts +4 -0
- package/dist/serialization/markdown/MarkdownHTMLRegistry.d.ts.map +1 -0
- package/dist/serialization/markdown/MarkdownParseContext.d.ts +23 -0
- package/dist/serialization/markdown/MarkdownParseContext.d.ts.map +1 -0
- package/dist/state/Mapping.d.ts +33 -10
- package/dist/state/Mapping.d.ts.map +1 -1
- package/dist/state/StepApplication.d.ts +3 -1
- package/dist/state/StepApplication.d.ts.map +1 -1
- package/dist/state/StepHandlers.d.ts.map +1 -1
- package/dist/state/StepInversion.d.ts +2 -1
- package/dist/state/StepInversion.d.ts.map +1 -1
- package/dist/state/StepMapping.d.ts +3 -2
- package/dist/state/StepMapping.d.ts.map +1 -1
- package/dist/state/StepMaps.d.ts +3 -2
- package/dist/state/StepMaps.d.ts.map +1 -1
- package/dist/state/Steps.d.ts +34 -2
- package/dist/state/Steps.d.ts.map +1 -1
- package/dist/state/TransactionBuilder.d.ts +7 -1
- package/dist/state/TransactionBuilder.d.ts.map +1 -1
- package/dist/test/MarkdownConformanceUtils.d.ts +12 -0
- package/dist/test/MarkdownConformanceUtils.d.ts.map +1 -0
- package/dist/view/BlockRendering.d.ts +5 -0
- package/dist/view/BlockRendering.d.ts.map +1 -1
- package/dist/view/DecorationRendering.d.ts +6 -0
- package/dist/view/DecorationRendering.d.ts.map +1 -1
- package/dist/view/EditorViewEvents.d.ts.map +1 -1
- package/dist/view/Reconciler.d.ts.map +1 -1
- package/package.json +14 -1
- package/dist/chunks/AttrRegistry-DcDVyzLm.mjs.map +0 -1
- package/dist/chunks/BlockInsertion-6rR9tIGP.mjs +0 -2
- package/dist/chunks/BlockInsertion-6rR9tIGP.mjs.map +0 -1
- package/dist/chunks/BlockquotePlugin-4V7KV_Sb.mjs +0 -2
- package/dist/chunks/CodeBlockPlugin-3V2K3RBe.mjs +0 -2
- package/dist/chunks/CodeBlockPlugin-3V2K3RBe.mjs.map +0 -1
- package/dist/chunks/ColorPickerPopup-lcf3jS6G.mjs +0 -2
- package/dist/chunks/Commands-BIIpx_Zd.mjs +0 -2
- package/dist/chunks/Commands-BIIpx_Zd.mjs.map +0 -1
- package/dist/chunks/Decoration-ZeyVfwJB.mjs +0 -2
- package/dist/chunks/Decoration-ZeyVfwJB.mjs.map +0 -1
- package/dist/chunks/Document-r7vLOAGA.mjs +0 -2
- package/dist/chunks/Document-r7vLOAGA.mjs.map +0 -1
- package/dist/chunks/DocumentParser-CcTSeT1B.mjs +0 -2
- package/dist/chunks/DocumentParser-CcTSeT1B.mjs.map +0 -1
- package/dist/chunks/FontSizePlugin-9StCjEfN.mjs.map +0 -1
- package/dist/chunks/FormulaPlugin-CV5VUxkb.mjs +0 -2
- package/dist/chunks/FormulaPlugin-CV5VUxkb.mjs.map +0 -1
- package/dist/chunks/GapCursorNavigation-ycNzuQVH.mjs +0 -2
- package/dist/chunks/HTMLUtils-C6B4UT00.mjs +0 -2
- package/dist/chunks/HTMLUtils-C6B4UT00.mjs.map +0 -1
- package/dist/chunks/HeadingPlugin-BuGoM9Rz.mjs +0 -2
- package/dist/chunks/HorizontalRulePlugin-0FjHPZuA.mjs +0 -2
- package/dist/chunks/HorizontalRulePlugin-0FjHPZuA.mjs.map +0 -1
- package/dist/chunks/ImagePlugin-KpkuE2LH.mjs +0 -2
- package/dist/chunks/InlineCodePlugin-DMr4O7c7.mjs.map +0 -1
- package/dist/chunks/InlineStyleMarkSpec-C6LJT7kp.mjs +0 -2
- package/dist/chunks/LinkPlugin-DvZ3MPgL.mjs +0 -2
- package/dist/chunks/LinkPlugin-DvZ3MPgL.mjs.map +0 -1
- package/dist/chunks/ListPlugin-2yl6KiTK.mjs +0 -2
- package/dist/chunks/ListPlugin-2yl6KiTK.mjs.map +0 -1
- package/dist/chunks/NodeSelectionCommands-Dj4VxLdD.mjs +0 -2
- package/dist/chunks/PluginHelpers-KDuTlmXm.mjs +0 -2
- package/dist/chunks/PopupPositioning-BB97-__N.mjs +0 -2
- package/dist/chunks/PrintPlugin-DyIZDY3Q.mjs +0 -2
- package/dist/chunks/PrintPlugin-DyIZDY3Q.mjs.map +0 -1
- package/dist/chunks/StrikethroughPlugin-BLKDRWtf.mjs +0 -2
- package/dist/chunks/StrikethroughPlugin-BLKDRWtf.mjs.map +0 -1
- package/dist/chunks/StyleRuntime-BFKu52mS.mjs +0 -2
- package/dist/chunks/StyleRuntime-BFKu52mS.mjs.map +0 -1
- package/dist/chunks/TablePlugin-BTH9VRZq.mjs +0 -2
- package/dist/chunks/TablePlugin-BTH9VRZq.mjs.map +0 -1
- package/dist/chunks/TextColorPlugin-CEfZQ6Md.mjs +0 -2
- package/dist/chunks/TextDirectionAutoPlugin-CzWJjrvG.mjs +0 -2
- package/dist/chunks/TextDirectionService-OFOU6r_s.mjs +0 -2
- package/dist/chunks/TextFormattingPlugin-Cubp3e7f.mjs +0 -2
- package/dist/chunks/TextFormattingPlugin-Cubp3e7f.mjs.map +0 -1
- package/dist/chunks/VideoPlugin-B3uf1Dwp.mjs +0 -2
- package/dist/chunks/VideoPlugin-B3uf1Dwp.mjs.map +0 -1
- package/dist/chunks/WordBoundary-DxeMBRyP.mjs +0 -2
- package/dist/chunks/ar-BTShmP2E.mjs +0 -2
- package/dist/chunks/ar-jbplYWkC.mjs +0 -2
- package/dist/chunks/ar-jbplYWkC.mjs.map +0 -1
- package/dist/chunks/de-DN-e6G5A.mjs +0 -2
- package/dist/chunks/de-DN-e6G5A.mjs.map +0 -1
- package/dist/chunks/es-CM55WeEN.mjs +0 -2
- package/dist/chunks/es-CM55WeEN.mjs.map +0 -1
- package/dist/chunks/fr-C_2i5Ono.mjs +0 -2
- package/dist/chunks/fr-C_2i5Ono.mjs.map +0 -1
- package/dist/chunks/full-BBl7mvwH.mjs +0 -2
- package/dist/chunks/hi-C9fvG91d.mjs +0 -2
- package/dist/chunks/hi-C9fvG91d.mjs.map +0 -1
- package/dist/chunks/minimal-CtnR4dqp.mjs +0 -2
- package/dist/chunks/pt-GqLw5tN0.mjs +0 -2
- package/dist/chunks/pt-GqLw5tN0.mjs.map +0 -1
- package/dist/chunks/ru-4g_qsaLr.mjs +0 -2
- package/dist/chunks/ru-4g_qsaLr.mjs.map +0 -1
- package/dist/chunks/src-C89Cw7ni.mjs +0 -2
- package/dist/chunks/src-C89Cw7ni.mjs.map +0 -1
- package/dist/chunks/zh-BjoyjClN.mjs +0 -2
- package/dist/chunks/zh-DeZP08HI.mjs +0 -2
- package/dist/chunks/zh-DeZP08HI.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Decoration-ZeyVfwJB.mjs","names":[],"sources":["../../src/state/Mapping.ts","../../src/state/BlockTreeOps.ts","../../src/state/InlineContentOps.ts","../../src/state/StepApplication.ts","../../src/model/ContentSlice.ts","../../src/state/Steps.ts","../../src/state/StepInversion.ts","../../src/state/StepMapping.ts","../../src/state/StepMaps.ts","../../src/state/StepHandlers.ts","../../src/decorations/PositionMapping.ts","../../src/decorations/Decoration.ts"],"sourcesContent":["/**\n * Generic position-mapping primitive.\n *\n * Each {@link Step} produces a {@link StepMap} that describes how positions\n * in `{blockId, offset}` space shift when the step is applied. A\n * {@link Mapping} composes a sequence of `StepMap`s — typically all the maps\n * of a transaction — into a single mapper, so any consumer (decorations,\n * comments, selections, remote cursors, history) can fold a position\n * through an entire change set without re-implementing per-step math.\n *\n * The model mirrors ProseMirror's `StepMap` / `Mapping`, adapted to\n * notectl's `{blockId, offset}` position space (positions are scoped to\n * blocks, not a flat document offset).\n *\n * ## Association (bias) semantics\n *\n * The optional `assoc` argument decides which side of a boundary a position\n * sticks to:\n *\n * - `assoc = -1` (\"sticky left\"): the position stays at the boundary when\n * content is inserted at, or split exactly at, the position. This is the\n * semantics expected by an inclusive-start range marker (a decoration's\n * `from`, the left edge of a selection).\n * - `assoc = +1` (\"sticky right\"): the position moves past inserted content\n * and migrates to the new block when its host block is split exactly at\n * the position. This is the semantics expected by an exclusive-end range\n * marker (a decoration's `to`, the right edge of a selection).\n *\n * The default is `-1`, matching the most common case (cursor and from-side\n * mappers).\n *\n * ## StepMap categories\n *\n * Every {@link Step} produces exactly one of six categories:\n *\n * 1. `identity` — no position shift (mark, attribute, schema, block-type).\n * 2. `shift` — within a single block, the range `[from, to)` is replaced\n * with content of length `newLen`. Covers `insertText`, `deleteText`,\n * `insertInlineNode`, `removeInlineNode` as a single primitive.\n * 3. `split` — a block is split at an offset; positions past the split\n * migrate to the new block with rebased offsets.\n * 4. `merge` — a source block is appended to a target block; positions in\n * the source block migrate to the target block with offsets shifted by\n * the target's previous length.\n * 5. `blockRemoval` — one block subtree vanishes; positions inside any\n * removed block are marked deleted, and sibling child-indices in the\n * same parent shift down by one past the removed index.\n * 6. `childIndexShift` — a new block was inserted at `fromIndex` in\n * `parentPath`'s children; sibling child-indices `≥ fromIndex` shift up.\n * Position space ({blockId, offset}) is unaffected.\n *\n * `blockRemoval` and `childIndexShift` are the two categories that carry\n * **structural** information about a parent's child list. They are\n * orthogonal to positions ({blockId, offset}) and are interpreted by\n * {@link mapChildIndex} when rebasing tree-structural steps\n * (`insertNode` / `removeNode`).\n */\n\nimport { isBlockNode } from '../model/Document.js';\nimport type { BlockNode } from '../model/Document.js';\nimport type { Position } from '../model/Selection.js';\nimport { createPosition } from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\n\n/**\n * Result of mapping an `(blockId, [from, to))` range through a {@link Mapping}.\n *\n * Both endpoints are guaranteed to live in the same block. Callers can rely\n * on `from <= to` (the helper returns `null` rather than producing an\n * inverted range).\n */\nexport interface MappedInBlockRange {\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n}\n\n/** Position-mapping bias at a boundary. */\nexport type Assoc = -1 | 1;\n\n// --- StepMap variants ---\n\n/** No-op map: positions pass through unchanged. */\nexport interface IdentityMap {\n\treadonly type: 'identity';\n}\n\n/**\n * Within `blockId`, the offset range `[from, to)` is replaced with content\n * of length `newLen`. Covers all in-block content edits with a single\n * primitive:\n *\n * - `insertText(blockId, off, text)` → `{from: off, to: off, newLen: text.length}`.\n * - `deleteText(blockId, f, t)` → `{from: f, to: t, newLen: 0}`.\n * - `insertInlineNode(blockId, off)` → `{from: off, to: off, newLen: 1}`.\n * - `removeInlineNode(blockId, off)` → `{from: off, to: off + 1, newLen: 0}`.\n */\nexport interface ShiftMap {\n\treadonly type: 'shift';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly newLen: number;\n}\n\n/**\n * A block is split at `offset`. Content `[0, offset)` stays in `blockId`;\n * content `[offset, length)` migrates to `newBlockId` rebased to start at 0.\n */\nexport interface SplitMap {\n\treadonly type: 'split';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly newBlockId: BlockId;\n}\n\n/**\n * `sourceBlockId` is appended to `targetBlockId`. Positions in the source\n * block migrate to the target block with offset shifted by\n * `targetLengthBefore` (the target's length before the merge).\n */\nexport interface MergeMap {\n\treadonly type: 'merge';\n\treadonly targetBlockId: BlockId;\n\treadonly sourceBlockId: BlockId;\n\treadonly targetLengthBefore: number;\n}\n\n/**\n * A block subtree is removed from the document. Positions whose `blockId`\n * is in `removedBlockIds` are marked deleted; `removedBlockIds` covers the\n * removed root **plus all descendant block IDs** (see\n * {@link collectRemovedBlockIds}).\n *\n * `parentPath` and `index` carry the removal's structural coordinates so\n * sibling child-indices in the same parent can be rebased: any\n * `(parentPath, i)` with `i === index` becomes invalid (the block is gone),\n * and `i > index` shifts down by one. See {@link mapChildIndex}.\n */\nexport interface BlockRemovalMap {\n\treadonly type: 'blockRemoval';\n\treadonly removedBlockIds: ReadonlySet<BlockId>;\n\treadonly parentPath: readonly BlockId[];\n\treadonly index: number;\n}\n\n/**\n * A new block was inserted at `fromIndex` in `parentPath`'s child list.\n * Sibling child-indices `≥ fromIndex` shift up by `delta` (always `+1`\n * since {@link InsertNodeStep} inserts a single block). Position space\n * (`{blockId, offset}`) is unaffected — the new block has no prior\n * positions, and positions inside other siblings keep their offsets.\n *\n * Only consumed by {@link mapChildIndex}.\n */\nexport interface ChildIndexShiftMap {\n\treadonly type: 'childIndexShift';\n\treadonly parentPath: readonly BlockId[];\n\treadonly fromIndex: number;\n\treadonly delta: number;\n}\n\n/** Discriminated union of all StepMap variants. */\nexport type StepMap =\n\t| IdentityMap\n\t| ShiftMap\n\t| SplitMap\n\t| MergeMap\n\t| BlockRemovalMap\n\t| ChildIndexShiftMap;\n\n// --- Map results ---\n\n/** Result of mapping a single position. */\nexport interface MapResult {\n\treadonly pos: Position;\n\t/** True if the input position fell inside content removed by the map. */\n\treadonly deleted: boolean;\n}\n\n/** A range expressed in `Position` space. */\nexport interface PositionRange {\n\treadonly from: Position;\n\treadonly to: Position;\n}\n\n// --- Singletons / factories ---\n\n/** The shared identity StepMap; reuse instead of allocating per step. */\nexport const IDENTITY_MAP: IdentityMap = { type: 'identity' };\n\n/**\n * Walks a block subtree and returns the set of its own ID plus every\n * descendant block ID. Used to build {@link BlockRemovalMap.removedBlockIds}.\n */\nexport function collectRemovedBlockIds(node: BlockNode): Set<BlockId> {\n\tconst ids = new Set<BlockId>();\n\tconst walk = (n: BlockNode): void => {\n\t\tids.add(n.id);\n\t\tfor (const child of n.children) {\n\t\t\tif (isBlockNode(child)) walk(child);\n\t\t}\n\t};\n\twalk(node);\n\treturn ids;\n}\n\n// --- Single-StepMap application ---\n\n/**\n * Maps a single position through one {@link StepMap}.\n *\n * @param pos input position\n * @param map the StepMap describing the change\n * @param assoc which side of a boundary to stick to (default `-1`)\n * @returns mapped position plus a `deleted` flag indicating whether `pos`\n * fell inside content that the step removed\n */\nexport function mapPositionThroughStep(pos: Position, map: StepMap, assoc: Assoc = -1): MapResult {\n\tswitch (map.type) {\n\t\tcase 'identity':\n\t\t\treturn { pos, deleted: false };\n\t\tcase 'shift':\n\t\t\treturn mapPositionThroughShift(pos, map, assoc);\n\t\tcase 'split':\n\t\t\treturn mapPositionThroughSplit(pos, map, assoc);\n\t\tcase 'merge':\n\t\t\treturn mapPositionThroughMerge(pos, map);\n\t\tcase 'blockRemoval':\n\t\t\treturn mapPositionThroughBlockRemoval(pos, map);\n\t\tcase 'childIndexShift':\n\t\t\t// Child-index shifts do not touch position space ({blockId, offset}):\n\t\t\t// a new sibling block has no prior positions to map, and existing\n\t\t\t// siblings keep their internal offsets even if their parent-relative\n\t\t\t// index changed. Consumed only by {@link mapChildIndex}.\n\t\t\treturn { pos, deleted: false };\n\t}\n}\n\nfunction mapPositionThroughShift(pos: Position, map: ShiftMap, assoc: Assoc): MapResult {\n\tif (pos.blockId !== map.blockId) return { pos, deleted: false };\n\n\tconst delta: number = map.newLen - (map.to - map.from);\n\tconst off: number = pos.offset;\n\n\t// Strictly before the affected range\n\tif (off < map.from) return { pos, deleted: false };\n\n\t// At the start boundary\n\tif (off === map.from) {\n\t\t// Pure insertion (from === to): assoc decides whether we stick before\n\t\t// or after the inserted run.\n\t\tif (map.from === map.to) {\n\t\t\tconst newOff: number = assoc === 1 ? map.from + map.newLen : map.from;\n\t\t\treturn newOff === off\n\t\t\t\t? { pos, deleted: false }\n\t\t\t\t: { pos: shiftedPos(pos, newOff), deleted: false };\n\t\t}\n\t\t// Deletion starts at this point — position stays at `from` regardless\n\t\t// of assoc; nothing was inserted to skip past.\n\t\treturn { pos, deleted: false };\n\t}\n\n\t// Strictly inside [from, to): position fell into removed content\n\tif (off < map.to) {\n\t\tconst newOff: number = assoc === 1 ? map.from + map.newLen : map.from;\n\t\treturn { pos: shiftedPos(pos, newOff), deleted: true };\n\t}\n\n\t// At or past the end boundary: shift by delta\n\tconst newOff: number = off + delta;\n\treturn newOff === off\n\t\t? { pos, deleted: false }\n\t\t: { pos: shiftedPos(pos, newOff), deleted: false };\n}\n\nfunction mapPositionThroughSplit(pos: Position, map: SplitMap, assoc: Assoc): MapResult {\n\tif (pos.blockId !== map.blockId) return { pos, deleted: false };\n\n\tif (pos.offset < map.offset) return { pos, deleted: false };\n\n\tif (pos.offset > map.offset) {\n\t\treturn {\n\t\t\tpos: createPosition(map.newBlockId, pos.offset - map.offset),\n\t\t\tdeleted: false,\n\t\t};\n\t}\n\n\t// At the split boundary: assoc decides which side keeps the cursor.\n\tif (assoc === 1) {\n\t\treturn { pos: createPosition(map.newBlockId, 0), deleted: false };\n\t}\n\treturn { pos, deleted: false };\n}\n\nfunction mapPositionThroughMerge(pos: Position, map: MergeMap): MapResult {\n\tif (pos.blockId !== map.sourceBlockId) return { pos, deleted: false };\n\treturn {\n\t\tpos: createPosition(map.targetBlockId, pos.offset + map.targetLengthBefore),\n\t\tdeleted: false,\n\t};\n}\n\nfunction mapPositionThroughBlockRemoval(pos: Position, map: BlockRemovalMap): MapResult {\n\tif (map.removedBlockIds.has(pos.blockId)) {\n\t\treturn { pos, deleted: true };\n\t}\n\treturn { pos, deleted: false };\n}\n\n/** Allocates a new Position with the given offset, preserving an optional `path`. */\nfunction shiftedPos(original: Position, newOffset: number): Position {\n\treturn createPosition(original.blockId, newOffset, original.path);\n}\n\n// --- Mapping ---\n\n/**\n * Composes a sequence of {@link StepMap}s into a single mapper. A `Mapping`\n * is immutable; `appendMap` returns a new instance.\n *\n * Construction always normalizes by dropping identity maps — they're a\n * common case and would otherwise inflate every transaction's mapping\n * pipeline with no-ops.\n */\nexport class Mapping {\n\t/** Shared empty Mapping. */\n\tstatic readonly empty: Mapping = new Mapping([]);\n\n\treadonly maps: readonly StepMap[];\n\n\tprivate constructor(maps: readonly StepMap[]) {\n\t\tthis.maps = maps;\n\t}\n\n\t/** Creates a Mapping from a list of StepMaps, dropping identity maps. */\n\tstatic from(maps: readonly StepMap[]): Mapping {\n\t\tconst filtered: StepMap[] = [];\n\t\tfor (const m of maps) {\n\t\t\tif (m.type !== 'identity') filtered.push(m);\n\t\t}\n\t\tif (filtered.length === 0) return Mapping.empty;\n\t\treturn new Mapping(filtered);\n\t}\n\n\t/** Returns a new Mapping with `map` appended. */\n\tappendMap(map: StepMap): Mapping {\n\t\tif (map.type === 'identity') return this;\n\t\treturn new Mapping([...this.maps, map]);\n\t}\n\n\t/** Concatenates two mappings into a new one. */\n\tappendMapping(other: Mapping): Mapping {\n\t\tif (other.maps.length === 0) return this;\n\t\tif (this.maps.length === 0) return other;\n\t\treturn new Mapping([...this.maps, ...other.maps]);\n\t}\n\n\t/** True if the mapping contains no position-changing maps. */\n\tget isEmpty(): boolean {\n\t\treturn this.maps.length === 0;\n\t}\n\n\t/**\n\t * Folds a position through every contained StepMap in order.\n\t * Returns the mapped position; the `deleted` flag is **not** preserved\n\t * (use {@link mapResult} when you need it).\n\t */\n\tmap(pos: Position, assoc: Assoc = -1): Position {\n\t\treturn this.mapResult(pos, assoc).pos;\n\t}\n\n\t/**\n\t * Like {@link map}, but returns whether the position landed in deleted\n\t * content at any step. Once a position is marked deleted, the flag is\n\t * sticky — subsequent steps do not \"un-delete\" it.\n\t */\n\tmapResult(pos: Position, assoc: Assoc = -1): MapResult {\n\t\tlet current: Position = pos;\n\t\tlet deleted = false;\n\t\tfor (const m of this.maps) {\n\t\t\tconst result: MapResult = mapPositionThroughStep(current, m, assoc);\n\t\t\tcurrent = result.pos;\n\t\t\tif (result.deleted) deleted = true;\n\t\t}\n\t\treturn { pos: current, deleted };\n\t}\n\n\t/**\n\t * Maps a range. By convention, `from` is mapped with `assoc = -1`\n\t * (inclusive-start) and `to` with `assoc = +1` (exclusive-end). The\n\t * caller may override either bias.\n\t *\n\t * Returns `null` when both endpoints land in deleted content **and** the\n\t * mapped range would collapse to length zero or negative — i.e. the\n\t * range no longer covers any live content.\n\t *\n\t * The returned `from`/`to` may live in different blocks (e.g. after a\n\t * `split` map). Callers that require an in-block range (decorations,\n\t * inline selections) must detect and split accordingly.\n\t */\n\tmapRange(range: PositionRange, assocFrom: Assoc = -1, assocTo: Assoc = 1): PositionRange | null {\n\t\tconst from: MapResult = this.mapResult(range.from, assocFrom);\n\t\tconst to: MapResult = this.mapResult(range.to, assocTo);\n\n\t\tif (from.deleted && to.deleted) {\n\t\t\tif (from.pos.blockId === to.pos.blockId && from.pos.offset >= to.pos.offset) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\treturn { from: from.pos, to: to.pos };\n\t}\n}\n\n// --- In-block range helpers (used by per-step Step→Step mapping) ---\n\n/**\n * Maps an `(blockId, [from, to))` range through `mapping`, asserting the\n * result lives in a single block.\n *\n * Returns `null` when the range no longer addresses live content in a single\n * block:\n *\n * - the host block was removed;\n * - the range was fully deleted (both endpoints flagged deleted and collapse);\n * - the endpoints migrated to different blocks (range fragmented, e.g. a\n * `split` map placed `from` and `to` on opposite sides of the cut).\n *\n * Default biases are **conservative for step rebasing**: `assocFrom = +1`,\n * `assocTo = -1`. An intervening insertion at either boundary therefore\n * does NOT expand the rebased range to cover the new content — the user's\n * original edit only addressed the original content, and the agent's\n * intervening insertion should be preserved across an undo/redo. This is\n * the opposite of {@link Mapping.mapRange}'s default biases, which model\n * selections (inclusive-start, exclusive-end) where boundary insertions\n * naturally extend the selection.\n */\nexport function mapInBlockRange(\n\tblockId: BlockId,\n\tfrom: number,\n\tto: number,\n\tmapping: Mapping,\n\tassocFrom: Assoc = 1,\n\tassocTo: Assoc = -1,\n): MappedInBlockRange | null {\n\tif (mapping.isEmpty) return { blockId, from, to };\n\n\tconst fromPos: Position = createPosition(blockId, from);\n\tconst toPos: Position = createPosition(blockId, to);\n\tconst fromResult: MapResult = mapping.mapResult(fromPos, assocFrom);\n\tconst toResult: MapResult = mapping.mapResult(toPos, assocTo);\n\n\t// If both endpoints fell inside removed/replaced content, the range no\n\t// longer addresses live document territory — abandon. A partial overlap\n\t// (one endpoint deleted, the other shifted) still survives clamped.\n\tif (fromResult.deleted && toResult.deleted) return null;\n\n\t// Range must remain within a single block. A split could have moved one\n\t// endpoint to the new block; that's a fragmentation we cannot represent\n\t// as a single in-block step.\n\tif (fromResult.pos.blockId !== toResult.pos.blockId) return null;\n\n\t// Defensive: a range whose endpoints inverted (from > to) is invalid.\n\t// An empty range with from === to is still valid (e.g. a pure-insertion\n\t// `shift` whose offset survived).\n\tif (fromResult.pos.offset > toResult.pos.offset) return null;\n\n\treturn {\n\t\tblockId: fromResult.pos.blockId,\n\t\tfrom: fromResult.pos.offset,\n\t\tto: toResult.pos.offset,\n\t};\n}\n\n/**\n * Maps an `(blockId, offset)` point through `mapping`, returning the\n * equivalent in-block position or `null` when the host block was removed.\n *\n * Convenience wrapper around {@link mapInBlockRange} for steps that carry a\n * single offset (`insertText`, `insertInlineNode`, `splitBlock`).\n */\nexport function mapOffsetInBlock(\n\tblockId: BlockId,\n\toffset: number,\n\tmapping: Mapping,\n\tassoc: Assoc = -1,\n): MappedInBlockRange | null {\n\tif (mapping.isEmpty) return { blockId, from: offset, to: offset };\n\n\tconst pos: Position = createPosition(blockId, offset);\n\tconst result: MapResult = mapping.mapResult(pos, assoc);\n\tif (result.deleted) return null;\n\treturn { blockId: result.pos.blockId, from: result.pos.offset, to: result.pos.offset };\n}\n\n// --- Child-index mapping (used by structural step rebasing) ---\n\n/**\n * Rebases a child-index `(parentPath, index)` through `mapping`. The\n * `index` is interpreted as the position of an **existing** child block:\n * if an intervening edit removed exactly that child, the result is\n * `null`. For an **insertion slot** (the target index of a future\n * `insertNode`), use {@link mapInsertionIndex} — slots stay valid even\n * when the block previously at that index is removed.\n *\n * Child-indices live in a coordinate space orthogonal to positions\n * (`{blockId, offset}`): they describe a slot in a parent's child list,\n * not a place inside text. Only two {@link StepMap} categories carry\n * child-index-affecting information:\n *\n * - {@link ChildIndexShiftMap} (produced by `insertNode`): shifts\n * sibling indices `≥ fromIndex` by `delta` (always `+1` today).\n * - {@link BlockRemovalMap} (produced by `removeNode`): removes the child\n * at `index` (the input index becomes invalid → `null`), and shifts\n * sibling indices `> index` down by `1`.\n *\n * Maps whose `parentPath` differs from the input pass through; all\n * non-structural categories (`shift`, `split`, `merge`, `identity`) are\n * no-ops here.\n */\nexport function mapChildIndex(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmapping: Mapping,\n): number | null {\n\treturn foldChildIndex(parentPath, index, mapping, 'existing');\n}\n\n/**\n * Rebases an **insertion slot** `(parentPath, index)` through `mapping`.\n * An insertion slot lives in `[0, children.length]` (inclusive of the\n * end) and represents \"where to insert\", not an existing block. Slots\n * remain valid across intervening edits — even when the block previously\n * at that index is removed — so this function never returns `null`.\n *\n * Difference from {@link mapChildIndex}: for a `BlockRemovalMap` with\n * matching parent and `index === map.index`, this function keeps the\n * slot (returning `map.index`, which is the same numeric position in the\n * post-removal frame); {@link mapChildIndex} would return `null`.\n * {@link ChildIndexShiftMap} handling is identical.\n */\nexport function mapInsertionIndex(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmapping: Mapping,\n): number {\n\t// `foldChildIndex` with `'insertion'` provably never returns `null` —\n\t// the only path that would (BlockRemovalMap, matching parent, matching\n\t// index) is short-circuited inside `mapChildIndexThroughStep`. The\n\t// overload signature carries that invariant into the type system.\n\treturn foldChildIndex(parentPath, index, mapping, 'insertion');\n}\n\ntype ChildIndexKind = 'existing' | 'insertion';\n\nfunction foldChildIndex(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmapping: Mapping,\n\tkind: 'existing',\n): number | null;\nfunction foldChildIndex(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmapping: Mapping,\n\tkind: 'insertion',\n): number;\nfunction foldChildIndex(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmapping: Mapping,\n\tkind: ChildIndexKind,\n): number | null {\n\tif (mapping.isEmpty) return index;\n\n\tlet current: number = index;\n\tfor (const m of mapping.maps) {\n\t\tconst next: number | null = mapChildIndexThroughStep(parentPath, current, m, kind);\n\t\tif (next === null) return null;\n\t\tcurrent = next;\n\t}\n\treturn current;\n}\n\nfunction mapChildIndexThroughStep(\n\tparentPath: readonly BlockId[],\n\tindex: number,\n\tmap: StepMap,\n\tkind: ChildIndexKind,\n): number | null {\n\tswitch (map.type) {\n\t\tcase 'identity':\n\t\tcase 'shift':\n\t\tcase 'split':\n\t\tcase 'merge':\n\t\t\treturn index;\n\t\tcase 'blockRemoval':\n\t\t\tif (!sameParentPath(parentPath, map.parentPath)) return index;\n\t\t\tif (index === map.index) {\n\t\t\t\t// Existing-child semantics: that child is gone → invalid.\n\t\t\t\t// Insertion-slot semantics: the slot survives; nothing was\n\t\t\t\t// inserted/removed *to the left* of `index`, so the slot\n\t\t\t\t// number is unchanged in the post-removal frame.\n\t\t\t\treturn kind === 'existing' ? null : index;\n\t\t\t}\n\t\t\tif (index > map.index) return index - 1;\n\t\t\treturn index;\n\t\tcase 'childIndexShift':\n\t\t\tif (!sameParentPath(parentPath, map.parentPath)) return index;\n\t\t\tif (index >= map.fromIndex) return index + map.delta;\n\t\t\treturn index;\n\t}\n}\n\nfunction sameParentPath(a: readonly BlockId[], b: readonly BlockId[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i] !== b[i]) return false;\n\t}\n\treturn true;\n}\n\n// --- StepMap inversion (used by history's frame-walk cancellation) ---\n\n/**\n * Returns the {@link StepMap} that undoes `map` in position space — i.e.\n * composing `map` with `invertStepMap(map)` is content-preserving (though\n * the composed position-mapping is *not* a true identity in our framework:\n * positions interior to a delete-then-reinsert round-trip clamp to the\n * deletion start during the deletion half and don't return on the insert\n * half).\n *\n * Used by history to detect mutually-inverse stepmaps in the rebase chain\n * and cancel them, sidestepping the round-trip clamping for cases where\n * the rebase is a no-op in content terms.\n *\n * `BlockRemovalMap`'s inverse is {@link IDENTITY_MAP}: re-inserting a\n * removed block subtree does not shift positions in *other* blocks, so the\n * inverse direction is invisible to position-mapping. Callers that need to\n * re-validate \"did the block come back\" must check the document instead.\n */\nexport function invertStepMap(map: StepMap): StepMap {\n\tswitch (map.type) {\n\t\tcase 'identity':\n\t\t\treturn IDENTITY_MAP;\n\t\tcase 'shift':\n\t\t\treturn {\n\t\t\t\ttype: 'shift',\n\t\t\t\tblockId: map.blockId,\n\t\t\t\tfrom: map.from,\n\t\t\t\tto: map.from + map.newLen,\n\t\t\t\tnewLen: map.to - map.from,\n\t\t\t};\n\t\tcase 'split':\n\t\t\treturn {\n\t\t\t\ttype: 'merge',\n\t\t\t\ttargetBlockId: map.blockId,\n\t\t\t\tsourceBlockId: map.newBlockId,\n\t\t\t\ttargetLengthBefore: map.offset,\n\t\t\t};\n\t\tcase 'merge':\n\t\t\treturn {\n\t\t\t\ttype: 'split',\n\t\t\t\tblockId: map.targetBlockId,\n\t\t\t\toffset: map.targetLengthBefore,\n\t\t\t\tnewBlockId: map.sourceBlockId,\n\t\t\t};\n\t\tcase 'blockRemoval':\n\t\t\t// Re-inserting a removed subtree does not shift positions in other\n\t\t\t// blocks, so the inverse position-space direction is invisible. The\n\t\t\t// child-index shift direction *is* representable as a\n\t\t\t// `childIndexShift` map, but history's cancellation only looks for\n\t\t\t// content-trivial round-trips; we return IDENTITY_MAP and let the\n\t\t\t// caller fall back to the standard rebase path. See JSDoc above.\n\t\t\treturn IDENTITY_MAP;\n\t\tcase 'childIndexShift':\n\t\t\t// Inverting an insertNode (delta = +1 at fromIndex) is a removeNode\n\t\t\t// at the same index, which carries both position- and child-index\n\t\t\t// effects via `BlockRemovalMap`. Producing a faithful inverse here\n\t\t\t// would require knowing `removedBlockIds`, which a position-only\n\t\t\t// `StepMap` does not carry. Return IDENTITY_MAP for the same reason\n\t\t\t// as `blockRemoval`: cancellation won't fire for these pairs, but\n\t\t\t// the frame-walk's standard rebase path still produces correct\n\t\t\t// rebased steps.\n\t\t\treturn IDENTITY_MAP;\n\t}\n}\n\n/**\n * Structural equality for {@link StepMap}s. Used by history to recognize\n * cancelling pairs in the rebase chain ({@link invertStepMap}(a) ≡ b).\n */\nexport function stepMapsEqual(a: StepMap, b: StepMap): boolean {\n\tif (a.type !== b.type) return false;\n\tswitch (a.type) {\n\t\tcase 'identity':\n\t\t\treturn true;\n\t\tcase 'shift': {\n\t\t\tconst bs = b as ShiftMap;\n\t\t\treturn (\n\t\t\t\ta.blockId === bs.blockId && a.from === bs.from && a.to === bs.to && a.newLen === bs.newLen\n\t\t\t);\n\t\t}\n\t\tcase 'split': {\n\t\t\tconst bs = b as SplitMap;\n\t\t\treturn a.blockId === bs.blockId && a.offset === bs.offset && a.newBlockId === bs.newBlockId;\n\t\t}\n\t\tcase 'merge': {\n\t\t\tconst bm = b as MergeMap;\n\t\t\treturn (\n\t\t\t\ta.targetBlockId === bm.targetBlockId &&\n\t\t\t\ta.sourceBlockId === bm.sourceBlockId &&\n\t\t\t\ta.targetLengthBefore === bm.targetLengthBefore\n\t\t\t);\n\t\t}\n\t\tcase 'blockRemoval': {\n\t\t\tconst br = b as BlockRemovalMap;\n\t\t\tif (a.index !== br.index) return false;\n\t\t\tif (!sameParentPath(a.parentPath, br.parentPath)) return false;\n\t\t\tif (a.removedBlockIds.size !== br.removedBlockIds.size) return false;\n\t\t\tfor (const id of a.removedBlockIds) {\n\t\t\t\tif (!br.removedBlockIds.has(id)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tcase 'childIndexShift': {\n\t\t\tconst cs = b as ChildIndexShiftMap;\n\t\t\treturn (\n\t\t\t\ta.fromIndex === cs.fromIndex &&\n\t\t\t\ta.delta === cs.delta &&\n\t\t\t\tsameParentPath(a.parentPath, cs.parentPath)\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Pure functions for recursive block-tree traversal and transformation.\n * Extracted from StepApplication.ts to keep files under ~500 lines.\n */\n\nimport { type BlockNode, type ChildNode, type Document, isBlockNode } from '../model/Document.js';\n\n/** Finds a block by ID anywhere in the tree and applies a transform. */\nexport function mapBlock(\n\tdoc: Document,\n\tblockId: string,\n\tfn: (block: BlockNode) => BlockNode,\n): Document {\n\treturn {\n\t\tchildren: mapBlockInChildren(doc.children, blockId, fn) as BlockNode[],\n\t};\n}\n\n/**\n * Recursively maps over children to find and transform a block by ID.\n *\n * Preserves reference identity: when the target block is not found in a given\n * subtree, the original `children` array (and the original child nodes along\n * the way) are returned unchanged, so unrelated subtrees are not reallocated on\n * every edit.\n */\nexport function mapBlockInChildren(\n\tchildren: readonly ChildNode[],\n\tblockId: string,\n\tfn: (block: BlockNode) => BlockNode,\n): ChildNode[] {\n\tlet changed = false;\n\tconst mapped: ChildNode[] = children.map((child) => {\n\t\tif (!isBlockNode(child)) return child;\n\t\tif (child.id === blockId) {\n\t\t\tchanged = true;\n\t\t\treturn fn(child);\n\t\t}\n\t\t// Recurse into block children; an unchanged subtree returns the same\n\t\t// `child.children` reference, so the identity check below holds.\n\t\tconst mappedChildren: ChildNode[] = mapBlockInChildren(child.children, blockId, fn);\n\t\tif (mappedChildren === child.children) return child;\n\t\tchanged = true;\n\t\treturn { ...child, children: mappedChildren };\n\t});\n\treturn changed ? mapped : (children as ChildNode[]);\n}\n\n/**\n * Maps a node at the given path, replacing it with the result of fn.\n * Navigates down the path immutably, creating new parent nodes as needed.\n */\nexport function mapNodeByPath(\n\tdoc: Document,\n\tpath: readonly string[],\n\tfn: (node: BlockNode) => BlockNode,\n): Document {\n\tif (path.length === 0) return doc;\n\n\tconst rootId: string | undefined = path[0];\n\tif (!rootId) return doc;\n\treturn {\n\t\tchildren: doc.children.map((child) => {\n\t\t\tif (!isBlockNode(child) || child.id !== rootId) return child;\n\t\t\tif (path.length === 1) return fn(child);\n\t\t\treturn mapNodeByPathRecursive(child, path, 1, fn);\n\t\t}),\n\t};\n}\n\n/** Recursive helper for mapNodeByPath — walks one level deeper. */\nexport function mapNodeByPathRecursive(\n\tnode: BlockNode,\n\tpath: readonly string[],\n\tdepth: number,\n\tfn: (node: BlockNode) => BlockNode,\n): BlockNode {\n\tconst targetId: string | undefined = path[depth];\n\tif (!targetId) return node;\n\tconst newChildren: ChildNode[] = node.children.map((child) => {\n\t\tif (!isBlockNode(child) || child.id !== targetId) return child;\n\t\tif (depth === path.length - 1) return fn(child);\n\t\treturn mapNodeByPathRecursive(child, path, depth + 1, fn);\n\t});\n\treturn { ...node, children: newChildren };\n}\n\n/**\n * Searches children for a level where `predicate` matches,\n * then applies `transform` at that level.\n * Recurses into nested BlockNodes if not found at the current level.\n *\n * Returns `null` if no matching level was found.\n */\nexport function findAndTransformChildren(\n\tchildren: readonly ChildNode[],\n\tpredicate: (children: readonly ChildNode[]) => boolean,\n\ttransform: (children: readonly ChildNode[]) => readonly ChildNode[],\n): readonly ChildNode[] | null {\n\tif (predicate(children)) {\n\t\treturn transform(children);\n\t}\n\n\tlet changed = false;\n\tconst newChildren: ChildNode[] = children.map((child) => {\n\t\tif (!isBlockNode(child)) return child;\n\t\tconst result: readonly ChildNode[] | null = findAndTransformChildren(\n\t\t\tchild.children,\n\t\t\tpredicate,\n\t\t\ttransform,\n\t\t);\n\t\tif (result) {\n\t\t\tchanged = true;\n\t\t\treturn { ...child, children: result };\n\t\t}\n\t\treturn child;\n\t});\n\n\treturn changed ? newChildren : null;\n}\n","/**\n * Pure functions for manipulating inline content (TextNode / InlineNode arrays).\n * Extracted from StepApplication.ts to keep files under ~500 lines.\n */\n\nimport {\n\ttype ChildNode,\n\ttype ContentSegment,\n\ttype InlineNode,\n\ttype Mark,\n\ttype TextNode,\n\taddMarkToSet,\n\tcontentSegmentToInlineNode,\n\tcreateTextNode,\n\tisInlineNode,\n\tisTextNode,\n\tmarksEqual,\n\tremoveMarkFromSet,\n} from '../model/Document.js';\nimport type { MarkTypeName } from '../model/TypeBrands.js';\n\n/**\n * Inserts text into mixed inline content at the given offset.\n * Handles both TextNode and InlineNode children.\n */\nexport function insertTextIntoInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\ttext: string,\n\tmarks: readonly Mark[],\n): (TextNode | InlineNode)[] {\n\treturn insertIntoInlineContent(nodes, offset, () => [createTextNode(text, marks)]);\n}\n\n/**\n * Inserts content segments (text and inline nodes) into mixed inline content\n * at the given offset. Inline segments are restored as atomic nodes, so this\n * round-trips the payload captured by `getBlockContentSegmentsInRange`.\n */\nexport function insertSegmentsIntoInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tsegments: readonly ContentSegment[],\n): (TextNode | InlineNode)[] {\n\treturn insertIntoInlineContent(nodes, offset, () => segments.map(contentSegmentToInlineNode));\n}\n\n/** Shared insertion logic for text and segments into mixed inline content. */\nfunction insertIntoInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tcreateInsertedNodes: () => readonly (TextNode | InlineNode)[],\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\tlet inserted = false;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (!inserted && offset === pos) {\n\t\t\t\tresult.push(...createInsertedNodes());\n\t\t\t\tinserted = true;\n\t\t\t}\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (!inserted && offset >= pos && offset <= nodeEnd) {\n\t\t\tconst localOffset: number = offset - pos;\n\t\t\tconst before: string = node.text.slice(0, localOffset);\n\t\t\tconst after: string = node.text.slice(localOffset);\n\n\t\t\tif (before) result.push(createTextNode(before, node.marks));\n\t\t\tresult.push(...createInsertedNodes());\n\t\t\tif (after) result.push(createTextNode(after, node.marks));\n\t\t\tinserted = true;\n\t\t} else {\n\t\t\tresult.push(node);\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (!inserted) {\n\t\tresult.push(...createInsertedNodes());\n\t}\n\n\treturn result;\n}\n\n/**\n * Deletes content from mixed inline content in the given range.\n * Removes InlineNodes that fall within the range.\n */\nexport function deleteFromInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tconst nodeEnd: number = pos + 1;\n\t\t\t// Keep if outside the delete range\n\t\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tresult.push(node);\n\t\t} else {\n\t\t\tconst deleteFrom: number = Math.max(0, from - pos);\n\t\t\tconst deleteTo: number = Math.min(node.text.length, to - pos);\n\t\t\tconst remaining: string = node.text.slice(0, deleteFrom) + node.text.slice(deleteTo);\n\t\t\tif (remaining.length > 0) {\n\t\t\t\tresult.push(createTextNode(remaining, node.marks));\n\t\t\t}\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\treturn result;\n}\n\n/**\n * Slices mixed inline content to the given range.\n * InlineNodes are preserved as atoms (included if within range).\n */\nexport function sliceInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tconst nodeEnd: number = pos + 1;\n\t\t\tif (nodeEnd > from && pos < to) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\t// Outside the slice range\n\t\t} else {\n\t\t\tconst sliceFrom: number = Math.max(0, from - pos);\n\t\t\tconst sliceTo: number = Math.min(node.text.length, to - pos);\n\t\t\tconst text: string = node.text.slice(sliceFrom, sliceTo);\n\t\t\tif (text.length > 0) {\n\t\t\t\tresult.push(createTextNode(text, node.marks));\n\t\t\t}\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (result.length === 0) {\n\t\tresult.push(createTextNode(''));\n\t}\n\n\treturn result;\n}\n\n/**\n * Applies or removes a mark from mixed inline content in the given range.\n * InlineNodes are passed through unchanged (marks only apply to text).\n */\nexport function applyMarkToInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n\tmark: Mark,\n\tadd: boolean,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tresult.push(node);\n\t\t} else if (pos >= from && nodeEnd <= to) {\n\t\t\tconst newMarks: readonly Mark[] = add\n\t\t\t\t? addMarkToSet(node.marks, mark)\n\t\t\t\t: removeMarkFromSet(node.marks, mark.type);\n\t\t\tresult.push(createTextNode(node.text, newMarks));\n\t\t} else {\n\t\t\tconst overlapStart: number = Math.max(0, from - pos);\n\t\t\tconst overlapEnd: number = Math.min(node.text.length, to - pos);\n\n\t\t\tconst beforeText: string = node.text.slice(0, overlapStart);\n\t\t\tconst insideText: string = node.text.slice(overlapStart, overlapEnd);\n\t\t\tconst afterText: string = node.text.slice(overlapEnd);\n\n\t\t\tif (beforeText) result.push(createTextNode(beforeText, node.marks));\n\t\t\tif (insideText) {\n\t\t\t\tconst newMarks: readonly Mark[] = add\n\t\t\t\t\t? addMarkToSet(node.marks, mark)\n\t\t\t\t\t: removeMarkFromSet(node.marks, mark.type);\n\t\t\t\tresult.push(createTextNode(insideText, newMarks));\n\t\t\t}\n\t\t\tif (afterText) result.push(createTextNode(afterText, node.marks));\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\treturn result;\n}\n\n/**\n * Maximal sub-ranges within [from, to) where no text node carries a mark\n * of type `markType`. InlineNodes are inert: they pass through and do not\n * break coalescing, but a range never starts on an InlineNode.\n *\n * Used by `TransactionBuilder.addMark` to emit `AddMarkStep`s only over\n * sub-ranges that actually lack the mark, so the symmetric inverse\n * preserves any marks that pre-existed.\n */\nexport function findRangesMissingMark(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n\tmarkType: MarkTypeName,\n): readonly { readonly from: number; readonly to: number }[] {\n\tconst result: { from: number; to: number }[] = [];\n\tif (from >= to) return result;\n\tlet current: { from: number; to: number } | null = null;\n\tlet pos = 0;\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tresult.push(current);\n\t\t\tcurrent = null;\n\t\t}\n\t};\n\n\tfor (const node of nodes) {\n\t\tconst nodeLength: number = isInlineNode(node) ? 1 : node.text.length;\n\t\tconst nodeEnd: number = pos + nodeLength;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst overlapStart: number = Math.max(pos, from);\n\t\tconst overlapEnd: number = Math.min(nodeEnd, to);\n\n\t\tif (isInlineNode(node)) {\n\t\t\tif (current) current.to = overlapEnd;\n\t\t} else if (node.marks.some((m) => m.type === markType)) {\n\t\t\tflush();\n\t\t} else if (current) {\n\t\t\tcurrent.to = overlapEnd;\n\t\t} else {\n\t\t\tcurrent = { from: overlapStart, to: overlapEnd };\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tflush();\n\treturn result;\n}\n\n/**\n * Maximal sub-ranges within [from, to) where every text node carries a mark\n * of type `markType`. Each range is paired with the actual mark from the\n * document (including attrs). Adjacent sub-ranges coalesce only when their\n * marks are `marksEqual`. InlineNodes are inert: they pass through and do\n * not break coalescing, but a range never starts on an InlineNode.\n *\n * Used by `TransactionBuilder.removeMark` to emit `RemoveMarkStep`s whose\n * `mark` reflects the actual document content, so the symmetric inverse\n * restores attrs faithfully.\n */\nexport function findRangesWithMark(\n\tnodes: readonly (TextNode | InlineNode)[],\n\tfrom: number,\n\tto: number,\n\tmarkType: MarkTypeName,\n): readonly { readonly from: number; readonly to: number; readonly mark: Mark }[] {\n\tconst result: { from: number; to: number; mark: Mark }[] = [];\n\tif (from >= to) return result;\n\tlet current: { from: number; to: number; mark: Mark } | null = null;\n\tlet pos = 0;\n\n\tconst flush = (): void => {\n\t\tif (current) {\n\t\t\tresult.push(current);\n\t\t\tcurrent = null;\n\t\t}\n\t};\n\n\tfor (const node of nodes) {\n\t\tconst nodeLength: number = isInlineNode(node) ? 1 : node.text.length;\n\t\tconst nodeEnd: number = pos + nodeLength;\n\n\t\tif (nodeEnd <= from || pos >= to) {\n\t\t\tpos = nodeEnd;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst overlapStart: number = Math.max(pos, from);\n\t\tconst overlapEnd: number = Math.min(nodeEnd, to);\n\n\t\tif (isInlineNode(node)) {\n\t\t\tif (current) current.to = overlapEnd;\n\t\t} else {\n\t\t\tconst actual: Mark | undefined = node.marks.find((m) => m.type === markType);\n\t\t\tif (!actual) {\n\t\t\t\tflush();\n\t\t\t} else if (current && marksEqual(current.mark, actual)) {\n\t\t\t\tcurrent.to = overlapEnd;\n\t\t\t} else {\n\t\t\t\tflush();\n\t\t\t\tcurrent = { from: overlapStart, to: overlapEnd, mark: actual };\n\t\t\t}\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tflush();\n\treturn result;\n}\n\n/** Inserts an InlineNode at the given offset in mixed inline content. */\nexport function insertInlineNodeAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tinlineNode: InlineNode,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\tlet inserted = false;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (!inserted && offset === pos) {\n\t\t\t\tresult.push(inlineNode);\n\t\t\t\tinserted = true;\n\t\t\t}\n\t\t\tresult.push(node);\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nodeEnd: number = pos + node.text.length;\n\n\t\tif (!inserted && offset >= pos && offset <= nodeEnd) {\n\t\t\tconst localOffset: number = offset - pos;\n\t\t\tconst before: string = node.text.slice(0, localOffset);\n\t\t\tconst after: string = node.text.slice(localOffset);\n\n\t\t\tif (before) result.push(createTextNode(before, node.marks));\n\t\t\tresult.push(inlineNode);\n\t\t\tif (after) result.push(createTextNode(after, node.marks));\n\t\t\tinserted = true;\n\t\t} else {\n\t\t\tresult.push(node);\n\t\t}\n\n\t\tpos = nodeEnd;\n\t}\n\n\tif (!inserted) {\n\t\tresult.push(inlineNode);\n\t}\n\n\treturn result;\n}\n\n/** Removes the InlineNode at the given offset from mixed inline content. */\nexport function removeInlineNodeAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (pos !== offset) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push(node);\n\t\tpos += node.text.length;\n\t}\n\n\treturn result;\n}\n\n/** Replaces the attrs of an InlineNode at the given offset. */\nexport function setInlineNodeAttrsAtOffset(\n\tnodes: readonly (TextNode | InlineNode)[],\n\toffset: number,\n\tattrs: Readonly<Record<string, string | number | boolean>>,\n): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tlet pos = 0;\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tif (pos === offset) {\n\t\t\t\tresult.push({ ...node, attrs });\n\t\t\t} else {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t\tpos += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push(node);\n\t\tpos += node.text.length;\n\t}\n\n\treturn result;\n}\n\n/**\n * Replaces the inline content children of a ChildNode array,\n * preserving any BlockNode children in their original positions.\n */\nexport function replaceInlineChildren(\n\toriginal: readonly ChildNode[],\n\tnewInlineChildren: readonly (TextNode | InlineNode)[],\n): readonly ChildNode[] {\n\t// Fast path: if no block children exist, just return new inline nodes\n\tif (original.every((c) => isTextNode(c) || isInlineNode(c))) {\n\t\treturn newInlineChildren;\n\t}\n\t// Mixed: put inline nodes first, then block nodes (preserves structure)\n\tconst blockChildren: ChildNode[] = original.filter((c) => !isTextNode(c) && !isInlineNode(c));\n\treturn [...newInlineChildren, ...blockChildren];\n}\n","/**\n * Per-step apply functions: each transforms a Document by applying a single\n * Step of the matching type. Dispatch lives in `StepHandlers.ts`, which pairs\n * each function with its inverse counterpart in `StepInversion.ts`.\n */\n\nimport {\n\ttype BlockAttrs,\n\ttype BlockNode,\n\ttype ChildNode,\n\ttype Document,\n\ttype InlineNode,\n\ttype TextNode,\n\tcreateBlockNode,\n\tgetBlockLength,\n\tgetInlineChildren,\n\tisBlockNode,\n\tnormalizeInlineContent,\n} from '../model/Document.js';\nimport type { NodeTypeName } from '../model/TypeBrands.js';\nimport { findAndTransformChildren, mapBlock, mapNodeByPath } from './BlockTreeOps.js';\nimport {\n\tapplyMarkToInlineContent,\n\tdeleteFromInlineContent,\n\tinsertInlineNodeAtOffset,\n\tinsertSegmentsIntoInlineContent,\n\tinsertTextIntoInlineContent,\n\tremoveInlineNodeAtOffset,\n\treplaceInlineChildren,\n\tsetInlineNodeAttrsAtOffset,\n\tsliceInlineContent,\n} from './InlineContentOps.js';\nimport type {\n\tAddMarkStep,\n\tDeleteTextStep,\n\tInsertInlineNodeStep,\n\tInsertNodeStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveInlineNodeStep,\n\tRemoveMarkStep,\n\tRemoveNodeStep,\n\tSetBlockTypeStep,\n\tSetInlineNodeAttrStep,\n\tSetNodeAttrStep,\n\tSplitBlockStep,\n} from './Transaction.js';\n\nexport function applyInsertText(doc: Document, step: InsertTextStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tstep.segments\n\t\t\t? insertSegmentsIntoInlineContent(inline, step.offset, step.segments)\n\t\t\t: insertTextIntoInlineContent(inline, step.offset, step.text, step.marks),\n\t);\n}\n\nexport function applyDeleteText(doc: Document, step: DeleteTextStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tdeleteFromInlineContent(inline, step.from, step.to),\n\t);\n}\n\nexport function applySplitBlock(doc: Document, step: SplitBlockStep): Document {\n\tconst splitAtLevel = (children: readonly ChildNode[]): readonly ChildNode[] => {\n\t\tconst blockIndex: number = children.findIndex((c) => isBlockNode(c) && c.id === step.blockId);\n\t\tif (blockIndex === -1) return children;\n\n\t\tconst block: BlockNode = children[blockIndex] as BlockNode;\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst len: number = getBlockLength(block);\n\t\tconst nodesBeforeSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\t0,\n\t\t\tstep.offset,\n\t\t);\n\t\tconst nodesAfterSplit: (TextNode | InlineNode)[] = sliceInlineContent(\n\t\t\tinlineChildren,\n\t\t\tstep.offset,\n\t\t\tlen,\n\t\t);\n\n\t\tconst updatedBlock: BlockNode = {\n\t\t\t...block,\n\t\t\tchildren: normalizeInlineContent(nodesBeforeSplit),\n\t\t};\n\n\t\t// When the step carries overrides (typically produced by inverting a\n\t\t// cross-type merge), use the captured source identity verbatim so\n\t\t// undo restores the original block. An absent override means the new\n\t\t// block inherits the target block's type/attrs, matching the natural\n\t\t// outcome of a user-initiated split.\n\t\tconst hasOverride: boolean = step.newBlockType !== undefined;\n\t\tconst newType: NodeTypeName = step.newBlockType ?? block.type;\n\t\tconst newAttrs: BlockAttrs | undefined = hasOverride ? step.newBlockAttrs : block.attrs;\n\n\t\tconst newBlock: BlockNode = createBlockNode(\n\t\t\tnewType,\n\t\t\tnormalizeInlineContent(nodesAfterSplit),\n\t\t\tstep.newBlockId,\n\t\t\tnewAttrs,\n\t\t);\n\n\t\tconst result: ChildNode[] = [...children];\n\t\tresult.splice(blockIndex, 1, updatedBlock, newBlock);\n\t\treturn result;\n\t};\n\n\tconst hasTarget = (children: readonly ChildNode[]): boolean =>\n\t\tchildren.some((c) => isBlockNode(c) && c.id === step.blockId);\n\n\tconst transformed: readonly ChildNode[] | null = findAndTransformChildren(\n\t\tdoc.children,\n\t\thasTarget,\n\t\tsplitAtLevel,\n\t);\n\treturn transformed ? { children: transformed as BlockNode[] } : doc;\n}\n\nexport function applyMergeBlocks(doc: Document, step: MergeBlocksStep): Document {\n\tconst mergeAtLevel = (children: readonly ChildNode[]): readonly ChildNode[] => {\n\t\tconst targetIdx: number = children.findIndex(\n\t\t\t(c) => isBlockNode(c) && c.id === step.targetBlockId,\n\t\t);\n\t\tconst sourceIdx: number = children.findIndex(\n\t\t\t(c) => isBlockNode(c) && c.id === step.sourceBlockId,\n\t\t);\n\t\tif (targetIdx === -1 || sourceIdx === -1) return children;\n\n\t\tconst target: BlockNode = children[targetIdx] as BlockNode;\n\t\tconst source: BlockNode = children[sourceIdx] as BlockNode;\n\t\tconst targetInline: readonly (TextNode | InlineNode)[] = getInlineChildren(target);\n\t\tconst sourceInline: readonly (TextNode | InlineNode)[] = getInlineChildren(source);\n\t\tconst mergedChildren: readonly (TextNode | InlineNode)[] = normalizeInlineContent([\n\t\t\t...targetInline,\n\t\t\t...sourceInline,\n\t\t]);\n\t\tconst mergedBlock: BlockNode = { ...target, children: mergedChildren };\n\n\t\tconst filtered: ChildNode[] = children.filter(\n\t\t\t(c) => !isBlockNode(c) || c.id !== step.sourceBlockId,\n\t\t);\n\t\treturn filtered.map((c) => (isBlockNode(c) && c.id === step.targetBlockId ? mergedBlock : c));\n\t};\n\n\tconst hasTargetAndSource = (children: readonly ChildNode[]): boolean =>\n\t\tchildren.some((c) => isBlockNode(c) && c.id === step.targetBlockId) &&\n\t\tchildren.some((c) => isBlockNode(c) && c.id === step.sourceBlockId);\n\n\tconst transformed: readonly ChildNode[] | null = findAndTransformChildren(\n\t\tdoc.children,\n\t\thasTargetAndSource,\n\t\tmergeAtLevel,\n\t);\n\treturn transformed ? { children: transformed as BlockNode[] } : doc;\n}\n\nexport function applyAddMark(doc: Document, step: AddMarkStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tapplyMarkToInlineContent(inline, step.from, step.to, step.mark, true),\n\t);\n}\n\nexport function applyRemoveMark(doc: Document, step: RemoveMarkStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tapplyMarkToInlineContent(inline, step.from, step.to, step.mark, false),\n\t);\n}\n\n/**\n * Stored marks live on EditorState, not on the Document, so applying this\n * step at the document level is a no-op. The state-level update happens in\n * `EditorState.apply()`.\n */\nexport function applySetStoredMarks(doc: Document): Document {\n\treturn doc;\n}\n\n// --- InlineNode Step Application ---\n\nexport function applyInsertInlineNode(doc: Document, step: InsertInlineNodeStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tinsertInlineNodeAtOffset(inline, step.offset, step.node),\n\t);\n}\n\nexport function applyRemoveInlineNode(doc: Document, step: RemoveInlineNodeStep): Document {\n\treturn mapBlockInlineContent(doc, step.blockId, (inline) =>\n\t\tremoveInlineNodeAtOffset(inline, step.offset),\n\t);\n}\n\nexport function applySetInlineNodeAttr(doc: Document, step: SetInlineNodeAttrStep): Document {\n\treturn mapBlockInlineContent(\n\t\tdoc,\n\t\tstep.blockId,\n\t\t(inline) => setInlineNodeAttrsAtOffset(inline, step.offset, step.attrs),\n\t\tfalse,\n\t);\n}\n\n/** Maps inline content of a block, optionally normalizing the result. */\nfunction mapBlockInlineContent(\n\tdoc: Document,\n\tblockId: string,\n\tfn: (inline: readonly (TextNode | InlineNode)[]) => (TextNode | InlineNode)[],\n\tnormalize = true,\n): Document {\n\treturn mapBlock(doc, blockId, (block) => {\n\t\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\t\tconst newChildren: (TextNode | InlineNode)[] = fn(inlineChildren);\n\t\treturn {\n\t\t\t...block,\n\t\t\tchildren: replaceInlineChildren(\n\t\t\t\tblock.children,\n\t\t\t\tnormalize ? normalizeInlineContent(newChildren) : newChildren,\n\t\t\t),\n\t\t};\n\t});\n}\n\nexport function applySetBlockType(doc: Document, step: SetBlockTypeStep): Document {\n\treturn mapBlock(doc, step.blockId, (block) => {\n\t\tconst { attrs: _previousAttrs, ...rest } = block;\n\t\treturn {\n\t\t\t...rest,\n\t\t\ttype: step.nodeType,\n\t\t\t...(step.attrs ? { attrs: step.attrs } : {}),\n\t\t};\n\t});\n}\n\n// --- Structural Step Application ---\n\nexport function applyInsertNode(doc: Document, step: InsertNodeStep): Document {\n\tif (step.parentPath.length === 0) {\n\t\t// Insert at document root\n\t\tconst newChildren: BlockNode[] = [...doc.children];\n\t\tnewChildren.splice(step.index, 0, step.node);\n\t\treturn { children: newChildren };\n\t}\n\n\treturn mapNodeByPath(doc, step.parentPath, (parent) => {\n\t\tconst newChildren: ChildNode[] = [...parent.children];\n\t\tnewChildren.splice(step.index, 0, step.node);\n\t\treturn { ...parent, children: newChildren };\n\t});\n}\n\nexport function applyRemoveNode(doc: Document, step: RemoveNodeStep): Document {\n\tif (step.parentPath.length === 0) {\n\t\t// Remove from document root\n\t\tconst newChildren: BlockNode[] = [...doc.children];\n\t\tnewChildren.splice(step.index, 1);\n\t\treturn { children: newChildren };\n\t}\n\n\treturn mapNodeByPath(doc, step.parentPath, (parent) => {\n\t\tconst newChildren: ChildNode[] = [...parent.children];\n\t\tnewChildren.splice(step.index, 1);\n\t\treturn { ...parent, children: newChildren };\n\t});\n}\n\nexport function applySetNodeAttr(doc: Document, step: SetNodeAttrStep): Document {\n\tconst nodeId: string | undefined = step.path[step.path.length - 1];\n\tif (!nodeId) return doc;\n\n\treturn mapBlock(doc, nodeId, (block) => ({\n\t\t...block,\n\t\tattrs: step.attrs,\n\t}));\n}\n","/**\n * ContentSlice: an immutable fragment of document content for paste operations.\n * Represents \"what to insert\" independent of where it will be inserted.\n */\n\nimport type { BlockAttrs, ContentSegment } from './Document.js';\nimport { textSegment } from './Document.js';\nimport type { NodeTypeName } from './TypeBrands.js';\nimport { nodeType } from './TypeBrands.js';\n\nexport interface SliceBlock {\n\treadonly type: NodeTypeName;\n\treadonly attrs?: BlockAttrs;\n\t/** Inline content: text segments (with marks) and atomic inline nodes. */\n\treadonly segments: readonly ContentSegment[];\n}\n\nexport interface ContentSlice {\n\treadonly blocks: readonly SliceBlock[];\n}\n\n/** Returns the offset-space length of a block's segments (inline nodes count as 1). */\nexport function segmentsLength(segments: readonly ContentSegment[]): number {\n\treturn segments.reduce(\n\t\t(acc: number, s: ContentSegment) => acc + (s.kind === 'inline' ? 1 : s.text.length),\n\t\t0,\n\t);\n}\n\n/** Creates a content slice from plain text, one paragraph block per line. */\nexport function plainTextSlice(text: string): ContentSlice {\n\tconst lines: readonly string[] = text.split(/\\r?\\n/);\n\treturn {\n\t\tblocks: lines.map(\n\t\t\t(line: string): SliceBlock => ({\n\t\t\t\ttype: nodeType('paragraph'),\n\t\t\t\tsegments: [textSegment(line)],\n\t\t\t}),\n\t\t),\n\t};\n}\n","/**\n * Step type definitions for the transaction system.\n * Each step represents an atomic, invertible change to the document.\n */\n\nimport { segmentsLength } from '../model/ContentSlice.js';\nimport type { BlockAttrs, BlockNode, ContentSegment, InlineNode, Mark } from '../model/Document.js';\nimport type { BlockId, NodeTypeName } from '../model/TypeBrands.js';\n\nexport interface InsertTextStep {\n\treadonly type: 'insertText';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n\t/**\n\t * Optional per-segment payload (text with marks, or atomic inline nodes).\n\t * When present it supersedes `text`/`marks` on apply, so it must carry the\n\t * full content, including any inline nodes, for paste and delete-undo to\n\t * round-trip faithfully.\n\t */\n\treadonly segments?: readonly ContentSegment[];\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface DeleteTextStep {\n\treadonly type: 'deleteText';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly deletedText: string;\n\treadonly deletedMarks: readonly Mark[];\n\t/** Full deleted content (text and inline nodes) so undo restores both. */\n\treadonly deletedSegments: readonly ContentSegment[];\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SplitBlockStep {\n\treadonly type: 'splitBlock';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly newBlockId: BlockId;\n\t/**\n\t * Override for the new block's node type. When present, the new block is\n\t * created with this type instead of inheriting from the target. Populated\n\t * by {@link invertMergeBlocks} so undo can restore the original source\n\t * block's identity across cross-type merges.\n\t */\n\treadonly newBlockType?: NodeTypeName;\n\t/**\n\t * Override for the new block's attrs. Only consulted when\n\t * {@link newBlockType} is also present; the override pair is taken\n\t * as-is (an absent value here means \"the source block had no attrs\").\n\t */\n\treadonly newBlockAttrs?: BlockAttrs;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface MergeBlocksStep {\n\treadonly type: 'mergeBlocks';\n\treadonly targetBlockId: BlockId;\n\treadonly sourceBlockId: BlockId;\n\treadonly targetLengthBefore: number;\n\t/**\n\t * Source block's node type at merge time. Captured by the builder so the\n\t * inverse split can restore the source block with its original identity.\n\t */\n\treadonly sourceType?: NodeTypeName;\n\t/** Source block's attrs at merge time, if any. */\n\treadonly sourceAttrs?: BlockAttrs;\n\treadonly path?: readonly BlockId[];\n}\n\n/**\n * Adds `mark` to every text node in `[from, to)`.\n *\n * **Builder invariant** (enforced by `TransactionBuilder.addMark`): the range\n * carries no text node with a mark of `mark.type`. Steps emitted under this\n * invariant invert exactly to a `RemoveMarkStep` over the same range, so undo\n * cannot strip pre-existing marks. Direct step construction (rare; e.g.\n * middleware) must uphold the same precondition.\n */\nexport interface AddMarkStep {\n\treadonly type: 'addMark';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly mark: Mark;\n\treadonly path?: readonly BlockId[];\n}\n\n/**\n * Removes the mark of `mark.type` from every text node in `[from, to)`.\n *\n * **Builder invariant** (enforced by `TransactionBuilder.removeMark`): every\n * text node in the range carries exactly `mark` (deep equality, including\n * attrs). The `mark` field therefore stores the actual document mark, which\n * the symmetric inverse (`AddMarkStep`) re-adds verbatim, preserving attrs\n * through undo. Direct step construction must uphold the same precondition.\n */\nexport interface RemoveMarkStep {\n\treadonly type: 'removeMark';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly mark: Mark;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SetStoredMarksStep {\n\treadonly type: 'setStoredMarks';\n\treadonly marks: readonly Mark[] | null;\n\treadonly previousMarks: readonly Mark[] | null;\n}\n\nexport interface SetBlockTypeStep {\n\treadonly type: 'setBlockType';\n\treadonly blockId: BlockId;\n\treadonly nodeType: NodeTypeName;\n\treadonly attrs?: BlockAttrs;\n\treadonly previousNodeType: NodeTypeName;\n\treadonly previousAttrs?: BlockAttrs;\n\treadonly path?: readonly BlockId[];\n}\n\n// --- Structural Steps (for nested documents) ---\n\nexport interface InsertNodeStep {\n\treadonly type: 'insertNode';\n\treadonly parentPath: readonly BlockId[];\n\treadonly index: number;\n\treadonly node: BlockNode;\n}\n\nexport interface RemoveNodeStep {\n\treadonly type: 'removeNode';\n\treadonly parentPath: readonly BlockId[];\n\treadonly index: number;\n\treadonly removedNode: BlockNode;\n}\n\nexport interface SetNodeAttrStep {\n\treadonly type: 'setNodeAttr';\n\treadonly path: readonly BlockId[];\n\treadonly attrs: BlockAttrs | undefined;\n\treadonly previousAttrs?: BlockAttrs;\n}\n\n// --- InlineNode Steps ---\n\nexport interface InsertInlineNodeStep {\n\treadonly type: 'insertInlineNode';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly node: InlineNode;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface RemoveInlineNodeStep {\n\treadonly type: 'removeInlineNode';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly removedNode: InlineNode;\n\treadonly path?: readonly BlockId[];\n}\n\nexport interface SetInlineNodeAttrStep {\n\treadonly type: 'setInlineNodeAttr';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly attrs: Readonly<Record<string, string | number | boolean>>;\n\treadonly previousAttrs: Readonly<Record<string, string | number | boolean>>;\n\treadonly path?: readonly BlockId[];\n}\n\nexport type Step =\n\t| InsertTextStep\n\t| DeleteTextStep\n\t| SplitBlockStep\n\t| MergeBlocksStep\n\t| AddMarkStep\n\t| RemoveMarkStep\n\t| SetStoredMarksStep\n\t| SetBlockTypeStep\n\t| InsertNodeStep\n\t| RemoveNodeStep\n\t| SetNodeAttrStep\n\t| InsertInlineNodeStep\n\t| RemoveInlineNodeStep\n\t| SetInlineNodeAttrStep;\n\nexport type TransactionOrigin = 'input' | 'paste' | 'command' | 'history' | 'api';\n\n/**\n * Block-space width an {@link InsertTextStep} occupies once applied. When the\n * step carries `segments` (which may include inline nodes, each width 1), the\n * width is the segment span, not the plain-text length, because `applyInsertText`\n * inserts the segments verbatim. The inverse delete range ({@link invertInsertText})\n * and the forward position map ({@link getMapInsertText}) must both use this so\n * undo/redo of a deletion that removed inline content round-trips without\n * corrupting positions.\n */\nexport function insertTextStepWidth(step: InsertTextStep): number {\n\treturn step.segments ? segmentsLength(step.segments) : step.text.length;\n}\n","/**\n * Per-step invert functions: each returns the inverse of a single step\n * for undo/redo support. Dispatch and transaction-level inversion live in\n * `StepHandlers.ts`, which pairs each function with its forward counterpart\n * in `StepApplication.ts`.\n */\n\nimport type { Mark } from '../model/Document.js';\nimport { textSegment } from '../model/Document.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport { insertTextStepWidth } from './Steps.js';\nimport type {\n\tAddMarkStep,\n\tDeleteTextStep,\n\tInsertInlineNodeStep,\n\tInsertNodeStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveInlineNodeStep,\n\tRemoveMarkStep,\n\tRemoveNodeStep,\n\tSetBlockTypeStep,\n\tSetInlineNodeAttrStep,\n\tSetNodeAttrStep,\n\tSetStoredMarksStep,\n\tSplitBlockStep,\n\tStep,\n} from './Steps.js';\nimport type { Transaction } from './Transaction.js';\n\n/** Returns a path spread object if the step has a path, or empty object otherwise. */\nfunction optionalPath(step: { readonly path?: readonly BlockId[] }):\n\t| { readonly path: readonly BlockId[] }\n\t| Record<string, never> {\n\treturn step.path ? { path: step.path } : {};\n}\n\nexport function invertInsertText(step: InsertTextStep): Step {\n\treturn {\n\t\ttype: 'deleteText',\n\t\tblockId: step.blockId,\n\t\tfrom: step.offset,\n\t\tto: step.offset + insertTextStepWidth(step),\n\t\tdeletedText: step.text,\n\t\tdeletedMarks: step.marks,\n\t\tdeletedSegments: step.segments ?? [textSegment(step.text, [...step.marks])],\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertDeleteText(step: DeleteTextStep): Step {\n\treturn {\n\t\ttype: 'insertText',\n\t\tblockId: step.blockId,\n\t\toffset: step.from,\n\t\ttext: step.deletedText,\n\t\tmarks: step.deletedMarks,\n\t\tsegments: step.deletedSegments,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertSplitBlock(step: SplitBlockStep): Step {\n\treturn {\n\t\ttype: 'mergeBlocks',\n\t\ttargetBlockId: step.blockId,\n\t\tsourceBlockId: step.newBlockId,\n\t\ttargetLengthBefore: step.offset,\n\t\t...(step.newBlockType !== undefined ? { sourceType: step.newBlockType } : {}),\n\t\t...(step.newBlockAttrs ? { sourceAttrs: step.newBlockAttrs } : {}),\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertMergeBlocks(step: MergeBlocksStep): Step {\n\treturn {\n\t\ttype: 'splitBlock',\n\t\tblockId: step.targetBlockId,\n\t\toffset: step.targetLengthBefore,\n\t\tnewBlockId: step.sourceBlockId,\n\t\t...(step.sourceType !== undefined ? { newBlockType: step.sourceType } : {}),\n\t\t...(step.sourceAttrs ? { newBlockAttrs: step.sourceAttrs } : {}),\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertAddMark(step: AddMarkStep): Step {\n\treturn {\n\t\ttype: 'removeMark',\n\t\tblockId: step.blockId,\n\t\tfrom: step.from,\n\t\tto: step.to,\n\t\tmark: step.mark,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertRemoveMark(step: RemoveMarkStep): Step {\n\treturn {\n\t\ttype: 'addMark',\n\t\tblockId: step.blockId,\n\t\tfrom: step.from,\n\t\tto: step.to,\n\t\tmark: step.mark,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertSetStoredMarks(step: SetStoredMarksStep): Step {\n\treturn {\n\t\ttype: 'setStoredMarks',\n\t\tmarks: step.previousMarks,\n\t\tpreviousMarks: step.marks,\n\t};\n}\n\nexport function invertSetBlockType(step: SetBlockTypeStep): Step {\n\treturn {\n\t\ttype: 'setBlockType',\n\t\tblockId: step.blockId,\n\t\tnodeType: step.previousNodeType,\n\t\tattrs: step.previousAttrs,\n\t\tpreviousNodeType: step.nodeType,\n\t\tpreviousAttrs: step.attrs,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertInsertNode(step: InsertNodeStep): Step {\n\treturn {\n\t\ttype: 'removeNode',\n\t\tparentPath: step.parentPath,\n\t\tindex: step.index,\n\t\tremovedNode: step.node,\n\t};\n}\n\nexport function invertRemoveNode(step: RemoveNodeStep): Step {\n\treturn {\n\t\ttype: 'insertNode',\n\t\tparentPath: step.parentPath,\n\t\tindex: step.index,\n\t\tnode: step.removedNode,\n\t};\n}\n\nexport function invertSetNodeAttr(step: SetNodeAttrStep): Step {\n\treturn {\n\t\ttype: 'setNodeAttr',\n\t\tpath: step.path,\n\t\tattrs: step.previousAttrs,\n\t\tpreviousAttrs: step.attrs,\n\t};\n}\n\nexport function invertInsertInlineNode(step: InsertInlineNodeStep): Step {\n\treturn {\n\t\ttype: 'removeInlineNode',\n\t\tblockId: step.blockId,\n\t\toffset: step.offset,\n\t\tremovedNode: step.node,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertRemoveInlineNode(step: RemoveInlineNodeStep): Step {\n\treturn {\n\t\ttype: 'insertInlineNode',\n\t\tblockId: step.blockId,\n\t\toffset: step.offset,\n\t\tnode: step.removedNode,\n\t\t...optionalPath(step),\n\t};\n}\n\nexport function invertSetInlineNodeAttr(step: SetInlineNodeAttrStep): Step {\n\treturn {\n\t\ttype: 'setInlineNodeAttr',\n\t\tblockId: step.blockId,\n\t\toffset: step.offset,\n\t\tattrs: step.previousAttrs,\n\t\tpreviousAttrs: step.attrs,\n\t\t...optionalPath(step),\n\t};\n}\n\n/**\n * Walks the transaction's steps to find the storedMarks value that was\n * active before the transaction ran, falling back to the post-state if\n * no `setStoredMarks` step was recorded.\n */\nexport function deriveStoredMarksBefore(tr: Transaction): readonly Mark[] | null {\n\tfor (const step of tr.steps) {\n\t\tif (step.type === 'setStoredMarks') {\n\t\t\treturn step.previousMarks;\n\t\t}\n\t}\n\treturn tr.storedMarksAfter;\n}\n","/**\n * Per-step rebase functions: each takes a {@link Step}, a {@link Mapping}\n * that describes intervening changes in position space, and the current\n * document state, and returns either the rebased step or `null` when the\n * step can no longer be applied meaningfully.\n *\n * This is the symmetric counterpart to {@link getStepMap} / {@link applyStep}\n * / {@link invertStep}: where `getStepMap` answers \"how do positions shift\n * **through** this step\", these `mapXxx` functions answer \"how do this\n * step's *inputs* shift through *another* mapping\". The pair is what makes\n * undo/redo robust under out-of-band intervening edits, and the same\n * primitive is the foundation any future collaborative-editing layer needs.\n *\n * ## `null`-semantics\n *\n * A `null` return is not an error — it means the step's referenced\n * coordinates no longer address live content in the current frame. Callers\n * (e.g. {@link HistoryManager.undo}) treat this as \"abandon the whole\n * undo/redo group\", because applying a partial rebase would silently\n * corrupt the document.\n *\n * Conditions that produce `null`:\n *\n * - the host block was removed by an intervening edit;\n * - a single-offset step's offset fell inside removed/replaced content;\n * - a range step's range was fully eaten;\n * - a range step's endpoints landed in different blocks (fragmented);\n * - for structural steps, an ancestor in `parentPath` was removed or\n * migrated to a new block identity.\n *\n * Dispatch is via the {@link StepHandlerRegistry} so adding a new `Step`\n * variant fails to type-check until its `map` is registered.\n */\n\nimport type { BlockNode, Document, InlineNode } from '../model/Document.js';\nimport {\n\tgetBlockContentSegmentsInRange,\n\tgetBlockLength,\n\tgetBlockMarksAtOffset,\n\tgetBlockText,\n\tgetContentAtOffset,\n\tisInlineNode,\n} from '../model/Document.js';\nimport { findNode, resolveChildAt, resolveNodeByPath } from '../model/NodeResolver.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport {\n\ttype MappedInBlockRange,\n\ttype Mapping,\n\tmapChildIndex,\n\tmapInBlockRange,\n\tmapInsertionIndex,\n\tmapOffsetInBlock,\n} from './Mapping.js';\nimport type {\n\tAddMarkStep,\n\tDeleteTextStep,\n\tInsertInlineNodeStep,\n\tInsertNodeStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveInlineNodeStep,\n\tRemoveMarkStep,\n\tRemoveNodeStep,\n\tSetBlockTypeStep,\n\tSetInlineNodeAttrStep,\n\tSetNodeAttrStep,\n\tSetStoredMarksStep,\n\tSplitBlockStep,\n\tStep,\n} from './Steps.js';\n\n// --- Helpers ---\n\n/**\n * Spreads `path` onto a rebased step only when the block identity did not\n * change. A migrated block likely sits at a different parent path, so\n * carrying the stale hint would mislead the applyStep fast-path lookup;\n * dropping it falls back to a global block-id search.\n */\nfunction preservedPath(\n\toriginalBlockId: BlockId,\n\tnewBlockId: BlockId,\n\tpath: readonly BlockId[] | undefined,\n): { readonly path: readonly BlockId[] } | Record<string, never> {\n\tif (!path) return {};\n\tif (originalBlockId !== newBlockId) return {};\n\treturn { path };\n}\n\n/**\n * Validates that every block id along `parentPath` still exists and has\n * not migrated. The `parentPath` itself is **never** rebased through\n * `childIndexShift` / `blockRemoval` (those describe shifts in *child\n * slots*, not in block identity), so when any ancestor block is gone the\n * structural anchor is lost and the step must be abandoned.\n */\nfunction parentPathStillValid(parentPath: readonly BlockId[], mapping: Mapping): boolean {\n\tif (mapping.isEmpty) return true;\n\tfor (const id of parentPath) {\n\t\tconst result = mapping.mapResult({ blockId: id, offset: 0 }, -1);\n\t\tif (result.deleted) return false;\n\t\tif (result.pos.blockId !== id) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Returns whether a rebased range is identical to the original range —\n * letting callers return the input step unchanged to preserve reference\n * equality (cheap downstream change-detection short-circuit).\n */\nfunction isRangeUnchanged(\n\toriginal: { readonly blockId: BlockId; readonly from: number; readonly to: number },\n\tmapped: MappedInBlockRange,\n): boolean {\n\treturn (\n\t\tmapped.blockId === original.blockId &&\n\t\tmapped.from === original.from &&\n\t\tmapped.to === original.to\n\t);\n}\n\n// --- Content-shifting steps ---\n\nexport function mapInsertText(step: InsertTextStep, mapping: Mapping, _doc: Document): Step | null {\n\tconst mapped = mapOffsetInBlock(step.blockId, step.offset, mapping, -1);\n\tif (!mapped) return null;\n\tif (mapped.blockId === step.blockId && mapped.from === step.offset) return step;\n\treturn {\n\t\ttype: 'insertText',\n\t\tblockId: mapped.blockId,\n\t\toffset: mapped.from,\n\t\ttext: step.text,\n\t\tmarks: step.marks,\n\t\t...(step.segments ? { segments: step.segments } : {}),\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\nexport function mapDeleteText(step: DeleteTextStep, mapping: Mapping, doc: Document): Step | null {\n\tconst mapped = mapInBlockRange(step.blockId, step.from, step.to, mapping);\n\tif (!mapped) return null;\n\tif (isRangeUnchanged({ blockId: step.blockId, from: step.from, to: step.to }, mapped)) {\n\t\treturn step;\n\t}\n\n\t// Re-snapshot the content payload from the current doc — the original\n\t// `deletedText` / `deletedSegments` / `deletedMarks` describe content that\n\t// no longer sits at the rebased range. Without the refresh, redoing this\n\t// undo would produce a step whose inverse reinserts the wrong content.\n\tconst block = findNode(doc, mapped.blockId);\n\tif (!block) return null;\n\tconst deletedText = getBlockText(block).slice(mapped.from, mapped.to);\n\tconst deletedMarks = getBlockMarksAtOffset(block, mapped.from);\n\tconst deletedSegments = getBlockContentSegmentsInRange(block, mapped.from, mapped.to);\n\n\treturn {\n\t\ttype: 'deleteText',\n\t\tblockId: mapped.blockId,\n\t\tfrom: mapped.from,\n\t\tto: mapped.to,\n\t\tdeletedText,\n\t\tdeletedMarks,\n\t\tdeletedSegments,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\nexport function mapInsertInlineNode(\n\tstep: InsertInlineNodeStep,\n\tmapping: Mapping,\n\t_doc: Document,\n): Step | null {\n\tconst mapped = mapOffsetInBlock(step.blockId, step.offset, mapping, -1);\n\tif (!mapped) return null;\n\tif (mapped.blockId === step.blockId && mapped.from === step.offset) return step;\n\treturn {\n\t\ttype: 'insertInlineNode',\n\t\tblockId: mapped.blockId,\n\t\toffset: mapped.from,\n\t\tnode: step.node,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\nexport function mapRemoveInlineNode(\n\tstep: RemoveInlineNodeStep,\n\tmapping: Mapping,\n\tdoc: Document,\n): Step | null {\n\t// Inline nodes occupy [offset, offset+1) atomically. Treating the position\n\t// as a width-1 range with sticky-right `from` is what keeps the rebased\n\t// offset pointing at the SAME slot even when intervening edits inserted\n\t// content immediately before it.\n\tconst mapped = mapInBlockRange(step.blockId, step.offset, step.offset + 1, mapping, 1, 1);\n\tif (!mapped) return null;\n\tif (mapped.to - mapped.from !== 1) return null;\n\n\t// Verify the inline at the rebased slot is still the one the user wanted\n\t// to remove. The position mapping does not track inline identity, so an\n\t// intervening `removeInlineNode` + `insertInlineNode` pair at the same\n\t// offset would shift the position by zero net while replacing the\n\t// content. Removing the substitute would corrupt the agent's edit; abandon\n\t// the group instead.\n\tconst block = findNode(doc, mapped.blockId);\n\tif (!block) return null;\n\tconst content = getContentAtOffset(block, mapped.from);\n\tif (!content || content.kind !== 'inline' || !isInlineNode(content.node)) return null;\n\tif (!inlineNodesEqual(step.removedNode, content.node)) return null;\n\n\tif (mapped.blockId === step.blockId && mapped.from === step.offset) return step;\n\treturn {\n\t\ttype: 'removeInlineNode',\n\t\tblockId: mapped.blockId,\n\t\toffset: mapped.from,\n\t\tremovedNode: content.node,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\n// --- Structural block steps ---\n\nexport function mapSplitBlock(step: SplitBlockStep, mapping: Mapping, _doc: Document): Step | null {\n\tconst mapped = mapOffsetInBlock(step.blockId, step.offset, mapping, -1);\n\tif (!mapped) return null;\n\tif (mapped.blockId === step.blockId && mapped.from === step.offset) return step;\n\treturn {\n\t\ttype: 'splitBlock',\n\t\tblockId: mapped.blockId,\n\t\toffset: mapped.from,\n\t\tnewBlockId: step.newBlockId,\n\t\t...(step.newBlockType !== undefined ? { newBlockType: step.newBlockType } : {}),\n\t\t...(step.newBlockAttrs ? { newBlockAttrs: step.newBlockAttrs } : {}),\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\nexport function mapMergeBlocks(\n\tstep: MergeBlocksStep,\n\tmapping: Mapping,\n\tdoc: Document,\n): Step | null {\n\tif (mapping.isEmpty) return step;\n\n\t// Both blocks must remain addressable as distinct entities.\n\tconst targetProbe = mapping.mapResult({ blockId: step.targetBlockId, offset: 0 }, -1);\n\tconst sourceProbe = mapping.mapResult({ blockId: step.sourceBlockId, offset: 0 }, -1);\n\tif (targetProbe.deleted || sourceProbe.deleted) return null;\n\tconst newTargetId = targetProbe.pos.blockId;\n\tconst newSourceId = sourceProbe.pos.blockId;\n\tif (newTargetId === newSourceId) return null;\n\n\t// Recompute targetLengthBefore from current doc — intervening edits inside\n\t// the target block changed its length, and applyMergeBlocks doesn't use\n\t// this field (it merges by ID), but the inverse split step does, and a\n\t// stale length would split at the wrong offset on redo.\n\tconst target = findNode(doc, newTargetId);\n\tif (!target) return null;\n\tconst targetLengthBefore = getBlockLength(target);\n\n\tif (\n\t\tnewTargetId === step.targetBlockId &&\n\t\tnewSourceId === step.sourceBlockId &&\n\t\ttargetLengthBefore === step.targetLengthBefore\n\t) {\n\t\treturn step;\n\t}\n\n\treturn {\n\t\ttype: 'mergeBlocks',\n\t\ttargetBlockId: newTargetId,\n\t\tsourceBlockId: newSourceId,\n\t\ttargetLengthBefore,\n\t\t...(step.sourceType !== undefined ? { sourceType: step.sourceType } : {}),\n\t\t...(step.sourceAttrs ? { sourceAttrs: step.sourceAttrs } : {}),\n\t\t...preservedPath(step.targetBlockId, newTargetId, step.path),\n\t};\n}\n\n// --- Mark steps ---\n\nexport function mapAddMark(step: AddMarkStep, mapping: Mapping, _doc: Document): Step | null {\n\tconst mapped = mapInBlockRange(step.blockId, step.from, step.to, mapping);\n\tif (!mapped) return null;\n\tif (isRangeUnchanged({ blockId: step.blockId, from: step.from, to: step.to }, mapped)) {\n\t\treturn step;\n\t}\n\treturn {\n\t\ttype: 'addMark',\n\t\tblockId: mapped.blockId,\n\t\tfrom: mapped.from,\n\t\tto: mapped.to,\n\t\tmark: step.mark,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\nexport function mapRemoveMark(step: RemoveMarkStep, mapping: Mapping, _doc: Document): Step | null {\n\tconst mapped = mapInBlockRange(step.blockId, step.from, step.to, mapping);\n\tif (!mapped) return null;\n\tif (isRangeUnchanged({ blockId: step.blockId, from: step.from, to: step.to }, mapped)) {\n\t\treturn step;\n\t}\n\treturn {\n\t\ttype: 'removeMark',\n\t\tblockId: mapped.blockId,\n\t\tfrom: mapped.from,\n\t\tto: mapped.to,\n\t\tmark: step.mark,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\n// --- Identity / attribute steps ---\n\nexport function mapSetStoredMarks(\n\tstep: SetStoredMarksStep,\n\t_mapping: Mapping,\n\t_doc: Document,\n): Step | null {\n\t// State-level only, no document coordinates to rebase.\n\treturn step;\n}\n\nexport function mapSetBlockType(\n\tstep: SetBlockTypeStep,\n\tmapping: Mapping,\n\tdoc: Document,\n): Step | null {\n\tif (mapping.isEmpty) return step;\n\tconst probe = mapping.mapResult({ blockId: step.blockId, offset: 0 }, -1);\n\tif (probe.deleted) return null;\n\tconst newBlockId = probe.pos.blockId;\n\n\t// Re-snapshot the previous type / attrs from the current doc so the inverse\n\t// step restores what was actually there post-intervening, not what was there\n\t// when the original step was emitted.\n\tconst block: BlockNode | undefined = findNode(doc, newBlockId);\n\tif (!block) return null;\n\n\tif (\n\t\tnewBlockId === step.blockId &&\n\t\tblock.type === step.previousNodeType &&\n\t\tblockAttrsEqual(block.attrs, step.previousAttrs)\n\t) {\n\t\treturn step;\n\t}\n\n\treturn {\n\t\ttype: 'setBlockType',\n\t\tblockId: newBlockId,\n\t\tnodeType: step.nodeType,\n\t\t...(step.attrs ? { attrs: step.attrs } : {}),\n\t\tpreviousNodeType: block.type,\n\t\t...(block.attrs ? { previousAttrs: block.attrs } : {}),\n\t\t...preservedPath(step.blockId, newBlockId, step.path),\n\t};\n}\n\nexport function mapSetNodeAttr(\n\tstep: SetNodeAttrStep,\n\tmapping: Mapping,\n\tdoc: Document,\n): Step | null {\n\tif (mapping.isEmpty) return step;\n\tif (!parentPathStillValid(step.path, mapping)) return null;\n\tconst node = resolveNodeByPath(doc, step.path);\n\tif (!node) return null;\n\treturn {\n\t\ttype: 'setNodeAttr',\n\t\tpath: step.path,\n\t\tattrs: step.attrs,\n\t\t...(node.attrs ? { previousAttrs: node.attrs } : {}),\n\t};\n}\n\nexport function mapSetInlineNodeAttr(\n\tstep: SetInlineNodeAttrStep,\n\tmapping: Mapping,\n\tdoc: Document,\n): Step | null {\n\tconst mapped = mapInBlockRange(step.blockId, step.offset, step.offset + 1, mapping, 1, 1);\n\tif (!mapped) return null;\n\tif (mapped.to - mapped.from !== 1) return null;\n\tif (mapped.blockId === step.blockId && mapped.from === step.offset) {\n\t\treturn step;\n\t}\n\n\tconst block = findNode(doc, mapped.blockId);\n\tif (!block) return null;\n\tconst content = getContentAtOffset(block, mapped.from);\n\tif (!content || content.kind !== 'inline' || !isInlineNode(content.node)) return null;\n\treturn {\n\t\ttype: 'setInlineNodeAttr',\n\t\tblockId: mapped.blockId,\n\t\toffset: mapped.from,\n\t\tattrs: step.attrs,\n\t\tpreviousAttrs: content.node.attrs,\n\t\t...preservedPath(step.blockId, mapped.blockId, step.path),\n\t};\n}\n\n// --- Tree-structural steps ---\n\nexport function mapInsertNode(step: InsertNodeStep, mapping: Mapping, _doc: Document): Step | null {\n\tif (!parentPathStillValid(step.parentPath, mapping)) return null;\n\t// Insertion-slot semantics: the slot survives even when the block\n\t// previously at this index was removed by an intervening edit. The slot\n\t// is *where to insert*, not a reference to an existing child.\n\tconst rebasedIndex: number = mapInsertionIndex(step.parentPath, step.index, mapping);\n\tif (rebasedIndex === step.index) return step;\n\treturn {\n\t\ttype: 'insertNode',\n\t\tparentPath: step.parentPath,\n\t\tindex: rebasedIndex,\n\t\tnode: step.node,\n\t};\n}\n\nexport function mapRemoveNode(step: RemoveNodeStep, mapping: Mapping, doc: Document): Step | null {\n\tif (!parentPathStillValid(step.parentPath, mapping)) return null;\n\t// The to-be-removed block itself must still exist as a distinct block.\n\tconst probe = mapping.mapResult({ blockId: step.removedNode.id, offset: 0 }, -1);\n\tif (probe.deleted) return null;\n\tif (probe.pos.blockId !== step.removedNode.id) return null;\n\n\tconst rebasedIndex: number | null = mapChildIndex(step.parentPath, step.index, mapping);\n\t// `null` means an intervening edit already removed the exact slot this\n\t// step targets; the inverse cannot meaningfully proceed.\n\tif (rebasedIndex === null) return null;\n\n\t// Re-snapshot the removed subtree from the current doc — intervening edits\n\t// may have modified the block's content (text inserted, marks toggled,\n\t// child blocks added) after the original step was recorded. Without the\n\t// refresh, the rebased step's inverse `insertNode` would restore the stale\n\t// payload and silently lose those edits on a subsequent undo. Same class\n\t// of bug as the inline identity check in {@link mapRemoveInlineNode}.\n\tconst block = resolveChildAt(doc, step.parentPath, rebasedIndex);\n\tif (!block) return null;\n\t// Defensive structural-integrity check: the rebased index must point at\n\t// the block we expect. A mismatch indicates either a mapping inconsistency\n\t// or that the slot is now occupied by a different block — either way we\n\t// must not remove an unrelated subtree.\n\tif (block.id !== step.removedNode.id) return null;\n\n\tif (rebasedIndex === step.index && block === step.removedNode) return step;\n\treturn {\n\t\ttype: 'removeNode',\n\t\tparentPath: step.parentPath,\n\t\tindex: rebasedIndex,\n\t\tremovedNode: block,\n\t};\n}\n\n// --- Local utilities ---\n\nfunction blockAttrsEqual(\n\ta: Readonly<Record<string, unknown>> | undefined,\n\tb: Readonly<Record<string, unknown>> | undefined,\n): boolean {\n\tif (a === b) return true;\n\tif (!a || !b) return false;\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\tif (aKeys.length !== bKeys.length) return false;\n\tfor (const k of aKeys) {\n\t\tif (a[k] !== b[k]) return false;\n\t}\n\treturn true;\n}\n\nfunction inlineNodesEqual(a: InlineNode, b: InlineNode): boolean {\n\tif (a === b) return true;\n\tif (a.inlineType !== b.inlineType) return false;\n\treturn blockAttrsEqual(a.attrs, b.attrs);\n}\n","/**\n * Per-step {@link StepMap} producers. Each function consumes the step plus\n * the document state **before** the step is applied (when needed) and\n * returns the StepMap that describes the position-space change.\n *\n * Dispatch is performed by `StepHandlers.ts` through the\n * `StepHandlerRegistry`, which co-locates `apply`, `invert`, and `getMap`\n * so adding a new step type is a single registry edit.\n */\n\nimport type { Document } from '../model/Document.js';\nimport {\n\ttype BlockRemovalMap,\n\ttype ChildIndexShiftMap,\n\tIDENTITY_MAP,\n\ttype MergeMap,\n\ttype ShiftMap,\n\ttype SplitMap,\n\ttype StepMap,\n\tcollectRemovedBlockIds,\n} from './Mapping.js';\nimport { insertTextStepWidth } from './Steps.js';\nimport type {\n\tAddMarkStep,\n\tDeleteTextStep,\n\tInsertInlineNodeStep,\n\tInsertNodeStep,\n\tInsertTextStep,\n\tMergeBlocksStep,\n\tRemoveInlineNodeStep,\n\tRemoveMarkStep,\n\tRemoveNodeStep,\n\tSetBlockTypeStep,\n\tSetInlineNodeAttrStep,\n\tSetNodeAttrStep,\n\tSetStoredMarksStep,\n\tSplitBlockStep,\n} from './Steps.js';\n\n// --- Content-shifting steps ---\n\nexport function getMapInsertText(_doc: Document, step: InsertTextStep): ShiftMap {\n\treturn {\n\t\ttype: 'shift',\n\t\tblockId: step.blockId,\n\t\tfrom: step.offset,\n\t\tto: step.offset,\n\t\tnewLen: insertTextStepWidth(step),\n\t};\n}\n\nexport function getMapDeleteText(_doc: Document, step: DeleteTextStep): ShiftMap {\n\treturn {\n\t\ttype: 'shift',\n\t\tblockId: step.blockId,\n\t\tfrom: step.from,\n\t\tto: step.to,\n\t\tnewLen: 0,\n\t};\n}\n\nexport function getMapInsertInlineNode(_doc: Document, step: InsertInlineNodeStep): ShiftMap {\n\treturn {\n\t\ttype: 'shift',\n\t\tblockId: step.blockId,\n\t\tfrom: step.offset,\n\t\tto: step.offset,\n\t\tnewLen: 1,\n\t};\n}\n\nexport function getMapRemoveInlineNode(_doc: Document, step: RemoveInlineNodeStep): ShiftMap {\n\treturn {\n\t\ttype: 'shift',\n\t\tblockId: step.blockId,\n\t\tfrom: step.offset,\n\t\tto: step.offset + 1,\n\t\tnewLen: 0,\n\t};\n}\n\n// --- Structural steps ---\n\nexport function getMapSplitBlock(_doc: Document, step: SplitBlockStep): SplitMap {\n\treturn {\n\t\ttype: 'split',\n\t\tblockId: step.blockId,\n\t\toffset: step.offset,\n\t\tnewBlockId: step.newBlockId,\n\t};\n}\n\nexport function getMapMergeBlocks(_doc: Document, step: MergeBlocksStep): MergeMap {\n\treturn {\n\t\ttype: 'merge',\n\t\ttargetBlockId: step.targetBlockId,\n\t\tsourceBlockId: step.sourceBlockId,\n\t\ttargetLengthBefore: step.targetLengthBefore,\n\t};\n}\n\nexport function getMapRemoveNode(_doc: Document, step: RemoveNodeStep): BlockRemovalMap {\n\treturn {\n\t\ttype: 'blockRemoval',\n\t\tremovedBlockIds: collectRemovedBlockIds(step.removedNode),\n\t\tparentPath: step.parentPath,\n\t\tindex: step.index,\n\t};\n}\n\n// --- Structural sibling shifts ---\n\n/**\n * Inserting a block at `step.index` in `step.parentPath`'s child list does\n * not move any position in `{blockId, offset}` space, but it shifts every\n * sibling index `≥ step.index` up by 1. {@link mapChildIndex} consumes this\n * to rebase later `insertNode` / `removeNode` steps that target the same\n * parent.\n */\nexport function getMapInsertNode(_doc: Document, step: InsertNodeStep): ChildIndexShiftMap {\n\treturn {\n\t\ttype: 'childIndexShift',\n\t\tparentPath: step.parentPath,\n\t\tfromIndex: step.index,\n\t\tdelta: 1,\n\t};\n}\n\n// --- Identity steps (positions unchanged) ---\n//\n// The following step types do not move offsets or child indices:\n// - addMark / removeMark: annotation only\n// - setStoredMarks: state-only\n// - setBlockType: type/attrs change, children unchanged\n// - setNodeAttr / setInlineNodeAttr: attribute-only\n\nexport function getMapAddMark(_doc: Document, _step: AddMarkStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n\nexport function getMapRemoveMark(_doc: Document, _step: RemoveMarkStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n\nexport function getMapSetStoredMarks(_doc: Document, _step: SetStoredMarksStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n\nexport function getMapSetBlockType(_doc: Document, _step: SetBlockTypeStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n\nexport function getMapSetNodeAttr(_doc: Document, _step: SetNodeAttrStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n\nexport function getMapSetInlineNodeAttr(_doc: Document, _step: SetInlineNodeAttrStep): StepMap {\n\treturn IDENTITY_MAP;\n}\n","/**\n * Single source of truth that pairs each `Step` discriminator with the\n * functions that apply, invert, and map it. The registry's mapped type\n * makes exhaustiveness a compile-time guarantee: introducing a new member\n * of the `Step` union without registering a handler is a type error here.\n *\n * Public dispatch (`applyStep`, `invertStep`, `getStepMap`,\n * `invertTransaction`) lives in this module; per-step logic lives in\n * `StepApplication.ts`, `StepInversion.ts`, and `StepMaps.ts`.\n */\n\nimport type { Document } from '../model/Document.js';\nimport { IDENTITY_MAP, Mapping, type StepMap } from './Mapping.js';\nimport {\n\tapplyAddMark,\n\tapplyDeleteText,\n\tapplyInsertInlineNode,\n\tapplyInsertNode,\n\tapplyInsertText,\n\tapplyMergeBlocks,\n\tapplyRemoveInlineNode,\n\tapplyRemoveMark,\n\tapplyRemoveNode,\n\tapplySetBlockType,\n\tapplySetInlineNodeAttr,\n\tapplySetNodeAttr,\n\tapplySetStoredMarks,\n\tapplySplitBlock,\n} from './StepApplication.js';\nimport {\n\tderiveStoredMarksBefore,\n\tinvertAddMark,\n\tinvertDeleteText,\n\tinvertInsertInlineNode,\n\tinvertInsertNode,\n\tinvertInsertText,\n\tinvertMergeBlocks,\n\tinvertRemoveInlineNode,\n\tinvertRemoveMark,\n\tinvertRemoveNode,\n\tinvertSetBlockType,\n\tinvertSetInlineNodeAttr,\n\tinvertSetNodeAttr,\n\tinvertSetStoredMarks,\n\tinvertSplitBlock,\n} from './StepInversion.js';\nimport {\n\tmapAddMark,\n\tmapDeleteText,\n\tmapInsertInlineNode,\n\tmapInsertNode,\n\tmapInsertText,\n\tmapMergeBlocks,\n\tmapRemoveInlineNode,\n\tmapRemoveMark,\n\tmapRemoveNode,\n\tmapSetBlockType,\n\tmapSetInlineNodeAttr,\n\tmapSetNodeAttr,\n\tmapSetStoredMarks,\n\tmapSplitBlock,\n} from './StepMapping.js';\nimport {\n\tgetMapAddMark,\n\tgetMapDeleteText,\n\tgetMapInsertInlineNode,\n\tgetMapInsertNode,\n\tgetMapInsertText,\n\tgetMapMergeBlocks,\n\tgetMapRemoveInlineNode,\n\tgetMapRemoveMark,\n\tgetMapRemoveNode,\n\tgetMapSetBlockType,\n\tgetMapSetInlineNodeAttr,\n\tgetMapSetNodeAttr,\n\tgetMapSetStoredMarks,\n\tgetMapSplitBlock,\n} from './StepMaps.js';\nimport type { Step } from './Steps.js';\nimport type { Transaction } from './Transaction.js';\n\n/**\n * Forward, inverse, position-mapping, and step-rebase behavior of one step\n * subtype, co-located so a new step type is one registry entry.\n *\n * - `apply` / `invert` / `getMap` cover the existing step pipeline.\n * - `map` rebases the step itself through a {@link Mapping} describing\n * intervening changes; returns `null` when the step can no longer be\n * applied meaningfully (block removed, range fragmented, range fully\n * eaten). See {@link StepMapping.ts} for per-step semantics.\n *\n * `getMap` and `map` both receive the document at the step's \"current\"\n * frame: `getMap` against the pre-apply doc, `map` against the doc that\n * the rebased step will be applied to. The latter is needed to re-snapshot\n * inverse-payload fields (`deletedText`, `previousAttrs`, etc.) so the\n * rebased step inverts correctly on redo.\n */\nexport interface StepHandler<S extends Step> {\n\treadonly apply: (doc: Document, step: S) => Document;\n\treadonly invert: (step: S) => Step;\n\treadonly getMap: (doc: Document, step: S) => StepMap;\n\treadonly map: (step: S, mapping: Mapping, doc: Document) => Step | null;\n}\n\n/**\n * Registry shape: every member of the `Step` union must have a matching\n * handler. If a new step type is added to the union without a handler,\n * the literal below fails to type-check.\n */\ntype StepHandlerRegistry = {\n\treadonly [K in Step['type']]: StepHandler<Extract<Step, { readonly type: K }>>;\n};\n\nconst STEP_HANDLERS: StepHandlerRegistry = {\n\tinsertText: {\n\t\tapply: applyInsertText,\n\t\tinvert: invertInsertText,\n\t\tgetMap: getMapInsertText,\n\t\tmap: mapInsertText,\n\t},\n\tdeleteText: {\n\t\tapply: applyDeleteText,\n\t\tinvert: invertDeleteText,\n\t\tgetMap: getMapDeleteText,\n\t\tmap: mapDeleteText,\n\t},\n\tsplitBlock: {\n\t\tapply: applySplitBlock,\n\t\tinvert: invertSplitBlock,\n\t\tgetMap: getMapSplitBlock,\n\t\tmap: mapSplitBlock,\n\t},\n\tmergeBlocks: {\n\t\tapply: applyMergeBlocks,\n\t\tinvert: invertMergeBlocks,\n\t\tgetMap: getMapMergeBlocks,\n\t\tmap: mapMergeBlocks,\n\t},\n\taddMark: {\n\t\tapply: applyAddMark,\n\t\tinvert: invertAddMark,\n\t\tgetMap: getMapAddMark,\n\t\tmap: mapAddMark,\n\t},\n\tremoveMark: {\n\t\tapply: applyRemoveMark,\n\t\tinvert: invertRemoveMark,\n\t\tgetMap: getMapRemoveMark,\n\t\tmap: mapRemoveMark,\n\t},\n\tsetStoredMarks: {\n\t\tapply: applySetStoredMarks,\n\t\tinvert: invertSetStoredMarks,\n\t\tgetMap: getMapSetStoredMarks,\n\t\tmap: mapSetStoredMarks,\n\t},\n\tsetBlockType: {\n\t\tapply: applySetBlockType,\n\t\tinvert: invertSetBlockType,\n\t\tgetMap: getMapSetBlockType,\n\t\tmap: mapSetBlockType,\n\t},\n\tinsertNode: {\n\t\tapply: applyInsertNode,\n\t\tinvert: invertInsertNode,\n\t\tgetMap: getMapInsertNode,\n\t\tmap: mapInsertNode,\n\t},\n\tremoveNode: {\n\t\tapply: applyRemoveNode,\n\t\tinvert: invertRemoveNode,\n\t\tgetMap: getMapRemoveNode,\n\t\tmap: mapRemoveNode,\n\t},\n\tsetNodeAttr: {\n\t\tapply: applySetNodeAttr,\n\t\tinvert: invertSetNodeAttr,\n\t\tgetMap: getMapSetNodeAttr,\n\t\tmap: mapSetNodeAttr,\n\t},\n\tinsertInlineNode: {\n\t\tapply: applyInsertInlineNode,\n\t\tinvert: invertInsertInlineNode,\n\t\tgetMap: getMapInsertInlineNode,\n\t\tmap: mapInsertInlineNode,\n\t},\n\tremoveInlineNode: {\n\t\tapply: applyRemoveInlineNode,\n\t\tinvert: invertRemoveInlineNode,\n\t\tgetMap: getMapRemoveInlineNode,\n\t\tmap: mapRemoveInlineNode,\n\t},\n\tsetInlineNodeAttr: {\n\t\tapply: applySetInlineNodeAttr,\n\t\tinvert: invertSetInlineNodeAttr,\n\t\tgetMap: getMapSetInlineNodeAttr,\n\t\tmap: mapSetInlineNodeAttr,\n\t},\n};\n\n/**\n * Looks up the handler for a step. The cast is bounded — `STEP_HANDLERS`\n * is typed such that `step.type` always selects a handler whose parameter\n * type matches `S`. TypeScript cannot narrow indexed access through a\n * discriminator without help, so we assert the relationship once here.\n */\nfunction getHandler<S extends Step>(step: S): StepHandler<S> {\n\treturn STEP_HANDLERS[step.type] as unknown as StepHandler<S>;\n}\n\n/** Applies a single step to a document and returns the new document. */\nexport function applyStep(doc: Document, step: Step): Document {\n\treturn getHandler(step).apply(doc, step);\n}\n\n/** Returns the inverse of a step, used for undo/redo. */\nexport function invertStep(step: Step): Step {\n\treturn getHandler(step).invert(step);\n}\n\n/**\n * Returns the position-space {@link StepMap} for a step, computed against\n * the document state **before** the step was applied.\n */\nexport function getStepMap(doc: Document, step: Step): StepMap {\n\treturn getHandler(step).getMap(doc, step);\n}\n\n/**\n * Rebases a step through a {@link Mapping} describing intervening edits in\n * position space, returning either the rebased step or `null` when the\n * step can no longer be applied meaningfully (block removed, range fully\n * eaten, range fragmented across blocks, structural ancestor migrated).\n *\n * `doc` must be the document at the frame the rebased step will run\n * against — `map` re-snapshots inverse-payload fields (`deletedText`,\n * `previousAttrs`, …) from it so the rebased step inverts correctly on\n * redo.\n *\n * Callers (e.g. {@link HistoryManager.undo}) treat a `null` as a signal to\n * abandon the entire undo/redo group rather than apply a partial rebase\n * that would silently corrupt the document.\n */\nexport function mapStep(step: Step, mapping: Mapping, doc: Document): Step | null {\n\tif (mapping.isEmpty) return step;\n\treturn getHandler(step).map(step, mapping, doc);\n}\n\n/**\n * Inverts an entire transaction (reverses step order and swaps selections).\n *\n * The returned transaction's `mapping` is {@link Mapping.empty}: producing a\n * faithful mapping for inverted steps requires the pre-apply document at\n * each inverse step (e.g. `removeNode` needs to walk the subtree, which is\n * only present in the forward step's payload, not its inverse). Callers\n * that need a real mapping for the inverted transaction should accumulate\n * step maps via {@link getStepMap} as they apply each inverse step.\n *\n * `forwardStepMaps` is set to identity placeholders for the same reason —\n * the inverse-step forward effect is only computable against the document\n * state at each inverse, which the caller (e.g. `HistoryManager.undo`)\n * tracks while walking.\n */\nexport function invertTransaction(tr: Transaction): Transaction {\n\tconst invertedSteps: Step[] = tr.steps.map(invertStep).reverse();\n\treturn {\n\t\tsteps: invertedSteps,\n\t\tselectionBefore: tr.selectionAfter,\n\t\tselectionAfter: tr.selectionBefore,\n\t\tstoredMarksAfter: deriveStoredMarksBefore(tr),\n\t\tmapping: Mapping.empty,\n\t\tforwardStepMaps: invertedSteps.map(() => IDENTITY_MAP),\n\t\tmetadata: {\n\t\t\torigin: 'history',\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t};\n}\n","/**\n * Thin decoration-specific adapters over the generic {@link StepMap}\n * primitive. Position-shift arithmetic lives in `state/Mapping.ts`; this\n * module only contains the decoration-shape concerns:\n *\n * - splitting an {@link InlineDecoration} into two when a `splitBlock`\n * crosses its range,\n * - dropping a {@link NodeDecoration} when its block disappears\n * (`removeNode`) or is absorbed by a merge,\n * - applying widget `side` as the mapping `assoc`.\n *\n * The legacy entry point `mapDecorationThroughStep(deco, step)` is\n * preserved as a thin shim over `mapDecorationThroughStepMap` so existing\n * tests keep working; new consumers should reach for `Transaction.mapping`\n * directly via `DecorationSet.map(tr)`.\n */\n\nimport type { Document } from '../model/Document.js';\nimport { createPosition } from '../model/Selection.js';\nimport type { MergeMap, ShiftMap, SplitMap, StepMap } from '../state/Mapping.js';\nimport { mapPositionThroughStep } from '../state/Mapping.js';\nimport { getStepMap } from '../state/StepHandlers.js';\nimport type { Step } from '../state/Transaction.js';\nimport type {\n\tDecoration,\n\tInlineDecoration,\n\tNodeDecoration,\n\tWidgetDecoration,\n} from './Decoration.js';\n\nconst EMPTY_DOC: Document = { children: [] };\n\n/**\n * Maps a decoration through a single {@link StepMap}. Returns:\n * - the (possibly identical) decoration,\n * - an array of two decorations when a `splitBlock` cuts an inline range,\n * - or `null` when the decoration was deleted.\n */\nexport function mapDecorationThroughStepMap(\n\tdeco: Decoration,\n\tstepMap: StepMap,\n): Decoration | readonly Decoration[] | null {\n\tswitch (deco.type) {\n\t\tcase 'inline':\n\t\t\treturn mapInline(deco, stepMap);\n\t\tcase 'widget':\n\t\t\treturn mapWidget(deco, stepMap);\n\t\tcase 'node':\n\t\t\treturn mapNode(deco, stepMap);\n\t}\n}\n\n/**\n * Legacy entry point — kept for backward compatibility with callers and\n * tests that hold a {@link Step} rather than a {@link StepMap}. Internally\n * converts step → StepMap (cheap, no doc state needed for any of the\n * shape categories used here) and delegates to\n * {@link mapDecorationThroughStepMap}.\n */\nexport function mapDecorationThroughStep(\n\tdeco: Decoration,\n\tstep: Step,\n): Decoration | readonly Decoration[] | null {\n\treturn mapDecorationThroughStepMap(deco, getStepMap(EMPTY_DOC, step));\n}\n\n// --- Inline ---\n\nfunction mapInline(\n\tdeco: InlineDecoration,\n\tstepMap: StepMap,\n): InlineDecoration | readonly InlineDecoration[] | null {\n\tswitch (stepMap.type) {\n\t\tcase 'identity':\n\t\t\treturn deco;\n\t\tcase 'shift':\n\t\t\treturn mapInlineShift(deco, stepMap);\n\t\tcase 'split':\n\t\t\treturn mapInlineSplit(deco, stepMap);\n\t\tcase 'merge':\n\t\t\treturn mapInlineMerge(deco, stepMap);\n\t\tcase 'blockRemoval':\n\t\t\treturn stepMap.removedBlockIds.has(deco.blockId) ? null : deco;\n\t\tcase 'childIndexShift':\n\t\t\t// Sibling-index shifts don't move text positions.\n\t\t\treturn deco;\n\t}\n}\n\nfunction mapInlineShift(deco: InlineDecoration, map: ShiftMap): InlineDecoration | null {\n\tif (deco.blockId !== map.blockId) return deco;\n\n\tconst fromPos = mapPositionThroughStep(createPosition(deco.blockId, deco.from), map, -1).pos;\n\tconst toPos = mapPositionThroughStep(createPosition(deco.blockId, deco.to), map, 1).pos;\n\n\tif (fromPos.offset >= toPos.offset) return null;\n\tif (fromPos.offset === deco.from && toPos.offset === deco.to) return deco;\n\treturn { ...deco, from: fromPos.offset, to: toPos.offset };\n}\n\nfunction mapInlineSplit(\n\tdeco: InlineDecoration,\n\tmap: SplitMap,\n): InlineDecoration | readonly InlineDecoration[] {\n\tif (deco.blockId !== map.blockId) return deco;\n\n\tif (deco.to <= map.offset) return deco;\n\n\tif (deco.from >= map.offset) {\n\t\treturn {\n\t\t\t...deco,\n\t\t\tblockId: map.newBlockId,\n\t\t\tfrom: deco.from - map.offset,\n\t\t\tto: deco.to - map.offset,\n\t\t};\n\t}\n\n\t// Spans the split — return both halves\n\tconst left: InlineDecoration = { ...deco, to: map.offset };\n\tconst right: InlineDecoration = {\n\t\t...deco,\n\t\tblockId: map.newBlockId,\n\t\tfrom: 0,\n\t\tto: deco.to - map.offset,\n\t};\n\treturn [left, right];\n}\n\nfunction mapInlineMerge(deco: InlineDecoration, map: MergeMap): InlineDecoration {\n\tif (deco.blockId !== map.sourceBlockId) return deco;\n\treturn {\n\t\t...deco,\n\t\tblockId: map.targetBlockId,\n\t\tfrom: deco.from + map.targetLengthBefore,\n\t\tto: deco.to + map.targetLengthBefore,\n\t};\n}\n\n// --- Widget ---\n\nfunction mapWidget(deco: WidgetDecoration, stepMap: StepMap): WidgetDecoration | null {\n\tswitch (stepMap.type) {\n\t\tcase 'identity':\n\t\t\treturn deco;\n\t\tcase 'shift':\n\t\t\treturn mapWidgetShift(deco, stepMap);\n\t\tcase 'split':\n\t\t\treturn mapWidgetSplit(deco, stepMap);\n\t\tcase 'merge':\n\t\t\treturn mapWidgetMerge(deco, stepMap);\n\t\tcase 'blockRemoval':\n\t\t\treturn stepMap.removedBlockIds.has(deco.blockId) ? null : deco;\n\t\tcase 'childIndexShift':\n\t\t\treturn deco;\n\t}\n}\n\nfunction mapWidgetShift(deco: WidgetDecoration, map: ShiftMap): WidgetDecoration | null {\n\tif (deco.blockId !== map.blockId) return deco;\n\n\tconst result = mapPositionThroughStep(createPosition(deco.blockId, deco.offset), map, deco.side);\n\t// A widget that lands strictly inside removed content is deleted.\n\tif (result.deleted) return null;\n\tif (result.pos.offset === deco.offset) return deco;\n\treturn { ...deco, offset: result.pos.offset };\n}\n\nfunction mapWidgetSplit(deco: WidgetDecoration, map: SplitMap): WidgetDecoration {\n\tif (deco.blockId !== map.blockId) return deco;\n\tconst result = mapPositionThroughStep(createPosition(deco.blockId, deco.offset), map, deco.side);\n\tif (result.pos.blockId === deco.blockId && result.pos.offset === deco.offset) return deco;\n\treturn { ...deco, blockId: result.pos.blockId, offset: result.pos.offset };\n}\n\nfunction mapWidgetMerge(deco: WidgetDecoration, map: MergeMap): WidgetDecoration {\n\tif (deco.blockId !== map.sourceBlockId) return deco;\n\treturn {\n\t\t...deco,\n\t\tblockId: map.targetBlockId,\n\t\toffset: deco.offset + map.targetLengthBefore,\n\t};\n}\n\n// --- Node ---\n\nfunction mapNode(deco: NodeDecoration, stepMap: StepMap): NodeDecoration | null {\n\tswitch (stepMap.type) {\n\t\tcase 'identity':\n\t\tcase 'shift':\n\t\tcase 'split':\n\t\t\t// Node decorations are bound to a block; in-block content edits\n\t\t\t// and splits don't affect them. Splits keep the decoration on the\n\t\t\t// original block (the new block has no decoration of its own).\n\t\t\treturn deco;\n\t\tcase 'merge':\n\t\t\t// Source block disappears as a separate block → its decoration is dropped.\n\t\t\treturn deco.blockId === stepMap.sourceBlockId ? null : deco;\n\t\tcase 'blockRemoval':\n\t\t\treturn stepMap.removedBlockIds.has(deco.blockId) ? null : deco;\n\t\tcase 'childIndexShift':\n\t\t\treturn deco;\n\t}\n}\n","/**\n * Decoration types and DecorationSet for transient, view-only annotations.\n * Decorations are NOT part of the document model and do NOT affect undo/redo.\n */\n\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport { mapDecorationThroughStepMap } from './PositionMapping.js';\n\n// --- Decoration Attrs ---\n\nexport interface DecorationAttrs {\n\treadonly class?: string;\n\treadonly style?: string;\n\treadonly nodeName?: string;\n\treadonly [key: string]: string | undefined;\n}\n\n// --- Decoration Types ---\n\nexport interface InlineDecoration {\n\treadonly type: 'inline';\n\treadonly blockId: BlockId;\n\treadonly from: number;\n\treadonly to: number;\n\treadonly attrs: DecorationAttrs;\n}\n\nexport interface NodeDecoration {\n\treadonly type: 'node';\n\treadonly blockId: BlockId;\n\treadonly attrs: DecorationAttrs;\n}\n\nexport interface WidgetDecoration {\n\treadonly type: 'widget';\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n\treadonly toDOM: () => HTMLElement;\n\treadonly side: -1 | 1;\n\treadonly key?: string;\n}\n\nexport type Decoration = InlineDecoration | NodeDecoration | WidgetDecoration;\n\n// --- Factory Functions ---\n\n/** Creates an inline decoration for a text range within a block. */\nexport function inline(\n\tblockId: BlockId,\n\tfrom: number,\n\tto: number,\n\tattrs: DecorationAttrs,\n): InlineDecoration {\n\treturn { type: 'inline', blockId, from, to, attrs };\n}\n\n/** Creates a node decoration that applies to a whole block element. */\nexport function node(blockId: BlockId, attrs: DecorationAttrs): NodeDecoration {\n\treturn { type: 'node', blockId, attrs };\n}\n\n/** Creates a widget decoration that inserts a DOM element at a position. */\nexport function widget(\n\tblockId: BlockId,\n\toffset: number,\n\ttoDOM: () => HTMLElement,\n\toptions?: { readonly side?: -1 | 1; readonly key?: string },\n): WidgetDecoration {\n\treturn {\n\t\ttype: 'widget',\n\t\tblockId,\n\t\toffset,\n\t\ttoDOM,\n\t\tside: options?.side ?? -1,\n\t\tkey: options?.key,\n\t};\n}\n\n// --- DecorationSet ---\n\n/**\n * Immutable set of decorations indexed by block ID.\n * Provides efficient lookup and merging of decoration collections.\n */\nexport class DecorationSet {\n\tstatic readonly empty: DecorationSet = new DecorationSet(new Map());\n\n\tprivate constructor(private readonly byBlock: ReadonlyMap<BlockId, readonly Decoration[]>) {}\n\n\t/** Creates a DecorationSet from a flat array of decorations. */\n\tstatic create(decorations: readonly Decoration[]): DecorationSet {\n\t\tif (decorations.length === 0) return DecorationSet.empty;\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const deco of decorations) {\n\t\t\tconst existing = map.get(deco.blockId);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(deco);\n\t\t\t} else {\n\t\t\t\tmap.set(deco.blockId, [deco]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns all decorations for a given block. */\n\tfind(blockId: BlockId): readonly Decoration[] {\n\t\treturn this.byBlock.get(blockId) ?? [];\n\t}\n\n\t/** Returns only inline decorations for a given block. */\n\tfindInline(blockId: BlockId): readonly InlineDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is InlineDecoration => d.type === 'inline');\n\t}\n\n\t/** Returns only node decorations for a given block. */\n\tfindNode(blockId: BlockId): readonly NodeDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is NodeDecoration => d.type === 'node');\n\t}\n\n\t/** Returns only widget decorations for a given block. */\n\tfindWidget(blockId: BlockId): readonly WidgetDecoration[] {\n\t\tconst decos = this.byBlock.get(blockId);\n\t\tif (!decos) return [];\n\t\treturn decos.filter((d): d is WidgetDecoration => d.type === 'widget');\n\t}\n\n\t/** Returns a new DecorationSet with the given decorations added. */\n\tadd(decorations: readonly Decoration[]): DecorationSet {\n\t\tif (decorations.length === 0) return this;\n\t\tif (this.isEmpty) return DecorationSet.create(decorations);\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tmap.set(bid, [...decos]);\n\t\t}\n\t\tfor (const deco of decorations) {\n\t\t\tconst existing = map.get(deco.blockId);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(deco);\n\t\t\t} else {\n\t\t\t\tmap.set(deco.blockId, [deco]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns a new DecorationSet with decorations matching the predicate removed. */\n\tremove(predicate: (d: Decoration) => boolean): DecorationSet {\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tlet changed = false;\n\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tconst filtered = decos.filter((d) => !predicate(d));\n\t\t\tif (filtered.length !== decos.length) changed = true;\n\t\t\tif (filtered.length > 0) {\n\t\t\t\tmap.set(bid, filtered);\n\t\t\t}\n\t\t}\n\n\t\tif (!changed) return this;\n\t\tif (map.size === 0) return DecorationSet.empty;\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Returns a new DecorationSet merging this set with another. */\n\tmerge(other: DecorationSet): DecorationSet {\n\t\tif (other.isEmpty) return this;\n\t\tif (this.isEmpty) return other;\n\n\t\tconst map = new Map<BlockId, Decoration[]>();\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tmap.set(bid, [...decos]);\n\t\t}\n\t\tfor (const [bid, decos] of other.byBlock) {\n\t\t\tconst existing = map.get(bid);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(...decos);\n\t\t\t} else {\n\t\t\t\tmap.set(bid, [...decos]);\n\t\t\t}\n\t\t}\n\t\treturn new DecorationSet(map);\n\t}\n\n\t/** Checks equality — reference first, then structural comparison. */\n\tequals(other: DecorationSet): boolean {\n\t\tif (this === other) return true;\n\t\tif (this.byBlock.size !== other.byBlock.size) return false;\n\n\t\tfor (const [bid, decos] of this.byBlock) {\n\t\t\tconst otherDecos = other.byBlock.get(bid);\n\t\t\tif (!otherDecos) return false;\n\t\t\tif (!decorationArraysEqual(decos, otherDecos)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** True if the set contains no decorations. */\n\tget isEmpty(): boolean {\n\t\treturn this.byBlock.size === 0;\n\t}\n\n\t/**\n\t * Maps decorations through document changes described by a transaction.\n\t * Decorations that become invalid (e.g. fully deleted range) are removed.\n\t * Decorations that span a split point are split into two.\n\t *\n\t * Iterates over `tr.mapping.maps` (the position-space {@link StepMap}s)\n\t * rather than `tr.steps`. This means selection-only or other identity\n\t * transactions short-circuit (`tr.mapping.isEmpty`) without rebuilding\n\t * the set, and the decoration-specific shape concerns (split-into-two,\n\t * drop-on-block-removal) are the only logic that lives here.\n\t */\n\tmap(tr: Transaction): DecorationSet {\n\t\tif (this.isEmpty || tr.mapping.isEmpty) return this;\n\n\t\tlet mapped: Decoration[] = [];\n\t\tfor (const decos of this.byBlock.values()) {\n\t\t\tfor (const d of decos) {\n\t\t\t\tmapped.push(d);\n\t\t\t}\n\t\t}\n\n\t\tfor (const stepMap of tr.mapping.maps) {\n\t\t\tconst next: Decoration[] = [];\n\t\t\tfor (const deco of mapped) {\n\t\t\t\tconst result = mapDecorationThroughStepMap(deco, stepMap);\n\t\t\t\tif (result === null) continue;\n\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\tfor (const r of result) {\n\t\t\t\t\t\tnext.push(r);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnext.push(result as Decoration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmapped = next;\n\t\t}\n\n\t\tif (mapped.length === 0) return DecorationSet.empty;\n\t\treturn DecorationSet.create(mapped);\n\t}\n}\n\n// --- Helpers ---\n\n/** Compares two decoration arrays for structural equality. */\nexport function decorationArraysEqual(a: readonly Decoration[], b: readonly Decoration[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst ai = a[i];\n\t\tconst bi = b[i];\n\t\tif (!ai || !bi || !decorationsEqual(ai, bi)) return false;\n\t}\n\treturn true;\n}\n\n/** Compares two individual decorations for structural equality. */\nfunction decorationsEqual(a: Decoration, b: Decoration): boolean {\n\tif (a.type !== b.type) return false;\n\tif (a.blockId !== b.blockId) return false;\n\n\tswitch (a.type) {\n\t\tcase 'inline': {\n\t\t\tconst bi = b as InlineDecoration;\n\t\t\treturn a.from === bi.from && a.to === bi.to && attrsEqual(a.attrs, bi.attrs);\n\t\t}\n\t\tcase 'node': {\n\t\t\tconst bn = b as NodeDecoration;\n\t\t\treturn attrsEqual(a.attrs, bn.attrs);\n\t\t}\n\t\tcase 'widget': {\n\t\t\tconst bw = b as WidgetDecoration;\n\t\t\treturn (\n\t\t\t\ta.offset === bw.offset && a.side === bw.side && a.key === bw.key && a.toDOM === bw.toDOM\n\t\t\t);\n\t\t}\n\t}\n}\n\n/** Compares two DecorationAttrs objects. */\nfunction attrsEqual(a: DecorationAttrs, b: DecorationAttrs): boolean {\n\tif (a === b) return true;\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\tif (aKeys.length !== bKeys.length) return false;\n\tfor (const key of aKeys) {\n\t\tif (a[key] !== b[key]) return false;\n\t}\n\treturn true;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function t(t,n=[]){return{kind:"text",text:t,marks:n}}function n(t){return{kind:"inline",node:t}}function e(t,n,e){const o=[];return r(t,n,e,{onText(t,n){o.push({kind:"text",text:t,marks:n})},onInline(t){o.push({kind:"inline",node:t})}}),o}function r(t,n,e,r){for(const{child:o,from:s,to:f}of U(c(t)))if(!(f<=n||s>=e))if(i(o))r.onInline?.(o);else{const t=Math.max(0,n-s),i=Math.min(o.text.length,e-s),f=o.text.slice(t,i);f.length>0&&r.onText(f,o.marks)}}function o(t){return"object"==typeof t&&null!==t&&"text"===t.type&&"string"==typeof t.text}function i(t){return"object"==typeof t&&null!==t&&"inline"===t.type&&"string"==typeof t.inlineType}function s(t){return"object"==typeof t&&null!==t&&"string"==typeof t.id&&"string"==typeof t.type&&"text"!==t.type&&"inline"!==t.type&&Array.isArray(t.children)}function f(t){return t.children.every(t=>o(t)||i(t))}function u(t){return t.children.filter(t=>o(t))}function c(t){return t.children.filter(t=>o(t)||i(t))}function l(t){return t.children.filter(t=>s(t))}function a(){return`block-${crypto.randomUUID()}`}function h(t){return{children:t??[p("paragraph")]}}function p(t,n,e,r){return{id:e??a(),type:t,...r?{attrs:r}:{},children:n??[y("")]}}function y(t,n){return{type:"text",text:t,marks:n??[]}}function g(t,n){return{type:"inline",inlineType:t,attrs:n??{}}}function m(t){return p("paragraph",[y("")],t)}function x(t){const n=c(t);let e="";for(const r of n)o(r)&&(e+=r.text);return e}function d(t){let n=0;for(const{to:e}of U(c(t)))n=e;return n}function k(t,n){const e=c(t);for(const{child:r,from:o,to:s}of U(e))if(i(r)){if(n===o)return[]}else{if(n>=o&&n<s)return r.marks;if(n===o&&0===r.text.length)return r.marks}for(let r=e.length-1;r>=0;r--){const t=e[r];if(t&&o(t))return t.marks}return[]}function b(t,n,e){const r=k(t,n);if(0===r.length)return r;const o=function(t,n){for(const{child:e,from:r,to:o}of U(c(t)))if(i(e)){if(n===r)return[]}else if(n>=r&&n<o)return e.marks;return[]}(t,n);return r.filter(t=>e(t.type)||o.some(n=>j(n,t)))}function j(t,n){if(t.type!==n.type)return!1;const e=t.attrs,r=n.attrs;if(!e&&!r)return!0;if(!e||!r)return!1;const o=Object.keys(e),i=Object.keys(r);return o.length===i.length&&o.every(t=>e[t]===r[t])}function v(t,n){return t.length===n.length&&t.every(t=>n.some(n=>j(t,n)))}function T(t,n){return t.some(t=>t.type===n)}function A(t,n){return T(t,n.type)?t:[...t,n]}function I(t,n){return t.filter(t=>t.type!==n)}function M(t){if(0===t.length)return[y("")];if(t.every(t=>o(t)))return function(t){if(0===t.length)return[y("")];const n=[];for(const e of t){const t=n[n.length-1];t&&v(t.marks,e.marks)?n[n.length-1]=y(t.text+e.text,t.marks):(e.text.length>0||0===n.length)&&n.push(e)}return 0===n.length?[y("")]:n}(t);const n=[];for(const r of t){if(i(r)){n.push(r);continue}const t=n[n.length-1];t&&o(t)&&v(t.marks,r.marks)?n[n.length-1]=y(t.text+r.text,t.marks):(r.text.length>0||0===n.length)&&n.push(r)}const e=n.filter((t,e)=>{if(i(t))return!0;if(t.text.length>0)return!0;if(1===n.length)return!0;const r=n[e-1],o=n[e+1];return!(r&&i(r)||o&&i(o))});return 0===e.length?[y("")]:e.some(t=>o(t))?e:[y(""),...e]}function O(t){return"inline"===t.kind?t.node:y(t.text,t.marks)}function D(t){return M(t.map(O))}function*U(t){let n=0;for(const e of t){const t=i(e)?1:e.text.length;yield{child:e,from:n,to:n+t},n+=t}}function w(t,n){let e=0;for(const{child:r,from:o,to:s}of U(c(t)))if(i(r)){if(o>=n)return e}else{if(s>=n)return e+(n-o);e+=r.text.length}return e}function C(t,n){const e=c(t);for(const{child:r,from:o}of U(e)){if(i(r)){if(n===o)return{kind:"inline",node:r};continue}const t=n-o;if(t>=0&&t<r.text.length)return{kind:"text",char:r.text[t]??"",marks:r.marks}}return null}export{D as A,i as C,j as D,v as E,U as M,M as O,s as S,o as T,b as _,h as a,T as b,y as c,l as d,e as f,C as g,x as h,p as i,t as j,I as k,r as l,k as m,w as n,m as o,d as p,O as r,g as s,A as t,a as u,c as v,f as w,n as x,u as y};
|
|
2
|
-
//# sourceMappingURL=Document-r7vLOAGA.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Document-r7vLOAGA.mjs","names":[],"sources":["../../src/model/Document.ts"],"sourcesContent":["/**\n * Core document model types for the Notectl editor.\n * All types are deeply readonly — mutations create new instances.\n */\n\nimport type { BlockId, InlineTypeName, MarkTypeName, NodeTypeName } from './TypeBrands.js';\n\n// --- Mark Types ---\n\nexport interface Mark {\n\treadonly type: MarkTypeName;\n\treadonly attrs?: Readonly<Record<string, string | number | boolean>>;\n}\n\nexport interface BoldMark extends Mark {\n\treadonly type: MarkTypeName & 'bold';\n}\n\nexport interface ItalicMark extends Mark {\n\treadonly type: MarkTypeName & 'italic';\n}\n\nexport interface UnderlineMark extends Mark {\n\treadonly type: MarkTypeName & 'underline';\n}\n\n// --- Node Types ---\n\nexport interface BlockAttrs {\n\treadonly [key: string]: string | number | boolean;\n}\n\nexport interface TextNode {\n\treadonly type: 'text';\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n}\n\n/** Atomic inline element (width 1 in offset space). */\nexport interface InlineNode {\n\treadonly type: 'inline';\n\treadonly inlineType: InlineTypeName;\n\treadonly attrs: Readonly<Record<string, string | number | boolean>>;\n}\n\n/** A child of a BlockNode: text, inline element, or nested block. */\nexport type ChildNode = TextNode | InlineNode | BlockNode;\n\nexport interface BlockNode {\n\treadonly id: BlockId;\n\treadonly type: NodeTypeName;\n\treadonly attrs?: BlockAttrs;\n\treadonly children: readonly ChildNode[];\n}\n\nexport interface Document {\n\treadonly children: readonly BlockNode[];\n}\n\n// --- Text Segment (for mark-preserving undo) ---\n\nexport interface TextSegment {\n\treadonly text: string;\n\treadonly marks: readonly Mark[];\n}\n\n/** A content segment: either text (with marks) or an inline node. */\nexport type ContentSegment =\n\t| { readonly kind: 'text'; readonly text: string; readonly marks: readonly Mark[] }\n\t| { readonly kind: 'inline'; readonly node: InlineNode };\n\n/** Creates a text {@link ContentSegment}. */\nexport function textSegment(text: string, marks: readonly Mark[] = []): ContentSegment {\n\treturn { kind: 'text', text, marks };\n}\n\n/** Creates an inline {@link ContentSegment} wrapping an {@link InlineNode}. */\nexport function inlineSegment(node: InlineNode): ContentSegment {\n\treturn { kind: 'inline', node };\n}\n\n/** Returns content segments (text and inline) for a block range. */\nexport function getBlockContentSegmentsInRange(\n\tblock: BlockNode,\n\tfrom: number,\n\tto: number,\n): readonly ContentSegment[] {\n\tconst segments: ContentSegment[] = [];\n\tforEachInlineChildInRange(block, from, to, {\n\t\tonText(text: string, marks: readonly Mark[]): void {\n\t\t\tsegments.push({ kind: 'text', text, marks });\n\t\t},\n\t\tonInline(node: InlineNode): void {\n\t\t\tsegments.push({ kind: 'inline', node });\n\t\t},\n\t});\n\treturn segments;\n}\n\n/** Visitor callbacks invoked by {@link forEachInlineChildInRange} for each in-range child. */\nexport interface BlockRangeVisitor {\n\t/** Called with the clipped text and its marks for each text node overlapping the range. */\n\treadonly onText: (text: string, marks: readonly Mark[]) => void;\n\t/** Called for each inline node falling within the range. */\n\treadonly onInline?: (node: InlineNode) => void;\n}\n\n/**\n * Walks the inline children of `block` overlapping `[from, to)` and invokes the\n * matching visitor callback for each. Text nodes are clipped to the range before\n * `onText` fires; empty slices are skipped. This is the single read-only walker\n * for range-based inline serialization (segments, HTML, clipboard).\n */\nexport function forEachInlineChildInRange(\n\tblock: BlockNode,\n\tfrom: number,\n\tto: number,\n\tvisitor: BlockRangeVisitor,\n): void {\n\tfor (const { child, from: childFrom, to: childEnd } of walkInlineContent(\n\t\tgetInlineChildren(block),\n\t)) {\n\t\tif (childEnd <= from || childFrom >= to) continue;\n\n\t\tif (isInlineNode(child)) {\n\t\t\tvisitor.onInline?.(child);\n\t\t} else {\n\t\t\tconst sliceFrom: number = Math.max(0, from - childFrom);\n\t\t\tconst sliceTo: number = Math.min(child.text.length, to - childFrom);\n\t\t\tconst text: string = child.text.slice(sliceFrom, sliceTo);\n\t\t\tif (text.length > 0) {\n\t\t\t\tvisitor.onText(text, child.marks);\n\t\t\t}\n\t\t}\n\t}\n}\n\n// --- Type Guards ---\n\n/** Checks whether a value is a {@link TextNode}. */\nexport function isTextNode(node: unknown): node is TextNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\t(node as TextNode).type === 'text' &&\n\t\ttypeof (node as TextNode).text === 'string'\n\t);\n}\n\n/** Checks whether a value is an {@link InlineNode}. */\nexport function isInlineNode(node: unknown): node is InlineNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\t(node as InlineNode).type === 'inline' &&\n\t\ttypeof (node as InlineNode).inlineType === 'string'\n\t);\n}\n\n/** Checks whether a value is a {@link BlockNode}. */\nexport function isBlockNode(node: unknown): node is BlockNode {\n\treturn (\n\t\ttypeof node === 'object' &&\n\t\tnode !== null &&\n\t\ttypeof (node as BlockNode).id === 'string' &&\n\t\ttypeof (node as BlockNode).type === 'string' &&\n\t\t(node as BlockNode).type !== ('text' as string) &&\n\t\t(node as BlockNode).type !== ('inline' as string) &&\n\t\tArray.isArray((node as BlockNode).children)\n\t);\n}\n\n// --- Child Node Helpers ---\n\n/** Returns true if a block has only inline content (TextNodes and InlineNodes). */\nexport function isLeafBlock(node: BlockNode): boolean {\n\treturn node.children.every((c) => isTextNode(c) || isInlineNode(c));\n}\n\n/** Returns only the TextNode children of a block. */\nexport function getTextChildren(node: BlockNode): readonly TextNode[] {\n\treturn node.children.filter((c): c is TextNode => isTextNode(c));\n}\n\n/** Returns the inline content children (TextNode | InlineNode) of a block. */\nexport function getInlineChildren(node: BlockNode): readonly (TextNode | InlineNode)[] {\n\treturn node.children.filter((c): c is TextNode | InlineNode => isTextNode(c) || isInlineNode(c));\n}\n\n/** Returns only the BlockNode children of a block. */\nexport function getBlockChildren(node: BlockNode): readonly BlockNode[] {\n\treturn node.children.filter((c): c is BlockNode => isBlockNode(c));\n}\n\n// --- Factory Functions ---\n\n/** Generates a unique block ID using crypto.randomUUID(). */\nexport function generateBlockId(): BlockId {\n\treturn `block-${crypto.randomUUID()}` as BlockId;\n}\n\n/** Creates a new empty {@link Document} with a single empty paragraph. */\nexport function createDocument(children?: readonly BlockNode[]): Document {\n\treturn {\n\t\tchildren: children ?? [createBlockNode('paragraph' as NodeTypeName)],\n\t};\n}\n\n/** Creates a new {@link BlockNode}. */\nexport function createBlockNode(\n\ttype: NodeTypeName,\n\tchildren?: readonly ChildNode[],\n\tid?: BlockId,\n\tattrs?: BlockAttrs,\n): BlockNode {\n\treturn {\n\t\tid: id ?? generateBlockId(),\n\t\ttype,\n\t\t...(attrs ? { attrs } : {}),\n\t\tchildren: children ?? [createTextNode('')],\n\t};\n}\n\n/** Creates a new {@link TextNode}. */\nexport function createTextNode(text: string, marks?: readonly Mark[]): TextNode {\n\treturn {\n\t\ttype: 'text',\n\t\ttext,\n\t\tmarks: marks ?? [],\n\t};\n}\n\n/** Creates a new {@link InlineNode}. */\nexport function createInlineNode(\n\tinlineType: InlineTypeName,\n\tattrs?: Readonly<Record<string, string | number | boolean>>,\n): InlineNode {\n\treturn {\n\t\ttype: 'inline',\n\t\tinlineType,\n\t\tattrs: attrs ?? {},\n\t};\n}\n\n/** Creates an empty paragraph block node with the given ID. */\nexport function createEmptyParagraph(id?: BlockId): BlockNode {\n\treturn createBlockNode('paragraph' as NodeTypeName, [createTextNode('')], id);\n}\n\n// --- Utility Functions ---\n\n/** Extracts plain text from a block (InlineNodes are skipped). */\nexport function getBlockText(block: BlockNode): string {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\tlet text = '';\n\tfor (const child of inlineChildren) {\n\t\tif (isTextNode(child)) {\n\t\t\ttext += child.text;\n\t\t}\n\t}\n\treturn text;\n}\n\n/** Returns the length of a block's inline content (InlineNodes count as 1). */\nexport function getBlockLength(block: BlockNode): number {\n\tlet len = 0;\n\tfor (const { to } of walkInlineContent(getInlineChildren(block))) {\n\t\tlen = to;\n\t}\n\treturn len;\n}\n\n/** Returns the marks active at the given offset (empty for InlineNode offsets). */\nexport function getBlockMarksAtOffset(block: BlockNode, offset: number): readonly Mark[] {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\n\tfor (const { child, from, to } of walkInlineContent(inlineChildren)) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (offset === from) return [];\n\t\t\tcontinue;\n\t\t}\n\t\tif (offset >= from && offset < to) {\n\t\t\treturn child.marks;\n\t\t}\n\t\t// Empty text node (from === to): match exactly at its position.\n\t\tif (offset === from && child.text.length === 0) {\n\t\t\treturn child.marks;\n\t\t}\n\t}\n\n\t// Fall back to last text child's marks\n\tfor (let i: number = inlineChildren.length - 1; i >= 0; i--) {\n\t\tconst child: TextNode | InlineNode | undefined = inlineChildren[i];\n\t\tif (child && isTextNode(child)) {\n\t\t\treturn child.marks;\n\t\t}\n\t}\n\treturn [];\n}\n\n/** Returns the marks of the text content immediately to the right of `offset`. */\nfunction getMarksAfterOffset(block: BlockNode, offset: number): readonly Mark[] {\n\tfor (const { child, from, to } of walkInlineContent(getInlineChildren(block))) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (offset === from) return [];\n\t\t\tcontinue;\n\t\t}\n\t\tif (offset >= from && offset < to) return child.marks;\n\t}\n\treturn [];\n}\n\n/**\n * Returns the marks that text typed at a collapsed cursor should carry.\n *\n * Marks are derived from the content around `offset` (via\n * {@link getBlockMarksAtOffset}). A mark whose spec is non-inclusive\n * (`isMarkInclusive` returns `false`) is only kept when it also covers the\n * content to the right of the cursor, so it never bleeds past its right\n * boundary onto newly typed text. Inclusive marks (the default) are unaffected.\n */\nexport function getCursorMarks(\n\tblock: BlockNode,\n\toffset: number,\n\tisMarkInclusive: (type: MarkTypeName) => boolean,\n): readonly Mark[] {\n\tconst marks: readonly Mark[] = getBlockMarksAtOffset(block, offset);\n\tif (marks.length === 0) return marks;\n\n\tconst after: readonly Mark[] = getMarksAfterOffset(block, offset);\n\treturn marks.filter(\n\t\t(mark) => isMarkInclusive(mark.type) || after.some((a) => marksEqual(a, mark)),\n\t);\n}\n\n/** Checks whether two marks are equal by type and attrs. */\nexport function marksEqual(a: Mark, b: Mark): boolean {\n\tif (a.type !== b.type) return false;\n\tconst aAttrs = a.attrs;\n\tconst bAttrs = b.attrs;\n\tif (!aAttrs && !bAttrs) return true;\n\tif (!aAttrs || !bAttrs) return false;\n\tconst aKeys = Object.keys(aAttrs);\n\tconst bKeys = Object.keys(bAttrs);\n\tif (aKeys.length !== bKeys.length) return false;\n\treturn aKeys.every((key) => aAttrs[key] === bAttrs[key]);\n}\n\n/** Checks whether two mark arrays contain the same marks (order-independent). */\nexport function markSetsEqual(a: readonly Mark[], b: readonly Mark[]): boolean {\n\tif (a.length !== b.length) return false;\n\treturn a.every((markA) => b.some((markB) => marksEqual(markA, markB)));\n}\n\n/** Returns true if the mark set contains a mark of the given type. */\nexport function hasMark(marks: readonly Mark[], markType: MarkTypeName): boolean {\n\treturn marks.some((m) => m.type === markType);\n}\n\n/** Adds a mark to a mark set (no duplicates). */\nexport function addMarkToSet(marks: readonly Mark[], mark: Mark): readonly Mark[] {\n\tif (hasMark(marks, mark.type)) return marks;\n\treturn [...marks, mark];\n}\n\n/** Removes a mark type from a mark set. */\nexport function removeMarkFromSet(marks: readonly Mark[], markType: MarkTypeName): readonly Mark[] {\n\treturn marks.filter((m) => m.type !== markType);\n}\n\n/**\n * Normalizes text nodes within a block: merges adjacent nodes with identical marks,\n * removes empty text nodes (keeping at least one).\n */\nexport function normalizeTextNodes(nodes: readonly TextNode[]): readonly TextNode[] {\n\tif (nodes.length === 0) return [createTextNode('')];\n\n\tconst result: TextNode[] = [];\n\tfor (const node of nodes) {\n\t\tconst prev: TextNode | undefined = result[result.length - 1];\n\t\tif (prev && markSetsEqual(prev.marks, node.marks)) {\n\t\t\tresult[result.length - 1] = createTextNode(prev.text + node.text, prev.marks);\n\t\t} else if (node.text.length > 0 || result.length === 0) {\n\t\t\tresult.push(node);\n\t\t}\n\t}\n\n\treturn result.length === 0 ? [createTextNode('')] : result;\n}\n\n/**\n * Normalizes mixed inline content: merges adjacent TextNodes with same marks,\n * removes empty TextNodes adjacent to InlineNodes, preserves InlineNodes as-is.\n * Guarantees at least one TextNode exists if all text is empty.\n */\nexport function normalizeInlineContent(\n\tnodes: readonly (TextNode | InlineNode)[],\n): readonly (TextNode | InlineNode)[] {\n\tif (nodes.length === 0) return [createTextNode('')];\n\n\t// Fast path: no InlineNodes, delegate to normalizeTextNodes\n\tif (nodes.every((n): n is TextNode => isTextNode(n))) {\n\t\treturn normalizeTextNodes(nodes);\n\t}\n\n\tconst result: (TextNode | InlineNode)[] = [];\n\n\tfor (const node of nodes) {\n\t\tif (isInlineNode(node)) {\n\t\t\tresult.push(node);\n\t\t\tcontinue;\n\t\t}\n\t\t// TextNode: try to merge with previous TextNode\n\t\tconst prev: TextNode | InlineNode | undefined = result[result.length - 1];\n\t\tif (prev && isTextNode(prev) && markSetsEqual(prev.marks, node.marks)) {\n\t\t\tresult[result.length - 1] = createTextNode(prev.text + node.text, prev.marks);\n\t\t} else if (node.text.length > 0 || result.length === 0) {\n\t\t\tresult.push(node);\n\t\t}\n\t}\n\n\t// Remove empty TextNodes that are adjacent to InlineNodes\n\tconst cleaned: (TextNode | InlineNode)[] = result.filter((node, i) => {\n\t\tif (isInlineNode(node)) return true;\n\t\tif (node.text.length > 0) return true;\n\t\t// Keep if it's the only node\n\t\tif (result.length === 1) return true;\n\t\t// Remove empty TextNode if adjacent to InlineNode\n\t\tconst prev: TextNode | InlineNode | undefined = result[i - 1];\n\t\tconst next: TextNode | InlineNode | undefined = result[i + 1];\n\t\tif ((prev && isInlineNode(prev)) || (next && isInlineNode(next))) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\t// Ensure at least one TextNode exists\n\tif (cleaned.length === 0) return [createTextNode('')];\n\tif (!cleaned.some((n) => isTextNode(n))) {\n\t\treturn [createTextNode(''), ...cleaned];\n\t}\n\n\treturn cleaned;\n}\n\n/** Materializes a single {@link ContentSegment} into its inline child node. */\nexport function contentSegmentToInlineNode(segment: ContentSegment): TextNode | InlineNode {\n\treturn segment.kind === 'inline' ? segment.node : createTextNode(segment.text, segment.marks);\n}\n\n/**\n * Materializes content segments (text + inline) into normalized inline children.\n * Inverse of {@link getBlockContentSegmentsInRange}: used when turning a range of\n * segments back into a block's children (paste insertion, slice extraction).\n */\nexport function segmentsToInlineChildren(\n\tsegments: readonly ContentSegment[],\n): readonly (TextNode | InlineNode)[] {\n\treturn normalizeInlineContent(segments.map(contentSegmentToInlineNode));\n}\n\n/** Yields each inline child with its offset range. InlineNodes have width 1. */\nexport function* walkInlineContent(children: readonly (TextNode | InlineNode)[]): Generator<{\n\treadonly child: TextNode | InlineNode;\n\treadonly from: number;\n\treadonly to: number;\n}> {\n\tlet pos = 0;\n\tfor (const child of children) {\n\t\tconst width: number = isInlineNode(child) ? 1 : child.text.length;\n\t\tyield { child, from: pos, to: pos + width };\n\t\tpos += width;\n\t}\n}\n\n/**\n * Converts a block-space offset to a text-space offset.\n *\n * Block-space counts InlineNodes as width 1, but `getBlockText()` skips them.\n * This function maps a block offset to the equivalent position in the\n * text-only string returned by `getBlockText()`.\n */\nexport function blockOffsetToTextOffset(block: BlockNode, blockOffset: number): number {\n\tlet textPos = 0;\n\n\tfor (const { child, from, to } of walkInlineContent(getInlineChildren(block))) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (from >= blockOffset) return textPos;\n\t\t} else {\n\t\t\tif (to >= blockOffset) return textPos + (blockOffset - from);\n\t\t\ttextPos += child.text.length;\n\t\t}\n\t}\n\n\treturn textPos;\n}\n\n/** Returns the content at a specific offset: text char, inline node, or null. */\nexport function getContentAtOffset(\n\tblock: BlockNode,\n\toffset: number,\n):\n\t| { readonly kind: 'text'; readonly char: string; readonly marks: readonly Mark[] }\n\t| { readonly kind: 'inline'; readonly node: InlineNode }\n\t| null {\n\tconst inlineChildren: readonly (TextNode | InlineNode)[] = getInlineChildren(block);\n\n\tfor (const { child, from } of walkInlineContent(inlineChildren)) {\n\t\tif (isInlineNode(child)) {\n\t\t\tif (offset === from) return { kind: 'inline', node: child };\n\t\t\tcontinue;\n\t\t}\n\t\tconst localOffset: number = offset - from;\n\t\tif (localOffset >= 0 && localOffset < child.text.length) {\n\t\t\treturn {\n\t\t\t\tkind: 'text',\n\t\t\t\tchar: child.text[localOffset] ?? '',\n\t\t\t\tmarks: child.marks,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{C as t,E as e,T as n,a as s,c as o,d as r,i,s as c,v as a,w as l}from"./Document-r7vLOAGA.mjs";import{a as u,i as f,r as d,t as p}from"./TypeBrands-Ch9856Gb.mjs";import{r as h}from"./AttrRegistry-DcDVyzLm.mjs";import{n as g,r as y,t as A}from"./HTMLUtils-C6B4UT00.mjs";import T from"dompurify";var m=/^[A-Za-z0-9_-]{1,64}$/;function E(t){return m.test(t)}function N(t,e){const n=t.getAttribute("data-block-id");if(n&&E(n)&&!e.has(n))return e.add(n),p(n)}function b(t){return t.split(";").map(t=>t.trim()).filter(t=>t.length>0).sort().join("; ")}function L(t){let e=2166136261;for(let n=0;n<t.length;n++)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return(e>>>0).toString(36).padStart(6,"0")}var k=class{classMap=/* @__PURE__ */new Map;usedHashes=/* @__PURE__ */new Set;getClassName(t){const e=b(t),n=this.classMap.get(e);if(n)return n;let s=L(e),o=0;for(;this.usedHashes.has(s);)o++,s=L(e+String(o));const r=`notectl-s-${s}`;return this.usedHashes.add(s),this.classMap.set(e,r),r}getAlignmentClassName(t){const e=b(`text-align: ${t}`),n=this.classMap.get(e);if(n)return n;const s=`notectl-align-${t}`;return this.classMap.set(e,s),s}toCSS(){if(0===this.classMap.size)return"";const t=[];for(const[e,n]of this.classMap)t.push(`.${n} { ${e}; }`);return t.join("\n")}toStyleMap(){const t=/* @__PURE__ */new Map;for(const[e,n]of this.classMap)t.set(n,e);return t}};function M(t){const e=t.getMarkTypes(),n=/* @__PURE__ */new Map;for(const s of e){const e=t.getMarkSpec(s);e&&n.set(s,e.rank??99)}return n}function x(t,e,n,s,o,r){if(""===t)return"";let i=y(t);if(0===e.length)return i;const c=s??M(n),a=[...e].sort((t,e)=>(c.get(t.type)??99)-(c.get(e.type)??99)),l=[],u=[];for(const f of a){const t=n.getMarkSpec(f.type);if(t?.toHTMLStyle){const e=t.toHTMLStyle(f);e&&l.push(e)}else u.push(f)}l.length>0&&(i=r(i,l.join("; ")));for(const f of u){const t=n.getMarkSpec(f.type);t?.toHTMLString&&(i=t.toHTMLString(f,i,o))}return i}function $(t,e,n,s,o){return x(t,e,n,s,o,(t,e)=>{const n=o?o.styleAttr(e):` style="${e}"`;return n?`<span${n}>${t}</span>`:t})}function O(t,e,n,s,o,r){return x(t,e,n,o,r,(t,e)=>`<span class="${s.getClassName(e)}">${t}</span>`)}var S=new Set(["start","center","end","justify"]),w={left:"start",right:"end"},v=new Set(["ltr","rtl"]);function C(t){return{styleAttr:e=>e?` class="${t.getClassName(e)}"`:""}}function D(t,e,n){const s=_(t);if(!s)return t;const o=t.slice(s.start,s.end+1),r=new RegExp(`\\s${e}\\s*=\\s*("([^"]*)"|'([^']*)')`),i=o.match(r);if(i){const c=i[2]??i[3]??"";if("style"===e&&/(?:^|;)\s*text-align\s*:/i.test(c))return t;const a=` ${e}="${c}${"style"===e?"; ":" "}${n}"`,l=o.replace(r,a);return`${t.slice(0,s.start)}${l}${t.slice(s.end+1)}`}const c=o.endsWith("/>")?`${o.slice(0,-2)} ${e}="${n}"/>`:`${o.slice(0,-1)} ${e}="${n}">`;return`${t.slice(0,s.start)}${c}${t.slice(s.end+1)}`}function _(t){let e=t.indexOf("<");for(;e>=0;){const n=t[e+1];if(n&&/[A-Za-z]/.test(n)){let n;for(let s=e+2;s<t.length;s++){const o=t[s]??"";if(n)o===n&&(n=void 0);else if('"'!==o&&"'"!==o){if(">"===o)return{start:e,end:s}}else n=o}return}e=t.indexOf("<",e+1)}}function R(t){const e=_(t);return e?t.slice(e.start,e.end+1):""}function H(t){return t?{}:{FORBID_ATTR:["data-block-id"]}}function I(t,e,n){const s=!1!==n?.includeBlockIds,o={registry:e,exportCtx:{styleAttr:t=>t?` style="${t}"`:""},includeBlockIds:s},r=P(t.children,o),i=e?e.getAllowedTags():["p","br","div","span"],c=e?e.getAllowedAttrs():["style","dir"];return T.sanitize(r,{ALLOWED_TAGS:i,ALLOWED_ATTR:c,ALLOWED_URI_REGEXP:A,...H(s)})}function j(t,e,n){const s=!1!==n?.includeBlockIds,o=new k,r={registry:e,collector:o,exportCtx:C(o),includeBlockIds:s},i=P(t.children,r),c=e?e.getAllowedTags():["p","br","div","span"],a=e?e.getAllowedAttrs():["style","class","dir"],l=(a.includes("class")?[...a]:[...a,"class"]).filter(t=>"style"!==t);return{html:T.sanitize(i,{ALLOWED_TAGS:c,ALLOWED_ATTR:l,ALLOWED_URI_REGEXP:A,...H(s)}),css:o.toCSS(),styleMap:o.toStyleMap()}}function P(t,e){const n=[];let s=0;for(;s<t.length;){const o=t[s];if(o)if(h(o,"list_item")){const o=[];for(;s<t.length;){const e=t[s];if(!e||!h(e,"list_item"))break;o.push(e),s++}n.push(W(o,e))}else n.push(G(o,e)),s++;else s++}return n.join("")}function W(t,e){const n=[],s=[];for(let o=0;o<t.length;o++){const r=t[o];if(!r)continue;const i=r.attrs?.listType??"bullet",c=r.attrs?.indent??0,a="ordered"===i?"ol":"ul";for(;s.length>0;){const t=s[s.length-1];if(!t)break;if(t.indent>c)n.push(`</${t.tag}></li>`),s.pop();else{if(t.indent!==c||t.tag===a)break;n.push(`</${t.tag}></li>`),s.pop()}}if(0===s.length)n.push(`<${a}>`),s.push({tag:a,indent:c});else{const t=s[s.length-1];t&&c>t.indent&&(n.push(`<${a}>`),s.push({tag:a,indent:c}))}const l=G(r,e),u=t[o+1],f=u?u.attrs?.indent??0:void 0;void 0!==f&&f>c?n.push(B(l)):n.push(l)}for(;s.length>0;){const t=s.pop();if(!t)break;n.push(`</${t.tag}>`),s.length>0&&n.push("</li>")}return n.join("")}function B(t){return t.endsWith("</li>")?t.slice(0,-5):t}function G(s,o){const i=l(s)?function(s,o){const r=function(s){if(s.length<=1)return s;const o=[];for(const r of s){if(t(r)){o.push(r);continue}const s=o[o.length-1];s&&n(s)&&e(s.marks,r.marks)?o[o.length-1]={type:"text",text:s.text+r.text,marks:s.marks}:o.push(r)}return o}(a(s)),i=[],c=o.registry?M(o.registry):void 0;for(const e of r)if(t(e)){const t=o.registry?.getInlineNodeSpec(e.inlineType);t?.toHTMLString&&i.push(t.toHTMLString(e))}else o.registry&&o.collector?i.push(O(e.text,e.marks,o.registry,o.collector,c,o.exportCtx)):o.registry?i.push($(e.text,e.marks,o.registry,c,o.exportCtx)):""!==e.text&&i.push(y(e.text));return i.join("")}(s,o):P(r(s),o),c=o.registry?.getNodeSpec(s.type);let u;u=c?.toHTML?c.toHTML(s,i,o.exportCtx):`<p>${i||"<br>"}</p>`,o.includeBlockIds&&E(s.id)&&(R(u).includes(" data-block-id=")||(u=D(u,"data-block-id",g(s.id))));const f=s.attrs?.align,d=f?w[f]??f:void 0;if(d&&"start"!==d&&S.has(d)){const t=g(d);if(o.collector){const t=o.collector.getAlignmentClassName(d);u=D(u,"class",g(t))}else u=D(u,"style",`text-align: ${t}`)}const p=s.attrs?.dir;return p&&v.has(p)&&(R(u).includes(" dir=")||(u=D(u,"dir",g(p)))),u}var X=/[ \t\n\r\f]+/g,U=new Set(["P","DIV","H1","H2","H3","H4","H5","H6","BLOCKQUOTE","UL","OL","LI","TABLE","THEAD","TBODY","TFOOT","TR","TD","TH","HR","FIGURE","FIGCAPTION","SECTION","ARTICLE","HEADER","FOOTER","MAIN","ASIDE","NAV","DL","DT","DD"]),z=new Set(["PRE","TEXTAREA"]),F=new Set(["pre","pre-wrap","pre-line","break-spaces"]);function q(t){V(t)}function V(t){const e={lastTextNode:null,collapsePending:!0};for(const n of Array.from(t.childNodes))Z(n,e);Q(e.lastTextNode)}function Z(t,e){if(t.nodeType===Node.TEXT_NODE)return void function(t,e){let n=t.data.replace(X," ");e.collapsePending&&n.startsWith(" ")&&(n=n.slice(1)),t.data=n,0!==n.length&&(e.collapsePending=n.endsWith(" "),e.lastTextNode=t)}(t,e);if(t.nodeType!==Node.ELEMENT_NODE)return;const n=t;if(function(t){if(z.has(t.tagName))return!0;const e=(t.style?.whiteSpace??"").toLowerCase();return F.has(e)}(n))K(e);else{if(function(t){return U.has(t.tagName)}(n))return K(e),void V(n);for(const t of Array.from(n.childNodes))Z(t,e)}}function K(t){Q(t.lastTextNode),t.lastTextNode=null,t.collapsePending=!0}function Q(t){t?.data.endsWith(" ")&&(t.data=t.data.slice(0,-1))}function Y(t,e,n){const o=e?e.getAllowedTags():["p","br","div","span"],r=e?e.getAllowedAttrs():["style","dir"];r.includes("data-block-id")||r.push("data-block-id"),n?.styleMap&&!r.includes("class")&&r.push("class");const i=document.createElement("template");i.innerHTML=T.sanitize(t,{ALLOWED_TAGS:o,ALLOWED_ATTR:r,ALLOWED_URI_REGEXP:A});const c=i.content;n?.styleMap&&function(t,e){const n=t.querySelectorAll("[class]");for(const s of Array.from(n)){const t=s,n=Array.from(t.classList),o=[];for(const s of n){const n=e.get(s);if(n){const e=t.getAttribute("style")??"",r=e&&!e.endsWith(";")?"; ":"";t.setAttribute("style",e+r+n),o.push(s)}}for(const e of o)t.classList.remove(e)}}(c,n.styleMap),q(c);const a=e?.getBlockParseRules()??[],l=[],u=/* @__PURE__ */new Set;for(const s of Array.from(c.childNodes))J(s,l,a,u,e);return 0===l.length?s():s(l)}function J(t,e,n,s,r){if(t.nodeType===Node.ELEMENT_NODE){const c=t,a=c.tagName.toLowerCase();if("ul"===a||"ol"===a){const t="ol"===a?"ordered":"bullet",n=c.getAttribute("dir");return void tt(c,t,0,e,s,r,n&&v.has(n)?n:void 0)}if("table"===a)return void function(t,e,n,s){const o=[],r=function(t){const e=[];for(const n of Array.from(t.children)){const t=n.tagName.toLowerCase();if("tr"===t)e.push(n);else if("thead"===t||"tbody"===t||"tfoot"===t)for(const s of Array.from(n.children))"tr"===s.tagName.toLowerCase()&&e.push(s)}return e}(t);for(const c of r){const t=[];for(const e of Array.from(c.children)){const o=e.tagName.toLowerCase();if("td"!==o&&"th"!==o)continue;const r=e,c=st(r,n,s),a={};nt(r,a);const l=i(u("table_cell"),c,N(r,n),Object.keys(a).length>0?a:void 0);t.push(l)}t.length>0&&o.push(i(u("table_row"),t,N(c,n)))}if(o.length>0){const s={};!function(t,e){const n=t.getAttribute("style")??"",s=et.exec(n);s?.[1]&&(e.borderColor="transparent"===s[1]?"none":s[1])}(t,s),e.push(i(u("table"),o,N(t,n),Object.keys(s).length>0?s:void 0))}}(c,e,s,r);if("blockquote"===a)return void function(t,e,n,s){const r=ot(t,s?.getBlockParseRules()??[],n,s);0===r.length&&r.push(i(u("paragraph"),[o("")]));const c={};ft(t,c),lt(t,c),e.push(i(u("blockquote"),r,N(t,n),Object.keys(c).length>0?c:void 0))}(c,e,s,r);const l=dt(c,n);if(l){const t=r?.getNodeSpec(l.type),n=t?.isVoid?[o("")]:it(c,r),a={...l.attrs};return t?.attrs?.align&&ft(c,a),t?.attrs?.dir&<(c,a),void e.push(i(u(l.type),n,N(c,s),Object.keys(a).length>0?a:void 0))}const f=it(c,r),d={};ft(c,d),lt(c,d),e.push(i(u("paragraph"),f,N(c,s),Object.keys(d).length>0?d:void 0))}else t.nodeType===Node.TEXT_NODE&&t.textContent?.trim()&&e.push(i(u("paragraph"),[o(t.textContent.trim())]))}function tt(t,e,n,s,o,r,c){for(const a of Array.from(t.children)){const t=a.tagName.toLowerCase();if("li"===t){const t=a,l=t.querySelector(':scope > input[type="checkbox"]'),f=null!==l,d=l?.hasAttribute("checked")??!1,p=f?"checklist":e,h=it(t,r,!0),g={listType:p,indent:n,checked:d},y=t.getAttribute("dir"),A=y&&v.has(y)?y:c;A&&(g.dir=A),s.push(i(u("list_item"),h,N(t,o),g));for(const e of Array.from(t.children)){const t=e.tagName.toLowerCase();if("ul"===t||"ol"===t){const i="ol"===t?"ordered":"bullet",c=e.getAttribute("dir");tt(e,i,n+1,s,o,r,c&&v.has(c)?c:A)}}}else if("ul"===t||"ol"===t){const e="ol"===t?"ordered":"bullet",i=a.getAttribute("dir");tt(a,e,n+1,s,o,r,i&&v.has(i)?i:c)}}}var et=/--ntbl-bc:\s*(#[0-9a-fA-F]{3,8}|transparent)/;function nt(t,e){const n=t.getAttribute("colspan");if(n){const t=Number.parseInt(n,10);t>1&&(e.colspan=t)}const s=t.getAttribute("rowspan");if(s){const t=Number.parseInt(s,10);t>1&&(e.rowspan=t)}}function st(t,e,n){const s=ot(t,n?.getBlockParseRules()??[],e,n);return 0===s.length&&s.push(i(u("paragraph"),[o("")])),s}function ot(t,e,n,s){const o=[];let r=[];const c=()=>{(function(t){for(const e of t){if(e.nodeType===Node.ELEMENT_NODE)return!0;if(e.nodeType===Node.TEXT_NODE&&e.textContent?.trim())return!0}return!1})(r)&&o.push(i(u("paragraph"),ct(r,s))),r=[]};for(const i of Array.from(t.childNodes))rt(i,e)?(c(),J(i,o,e,n,s)):r.push(i);return c(),o}function rt(t,e){if(t.nodeType!==Node.ELEMENT_NODE)return!1;const n=t,s=n.tagName.toLowerCase();return"ul"===s||"ol"===s||"table"===s||"blockquote"===s||null!==dt(n,e)}function it(t,e,n){return ct([t],e,n)}function ct(e,n,s){const r=[],i=n?.getMarkParseRules()??[],c=n?.getInlineParseRules()??[];for(const t of e)at(t,[],r,i,c,s);return 1===r.length&&t(r[0])&&"hard_break"===r[0].inlineType?[o("")]:r.length>0?r:[o("")]}function at(t,e,n,s,r,i){if(t.nodeType===Node.TEXT_NODE){const s=t.textContent??"";return void(s&&n.push(o(s,[...e])))}if(t.nodeType!==Node.ELEMENT_NODE)return;const a=t,l=a.tagName.toLowerCase();if(i&&("ul"===l||"ol"===l))return;if(i&&"input"===l&&"checkbox"===a.getAttribute("type"))return;for(const o of r)if(o.rule.tag===l){if(o.rule.getAttrs){const t=o.rule.getAttrs(a);if(!1===t)continue;return void n.push(c(d(o.type),t))}return void n.push(c(d(o.type)))}const u=[...e],p=/* @__PURE__ */new Set;for(const o of s)if(o.rule.tag===l&&!p.has(o.type))if(o.rule.getAttrs){const t=o.rule.getAttrs(a);if(!1===t)continue;u.some(t=>t.type===o.type)||(u.push({type:f(o.type),...Object.keys(t).length>0?{attrs:t}:{}}),p.add(o.type))}else u.some(t=>t.type===o.type)||(u.push({type:f(o.type)}),p.add(o.type));for(const o of Array.from(a.childNodes))at(o,u,n,s,r,i)}function lt(t,e){const n=t.getAttribute("dir");if(n&&v.has(n))return void(e.dir=n);const s=t.style?.direction??"";s&&v.has(s)&&(e.dir=s)}var ut={left:"start",right:"end"};function ft(t,e){let n=t.style?.textAlign??"";const s=ut[n];if(s&&(n=s),n&&S.has(n))e.align=n;else for(const o of Array.from(t.classList)){let t=o.match(/^notectl-align-(\w+)$/)?.[1];const n=ut[t??""];if(n&&(t=n),t&&S.has(t))return void(e.align=t)}}function dt(t,e){const n=t.tagName.toLowerCase();for(const s of e)if(s.rule.tag===n){if(s.rule.getAttrs){const e=s.rule.getAttrs(t);if(!1===e)continue;return{type:s.type,attrs:e}}return{type:s.type}}return null}export{j as a,$ as c,v as i,q as n,I as o,S as r,M as s,Y as t};
|
|
2
|
-
//# sourceMappingURL=DocumentParser-CcTSeT1B.mjs.map
|