Using Extensions
Extensions are at the heart of ProseKit’s flexibility and power. They allow you to add functionality to your editor in a modular way, making it easy to build exactly the editing experience you need.
Extensions in ProseKit are modular pieces of functionality that you can add to your editor. They can provide:
- Nodes (paragraphs, headings, lists, code blocks, etc.)
- Marks (bold, italic, underline, etc.)
- Commands (functions that modify the document)
- Keyboard shortcuts
- Input rules (automatic transformations as you type)
- Custom behaviors and much more
ProseKit provides a defineBasicExtension()
function that includes the most common features:
import {
} from 'prosekit/basic' import { defineBasicExtension function defineBasicExtension(): BasicExtension
Define a basic extension that includes some common functionality. You can copy this function and customize it to your needs. It's a combination of the following extension functions: - {@link defineDoc } - {@link defineText } - {@link defineParagraph } - {@link defineHeading } - {@link defineList } - {@link defineBlockquote } - {@link defineImage } - {@link defineHorizontalRule } - {@link defineTable } - {@link defineCodeBlock } - {@link defineItalic } - {@link defineBold } - {@link defineUnderline } - {@link defineStrike } - {@link defineCode } - {@link defineLink } - {@link defineBaseKeymap } - {@link defineBaseCommands } - {@link defineHistory } - {@link defineDropCursor } - {@link defineGapCursor } - {@link defineVirtualSelection } - {@link defineModClickPrevention }} from 'prosekit/core' // Create an editor with the extension const createEditor function createEditor<E extends Extension>(options: EditorOptions<E>): Editor<E>
= editor const editor: Editor<BasicExtension>
({ createEditor createEditor<BasicExtension>(options: EditorOptions<BasicExtension>): Editor<BasicExtension>
: extension EditorOptions<BasicExtension>.extension: BasicExtension
The extension to use when creating the editor.() }) defineBasicExtension function defineBasicExtension(): BasicExtension
Define a basic extension that includes some common functionality. You can copy this function and customize it to your needs. It's a combination of the following extension functions: - {@link defineDoc } - {@link defineText } - {@link defineParagraph } - {@link defineHeading } - {@link defineList } - {@link defineBlockquote } - {@link defineImage } - {@link defineHorizontalRule } - {@link defineTable } - {@link defineCodeBlock } - {@link defineItalic } - {@link defineBold } - {@link defineUnderline } - {@link defineStrike } - {@link defineCode } - {@link defineLink } - {@link defineBaseKeymap } - {@link defineBaseCommands } - {@link defineHistory } - {@link defineDropCursor } - {@link defineGapCursor } - {@link defineVirtualSelection } - {@link defineModClickPrevention }
A key concept in ProseKit is that all extensions are composed of other extensions using the union
function. This composability lets you create complex functionality by combining simpler building blocks.
For example, defineBasicExtension
is simply a composition of many smaller extensions:
import {
, defineBaseCommands function defineBaseCommands(): BaseCommandsExtension
Add some base commands, defineBaseKeymap
function defineBaseKeymap(options?: { priority?: Priority; }): BaseKeymapExtension
Defines some basic key bindings., defineHistory function defineHistory({ depth, newGroupDelay, }?: HistoryOptions): HistoryExtension
Add undo/redo history to the editor., } from 'prosekit/core' import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions.} from 'prosekit/extensions/blockquote' import { defineBlockquote function defineBlockquote(): BlockquoteExtension
} from 'prosekit/extensions/bold' import { defineBold function defineBold(): BoldExtension
} from 'prosekit/extensions/code' import { defineCode function defineCode(): CodeExtension
} from 'prosekit/extensions/code-block' import { defineCodeBlock function defineCodeBlock(): CodeBlockExtension
Adds `codeBlock` nodes to the editor. This includes the following extensions: - {@link defineCodeBlockSpec } - {@link defineCodeBlockInputRule } - {@link defineCodeBlockEnterRule } - {@link defineCodeBlockKeymap } - {@link defineCodeBlockCommands } .} from 'prosekit/extensions/doc' import { defineDoc function defineDoc(): DocExtension
} from 'prosekit/extensions/drop-cursor' import { defineDropCursor function defineDropCursor(options?: DropCursorOptions): DropCursorExtension
Show up a decoration at the drop position when something is dragged over the editor. See [prosemirror-dropcursor](https://github.com/ProseMirror/prosemirror-dropcursor) for more information.} from 'prosekit/extensions/gap-cursor' import { defineGapCursor function defineGapCursor(): GapCursorExtension
Capture clicks near and arrow-key-motion past places that don't have a normally selectable position nearby, and create a gap cursor selection for them. The cursor is drawn as an element with class `ProseMirror-gapcursor`. You can either include `prosekit/extensions/gap-cursor.css` or add your own styles to make it visible. See [prosemirror-gapcursor](https://github.com/ProseMirror/prosemirror-gapcursor) for more information.} from 'prosekit/extensions/heading' import { defineHeading function defineHeading(): HeadingExtension
} from 'prosekit/extensions/horizontal-rule' import { defineHorizontalRule function defineHorizontalRule(): HorizontalRuleExtension
} from 'prosekit/extensions/image' import { defineImage function defineImage(): ImageExtension
} from 'prosekit/extensions/italic' import { defineItalic function defineItalic(): ItalicExtension
} from 'prosekit/extensions/link' import { defineLink function defineLink(): LinkExtension
} from 'prosekit/extensions/list' import { defineList function defineList(): ListExtension
} from 'prosekit/extensions/mod-click-prevention' import { defineModClickPrevention function defineModClickPrevention(): ModClickPreventionExtension
By default, clicking a node while holding the mod key will select the node. This extension disables that behavior.} from 'prosekit/extensions/paragraph' import { defineParagraph function defineParagraph(): ParagraphExtension
} from 'prosekit/extensions/strike' import { defineStrike function defineStrike(): StrikeExtension
} from 'prosekit/extensions/table' import { defineTable function defineTable(): TableExtension
} from 'prosekit/extensions/text' import { defineText function defineText(): TextExtension
} from 'prosekit/extensions/underline' import { defineUnderline function defineUnderline(): UnderlineExtension
} from 'prosekit/extensions/virtual-selection' function defineVirtualSelection function defineVirtualSelection(): VirtualSelectionExtension
Shows a virtual selection when the editor is not focused. When the editor is not focused, the selected inline content will be wrapped in a `<span>` element with the class `prosekit-virtual-selection`. This is useful when you want to move the focus to an element outside the editor, but still want to show the selection.() { return defineBasicExtension function defineBasicExtension(): Union<readonly [DocExtension, TextExtension, ParagraphExtension, HeadingExtension, ListExtension, ... 17 more ..., PlainExtension]>
( // Nodes union union<readonly [DocExtension, TextExtension, ParagraphExtension, HeadingExtension, ListExtension, ... 17 more ..., PlainExtension]>(exts_0: DocExtension, exts_1: TextExtension, exts_2: ParagraphExtension, exts_3: HeadingExtension, exts_4: ListExtension, exts_5: BlockquoteExtension, exts_6: ImageExtension, exts_7: HorizontalRuleExtension, exts_8: TableExtension, exts_9: CodeBlockExtension, exts_10: ItalicExtension, exts_11: BoldExtension, exts_12: UnderlineExtension, exts_13: StrikeExtension, exts_14: CodeExtension, exts_15: LinkExtension, exts_16: PlainExtension, exts_17: BaseCommandsExtension, exts_18: HistoryExtension, exts_19: PlainExtension, exts_20: PlainExtension, exts_21: PlainExtension, exts_22: PlainExtension): Union<...> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions.(), defineDoc function defineDoc(): DocExtension
(), defineText function defineText(): TextExtension
(), defineParagraph function defineParagraph(): ParagraphExtension
(), defineHeading function defineHeading(): HeadingExtension
(), defineList function defineList(): ListExtension
(), defineBlockquote function defineBlockquote(): BlockquoteExtension
(), defineImage function defineImage(): ImageExtension
(), defineHorizontalRule function defineHorizontalRule(): HorizontalRuleExtension
(), defineTable function defineTable(): TableExtension
(), // Marks defineCodeBlock function defineCodeBlock(): CodeBlockExtension
Adds `codeBlock` nodes to the editor. This includes the following extensions: - {@link defineCodeBlockSpec } - {@link defineCodeBlockInputRule } - {@link defineCodeBlockEnterRule } - {@link defineCodeBlockKeymap } - {@link defineCodeBlockCommands } .(), defineItalic function defineItalic(): ItalicExtension
(), defineBold function defineBold(): BoldExtension
(), defineUnderline function defineUnderline(): UnderlineExtension
(), defineStrike function defineStrike(): StrikeExtension
(), defineCode function defineCode(): CodeExtension
(), // Others defineLink function defineLink(): LinkExtension
(), defineBaseKeymap
function defineBaseKeymap(options?: { priority?: Priority; }): BaseKeymapExtension
Defines some basic key bindings.(), defineBaseCommands function defineBaseCommands(): BaseCommandsExtension
Add some base commands(), defineHistory function defineHistory({ depth, newGroupDelay, }?: HistoryOptions): HistoryExtension
Add undo/redo history to the editor.(), defineDropCursor function defineDropCursor(options?: DropCursorOptions): DropCursorExtension
Show up a decoration at the drop position when something is dragged over the editor. See [prosemirror-dropcursor](https://github.com/ProseMirror/prosemirror-dropcursor) for more information.(), defineGapCursor function defineGapCursor(): GapCursorExtension
Capture clicks near and arrow-key-motion past places that don't have a normally selectable position nearby, and create a gap cursor selection for them. The cursor is drawn as an element with class `ProseMirror-gapcursor`. You can either include `prosekit/extensions/gap-cursor.css` or add your own styles to make it visible. See [prosemirror-gapcursor](https://github.com/ProseMirror/prosemirror-gapcursor) for more information.(), defineVirtualSelection function defineVirtualSelection(): VirtualSelectionExtension
Shows a virtual selection when the editor is not focused. When the editor is not focused, the selected inline content will be wrapped in a `<span>` element with the class `prosekit-virtual-selection`. This is useful when you want to move the focus to an element outside the editor, but still want to show the selection.(), ) } defineModClickPrevention function defineModClickPrevention(): ModClickPreventionExtension
By default, clicking a node while holding the mod key will select the node. This extension disables that behavior.
This compositional pattern allows you to build on existing extensions and add exactly the features you need. For example, if you want all the functionality of the basic extension plus syntax highlighting for code blocks, you can simply combine them:
import {
} from 'prosekit/basic' import { defineBasicExtension function defineBasicExtension(): BasicExtension
Define a basic extension that includes some common functionality. You can copy this function and customize it to your needs. It's a combination of the following extension functions: - {@link defineDoc } - {@link defineText } - {@link defineParagraph } - {@link defineHeading } - {@link defineList } - {@link defineBlockquote } - {@link defineImage } - {@link defineHorizontalRule } - {@link defineTable } - {@link defineCodeBlock } - {@link defineItalic } - {@link defineBold } - {@link defineUnderline } - {@link defineStrike } - {@link defineCode } - {@link defineLink } - {@link defineBaseKeymap } - {@link defineBaseCommands } - {@link defineHistory } - {@link defineDropCursor } - {@link defineGapCursor } - {@link defineVirtualSelection } - {@link defineModClickPrevention }, createEditor function createEditor<E extends Extension>(options: EditorOptions<E>): Editor<E>
, } from 'prosekit/core' import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions.} from 'prosekit/extensions/code-block' function defineCodeBlockShiki function defineCodeBlockShiki({ themes, langs, ...rest }?: CodeBlockShikiOptions): Extension
Adds syntax highlighting to code blocks using the [Shiki](https://github.com/shikijs/shiki) package. It will set two CSS variables on the code block elements: - `--prosemirror-highlight`: sets text color - `--prosemirror-highlight-bg`: sets background color() { return defineMyExtension function defineMyExtension(): Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>
( union union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>(exts_0: BasicExtension, exts_1: Extension<ExtensionTyping<any, any, any>>): Union<...> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions.(), defineBasicExtension function defineBasicExtension(): BasicExtension
Define a basic extension that includes some common functionality. You can copy this function and customize it to your needs. It's a combination of the following extension functions: - {@link defineDoc } - {@link defineText } - {@link defineParagraph } - {@link defineHeading } - {@link defineList } - {@link defineBlockquote } - {@link defineImage } - {@link defineHorizontalRule } - {@link defineTable } - {@link defineCodeBlock } - {@link defineItalic } - {@link defineBold } - {@link defineUnderline } - {@link defineStrike } - {@link defineCode } - {@link defineLink } - {@link defineBaseKeymap } - {@link defineBaseCommands } - {@link defineHistory } - {@link defineDropCursor } - {@link defineGapCursor } - {@link defineVirtualSelection } - {@link defineModClickPrevention }(), ) } const defineCodeBlockShiki function defineCodeBlockShiki({ themes, langs, ...rest }?: CodeBlockShikiOptions): Extension
Adds syntax highlighting to code blocks using the [Shiki](https://github.com/shikijs/shiki) package. It will set two CSS variables on the code block elements: - `--prosemirror-highlight`: sets text color - `--prosemirror-highlight-bg`: sets background color= editor const editor: Editor<Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>>
({ createEditor createEditor<Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>>(options: EditorOptions<Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>>): Editor<...>
: extension EditorOptions<Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>>.extension: Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>
The extension to use when creating the editor.() }) defineMyExtension function defineMyExtension(): Union<readonly [BasicExtension, Extension<ExtensionTyping<any, any, any>>]>
Since each extension is composed of smaller parts, you can easily customize functionality by picking exactly which components you want. For example, the defineCode()
extension defines a mark spec, commands, keyboard shortcut, and input rule.
If you want to keep everything except the keyboard shortcut, you can inspect the source code of the defineCode()
extension, and create a custom version:
import {
} from 'prosekit/core' import { union function union<const E extends readonly Extension[]>(...exts: E): Union<E> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions., defineCodeCommands function defineCodeCommands(): CodeCommandsExtension
, defineCodeInputRule function defineCodeInputRule(): PlainExtension
, // Omitting defineCodeKeymap } from 'prosekit/extensions/code' function defineCodeSpec function defineCodeSpec(): CodeSpecExtension
() { return defineMyCode function defineMyCode(): Union<readonly [CodeSpecExtension, CodeCommandsExtension, PlainExtension]>
( union union<readonly [CodeSpecExtension, CodeCommandsExtension, PlainExtension]>(exts_0: CodeSpecExtension, exts_1: CodeCommandsExtension, exts_2: PlainExtension): Union<...> (+1 overload)
Merges multiple extensions into one. You can pass multiple extensions as arguments or a single array containing multiple extensions.(), defineCodeSpec function defineCodeSpec(): CodeSpecExtension
(), defineCodeCommands function defineCodeCommands(): CodeCommandsExtension
(), // No keyboard shortcut ) } defineCodeInputRule function defineCodeInputRule(): PlainExtension