# Table of Contents - [Quickstart - Quill Rich Text Editor](#quickstart-quill-rich-text-editor) - [Why Quill - Quill Rich Text Editor](#why-quill-quill-rich-text-editor) - [Delta - Quill Rich Text Editor](#delta-quill-rich-text-editor) - [Formats - Quill Rich Text Editor](#formats-quill-rich-text-editor) - [Clipboard Module - Quill Rich Text Editor](#clipboard-module-quill-rich-text-editor) - [Toolbar Module - Quill Rich Text Editor](#toolbar-module-quill-rich-text-editor) - [API - Quill Rich Text Editor](#api-quill-rich-text-editor) - [History Module - Quill Rich Text Editor](#history-module-quill-rich-text-editor) - [Installation - Quill Rich Text Editor](#installation-quill-rich-text-editor) - [Upgrading to 2.0 - Quill Rich Text Editor](#upgrading-to-2-0-quill-rich-text-editor) - [Themes - Quill Rich Text Editor](#themes-quill-rich-text-editor) - [Modules - Quill Rich Text Editor](#modules-quill-rich-text-editor) - [Registries - Quill Rich Text Editor](#registries-quill-rich-text-editor) - [Configuration - Quill Rich Text Editor](#configuration-quill-rich-text-editor) - [Syntax Highlighter Module - Quill Rich Text Editor](#syntax-highlighter-module-quill-rich-text-editor) - [Customization - Quill Rich Text Editor](#customization-quill-rich-text-editor) - [Building a Custom Module - Quill Rich Text Editor](#building-a-custom-module-quill-rich-text-editor) - [Keyboard Module - Quill Rich Text Editor](#keyboard-module-quill-rich-text-editor) - [Designing the Delta Format - Quill Rich Text Editor](#designing-the-delta-format-quill-rich-text-editor) - [Cloning Medium with Parchment - Quill Rich Text Editor](#cloning-medium-with-parchment-quill-rich-text-editor) --- # Quickstart - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationQuickstart [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/quickstart.mdx "Edit on GitHub") Quickstart ========== The best way to get started is to try a simple example. Quill is initialized with a DOM element to contain the editor. The contents of that element will become the initial contents of Quill.
Hello World! Some initial bold text
Note by supplying your own HTML element, Quill searches for particular input elements, but your own inputs that have nothing to do with Quill can still be added and styled and coexist.
[](https://quilljs.com/docs/modules/toolbar#handlers) Handlers -------------------------------------------------------------- The toolbar controls by default applies and removes formatting, but you can also overwrite this with custom handlers, for example in order to show external UI. Handler functions will be bound to the toolbar (so using `this` will refer to the toolbar instance) and passed the `value` attribute of the input if the corresponding format is inactive, and `false` otherwise. Adding a custom handler will overwrite the default toolbar and theme behavior. const toolbarOptions = { handlers: { // handlers object will be merged with default handlers object link: function (value) { if (value) { const href = prompt('Enter the URL'); this.quill.format('link', href); } else { this.quill.format('link', false); } } }}; const quill = new Quill('#editor', { modules: { toolbar: toolbarOptions }}); // Handlers can also be added post initializationconst toolbar = quill.getModule('toolbar');toolbar.addHandler('image', showImageUI); * * * An Open Source Project ---------------------- Quill is developed and maintained by [Slab](https://slab.com/) . It is permissively licensed under BSD. Use it freely in personal or commercial projects! [Star](https://github.com/slab/quill/ "Star Quill on GitHub") [37,622](https://github.com/slab/quill/stargazers "Quill Stargazers") --- # API - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationAPI [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/api.mdx "Edit on GitHub") API === [](https://quilljs.com/docs/api#content) Content ------------------------------------------------ ### [](https://quilljs.com/docs/api#deletetext) deleteText Deletes text from the editor, returning a [Delta](https://quilljs.com/docs/delta) representing the change. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** deleteText(index: number, length: number, source: string = 'api'): Delta **Example 1** quill.deleteText(6, 4); **Example 2** const quill = new Quill('#editor', { theme: 'snow' }); document.querySelector('#deleteButton').addEventListener('click', () \=> { quill.deleteText(5, 7); }); Run Code ### [](https://quilljs.com/docs/api#getcontents) getContents Retrieves contents of the editor, with formatting data, represented by a [Delta](https://quilljs.com/docs/delta) object. **Methods** getContents(index: number = 0, length: number = remaining): Delta **Examples** const delta = quill.getContents(); ### [](https://quilljs.com/docs/api#getlength) getLength Retrieves the length of the editor contents. Note even when Quill is empty, there is still a blank line represented by '\\n', so `getLength` will return 1. **Methods** getLength(): number **Examples** const length = quill.getLength(); ### [](https://quilljs.com/docs/api#gettext) getText Retrieves the string contents of the editor. Non-string content are omitted, so the returned string's length may be shorter than the editor's as returned by [`getLength`](https://quilljs.com/docs/api#getlength) . Note even when Quill is empty, there is still a blank line in the editor, so in these cases `getText` will return '\\n'. The `length` parameter defaults to the length of the remaining document. **Methods** getText(index: number = 0, length: number = remaining): string **Examples** const text = quill.getText(0, 10); ### [](https://quilljs.com/docs/api#getsemantichtml) getSemanticHTML Get the HTML representation of the editor contents. This method is useful for exporting the contents of the editor in a format that can be used in other applications. The `length` parameter defaults to the length of the remaining document. **Methods** getSemanticHTML(index: number = 0, length: number = remaining): string **Examples** const html = quill.getSemanticHTML(0, 10); ### [](https://quilljs.com/docs/api#insertembed) insertEmbed Insert embedded content into the editor, returning a [Delta](https://quilljs.com/docs/delta) representing the change. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** insertEmbed(index: number, type: string, value: any, source: string = 'api'): Delta **Examples** quill.insertEmbed(10, 'image', 'https://quilljs.com/images/cloud.png'); ### [](https://quilljs.com/docs/api#inserttext) insertText Inserts text into the editor, optionally with a specified format or multiple [formats](https://quilljs.com/docs/formats) . Returns a [Delta](https://quilljs.com/docs/delta) representing the change. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** insertText(index: number, text: string, source: string = 'api'): DeltainsertText(index: number, text: string, format: string, value: any, source: string = 'api'): DeltainsertText(index: number, text: string, formats: { [name: string]: any }, source: string = 'api'): Delta **Examples** quill.insertText(0, 'Hello', 'bold', true); quill.insertText(5, 'Quill', { color: '#ffff00', italic: true,}); ### [](https://quilljs.com/docs/api#setcontents) setContents Overwrites editor with given contents. Contents should end with a [newline](https://quilljs.com/docs/delta#line-formatting) . Returns a Delta representing the change. This will be the same as the Delta passed in, if given Delta had no invalid operations. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** setContents(delta: Delta, source: string = 'api'): Delta **Examples** quill.setContents([ { insert: 'Hello ' }, { insert: 'World!', attributes: { bold: true } }, { insert: '\n' },]); ### [](https://quilljs.com/docs/api#settext) setText Sets contents of editor with given text, returning a [Delta](https://quilljs.com/docs/delta) representing the change. Note Quill documents must end with a newline so one will be added for you if omitted. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** setText(text: string, source: string = 'api'): Delta **Examples** quill.setText('Hello\n'); ### [](https://quilljs.com/docs/api#updatecontents) updateContents Applies Delta to editor contents, returning a [Delta](https://quilljs.com/docs/delta) representing the change. These Deltas will be the same if the Delta passed in had no invalid operations. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** updateContents(delta: Delta, source: string = 'api'): Delta **Examples** // Assuming editor currently contains [{ insert: 'Hello World!' }]quill.updateContents(new Delta() .retain(6) // Keep 'Hello ' .delete(5) // 'World' is deleted .insert('Quill') .retain(1, { bold: true }) // Apply bold to exclamation mark);// Editor should now be [// { insert: 'Hello Quill' },// { insert: '!', attributes: { bold: true} }// ] Note This method updates the contents from the beginning, not from the current selection. Use `Delta#retain(length: number)` to skip the contents you wish to leave unchanged. [](https://quilljs.com/docs/api#formatting) Formatting ------------------------------------------------------ ### [](https://quilljs.com/docs/api#format) format Format text at user's current selection, returning a [Delta](https://quilljs.com/docs/delta) representing the change. If the user's selection length is 0, i.e. it is a cursor, the format will be set active, so the next character the user types will have that formatting. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** format(name: string, value: any, source: string = 'api'): Delta **Examples** quill.format('color', 'red');quill.format('align', 'right'); ### [](https://quilljs.com/docs/api#formatline) formatLine Formats all lines in given range, returning a [Delta](https://quilljs.com/docs/delta) representing the change. See [formats](https://quilljs.com/docs/formats) for a list of available formats. Has no effect when called with inline formats. To remove formatting, pass `false` for the value argument. The user's selection may not be preserved. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** formatLine(index: number, length: number, source: string = 'api'): DeltaformatLine(index: number, length: number, format: string, value: any, source: string = 'api'): DeltaformatLine(index: number, length: number, formats: { [name: string]: any }, source: string = 'api'): Delta **Examples** quill.setText('Hello\nWorld!\n'); quill.formatLine(1, 2, 'align', 'right'); // right aligns the first linequill.formatLine(4, 4, 'align', 'center'); // center aligns both lines ### [](https://quilljs.com/docs/api#formattext) formatText Formats text in the editor, returning a [Delta](https://quilljs.com/docs/delta) representing the change. For line level formats, such as text alignment, target the newline character or use the [`formatLine`](https://quilljs.com/docs/api#formatline) helper. See [formats](https://quilljs.com/docs/formats) for a list of available formats. To remove formatting, pass `false` for the value argument. The user's selection may not be preserved. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** formatText(index: number, length: number, source: string = 'api'): DeltaformatText(index: number, length: number, format: string, value: any, source: string = 'api'): DeltaformatText(index: number, length: number, formats: { [name: string]: any }, source: string = 'api'): Delta **Examples** quill.setText('Hello\nWorld!\n'); quill.formatText(0, 5, 'bold', true); // bolds 'hello' quill.formatText(0, 5, { // unbolds 'hello' and set its color to blue 'bold': false, 'color': 'rgb(0, 0, 255)'}); quill.formatText(5, 1, 'align', 'right'); // right aligns the 'hello' line ### [](https://quilljs.com/docs/api#getformat) getFormat Retrieves common formatting of the text in the given range. For a format to be reported, all text within the range must have a truthy value. If there are different truthy values, an array with all truthy values will be reported. If no range is supplied, the user's current selection range is used. May be used to show which formats have been set on the cursor. If called with no arguments, the user's current selection range will be used. **Methods** getFormat(range: Range = current): RecordgetFormat(index: number, length: number = 0): Record **Examples** quill.setText('Hello World!');quill.formatText(0, 2, 'bold', true);quill.formatText(1, 2, 'italic', true);quill.getFormat(0, 2); // { bold: true }quill.getFormat(1, 1); // { bold: true, italic: true } quill.formatText(0, 2, 'color', 'red');quill.formatText(2, 1, 'color', 'blue');quill.getFormat(0, 3); // { color: ['red', 'blue'] } quill.setSelection(3);quill.getFormat(); // { italic: true, color: 'blue' } quill.format('strike', true);quill.getFormat(); // { italic: true, color: 'blue', strike: true } quill.formatLine(0, 1, 'align', 'right');quill.getFormat(); // { italic: true, color: 'blue', strike: true, // align: 'right' } ### [](https://quilljs.com/docs/api#removeformat) removeFormat Removes all formatting and embeds within given range, returning a [Delta](https://quilljs.com/docs/delta) representing the change. Line formatting will be removed if any part of the line is included in the range. The user's selection may not be preserved. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. Calls where the `source` is `"user"` when the editor is [disabled](https://quilljs.com/docs/api#disable) are ignored. **Methods** removeFormat(index: number, length: number, source: string = 'api'): Delta **Examples** quill.setContents([ { insert: 'Hello', { bold: true } }, { insert: '\n', { align: 'center' } }, { insert: { formula: 'x^2' } }, { insert: '\n', { align: 'center' } }, { insert: 'World', { italic: true }}, { insert: '\n', { align: 'center' } }]); quill.removeFormat(3, 7);// Editor contents are now// [// { insert: 'Hel', { bold: true } },// { insert: 'lo\n\nWo' },// { insert: 'rld', { italic: true }},// { insert: '\n', { align: 'center' } }// ] [](https://quilljs.com/docs/api#selection) Selection ---------------------------------------------------- ### [](https://quilljs.com/docs/api#getbounds) getBounds Retrieves the pixel position (relative to the editor container) and dimensions of a selection at a given location. The user's current selection need not be at that index. Useful for calculating where to place tooltips. **Methods** getBounds(index: number, length: number = 0): { left: number, top: number, height: number, width: number } **Examples** quill.setText('Hello\nWorld\n');quill.getBounds(7); // Returns { height: 15, width: 0, left: 27, top: 31 } ### [](https://quilljs.com/docs/api#getselection) getSelection Retrieves the user's selection range, optionally to focus the editor first. Otherwise `null` may be returned if editor does not have focus. **Methods** getSelection(focus = false): { index: number, length: number } **Examples** const range = quill.getSelection();if (range) { if (range.length == 0) { console.log('User cursor is at index', range.index); } else { const text = quill.getText(range.index, range.length); console.log('User has highlighted: ', text); }} else { console.log('User cursor is not in editor');} ### [](https://quilljs.com/docs/api#setselection) setSelection Sets user selection to given range, which will also focus the editor. Providing `null` as the selection range will blur the editor. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. **Methods** setSelection(index: number, length: number = 0, source: string = 'api')setSelection(range: { index: number, length: number }, source: string = 'api') **Examples** quill.setSelection(0, 5); ### [](https://quilljs.com/docs/api#scrollselectionintoview) scrollSelectionIntoView Scroll the current selection into the visible area. If the selection is already visible, no scrolling will occur. Note Quill calls this method automatically when [setSelection](https://quilljs.com/docs/api#setselection) is called, unless the source is `"silent"`. **Methods** scrollSelectionIntoView(); **Examples** quill.scrollSelectionIntoView(); [](https://quilljs.com/docs/api#editor) Editor ---------------------------------------------- ### [](https://quilljs.com/docs/api#blur) blur Removes focus from the editor. **Methods** blur(); **Examples** quill.blur(); ### [](https://quilljs.com/docs/api#disable) disable Shorthand for [`enable(false)`](https://quilljs.com/docs/api#enable) . ### [](https://quilljs.com/docs/api#enable) enable Set ability for user to edit, via input devices like the mouse or keyboard. Does not affect capabilities of API calls, when the `source` is `"api"` or `"silent"`. **Methods** enable(enabled: boolean = true); **Examples** quill.enable();quill.enable(false); // Disables user input ### [](https://quilljs.com/docs/api#focus) focus Focuses the editor and restores its last range. **Methods** focus(options: { preventScroll?: boolean } = {}); **Examples** // Focus the editor, and scroll the selection into viewquill.focus(); // Focus the editor, but don't scrollquill.focus({ preventScroll: true }); ### [](https://quilljs.com/docs/api#hasfocus) hasFocus Checks if editor has focus. Note focus on toolbar, tooltips, does not count as the editor. **Methods** hasFocus(): boolean **Examples** quill.hasFocus(); ### [](https://quilljs.com/docs/api#update) update Synchronously check editor for user updates and fires events, if changes have occurred. Useful for collaborative use cases during conflict resolution requiring the latest up to date state. [Source](https://quilljs.com/docs/api#events) may be `"user"`, `"api"`, or `"silent"`. **Methods** update(((source: string) = 'user')); **Examples** quill.update(); ### [](https://quilljs.com/docs/api#scrollrectintoview-experimental) scrollRectIntoViewexperimental Scrolls the editor to the given pixel position. [`scrollSelectionIntoView`](https://quilljs.com/docs/api#scrollselectionintoview) is implemented by calling this method with the bounds of the current selection. scrollRectIntoView(bounds: { top: number; right: number; bottom: number; left: number;}); **Example 1** // Scroll the editor to reveal the range of { index: 20, length: 5 }const bounds = this.selection.getBounds(20, 5);if (bounds) { quill.scrollRectIntoView(bounds);} **Example 2** let text = ""; for (let i = 0; i < 100; i += 1) { text += \`line ${i + 1}\\n\`; } const quill = new Quill('#editor', { theme: 'snow' }); quill.setText(text); const target = 'line 50'; const bounds = quill.selection.getBounds( text.indexOf(target), target.length ); if (bounds) { quill.scrollRectIntoView(bounds); } Run Code [](https://quilljs.com/docs/api#events) Events ---------------------------------------------- ### [](https://quilljs.com/docs/api#text-change) text-change Emitted when the contents of Quill have changed. Details of the change, representation of the editor contents before the change, along with the source of the change are provided. The source will be `"user"` if it originates from the users. For example: * User types into the editor * User formats text using the toolbar * User uses a hotkey to undo * User uses OS spelling correction Changes may occur through an API but as long as they originate from the user, the provided source should still be `"user"`. For example, when a user clicks on the toolbar, technically the toolbar module calls a Quill API to effect the change. But source is still `"user"` since the origin of the change was the user's click. APIs causing text to change may also be called with a `"silent"` source, in which case `text-change` will not be emitted. This is not recommended as it will likely break the undo stack and other functions that rely on a full record of text changes. Changes to text may cause changes to the selection (ex. typing advances the cursor), however during the `text-change` handler, the selection is not yet updated, and native browser behavior may place it in an inconsistent state. Use [`selection-change`](https://quilljs.com/docs/api#selection-change) or [`editor-change`](https://quilljs.com/docs/api#editor-change) for reliable selection updates. **Callback Signature** handler(delta: Delta, oldContents: Delta, source: string) **Examples** quill.on('text-change', (delta, oldDelta, source) => { if (source == 'api') { console.log('An API call triggered this change.'); } else if (source == 'user') { console.log('A user action triggered this change.'); }}); ### [](https://quilljs.com/docs/api#selection-change) selection-change Emitted when a user or API causes the selection to change, with a range representing the selection boundaries. A null range indicates selection loss (usually caused by loss of focus from the editor). You can also use this event as a focus change event by just checking if the emitted range is null or not. APIs causing the selection to change may also be called with a `"silent"` source, in which case `selection-change` will not be emitted. This is useful if `selection-change` is a side effect. For example, typing causes the selection to change but would be very noisy to also emit a `selection-change` event on every character. **Callback Signature** handler(range: { index: number, length: number }, oldRange: { index: number, length: number }, source: string) **Examples** quill.on('selection-change', (range, oldRange, source) => { if (range) { if (range.length == 0) { console.log('User cursor is on', range.index); } else { const text = quill.getText(range.index, range.length); console.log('User has highlighted', text); } } else { console.log('Cursor not in the editor'); }}); ### [](https://quilljs.com/docs/api#editor-change) editor-change Emitted when either `text-change` or `selection-change` would be emitted, even when the source is `"silent"`. The first parameter is the event name, either `text-change` or `selection-change`, followed by the arguments normally passed to those respective handlers. **Callback Signature** handler(name: string, ...args) **Examples** quill.on('editor-change', (eventName, ...args) => { if (eventName === 'text-change') { // args[0] will be delta } else if (eventName === 'selection-change') { // args[0] will be old range }}); ### [](https://quilljs.com/docs/api#on) on Adds event handler. See [text-change](https://quilljs.com/docs/api#text-change) or [selection-change](https://quilljs.com/docs/api#selection-change) for more details on the events themselves. **Methods** on(name: string, handler: Function): Quill **Examples** quill.on('text-change', () => { console.log('Text change!');}); ### [](https://quilljs.com/docs/api#once) once Adds handler for one emission of an event. See [text-change](https://quilljs.com/docs/api#text-change) or [selection-change](https://quilljs.com/docs/api#selection-change) for more details on the events themselves. **Methods** once(name: string, handler: Function): Quill **Examples** quill.once('text-change', () => { console.log('First text change!');}); ### [](https://quilljs.com/docs/api#off) off Removes event handler. **Methods** off(name: string, handler: Function): Quill **Examples** function handler() { console.log('Hello!');} quill.on('text-change', handler);quill.off('text-change', handler); [](https://quilljs.com/docs/api#model) Model -------------------------------------------- ### [](https://quilljs.com/docs/api#find) find Static method returning the Quill or [Blot](https://github.com/quilljs/parchment) instance for the given DOM node. In the latter case, passing in true for the `bubble` parameter will search up the given DOM's ancestors until it finds a corresponding [Blot](https://github.com/quilljs/parchment) . **Methods** Quill.find(domNode: Node, bubble: boolean = false): Blot | Quill **Examples** const container = document.querySelector('#container');const quill = new Quill(container);console.log(Quill.find(container) === quill); // Should be true quill.insertText(0, 'Hello', 'link', 'https://world.com');const linkNode = document.querySelector('#container a');const linkBlot = Quill.find(linkNode); // Find Quill instance from a blotconsole.log(Quill.find(linkBlot.scroll.domNode.parentElement)); ### [](https://quilljs.com/docs/api#getindex) getIndex Returns the distance between the beginning of document to the occurrence of the given [Blot](https://github.com/quilljs/parchment) . **Methods** getIndex(blot: Blot): number **Examples** let [line, offset] = quill.getLine(10);let index = quill.getIndex(line); // index + offset should == 10 ### [](https://quilljs.com/docs/api#getleaf) getLeaf Returns the leaf [Blot](https://github.com/quilljs/parchment) at the specified index within the document. **Methods** getLeaf(index: number): [LeafBlot | null, number] **Examples** quill.setText('Hello Good World!');quill.formatText(6, 4, 'bold', true); let [leaf, offset] = quill.getLeaf(7);// leaf should be a Text Blot with value "Good"// offset should be 1, since the returned leaf started at index 6 ### [](https://quilljs.com/docs/api#getline) getLine Returns the line [Blot](https://github.com/quilljs/parchment) at the specified index within the document. **Methods** getLine(index: number): [Block | BlockEmbed | null, number] **Examples** quill.setText('Hello\nWorld!'); let [line, offset] = quill.getLine(7);// line should be a Block Blot representing the 2nd "World!" line// offset should be 1, since the returned line started at index 6 ### [](https://quilljs.com/docs/api#getlines) getLines Returns the lines contained within the specified location. **Methods** getLines(index: number = 0, length: number = remaining): (Block | BlockEmbed)[]getLines(range: Range): (Block | BlockEmbed)[] **Examples** quill.setText('Hello\nGood\nWorld!');quill.formatLine(1, 1, 'list', 'bullet'); let lines = quill.getLines(2, 5);// array with a ListItem and Block Blot,// representing the first two lines [](https://quilljs.com/docs/api#extension) Extension ---------------------------------------------------- ### [](https://quilljs.com/docs/api#debug) debug Static method enabling logging messages at a given level: `'error'`, `'warn'`, `'log'`, or `'info'`. Passing `true` is equivalent to passing `'log'`. Passing `false` disables all messages. **Methods** Quill.debug(level: string | boolean) **Examples** Quill.debug('info'); ### [](https://quilljs.com/docs/api#import) import Static method returning Quill library, format, module, or theme. In general the path should map exactly to Quill source code directory structure. Unless stated otherwise, modification of returned entities may break required Quill functionality and is strongly discouraged. **Methods** Quill.import(path): any **Examples** const Parchment = Quill.import('parchment');const Delta = Quill.import('delta'); const Toolbar = Quill.import('modules/toolbar');const Link = Quill.import('formats/link');// Similar to ES6 syntax `import Link from 'quill/formats/link';` Note Don't confuse this with the [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) keyword for ECMAScript modules. `Quill.import()` doesn't load scripts over the network, it just returns the corresponding module from the Quill library without causing any side-effects. ### [](https://quilljs.com/docs/api#register) register Registers a module, theme, or format(s), making them available to be added to an editor. Can later be retrieved with [`Quill.import`](https://quilljs.com/docs/api#import) . Use the path prefix of `'formats/'`, `'modules/'`, or `'themes/'` for registering formats, modules or themes, respectively. For formats specifically there is a shorthand to just pass in the format directly and the path will be autogenerated. Will overwrite existing definitions with the same path. **Methods** Quill.register(format: Attributor | BlotDefinintion, supressWarning: boolean = false)Quill.register(path: string, def: any, supressWarning: boolean = false)Quill.register(defs: { [path: string]: any }, supressWarning: boolean = false) **Examples** const Module = Quill.import('core/module'); class CustomModule extends Module {} Quill.register('modules/custom-module', CustomModule); Quill.register({ 'formats/custom-format': CustomFormat, 'modules/custom-module-a': CustomModuleA, 'modules/custom-module-b': CustomModuleB,}); Quill.register(CustomFormat);// You cannot do Quill.register(CustomModuleA); as CustomModuleA is not a format ### [](https://quilljs.com/docs/api#addcontainer) addContainer Adds and returns a container element inside the Quill container, sibling to the editor itself. By convention, Quill modules should have a class name prefixed with `ql-`. Optionally include a refNode where container should be inserted before. **Methods** addContainer(className: string, refNode?: Node): ElementaddContainer(domNode: Node, refNode?: Node): Element **Examples** const container = quill.addContainer('ql-custom'); ### [](https://quilljs.com/docs/api#getmodule) getModule Retrieves a module that has been added to the editor. **Methods** getModule(name: string): any **Examples** const toolbar = quill.getModule('toolbar'); * * * An Open Source Project ---------------------- Quill is developed and maintained by [Slab](https://slab.com/) . It is permissively licensed under BSD. Use it freely in personal or commercial projects! [Star](https://github.com/slab/quill/ "Star Quill on GitHub") [37,622](https://github.com/slab/quill/stargazers "Quill Stargazers") --- # History Module - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationHistory Module [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/modules/history.mdx "Edit on GitHub") History Module ============== The History module is responsible for handling undo and redo for Quill. It can be configured with the following options: [](https://quilljs.com/docs/modules/history#configuration) Configuration ------------------------------------------------------------------------ #### [](https://quilljs.com/docs/modules/history#delay) delay * Default: `1000` Changes occuring within the `delay` number of milliseconds are merged into a single change. For example, with delay set to `0`, nearly every character is recorded as one change and so undo would undo one character at a time. With delay set to `1000`, undo would undo all changes that occured within the last 1000 milliseconds. #### [](https://quilljs.com/docs/modules/history#maxstack) maxStack * Default: `100` Maximum size of the history's undo/redo stack. Merged changes with the `delay` option counts as a singular change. #### [](https://quilljs.com/docs/modules/history#useronly) userOnly * Default: `false` By default all changes, whether originating from user input or programmatically through the API, are treated the same and change be undone or redone by the history module. If `userOnly` is set to `true`, only user changes will be undone or redone. ### [](https://quilljs.com/docs/modules/history#example) Example const quill = new Quill('#editor', { modules: { history: { delay: 2000, maxStack: 500, userOnly: true }, }, theme: 'snow'}); [](https://quilljs.com/docs/modules/history#api) API ---------------------------------------------------- #### [](https://quilljs.com/docs/modules/history#clear) clear Clears the history stack. **Methods** clear() **Examples** quill.history.clear(); #### [](https://quilljs.com/docs/modules/history#cutoff) cutoff Normally changes made in short succession (configured by `delay`) are merged as a single change, so that triggering an undo will undo multiple changes. Using `cutoff()` will reset the merger window so that a changes before and after `cutoff()` is called will not be merged. **Methods** cutoff() **Examples** quill.history.cutoff(); #### [](https://quilljs.com/docs/modules/history#undo) undo Undo last change. **Methods** undo() **Examples** quill.history.undo(); #### [](https://quilljs.com/docs/modules/history#redo) redo If last change was an undo, redo this undo. Otherwise does nothing. **Methods** redo() **Examples** quill.history.redo(); * * * An Open Source Project ---------------------- Quill is developed and maintained by [Slab](https://slab.com/) . It is permissively licensed under BSD. Use it freely in personal or commercial projects! [Star](https://github.com/slab/quill/ "Star Quill on GitHub") [37,622](https://github.com/slab/quill/stargazers "Quill Stargazers") --- # Installation - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationInstallation [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/installation.mdx "Edit on GitHub") Installation ============ Quill comes ready to use in several convenient forms. [](https://quilljs.com/docs/installation#cdn) CDN ------------------------------------------------- A globally distributed and available CDN is provided, backed by [jsDelivr](https://www.jsdelivr.com/) . This is the most convenient way to get started with Quill, and requires no build steps or package managers. ### [](https://quilljs.com/docs/installation#full-build) Full Build For most users, the full build is the easiest way to get started with Quill. It include the core Quill library, as well as common themes, formats, and modules. To import the full build, you will need to include the "quill.js" script and the stylesheet for the theme you wish to use. [](https://quilljs.com/docs/customization/themes#bubble) Bubble --------------------------------------------------------------- Bubble is a simple tooltip based theme. Show Code [Standalone](https://quilljs.com/standalone/bubble/) [](https://quilljs.com/docs/customization/themes#snow) Snow ----------------------------------------------------------- Snow is a clean, flat toolbar theme. Show Code [Standalone](https://quilljs.com/standalone/snow/) ### [](https://quilljs.com/docs/customization/themes#customization) Customization Themes primarily control the visual look of Quill through its CSS stylesheet, and many changes can easily be made by overriding these rules. This is easiest to do, as with any other web application, by simply using your browser developer console to inspect the elements to view the rules affecting them. Many other customizations can be done through the respective modules. For example, the toolbar is perhaps the most visible user interface, but much of the customization is done through the [Toolbar module](https://quilljs.com/docs/modules/toolbar) . * * * An Open Source Project ---------------------- Quill is developed and maintained by [Slab](https://slab.com/) . It is permissively licensed under BSD. Use it freely in personal or commercial projects! [Star](https://github.com/slab/quill/ "Star Quill on GitHub") [37,622](https://github.com/slab/quill/stargazers "Quill Stargazers") --- # Modules - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationModules [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/modules.mdx "Edit on GitHub") Modules ======= Modules allow Quill's behavior and functionality to be customized. Several officially supported modules are available to pick and choose from, some with additional configuration options and APIs. Refer to their respective documentation pages for more details. To enable a module, simply include it in Quill's configuration. const quill = new Quill('#editor', { modules: { history: { // Enable with custom configurations delay: 2500, userOnly: true }, syntax: true // Enable with default configuration }}); The [Clipboard](https://quilljs.com/docs/modules/clipboard) , [Keyboard](https://quilljs.com/docs/modules/keyboard) , and [History](https://quilljs.com/docs/modules/history) modules are required by Quill and do not need to be included explictly, but may be configured like any other module. [](https://quilljs.com/docs/modules#extending) Extending -------------------------------------------------------- Modules may also be extended and re-registered, replacing the original module. Even required modules may be re-registered and replaced. const Clipboard = Quill.import('modules/clipboard');const Delta = Quill.import('delta'); class PlainClipboard extends Clipboard { convert(html = null) { if (typeof html === 'string') { this.container.innerHTML = html; } let text = this.container.innerText; this.container.innerHTML = ''; return new Delta().insert(text); }} Quill.register('modules/clipboard', PlainClipboard, true); // Will be created with instance of PlainClipboardconst quill = new Quill('#editor'); Note This particular example was selected to show what is possible. It is often easier to just use an API or configuration the existing module exposes. In this example, the existing Clipboard's [addMatcher](https://quilljs.com/docs/modules/clipboard#addmatcher) API is suitable for most paste customization scenarios. * * * An Open Source Project ---------------------- Quill is developed and maintained by [Slab](https://slab.com/) . It is permissively licensed under BSD. Use it freely in personal or commercial projects! [Star](https://github.com/slab/quill/ "Star Quill on GitHub") [37,622](https://github.com/slab/quill/stargazers "Quill Stargazers") --- # Registries - Quill Rich Text Editor Document Navigation * [Quickstart](https://quilljs.com/docs/quickstart) * [Why Quill](https://quilljs.com/docs/why-quill) * [Installation](https://quilljs.com/docs/installation) * [Upgrading to 2.0](https://quilljs.com/docs/upgrading-to-2-0) * [Configuration](https://quilljs.com/docs/configuration) * [Formats](https://quilljs.com/docs/formats) * [API](https://quilljs.com/docs/api) * [Content](https://quilljs.com/docs/api#content) * [Formatting](https://quilljs.com/docs/api#formatting) * [Selection](https://quilljs.com/docs/api#selection) * [Editor](https://quilljs.com/docs/api#editor) * [Events](https://quilljs.com/docs/api#events) * [Model](https://quilljs.com/docs/api#model) * [Extension](https://quilljs.com/docs/api#extension) * [Delta](https://quilljs.com/docs/delta) * [Modules](https://quilljs.com/docs/modules) * [Toolbar](https://quilljs.com/docs/modules/toolbar) * [Keyboard](https://quilljs.com/docs/modules/keyboard) * [History](https://quilljs.com/docs/modules/history) * [Clipboard](https://quilljs.com/docs/modules/clipboard) * [Syntax](https://quilljs.com/docs/modules/syntax) * [Customization](https://quilljs.com/docs/customization) * [Themes](https://quilljs.com/docs/customization/themes) * [Registries](https://quilljs.com/docs/customization/registries) * [Guides](https://quilljs.com/docs/guides/designing-the-delta-format) * [Designing the Delta Format](https://quilljs.com/docs/guides/designing-the-delta-format) * [Building a Custom Module](https://quilljs.com/docs/guides/building-a-custom-module) * [Cloning Medium with Parchment](https://quilljs.com/docs/guides/cloning-medium-with-parchment) DocumentationRegistries [Edit page on GitHub ↗](https://github.com/slab/quill/tree/main/packages/website/content/docs/customization/registries.mdx "Edit on GitHub") Registries ========== Registries allow multiple editors with different formats to coexist on the same page. If you register a format with `Quill.register()`, the format will be registered to a global registry, which will be used by all Quill instances. However, in some cases, you might want to have multiple registries, so that different Quill instances can have different formats. For example, you might want to have a Quill instance that only supports bold and italic, and another Quill instance that supports bold, italic, and underline. [](https://quilljs.com/docs/customization/registries#usage) Usage ----------------------------------------------------------------- To create a Quill with a custom registry, you can pass in a registry object to the Quill constructor: const registry = new Parchment.Registry(); // Register the formats that you need for the editor with `registry.register()`.// We will cover this in more detail in the next section. const quill = new Quill('#editor', { registry, // ...other options}) [](https://quilljs.com/docs/customization/registries#register-formats) Register Formats --------------------------------------------------------------------------------------- A custom registry doesn't come with any formats by default. You should register the formats that you need with `registry.register()`. There are some essential formats that you will need to register in order to have a functional editor: index.htmlindex.js