plugins#
Type: object | string[]
Default: {}
Enables plugin instances for the editor. Import (or include) each plugin so it registers with Redactor.addPlugin, then pass plugin keys (camelCase) in the plugins setting.
The usual form is a string array:
const app = Redactor('#entry', {
plugins: ['counter']
});
Several plugins:
const app = Redactor('#entry', {
plugins: ['counter', 'emoji', 'textStats']
});
You can also pass an object map (useful when you need per-plugin options in the same place — see Plugin options below):
const app = Redactor('#entry', {
plugins: {
textStats: {
plugin: 'textStats',
options: {
containerClass: 'my-counter'
}
}
}
});
The instance key (array item, or map key) is used for getPlugin, app[key], commands (textStats.open), and option merging.
Connect plugins#
Plugins live under plugins/{slug}/ in the package. Connect them after the Redactor core, then enable them with plugins as shown above.
Script tags (no bundler)
Include each plugin after redactor.js:
<link rel="stylesheet" href="redactor.css">
<script src="redactor.js"></script>
<script src="plugins/counter/counter.js"></script>
<script>
const app = Redactor('#entry', {
plugins: ['counter']
});
</script>
ES modules / bundlers (Vite, React, Vue, …)
Import Redactor, then import the plugin module (side-effect). The plugin registers itself with Redactor.addPlugin:
import Redactor from './redactor.esm.min.js';
import './redactor.css';
import './plugins/counter.js';
const app = Redactor('#entry', {
plugins: ['counter']
});
Plugin keys#
Plugin keys use camelCase. Multi-word names are not hyphenated. The folder and filename in the package use kebab-case (the slug):
| Key | Script path in the package |
|---|---|
textStats |
plugins/text-stats/text-stats.js |
blockClass |
plugins/block-class/block-class.js |
definedLinks |
plugins/defined-links/defined-links.js |
alignment |
plugins/alignment/alignment.js |
Single-word plugins stay lowercase (anchor, math, counter). The key in plugins must match the name passed to Redactor.addPlugin.
When you use the object map with plugin: 'name', Redactor resolves the class in this order:
Redactor.getPlugin(name)— plugins registered withRedactor.addPluginwindow.RedactorPlugins[name]— fallback for legacy/global bundles
If the class cannot be resolved and debug: true, a warning is printed and the entry is skipped.
Custom plugins you author yourself can call Redactor.addPlugin(key, YourPluginClass) from your code, then enable them with the same string-key pattern. See Create a plugin.
Plugin options#
Options are merged in this order (later wins):
PluginClass.defaultOptions— defaults defined on the plugin classplugins[key].options— per-instance options in thepluginsmap- Top-level
[key]— options under the same camelCase name as the instance key
Top-level options (typical)
Pass plugin options at the top level by plugin key, not inside plugins:
const app = Redactor('#entry', {
plugins: ['textStats'],
textStats: {
containerClass: 'my-counter'
}
});
const app = Redactor('#entry', {
plugins: ['alignment', 'math'],
alignment: {
context: true
},
math: {
classname: 'katex'
}
});
Options inside the plugins map
const app = Redactor('#entry', {
plugins: {
textStats: {
plugin: 'textStats',
options: {
containerClass: 'my-counter'
}
}
}
});
Inside a plugin, merged options are available as this.options. Some plugins also read this.app.getOption('pluginKey') for the same merged object.