@domternal/core 0.6.1 → 0.7.0
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/index.cjs +1409 -218
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1795 -1335
- package/dist/index.d.ts +1795 -1335
- package/dist/index.js +1388 -218
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Schema, Node as Node$1, DOMOutputSpec, NodeType, Mark as Mark$1, MarkType, Attrs,
|
|
1
|
+
import { Schema, Node as Node$1, DOMOutputSpec, NodeType, Mark as Mark$1, MarkType, Attrs, ResolvedPos, DOMParser, ContentMatch, NodeSpec, MarkSpec } from '@domternal/pm/model';
|
|
2
2
|
import { Transaction, EditorState, Plugin, PluginKey, Selection as Selection$1 } from '@domternal/pm/state';
|
|
3
3
|
export { PluginKey } from '@domternal/pm/state';
|
|
4
4
|
import { InputRule } from '@domternal/pm/inputrules';
|
|
5
|
-
import {
|
|
5
|
+
import { NodeViewConstructor, EditorView } from '@domternal/pm/view';
|
|
6
6
|
import { Placement } from '@floating-ui/dom';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -131,8 +131,7 @@ interface ErrorEventProps$1 {
|
|
|
131
131
|
context: string;
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
134
|
-
* All editor events with their payload types
|
|
135
|
-
* Used by EventEmitter for type-safe event handling
|
|
134
|
+
* All editor events with their payload types.
|
|
136
135
|
*/
|
|
137
136
|
interface EditorEvents {
|
|
138
137
|
/** Fired before editor is created - can modify options */
|
|
@@ -169,6 +168,10 @@ interface EditorEvents {
|
|
|
169
168
|
linkEdit: {
|
|
170
169
|
anchorElement?: HTMLElement;
|
|
171
170
|
};
|
|
171
|
+
/** Fired when the Notion color picker should open, with the trigger as anchor. */
|
|
172
|
+
notionColorOpen: {
|
|
173
|
+
anchorElement?: HTMLElement | null;
|
|
174
|
+
};
|
|
172
175
|
}
|
|
173
176
|
/**
|
|
174
177
|
* Event names as a type
|
|
@@ -212,11 +215,9 @@ type FocusPosition = boolean | 'start' | 'end' | 'all' | number | null;
|
|
|
212
215
|
*/
|
|
213
216
|
interface EditorOptions {
|
|
214
217
|
/**
|
|
215
|
-
* ProseMirror Schema for the editor
|
|
216
|
-
*
|
|
217
|
-
* Step 1.3: Required (no extensions system yet)
|
|
218
|
-
* Step 2+: Optional if extensions are provided (schema built from extensions)
|
|
218
|
+
* ProseMirror Schema for the editor.
|
|
219
219
|
*
|
|
220
|
+
* Optional when `extensions` is provided (schema is built from them).
|
|
220
221
|
* The schema must contain at least 'doc' and 'text' nodes.
|
|
221
222
|
*/
|
|
222
223
|
schema?: Schema;
|
|
@@ -480,7 +481,7 @@ interface ToolbarButton {
|
|
|
480
481
|
* How to check if this button is active.
|
|
481
482
|
* - string: extension name passed to `editor.isActive(name)`
|
|
482
483
|
* - object: `{ name, attributes }` passed to `editor.isActive(name, attributes)`
|
|
483
|
-
* - array: OR-check
|
|
484
|
+
* - array: OR-check - active if ANY entry matches (useful for attributes on multiple node types)
|
|
484
485
|
* - undefined: button has no active state (e.g. undo/redo)
|
|
485
486
|
*/
|
|
486
487
|
isActive?: string | {
|
|
@@ -602,1485 +603,1600 @@ interface ToolbarLayoutDropdown {
|
|
|
602
603
|
/**
|
|
603
604
|
* A single entry in a toolbar layout array.
|
|
604
605
|
*
|
|
605
|
-
* - `string`
|
|
606
|
-
* - `ToolbarLayoutDropdown`
|
|
606
|
+
* - `string` - item name (e.g. `'bold'`) or separator (`'|'`)
|
|
607
|
+
* - `ToolbarLayoutDropdown` - custom dropdown grouping
|
|
607
608
|
*/
|
|
608
609
|
type ToolbarLayoutEntry = string | ToolbarLayoutDropdown;
|
|
609
610
|
|
|
610
611
|
/**
|
|
611
|
-
*
|
|
612
|
+
* Callback type for event handlers
|
|
613
|
+
* - Events with payload: (data: T) => void
|
|
614
|
+
* - Events without payload (undefined): () => void
|
|
615
|
+
*/
|
|
616
|
+
type EventCallback<T> = T extends undefined ? () => void : (data: T) => void;
|
|
617
|
+
/**
|
|
618
|
+
* Generic, type-safe event emitter
|
|
612
619
|
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
620
|
+
* @example
|
|
621
|
+
* ```typescript
|
|
622
|
+
* interface MyEvents {
|
|
623
|
+
* update: { value: number };
|
|
624
|
+
* destroy: undefined;
|
|
625
|
+
* }
|
|
626
|
+
*
|
|
627
|
+
* const emitter = new EventEmitter<MyEvents>();
|
|
628
|
+
* emitter.on('update', ({ value }) => console.log(value));
|
|
629
|
+
* emitter.on('destroy', () => console.log('destroyed'));
|
|
630
|
+
* ```
|
|
615
631
|
*/
|
|
632
|
+
declare class EventEmitter<Events extends {
|
|
633
|
+
[K in keyof Events]: unknown;
|
|
634
|
+
} = Record<string, never>> {
|
|
635
|
+
protected callbacks: Map<keyof Events, Set<(data: unknown) => void>>;
|
|
636
|
+
/**
|
|
637
|
+
* Register an event listener
|
|
638
|
+
*/
|
|
639
|
+
on<E extends keyof Events>(event: E, callback: EventCallback<Events[E]>): this;
|
|
640
|
+
/**
|
|
641
|
+
* Remove an event listener, or all listeners for an event if no callback specified
|
|
642
|
+
*/
|
|
643
|
+
off<E extends keyof Events>(event: E, callback?: EventCallback<Events[E]>): this;
|
|
644
|
+
/**
|
|
645
|
+
* Emit an event to all registered listeners
|
|
646
|
+
* Uses .call(this) to preserve context for callbacks
|
|
647
|
+
*/
|
|
648
|
+
emit<E extends keyof Events>(event: E, ...args: Events[E] extends undefined ? [] : [Events[E]]): this;
|
|
649
|
+
/**
|
|
650
|
+
* Register an event listener that fires only once
|
|
651
|
+
*/
|
|
652
|
+
once<E extends keyof Events>(event: E, callback: EventCallback<Events[E]>): this;
|
|
653
|
+
/**
|
|
654
|
+
* Remove all listeners for a specific event, or all events if no event specified
|
|
655
|
+
*/
|
|
656
|
+
removeAllListeners(event?: keyof Events): this;
|
|
657
|
+
/**
|
|
658
|
+
* Get the number of listeners for a specific event
|
|
659
|
+
*/
|
|
660
|
+
listenerCount(event: keyof Events): number;
|
|
661
|
+
/**
|
|
662
|
+
* Get all event names that have listeners
|
|
663
|
+
*/
|
|
664
|
+
eventNames(): (keyof Events)[];
|
|
665
|
+
}
|
|
616
666
|
|
|
617
667
|
/**
|
|
618
|
-
*
|
|
668
|
+
* ExtensionManager - manages extensions and schema.
|
|
669
|
+
*
|
|
670
|
+
* Handles:
|
|
671
|
+
* - Extension lifecycle (flatten, resolve, bind)
|
|
672
|
+
* - Schema building from Node/Mark extensions
|
|
673
|
+
* - Plugin collection from all extensions
|
|
674
|
+
* - Extension storage management
|
|
675
|
+
* - Conflict detection (duplicate extension names)
|
|
619
676
|
*/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Error event props for safeCall
|
|
680
|
+
*/
|
|
681
|
+
interface ErrorEventProps {
|
|
682
|
+
error: Error;
|
|
683
|
+
context: string;
|
|
625
684
|
}
|
|
626
685
|
/**
|
|
627
|
-
*
|
|
686
|
+
* Editor interface for ExtensionManager
|
|
687
|
+
* Forward declaration to avoid circular dependency
|
|
628
688
|
*/
|
|
629
|
-
interface
|
|
630
|
-
|
|
631
|
-
|
|
689
|
+
interface ExtensionManagerEditor {
|
|
690
|
+
readonly schema: Schema;
|
|
691
|
+
emit?(event: 'error', props: ErrorEventProps): void;
|
|
632
692
|
}
|
|
633
693
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
694
|
+
* Context attached to node view constructors for framework wrappers.
|
|
695
|
+
* Accessible via `(constructor as any).__domternalContext`.
|
|
636
696
|
*/
|
|
637
|
-
interface
|
|
697
|
+
interface NodeViewContext {
|
|
698
|
+
editor: ExtensionManagerEditor;
|
|
699
|
+
extension: {
|
|
700
|
+
name: string;
|
|
701
|
+
options: Record<string, unknown>;
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Options for ExtensionManager constructor
|
|
706
|
+
*/
|
|
707
|
+
interface ExtensionManagerOptions {
|
|
638
708
|
/**
|
|
639
|
-
*
|
|
709
|
+
* Extensions to process
|
|
710
|
+
* If provided, schema is built from extensions
|
|
640
711
|
*/
|
|
641
|
-
|
|
712
|
+
extensions?: AnyExtension[] | undefined;
|
|
642
713
|
/**
|
|
643
|
-
*
|
|
644
|
-
* @param element - The DOM element to parse from
|
|
645
|
-
* @returns The parsed attribute value
|
|
714
|
+
* Direct schema. If provided, extensions are ignored for schema building.
|
|
646
715
|
*/
|
|
647
|
-
|
|
716
|
+
schema?: Schema | undefined;
|
|
717
|
+
}
|
|
718
|
+
declare class ExtensionManager {
|
|
648
719
|
/**
|
|
649
|
-
*
|
|
650
|
-
* @param attributes - The node/mark attributes
|
|
651
|
-
* @returns Object of HTML attributes to set, or null/empty to skip
|
|
720
|
+
* Processed extensions (flattened, sorted by priority)
|
|
652
721
|
*/
|
|
653
|
-
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* Global attributes definition for injecting into node/mark types.
|
|
657
|
-
*/
|
|
658
|
-
interface GlobalAttributes {
|
|
722
|
+
private readonly _extensions;
|
|
659
723
|
/**
|
|
660
|
-
*
|
|
661
|
-
* @example ['heading', 'paragraph']
|
|
724
|
+
* ProseMirror schema (built from extensions or passed directly)
|
|
662
725
|
*/
|
|
663
|
-
|
|
726
|
+
private readonly _schema;
|
|
664
727
|
/**
|
|
665
|
-
*
|
|
666
|
-
* @example { textAlign: { default: 'left', parseHTML: (el) => el.style.textAlign } }
|
|
728
|
+
* Reference to the editor instance
|
|
667
729
|
*/
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Context interface that describes what `this` will be in config methods.
|
|
672
|
-
* This enables proper typing of `this.options`, `this.editor`, etc.
|
|
673
|
-
* without creating circular dependencies.
|
|
674
|
-
*
|
|
675
|
-
* @typeParam Options - Extension options type
|
|
676
|
-
* @typeParam Storage - Extension storage type
|
|
677
|
-
*/
|
|
678
|
-
interface ExtensionContext<Options = unknown, Storage = unknown> {
|
|
679
|
-
/** Extension type identifier */
|
|
680
|
-
readonly type: 'extension' | 'node' | 'mark';
|
|
681
|
-
/** Unique extension name */
|
|
682
|
-
readonly name: string;
|
|
683
|
-
/** Extension options (immutable after creation) */
|
|
684
|
-
readonly options: Options;
|
|
685
|
-
/** Extension storage (mutable state) */
|
|
686
|
-
storage: Storage;
|
|
687
|
-
/** Editor instance (null until bound by ExtensionManager) */
|
|
688
|
-
editor: ExtensionEditor | null;
|
|
730
|
+
readonly editor: ExtensionManagerEditor;
|
|
689
731
|
/**
|
|
690
|
-
*
|
|
691
|
-
* Available only inside overridden config methods.
|
|
692
|
-
* Use `this.parent?.()` to call the parent's version of the current method.
|
|
732
|
+
* Extension storage (keyed by extension name)
|
|
693
733
|
*/
|
|
694
|
-
|
|
695
|
-
}
|
|
696
|
-
/**
|
|
697
|
-
* Base configuration properties for all extension types.
|
|
698
|
-
* This interface contains just the properties without ThisType,
|
|
699
|
-
* allowing Node and Mark configs to use their own context types.
|
|
700
|
-
*
|
|
701
|
-
* @typeParam Options - Extension options type
|
|
702
|
-
* @typeParam Storage - Extension storage type
|
|
703
|
-
*/
|
|
704
|
-
interface ExtensionConfigBase<Options = unknown, Storage = unknown> {
|
|
734
|
+
private readonly _storage;
|
|
705
735
|
/**
|
|
706
|
-
*
|
|
707
|
-
* Used for identification, storage access, and error messages
|
|
736
|
+
* Whether the manager has been destroyed
|
|
708
737
|
*/
|
|
709
|
-
|
|
738
|
+
private isDestroyed;
|
|
710
739
|
/**
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
* Reserved ranges:
|
|
714
|
-
* - 900-1000: Core nodes (Document, Text, Paragraph)
|
|
715
|
-
* - 500-899: Standard extensions (Heading, Bold, etc.)
|
|
716
|
-
* - 100-499: Default range for user extensions
|
|
717
|
-
* - 0-99: Low priority extensions (run after everything)
|
|
718
|
-
*
|
|
719
|
-
* @default 100
|
|
740
|
+
* Cached plugins (built lazily)
|
|
720
741
|
*/
|
|
721
|
-
|
|
742
|
+
private _plugins;
|
|
722
743
|
/**
|
|
723
|
-
*
|
|
724
|
-
* ExtensionManager throws if any dependency is missing
|
|
725
|
-
*
|
|
726
|
-
* @example
|
|
727
|
-
* dependencies: ['bulletList', 'orderedList']
|
|
744
|
+
* Cached commands (collected lazily)
|
|
728
745
|
*/
|
|
729
|
-
|
|
746
|
+
private _commands;
|
|
730
747
|
/**
|
|
731
|
-
*
|
|
732
|
-
* Called during extension creation with `this` bound to the extension
|
|
748
|
+
* Cached toolbar items (collected lazily)
|
|
733
749
|
*/
|
|
734
|
-
|
|
750
|
+
private _toolbarItems;
|
|
735
751
|
/**
|
|
736
|
-
*
|
|
737
|
-
* Storage is mutable and accessible via editor.storage[extensionName]
|
|
752
|
+
* Cached floating-menu items (collected lazily)
|
|
738
753
|
*/
|
|
739
|
-
|
|
754
|
+
private _floatingMenuItems;
|
|
740
755
|
/**
|
|
741
|
-
*
|
|
742
|
-
* Commands are accessible via editor.commands.commandName()
|
|
743
|
-
*
|
|
744
|
-
* @example
|
|
745
|
-
* addCommands() {
|
|
746
|
-
* return {
|
|
747
|
-
* toggleBold: () => ({ commands }) => commands.toggleMark('bold'),
|
|
748
|
-
* };
|
|
749
|
-
* }
|
|
756
|
+
* Cached node views (collected lazily)
|
|
750
757
|
*/
|
|
751
|
-
|
|
758
|
+
private _nodeViews;
|
|
752
759
|
/**
|
|
753
|
-
*
|
|
754
|
-
* Keys are shortcut strings (e.g., 'Mod-b'), values are handler functions
|
|
760
|
+
* Creates a new ExtensionManager
|
|
755
761
|
*
|
|
756
|
-
* @
|
|
757
|
-
*
|
|
758
|
-
* return {
|
|
759
|
-
* 'Mod-b': () => this.editor.commands.toggleBold(),
|
|
760
|
-
* };
|
|
761
|
-
* }
|
|
762
|
+
* @param options - Extensions or direct schema
|
|
763
|
+
* @param editor - Editor instance
|
|
762
764
|
*/
|
|
763
|
-
|
|
765
|
+
constructor(options: ExtensionManagerOptions, editor: ExtensionManagerEditor);
|
|
764
766
|
/**
|
|
765
|
-
*
|
|
766
|
-
* Triggered when user types matching patterns
|
|
767
|
-
*
|
|
768
|
-
* @example
|
|
769
|
-
* addInputRules() {
|
|
770
|
-
* return [
|
|
771
|
-
* textblockTypeInputRule(/^## $/, this.type),
|
|
772
|
-
* ];
|
|
773
|
-
* }
|
|
767
|
+
* Gets the processed extensions array
|
|
774
768
|
*/
|
|
775
|
-
|
|
769
|
+
get extensions(): readonly AnyExtension[];
|
|
776
770
|
/**
|
|
777
|
-
*
|
|
771
|
+
* Gets the ProseMirror schema
|
|
778
772
|
*/
|
|
779
|
-
|
|
773
|
+
get schema(): Schema;
|
|
780
774
|
/**
|
|
781
|
-
*
|
|
782
|
-
* These extensions are flattened and processed like top-level extensions
|
|
775
|
+
* Gets extension storage (accessed via editor.storage)
|
|
783
776
|
*/
|
|
784
|
-
|
|
777
|
+
get storage(): Record<string, unknown>;
|
|
785
778
|
/**
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
* to several nodes (heading, paragraph, etc.) without modifying each.
|
|
789
|
-
*
|
|
790
|
-
* @example
|
|
791
|
-
* addGlobalAttributes() {
|
|
792
|
-
* return [{
|
|
793
|
-
* types: ['heading', 'paragraph'],
|
|
794
|
-
* attributes: {
|
|
795
|
-
* textAlign: {
|
|
796
|
-
* default: 'left',
|
|
797
|
-
* parseHTML: (element) => element.style.textAlign || 'left',
|
|
798
|
-
* renderHTML: (attrs) => attrs.textAlign !== 'left'
|
|
799
|
-
* ? { style: `text-align: ${attrs.textAlign}` }
|
|
800
|
-
* : null,
|
|
801
|
-
* },
|
|
802
|
-
* },
|
|
803
|
-
* }];
|
|
804
|
-
* }
|
|
805
|
-
*/
|
|
806
|
-
addGlobalAttributes?: () => GlobalAttributes[];
|
|
807
|
-
/**
|
|
808
|
-
* Toolbar items this extension contributes.
|
|
809
|
-
* Framework toolbar components read these to auto-generate buttons.
|
|
810
|
-
*
|
|
811
|
-
* @example
|
|
812
|
-
* addToolbarItems() {
|
|
813
|
-
* return [{
|
|
814
|
-
* type: 'button',
|
|
815
|
-
* name: 'bold',
|
|
816
|
-
* command: 'toggleBold',
|
|
817
|
-
* isActive: 'bold',
|
|
818
|
-
* icon: 'textB',
|
|
819
|
-
* label: 'Bold',
|
|
820
|
-
* shortcut: 'Mod-b',
|
|
821
|
-
* group: 'format',
|
|
822
|
-
* }];
|
|
823
|
-
* }
|
|
779
|
+
* Gets plugins from all extensions
|
|
780
|
+
* Cached after first call
|
|
824
781
|
*/
|
|
825
|
-
|
|
782
|
+
get plugins(): Plugin[];
|
|
826
783
|
/**
|
|
827
|
-
*
|
|
828
|
-
* Can be used to modify editor options
|
|
784
|
+
* Gets commands from all extensions
|
|
829
785
|
*/
|
|
830
|
-
|
|
786
|
+
get commands(): CommandMap;
|
|
831
787
|
/**
|
|
832
|
-
*
|
|
788
|
+
* Gets toolbar items from all extensions
|
|
789
|
+
* Cached after first call
|
|
833
790
|
*/
|
|
834
|
-
|
|
791
|
+
get toolbarItems(): ToolbarItem[];
|
|
835
792
|
/**
|
|
836
|
-
*
|
|
793
|
+
* Gets floating-menu items from all extensions
|
|
794
|
+
* Cached after first call
|
|
837
795
|
*/
|
|
838
|
-
|
|
796
|
+
get floatingMenuItems(): FloatingMenuItem[];
|
|
839
797
|
/**
|
|
840
|
-
*
|
|
798
|
+
* Gets node views from all Node extensions that define addNodeView
|
|
841
799
|
*/
|
|
842
|
-
|
|
800
|
+
get nodeViews(): Record<string, NodeViewConstructor>;
|
|
843
801
|
/**
|
|
844
|
-
*
|
|
845
|
-
*
|
|
802
|
+
* Clears all caches (plugins, commands)
|
|
803
|
+
* Call when extensions change dynamically
|
|
846
804
|
*/
|
|
847
|
-
|
|
848
|
-
transaction: Transaction;
|
|
849
|
-
}) => void;
|
|
805
|
+
clearAllCaches(): void;
|
|
850
806
|
/**
|
|
851
|
-
*
|
|
807
|
+
* Recursively flattens extensions by expanding addExtensions()
|
|
808
|
+
* This allows extension bundles like StarterKit to work
|
|
852
809
|
*/
|
|
853
|
-
|
|
854
|
-
event: FocusEvent;
|
|
855
|
-
}) => void;
|
|
810
|
+
private flattenExtensions;
|
|
856
811
|
/**
|
|
857
|
-
*
|
|
812
|
+
* Removes duplicate extensions by name, keeping the last occurrence.
|
|
813
|
+
* This allows parent extensions to auto-include children via addExtensions()
|
|
814
|
+
* while letting users override with explicitly configured versions.
|
|
858
815
|
*/
|
|
859
|
-
|
|
860
|
-
event: FocusEvent;
|
|
861
|
-
}) => void;
|
|
816
|
+
private deduplicateExtensions;
|
|
862
817
|
/**
|
|
863
|
-
*
|
|
864
|
-
*
|
|
818
|
+
* Sorts extensions by priority (higher priority first)
|
|
819
|
+
* Default priority is 100
|
|
865
820
|
*/
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Full configuration type for Extension.create()
|
|
870
|
-
* Combines base properties with ThisType for proper `this` typing.
|
|
871
|
-
*
|
|
872
|
-
* @typeParam Options - Extension options type
|
|
873
|
-
* @typeParam Storage - Extension storage type
|
|
874
|
-
*/
|
|
875
|
-
type ExtensionConfig<Options = unknown, Storage = unknown> = ExtensionConfigBase<Options, Storage> & ThisType<ExtensionContext<Options, Storage>>;
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* Attribute specification for Node and Mark extensions
|
|
879
|
-
*
|
|
880
|
-
* Used by addAttributes() to define node/mark attributes
|
|
881
|
-
* with parsing, rendering, and validation rules.
|
|
882
|
-
*
|
|
883
|
-
* @example
|
|
884
|
-
* addAttributes() {
|
|
885
|
-
* return {
|
|
886
|
-
* level: {
|
|
887
|
-
* default: 1,
|
|
888
|
-
* parseHTML: (element) => parseInt(element.tagName.charAt(1), 10),
|
|
889
|
-
* renderHTML: (attributes) => ({ 'data-level': attributes.level }),
|
|
890
|
-
* },
|
|
891
|
-
* };
|
|
892
|
-
* }
|
|
893
|
-
*/
|
|
894
|
-
/**
|
|
895
|
-
* Specification for a single attribute
|
|
896
|
-
*/
|
|
897
|
-
interface AttributeSpec {
|
|
821
|
+
private resolveExtensions;
|
|
898
822
|
/**
|
|
899
|
-
*
|
|
900
|
-
*
|
|
823
|
+
* Detects duplicate extension names.
|
|
824
|
+
* @throws Error if duplicate names found
|
|
901
825
|
*/
|
|
902
|
-
|
|
826
|
+
private detectConflicts;
|
|
903
827
|
/**
|
|
904
|
-
*
|
|
905
|
-
* @
|
|
828
|
+
* Validates that all extension dependencies are present
|
|
829
|
+
* @throws Error if required dependency is missing
|
|
906
830
|
*/
|
|
907
|
-
|
|
831
|
+
private checkDependencies;
|
|
908
832
|
/**
|
|
909
|
-
*
|
|
910
|
-
* For example, heading level should be kept when pressing Enter
|
|
911
|
-
* @default true
|
|
833
|
+
* Sets editor reference on all extensions
|
|
912
834
|
*/
|
|
913
|
-
|
|
835
|
+
private bindEditorToExtensions;
|
|
914
836
|
/**
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
* (`"number"`, `"string"`, `"boolean"`, `"null"`, `"undefined"`).
|
|
918
|
-
* When a function, it should throw if the value is invalid.
|
|
919
|
-
*
|
|
920
|
-
* @example
|
|
921
|
-
* validate: 'number'
|
|
922
|
-
* validate: 'string|null'
|
|
923
|
-
* validate: (value) => { if (typeof value !== 'number') throw new Error('expected number'); }
|
|
837
|
+
* Collects global attributes from all extensions.
|
|
838
|
+
* Returns a map of type name -> attribute specs to merge.
|
|
924
839
|
*/
|
|
925
|
-
|
|
840
|
+
private collectGlobalAttributes;
|
|
926
841
|
/**
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
* @returns The attribute value
|
|
932
|
-
*
|
|
933
|
-
* @example
|
|
934
|
-
* parseHTML: (element) => element.getAttribute('data-level')
|
|
842
|
+
* Applies global attributes to a node or mark spec.
|
|
843
|
+
* Merges extra attrs into spec.attrs, wraps parseDOM getAttrs to parse
|
|
844
|
+
* global attributes from DOM elements, and wraps toDOM to inject rendered
|
|
845
|
+
* global HTML attributes into the output.
|
|
935
846
|
*/
|
|
936
|
-
|
|
847
|
+
private applyGlobalAttributes;
|
|
937
848
|
/**
|
|
938
|
-
*
|
|
939
|
-
* Called during HTML serialization
|
|
940
|
-
*
|
|
941
|
-
* @param attributes - All attributes of the node/mark
|
|
942
|
-
* @returns HTML attributes object or null to skip
|
|
943
|
-
*
|
|
944
|
-
* @example
|
|
945
|
-
* renderHTML: (attributes) => ({ 'data-level': attributes.level })
|
|
849
|
+
* Builds ProseMirror Schema from Node and Mark extensions
|
|
946
850
|
*/
|
|
947
|
-
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Collection of attribute specifications
|
|
951
|
-
* Keyed by attribute name
|
|
952
|
-
*/
|
|
953
|
-
type AttributeSpecs = Record<string, AttributeSpec>;
|
|
954
|
-
|
|
955
|
-
/**
|
|
956
|
-
* Node configuration types
|
|
957
|
-
*
|
|
958
|
-
* These types define the configuration object passed to Node.create()
|
|
959
|
-
* for creating ProseMirror node extensions.
|
|
960
|
-
*/
|
|
961
|
-
|
|
962
|
-
/**
|
|
963
|
-
* Editor interface for Node context
|
|
964
|
-
* Includes schema with nodes for NodeType getter
|
|
965
|
-
*/
|
|
966
|
-
interface NodeEditorContext {
|
|
967
|
-
readonly state: EditorState;
|
|
968
|
-
readonly view: EditorView;
|
|
969
|
-
readonly schema: {
|
|
970
|
-
nodes: Record<string, NodeType>;
|
|
971
|
-
};
|
|
972
|
-
readonly commands: Record<string, (...args: unknown[]) => boolean>;
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Context interface for Node config methods.
|
|
976
|
-
* Extends ExtensionContext with node-specific properties.
|
|
977
|
-
* This enables proper typing of `this.options`, `this.nodeType`, etc.
|
|
978
|
-
*
|
|
979
|
-
* @typeParam Options - Node options type
|
|
980
|
-
* @typeParam Storage - Node storage type
|
|
981
|
-
*/
|
|
982
|
-
interface NodeContext<Options = unknown, Storage = unknown> extends Omit<ExtensionContext<Options, Storage>, 'editor' | 'type'> {
|
|
983
|
-
/** Node type identifier */
|
|
984
|
-
readonly type: 'node';
|
|
985
|
-
/** Editor instance with schema access */
|
|
986
|
-
editor: NodeEditorContext | null;
|
|
987
|
-
/** ProseMirror NodeType (null until editor is initialized) */
|
|
988
|
-
readonly nodeType: NodeType | null;
|
|
989
|
-
}
|
|
990
|
-
/**
|
|
991
|
-
* Parse rule for converting HTML to ProseMirror node
|
|
992
|
-
* Simplified version of ProseMirror's ParseRule
|
|
993
|
-
*/
|
|
994
|
-
interface NodeParseRule {
|
|
851
|
+
private buildSchema;
|
|
995
852
|
/**
|
|
996
|
-
*
|
|
997
|
-
* @example 'p', 'h1', 'div.my-class'
|
|
853
|
+
* Initializes storage for all extensions
|
|
998
854
|
*/
|
|
999
|
-
|
|
855
|
+
private initializeStorage;
|
|
1000
856
|
/**
|
|
1001
|
-
*
|
|
1002
|
-
* @example 'font-weight'
|
|
857
|
+
* Builds all ProseMirror plugins from extensions
|
|
1003
858
|
*/
|
|
1004
|
-
|
|
859
|
+
private buildPlugins;
|
|
1005
860
|
/**
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
861
|
+
* Collects keyboard shortcuts from all extensions
|
|
862
|
+
* Returns ProseMirror-compatible commands for keymap plugin
|
|
863
|
+
*
|
|
864
|
+
* Note: Extensions should return PM-compatible commands from addKeyboardShortcuts()
|
|
1008
865
|
*/
|
|
1009
|
-
|
|
866
|
+
private collectKeyboardShortcuts;
|
|
1010
867
|
/**
|
|
1011
|
-
*
|
|
1012
|
-
* @default true
|
|
868
|
+
* Collects input rules from all extensions
|
|
1013
869
|
*/
|
|
1014
|
-
|
|
870
|
+
private collectInputRules;
|
|
1015
871
|
/**
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
872
|
+
* Collects commands from all extensions
|
|
873
|
+
*
|
|
874
|
+
* Note: Commands with the same name will be overwritten by later extensions
|
|
875
|
+
* (lower priority extensions override higher priority). This is intentional
|
|
876
|
+
* to allow customization of built-in commands.
|
|
1018
877
|
*/
|
|
1019
|
-
|
|
878
|
+
private collectCommands;
|
|
1020
879
|
/**
|
|
1021
|
-
*
|
|
1022
|
-
* Return null/undefined to skip this rule
|
|
880
|
+
* Collects toolbar items from all extensions
|
|
1023
881
|
*/
|
|
1024
|
-
|
|
882
|
+
private collectToolbarItems;
|
|
1025
883
|
/**
|
|
1026
|
-
*
|
|
1027
|
-
* Return false to use default content parsing
|
|
884
|
+
* Collects floating-menu items from all extensions via `addFloatingMenuItems()`.
|
|
1028
885
|
*/
|
|
1029
|
-
|
|
886
|
+
private collectFloatingMenuItems;
|
|
1030
887
|
/**
|
|
1031
|
-
*
|
|
1032
|
-
|
|
1033
|
-
preserveWhitespace?: boolean | 'full';
|
|
1034
|
-
}
|
|
1035
|
-
/**
|
|
1036
|
-
* Props passed to renderHTML function
|
|
1037
|
-
*/
|
|
1038
|
-
interface NodeRenderHTMLProps {
|
|
1039
|
-
/**
|
|
1040
|
-
* The ProseMirror node being rendered
|
|
1041
|
-
*/
|
|
1042
|
-
node: Node$1;
|
|
1043
|
-
/**
|
|
1044
|
-
* Merged HTML attributes from all sources
|
|
1045
|
-
*/
|
|
1046
|
-
HTMLAttributes: Record<string, unknown>;
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* Node-specific configuration properties (schema-related)
|
|
1050
|
-
*/
|
|
1051
|
-
interface NodeSchemaProperties {
|
|
1052
|
-
/**
|
|
1053
|
-
* Node group(s) this node belongs to
|
|
1054
|
-
* Used in content expressions
|
|
888
|
+
* Collects node views from all Node extensions.
|
|
889
|
+
* Returns a map of node name to NodeViewConstructor for EditorView.
|
|
1055
890
|
*
|
|
1056
|
-
*
|
|
1057
|
-
*
|
|
891
|
+
* Each constructor is annotated with `__domternalContext` containing
|
|
892
|
+
* the editor and extension metadata so framework wrappers (React, Vue)
|
|
893
|
+
* can access them without changing the ProseMirror calling convention.
|
|
1058
894
|
*/
|
|
1059
|
-
|
|
895
|
+
private collectNodeViews;
|
|
1060
896
|
/**
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
* @example 'inline*', 'block+', 'paragraph block*'
|
|
897
|
+
* Validates that the schema has required nodes
|
|
898
|
+
* @throws Error if schema is missing 'doc' or 'text' nodes
|
|
1065
899
|
*/
|
|
1066
|
-
|
|
900
|
+
validateSchema(): void;
|
|
1067
901
|
/**
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
* @default false
|
|
902
|
+
* Cleans up the extension manager
|
|
903
|
+
* Calls onDestroy on all extensions and clears all caches
|
|
1071
904
|
*/
|
|
1072
|
-
|
|
905
|
+
destroy(): void;
|
|
1073
906
|
/**
|
|
1074
|
-
*
|
|
1075
|
-
*
|
|
907
|
+
* Safely executes a function, catching and reporting errors
|
|
908
|
+
* Prevents a single extension error from crashing the entire editor
|
|
1076
909
|
*
|
|
1077
|
-
*
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
*
|
|
1082
|
-
* @default true for leaf nodes, false for others
|
|
1083
|
-
*/
|
|
1084
|
-
selectable?: boolean;
|
|
1085
|
-
/**
|
|
1086
|
-
* Whether the node can be dragged
|
|
1087
|
-
* @default false
|
|
1088
|
-
*/
|
|
1089
|
-
draggable?: boolean;
|
|
1090
|
-
/**
|
|
1091
|
-
* Whether this node represents code
|
|
1092
|
-
* Affects text input handling (disables smart quotes, etc.)
|
|
1093
|
-
*/
|
|
1094
|
-
code?: boolean;
|
|
1095
|
-
/**
|
|
1096
|
-
* How whitespace is handled in this node
|
|
1097
|
-
* - 'pre': preserve whitespace (like <pre>)
|
|
1098
|
-
* - 'normal': collapse whitespace (default)
|
|
910
|
+
* Handles both synchronous errors and async promise rejections.
|
|
911
|
+
*
|
|
912
|
+
* @param fn - Function to execute
|
|
913
|
+
* @param context - Context for error reporting (e.g., 'Bold.onUpdate')
|
|
914
|
+
* @returns The function result, or undefined if an error occurred
|
|
1099
915
|
*/
|
|
1100
|
-
|
|
916
|
+
safeCall<T>(fn: () => T, context: string): T | undefined;
|
|
1101
917
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
* Marks don't extend across isolating boundaries
|
|
918
|
+
* Calls onBeforeCreate on all extensions
|
|
1104
919
|
*/
|
|
1105
|
-
|
|
920
|
+
callOnBeforeCreate(): void;
|
|
1106
921
|
/**
|
|
1107
|
-
*
|
|
1108
|
-
* Set to false to prevent gapcursor from appearing inside this node.
|
|
1109
|
-
* Set to true to force gapcursor even if the default heuristic disallows it.
|
|
1110
|
-
* When undefined, uses ProseMirror's default heuristic.
|
|
922
|
+
* Calls onCreate on all extensions
|
|
1111
923
|
*/
|
|
1112
|
-
|
|
924
|
+
callOnCreate(): void;
|
|
1113
925
|
/**
|
|
1114
|
-
*
|
|
1115
|
-
* Nodes with a tableRole are discovered by prosemirror-tables via spec.tableRole.
|
|
1116
|
-
* One of: 'table', 'row', 'cell', 'header_cell'
|
|
926
|
+
* Calls onUpdate on all extensions
|
|
1117
927
|
*/
|
|
1118
|
-
|
|
928
|
+
callOnUpdate(): void;
|
|
1119
929
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
* Only one node should have this set to true
|
|
930
|
+
* Calls onSelectionUpdate on all extensions
|
|
1122
931
|
*/
|
|
1123
|
-
|
|
932
|
+
callOnSelectionUpdate(): void;
|
|
1124
933
|
/**
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
934
|
+
* Calls onTransaction on all extensions
|
|
935
|
+
* @param props - Transaction props
|
|
1127
936
|
*/
|
|
1128
|
-
|
|
937
|
+
callOnTransaction(props: {
|
|
938
|
+
transaction: Transaction;
|
|
939
|
+
}): void;
|
|
1129
940
|
/**
|
|
1130
|
-
*
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
* @example '', '_', 'bold italic'
|
|
941
|
+
* Calls onFocus on all extensions
|
|
942
|
+
* @param props - Focus event props
|
|
1134
943
|
*/
|
|
1135
|
-
|
|
944
|
+
callOnFocus(props: {
|
|
945
|
+
event: FocusEvent;
|
|
946
|
+
}): void;
|
|
1136
947
|
/**
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1139
|
-
*
|
|
1140
|
-
* @example '\n' for hard break
|
|
948
|
+
* Calls onBlur on all extensions
|
|
949
|
+
* @param props - Blur event props
|
|
1141
950
|
*/
|
|
1142
|
-
|
|
951
|
+
callOnBlur(props: {
|
|
952
|
+
event: FocusEvent;
|
|
953
|
+
}): void;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Inline Styles Utility
|
|
958
|
+
*
|
|
959
|
+
* Applies inline CSS styles to serialized HTML so it renders correctly
|
|
960
|
+
* when pasted outside the editor (email clients, CMS, Google Docs, etc.).
|
|
961
|
+
*
|
|
962
|
+
* Uses hardcoded light-theme defaults (same approach as Google Docs, Notion,
|
|
963
|
+
* TinyMCE). Optionally accepts overrides for custom styling.
|
|
964
|
+
*
|
|
965
|
+
* Only structural styles are inlined (borders, padding, margins, fonts).
|
|
966
|
+
* Colors are NOT inlined - explicit colors (TextColor, Highlight, cell bg)
|
|
967
|
+
* are already inline from renderHTML, and default text color is browser default.
|
|
968
|
+
*/
|
|
969
|
+
interface InlineStyleOverrides {
|
|
970
|
+
blockquoteBorder?: string;
|
|
971
|
+
blockquoteColor?: string;
|
|
972
|
+
tableBorder?: string;
|
|
973
|
+
tableHeaderBg?: string;
|
|
974
|
+
codeBg?: string;
|
|
975
|
+
codeFont?: string;
|
|
976
|
+
codeBorder?: string;
|
|
977
|
+
codeBlockBg?: string;
|
|
978
|
+
codeBlockFont?: string;
|
|
979
|
+
hrBorder?: string;
|
|
980
|
+
linkColor?: string;
|
|
981
|
+
detailsBorder?: string;
|
|
982
|
+
detailsBg?: string;
|
|
1143
983
|
/**
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
* addAttributes() {
|
|
1149
|
-
* return {
|
|
1150
|
-
* level: { default: 1 },
|
|
1151
|
-
* };
|
|
1152
|
-
* }
|
|
984
|
+
* How to export table column widths from `data-colwidth` attributes.
|
|
985
|
+
* - `'percent'` (default): convert to percentage widths on first-row cells
|
|
986
|
+
* - `'pixel'`: convert to pixel widths on first-row cells, table gets fixed width
|
|
987
|
+
* - `'none'`: leave `data-colwidth` as-is, no width styles applied
|
|
1153
988
|
*/
|
|
1154
|
-
|
|
989
|
+
tableColumnWidths?: 'percent' | 'pixel' | 'none';
|
|
1155
990
|
/**
|
|
1156
|
-
*
|
|
1157
|
-
*
|
|
991
|
+
* Optional callback to syntax-highlight code blocks.
|
|
992
|
+
* Receives the raw text content and optional language, returns highlighted HTML
|
|
993
|
+
* with `<span class="hljs-*">` markup (or any spans with inline styles).
|
|
1158
994
|
*
|
|
1159
995
|
* @example
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1164
|
-
* ];
|
|
1165
|
-
* }
|
|
1166
|
-
*/
|
|
1167
|
-
parseHTML?: () => NodeParseRule[];
|
|
1168
|
-
/**
|
|
1169
|
-
* Render this node to DOM
|
|
1170
|
-
* Returns DOMOutputSpec (tag, attributes, children)
|
|
996
|
+
* ```ts
|
|
997
|
+
* import { createLowlight, common } from 'lowlight';
|
|
998
|
+
* import { toHtml } from 'hast-util-to-html';
|
|
999
|
+
* const lowlight = createLowlight(common);
|
|
1171
1000
|
*
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1175
|
-
*
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1181
|
-
*/
|
|
1182
|
-
addNodeView?: () => NodeViewConstructor;
|
|
1183
|
-
/**
|
|
1184
|
-
* Additional ProseMirror plugins for this node
|
|
1185
|
-
* Called during plugin collection
|
|
1001
|
+
* inlineStyles(html, {
|
|
1002
|
+
* codeHighlighter: (code, language) => {
|
|
1003
|
+
* if (language && lowlight.registered(language)) {
|
|
1004
|
+
* return toHtml(lowlight.highlight(language, code));
|
|
1005
|
+
* }
|
|
1006
|
+
* return null; // no highlighting
|
|
1007
|
+
* },
|
|
1008
|
+
* });
|
|
1009
|
+
* ```
|
|
1186
1010
|
*/
|
|
1187
|
-
|
|
1011
|
+
codeHighlighter?: (code: string, language: string | null) => string | null;
|
|
1188
1012
|
}
|
|
1189
1013
|
/**
|
|
1190
|
-
*
|
|
1191
|
-
*
|
|
1192
|
-
|
|
1014
|
+
* Applies inline styles to all elements in a container.
|
|
1015
|
+
* Exported for use in clipboardSerializer (operates on DOM directly).
|
|
1016
|
+
*/
|
|
1017
|
+
declare function applyInlineStyles(container: HTMLElement, overrides?: InlineStyleOverrides): void;
|
|
1018
|
+
/**
|
|
1019
|
+
* Takes an HTML string and returns it with inline CSS styles applied
|
|
1020
|
+
* to all elements, so it renders correctly outside the editor.
|
|
1193
1021
|
*
|
|
1194
|
-
* @
|
|
1195
|
-
* @
|
|
1022
|
+
* @param html - Serialized HTML string from editor.getHTML()
|
|
1023
|
+
* @param overrides - Optional style overrides for custom theming
|
|
1196
1024
|
*
|
|
1197
1025
|
* @example
|
|
1198
|
-
*
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1203
|
-
*
|
|
1204
|
-
*
|
|
1205
|
-
*
|
|
1206
|
-
* renderHTML({ HTMLAttributes }) {
|
|
1207
|
-
* return ['p', HTMLAttributes, 0];
|
|
1208
|
-
* },
|
|
1026
|
+
* ```ts
|
|
1027
|
+
* // Default light-theme styles
|
|
1028
|
+
* const styled = inlineStyles(editor.getHTML());
|
|
1029
|
+
*
|
|
1030
|
+
* // With custom overrides
|
|
1031
|
+
* const styled = inlineStyles(editor.getHTML(), {
|
|
1032
|
+
* blockquoteBorder: '5px solid red',
|
|
1033
|
+
* linkColor: '#ff6600',
|
|
1209
1034
|
* });
|
|
1035
|
+
* ```
|
|
1210
1036
|
*/
|
|
1211
|
-
|
|
1037
|
+
declare function inlineStyles(html: string, overrides?: InlineStyleOverrides): string;
|
|
1212
1038
|
|
|
1213
1039
|
/**
|
|
1214
|
-
*
|
|
1040
|
+
* Editor - Main editor class wrapping ProseMirror
|
|
1215
1041
|
*
|
|
1216
|
-
*
|
|
1217
|
-
* for creating ProseMirror mark extensions.
|
|
1042
|
+
* Manages extensions, schema, commands, and the ProseMirror EditorView/State.
|
|
1218
1043
|
*/
|
|
1219
1044
|
|
|
1220
1045
|
/**
|
|
1221
|
-
*
|
|
1222
|
-
* Includes schema with marks for MarkType getter
|
|
1223
|
-
*/
|
|
1224
|
-
interface MarkEditorContext {
|
|
1225
|
-
readonly state: EditorState;
|
|
1226
|
-
readonly view: EditorView;
|
|
1227
|
-
readonly schema: {
|
|
1228
|
-
marks: Record<string, MarkType>;
|
|
1229
|
-
};
|
|
1230
|
-
readonly commands: Record<string, (...args: unknown[]) => boolean>;
|
|
1231
|
-
}
|
|
1232
|
-
/**
|
|
1233
|
-
* Context interface for Mark config methods.
|
|
1234
|
-
* Extends ExtensionContext with mark-specific properties.
|
|
1235
|
-
* This enables proper typing of `this.options`, `this.markType`, etc.
|
|
1046
|
+
* Main editor class
|
|
1236
1047
|
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1048
|
+
* Wraps ProseMirror's EditorView and EditorState with a cleaner API.
|
|
1049
|
+
*
|
|
1050
|
+
* @example
|
|
1051
|
+
* ```ts
|
|
1052
|
+
* import { Editor } from '@domternal/core';
|
|
1053
|
+
* import { Schema } from '@domternal/pm/model';
|
|
1054
|
+
*
|
|
1055
|
+
* const schema = new Schema({
|
|
1056
|
+
* nodes: { doc: { content: 'paragraph+' }, paragraph: { content: 'text*' }, text: {} }
|
|
1057
|
+
* });
|
|
1058
|
+
*
|
|
1059
|
+
* const editor = new Editor({
|
|
1060
|
+
* schema,
|
|
1061
|
+
* element: document.getElementById('editor'),
|
|
1062
|
+
* content: '<p>Hello world</p>',
|
|
1063
|
+
* });
|
|
1064
|
+
*
|
|
1065
|
+
* // Get content
|
|
1066
|
+
* const json = editor.getJSON();
|
|
1067
|
+
* const html = editor.getHTML();
|
|
1068
|
+
*
|
|
1069
|
+
* // Set content
|
|
1070
|
+
* editor.commands.setContent('<p>New content</p>');
|
|
1071
|
+
*
|
|
1072
|
+
* // Cleanup
|
|
1073
|
+
* editor.destroy();
|
|
1074
|
+
* ```
|
|
1251
1075
|
*/
|
|
1252
|
-
|
|
1076
|
+
declare class Editor extends EventEmitter<EditorEvents> {
|
|
1253
1077
|
/**
|
|
1254
|
-
*
|
|
1255
|
-
* @example 'strong', 'b', 'span.bold'
|
|
1078
|
+
* Editor configuration options
|
|
1256
1079
|
*/
|
|
1257
|
-
|
|
1080
|
+
private options;
|
|
1258
1081
|
/**
|
|
1259
|
-
*
|
|
1260
|
-
*
|
|
1261
|
-
* @example 'font-weight', 'font-weight=bold'
|
|
1082
|
+
* Manages extensions and schema
|
|
1083
|
+
* @internal Exposed for CommandManager, not for public use
|
|
1262
1084
|
*/
|
|
1263
|
-
|
|
1085
|
+
private _extensionManager;
|
|
1264
1086
|
/**
|
|
1265
|
-
*
|
|
1266
|
-
* @
|
|
1087
|
+
* Gets the extension manager
|
|
1088
|
+
* @internal For CommandManager use only
|
|
1267
1089
|
*/
|
|
1268
|
-
|
|
1090
|
+
get extensionManager(): ExtensionManager;
|
|
1269
1091
|
/**
|
|
1270
|
-
*
|
|
1271
|
-
* @default true
|
|
1092
|
+
* Manages commands
|
|
1272
1093
|
*/
|
|
1273
|
-
|
|
1094
|
+
private commandManager;
|
|
1274
1095
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
* Return null/undefined to skip this rule
|
|
1277
|
-
* Return false to explicitly not match
|
|
1278
|
-
*
|
|
1279
|
-
* For style rules, receives the style value as string
|
|
1096
|
+
* ProseMirror EditorView instance
|
|
1280
1097
|
*/
|
|
1281
|
-
|
|
1282
|
-
}
|
|
1283
|
-
/**
|
|
1284
|
-
* Props passed to renderHTML function for marks
|
|
1285
|
-
*/
|
|
1286
|
-
interface MarkRenderHTMLProps {
|
|
1098
|
+
view: EditorView;
|
|
1287
1099
|
/**
|
|
1288
|
-
*
|
|
1100
|
+
* Whether the editor has been destroyed
|
|
1289
1101
|
*/
|
|
1290
|
-
|
|
1102
|
+
private _isDestroyed;
|
|
1291
1103
|
/**
|
|
1292
|
-
*
|
|
1104
|
+
* Timer for autofocus (cleared on destroy to prevent memory leaks)
|
|
1293
1105
|
*/
|
|
1294
|
-
|
|
1295
|
-
}
|
|
1296
|
-
/**
|
|
1297
|
-
* Mark-specific configuration properties (schema-related)
|
|
1298
|
-
*/
|
|
1299
|
-
interface MarkSchemaProperties {
|
|
1106
|
+
private _autofocusTimer;
|
|
1300
1107
|
/**
|
|
1301
|
-
*
|
|
1302
|
-
* is at its end (or beginning for marks that open).
|
|
1303
|
-
*
|
|
1304
|
-
* When true, typing at the mark's boundary continues the mark.
|
|
1305
|
-
* When false, typing creates unmarked content.
|
|
1108
|
+
* Creates a new Editor instance
|
|
1306
1109
|
*
|
|
1307
|
-
* @
|
|
1110
|
+
* @param options - Editor configuration
|
|
1111
|
+
* @throws Error if running in SSR environment (no window)
|
|
1112
|
+
* @throws Error if schema is not provided
|
|
1308
1113
|
*/
|
|
1309
|
-
|
|
1114
|
+
constructor(options: EditorOptions);
|
|
1310
1115
|
/**
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
* - '_' excludes all marks
|
|
1314
|
-
* - Space-separated mark names exclude specific marks
|
|
1315
|
-
* - Empty string or undefined means no exclusions
|
|
1316
|
-
*
|
|
1317
|
-
* @example 'code' - excludes code mark
|
|
1318
|
-
* @example 'bold italic' - excludes bold and italic
|
|
1319
|
-
* @example '_' - excludes all other marks
|
|
1116
|
+
* Gets the current EditorState
|
|
1320
1117
|
*/
|
|
1321
|
-
|
|
1118
|
+
get state(): EditorState;
|
|
1322
1119
|
/**
|
|
1323
|
-
*
|
|
1324
|
-
* Used in node's marks property
|
|
1325
|
-
*
|
|
1326
|
-
* @example 'formatting', 'inline'
|
|
1120
|
+
* Gets the ProseMirror schema
|
|
1327
1121
|
*/
|
|
1328
|
-
|
|
1122
|
+
get schema(): Schema;
|
|
1329
1123
|
/**
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
* When true (default), the mark persists across inline nodes.
|
|
1333
|
-
* When false, the mark only applies within a single text node.
|
|
1334
|
-
*
|
|
1335
|
-
* @default true
|
|
1124
|
+
* Checks if the editor is editable
|
|
1336
1125
|
*/
|
|
1337
|
-
|
|
1126
|
+
get isEditable(): boolean;
|
|
1338
1127
|
/**
|
|
1339
|
-
*
|
|
1128
|
+
* Checks if the editor content is empty
|
|
1129
|
+
*/
|
|
1130
|
+
get isEmpty(): boolean;
|
|
1131
|
+
/**
|
|
1132
|
+
* Checks if the editor has focus
|
|
1133
|
+
*/
|
|
1134
|
+
get isFocused(): boolean;
|
|
1135
|
+
/**
|
|
1136
|
+
* Checks if the editor has been destroyed
|
|
1137
|
+
*/
|
|
1138
|
+
get isDestroyed(): boolean;
|
|
1139
|
+
/**
|
|
1140
|
+
* Gets single commands for immediate execution
|
|
1141
|
+
* @example editor.commands.focus('end')
|
|
1142
|
+
*/
|
|
1143
|
+
get commands(): SingleCommands;
|
|
1144
|
+
/**
|
|
1145
|
+
* Creates a command chain for batched execution
|
|
1146
|
+
* @example editor.chain().focus().insertText('Hello').run()
|
|
1147
|
+
*/
|
|
1148
|
+
chain(): ChainedCommands;
|
|
1149
|
+
/**
|
|
1150
|
+
* Checks if commands can be executed (dry-run)
|
|
1151
|
+
* @example if (editor.can().toggleBold()) { ... }
|
|
1152
|
+
*/
|
|
1153
|
+
can(): CanCommands;
|
|
1154
|
+
/**
|
|
1155
|
+
* Gets extension storage
|
|
1156
|
+
* Access via: editor.storage.extensionName.propertyName
|
|
1157
|
+
*/
|
|
1158
|
+
get storage(): Record<string, unknown>;
|
|
1159
|
+
/**
|
|
1160
|
+
* Toolbar items registered by all extensions.
|
|
1161
|
+
*/
|
|
1162
|
+
get toolbarItems(): ToolbarItem[];
|
|
1163
|
+
/**
|
|
1164
|
+
* Floating-menu items registered by all extensions, rendered as the
|
|
1165
|
+
* block-insert menu shown on empty paragraphs.
|
|
1166
|
+
*/
|
|
1167
|
+
get floatingMenuItems(): FloatingMenuItem[];
|
|
1168
|
+
/**
|
|
1169
|
+
* Checks if a node or mark is currently active
|
|
1340
1170
|
*
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
1171
|
+
* For toolbar button states - returns true if:
|
|
1172
|
+
* - For marks: the current selection has the mark applied
|
|
1173
|
+
* - For nodes: the cursor is inside that node type
|
|
1344
1174
|
*
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
* Link.configure({ isFormatting: true }) // make links clearable
|
|
1348
|
-
* ```
|
|
1175
|
+
* @param nameOrAttributes - Extension name, or object with name and attributes
|
|
1176
|
+
* @param attributes - Optional attributes to match (for node/mark specific states)
|
|
1349
1177
|
*
|
|
1350
|
-
* @
|
|
1178
|
+
* @example
|
|
1179
|
+
* editor.isActive('bold') // → true if bold mark is active
|
|
1180
|
+
* editor.isActive('heading', { level: 2 }) // → true if in h2
|
|
1181
|
+
* editor.isActive({ name: 'textAlign', attributes: { align: 'center' } })
|
|
1351
1182
|
*/
|
|
1352
|
-
|
|
1183
|
+
isActive(nameOrAttributes: string | {
|
|
1184
|
+
name: string;
|
|
1185
|
+
attributes?: Record<string, unknown>;
|
|
1186
|
+
}, attributes?: Record<string, unknown>): boolean;
|
|
1353
1187
|
/**
|
|
1354
|
-
*
|
|
1355
|
-
*
|
|
1188
|
+
* Gets attributes of the currently active node or mark
|
|
1189
|
+
*
|
|
1190
|
+
* Returns empty object if the node/mark is not found or not active.
|
|
1191
|
+
*
|
|
1192
|
+
* @param name - Extension name (node or mark)
|
|
1356
1193
|
*
|
|
1357
1194
|
* @example
|
|
1358
|
-
*
|
|
1359
|
-
*
|
|
1360
|
-
* color: { default: null },
|
|
1361
|
-
* };
|
|
1362
|
-
* }
|
|
1195
|
+
* editor.getAttributes('heading') // → { level: 2 }
|
|
1196
|
+
* editor.getAttributes('link') // → { href: 'https://...', target: '_blank' }
|
|
1363
1197
|
*/
|
|
1364
|
-
|
|
1198
|
+
getAttributes(name: string): Record<string, unknown>;
|
|
1365
1199
|
/**
|
|
1366
|
-
*
|
|
1367
|
-
*
|
|
1200
|
+
* Helper to match attributes
|
|
1201
|
+
* Returns true if target contains all key/value pairs from source
|
|
1202
|
+
*/
|
|
1203
|
+
private matchAttributes;
|
|
1204
|
+
/**
|
|
1205
|
+
* Gets the document content as JSON
|
|
1206
|
+
*/
|
|
1207
|
+
getJSON(): JSONContent;
|
|
1208
|
+
/**
|
|
1209
|
+
* Gets the document content as HTML string
|
|
1368
1210
|
*
|
|
1369
|
-
* @
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
* { tag: 'strong' },
|
|
1373
|
-
* { tag: 'b' },
|
|
1374
|
-
* { style: 'font-weight', getAttrs: (value) => /bold|[5-9]\d{2}/.test(value) && null },
|
|
1375
|
-
* ];
|
|
1376
|
-
* }
|
|
1211
|
+
* @param options - Optional settings
|
|
1212
|
+
* @param options.styled - When true (or an override object), applies inline CSS
|
|
1213
|
+
* styles so the HTML renders correctly outside the editor (email, CMS, etc.)
|
|
1377
1214
|
*/
|
|
1378
|
-
|
|
1215
|
+
getHTML(options?: {
|
|
1216
|
+
styled?: boolean | InlineStyleOverrides;
|
|
1217
|
+
}): string;
|
|
1379
1218
|
/**
|
|
1380
|
-
*
|
|
1381
|
-
* Returns DOMOutputSpec (tag, attributes, hole)
|
|
1219
|
+
* Gets the document content as plain text
|
|
1382
1220
|
*
|
|
1383
|
-
*
|
|
1221
|
+
* @param options - Options for text extraction
|
|
1222
|
+
* @param options.blockSeparator - String to insert between blocks (default: '\n\n')
|
|
1223
|
+
*/
|
|
1224
|
+
getText(options?: {
|
|
1225
|
+
blockSeparator?: string;
|
|
1226
|
+
}): string;
|
|
1227
|
+
/**
|
|
1228
|
+
* Executes a command with proper CommandProps
|
|
1229
|
+
* @internal
|
|
1230
|
+
*/
|
|
1231
|
+
private runCommand;
|
|
1232
|
+
/**
|
|
1233
|
+
* Sets the editor content
|
|
1384
1234
|
*
|
|
1385
|
-
* @
|
|
1386
|
-
*
|
|
1387
|
-
*
|
|
1388
|
-
* }
|
|
1235
|
+
* @param content - JSON or HTML content
|
|
1236
|
+
* @param emitUpdate - Whether to emit update event (default: true)
|
|
1237
|
+
* @returns true if content was set successfully, false if content was invalid
|
|
1389
1238
|
*/
|
|
1390
|
-
|
|
1239
|
+
setContent(content: Content, emitUpdate?: boolean): boolean;
|
|
1240
|
+
/**
|
|
1241
|
+
* Clears the editor content
|
|
1242
|
+
*
|
|
1243
|
+
* @param emitUpdate - Whether to emit update event (default: true)
|
|
1244
|
+
* @returns true if content was cleared successfully
|
|
1245
|
+
*/
|
|
1246
|
+
clearContent(emitUpdate?: boolean): boolean;
|
|
1247
|
+
/**
|
|
1248
|
+
* Sets whether the editor is editable
|
|
1249
|
+
*
|
|
1250
|
+
* @param editable - Whether the editor should be editable
|
|
1251
|
+
*/
|
|
1252
|
+
setEditable(editable: boolean): this;
|
|
1253
|
+
/**
|
|
1254
|
+
* Focuses the editor
|
|
1255
|
+
*
|
|
1256
|
+
* @param position - Where to place cursor (default: null = just focus)
|
|
1257
|
+
*/
|
|
1258
|
+
focus(position?: FocusPosition): this;
|
|
1259
|
+
/**
|
|
1260
|
+
* Removes focus from the editor
|
|
1261
|
+
*/
|
|
1262
|
+
blur(): this;
|
|
1263
|
+
/**
|
|
1264
|
+
* Registers a ProseMirror plugin dynamically at runtime, after the editor
|
|
1265
|
+
* has been created. Safe to call repeatedly with the same plugin key.
|
|
1266
|
+
*/
|
|
1267
|
+
registerPlugin(plugin: Plugin): void;
|
|
1268
|
+
/**
|
|
1269
|
+
* Unregisters a ProseMirror plugin by its PluginKey.
|
|
1270
|
+
* Uses PluginKey.get() to identify the plugin to remove.
|
|
1271
|
+
*/
|
|
1272
|
+
unregisterPlugin(key: PluginKey): void;
|
|
1273
|
+
/**
|
|
1274
|
+
* Destroys the editor and cleans up resources
|
|
1275
|
+
*
|
|
1276
|
+
* After calling destroy(), the editor instance should not be used.
|
|
1277
|
+
*/
|
|
1278
|
+
destroy(): void;
|
|
1279
|
+
/**
|
|
1280
|
+
* Builds a clipboardSerializer that applies a transform function to HTML on copy/cut.
|
|
1281
|
+
*/
|
|
1282
|
+
private buildClipboardSerializer;
|
|
1283
|
+
/**
|
|
1284
|
+
* Creates the editor instance
|
|
1285
|
+
*/
|
|
1286
|
+
private createEditor;
|
|
1287
|
+
/**
|
|
1288
|
+
* Handles ProseMirror transactions
|
|
1289
|
+
*/
|
|
1290
|
+
private dispatchTransaction;
|
|
1291
|
+
/**
|
|
1292
|
+
* Emit method - needed for CommandManager interface
|
|
1293
|
+
*/
|
|
1294
|
+
emit<E extends keyof EditorEvents>(event: E, ...args: EditorEvents[E] extends undefined ? [] : [EditorEvents[E]]): this;
|
|
1391
1295
|
}
|
|
1296
|
+
|
|
1392
1297
|
/**
|
|
1393
|
-
*
|
|
1394
|
-
* Combines ExtensionConfigBase with mark-specific schema properties.
|
|
1395
|
-
* Uses ThisType<MarkContext> to provide proper typing for `this` in config methods.
|
|
1298
|
+
* FloatingMenu configuration types
|
|
1396
1299
|
*
|
|
1397
|
-
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
* @example
|
|
1401
|
-
* const Bold = Mark.create({
|
|
1402
|
-
* name: 'bold',
|
|
1403
|
-
* parseHTML() {
|
|
1404
|
-
* // `this` is properly typed here!
|
|
1405
|
-
* return [{ tag: 'strong' }, { tag: 'b' }];
|
|
1406
|
-
* },
|
|
1407
|
-
* renderHTML({ HTMLAttributes }) {
|
|
1408
|
-
* return ['strong', HTMLAttributes, 0];
|
|
1409
|
-
* },
|
|
1410
|
-
* });
|
|
1300
|
+
* Types for block-insert items contributed by extensions via the
|
|
1301
|
+
* `addFloatingMenuItems()` hook. Framework wrappers read these items
|
|
1302
|
+
* and render a WAI-ARIA menu shown on empty paragraphs.
|
|
1411
1303
|
*/
|
|
1412
|
-
type MarkConfig<Options = unknown, Storage = unknown> = ExtensionConfigBase<Options, Storage> & MarkSchemaProperties & ThisType<MarkContext<Options, Storage>>;
|
|
1413
1304
|
|
|
1414
1305
|
/**
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1417
|
-
*
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
* Generic, type-safe event emitter
|
|
1306
|
+
* A single entry in the floating menu.
|
|
1307
|
+
*
|
|
1308
|
+
* Unlike `ToolbarButton`, floating-menu items represent one-shot insert
|
|
1309
|
+
* actions (no toggle / active state), carry an optional `description` for
|
|
1310
|
+
* Notion-style two-line rendering, and expose `keywords` for future
|
|
1311
|
+
* slash-command filtering.
|
|
1422
1312
|
*
|
|
1423
1313
|
* @example
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1426
|
-
*
|
|
1427
|
-
*
|
|
1314
|
+
* {
|
|
1315
|
+
* name: 'heading-1',
|
|
1316
|
+
* label: 'Heading 1',
|
|
1317
|
+
* description: 'Big section heading',
|
|
1318
|
+
* icon: 'textHOne',
|
|
1319
|
+
* group: 'Basic',
|
|
1320
|
+
* shortcut: '# ',
|
|
1321
|
+
* command: 'toggleHeading',
|
|
1322
|
+
* commandArgs: [{ level: 1 }],
|
|
1428
1323
|
* }
|
|
1429
|
-
*
|
|
1430
|
-
* const emitter = new EventEmitter<MyEvents>();
|
|
1431
|
-
* emitter.on('update', ({ value }) => console.log(value));
|
|
1432
|
-
* emitter.on('destroy', () => console.log('destroyed'));
|
|
1433
|
-
* ```
|
|
1434
1324
|
*/
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
* Remove an event listener, or all listeners for an event if no callback specified
|
|
1445
|
-
*/
|
|
1446
|
-
off<E extends keyof Events>(event: E, callback?: EventCallback<Events[E]>): this;
|
|
1447
|
-
/**
|
|
1448
|
-
* Emit an event to all registered listeners
|
|
1449
|
-
* Uses .call(this) to preserve context for callbacks
|
|
1450
|
-
*/
|
|
1451
|
-
emit<E extends keyof Events>(event: E, ...args: Events[E] extends undefined ? [] : [Events[E]]): this;
|
|
1325
|
+
interface FloatingMenuItem {
|
|
1326
|
+
/** Unique identifier (used as React key, aria id, and dedup key when merging). */
|
|
1327
|
+
name: string;
|
|
1328
|
+
/** Primary label shown to the user. */
|
|
1329
|
+
label: string;
|
|
1330
|
+
/** Optional secondary line shown under the label. */
|
|
1331
|
+
description?: string;
|
|
1332
|
+
/** Icon key resolved against the editor's IconSet. Optional. */
|
|
1333
|
+
icon?: string;
|
|
1452
1334
|
/**
|
|
1453
|
-
*
|
|
1335
|
+
* Group heading. Items with the same group render under a shared
|
|
1336
|
+
* `<div role="group" aria-label={group}>` section.
|
|
1337
|
+
* @default '' (no group heading)
|
|
1454
1338
|
*/
|
|
1455
|
-
|
|
1339
|
+
group?: string;
|
|
1340
|
+
/** Sort order within group (higher first). @default 100 */
|
|
1341
|
+
priority?: number;
|
|
1342
|
+
/** Keywords for future slash-command fuzzy filtering. */
|
|
1343
|
+
keywords?: string[];
|
|
1344
|
+
/** Visible keyboard-shortcut hint (e.g. `# `, `Mod-Alt-1`). */
|
|
1345
|
+
shortcut?: string;
|
|
1456
1346
|
/**
|
|
1457
|
-
*
|
|
1347
|
+
* Command to execute on activation.
|
|
1348
|
+
*
|
|
1349
|
+
* - String: key of `editor.commands`; invoked with `commandArgs`.
|
|
1350
|
+
* - Function: arbitrary callback receiving the editor. Use when the
|
|
1351
|
+
* action is not a registered command (e.g. opening a popover).
|
|
1458
1352
|
*/
|
|
1459
|
-
|
|
1353
|
+
command: string | ((editor: Editor) => void);
|
|
1354
|
+
/** Arguments for string commands. Ignored when `command` is a function. */
|
|
1355
|
+
commandArgs?: unknown[];
|
|
1460
1356
|
/**
|
|
1461
|
-
*
|
|
1357
|
+
* Custom disabled predicate. When omitted, the controller dry-runs the
|
|
1358
|
+
* command via `editor.can()` (string commands only) to detect availability.
|
|
1462
1359
|
*/
|
|
1463
|
-
|
|
1360
|
+
isDisabled?: (editor: Editor) => boolean;
|
|
1464
1361
|
/**
|
|
1465
|
-
*
|
|
1362
|
+
* Node-type names that, when present as ancestors of the cursor, cause
|
|
1363
|
+
* the slash menu to hide this item. Useful for list/task-list entries:
|
|
1364
|
+
* e.g. `['bulletList']` removes "Bulleted list" from the menu while the
|
|
1365
|
+
* cursor is already inside a bullet list, so picking it doesn't lift
|
|
1366
|
+
* the user out of the list unexpectedly.
|
|
1466
1367
|
*/
|
|
1467
|
-
|
|
1368
|
+
hideWhenInside?: string[];
|
|
1468
1369
|
}
|
|
1469
|
-
|
|
1470
1370
|
/**
|
|
1471
|
-
*
|
|
1371
|
+
* Override form accepted by `FloatingMenu.configure({ items })`.
|
|
1472
1372
|
*
|
|
1473
|
-
*
|
|
1474
|
-
* -
|
|
1475
|
-
* - Schema building from Node/Mark extensions
|
|
1476
|
-
* - Plugin collection from all extensions
|
|
1477
|
-
* - Extension storage management
|
|
1478
|
-
* - Conflict detection (AD-7)
|
|
1373
|
+
* - Array: replaces the collected defaults entirely.
|
|
1374
|
+
* - Function: transforms the defaults (filter / reorder / extend).
|
|
1479
1375
|
*/
|
|
1376
|
+
type FloatingMenuItemsOverride = FloatingMenuItem[] | ((defaults: FloatingMenuItem[], editor: Editor) => FloatingMenuItem[]);
|
|
1480
1377
|
|
|
1481
1378
|
/**
|
|
1482
|
-
*
|
|
1379
|
+
* Extension configuration types
|
|
1380
|
+
*
|
|
1381
|
+
* These types define the configuration object passed to Extension.create(),
|
|
1382
|
+
* Node.create(), and Mark.create() factory methods.
|
|
1483
1383
|
*/
|
|
1484
|
-
|
|
1485
|
-
error: Error;
|
|
1486
|
-
context: string;
|
|
1487
|
-
}
|
|
1384
|
+
|
|
1488
1385
|
/**
|
|
1489
|
-
* Editor
|
|
1490
|
-
* Forward declaration to avoid circular dependency
|
|
1386
|
+
* Editor instance type (forward declaration)
|
|
1491
1387
|
*/
|
|
1492
|
-
interface
|
|
1493
|
-
readonly
|
|
1494
|
-
|
|
1388
|
+
interface ExtensionEditor {
|
|
1389
|
+
readonly state: EditorState;
|
|
1390
|
+
readonly view: EditorView;
|
|
1391
|
+
readonly schema: unknown;
|
|
1392
|
+
readonly commands: SingleCommands;
|
|
1495
1393
|
}
|
|
1496
1394
|
/**
|
|
1497
|
-
*
|
|
1498
|
-
* Accessible via `(constructor as any).__domternalContext`.
|
|
1395
|
+
* Any extension type (forward declaration)
|
|
1499
1396
|
*/
|
|
1500
|
-
interface
|
|
1501
|
-
|
|
1502
|
-
extension
|
|
1503
|
-
name: string;
|
|
1504
|
-
options: Record<string, unknown>;
|
|
1505
|
-
};
|
|
1397
|
+
interface AnyExtensionConfig {
|
|
1398
|
+
name: string;
|
|
1399
|
+
type?: 'extension' | 'node' | 'mark';
|
|
1506
1400
|
}
|
|
1507
1401
|
/**
|
|
1508
|
-
*
|
|
1402
|
+
* Global attribute specification for injecting attributes into multiple node/mark types.
|
|
1403
|
+
* Used by extensions like TextAlign to add alignment to heading, paragraph, etc.
|
|
1509
1404
|
*/
|
|
1510
|
-
interface
|
|
1511
|
-
/**
|
|
1512
|
-
* Extensions to process
|
|
1513
|
-
* If provided, schema is built from extensions
|
|
1514
|
-
*/
|
|
1515
|
-
extensions?: AnyExtension[] | undefined;
|
|
1516
|
-
/**
|
|
1517
|
-
* Direct schema (backward compatibility with Step 1.3)
|
|
1518
|
-
* If provided, extensions are ignored for schema building
|
|
1519
|
-
*/
|
|
1520
|
-
schema?: Schema | undefined;
|
|
1521
|
-
}
|
|
1522
|
-
declare class ExtensionManager {
|
|
1405
|
+
interface GlobalAttributeSpec {
|
|
1523
1406
|
/**
|
|
1524
|
-
*
|
|
1407
|
+
* Default value for the attribute.
|
|
1525
1408
|
*/
|
|
1526
|
-
|
|
1409
|
+
default?: unknown;
|
|
1527
1410
|
/**
|
|
1528
|
-
*
|
|
1411
|
+
* Parse attribute value from HTML element.
|
|
1412
|
+
* @param element - The DOM element to parse from
|
|
1413
|
+
* @returns The parsed attribute value
|
|
1529
1414
|
*/
|
|
1530
|
-
|
|
1415
|
+
parseHTML?: (element: HTMLElement) => unknown;
|
|
1531
1416
|
/**
|
|
1532
|
-
*
|
|
1417
|
+
* Render attribute value to HTML attributes.
|
|
1418
|
+
* @param attributes - The node/mark attributes
|
|
1419
|
+
* @returns Object of HTML attributes to set, or null/empty to skip
|
|
1533
1420
|
*/
|
|
1534
|
-
|
|
1421
|
+
renderHTML?: (attributes: Record<string, unknown>) => Record<string, string> | null;
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Global attributes definition for injecting into node/mark types.
|
|
1425
|
+
*/
|
|
1426
|
+
interface GlobalAttributes {
|
|
1535
1427
|
/**
|
|
1536
|
-
*
|
|
1428
|
+
* Node or mark type names to add these attributes to.
|
|
1429
|
+
* @example ['heading', 'paragraph']
|
|
1537
1430
|
*/
|
|
1538
|
-
|
|
1431
|
+
types: string[];
|
|
1539
1432
|
/**
|
|
1540
|
-
*
|
|
1433
|
+
* Attribute specifications to add.
|
|
1434
|
+
* @example { textAlign: { default: 'left', parseHTML: (el) => el.style.textAlign } }
|
|
1541
1435
|
*/
|
|
1542
|
-
|
|
1436
|
+
attributes: Record<string, GlobalAttributeSpec>;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Context interface that describes what `this` will be in config methods.
|
|
1440
|
+
* This enables proper typing of `this.options`, `this.editor`, etc.
|
|
1441
|
+
* without creating circular dependencies.
|
|
1442
|
+
*
|
|
1443
|
+
* @typeParam Options - Extension options type
|
|
1444
|
+
* @typeParam Storage - Extension storage type
|
|
1445
|
+
*/
|
|
1446
|
+
interface ExtensionContext<Options = unknown, Storage = unknown> {
|
|
1447
|
+
/** Extension type identifier */
|
|
1448
|
+
readonly type: 'extension' | 'node' | 'mark';
|
|
1449
|
+
/** Unique extension name */
|
|
1450
|
+
readonly name: string;
|
|
1451
|
+
/** Extension options (immutable after creation) */
|
|
1452
|
+
readonly options: Options;
|
|
1453
|
+
/** Extension storage (mutable state) */
|
|
1454
|
+
storage: Storage;
|
|
1455
|
+
/** Editor instance (null until bound by ExtensionManager) */
|
|
1456
|
+
editor: ExtensionEditor | null;
|
|
1543
1457
|
/**
|
|
1544
|
-
*
|
|
1458
|
+
* Reference to the parent config method when using extend().
|
|
1459
|
+
* Available only inside overridden config methods.
|
|
1460
|
+
* Use `this.parent?.()` to call the parent's version of the current method.
|
|
1545
1461
|
*/
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1462
|
+
parent?: ((...args: unknown[]) => unknown) | undefined;
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Base configuration properties for all extension types.
|
|
1466
|
+
* This interface contains just the properties without ThisType,
|
|
1467
|
+
* allowing Node and Mark configs to use their own context types.
|
|
1468
|
+
*
|
|
1469
|
+
* @typeParam Options - Extension options type
|
|
1470
|
+
* @typeParam Storage - Extension storage type
|
|
1471
|
+
*/
|
|
1472
|
+
interface ExtensionConfigBase<Options = unknown, Storage = unknown> {
|
|
1551
1473
|
/**
|
|
1552
|
-
*
|
|
1474
|
+
* Unique extension name
|
|
1475
|
+
* Used for identification, storage access, and error messages
|
|
1553
1476
|
*/
|
|
1554
|
-
|
|
1477
|
+
name: string;
|
|
1555
1478
|
/**
|
|
1556
|
-
*
|
|
1479
|
+
* Extension priority (higher = loaded first)
|
|
1480
|
+
*
|
|
1481
|
+
* Reserved ranges:
|
|
1482
|
+
* - 900-1000: Core nodes (Document, Text, Paragraph)
|
|
1483
|
+
* - 500-899: Standard extensions (Heading, Bold, etc.)
|
|
1484
|
+
* - 100-499: Default range for user extensions
|
|
1485
|
+
* - 0-99: Low priority extensions (run after everything)
|
|
1486
|
+
*
|
|
1487
|
+
* @default 100
|
|
1557
1488
|
*/
|
|
1558
|
-
|
|
1489
|
+
priority?: number;
|
|
1559
1490
|
/**
|
|
1560
|
-
*
|
|
1491
|
+
* Required extensions that must be present
|
|
1492
|
+
* ExtensionManager throws if any dependency is missing
|
|
1561
1493
|
*
|
|
1562
|
-
* @
|
|
1563
|
-
*
|
|
1494
|
+
* @example
|
|
1495
|
+
* dependencies: ['bulletList', 'orderedList']
|
|
1564
1496
|
*/
|
|
1565
|
-
|
|
1497
|
+
dependencies?: string[];
|
|
1566
1498
|
/**
|
|
1567
|
-
*
|
|
1499
|
+
* Default options for this extension
|
|
1500
|
+
* Called during extension creation with `this` bound to the extension
|
|
1568
1501
|
*/
|
|
1569
|
-
|
|
1502
|
+
addOptions?: () => Options;
|
|
1570
1503
|
/**
|
|
1571
|
-
*
|
|
1504
|
+
* Initial storage state for this extension
|
|
1505
|
+
* Storage is mutable and accessible via editor.storage[extensionName]
|
|
1572
1506
|
*/
|
|
1573
|
-
|
|
1507
|
+
addStorage?: () => Storage;
|
|
1574
1508
|
/**
|
|
1575
|
-
*
|
|
1509
|
+
* Commands this extension provides
|
|
1510
|
+
* Commands are accessible via editor.commands.commandName()
|
|
1511
|
+
*
|
|
1512
|
+
* @example
|
|
1513
|
+
* addCommands() {
|
|
1514
|
+
* return {
|
|
1515
|
+
* toggleBold: () => ({ commands }) => commands.toggleMark('bold'),
|
|
1516
|
+
* };
|
|
1517
|
+
* }
|
|
1576
1518
|
*/
|
|
1577
|
-
|
|
1519
|
+
addCommands?: () => Record<string, (...args: never[]) => Command>;
|
|
1578
1520
|
/**
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1521
|
+
* Keyboard shortcuts for this extension
|
|
1522
|
+
* Keys are shortcut strings (e.g., 'Mod-b'), values are handler functions
|
|
1523
|
+
*
|
|
1524
|
+
* @example
|
|
1525
|
+
* addKeyboardShortcuts() {
|
|
1526
|
+
* return {
|
|
1527
|
+
* 'Mod-b': () => this.editor.commands.toggleBold(),
|
|
1528
|
+
* };
|
|
1529
|
+
* }
|
|
1581
1530
|
*/
|
|
1582
|
-
|
|
1531
|
+
addKeyboardShortcuts?: () => Record<string, KeyboardShortcutCommand>;
|
|
1583
1532
|
/**
|
|
1584
|
-
*
|
|
1533
|
+
* Input rules (markdown-style shortcuts)
|
|
1534
|
+
* Triggered when user types matching patterns
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* addInputRules() {
|
|
1538
|
+
* return [
|
|
1539
|
+
* textblockTypeInputRule(/^## $/, this.type),
|
|
1540
|
+
* ];
|
|
1541
|
+
* }
|
|
1585
1542
|
*/
|
|
1586
|
-
|
|
1543
|
+
addInputRules?: () => InputRule[];
|
|
1587
1544
|
/**
|
|
1588
|
-
*
|
|
1589
|
-
* Cached after first call
|
|
1545
|
+
* ProseMirror plugins for this extension
|
|
1590
1546
|
*/
|
|
1591
|
-
|
|
1547
|
+
addProseMirrorPlugins?: () => Plugin[];
|
|
1592
1548
|
/**
|
|
1593
|
-
*
|
|
1549
|
+
* Nested extensions (for extension bundles like StarterKit)
|
|
1550
|
+
* These extensions are flattened and processed like top-level extensions
|
|
1594
1551
|
*/
|
|
1595
|
-
|
|
1552
|
+
addExtensions?: () => AnyExtensionConfig[];
|
|
1596
1553
|
/**
|
|
1597
|
-
*
|
|
1598
|
-
*
|
|
1554
|
+
* Global attributes to add to multiple node/mark types.
|
|
1555
|
+
* Useful for extensions like TextAlign that need to add attributes
|
|
1556
|
+
* to several nodes (heading, paragraph, etc.) without modifying each.
|
|
1557
|
+
*
|
|
1558
|
+
* @example
|
|
1559
|
+
* addGlobalAttributes() {
|
|
1560
|
+
* return [{
|
|
1561
|
+
* types: ['heading', 'paragraph'],
|
|
1562
|
+
* attributes: {
|
|
1563
|
+
* textAlign: {
|
|
1564
|
+
* default: 'left',
|
|
1565
|
+
* parseHTML: (element) => element.style.textAlign || 'left',
|
|
1566
|
+
* renderHTML: (attrs) => attrs.textAlign !== 'left'
|
|
1567
|
+
* ? { style: `text-align: ${attrs.textAlign}` }
|
|
1568
|
+
* : null,
|
|
1569
|
+
* },
|
|
1570
|
+
* },
|
|
1571
|
+
* }];
|
|
1572
|
+
* }
|
|
1599
1573
|
*/
|
|
1600
|
-
|
|
1574
|
+
addGlobalAttributes?: () => GlobalAttributes[];
|
|
1601
1575
|
/**
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1576
|
+
* Toolbar items this extension contributes.
|
|
1577
|
+
* Framework toolbar components read these to auto-generate buttons.
|
|
1578
|
+
*
|
|
1579
|
+
* @example
|
|
1580
|
+
* addToolbarItems() {
|
|
1581
|
+
* return [{
|
|
1582
|
+
* type: 'button',
|
|
1583
|
+
* name: 'bold',
|
|
1584
|
+
* command: 'toggleBold',
|
|
1585
|
+
* isActive: 'bold',
|
|
1586
|
+
* icon: 'textB',
|
|
1587
|
+
* label: 'Bold',
|
|
1588
|
+
* shortcut: 'Mod-b',
|
|
1589
|
+
* group: 'format',
|
|
1590
|
+
* }];
|
|
1591
|
+
* }
|
|
1604
1592
|
*/
|
|
1605
|
-
|
|
1593
|
+
addToolbarItems?: () => ToolbarItem[];
|
|
1606
1594
|
/**
|
|
1607
|
-
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1595
|
+
* Floating-menu items this extension contributes.
|
|
1596
|
+
* Block-insert menu shown on empty paragraphs aggregates these items
|
|
1597
|
+
* across all extensions. Framework wrappers render them as a WAI-ARIA
|
|
1598
|
+
* menu with groups, arrow-key navigation, and Enter to execute.
|
|
1599
|
+
*
|
|
1600
|
+
* @example
|
|
1601
|
+
* addFloatingMenuItems() {
|
|
1602
|
+
* return [{
|
|
1603
|
+
* name: 'heading-1',
|
|
1604
|
+
* label: 'Heading 1',
|
|
1605
|
+
* description: 'Big section heading',
|
|
1606
|
+
* icon: 'textHOne',
|
|
1607
|
+
* group: 'Basic',
|
|
1608
|
+
* command: 'toggleHeading',
|
|
1609
|
+
* commandArgs: [{ level: 1 }],
|
|
1610
|
+
* }];
|
|
1611
|
+
* }
|
|
1610
1612
|
*/
|
|
1611
|
-
|
|
1613
|
+
addFloatingMenuItems?: () => FloatingMenuItem[];
|
|
1612
1614
|
/**
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
+
* Called before editor is created
|
|
1616
|
+
* Can be used to modify editor options
|
|
1615
1617
|
*/
|
|
1616
|
-
|
|
1618
|
+
onBeforeCreate?: () => void;
|
|
1617
1619
|
/**
|
|
1618
|
-
*
|
|
1619
|
-
* @throws Error if duplicate names found
|
|
1620
|
+
* Called when editor is fully initialized and ready
|
|
1620
1621
|
*/
|
|
1621
|
-
|
|
1622
|
+
onCreate?: () => void;
|
|
1622
1623
|
/**
|
|
1623
|
-
*
|
|
1624
|
-
* @throws Error if required dependency is missing
|
|
1624
|
+
* Called when document content changes
|
|
1625
1625
|
*/
|
|
1626
|
-
|
|
1626
|
+
onUpdate?: () => void;
|
|
1627
1627
|
/**
|
|
1628
|
-
*
|
|
1628
|
+
* Called when selection changes (without content change)
|
|
1629
1629
|
*/
|
|
1630
|
-
|
|
1630
|
+
onSelectionUpdate?: () => void;
|
|
1631
1631
|
/**
|
|
1632
|
-
*
|
|
1633
|
-
*
|
|
1632
|
+
* Called on every transaction
|
|
1633
|
+
* Can be used to intercept or modify transactions
|
|
1634
1634
|
*/
|
|
1635
|
-
|
|
1635
|
+
onTransaction?: (props: {
|
|
1636
|
+
transaction: Transaction;
|
|
1637
|
+
}) => void;
|
|
1636
1638
|
/**
|
|
1637
|
-
*
|
|
1638
|
-
* Merges extra attrs into spec.attrs, wraps parseDOM getAttrs to parse
|
|
1639
|
-
* global attributes from DOM elements, and wraps toDOM to inject rendered
|
|
1640
|
-
* global HTML attributes into the output.
|
|
1639
|
+
* Called when editor receives focus
|
|
1641
1640
|
*/
|
|
1642
|
-
|
|
1641
|
+
onFocus?: (props: {
|
|
1642
|
+
event: FocusEvent;
|
|
1643
|
+
}) => void;
|
|
1643
1644
|
/**
|
|
1644
|
-
*
|
|
1645
|
+
* Called when editor loses focus
|
|
1645
1646
|
*/
|
|
1646
|
-
|
|
1647
|
+
onBlur?: (props: {
|
|
1648
|
+
event: FocusEvent;
|
|
1649
|
+
}) => void;
|
|
1647
1650
|
/**
|
|
1648
|
-
*
|
|
1651
|
+
* Called when editor is being destroyed
|
|
1652
|
+
* Use for cleanup (remove event listeners, etc.)
|
|
1649
1653
|
*/
|
|
1650
|
-
|
|
1654
|
+
onDestroy?: () => void;
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Full configuration type for Extension.create()
|
|
1658
|
+
* Combines base properties with ThisType for proper `this` typing.
|
|
1659
|
+
*
|
|
1660
|
+
* @typeParam Options - Extension options type
|
|
1661
|
+
* @typeParam Storage - Extension storage type
|
|
1662
|
+
*/
|
|
1663
|
+
type ExtensionConfig<Options = unknown, Storage = unknown> = ExtensionConfigBase<Options, Storage> & ThisType<ExtensionContext<Options, Storage>>;
|
|
1664
|
+
|
|
1665
|
+
/**
|
|
1666
|
+
* Attribute specification for Node and Mark extensions
|
|
1667
|
+
*
|
|
1668
|
+
* Used by addAttributes() to define node/mark attributes
|
|
1669
|
+
* with parsing, rendering, and validation rules.
|
|
1670
|
+
*
|
|
1671
|
+
* @example
|
|
1672
|
+
* addAttributes() {
|
|
1673
|
+
* return {
|
|
1674
|
+
* level: {
|
|
1675
|
+
* default: 1,
|
|
1676
|
+
* parseHTML: (element) => parseInt(element.tagName.charAt(1), 10),
|
|
1677
|
+
* renderHTML: (attributes) => ({ 'data-level': attributes.level }),
|
|
1678
|
+
* },
|
|
1679
|
+
* };
|
|
1680
|
+
* }
|
|
1681
|
+
*/
|
|
1682
|
+
/**
|
|
1683
|
+
* Specification for a single attribute
|
|
1684
|
+
*/
|
|
1685
|
+
interface AttributeSpec {
|
|
1651
1686
|
/**
|
|
1652
|
-
*
|
|
1687
|
+
* Default value for the attribute
|
|
1688
|
+
* Used when the attribute is not explicitly set
|
|
1653
1689
|
*/
|
|
1654
|
-
|
|
1690
|
+
default?: unknown;
|
|
1655
1691
|
/**
|
|
1656
|
-
*
|
|
1657
|
-
*
|
|
1658
|
-
*
|
|
1659
|
-
* Note: Extensions should return PM-compatible commands from addKeyboardShortcuts()
|
|
1692
|
+
* Whether this attribute is rendered to the DOM
|
|
1693
|
+
* @default true
|
|
1660
1694
|
*/
|
|
1661
|
-
|
|
1695
|
+
rendered?: boolean;
|
|
1662
1696
|
/**
|
|
1663
|
-
*
|
|
1697
|
+
* Keep this attribute when splitting the node
|
|
1698
|
+
* For example, heading level should be kept when pressing Enter
|
|
1699
|
+
* @default true
|
|
1664
1700
|
*/
|
|
1665
|
-
|
|
1701
|
+
keepOnSplit?: boolean;
|
|
1666
1702
|
/**
|
|
1667
|
-
*
|
|
1703
|
+
* Validate attribute value (ProseMirror 1.22.0+).
|
|
1704
|
+
* When a string, a `|`-separated list of primitive types
|
|
1705
|
+
* (`"number"`, `"string"`, `"boolean"`, `"null"`, `"undefined"`).
|
|
1706
|
+
* When a function, it should throw if the value is invalid.
|
|
1668
1707
|
*
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1671
|
-
*
|
|
1672
|
-
|
|
1673
|
-
private collectCommands;
|
|
1674
|
-
/**
|
|
1675
|
-
* Collects toolbar items from all extensions
|
|
1708
|
+
* @example
|
|
1709
|
+
* validate: 'number'
|
|
1710
|
+
* validate: 'string|null'
|
|
1711
|
+
* validate: (value) => { if (typeof value !== 'number') throw new Error('expected number'); }
|
|
1676
1712
|
*/
|
|
1677
|
-
|
|
1713
|
+
validate?: string | ((value: unknown) => void);
|
|
1678
1714
|
/**
|
|
1679
|
-
*
|
|
1680
|
-
*
|
|
1715
|
+
* Parse attribute value from HTML element
|
|
1716
|
+
* Called during HTML parsing to extract attribute value
|
|
1681
1717
|
*
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
/**
|
|
1688
|
-
* Validates that the schema has required nodes
|
|
1689
|
-
* @throws Error if schema is missing 'doc' or 'text' nodes
|
|
1690
|
-
*/
|
|
1691
|
-
validateSchema(): void;
|
|
1692
|
-
/**
|
|
1693
|
-
* Cleans up the extension manager
|
|
1694
|
-
* Calls onDestroy on all extensions and clears all caches
|
|
1718
|
+
* @param element - The HTML element being parsed
|
|
1719
|
+
* @returns The attribute value
|
|
1720
|
+
*
|
|
1721
|
+
* @example
|
|
1722
|
+
* parseHTML: (element) => element.getAttribute('data-level')
|
|
1695
1723
|
*/
|
|
1696
|
-
|
|
1724
|
+
parseHTML?: (element: HTMLElement) => unknown;
|
|
1697
1725
|
/**
|
|
1698
|
-
*
|
|
1699
|
-
*
|
|
1726
|
+
* Render attribute to HTML attributes object
|
|
1727
|
+
* Called during HTML serialization
|
|
1700
1728
|
*
|
|
1701
|
-
*
|
|
1729
|
+
* @param attributes - All attributes of the node/mark
|
|
1730
|
+
* @returns HTML attributes object or null to skip
|
|
1702
1731
|
*
|
|
1703
|
-
* @
|
|
1704
|
-
*
|
|
1705
|
-
* @returns The function result, or undefined if an error occurred
|
|
1706
|
-
*/
|
|
1707
|
-
safeCall<T>(fn: () => T, context: string): T | undefined;
|
|
1708
|
-
/**
|
|
1709
|
-
* Calls onBeforeCreate on all extensions
|
|
1732
|
+
* @example
|
|
1733
|
+
* renderHTML: (attributes) => ({ 'data-level': attributes.level })
|
|
1710
1734
|
*/
|
|
1711
|
-
|
|
1735
|
+
renderHTML?: (attributes: Record<string, unknown>) => Record<string, string | number | boolean | null | undefined> | null;
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Collection of attribute specifications
|
|
1739
|
+
* Keyed by attribute name
|
|
1740
|
+
*/
|
|
1741
|
+
type AttributeSpecs = Record<string, AttributeSpec>;
|
|
1742
|
+
|
|
1743
|
+
/**
|
|
1744
|
+
* Node configuration types
|
|
1745
|
+
*
|
|
1746
|
+
* These types define the configuration object passed to Node.create()
|
|
1747
|
+
* for creating ProseMirror node extensions.
|
|
1748
|
+
*/
|
|
1749
|
+
|
|
1750
|
+
/**
|
|
1751
|
+
* Editor interface for Node context
|
|
1752
|
+
* Includes schema with nodes for NodeType getter
|
|
1753
|
+
*/
|
|
1754
|
+
interface NodeEditorContext {
|
|
1755
|
+
readonly state: EditorState;
|
|
1756
|
+
readonly view: EditorView;
|
|
1757
|
+
readonly schema: {
|
|
1758
|
+
nodes: Record<string, NodeType>;
|
|
1759
|
+
};
|
|
1760
|
+
readonly commands: Record<string, (...args: unknown[]) => boolean>;
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Context interface for Node config methods.
|
|
1764
|
+
* Extends ExtensionContext with node-specific properties.
|
|
1765
|
+
* This enables proper typing of `this.options`, `this.nodeType`, etc.
|
|
1766
|
+
*
|
|
1767
|
+
* @typeParam Options - Node options type
|
|
1768
|
+
* @typeParam Storage - Node storage type
|
|
1769
|
+
*/
|
|
1770
|
+
interface NodeContext<Options = unknown, Storage = unknown> extends Omit<ExtensionContext<Options, Storage>, 'editor' | 'type'> {
|
|
1771
|
+
/** Node type identifier */
|
|
1772
|
+
readonly type: 'node';
|
|
1773
|
+
/** Editor instance with schema access */
|
|
1774
|
+
editor: NodeEditorContext | null;
|
|
1775
|
+
/** ProseMirror NodeType (null until editor is initialized) */
|
|
1776
|
+
readonly nodeType: NodeType | null;
|
|
1777
|
+
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Parse rule for converting HTML to ProseMirror node
|
|
1780
|
+
* Simplified version of ProseMirror's ParseRule
|
|
1781
|
+
*/
|
|
1782
|
+
interface NodeParseRule {
|
|
1712
1783
|
/**
|
|
1713
|
-
*
|
|
1784
|
+
* CSS selector or tag name to match
|
|
1785
|
+
* @example 'p', 'h1', 'div.my-class'
|
|
1714
1786
|
*/
|
|
1715
|
-
|
|
1787
|
+
tag?: string;
|
|
1716
1788
|
/**
|
|
1717
|
-
*
|
|
1789
|
+
* Match by CSS style
|
|
1790
|
+
* @example 'font-weight'
|
|
1718
1791
|
*/
|
|
1719
|
-
|
|
1792
|
+
style?: string;
|
|
1720
1793
|
/**
|
|
1721
|
-
*
|
|
1794
|
+
* Priority for this rule (higher = checked first)
|
|
1795
|
+
* @default 50
|
|
1722
1796
|
*/
|
|
1723
|
-
|
|
1797
|
+
priority?: number;
|
|
1724
1798
|
/**
|
|
1725
|
-
*
|
|
1726
|
-
* @
|
|
1799
|
+
* Whether to consume the matched element
|
|
1800
|
+
* @default true
|
|
1727
1801
|
*/
|
|
1728
|
-
|
|
1729
|
-
transaction: Transaction;
|
|
1730
|
-
}): void;
|
|
1802
|
+
consuming?: boolean;
|
|
1731
1803
|
/**
|
|
1732
|
-
*
|
|
1733
|
-
*
|
|
1804
|
+
* Context required for this rule to match
|
|
1805
|
+
* ProseMirror content expression
|
|
1734
1806
|
*/
|
|
1735
|
-
|
|
1736
|
-
event: FocusEvent;
|
|
1737
|
-
}): void;
|
|
1807
|
+
context?: string;
|
|
1738
1808
|
/**
|
|
1739
|
-
*
|
|
1740
|
-
*
|
|
1809
|
+
* Get attributes from the matched element
|
|
1810
|
+
* Return null/undefined to skip this rule
|
|
1741
1811
|
*/
|
|
1742
|
-
|
|
1743
|
-
event: FocusEvent;
|
|
1744
|
-
}): void;
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
/**
|
|
1748
|
-
* Inline Styles Utility
|
|
1749
|
-
*
|
|
1750
|
-
* Applies inline CSS styles to serialized HTML so it renders correctly
|
|
1751
|
-
* when pasted outside the editor (email clients, CMS, Google Docs, etc.).
|
|
1752
|
-
*
|
|
1753
|
-
* Uses hardcoded light-theme defaults (same approach as Google Docs, Notion,
|
|
1754
|
-
* TinyMCE). Optionally accepts overrides for custom styling.
|
|
1755
|
-
*
|
|
1756
|
-
* Only structural styles are inlined (borders, padding, margins, fonts).
|
|
1757
|
-
* Colors are NOT inlined — explicit colors (TextColor, Highlight, cell bg)
|
|
1758
|
-
* are already inline from renderHTML, and default text color is browser default.
|
|
1759
|
-
*/
|
|
1760
|
-
interface InlineStyleOverrides {
|
|
1761
|
-
blockquoteBorder?: string;
|
|
1762
|
-
blockquoteColor?: string;
|
|
1763
|
-
tableBorder?: string;
|
|
1764
|
-
tableHeaderBg?: string;
|
|
1765
|
-
codeBg?: string;
|
|
1766
|
-
codeFont?: string;
|
|
1767
|
-
codeBorder?: string;
|
|
1768
|
-
codeBlockBg?: string;
|
|
1769
|
-
codeBlockFont?: string;
|
|
1770
|
-
hrBorder?: string;
|
|
1771
|
-
linkColor?: string;
|
|
1772
|
-
detailsBorder?: string;
|
|
1773
|
-
detailsBg?: string;
|
|
1812
|
+
getAttrs?: ((node: HTMLElement) => Record<string, unknown> | null | undefined) | null;
|
|
1774
1813
|
/**
|
|
1775
|
-
*
|
|
1776
|
-
*
|
|
1777
|
-
* - `'pixel'`: convert to pixel widths on first-row cells, table gets fixed width
|
|
1778
|
-
* - `'none'`: leave `data-colwidth` as-is, no width styles applied
|
|
1814
|
+
* Get content from the matched element
|
|
1815
|
+
* Return false to use default content parsing
|
|
1779
1816
|
*/
|
|
1780
|
-
|
|
1817
|
+
getContent?: (node: HTMLElement, schema: unknown) => unknown;
|
|
1781
1818
|
/**
|
|
1782
|
-
*
|
|
1783
|
-
* Receives the raw text content and optional language, returns highlighted HTML
|
|
1784
|
-
* with `<span class="hljs-*">` markup (or any spans with inline styles).
|
|
1785
|
-
*
|
|
1786
|
-
* @example
|
|
1787
|
-
* ```ts
|
|
1788
|
-
* import { createLowlight, common } from 'lowlight';
|
|
1789
|
-
* import { toHtml } from 'hast-util-to-html';
|
|
1790
|
-
* const lowlight = createLowlight(common);
|
|
1791
|
-
*
|
|
1792
|
-
* inlineStyles(html, {
|
|
1793
|
-
* codeHighlighter: (code, language) => {
|
|
1794
|
-
* if (language && lowlight.registered(language)) {
|
|
1795
|
-
* return toHtml(lowlight.highlight(language, code));
|
|
1796
|
-
* }
|
|
1797
|
-
* return null; // no highlighting
|
|
1798
|
-
* },
|
|
1799
|
-
* });
|
|
1800
|
-
* ```
|
|
1819
|
+
* How to preserve whitespace
|
|
1801
1820
|
*/
|
|
1802
|
-
|
|
1821
|
+
preserveWhitespace?: boolean | 'full';
|
|
1803
1822
|
}
|
|
1804
1823
|
/**
|
|
1805
|
-
*
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
declare function applyInlineStyles(container: HTMLElement, overrides?: InlineStyleOverrides): void;
|
|
1809
|
-
/**
|
|
1810
|
-
* Takes an HTML string and returns it with inline CSS styles applied
|
|
1811
|
-
* to all elements, so it renders correctly outside the editor.
|
|
1812
|
-
*
|
|
1813
|
-
* @param html - Serialized HTML string from editor.getHTML()
|
|
1814
|
-
* @param overrides - Optional style overrides for custom theming
|
|
1815
|
-
*
|
|
1816
|
-
* @example
|
|
1817
|
-
* ```ts
|
|
1818
|
-
* // Default light-theme styles
|
|
1819
|
-
* const styled = inlineStyles(editor.getHTML());
|
|
1820
|
-
*
|
|
1821
|
-
* // With custom overrides
|
|
1822
|
-
* const styled = inlineStyles(editor.getHTML(), {
|
|
1823
|
-
* blockquoteBorder: '5px solid red',
|
|
1824
|
-
* linkColor: '#ff6600',
|
|
1825
|
-
* });
|
|
1826
|
-
* ```
|
|
1827
|
-
*/
|
|
1828
|
-
declare function inlineStyles(html: string, overrides?: InlineStyleOverrides): string;
|
|
1829
|
-
|
|
1830
|
-
/**
|
|
1831
|
-
* Editor - Main editor class wrapping ProseMirror
|
|
1832
|
-
*
|
|
1833
|
-
* Manages extensions, schema, commands, and the ProseMirror EditorView/State.
|
|
1834
|
-
*/
|
|
1835
|
-
|
|
1836
|
-
/**
|
|
1837
|
-
* Main editor class
|
|
1838
|
-
*
|
|
1839
|
-
* Wraps ProseMirror's EditorView and EditorState with a cleaner API.
|
|
1840
|
-
*
|
|
1841
|
-
* @example
|
|
1842
|
-
* ```ts
|
|
1843
|
-
* import { Editor } from '@domternal/core';
|
|
1844
|
-
* import { Schema } from '@domternal/pm/model';
|
|
1845
|
-
*
|
|
1846
|
-
* const schema = new Schema({
|
|
1847
|
-
* nodes: { doc: { content: 'paragraph+' }, paragraph: { content: 'text*' }, text: {} }
|
|
1848
|
-
* });
|
|
1849
|
-
*
|
|
1850
|
-
* const editor = new Editor({
|
|
1851
|
-
* schema,
|
|
1852
|
-
* element: document.getElementById('editor'),
|
|
1853
|
-
* content: '<p>Hello world</p>',
|
|
1854
|
-
* });
|
|
1855
|
-
*
|
|
1856
|
-
* // Get content
|
|
1857
|
-
* const json = editor.getJSON();
|
|
1858
|
-
* const html = editor.getHTML();
|
|
1859
|
-
*
|
|
1860
|
-
* // Set content
|
|
1861
|
-
* editor.commands.setContent('<p>New content</p>');
|
|
1862
|
-
*
|
|
1863
|
-
* // Cleanup
|
|
1864
|
-
* editor.destroy();
|
|
1865
|
-
* ```
|
|
1866
|
-
*/
|
|
1867
|
-
declare class Editor extends EventEmitter<EditorEvents> {
|
|
1868
|
-
/**
|
|
1869
|
-
* Editor configuration options
|
|
1870
|
-
*/
|
|
1871
|
-
private options;
|
|
1872
|
-
/**
|
|
1873
|
-
* Manages extensions and schema
|
|
1874
|
-
* @internal Exposed for CommandManager, not for public use
|
|
1875
|
-
*/
|
|
1876
|
-
private _extensionManager;
|
|
1824
|
+
* Props passed to renderHTML function
|
|
1825
|
+
*/
|
|
1826
|
+
interface NodeRenderHTMLProps {
|
|
1877
1827
|
/**
|
|
1878
|
-
*
|
|
1879
|
-
* @internal For CommandManager use only
|
|
1828
|
+
* The ProseMirror node being rendered
|
|
1880
1829
|
*/
|
|
1881
|
-
|
|
1830
|
+
node: Node$1;
|
|
1882
1831
|
/**
|
|
1883
|
-
*
|
|
1832
|
+
* Merged HTML attributes from all sources
|
|
1884
1833
|
*/
|
|
1885
|
-
|
|
1834
|
+
HTMLAttributes: Record<string, unknown>;
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Node-specific configuration properties (schema-related)
|
|
1838
|
+
*/
|
|
1839
|
+
interface NodeSchemaProperties {
|
|
1886
1840
|
/**
|
|
1887
|
-
*
|
|
1841
|
+
* Node group(s) this node belongs to
|
|
1842
|
+
* Used in content expressions
|
|
1843
|
+
*
|
|
1844
|
+
* @example 'block', 'inline', 'block list'
|
|
1845
|
+
* Can be a function that returns the group string (useful for dynamic group based on options)
|
|
1888
1846
|
*/
|
|
1889
|
-
|
|
1847
|
+
group?: string | (() => string);
|
|
1890
1848
|
/**
|
|
1891
|
-
*
|
|
1849
|
+
* Content expression defining allowed children
|
|
1850
|
+
* Uses ProseMirror content expression syntax
|
|
1851
|
+
*
|
|
1852
|
+
* @example 'inline*', 'block+', 'paragraph block*'
|
|
1892
1853
|
*/
|
|
1893
|
-
|
|
1854
|
+
content?: string;
|
|
1894
1855
|
/**
|
|
1895
|
-
*
|
|
1856
|
+
* Whether this is an inline node
|
|
1857
|
+
* Can be a function for dynamic inline based on options
|
|
1858
|
+
* @default false
|
|
1896
1859
|
*/
|
|
1897
|
-
|
|
1860
|
+
inline?: boolean | (() => boolean);
|
|
1898
1861
|
/**
|
|
1899
|
-
*
|
|
1862
|
+
* Whether this node is an atom (no direct content editing)
|
|
1863
|
+
* Cursor moves around atoms, not into them
|
|
1900
1864
|
*
|
|
1901
|
-
* @
|
|
1902
|
-
* @throws Error if running in SSR environment (no window)
|
|
1903
|
-
* @throws Error if schema is not provided
|
|
1865
|
+
* @example true for images, mentions, emoji
|
|
1904
1866
|
*/
|
|
1905
|
-
|
|
1867
|
+
atom?: boolean;
|
|
1906
1868
|
/**
|
|
1907
|
-
*
|
|
1869
|
+
* Whether the node can be selected as a whole
|
|
1870
|
+
* @default true for leaf nodes, false for others
|
|
1908
1871
|
*/
|
|
1909
|
-
|
|
1872
|
+
selectable?: boolean;
|
|
1910
1873
|
/**
|
|
1911
|
-
*
|
|
1874
|
+
* Whether the node can be dragged
|
|
1875
|
+
* @default false
|
|
1912
1876
|
*/
|
|
1913
|
-
|
|
1877
|
+
draggable?: boolean;
|
|
1914
1878
|
/**
|
|
1915
|
-
*
|
|
1879
|
+
* Whether this node represents code
|
|
1880
|
+
* Affects text input handling (disables smart quotes, etc.)
|
|
1916
1881
|
*/
|
|
1917
|
-
|
|
1882
|
+
code?: boolean;
|
|
1918
1883
|
/**
|
|
1919
|
-
*
|
|
1884
|
+
* How whitespace is handled in this node
|
|
1885
|
+
* - 'pre': preserve whitespace (like <pre>)
|
|
1886
|
+
* - 'normal': collapse whitespace (default)
|
|
1920
1887
|
*/
|
|
1921
|
-
|
|
1888
|
+
whitespace?: 'pre' | 'normal';
|
|
1922
1889
|
/**
|
|
1923
|
-
*
|
|
1890
|
+
* Whether this node isolates marks at its boundaries
|
|
1891
|
+
* Marks don't extend across isolating boundaries
|
|
1924
1892
|
*/
|
|
1925
|
-
|
|
1893
|
+
isolating?: boolean;
|
|
1926
1894
|
/**
|
|
1927
|
-
*
|
|
1895
|
+
* Whether a gap cursor is allowed inside this node.
|
|
1896
|
+
* Set to false to prevent gapcursor from appearing inside this node.
|
|
1897
|
+
* Set to true to force gapcursor even if the default heuristic disallows it.
|
|
1898
|
+
* When undefined, uses ProseMirror's default heuristic.
|
|
1928
1899
|
*/
|
|
1929
|
-
|
|
1900
|
+
allowGapCursor?: boolean;
|
|
1930
1901
|
/**
|
|
1931
|
-
*
|
|
1932
|
-
*
|
|
1902
|
+
* Table role for prosemirror-tables integration.
|
|
1903
|
+
* Nodes with a tableRole are discovered by prosemirror-tables via spec.tableRole.
|
|
1904
|
+
* One of: 'table', 'row', 'cell', 'header_cell'
|
|
1933
1905
|
*/
|
|
1934
|
-
|
|
1906
|
+
tableRole?: 'table' | 'row' | 'cell' | 'header_cell';
|
|
1935
1907
|
/**
|
|
1936
|
-
*
|
|
1937
|
-
*
|
|
1908
|
+
* Whether this is a top-level node (document root)
|
|
1909
|
+
* Only one node should have this set to true
|
|
1938
1910
|
*/
|
|
1939
|
-
|
|
1911
|
+
topNode?: boolean;
|
|
1940
1912
|
/**
|
|
1941
|
-
*
|
|
1942
|
-
*
|
|
1913
|
+
* Whether this node defines its own scope
|
|
1914
|
+
* Content and marks don't leak out of defining nodes
|
|
1943
1915
|
*/
|
|
1944
|
-
|
|
1916
|
+
defining?: boolean;
|
|
1945
1917
|
/**
|
|
1946
|
-
*
|
|
1947
|
-
*
|
|
1918
|
+
* Which marks are allowed in this node
|
|
1919
|
+
* Empty string means no marks allowed
|
|
1920
|
+
*
|
|
1921
|
+
* @example '', '_', 'bold italic'
|
|
1948
1922
|
*/
|
|
1949
|
-
|
|
1923
|
+
marks?: string;
|
|
1950
1924
|
/**
|
|
1951
|
-
*
|
|
1952
|
-
*
|
|
1925
|
+
* Custom text for leaf nodes returned by `getText()` / `textContent`.
|
|
1926
|
+
*
|
|
1927
|
+
* @example '\n' for hard break
|
|
1953
1928
|
*/
|
|
1954
|
-
|
|
1929
|
+
leafText?: string | ((node: Node$1) => string);
|
|
1955
1930
|
/**
|
|
1956
|
-
*
|
|
1957
|
-
*
|
|
1958
|
-
* For toolbar button states - returns true if:
|
|
1959
|
-
* - For marks: the current selection has the mark applied
|
|
1960
|
-
* - For nodes: the cursor is inside that node type
|
|
1961
|
-
*
|
|
1962
|
-
* @param nameOrAttributes - Extension name, or object with name and attributes
|
|
1963
|
-
* @param attributes - Optional attributes to match (for node/mark specific states)
|
|
1931
|
+
* Define node attributes
|
|
1932
|
+
* Returns attribute specifications
|
|
1964
1933
|
*
|
|
1965
1934
|
* @example
|
|
1966
|
-
*
|
|
1967
|
-
*
|
|
1968
|
-
*
|
|
1935
|
+
* addAttributes() {
|
|
1936
|
+
* return {
|
|
1937
|
+
* level: { default: 1 },
|
|
1938
|
+
* };
|
|
1939
|
+
* }
|
|
1969
1940
|
*/
|
|
1970
|
-
|
|
1971
|
-
name: string;
|
|
1972
|
-
attributes?: Record<string, unknown>;
|
|
1973
|
-
}, attributes?: Record<string, unknown>): boolean;
|
|
1941
|
+
addAttributes?: () => AttributeSpecs;
|
|
1974
1942
|
/**
|
|
1975
|
-
*
|
|
1976
|
-
*
|
|
1977
|
-
* Returns empty object if the node/mark is not found or not active.
|
|
1978
|
-
*
|
|
1979
|
-
* @param name - Extension name (node or mark)
|
|
1943
|
+
* Parse rules for converting HTML to this node
|
|
1944
|
+
* Each rule defines how to match and parse HTML elements
|
|
1980
1945
|
*
|
|
1981
1946
|
* @example
|
|
1982
|
-
*
|
|
1983
|
-
*
|
|
1947
|
+
* parseHTML() {
|
|
1948
|
+
* return [
|
|
1949
|
+
* { tag: 'p' },
|
|
1950
|
+
* { tag: 'div', priority: 10 },
|
|
1951
|
+
* ];
|
|
1952
|
+
* }
|
|
1984
1953
|
*/
|
|
1985
|
-
|
|
1954
|
+
parseHTML?: () => NodeParseRule[];
|
|
1986
1955
|
/**
|
|
1987
|
-
*
|
|
1988
|
-
* Returns
|
|
1956
|
+
* Render this node to DOM
|
|
1957
|
+
* Returns DOMOutputSpec (tag, attributes, children)
|
|
1958
|
+
*
|
|
1959
|
+
* @example
|
|
1960
|
+
* renderHTML({ node, HTMLAttributes }) {
|
|
1961
|
+
* return ['p', HTMLAttributes, 0];
|
|
1962
|
+
* }
|
|
1989
1963
|
*/
|
|
1990
|
-
|
|
1964
|
+
renderHTML?: (props: NodeRenderHTMLProps) => DOMOutputSpec;
|
|
1991
1965
|
/**
|
|
1992
|
-
*
|
|
1966
|
+
* Custom node view constructor
|
|
1967
|
+
* For complex interactive nodes
|
|
1993
1968
|
*/
|
|
1994
|
-
|
|
1969
|
+
addNodeView?: () => NodeViewConstructor;
|
|
1995
1970
|
/**
|
|
1996
|
-
*
|
|
1997
|
-
*
|
|
1998
|
-
* @param options - Optional settings
|
|
1999
|
-
* @param options.styled - When true (or an override object), applies inline CSS
|
|
2000
|
-
* styles so the HTML renders correctly outside the editor (email, CMS, etc.)
|
|
1971
|
+
* Additional ProseMirror plugins for this node
|
|
1972
|
+
* Called during plugin collection
|
|
2001
1973
|
*/
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
1974
|
+
addProseMirrorPlugins?: () => Plugin[];
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Configuration for Node extensions
|
|
1978
|
+
* Combines ExtensionConfig base with node-specific schema properties.
|
|
1979
|
+
* Uses ThisType<NodeContext> to provide proper typing for `this` in config methods.
|
|
1980
|
+
*
|
|
1981
|
+
* @typeParam Options - Node options type
|
|
1982
|
+
* @typeParam Storage - Node storage type
|
|
1983
|
+
*
|
|
1984
|
+
* @example
|
|
1985
|
+
* const Paragraph = Node.create({
|
|
1986
|
+
* name: 'paragraph',
|
|
1987
|
+
* group: 'block',
|
|
1988
|
+
* content: 'inline*',
|
|
1989
|
+
* parseHTML() {
|
|
1990
|
+
* // `this` is properly typed here!
|
|
1991
|
+
* return [{ tag: 'p' }];
|
|
1992
|
+
* },
|
|
1993
|
+
* renderHTML({ HTMLAttributes }) {
|
|
1994
|
+
* return ['p', HTMLAttributes, 0];
|
|
1995
|
+
* },
|
|
1996
|
+
* });
|
|
1997
|
+
*/
|
|
1998
|
+
type NodeConfig<Options = unknown, Storage = unknown> = ExtensionConfigBase<Options, Storage> & NodeSchemaProperties & ThisType<NodeContext<Options, Storage>>;
|
|
1999
|
+
|
|
2000
|
+
/**
|
|
2001
|
+
* Mark configuration types
|
|
2002
|
+
*
|
|
2003
|
+
* These types define the configuration object passed to Mark.create()
|
|
2004
|
+
* for creating ProseMirror mark extensions.
|
|
2005
|
+
*/
|
|
2006
|
+
|
|
2007
|
+
/**
|
|
2008
|
+
* Editor interface for Mark context
|
|
2009
|
+
* Includes schema with marks for MarkType getter
|
|
2010
|
+
*/
|
|
2011
|
+
interface MarkEditorContext {
|
|
2012
|
+
readonly state: EditorState;
|
|
2013
|
+
readonly view: EditorView;
|
|
2014
|
+
readonly schema: {
|
|
2015
|
+
marks: Record<string, MarkType>;
|
|
2016
|
+
};
|
|
2017
|
+
readonly commands: Record<string, (...args: unknown[]) => boolean>;
|
|
2018
|
+
}
|
|
2019
|
+
/**
|
|
2020
|
+
* Context interface for Mark config methods.
|
|
2021
|
+
* Extends ExtensionContext with mark-specific properties.
|
|
2022
|
+
* This enables proper typing of `this.options`, `this.markType`, etc.
|
|
2023
|
+
*
|
|
2024
|
+
* @typeParam Options - Mark options type
|
|
2025
|
+
* @typeParam Storage - Mark storage type
|
|
2026
|
+
*/
|
|
2027
|
+
interface MarkContext<Options = unknown, Storage = unknown> extends Omit<ExtensionContext<Options, Storage>, 'editor' | 'type'> {
|
|
2028
|
+
/** Mark type identifier */
|
|
2029
|
+
readonly type: 'mark';
|
|
2030
|
+
/** Editor instance with schema access */
|
|
2031
|
+
editor: MarkEditorContext | null;
|
|
2032
|
+
/** ProseMirror MarkType (null until editor is initialized) */
|
|
2033
|
+
readonly markType: MarkType | null;
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Parse rule for converting HTML to ProseMirror mark
|
|
2037
|
+
* Simplified version of ProseMirror's ParseRule for marks
|
|
2038
|
+
*/
|
|
2039
|
+
interface MarkParseRule {
|
|
2005
2040
|
/**
|
|
2006
|
-
*
|
|
2007
|
-
*
|
|
2008
|
-
* @param options - Options for text extraction
|
|
2009
|
-
* @param options.blockSeparator - String to insert between blocks (default: '\n\n')
|
|
2041
|
+
* CSS selector or tag name to match
|
|
2042
|
+
* @example 'strong', 'b', 'span.bold'
|
|
2010
2043
|
*/
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2044
|
+
tag?: string;
|
|
2045
|
+
/**
|
|
2046
|
+
* Match by CSS style property
|
|
2047
|
+
* Can include expected value after '='
|
|
2048
|
+
* @example 'font-weight', 'font-weight=bold'
|
|
2049
|
+
*/
|
|
2050
|
+
style?: string;
|
|
2014
2051
|
/**
|
|
2015
|
-
*
|
|
2016
|
-
* @
|
|
2052
|
+
* Priority for this rule (higher = checked first)
|
|
2053
|
+
* @default 50
|
|
2017
2054
|
*/
|
|
2018
|
-
|
|
2055
|
+
priority?: number;
|
|
2019
2056
|
/**
|
|
2020
|
-
*
|
|
2021
|
-
*
|
|
2022
|
-
* @param content - JSON or HTML content
|
|
2023
|
-
* @param emitUpdate - Whether to emit update event (default: true)
|
|
2024
|
-
* @returns true if content was set successfully, false if content was invalid
|
|
2057
|
+
* Whether to consume the matched element
|
|
2058
|
+
* @default true
|
|
2025
2059
|
*/
|
|
2026
|
-
|
|
2060
|
+
consuming?: boolean;
|
|
2027
2061
|
/**
|
|
2028
|
-
*
|
|
2062
|
+
* Get attributes from the matched element
|
|
2063
|
+
* Return null/undefined to skip this rule
|
|
2064
|
+
* Return false to explicitly not match
|
|
2029
2065
|
*
|
|
2030
|
-
*
|
|
2031
|
-
* @returns true if content was cleared successfully
|
|
2066
|
+
* For style rules, receives the style value as string
|
|
2032
2067
|
*/
|
|
2033
|
-
|
|
2068
|
+
getAttrs?: ((node: HTMLElement | string) => Record<string, unknown> | false | null) | null;
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* Props passed to renderHTML function for marks
|
|
2072
|
+
*/
|
|
2073
|
+
interface MarkRenderHTMLProps {
|
|
2034
2074
|
/**
|
|
2035
|
-
*
|
|
2036
|
-
*
|
|
2037
|
-
* @param editable - Whether the editor should be editable
|
|
2075
|
+
* The ProseMirror mark being rendered
|
|
2038
2076
|
*/
|
|
2039
|
-
|
|
2077
|
+
mark: Mark$1;
|
|
2040
2078
|
/**
|
|
2041
|
-
*
|
|
2042
|
-
*
|
|
2043
|
-
* @param position - Where to place cursor (default: null = just focus)
|
|
2079
|
+
* Merged HTML attributes from all sources
|
|
2044
2080
|
*/
|
|
2045
|
-
|
|
2081
|
+
HTMLAttributes: Record<string, unknown>;
|
|
2082
|
+
}
|
|
2083
|
+
/**
|
|
2084
|
+
* Mark-specific configuration properties (schema-related)
|
|
2085
|
+
*/
|
|
2086
|
+
interface MarkSchemaProperties {
|
|
2046
2087
|
/**
|
|
2047
|
-
*
|
|
2088
|
+
* Whether this mark should be active when the cursor
|
|
2089
|
+
* is at its end (or beginning for marks that open).
|
|
2090
|
+
*
|
|
2091
|
+
* When true, typing at the mark's boundary continues the mark.
|
|
2092
|
+
* When false, typing creates unmarked content.
|
|
2093
|
+
*
|
|
2094
|
+
* @default true
|
|
2048
2095
|
*/
|
|
2049
|
-
|
|
2096
|
+
inclusive?: boolean | (() => boolean);
|
|
2050
2097
|
/**
|
|
2051
|
-
*
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2098
|
+
* Marks that this mark excludes (cannot coexist with)
|
|
2099
|
+
*
|
|
2100
|
+
* - '_' excludes all marks
|
|
2101
|
+
* - Space-separated mark names exclude specific marks
|
|
2102
|
+
* - Empty string or undefined means no exclusions
|
|
2103
|
+
*
|
|
2104
|
+
* @example 'code' - excludes code mark
|
|
2105
|
+
* @example 'bold italic' - excludes bold and italic
|
|
2106
|
+
* @example '_' - excludes all other marks
|
|
2054
2107
|
*/
|
|
2055
|
-
|
|
2108
|
+
excludes?: string;
|
|
2056
2109
|
/**
|
|
2057
|
-
*
|
|
2058
|
-
*
|
|
2110
|
+
* Mark group(s) this mark belongs to
|
|
2111
|
+
* Used in node's marks property
|
|
2112
|
+
*
|
|
2113
|
+
* @example 'formatting', 'inline'
|
|
2059
2114
|
*/
|
|
2060
|
-
|
|
2115
|
+
group?: string;
|
|
2061
2116
|
/**
|
|
2062
|
-
*
|
|
2117
|
+
* Whether this mark can span multiple nodes
|
|
2063
2118
|
*
|
|
2064
|
-
*
|
|
2119
|
+
* When true (default), the mark persists across inline nodes.
|
|
2120
|
+
* When false, the mark only applies within a single text node.
|
|
2121
|
+
*
|
|
2122
|
+
* @default true
|
|
2065
2123
|
*/
|
|
2066
|
-
|
|
2124
|
+
spanning?: boolean;
|
|
2067
2125
|
/**
|
|
2068
|
-
*
|
|
2126
|
+
* Whether this mark represents visual formatting.
|
|
2127
|
+
*
|
|
2128
|
+
* Used by `unsetAllMarks` to decide which marks to remove.
|
|
2129
|
+
* Marks with `isFormatting: false` survive clear formatting
|
|
2130
|
+
* (e.g., links, comments, annotations).
|
|
2131
|
+
*
|
|
2132
|
+
* Can be overridden via `.configure()`:
|
|
2133
|
+
* ```ts
|
|
2134
|
+
* Link.configure({ isFormatting: true }) // make links clearable
|
|
2135
|
+
* ```
|
|
2136
|
+
*
|
|
2137
|
+
* @default true
|
|
2069
2138
|
*/
|
|
2070
|
-
|
|
2139
|
+
isFormatting?: boolean;
|
|
2071
2140
|
/**
|
|
2072
|
-
*
|
|
2141
|
+
* Define mark attributes
|
|
2142
|
+
* Returns attribute specifications
|
|
2143
|
+
*
|
|
2144
|
+
* @example
|
|
2145
|
+
* addAttributes() {
|
|
2146
|
+
* return {
|
|
2147
|
+
* color: { default: null },
|
|
2148
|
+
* };
|
|
2149
|
+
* }
|
|
2073
2150
|
*/
|
|
2074
|
-
|
|
2151
|
+
addAttributes?: () => AttributeSpecs;
|
|
2075
2152
|
/**
|
|
2076
|
-
*
|
|
2153
|
+
* Parse rules for converting HTML to this mark
|
|
2154
|
+
* Each rule defines how to match and parse HTML elements
|
|
2155
|
+
*
|
|
2156
|
+
* @example
|
|
2157
|
+
* parseHTML() {
|
|
2158
|
+
* return [
|
|
2159
|
+
* { tag: 'strong' },
|
|
2160
|
+
* { tag: 'b' },
|
|
2161
|
+
* { style: 'font-weight', getAttrs: (value) => /bold|[5-9]\d{2}/.test(value) && null },
|
|
2162
|
+
* ];
|
|
2163
|
+
* }
|
|
2077
2164
|
*/
|
|
2078
|
-
|
|
2165
|
+
parseHTML?: () => MarkParseRule[];
|
|
2079
2166
|
/**
|
|
2080
|
-
*
|
|
2167
|
+
* Render this mark to DOM
|
|
2168
|
+
* Returns DOMOutputSpec (tag, attributes, hole)
|
|
2169
|
+
*
|
|
2170
|
+
* The 0 in the return array indicates where child content goes.
|
|
2171
|
+
*
|
|
2172
|
+
* @example
|
|
2173
|
+
* renderHTML({ mark, HTMLAttributes }) {
|
|
2174
|
+
* return ['strong', HTMLAttributes, 0];
|
|
2175
|
+
* }
|
|
2081
2176
|
*/
|
|
2082
|
-
|
|
2177
|
+
renderHTML?: (props: MarkRenderHTMLProps) => DOMOutputSpec;
|
|
2083
2178
|
}
|
|
2179
|
+
/**
|
|
2180
|
+
* Configuration for Mark extensions
|
|
2181
|
+
* Combines ExtensionConfigBase with mark-specific schema properties.
|
|
2182
|
+
* Uses ThisType<MarkContext> to provide proper typing for `this` in config methods.
|
|
2183
|
+
*
|
|
2184
|
+
* @typeParam Options - Mark options type
|
|
2185
|
+
* @typeParam Storage - Mark storage type
|
|
2186
|
+
*
|
|
2187
|
+
* @example
|
|
2188
|
+
* const Bold = Mark.create({
|
|
2189
|
+
* name: 'bold',
|
|
2190
|
+
* parseHTML() {
|
|
2191
|
+
* // `this` is properly typed here!
|
|
2192
|
+
* return [{ tag: 'strong' }, { tag: 'b' }];
|
|
2193
|
+
* },
|
|
2194
|
+
* renderHTML({ HTMLAttributes }) {
|
|
2195
|
+
* return ['strong', HTMLAttributes, 0];
|
|
2196
|
+
* },
|
|
2197
|
+
* });
|
|
2198
|
+
*/
|
|
2199
|
+
type MarkConfig<Options = unknown, Storage = unknown> = ExtensionConfigBase<Options, Storage> & MarkSchemaProperties & ThisType<MarkContext<Options, Storage>>;
|
|
2084
2200
|
|
|
2085
2201
|
/**
|
|
2086
2202
|
* Focus command - focuses the editor at the specified position
|
|
@@ -2168,7 +2284,7 @@ declare const insertText: CommandSpec$1<[text: string]>;
|
|
|
2168
2284
|
declare const insertContent: CommandSpec$1<[content: Content]>;
|
|
2169
2285
|
|
|
2170
2286
|
/**
|
|
2171
|
-
* Mark commands
|
|
2287
|
+
* Mark commands - toggleMark, setMark, unsetMark, unsetAllMarks
|
|
2172
2288
|
*/
|
|
2173
2289
|
|
|
2174
2290
|
/**
|
|
@@ -2271,7 +2387,7 @@ declare const lift: CommandSpec$1;
|
|
|
2271
2387
|
declare const toggleList: CommandSpec$1<[listNodeName: string, listItemNodeName: string, attributes?: Attrs]>;
|
|
2272
2388
|
|
|
2273
2389
|
/**
|
|
2274
|
-
* Attribute commands
|
|
2390
|
+
* Attribute commands - updateAttributes, resetAttributes
|
|
2275
2391
|
*/
|
|
2276
2392
|
|
|
2277
2393
|
/**
|
|
@@ -2370,8 +2486,8 @@ declare class CommandManager {
|
|
|
2370
2486
|
*/
|
|
2371
2487
|
private buildCommandProps;
|
|
2372
2488
|
/**
|
|
2373
|
-
* Single commands that execute immediately
|
|
2374
|
-
* Uses Proxy to dynamically generate command methods
|
|
2489
|
+
* Single commands that execute immediately.
|
|
2490
|
+
* Uses a Proxy to dynamically generate command methods.
|
|
2375
2491
|
*
|
|
2376
2492
|
* @example
|
|
2377
2493
|
* editor.commands.focus('end');
|
|
@@ -2430,61 +2546,237 @@ interface PositionFloatingOptions {
|
|
|
2430
2546
|
trackScroll?: boolean;
|
|
2431
2547
|
}
|
|
2432
2548
|
/**
|
|
2433
|
-
* Positions a floating element relative to a reference element or virtual rect,
|
|
2434
|
-
* and keeps it positioned on scroll, resize, and layout shifts.
|
|
2435
|
-
*
|
|
2436
|
-
* Uses `autoUpdate` from floating-ui with `animationFrame` polling for
|
|
2437
|
-
* jitter-free scroll tracking (rAF syncs with browser paint).
|
|
2438
|
-
*
|
|
2439
|
-
* Includes `hide` middleware
|
|
2440
|
-
* view, the floating element is hidden via `visibility: hidden`.
|
|
2441
|
-
*
|
|
2442
|
-
* The floating element must have `position: fixed`.
|
|
2443
|
-
*
|
|
2444
|
-
* Returns a cleanup function. **Always call it** when hiding or destroying
|
|
2445
|
-
* the floating element to stop listeners and prevent memory leaks.
|
|
2446
|
-
*
|
|
2447
|
-
* @example
|
|
2448
|
-
* ```ts
|
|
2449
|
-
* // Start auto-positioning (follows scroll/resize)
|
|
2450
|
-
* const cleanup = positionFloating(buttonEl, dropdownEl, {
|
|
2451
|
-
* placement: 'bottom-start',
|
|
2452
|
-
* });
|
|
2453
|
-
*
|
|
2454
|
-
* // Virtual reference (e.g. cursor position
|
|
2455
|
-
* const virtualEl = {
|
|
2456
|
-
* getBoundingClientRect: () => {
|
|
2457
|
-
* const coords = view.coordsAtPos(pos);
|
|
2458
|
-
* return new DOMRect(coords.left, coords.top, 0, coords.bottom - coords.top);
|
|
2459
|
-
* },
|
|
2460
|
-
* };
|
|
2461
|
-
* const cleanup = positionFloating(virtualEl, tooltipEl, { placement: 'top' });
|
|
2549
|
+
* Positions a floating element relative to a reference element or virtual rect,
|
|
2550
|
+
* and keeps it positioned on scroll, resize, and layout shifts.
|
|
2551
|
+
*
|
|
2552
|
+
* Uses `autoUpdate` from floating-ui with `animationFrame` polling for
|
|
2553
|
+
* jitter-free scroll tracking (rAF syncs with browser paint).
|
|
2554
|
+
*
|
|
2555
|
+
* Includes `hide` middleware - when the reference element is scrolled out of
|
|
2556
|
+
* view, the floating element is hidden via `visibility: hidden`.
|
|
2557
|
+
*
|
|
2558
|
+
* The floating element must have `position: fixed`.
|
|
2559
|
+
*
|
|
2560
|
+
* Returns a cleanup function. **Always call it** when hiding or destroying
|
|
2561
|
+
* the floating element to stop listeners and prevent memory leaks.
|
|
2562
|
+
*
|
|
2563
|
+
* @example
|
|
2564
|
+
* ```ts
|
|
2565
|
+
* // Start auto-positioning (follows scroll/resize)
|
|
2566
|
+
* const cleanup = positionFloating(buttonEl, dropdownEl, {
|
|
2567
|
+
* placement: 'bottom-start',
|
|
2568
|
+
* });
|
|
2569
|
+
*
|
|
2570
|
+
* // Virtual reference (e.g. cursor position - must return fresh coords)
|
|
2571
|
+
* const virtualEl = {
|
|
2572
|
+
* getBoundingClientRect: () => {
|
|
2573
|
+
* const coords = view.coordsAtPos(pos);
|
|
2574
|
+
* return new DOMRect(coords.left, coords.top, 0, coords.bottom - coords.top);
|
|
2575
|
+
* },
|
|
2576
|
+
* };
|
|
2577
|
+
* const cleanup = positionFloating(virtualEl, tooltipEl, { placement: 'top' });
|
|
2578
|
+
*
|
|
2579
|
+
* // Stop when done
|
|
2580
|
+
* cleanup();
|
|
2581
|
+
* ```
|
|
2582
|
+
*/
|
|
2583
|
+
declare function positionFloating(reference: Element | {
|
|
2584
|
+
getBoundingClientRect: () => DOMRect;
|
|
2585
|
+
}, floating: HTMLElement, options?: PositionFloatingOptions): () => void;
|
|
2586
|
+
/**
|
|
2587
|
+
* Positions a floating element using `strategy: 'absolute'` so it scrolls
|
|
2588
|
+
* together with its offsetParent - zero jitter by design.
|
|
2589
|
+
*
|
|
2590
|
+
* Ideal for dropdowns inside scroll containers (e.g. emoji suggestion inside
|
|
2591
|
+
* `.dm-editor`) and toolbar dropdowns. The absolute coordinates are stable
|
|
2592
|
+
* across scrolls - only `flip`/`shift` decisions change on scroll, producing
|
|
2593
|
+
* a discrete jump rather than continuous jitter.
|
|
2594
|
+
*
|
|
2595
|
+
* The floating element must have `position: absolute` and its offsetParent
|
|
2596
|
+
* must have `position: relative`.
|
|
2597
|
+
*
|
|
2598
|
+
* Returns a cleanup function - call it when hiding or destroying the
|
|
2599
|
+
* floating element.
|
|
2600
|
+
*/
|
|
2601
|
+
declare function positionFloatingOnce(reference: Element | {
|
|
2602
|
+
getBoundingClientRect: () => DOMRect;
|
|
2603
|
+
}, floating: HTMLElement, options?: PositionFloatingOptions): () => void;
|
|
2604
|
+
|
|
2605
|
+
/**
|
|
2606
|
+
* Clipboard helper - writes plain text to the system clipboard.
|
|
2607
|
+
*
|
|
2608
|
+
* Tries the modern async Clipboard API first; if unavailable or denied
|
|
2609
|
+
* (Safari private mode, insecure context, missing user gesture), falls
|
|
2610
|
+
* back to a hidden textarea + `document.execCommand('copy')`.
|
|
2611
|
+
*
|
|
2612
|
+
* Returns `true` on success, `false` on failure. Never throws - callers
|
|
2613
|
+
* decide how to surface failure (toast, re-throw, silent).
|
|
2614
|
+
*
|
|
2615
|
+
* @example
|
|
2616
|
+
* ```ts
|
|
2617
|
+
* const ok = await writeToClipboard('https://example.com#block-abc123');
|
|
2618
|
+
* if (!ok) showError('Copy failed');
|
|
2619
|
+
* ```
|
|
2620
|
+
*/
|
|
2621
|
+
declare function writeToClipboard(text: string): Promise<boolean>;
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* Default `contexts` map for a bubble menu when the consumer has not
|
|
2625
|
+
* supplied one. Returns a richer item set when the editor (or any
|
|
2626
|
+
* ancestor) carries the `.dm-notion-mode` class - that class is the
|
|
2627
|
+
* project-wide signal that the host is rendering Notion-style UX, so
|
|
2628
|
+
* the bubble menu mirrors it by including `link` and `textAlign`.
|
|
2629
|
+
*
|
|
2630
|
+
* Consumers can always override by passing their own `contexts` prop.
|
|
2631
|
+
*/
|
|
2632
|
+
declare function defaultBubbleContexts(editor: Editor): Record<string, string[]>;
|
|
2633
|
+
|
|
2634
|
+
interface InsertAsListItemChildArgs {
|
|
2635
|
+
/** Existing transaction to mutate. Caller dispatches. */
|
|
2636
|
+
tr: Transaction;
|
|
2637
|
+
/** Position of the list wrapper node (bulletList / orderedList / taskList) in `tr.doc`. */
|
|
2638
|
+
wrapperPos: number;
|
|
2639
|
+
/**
|
|
2640
|
+
* Position of the target list item node (= position right BEFORE the
|
|
2641
|
+
* item) in `tr.doc`. When omitted, the wrapper's LAST child is used,
|
|
2642
|
+
* matching the Tab keyboard behaviour ("indent into last item").
|
|
2643
|
+
*/
|
|
2644
|
+
targetItemPos?: number;
|
|
2645
|
+
/** Block node to append as the LAST child of the target item. */
|
|
2646
|
+
blockNode: Node$1;
|
|
2647
|
+
/**
|
|
2648
|
+
* Optional source range to delete in the SAME transaction (when
|
|
2649
|
+
* MOVING an existing block instead of creating a new one). Position
|
|
2650
|
+
* math handles source-before-vs-after-target ordering automatically.
|
|
2651
|
+
*/
|
|
2652
|
+
sourceRange?: {
|
|
2653
|
+
from: number;
|
|
2654
|
+
to: number;
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
interface InsertAsListItemChildResult {
|
|
2658
|
+
/** True when schema accepted the insertion and `tr` was mutated. */
|
|
2659
|
+
ok: boolean;
|
|
2660
|
+
/**
|
|
2661
|
+
* Position right BEFORE the inserted block in the resulting doc.
|
|
2662
|
+
* Caller can resolve `insertedAt + 1` to place the caret inside the
|
|
2663
|
+
* inserted block. Only present when `ok === true`.
|
|
2664
|
+
*/
|
|
2665
|
+
insertedAt?: number;
|
|
2666
|
+
}
|
|
2667
|
+
/**
|
|
2668
|
+
* Insert `blockNode` as the LAST child of a list item (target item or, when
|
|
2669
|
+
* omitted, the wrapper's last item). When `sourceRange` is set, the source
|
|
2670
|
+
* range is removed in the same transaction so the op is a clean MOVE.
|
|
2671
|
+
* Returns `{ ok: false }` WITHOUT mutating `tr` on schema reject so callers
|
|
2672
|
+
* can fall through to a sibling-mode fallback.
|
|
2673
|
+
*/
|
|
2674
|
+
declare function insertAsListItemChild(args: InsertAsListItemChildArgs): InsertAsListItemChildResult;
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* Cursor context relative to the INNERMOST containing list/task item,
|
|
2678
|
+
* resolved only when the cursor's parent paragraph is a DIRECT child of
|
|
2679
|
+
* that item. Innermost so nested lists hand control to the deepest item;
|
|
2680
|
+
* direct-child so paragraphs inside blockquote/table-cell/etc. inside a
|
|
2681
|
+
* list item fall through to the container's own Enter/Backspace.
|
|
2682
|
+
*/
|
|
2683
|
+
interface ListItemCursorContext {
|
|
2684
|
+
/** Depth of the containing list item ancestor in the resolved pos. */
|
|
2685
|
+
itemDepth: number;
|
|
2686
|
+
/** Position right BEFORE the containing list item in the doc. */
|
|
2687
|
+
itemPos: number;
|
|
2688
|
+
/** Position right BEFORE the containing list wrapper (one depth above the item). */
|
|
2689
|
+
wrapperPos: number;
|
|
2690
|
+
/** `true` when the parent paragraph is not the first child of the list item. */
|
|
2691
|
+
isInChildrenZone: boolean;
|
|
2692
|
+
/** `true` when the parent paragraph has no inline content. */
|
|
2693
|
+
paragraphIsEmpty: boolean;
|
|
2694
|
+
/** `true` when the parent paragraph is the LAST child of the list item. */
|
|
2695
|
+
isLastChild: boolean;
|
|
2696
|
+
/** Index of the parent paragraph within the list item (0 = label). */
|
|
2697
|
+
childIndex: number;
|
|
2698
|
+
/** Index of the containing list item within its wrapper. */
|
|
2699
|
+
itemIndexInWrapper: number;
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Resolve list-item cursor context. Returns `null` when the cursor's
|
|
2703
|
+
* shape does not match `(wrapper > item > paragraph)`; callers should
|
|
2704
|
+
* fall through to default Enter/Backspace in that case.
|
|
2705
|
+
*/
|
|
2706
|
+
declare function getListItemCursorContext($from: ResolvedPos): ListItemCursorContext | null;
|
|
2707
|
+
|
|
2708
|
+
/**
|
|
2709
|
+
* Lift an empty children-zone paragraph out of its list/task item as a
|
|
2710
|
+
* top-level sibling. PM's `liftTarget` covers the common case; we fall
|
|
2711
|
+
* back to manual delete-and-insert when it returns null (empty p sandwiched
|
|
2712
|
+
* before a non-paragraph would leave the after-cut half violating the
|
|
2713
|
+
* `paragraph block*` schema).
|
|
2714
|
+
*/
|
|
2715
|
+
declare function liftEmptyChildrenZoneParagraph(state: EditorState, dispatch: ((tr: Transaction) => void) | undefined, ctx: ListItemCursorContext): boolean;
|
|
2716
|
+
|
|
2717
|
+
/**
|
|
2718
|
+
* Insert an empty paragraph as next sibling inside the same list/task item,
|
|
2719
|
+
* keeping the cursor in the children-zone so Enter accumulates blocks at the
|
|
2720
|
+
* same nesting level (Notion semantics). Exit paths are Backspace on empty,
|
|
2721
|
+
* Shift+Tab, or Enter on the empty label paragraph.
|
|
2722
|
+
*/
|
|
2723
|
+
declare function insertChildrenZoneSibling(state: EditorState, dispatch: ((tr: Transaction) => void) | undefined, ctx: ListItemCursorContext): boolean;
|
|
2724
|
+
|
|
2725
|
+
/**
|
|
2726
|
+
* Activation conditions (single-cursor only):
|
|
2727
|
+
* - selection is empty (single caret)
|
|
2728
|
+
* - cursor's nearest list-item ancestor exists
|
|
2729
|
+
* - cursor's containing block is at index 0 (label slot) of that item
|
|
2730
|
+
* - `tr` has no prior steps (lift steps captured from a fresh state must
|
|
2731
|
+
* replay against the same starting state as `tr`)
|
|
2732
|
+
*
|
|
2733
|
+
* Returns true if the lift was applied to `tr`. The caller can keep
|
|
2734
|
+
* chaining work on `tr` (e.g. `setBlockType`, `wrapIn`) on the new
|
|
2735
|
+
* top-level paragraph.
|
|
2736
|
+
*/
|
|
2737
|
+
declare function liftCurrentListItem(state: EditorState, tr: Transaction): boolean;
|
|
2738
|
+
|
|
2739
|
+
interface SplitListForInsertRange {
|
|
2740
|
+
from: number;
|
|
2741
|
+
to: number;
|
|
2742
|
+
}
|
|
2743
|
+
/**
|
|
2744
|
+
* Activation conditions (single-cursor only):
|
|
2745
|
+
* - selection is empty
|
|
2746
|
+
* - cursor's nearest list-item ancestor exists
|
|
2747
|
+
* - cursor's containing block is at index 0 (label slot) of that item
|
|
2748
|
+
* - `tr` has no prior steps
|
|
2462
2749
|
*
|
|
2463
|
-
*
|
|
2464
|
-
*
|
|
2465
|
-
*
|
|
2750
|
+
* @returns A range where the caller should call `tr.replaceWith(from, to,
|
|
2751
|
+
* [block, optionalTrailingParagraph])`, or `null` if the cursor isn't
|
|
2752
|
+
* in a list-item label.
|
|
2466
2753
|
*/
|
|
2467
|
-
declare function
|
|
2468
|
-
|
|
2469
|
-
}, floating: HTMLElement, options?: PositionFloatingOptions): () => void;
|
|
2754
|
+
declare function splitListForInsert(state: EditorState, tr: Transaction): SplitListForInsertRange | null;
|
|
2755
|
+
|
|
2470
2756
|
/**
|
|
2471
|
-
*
|
|
2472
|
-
*
|
|
2473
|
-
*
|
|
2474
|
-
*
|
|
2475
|
-
*
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
*
|
|
2757
|
+
* Shared helpers for locating a list/task item ancestor of a resolved
|
|
2758
|
+
* position. Centralises the `LIST_ITEM_TYPE_NAMES` constant + ancestor
|
|
2759
|
+
* walk so the four+ consumers (liftCurrentListItem, splitListForInsert,
|
|
2760
|
+
* TaskItem keymap, Details proactive lift, slash menu filtering) stay
|
|
2761
|
+
* in sync.
|
|
2762
|
+
*/
|
|
2763
|
+
|
|
2764
|
+
declare const LIST_ITEM_TYPE_NAMES: Set<string>;
|
|
2765
|
+
/**
|
|
2766
|
+
* Returns the depth at which the nearest list/task item ancestor sits,
|
|
2767
|
+
* or -1 if none.
|
|
2481
2768
|
*
|
|
2482
|
-
*
|
|
2483
|
-
* floating element.
|
|
2769
|
+
* Walks UP from `$pos.depth` toward 1 (we skip depth 0 = doc itself).
|
|
2484
2770
|
*/
|
|
2485
|
-
declare function
|
|
2486
|
-
|
|
2487
|
-
|
|
2771
|
+
declare function findListItemAncestorDepth($pos: ResolvedPos): number;
|
|
2772
|
+
/** Convenience: true when the cursor has a list/task item ancestor. */
|
|
2773
|
+
declare function isInsideListItem($pos: ResolvedPos): boolean;
|
|
2774
|
+
/**
|
|
2775
|
+
* True when the cursor sits in the LABEL paragraph (index 0) of its
|
|
2776
|
+
* nearest list/task item ancestor. Used to gate Notion-style "operate
|
|
2777
|
+
* on the label" commands (slash menu CONVERT, INSERT, etc.).
|
|
2778
|
+
*/
|
|
2779
|
+
declare function isInListItemLabel($pos: ResolvedPos): boolean;
|
|
2488
2780
|
|
|
2489
2781
|
/**
|
|
2490
2782
|
* Create a ProseMirror document from content
|
|
@@ -3160,7 +3452,7 @@ declare class Extension<Options = unknown, Storage = unknown> {
|
|
|
3160
3452
|
* // Shallow merge behavior with nested objects:
|
|
3161
3453
|
* // Given: options = { nested: { a: 1, b: 2 } }
|
|
3162
3454
|
* // configure({ nested: { b: 3 } })
|
|
3163
|
-
* // Result: { nested: { b: 3 } }
|
|
3455
|
+
* // Result: { nested: { b: 3 } } - 'a' is lost!
|
|
3164
3456
|
* // To preserve nested values, spread manually:
|
|
3165
3457
|
* // configure({ nested: { ...original.options.nested, b: 3 } })
|
|
3166
3458
|
*/
|
|
@@ -3289,25 +3581,12 @@ declare class Node<Options = unknown, Storage = unknown> extends Extension<Optio
|
|
|
3289
3581
|
*/
|
|
3290
3582
|
static create<O = unknown, S = unknown>(config: NodeConfig<O, S>): Node<O, S>;
|
|
3291
3583
|
/**
|
|
3292
|
-
* Creates a new node with merged options
|
|
3293
|
-
*
|
|
3294
|
-
*
|
|
3295
|
-
* **Note:** Options are merged shallowly using object spread (`...`).
|
|
3296
|
-
* Nested objects are replaced entirely, not deeply merged.
|
|
3297
|
-
*
|
|
3298
|
-
* @param options - Options to merge with existing options
|
|
3299
|
-
* @returns New node instance with merged options
|
|
3584
|
+
* Creates a new node with merged options. Original node is not modified.
|
|
3585
|
+
* Options merge shallowly (object spread); see {@link Extension.configure}
|
|
3586
|
+
* for the nested-object gotcha and a workaround.
|
|
3300
3587
|
*
|
|
3301
3588
|
* @example
|
|
3302
3589
|
* const CustomParagraph = Paragraph.configure({ HTMLAttributes: { class: 'custom' } });
|
|
3303
|
-
*
|
|
3304
|
-
* @example
|
|
3305
|
-
* // Shallow merge behavior with nested objects:
|
|
3306
|
-
* // Given: options = { HTMLAttributes: { class: 'a', id: 'b' } }
|
|
3307
|
-
* // configure({ HTMLAttributes: { class: 'c' } })
|
|
3308
|
-
* // Result: { HTMLAttributes: { class: 'c' } } — 'id' is lost!
|
|
3309
|
-
* // To preserve nested values, spread manually:
|
|
3310
|
-
* // configure({ HTMLAttributes: { ...original.options.HTMLAttributes, class: 'c' } })
|
|
3311
3590
|
*/
|
|
3312
3591
|
configure(options: Partial<Options>): Node<Options, Storage>;
|
|
3313
3592
|
/**
|
|
@@ -3351,7 +3630,7 @@ declare class Node<Options = unknown, Storage = unknown> extends Extension<Optio
|
|
|
3351
3630
|
}
|
|
3352
3631
|
|
|
3353
3632
|
/**
|
|
3354
|
-
* ToolbarController
|
|
3633
|
+
* ToolbarController - Headless, framework-agnostic toolbar state machine
|
|
3355
3634
|
*
|
|
3356
3635
|
* Manages toolbar item collection, grouping, active state tracking,
|
|
3357
3636
|
* dropdown state, and keyboard navigation. Framework wrappers (Angular,
|
|
@@ -3359,7 +3638,7 @@ declare class Node<Options = unknown, Storage = unknown> extends Extension<Optio
|
|
|
3359
3638
|
*
|
|
3360
3639
|
* @example
|
|
3361
3640
|
* const controller = new ToolbarController(editor, () => {
|
|
3362
|
-
* // Called on every state change
|
|
3641
|
+
* // Called on every state change - trigger framework re-render
|
|
3363
3642
|
* });
|
|
3364
3643
|
* controller.subscribe();
|
|
3365
3644
|
* // ... use controller.groups, controller.activeMap, etc.
|
|
@@ -3419,7 +3698,7 @@ declare class ToolbarController {
|
|
|
3419
3698
|
private _activeMap;
|
|
3420
3699
|
/** Disabled state for each button (keyed by item.name) */
|
|
3421
3700
|
private _disabledMap;
|
|
3422
|
-
/** Expanded state for emitEvent buttons
|
|
3701
|
+
/** Expanded state for emitEvent buttons - true when their panel is open */
|
|
3423
3702
|
private _expandedMap;
|
|
3424
3703
|
/** Currently open dropdown name (null = none) */
|
|
3425
3704
|
private _openDropdown;
|
|
@@ -3518,6 +3797,124 @@ declare class ToolbarController {
|
|
|
3518
3797
|
private checkButtonExpanded;
|
|
3519
3798
|
}
|
|
3520
3799
|
|
|
3800
|
+
/**
|
|
3801
|
+
* A group of floating-menu items sharing the same `group` value.
|
|
3802
|
+
*/
|
|
3803
|
+
interface FloatingMenuGroup {
|
|
3804
|
+
name: string;
|
|
3805
|
+
items: FloatingMenuItem[];
|
|
3806
|
+
}
|
|
3807
|
+
/**
|
|
3808
|
+
* Groups items by their `group` property, preserving extension insertion
|
|
3809
|
+
* order of groups. Within each group, items are sorted by `priority`
|
|
3810
|
+
* descending (higher first, default 100).
|
|
3811
|
+
*
|
|
3812
|
+
* Shared between `FloatingMenuController` (which renders grouped item lists
|
|
3813
|
+
* for FloatingMenu + framework wrappers) and `createSlashSuggestionRenderer`
|
|
3814
|
+
* (the popup shown by SlashCommand). Having one implementation keeps visual
|
|
3815
|
+
* grouping consistent across every trigger mechanism.
|
|
3816
|
+
*/
|
|
3817
|
+
declare function groupFloatingMenuItems(items: FloatingMenuItem[]): FloatingMenuGroup[];
|
|
3818
|
+
|
|
3819
|
+
/**
|
|
3820
|
+
* FloatingMenuController - Headless, framework-agnostic state machine for the
|
|
3821
|
+
* block-insert floating menu.
|
|
3822
|
+
*
|
|
3823
|
+
* Mirrors the shape of ToolbarController: collects items from extensions,
|
|
3824
|
+
* groups them, tracks focused index for roving-tabindex keyboard navigation,
|
|
3825
|
+
* and executes commands. Framework wrappers (Angular, React, Vue) bind their
|
|
3826
|
+
* templates to this controller.
|
|
3827
|
+
*
|
|
3828
|
+
* @example
|
|
3829
|
+
* const controller = new FloatingMenuController(editor, () => {
|
|
3830
|
+
* // onChange - re-render
|
|
3831
|
+
* });
|
|
3832
|
+
* controller.subscribe();
|
|
3833
|
+
* // ... controller.groups, controller.focusedIndex, controller.execute(item)
|
|
3834
|
+
* controller.destroy();
|
|
3835
|
+
*/
|
|
3836
|
+
|
|
3837
|
+
/** -1 means no item is focused (menu not entered via keyboard). */
|
|
3838
|
+
declare const FLOATING_MENU_NO_FOCUS = -1;
|
|
3839
|
+
declare class FloatingMenuController {
|
|
3840
|
+
/**
|
|
3841
|
+
* Resolves an `items` option (array | function) against the editor's
|
|
3842
|
+
* default floating-menu items. Exposed as static so the plugin can
|
|
3843
|
+
* resolve once at init without constructing a controller.
|
|
3844
|
+
*/
|
|
3845
|
+
static resolveItems(editor: Editor, override?: FloatingMenuItemsOverride): FloatingMenuItem[];
|
|
3846
|
+
/**
|
|
3847
|
+
* Executes a floating-menu item's command on the editor.
|
|
3848
|
+
* String commands are dispatched via `editor.commands[name](...args)`;
|
|
3849
|
+
* function commands are called directly.
|
|
3850
|
+
*/
|
|
3851
|
+
static executeItem(editor: Editor, item: FloatingMenuItem): void;
|
|
3852
|
+
private editor;
|
|
3853
|
+
private onChange;
|
|
3854
|
+
private override;
|
|
3855
|
+
private transactionHandler;
|
|
3856
|
+
private _groups;
|
|
3857
|
+
private _flatItems;
|
|
3858
|
+
private _disabledMap;
|
|
3859
|
+
private _focusedIndex;
|
|
3860
|
+
constructor(editor: Editor, onChange: () => void, override?: FloatingMenuItemsOverride);
|
|
3861
|
+
get groups(): FloatingMenuGroup[];
|
|
3862
|
+
get flatItems(): FloatingMenuItem[];
|
|
3863
|
+
get disabledMap(): ReadonlyMap<string, boolean>;
|
|
3864
|
+
get focusedIndex(): number;
|
|
3865
|
+
/** True when keyboard focus is inside the menu (at least one item focused). */
|
|
3866
|
+
get isEntered(): boolean;
|
|
3867
|
+
get itemCount(): number;
|
|
3868
|
+
isDisabled(item: FloatingMenuItem): boolean;
|
|
3869
|
+
/**
|
|
3870
|
+
* Executes an item's command, then closes the menu keyboard focus.
|
|
3871
|
+
* Callers should refocus the editor after calling this.
|
|
3872
|
+
*/
|
|
3873
|
+
execute(item: FloatingMenuItem): void;
|
|
3874
|
+
/**
|
|
3875
|
+
* Rebuilds items from the editor. Call when the editor's extensions
|
|
3876
|
+
* change (rare) or on explicit refresh. Notification is delegated to
|
|
3877
|
+
* `updateDisabledStates` which fires `onChange` only when a disabled
|
|
3878
|
+
* state flipped - wrappers that need to react to pure group-structure
|
|
3879
|
+
* changes do so by bumping their own render signal after constructing
|
|
3880
|
+
* / re-using the controller (see framework wrapper usage).
|
|
3881
|
+
*/
|
|
3882
|
+
rebuild(): void;
|
|
3883
|
+
/** Enter keyboard focus on the menu (first item). Called by the plugin's keymap. */
|
|
3884
|
+
enterMenu(): number;
|
|
3885
|
+
/** Leave keyboard focus (Escape). Refocus of the editor is the caller's job. */
|
|
3886
|
+
leaveMenu(): void;
|
|
3887
|
+
/** ArrowDown - wrap to first at end. */
|
|
3888
|
+
next(): number;
|
|
3889
|
+
/** ArrowUp - wrap to last at start. */
|
|
3890
|
+
prev(): number;
|
|
3891
|
+
first(): number;
|
|
3892
|
+
last(): number;
|
|
3893
|
+
/** Set focused index directly (e.g. on pointer hover). */
|
|
3894
|
+
setFocusedIndex(index: number): void;
|
|
3895
|
+
/** Get focused item (or null). */
|
|
3896
|
+
focusedItem(): FloatingMenuItem | null;
|
|
3897
|
+
/** Get flat index of item by name (for wrappers binding roving tabindex). */
|
|
3898
|
+
getFlatIndex(name: string): number;
|
|
3899
|
+
/** Subscribes to editor transactions for disabled-state tracking. */
|
|
3900
|
+
subscribe(): void;
|
|
3901
|
+
/** Unsubscribes and clears internal state. */
|
|
3902
|
+
destroy(): void;
|
|
3903
|
+
/**
|
|
3904
|
+
* Groups items by `group` preserving insertion order, then sorts by
|
|
3905
|
+
* priority (higher first) within each group. Delegates to the shared
|
|
3906
|
+
* utility so `SlashCommand`'s renderer and this controller always
|
|
3907
|
+
* produce identical ordering.
|
|
3908
|
+
*/
|
|
3909
|
+
private groupItems;
|
|
3910
|
+
/**
|
|
3911
|
+
* Updates disabled state for each item. Uses custom predicate when
|
|
3912
|
+
* provided; otherwise tries a dry-run against `editor.can()[command]`.
|
|
3913
|
+
* Only notifies on change to avoid noisy re-renders.
|
|
3914
|
+
*/
|
|
3915
|
+
private updateDisabledStates;
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3521
3918
|
declare const defaultIcons: IconSet;
|
|
3522
3919
|
|
|
3523
3920
|
/**
|
|
@@ -3619,25 +4016,12 @@ declare class Mark<Options = unknown, Storage = unknown> extends Extension<Optio
|
|
|
3619
4016
|
*/
|
|
3620
4017
|
static create<O = unknown, S = unknown>(config: MarkConfig<O, S>): Mark<O, S>;
|
|
3621
4018
|
/**
|
|
3622
|
-
* Creates a new mark with merged options
|
|
3623
|
-
*
|
|
3624
|
-
*
|
|
3625
|
-
* **Note:** Options are merged shallowly using object spread (`...`).
|
|
3626
|
-
* Nested objects are replaced entirely, not deeply merged.
|
|
3627
|
-
*
|
|
3628
|
-
* @param options - Options to merge with existing options
|
|
3629
|
-
* @returns New mark instance with merged options
|
|
4019
|
+
* Creates a new mark with merged options. Original mark is not modified.
|
|
4020
|
+
* Options merge shallowly (object spread); see {@link Extension.configure}
|
|
4021
|
+
* for the nested-object gotcha and a workaround.
|
|
3630
4022
|
*
|
|
3631
4023
|
* @example
|
|
3632
4024
|
* const CustomBold = Bold.configure({ HTMLAttributes: { class: 'custom-bold' } });
|
|
3633
|
-
*
|
|
3634
|
-
* @example
|
|
3635
|
-
* // Shallow merge behavior with nested objects:
|
|
3636
|
-
* // Given: options = { HTMLAttributes: { class: 'a', id: 'b' } }
|
|
3637
|
-
* // configure({ HTMLAttributes: { class: 'c' } })
|
|
3638
|
-
* // Result: { HTMLAttributes: { class: 'c' } } — 'id' is lost!
|
|
3639
|
-
* // To preserve nested values, spread manually:
|
|
3640
|
-
* // configure({ HTMLAttributes: { ...original.options.HTMLAttributes, class: 'c' } })
|
|
3641
4025
|
*/
|
|
3642
4026
|
configure(options: Partial<Options> & {
|
|
3643
4027
|
isFormatting?: boolean;
|
|
@@ -4086,14 +4470,19 @@ interface OrderedListOptions {
|
|
|
4086
4470
|
declare const OrderedList: Node<OrderedListOptions, unknown>;
|
|
4087
4471
|
|
|
4088
4472
|
/**
|
|
4089
|
-
*
|
|
4473
|
+
* Enter / Backspace state machine for listItem (cursor's parent must be a paragraph):
|
|
4090
4474
|
*
|
|
4091
|
-
*
|
|
4092
|
-
*
|
|
4475
|
+
* LABEL paragraph (childIndex 0):
|
|
4476
|
+
* Enter, empty -> liftListItem (exit empty bullet)
|
|
4477
|
+
* Enter, non-empty -> splitListItem (new sibling listItem)
|
|
4478
|
+
* Backspace, empty -> falls through to ListKeymap (liftListItem)
|
|
4093
4479
|
*
|
|
4094
|
-
*
|
|
4095
|
-
*
|
|
4096
|
-
* -
|
|
4480
|
+
* CHILDREN-ZONE paragraph (childIndex > 0):
|
|
4481
|
+
* Enter, empty -> insertChildrenZoneSibling (accumulate inside the item)
|
|
4482
|
+
* Enter, non-empty -> splitBlock (both halves stay inside the same item)
|
|
4483
|
+
* Backspace, empty -> liftEmptyChildrenZoneParagraph (exit as top-level)
|
|
4484
|
+
*
|
|
4485
|
+
* Tab / Shift-Tab handled by the ListKeymap extension.
|
|
4097
4486
|
*/
|
|
4098
4487
|
|
|
4099
4488
|
interface ListItemOptions {
|
|
@@ -4155,17 +4544,21 @@ interface TaskListOptions {
|
|
|
4155
4544
|
declare const TaskList: Node<TaskListOptions, unknown>;
|
|
4156
4545
|
|
|
4157
4546
|
/**
|
|
4158
|
-
*
|
|
4547
|
+
* Enter / Backspace state machine for taskItem (cursor's parent must be a paragraph):
|
|
4159
4548
|
*
|
|
4160
|
-
*
|
|
4161
|
-
*
|
|
4549
|
+
* LABEL paragraph (childIndex 0):
|
|
4550
|
+
* Enter, empty -> splitListItem fall-through, then taskItem-in-listItem
|
|
4551
|
+
* promotion (nested orderedList > listItem > taskList > taskItem
|
|
4552
|
+
* context), else liftListItem.
|
|
4553
|
+
* Enter, non-empty -> splitListItem (new sibling taskItem)
|
|
4554
|
+
* Backspace, empty -> liftListItem (exit empty checkbox)
|
|
4162
4555
|
*
|
|
4163
|
-
*
|
|
4164
|
-
*
|
|
4165
|
-
* -
|
|
4166
|
-
*
|
|
4167
|
-
*
|
|
4168
|
-
* - Mod-Enter
|
|
4556
|
+
* CHILDREN-ZONE paragraph (childIndex > 0):
|
|
4557
|
+
* Enter, empty -> insertChildrenZoneSibling (accumulate inside the item)
|
|
4558
|
+
* Enter, non-empty -> splitBlock (both halves stay inside the same item)
|
|
4559
|
+
* Backspace, empty -> liftEmptyChildrenZoneParagraph (exit as top-level)
|
|
4560
|
+
*
|
|
4561
|
+
* Tab / Shift-Tab sink / lift the item; Mod-Enter toggles checked state.
|
|
4169
4562
|
*/
|
|
4170
4563
|
|
|
4171
4564
|
declare module '@domternal/core' {
|
|
@@ -4376,9 +4769,6 @@ declare module '@domternal/core' {
|
|
|
4376
4769
|
}
|
|
4377
4770
|
}
|
|
4378
4771
|
|
|
4379
|
-
/**
|
|
4380
|
-
* Options for the Link mark
|
|
4381
|
-
*/
|
|
4382
4772
|
interface LinkOptions {
|
|
4383
4773
|
/**
|
|
4384
4774
|
* HTML attributes to add to the rendered element
|
|
@@ -4882,6 +5272,61 @@ interface ListKeymapOptions {
|
|
|
4882
5272
|
}
|
|
4883
5273
|
declare const ListKeymap: Extension<ListKeymapOptions, unknown>;
|
|
4884
5274
|
|
|
5275
|
+
/**
|
|
5276
|
+
* Keyboard indent across list boundaries. `Tab` on a top-level block whose
|
|
5277
|
+
* previous sibling is a list moves the block INTO the last item as a nested
|
|
5278
|
+
* child; `Shift-Tab` reverses for a block sitting as the last child of the
|
|
5279
|
+
* last item.
|
|
5280
|
+
*
|
|
5281
|
+
* Trigger is intentionally narrow so ListKeymap retains in-list Tab/Shift-Tab
|
|
5282
|
+
* (`sinkListItem` / `liftListItem`). Schema is validated via `canReplaceWith`;
|
|
5283
|
+
* invalid placements are a clean no-op so the keymap chain falls through.
|
|
5284
|
+
*
|
|
5285
|
+
* Intentional design restrictions (NOT bugs to "fix"):
|
|
5286
|
+
* - Tab indents into the IMMEDIATE last item only, not recursively into a
|
|
5287
|
+
* deeper "deepest last item". Users get deeper nesting via repeated Tab
|
|
5288
|
+
* inside the now-nested context (then ListKeymap takes over).
|
|
5289
|
+
* - Tab only fires for cursors in TOP-LEVEL blocks (depth === 1). Cursors
|
|
5290
|
+
* inside other containers (blockquote, table cell) fall through.
|
|
5291
|
+
* - Shift-Tab only fires when the block is BOTH the last child of its
|
|
5292
|
+
* item AND the item is the last in its wrapper. Mid-position outdent
|
|
5293
|
+
* would require splitting the list item, which is deferred.
|
|
5294
|
+
*
|
|
5295
|
+
* Registration order: must come AFTER ListKeymap so this extension's keymap
|
|
5296
|
+
* runs FIRST and can defer to ListKeymap for in-list flows.
|
|
5297
|
+
*/
|
|
5298
|
+
|
|
5299
|
+
/**
|
|
5300
|
+
* `Tab` handler: indent a top-level block as the last child of the
|
|
5301
|
+
* last item of the immediately-preceding list wrapper. Returns true
|
|
5302
|
+
* when the operation succeeded (and dispatched, if `dispatch` is
|
|
5303
|
+
* provided), false when any precondition fails so the keymap chain
|
|
5304
|
+
* can fall through to the next handler.
|
|
5305
|
+
*/
|
|
5306
|
+
declare function indentBlockAsListChild(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
|
|
5307
|
+
/**
|
|
5308
|
+
* `Shift-Tab` handler: lift a non-label nested block out of its list
|
|
5309
|
+
* item to become a top-level sibling AFTER the list wrapper. Only
|
|
5310
|
+
* fires for the strict end-of-end case (last child of last item) so
|
|
5311
|
+
* the lift is deterministic and never needs to split a list item.
|
|
5312
|
+
*
|
|
5313
|
+
* Precondition table:
|
|
5314
|
+
* - cursor empty
|
|
5315
|
+
* - cursor textblock parent is NOT a paragraph (so we never
|
|
5316
|
+
* accidentally outdent the label; ListKeymap.Shift-Tab handles
|
|
5317
|
+
* in-label cases via liftListItem)
|
|
5318
|
+
* - the cursor's enclosing list item exists in the ancestry
|
|
5319
|
+
* - the cursor's containing block is a DIRECT child of the list
|
|
5320
|
+
* item (depth = listItemDepth + 1) - keeps the math local to
|
|
5321
|
+
* immediate li children rather than reaching deeper into nested
|
|
5322
|
+
* containers
|
|
5323
|
+
* - the block is the LAST child of the list item
|
|
5324
|
+
* - the list item is the LAST child of its wrapper
|
|
5325
|
+
* - the wrapper's parent accepts the block as a sibling (schema)
|
|
5326
|
+
*/
|
|
5327
|
+
declare function outdentBlockFromListItem(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
|
|
5328
|
+
declare const ListIndent: Extension<unknown, unknown>;
|
|
5329
|
+
|
|
4885
5330
|
/**
|
|
4886
5331
|
* CharacterCount Extension
|
|
4887
5332
|
*
|
|
@@ -5113,25 +5558,8 @@ interface LineHeightOptions {
|
|
|
5113
5558
|
declare const LineHeight: Extension<LineHeightOptions, unknown>;
|
|
5114
5559
|
|
|
5115
5560
|
/**
|
|
5116
|
-
*
|
|
5117
|
-
*
|
|
5118
|
-
* Automatically assigns unique IDs to specified node types.
|
|
5119
|
-
* Useful for collaborative editing, linking, and history tracking.
|
|
5120
|
-
*
|
|
5121
|
-
* @example
|
|
5122
|
-
* ```ts
|
|
5123
|
-
* import { UniqueID } from '@domternal/core';
|
|
5124
|
-
*
|
|
5125
|
-
* const editor = new Editor({
|
|
5126
|
-
* extensions: [
|
|
5127
|
-
* // ... other extensions
|
|
5128
|
-
* UniqueID.configure({
|
|
5129
|
-
* types: ['paragraph', 'heading'],
|
|
5130
|
-
* attributeName: 'id',
|
|
5131
|
-
* }),
|
|
5132
|
-
* ],
|
|
5133
|
-
* });
|
|
5134
|
-
* ```
|
|
5561
|
+
* Canonical block-id system. Assigns ids to configured node types and is
|
|
5562
|
+
* read by TableOfContents and BlockContextMenu.
|
|
5135
5563
|
*/
|
|
5136
5564
|
|
|
5137
5565
|
declare const uniqueIDPluginKey: PluginKey<any>;
|
|
@@ -5159,6 +5587,70 @@ interface UniqueIDOptions {
|
|
|
5159
5587
|
}
|
|
5160
5588
|
declare const UniqueID: Extension<UniqueIDOptions, unknown>;
|
|
5161
5589
|
|
|
5590
|
+
/**
|
|
5591
|
+
* Tints whole blocks via `bgColor` / `textColor` attributes rendered as
|
|
5592
|
+
* `data-bg-color` / `data-text-color`. Theme's `_block-colors.scss` maps
|
|
5593
|
+
* names to CSS custom properties with light/dark variants. `null` clears
|
|
5594
|
+
* the attribute; unknown palette names are rejected by commands.
|
|
5595
|
+
*/
|
|
5596
|
+
|
|
5597
|
+
declare module '@domternal/core' {
|
|
5598
|
+
interface RawCommands {
|
|
5599
|
+
setBlockBgColor: CommandSpec<[color: string | null]>;
|
|
5600
|
+
setBlockTextColor: CommandSpec<[color: string | null]>;
|
|
5601
|
+
unsetBlockColors: CommandSpec;
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
/**
|
|
5605
|
+
* Notion's public palette. Names are semantic (not tied to specific hex);
|
|
5606
|
+
* the stylesheet owns the actual colors so themes can customize them.
|
|
5607
|
+
* `'default'` is implicit - represented by `null` (no data attribute).
|
|
5608
|
+
*/
|
|
5609
|
+
declare const DEFAULT_BLOCK_COLORS: string[];
|
|
5610
|
+
/**
|
|
5611
|
+
* Default set of block types that receive the color attributes. `codeBlock`
|
|
5612
|
+
* is intentionally excluded - `<pre><code>` already has its own background
|
|
5613
|
+
* that would conflict visually. Similarly, details-content blocks have
|
|
5614
|
+
* their own affordance. Callers can extend via `types` option.
|
|
5615
|
+
*/
|
|
5616
|
+
declare const DEFAULT_BLOCK_COLOR_TYPES: string[];
|
|
5617
|
+
interface BlockColorOptions {
|
|
5618
|
+
/**
|
|
5619
|
+
* Node types that receive `bgColor` / `textColor` attributes.
|
|
5620
|
+
* @default DEFAULT_BLOCK_COLOR_TYPES
|
|
5621
|
+
*/
|
|
5622
|
+
types: string[];
|
|
5623
|
+
/**
|
|
5624
|
+
* Palette used by the `setBlockBgColor` command. Commands reject values
|
|
5625
|
+
* outside this list (no-op + false return) so host apps can curate
|
|
5626
|
+
* what's selectable.
|
|
5627
|
+
* @default DEFAULT_BLOCK_COLORS
|
|
5628
|
+
*/
|
|
5629
|
+
bgColors: string[];
|
|
5630
|
+
/**
|
|
5631
|
+
* Palette used by the `setBlockTextColor` command.
|
|
5632
|
+
* @default DEFAULT_BLOCK_COLORS
|
|
5633
|
+
*/
|
|
5634
|
+
textColors: string[];
|
|
5635
|
+
}
|
|
5636
|
+
/**
|
|
5637
|
+
* Strip any inline `textStyle` marks inside [from, to] that carry the inline
|
|
5638
|
+
* counterpart of a block-level color attribute. Mutates the transaction in
|
|
5639
|
+
* place. This makes "last action wins": applying a block color erases
|
|
5640
|
+
* conflicting inline colors so the new block tint isn't visually hidden by
|
|
5641
|
+
* old span overrides.
|
|
5642
|
+
*
|
|
5643
|
+
* `which` may be 'text', 'bg', or 'both' - 'both' handles the unset case
|
|
5644
|
+
* in a single pass so the two strip operations don't step on each other's
|
|
5645
|
+
* replaced mark instances.
|
|
5646
|
+
*
|
|
5647
|
+
* Exported so `BlockContextMenu` (which writes node attrs directly via
|
|
5648
|
+
* `setNodeMarkup` instead of going through `setBlockBgColor` /
|
|
5649
|
+
* `setBlockTextColor`) shares the same conflict-stripping behavior.
|
|
5650
|
+
*/
|
|
5651
|
+
declare function stripInlineColorConflicts(tr: Transaction, state: EditorState, from: number, to: number, which: 'text' | 'bg' | 'both'): void;
|
|
5652
|
+
declare const BlockColor: Extension<BlockColorOptions, unknown>;
|
|
5653
|
+
|
|
5162
5654
|
/**
|
|
5163
5655
|
* Selection Extension
|
|
5164
5656
|
*
|
|
@@ -5237,7 +5729,7 @@ declare const Selection: Extension<SelectionOptions, SelectionStorage>;
|
|
|
5237
5729
|
* clicks outside the editor (approach A - same as Google Docs / Notion).
|
|
5238
5730
|
*
|
|
5239
5731
|
* Toolbar and bubble-menu buttons call `event.preventDefault()` on
|
|
5240
|
-
* `mousedown`, so they never trigger blur
|
|
5732
|
+
* `mousedown`, so they never trigger blur - the selection stays intact
|
|
5241
5733
|
* while the user interacts with editor UI.
|
|
5242
5734
|
*/
|
|
5243
5735
|
|
|
@@ -5358,6 +5850,8 @@ declare module '@domternal/core' {
|
|
|
5358
5850
|
interface RawCommands {
|
|
5359
5851
|
setTextColor: CommandSpec<[color: string]>;
|
|
5360
5852
|
unsetTextColor: CommandSpec;
|
|
5853
|
+
setTextColorToken: CommandSpec<[token: string | null]>;
|
|
5854
|
+
unsetTextColorToken: CommandSpec;
|
|
5361
5855
|
}
|
|
5362
5856
|
}
|
|
5363
5857
|
/**
|
|
@@ -5419,6 +5913,8 @@ declare module '@domternal/core' {
|
|
|
5419
5913
|
toggleHighlight: CommandSpec<[attributes?: {
|
|
5420
5914
|
color?: string;
|
|
5421
5915
|
}]>;
|
|
5916
|
+
setBackgroundColorToken: CommandSpec<[token: string | null]>;
|
|
5917
|
+
unsetBackgroundColorToken: CommandSpec;
|
|
5422
5918
|
}
|
|
5423
5919
|
}
|
|
5424
5920
|
/**
|
|
@@ -5534,6 +6030,59 @@ interface FontSizeOptions {
|
|
|
5534
6030
|
}
|
|
5535
6031
|
declare const FontSize: Extension<FontSizeOptions, unknown>;
|
|
5536
6032
|
|
|
6033
|
+
/**
|
|
6034
|
+
* NotionColorPicker Extension
|
|
6035
|
+
*
|
|
6036
|
+
* Provides toolbar registration for a Notion-style inline color picker that
|
|
6037
|
+
* drives the `colorToken` / `backgroundColorToken` attributes on the textStyle
|
|
6038
|
+
* mark (added by TextColor and Highlight).
|
|
6039
|
+
*
|
|
6040
|
+
* Owns:
|
|
6041
|
+
* - The shared named-token palette (default: 9 Notion-style colors).
|
|
6042
|
+
* - A bubble-menu-only toolbar item (`notionColor`) that emits a custom
|
|
6043
|
+
* `notionColorOpen` event when clicked. Framework wrappers listen for the
|
|
6044
|
+
* event and render the actual picker panel.
|
|
6045
|
+
*
|
|
6046
|
+
* The panel renders the full palette every time it opens; no MRU/recent
|
|
6047
|
+
* tracking is kept because all 18 swatches (9 text + 9 bg) fit in one view.
|
|
6048
|
+
*
|
|
6049
|
+
* @example
|
|
6050
|
+
* ```ts
|
|
6051
|
+
* import { TextStyle, TextColor, Highlight, NotionColorPicker } from '@domternal/core';
|
|
6052
|
+
*
|
|
6053
|
+
* const editor = new Editor({
|
|
6054
|
+
* extensions: [
|
|
6055
|
+
* TextStyle,
|
|
6056
|
+
* TextColor,
|
|
6057
|
+
* Highlight,
|
|
6058
|
+
* NotionColorPicker,
|
|
6059
|
+
* ],
|
|
6060
|
+
* });
|
|
6061
|
+
* ```
|
|
6062
|
+
*/
|
|
6063
|
+
|
|
6064
|
+
/**
|
|
6065
|
+
* Default named tokens. Match the BlockColor palette + theme tokens
|
|
6066
|
+
* (`--dm-block-text-<token>`, `--dm-block-bg-<token>`) so light and dark
|
|
6067
|
+
* themes render the right hex without any extra CSS work.
|
|
6068
|
+
*/
|
|
6069
|
+
declare const DEFAULT_NOTION_COLOR_PALETTE: readonly string[];
|
|
6070
|
+
interface NotionColorPickerOptions {
|
|
6071
|
+
/**
|
|
6072
|
+
* Named tokens shown in the picker. Each token must have matching
|
|
6073
|
+
* `--dm-block-text-<token>` and `--dm-block-bg-<token>` CSS variables in
|
|
6074
|
+
* the active theme; tokens with no theme support render as transparent
|
|
6075
|
+
* swatches.
|
|
6076
|
+
* @default DEFAULT_NOTION_COLOR_PALETTE
|
|
6077
|
+
*/
|
|
6078
|
+
palette: readonly string[];
|
|
6079
|
+
}
|
|
6080
|
+
interface NotionColorPickerStorage {
|
|
6081
|
+
/** Whether the picker panel is currently open. UI sets this. */
|
|
6082
|
+
isOpen: boolean;
|
|
6083
|
+
}
|
|
6084
|
+
declare const NotionColorPicker: Extension<NotionColorPickerOptions, NotionColorPickerStorage>;
|
|
6085
|
+
|
|
5537
6086
|
/**
|
|
5538
6087
|
* ClearFormatting Extension
|
|
5539
6088
|
*
|
|
@@ -5569,33 +6118,7 @@ interface LinkPopoverOptions {
|
|
|
5569
6118
|
declare const LinkPopover: Extension<LinkPopoverOptions, unknown>;
|
|
5570
6119
|
|
|
5571
6120
|
/**
|
|
5572
|
-
*
|
|
5573
|
-
*
|
|
5574
|
-
* Shows a floating menu when text is selected in the editor.
|
|
5575
|
-
* Useful for formatting toolbars that appear contextually.
|
|
5576
|
-
*
|
|
5577
|
-
* Styles are included automatically via `@domternal/theme` (`_bubble-menu.scss`).
|
|
5578
|
-
*
|
|
5579
|
-
* @example
|
|
5580
|
-
* ```ts
|
|
5581
|
-
* import { BubbleMenu } from '@domternal/core';
|
|
5582
|
-
*
|
|
5583
|
-
* // Create menu element
|
|
5584
|
-
* const menuElement = document.getElementById('bubble-menu');
|
|
5585
|
-
*
|
|
5586
|
-
* const editor = new Editor({
|
|
5587
|
-
* extensions: [
|
|
5588
|
-
* // ... other extensions
|
|
5589
|
-
* BubbleMenu.configure({
|
|
5590
|
-
* element: menuElement,
|
|
5591
|
-
* shouldShow: ({ editor, state, from, to }) => {
|
|
5592
|
-
* // Only show for text selections
|
|
5593
|
-
* return !state.selection.empty;
|
|
5594
|
-
* },
|
|
5595
|
-
* }),
|
|
5596
|
-
* ],
|
|
5597
|
-
* });
|
|
5598
|
-
* ```
|
|
6121
|
+
* Floating menu shown when text is selected. Contextual formatting toolbar.
|
|
5599
6122
|
*/
|
|
5600
6123
|
|
|
5601
6124
|
declare const bubbleMenuPluginKey: PluginKey<any>;
|
|
@@ -5649,76 +6172,6 @@ interface CreateBubbleMenuPluginOptions {
|
|
|
5649
6172
|
declare function createBubbleMenuPlugin(options: CreateBubbleMenuPluginOptions): Plugin;
|
|
5650
6173
|
declare const BubbleMenu: Extension<BubbleMenuOptions, unknown>;
|
|
5651
6174
|
|
|
5652
|
-
/**
|
|
5653
|
-
* FloatingMenu Extension
|
|
5654
|
-
*
|
|
5655
|
-
* Shows a floating menu when the cursor is in an empty paragraph.
|
|
5656
|
-
* Useful for showing block-level insertion options.
|
|
5657
|
-
*
|
|
5658
|
-
* @example
|
|
5659
|
-
* ```ts
|
|
5660
|
-
* import { FloatingMenu } from '@domternal/core';
|
|
5661
|
-
*
|
|
5662
|
-
* // Create menu element
|
|
5663
|
-
* const menuElement = document.getElementById('floating-menu');
|
|
5664
|
-
*
|
|
5665
|
-
* const editor = new Editor({
|
|
5666
|
-
* extensions: [
|
|
5667
|
-
* // ... other extensions
|
|
5668
|
-
* FloatingMenu.configure({
|
|
5669
|
-
* element: menuElement,
|
|
5670
|
-
* shouldShow: ({ editor, state }) => {
|
|
5671
|
-
* const { $from, empty } = state.selection;
|
|
5672
|
-
* // Show in empty paragraphs
|
|
5673
|
-
* return empty &&
|
|
5674
|
-
* $from.parent.type.name === 'paragraph' &&
|
|
5675
|
-
* $from.parent.content.size === 0;
|
|
5676
|
-
* },
|
|
5677
|
-
* }),
|
|
5678
|
-
* ],
|
|
5679
|
-
* });
|
|
5680
|
-
* ```
|
|
5681
|
-
*
|
|
5682
|
-
* Styles are included automatically via `@domternal/theme` (`_floating-menu.scss`).
|
|
5683
|
-
*/
|
|
5684
|
-
|
|
5685
|
-
declare const floatingMenuPluginKey: PluginKey<any>;
|
|
5686
|
-
interface FloatingMenuOptions {
|
|
5687
|
-
/**
|
|
5688
|
-
* The HTML element that contains the menu.
|
|
5689
|
-
* Must be provided by the user.
|
|
5690
|
-
*/
|
|
5691
|
-
element: HTMLElement | null;
|
|
5692
|
-
/**
|
|
5693
|
-
* Function to determine if the menu should be shown.
|
|
5694
|
-
* By default, shows when the cursor is in an empty paragraph.
|
|
5695
|
-
*/
|
|
5696
|
-
shouldShow: (props: {
|
|
5697
|
-
editor: Editor;
|
|
5698
|
-
view: EditorView;
|
|
5699
|
-
state: EditorState;
|
|
5700
|
-
}) => boolean;
|
|
5701
|
-
/**
|
|
5702
|
-
* Offset in pixels from the cursor position.
|
|
5703
|
-
* @default 0
|
|
5704
|
-
*/
|
|
5705
|
-
offset: number;
|
|
5706
|
-
}
|
|
5707
|
-
interface CreateFloatingMenuPluginOptions {
|
|
5708
|
-
pluginKey: PluginKey;
|
|
5709
|
-
editor: Editor;
|
|
5710
|
-
element: HTMLElement;
|
|
5711
|
-
shouldShow?: FloatingMenuOptions['shouldShow'];
|
|
5712
|
-
offset?: number;
|
|
5713
|
-
}
|
|
5714
|
-
/**
|
|
5715
|
-
* Creates a standalone FloatingMenu ProseMirror plugin.
|
|
5716
|
-
* Can be used by framework wrappers (Angular, React, Vue) to create the plugin
|
|
5717
|
-
* independently of the extension system.
|
|
5718
|
-
*/
|
|
5719
|
-
declare function createFloatingMenuPlugin(options: CreateFloatingMenuPluginOptions): Plugin;
|
|
5720
|
-
declare const FloatingMenu: Extension<FloatingMenuOptions, unknown>;
|
|
5721
|
-
|
|
5722
6175
|
/**
|
|
5723
6176
|
* StarterKit Extension
|
|
5724
6177
|
*
|
|
@@ -5827,6 +6280,13 @@ interface StarterKitOptions {
|
|
|
5827
6280
|
* Set to false to disable the ListKeymap extension, or pass options to configure it.
|
|
5828
6281
|
*/
|
|
5829
6282
|
listKeymap?: false | Partial<ListKeymapOptions>;
|
|
6283
|
+
/**
|
|
6284
|
+
* Set to false to disable the ListIndent extension. ListIndent adds
|
|
6285
|
+
* Tab / Shift-Tab keymap that indents a top-level block under the
|
|
6286
|
+
* previous list (and outdents back). Registered AFTER ListKeymap so
|
|
6287
|
+
* the in-list-item Tab/Shift-Tab keep priority.
|
|
6288
|
+
*/
|
|
6289
|
+
listIndent?: false;
|
|
5830
6290
|
/**
|
|
5831
6291
|
* Set to false to disable the LinkPopover extension, or pass options to configure it.
|
|
5832
6292
|
*/
|
|
@@ -5846,4 +6306,4 @@ declare const StarterKit: Extension<StarterKitOptions, unknown>;
|
|
|
5846
6306
|
*/
|
|
5847
6307
|
declare const VERSION = "0.1.0";
|
|
5848
6308
|
|
|
5849
|
-
export { type AnyExtension, type AnyExtensionConfig, type AttributeSpec, type AttributeSpecs, type AutolinkPluginOptions, BaseKeymap, type BaseKeymapOptions, Blockquote, type BlockquoteOptions, Bold, type BoldOptions, BubbleMenu, type BubbleMenuOptions, type BuildCommandPropsOptions, BulletList, type BulletListOptions, type CanChainedCommands, CanChecker, type CanCheckerEditor, type CanCheckerOptions, type CanCommands, ChainBuilder, type ChainBuilderEditor, type ChainBuilderOptions, type ChainFailure, type ChainedCommands, CharacterCount, type CharacterCountOptions, type CharacterCountStorage, type ClearContentOptions, ClearFormatting, Code, CodeBlock, type CodeBlockOptions, type CodeOptions, type Command, type CommandEditor, CommandManager, type CommandManagerEditor, type CommandMap, type CommandProps, type CommandPropsEditor, type CommandSpec$1 as CommandSpec, type Content, type ContentErrorProps, type CreateBubbleMenuPluginOptions, type CreateDocumentOptions, type CreateEventProps,
|
|
6309
|
+
export { type AnyExtension, type AnyExtensionConfig, type AttributeSpec, type AttributeSpecs, type AutolinkPluginOptions, BaseKeymap, type BaseKeymapOptions, BlockColor, type BlockColorOptions, Blockquote, type BlockquoteOptions, Bold, type BoldOptions, BubbleMenu, type BubbleMenuOptions, type BuildCommandPropsOptions, BulletList, type BulletListOptions, type CanChainedCommands, CanChecker, type CanCheckerEditor, type CanCheckerOptions, type CanCommands, ChainBuilder, type ChainBuilderEditor, type ChainBuilderOptions, type ChainFailure, type ChainedCommands, CharacterCount, type CharacterCountOptions, type CharacterCountStorage, type ClearContentOptions, ClearFormatting, Code, CodeBlock, type CodeBlockOptions, type CodeOptions, type Command, type CommandEditor, CommandManager, type CommandManagerEditor, type CommandMap, type CommandProps, type CommandPropsEditor, type CommandSpec$1 as CommandSpec, type Content, type ContentErrorProps, type CreateBubbleMenuPluginOptions, type CreateDocumentOptions, type CreateEventProps, DEFAULT_BLOCK_COLORS, DEFAULT_BLOCK_COLOR_TYPES, DEFAULT_HIGHLIGHT_COLORS, DEFAULT_NOTION_COLOR_PALETTE, DEFAULT_TEXT_COLORS, type DeleteEventProps, Document$1 as Document, type DropEventProps, Dropcursor, type DropcursorOptions, Editor, type EditorEventName, type EditorEvents, type EditorInstance, type EditorOptions, EventEmitter, Extension, type ExtensionConfig, type ExtensionEditor, ExtensionManager, type ExtensionManagerEditor, type ExtensionManagerOptions, FLOATING_MENU_NO_FOCUS, type FindChildResult, type FindParentNodeResult, FloatingMenuController, type FloatingMenuGroup, type FloatingMenuItem, type FloatingMenuItemsOverride, Focus, type FocusEventProps, type FocusOptions, type FocusPosition, FontFamily, type FontFamilyOptions, FontSize, type FontSizeOptions, Gapcursor, type GenerateHTMLOptions, type GenerateJSONOptions, type GenerateTextOptions, type GlobalAttributeSpec, type GlobalAttributes, HardBreak, type HardBreakOptions, Heading, type HeadingOptions, Highlight, type HighlightOptions, History, type HistoryOptions, HorizontalRule, type HorizontalRuleOptions, type IconSet, type InlineStyleOverrides, type InsertAsListItemChildArgs, type InsertAsListItemChildResult, InvisibleChars, type InvisibleCharsOptions, type InvisibleCharsStorage, type IsNodeEmptyOptions, type IsValidUrlOptions, Italic, type ItalicOptions, type JSONAttribute, type JSONContent, type JSONMark, type KeyboardShortcutCommand, LIST_ITEM_TYPE_NAMES, LineHeight, type LineHeightOptions, Link, type LinkAttributes, type LinkClickPluginOptions, type LinkExitPluginOptions, type LinkOptions, type LinkPastePluginOptions, LinkPopover, type LinkPopoverOptions, ListIndent, ListItem, type ListItemCursorContext, type ListItemOptions, ListKeymap, type ListKeymapOptions, Mark, type MarkConfig, type MarkInputRuleOptions, type MarkParseRule, type MarkRange, type MarkRenderHTMLProps, type MountEventProps, Node, type NodeConfig, type NodeInputRuleOptions, type NodeParseRule, type NodeRenderHTMLProps, type NodeViewContext, NotionColorPicker, type NotionColorPickerOptions, type NotionColorPickerStorage, OrderedList, type OrderedListOptions, Paragraph, type ParagraphOptions, type PasteEventProps, Placeholder, type PlaceholderOptions, type PositionFloatingOptions, type Range, type RawCommands, Selection, SelectionDecoration, type SelectionDecorationOptions, type SelectionOptions, type SelectionStorage, type SetContentOptions, type SingleCommands, type SplitListForInsertRange, StarterKit, type StarterKitOptions, Strike, type StrikeOptions, Subscript, type SubscriptOptions, Superscript, type SuperscriptOptions, TaskItem, type TaskItemOptions, TaskList, type TaskListOptions, Text, TextAlign, type TextAlignOptions, TextColor, type TextColorOptions, type TextInputRuleOptions, TextStyle, type TextStyleOptions, type TextblockTypeInputRuleOptions, type ToolbarButton, ToolbarController, type ToolbarControllerEditor, type ToolbarDropdown, type ToolbarGroup, type ToolbarItem, type ToolbarLayoutDropdown, type ToolbarLayoutEntry, type ToolbarSeparator, TrailingNode, type TrailingNodeOptions, type TransactionEventProps, Typography, type TypographyOptions, Underline, type UnderlineOptions, UniqueID, type UniqueIDOptions, VERSION, type WrappingInputRuleOptions, applyInlineStyles, autolinkPlugin, autolinkPluginKey, blur, bubbleMenuPluginKey, buildCommandProps, builtInCommands, callOrReturn, characterCountPluginKey, clearContent, createAccumulatingDispatch, createBubbleMenuPlugin, createCanChecker, createChainBuilder, createDocument, defaultBlockAt, defaultBubbleContexts, defaultIcons, deleteSelection, findChildren, findListItemAncestorDepth, findParentNode, focus, focusPluginKey, generateHTML, generateJSON, generateText, getListItemCursorContext, getMarkRange, groupFloatingMenuItems, indentBlockAsListChild, inlineStyles, insertAsListItemChild, insertChildrenZoneSibling, insertContent, insertText, invisibleCharsPluginKey, isDocumentEmpty, isInListItemLabel, isInsideListItem, isNodeEmpty, isValidUrl, lift, liftCurrentListItem, liftEmptyChildrenZoneParagraph, linkClickPlugin, linkClickPluginKey, linkExitPlugin, linkExitPluginKey, linkPastePlugin, linkPastePluginKey, markInputRule, markInputRulePatterns, nodeInputRule, outdentBlockFromListItem, placeholderPluginKey, positionFloating, positionFloatingOnce, resetAttributes, selectAll, selectNodeBackward, selectionDecorationPluginKey, setBlockType, setContent, setMark, splitListForInsert, stripInlineColorConflicts, textInputRule, textblockTypeInputRule, toggleBlockType, toggleList, toggleMark, toggleWrap, uniqueIDPluginKey, unsetAllMarks, unsetMark, updateAttributes, wrapIn, wrappingInputRule, writeToClipboard };
|