Pure javascript based WYSIWYG html editor, with no dependencies.

Overview

SunEditor

Pure javscript based WYSIWYG web editor, with no dependencies

Demo : suneditor.com

GitHub GitHub release npm version bower version npm npm bundle size (minified + gzip)

The Suneditor is a lightweight, flexible, customizable WYSIWYG text editor for your web applications.

  • Pasting from Microsoft Word and Excel.
  • Custom table selection, merge and split.
  • Media embed, images upload.
  • Can use CodeMirror, KaTeX.
  • And.. many other features :)

WYSIWYG HTML Editor

Table of contents

Browser Support

Chrome Chrome Firefox Firefox Opera Opera Safari Safari Edge Edge Explorer Internet Explorer
Yes Yes Yes Yes Yes 11+

Install

Npm

$ npm install suneditor --save

Bower

$ bower install suneditor --save

CDN

<link href="https://cdn.jsdelivr.net/npm/suneditor@latest/dist/css/suneditor.min.css" rel="stylesheet">
<!-- <link href="https://cdn.jsdelivr.net/npm/suneditor@latest/assets/css/suneditor.css" rel="stylesheet"> -->
<!-- <link href="https://cdn.jsdelivr.net/npm/suneditor@latest/assets/css/suneditor-contents.css" rel="stylesheet"> -->
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/dist/suneditor.min.js"></script>
<!-- languages (Basic Language: English/en) -->
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/lang/ko.js"></script>

jsdelivr/suneditor

Getting Started

1. Target Element

<textarea id="sample">Hi</textarea>

2. Create

/**
* ID : 'suneditor_sample'
* ClassName : 'sun-eidtor'
*/
// ID or DOM object
const editor = SUNEDITOR.create((document.getElementById('sample') || 'sample'),{
    // All of the plugins are loaded in the "window.SUNEDITOR" object in dist/suneditor.min.js file
    // Insert options
    // Language global object (default: en)
    lang: SUNEDITOR_LANG['ko']
});

3. Contents display

When you display a document created by suneditor
You need to include "src/assets/css/suneditor-contents.css" or "dist/css/suneditor.min.css" file.
Then add "sun-editor-editable" to the class name of the Tag element that displays the content.
If you are using RTL mode, you also need to add "se-rtl".
In "suneditor-contents.css", you can define the style of all the tags created in suneditor.

When inserting custom tags in the editor

- Empty tags without meaning or tags that do not fit the editor's format are modified or deleted.
    Tags with the class name "se-component" or "__se__tag" of the top-level tag will not be deleted.
        "se-component" is the component type of the editor.
        Class name for wrapper tags such as images and videos.

Use import statement

1. Load only what you want

import 'suneditor/dist/css/suneditor.min.css'
// import 'suneditor/assets/css/suneditor.css'
// import 'suneditor/assets/css/suneditor-contents.css'
import suneditor from 'suneditor'

// How to import plugins
import image from 'suneditor/src/plugins/dialog/link'
import list from 'suneditor/src/plugins/submenu/list'
import {font, video} from 'suneditor/src/plugins'

// How to import language files (default: en)
import lang from 'suneditor/src/lang'
import {ko} from 'suneditor/src/lang'
import de from 'suneditor/src/lang/de'

suneditor.create('sample', {
    plugins: [font, video, image, list],
    buttonList: [
        ['font', 'video', 'image', 'list']
    ],
    lang: lang.ko
});

2. Load all plugins

import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
import plugins from 'suneditor/src/plugins'

suneditor.create('sample', {
    plugins: plugins,
    buttonList: [
        ['undo', 'redo'],
        ['font', 'fontSize', 'formatBlock'],
        ['paragraphStyle', 'blockquote'],
        ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
        ['fontColor', 'hiliteColor', 'textStyle'],
        ['removeFormat'],
        '/', // Line break
        ['outdent', 'indent'],
        ['align', 'horizontalRule', 'list', 'lineHeight'],
        ['table', 'link', 'image', 'video', 'audio' /** ,'math' */], // You must add the 'katex' library at options to use the 'math' plugin.
        /** ['imageGallery'] */ // You must add the "imageGalleryUrl".
        ['fullScreen', 'showBlocks', 'codeView'],
        ['preview', 'print'],
        ['save', 'template'],
        /** ['dir', 'dir_ltr', 'dir_rtl'] */ // "dir": Toggle text direction, "dir_ltr": Right to Left, "dir_rtl": Left to Right
    ]
})

// You can also load what you want
suneditor.create('sample', {
    plugins: [plugins.font],
    // Plugins can be used directly in the button list
    buttonList: [
        ['font', plugins.image]
    ]
})

3. Plugins can be used directly in the button list

import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
import {align, font, fontSize, fontColor, hiliteColor, 
        horizontalRule, image, template} from 'suneditor/src/plugins'

suneditor.create('sample', {
    buttonList: [
        ['undo', 'redo', 'removeFormat'],
        [align, font, fontSize, fontColor, hiliteColor],
        [horizontalRule, image, template]
    ],
})

Init function

The init function can be used by predefining options and calling the create function on the returned object.
The value of the option argument put in the "create" function call takes precedence
import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
import plugins from 'suneditor/src/plugins'

// all plugins
const initEditor = suneditor.init({
    plugins: plugins,
    height: 200,
    buttonList: [
        [
        'undo', 'redo',
        'font', 'fontSize', 'formatBlock',
        'paragraphStyle', 'blockquote',
        'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript',
        'fontColor', 'hiliteColor', 'textStyle',
        'removeFormat',
        'outdent', 'indent',
        'align', 'horizontalRule', 'list', 'lineHeight',
        'table', 'link', 'image', 'video', 'audio', /** 'math', */ // You must add the 'katex' library at options to use the 'math' plugin.
        /** 'imageGallery', */ // You must add the "imageGalleryUrl".
        'fullScreen', 'showBlocks', 'codeView',
        'preview', 'print', 'save', 'template',
        /** 'dir', 'dir_ltr', 'dir_rtl' */ // "dir": Toggle text direction, "dir_ltr": Right to Left, "dir_rtl": Left to Right
        ]
    ]
});

initEditor.create('sample_1', {
    // The value of the option argument put in the "create" function call takes precedence
});

initEditor.create('sample_2', {
    // The value of the option argument put in the "create" function call takes precedence
    height: 'auto',
    buttonList: [
        ['bold', 'underline', 'italic'],
        ['removeFormat'],
        ['preview', 'print']
    ]
});

Use CodeMirror

<!-- https://github.com/codemirror/CodeMirror -->
<!-- codeMirror (^5.0.0) -->
<!-- Use version 5.x.x -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/mode/htmlmixed/htmlmixed.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/mode/xml/xml.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/mode/css/css.js"></script>
import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
// Import codeMirror
import CodeMirror from 'codemirror'
import 'codemirror/mode/htmlmixed/htmlmixed'
import 'codemirror/lib/codemirror.css'

suneditor.create('sample', {
    codeMirror: CodeMirror // window.CodeMirror,
    // Set options
    // codeMirror: {
    //     src: CodeMirror,
    //     options: {...}
    // }
    buttonList: [
        ['codeView']
    ],
    height: 400
});

Use KaTeX (math plugin)

<!-- https://github.com/KaTeX/KaTeX -->
<!-- KaTeX (^0.11.1) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"></script>
import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
// Import katex
import katex from 'katex'
import 'katex/dist/katex.min.css'

suneditor.create('sample', {
    katex: katex // window.katex,
    // Set options
    // katex: {
    //     src: katex,
    //     options: {...}
    // }
    buttonList: [
        ['math']
    ]
});

Options

plugins: [
    /** command */
    blockquote,
    /** Submenu */
    align,
    font,
    fontColor,
    fontSize,
    formatBlock,
    hiliteColor,
    horizontalRule,
    lineHeight,
    list,
    paragraphStyle,
    table,
    template,
    textStyle,
    /** Dialog */
    image,
    link,
    video,
    audio,
    math, // You must add the 'katex' library at options to use the 'math' plugin.
    /** File browser */
    // You must add the "imageGalleryUrl".
    // A button is added to the image modal.
    // You can also use image gallery by adding it directly to the button list. (You must add "image" plugin.)
    imageGallery
]
: Plugins array.     default: null {Array}

// Values
lang            : language object.   default : en {Object}
defaultTag      : Specifies default tag name of the editor.     default: 'p' {String}
textTags        : You can change the tag of the default text button.   default: { bold: 'STRONG', underline: 'U', italic: 'EM', strike: 'DEL' }
                  ex) {
                      bold: 'b',
                      strike: 's'
                  }
value           : Initial value(html string) of the edit area.
                  If not, the value of the "target textarea".   default: null {String}
historyStackDelayTime : When recording the history stack, this is the delay time(miliseconds) since the last input.  default: 400 {Number}

// Whitelist, Blacklist -----------------------------------------------------------------------------------------
// (You can use regular expression syntax.)
// _defaultTagsWhitelist : 'br|p|div|pre|blockquote|h1|h2|h3|h4|h5|h6|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup|code|svg|path|details|summary'
addTagsWhitelist      : Add tags to the default tags whitelist of editor.   default: '' {String}
                        ex) 'mark|canvas|label|select|option|input|//' // "//" This means HTML comments.
                        ex) '*' // This means all tags are allowed. (Not available on "blacklist")
tagsBlacklist         : Blacklist of the editor default tags.               default: null {String}
                        ex) 'h1|h2'
// _editorTagsWhitelist  : _defaultTagsWhitelist + addTagsWhitelist - tagsBlacklist
pasteTagsWhitelist    : Whitelist of tags when pasting.                     default: _editorTagsWhitelist {String}
                        ex) 'p|h1|h2|h3'
                        ex) '*' // This means all tags are allowed. (Not available on "blacklist")
pasteTagsBlacklist    : Blacklist of tags when pasting.                     default: null {String}
                        ex) 'h1|h2'
attributesWhitelist   : Add attributes whitelist of tags that should be kept undeleted from the editor.   default: null {Object}
                        // -- Fixed whitelist --
                        // Native attributes: 'contenteditable|colspan|rowspan|target|href|download|rel|src|alt|class|type|controls'
                        // Editor attributes: 'data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|origin-size|data-exp|data-font-size'
                        ex) {
                            'all': 'style|data-.+', // Apply to all tags
                            'input': 'checked|name' // Apply to input tag
                            '???': '*' // "*" === all attributes
                        }
