🧩 Plugins

What Is Plugin?

TOAST UI Editor (henceforth referred to as ‘Editor’) provides a plugin. Plugin is an extension that can be added as needed. There are a total of 5 plugins provided by the Editor.

Plugin Name Package Name Description
chart @toast-ui/editor-plugin-chart Plugin to render chart
code-syntax-highlight @toast-ui/editor-plugin-code-syntax-highlight Plugin to highlight code syntax
color-syntax @toast-ui/editor-plugin-color-syntax Plugin to color editing text
table-merged-cell @toast-ui/editor-plugin-table-merged-cell Plugin to merge table cells
uml @toast-ui/editor-plugin-uml Plugin to render UML

How to Use Plugin

Each plugin can be installed and used with npm, or it can be used as provided CDN files.

Via Package Manager (npm)

You can install each plugin using the command, and add the name of the plugin you want to install to ${pluginName} below. For example, if you install the chart plugin, install it asnpm install @toast-ui/editor-plugin-chart.

  1. $ npm install --save @toast-ui/editor-plugin-${pluginName} # Latest Version
  2. $ npm install --save @toast-ui/editor-plugin-${pluginName}@<version> # Specific Version

When installed and used with npm, the list of files that can be imported is as follows:

  1. - node_modules/
  2. ├─ @toast-ui/editor-plugin-${pluginName}
  3. ├─ dist/
  4. ├─ toastui-editor-plugin-${pluginName}.js
  5. ├─ ...

Installed plugins can be imported as shown below depending on the environment.

  • ES Module
  1. import pluginFn from '@toast-ui/editor-plugin-${pluginName}';
  • CommonJS
  1. const pluginFn = require('@toast-ui/editor-plugin-${pluginName}');

For example, chart plugin can be imported as follows:

  1. import chart from '@toast-ui/editor-plugin-chart';

Via Contents Delivery Network (CDN)

Each plugin is available over the CDN powered by NHN Cloud.

  1. ...
  2. <body>
  3. ...
  4. <script src="https://uicdn.toast.com/editor-plugin-${pluginName}/latest/toastui-editor-plugin-${pluginName}.min.js"></script>
  5. </body>
  6. ...

If you want to use a specific version, use the tag name instead of latest in the url’s path.

The CDN directory has the following structure:

  1. - uicdn.toast.com/
  2. ├─ editor-plugin-${pluginName}/
  3. ├─ latest/
  4. ├─ toastui-editor-plugin-${pluginName}.js
  5. └─ ...
  6. ├─ 3.0.0/
  7. └─ ...

Note: Each plugin’s CDN file contains all dependencies depending on the situation, or provides different types of bundled files. For more information, please check the each plugin repository.

When importing the plugin into the namespace, use the plugin’s namespace registered under toastui.Editor.plugin.

  1. const pluginFn = toastui.Editor.plugin[${pluginName}];

For example, the chart plugin imports as follows:

  1. const { chart } = toastui.Editor.plugin;

Using the Plugin in Editor

To use a plugin imported from the Editor, use an editor’s plugins option. You can add each plugin function you imported to this option. The type of plugins option is Array.<function>.

  1. const editor = new Editor({
  2. // ...
  3. plugins: [plugin]
  4. });

For example, if you add the chart and uml plugin, you can do something like this:

  • ES Module
  1. import Editor from '@toast-ui/editor';
  2. import chart from '@toast-ui/editor-plugin-chart';
  3. import uml from '@toast-ui/editor-plugin-uml';
  4. const editor = new Editor({
  5. // ...
  6. plugins: [chart, uml]
  7. });
  • CDN
  1. const { Editor } = toastui;
  2. const { chart, uml } = Editor.plugin;
  3. const editor = new Editor({
  4. // ...
  5. plugins: [chart, uml]
  6. });

If you need an option to use in a plugin function, you can add an array value of the plugins option as a tuple.

  1. const pluginOptions = {
  2. // ...
  3. };
  4. const editor = new Editor({
  5. // ...
  6. plugins: [[plugin, pluginOptions]]
  7. });

