@barocss/extensions
The Extensions package provides extension functionality for Barocss Editor. Extensions allow you to add new commands, keybindings, and features to the editor.
Purpose
Extensions are the primary way to extend editor functionality. They provide:
- Commands: New operations that can be executed
- Keybindings: Keyboard shortcuts for commands
- Decorators: Visual overlays and widgets
- Lifecycle Hooks: onCreate, onDestroy for setup/cleanup
Key Exports
Extension- Base extension interfacecreateCoreExtensions()- Basic editing extensions (text, delete, paragraph, selection, indent, clipboard, hard break)createBasicExtensions()- Formatting extensions (bold, italic, heading, list, blockquote)createRichExtensions()- Full schema coverage (formatting marks, rich content, media, document structure, inline atoms)
Basic Usage
import { Editor } from '@barocss/editor-core';
import { createCoreExtensions, createBasicExtensions } from '@barocss/extensions';
const editor = new Editor({
dataStore,
schema,
extensions: [
...createCoreExtensions(), // Basic editing (insertText, delete, etc.)
...createBasicExtensions(), // Formatting (bold, italic, etc.)
]
});
Extension Structure
An extension is a class or object that implements the Extension interface:
import { Extension } from '@barocss/extensions';
class MyExtension implements Extension {
onCreate(context) {
// Register commands
context.registerCommand('myCommand', async (payload) => {
// Command implementation
});
// Register keybindings
context.registerKeybinding('Mod-k', 'myCommand', {
when: 'editorFocus'
});
}
onDestroy(context) {
// Cleanup
}
}
Extension Lifecycle
-
onCreate: Called when editor is created
- Register commands
- Register keybindings
- Register decorators
- Set up event listeners
-
Active State: Extension is active
- Commands can be executed
- Keybindings are active
- Event listeners are active
-
onDestroy: Called when editor is destroyed
- Clean up resources
- Remove event listeners
Registering Commands
Commands are the primary way to add functionality:
class MyExtension implements Extension {
onCreate(context) {
context.registerCommand('insertHello', async (payload) => {
const selection = context.editor.getSelection();
if (!selection) return;
await context.editor.executeCommand('insertText', {
text: 'Hello',
nodeId: selection.startNodeId,
offset: selection.startOffset
});
});
}
}
Registering Keybindings
Keybindings connect keyboard shortcuts to commands:
class MyExtension implements Extension {
onCreate(context) {
// Simple keybinding
context.registerKeybinding('Mod-h', 'insertHello');
// Keybinding with when condition
context.registerKeybinding('Mod-k', 'myCommand', {
when: 'editorFocus && editorEditable'
});
}
}
Extension Sets
Pre-built extension sets provide common functionality:
Core Extensions
Required editing primitives (auto-registered):
TextExtension- Text input, replaceDeleteExtension- Backspace, DeleteParagraphExtension- Paragraph structureMoveSelectionExtension- Arrow key cursor movementSelectAllExtension- Select all (Mod+a)IndentExtension- Tab/Shift+Tab indentationCopyPasteExtension- Clipboard operations (Mod+c/x/v)EscapeExtension- Escape key handlingHardBreakExtension- Line break within block (Shift+Enter)
Basic Extensions
Text formatting:
BoldExtension- Toggle bold (Mod+b)ItalicExtension- Toggle italic (Mod+i)HeadingExtension- Heading levels 1-6 (Mod+Alt+1-6)ListExtension- Bullet and numbered listsBlockquoteExtension- Blockquotes
Rich Extensions
Full schema-complete extension set covering all 48 node types and 24 marks:
Formatting Marks:
UnderlineExtension- Underline (cross-node)StrikeThroughExtension- Strikethrough (cross-node)CodeMarkExtension- Inline codeHighlightExtension- Text highlightFontColorExtension- Font color and background colorSubSuperExtension- Subscript/superscriptFontSizeExtension- Font sizeFontFamilyExtension- Font familyTextFormattingExtension- smallCaps, kbd, spoiler, letterSpacing, wordSpacing, lineHeight, textShadow, border, spanLangMentionExtension- @mentionsFootnoteExtension- Footnote def/ref
Rich Content Blocks:
LinkExtension- Link insert/removeImageExtension- Image insertionCodeBlockExtension- Code blocksHorizontalRuleExtension- Horizontal rulesPageBreakExtension- Page breaksTableExtension- Table (table, row, cell, header)ChecklistExtension- Checklist/task itemsCalloutExtension- Callout/admonitionMathBlockExtension- Math equations (block)MathInlineExtension- Math equations (inline)CommentExtension- Comment threads
Block Structures:
PullQuoteExtension- Pull quotesColumnsExtension- Multi-column layoutTocExtension- Table of contentsDetailsExtension- Collapsible contentDescriptionListExtension- Description listsFigureExtension- Figure with caption
Media:
MediaExtension- Video, audio, embed
Inline Atoms:
BookmarkExtension- Bookmark anchorsFieldExtension- Document fields (page number, date, title, author)
Document Structure:
DocStructureExtension- Section, header, footer, bibliography, endnote, index, chart
UX Extensions
User experience enhancements:
MoveBlockExtension- Block reordering (Mod+ArrowUp/Down)DragDropExtension- Block-level drag and dropSlashCommandExtension- Slash command palette (/)FloatingToolbarExtension- Floating toolbar on selectionFindReplaceExtension- Find and replace (Mod+f,Mod+h)
Custom Extensions
Create your own extensions:
import { Extension } from '@barocss/extensions';
class CommentExtension implements Extension {
onCreate(context) {
// Register comment command
context.registerCommand('comment.add', async (payload) => {
const { nodeId, range } = payload;
// Add comment decorator
context.editor.viewDOM?.decoratorManager.add({
id: `comment-${Date.now()}`,
category: 'inline',
type: 'comment',
target: { nodeId, startOffset: range[0], endOffset: range[1] },
data: { text: payload.text }
});
});
// Register keybinding
context.registerKeybinding('Mod-Shift-m', 'comment.add', {
when: 'editorFocus && !selectionEmpty'
});
}
onDestroy(context) {
// Cleanup if needed
}
}
Extension Context
Extensions receive a context object with:
interface ExtensionContext {
editor: Editor;
dataStore: DataStore;
schema: Schema;
registerCommand: (name: string, handler: CommandHandler) => void;
registerKeybinding: (key: string, command: string, options?: KeybindingOptions) => void;
registerDecorator: (type: string, renderer: DecoratorRenderer) => void;
setContext: (key: string, value: unknown) => void;
getContext: (key: string) => unknown;
}
Integration
Extensions integrate with:
- Editor Core: Commands and keybindings are registered with editor
- Model: Commands execute transactions
- Editor View DOM: Decorators are rendered in view layer
- DataStore: All operations go through DataStore
When to Use Extensions
- Add New Commands: Create new editing operations
- Add Keyboard Shortcuts: Map keys to commands
- Add Visual Features: Decorators, toolbars, etc.
- Customize Editor Behavior: Modify default behavior
Related
- Extension Design Guide - Detailed extension development guide
- Editor Core - How extensions integrate with editor
- Core Concepts: Decorators - How to use decorators