Skip to content

@editu/core

Framework-agnostic core package containing Tiptap extensions, types, utilities, and styles.

Installation

bash
npm install @editu/core

TIP

You typically don't need to install this package directly. It's included as a dependency of @editu/react.

Styles

Default Styles

typescript
import '@editu/core/styles.css';

This stylesheet includes CSS variables and component styles.

Components Only

typescript
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.

typescript
import { createEdituExtensions } from '@editu/core';

const extensions = await createEdituExtensions({
  placeholder: 'Start writing...',
  features: {
    markdown: true,
    mathematics: true,
  },
});

Base Extensions (Always Included)

ExtensionDescription
DocumentDocument node
ParagraphParagraph node
TextText node
BoldBold mark
ItalicItalic mark
StrikeStrikethrough mark
UnderlineUnderline mark
CodeInline code mark
HeadingH1-H6 headings
BulletListBullet list
OrderedListNumbered list
ListItemList item
BlockquoteBlock quote
HorizontalRuleHorizontal divider
HardBreakLine break
HistoryUndo/redo
PlaceholderPlaceholder text
DropcursorDrop cursor
GapcursorGap cursor

Feature Extensions

FeatureExtensions
slashCommandSlashCommand
tableTable, TableRow, TableCell, TableHeader
linkLink
imageImage, ImageResize
codeBlockCodeBlockLowlight
characterCountCharacterCount
textColorColor, Highlight
taskListTaskList, TaskItem
dragHandleDragHandle
markdownMarkdown
mathematicsMathematics
embedEmbed
detailsDetails, DetailsContent, DetailsSummary
diagramDiagram
wikiLinkWikiLink
commentCommentMark
calloutCallout
mentionMention
tableOfContentsTableOfContents
superscriptSuperscript
subscriptSubscript
typographyTypography
collaborationYjs extensions (Collaboration, CollaborationCursor)

Types

EdituEditorOptions

typescript
import type { EdituEditorOptions } from '@editu/core';

See Type Definitions for full interface.

EdituFeatureOptions

typescript
import type { EdituFeatureOptions } from '@editu/core';

See Type Definitions for full interface.

EdituMarkdownFlavor

typescript
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

typescript
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

typescript
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:

typescript
import type { JSONContent } from '@tiptap/core';

const content: JSONContent = {
  type: 'doc',
  content: [
    { type: 'paragraph', content: [{ type: 'text', text: 'Hello' }] }
  ],
};

EdituSaveStatus

typescript
import type { EdituSaveStatus } from '@editu/core';

type EdituSaveStatus = 'saved' | 'saving' | 'unsaved' | 'error';

Theme Types

typescript
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.

typescript
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.

typescript
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.

typescript
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 === false

getEdituEditorState

This function returns the current editor state.

typescript
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.

typescript
import { formatEdituRelativeTime } from '@editu/core';

formatEdituRelativeTime(new Date(Date.now() - 60000));
// "1m ago"

Theme Utilities

getEdituSystemTheme

This function returns the system color scheme preference.

typescript
import { getEdituSystemTheme } from '@editu/core';

const theme = getEdituSystemTheme();
// 'light' | 'dark'

resolveEdituTheme

This function resolves a theme setting to an actual theme value.

typescript
import { resolveEdituTheme } from '@editu/core';

resolveEdituTheme('system', 'dark');
// 'dark'

applyEdituTheme

This function applies a theme to the DOM.

typescript
import { applyEdituTheme } from '@editu/core';

applyEdituTheme('dark', 'html');

getEdituThemeInitScript

This function returns an inline script that prevents flash of unstyled content.

typescript
import { getEdituThemeInitScript } from '@editu/core';

const script = getEdituThemeInitScript('my-theme-key');
// Include in <head>

Image Utilities

createEdituImageUploader

This function creates an image upload handler.

typescript
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.

typescript
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.

typescript
import { getEdituRecentColors } from '@editu/core';

const colors = getEdituRecentColors('text');
// ['#ff0000', '#00ff00', ...]

addEdituRecentColor

This function adds a color to the recent colors list.

typescript
import { addEdituRecentColor } from '@editu/core';