Creating the User Plugin

In addition to the plugins provided by default, users can create and use plugin functions themselves. The method is very easy.

It defines the plugin function as shown below to return objects having specified properties.

  1. interface PluginInfo {
  2. toHTMLRenderers?: HTMLConvertorMap;
  3. toMarkdownRenderers?: ToMdConvertorMap;
  4. markdownPlugins?: PluginProp[];
  5. wysiwygPlugins?: PluginProp[];
  6. wysiwygNodeViews?: NodeViewPropMap;
  7. markdownCommands?: PluginCommandMap;
  8. wysiwygCommands?: PluginCommandMap;
  9. toolbarItems?: PluginToolbarItem[];
  10. }
  11. const pluginResult: PluginInfo = {
  12. // ...
  13. }
  14. function customPlugin() {
  15. // ...
  16. return pluginResult;
  17. }

Like other plugins, it can be used by adding plugin functions defined through the plugins option.

  1. const editor = new Editor({
  2. // ...
  3. plugins: [customPlugin]
  4. });

Plugin Return Object

Let’s find out the properties of the objects returned by the plugin. There are a total of 8 properties, as shown below, and user can define only the desired properties for customization.

  1. interface PluginInfo {
  2. toHTMLRenderers?: HTMLConvertorMap;
  3. toMarkdownRenderers?: ToMdConvertorMap;
  4. markdownCommands?: PluginCommandMap;
  5. wysiwygCommands?: PluginCommandMap;
  6. toolbarItems?: PluginToolbarItem[];
  7. markdownPlugins?: PluginProp[];
  8. wysiwygPlugins?: PluginProp[];
  9. wysiwygNodeViews?: NodeViewPropMap;
  10. }

toHTMLRenderers

toHTMLRenderers object can change the rendering results of elements when rendered in the Markdown Preview or when converted from Markdown Editor to WYSIWYG Editor. It is same as the customHTMLRenderer option in the editor.

toMarkdownRenderers

toMarkdownRenderers object can override markdown text that is converted from WYSIWYG editor to Markdown editor. The function defined in toMarkdownRenderers object has 2 parameters: nodeInfo and context.

  • nodeInfo: WYSIWYG node information when converting from WYSIWYG editor to Markdown editor.
    • node: The information about the target node.
    • parent: The parent node information of the target node.
    • index: The index as child.
  • context: The information needed for converting except nodeInfo.
    • entering: This can be seen whether it is a first visit to that node or if it is a visit after traversing all of the child nodes.
    • origin: The function that executes the operation of an original converting function.

The function defined in toMarkdownRenderers returns the token information needed to convert the result to markdown text.

  1. interface ToMdConvertorReturnValues {
  2. delim?: string | string[];
  3. rawHTML?: string | string[] | null;
  4. text?: string;
  5. attrs?: Attrs;
  6. }
  • delim: Defines symbols to be used in markdown text. It is used when it can be converted to multiple symbols, such as * and - on a list of markdown bullet list.
  • rawHTML: This text is required when converting a node to an HTML node (HTML text) in Markdown.
  • text: Text to be shown in Markdown.
  • attrs: Properties to use when converting a node to markdown text. For example, whether the task list is checked or not, or the url of the image node.

Example

  1. return {
  2. toHTMLRenderers: {
  3. // ...
  4. tableCell(node: MergedTableCellMdNode, { entering, origin }) {
  5. const result = origin!();
  6. // ...
  7. return result;
  8. },
  9. },
  10. toMarkdownRenderers: {
  11. // ...
  12. tableHead(nodeInfo) {
  13. const row = (nodeInfo.node as ProsemirrorNode).firstChild;
  14. let delim = '';
  15. if (row) {
  16. row.forEach(({ textContent, attrs }) => {
  17. const headDelim = createTableHeadDelim(textContent, attrs.align);
  18. delim += `| ${headDelim} `;
  19. // ...
  20. });
  21. }
  22. return { delim };
  23. },
  24. },
  25. };

