jodit
Version:
Jodit is an awesome and useful wysiwyg editor with filebrowser
1,595 lines (1,594 loc) • 61.3 kB
TypeScript
import type { AjaxOptions } from "./types/index";
import type { IDialogOptions } from "./types/index";
import type { IFileBrowserOptions } from "./types/index";
import type { ImageEditorOptions } from "./types/index";
import type { IUploaderOptions } from "./types/index";
import type { IUploader } from "./types/index";
import type { HTMLTagNames } from "./types/index";
import type { AiAssistantSettings } from "./plugins/ai-assistant/interface";
import type { IDictionary } from "./types/index";
import type { Nullable } from "./types/index";
import type { ImagePropertiesOptions } from "./plugins/image-properties/interface";
import type { IControlType } from "./types/index";
import type { IJodit } from "./types/index";
import type { formTemplate } from "./plugins/link/template";
import type { IUIForm } from "./types/index";
import type { IUIOption } from "./types/index";
import type { ButtonsOption } from "./types/index";
import type { InsertMode } from "./types/index";
import type { FuzzySearch } from "./types/index";
import type { ISourceEditor } from "./types/index";
import type { ISpeechRecognizeConstructor } from "./plugins/speech-recognize/interface";
import type { Attributes } from "./types/index";
import type { Controls } from "./types/index";
import type { IAsyncStorageOptions } from "./types/index";
import type { IExtraPlugin } from "./types/index";
import type { IUIButtonState } from "./types/index";
import type { IViewOptions } from "./types/index";
import type { NodeFunction } from "./types/index";
/**
* Default Editor's Configuration.
*
* This class holds all default option values for the Jodit editor.
* It uses a **private constructor** and a **lazy singleton** pattern — the single instance
* is created on the first access to {@link Config.defaultOptions} (also available as `Jodit.defaultOptions`).
*
* ## How options are resolved
*
* When you create an editor with `Jodit.make('#editor', userOptions)`, the library
* calls {@link ConfigProto}(userOptions, Config.defaultOptions). `ConfigProto` does
* **not** deep-clone the defaults. Instead it creates a new object whose JavaScript
* prototype is `Config.defaultOptions`:
*
* ```
* userOptions ──[[Prototype]]──► Config.defaultOptions
* ```
*
* Any key present in `userOptions` shadows the default;
* any key **not** present falls through to `Config.defaultOptions` via the prototype chain.
* Nested plain objects are recursively prototyped in the same way, so partial overrides
* of nested options work automatically:
*
* ```js
* // Only override `dialogWidth`; all other `image.*` defaults are still available
* Jodit.make('#editor', {
* image: { dialogWidth: 500 }
* });
* ```
*
* ## How plugins extend the config
*
* Each plugin adds its own defaults by assigning to `Config.prototype` and augmenting
* the TypeScript type with `declare module`:
*
* ```ts
* // 1. Type augmentation (compile-time)
* declare module 'jodit/config' {
* interface Config {
* toolbarSticky: boolean;
* }
* }
*
* // 2. Runtime default
* Config.prototype.toolbarSticky = true;
* ```
*
* Because the constructor runs `Object.assign(this, ConfigPrototype)` (where
* `ConfigPrototype` is captured as `Config.prototype` after the class definition),
* all prototype-level values — including those added by plugins — are materialized
* as own properties on the singleton. This means `Config.defaultOptions` always
* contains every registered option as an own, enumerable property.
*
* ## Changing global defaults
*
* You can modify `Jodit.defaultOptions` **before** creating editors to change
* defaults globally:
*
* ```js
* Jodit.defaultOptions.language = 'de';
* Jodit.defaultOptions.theme = 'dark';
*
* // Both editors inherit the new defaults
* Jodit.make('#editor1');
* Jodit.make('#editor2');
* ```
*
* ## `Jodit.atom` — preventing deep merge
*
* By default, `ConfigProto` deep-merges nested plain objects and arrays.
* Wrap a value with `Jodit.atom(value)` to make it **atomic** — it will completely
* replace the default instead of being merged:
*
* ```js
* Jodit.make('#editor', {
* controls: {
* fontsize: {
* // Replace the entire list rather than merging with the default one
* list: Jodit.atom([8, 9, 10])
* }
* }
* });
* ```
*
* `Jodit.atom` calls {@link markAsAtomic}, which sets a non-enumerable
* `isAtom` flag on the object. `ConfigProto` checks this flag and skips
* recursive merging when it is present. Note: top-level arrays (depth 0)
* are always treated as atomic — they replace rather than merge.
*
* @see {@link ConfigProto} for the full merge algorithm
* @see {@link markAsAtomic} / {@link isAtom} for the atom marker implementation
*/
declare class Config implements IViewOptions {
private constructor();
/**
* When enabled, the editor caches the results of expensive computations (e.g. toolbar rebuilds)
* to improve performance. Disable for debugging or when options change frequently at runtime.
*/
cache: boolean;
/**
* Timeout of all asynchronous methods
*/
defaultTimeout: number;
/**
* Prefix used for CSS class names and local-storage keys to avoid collisions
* when multiple editor instances or applications share the same page.
*/
namespace: string;
/**
* Editor loads completely without plugins. Useful when debugging your own plugin.
*/
safeMode: boolean;
/**
* Editor's width
*
* ```javascript
* Jodit.make('.editor', {
* width: '100%',
* })
* ```
* ```javascript
* Jodit.make('.editor', {
* width: 600, // equivalent for '600px'
* })
* ```
* ```javascript
* Jodit.make('.editor', {
* width: 'auto', // autosize
* })
* ```
*/
width: number | string;
/**
* Editor's height
*
* ```javascript
* Jodit.make('.editor', {
* height: '100%',
* })
* ```
* ```javascript
* Jodit.make('.editor', {
* height: 600, // equivalent for '600px'
* })
* ```
* ```javascript
* Jodit.make('.editor', {
* height: 'auto', // default - autosize
* })
* ```
*/
height: number | string;
/**
* List of plugins that will be initialized in safe mode.
*
* ```js
* Jodit.make('#editor', {
* safeMode: true,
* safePluginsList: ['about'],
* extraPlugins: ['yourPluginDev']
* });
* ```
*/
safePluginsList: string[];
commandToHotkeys: IDictionary<string | string[]>;
/**
* Reserved for the paid version of the editor
*/
license: string;
/**
* The name of the preset that will be used to initialize the editor.
* The list of available presets can be found here Jodit.defaultOptions.presets
* ```javascript
* Jodit.make('.editor', {
* preset: 'inline'
* });
* ```
*/
preset: string;
/**
* Dictionary of named configuration presets. Each key is a preset name and the value
* is a partial options object that will be merged into the editor config when
* {@link Config.preset} matches the key.
*
* ```javascript
* // Use a built-in preset
* Jodit.make('#editor', {
* preset: 'inline'
* });
* ```
*
* ```javascript
* // Define and use a custom preset
* Jodit.defaultOptions.presets.myCompact = {
* toolbarButtonSize: 'small',
* showCharsCounter: false,
* showWordsCounter: false,
* showXPathInStatusbar: false
* };
*
* Jodit.make('#editor', {
* preset: 'myCompact'
* });
* ```
*/
presets: IDictionary;
/**
* The Document object the editor operates within. Defaults to the current `document`.
* Override when the editor is created inside an iframe or a different browsing context.
*/
ownerDocument: Document;
/**
* Allows you to specify the window in which the editor will be created. Default - window
* This is necessary if you are creating the editor inside an iframe but the code is running in the parent window
*/
ownerWindow: Window;
/**
* Shadow root if Jodit was created in it
*
* ```html
* <div id="editor"></div>
* ```
*
* ```js
* const app = document.getElementById('editor');
* app.attachShadow({ mode: 'open' });
* const root = app.shadowRoot;
*
* root.innerHTML = `
* <link rel="stylesheet" href="./build/jodit.css"/>
* <h1>Jodit example in Shadow DOM</h1>
* <div id="edit"></div>
* `;
*
* const editor = Jodit.make(root.getElementById('edit'), {
* globalFullSize: false,
* shadowRoot: root
* });
* editor.value = '<p>start</p>';
* ```
*/
shadowRoot: Nullable<ShadowRoot>;
/**
* CSP nonce applied to every `<style>`, `<script>` and `<link>` element
* Jodit injects at runtime (plugin styles, CDN scripts for ACE/beautify,
* downloaded stylesheets). Set it to the same nonce your server puts in the
* `Content-Security-Policy` header so a strict `style-src`/`script-src`
* policy does not block the editor.
*
* ```js
* Jodit.make('#editor', {
* nonce: 'r4nd0m'
* });
* ```
*/
nonce: string;
/**
* Base CSS `z-index` for the editor UI (toolbar, popups, dialogs).
* Set to a higher value when other page elements overlap the editor.
* `0` means no explicit z-index is applied.
*/
zIndex: number;
/**
* Change the read-only state of the editor
*/
readonly: boolean;
/**
* Change the disabled state of the editor
*/
disabled: boolean;
/**
* In readOnly mode, some buttons can still be useful, for example, the button to view source code or print
*/
activeButtonsInReadOnly: string[];
/**
* When the editor is in read-only mode, some commands can still be executed:
* ```javascript
* const editor = Jodit.make('.editor', {
* allowCommandsInReadOnly: ['selectall', 'preview', 'print']
* readonly: true
* });
* editor.execCommand('selectall');// will be selected all content
* editor.execCommand('delete');// but content will not be deleted
* ```
*/
allowCommandsInReadOnly: string[];
/**
* Size of icons in the toolbar (can be "small", "middle", "large")
*
* ```javascript
* const editor = Jodit.make(".dark_editor", {
* toolbarButtonSize: "small"
* });
* ```
*/
toolbarButtonSize: IUIButtonState['size'];
/**
* Allow navigation in the toolbar of the editor by Tab key
*/
allowTabNavigation: boolean;
/**
* When enabled, the editor renders without its own container chrome (toolbar, borders, statusbar).
* The editable area becomes the element itself. Typically combined with
* `toolbarInline: true` so a floating toolbar appears on selection.
*/
inline: boolean;
/**
* Theme (can be "dark")
*
* ```javascript
* const editor = Jodit.make(".dark_editor", {
* theme: "dark"
* });
* ```
*/
theme: string;
/**
* if set true, then the current mode is saved in a cookie, and is restored after a reload of the page
*/
saveModeInStorage: boolean;
/**
* Configure the provider that backs {@link IViewBased.asyncStorage}.
*
* By default the editor's `asyncStorage` uses persistent `IndexedDB` (with an
* in-memory fallback when it is unavailable). Set `defaultProvider` to override it:
* - `'local'` — persist in `localStorage`;
* - `'memory'` — keep everything in memory (nothing survives a reload);
* - a custom {@link IAsyncStorage} implementation — plug in your own backend.
*
* ```javascript
* Jodit.make('#editor', {
* asyncStorage: { defaultProvider: 'local' }
* });
*
* // or a fully custom backend
* Jodit.make('#editor', {
* asyncStorage: { defaultProvider: myAsyncStorage }
* });
* ```
*/
asyncStorage: IAsyncStorageOptions;
/**
* Class name that can be appended to the editable area
*
* @see {@link Config.iframeCSSLinks}
* @see {@link Config.iframeStyle}
*
* ```javascript
* Jodit.make('#editor', {
* editorClassName: 'some_my_class'
* });
* ```
* ```html
* <style>
* .some_my_class p{
* line-height: 16px;
* }
* </style>
* ```
*/
editorClassName: false | string;
/**
* Class name that can be appended to the main editor container
*
* ```javascript
* const jodit = Jodit.make('#editor', {
* className: 'some_my_class'
* });
*
* console.log(jodit.container.classList.contains('some_my_class')); // true
* ```
* ```html
* <style>
* .some_my_class {
* max-width: 600px;
* margin: 0 auto;
* }
* </style>
* ```
*/
className: false | string;
/**
* The internal styles of the editable area. They are intended to change
* not the appearance of the editor, but to change the appearance of the content.
*
* ```javascript
* Jodit.make('#editor', {
* style: {
* font: '12px Arial',
* color: '#0c0c0c'
* }
* });
* ```
*/
style: false | IDictionary;
/**
* Inline CSS styles applied to the outer editor container element.
* Use this to style the editor wrapper (borders, background, etc.) without affecting content.
*
* ```javascript
* Jodit.make('#editor', {
* containerStyle: {
* border: '1px solid #ccc',
* background: '#f9f9f9'
* }
* });
* ```
*/
containerStyle: false | IDictionary;
/**
* Dictionary of variable values in css, a complete list can be found here
* https://github.com/xdan/jodit/blob/main/src/styles/variables.less#L25
*
* ```js
* const editor = Jodit.make('#editor', {
* styleValues: {
* 'color-text': 'red',
* colorBorder: 'black',
* 'color-panel': 'blue'
* }
* });
* ```
*/
styleValues: IDictionary;
/**
* When enabled, the editor dispatches a native `change` event on the original
* `<textarea>` element whenever the content changes, so standard DOM listeners work.
*
* ```javascript
* const editor = Jodit.make('#editor');
* document.getElementById('editor').addEventListener('change', function () {
* console.log(this.value);
* })
* ```
*/
triggerChangeEvent: boolean;
/**
* The writing direction of the language which is used to create editor content. Allowed values are: ''
* (an empty string) – Indicates that content direction will be the same as either the editor UI direction or
* the page element direction. 'ltr' – Indicates a Left-To-Right text direction (like in English).
* 'rtl' – Indicates a Right-To-Left text direction (like in Arabic).
*
* ```javascript
* Jodit.make('.editor', {
* direction: 'rtl'
* })
* ```
*/
direction: 'rtl' | 'ltr' | '';
/**
* Language by default. if `auto` language set by document.documentElement.lang ||
* (navigator.language && navigator.language.substr(0, 2)) ||
* (navigator.browserLanguage && navigator.browserLanguage.substr(0, 2)) || 'en'
*
* ```html
* <!-- include in you page lang file -->
* <script src="jodit/lang/de.js"></script>
* <script>
* var editor = Jodit.make('.editor', {
* language: 'de'
* });
* </script>
* ```
*/
language: string;
/**
* if true all Lang.i18n(key) return `{key}`
*
* ```html
* <script>
* var editor = Jodit.make('.editor', {
* debugLanguage: true
* });
*
* console.log(editor.i18n("Test")); // {Test}
* </script>
* ```
*/
debugLanguage: boolean;
/**
* Collection of language pack data `{en: {'Type something': 'Type something', ...}}`
*
* ```javascript
* const editor = Jodit.make('#editor', {
* language: 'ru',
* i18n: {
* ru: {
* 'Type something': 'Начните что-либо вводить'
* }
* }
* });
* console.log(editor.i18n('Type something')) //Начните что-либо вводить
* ```
*/
i18n: IDictionary<IDictionary<string>> | false;
/**
* The tabindex global attribute is an integer indicating if the element can take
* input focus (is focusable), if it should participate to sequential keyboard navigation,
* and if so, at what position. It can take several values
*/
tabIndex: number;
/**
* Boolean, whether the toolbar should be shown.
* Alternatively, a valid css-selector-string to use an element as toolbar container.
*/
toolbar: boolean | string | HTMLElement;
/**
* Boolean, whether the statusbar should be shown.
*/
statusbar: boolean;
/**
* Show tooltip after mouse enter on the button
*/
showTooltip: boolean;
/**
* Delay before show tooltip
*/
showTooltipDelay: number;
/**
* Instead of creating a custom tooltip, use the browser's native title tooltips
*/
useNativeTooltip: boolean;
/**
* How pasted content is inserted into the editor by default.
* Possible values: `insert_as_html`, `insert_as_text`, `insert_only_text`, `insert_clear_html`.
*/
defaultActionOnPaste: InsertMode;
/**
* Element that will be created when you press Enter
*/
enter: 'p' | 'div' | 'br';
/**
* When this option is enabled, the editor's content will be placed in an iframe and isolated from the rest of the page.
*
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeStyle: 'html{margin: 0px;}body{padding:10px;background:transparent;color:#000;position:relative;z-index:2;\
* user-select:auto;margin:0px;overflow:hidden;}body:after{content:"";clear:both;display:block}';
* });
* ```
*/
iframe: boolean;
/**
* Allow editing the entire HTML document(html, head)
* \> Works together with the iframe option.
*
* ```js
* const editor = Jodit.make('#editor', {
* iframe: true,
* editHTMLDocumentMode: true
* });
* editor.value = '<!DOCTYPE html><html lang="en" style="overflow-y:hidden">' +
* '<head><title>Jodit Editor</title></head>' +
* '<body spellcheck="false"><p>Some text</p><p> a </p></body>' +
* '</html>';
* ```
*/
editHTMLDocumentMode: boolean;
/**
* Use when you need to insert new block element
* use enter option if not set
*/
enterBlock: 'p' | 'div';
/**
* Jodit.MODE_WYSIWYG The HTML editor allows you to write like MSWord,
* Jodit.MODE_SOURCE syntax highlighting source editor
*
* ```javascript
* var editor = Jodit.make('#editor', {
* defaultMode: Jodit.MODE_SPLIT
* });
* console.log(editor.getRealMode())
* ```
*/
defaultMode: number;
/**
* When enabled, the editor displays both the WYSIWYG view and the source-code view side by side.
*/
useSplitMode: boolean;
/**
* The colors in HEX representation to select a color for the background and for the text in colorpicker
*
* ```javascript
* Jodit.make('#editor', {
* colors: ['#ff0000', '#00ff00', '#0000ff']
* })
* ```
*/
colors: IDictionary<string[]> | string[];
/**
* The default tab color picker
*
* ```javascript
* Jodit.make('#editor2', {
* colorPickerDefaultTab: 'color'
* })
* ```
*/
colorPickerDefaultTab: 'background' | 'color';
/**
* Default width (in pixels) applied to images inserted into the editor
*/
imageDefaultWidth: number;
/**
* Do not display these buttons that are on the list
*
* ```javascript
* Jodit.make('#editor2', {
* removeButtons: ['hr', 'source']
* });
* ```
*/
removeButtons: string[];
/**
* Do not init these plugins
*
* ```typescript
* var editor = Jodit.make('.editor', {
* disablePlugins: 'table,iframe'
* });
* //or
* var editor = Jodit.make('.editor', {
* disablePlugins: ['table', 'iframe']
* });
* ```
*/
disablePlugins: string[] | string;
/**
* Init and download extra plugins that are **not** already bundled/registered.
*
* For every name in this list that is not found in the plugin registry, Jodit
* loads it **at runtime over the network** from:
*
* ```text
* <basePath>plugins/<name>/<name>(.min).js
* ```
*
* (see {@link Config.basePath} and {@link Config.minified}). If the plugin is
* already registered — e.g. you imported it statically, or you use a bundle
* that ships it (such as the `jodit-pro` / `jodit-pro-react` "all plugins"
* build) — it is **skipped** and no request is made; in that case you don't
* need `extraPlugins` at all, just add the plugin's button.
*
* ```typescript
* // Dynamic loading: fetches <basePath>plugins/emoji/emoji.js
* const editor = Jodit.make('.editor', {
* extraPlugins: ['emoji']
* });
* ```
*
* You can also pass an explicit URL to bypass the `basePath` convention:
*
* ```typescript
* const editor = Jodit.make('.editor', {
* extraPlugins: [{ name: 'emoji', url: 'https://cdn.example.com/emoji.js' }]
* });
* ```
*
* Note: if you see a request to a malformed URL (e.g. `.../src/main.tsx?t=...plugins/emoji/emoji.js`),
* it means `basePath` was auto-detected incorrectly under your bundler — set
* {@link Config.basePath} explicitly. See the Plugin System docs for details.
*/
extraPlugins: Array<string | IExtraPlugin>;
/**
* Base path used to build the URL for dynamically loaded {@link Config.extraPlugins}
* (and their styles): `<basePath>plugins/<name>/<name>(.min).js`.
*
* When not set, Jodit auto-detects it from `document.currentScript`, then the
* last `<script src>` on the page, then `location.href`. That detection works
* for classic `<script>` includes, but **fails under ESM bundlers / dev
* servers** (Vite, Webpack dev, etc.) where there is no script tag for the
* bundle — it falls back to the entry module URL (e.g. `main.tsx`) and produces
* a broken plugin URL.
*
* Fix: host the plugin files at a public location and point `basePath` there
* (note the trailing slash):
*
* ```typescript
* const editor = Jodit.make('.editor', {
* basePath: 'https://your-site.com/jodit-assets/',
* extraPlugins: ['emoji']
* // → loads https://your-site.com/jodit-assets/plugins/emoji/emoji.js
* });
* ```
*/
basePath?: string;
/**
* Additional buttons appended to the {@link Config.buttons} list
*/
extraButtons: Array<string | IControlType>;
/**
* By default, you can only install an icon from the Jodit suite.
* You can add your icon to the set using the `Jodit.modules.Icon.set (name, svg Code)` method.
* But for a declarative declaration, you can use this option.
*
* ```js
* Jodit.modules.Icon.set('someIcon', '<svg><path.../></svg>');
* const editor = Jodit.make({
* extraButtons: [{
* name: 'someButton',
* icon: 'someIcon'
* }]
* });
* ```
*
* ```js
* const editor = Jodit.make({
* extraIcons: {
* someIcon: '<svg><path.../></svg>'
* },
* extraButtons: [{
* name: 'someButton',
* icon: 'someIcon'
* }]
* });
* ```
*
* ```js
* const editor = Jodit.make({
* extraButtons: [{
* name: 'someButton',
* icon: '<svg><path.../></svg>'
* }]
* });
* ```
*/
extraIcons: IDictionary<string>;
/**
* Default attributes for created inside editor elements
*
* ```js
* const editor2 = Jodit.make('#editor', {
* createAttributes: {
* div: {
* class: 'test'
* },
* ul: function (ul) {
* ul.classList.add('ui-test');
* }
* }
* });
*
* const div2 = editor2.createInside.div();
* expect(div2.className).equals('test');
*
* const ul = editor2.createInside.element('ul');
* expect(ul.className).equals('ui-test');
* ```
* Or JSX in React
*
* ```jsx
* import React, {useState, useRef} from 'react';
* import JoditEditor from "jodit-react";
*
* const config = {
* createAttributes: {
* div: {
* class: 'align-center'
* }
* }
* };
*
* <JoditEditor config={config}/>
* ```
*/
createAttributes: IDictionary<Attributes | NodeFunction>;
/**
* The width of the editor, accepted as the biggest. Used to the responsive version of the editor
*/
sizeLG: number;
/**
* The width of the editor, accepted as the medium. Used to the responsive version of the editor
*/
sizeMD: number;
/**
* The width of the editor, accepted as the small. Used to the responsive version of the editor
*/
sizeSM: number;
/**
* The list of buttons that appear in the editor's toolbar on large places (≥ options.sizeLG).
* Note - this is not the width of the device, the width of the editor
*
* ```javascript
* Jodit.make('#editor', {
* buttons: ['bold', 'italic', 'source'],
* buttonsMD: ['bold', 'italic'],
* buttonsXS: ['bold', 'fullsize'],
* });
* ```
*
* ```javascript
* Jodit.make('#editor2', {
* buttons: [{
* name: 'empty',
* icon: 'source',
* exec: function (editor) {
* const dialog = new Jodit.modules.Dialog({}),
* text = editor.c.element('textarea');
*
* dialog.setHeader('Source code');
* dialog.setContent(text);
* dialog.setSize(400, 300);
*
* Jodit.modules.Helpers.css(elm, {
* width: '100%',
* height: '100%'
* })
* dialog.open();
* }
* }]
* });
* ```
*
* ```javascript
* Jodit.make('#editor2', {
* buttons: Jodit.defaultOptions.buttons.concat([{
* name: 'listsss',
* iconURL: 'stuf/dummy.png',
* list: {
* h1: 'insert Header 1',
* h2: 'insert Header 2',
* clear: 'Empty editor',
* },
* exec: ({originalEvent, control, btn}) => {
* var key = control.args[0],
* value = control.args[1];
* if (key === 'clear') {
* this.val('');
* return;
* }
* this.s.insertNode(this.c.element(key, ''));
* this.message.info('Was inserted ' + value);
* },
* template: function (key, value) {
* return '<div>' + value + '</div>';
* }
* });
* ```
*/
buttons: ButtonsOption;
/**
* Map of toolbar button names to their control definitions (icon, tooltip, exec handler, etc.).
* Plugins extend this object with their own button definitions via `Config.prototype.controls`.
*/
controls: Controls;
/**
* Some events are called when the editor is initialized, for example, the `afterInit` event.
* So this code won't work:
* ```javascript
* const editor = Jodit.make('#editor');
* editor.events.on('afterInit', () => console.log('afterInit'));
* ```
* You need to do this:
* ```javascript
* Jodit.make('#editor', {
* events: {
* afterInit: () => console.log('afterInit')
* }
* });
* ```
* The option can use any Jodit events, for example:
* ```javascript
* const editor = Jodit.make('#editor', {
* events: {
* hello: (name) => console.log('Hello', name)
* }
* });
* editor.e.fire('hello', 'Mike');
* ```
*/
events: IDictionary<(...args: any[]) => any>;
/**
* Buttons in toolbar without SVG - only texts
*/
textIcons: boolean;
/**
* Element for dialog container
*/
popupRoot: Nullable<HTMLElement>;
/**
* shows a INPUT[type=color] to open the browser color picker, on the right bottom of widget color picker
*/
showBrowserColorPicker: boolean;
private static __defaultOptions;
static get defaultOptions(): Config;
}
export { Config };
interface Config {
/**
* A set of key/value pairs that configure the Ajax request. All settings are optional
*/
defaultAjaxOptions: AjaxOptions;
}
interface Config {
dialog: IDialogOptions;
}
interface Config {
filebrowser: IFileBrowserOptions;
}
interface Config {
history: {
enable: boolean;
/**
* Limit of history length
*/
maxHistoryLength: number;
/**
* Delay on every change
*/
timeout: number;
};
}
interface Config {
imageeditor: ImageEditorOptions;
}
interface Config {
/**
* Enable drag and drop file editor
*/
enableDragAndDropFileToEditor: boolean;
uploader: IUploaderOptions<IUploader>;
}
interface Config {
/**
* Show a green "add paragraph" bar when the cursor hovers near the top or bottom
* edge of certain block elements (tables, images, iframes, etc.)
*/
addNewLine: boolean;
/**
* Block-level tag names near which the "add new line" bar will appear
*/
addNewLineTagsTriggers: HTMLTagNames[];
/**
* On dbl click on empty space of editor it add new P element
*
* ```js
* Jodit.make('#editor', {
* addNewLineOnDBLClick: false // disable
* })
* ```
*/
addNewLineOnDBLClick: boolean;
/**
* Absolute delta between cursor position and edge(top or bottom)
* of element when show line
*/
addNewLineDeltaShow: number;
}
interface Config {
aiAssistant: AiAssistantSettings;
}
interface Config {
/**
* Keyboard hotkey mappings for delete and backspace operations (character, word, sentence).
*/
delete: {
hotkeys: {
delete: string[];
deleteWord: string[];
deleteSentence: string[];
backspace: string[];
backspaceWord: string[];
backspaceSentence: string[];
};
/**
* Disable specific Backspace/Delete cleanup cases by their stable
* key, so the plugin no longer applies that particular behavior.
* Available keys: `remove-unbreakable`, `remove-not-editable`,
* `remove-char`, `table-cell`, `remove-empty-parent`,
* `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
* `unwrap-first-list-item`.
*
* ```javascript
* Jodit.make('#editor', {
* delete: { disableCases: new Set(['remove-empty-parent']) }
* });
* ```
*/
disableCases?: Set<string>;
};
}
interface Config {
cleanHTML: {
timeout: number;
/**
* Replace &nbsp; to plain space
*/
replaceNBSP: boolean;
/**
* Remove empty P tags, if they are not in the beginning of the text
*/
fillEmptyParagraph: boolean;
/**
* Remove empty elements
*/
removeEmptyElements: boolean;
/**
* Return an empty string from `editor.value` (and the synced source
* element) when the editor holds only a single empty block — e.g.
* `<p><br></p>` left after the user deletes all the content.
* `contenteditable` keeps that caret container in the DOM, so by
* default the value getter returns it as-is; enable this to collapse
* it to `''` for form submission.
*/
collapseEmptyValueToEmptyString: boolean;
/**
* Replace old tags to new eg. <i> to <em>, <b> to <strong>
*/
replaceOldTags: IDictionary<HTMLTagNames> | false;
/**
* You can use an iframe with the sandbox attribute to safely paste and test HTML code.
* It prevents scripts and handlers from running, but it does slow things down.
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* useIframeSandbox: true
* }
* });
* ```
*/
useIframeSandbox: boolean;
/**
* @deprecated Use `removeEventAttributes` instead
* Remove onError attributes
*/
removeOnError: boolean;
/**
* Remove all `on*` event handler attributes (onerror, onclick, onload, onmouseover, etc.)
* When enabled, this replaces the legacy `removeOnError` behavior with comprehensive protection.
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* removeEventAttributes: true
* }
* });
* ```
*/
removeEventAttributes: boolean;
/**
* Safe href="javascript:" links
*/
safeJavaScriptLink: boolean;
/**
* Automatically add `rel="noopener noreferrer"` to links with `target="_blank"`
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* safeLinksTarget: true
* }
* });
* ```
*/
safeLinksTarget: boolean;
/**
* Whitelist of allowed CSS properties inside `style` attributes.
* If set, all CSS properties not in the list will be removed.
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* allowedStyles: {
* '*': ['color', 'background-color', 'font-size', 'text-align'],
* img: ['width', 'height']
* }
* }
* });
* ```
*/
allowedStyles: false | IDictionary<string[]>;
/**
* Custom sanitizer function. Called after Jodit's built-in sanitization.
* Use this to integrate DOMPurify or other external sanitizers.
*
* ```javascript
* import DOMPurify from 'dompurify';
*
* Jodit.make('#editor', {
* cleanHTML: {
* sanitizer: (html) => DOMPurify.sanitize(html)
* }
* });
* ```
*/
sanitizer: false | ((value: string) => string);
/**
* Automatically add `sandbox=""` attribute to all `<iframe>` elements in editor content.
* Prevents embedded content from running scripts or accessing the parent page.
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* sandboxIframesInContent: true
* }
* });
* ```
*/
sandboxIframesInContent: boolean;
/**
* Convert unsafe embed elements to sandboxed `<iframe>`.
* - `['object', 'embed']` — default
* - `false` — disabled
* - `string[]` — custom list of tag names to convert
*
* ```javascript
* Jodit.make('#editor', {
* cleanHTML: {
* convertUnsafeEmbeds: Jodit.atom(['object', 'embed', 'applet'])
* }
* });
* ```
*/
convertUnsafeEmbeds: false | string[];
/**
* The allowTags option defines which elements will remain in the
* edited text when the editor saves. You can use this limit the returned HTML.
*
* ```javascript
* const jodit = new Jodit.make('#editor', {
* cleanHTML: {
* cleanOnPaste: false
* }
* });
* ```
*
* ```javascript
* const editor = Jodit.make('#editor', {
* cleanHTML: {
* allowTags: 'p,a[href],table,tr,td, img[src=1.png]' // allow only <p>,<a>,<table>,<tr>,<td>,<img> tags and
* for <a> allow only `href` attribute and <img> allow only `src` attribute == '1.png'
* }
* });
* editor.value = 'Sorry! <strong>Goodby</strong>\
* <span>mr.</span> <a style="color:red" href="https://xdsoft.net">Freeman</a>';
* console.log(editor.value); //Sorry! <a href="https://xdsoft.net">Freeman</a>
* ```
*
* ```javascript
* const editor = Jodit.make('#editor', {
* cleanHTML: {
* allowTags: {
* p: true,
* a: {
* href: true
* },
* table: true,
* tr: true,
* td: true,
* img: {
* src: '1.png'
* }
* }
* }
* });
* ```
*/
allowTags: false | string | IDictionary<string>;
denyTags: false | string | IDictionary<string>;
/**
* Node filtering rules that do not need to be applied to content
* The full list of rules is generated dynamically from the folder
* https://github.com/xdan/jodit/tree/main/src/plugins/clean-html/helpers/visitor/filters
*/
disableCleanFilter: Nullable<Set<string>>;
};
}
interface Config {
/**
* Draggable elements
*/
draggableTags: string | string[];
}
interface Config {
dtd: {
/**
* Remove extra br element inside block element after pasting
*/
removeExtraBr: boolean;
/**
* Check when inserting a block element if it can be inside another block element (according `blockLimits`)
*/
checkBlockNesting: boolean;
/**
* List of elements that contain other blocks
*/
blockLimits: IDictionary<1>;
};
}
interface Config {
autofocus: boolean;
cursorAfterAutofocus: 'start' | 'end';
saveSelectionOnBlur: boolean;
}
interface Config {
defaultFontSizePoints: 'px' | 'pt';
}
interface Config {
/**
* Open WYSIWYG in full screen
*
* ```javascript
* var editor = Jodit.make({
* fullsize: true // fullsize editor
* });
* ```
*
* ```javascript
* var editor = Jodit.make();
* editor.e.fire('toggleFullSize');
* editor.e.fire('toggleFullSize', true); // fullsize
* editor.e.fire('toggleFullSize', false); // usual mode
* ```
*/
fullsize: boolean;
/**
* True, after `fullsize` - all editors elements above jodit will get `jodit_fullsize-box_true` class (z-index: 100000 !important;)
*/
globalFullSize: boolean;
}
interface Config {
/**
* You can redefine hotkeys for some command
*
* ```js
* const jodit = Jodit.make('#editor', {
* commandToHotkeys: {
* bold: 'ctrl+shift+b',
* italic: ['ctrl+i', 'ctrl+b'],
* }
* })
* ```
*/
commandToHotkeys: IDictionary<string | string[]>;
}
interface Config {
/**
* You can redefine default page
*
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeDefaultSrc: 'https://xdsoft.net/jodit/docs/',
* });
* ```
*/
iframeDefaultSrc: string;
/**
* Base URL where the root directory for {@link Config.iframe} mode
*
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeBaseUrl: 'https://xdsoft.net/jodit/docs/',
* });
* ```
*/
iframeBaseUrl: string;
/**
* Iframe title's content
*/
iframeTitle: string;
/**
* Iframe's DOCTYPE
*/
iframeDoctype: string;
/**
* Custom style to be used inside the iframe to display content.
*
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeStyle: 'html{margin: 0px;}',
* })
* ```
*/
iframeStyle: string;
/**
* Custom stylesheet files to be used inside the iframe to display content.
*
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeCSSLinks: ['styles/default.css'],
* })
* ```
*/
iframeCSSLinks: string[];
/**
* Custom sandbox attribute for the iframe.
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox
* ```javascript
* Jodit.make('#editor', {
* iframe: true,
* iframeSandbox: 'allow-same-origin allow-scripts'
* });
* ```
* Empty string value means that all restrictions are enabled.
*/
iframeSandbox: string | null;
}
interface Config {
/**
* Options for processing images inserted into the editor (e.g. converting base64 data URIs to Blob URLs).
*/
imageProcessor: {
replaceDataURIToBlobIdInView: boolean;
};
}
interface Config {
/**
* Configuration for the image properties dialog (opened on double-click).
* Controls which editing tabs are available: src, alt, title, link, size, margins, classes, styles, etc.
*/
image: ImagePropertiesOptions;
}
interface Config {
/**
* The number of pixels to use for indenting the current line.
*/
indentMargin: number;
}
interface Config {
/**
* Element-specific popup toolbars. Keys are tag names (e.g. `img`, `a`, `cells`)
* and values are button lists or factory functions that return them.
*/
popup: IDictionary<Array<IControlType | string> | ((editor: IJodit, target: HTMLElement | undefined, close: () => void) => Array<IControlType | string> | HTMLElement | string)>;
/**
* List of button names to exclude from the inline toolbar
*/
toolbarInlineDisabledButtons: string[];
/**
* Show an inline toolbar when the user clicks inside the editor area (e.g. near images, links)
*/
toolbarInline: boolean;
/**
* Show an inline toolbar when the user selects text
*/
toolbarInlineForSelection: boolean;
/**
* CSS selector or array of selectors for elements that should not trigger the inline toolbar
*/
toolbarInlineDisableFor: string | string[];
}
interface Config {
/**
* Maximum number of words allowed in the editor. Set to `false` to disable the limit.
*/
limitWords: false | number;
/**
* Maximum number of characters allowed in the editor. Set to `false` to disable the limit.
*/
limitChars: false | number;
/**
* Maximum number of characters counted from the raw HTML source. Set to `false` to disable the limit.
*/
limitHTML: false;
}
interface Config {
/**
* Default line spacing for the entire editor
*
* ```js
* Jodit.make('#editor', {
* defaultLineHeight: 1.2
* })
* ```
*/
defaultLineHeight: number | null;
}
interface Config {
link: {
/**
* Template for the link dialog form
*/
formTemplate: (editor: IJodit) => string | HTMLElement | IUIForm;
formClassName?: string;
/**
* Follow link address after dblclick
*/
followOnDblClick: boolean;
/**
* Replace inserted youtube/vimeo link to `iframe`
*/
processVideoLink: boolean;
/**
* Wrap inserted link
*/
processPastedLink: boolean;
/**
* When opening the link dialog for a new link with an empty URL field,
* pre-fill it from the selected text if that text looks like a URL or
* an email address (`example.com` → `https://example.com`,
* `user@site.com` → `mailto:user@site.com`). Plain text that is not a
* URL/email is left untouched. Default: false.
*/
deriveUrlFromText: boolean;
/**
* Show `no follow` checkbox in link dialog.
*/
noFollowCheckbox: boolean;
/**
* Show `Open in new tab` checkbox in link dialog.
*/
openInNewTabCheckbox: boolean;
/**
* Default value for the `Open in new tab` checkbox when inserting a new link.
*/
openInNewTabCheckboxDefaultChecked: boolean;
/**
* Show an `aria-label` text input in the link dialog so an
* accessible name can be set on the `<a>` (useful when several
* links share the same visible text, e.g. "here"). Default: false.
*/
ariaLabelInput: boolean;
/**
* Use an input text to ask the classname or a select or not ask
*/
modeClassName: 'input' | 'select';
/**
* Allow multiple choises (to use with modeClassName="select")
*/
selectMultipleClassName: boolean;
/**
* The size of the select (to use with modeClassName="select")
*/
selectSizeClassName?: number;
/**
* The list of the option for the select (to use with modeClassName="select")
*/
selectOptionsClassName: IUIOption[];
hotkeys: string[];
/**
* Prevent navigation to the link if it is readonly. Default: true
*/
preventReadOnlyNavigation: boolean;
};
}
interface Config {
/**
* Decorate media elements
*/
mediaInFakeBlock: boolean;
/**
* Decorate media element with tag
*/
mediaFakeTag: string;
/**
* Media tags
*/
mediaBlocks: string[];
}
interface Config {
/**
* Mobile timeout for CLICK emulation
*/
mobileTapTimeout: number;
/**
* After resizing, the set of buttons will change to accommodate different sizes.
*/
toolbarAdaptive: boolean;
/**
* The list of buttons that appear in the editor's toolbar for medium-sized spaces (≥ options.sizeMD).
*
* The set is constrained to `buttons`: resizing may only drop buttons on
* smaller widths, never surface a button that is not in `buttons`. So if
* you customise only `buttons` and leave this at its default, a narrow
* editor still shows just your `buttons`. Set this explicitly (as a subset
* of `buttons`) to get a different medium-width set.
*/
buttonsMD: ButtonsOption;
/**
* The list of buttons that appear in the editor's toolbar for small-sized spaces (≥ options.sizeSM).
*
* Constrained to `buttons` — see {@link buttonsMD}.
*/
buttonsSM: ButtonsOption;
/**
* The list of buttons that appear in the editor's toolbar for extra-small spaces (less than options.sizeSM).
*
* Constrained to `buttons` — see {@link buttonsMD}.
*/
buttonsXS: ButtonsOption;
}
interface Config {
/**
* Ask before paste HTML in WYSIWYG mode
*/
askBeforePasteHTML: boolean;
/**
* When the user inserts a snippet of HTML, the plugin will prompt for the insertion method.
* If the user inserts the same fragment again, the previously selected option will be used without prompting for confirmation.
*/
memorizeChoiceWhenPasteFragment: boolean;
/**
* Handle pasted text - similar to HTML
*/
processPasteHTML: boolean;
/**
* Inserts HTML line breaks before all newlines in a string
*/
nl2brInPlainText: boolean;
/**
* List of tags that will not be removed from the pasted HTML with INSERT_AS_TEXT mode
*/
pasteExcludeStripTags: HTMLTagNames[];
/**
* Options when inserting HTML string
*/
pasteHTMLActionList: IUIOption[];
/**
* Scroll the editor to the pasted fragment
*/
scrollToPastedContent: boolean;
}
interface Config {
/**
* Show the paste dialog if the html is similar to what MSWord gives when copying.
*/
askBeforePasteFromWord: boolean;
/**
* Handle pasting of HTML - similar to a fragment copied from MSWord
*/
processPasteFromWord: boolean;
/**
* Default insert method from word, if not define, it will use defaultActionOnPaste instead
*
* ```js
* Jodit.make('#editor', {
* defaultActionOnPasteFromWord: 'insert_clear_html'
* })
* ```
*/
defaultActionOnPasteFromWord: InsertMode | null;
/**
* Options when inserting data from Word
*/
pasteFromWordActionList: IUIOption[];
}
interface Config {
/**
* Show placeholder
*
* ```javascript
* const editor = Jodit.make('#editor', {
* showPlaceholder: false
* });
* ```
*/
showPlaceholder: boolean;
/**
* Use a placeholder from original input field, if it was set
*
* ```javascript
* //<textarea id="editor" placeholder="start typing text ..." cols="30" rows="10"></textarea>
* const editor = Jodit.make('#editor', {
* useInputsPlaceholder: true
* });
* ```
*/
useInputsPlaceholder: boolean;
/**
* Default