addEdituRecentColor('text', '#ff0000');

Embed Utilities

detectEdituEmbedProvider

This function detects the oEmbed provider from a URL.

typescript
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.

typescript
import { EDITU_DEFAULT_FLAVOR } from '@editu/core';
// "gfm"

EDITU_TEXT_COLORS

This constant defines the default text color palette.

typescript
import { EDITU_TEXT_COLORS } from '@editu/core';
// Array of { name: string, color: string }

EDITU_HIGHLIGHT_COLORS

This constant defines the default highlight color palette.

typescript
import { EDITU_HIGHLIGHT_COLORS } from '@editu/core';
// Array of { name: string, color: string }

edituDefaultEmbedProviders

This constant defines the default oEmbed providers.

typescript
import { edituDefaultEmbedProviders } from '@editu/core';
// YouTube, Vimeo, Twitter, etc.

Toolbar

EdituToolbarAction

Type definition for a toolbar action.

typescript
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.

typescript
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.

typescript
import type { EdituToolbarActionItem } from '@editu/core';

type EdituToolbarActionItem = EdituToolbarAction | EdituToolbarDropdownAction;

isEdituToolbarDropdownAction

Type guard to check if a toolbar item is a dropdown action.

typescript
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.

typescript
import { edituDefaultToolbarActions } from '@editu/core';
// Array of EdituToolbarAction

Default 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.

typescript
import { groupEdituToolbarActions } from '@editu/core';

const groups = groupEdituToolbarActions(actions);
// EdituToolbarActionItem[][] - each sub-array is a group

Find & 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.

typescript
import { createEdituFindReplaceExtension } from '@editu/core';

const findReplace = createEdituFindReplaceExtension({
  caseSensitive: false,
  onResultsChange: ({ total, current }) => {
    console.log(`Match ${current} of ${total}`);
  },
});

Options

OptionTypeDefaultDescription
caseSensitivebooleanfalseEnable case-sensitive search
onResultsChange(results: { total: number; current: number }) => voidCalled when search results change

Editor Commands

The extension registers the following commands on the editor:

CommandParametersDescription
openFindReplacemode?: 'find' | 'replace'Open the Find & Replace panel
closeFindReplaceClose the panel
findquery: stringSearch for text in the document
findNextNavigate to the next match
findPreviousNavigate to the previous match
replacetext: stringReplace the current match
replaceAlltext: stringReplace all matches
setFindCaseSensitivecaseSensitive: booleanToggle case-sensitive search
clearFindClear the search state

Keyboard Shortcuts

ShortcutAction
Mod-fOpen Find panel
Mod-Shift-hOpen Replace panel

getEdituFindReplaceState

This function returns the current Find & Replace plugin state from the editor.

typescript
import { getEdituFindReplaceState } from '@editu/core';

const state = getEdituFindReplaceState(editor.state);
// {
//   query: string,
//   matches: EdituFindMatch[],
//   activeIndex: number,
//   caseSensitive: boolean,
//   isOpen: boolean,
//   mode: 'find' | 'replace',
// }

Types

typescript
import type {
  EdituFindReplaceOptions,
  EdituFindReplaceState,
  EdituFindMatch,
} from '@editu/core';

import { edituFindReplacePluginKey } from '@editu/core';
TypeDescription
EdituFindReplaceOptionsConfiguration options for the extension
EdituFindReplaceStatePlugin state containing query, matches, activeIndex, and more
EdituFindMatchSingle match with from and to positions
edituFindReplacePluginKeyProseMirror PluginKey for accessing the plugin state

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.

typescript
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

OptionTypeDefaultDescription
resolveLink(pageName: string) => string(p) => '#' + pResolve a page name to a URL
pageExists(pageName: string) => boolean() => trueCheck whether a page exists (for visual differentiation)
getPageSuggestions(query: string) => EdituWikiLinkSuggestion[]Return autocomplete suggestions
onLinkClick(pageName: string, event: MouseEvent) => voidCalled when a wiki link is clicked
existingClassstring'editu-wiki-link--existing'CSS class for existing page links
newClassstring'editu-wiki-link--new'CSS class for non-existing page links
HTMLAttributesRecord<string, unknown>{}Additional HTML attributes