attributesBlacklist   : Add attribute blacklist of tags that should be deleted in editor.   default: null {Object}
                        ex) {
                            'all': 'id', // Apply to all tags
                            'input': 'style' // Apply to input tag
                            '???': '*' // "*" === all attributes
                        }
// Layout-------------------------------------------------------------------------------------------------------
mode            : The mode of the editor ('classic', 'inline', 'balloon', 'balloon-always'). default: 'classic' {String}
rtl             : If true, the editor is set to RTL(Right To Left) mode.   default: false {Boolean}
lineAttrReset   : Deletes other attributes except for the property set at the time of line break.
                  If there is no value, no all attribute is deleted.    default: '' {String}
                  ex) 'class|style': Attributes other than "class" and "style" are deleted at line break.
                      '*': All attributes are deleted at line break.
toolbarWidth    : The width of the toolbar. Applies only when the editor mode is 
                  'inline' or 'balloon' mode.     default: 'auto' {Number|String}
toolbarContainer: A custom HTML selector placing the toolbar inside.
                  The class name of the element must be 'sun-editor'.
                  Element or querySelector argument.     default: null {Element|String}
                  ex) document.querySelector('#id') || '#id'
stickyToolbar   : Top offset value of "sticky toolbar".
                  Set to 0, '0px', '50px'...
                  If set to -1 or false or null to turn off.        default: 0 {Number|String|Boolean}
hideToolbar     : The toolbar is rendered hidden.                   default: false {Boolean}
fullScreenOffset: Top offset value of "full Screen".
                  Set to 0, '0px', '50px'...     default: 0 {Number|String}
iframe          : Content will be placed in an iframe and isolated from the rest of the page.  default: false {Boolean}
fullPage        : Allows the usage of HTML, HEAD, BODY tags and DOCTYPE declaration.  default: false {Boolean}
iframeAttributes  : Attributes of the iframe.                       default: null {Object}
                    ex) {'scrolling': 'no'}
iframeCSSFileName : Name or Array of the CSS file to apply inside the iframe.
                    You can also use regular expressions.
                    Applied by searching by filename in the link tag of document,
                    or put the URL value (".css" can be omitted).   default: 'suneditor' {Array|String}
                    ex) '.+' or ['suneditor', 'http://suneditor.com/sample/css/sample.css', '.+\\.min\\.css']
previewTemplate : A template of the "preview".
                  The {{contents}} part in the HTML string is replaced with the contents of the editor. default: null {String}
                  ex) "<div style='width:auto; max-width:1080px; margin:auto;'><h1>Preview Template</h1> {{contents}} <div>_Footer_</div></div>"
printTemplate   : A template of the "print".
                  The {{contents}} part in the HTML string is replaced with the contents of the editor. default: null {String}
                  ex) "<div style='width:auto; max-width:1080px; margin:auto;'><h1>Print Template</h1> {{contents}} <div>_Footer_</div></div>"
codeMirror      : If you put the CodeMirror object as an option, you can do Codeview using CodeMirror. default: null {Object}
                  Use version 5.x.x // https://github.com/codemirror/CodeMirror
                  ex) codeMirror: CodeMirror // Default option
                      codeMirror: { // Custom option
                        src: CodeMirror,
                        options: {
                            /** default options **
                            * mode: 'htmlmixed',
                            * htmlMode: true,
                            * lineNumbers: true
                            * lineWrapping: true
                            */
                        }
                      }
katex           : Required library for math plugins.               default: null {Object}
                  Use version 0.x.x // https://github.com/KaTeX/KaTeX
                  ex) katex: katex // Default option
                      katex: { // Custom option
                        src: katex,
                        options: {
                            /** default options **
                            * throwOnError: false,
                            */
                        }
                      }
mathFontSize    : Math plugin font size list.                       default: [{..}] {Array}
                  Default value: [
                    {text: '1', value: '1em', default: true},
                    {text: '1.5', value: '1.5em'},
                    {text: '2', value: '2em'},
                    {text: '2.5', value: '2.5em'}
                  ]

// Display-------------------------------------------------------------------------------------------------------
position        : The position property of suneditor.               default: null {String}
display         : The display property of suneditor.                default: 'block' {String}
popupDisplay    : Size of background area when activating dialog window ('full'||'local') default: 'full' {String}

// Bottom resizing bar-------------------------------------------------------------------------------------------
resizingBar     : Show the bottom resizing bar.
                  If 'height' value is 'auto', it will not be resized. default: true {Boolean}
showPathLabel   : Displays the current node structure to resizingBar.  default: true {Boolean}
resizeEnable  : Enable/disable resize function of bottom resizing bar.   default: true {Boolean}
resizingBarContainer: A custom HTML selector placing the resizing bar inside.
                      The class name of the element must be 'sun-editor'.
                      Element or querySelector argument.     default: null {Element|String}
                      ex) document.querySelector('#id') || '#id'

// Character count-----------------------------------------------------------------------------------------------
charCounter     : Shows the number of characters in the editor.     
                  If the maxCharCount option has a value, it becomes true. default: false {Boolean}
charCounterType : Defines the calculation method of the "charCounter" option.
                  'char': Characters length.
                  'byte': Binary data size of characters.
                  'byte-html': Binary data size of the full HTML string.   default: 'char' {String}
charCounterLabel: Text to be displayed in the "charCounter" area of the bottom bar.
                  Screen ex) 'charCounterLabel : 20/200'.           default: null {String}
maxCharCount    : The maximum number of characters allowed to be inserted into the editor. default: null {Number}

// Width size----------------------------------------------------------------------------------------------------
width           : The width size of the editor.                     default: clientWidth||'100%' {Number|String}
minWidth        : The min-width size of the editor.
                  Used when 'width' value is 'auto' or '~%'.        default: null {Number|String}
maxWidth        : The max-width size of the editor.
                  Used when 'width' value is 'auto' or '~%'.        default: null {Number|String}

// Height size---------------------------------------------------------------------------------------------------
height          : The height size of the editor.                    default: clientHeight||'auto' {Number|String}
minHeight       : The min-height size of the editor.
                  Used when 'height' value is 'auto'.               default: null {Number|String}
maxHeight       : The max-height size of the editor.
                  Used when 'height' value is 'auto'.               default: null {Number|String}

// Editing area -------------------------------------------------------------------------------------------------
className       : Add a "class" to the editing area[.sun-editor-editable].    default: '' {String}
defaultStyle    : You can define the style of the editing area[.sun-editor-editable].
                  It affects the entire editing area.               default: '' {String}
                  ('z-index', 'position' and 'width' properties apply to the top div.)
                  ex) 'font-family: cursive; font-size: 10px;'

// Defining menu items-------------------------------------------------------------------------------------------
font            : Change default font-family array.                 default: [...] {Array}
                  Default value: [
                    'Arial', 'Comic Sans MS', 'Courier New', 'Impact',
                    'Georgia','tahoma', 'Trebuchet MS', 'Verdana'
                  ]
fontSize        : Change default font-size array.                   default: [...] {Array}
                  Default value: [
                    8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
                  ]
fontSizeUnit    : The font size unit.                               default: 'px' {String}
alignItems      : A list of drop-down options for the 'align' plugin.   default: rtl === true ? ['right', 'center', 'left', 'justify'] : ['left', 'center', 'right', 'justify'] {Array}
formats         : Change default formatBlock array.                 default: [...] {Array}
                  Default value: [
                    'p', 'div', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
                    // "blockquote": range format, "pre": free format, "Other tags": replace format
                  ],
                  Custom: [{
                    tag: 'div', // Tag name
                    name: 'Custom div' || null, // default: tag name
                    command: 'replace' || 'range' || 'free', // default: "replace"
                    class: '__se__format__replace_xxx' || '__se__format__range_xxx' || '__se__format__free_xxx' || '__se__format__free__closure_xxx'
                    // Class names must always begin with "__se__format__(replace, range, free)_"
                  }]
colorList       : Change default color array of color picker.       default: [..[..]..] {Array}
                  Default value: [
                    '#ff0000', '#ff5e00', '#ffe400', '#abf200', '#00d8ff', '#0055ff', '#6600ff', '#ff00dd', '#000000',
                    '#ffd8d8', '#fae0d4', '#faf4c0', '#e4f7ba', '#d4f4fa', '#d9e5ff', '#e8d9ff', '#ffd9fa', '#f1f1f1',
                    '#ffa7a7', '#ffc19e', '#faed7d', '#cef279', '#b2ebf4', '#b2ccff', '#d1b2ff', '#ffb2f5', '#bdbdbd',
                    '#f15f5f', '#f29661', '#e5d85c', '#bce55c', '#5cd1e5', '#6699ff', '#a366ff', '#f261df', '#8c8c8c',
                    '#980000', '#993800', '#998a00', '#6b9900', '#008299', '#003399', '#3d0099', '#990085', '#353535',
                    '#670000', '#662500', '#665c00', '#476600', '#005766', '#002266', '#290066', '#660058', '#222222'
                  ]
                  ex) [
                    ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown'], // Line break
                    ['SlateGray', 'BurlyWood', 'DeepPink', 'FireBrick', 'Gold', 'SeaGreen']
                  ]
lineHeights     : Change default line-height array.                 default: [{}..] {Array}
                  Default value: [
                    {text: '1', value: 1},
                    {text: '1.15', value: 1.15},
                    {text: '1.5', value: 1.5},
                    {text: '2', value: 2}
                  ]
                  ex) [
                    {text: 'Single', value: 1},
                    {text: 'Double', value: 2}
                  ]
paragraphStyles : You can apply custom class to format.
                  ex) '.sun-editor-editable .__se__customClass'
                      '.sun-editor .__se__customClass' // If you want to apply styles to menu items as well
                  Default value: [
                    {
                        name: 'Spaced', // Format style name
                        class: '__se__p-spaced', // Define style for used class (Class names must always begin with "__se__")
                        _class: '' // You can control the style of the tags displayed in the menu by putting a class on the button of the menu.
                    },
                    {
                        name: 'Bordered',
                        class: '__se__p-bordered'
                    },
                    {
                        name: 'Neon',
                        class: '__se__p-neon'
                    }
                  ]
                  ex) [
                      'spaced', 'neon', // The default value is called by name only and the name is called in the language file.
                      {
                          name: 'Custom',
                          class: '__se__customClass'
                      }
                  ]
