@editu/core
Framework-agnostic core package containing Tiptap extensions, types, utilities, and styles.
Installation
npm install @editu/coreTIP
You typically don't need to install this package directly. It's included as a dependency of @editu/react.
Styles
Default Styles
import '@editu/core/styles.css';This stylesheet includes CSS variables and component styles.
Components Only
import '@editu/core/components.css';This stylesheet provides component styles without CSS variable definitions. Use it with custom theming or shadcn/ui.
Extensions
Editu provides pre-configured Tiptap extensions.
createEdituExtensions
This function creates the default set of Editu extensions.
import { createEdituExtensions } from '@editu/core';
const extensions = await createEdituExtensions({
placeholder: 'Start writing...',
features: {
markdown: true,
mathematics: true,
},
});Base Extensions (Always Included)
| Extension | Description |
|---|---|
Document | Document node |
Paragraph | Paragraph node |
Text | Text node |
Bold | Bold mark |
Italic | Italic mark |
Strike | Strikethrough mark |
Underline | Underline mark |
Code | Inline code mark |
Heading | H1-H6 headings |
BulletList | Bullet list |
OrderedList | Numbered list |
ListItem | List item |
Blockquote | Block quote |
HorizontalRule | Horizontal divider |
HardBreak | Line break |
History | Undo/redo |
Placeholder | Placeholder text |
Dropcursor | Drop cursor |
Gapcursor | Gap cursor |
Feature Extensions
| Feature | Extensions |
|---|---|
slashCommand | SlashCommand |
table | Table, TableRow, TableCell, TableHeader |
link | Link |
image | Image, ImageResize |
codeBlock | CodeBlockLowlight |
characterCount | CharacterCount |
textColor | Color, Highlight |
taskList | TaskList, TaskItem |
dragHandle | DragHandle |
markdown | Markdown |
mathematics | Mathematics |
embed | Embed |
details | Details, DetailsContent, DetailsSummary |
diagram | Diagram |
wikiLink | WikiLink |
comment | CommentMark |
callout | Callout |
mention | Mention |
tableOfContents | TableOfContents |
superscript | Superscript |
subscript | Subscript |
typography | Typography |
collaboration | Yjs extensions (Collaboration, CollaborationCursor) |
Types
EdituEditorOptions
import type { EdituEditorOptions } from '@editu/core';See Type Definitions for full interface.
EdituFeatureOptions
import type { EdituFeatureOptions } from '@editu/core';See Type Definitions for full interface.
EdituMarkdownFlavor
import type { EdituMarkdownFlavor } from '@editu/core';
type EdituMarkdownFlavor = "commonmark" | "gfm" | "obsidian" | "docusaurus";Supported Markdown output flavors. Controls how content is serialized when exporting Markdown. The default is "gfm".
EdituFlavorConfig
import type { EdituFlavorConfig } from '@editu/core';
interface EdituFlavorConfig {
/** How callout/admonition blocks are serialized */
calloutFormat: EdituCalloutMarkdownFormat;
/** Whether wiki links are serialized as [[page]] (true) or standard links (false) */
wikiLinkSerialize: boolean;
}Flavor-specific configuration resolved from a EdituMarkdownFlavor. Used internally by extensions to determine how to serialize Markdown.
EdituCalloutMarkdownFormat
import type { EdituCalloutMarkdownFormat } from '@editu/core';
type EdituCalloutMarkdownFormat =
| "github-alerts"
| "obsidian-callouts"
| "directives"
| "blockquote-fallback";Callout/admonition output format for Markdown serialization.
JSONContent
Tiptap's JSON content format. Import directly from @tiptap/core:
import type { JSONContent } from '@tiptap/core';
const content: JSONContent = {
type: 'doc',
content: [
{ type: 'paragraph', content: [{ type: 'text', text: 'Hello' }] }
],
};EdituSaveStatus
import type { EdituSaveStatus } from '@editu/core';
type EdituSaveStatus = 'saved' | 'saving' | 'unsaved' | 'error';Theme Types
import type { EdituTheme, EdituResolvedTheme } from '@editu/core';
type EdituTheme = 'light' | 'dark' | 'system';
type EdituResolvedTheme = 'light' | 'dark';Utilities
groupByConsecutiveField
This function groups items into consecutive runs by a string field. Items with the same field value that appear sequentially are placed in the same group. Non-adjacent items with the same value are placed in separate groups.
import { groupByConsecutiveField } from '@editu/core';
const items = [
{ group: "a", name: "1" },
{ group: "a", name: "2" },
{ group: "b", name: "3" },
{ group: "a", name: "4" },
];
const groups = groupByConsecutiveField(items, "group");
// [
// [{ group: "a", name: "1" }, { group: "a", name: "2" }],
// [{ group: "b", name: "3" }],
// [{ group: "a", name: "4" }],
// ]resolveEdituFeatures
This function resolves feature options to extension configuration.
import { resolveEdituFeatures } from '@editu/core';
const resolved = resolveEdituFeatures({
features: {
markdown: true,
mathematics: { katexOptions: { strict: false } },
},
createSlashMenuRenderer: mySlashMenuRenderer,
});resolveEdituFlavorConfig
This function resolves flavor-specific configuration from a Markdown flavor name.
import { resolveEdituFlavorConfig } from '@editu/core';
const config = resolveEdituFlavorConfig('obsidian');
// config.calloutFormat === "obsidian-callouts"
// config.wikiLinkSerialize === true
// Defaults to "gfm" when called without arguments
const defaultConfig = resolveEdituFlavorConfig();
// defaultConfig.calloutFormat === "github-alerts"
// defaultConfig.wikiLinkSerialize === falsegetEdituEditorState
This function returns the current editor state.
import { getEdituEditorState } from '@editu/core';
const state = getEdituEditorState(editor);
// {
// isFocused: boolean,
// isEmpty: boolean,
// canUndo: boolean,
// canRedo: boolean,
// characterCount: number,
// wordCount: number,
// }formatEdituRelativeTime
This function formats a date as relative time.
import { formatEdituRelativeTime } from '@editu/core';
formatEdituRelativeTime(new Date(Date.now() - 60000));
// "1m ago"Theme Utilities
getEdituSystemTheme
This function returns the system color scheme preference.
import { getEdituSystemTheme } from '@editu/core';
const theme = getEdituSystemTheme();
// 'light' | 'dark'resolveEdituTheme
This function resolves a theme setting to an actual theme value.
import { resolveEdituTheme } from '@editu/core';
resolveEdituTheme('system', 'dark');
// 'dark'applyEdituTheme
This function applies a theme to the DOM.
import { applyEdituTheme } from '@editu/core';
applyEdituTheme('dark', 'html');getEdituThemeInitScript
This function returns an inline script that prevents flash of unstyled content.
import { getEdituThemeInitScript } from '@editu/core';
const script = getEdituThemeInitScript('my-theme-key');
// Include in <head>Image Utilities
createEdituImageUploader
This function creates an image upload handler.
import { createEdituImageUploader } from '@editu/core';
const upload = createEdituImageUploader({
onUpload: async (file) => {
// Upload file
return 'https://example.com/image.png';
},
maxFileSize: 5 * 1024 * 1024,
allowedTypes: ['image/jpeg', 'image/png'],
});validateEdituImageFile
This function validates an image file against size and type constraints.
import { validateEdituImageFile } from '@editu/core';
const result = validateEdituImageFile(file, {
maxFileSize: 5 * 1024 * 1024,
allowedTypes: ['image/jpeg', 'image/png'],
});
if (!result.valid) {
console.error(result.error);
}Color Utilities
getEdituRecentColors
This function retrieves recent colors from localStorage.
import { getEdituRecentColors } from '@editu/core';
const colors = getEdituRecentColors('text');
// ['#ff0000', '#00ff00', ...]addEdituRecentColor
This function adds a color to the recent colors list.
import { addEdituRecentColor } from '@editu/core';
addEdituRecentColor('text', '#ff0000');Embed Utilities
detectEdituEmbedProvider
This function detects the oEmbed provider from a URL.
import { detectEdituEmbedProvider } from '@editu/core';
const provider = detectEdituEmbedProvider('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
// { name: 'YouTube', ... }Constants
EDITU_DEFAULT_FLAVOR
This constant defines the default Markdown output flavor.
import { EDITU_DEFAULT_FLAVOR } from '@editu/core';
// "gfm"EDITU_TEXT_COLORS
This constant defines the default text color palette.
import { EDITU_TEXT_COLORS } from '@editu/core';
// Array of { name: string, color: string }EDITU_HIGHLIGHT_COLORS
This constant defines the default highlight color palette.
import { EDITU_HIGHLIGHT_COLORS } from '@editu/core';
// Array of { name: string, color: string }edituDefaultEmbedProviders
This constant defines the default oEmbed providers.
import { edituDefaultEmbedProviders } from '@editu/core';
// YouTube, Vimeo, Twitter, etc.Toolbar
EdituToolbarAction
Type definition for a toolbar action.
import type { EdituToolbarAction } from '@editu/core';
interface EdituToolbarAction {
id: string;
label: string;
icon: EdituIconName;
group: string;
isActive: (editor: Editor) => boolean;
isEnabled: (editor: Editor) => boolean;
run: (editor: Editor) => void;
shortcut?: string;
}EdituToolbarDropdownAction
Type definition for a dropdown toolbar action that groups multiple sub-actions.
import type { EdituToolbarDropdownAction } from '@editu/core';
interface EdituToolbarDropdownAction {
id: string;
label: string;
icon: EdituIconName;
group: string;
type: 'dropdown';
options: EdituToolbarAction[];
getActiveOption?: (editor: Editor) => EdituToolbarAction | undefined;
}EdituToolbarActionItem
Union type for any toolbar item — either a simple action or a dropdown.
import type { EdituToolbarActionItem } from '@editu/core';
type EdituToolbarActionItem = EdituToolbarAction | EdituToolbarDropdownAction;isEdituToolbarDropdownAction
Type guard to check if a toolbar item is a dropdown action.
import { isEdituToolbarDropdownAction } from '@editu/core';
if (isEdituToolbarDropdownAction(action)) {
// action is EdituToolbarDropdownAction
action.options.forEach(opt => /* ... */);
}edituDefaultToolbarActions
This constant provides the default toolbar actions including undo/redo, formatting, headings, lists, and blocks.
import { edituDefaultToolbarActions } from '@editu/core';
// Array of EdituToolbarActionDefault groups: history, format, heading, list, block
groupEdituToolbarActions
This function groups toolbar actions by their group property for rendering with dividers. Supports both simple actions and dropdown actions.
import { groupEdituToolbarActions } from '@editu/core';
const groups = groupEdituToolbarActions(actions);
// EdituToolbarActionItem[][] - each sub-array is a groupFind & Replace
A standalone Tiptap extension for text search and replacement within the editor. This extension is not included in createEdituExtensions() — you add it manually.
createEdituFindReplaceExtension
This function creates the Find & Replace extension.
import { createEdituFindReplaceExtension } from '@editu/core';
const findReplace = createEdituFindReplaceExtension({
caseSensitive: false,
onResultsChange: ({ total, current }) => {
console.log(`Match ${current} of ${total}`);
},
});Options
| Option | Type | Default | Description |
|---|---|---|---|
caseSensitive | boolean | false | Enable case-sensitive search |
onResultsChange | (results: { total: number; current: number }) => void | — | Called when search results change |
Editor Commands
The extension registers the following commands on the editor:
| Command | Parameters | Description |
|---|---|---|
openFindReplace | mode?: 'find' | 'replace' | Open the Find & Replace panel |
closeFindReplace | — | Close the panel |
find | query: string | Search for text in the document |
findNext | — | Navigate to the next match |
findPrevious | — | Navigate to the previous match |
replace | text: string | Replace the current match |
replaceAll | text: string | Replace all matches |
setFindCaseSensitive | caseSensitive: boolean | Toggle case-sensitive search |
clearFind | — | Clear the search state |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Mod-f | Open Find panel |
Mod-Shift-h | Open Replace panel |
getEdituFindReplaceState
This function returns the current Find & Replace plugin state from the editor.
import { getEdituFindReplaceState } from '@editu/core';
const state = getEdituFindReplaceState(editor.state);
// {
// query: string,
// matches: EdituFindMatch[],
// activeIndex: number,
// caseSensitive: boolean,
// isOpen: boolean,
// mode: 'find' | 'replace',
// }Types
import type {
EdituFindReplaceOptions,
EdituFindReplaceState,
EdituFindMatch,
} from '@editu/core';
import { edituFindReplacePluginKey } from '@editu/core';| Type | Description |
|---|---|
EdituFindReplaceOptions | Configuration options for the extension |
EdituFindReplaceState | Plugin state containing query, matches, activeIndex, and more |
EdituFindMatch | Single match with from and to positions |
edituFindReplacePluginKey | ProseMirror PluginKey for accessing the plugin state |
Wiki Link
A mark extension for wiki-style [[page-name]] links. Supports display text aliases with [[page-name|display text]] syntax.
createEdituWikiLinkExtension
This function creates a configured Wiki Link extension.
import { createEdituWikiLinkExtension } from '@editu/core';
const wikiLink = createEdituWikiLinkExtension({
resolveLink: (page) => `/wiki/${encodeURIComponent(page)}`,
pageExists: (page) => knownPages.has(page),
onLinkClick: (page, event) => {
event.preventDefault();
router.push(`/wiki/${page}`);
},
});Options
| Option | Type | Default | Description |
|---|---|---|---|
resolveLink | (pageName: string) => string | (p) => '#' + p | Resolve a page name to a URL |
pageExists | (pageName: string) => boolean | () => true | Check whether a page exists (for visual differentiation) |
getPageSuggestions | (query: string) => EdituWikiLinkSuggestion[] | — | Return autocomplete suggestions |
onLinkClick | (pageName: string, event: MouseEvent) => void | — | Called when a wiki link is clicked |
existingClass | string | 'editu-wiki-link--existing' | CSS class for existing page links |
newClass | string | 'editu-wiki-link--new' | CSS class for non-existing page links |
HTMLAttributes | Record<string, unknown> | {} | Additional HTML attributes |
Editor Commands
| Command | Parameters | Description |
|---|---|---|
setWikiLink | pageName: string, displayText?: string | Insert a wiki link at the current position |
unsetWikiLink | — | Remove the wiki link mark from the selection |
Types
import type { EdituWikiLinkOptions, EdituWikiLinkSuggestion } from '@editu/core';
import { EdituWikiLink, edituWikiLinkPluginKey } from '@editu/core';| Type | Description |
|---|---|
EdituWikiLinkOptions | Configuration options for the extension |
EdituWikiLinkSuggestion | Page suggestion with name and optional label |
EdituWikiLink | Tiptap Mark extension class |
edituWikiLinkPluginKey | ProseMirror PluginKey for the wiki link plugin |
Comments
Comment management module for adding, resolving, and replying to text annotations. This module provides a handler factory pattern with pluggable storage backends.
createEdituCommentHandlers
This function creates comment handler methods for an editor.
import { createEdituCommentHandlers } from '@editu/core';
import type { EdituCommentState } from '@editu/core';
const handlers = createEdituCommentHandlers(
() => editor,
{
storage: 'localStorage',
key: 'my-comments',
onAdd: (comment) => console.log('Added:', comment.id),
},
(partial) => setState((prev) => ({ ...prev, ...partial }))
);
// Add a comment to the current text selection
await handlers.addComment('Needs clarification', 'Alice');
// Resolve a comment
await handlers.resolveComment(commentId);
// Reply to a comment
await handlers.replyToComment(commentId, 'Fixed in latest commit', 'Bob');Parameters
| Parameter | Type | Description |
|---|---|---|
getEditor | () => Editor | null | undefined | Getter function for the editor instance |
options | EdituCommentOptions | Configuration options |
onStateChange | (state: Partial<EdituCommentState>) => void | Callback to update reactive state |
Return Value
| Method | Signature | Description |
|---|---|---|
addComment | (text: string, author?: string) => Promise<EdituComment | null> | Add a comment to the current selection |
removeComment | (commentId: string) => Promise<void> | Remove a comment and its mark |
resolveComment | (commentId: string) => Promise<boolean> | Mark a comment as resolved |
reopenComment | (commentId: string) => Promise<boolean> | Reopen a resolved comment |
replyToComment | (commentId: string, text: string, author?: string) => Promise<EdituCommentReply | null> | Add a reply to a comment |
setActiveComment | (commentId: string | null) => void | Set the currently active comment |
loadComments | () => Promise<EdituComment[]> | Load all comments from storage |
getCommentById | (commentId: string) => EdituComment | undefined | Get a comment by its ID |
getEdituCommentStorageBackend
This function creates a normalized storage backend from the storage option.
import { getEdituCommentStorageBackend } from '@editu/core';
const backend = getEdituCommentStorageBackend('localStorage', 'my-comments');
const comments = await backend.load();
await backend.save(comments);Comment Extension
This extension adds a mark to the editor for highlighting commented text.
import { createEdituCommentExtension } from '@editu/core';
const commentExtension = createEdituCommentExtension();Types
import type {
EdituComment,
EdituCommentReply,
EdituCommentState,
EdituCommentOptions,
EdituCommentStorage,
} from '@editu/core';
import {
EDITU_DEFAULT_COMMENT_OPTIONS,
edituCommentPluginKey,
} from '@editu/core';| Type | Description |
|---|---|
EdituComment | Comment annotation with id, text, author, createdAt, resolved, replies |
EdituCommentReply | Reply with id, text, author, createdAt |
EdituCommentState | State object containing comments, activeCommentId, isLoading, error |
EdituCommentOptions | Configuration for enabled, storage, key, and event callbacks |
EdituCommentStorage | 'localStorage' or custom { save, load } backend |
Version History
Version history module for saving, restoring, and managing document snapshots. This module uses the same handler factory pattern and pluggable storage backends as Comments.
createEdituVersionHistoryHandlers
This function creates version history handler methods for an editor.
import { createEdituVersionHistoryHandlers } from '@editu/core';
import type { EdituVersionHistoryState } from '@editu/core';
const handlers = createEdituVersionHistoryHandlers(
() => editor,
{
maxVersions: 20,
storage: 'localStorage',
onSave: (snapshot) => console.log('Saved version:', snapshot.id),
},
(partial) => setState((prev) => ({ ...prev, ...partial }))
);
// Save the current document state
await handlers.saveVersion('Initial draft', 'Alice');
// List all versions
const versions = await handlers.loadVersions();
// Restore a specific version
await handlers.restoreVersion(versions[0].id);Parameters
| Parameter | Type | Description |
|---|---|---|
getEditor | () => Editor | null | undefined | Getter function for the editor instance |
options | EdituVersionHistoryOptions | Configuration options |
onStateChange | (state: Partial<EdituVersionHistoryState>) => void | Callback to update reactive state |
Return Value
| Method | Signature | Description |
|---|---|---|
saveVersion | (description?: string, author?: string) => Promise<EdituVersionSnapshot | null> | Save the current document as a new version |
restoreVersion | (versionId: string) => Promise<boolean> | Restore the document to a specific version |
loadVersions | () => Promise<EdituVersionSnapshot[]> | Load all versions from storage |
deleteVersion | (versionId: string) => Promise<void> | Delete a specific version |
clearVersions | () => Promise<void> | Delete all versions |
getEdituVersionStorageBackend
This function creates a normalized storage backend from the storage option.
import { getEdituVersionStorageBackend } from '@editu/core';
const backend = getEdituVersionStorageBackend('localStorage', 'my-versions');
const snapshots = await backend.load();
await backend.save(snapshots);Types
import type {
EdituVersionSnapshot,
EdituVersionHistoryState,
EdituVersionHistoryOptions,
EdituVersionStorage,
} from '@editu/core';
import { EDITU_DEFAULT_VERSION_HISTORY_OPTIONS } from '@editu/core';| Type | Description |
|---|---|
EdituVersionSnapshot | Snapshot with id, content (JSONContent), timestamp, description, author |
EdituVersionHistoryState | State object containing snapshots, isLoading, error |
EdituVersionHistoryOptions | Configuration for enabled, maxVersions, storage, key, and callbacks |
EdituVersionStorage | 'localStorage' or custom { save, load } backend |
Default Options
EDITU_DEFAULT_VERSION_HISTORY_OPTIONS = {
enabled: true,
maxVersions: 50,
storage: 'localStorage',
key: 'editu-versions',
};Collaboration
Real-time multi-user editing module built on Yjs. This module provides types, state management, and lifecycle utilities for integrating Yjs-based collaboration.
WARNING
You must install your own compatible versions of yjs, a Yjs provider (e.g. y-websocket), @tiptap/extension-collaboration, and @tiptap/extension-collaboration-cursor.
createEdituCollaborationHandlers
This function creates collaboration handler methods for tracking provider state and managing lifecycle.
import { createEdituCollaborationHandlers } from '@editu/core';
import type { EdituCollaborationState } from '@editu/core';
const handlers = createEdituCollaborationHandlers(
() => wsProvider,
{
user: { name: 'Alice', color: '#ff0000' },
onConnect: () => console.log('Connected'),
onPeersChange: (count) => console.log('Peers:', count),
},
(partial) => setState((prev) => ({ ...prev, ...partial }))
);
// Start listening to provider events
const unsubscribe = handlers.subscribe();
// Connect to the server
handlers.connect();
// Later, clean up
unsubscribe();Parameters
| Parameter | Type | Description |
|---|---|---|
getProvider | () => EdituYjsProvider | null | undefined | Getter function for the Yjs provider |
options | EdituCollaborationOptions | Collaboration options including user info |
onStateChange | (state: Partial<EdituCollaborationState>) => void | Callback to update reactive state |
Return Value
| Method | Signature | Description |
|---|---|---|
connect | () => void | Connect to the collaboration server |
disconnect | () => void | Disconnect from the server |
updateUser | (user: EdituCollaborationUser) => void | Update the current user's cursor information |
subscribe | () => () => void | Subscribe to provider events; returns an unsubscribe function |
Types
import type {
EdituCollaborationUser,
EdituCollaborationOptions,
EdituCollaborationState,
EdituYjsProvider,
EdituYjsAwareness,
} from '@editu/core';
import { EDITU_DEFAULT_COLLABORATION_OPTIONS } from '@editu/core';| Type | Description |
|---|---|
EdituCollaborationUser | User info with name and color |
EdituCollaborationOptions | Configuration for enabled, user, and event callbacks |
EdituCollaborationState | State containing isConnected, isSynced, peerCount, error |
EdituYjsProvider | Interface matching the Yjs WebSocket provider API |
EdituYjsAwareness | Interface matching the Yjs Awareness API |
EdituCollaborationOptions
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable collaboration tracking |
user | EdituCollaborationUser | — | Current user info for cursor display (required) |
onConnect | () => void | — | Called when connected |
onDisconnect | () => void | — | Called when disconnected |
onSynced | () => void | — | Called when initial document sync completes |
onError | (error: Error) => void | — | Called when an error occurs |
onPeersChange | (count: number) => void | — | Called when the number of connected peers changes |
Plugin System
A plugin architecture for extending Editu with third-party functionality. The plugin system supports dependency resolution, lifecycle hooks, style injection, and transaction handling.
EdituPluginManager
The main class for managing plugins.
import { EdituPluginManager } from '@editu/core';
import type { EdituPlugin } from '@editu/core';
const manager = new EdituPluginManager();
// Register a plugin
manager.register(myPlugin);
// Pass plugin extensions to the editor
const editor = useEdituEditor({
extensions: manager.getExtensions(),
});
// Connect the editor to enable lifecycle hooks
if (editor) manager.setEditor(editor);
// Clean up
manager.destroy();Methods
| Method | Signature | Description |
|---|---|---|
register | (plugin: EdituPlugin) => void | Register a plugin (validates, injects styles, calls onInstall if the editor is connected) |
unregister | (pluginName: string) => void | Unregister a plugin (checks dependents, removes styles, calls onUninstall) |
setEditor | (editor: Editor) => void | Connect an editor instance and call onInstall on all plugins |
destroy | () => void | Disconnect the editor and clean up all plugins |
getExtensions | () => Extensions | Return aggregated extensions from all plugins in dependency order |
getPlugin | (name: string) => EdituPlugin | undefined | Get a registered plugin by name |
listPlugins | () => EdituPlugin[] | List all registered plugins |
hasPlugin | (name: string) => boolean | Check whether a plugin is registered |
EdituPlugin Interface
import type { EdituPlugin } from '@editu/core';
const myPlugin: EdituPlugin = {
name: 'my-editu-plugin',
version: '1.0.0',
description: 'Adds cool feature to Editu',
extensions: [MyExtension],
styles: '.my-plugin { color: red; }',
dependencies: ['other-plugin'],
onInstall: (editor) => console.log('Installed'),
onUninstall: (editor) => console.log('Uninstalled'),
onTransaction: ({ editor, transaction }) => { /* handle transaction */ },
};| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique identifier (kebab-case) |
version | string | Yes | Semver version (e.g. '1.0.0') |
description | string | No | Human-readable description |
extensions | Extensions | No | Tiptap extensions to add |
styles | string | No | CSS styles to inject |
onInstall | (editor: Editor) => void | No | Called when the editor installs the plugin |
onUninstall | (editor: Editor) => void | No | Called when the editor uninstalls the plugin |
onTransaction | (props: { editor: Editor; transaction: Transaction }) => void | No | Called on each editor transaction |
dependencies | string[] | No | Plugin names that you must register first |
validateEdituPlugin
This function validates a plugin's required fields and format. It throws a descriptive error if validation fails.
import { validateEdituPlugin } from '@editu/core';
validateEdituPlugin(myPlugin); // throws if invalidresolveEdituPluginDependencies
This function resolves plugin dependencies via topological sort. It throws if it detects a circular dependency or a missing dependency.
import { resolveEdituPluginDependencies } from '@editu/core';
const ordered = resolveEdituPluginDependencies(plugins);
// Returns plugins in dependency-first orderInternationalization (i18n)
EdituLocale
Type definition for all translatable UI strings. The locale is organized by component section:
import type { EdituLocale } from '@editu/core';| Section | Description | Key Fields |
|---|---|---|
toolbar | Toolbar button labels | ariaLabel, undo, redo, bold, italic, strikethrough, underline, code, heading1-heading3, bulletList, numberedList, taskList, quote, codeBlock, horizontalRule, moreActions |
nodeTypes | Node type selector labels | text, heading1-heading6, bulletList, numberedList, taskList, quote, code |
blockMenu | Block context menu | label, delete, duplicate, copy, cut, turnInto |
slashMenu | Slash command menu | noResults, groups, items, enterImageUrl, enterUrl, enterEmbedUrl |
findReplace | Find and replace panel | label, findPlaceholder, replacePlaceholder, noResults, and button labels |
codeBlock | Code block UI | languagePlaceholder, hideLineNumbers, showLineNumbers, copyCode, copied |
dragHandle | Drag handle | ariaLabel |
saveIndicator | Save indicator | saved, saving, unsaved, error |
nodeSelector | Node selector dropdown | changeBlockType, blockTypes, currentBlockType |
relativeTime | Relative time formatting | justNow, secondsAgo, minutesAgo, hoursAgo, daysAgo |
bubbleMenu | Bubble menu labels | ariaLabel, bold, italic, strikethrough, underline, code, link, superscript, subscript |
colorPicker | Color picker labels | textColor, highlight, textColorPalette, highlightPalette, recent, hexPlaceholder, apply, applyAriaLabel |
linkEditor | Link editor popup | urlPlaceholder, apply, applyAriaLabel, removeLink, removeLinkAriaLabel, openInNewTab, visit, visitTitle, embedAsRichContent |
edituEnLocale
The default English locale constant.
import { edituEnLocale } from '@editu/core';
console.log(edituEnLocale.toolbar.bold); // "Bold"
console.log(edituEnLocale.bubbleMenu.superscript); // "Superscript"
console.log(edituEnLocale.colorPicker.textColor); // "Text Color"
console.log(edituEnLocale.linkEditor.urlPlaceholder); // "Enter URL..."createEdituLocale
This function merges a partial locale with the English defaults, producing a complete EdituLocale.
import { createEdituLocale } from '@editu/core';
const jaLocale = createEdituLocale({
toolbar: { ariaLabel: '書式設定', bold: '太字', italic: '斜体' },
bubbleMenu: { ariaLabel: 'テキスト書式', bold: '太字', italic: '斜体', link: 'リンク', superscript: '上付き', subscript: '下付き' },
colorPicker: { textColor: '文字色', highlight: 'ハイライト' },
linkEditor: { urlPlaceholder: 'URLを入力...', apply: '適用' },
});EdituLocalePartial
Deep partial type that makes all nested locale properties optional. Used as the parameter type for createEdituLocale().
import type { EdituLocalePartial } from '@editu/core';
const partial: EdituLocalePartial = {
bubbleMenu: { superscript: 'Hochgestellt' },
colorPicker: { textColor: 'Textfarbe' },
};Importing from Tiptap
For convenience, @editu/core re-exports commonly used Tiptap types and classes: Editor, Extensions, JSONContent, BubbleMenuPlugin, SuggestionOptions, and SuggestionProps. You can import them from either @editu/core or directly from @tiptap/core:
// Option 1: Import from @editu/core (convenience re-exports)
import { createEdituExtensions, getEdituEditorState } from '@editu/core';
import type { Editor, JSONContent, Extensions, EdituEditorOptions } from '@editu/core';
// Option 2: Import Tiptap types directly
import type { Editor, JSONContent, Extensions } from '@tiptap/core';For types not re-exported by Editu, import them directly from the relevant @tiptap/* package.
Next Steps
- CSS Variables
- Type Definitions
- React API - React-specific APIs
- Wiki Links Guide - Wiki link usage guide
- Comments Guide - Comment management guide
- Version History Guide - Version history guide
- Collaboration Guide - Real-time collaboration guide
- Plugins Guide - Plugin system guide