Editor Commands

CommandParametersDescription
setWikiLinkpageName: string, displayText?: stringInsert a wiki link at the current position
unsetWikiLinkRemove the wiki link mark from the selection

Types

typescript
import type { EdituWikiLinkOptions, EdituWikiLinkSuggestion } from '@editu/core';
import { EdituWikiLink, edituWikiLinkPluginKey } from '@editu/core';
TypeDescription
EdituWikiLinkOptionsConfiguration options for the extension
EdituWikiLinkSuggestionPage suggestion with name and optional label
EdituWikiLinkTiptap Mark extension class
edituWikiLinkPluginKeyProseMirror 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.

typescript
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

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor instance
optionsEdituCommentOptionsConfiguration options
onStateChange(state: Partial<EdituCommentState>) => voidCallback to update reactive state

Return Value

MethodSignatureDescription
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) => voidSet the currently active comment
loadComments() => Promise<EdituComment[]>Load all comments from storage
getCommentById(commentId: string) => EdituComment | undefinedGet a comment by its ID

getEdituCommentStorageBackend

This function creates a normalized storage backend from the storage option.

typescript
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.

typescript
import { createEdituCommentExtension } from '@editu/core';

const commentExtension = createEdituCommentExtension();

Types

typescript
import type {
  EdituComment,
  EdituCommentReply,
  EdituCommentState,
  EdituCommentOptions,
  EdituCommentStorage,
} from '@editu/core';

import {
  EDITU_DEFAULT_COMMENT_OPTIONS,
  edituCommentPluginKey,
} from '@editu/core';
TypeDescription
EdituCommentComment annotation with id, text, author, createdAt, resolved, replies
EdituCommentReplyReply with id, text, author, createdAt
EdituCommentStateState object containing comments, activeCommentId, isLoading, error
EdituCommentOptionsConfiguration 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.

typescript
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

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor instance
optionsEdituVersionHistoryOptionsConfiguration options
onStateChange(state: Partial<EdituVersionHistoryState>) => voidCallback to update reactive state

Return Value

MethodSignatureDescription
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.

typescript
import { getEdituVersionStorageBackend } from '@editu/core';

const backend = getEdituVersionStorageBackend('localStorage', 'my-versions');
const snapshots = await backend.load();
await backend.save(snapshots);

Types

typescript
import type {
  EdituVersionSnapshot,
  EdituVersionHistoryState,
  EdituVersionHistoryOptions,
  EdituVersionStorage,
} from '@editu/core';

import { EDITU_DEFAULT_VERSION_HISTORY_OPTIONS } from '@editu/core';
TypeDescription
EdituVersionSnapshotSnapshot with id, content (JSONContent), timestamp, description, author
EdituVersionHistoryStateState object containing snapshots, isLoading, error
EdituVersionHistoryOptionsConfiguration for enabled, maxVersions, storage, key, and callbacks
EdituVersionStorage'localStorage' or custom { save, load } backend

Default Options

typescript
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.

typescript
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

ParameterTypeDescription
getProvider() => EdituYjsProvider | null | undefinedGetter function for the Yjs provider
optionsEdituCollaborationOptionsCollaboration options including user info
onStateChange(state: Partial<EdituCollaborationState>) => voidCallback to update reactive state

Return Value

MethodSignatureDescription
connect() => voidConnect to the collaboration server
disconnect() => voidDisconnect from the server
updateUser(user: EdituCollaborationUser) => voidUpdate the current user's cursor information
subscribe() => () => voidSubscribe to provider events; returns an unsubscribe function

Types

typescript
import type {
  EdituCollaborationUser,
  EdituCollaborationOptions,
  EdituCollaborationState,
  EdituYjsProvider,
  EdituYjsAwareness,
} from '@editu/core';

import { EDITU_DEFAULT_COLLABORATION_OPTIONS } from '@editu/core';
TypeDescription
EdituCollaborationUserUser info with name and color
EdituCollaborationOptionsConfiguration for enabled, user, and event callbacks
EdituCollaborationStateState containing isConnected, isSynced, peerCount, error
EdituYjsProviderInterface matching the Yjs WebSocket provider API
EdituYjsAwarenessInterface matching the Yjs Awareness API