textStyles      : You can apply custom style or class to selected text.
                  ex(using a class)) '.sun-editor-editable .__se__customClass'
                                     '.sun-editor .__se__customClass' // If you want to apply styles to menu items as well
                  Default value: [
                    {
                        name: 'Code',
                        class: '__se__t-code',
                        tag: 'code',
                    },
                    {
                        name: 'Translucent', // Text style name
                        style: 'opacity: 0.5;', // Style query
                        tag: 'span', // Style tag name (default: span)
                        _class: '' // You can control the style of the tags displayed in the menu by putting a class on the button of the menu.
                    },
                    {
                        name: 'Shadow',
                        class: '__se__t-shadow', // Class names (Class names must always begin with "__se__")
                        tag: 'span'
                    }
                  ]
                  ex) [
                      'Code', // The default value is called by name only and the name is called in the language file.
                      {
                          name: 'Emphasis',
                          style: '-webkit-text-emphasis: filled;',
                          tag: 'span'
                      }
                  ]

// Image---------------------------------------------------------------------------------------------------------
imageResizing   : Can resize the image.                               default: true {Boolean}
imageHeightShow : Choose whether the image height input is visible.   default: true {Boolean}
imageAlignShow  : Choose whether the image align radio buttons are visible.       default: true {Boolean}
imageWidth      : The default width size of the image frame.          default: 'auto' {String}
imageHeight     : The default height size of the image frame.         default: 'auto' {String}
imageSizeOnlyPercentage : If true, image size can only be scaled by percentage.   default: false {Boolean}
imageRotation   : Choose whether to image rotation buttons display.
                  When "imageSizeOnlyPercentage" is "true" or  or "imageHeightShow" is "false" the default value is false.                       
                  If you want the button to be visible, put it a true.     default: true {Boolean}
imageFileInput  : Choose whether to create a file input tag in the image upload window.  default: true {Boolean}
imageUrlInput   : Choose whether to create a image url input tag in the image upload window.
                  If the value of imageFileInput is false, it will be unconditionally.   default: true {Boolean}
imageUploadHeader : Http Header when uploading images.              default: null {Object}
imageUploadUrl  : The image upload to server mapping address.       default: null {String}
                  (When not used the "imageUploadUrl" option, image is enters base64 data)
                  ex) "/editor/uploadImage"
                  request format: {
                            "file-0": File,
                            "file-1": File
                        }
                  response format: {
                            "errorMessage": "insert error message",
                            "result": [
                                {
                                    "url": "/download/editorImg/test_image.jpg",
                                    "name": "test_image.jpg",
                                    "size": "561276"
                                }
                            ]
                        }
imageUploadSizeLimit: The size of the total uploadable images (in bytes).
                      Invokes the "onImageUploadError" method.  default: null {Number}
imageMultipleFile: If true, multiple images can be selected.    default: false {Boolean}
imageAccept      : Define the "accept" attribute of the input.  default: "*" {String}
                   ex) "*" or ".jpg, .png .."
// Image - image gallery
imageGalleryUrl     : The url of the image gallery, if you use the image gallery.
                      When "imageUrlInput" is true, an image gallery button is created in the image modal.
                      You can also use it by adding "imageGallery" to the button list.   default: null {String}
                      ex) "/editor/getGallery"
                      response format: {
                            "result": [
                                {
                                    "src": "/download/editorImg/test_image.jpg", // @Require
                                    "thumbnail": "/download/editorImg/test_thumbnail.jpg", // @Option - Thumbnail image to be displayed in the image gallery.
                                    "name": "Test image", // @Option - default: src.split('/').pop()
                                    "alt": "Alt text", // @Option - default: src.split('/').pop()
                                    "tag": "Tag name" // @Option
                                }
                            ],
                            "nullMessage": "Text string or HTML string", // It is displayed when "result" is empty.
                            "errorMessage": "Insert error message", // It is displayed when an error occurs. 
                        }
                      You can redefine the "plugins.imageGallery.drawItems" method.
imageGalleryHeader: Http Header when get image gallery.         default: null {Object}

// Video----------------------------------------------------------------------------------------------------------
videoResizing   : Can resize the video (iframe, video).                         default: true {Boolean}
videoHeightShow : Choose whether the video height input is visible.    default: true {Boolean}
videoAlignShow  : Choose whether the video align radio buttons are visible.       default: true {Boolean}
videoRatioShow  : Choose whether the video ratio options is visible.   default: true {Boolean}
videoWidth      : The default width size of the video frame.           default: '100%' {String}
videoHeight     : The default height size of the video frame.          default: '56.25%' {String}
videoSizeOnlyPercentage : If true, video size can only be scaled by percentage.   default: false {Boolean}
videoRotation   : Choose whether to video rotation buttons display.
                  When "videoSizeOnlyPercentage" is "true" or "videoHeightShow" is "false" the default value is false.
                  If you want the button to be visible, put it a true.     default: true {Boolean}
videoRatio      : The default aspect ratio of the video.
                  Up to four decimal places are allowed.             default: 0.5625 (16:9) {Float}
videoRatioList  : Video ratio selection options.
                  default: [
                    {name: '16:9', value: 0.5625},
                    {name: '4:3', value: 0.75},
                    {name: '21:9', value: 0.4285}
                  ],
                  ex) [
                    {name: 'Classic Film 3:2', value: 0.6666},
                    {name: 'HD', value: 0.5625}
                  ]
youtubeQuery    : The query string of a YouTube embedded URL.        default: '' {String}
                  It takes precedence over the value user entered.
                  ex) 'autoplay=1&mute=1&enablejsapi=1&controls=0&rel=0&modestbranding=1'
                    // https://developers.google.com/youtube/player_parameters
videoFileInput  : Choose whether to create a file input tag in the video upload window.  default: false {Boolean}
videoUrlInput   : Choose whether to create a video url input tag in the video upload window.
                  If the value of videoFileInput is false, it will be unconditionally.   default: true {Boolean}
videoUploadHeader : Http Header when uploading videos.              default: null {Object}
videoUploadUrl  : The video upload to server mapping address.       default: null {String}
                  ex) "/editor/uploadVideo"
                  request format: {
                            "file-0": File,
                            "file-1": File
                        }
                  Use video tags. (supported video formats: '.mp4', '.webm', '.ogg')
                  response format: {
                            "errorMessage": "insert error message",
                            "result": [
                                {
                                    "url": "/download/editorVideos/test_video.mp4",
                                    "name": "test_video.mp4",
                                    "size": "561276"
                                }
                            ]
                        }
videoUploadSizeLimit: The size of the total uploadable videos (in bytes).
                      Invokes the "onVideoUploadError" method.  default: null {Number}
videoMultipleFile: If true, multiple videos can be selected.    default: false {Boolean}
videoTagAttrs    : Define "Attributes" of the video tag.                      default: null {Object} 
                   ex) { poster: "http://suneditor.com/docs/loading.gif", autoplay: true }
videoIframeAttrs : Define "Attributes" of the iframe tag. (Youtube, Vimeo).   default: null {Object}
                   ex) { style: "border: 2px solid red;" }
videoAccept      : Define the "accept" attribute of the input.  default: "*" {String}
                   ex) "*" or ".mp4, .avi .."

// Audio----------------------------------------------------------------------------------------------------------
audioWidth      : The default width size of the audio frame.        default: '300px' {String}
audioHeight     : The default height size of the audio frame.       default: '54px' {String}
audioFileInput  : Choose whether to create a file input tag in the audio upload window.  default: false {Boolean}
audioUrlInput   : Choose whether to create a audio url input tag in the audio upload window.
                  If the value of audioFileInput is false, it will be unconditionally.   default: true {Boolean}
audioUploadHeader : Http Header when uploading audios.              default: null {Object}
audioUploadUrl  : The audio upload to server mapping address.       default: null {String}
                  ex) "/editor/uploadAudio"
                  request format: {
                            "file-0": File,
                            "file-1": File
                        }
                  Use audio tags. (supported audio formats: '.mp4', '.webm', '.ogg')
                  response format: {
                            "errorMessage": "insert error message",
                            "result": [
                                {
                                    "url": "/download/editorAudios/test_audio.mp3",
                                    "name": "test_audio.mp3",
                                    "size": "561276"
                                }
                            ]
                        }
audioUploadSizeLimit: The size of the total uploadable audios (in bytes).
                      Invokes the "onAudioUploadError" method.  default: null {Number}
audioMultipleFile: If true, multiple audios can be selected.    default: false {Boolean}
audioTagAttrs    : Define "Attributes" of the audio tag.        default: null {Object} 
                   ex) { controlslist: "nodownload", autoplay: true }
videoAccept      : Define the "accept" attribute of the input.  default: "*" {String}
                   ex) "*" or ".mp3, .wav .."

// Table----------------------------------------------------------------------------------------------------------
tableCellControllerPosition : Define position to the table cell controller('cell', 'top'). default: 'cell' {String}

// Link-----------------------------------------------------------------------------------------------------------
linkTargetNewWindow : Default checked value of the "Open in new window" checkbox.   default: false {Boolean}
linkProtocol    : Default protocol for the links. ('link', 'image', 'video', 'audio')
                  This applies to all plugins that enter the internet url.   default: null {String}
linkRel         : Defines "rel" attribute list of anchor tag.   default: [] {Array}
                  // https://www.w3schools.com/tags/att_a_rel.asp
                  ex) [
                    'author',
                    'external',
                    'help',
                    'license',
                    'next',
                    'follow',
                    'nofollow',
                    'noreferrer',
                    'noopener',
                    'prev',
                    'search',
                    'tag'
                ]
linkRelDefault  : Defines default "rel" attributes of anchor tag.   default: {} {Object}
                  ex) linkRelDefault: {
                        default: 'nofollow', // Default rel
                        check_new_window: 'noreferrer noopener', // When "open new window" is checked 
                        check_bookmark: 'bookmark' // When "bookmark" is checked 
                    },
                    // If properties other than "default" start with "only:", the existing "rel" is cleared and applied. 
                    linkRelDefault: {
                        check_new_window: 'only:noreferrer noopener'
                    }
linkNoPrefix   : If true, disables the automatic prefixing of the host URL to the value of the link. default: false {Boolean}

// HR----------------------------------------------------------------------------------------------------
hrItems         : Defines the hr items.
                  "class" or "style" must be specified.
                  default: [
                      {name: lang.toolbar.hr_solid, class: '__se__solid'},
                      {name: lang.toolbar.hr_dashed, class: '__se__dashed'},
                      {name: lang.toolbar.hr_dotted, class: '__se__dotted'}
                  ]
                  ex) [ {name: "Outset", style: "border-style: outset;"} ]


// Key actions----------------------------------------------------------------------------------------------------
tabDisable      : If true, disables the interaction of the editor and tab key.  default: false {Boolean}
shortcutsDisable: You can disable shortcuts.    default: [] {Array}
                  ex) ['bold', 'strike', 'underline', 'italic', 'undo', 'indent', 'save']
