What are Extensions?
Tiptap has three types of extensions:Extensions
Generic extensions that add functionality without defining content structure (e.g.,
StarterKit, Placeholder, CharacterCount)Nodes
Block or inline content types that make up your document (e.g.,
Paragraph, Heading, Image)Marks
Formatting that can be applied to text (e.g.,
Bold, Italic, Link)Extendable base class and can be used interchangeably in the extensions array.
Using Extensions
Extensions are passed to the editor via theextensions option:
Configuring Extensions
Most extensions accept options that can be configured using theconfigure() method:
Extension Structure
Every extension is created using theExtension.create(), Node.create(), or Mark.create() static methods:
/home/daytona/workspace/source/packages/core/src/Extension.ts:23
Extension API
Configuration
string
required
The unique name of the extension. This is used to identify the extension.
number
default:"100"
The priority determines the order in which extensions are loaded. Higher priority extensions are loaded first.
() => Options
Define default options for your extension.
() => Storage
Define storage that persists across the lifetime of the editor.Access storage via
editor.storage.extensionName:Commands
() => Commands
Add commands that can be called via Usage:
editor.commands.Keyboard Shortcuts
() => Record<string, () => boolean>
Add keyboard shortcuts for your extension.
Mod is Cmd on Mac and Ctrl on Windows/Linux.Input Rules
() => InputRule[]
Add input rules for markdown-style shortcuts.This would convert
**text** to bold text as you type.Paste Rules
() => PasteRule[]
Add paste rules for handling pasted content.
ProseMirror Plugins
() => Plugin[]
Add ProseMirror plugins to extend functionality.
Global Attributes
() => GlobalAttribute[]
Add attributes to multiple node or mark types.
Lifecycle Hooks
() => void
Called when the editor is created.
() => void
Called when the editor content changes.
() => void
Called when the selection changes.
({ transaction }) => void
Called for every transaction.
({ event }) => void
Called when the editor receives focus.
({ event }) => void
Called when the editor loses focus.
() => void
Called when the editor is destroyed. Use this to clean up resources.
Creating an Extension
Here’s a complete example of a custom extension:Usage
Extending Extensions
You can extend existing extensions to modify or add functionality:this.parent?.() call merges the parent extension’s attributes with your new ones.
Extension Packages
Tiptap provides many official extensions:Starter Kit
- Document
- Paragraph
- Text
- Bold
- Italic
- Strike
- Code
- Heading
- Blockquote
- BulletList
- OrderedList
- ListItem
- CodeBlock
- HardBreak
- HorizontalRule
- History
- Dropcursor
- Gapcursor
Individual Extensions
Real-World Example: Bold Extension
Here’s the actual implementation of the Bold extension from the Tiptap source:/home/daytona/workspace/source/packages/extension-bold/src/bold.tsx:56
TypeScript Support
Best Practices
Unique Names
Always use unique extension names to avoid conflicts.
Clean Up Resources
Use
onDestroy to clean up event listeners, timers, and other resources.Use TypeScript
Define types for your options and storage for better developer experience.
Test Thoroughly
Extensions can interact in unexpected ways. Test your extension with various combinations of other extensions.
Related
Nodes & Marks
Learn about creating node and mark extensions
Commands
Learn about the command system
Schema
Learn about how extensions generate the schema
Editor
Learn about the Editor class