EdituCollaborationOptions

OptionTypeDefaultDescription
enabledbooleantrueEnable collaboration tracking
userEdituCollaborationUserCurrent user info for cursor display (required)
onConnect() => voidCalled when connected
onDisconnect() => voidCalled when disconnected
onSynced() => voidCalled when initial document sync completes
onError(error: Error) => voidCalled when an error occurs
onPeersChange(count: number) => voidCalled 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.

typescript
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

MethodSignatureDescription
register(plugin: EdituPlugin) => voidRegister a plugin (validates, injects styles, calls onInstall if the editor is connected)
unregister(pluginName: string) => voidUnregister a plugin (checks dependents, removes styles, calls onUninstall)
setEditor(editor: Editor) => voidConnect an editor instance and call onInstall on all plugins
destroy() => voidDisconnect the editor and clean up all plugins
getExtensions() => ExtensionsReturn aggregated extensions from all plugins in dependency order
getPlugin(name: string) => EdituPlugin | undefinedGet a registered plugin by name
listPlugins() => EdituPlugin[]List all registered plugins
hasPlugin(name: string) => booleanCheck whether a plugin is registered

EdituPlugin Interface

typescript
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 */ },
};
FieldTypeRequiredDescription
namestringYesUnique identifier (kebab-case)
versionstringYesSemver version (e.g. '1.0.0')
descriptionstringNoHuman-readable description
extensionsExtensionsNoTiptap extensions to add
stylesstringNoCSS styles to inject
onInstall(editor: Editor) => voidNoCalled when the editor installs the plugin
onUninstall(editor: Editor) => voidNoCalled when the editor uninstalls the plugin
onTransaction(props: { editor: Editor; transaction: Transaction }) => voidNoCalled on each editor transaction
dependenciesstring[]NoPlugin 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.

typescript
import { validateEdituPlugin } from '@editu/core';

validateEdituPlugin(myPlugin); // throws if invalid

resolveEdituPluginDependencies

This function resolves plugin dependencies via topological sort. It throws if it detects a circular dependency or a missing dependency.

typescript
import { resolveEdituPluginDependencies } from '@editu/core';

const ordered = resolveEdituPluginDependencies(plugins);
// Returns plugins in dependency-first order

Internationalization (i18n)

EdituLocale

Type definition for all translatable UI strings. The locale is organized by component section:

typescript
import type { EdituLocale } from '@editu/core';
SectionDescriptionKey Fields
toolbarToolbar button labelsariaLabel, undo, redo, bold, italic, strikethrough, underline, code, heading1-heading3, bulletList, numberedList, taskList, quote, codeBlock, horizontalRule, moreActions
nodeTypesNode type selector labelstext, heading1-heading6, bulletList, numberedList, taskList, quote, code
blockMenuBlock context menulabel, delete, duplicate, copy, cut, turnInto
slashMenuSlash command menunoResults, groups, items, enterImageUrl, enterUrl, enterEmbedUrl
findReplaceFind and replace panellabel, findPlaceholder, replacePlaceholder, noResults, and button labels
codeBlockCode block UIlanguagePlaceholder, hideLineNumbers, showLineNumbers, copyCode, copied
dragHandleDrag handleariaLabel
saveIndicatorSave indicatorsaved, saving, unsaved, error
nodeSelectorNode selector dropdownchangeBlockType, blockTypes, currentBlockType
relativeTimeRelative time formattingjustNow, secondsAgo, minutesAgo, hoursAgo, daysAgo
bubbleMenuBubble menu labelsariaLabel, bold, italic, strikethrough, underline, code, link, superscript, subscript
colorPickerColor picker labelstextColor, highlight, textColorPalette, highlightPalette, recent, hexPlaceholder, apply, applyAriaLabel
linkEditorLink editor popupurlPlaceholder, apply, applyAriaLabel, removeLink, removeLinkAriaLabel, openInNewTab, visit, visitTitle, embedAsRichContent

edituEnLocale

The default English locale constant.

typescript
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.

typescript
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().

typescript
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:

typescript
// 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

Released under the MIT License.