shortcutsHint   : If false, hide the shortcuts hint.    default: true {Boolean}

// Defining save button-------------------------------------------------------------------------------------------
callBackSave    : Callback functions that is called when the Save button is clicked. 
                  Arguments - (contents, isChanged).                            default: functions.save {Function}

// Templates Array------------------------------------------------------------------------------------------------
templates       : If you use a template plugin, add it.
                  Defines a list of templates.                       default: null {Array} 
                  ex) [
                    {
                        name: 'Template-1',
                        html: '<p>HTML source1</p>'
                    },
                    {
                        name: 'Template-2',
                        html: '<p>HTML source2</p>'
                    }
                  ]

// ETC------------------------------------------------------------------------------------------------------------
placeholder     : The placeholder text.                              default: null {String}
mediaAutoSelect : Activate the media[image, video, audio] selection status immediately after inserting the media tag.  default: true {Boolean}
icons           : You can redefine icons.                            default: null {Object}
                  ex) {
                      bold: '<span class="se-icon-text">B</span>',
                      table: '<i class="xx xxx></i>',
                      insert_row_above: '<svg></svg>'
                  }

// Buttons--------------------------------------------------------------------------------------------------------
buttonList      : Defines button list to array {Array}
                  default: [
                    ['undo', 'redo'],
                    // ['font', 'fontSize', 'formatBlock'],
                    // ['paragraphStyle', 'blockquote'],
                    ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
                    // ['fontColor', 'hiliteColor', 'textStyle'],
                    ['removeFormat'],
                    ['outdent', 'indent'],
                    // ['align', 'horizontalRule', 'list', 'lineHeight'],
                    // ['table', 'link', 'image', 'video', 'math'], // You must add the 'katex' library at options to use the 'math' plugin.
                    // ['imageGallery'], // You must add the "imageGalleryUrl".
                    ['fullScreen', 'showBlocks', 'codeView'],
                    ['preview', 'print'],
                    // ['save', 'template'],
                    // ['dir', 'dir_ltr', 'dir_rtl'],
                    // '/', Line break
                  ]

----------------- ex) When do not use group: ----------------------------------------------------------------------
                  // If you don't want to use a group, put all the buttons in one array.
                  [
                    ['undo', 'redo', 'bold', 'underline', 'fontColor', 'table', 'link', 'image', 'video']
                  ]

------------------ex) Alignment of button group:-------------------------------------------------------------------
                  // Set "-[align]" to the first item in the group. (default: left)
                  [
                    ['-left', 'undo', 'redo']
                    ['-right', 'bold', 'underline', 'italic', 'strike'],
                  ]

------------------ex) Options in the button group(#):--------------------------------------------------------------
                  // Set "#fix" - Fixed the order of buttons within a group in the "rtl" mode.
                  [
                    ['bold'],
                    ['preview', 'print'],
                    ['-left', '#fix', 'rtl_l', 'rtl_r']
                  ]

----------------- ex) More button: --------------------------------------------------------------------------------
                  // The more button is defined as a string starting with a colon.(":").
                  // :Identifier - Title attribute - Button's innerHTML
                  /**
                   * "Identifier": The button's identifier. Please specify uniquely.
                   * "Title attribute": Title attribute of the button to be displayed as a tooltip.
                   * "Button's innerHTML": Define the button's "innerHTML".
                   * default.xxx -> Use the attributes of "defaultIcons".
                   * (more_text, more_paragraph, more_plus, more_horizontal, more_vertical)
                   * text.xxx -> Use the text.
                   * xxx -> HTML
                   */
                  [
                    ['undo', 'redo'],
                    [':t-More Text-default.more_text', 'bold', 'underline', 'italic'],
                    [':p-More Paragraph-default.more_paragraph', 'font', 'formatBlock', 'align', 'list'],
                    [':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video'],
                    [':v-View-text.View', 'fullScreen', 'codeView', 'print'],
                    ['-right', ':o-More Others-<i class="xxx"></i>', 'save', 'template'], // Used with alignment
                  ]
                  
