# Plugins [中文文档见此](./plugin.zh-CN.md) ## What can plugins do? Plugins can insert buttons into menu bar, and control editor's content. ## Use or un-use a plugin Through the `use` and `unuse` APIs, or through the `plugins` property. See the [API documentation](./api.md) and [configure documentation](./configure.md) ## Built-in plugins ### Plugins list Those plugins are built-in plugin: * header: title * font-bold: bold * font-italic: italic * font-underline: underline * font-strikethrough: strikethrough * list-unordered: unordered * list-ordered: ordered * block-quote: quote * block-wrap: wrap new line * block-code-inline: inline code * block-code-block: block code * table: table * image: image upload * link: hyperlinks * clear: clear texts * logger: history (undo/redo) * mode-toggle: toggle view mode * full-screen: toggle full screen * auto-resize: auto-resize plugin (disabled by default) * tab-insert: insert tab or spaces (disabled by default) ```js [ 'header', 'font-bold', 'font-italic', 'font-underline', 'font-strikethrough', 'list-unordered', 'list-ordered', 'block-quote', 'block-wrap', 'block-code-inline', 'block-code-block', 'table', 'image', 'link', 'clear', 'logger', 'mode-toggle', 'full-screen', 'tab-insert' ] ``` * If you enabled `logger` plugin, it will auto register `undo` and `redo` API, you can use them with `callPluginApi`. ### Un-use a built-in plugin ```js import Editor, { Plugins } from 'react-markdown-editor-lite'; Editor.unuse(Plugins.Header); // header Editor.unuse(Plugins.FontBold); // font-bold ``` ### Use auto-resize plugin ```js import Editor, { Plugins } from 'react-markdown-editor-lite'; Editor.use(Plugins.AutoResize, { min: 200, // min height max: 600, // max height }); ``` ### Use tab-insert plugin By default, Markdown Editor will lose input focus when user type a Tab key. You can use the built-in tab-insert plugin to solve this problem. ```js import Editor, { Plugins } from 'react-markdown-editor-lite'; Editor.use(Plugins.TabInsert, { /** * Number of spaces will be inputted when user type a Tab key. * Especially, note that 1 means a '\t' instead of ' '. * Default value is 1. */ tabMapValue: 1, }); ``` ### Insert dividers `divider` is a special plugin, you can not un-use it, and you also shouldn't use it. If you want to insert a divider into toolbar, just put `divider` into the `plugins` array. ```js import Editor, { Plugins } from 'react-markdown-editor-lite'; const plugins = ['header', 'table', 'divider', 'link', 'clear', 'divider', 'font-bold']; ``` ## Demo ```js import Editor, { Plugins } from 'react-markdown-editor-lite'; import MyPlugin from './MyPlugin'; Editor.use(MyPlugin); // Remove built-in header plugin here, in all editors Editor.unuse(Plugins.Header); // Remove built-in image plugin here, only this editor const plugins = ['header', 'table', 'my-plugins', 'link', 'clear', 'logger', 'mode-toggle', 'full-screen']; ``` ## Written a plugin ### Demos * [Demo](https://codesandbox.io/s/rmel-demo-write-plugin-p82fc) * [SSR Demo](https://codesandbox.io/s/next-js-80bne) ### Normal Plugin is a React Component, and must extend PluginComponent or implement FunctionPlugin. In PluginComponent, you can: * Get editor instance by `this.editor`, and call all editor's APIs. * Get editor's config by `this.editorConfig`. * Get the options passed in use by `this.getConfig` or `this.props.config`. In PluginComponent, you can: * Get editor instance by `props.editor`, and call all editor's APIs. * Get editor's config by `props.editorConfig`. * Get the options passed in use by `props.config`. In following, we written a counter, insert an increasing number into the editor with each click. The starting number is read from the options passed in use. ```js import { PluginComponent } from 'react-markdown-editor-lite'; interface CounterState { num: number; } interface CounterConfig { start: number; } class Counter extends PluginComponent { // Define plugin name here, must be unique static pluginName = 'counter'; // Define which place to be render, default is left, you can also use 'right' static align = 'left'; // Define default config if required static defaultConfig = { start: 0 } constructor(props: any) { super(props); this.handleClick = this.handleClick.bind(this); this.state = { num: this.getConfig('start') }; } handleClick() { // Call API, insert number to editor this.editor.insertText(this.state.num); // Update itself's state this.setState({ num: this.state.num++ }); } render() { return ( {this.state.num} ); } } // Usage: Editor.use(Counter, { start: 10 }); // Or: ``` ### Function component You can also use function component to write a plugin ```js import React from 'react'; import { FunctionPlugin } from 'react-markdown-editor-lite'; interface CounterState { num: number; } interface CounterConfig { start: number; } const Counter: FunctionPlugin = (props) => { const [num, setNum] = React.useState(props.config.start); const handleClick = () => { // Call API, insert number to editor props.editor.insertText(num); // Update itself's state setNum(num + 1); } return ( {num} ); } // Must define plugin name Counter.pluginName = 'counter'; // Define default config if required Counter.defaultConfig = { start: 0 } Counter.align = 'left'; // Usage: Editor.use(Counter, { start: 10 }); // Or: ``` ## Is it possible not to render any UI ? Yes, just return a empty element (such as ``, etc) in `render` method.