The code above is an example of a merge table cell plugin. The return result of tableCell node defined in toHTMLRenderers is used for converting to Markdown Preview and WYSIWYG Editor, while result of tableHead nodes defined in toMarkdownRenderers are used for converting to Markdown Editor.

image

markdownCommands, wysiwygCommands

Plugin allows adding of markdown and WYSIWYG commands using markdownCommands and wysiwygCommands options.

Each command function has 3 parameters: payload, state, and dispatch, which can be used to control the internal operation of the editor based on Prosemirror.

  • payload: This is a payload that is needed to execute commands.
  • state: An instance indicating the editor’s internal state, which is the same as prosemirror-state.
  • dispatch: If you want to change the contents of an editor through command execution, you have to run the dispatch function. It is same as dispatch function of Prosemirror.

If a change occurs in the editor’s content by executing a command function, it must return true. In the opposite case, false must be returned.

  1. return {
  2. markdownCommands: {
  3. myCommand: (payload, state, dispatch) => {
  4. // ...
  5. return true;
  6. },
  7. },
  8. wysiwygCommands: {
  9. myCommand: (payload, state, dispatch) => {
  10. // ...
  11. return true;
  12. },
  13. },
  14. };

If you define and return a command function in a plugin, as shown in the example code above, that command can be used in the editor.

toolbarItems

You can also register an editor’s toolbar item from the plugin.

  1. return {
  2. // ...
  3. toolbarItems: [
  4. {
  5. groupIndex: 0,
  6. itemIndex: 3,
  7. item: toolbarItem,
  8. },
  9. ],
  10. };

Like the code above, you can set which items to add to the toolbarItems array. Each option object has 3 properties: groupIndex, itemIndex, and item`.

  • groupIndex: Toolbar group index to add toolbar item.
  • itemIndex: Toolbar item index in group.
  • item: Toolbar Item. It is the same form as the object used in toolbar customization.

If the toolbarItems option is set, as in the example code, the toolbar item will be added as the fourth index of the first toolbar group.

markdownPlugins, wysiwygPlugins

The editor use Prosemirror internally. Prosemirror provides its own plugin system. These Prosemirror plugins can also be defined in order to control out editor’s internal state. In most cases, these options are not necessary, but are often necessary. For example, code syntax highlighting plugin are used to highlight code displayed in the WYSIWYGs editor codeBlock.

  1. return {
  2. wysiwygPlugins: [() => codeSyntaxHighlighting(context, prism)],
  3. };

The method of using this option object is the same as the plugin definition method in Prosemirror, so see [here] (https://prosemirror.net/docs/ref/#state.Plugin).

wysiwygNodeViews

Markdown Editor’s contents is plain text, but WYSIWYG Editor’s content consists of specific nodes. These nodes can be customized to add attribute or class using the customHTMLRenderer option. However, there is a limit to customHTMLRenderer option if you want to control something by adding event handker or having more complex interactions. In this case, the plugin’s wysiwygNodeViews option allows customization of nodes that are rendered in the WYSIWYG Editor. This option will also be unnecessary in most cases. Like the wysiwygPlugins property, the wysiwygNodeViews property is also used in code syntax highlighting plugin.

  1. return {
  2. wysiwygNodeViews: {
  3. codeBlock: createCodeSyntaxHighlightView(registerdlanguages),
  4. },
  5. };

The method of using this option object is the same as the nodeView definition method in Prosemirror, so see [here] (https://prosemirror.net/docs/ref/#view.NodeView).

‘context’ parameter of plugin function

Plugin functions can use some information with context parameters to define the various properties described above. The context parameter contains the following properties.

  • eventEmitter: It is the same as eventEmitter in an editor. It is used to communicate with the editor.
  • usageStatistics: It decides whether to collect the plugin as GA for @toast-ui/editor.
  • i18n: It is an instance for adding i18n.
  • pmState: Some modules of [prosmirror-state] (https://prosemirror.net/docs/ref/#state).
  • pmView: Some modules of prosemirror-view.
  • pmModel: Some modules of prosemirror-model.

Example

Examples can be found here and in the plugin package.