@editora/plugins
v1.0.12
Published
Enterprise plugin suite for Editora rich text editor in React and web apps, including tables, media, workflow, and compliance tooling.
Downloads
262
Maintainers
Keywords
Readme
@editora/plugins
[!IMPORTANT] Live Website: https://editora-ecosystem.netlify.app/
Storybook: https://editora-ecosystem-storybook.netlify.app/
Comprehensive plugin collection for Editora Rich Text Editor with 40+ plugins for text formatting, media management, accessibility, and more.
📦 Installation
npm install @editora/plugins @editora/core @editora/themesWhen using plugin UI features (table toolbar, pickers, dialogs), also import:
import "@editora/plugins/styles.css";🎯 Overview
This package provides a complete set of plugins for building feature-rich text editors. Each plugin is modular, tree-shakeable, and can be used independently.
✨ Plugin Categories
Text Formatting (12 plugins)
- Bold, Italic, Underline, Strikethrough
- Font Family, Font Size, Text Color, Background Color
- Subscript, Superscript, Code Inline
- Clear Formatting
Block Elements (8 plugins)
- Headings (H1-H6)
- Paragraphs
- Blockquotes
- Code Blocks with syntax highlighting
- Horizontal Rules
- Page Breaks
- Preformatted Text
- Footnotes
Lists & Structure (5 plugins)
- Bullet Lists
- Numbered Lists
- Checklists
- Indent/Outdent
- Text Alignment (Left, Center, Right, Justify)
Media & Embeds (6 plugins)
- Images with upload
- Videos
- Audio
- Embed IFrames
- Media Manager
- Special Characters & Emojis
Advanced Features (10 plugins)
- Tables (full editing capabilities)
- Math Equations (LaTeX support)
- Merge Tags / Templates
- Comments & Annotations
- Document Manager (import/export)
- Spell Checker
- Accessibility Checker
- Link Management
- Anchor Links
- Print Preview
Utilities (4 plugins)
- History (Undo/Redo)
- Fullscreen Mode
- Line Height
- Text Direction (LTR/RTL)
- Capitalization (uppercase, lowercase, title case)
🚀 Quick Start
Entry Paths (All Free + Customizable)
Every plugin entry path is MIT-licensed, free to use, and customizable:
@editora/plugins: full plugin catalog@editora/plugins/lite: common/core plugin subset for lean bundles@editora/plugins/enterprise: advanced/specialized workflow plugins@editora/plugins/<plugin-name>: targeted per-plugin imports
Recommended Imports For Smaller Bundles
For best bundle size, avoid importing everything from @editora/plugins in large apps.
Use one of these patterns:
// Lightweight preset entry
import { BoldPlugin, ItalicPlugin, HistoryPlugin } from '@editora/plugins/lite';
// Enterprise preset entry (advanced/specialized plugins)
import { MentionPlugin, TrackChangesPlugin, SmartPastePlugin } from '@editora/plugins/enterprise';
// Per-plugin subpath entry (most explicit)
import { BoldPlugin } from '@editora/plugins/bold';
import { ItalicPlugin } from '@editora/plugins/italic';
import { SpellCheckPlugin } from '@editora/plugins/spell-check';Lazy-load heavy plugins only when needed:
const { DocumentManagerPlugin } = await import('@editora/plugins/document-manager');
const { MediaManagerPlugin } = await import('@editora/plugins/media-manager');
const { SpellCheckPlugin } = await import('@editora/plugins/spell-check');Enterprise Preset Details
@editora/plugins/enterprise includes advanced plugins for governance, compliance, workflow, and QA:
- Collaboration/workflow:
TrackChangesPlugin,VersionDiffPlugin,CommentsPlugin,ApprovalWorkflowPlugin - Validation/compliance:
ContentRulesPlugin,DocSchemaPlugin,A11yCheckerPlugin,SpellCheckPlugin,PIIRedactionPlugin - Structured/dynamic authoring:
ConditionalContentPlugin,DataBindingPlugin,MergeTagPlugin,TemplatePlugin,CitationsPlugin - Productivity/runtime intelligence:
SmartPastePlugin,SlashCommandsPlugin,MentionPlugin,BlocksLibraryPlugin,TranslationWorkflowPlugin - Manager-backed advanced plugins:
MediaManagerPlugin,DocumentManagerPlugin
Basic Formatting
import {
BoldPlugin,
ItalicPlugin,
UnderlinePlugin,
StrikethroughPlugin
} from '@editora/plugins';
import "@editora/plugins/styles.css";
import "@editora/themes/themes/default.css";
const plugins = [
BoldPlugin(),
ItalicPlugin(),
UnderlinePlugin(),
StrikethroughPlugin()
];Complete Editor Setup
import {
// Text formatting
BoldPlugin,
ItalicPlugin,
UnderlinePlugin,
FontFamilyPlugin,
FontSizePlugin,
TextColorPlugin,
BackgroundColorPlugin,
// Block elements
HeadingPlugin,
BlockquotePlugin,
CodeSamplePlugin,
// Lists
ListPlugin,
ChecklistPlugin,
IndentPlugin,
TextAlignmentPlugin,
// Media
LinkPlugin,
TablePlugin,
MediaManagerPlugin,
// Advanced
MathPlugin,
CommentsPlugin,
HistoryPlugin,
FullscreenPlugin,
DocumentManagerPlugin
} from '@editora/plugins';
const plugins = [
// Text formatting
BoldPlugin(),
ItalicPlugin(),
UnderlinePlugin(),
FontFamilyPlugin(),
FontSizePlugin(),
TextColorPlugin(),
BackgroundColorPlugin(),
// Block elements
HeadingPlugin(),
BlockquotePlugin(),
CodeSamplePlugin(),
// Lists
ListPlugin(),
ChecklistPlugin(),
IndentPlugin(),
TextAlignmentPlugin(),
// Media
LinkPlugin(),
TablePlugin(),
MediaManagerPlugin(),
// Advanced
MathPlugin(),
CommentsPlugin(),
HistoryPlugin(),
FullscreenPlugin(),
DocumentManagerPlugin()
];📖 Plugin API Reference
Text Formatting Plugins
Bold Plugin
BoldPlugin(options?: {
keyboard?: string; // Default: 'Mod-b'
icon?: ReactNode;
className?: string;
})Font Family Plugin
FontFamilyPlugin(options?: {
fonts?: Array<{
name: string;
value: string;
fallback?: string;
}>;
defaultFont?: string;
})
// Example
const fontFamilyPlugin = FontFamilyPlugin({
fonts: [
{ name: 'Arial', value: 'Arial, sans-serif' },
{ name: 'Times New Roman', value: 'Times New Roman, serif' },
{ name: 'Courier New', value: 'Courier New, monospace' }
]
});Font Size Plugin
FontSizePlugin(options?: {
sizes?: string[]; // Default: ['8pt', '10pt', '12pt', '14pt', '18pt', '24pt', '36pt']
defaultSize?: string;
})Text Color Plugin
TextColorPlugin(options?: {
colors?: string[];
customColors?: boolean;
recentColors?: boolean;
})Block Element Plugins
Heading Plugin
HeadingPlugin(options?: {
levels?: number[]; // Default: [1, 2, 3, 4, 5, 6]
defaultLevel?: number;
keyboard?: Record<number, string>;
})
// Example
const headingPlugin = HeadingPlugin({
levels: [1, 2, 3],
keyboard: {
1: 'Mod-Alt-1',
2: 'Mod-Alt-2',
3: 'Mod-Alt-3'
}
});Code Sample Plugin
CodeSamplePlugin(options?: {
languages?: Array<{
name: string;
value: string;
}>;
theme?: 'light' | 'dark' | 'github' | 'monokai';
lineNumbers?: boolean;
highlightActiveLine?: boolean;
})
// Example
const codeSamplePlugin = CodeSamplePlugin({
languages: [
{ name: 'JavaScript', value: 'javascript' },
{ name: 'TypeScript', value: 'typescript' },
{ name: 'Python', value: 'python' },
{ name: 'HTML', value: 'html' },
{ name: 'CSS', value: 'css' }
],
theme: 'github',
lineNumbers: true
});List Plugins
List Plugin
ListPlugin(options?: {
bulletList?: boolean;
orderedList?: boolean;
keyboard?: {
bullet?: string; // Default: 'Mod-Shift-8'
ordered?: string; // Default: 'Mod-Shift-7'
};
})Checklist Plugin
ChecklistPlugin(options?: {
nested?: boolean;
keyboard?: string;
})Media Plugins
Image Plugin
MediaManagerPlugin(options: {
upload: (file: File) => Promise<string>;
validate?: (file: File) => boolean;
maxSize?: number; // bytes
allowedTypes?: string[];
resize?: boolean;
maxWidth?: number;
maxHeight?: number;
quality?: number; // 0-1
})
// Example
const imagePlugin = MediaManagerPlugin({
upload: async (file) => {
const formData = new FormData();
formData.append('image', file);
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
return data.url;
},
maxSize: 5 * 1024 * 1024, // 5MB
allowedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
resize: true,
maxWidth: 1200,
quality: 0.9
});Link Plugin
LinkPlugin(options?: {
openOnClick?: boolean;
validate?: (url: string) => boolean;
onLinkClick?: (url: string) => void;
targetBlank?: boolean;
nofollow?: boolean;
})
// Example
const linkPlugin = LinkPlugin({
openOnClick: false,
validate: (url) => {
return url.startsWith('http://') || url.startsWith('https://');
},
onLinkClick: (url) => {
window.open(url, '_blank', 'noopener,noreferrer');
},
targetBlank: true
});Advanced Plugins
Table Plugin
TablePlugin(options?: {
allowResize?: boolean;
defaultRows?: number;
defaultCols?: number;
maxRows?: number;
maxCols?: number;
cellSelection?: boolean;
headerRow?: boolean;
})
// Example
const tablePlugin = TablePlugin({
allowResize: true,
defaultRows: 3,
defaultCols: 3,
maxRows: 20,
maxCols: 10,
cellSelection: true,
headerRow: true
});Math Plugin
MathPlugin(options?: {
engine?: 'katex' | 'mathjax';
inline?: boolean;
display?: boolean;
macros?: Record<string, string>;
})
// Example
const mathPlugin = MathPlugin({
engine: 'katex',
inline: true,
display: true,
macros: {
'\\R': '\\mathbb{R}',
'\\N': '\\mathbb{N}'
}
});Comments Plugin
CommentsPlugin(options?: {
onCommentAdd?: (comment: Comment) => void;
onCommentEdit?: (comment: Comment) => void;
onCommentDelete?: (commentId: string) => void;
onCommentResolve?: (commentId: string) => void;
showResolved?: boolean;
})Document Manager Plugin
DocumentManagerPlugin(options?: {
export?: {
word?: boolean;
pdf?: boolean;
html?: boolean;
markdown?: boolean;
};
import?: {
word?: boolean;
html?: boolean;
markdown?: boolean;
};
fileName?: string;
})
// Example
const documentManagerPlugin = DocumentManagerPlugin({
export: {
word: true,
pdf: true,
html: true
},
fileName: 'document'
});Spell Check Plugin
SpellCheckPlugin(options?: {
language?: string; // Default: 'en-US'
customDictionary?: string[];
ignoreUppercase?: boolean;
ignoreNumbers?: boolean;
})Accessibility Checker Plugin
A11yCheckerPlugin(options?: {
rules?: string[];
autoCheck?: boolean;
severity?: 'error' | 'warning' | 'info';
})Utility Plugins
History Plugin
HistoryPlugin(options?: {
depth?: number; // Default: 100
keyboard?: {
undo?: string; // Default: 'Mod-z'
redo?: string; // Default: 'Mod-Shift-z'
};
})Fullscreen Plugin
FullscreenPlugin(options?: {
keyboard?: string; // Default: 'F11'
onEnter?: () => void;
onExit?: () => void;
})💡 Usage Examples
Blog Editor
import {
BoldPlugin,
ItalicPlugin,
HeadingPlugin,
ParagraphPlugin,
LinkPlugin,
MediaManagerPlugin,
ListPlugin,
BlockquotePlugin,
HistoryPlugin
} from '@editora/plugins';
const blogPlugins = [
BoldPlugin(),
ItalicPlugin(),
HeadingPlugin({ levels: [1, 2, 3] }),
LinkPlugin({ targetBlank: true }),
MediaManagerPlugin({
upload: uploadImage,
maxSize: 2 * 1024 * 1024
}),
ListPlugin(),
BlockquotePlugin(),
HistoryPlugin()
];Technical Documentation Editor
import {
BoldPlugin,
ItalicPlugin,
CodePlugin,
CodeSamplePlugin,
HeadingPlugin,
TablePlugin,
LinkPlugin,
AnchorPlugin,
MathPlugin,
HistoryPlugin
} from '@editora/plugins';
const docsPlugins = [
BoldPlugin(),
ItalicPlugin(),
CodePlugin(),
CodeSamplePlugin({
languages: [
{ name: 'JavaScript', value: 'javascript' },
{ name: 'TypeScript', value: 'typescript' },
{ name: 'Python', value: 'python' }
],
lineNumbers: true
}),
HeadingPlugin(),
TablePlugin({ headerRow: true }),
LinkPlugin(),
AnchorPlugin(),
MathPlugin({ engine: 'katex' }),
HistoryPlugin()
];Collaborative Editor
import {
BoldPlugin,
ItalicPlugin,
CommentsPlugin,
HistoryPlugin,
MergeTagPlugin
} from '@editora/plugins';
const collaborativePlugins = [
BoldPlugin(),
ItalicPlugin(),
CommentsPlugin({
onCommentAdd: async (comment) => {
await saveComment(comment);
},
onCommentResolve: async (commentId) => {
await resolveComment(commentId);
}
}),
MergeTagPlugin({
tags: [
{ label: 'First Name', value: '{{firstName}}', category: 'User' },
{ label: 'Last Name', value: '{{lastName}}', category: 'User' },
{ label: 'Email', value: '{{email}}', category: 'User' }
],
defaultCategory: 'User',
dialog: {
title: 'Insert Variable',
searchPlaceholder: 'Search variables...',
showPreview: true
},
tokenTemplate: '{value}'
}),
HistoryPlugin()
];MergeTagPlugin supports functional customization:
tags: flat list of tags (auto-grouped bycategory)categories: explicit grouped categories with custom orderdefaultCategory: initial tabdialog: labels/placeholders/preview toggletokenTemplate: string template ({key},{label},{category},{value}) or formatter function
Custom Templates
You can register your own templates before initializing the editor:
import { TemplatePlugin, addCustomTemplate } from '@editora/plugins';
addCustomTemplate({
id: 'invoice-basic',
name: 'Invoice (Basic)',
category: 'Billing',
description: 'Simple invoice template',
html: `
<h1>Invoice</h1>
<p><strong>Customer:</strong> {{customer.name}}</p>
<p><strong>Date:</strong> {{today}}</p>
<p><strong>Total:</strong> {{invoice.total}}</p>
`,
tags: ['invoice', 'billing']
});
const plugins = [
TemplatePlugin()
];Notes:
idmust be unique.- HTML is sanitized on insertion.
- Use
validateTemplate(template)if you want to pre-check templates before registering.
🔧 TypeScript Support
All plugins include full TypeScript definitions:
import type { Plugin, PluginConfig } from '@editora/plugins';
const customConfig: PluginConfig = {
// Full type safety
};📄 License
MIT © Ajay Kumar
