@notectl/core 2.0.1 → 2.0.2
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/README.md +12 -10
- package/dist/chunks/{AttrRegistry-Ckj9eCHj.mjs → AttrRegistry-iNpjvcSG.mjs} +2 -2
- package/dist/chunks/{AttrRegistry-Ckj9eCHj.mjs.map → AttrRegistry-iNpjvcSG.mjs.map} +1 -1
- package/dist/chunks/AttributedMarkCommands-BY1BSYWM.mjs +2 -0
- package/dist/chunks/{AttributedMarkCommands-x7h4Xy7V.mjs.map → AttributedMarkCommands-BY1BSYWM.mjs.map} +1 -1
- package/dist/chunks/BlockInsertion-BJFhE0jA.mjs +2 -0
- package/dist/chunks/BlockInsertion-BJFhE0jA.mjs.map +1 -0
- package/dist/chunks/{ColorPickerPopup-CDUvkgcK.mjs → ColorPickerPopup-D6XjShhv.mjs} +2 -2
- package/dist/chunks/{ColorPickerPopup-CDUvkgcK.mjs.map → ColorPickerPopup-D6XjShhv.mjs.map} +1 -1
- package/dist/chunks/CommandHelpers-M6mPS6Ww.mjs +2 -0
- package/dist/chunks/CommandHelpers-M6mPS6Ww.mjs.map +1 -0
- package/dist/chunks/Commands-D_gMCnVa.mjs +2 -0
- package/dist/chunks/Commands-D_gMCnVa.mjs.map +1 -0
- package/dist/chunks/Document-3pNX7ear.mjs +2 -0
- package/dist/chunks/{Document-HC8s50qJ.mjs.map → Document-3pNX7ear.mjs.map} +1 -1
- package/dist/chunks/{DocumentParser-w70-Axud.mjs → DocumentParser-LvzDQOd1.mjs} +2 -2
- package/dist/chunks/{DocumentParser-w70-Axud.mjs.map → DocumentParser-LvzDQOd1.mjs.map} +1 -1
- package/dist/chunks/{HeadingPlugin-B-LF-AMM.mjs → HeadingPlugin-BmkeUXj8.mjs} +2 -2
- package/dist/chunks/{HeadingPlugin-B-LF-AMM.mjs.map → HeadingPlugin-BmkeUXj8.mjs.map} +1 -1
- package/dist/chunks/MarkCommands-CeCa4WSC.mjs +2 -0
- package/dist/chunks/{MarkCommands-CTuVDqnn.mjs.map → MarkCommands-CeCa4WSC.mjs.map} +1 -1
- package/dist/chunks/NavigationQueries-11qe4j9x.mjs +2 -0
- package/dist/chunks/NavigationQueries-11qe4j9x.mjs.map +1 -0
- package/dist/chunks/NodeResolver-z0ReCR34.mjs +2 -0
- package/dist/chunks/NodeResolver-z0ReCR34.mjs.map +1 -0
- package/dist/chunks/NodeSelectionCommands-CXrOcPtG.mjs +2 -0
- package/dist/chunks/NodeSelectionCommands-CXrOcPtG.mjs.map +1 -0
- package/dist/chunks/NotectlEditor-BJD7-FFx.mjs +4 -0
- package/dist/chunks/NotectlEditor-BJD7-FFx.mjs.map +1 -0
- package/dist/chunks/PopupManager-0b_Q0m7K.mjs +2 -0
- package/dist/chunks/PopupManager-0b_Q0m7K.mjs.map +1 -0
- package/dist/chunks/{RangeIterator-CprUbOWv.mjs → RangeIterator-XFN5FaYf.mjs} +2 -2
- package/dist/chunks/{RangeIterator-CprUbOWv.mjs.map → RangeIterator-XFN5FaYf.mjs.map} +1 -1
- package/dist/chunks/SelectionTransactions-DzIZxcuN.mjs +2 -0
- package/dist/chunks/{SelectionTransactions-DB3YDIEa.mjs.map → SelectionTransactions-DzIZxcuN.mjs.map} +1 -1
- package/dist/chunks/{TextDirectionLocale-BraFI9JF.mjs → TextDirectionLocale-CKz0ZrH_.mjs} +2 -2
- package/dist/chunks/{TextDirectionLocale-BraFI9JF.mjs.map → TextDirectionLocale-CKz0ZrH_.mjs.map} +1 -1
- package/dist/chunks/index-C-L4awHz.mjs +2 -0
- package/dist/chunks/index-C-L4awHz.mjs.map +1 -0
- package/dist/chunks/{index-D3BZFsAD.mjs → index-Cs9iqxhF.mjs} +2 -2
- package/dist/chunks/{index-D3BZFsAD.mjs.map → index-Cs9iqxhF.mjs.map} +1 -1
- package/dist/commands/BlockInsertion.d.ts.map +1 -1
- package/dist/commands/CommandHelpers.d.ts +13 -2
- package/dist/commands/CommandHelpers.d.ts.map +1 -1
- package/dist/commands/NodeSelectionCommands.d.ts +3 -8
- package/dist/commands/NodeSelectionCommands.d.ts.map +1 -1
- package/dist/editor/ContentSerializer.d.ts.map +1 -1
- package/dist/editor/EditorConfig.d.ts +50 -0
- package/dist/editor/EditorConfig.d.ts.map +1 -0
- package/dist/editor/EditorConfigController.d.ts +1 -1
- package/dist/editor/EditorConfigController.d.ts.map +1 -1
- package/dist/editor/EditorDOM.d.ts.map +1 -1
- package/dist/editor/EditorInitializer.d.ts +37 -0
- package/dist/editor/EditorInitializer.d.ts.map +1 -0
- package/dist/editor/EditorLifecycleCoordinator.d.ts +6 -1
- package/dist/editor/EditorLifecycleCoordinator.d.ts.map +1 -1
- package/dist/editor/NotectlEditor.d.ts +13 -51
- package/dist/editor/NotectlEditor.d.ts.map +1 -1
- package/dist/editor/PluginBootstrapper.d.ts +1 -1
- package/dist/editor/PluginBootstrapper.d.ts.map +1 -1
- package/dist/full.mjs +1 -1
- package/dist/html.mjs +1 -1
- package/dist/input/ClipboardHandler.d.ts +5 -0
- package/dist/input/ClipboardHandler.d.ts.map +1 -1
- package/dist/input/HTMLParser.d.ts +9 -5
- package/dist/input/HTMLParser.d.ts.map +1 -1
- package/dist/input/InputHandler.d.ts +1 -0
- package/dist/input/InputHandler.d.ts.map +1 -1
- package/dist/input/PasteHTMLHandler.d.ts +25 -0
- package/dist/input/PasteHTMLHandler.d.ts.map +1 -0
- package/dist/input/PasteHandler.d.ts +2 -27
- package/dist/input/PasteHandler.d.ts.map +1 -1
- package/dist/input/PasteRichBlockHandler.d.ts +23 -0
- package/dist/input/PasteRichBlockHandler.d.ts.map +1 -0
- package/dist/input/SelectionDocument.d.ts +10 -0
- package/dist/input/SelectionDocument.d.ts.map +1 -0
- package/dist/model/RichBlockData.d.ts +12 -2
- package/dist/model/RichBlockData.d.ts.map +1 -1
- 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/plugins/PluginContextFactory.d.ts +73 -0
- package/dist/plugins/PluginContextFactory.d.ts.map +1 -0
- package/dist/plugins/PluginManager.d.ts +5 -0
- package/dist/plugins/PluginManager.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.mjs +1 -1
- package/dist/plugins/font-size.mjs +1 -1
- package/dist/plugins/font.mjs +1 -1
- package/dist/plugins/gap-cursor.mjs +1 -1
- package/dist/plugins/hard-break.mjs +1 -1
- package/dist/plugins/heading.mjs +1 -1
- package/dist/plugins/highlight.mjs +1 -1
- package/dist/plugins/horizontal-rule.mjs +1 -1
- package/dist/plugins/image/ImageCommands.d.ts.map +1 -1
- package/dist/plugins/image.mjs +1 -1
- package/dist/plugins/image.mjs.map +1 -1
- package/dist/plugins/link.mjs +1 -1
- package/dist/plugins/list.mjs +1 -1
- package/dist/plugins/print.mjs +1 -1
- package/dist/plugins/shared/PopupManager.d.ts.map +1 -1
- package/dist/plugins/shared.mjs +1 -1
- package/dist/plugins/smart-paste.mjs +1 -1
- package/dist/plugins/strikethrough.mjs +1 -1
- package/dist/plugins/super-sub.mjs +1 -1
- package/dist/plugins/table/TableCommands.d.ts +1 -0
- package/dist/plugins/table/TableCommands.d.ts.map +1 -1
- package/dist/plugins/table/TableContextMenu.d.ts.map +1 -1
- package/dist/plugins/table/TableSelection.d.ts.map +1 -1
- package/dist/plugins/table.mjs +1 -1
- package/dist/plugins/table.mjs.map +1 -1
- package/dist/plugins/text-color.mjs +1 -1
- package/dist/plugins/text-direction-advanced.mjs +1 -1
- package/dist/plugins/text-direction.mjs +1 -1
- package/dist/plugins/text-formatting.mjs +1 -1
- package/dist/plugins/toolbar/ToolbarOverflowController.d.ts +2 -0
- package/dist/plugins/toolbar/ToolbarOverflowController.d.ts.map +1 -1
- package/dist/plugins/toolbar.mjs +1 -1
- package/dist/plugins/toolbar.mjs.map +1 -1
- package/dist/presets/full.mjs +1 -1
- package/dist/state/StepInversion.d.ts.map +1 -1
- package/dist/view/EditorView.d.ts +8 -58
- package/dist/view/EditorView.d.ts.map +1 -1
- package/dist/view/EditorViewEvents.d.ts +54 -0
- package/dist/view/EditorViewEvents.d.ts.map +1 -0
- package/dist/view/EditorViewNavigation.d.ts +47 -0
- package/dist/view/EditorViewNavigation.d.ts.map +1 -0
- package/dist/view/SelectionSync.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/chunks/AttributedMarkCommands-x7h4Xy7V.mjs +0 -2
- package/dist/chunks/BlockInsertion-zPxm6oa_.mjs +0 -2
- package/dist/chunks/BlockInsertion-zPxm6oa_.mjs.map +0 -1
- package/dist/chunks/Commands-DwXBBVGR.mjs +0 -2
- package/dist/chunks/Commands-DwXBBVGR.mjs.map +0 -1
- package/dist/chunks/Document-HC8s50qJ.mjs +0 -2
- package/dist/chunks/MarkCommands-CTuVDqnn.mjs +0 -2
- package/dist/chunks/NavigationQueries-DCOv4Ca5.mjs +0 -2
- package/dist/chunks/NavigationQueries-DCOv4Ca5.mjs.map +0 -1
- package/dist/chunks/NotectlEditor-DBBJkPCW.mjs +0 -3
- package/dist/chunks/NotectlEditor-DBBJkPCW.mjs.map +0 -1
- package/dist/chunks/PopupManager-Du3dYnsJ.mjs +0 -2
- package/dist/chunks/PopupManager-Du3dYnsJ.mjs.map +0 -1
- package/dist/chunks/SelectionTransactions-DB3YDIEa.mjs +0 -2
- package/dist/chunks/index-CVwf0cdH.mjs +0 -2
- package/dist/chunks/index-CVwf0cdH.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../src/view/EditorView.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"EditorView.d.ts","sourceRoot":"","sources":["../../src/view/EditorView.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,MAAM,mBAAmB,GAAG,CACjC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,WAAW,KACX,IAAI,CAAC;AAEV,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,WAAW,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,WAAW,KAAK,aAAa,CAAC;IACzE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED,qBAAa,UAAU;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAA0D;IAC1F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB;IAmDnE,wCAAwC;IACxC,QAAQ,IAAI,WAAW;IAIvB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmCnB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAK/B,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,qBAAqB;IACrB,IAAI,IAAI,IAAI;IAOZ,yCAAyC;IACzC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAQxD,wEAAwE;IACxE,YAAY,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAkCzC,iDAAiD;IACjD,aAAa,IAAI,IAAI;IAIrB,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,gBAAgB;IAmBxB,kDAAkD;IAClD,OAAO,IAAI,IAAI;CASf"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { CompositionState } from '../model/CompositionState.js';
|
|
2
|
+
import { FileHandlerRegistry } from '../model/FileHandlerRegistry.js';
|
|
3
|
+
import { EditorState } from '../state/EditorState.js';
|
|
4
|
+
import { Transaction } from '../state/Transaction.js';
|
|
5
|
+
import { CursorWrapper } from './CursorWrapper.js';
|
|
6
|
+
export interface EventCoordinatorDeps {
|
|
7
|
+
readonly contentElement: HTMLElement;
|
|
8
|
+
readonly getState: () => EditorState;
|
|
9
|
+
readonly dispatch: (tr: Transaction) => void;
|
|
10
|
+
readonly applyUpdate: (newState: EditorState, tr: Transaction) => void;
|
|
11
|
+
readonly isUpdating: () => boolean;
|
|
12
|
+
readonly compositionState: CompositionState;
|
|
13
|
+
readonly cursorWrapper: CursorWrapper;
|
|
14
|
+
readonly isReadOnly: () => boolean;
|
|
15
|
+
readonly fileHandlerRegistry?: FileHandlerRegistry;
|
|
16
|
+
readonly onMousedown?: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare class EditorViewEvents {
|
|
19
|
+
private readonly deps;
|
|
20
|
+
private readonly handleSelectionChange;
|
|
21
|
+
private readonly handleMousedown;
|
|
22
|
+
private readonly handleDragover;
|
|
23
|
+
private readonly handleDrop;
|
|
24
|
+
private readonly handleCompositionStart;
|
|
25
|
+
private readonly handleCompositionEnd;
|
|
26
|
+
private pendingNodeSelectionClear;
|
|
27
|
+
private pendingGapCursorClear;
|
|
28
|
+
constructor(deps: EventCoordinatorDeps);
|
|
29
|
+
/** Syncs the DOM selection into editor state. */
|
|
30
|
+
syncSelectionFromDOM(): void;
|
|
31
|
+
/** Removes all event listeners. */
|
|
32
|
+
destroy(): void;
|
|
33
|
+
/** Handles DOM selection changes (clicks, arrow keys). */
|
|
34
|
+
private onSelectionChange;
|
|
35
|
+
/** Handles mousedown on selectable/void blocks. */
|
|
36
|
+
private onMousedown;
|
|
37
|
+
/**
|
|
38
|
+
* When the user clicks below all rendered blocks, appends a
|
|
39
|
+
* new paragraph after the last block and focuses it.
|
|
40
|
+
*/
|
|
41
|
+
private handleClickBelowContent;
|
|
42
|
+
/** Allows file drop by preventing default on dragover. */
|
|
43
|
+
private onDragover;
|
|
44
|
+
/** Handles file drop via registered file handlers. */
|
|
45
|
+
private onDrop;
|
|
46
|
+
/** Converts screen coordinates to an editor Position. */
|
|
47
|
+
private getPositionFromPoint;
|
|
48
|
+
/**
|
|
49
|
+
* Marks pending clear flags when clicking non-selectable blocks
|
|
50
|
+
* while NodeSelection or GapCursor is active.
|
|
51
|
+
*/
|
|
52
|
+
private markPendingSelectionClear;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=EditorViewEvents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorViewEvents.d.ts","sourceRoot":"","sources":["../../src/view/EditorViewEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAW3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAa;IAClD,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,IAAI,EAAE,oBAAoB;IAyBtC,iDAAiD;IACjD,oBAAoB,IAAI,IAAI;IAiC5B,mCAAmC;IACnC,OAAO,IAAI,IAAI;IAUf,0DAA0D;IAC1D,OAAO,CAAC,iBAAiB;IAczB,mDAAmD;IACnD,OAAO,CAAC,WAAW;IAmDnB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAwC/B,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAQlB,sDAAsD;IACtD,OAAO,CAAC,MAAM;IA0Bd,yDAAyD;IACzD,OAAO,CAAC,oBAAoB;IAU5B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;CASjC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { KeymapRegistry } from '../model/KeymapRegistry.js';
|
|
2
|
+
import { EditorState } from '../state/EditorState.js';
|
|
3
|
+
import { Transaction } from '../state/Transaction.js';
|
|
4
|
+
export interface NavigationHandlerDeps {
|
|
5
|
+
readonly contentElement: HTMLElement;
|
|
6
|
+
readonly getState: () => EditorState;
|
|
7
|
+
readonly dispatch: (tr: Transaction) => void;
|
|
8
|
+
readonly keymapRegistry?: KeymapRegistry;
|
|
9
|
+
}
|
|
10
|
+
export declare class EditorViewNavigation {
|
|
11
|
+
private readonly deps;
|
|
12
|
+
private navigationKeymap;
|
|
13
|
+
private goalColumn;
|
|
14
|
+
private preserveGoalColumn;
|
|
15
|
+
constructor(deps: NavigationHandlerDeps);
|
|
16
|
+
/**
|
|
17
|
+
* Resets goalColumn after an update unless vertical navigation
|
|
18
|
+
* is in progress.
|
|
19
|
+
*/
|
|
20
|
+
resetAfterUpdate(): void;
|
|
21
|
+
/** Clears goalColumn unconditionally (e.g. on mousedown). */
|
|
22
|
+
clearGoalColumn(): void;
|
|
23
|
+
/** Removes navigation keymaps from the registry. */
|
|
24
|
+
destroy(): void;
|
|
25
|
+
/** Registers arrow-key keymaps with navigation priority. */
|
|
26
|
+
private registerKeymaps;
|
|
27
|
+
/** Handles a navigation arrow key at textblock boundaries. */
|
|
28
|
+
private handleArrow;
|
|
29
|
+
/** Handles horizontal arrow: InlineNode skip + cross-block. */
|
|
30
|
+
private handleHorizontalArrow;
|
|
31
|
+
/**
|
|
32
|
+
* Maps visual horizontal arrow to logical movement direction
|
|
33
|
+
* in offset space for the current block direction.
|
|
34
|
+
*/
|
|
35
|
+
private resolveLogicalDirection;
|
|
36
|
+
/** Handles vertical arrow with goalColumn preservation. */
|
|
37
|
+
private handleVerticalArrow;
|
|
38
|
+
/**
|
|
39
|
+
* Validates DOM cursor after an InlineNode skip.
|
|
40
|
+
*
|
|
41
|
+
* Chrome can place the cursor inside a `contenteditable="false"`
|
|
42
|
+
* element (phantom position), and Firefox may lose the cursor.
|
|
43
|
+
* This read-back roundtrip detects drift and forces re-sync.
|
|
44
|
+
*/
|
|
45
|
+
private validateSelectionAfterInlineSkip;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=EditorViewNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorViewNavigation.d.ts","sourceRoot":"","sources":["../../src/view/EditorViewNavigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AASjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAW3D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,WAAW,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CACzC;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAwB;IAC7C,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,IAAI,EAAE,qBAAqB;IAKvC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAMxB,6DAA6D;IAC7D,eAAe,IAAI,IAAI;IAIvB,oDAAoD;IACpD,OAAO,IAAI,IAAI;IAOf,4DAA4D;IAC5D,OAAO,CAAC,eAAe;IAqBvB,8DAA8D;IAC9D,OAAO,CAAC,WAAW;IAanB,+DAA+D;IAC/D,OAAO,CAAC,qBAAqB;IAwB7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAa/B,2DAA2D;IAC3D,OAAO,CAAC,mBAAmB;IA+B3B;;;;;;OAMG;IACH,OAAO,CAAC,gCAAgC;CAYxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionSync.d.ts","sourceRoot":"","sources":["../../src/view/SelectionSync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAelF,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,CAE1D;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,UAAU,CAAC,SAAS,GACvB,kBAAkB,GAAG,IAAI,CAsC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,UAAU,CAAC,SAAS,GAC1B,kBAAkB,GAAG,IAAI,CAe3B;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI,CAmC3F;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAiB7E;AAsED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,WAAW,EACtB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,GACf,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"SelectionSync.d.ts","sourceRoot":"","sources":["../../src/view/SelectionSync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAelF,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,CAE1D;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,UAAU,CAAC,SAAS,GACvB,kBAAkB,GAAG,IAAI,CAsC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,UAAU,CAAC,SAAS,GAC1B,kBAAkB,GAAG,IAAI,CAe3B;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI,CAmC3F;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAiB7E;AAsED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,WAAW,EACtB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,GACf,QAAQ,GAAG,IAAI,CAkEjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notectl/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "A modern and accessible rich text editor shipped as a single Web Component. Immutable state, transaction-based architecture, and a plugin system that powers every feature.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
}
|
|
363
363
|
],
|
|
364
364
|
"dependencies": {
|
|
365
|
-
"dompurify": "^3.3.
|
|
365
|
+
"dompurify": "^3.3.2"
|
|
366
366
|
},
|
|
367
367
|
"devDependencies": {
|
|
368
368
|
"@size-limit/preset-small-lib": "^12.0.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as t}from"./AttrRegistry-Ckj9eCHj.mjs";import{h as n,m as o,k as r,q as e}from"./Document-HC8s50qJ.mjs";import{j as s,i as c,s as i}from"./Selection-DhbizDM4.mjs";import{m as a}from"./TypeBrands-Bp_Z_o5Y.mjs";import{f as l}from"./RangeIterator-CprUbOWv.mjs";function f(t,o){const r=t.selection;if(!s(r))return null;const e=a(o.type);if(c(r)){const s=t.getBlock(r.anchor.blockId);if(!s)return null;const c=[...(t.storedMarks??n(s,r.anchor.offset)).filter(t=>t.type!==e),o];return t.transaction("command").setStoredMarks(c,t.storedMarks).setSelection(r).build()}const f=i(r,t.getBlockOrder()),u=t.transaction("command");return l(t,f,(n,r,s)=>{const c=t.getBlock(n);if(c){const t=k(c,e,r,s);t&&u.removeMark(n,r,s,t)}u.addMark(n,r,s,o)}),u.setSelection(r),u.build()}function u(t,r){const e=t.selection;if(!s(e))return null;if(c(e)){const s=t.getBlock(e.anchor.blockId);if(!s)return null;const c=t.storedMarks??n(s,e.anchor.offset);if(!o(c,r))return null;const i=c.filter(t=>t.type!==r);return t.transaction("command").setStoredMarks(i,t.storedMarks).setSelection(e).build()}const a=i(e,t.getBlockOrder()),f=t.transaction("command");return l(t,a,(n,o,e)=>{const s=t.getBlock(n),c=s?k(s,r,o,e):void 0;f.removeMark(n,o,e,c??{type:r})}),f.setSelection(e),f.build()}function m(o,r,e){const i=o.selection;if(!s(i))return null;if(c(i)&&o.storedMarks){const n=o.storedMarks.find(t=>t.type===r);return n&&t(n,r)?e(n):null}const a=o.getBlock(i.anchor.blockId);if(!a)return null;const l=n(a,i.anchor.offset).find(t=>t.type===r);return l&&t(l,r)?e(l):null}function d(t,n){return null!==m(t,n,()=>!0)}function k(t,n,o,s){const c=r(t);let i=0;for(const r of c){if(!e(r)){i+=1;continue}const t=i+r.text.length;if(t>o&&i<s){const t=r.marks.find(t=>t.type===n);if(t)return t}i=t}}export{f as a,m as g,d as i,u as r};
|
|
2
|
-
//# sourceMappingURL=AttributedMarkCommands-x7h4Xy7V.mjs.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n as t,s as n,c as e,i as o,e as r}from"./Document-HC8s50qJ.mjs";import{a as s}from"./NavigationQueries-DCOv4Ca5.mjs";import{h as c,g as a}from"./Selection-DhbizDM4.mjs";import{n as i}from"./TypeBrands-Bp_Z_o5Y.mjs";import{g as f,h as u,j as d}from"./Commands-DwXBBVGR.mjs";function p(t,n,e){const o=s(t.doc,n),r=f(o),c=u(t,r),a=d(c,n);if(!(a<0))return{parentPath:r,anchorIndex:a,isAnchorEmpty:b(t,n,e)}}function m(n,e,o,r){const c=s(n.doc,o);if(!c)return;const a=n.getBlock(o);return a?{parentPath:c,anchorIndex:a.children.findIndex(n=>t(n)&&n.id===e),isAnchorEmpty:b(n,e,r)}:void 0}function h(t,n){const e=t.getBlock(n);if("table_cell"===e?.type)return n;const o=s(t.doc,n);if(o)for(const r of o){const n=t.getBlock(r);if("table_cell"===n?.type)return r}}function l(t){return c(t)?t.nodeId:a(t)?t.blockId:t.anchor.blockId}function y(t,n,e,o,r,s){const c=h(t,e);if(c){const r=m(t,e,c,s);if(!r)return!1;const a=r.anchorIndex+1;n.insertNode(r.parentPath,a,o),r.isAnchorEmpty&&r.anchorIndex>=0&&n.removeNode(r.parentPath,r.anchorIndex)}else{const c=p(t,e,s);if(!c)return!1;const i=a(r)&&"before"===r.side?0:1;n.insertNode(c.parentPath,c.anchorIndex+i,o),c.isAnchorEmpty&&!a(r)&&n.removeNode(c.parentPath,c.anchorIndex)}return!0}function g(o,r){const s=o.children.map(e=>t(e)?g(e,n()):e);return e(o.type,s,r,o.attrs)}function x(n,e){if(n.id===e)return n;for(const o of n.children){if(!t(o))continue;const n=x(o,e);if(n)return n}}function I(t,n){if(!n)return;const e={};let o=!1;for(const r of Object.keys(n)){const s=n[r],c=t?.[r];"string"==typeof c||"number"==typeof c||"boolean"==typeof c?e[r]=c:void 0!==s.default&&(e[r]=s.default),r in e&&(o=!0)}return o?e:void 0}function b(t,n,e){const r=t.getBlock(n);if(!r)return!1;const s=e?.getNodeSpec(r.type);return!s?.isVoid&&""===o(r)}function v(t,n){if(!t.type)return;if(!n)return t;const e=n.getNodeSpec(t.type);if(!e)return;const o=I(t.attrs,e.attrs);return{...t,attrs:o}}function k(t){const o=n(),s=function(t,n){return t.segments&&t.segments.length>0?function(t){const n=[];for(const e of t){if(0===e.text.length)continue;const t=e.marks.map(t=>({type:t.type,...t.attrs?{attrs:t.attrs}:{}}));n.push(r(e.text,t))}return n}(t.segments):n?[r(n)]:void 0}(t,t.text??""),c=t.attrs?t.attrs:void 0;return e(i(t.type),s,o,c)}export{p as a,g as b,k as c,x as d,l as e,h as f,y as i,m as r,I as s,v};
|
|
2
|
-
//# sourceMappingURL=BlockInsertion-zPxm6oa_.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BlockInsertion-zPxm6oa_.mjs","sources":["../../src/commands/BlockInsertion.ts"],"sourcesContent":["/**\n * Block insertion utilities for paste and clipboard operations.\n *\n * Provides context resolution (parent path, anchor index, empty detection)\n * for inserting blocks into the document tree — both at root level and\n * inside table cells. Also contains pure helpers for block cloning,\n * recursive lookup, and attribute sanitization against a NodeSpec.\n */\n\nimport {\n\ttype BlockAttrs,\n\ttype BlockNode,\n\ttype ChildNode,\n\ttype Mark,\n\ttype TextNode,\n\tcreateBlockNode,\n\tcreateTextNode,\n\tgenerateBlockId,\n\tgetBlockText,\n\tisBlockNode,\n} from '../model/Document.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport type { AttrSpec } from '../model/NodeSpec.js';\nimport type { RichBlockData, RichSegment } from '../model/RichBlockData.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport type { EditorSelection } from '../model/Selection.js';\nimport { isGapCursor, isNodeSelection } from '../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../model/TypeBrands.js';\nimport { nodeType } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport type { TransactionBuilder } from '../state/Transaction.js';\nimport { extractParentPath, findSiblingIndex, getSiblings } from './CommandHelpers.js';\n\n/**\n * Resolved insertion target within the document tree.\n * Contains everything needed to insert blocks at a specific anchor position.\n */\nexport interface InsertionContext {\n\treadonly parentPath: readonly BlockId[];\n\treadonly anchorIndex: number;\n\treadonly isAnchorEmpty: boolean;\n}\n\n/**\n * Resolves an insertion context for root-level (or nested-parent-level) insertion.\n * Computes the parent path, anchor index among siblings, and whether the anchor is empty.\n */\nexport function resolveRootInsertionContext(\n\tstate: EditorState,\n\tanchorBlockId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): InsertionContext | undefined {\n\tconst path: readonly string[] | undefined = findNodePath(state.doc, anchorBlockId);\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\n\tconst siblings: readonly ChildNode[] = getSiblings(state, parentPath);\n\tconst anchorIndex: number = findSiblingIndex(siblings, anchorBlockId);\n\tif (anchorIndex < 0) return undefined;\n\n\tconst isAnchorEmpty: boolean = isBlockEmpty(state, anchorBlockId, schemaRegistry);\n\treturn { parentPath, anchorIndex, isAnchorEmpty };\n}\n\n/**\n * Resolves an insertion context within a table cell.\n * The parent path points to the cell itself; siblings are the cell's children.\n */\nexport function resolveCellInsertionContext(\n\tstate: EditorState,\n\tanchorBlockId: BlockId,\n\tcellId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): InsertionContext | undefined {\n\tconst cellPath: BlockId[] | undefined = findNodePath(state.doc, cellId) as BlockId[] | undefined;\n\tif (!cellPath) return undefined;\n\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return undefined;\n\n\tconst anchorIndex: number = cell.children.findIndex(\n\t\t(c) => isBlockNode(c) && c.id === anchorBlockId,\n\t);\n\n\tconst isAnchorEmpty: boolean = isBlockEmpty(state, anchorBlockId, schemaRegistry);\n\treturn { parentPath: cellPath, anchorIndex, isAnchorEmpty };\n}\n\n/**\n * Finds a table_cell ancestor for the given block.\n * Walks the node path upward, returning the first table_cell BlockId found.\n */\nexport function findTableCellAncestor(state: EditorState, blockId: BlockId): BlockId | undefined {\n\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\tif (block?.type === 'table_cell') return blockId;\n\n\tconst path: BlockId[] | undefined = findNodePath(state.doc, blockId) as BlockId[] | undefined;\n\tif (!path) return undefined;\n\n\tfor (const id of path) {\n\t\tconst node: BlockNode | undefined = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table_cell') return id as BlockId;\n\t}\n\treturn undefined;\n}\n\n/**\n * Resolves the anchor block ID from the current editor selection.\n * Handles text selection, node selection, and gap cursor uniformly.\n */\nexport function resolveAnchorBlockId(selection: EditorSelection): BlockId {\n\tif (isNodeSelection(selection)) return selection.nodeId;\n\tif (isGapCursor(selection)) return selection.blockId;\n\treturn selection.anchor.blockId;\n}\n\n/**\n * Inserts a block node after the anchor position, resolving cell vs root context.\n * Removes the anchor block if it is empty (matching standard paste behavior).\n * Returns true on success, false if context resolution fails.\n */\nexport function insertBlockAfterAnchor(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\tanchorBlockId: BlockId,\n\tblock: BlockNode,\n\tselection: EditorSelection,\n\tschemaRegistry?: SchemaRegistry,\n): boolean {\n\tconst cellId: BlockId | undefined = findTableCellAncestor(state, anchorBlockId);\n\n\tif (cellId) {\n\t\tconst ctx: InsertionContext | undefined = resolveCellInsertionContext(\n\t\t\tstate,\n\t\t\tanchorBlockId,\n\t\t\tcellId,\n\t\t\tschemaRegistry,\n\t\t);\n\t\tif (!ctx) return false;\n\n\t\tconst insertIndex: number = ctx.anchorIndex + 1;\n\t\tbuilder.insertNode(ctx.parentPath, insertIndex, block);\n\n\t\tif (ctx.isAnchorEmpty && ctx.anchorIndex >= 0) {\n\t\t\tbuilder.removeNode(ctx.parentPath, ctx.anchorIndex);\n\t\t}\n\t} else {\n\t\tconst ctx: InsertionContext | undefined = resolveRootInsertionContext(\n\t\t\tstate,\n\t\t\tanchorBlockId,\n\t\t\tschemaRegistry,\n\t\t);\n\t\tif (!ctx) return false;\n\n\t\tconst insertOffset: number = isGapCursor(selection) && selection.side === 'before' ? 0 : 1;\n\t\tbuilder.insertNode(ctx.parentPath, ctx.anchorIndex + insertOffset, block);\n\n\t\tif (ctx.isAnchorEmpty && !isGapCursor(selection)) {\n\t\t\tbuilder.removeNode(ctx.parentPath, ctx.anchorIndex);\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/** Recursively clones a block tree, assigning new IDs to all block nodes. */\nexport function cloneBlockWithNewIds(block: BlockNode, newId: BlockId): BlockNode {\n\tconst children = block.children.map((child) => {\n\t\tif (isBlockNode(child)) {\n\t\t\treturn cloneBlockWithNewIds(child, generateBlockId());\n\t\t}\n\t\treturn child;\n\t});\n\treturn createBlockNode(block.type, children, newId, block.attrs);\n}\n\n/** Recursively searches a block tree for a block with the given ID (DFS). */\nexport function findBlockRecursive(block: BlockNode, blockId: BlockId): BlockNode | undefined {\n\tif (block.id === blockId) return block;\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tconst found: BlockNode | undefined = findBlockRecursive(child, blockId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\n/**\n * Validates incoming attributes against the declared AttrSpec.\n * Only keys declared in the spec are kept; non-primitive values fall back to defaults.\n */\nexport function sanitizeAttrs(\n\tincoming: Record<string, unknown> | undefined,\n\tspecAttrs: Readonly<Record<string, AttrSpec>> | undefined,\n): Record<string, string | number | boolean> | undefined {\n\tif (!specAttrs) return undefined;\n\n\tconst result: Record<string, string | number | boolean> = {};\n\tlet hasKeys = false;\n\n\tfor (const key of Object.keys(specAttrs)) {\n\t\tconst spec: AttrSpec = specAttrs[key] as AttrSpec;\n\t\tconst raw: unknown = incoming?.[key];\n\n\t\tif (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {\n\t\t\tresult[key] = raw;\n\t\t} else if (spec.default !== undefined) {\n\t\t\tresult[key] = spec.default;\n\t\t}\n\t\tif (key in result) hasKeys = true;\n\t}\n\n\treturn hasKeys ? result : undefined;\n}\n\n/** Checks whether a block is empty (has no text and is not a void block). */\nfunction isBlockEmpty(\n\tstate: EditorState,\n\tblockId: BlockId,\n\tschemaRegistry?: SchemaRegistry,\n): boolean {\n\tconst block: BlockNode | undefined = state.getBlock(blockId);\n\tif (!block) return false;\n\n\tconst spec = schemaRegistry?.getNodeSpec(block.type);\n\treturn !spec?.isVoid && getBlockText(block) === '';\n}\n\n// --- Rich block creation ---\n\n/**\n * Validates a rich block against the schema registry.\n * Returns undefined for blocks with unknown types; sanitizes attributes\n * against the declared spec.\n */\nexport function validateRichBlockData(\n\traw: RichBlockData,\n\tschemaRegistry?: SchemaRegistry,\n): RichBlockData | undefined {\n\tif (!raw.type) return undefined;\n\tif (!schemaRegistry) return raw;\n\n\tconst spec = schemaRegistry.getNodeSpec(raw.type);\n\tif (!spec) return undefined;\n\n\tconst attrs: Record<string, string | number | boolean> | undefined = sanitizeAttrs(\n\t\traw.attrs,\n\t\tspec.attrs,\n\t);\n\treturn { ...raw, attrs };\n}\n\n/**\n * Creates a BlockNode from validated rich block data.\n * Converts segments or plain text into inline children.\n */\nexport function createBlockFromRichData(blockData: RichBlockData): BlockNode {\n\tconst newId: BlockId = generateBlockId();\n\tconst text: string = blockData.text ?? '';\n\tconst children: TextNode[] | undefined = createChildrenFromRichBlock(blockData, text);\n\tconst attrs: BlockAttrs | undefined = blockData.attrs\n\t\t? (blockData.attrs as BlockAttrs)\n\t\t: undefined;\n\n\treturn createBlockNode(nodeType(blockData.type) as NodeTypeName, children, newId, attrs);\n}\n\n/**\n * Creates inline children from rich block data.\n * Uses mark-preserving segments when available, falls back to plain text.\n */\nfunction createChildrenFromRichBlock(\n\tblockData: RichBlockData,\n\ttext: string,\n): TextNode[] | undefined {\n\tif (blockData.segments && blockData.segments.length > 0) {\n\t\treturn createChildrenFromSegments(blockData.segments);\n\t}\n\treturn text ? [createTextNode(text)] : undefined;\n}\n\n/** Converts rich segments into TextNode children with marks. */\nfunction createChildrenFromSegments(segments: readonly RichSegment[]): TextNode[] {\n\tconst children: TextNode[] = [];\n\tfor (const seg of segments) {\n\t\tif (seg.text.length === 0) continue;\n\t\tconst marks: readonly Mark[] = seg.marks.map((m) => ({\n\t\t\ttype: m.type as Mark['type'],\n\t\t\t...(m.attrs ? { attrs: m.attrs as Mark['attrs'] } : {}),\n\t\t}));\n\t\tchildren.push(createTextNode(seg.text, marks));\n\t}\n\treturn children;\n}\n"],"names":["resolveRootInsertionContext","state","anchorBlockId","schemaRegistry","path","findNodePath","doc","parentPath","extractParentPath","siblings","getSiblings","anchorIndex","findSiblingIndex","isAnchorEmpty","isBlockEmpty","resolveCellInsertionContext","cellId","cellPath","cell","getBlock","children","findIndex","c","isBlockNode","id","findTableCellAncestor","blockId","block","type","node","resolveAnchorBlockId","selection","isNodeSelection","nodeId","isGapCursor","anchor","insertBlockAfterAnchor","builder","ctx","insertIndex","insertNode","removeNode","insertOffset","side","cloneBlockWithNewIds","newId","map","child","generateBlockId","createBlockNode","attrs","findBlockRecursive","found","sanitizeAttrs","incoming","specAttrs","result","hasKeys","key","Object","keys","spec","raw","default","getNodeSpec","isVoid","getBlockText","validateRichBlockData","createBlockFromRichData","blockData","text","segments","length","seg","marks","m","push","createTextNode","createChildrenFromSegments","createChildrenFromRichBlock","nodeType"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n as t,c as n,e,s as o,f as r,d as c,h as i,p as l}from"./Document-HC8s50qJ.mjs";import{a as s,e as f,d as u,s as d,i as a}from"./NavigationQueries-DCOv4Ca5.mjs";import{i as b,s as k,c as I,h,g,a as m,b as p,j as S,e as B}from"./Selection-DhbizDM4.mjs";import{n as x,i as O}from"./TypeBrands-Bp_Z_o5Y.mjs";function N(t,n){if(0===n.length)return t.doc.children;const e=t.getBlock(n[n.length-1]);return e?e.children:[]}function A(t){return n(x("paragraph"),[e("")],t)}function T(t,n){if(b(t))return{blockId:t.anchor.blockId,offset:t.anchor.offset};const e=k(t,n);return{blockId:e.from.blockId,offset:e.from.offset}}function j(t){return t&&t.length>1?t.slice(0,-1):[]}function v(n,e){return n.findIndex(n=>t(n)&&n.id===e)}function w(n,e){const c=s(n.doc,e.nodeId);if(!c)return null;const i=j(c),l=N(n,i),f=v(l,e.nodeId);if(f<0)return null;const u=n.transaction("input");if(1===l.length&&0===i.length){const t=o();return u.insertNode(i,0,A(t)),u.removeNode(i,1),u.setSelection(I(t,0)),u.build()}u.removeNode(i,f);const d=l[f-1];if(d&&t(d)){const t=y(d);if(t){const e=n.getBlock(t),o=e?r(e):0;u.setSelection(I(t,o))}}else{const n=l[f+1];if(n&&t(n)){const t=_(n);t&&u.setSelection(I(t,0))}}return u.build()}function M(t,n,e){const o=t.selection,c=t.getBlockOrder(),i=!e||"left"!==n&&"right"!==n?n:"left"===n?"right":"left";return h(o)?function(t,n,e,o){const c=o.indexOf(n.nodeId),i=s(t.doc,n.nodeId)??[];if("left"===e||"up"===e){if(c>0){const e=o[c-1];if(!e)return null;if(f(t,e))return t.transaction("input").setSelection(m(n.nodeId,"before",i)).build();const l=t.getBlock(e),s=l?r(l):0;return t.transaction("input").setSelection(I(e,s)).build()}return t.transaction("input").setSelection(m(n.nodeId,"before",i)).build()}if(c<o.length-1){const e=o[c+1];return e?f(t,e)?t.transaction("input").setSelection(m(n.nodeId,"after",i)).build():t.transaction("input").setSelection(I(e,0)).build():null}return t.transaction("input").setSelection(m(n.nodeId,"after",i)).build()}(t,o,i,c):g(o)?null:b(o)?function(t,n,e,o){const c=o.indexOf(n.anchor.blockId),i=t.getBlock(n.anchor.blockId);if(!i)return null;const l=r(i);if(("right"===e||"down"===e)&&n.anchor.offset===l&&c<o.length-1){const n=o[c+1];if(n&&f(t,n)){const e=s(t.doc,n)??[];return t.transaction("input").setSelection(p(n,e)).build()}}if(("left"===e||"up"===e)&&0===n.anchor.offset&&c>0){const n=o[c-1];if(n&&f(t,n)){const e=s(t.doc,n)??[];return t.transaction("input").setSelection(p(n,e)).build()}}return null}(t,o,i,c):null}function _(n){let e=n;for(;;){const n=e.children.find(n=>t(n));if(!n)return e.id;e=n}}function y(n){let e=n;for(;;){let n;for(let o=e.children.length-1;o>=0;o--){const r=e.children[o];if(r&&t(r)){n=r;break}}if(!n)return e.id;e=n}}function D(t,n){if("after"===n.side)return q(t,n);const e=t.getBlockOrder(),o=e.indexOf(n.blockId);if(o<=0)return null;const c=e[o-1];if(!c)return null;if(f(t,c)){const n=s(t.doc,c)??[];return t.transaction("input").setSelection(p(c,n)).build()}const i=t.getBlock(c);if(!i)return null;const l=r(i);return t.transaction("input").setSelection(I(c,l)).build()}function Q(t,n){if("before"===n.side)return q(t,n);const e=t.getBlockOrder(),o=e.indexOf(n.blockId);if(o>=e.length-1)return null;const r=e[o+1];if(!r)return null;if(f(t,r)){const n=s(t.doc,r)??[];return t.transaction("input").setSelection(p(r,n)).build()}return t.transaction("input").setSelection(I(r,0)).build()}function q(t,n){const e=s(t.doc,n.blockId)??[];return w(t,p(n.blockId,e))}function z(t,n,e="input"){const r=t.selection;if(h(r))return function(t,n,e,r){const c=j(s(t.doc,n.nodeId)),i=N(t,c),l=v(i,n.nodeId),f=o(),u=t.transaction(r),d=l>=0?l+1:i.length;return u.insertNode(c,d,A(f)),u.insertText(f,0,e,[]),u.setSelection(I(f,e.length)),u.build()}(t,r,n,e);if(g(r))return function(t,n,e,r){const c=j(s(t.doc,n.blockId)),i=N(t,c),l=v(i,n.blockId),f="before"===n.side?Math.max(l,0):l>=0?l+1:i.length,u=o(),d=t.transaction(r);return d.insertNode(c,f,A(u)),d.insertText(u,0,e,[]),d.setSelection(I(u,e.length)),d.build()}(t,r,n,e);const c=t.transaction(e),l=function(t){if(t.storedMarks)return t.storedMarks;if(!S(t.selection))return[];const n=t.getBlock(t.selection.anchor.blockId);return n?i(n,t.selection.anchor.offset):[]}(t);let f;b(r)||(f=L(t,c));const u=T(r,t.getBlockOrder()),d=f??u.blockId,a=f?0:u.offset;return c.insertText(d,a,n,l),c.setSelection(I(d,a+n.length)),c.build()}function C(t){if(h(t.selection))return w(t,t.selection);if(g(t.selection))return null;if(b(t.selection))return null;const n=t.transaction("input"),e=L(t,n),o=k(t.selection,t.getBlockOrder()),r=e??o.from.blockId,c=e?0:o.from.offset;return n.setSelection(I(r,c)),n.build()}function E(t){const n=t.selection;if(h(n))return function(t,n){const e=s(t.doc,n.nodeId);if(!e)return null;const r=j(e),c=v(N(t,r),n.nodeId);if(c<0)return null;const i=o(),l=t.transaction("input");return l.insertNode(r,c+1,A(i)),l.setSelection(I(i,0)),l.build()}(t,n);if(g(n))return function(t,n){const e=s(t.doc,n.blockId);if(!e)return null;const r=j(e),c=v(N(t,r),n.blockId);if(c<0)return null;const i="before"===n.side?c:c+1,l=o(),f=t.transaction("input");return f.insertNode(r,i,A(l)),f.setSelection(I(l,0)),f.build()}(t,n);const e=t.transaction("input");let r;b(n)||(r=L(t,e));const c=T(n,t.getBlockOrder()),i=r??c.blockId,l=r?0:c.offset,f=o();return e.splitBlock(i,l,f),e.setSelection(I(f,0)),e.build()}function F(t){const n=t.selection;if(!S(n))return null;const e=t.transaction("input");let o;if(b(n)||(o=L(t,e)),o)e.insertInlineNode(o,0,c(O("hard_break"))),e.setSelection(I(o,1));else{const{blockId:o,offset:r}=T(n,t.getBlockOrder());e.insertInlineNode(o,r,c(O("hard_break"))),e.setSelection(I(o,r+1))}return e.build()}function G(t){return J(t,"backward")}function H(t){return J(t,"forward")}function J(t,n){const e=t.selection;if(!S(e))return null;const o=t.getBlockOrder(),c=o.indexOf(e.anchor.blockId),i="backward"===n?c-1:c+1;if(i<0||i>=o.length)return null;const l=o[i];if(!l)return null;if(u(t,e.anchor.blockId)||u(t,l))return null;if(!d(t,e.anchor.blockId,l)&&a(t,e.anchor.blockId))return null;if(f(t,l)){const n=s(t.doc,l)??[];return t.transaction("input").setSelection(p(l,n)).build()}if("backward"===n){const n=t.getBlock(l);if(!n)return null;const o=r(n);return t.transaction("input").mergeBlocksAt(l,e.anchor.blockId).setSelection(I(l,o)).build()}return t.transaction("input").mergeBlocksAt(e.anchor.blockId,l).setSelection(I(e.anchor.blockId,e.anchor.offset)).build()}function K(t){const n=t.doc.children,e=n[0],o=n[n.length-1];if(!e||!o)return t.transaction("command").setSelection(t.selection).build();const c=_(e),i=y(o),l=t.getBlock(i),s=l?r(l):0;return t.transaction("command").setSelection(B({blockId:c,offset:0},{blockId:i,offset:s})).build()}function L(t,n){if(!S(t.selection))return;const e=t.getBlockOrder(),c=k(t.selection,e),i=e.indexOf(c.from.blockId),s=e.indexOf(c.to.blockId);if(i===s)return void n.deleteTextAt(c.from.blockId,c.from.offset,c.to.offset);const f=P(t,c.from.blockId),u=P(t,c.to.blockId);if(!(f===u||f<0||u<0))return function(t,n,e,c,i){const s=t.doc.children[c],f=t.doc.children[i];if(!s||!f)return;const u=l(s),d=l(f);let a,b=0;if(u||(a=o(),n.insertNode([],c,A(a)),b=1),u){const o=t.getBlock(e.from.blockId);if(o){const t=r(o);e.from.offset<t&&n.deleteTextAt(e.from.blockId,e.from.offset,t)}}d&&e.to.offset>0&&n.deleteTextAt(e.to.blockId,0,e.to.offset);const k=u?c+1:c+b;for(let o=d?i-1+b:i+b;o>=k;o--)n.removeNode([],o);return u&&d&&n.mergeBlocksAt(e.from.blockId,e.to.blockId),a}(t,n,c,f,u);!function(t,n,e,o,c,i){const l=t.getBlock(o.from.blockId);if(!l)return;const s=r(l);o.from.offset<s&&n.deleteTextAt(o.from.blockId,o.from.offset,s),o.to.offset>0&&n.deleteTextAt(o.to.blockId,0,o.to.offset);for(let f=c+1;f<i;f++){const c=e[f];if(!c)continue;const i=t.getBlock(c);if(!i)continue;const l=r(i);l>0&&n.deleteTextAt(c,0,l),n.mergeBlocksAt(o.from.blockId,c)}n.mergeBlocksAt(o.from.blockId,o.to.blockId)}(t,n,e,c,i,s)}function P(t,n){const e=s(t.doc,n);if(!e||0===e.length)return-1;const o=e[0];return t.doc.children.findIndex(t=>t.id===o)}export{Q as a,w as b,C as c,D as d,z as e,E as f,j as g,N as h,F as i,v as j,H as k,L as l,G as m,M as n,y as o,T as r,K as s};
|
|
2
|
-
//# sourceMappingURL=Commands-DwXBBVGR.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Commands-DwXBBVGR.mjs","sources":["../../src/commands/CommandHelpers.ts","../../src/commands/NodeSelectionCommands.ts","../../src/commands/GapCursorCommands.ts","../../src/commands/Commands.ts"],"sourcesContent":["/**\n * Shared helpers used across multiple command modules.\n *\n * - {@link getSiblings} — resolves a parent path to its child list\n * - {@link createEmptyParagraph} — builds an empty paragraph BlockNode\n * - {@link resolveInsertPoint} — normalizes a text selection to a single insert position\n */\n\nimport type { BlockNode, ChildNode } from '../model/Document.js';\nimport { createBlockNode, createTextNode, isBlockNode } from '../model/Document.js';\nimport { isCollapsed, selectionRange } from '../model/Selection.js';\nimport type { Selection } from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport { nodeType } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\n\n/** The resolved insert position within a single block. */\nexport interface InsertPoint {\n\treadonly blockId: BlockId;\n\treadonly offset: number;\n}\n\n/** Resolves the children of a parent path: doc root or a nested block. */\nexport function getSiblings(\n\tstate: EditorState,\n\tparentPath: readonly BlockId[],\n): readonly ChildNode[] {\n\tif (parentPath.length === 0) return state.doc.children;\n\tconst parent: BlockNode | undefined = state.getBlock(\n\t\tparentPath[parentPath.length - 1] as BlockId,\n\t);\n\treturn parent ? parent.children : [];\n}\n\n/** Creates an empty paragraph block node with the given ID. */\nexport function createEmptyParagraph(id: BlockId): BlockNode {\n\treturn createBlockNode(nodeType('paragraph'), [createTextNode('')], id);\n}\n\n/**\n * Normalizes a text selection to a single insert point.\n *\n * - Collapsed selection → anchor position.\n * - Range selection → normalized `from` position (document-order start).\n */\nexport function resolveInsertPoint(sel: Selection, blockOrder: readonly BlockId[]): InsertPoint {\n\tif (isCollapsed(sel)) {\n\t\treturn { blockId: sel.anchor.blockId, offset: sel.anchor.offset };\n\t}\n\tconst range = selectionRange(sel, blockOrder);\n\treturn { blockId: range.from.blockId, offset: range.from.offset };\n}\n\n/** Extracts the parent path from a full node path (all elements except the last). */\nexport function extractParentPath(path: readonly string[] | undefined): BlockId[] {\n\treturn path && path.length > 1 ? (path.slice(0, -1) as BlockId[]) : [];\n}\n\n/** Finds the index of a block by ID within a sibling list. */\nexport function findSiblingIndex(siblings: readonly ChildNode[], targetId: BlockId): number {\n\treturn siblings.findIndex((c) => isBlockNode(c) && c.id === targetId);\n}\n","/**\n * Commands for NodeSelection: deleting void blocks, inserting paragraphs\n * after void blocks, and navigating arrow keys into/out of void blocks.\n */\n\nimport { type BlockNode, generateBlockId, getBlockLength, isBlockNode } from '../model/Document.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport type { NodeSelection } from '../model/Selection.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateGapCursor,\n\tcreateNodeSelection,\n\tisCollapsed,\n\tisGapCursor,\n\tisNodeSelection,\n} from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport { isVoidBlock } from '../state/NavigationQueries.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport {\n\tcreateEmptyParagraph,\n\textractParentPath,\n\tfindSiblingIndex,\n\tgetSiblings,\n} from './CommandHelpers.js';\n\n/**\n * Deletes the void block targeted by a NodeSelection and places cursor\n * on the adjacent block. If it's the only block, replaces with empty paragraph.\n */\nexport function deleteNodeSelection(state: EditorState, sel: NodeSelection): Transaction | null {\n\tconst path = findNodePath(state.doc, sel.nodeId);\n\tif (!path) return null;\n\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\tconst siblings = getSiblings(state, parentPath);\n\n\tconst index: number = findSiblingIndex(siblings, sel.nodeId);\n\tif (index < 0) return null;\n\n\tconst builder = state.transaction('input');\n\n\t// If this is the only block in the document, insert empty paragraph first\n\tif (siblings.length === 1 && parentPath.length === 0) {\n\t\tconst newId = generateBlockId();\n\t\tbuilder.insertNode(parentPath, 0, createEmptyParagraph(newId));\n\t\tbuilder.removeNode(parentPath, 1);\n\t\tbuilder.setSelection(createCollapsedSelection(newId, 0));\n\t\treturn builder.build();\n\t}\n\n\tbuilder.removeNode(parentPath, index);\n\n\t// Find where to place cursor: prefer previous sibling leaf, else next sibling leaf.\n\tconst prevSibling = siblings[index - 1];\n\tif (prevSibling && isBlockNode(prevSibling)) {\n\t\tconst prevLeafId = findLastLeafBlockId(prevSibling);\n\t\tif (prevLeafId) {\n\t\t\tconst prevLeaf = state.getBlock(prevLeafId);\n\t\t\tconst prevLen = prevLeaf ? getBlockLength(prevLeaf) : 0;\n\t\t\tbuilder.setSelection(createCollapsedSelection(prevLeafId, prevLen));\n\t\t}\n\t} else {\n\t\tconst nextSibling = siblings[index + 1];\n\t\tif (nextSibling && isBlockNode(nextSibling)) {\n\t\t\tconst nextLeafId = findFirstLeafBlockId(nextSibling);\n\t\t\tif (nextLeafId) {\n\t\t\t\tbuilder.setSelection(createCollapsedSelection(nextLeafId, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn builder.build();\n}\n\n/** Inserts a new paragraph after a NodeSelection-targeted void block. */\nexport function insertParagraphAfterNodeSelection(\n\tstate: EditorState,\n\tsel: NodeSelection,\n): Transaction | null {\n\tconst path = findNodePath(state.doc, sel.nodeId);\n\tif (!path) return null;\n\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\tconst siblings = getSiblings(state, parentPath);\n\n\tconst index: number = findSiblingIndex(siblings, sel.nodeId);\n\tif (index < 0) return null;\n\n\tconst newId = generateBlockId();\n\tconst builder = state.transaction('input');\n\tbuilder.insertNode(parentPath, index + 1, createEmptyParagraph(newId));\n\tbuilder.setSelection(createCollapsedSelection(newId, 0));\n\treturn builder.build();\n}\n\n/** Inserts text in a new paragraph after a NodeSelection-targeted void block. */\nexport function insertTextAfterNodeSelection(\n\tstate: EditorState,\n\tsel: NodeSelection,\n\ttext: string,\n\torigin: 'input' | 'paste',\n): Transaction {\n\tconst path = findNodePath(state.doc, sel.nodeId);\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\tconst siblings = getSiblings(state, parentPath);\n\n\tconst index: number = findSiblingIndex(siblings, sel.nodeId);\n\n\tconst newId = generateBlockId();\n\tconst builder = state.transaction(origin);\n\n\tconst insertIdx = index >= 0 ? index + 1 : siblings.length;\n\tbuilder.insertNode(parentPath, insertIdx, createEmptyParagraph(newId));\n\tbuilder.insertText(newId, 0, text, []);\n\tbuilder.setSelection(createCollapsedSelection(newId, text.length));\n\treturn builder.build();\n}\n\n/**\n * Navigates arrow keys into/out of void blocks.\n * Returns a transaction if navigation should create a NodeSelection, or null.\n *\n * @param isRtl — When true, flips left/right to account for RTL block direction.\n */\nexport function navigateArrowIntoVoid(\n\tstate: EditorState,\n\tdirection: 'left' | 'right' | 'up' | 'down',\n\tisRtl?: boolean,\n): Transaction | null {\n\tconst sel = state.selection;\n\tconst blockOrder = state.getBlockOrder();\n\tconst effectiveDir: 'left' | 'right' | 'up' | 'down' =\n\t\tisRtl && (direction === 'left' || direction === 'right')\n\t\t\t? direction === 'left'\n\t\t\t\t? 'right'\n\t\t\t\t: 'left'\n\t\t\t: direction;\n\n\t// If currently on a NodeSelection, navigate away from it\n\tif (isNodeSelection(sel)) {\n\t\treturn navigateAwayFromNodeSelection(state, sel, effectiveDir, blockOrder);\n\t}\n\n\t// GapCursor is handled by navigateFromGapCursor in CaretNavigation\n\tif (isGapCursor(sel)) return null;\n\n\t// Text selection: check if navigating into a void block\n\tif (!isCollapsed(sel)) return null;\n\n\treturn navigateIntoVoid(state, sel, effectiveDir, blockOrder);\n}\n\n/** Finds the first leaf (deepest-first-child) block ID in a subtree. */\nexport function findFirstLeafBlockId(node: BlockNode): BlockId {\n\tlet current: BlockNode = node;\n\twhile (true) {\n\t\tconst firstBlockChild = current.children.find((child): child is BlockNode =>\n\t\t\tisBlockNode(child),\n\t\t);\n\t\tif (!firstBlockChild) return current.id;\n\t\tcurrent = firstBlockChild;\n\t}\n}\n\n/** Finds the last leaf (deepest-last-child) block ID in a subtree. */\nexport function findLastLeafBlockId(node: BlockNode): BlockId {\n\tlet current: BlockNode = node;\n\twhile (true) {\n\t\tlet lastBlockChild: BlockNode | undefined;\n\t\tfor (let i = current.children.length - 1; i >= 0; i--) {\n\t\t\tconst child = current.children[i];\n\t\t\tif (child && isBlockNode(child)) {\n\t\t\t\tlastBlockChild = child;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!lastBlockChild) return current.id;\n\t\tcurrent = lastBlockChild;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Handles navigation away from a NodeSelection (arrow keys while void is selected). */\nfunction navigateAwayFromNodeSelection(\n\tstate: EditorState,\n\tsel: NodeSelection,\n\tdirection: 'left' | 'right' | 'up' | 'down',\n\tblockOrder: readonly BlockId[],\n): Transaction | null {\n\tconst nodeIdx = blockOrder.indexOf(sel.nodeId);\n\tconst nodePath = (findNodePath(state.doc, sel.nodeId) ?? []) as BlockId[];\n\n\tif (direction === 'left' || direction === 'up') {\n\t\tif (nodeIdx > 0) {\n\t\t\tconst prevId = blockOrder[nodeIdx - 1];\n\t\t\tif (!prevId) return null;\n\t\t\tif (isVoidBlock(state, prevId)) {\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.setSelection(createGapCursor(sel.nodeId, 'before', nodePath))\n\t\t\t\t\t.build();\n\t\t\t}\n\t\t\tconst prevBlock = state.getBlock(prevId);\n\t\t\tconst prevLen = prevBlock ? getBlockLength(prevBlock) : 0;\n\t\t\treturn state\n\t\t\t\t.transaction('input')\n\t\t\t\t.setSelection(createCollapsedSelection(prevId, prevLen))\n\t\t\t\t.build();\n\t\t}\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.setSelection(createGapCursor(sel.nodeId, 'before', nodePath))\n\t\t\t.build();\n\t}\n\n\t// right or down\n\tif (nodeIdx < blockOrder.length - 1) {\n\t\tconst nextId = blockOrder[nodeIdx + 1];\n\t\tif (!nextId) return null;\n\t\tif (isVoidBlock(state, nextId)) {\n\t\t\treturn state\n\t\t\t\t.transaction('input')\n\t\t\t\t.setSelection(createGapCursor(sel.nodeId, 'after', nodePath))\n\t\t\t\t.build();\n\t\t}\n\t\treturn state.transaction('input').setSelection(createCollapsedSelection(nextId, 0)).build();\n\t}\n\treturn state\n\t\t.transaction('input')\n\t\t.setSelection(createGapCursor(sel.nodeId, 'after', nodePath))\n\t\t.build();\n}\n\n/** Handles text selection navigating into an adjacent void block. */\nfunction navigateIntoVoid(\n\tstate: EditorState,\n\tsel: { readonly anchor: { readonly blockId: BlockId; readonly offset: number } },\n\tdirection: 'left' | 'right' | 'up' | 'down',\n\tblockOrder: readonly BlockId[],\n): Transaction | null {\n\tconst blockIdx = blockOrder.indexOf(sel.anchor.blockId);\n\tconst block = state.getBlock(sel.anchor.blockId);\n\tif (!block) return null;\n\tconst blockLen = getBlockLength(block);\n\n\tif (direction === 'right' || direction === 'down') {\n\t\tif (sel.anchor.offset === blockLen && blockIdx < blockOrder.length - 1) {\n\t\t\tconst nextId = blockOrder[blockIdx + 1];\n\t\t\tif (nextId && isVoidBlock(state, nextId)) {\n\t\t\t\tconst path = findNodePath(state.doc, nextId) ?? [];\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.setSelection(createNodeSelection(nextId, path as BlockId[]))\n\t\t\t\t\t.build();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (direction === 'left' || direction === 'up') {\n\t\tif (sel.anchor.offset === 0 && blockIdx > 0) {\n\t\t\tconst prevId = blockOrder[blockIdx - 1];\n\t\t\tif (prevId && isVoidBlock(state, prevId)) {\n\t\t\t\tconst path = findNodePath(state.doc, prevId) ?? [];\n\t\t\t\treturn state\n\t\t\t\t\t.transaction('input')\n\t\t\t\t\t.setSelection(createNodeSelection(prevId, path as BlockId[]))\n\t\t\t\t\t.build();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n","/**\n * Commands for GapCursor: deleting void blocks adjacent to gap cursors\n * and inserting paragraphs at gap positions.\n */\n\nimport { generateBlockId, getBlockLength } from '../model/Document.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport type { GapCursorSelection, NodeSelection } from '../model/Selection.js';\nimport { createCollapsedSelection, createNodeSelection } from '../model/Selection.js';\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport { isVoidBlock } from '../state/NavigationQueries.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport {\n\tcreateEmptyParagraph,\n\textractParentPath,\n\tfindSiblingIndex,\n\tgetSiblings,\n} from './CommandHelpers.js';\nimport { deleteNodeSelection } from './NodeSelectionCommands.js';\n\n/**\n * Deletes the void block adjacent to a GapCursor when pressing Backspace.\n *\n * - `side === 'after'` → void block is behind the cursor → delete it.\n * - `side === 'before'` → void block is ahead → navigate backward (to previous block).\n * - At document start with `side === 'before'` → `null` (no-op).\n */\nexport function deleteBackwardAtGap(\n\tstate: EditorState,\n\tsel: GapCursorSelection,\n): Transaction | null {\n\tif (sel.side === 'after') {\n\t\treturn deleteVoidAtGap(state, sel);\n\t}\n\n\t// side === 'before': navigate to previous block\n\tconst blockOrder: readonly BlockId[] = state.getBlockOrder();\n\tconst blockIdx: number = blockOrder.indexOf(sel.blockId);\n\n\tif (blockIdx <= 0) return null;\n\n\tconst prevId: BlockId | undefined = blockOrder[blockIdx - 1];\n\tif (!prevId) return null;\n\n\tif (isVoidBlock(state, prevId)) {\n\t\tconst path = findNodePath(state.doc, prevId) ?? [];\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.setSelection(createNodeSelection(prevId, path as BlockId[]))\n\t\t\t.build();\n\t}\n\n\tconst prevBlock = state.getBlock(prevId);\n\tif (!prevBlock) return null;\n\tconst prevLen: number = getBlockLength(prevBlock);\n\treturn state.transaction('input').setSelection(createCollapsedSelection(prevId, prevLen)).build();\n}\n\n/**\n * Deletes the void block adjacent to a GapCursor when pressing Delete.\n *\n * - `side === 'before'` → void block is ahead of the cursor → delete it.\n * - `side === 'after'` → void block is behind → navigate forward (to next block).\n * - At document end with `side === 'after'` → `null` (no-op).\n */\nexport function deleteForwardAtGap(\n\tstate: EditorState,\n\tsel: GapCursorSelection,\n): Transaction | null {\n\tif (sel.side === 'before') {\n\t\treturn deleteVoidAtGap(state, sel);\n\t}\n\n\t// side === 'after': navigate to next block\n\tconst blockOrder: readonly BlockId[] = state.getBlockOrder();\n\tconst blockIdx: number = blockOrder.indexOf(sel.blockId);\n\n\tif (blockIdx >= blockOrder.length - 1) return null;\n\n\tconst nextId: BlockId | undefined = blockOrder[blockIdx + 1];\n\tif (!nextId) return null;\n\n\tif (isVoidBlock(state, nextId)) {\n\t\tconst path = findNodePath(state.doc, nextId) ?? [];\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.setSelection(createNodeSelection(nextId, path as BlockId[]))\n\t\t\t.build();\n\t}\n\n\treturn state.transaction('input').setSelection(createCollapsedSelection(nextId, 0)).build();\n}\n\n/** Deletes the void block that the GapCursor is adjacent to, delegating to deleteNodeSelection. */\nfunction deleteVoidAtGap(state: EditorState, sel: GapCursorSelection): Transaction | null {\n\tconst path = (findNodePath(state.doc, sel.blockId) ?? []) as BlockId[];\n\tconst nodeSel: NodeSelection = createNodeSelection(sel.blockId, path);\n\treturn deleteNodeSelection(state, nodeSel);\n}\n\n/** Inserts a new paragraph at a GapCursor position (before or after the void block). */\nexport function insertParagraphAtGap(\n\tstate: EditorState,\n\tsel: GapCursorSelection,\n): Transaction | null {\n\tconst path = findNodePath(state.doc, sel.blockId);\n\tif (!path) return null;\n\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\tconst siblings = getSiblings(state, parentPath);\n\n\tconst index: number = findSiblingIndex(siblings, sel.blockId);\n\tif (index < 0) return null;\n\n\tconst insertIdx: number = sel.side === 'before' ? index : index + 1;\n\tconst newId = generateBlockId();\n\tconst builder = state.transaction('input');\n\tbuilder.insertNode(parentPath, insertIdx, createEmptyParagraph(newId));\n\tbuilder.setSelection(createCollapsedSelection(newId, 0));\n\treturn builder.build();\n}\n\n/** Inserts text in a new paragraph at a GapCursor position. */\nexport function insertTextAtGap(\n\tstate: EditorState,\n\tsel: GapCursorSelection,\n\ttext: string,\n\torigin: 'input' | 'paste',\n): Transaction {\n\tconst path = findNodePath(state.doc, sel.blockId);\n\tconst parentPath: BlockId[] = extractParentPath(path);\n\tconst siblings = getSiblings(state, parentPath);\n\n\tconst index: number = findSiblingIndex(siblings, sel.blockId);\n\tconst insertIdx: number =\n\t\tsel.side === 'before' ? Math.max(index, 0) : index >= 0 ? index + 1 : siblings.length;\n\n\tconst newId = generateBlockId();\n\tconst builder = state.transaction(origin);\n\tbuilder.insertNode(parentPath, insertIdx, createEmptyParagraph(newId));\n\tbuilder.insertText(newId, 0, text, []);\n\tbuilder.setSelection(createCollapsedSelection(newId, text.length));\n\treturn builder.build();\n}\n","/**\n * Core editor commands and barrel re-exports from submodules.\n *\n * This module contains text insertion, block splitting, block merging,\n * selection deletion, and select-all. Mark, delete, gap-cursor, node-selection,\n * and word-boundary commands are re-exported from their respective modules.\n */\n\nimport {\n\ttype Mark,\n\tcreateInlineNode,\n\tgenerateBlockId,\n\tgetBlockLength,\n\tgetBlockMarksAtOffset,\n\tisLeafBlock,\n} from '../model/Document.js';\nimport { findNodePath } from '../model/NodeResolver.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tcreateSelection,\n\tisCollapsed,\n\tisGapCursor,\n\tisNodeSelection,\n\tisTextSelection,\n\tselectionRange,\n} from '../model/Selection.js';\nimport { type BlockId, inlineType } from '../model/TypeBrands.js';\nimport type { EditorState } from '../state/EditorState.js';\nimport {\n\tisInsideIsolating,\n\tisIsolatingBlock,\n\tisVoidBlock,\n\tsharesParent,\n} from '../state/NavigationQueries.js';\nimport type { Transaction } from '../state/Transaction.js';\nimport type { TransactionBuilder } from '../state/Transaction.js';\nimport { createEmptyParagraph, resolveInsertPoint } from './CommandHelpers.js';\nimport { insertParagraphAtGap, insertTextAtGap } from './GapCursorCommands.js';\nimport {\n\tdeleteNodeSelection,\n\tfindFirstLeafBlockId,\n\tfindLastLeafBlockId,\n\tinsertParagraphAfterNodeSelection,\n\tinsertTextAfterNodeSelection,\n} from './NodeSelectionCommands.js';\n\n// --- Re-exports from submodules ---\n\nexport {\n\tcanCrossBlockBoundary,\n\tisInsideIsolating,\n\tisIsolatingBlock,\n\tisVoidBlock,\n\tsharesParent,\n} from '../state/NavigationQueries.js';\n\nexport type { FeatureConfig } from './MarkCommands.js';\nexport {\n\tisMarkActive,\n\ttoggleBold,\n\ttoggleItalic,\n\ttoggleMark,\n\ttoggleUnderline,\n} from './MarkCommands.js';\n\nexport {\n\tdeleteBackward,\n\tdeleteForward,\n\tdeleteSoftLineBackward,\n\tdeleteSoftLineForward,\n\tdeleteWordBackward,\n\tdeleteWordForward,\n} from './DeleteCommands.js';\n\nexport {\n\tdeleteNodeSelection,\n\tfindFirstLeafBlockId,\n\tfindLastLeafBlockId,\n\tinsertParagraphAfterNodeSelection,\n\tinsertTextAfterNodeSelection,\n\tnavigateArrowIntoVoid,\n} from './NodeSelectionCommands.js';\n\nexport {\n\tdeleteBackwardAtGap,\n\tdeleteForwardAtGap,\n\tinsertParagraphAtGap,\n\tinsertTextAtGap,\n} from './GapCursorCommands.js';\n\nexport {\n\tfindWordBoundaryBackward,\n\tfindWordBoundaryForward,\n} from './WordBoundary.js';\n\nexport {\n\tapplyAttributedMark,\n\tgetMarkAttrAtSelection,\n\tisAttributedMarkActive,\n\tremoveAttributedMark,\n} from './AttributedMarkCommands.js';\n\nexport { forEachBlockInRange } from './RangeIterator.js';\n\n// --- Text Commands ---\n\n/** Inserts text at the current selection, replacing any selected range. */\nexport function insertTextCommand(\n\tstate: EditorState,\n\ttext: string,\n\torigin: 'input' | 'paste' = 'input',\n): Transaction {\n\tconst sel = state.selection;\n\n\t// NodeSelection: insert paragraph after void block with the text\n\tif (isNodeSelection(sel)) {\n\t\treturn insertTextAfterNodeSelection(state, sel, text, origin);\n\t}\n\n\t// GapCursor: insert paragraph at the gap position with the text\n\tif (isGapCursor(sel)) {\n\t\treturn insertTextAtGap(state, sel, text, origin);\n\t}\n\n\tconst builder = state.transaction(origin);\n\tconst marks = resolveActiveMarks(state);\n\n\tlet landingId: BlockId | undefined;\n\tif (!isCollapsed(sel)) {\n\t\tlandingId = addDeleteSelectionSteps(state, builder);\n\t}\n\n\tconst resolved = resolveInsertPoint(sel, state.getBlockOrder());\n\tconst insertBlockId: BlockId = landingId ?? resolved.blockId;\n\tconst insertOffset: number = landingId ? 0 : resolved.offset;\n\n\tbuilder.insertText(insertBlockId, insertOffset, text, marks);\n\tbuilder.setSelection(createCollapsedSelection(insertBlockId, insertOffset + text.length));\n\n\treturn builder.build();\n}\n\n/** Deletes the current selection. */\nexport function deleteSelectionCommand(state: EditorState): Transaction | null {\n\tif (isNodeSelection(state.selection)) {\n\t\treturn deleteNodeSelection(state, state.selection);\n\t}\n\tif (isGapCursor(state.selection)) return null;\n\tif (isCollapsed(state.selection)) return null;\n\n\tconst builder = state.transaction('input');\n\tconst landingId: BlockId | undefined = addDeleteSelectionSteps(state, builder);\n\n\tconst range = selectionRange(state.selection, state.getBlockOrder());\n\tconst cursorBlockId: BlockId = landingId ?? range.from.blockId;\n\tconst cursorOffset: number = landingId ? 0 : range.from.offset;\n\tbuilder.setSelection(createCollapsedSelection(cursorBlockId, cursorOffset));\n\n\treturn builder.build();\n}\n\n/** Splits the current block at the cursor position (Enter key). */\nexport function splitBlockCommand(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\t// NodeSelection: insert empty paragraph after the void block\n\tif (isNodeSelection(sel)) {\n\t\treturn insertParagraphAfterNodeSelection(state, sel);\n\t}\n\n\t// GapCursor: insert empty paragraph at the gap position\n\tif (isGapCursor(sel)) {\n\t\treturn insertParagraphAtGap(state, sel);\n\t}\n\n\tconst builder = state.transaction('input');\n\n\tlet landingId: BlockId | undefined;\n\tif (!isCollapsed(sel)) {\n\t\tlandingId = addDeleteSelectionSteps(state, builder);\n\t}\n\n\tconst resolved = resolveInsertPoint(sel, state.getBlockOrder());\n\tconst blockId: BlockId = landingId ?? resolved.blockId;\n\tconst offset: number = landingId ? 0 : resolved.offset;\n\tconst newBlockId = generateBlockId();\n\n\t// splitBlock operates at the same level in the tree — the StepApplication\n\t// handles this correctly because it looks up the block by ID recursively.\n\tbuilder.splitBlock(blockId, offset, newBlockId);\n\tbuilder.setSelection(createCollapsedSelection(newBlockId, 0));\n\n\treturn builder.build();\n}\n\n/** Inserts a hard line break (InlineNode) at the current cursor position. */\nexport function insertHardBreakCommand(state: EditorState): Transaction | null {\n\tconst sel = state.selection;\n\n\tif (!isTextSelection(sel)) return null;\n\n\tconst builder = state.transaction('input');\n\n\tlet cursorBlockId: BlockId | undefined;\n\tif (!isCollapsed(sel)) {\n\t\tconst landingId: BlockId | undefined = addDeleteSelectionSteps(state, builder);\n\t\tcursorBlockId = landingId;\n\t}\n\n\tif (cursorBlockId) {\n\t\t// Cross-root deletion replaced from-block; insert hard break in landing block\n\t\tbuilder.insertInlineNode(cursorBlockId, 0, createInlineNode(inlineType('hard_break')));\n\t\tbuilder.setSelection(createCollapsedSelection(cursorBlockId, 1));\n\t} else {\n\t\tconst { blockId: insertBlockId, offset: insertOffset } = resolveInsertPoint(\n\t\t\tsel,\n\t\t\tstate.getBlockOrder(),\n\t\t);\n\t\tbuilder.insertInlineNode(\n\t\t\tinsertBlockId,\n\t\t\tinsertOffset,\n\t\t\tcreateInlineNode(inlineType('hard_break')),\n\t\t);\n\t\tbuilder.setSelection(createCollapsedSelection(insertBlockId, insertOffset + 1));\n\t}\n\n\treturn builder.build();\n}\n\n/**\n * Merges the current block with the previous block, respecting\n * isolating boundaries and void blocks.\n */\nexport function mergeBlockBackward(state: EditorState): Transaction | null {\n\treturn mergeAdjacentBlock(state, 'backward');\n}\n\n/**\n * Merges the next block into the current block, respecting\n * isolating boundaries and void blocks.\n */\nexport function mergeBlockForward(state: EditorState): Transaction | null {\n\treturn mergeAdjacentBlock(state, 'forward');\n}\n\n/**\n * Shared implementation for merging adjacent blocks in either direction.\n * Validates selection, isolating boundaries, and void blocks before merging.\n */\nfunction mergeAdjacentBlock(\n\tstate: EditorState,\n\tdirection: 'backward' | 'forward',\n): Transaction | null {\n\tconst sel = state.selection;\n\tif (!isTextSelection(sel)) return null;\n\n\tconst blockOrder = state.getBlockOrder();\n\tconst blockIdx: number = blockOrder.indexOf(sel.anchor.blockId);\n\n\tconst adjacentIdx: number = direction === 'backward' ? blockIdx - 1 : blockIdx + 1;\n\tif (adjacentIdx < 0 || adjacentIdx >= blockOrder.length) return null;\n\n\tconst adjacentId: BlockId | undefined = blockOrder[adjacentIdx];\n\tif (!adjacentId) return null;\n\n\tif (isIsolatingBlock(state, sel.anchor.blockId) || isIsolatingBlock(state, adjacentId)) {\n\t\treturn null;\n\t}\n\tif (!sharesParent(state, sel.anchor.blockId, adjacentId)) {\n\t\tif (isInsideIsolating(state, sel.anchor.blockId)) return null;\n\t}\n\n\tif (isVoidBlock(state, adjacentId)) {\n\t\tconst path = findNodePath(state.doc, adjacentId) ?? [];\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.setSelection(createNodeSelection(adjacentId, path as BlockId[]))\n\t\t\t.build();\n\t}\n\n\tif (direction === 'backward') {\n\t\tconst prevBlock = state.getBlock(adjacentId);\n\t\tif (!prevBlock) return null;\n\t\tconst prevLen: number = getBlockLength(prevBlock);\n\t\treturn state\n\t\t\t.transaction('input')\n\t\t\t.mergeBlocksAt(adjacentId, sel.anchor.blockId)\n\t\t\t.setSelection(createCollapsedSelection(adjacentId, prevLen))\n\t\t\t.build();\n\t}\n\n\treturn state\n\t\t.transaction('input')\n\t\t.mergeBlocksAt(sel.anchor.blockId, adjacentId)\n\t\t.setSelection(createCollapsedSelection(sel.anchor.blockId, sel.anchor.offset))\n\t\t.build();\n}\n\n/** Selects all content in the editor, using leaf block endpoints. */\nexport function selectAll(state: EditorState): Transaction {\n\tconst blocks = state.doc.children;\n\tconst firstBlock = blocks[0];\n\tconst lastBlock = blocks[blocks.length - 1];\n\tif (!firstBlock || !lastBlock)\n\t\treturn state.transaction('command').setSelection(state.selection).build();\n\n\tconst firstLeafId: BlockId = findFirstLeafBlockId(firstBlock);\n\tconst lastLeafId: BlockId = findLastLeafBlockId(lastBlock);\n\tconst lastLeaf = state.getBlock(lastLeafId);\n\tconst lastLeafLen: number = lastLeaf ? getBlockLength(lastLeaf) : 0;\n\n\treturn state\n\t\t.transaction('command')\n\t\t.setSelection(\n\t\t\tcreateSelection(\n\t\t\t\t{ blockId: firstLeafId, offset: 0 },\n\t\t\t\t{ blockId: lastLeafId, offset: lastLeafLen },\n\t\t\t),\n\t\t)\n\t\t.build();\n}\n\n// --- Internal Helpers ---\n\nfunction resolveActiveMarks(state: EditorState): readonly Mark[] {\n\tif (state.storedMarks) return state.storedMarks;\n\tif (!isTextSelection(state.selection)) return [];\n\n\tconst block = state.getBlock(state.selection.anchor.blockId);\n\tif (!block) return [];\n\n\treturn getBlockMarksAtOffset(block, state.selection.anchor.offset);\n}\n\n/**\n * Adds steps to delete the current text selection.\n * Returns a replacement cursor block ID when the original from-block\n * was inside a composite root that got removed (undefined otherwise).\n */\nexport function addDeleteSelectionSteps(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n): BlockId | undefined {\n\tif (!isTextSelection(state.selection)) return undefined;\n\tconst blockOrder = state.getBlockOrder();\n\tconst range = selectionRange(state.selection, blockOrder);\n\tconst fromIdx = blockOrder.indexOf(range.from.blockId);\n\tconst toIdx = blockOrder.indexOf(range.to.blockId);\n\n\tif (fromIdx === toIdx) {\n\t\tbuilder.deleteTextAt(range.from.blockId, range.from.offset, range.to.offset);\n\t\treturn undefined;\n\t}\n\n\tconst fromRootIdx: number = getRootBlockIndex(state, range.from.blockId);\n\tconst toRootIdx: number = getRootBlockIndex(state, range.to.blockId);\n\n\tif (fromRootIdx === toRootIdx || fromRootIdx < 0 || toRootIdx < 0) {\n\t\tdeleteLeafRange(state, builder, blockOrder, range, fromIdx, toIdx);\n\t\treturn undefined;\n\t}\n\n\treturn deleteCrossRootRange(state, builder, range, fromRootIdx, toRootIdx);\n}\n\n/** Returns the root-level ancestor index in doc.children for a given block. */\nfunction getRootBlockIndex(state: EditorState, blockId: BlockId): number {\n\tconst path = findNodePath(state.doc, blockId);\n\tif (!path || path.length === 0) return -1;\n\tconst rootId: string = path[0] as string;\n\treturn state.doc.children.findIndex((c) => c.id === rootId);\n}\n\n/** Deletes a multi-block selection where all blocks share the same root ancestor. */\nfunction deleteLeafRange(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\tblockOrder: readonly BlockId[],\n\trange: {\n\t\treadonly from: { readonly blockId: BlockId; readonly offset: number };\n\t\treadonly to: { readonly blockId: BlockId; readonly offset: number };\n\t},\n\tfromIdx: number,\n\ttoIdx: number,\n): void {\n\tconst firstBlock = state.getBlock(range.from.blockId);\n\tif (!firstBlock) return;\n\tconst firstLen = getBlockLength(firstBlock);\n\n\tif (range.from.offset < firstLen) {\n\t\tbuilder.deleteTextAt(range.from.blockId, range.from.offset, firstLen);\n\t}\n\n\tif (range.to.offset > 0) {\n\t\tbuilder.deleteTextAt(range.to.blockId, 0, range.to.offset);\n\t}\n\n\tfor (let i = fromIdx + 1; i < toIdx; i++) {\n\t\tconst midBlockId = blockOrder[i];\n\t\tif (!midBlockId) continue;\n\t\tconst midBlock = state.getBlock(midBlockId);\n\t\tif (!midBlock) continue;\n\t\tconst midLen = getBlockLength(midBlock);\n\t\tif (midLen > 0) {\n\t\t\tbuilder.deleteTextAt(midBlockId, 0, midLen);\n\t\t}\n\t\tbuilder.mergeBlocksAt(range.from.blockId, midBlockId);\n\t}\n\n\tbuilder.mergeBlocksAt(range.from.blockId, range.to.blockId);\n}\n\n/**\n * Deletes a selection spanning different root-level ancestors.\n * Removes intermediate and composite root blocks, merges leaf roots.\n * Returns a replacement cursor block ID if from was inside a removed composite.\n */\nfunction deleteCrossRootRange(\n\tstate: EditorState,\n\tbuilder: TransactionBuilder,\n\trange: {\n\t\treadonly from: { readonly blockId: BlockId; readonly offset: number };\n\t\treadonly to: { readonly blockId: BlockId; readonly offset: number };\n\t},\n\tfromRootIdx: number,\n\ttoRootIdx: number,\n): BlockId | undefined {\n\tconst fromRoot = state.doc.children[fromRootIdx];\n\tconst toRoot = state.doc.children[toRootIdx];\n\tif (!fromRoot || !toRoot) return undefined;\n\n\tconst fromIsLeaf: boolean = isLeafBlock(fromRoot);\n\tconst toIsLeaf: boolean = isLeafBlock(toRoot);\n\n\t// When from is inside a composite root, insert a landing paragraph\n\t// so callers can reference a surviving block for cursor/insert.\n\tlet landingId: BlockId | undefined;\n\tlet indexShift = 0;\n\n\tif (!fromIsLeaf) {\n\t\tlandingId = generateBlockId();\n\t\tbuilder.insertNode([], fromRootIdx, createEmptyParagraph(landingId));\n\t\tindexShift = 1;\n\t}\n\n\t// Delete text in from-leaf (only for leaf roots; composite roots are removed entirely)\n\tif (fromIsLeaf) {\n\t\tconst fromBlock = state.getBlock(range.from.blockId);\n\t\tif (fromBlock) {\n\t\t\tconst fromLen: number = getBlockLength(fromBlock);\n\t\t\tif (range.from.offset < fromLen) {\n\t\t\t\tbuilder.deleteTextAt(range.from.blockId, range.from.offset, fromLen);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Delete text in to-leaf (only for leaf roots)\n\tif (toIsLeaf && range.to.offset > 0) {\n\t\tbuilder.deleteTextAt(range.to.blockId, 0, range.to.offset);\n\t}\n\n\t// Remove root-level blocks in descending index order.\n\t// Keep from-root if it's a leaf; remove if composite (shifted by indexShift).\n\t// Keep to-root if it's a leaf (will merge into from); remove if composite.\n\tconst removeEnd: number = toIsLeaf ? toRootIdx - 1 + indexShift : toRootIdx + indexShift;\n\tconst removeStart: number = fromIsLeaf ? fromRootIdx + 1 : fromRootIdx + indexShift;\n\n\tfor (let i = removeEnd; i >= removeStart; i--) {\n\t\tbuilder.removeNode([], i);\n\t}\n\n\t// Merge to-root into from if both are leaf roots\n\tif (fromIsLeaf && toIsLeaf) {\n\t\tbuilder.mergeBlocksAt(range.from.blockId, range.to.blockId);\n\t}\n\n\treturn landingId;\n}\n"],"names":["getSiblings","state","parentPath","length","doc","children","parent","getBlock","createEmptyParagraph","id","createBlockNode","nodeType","createTextNode","resolveInsertPoint","sel","blockOrder","isCollapsed","blockId","anchor","offset","range","selectionRange","from","extractParentPath","path","slice","findSiblingIndex","siblings","targetId","findIndex","c","isBlockNode","deleteNodeSelection","findNodePath","nodeId","index","builder","transaction","newId","generateBlockId","insertNode","removeNode","setSelection","createCollapsedSelection","build","prevSibling","prevLeafId","findLastLeafBlockId","prevLeaf","prevLen","getBlockLength","nextSibling","nextLeafId","findFirstLeafBlockId","navigateArrowIntoVoid","direction","isRtl","selection","getBlockOrder","effectiveDir","isNodeSelection","nodeIdx","indexOf","nodePath","prevId","isVoidBlock","createGapCursor","prevBlock","nextId","navigateAwayFromNodeSelection","isGapCursor","blockIdx","block","blockLen","createNodeSelection","navigateIntoVoid","node","current","firstBlockChild","find","child","lastBlockChild","i","deleteBackwardAtGap","side","deleteVoidAtGap","deleteForwardAtGap","insertTextCommand","text","origin","insertIdx","insertText","insertTextAfterNodeSelection","Math","max","insertTextAtGap","marks","storedMarks","isTextSelection","getBlockMarksAtOffset","resolveActiveMarks","landingId","addDeleteSelectionSteps","resolved","insertBlockId","insertOffset","deleteSelectionCommand","cursorBlockId","cursorOffset","splitBlockCommand","insertParagraphAfterNodeSelection","insertParagraphAtGap","newBlockId","splitBlock","insertHardBreakCommand","insertInlineNode","createInlineNode","inlineType","mergeBlockBackward","mergeAdjacentBlock","mergeBlockForward","adjacentIdx","adjacentId","isIsolatingBlock","sharesParent","isInsideIsolating","mergeBlocksAt","selectAll","blocks","firstBlock","lastBlock","firstLeafId","lastLeafId","lastLeaf","lastLeafLen","createSelection","fromIdx","toIdx","to","deleteTextAt","fromRootIdx","getRootBlockIndex","toRootIdx","fromRoot","toRoot","fromIsLeaf","isLeafBlock","toIsLeaf","indexShift","fromBlock","fromLen","removeStart","deleteCrossRootRange","firstLen","midBlockId","midBlock","midLen","deleteLeafRange","rootId"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function t(t,n,r){const o=[];return function(t,n,r,o){const i=s(t);let f=0;for(const s of i){const t=f+(e(s)?1:s.text.length);if(t<=n||f>=r)f=t;else{if(e(s))o.onInline?.(s);else{const t=Math.max(0,n-f),e=Math.min(s.text.length,r-f),i=s.text.slice(t,e);i.length>0&&o.onText(i,s.marks)}f=t}}}(t,n,r,{onText(t,n){o.push({text:t,marks:n})}}),o}function n(t){return"object"==typeof t&&null!==t&&"text"===t.type&&"string"==typeof t.text}function e(t){return"object"==typeof t&&null!==t&&"inline"===t.type&&"string"==typeof t.inlineType}function r(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 o(t){return t.children.every(t=>n(t)||e(t))}function i(t){return t.children.filter(t=>n(t))}function s(t){return t.children.filter(t=>n(t)||e(t))}function f(t){return t.children.filter(t=>r(t))}function u(){return`block-${crypto.randomUUID()}`}function c(t){return{children:t??[l("paragraph")]}}function l(t,n,e,r){return{id:e??u(),type:t,...r?{attrs:r}:{},children:n??[a("")]}}function a(t,n){return{type:"text",text:t,marks:n??[]}}function h(t,n){return{type:"inline",inlineType:t,attrs:n??{}}}function g(t){const e=s(t);let r="";for(const o of e)n(o)&&(r+=o.text);return r}function y(t){const n=s(t);let r=0;for(const o of n)r+=e(o)?1:o.text.length;return r}function p(t,r){const o=s(t);let i=0;for(const n of o){if(e(n)){if(r===i)return[];i+=1;continue}const t=i+n.text.length;if(r>=i&&r<t)return n.marks;if(r===i&&0===n.text.length)return n.marks;i=t}for(let e=o.length-1;e>=0;e--){const t=o[e];if(t&&n(t))return t.marks}return[]}function x(t,n){return t.length===n.length&&t.every(t=>n.some(n=>function(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])}(t,n)))}function m(t,n){return t.some(t=>t.type===n)}function k(t,n){return m(t,n.type)?t:[...t,n]}function d(t,n){return t.filter(t=>t.type!==n)}function b(t){if(0===t.length)return[a("")];if(t.every(t=>n(t)))return function(t){if(0===t.length)return[a("")];const n=[];for(const e of t){const t=n[n.length-1];t&&x(t.marks,e.marks)?n[n.length-1]=a(t.text+e.text,t.marks):(e.text.length>0||0===n.length)&&n.push(e)}return 0===n.length?[a("")]:n}(t);const r=[];for(const i of t){if(e(i)){r.push(i);continue}const t=r[r.length-1];t&&n(t)&&x(t.marks,i.marks)?r[r.length-1]=a(t.text+i.text,t.marks):(i.text.length>0||0===r.length)&&r.push(i)}const o=r.filter((t,n)=>{if(e(t))return!0;if(t.text.length>0)return!0;if(1===r.length)return!0;const o=r[n-1],i=r[n+1];return!(o&&e(o)||i&&e(i))});return 0===o.length?[a("")]:o.some(t=>n(t))?o:[a(""),...o]}function j(t,n){const r=s(t);let o=0,i=0;for(const s of r)if(e(s)){if(o>=n)return i;o+=1}else{if(o+s.text.length>=n)return i+(n-o);o+=s.text.length,i+=s.text.length}return i}function v(t,n){const r=s(t);for(const{child:o,from:i}of function*(t){let n=0;for(const r of t){const t=e(r)?1:r.text.length;yield{child:r,from:n,to:n+t},n+=t}}(r)){if(e(o)){if(n===i)return{kind:"inline",node:o};continue}const t=n-i;if(t>=0&&t<o.text.length)return{kind:"text",char:o.text[t]??"",marks:o.marks}}return null}export{c as a,j as b,l as c,h as d,a as e,y as f,f as g,p as h,g as i,v as j,s as k,i as l,m,r as n,e as o,o as p,n as q,x as r,u as s,k as t,d as u,b as v,t as w};
|
|
2
|
-
//# sourceMappingURL=Document-HC8s50qJ.mjs.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{m as e,h as t,f as n,k as r,q as o}from"./Document-HC8s50qJ.mjs";import{j as s,i,s as c}from"./Selection-DhbizDM4.mjs";import{m as a}from"./TypeBrands-Bp_Z_o5Y.mjs";import{f as u}from"./RangeIterator-CprUbOWv.mjs";function f(){return{nodeTypes:["paragraph"],markTypes:["bold","italic","underline"],getNodeSpec:()=>{}}}function l(e){return{nodeTypes:e.getNodeTypes(),markTypes:e.getMarkTypes(),getNodeSpec:t=>e.getNodeSpec(t)}}function d(e,t){return e.markTypes.includes(t)}function m(e,t){return e.nodeTypes.includes(t)}const k={bold:!0,italic:!0,underline:!0};function p(n,r,o=k){if(function(e,t){const n=e;return"bold"===n?!t.bold:"italic"===n?!t.italic:"underline"===n&&!t.underline}(r,o))return null;if(!d(n.schema,r))return null;if(!s(n.selection))return null;const a={type:r},f=n.selection;if(i(f)){const o=n.getBlock(f.anchor.blockId);if(!o)return null;const s=n.storedMarks??t(o,f.anchor.offset),i=e(s,r)?s.filter(e=>e.type!==r):[...s,a];return n.transaction("command").setStoredMarks(i,n.storedMarks).setSelection(f).build()}const l=c(f,n.getBlockOrder()),m=n.transaction("command"),p=h(n,r);return u(n,l,(e,t,n)=>{p?m.removeMark(e,t,n,a):m.addMark(e,t,n,a)}),m.setSelection(f),m.build()}function g(e,t){return p(e,a("bold"),t)}function b(e,t){return p(e,a("italic"),t)}function y(e,t){return p(e,a("underline"),t)}function T(n,r){const o=n.selection;if(!s(o))return!1;if(i(o)){if(n.storedMarks)return e(n.storedMarks,r);const s=n.getBlock(o.anchor.blockId);if(!s)return!1;const i=t(s,o.anchor.offset);return e(i,r)}return h(n,r)}function h(e,t){const r=e.selection;if(!s(r))return!1;const o=e.getBlockOrder(),i=c(r,o),a=o.indexOf(i.from.blockId),u=o.indexOf(i.to.blockId);for(let s=a;s<=u;s++){const r=o[s];if(!r)continue;const c=e.getBlock(r);if(!c)continue;const f=n(c);if(!M(c,s===a?i.from.offset:0,s===u?i.to.offset:f,t))return!1}return!0}function M(t,n,s,i){if(n===s)return!1;let c=0;for(const a of r(t))if(o(a)){const t=c+a.text.length;if(t>n&&c<s&&!e(a.marks,i))return!1;c=t}else c+=1;return!0}export{d as a,b,p as c,f as d,y as e,m as f,T as i,l as s,g as t};
|
|
2
|
-
//# sourceMappingURL=MarkCommands-CTuVDqnn.mjs.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n}from"./Document-HC8s50qJ.mjs";function t(t,e){if(0===e.length)return;let r=t.children.find(n=>n.id===e[0]);if(r){for(let t=1;t<e.length;t++){const i=e[t];if(!i)return;const o=r?.children.find(t=>n(t)&&t.id===i);if(!o)return;r=o}return r}}function e(e,r){if(0===r.length)return;if(1===r.length){const n=e.children.findIndex(n=>n.id===r[0]);if(-1===n)return;return{parent:e,index:n}}const i=t(e,r.slice(0,-1));if(!i)return;const o=r[r.length-1];if(!o)return;const c=i.children.findIndex(t=>n(t)&&t.id===o);return-1!==c?{parent:i,index:c}:void 0}function r(n,t){for(const e of n.children){if(e.id===t)return[t];const n=i(e,t);if(n)return[e.id,...n]}}function i(t,e){for(const r of t.children){if(!n(r))continue;if(r.id===e)return[e];const t=i(r,e);if(t)return[r.id,...t]}}function o(n,t){for(const e of n.children)c(e,[e.id],t)}function c(t,e,r){r(t,e);for(const i of t.children)n(i)&&c(i,[...e,i.id],r)}function f(n,t){for(const e of n.children){if(e.id===t)return e;const n=u(e,t);if(n)return n}}function u(t,e){for(const r of t.children){if(!n(r))continue;if(r.id===e)return r;const t=u(r,e);if(t)return t}}function s(n,e){const i=r(n,e);if(!i)return;const o=t(n,i);return o?{node:o,path:i}:void 0}function d(n,t){const e=n.getBlock(t);if(!e)return!1;const r=n.schema.getNodeSpec;return!!r&&!0===r(e.type)?.isVoid}function l(n,t,e){const r=n.getNodePath(t),i=n.getNodePath(e);if(!r||!i)return!1;if(r.length!==i.length)return!1;for(let o=0;o<r.length-1;o++)if(r[o]!==i[o])return!1;return!0}function h(n,t){const e=n.schema.getNodeSpec;if(!e)return!1;const r=n.getNodePath(t);if(!r||r.length<=1)return!1;for(let i=0;i<r.length-1;i++){const t=r[i];if(!t)continue;const o=n.getBlock(t);if(!o)continue;const c=e(o.type);if(c?.isolating)return!0}return!1}function a(n,t){const e=n.schema.getNodeSpec;if(!e)return!1;const r=n.getBlock(t);return!!r&&!0===e(r.type)?.isolating}function g(n,t,e){if(a(n,t)||a(n,e))return!1;const r=h(n,t),i=h(n,e);return r===i&&(!r||!i||l(n,t,e))}export{r as a,s as b,g as c,a as d,d as e,f,e as g,h as i,t as r,l as s,o as w};
|
|
2
|
-
//# sourceMappingURL=NavigationQueries-DCOv4Ca5.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationQueries-DCOv4Ca5.mjs","sources":["../../src/model/NodeResolver.ts","../../src/state/NavigationQueries.ts"],"sourcesContent":["/**\n * Utilities for resolving nodes by path within the document tree.\n * Supports both flat and recursive (nested) document structures.\n */\n\nimport type { BlockNode, Document } from './Document.js';\nimport { isBlockNode } from './Document.js';\n\n/**\n * Resolves a node in the document tree by its path (array of block IDs).\n * The path traces the lineage from the root block down to the target.\n */\nexport function resolveNodeByPath(doc: Document, path: readonly string[]): BlockNode | undefined {\n\tif (path.length === 0) return undefined;\n\n\tlet current: BlockNode | undefined = doc.children.find((b) => b.id === path[0]);\n\tif (!current) return undefined;\n\n\tfor (let i = 1; i < path.length; i++) {\n\t\tconst childId = path[i];\n\t\tif (!childId) return undefined;\n\t\tconst next: BlockNode | undefined = current?.children.find(\n\t\t\t(c): c is BlockNode => isBlockNode(c) && c.id === childId,\n\t\t);\n\t\tif (!next) return undefined;\n\t\tcurrent = next;\n\t}\n\n\treturn current;\n}\n\n/**\n * Resolves the parent of a node at the given path.\n * Returns the parent container (Document or BlockNode) and the child's index within it.\n */\nexport function resolveParentByPath(\n\tdoc: Document,\n\tpath: readonly string[],\n): { parent: Document | BlockNode; index: number } | undefined {\n\tif (path.length === 0) return undefined;\n\n\tif (path.length === 1) {\n\t\tconst index = doc.children.findIndex((b) => b.id === path[0]);\n\t\tif (index === -1) return undefined;\n\t\treturn { parent: doc, index };\n\t}\n\n\tconst parentPath = path.slice(0, -1);\n\tconst parent = resolveNodeByPath(doc, parentPath);\n\tif (!parent) return undefined;\n\n\tconst childId = path[path.length - 1];\n\tif (!childId) return undefined;\n\tconst index = parent.children.findIndex(\n\t\t(c): c is BlockNode => isBlockNode(c) && c.id === childId,\n\t);\n\tif (index === -1) return undefined;\n\n\treturn { parent, index };\n}\n\n/**\n * Finds the path (array of block IDs) to a node by its ID.\n * Performs recursive DFS through the document tree.\n */\nexport function findNodePath(doc: Document, nodeId: string): string[] | undefined {\n\tfor (const block of doc.children) {\n\t\tif (block.id === nodeId) return [nodeId];\n\n\t\tconst subPath = findNodePathInBlock(block, nodeId);\n\t\tif (subPath) return [block.id, ...subPath];\n\t}\n\treturn undefined;\n}\n\nfunction findNodePathInBlock(block: BlockNode, nodeId: string): string[] | undefined {\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tif (child.id === nodeId) return [nodeId];\n\n\t\tconst subPath = findNodePathInBlock(child, nodeId);\n\t\tif (subPath) return [child.id, ...subPath];\n\t}\n\treturn undefined;\n}\n\n/**\n * Walks all block nodes in the document tree in depth-first order.\n * Visits every BlockNode, including nested ones, with their full path.\n */\nexport function walkNodes(\n\tdoc: Document,\n\tcallback: (node: BlockNode, path: string[]) => void,\n): void {\n\tfor (const block of doc.children) {\n\t\twalkNodeRecursive(block, [block.id], callback);\n\t}\n}\n\nfunction walkNodeRecursive(\n\tnode: BlockNode,\n\tpath: string[],\n\tcallback: (node: BlockNode, path: string[]) => void,\n): void {\n\tcallback(node, path);\n\tfor (const child of node.children) {\n\t\tif (isBlockNode(child)) {\n\t\t\twalkNodeRecursive(child, [...path, child.id], callback);\n\t\t}\n\t}\n}\n\n/**\n * Finds a block node by ID anywhere in the document tree (recursive DFS).\n */\nexport function findNode(doc: Document, nodeId: string): BlockNode | undefined {\n\tfor (const block of doc.children) {\n\t\tif (block.id === nodeId) return block;\n\t\tconst found = findNodeInBlock(block, nodeId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\nfunction findNodeInBlock(block: BlockNode, nodeId: string): BlockNode | undefined {\n\tfor (const child of block.children) {\n\t\tif (!isBlockNode(child)) continue;\n\t\tif (child.id === nodeId) return child;\n\t\tconst found = findNodeInBlock(child, nodeId);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\n/**\n * Finds a block node and returns it together with its path.\n */\nexport function findNodeWithPath(\n\tdoc: Document,\n\tnodeId: string,\n): { node: BlockNode; path: string[] } | undefined {\n\tconst path = findNodePath(doc, nodeId);\n\tif (!path) return undefined;\n\tconst node = resolveNodeByPath(doc, path);\n\tif (!node) return undefined;\n\treturn { node, path };\n}\n","/**\n * Pure navigation query functions for block boundary and isolating checks.\n *\n * These utilities inspect the document structure and schema to answer\n * questions about block traversal — whether a block is void, isolating,\n * or whether navigation between two blocks is allowed.\n */\n\nimport type { BlockId } from '../model/TypeBrands.js';\nimport type { EditorState } from './EditorState.js';\n\n/** Returns true if the block with the given ID is a void block (e.g. image, HR). */\nexport function isVoidBlock(state: EditorState, bid: BlockId): boolean {\n\tconst block = state.getBlock(bid);\n\tif (!block) return false;\n\tconst getNodeSpec = state.schema.getNodeSpec;\n\tif (!getNodeSpec) return false;\n\treturn getNodeSpec(block.type)?.isVoid === true;\n}\n\n/** Checks whether two blocks share the same parent in the document tree. */\nexport function sharesParent(state: EditorState, blockIdA: BlockId, blockIdB: BlockId): boolean {\n\tconst pathA = state.getNodePath(blockIdA);\n\tconst pathB = state.getNodePath(blockIdB);\n\tif (!pathA || !pathB) return false;\n\tif (pathA.length !== pathB.length) return false;\n\t// Compare parent paths (all but last element)\n\tfor (let i = 0; i < pathA.length - 1; i++) {\n\t\tif (pathA[i] !== pathB[i]) return false;\n\t}\n\treturn true;\n}\n\n/** Checks whether a block is inside an isolating node (e.g. table_cell). */\nexport function isInsideIsolating(state: EditorState, blockId: BlockId): boolean {\n\tconst getNodeSpec = state.schema.getNodeSpec;\n\tif (!getNodeSpec) return false;\n\tconst path = state.getNodePath(blockId);\n\tif (!path || path.length <= 1) return false;\n\n\t// Check ancestors (not the block itself)\n\tfor (let i = 0; i < path.length - 1; i++) {\n\t\tconst ancestorId = path[i];\n\t\tif (!ancestorId) continue;\n\t\tconst ancestor = state.getBlock(ancestorId);\n\t\tif (!ancestor) continue;\n\t\tconst spec = getNodeSpec(ancestor.type);\n\t\tif (spec?.isolating) return true;\n\t}\n\treturn false;\n}\n\n/** Returns true if the block itself has the isolating property. */\nexport function isIsolatingBlock(state: EditorState, blockId: BlockId): boolean {\n\tconst getNodeSpec = state.schema.getNodeSpec;\n\tif (!getNodeSpec) return false;\n\tconst block = state.getBlock(blockId);\n\tif (!block) return false;\n\treturn getNodeSpec(block.type)?.isolating === true;\n}\n\n/**\n * Checks whether navigation between two blocks is allowed.\n * Prevents crossing isolating boundaries (e.g. table cells).\n */\nexport function canCrossBlockBoundary(state: EditorState, fromId: BlockId, toId: BlockId): boolean {\n\t// A block that is itself isolating cannot be crossed into via arrow keys\n\tif (isIsolatingBlock(state, fromId) || isIsolatingBlock(state, toId)) return false;\n\n\tconst fromInside: boolean = isInsideIsolating(state, fromId);\n\tconst toInside: boolean = isInsideIsolating(state, toId);\n\n\t// One inside isolating, the other not → disallow\n\tif (fromInside !== toInside) return false;\n\n\t// Both inside isolating → must share the same parent\n\tif (fromInside && toInside) return sharesParent(state, fromId, toId);\n\n\treturn true;\n}\n"],"names":["resolveNodeByPath","doc","path","length","current","children","find","b","id","i","childId","next","c","isBlockNode","resolveParentByPath","index","findIndex","parent","slice","findNodePath","nodeId","block","subPath","findNodePathInBlock","child","walkNodes","callback","walkNodeRecursive","node","findNode","found","findNodeInBlock","findNodeWithPath","isVoidBlock","state","bid","getBlock","getNodeSpec","schema","type","isVoid","sharesParent","blockIdA","blockIdB","pathA","getNodePath","pathB","isInsideIsolating","blockId","ancestorId","ancestor","spec","isolating","isIsolatingBlock","canCrossBlockBoundary","fromId","toId","fromInside","toInside"],"mappings":"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"}
|