
Security News
npm Tooling Bug Incorrectly Marks One-Character Packages as Security Holders
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.
@editora/plugins
Advanced tools
Enterprise plugin suite for Editora rich text editor in React and web apps, including tables, media, workflow, and compliance tooling.
[!IMPORTANT] Live Website: https://editora-ecosystem.netlify.app/
Storybook: https://editora-ecosystem-storybook.netlify.app/
Comprehensive plugin collection with 40+ plugins for rich text editing
Comprehensive plugin collection for Editora Rich Text Editor with 40+ plugins for text formatting, media management, accessibility, and more.
npm install @editora/plugins @editora/core @editora/themes
When using plugin UI features (table toolbar, pickers, dialogs), also import:
import "@editora/plugins/styles.css";
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.
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 importsFor 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');
@editora/plugins/enterprise includes advanced plugins for governance, compliance, workflow, and QA:
TrackChangesPlugin, VersionDiffPlugin, CommentsPlugin, ApprovalWorkflowPluginContentRulesPlugin, DocSchemaPlugin, A11yCheckerPlugin, SpellCheckPlugin, PIIRedactionPluginConditionalContentPlugin, DataBindingPlugin, MergeTagPlugin, TemplatePlugin, CitationsPluginSmartPastePlugin, SlashCommandsPlugin, MentionPlugin, BlocksLibraryPlugin, TranslationWorkflowPluginMediaManagerPlugin, DocumentManagerPluginimport {
BoldPlugin,
ItalicPlugin,
UnderlinePlugin,
StrikethroughPlugin
} from '@editora/plugins';
import "@editora/plugins/styles.css";
import "@editora/themes/themes/default.css";
const plugins = [
BoldPlugin(),
ItalicPlugin(),
UnderlinePlugin(),
StrikethroughPlugin()
];
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()
];
BoldPlugin(options?: {
keyboard?: string; // Default: 'Mod-b'
icon?: ReactNode;
className?: string;
})
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' }
]
});
FontSizePlugin(options?: {
sizes?: string[]; // Default: ['8pt', '10pt', '12pt', '14pt', '18pt', '24pt', '36pt']
defaultSize?: string;
})
TextColorPlugin(options?: {
colors?: string[];
customColors?: boolean;
recentColors?: boolean;
})
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'
}
});
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
});
ListPlugin(options?: {
bulletList?: boolean;
orderedList?: boolean;
keyboard?: {
bullet?: string; // Default: 'Mod-Shift-8'
ordered?: string; // Default: 'Mod-Shift-7'
};
})
ChecklistPlugin(options?: {
nested?: boolean;
keyboard?: string;
})
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
});
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
});
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
});
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}'
}
});
CommentsPlugin(options?: {
onCommentAdd?: (comment: Comment) => void;
onCommentEdit?: (comment: Comment) => void;
onCommentDelete?: (commentId: string) => void;
onCommentResolve?: (commentId: string) => void;
showResolved?: boolean;
})
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'
});
SpellCheckPlugin(options?: {
language?: string; // Default: 'en-US'
customDictionary?: string[];
ignoreUppercase?: boolean;
ignoreNumbers?: boolean;
})
A11yCheckerPlugin(options?: {
rules?: string[];
autoCheck?: boolean;
severity?: 'error' | 'warning' | 'info';
})
HistoryPlugin(options?: {
depth?: number; // Default: 100
keyboard?: {
undo?: string; // Default: 'Mod-z'
redo?: string; // Default: 'Mod-Shift-z'
};
})
FullscreenPlugin(options?: {
keyboard?: string; // Default: 'F11'
onEnter?: () => void;
onExit?: () => void;
})
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()
];
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()
];
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 by category)categories: explicit grouped categories with custom orderdefaultCategory: initial tabdialog: labels/placeholders/preview toggletokenTemplate: string template ({key}, {label}, {category}, {value}) or formatter functionYou 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:
id must be unique.validateTemplate(template) if you want to pre-check templates before registering.All plugins include full TypeScript definitions:
import type { Plugin, PluginConfig } from '@editora/plugins';
const customConfig: PluginConfig = {
// Full type safety
};
MIT © Ajay Kumar
FAQs
Enterprise plugin suite for Editora rich text editor in React and web apps, including tables, media, workflow, and compliance tooling.
We found that @editora/plugins demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.