----------------- ex) Responsive setting: -------------------------------------------------------------------------
                  // You can specify the arrangement of buttons according to the screen size in advance.
                  // Responsive settings start with a percent sign.("%").
                  // %510(Number based on "px")
                  [
                    // Default
                    ['undo', 'redo'],
                    ['font', 'fontSize', 'formatBlock'],
                    ['paragraphStyle', 'blockquote'],
                    ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
                    ['fontColor', 'hiliteColor', 'textStyle'],
                    ['removeFormat'],
                    ['outdent', 'indent'],
                    ['align', 'horizontalRule', 'list', 'lineHeight'],
                    ['table', 'link', 'image', 'video', 'audio', 'math'],
                    ['imageGallery'],
                    ['fullScreen', 'showBlocks', 'codeView'],
                    ['preview', 'print'],
                    ['save', 'template'],
                    ['-left', '#fix', 'dir_ltr', 'dir_rtl'],
                    // (min-width:992px)
                    ['%992', [
                        ['undo', 'redo'],
                        [':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
                        ['bold', 'underline', 'italic', 'strike'],
                        [':t-More Text-default.more_text', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
                        ['removeFormat'],
                        ['outdent', 'indent'],
                        ['align', 'horizontalRule', 'list', 'lineHeight'],
                        ['-right', 'dir'],
                        ['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template'],
                        ['-right', ':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video', 'audio', 'math', 'imageGallery']
                    ]],
                    // (min-width:768px)
                    ['%768', [
                        ['undo', 'redo'],
                        [':p-More Paragraph-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
                        [':t-More Text-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle', 'removeFormat'],
                        [':e-More Line-default.more_horizontal', 'outdent', 'indent', 'align', 'horizontalRule', 'list', 'lineHeight'],
                        [':r-More Rich-default.more_plus', 'table', 'link', 'image', 'video', 'audio', 'math', 'imageGallery'],
                        ['-right', 'dir'],
                        ['-right', ':i-More Misc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview', 'print', 'save', 'template']
                    ]]
                  ]
                  

Functions

import suneditor from 'suneditor'

const editor = suneditor.create('example');

editor.core; // core object (The core object contains "util" and "functions".)
editor.util; // util object

// Reset the buttons on the toolbar. (Editor is not reloaded)
// You cannot set a new plugin for the button.
editor.setToolbarButtons([
    [':moreText-More Text-default.more_horizontal', 'bold', 'underline', 'strike', 'subscript', 'superscript'],
    ['undo', 'redo']
]);

// Add or reset option property. (Editor is reloaded)
editor.setOptions({
    minHeight: '300px',
    buttonList: [
        ['fontColor', 'hiliteColor']
    ],
    colorList: [
        ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown']
    ]
});

// Set "options.defaultStyle" style.
// Define the style of the edit area
// It can also be defined with the "setOptions" method, but the "setDefaultStyle" method does not render the editor again.
editor.setDefaultStyle('font-family: cursive; font-size: 10px;');

// Open a notice area
editor.noticeOpen('test notice');

// Close a notice area
editor.noticeClose();

// Copies the contents of the suneditor into a [textarea]
editor.save();

// Gets the suneditor's context object. Contains settings, plugins, and cached element objects
editor.getContext();

// Gets the contents of the suneditor
// onlyContents {Boolean}: Return only the contents of the body without headers when the "fullPage" option is true
editor.getContents(onlyContents: Boolean);
// Gets the current contents with containing parent div(div.sun-editor-editable).
//  <div class="sun-editor-editable">{contents}</div>
editor.getFullContents(onlyContents: Boolean);

// Gets only the text of the suneditor contents
editor.getText();

// Gets a list of images uploaded to the editor
/** 
 * {
 *  element: image element
 *  src: imgage src
 *  index: data index
 *  name: file name
 *  size: file size
 *  select: select function
 *  delete: delete function
 * }
 **/
editor.getImagesInfo();

// Gets uploaded files(plugin using fileManager) information list.
// image: [img], video: [video, iframe], audio: [audio]
// When the argument value is 'image', it is the same function as "getImagesInfo".
/** 
 * {
 *  element: image element
 *  src: imgage src
 *  index: data index
 *  name: file name
 *  size: file size
 *  select: select function
 *  delete: delete function
 * }
 * pluginName: Plugin name (image, video, audio)
 **/
editor.getFilesInfo(pluginName);

// Upload images using image plugin
// document.getElementById('example_files_input').files
editor.insertImage(FileList);

// Inserts an HTML element or HTML string or plain string at the current cursor position
/**
 * @param {Boolean} notCleaningData If true, inserts the HTML string without refining it with core.cleanHTML.
 * @param {Boolean} checkCharCount If true, if "options.maxCharCount" is exceeded when "element" is added, null is returned without addition.
 */
editor.insertHTML('<img src="http://suneditor.com/sample/img/sunset.jpg">', true, true);

// Change the contents of the suneditor
editor.setContents('set contents');

// Get the editor's number of characters or binary data size.
// You can use the "charCounterType" option format.
// If argument is no value, the currently set "charCounterType" option is used.
editor.getCharCount((null || 'char' || 'byte' || 'byte-html'));

// Add content to the suneditor
editor.appendContents('append contents');

// Switch to or off "ReadOnly" mode.
editor.readOnly(true || false)

// Disable the suneditor
editor.disable();

// Enable the suneditor
editor.enable();

// Hide the suneditor
editor.hide();

// Show the suneditor
editor.show();
    
// Destroy the suneditor
editor.destroy();

// Toolbar methods
// Disable the toolbar
editor.toolbar.disable();

// Enable the toolbar
editor.toolbar.enable();

// Hide the toolbar
editor.toolbar.hide();

// Show the toolbar
editor.toolbar.show();

// Event functions -------------------------------------------------------------------------------------
// It can be redefined by receiving event object as parameter.
// It is not called in exceptional cases and is called after the default event function has before finished.
// e: event object, core: Core object
editor.onScroll = function (e, core) { console.log('onScroll', e) }

editor.onMouseDown = function (e, core) { console.log('onMouseDown', e) }

editor.onClick = function (e, core) { console.log('onClick', e) }

editor.onInput = function (e, core) { console.log('onInput', e) }

editor.onKeyDown = function (e, core) { console.log('onKeyDown', e) }

editor.onKeyUp = function (e, core) { console.log('onKeyUp', e) }

editor.onFocus = function (e, core) { console.log('onFocus', e) }

editor.onBlur = function (e, core) { console.log('onBlur', e) }

// onchange event
// contents: core.getContents(), Core object
editor.onChange = function (contents, core) { console.log('onChange', contents) }

// onload event
// When reloaded with the "setOptions" method, the value of the "reload" argument is true.
editor.onload = function (core, reload) {
    console.log('onload-core', core)
    console.log('onload-reload', reload)
}

// Clipboard event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * paste event
 * e: Event object
 * cleanData: HTML string modified for editor format
 * maxCharCount: maxChartCount option (true if max character is exceeded)
 * core: Core object
 */
editor.onPaste = function (e, cleanData, maxCharCount, core) { console.log('onPaste', e) }

// Copy event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * copy event
 * e: Event object
 * clipboardData: event.clipboardData
 * core: Core object
 */
editor.onCopy = function (e, clipboardData, core) { console.log('onCopy', e) }

// Cut event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * cut event
 * e: Event object
 * clipboardData: event.clipboardData
 * core: Core object
 */
editor.onCut = function (e, clipboardData, core) { console.log('onCut', e) }

// Drop event.
// Called before the editor's default event action.
// If it returns false, it stops without executing the rest of the action.
/**
 * e: Event object
 * cleanData: HTML string modified for editor format
 * maxCharCount: maxChartCount option (true if max character is exceeded)
 * core: Core object
 */
editor.onDrop = function (e, cleanData, maxCharCount, core) { console.log('onDrop', e) }

// Save event
// Called just after the save was executed.
/**
 * contents Editor content
 * core: Core object
 */   
editor.onSave = function (contents, core) {console.log(contents) };

// Called before the image is uploaded
// If true is returned, the internal upload process runs normally.
// If false is returned, no image upload is performed.
// If new fileList are returned,  replaced the previous fileList
// If undefined is returned, it waits until "uploadHandler" is executed.
/**
 * files: Files array
 * info: {
 * - linkValue: Link url value
 * - linkNewWindow: Open in new window Check Value
 * - inputWidth: Value of width input
 * - inputHeight: Value of height input
 * - align: Align Check Value
 * - isUpdate: Update image if true, create image if false
 * - element: If isUpdate is true, the currently selected image.
 * }
 * core: Core object,
 * uploadHandler: If undefined is returned, it waits until "uploadHandler" is executed.
 *                "uploadHandler" is an upload function with "core" and "info" bound. (plugin.upload.bind(core, info))
 *                [upload files] : uploadHandler(files or [new File(...),])
 *                [error]        : uploadHandler("Error message")
 *                [Just finish]  : uploadHandler()
 *                [directly register] : uploadHandler(response) // Same format as "imageUploadUrl" response
 *                                   ex) {
 *                                      // "errorMessage": "insert error message",
 *                                      "result": [ { "url": "...", "name": "...", "size": "999" }, ]
 *                                   }
 * return {Boolean|Array|undefined}
 */
editor.onImageUploadBefore: function (files, info, core, uploadHandler) {
    return Boolean || return (new FileList) || return undefined;
}
// Called before the video is uploaded
// If true is returned, the internal upload process runs normally.
// If false is returned, no video(iframe, video) upload is performed.
// If new fileList are returned,  replaced the previous fileList
// If undefined is returned, it waits until "uploadHandler" is executed.
/** 
 * files: Files array
 * info: {
 * - inputWidth: Value of width input
 * - inputHeight: Value of height input
 * - align: Align Check Value
 * - isUpdate: Update video if true, create video if false
 * - element: If isUpdate is true, the currently selected video.
 * }
 * core: Core object,
 * uploadHandler: If undefined is returned, it waits until "uploadHandler" is executed.
 *                "uploadHandler" is an upload function with "core" and "info" bound. (plugin.upload.bind(core, info))
 *                [upload files] : uploadHandler(files or [new File(...),])
 *                [error]        : uploadHandler("Error message")
 *                [Just finish]  : uploadHandler()
 *                [directly register] : uploadHandler(response) // Same format as "videoUploadUrl" response
 *                                   ex) {
 *                                      // "errorMessage": "insert error message",
 *                                      "result": [ { "url": "...", "name": "...", "size": "999" }, ]
 *                                   }
 * return {Boolean|Array|undefined}
 */
editor.onVideoUploadBefore: function (files, info, core, uploadHandler) {
    return Boolean || return (new FileList) || return undefined;
}
// Called before the audio is uploaded
// If true is returned, the internal upload process runs normally.
// If false is returned, no audio upload is performed.
// If new fileList are returned,  replaced the previous fileList
// If undefined is returned, it waits until "uploadHandler" is executed.
/** 
 * files: Files array
 * info: {
 * - isUpdate: Update audio if true, create audio if false
 * - currentaudio: If isUpdate is true, the currently selected audio.
 * }
 * core: Core object,
 * uploadHandler: If undefined is returned, it waits until "uploadHandler" is executed.
 *                "uploadHandler" is an upload function with "core" and "info" bound. (plugin.upload.bind(core, info))
 *                [upload files] : uploadHandler(files or [new File(...),])
 *                [error]        : uploadHandler("Error message")
 *                [Just finish]  : uploadHandler()
 *                [directly register] : uploadHandler(response) // Same format as "audioUploadUrl" response
 *                                   ex) {
 *                                      // "errorMessage": "insert error message",
 *                                      "result": [ { "url": "...", "name": "...", "size": "999" }, ]
 *                                   }
 * return {Boolean|Array|undefined}
 */
editor.onAudioUploadBefore: function (files, info, core, uploadHandler) {
    return Boolean || return (new FileList) || return undefined;
}

// Called when the image is uploaded, updated, deleted.
/**
 * targetElement: Target element
 * index: Uploaded index (key value)
 * state: Upload status ('create', 'update', 'delete')
 * info: {
 * - index: data index
 * - name: file name
 * - size: file size
 * - select: select function
 * - delete: delete function
 * - element: Target element
 * - src: src attribute of tag
 * }
 * remainingFilesCount: Count of remaining files to upload (0 when added as a url)
 * core: Core object
*/
editor.onImageUpload = function (targetElement, index, state, info, remainingFilesCount, core) {
    console.log(`targetElement:${targetElement}, index:${index}, state('create', 'update', 'delete'):${state}`)
    console.log(`info:${info}, remainingFilesCount:${remainingFilesCount}`)
}
// Called when the video(iframe, video) is is uploaded, updated, deleted
// -- arguments is same "onImageUpload" --
editor.onVideoUpload = function (targetElement, index, state, info, remainingFilesCount, core) {
    console.log(`targetElement:${targetElement}, index:${index}, state('create', 'update', 'delete'):${state}`)
    console.log(`info:${info}, remainingFilesCount:${remainingFilesCount}`)
}
// Called when the audio is is uploaded, updated, deleted
// -- arguments is same "onImageUpload" --
editor.onAudioUpload = function (targetElement, index, state, info, remainingFilesCount, core) {
    console.log(`targetElement:${targetElement}, index:${index}, state('create', 'update', 'delete'):${state}`)
    console.log(`info:${info}, remainingFilesCount:${remainingFilesCount}`)
}

// Called when the image is upload failed.
// If you return false, the default notices are not called.
/**
 * errorMessage: Error message
 * result: Response Object
 * core: Core object
 * return {Boolean}
*/
editor.onImageUploadError = function (errorMessage, result, core) {
    alert(errorMessage)
    return Boolean
}
// Called when the video(iframe, video) upload failed
// -- arguments is same "onImageUploadError" --
editor.onVideoUploadError = function (errorMessage, result, core) {
    alert(errorMessage)
    return Boolean
}
// Called when the audio upload failed
// -- arguments is same "onImageUploadError" --
editor.onAudioUploadError = function (errorMessage, result, core) {
    alert(errorMessage)
    return Boolean
}

// Called when the editor is resized using the bottom bar
// height, prevHeight are number
editor.onResizeEditor = function (height, prevHeight, core, resizeObserverEntry) {
    console.log(`height: ${height}, prevHeight: ${prevHeight}`, resizeObserverEntry)
    // "resizeObserverEntry" is not provided in IE Browser. 
}

// Called after the "setToolbarButtons" invocation
// Can be used to tweak buttons properties (useful for custom buttons)
/**
 * buttonList: buttonList array 
 * core: Core object
 */
editor.onSetToolbarButtons = function (buttonList, core) {
    console.log(`buttonList: ${buttonList}`)
}

// It replaces the default callback function of the image upload
/**
 * xmlHttp: xmlHttpRequest object
 * info: Input information
 * - linkValue: Link url value
 * - linkNewWindow: Open in new window Check Value
 * - inputWidth: Value of width input
 * - inputHeight: Value of height input
 * - align: Align Check Value
 * - isUpdate: Update image if true, create image if false
 * - element: If isUpdate is true, the currently selected image.
 * core: Core object
 */
editor.imageUploadHandler = function (xmlHttp, info, core) {
    // Editor code
    const response = JSON.parse(xmlHttp.responseText);
    if (response.errorMessage) {
        this.plugins.image.error.call(this, response.errorMessage, response);
    } else {
        this.plugins.image.register.call(this, info, response);
    }
}
/**
 * @description It replaces the default callback function of the video upload
 * xmlHttp: xmlHttpRequest object
 * info: Input information
 * - inputWidth: Value of width input
 * - inputHeight: Value of height input
 * - align: Align Check Value
 * - isUpdate: Update video if true, create video if false
 * - element: If isUpdate is true, the currently selected video.
 * core: Core object
 */
editor.videoUploadHandler = function (xmlHttp, info, core) {
    // Editor code
    const response = JSON.parse(xmlHttp.responseText);
    if (response.errorMessage) {
        this.plugins.video.error.call(this, response.errorMessage, response);
    } else {
        this.plugins.video.register.call(this, info, response);
    }
}

/**
 * @description It replaces the default callback function of the audio upload
 * xmlHttp xmlHttpRequest object
 * info Input information
 * - isUpdate: Update audio if true, create audio if false
 * - element: If isUpdate is true, the currently selected audio.
 * core Core object
 */
editor.audioUploadHandler = function (xmlHttp, info, core) {
    // Editor code
    const response = JSON.parse(xmlHttp.responseText);
    if (response.errorMessage) {
        this.plugins.audio.error.call(this, response.errorMessage, response);
    } else {
        this.plugins.audio.register.call(this, info, response);
    }
}

// An event when toggling between code view and wysiwyg view.
/**
 * isCodeView: Whether the current code view mode
 * core: Core object
 */
editor.toggleCodeView = function (isCodeView, core) {
    console.log('isCodeView', isCodeView);
}

// An event when toggling full screen.
/**
 * isFullScreen: Whether the current full screen mode
 * core: Core object
 */
editor.toggleFullScreen = function (isFullScreen, core) {
    console.log('isFullScreen', isFullScreen);
}

// Called just before the inline toolbar is positioned and displayed on the screen.
/**
 * toolbar: Toolbar Element
 * context: The editor's context object (editor.getContext()|core.context)
 * core Core object
*/
editor.showInline = function (toolbar, context, core) {
    console.log('toolbar', toolbar);
    console.log('context', context);
}

// Called just after the controller is positioned and displayed on the screen.
// controller - editing elements displayed on the screen [image resizing, table editor, link editor..]]
/**
 * name: The name of the plugin that called the controller
 * controllers: Array of Controller elements
 * core: Core object
*/
editor.showController = function (name, controllers, core) {
    console.log('plugin name', name);
    console.log('controller elements', controllers);
}

Plugins list

The plugin and the button have the same name.

Name Type
blockquote command
image dialog
link
video
audio
math
align submenu
font
fontColor
fontSize
formatBlock
hiliteColor
horizontalRule
lineHeight
list
paragraphStyle
table
template
textStyle
imageGallery fileBrowser

Examples

Examples

Options template

Options template

Custom plugins

Custom plugins

Document

Document

Other libraries using SunEditor

suneditor-react (@mkhstar) - Pure React Component for SunEditor.

angular-suneditor (@BauViso) - Angular module for the SunEditor WYSIWYG Editor.

Livewire & Alpine.JS (@kaju74) - Using SunEditor with Livewire & Alpine.JS

Plugin for Pluxml (@sudwebdesign) - Plugin for Pluxml.

AEM-SunEditor (@ahmed-musallam) - Enables using SunEditor in AEM dialogs as an RTE replacement.

License

Suneditor may be freely distributed under the MIT license.

Comments
  • Image upload to AWS S3

    Image upload to AWS S3

    Can someone help me with getting the images uploaded to AWS S3 first and then using that link here in the editor?

    @JiHong88 This can be integrated as a core offering since it is very common to have images on S3. It is available in many other editors out-of-the-box (check out Froala).

    question 
    opened by dgandhi1993 55
  • se-rtl not set in document created by suneditor

    se-rtl not set in document created by suneditor

    @JiHong88 hi

    The se-rtl class is set in the editor and works well. But there is no editor output in the content. And prevents rtl from being applied tothe content display.

    This image shows that the se-rtl class is applied correctly in the editor :

    image

    But the image below, which is related to the display of content, clearly shows that the se-rtl class is not set at all.

    image

    As a result, the text is displayed correctly in the editor and is from right to left. But the screen is not right and from left to right.

    feature question 
    opened by Saeeed-B 40
  • Is it possible to add a Latex code via a function or method?

    Is it possible to add a Latex code via a function or method?

    Currently one has to open the formula modal, input the latex code into the field and then submit it. Instead, is there a possibility to simply pass the input value to a function and add the equivalent latex code to the editor?

    What would be amazing is if we can type the latex inside the editor, select the latex code and click on an editor button that converts it into its preview.

    feature 
    opened by dgandhi1993 24
  • Default styles are not working!

    Default styles are not working!

    Issue with default styles settings

    Find bellow attached video you will find the steps

    Expected behavior Default styles are not added to paragraph/heading/dev tag styles attribute when we define defaultStyles in editor props, which leads to a bug where I as a user assume to have the same styles saved in db along with their respective tag.

    Video

    https://user-images.githubusercontent.com/38204661/138889124-ad54852b-e56d-4216-9064-5fa42a84c52e.mov

    Additional context The screen in this video is from your website options page.

    question enhancement 
    opened by alichampion 23
  • Video attribute controls always true, how can it be removed

    Video attribute controls always true, how can it be removed

    Video attribute controls always true, I tried to remove it in html code but when I switch back to editor mode or save it back to controls=true. how can it be removed when I don't need controls of video or audio ?

    I checked the code https://github.com/JiHong88/SunEditor/blob/6d4414ba476c843001da97e326c48c54cf60734a/src/plugins/dialog/video.js#L222 it seems we force it to be true, is there any reason why we did that? And How can I override the behavior ?

    Version

    2.41.3

    Additional context

    image

    feature 
    opened by zt1983811 23
  • Feature request: Allow the possibility to modify image blob/fileList prior to upload

    Feature request: Allow the possibility to modify image blob/fileList prior to upload

    It would be useful to be able to perform file size reduction of images prior to upload. If a callback could be defined which is called at the very beginning of image dialog, the fileList/blob could be modified by this callback function and returned to the image dialog plugin for further processing and upload. How the callback could look like I can post an example here if/when this is implemented.

    enhancement discussion 
    opened by MRB60 22
  • Browser

    Browser

    Hello, How do i have to proceed? I need to view only SunEditor content, including "katex". I need the user to see the content, not edit it and not see the editor control.

    Thank you.

    question 
    opened by pazicb 18
  • Font Size, Font Family button default text

    Font Size, Font Family button default text

    Hi @JiHong88 ,

    Thank you for the amazing editor. Finally, Suneditor is going production in our application.

    Our UI/UX team raised a concern, is it possible to give default font size, font family on the toolbar button?

    Instead of showing font, size text. I am trying to display the default font value. eg: 14px, Arial Group 4

    The reason behind this is, people will know the default font size, font when they start writing.

    Reference: Screenshot 2021-05-10 at 10 16 37 PM Screenshot 2021-05-10 at 10 16 21 PM

    Is there any way to do that? Please let me know.

    Thank you very much :)

    enhancement 
    opened by gopal1996 17
  • (re)Init Error

    (re)Init Error

    Hello, Here my problem :)

    I use sunEditor for one of my dynamic component related to my form builder in vuejs.

    The first time when it init it's ok. But when the instance is destroy and when i try to reinitialise it i got :

    TypeError: m.fileTags[t].toLowerCase is not a function at Object._init (suneditor.min.js:9865) at Object._editorInit (suneditor.min.js:10140) at A (suneditor.min.js:11737) at Object.create (suneditor.min.js:11790) at Object. (suneditor.min.js:11747) at VueComponent.mounted (js.js:128) at invokeWithErrorHandling (vue.js:1863) at callHook (vue.js:4220) at Object.insert (vue.js:3146) at invokeInsertHook (vue.js:6341)

    But only this error in fact count => suneditor.min.js:9865

    It's related to code :

    this._fileManager.pluginMap[m.fileTags[t].toLowerCase()] = e

    if i put this line into a try catch it's ok.

    Do you have any ideas why this line break the init the second time ?

    Best regards ( By the way your editor rock!)

    bug 
    opened by shaan1974 17
  • image URL address

    image URL address

    hello. The image URL adds the website address. for example, I add only the absolute path like this: /upload/img1.jpg But the editor adds the website address and now the path is like this: http://website.com/upload/img1.jpg How to avid adding the website address?

    discussion 
    opened by daybat 17
  • TypeScript support is very partial

    TypeScript support is very partial

    Hi!

    Thanks for adding TypeScript support. However, I think that current support is not sufficient. Actually, after doing suneditor.init, we're getting type "any", so we don't have any type annotations for editor functionalities. I think that's the most crucial part because most of the logic is after instantiating the object, not before. Another thing with the support is the fact, that currently, support is only for the main suneditor module. There's no support for plugins and locale, so in strictly typed environment we still need to add empty declaration like declare module 'suneditor/*'; to avoid TypeScript errors.

    It's not critical, it's just a nice to have feature, that would be very useful for development purposes. It's much easier to browse through code suggestions from TypeScript in IDEs like WebStorm or VS Code than browsing through documentation.

    Cheers!

    enhancement 
    opened by tswistak 17
  • Uncaught TypeError: d._resourcesStateChange is not a function after getting latest .min file

    Uncaught TypeError: d._resourcesStateChange is not a function after getting latest .min file

    I just got the latest suneditor.min.js file.

    Now I am noticing the following error in the console...

    image

    Any pointers as to what its about? Everything seems ok but it concerns me that I could have broken something after the upgrade.

    opened by sdraper69 0
  • Base Theming for Sun Editor

    Base Theming for Sun Editor

    In response to issue #978, I have created a file called "_variables.css" that define all colors, font families, and data images involved in the styling of the editor. The editor supports light mode and dark mode out of the box. Custom themes and overrides can be added by the user.

    I apologize for some of the style changes, my editor lints files when saving, and some changes are simply stylistic.

    opened by booellean 0
  • Link action inserts zero width space and it makes unclickable character.

    Link action inserts zero width space and it makes unclickable character.

    Describe the problem

    When I use Link action, zero width white space are inserted after <p> tag and before <br> tag.

    And if certain fonts are used, the first character of <a> tag will not be clickable. (e.g. Noto Sans Japanese)

    Generated HTML with SunEditor

    <p>&#8203;<a href="https://example.com" alt="example.com">example.com</a>&#8203;<br>
    </p>
    

    Plain HTML to reproduce the same issue (No SunEditor)

    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;700&display=swap" rel="stylesheet">
    <style>
    body {
      font-family: "Noto Sans JP";
    }
    </style>
    <p>&#8203;<a href="https://example.com" alt="aaaa">example.com</a></p>
    

    Preview

    e is not clickable.

    127006 - Google Chrome_2022-12-22_12-1-12_No-00

    opened by YoshitoONISHI 0
  • TypeError: core._resourcesStateChange with React 18 and v2.44.0 or greater

    TypeError: core._resourcesStateChange with React 18 and v2.44.0 or greater

    Describe the bug Using Next.js with React 18 starting with v2.44.0 there is an error. v2.43.14 works without error.

    Unhandled Runtime Error
    TypeError: core._resourcesStateChange is not a function
    
    Call Stack
    eval
    node_modules\suneditor\src\lib\core.js (6186:0)
    

    To Reproduce Steps to reproduce the behavior:

    1. Simply install suneditor-react and suneditor both with latest, and render the components as such:

    HtmlEditor.tsx

    import { Box } from '@chakra-ui/react';
    import dynamic from 'next/dynamic';
    
    import 'suneditor/dist/css/suneditor.min.css'; // Import Sun Editor's CSS File
    
    const SunEditor = dynamic(() => import('suneditor-react'), {
      ssr: false,
    });
    
    const HtmlEditor = () => {
      return (
        <Box>
          <SunEditor />
        </Box>
      );
    };
    
    export default HtmlEditor;
    

    The component consumer the HtmlEditor.tsx

    import { Box } from '@chakra-ui/react';
    import React from 'react';
    
    import HtmlEditor from '../HtmlEditor/HtmlEditor';
    
    const HtmlEditorTest = () => {
      return (
        <Box>
          <HtmlEditor />
        </Box>
      );
    };
    
    export default HtmlEditorTest;
    
    1. Click on '....'
    2. Scroll down to '....'
    3. See error

    Expected behavior To see the Editor with no errors > this is with v2.43.14...

    CleanShot 2022-12-20 at 00 52 52@2x

    Screenshots Here is the error with version 2.44.0

    CleanShot 2022-12-20 at 00 54 33@2x

    Additional context As mentioned 2.43.14 works, 2.44.0 and above throws the error TypeError: core._resourcesStateChange is not a function

    opened by tzarger 0
  • Get latex original content from math nodes

    Get latex original content from math nodes

    There's any way to get only math content as the original latex? So basically, I want to maintain core.getContents() behavior, but instead of html katex, get other html inserted plus the original latex for each node.

    Context: I have a CMS where I can edit content using this editor and then save it into a database. One of the problems here is the size of the latex content after compiled by katex and some errors when re-rendering the katex html at the other app.

    Current behavior:

    From this: image

    Get this:

    <h1>Should be a h1</h1><p>​<span class="__se__katex katex" contenteditable="false" data-exp="x = \frac{1}{2}" data-font-size="1em" style="font-size: 1em;"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>x</mi><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex">x = \frac{1}{2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0074em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>​​<br></p>
    

    Desired behavior

    From this: image

    Get something like this:

    <h1>Should be a h1</h1>
    <p>$$x = \frac{1}{2}$$<\p>
    

    Version

    Suneditor: 2.44.3

    opened by mendeseduda 0
Releases(2.44.3)
  • 2.44.3(Oct 8, 2022)

    Enhancement

    • Fixed have been made so that the same tags do not continue to overlap when pasting styled text.

    Bugfix

    • Fixed a bug where unintentional styles were applied when pasting. #1093
    • The "https://github.com/JiHong88/SunEditor/issues/1011" issue that was fixed in v2.43.8 recurred in 2.44.0 and has been fixed.
    Source code(tar.gz)
    Source code(zip)
  • 2.44.0(Sep 22, 2022)

    Hotfix(since v2.43.10)

    • A bug where Excel data was not pasted properly has been fixed. #1075

    New Feature

    • A "frameAttrbutes" option has been added. #1066

    Enhancement

    • Improve embed video to gives a proper iframe #1061
    • Fixed so that the font size is changed to the value of the editor's "fontSizeUnit" option when pasting. #1064
    • Fixed bug output style on "Katex" error. #1084

    Bugfix

    • Fixed a bug an intermittent error occurred when resizing the editor.
    • Fixed position bug of caption when rotating image.
    • Fixed positioning bug when rotating component in "rtl" mode
    • Fixed a bug when image resizing. #1080
    • Fix a bug related to event after loading editor. #1037
    • Fixed a bug where the "defaultStyle" option was ignored in fullscreen mode. #1085
    • Fixed a bug where images were not displayed properly when specifying a link on uploading multiple images. #1086
    • Fixed a bug where some characters would disappear when using the "core.insertNode()" function or copy/paste or use it. #1071 #1091
    Source code(tar.gz)
    Source code(zip)
  • 2.43.14(Jul 5, 2022)

  • 2.43.13(Jun 24, 2022)

    Enhancement

    • When editing a link, it has been improved so that the link appears as entered.

    Bugfix

    • Fixed a bug where editor links were not displayed in the edit window when using linkNoPrefix. #1044
    Source code(tar.gz)
    Source code(zip)
  • 2.43.12(Jun 24, 2022)

    Enhancement

    • It has been modified so that the editor does not have focus when clicking on the toolbar.

    Bugfix

    • The bug when the editor was loaded, the "setDir" method was executed so the style of the content was changed has been fixed. #1041
    Source code(tar.gz)
    Source code(zip)
  • 2.43.11(Jun 18, 2022)

    Bugfix

    • Fixed a bug where transparent color was applied to the text style when copying and pasting on some mobile devices.
    • Fix hideToolbar option type error
    Source code(tar.gz)
    Source code(zip)
  • 2.43.10(Jun 18, 2022)

    Bugfix

    • Fixed a bug that scrolled when focusing in Chrome. #1035
    • Fixed a bug in which the "br" tag was added when pasting in Windows Chrome. #1033
    • Fixed a bug in the IME input method where the first typed character was not properly entered after adding a line. #1031
    Source code(tar.gz)
    Source code(zip)
  • 2.43.9(Jun 10, 2022)

    Hotfix(v2.43.7)

    • Fixed a bug where the tag properties were deleted of the value of "options.value" and the value modified in code view mode. #1026 #1029

    Enhancement

    • Added "hideToolbar" option. #1023
    Source code(tar.gz)
    Source code(zip)
  • 2.43.8(May 30, 2022)

    Enhancement

    • Modified so that excessive "span" tags are not generated when copying/pasting text in the Chrome browser.

    Bugfix

    • Fixed editor resizing bug accrue in lower browser versions.
    • Fixed a bug where sometimes there were too many line breaks when pasting. #1011
    • Fixed a bug where copy/paste in the list behaved differently than expected. #922
    Source code(tar.gz)
    Source code(zip)
  • 2.43.6(May 20, 2022)

    Hotfix(v2.43.5)

    • Fiexd a bug where the button activation effect did not work properly when using the responsive toolbar.

    Enhancement

    • The behavior when pasting into a list has been improved.
    • Added "aria-label" attribute to button. #1004

    Bugfix

    • Fixed a bug where the "shortcutsDisable" option did not work properly in some browsers. #1007
    • Fixed a bug where the indent icon was displayed in reverse.
    Source code(tar.gz)
    Source code(zip)
  • 2.43.5(May 15, 2022)

    Hotfix(v2.43.0)

    • Fixed a bug where placeholders did not appear. #983
    • Fixed a IE syntax error. #986
    • Fixed a bug where the video was not resizing properly. #990
    • A bug where the balloon toolbar was not displayed when selecting all has been fixed. #992
    • Fixed a bug where the style was not applied properly when applying the style to the text in the list.
    • Fixed a bug where the button state was not applied properly after focus out.
    • Add usage in Livewire & Alpine.JS @kaju74
    Source code(tar.gz)
    Source code(zip)
  • 2.43.0(Apr 25, 2022)

    Translation

    • Chinese (zh_cn) translation fixed. #943 (@stevending1st)

    New Feature

    • Added "core.getFullContents" method. #888 #921
    • Added "__defaultFontSize" option. #800 If the default font size is not in "px" units, forcefully specify the default font size.
    • Added "classsName" option. #914

    Enhancement

    • Added "editorInstance.context.template.selectedIndex" state. #903
    • The editor width change has been modified to be affected by the width change of the editor itself, not the size of the browser window. (IE is not supported) #974
    • It has been modified to work after adding focus to the editor when "insertHTML" is called when the editor has no focus. #970
    • "onResizeEditor" #948
    • The "onResizeEditor" event has been improved so that it is called even when the editor height changes when text is input. #948
    • historyStackDelayTime

    Critical bugfix

    • Fixed a bug that did not add properly when adding a table or list using the "SetContents" method. #957

    Bugfix

    • Fixed a bug where inserting a link with an empty URL would cause an error. #933 (@NakZMichael)
    • Added "historyStackDelayTime" option type. #960 (@kubabogaczewicz)
    • Fixed a bug where indent and indent icons were inverted when using custom icons. #968 (@CharlesCoqueret)
    • Fixed a bug where tables were not appended properly with the "appendContent" method. #979 (@a-tonchev)
    • Fixed, "list" and "quote" button activation error in Edge browser. #923
    • Fixed a bug where audio and video were not playing in "readOnly" mode. #936
    • The bug that the print function did not work when using the "voice-in-voice-typing" plugin from Chromium browser has been fixed. #947
    • Fixed a bug where the common style of the list was not applied properly when specifying the font size as a percentage. #930
    • Fixed a bug where focus did not move normally when there are more than n editor declarations. #951
    • Fixed a bug where the cursor position was set incorrectly when adding a list from an empty line. #961
    • Fixed a bug where copy/paste in the list behaved differently than expected. #922
    • Fixed a bug where "figcaption" could not be edited when editing saved content. #924 - Fixed a bug where hash links were not entered correctly. #919
    • Fixed a bug where shortcuts in bold were not disabled in the Chromium browser. #927
    • Fixed a bug where aligned videos were not resizing properly. #880
    Source code(tar.gz)
    Source code(zip)
  • 2.42.0(Jan 13, 2022)

    Translation.

    • French (fr) translation fixed. #816 (@ad2ien)

    New Feature

    • onSetToolbarButtons event callback has been added. #834 (@SystemChanger)
    • onSave event callback has been added. #812 (@DE-Danloc)
    • iframeAttributes option has been added. #804
    • [image, video]AlignShow options has been added. #802
    • attributesBlacklist, tagsBlacklist, pasteTagsBlacklist options has been added. #895
    • dir, dir_ltr, dir_rtl buttons has been added. #838
    • "#fix" feature has been added to the button group.
    • linkTargetNewWindow option has been added. #898
    • nullMessage, thumbnail attributes has been added to the "imageGalleryUrl" response data. #900 #908
    • resizeEnable, resizingBarContainer options has been added. #883
    • alignItems option has been added. #870
    • lineAttrReset option has been added. #848
    • hrItems option has been added. #806

    Enhancement

    • iframeAttributes option has been added. #804
    • Fixed to allow empty anchor tags in editor. #818
    • Added alt attribute to "imageInfo". #813
    • Fixed to automatically remove trailing whitespace from selected text when creating a link. #894

    Bugfix

    • Fixed incorrect return types from onCut, onCopy event callbacks. #810 (@DE-Danloc)
    • fix: toolbar buttons not being activated when deselecting. #820 (@SystemChanger)
    • Fixed a bug where code data could be set when the editor was not editable. #877 (@SystemChanger)
    • Fixed a bug where "more layer" was not closed when setToolbarButtons was executed. #832 (@SystemChanger)
    • Several bugs in read-only mode have been fixed. #832 (@SystemChanger)
    • Fixed a bug that caused an error when an empty string was entered in defaultTag option. #807
    • Fixed a bug where fonts were not displayed after executing setOptions. #824
    • Added exception handling to "list" and "align". #814 #828
    • Typescript build error has been fixed. #830
    • Fixed a bug where spaces were removed when pasting from MS Word. #808
    • Fixed a bug where some of the last words of a paragraph did not change when changing the text style of a long paragraph. #827
    • Fixed a bug where spaces were converted to new lines when inputting HTML. #809
    • Fixed a bug related to video tag control properties. #847 #851
    • Fixed a bug related to HTML entity. #845
    • Fixed a bug where the "Show Blocks" button did not work intermittently when using the fullPage option. #863
    • Fixed a bugs related to <iframe> and <img> tags. #831 #879 #890
    • Fixed a bug where selecting text by triple-clicking would also affect the line below when changing the text style. #852
    • Fixed a bug that caused an error when editing an image with a link. #840
    • Fixed a bug where the code view could not be scrolled in full screen mode when the height was auto. #853
    • Fixed a bug where cursor position information was not updated when right-clicking. #891
    • Fixed a bug that did not work well pasting after selecting all in IE11. #899
    Source code(tar.gz)
    Source code(zip)
  • 2.41.3(Jul 2, 2021)

  • 2.41.2(Jun 28, 2021)

  • 2.41.1(Jun 26, 2021)

    Bugfix

    • Fixed bugs in readOnly mode.
    • XSS attack vulnerability fixes. #784
    • Fixed a bug where the hr tag was not deleted.
    • Fixed a bug when media tag init.
    Source code(tar.gz)
    Source code(zip)
  • 2.41.0(Jun 22, 2021)

    Translation.

    • Dutch (nl) translation fixed. #785 (@Flavio-Occ)

    Enhancement

    • A readOnly method has been added.
    • It has been modified not to check the default format in the __se__tag class. #781
    • Added details, summary tags to the default tags.
    • In "Code View" mode, it has been modified not to check the format duplicate. #720

    Bugfix

    • Fixed a bug where "nl"(Dutch) could not be accessed in "lang" object.

    Maintenance

    • added: history object - getCurrentStack.
    Source code(tar.gz)
    Source code(zip)
  • 2.40.0(Jun 9, 2021)

    Translation

    • Dutch (nl) translation added. #759 (@jellev123)

    Enhancement

    • Improved the "stickytoolbar" option also works in "inline" mode. #766

    Bugfix

    • Fixed a TypeScript error. #763
    • Fixed a bug when delete key not worked after select all in chrome. #767
    • Fixed a bug that related a list style. #771
    • Fixed a bug when text style not working when triple click to select
    Source code(tar.gz)
    Source code(zip)
  • 2.39.0(May 16, 2021)

    New Feature

    • The onResizeEditor event has been added. #753

    Enhancement

    • Improved tag indent and line break in code view mode.

    Bugfix

    • Fixed a bug that TypeScript build fails. #754
    • Fixed a bug when paste from "Notepad" displayed <br> tag. #743
    • Fixed a bug that HTML converter.
    • XSS attack vulnerability fixes.
    Source code(tar.gz)
    Source code(zip)
  • 2.38.10(May 11, 2021)

    Enhancement

    • "Font" and "Size" have been modified to display default values. #748

    Bugfix

    • Fixed a bug where the text style was not maintained when entering the enter key at the end of the text.
    Source code(tar.gz)
    Source code(zip)
  • 2.38.8(May 6, 2021)

  • 2.38.7(May 5, 2021)

    Bugfix

    • When pasting an external image or video, a bug that sometimes the element was not properly added has been fixed. #709
    • Fixed a bug in which the default action was not canceled even when returning false in the user event. #736
    Source code(tar.gz)
    Source code(zip)
  • 2.38.6(May 4, 2021)

    Enhancement

    • The user event location has been modified so that the current event action can be canceled by a user event. #736
    // EX)
    editorInstance.onKeyDown = (event, core) => {
        event.preventDefault();
        return false;
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 2.38.5(Apr 28, 2021)

  • 2.38.4(Apr 27, 2021)

    Bugfix

    • Fixed a bug that core.insertNode() is creates a new line when inserted in the middle of the string has been confirmed. #725
    • Fixed a bug that TypeScript build fails. #727
    • Fixed a bug where the default color of the font was not applied properly. #729
    Source code(tar.gz)
    Source code(zip)
  • 2.38.3(Apr 17, 2021)

  • 2.38.2(Apr 16, 2021)

    Bugfix

    • When pasting an external image or video, a bug that sometimes the element was not properly added has been fixed. #709 #714
    • XSS attack vulnerability fixes.
    Source code(tar.gz)
    Source code(zip)
  • 2.38.1(Apr 11, 2021)

    Enhancement

    • The "z-index" and "position" properties of options.defaultStyle have been modified to be applied to the top div. #706

    Bugfix

    • Fiexed a bug where KaTeX rendering was broken, since 2.37.4 version. #707
    Source code(tar.gz)
    Source code(zip)
  • 2.38.0(Apr 11, 2021)

    New feture

    • The printTemplate option has been added. #696

    Enhancement

    • Adapt module export for Typescript 2.6. #700 (@DouglasOGarrido)
    • Updated Typescript definitions. #701 (@Josef-Haupt)
    • Modified the anchor module to can use the "tel:" and "sms:".

    Bugfix

    • Fiexed "Request-Headers" error at the ImageGallery. #702 (@verti4cal)
    • Added media component exception handling. #694
    • Fixed a bug where tag would render when pasting text containing HTML tags. #691
    • Fixed a bug that focusing on the editor when using the core.setContents() method. #686
    Source code(tar.gz)
    Source code(zip)
  • 2.37.4(Apr 1, 2021)

Owner
Yi JiHong
Web developer
Yi JiHong
The next generation Javascript WYSIWYG HTML Editor.

Froala Editor V3 Froala WYSIWYG HTML Editor is one of the most powerful JavaScript rich text editors ever. Slim - only add the plugins that you need (

Froala 5k Jan 1, 2023
A lightweight HTML and BBCode WYSIWYG editor

SCEditor v3.1.1 A lightweight WYSIWYG BBCode and XHTML editor. For more information visit sceditor.com Usage Include the SCEditor JavaScript: <link re

Sam 566 Dec 23, 2022
A lightweight and amazing WYSIWYG JavaScript editor - 20kB only (8kB gzip)

Supporting Trumbowyg Trumbowyg is an MIT-licensed open source project and completely free to use. However, the amount of effort needed to maintain and

Alexandre Demode 3.8k Jan 7, 2023
A modern, simple and elegant WYSIWYG rich text editor.

jQuery-Notebook A simple, clean and elegant WYSIWYG rich text editor for web aplications Note: Check out the fully functional demo and examples here.

Raphael Cruzeiro 1.7k Dec 12, 2022
Quill is a modern WYSIWYG editor built for compatibility and extensibility.

Note: This branch and README covers the upcoming 2.0 release. View 1.x docs here. Quill Rich Text Editor Quickstart • Documentation • Development • Co

Quill 34.3k Jan 2, 2023
Medium.com WYSIWYG editor clone. Uses contenteditable API to implement a rich text solution.

If you would be interested in helping to maintain one of the most successful WYSIWYG text editors on github, let us know! (See issue #1503) MediumEdit

yabwe 15.7k Jan 4, 2023
Simple, beautiful wysiwyg editor

This repo is no longer maintained. bootstrap3-wysiwyg is much better Overview Bootstrap-wysihtml5 is a javascript plugin that makes it easy to create

James Hollingworth 4.2k Dec 30, 2022
Raptor, an HTML5 WYSIWYG content editor!

Raptor Editor Raptor Editor is a user-focused extensible WYSIWYG website content editor - check out the Demo. It is designed to be user and developer

PANmedia 533 Sep 24, 2022
Super simple WYSIWYG editor

Summernote Super simple WYSIWYG Editor. Summernote Summernote is a JavaScript library that helps you create WYSIWYG editors online. Home page: https:/

Summernote 11k Jan 7, 2023
🍞📝 Markdown WYSIWYG Editor. GFM Standard + Chart & UML Extensible.

TOAST UI Editor v3 major update planning ?? ?? ?? TOAST UI Editor is planning a v3 major update for 2021. You can see our detail RoadMap here! GFM Mar

NHN 15.5k Jan 3, 2023
The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.

CKEditor 4 - Smart WYSIWYG HTML editor A highly configurable WYSIWYG HTML editor with hundreds of features, from creating rich text content with capti

CKEditor Ecosystem 5.7k Dec 27, 2022
An Easy and Fast WYSIWYG Editor

Simditor Simditor is a browser-based WYSIWYG text editor. It is used by Tower -- a popular project management web application. Supported Browsers: IE1

彩程设计 5k Jan 3, 2023
WYSIWYG editor developed as jQuery plugin

RichText WYSIWYG editor developed as jQuery plugin. Requirements jQuery (v.3+, v.3.2+ recommended) FontAwesome (v.4.7.0 / v.5+) src/jquery.richtext.mi

Bob 95 Dec 30, 2022
A JS library for building WYSIWYG editors for HTML content.

For information on the ContentTools 2.x roadmap please view the: Roadmap repo ContentTools A JS library for building WYSIWYG editors for HTML content.

getme 3.9k Jan 8, 2023
A toolkit for building WYSIWYG editors with Mobiledoc

Mobiledoc Kit Mobiledoc Kit is a framework-agnostic library for building WYSIWYG editors supporting rich content via cards. Libraries This repository

Bustle 1.5k Jan 3, 2023
A markdown editor. http://lab.lepture.com/editor/

Editor A markdown editor you really want. Sponsors Editor is sponsored by Typlog. Overview Editor is not a WYSIWYG editor, it is a plain text markdown

Hsiaoming Yang 2.8k Dec 19, 2022
Override the rich text editor in Strapi admin with ToastUI Editor.

strapi-plugin-wysiwyg-tui-editor ⚠️ This is a strapi v4 plugin which does not support any earlier version! A Strapi plugin to replace the default rich

Zhuo Chen 12 Dec 23, 2022
A chrome extension which helps change ace editor to monaco editor in web pages, supporting all features including autocompletes.

Monaco-It Monaco-It is a chrome extension turning Ace Editor into Monaco Editor, supporting all features including autocompletes. 一些中文说明 Supported Lan

null 3 May 17, 2022
Open source rich text editor based on HTML5 and the progressive-enhancement approach. Uses a sophisticated security concept and aims to generate fully valid HTML5 markup by preventing unmaintainable tag soups and inline styles.

This project isn’t maintained anymore Please check out this fork. wysihtml5 0.3.0 wysihtml5 is an open source rich text editor based on HTML5 technolo

Christopher Blum 6.5k Jan 7, 2023