Jesse A. Green / notebook

Quill — Administrator & Architecture Guide

Generated June 2026 from slab/quill at 539cbff

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the in‑depth technical reference for Quill 2.0.3: its architecture, internal model, module system, build and release pipeline, security considerations, and code‑level internals. It is written for developers integrating Quill at scale, architects evaluating it, and contributors working on the codebase itself.

Quill is not a deployed service — it is a browser library published to npm and a CDN, accompanied by a documentation website. "Operations" here therefore means building, testing, releasing, and embedding the library safely, rather than running a server.

Note

For day‑to‑day integration usage — installation, configuration options, the editor API, and recipes — see the companion User Guide. This guide assumes that material and goes deeper into how Quill works and how to operate it as a dependency.


1. Executive Summary

Quill is a modular, API‑driven rich text editor built on a structured document model rather than on contenteditable HTML soup. Three ideas define its architecture:

  1. The document is a Delta. Content is a JSON op list (quill-delta), not HTML. This makes content lossless, diff‑able, transformable, and collaboration‑friendly.
  2. The DOM is a tree of blots. Quill renders through Parchment, a document model that maps document nodes ("blots") to DOM nodes. Formats are blots or attributors registered in a shared registry.
  3. Everything else is a module. The toolbar, keyboard handling, history, clipboard, uploader, tables, and syntax highlighting are all swappable modules layered onto a small core.
Property Value
Version 2.0.3
License BSD‑3‑Clause
Language TypeScript (compiled to ES modules)
Runtime Browser (DOM)
Core dependencies parchment ^3.0.0, quill-delta ^5.1.0, eventemitter3 ^5.0.1, lodash-es ^4.17.21
Repository layout npm‑workspaces monorepo (packages/quill, packages/website)
Build webpack (library), Next.js (website)
Tests Vitest (unit + fuzz), Playwright (e2e)
Distribution npm (quill) + jsDelivr CDN

Important

The GitHub issue tracker for this snapshot shows active community concern about maintenance cadence and at least one open security advisory (CVE‑2025‑15056 / GHSA‑v3m3‑f69x‑jf25). Treat Quill as stable and widely deployed, but factor maintenance responsiveness and your own paste‑sanitization strategy into adoption decisions. See Security.


2. Architecture

2.1 High‑level component map

                         ┌──────────────────────────────────────┐
                         │              Quill (core)            │
                         │  public API · option expansion ·     │
                         │  static registry / import / register │
                         └───────────────┬──────────────────────┘
                                         │ orchestrates
   ┌──────────────┬───────────────┬──────┴───────┬──────────────┬───────────────┐
   ▼              ▼               ▼              ▼              ▼               ▼
┌────────┐   ┌─────────┐    ┌──────────┐   ┌───────────┐  ┌────────┐    ┌──────────┐
│ Editor │   │Selection│    │Composition│  │  Emitter  │  │ Theme  │    │ Modules  │
│ Delta  │   │ native  │    │  IME /    │  │ event bus │  │ snow / │    │ toolbar  │
│ sync   │   │ range   │    │ compose   │  │(eventemit-│  │ bubble │    │ keyboard │
│        │   │ bridge  │    │  events   │  │  ter3)    │  │ /core  │    │ history… │
└───┬────┘   └────┬────┘    └─────┬─────┘  └─────┬─────┘  └────────┘    └──────────┘
    │             │               │              │
    ▼             ▼               ▼              ▼
┌──────────────────────────────────────────────────────────┐
│                    Scroll (Parchment ScrollBlot)          │
│   the root blot — a tree of block/inline/embed/text blots │
│   mapped onto the contenteditable DOM (.ql-editor)        │
└──────────────────────────────────────────────────────────┘
                              │ renders
                              ▼
                ┌──────────────────────────────┐
                │  contenteditable DOM (.ql-…)  │
                └──────────────────────────────┘

2.2 The core objects

The Quill constructor wires up a fixed set of collaborators (packages/quill/src/core/quill.ts):

Object Source Responsibility
Scroll Parchment ScrollBlot (blots/scroll.ts) The root blot. Owns the blot tree and the editor's root DOM node (.ql-editor). All structural mutations flow through it.
Editor core/editor.ts The bridge between Deltas and the blot tree. Translates applyDelta, insertText, formatLine, etc. into Scroll operations, and keeps a canonical delta in sync via update().
Selection core/selection.ts Bridges the browser's native Selection/Range to Quill Range ({index, length}) objects, handling focus, bounds, and cursor restoration across mutations.
Composition core/composition.ts Manages IME composition (compositionstart/compositionend), batching DOM changes so multi‑keystroke input (CJK, accents) commits atomically.
Emitter core/emitter.ts The event bus (extends eventemitter3). Owns the event/source name constants and dispatches DOM events to the right instance.
Theme core/theme.ts + themes/* Builds the toolbar/tooltip UI and decides which modules are added.
Modules modules/* Feature units (toolbar, keyboard, history, clipboard, uploader, syntax, table…).

2.3 Construction sequence

When you call new Quill(container, options):

  1. expandConfig() resolves the container selector, picks the theme constructor, merges Quill defaults + theme defaults + your options + per‑module defaults, and resolves the registry (custom registry > formats filter > shared global).
  2. The container is cleared, marked .ql-container, and registered in a global WeakMap (core/instances.ts) keyed by DOM node.
  3. A .ql-editor root is created and the Scroll blot is instantiated from the registry.
  4. Editor, Selection, and Composition are constructed around the Scroll.
  5. The theme is instantiated; it adds the default modules — keyboard, clipboard, history, uploader, plus input and uiNode — and any theme‑specific modules, then runs theme.init().
  6. Event wiring connects Scroll updates back into the Editor's Delta sync and toggles the .ql-blank class.
  7. If the container had initial HTML, it is converted through the clipboard and set as the initial contents; history is cleared; placeholder/readOnly are applied.

Note

The shared globalRegistry (a Parchment.Registry) is created once at module load. Because it is shared across all editor instances by default, registering a format with Quill.register affects every editor on the page unless you pass a per‑instance registry.

2.4 The Delta synchronization loop

The heart of Quill is keeping a canonical Delta in lockstep with a contenteditable DOM that the user (and the browser) mutate unpredictably.

user types / pastes / IME      API call (insertText, format, …)
        │                                │
        ▼                                ▼
  DOM mutation                    Editor.<method>()
        │                                │
   MutationObserver                 Scroll mutation
        │                                │
        ▼                                ▼
  Scroll.update() ──────► Emitter SCROLL_UPDATE ──► Editor.update()
        │                                                  │
        ▼                                                  ▼
  diff old vs. new Delta  ◄──────────────────────  new canonical delta
        │
        ▼
  TEXT_CHANGE (change, oldContents, source)  ──► your handlers

Editor.update() is the reconciliation point. It recomputes the document Delta from the blot tree, diffs it against the previous Delta, and emits the change. A fast path optimizes single‑character ASCII edits to avoid a full re‑diff.


3. The Document Model (Parchment & Delta)

3.1 Blots

Quill's content tree is made of blots (from Parchment). Each blot wraps a DOM node and declares a blotName, a tagName, and an optional className. Quill defines these core blots in packages/quill/src/blots/:

Blot blotName DOM Role
Scroll scroll DIV.ql-editor Root container; the editing surface.
Block block P A block‑level line.
BlockEmbed (block embed) varies A block‑level embed (e.g. video).
Break break BR Empty‑line placeholder.
Inline inline SPAN Base for inline formats.
Cursor cursor SPAN.ql-cursor Zero‑width cursor anchor.
Embed — varies Base for inline embeds.
Text text text node Raw text leaf.
Container container — Structural grouping (e.g. list/table containers).

3.2 Formats

Formats are blots or attributors registered under formats/{name}. Quill ships these in packages/quill/src/formats/:

Category Formats (blotName → tag)
Inline marks bold→STRONG/B, italic→EM/I, underline→U, strike→S/STRIKE, code→CODE, script→SUB/SUP
Inline attributes color, background, font, size, link→A
Block / line header→H1…H6, blockquote→BLOCKQUOTE, code-block→DIV.ql-code-block, list→LI (+list-container→OL), align, indent, direction
Embeds image→IMG, video→IFRAME.ql-video, formula→SPAN.ql-formula, table→TD (+table-row/table-body/table-container)

Formats come in three implementation shapes:

  • Blot formats (e.g. bold, link, header) wrap content in a DOM element.
  • Class attributors apply ql-{format}-{value} classes (used for things like alignment when class‑based).
  • Style attributors apply inline CSS (e.g. color, background, size, font have style variants used during paste normalization).

Tip

Registering a format via Quill.register(BlotOrAttributor) infers the name from blotName/attrName and adds it under formats/{name}. Anything registered under blots/ or formats/ is also pushed into the global Parchment registry so the Scroll can build it.

3.3 Delta

quill-delta (re‑exported as Quill.import('delta')) provides the Delta class with insert/retain/delete ops, plus compose, diff, transform, and invert. These operations are what make:

  • History work — undo entries are inverse Deltas (record() stores changeDelta.invert(oldDelta)).
  • Collaboration possible — transform is operational transformation, letting concurrent edits be rebased.
  • Tables/embeds composable — embed handlers (tableEmbed.ts) register custom compose/transform/invert logic with Delta.

4. The Module System

4.1 The Module base class

All modules extend the tiny base in core/module.ts:

abstract class Module<T extends {} = {}> {
  static DEFAULTS = {};
  constructor(public quill: Quill, protected options: Partial<T> = {}) {}
}

A module receives its host Quill instance and merged options. It wires up its behavior in the constructor (event listeners, key bindings, DOM hooks). Modules are added by the theme via theme.addModule(name), which looks the module class up from the registry (modules/{name}), merges Module.DEFAULTS with user options, and constructs it.

4.2 Built‑in modules and their defaults

Module Source DEFAULTS (key facts)
clipboard modules/clipboard.ts matchers: [] — user matchers append to a built‑in matcher list covering text, breaks, lists, code, tables, Word/Docs normalization.
keyboard modules/keyboard.ts Binds Enter, Backspace/Delete (platform‑specific), and arrow/UI‑node navigation. shortKey resolves to metaKey on macOS, ctrlKey elsewhere.
history modules/history.ts delay: 1000, maxStack: 100, userOnly: false. Binds undo/redo shortcuts and beforeinput history events.
uploader modules/uploader.ts mimetypes: ['image/png','image/jpeg']; default handler reads files as data URLs and inserts image embeds.
toolbar modules/toolbar.ts container: null plus handlers for clean, direction, indent, link, list. Builds toolbar DOM from array config or binds to existing controls by ql-{format} class.
syntax modules/syntax.ts hljs: window.hljs, interval: 1000, and a 14‑language picker list. Requires highlight.js.
table modules/table.ts Registers table blots; exposes insert/delete row/column/table operations and auto‑balances cells.
tableEmbed modules/tableEmbed.ts Registers a table-embed Delta embed handler (compose/transform/invert) for OT‑safe tables.
input modules/input.ts Normalizes beforeinput insert/replace events and IME start, replacing selected ranges consistently.
uiNode modules/uiNode.ts Handles caret movement around UI nodes (e.g. list/code‑block selectors), including RTL and Ctrl+A on macOS.

4.3 Themes as module orchestrators

Themes (themes/snow.ts, themes/bubble.ts, base themes/base.ts) extend BaseTheme. Each:

  • Supplies a default toolbar config if the toolbar module is enabled without a container.
  • Builds toolbar buttons and pickers with the SVG icon set (ui/icons.ts, ui/picker.ts, ui/color-picker.ts, ui/icon-picker.ts).
  • Wires a tooltip (ui/tooltip.ts) for link editing (snow) or selection‑anchored formatting (bubble).
  • Adds a theme‑specific link handler (snow shows an inline edit tooltip; bubble opens the tooltip editor).
snow default toolbar:   [header 1/2/3] · [bold italic underline link] · [list ordered/bullet] · [clean]
bubble default toolbar: [bold italic link] · [header 1, header 2, blockquote]

5. Repository Structure

quill/                              (monorepo root — npm workspaces)
├── package.json                    workspace config; build/start/lint scripts
├── tsconfig.json
├── packages/
│   ├── quill/                      THE LIBRARY (published as `quill`)
│   │   ├── package.json            deps, webpack/vitest/playwright scripts
│   │   ├── webpack.config.cjs      build configuration
│   │   ├── webpack.common.cjs
│   │   ├── babel.config.cjs        preset-env + preset-typescript
│   │   ├── playwright.config.ts    e2e config
│   │   ├── scripts/build           build entry (`./scripts/build production`)
│   │   └── src/
│   │       ├── core.ts             full build entry (registers all formats/modules)
│   │       ├── quill.ts            re-export of core/quill
│   │       ├── core/               quill, editor, selection, emitter, composition,
│   │       │                       theme, module, logger, instances, utils/
│   │       ├── blots/              block, inline, text, break, cursor, embed,
│   │       │                       container, scroll
│   │       ├── formats/            21 format definitions
│   │       ├── modules/            clipboard, keyboard, history, toolbar, syntax,
│   │       │                       table, tableEmbed, uploader, input, uiNode,
│   │       │                       normalizeExternalHTML/
│   │       ├── themes/             base, snow, bubble
│   │       ├── ui/                 picker, color-picker, icon-picker, icons, tooltip
│   │       └── assets/             *.styl stylesheets + SVG icons
│   │       └── test/               unit/ (vitest), fuzz/ (vitest), e2e/ (playwright)
│   └── website/                    DOCS SITE (private, Next.js + MDX)
│       ├── next.config.mjs
│       ├── env.js
│       ├── content/                docs/*.mdx, blog/*.mdx, guides/*.mdx
│       └── src/                    pages/, components/, playground/, data/, svg/
└── scripts/                        changelog.mjs, release.js, utils/configGit.mjs

5.1 Build entries

  • Full build (src/core.ts) imports and registers every standard format and module, plus both themes. This is what import 'quill' resolves to.
  • Core build (quill/core) provides only the editor core; consumers register what they need.

Versioning is injected at build time: Quill.version reads a QUILL_VERSION global defined by babel-plugin-transform-define, falling back to 'dev'.


6. Building, Testing & Releasing

6.1 Prerequisites

Requirement Value
Node.js A version compatible with the toolchain (webpack 5, Next.js 14, TypeScript 5.4).
npm >= 8.2.3 (enforced via engineStrict).
Workspaces The repo uses npm workspaces (packages/*); run install at the root.
npm install            # install all workspace deps from the repo root

6.2 Development servers

Command Effect
npm start Runs both the library dev server (webpack‑dev‑server, port 9080) and the website (Next.js, port 9000) in parallel.
npm run start:quill Library dev server only.
npm run start:website Website only, with NEXT_PUBLIC_LOCAL_QUILL=true so the site uses the local Quill build.

6.3 Building

Command Effect
npm run build Builds both packages in parallel.
npm run build:quill Builds the library (./scripts/build production → webpack → dist/).
npm run build:website Builds the docs site (next build).

The library build emits dist/quill.js, dist/quill.core.js, and the stylesheets quill.core.css, quill.snow.css, quill.bubble.css (compiled from the Stylus .styl assets), plus source maps.

6.4 Testing

Command Framework Scope
npm test (in packages/quill) runs all suites in sequence unit → fuzz → e2e
test:unit Vitest (@vitest/browser) Core, blots, formats, modules unit tests.
test:fuzz Vitest Randomized editor and tableEmbed operation fuzzing — validates Delta compose/transform invariants.
test:e2e Playwright Full browser interaction tests (typing, history, lists, selection replacement).

Tip

The fuzz suite is the strongest correctness signal for the Delta/OT logic — it generates random operation sequences and checks that compose/transform/invert hold. Run it after any change to editor.ts, history.ts, or tableEmbed.ts.

6.5 Linting

npm run lint runs across all workspaces. The library lints with ESLint (TypeScript, import resolution, prettier, jsx‑a11y, require‑extensions) and tsc --noEmit for type checking. Prettier is configured for single quotes.

6.6 Release

Release tooling lives in scripts/:

Script Purpose
scripts/release.js Drives the package release process.
scripts/changelog.mjs Generates the changelog.
scripts/utils/configGit.mjs Git configuration helper used during release.

The published artifact is the quill package (packages/quill), with main: quill.js, type module. The website is private ("private": true) and not published to npm — it is deployed separately as the documentation site at quilljs.com.

Important

The CDN (jsDelivr) serves the published npm package directly. Releasing a new version to npm makes it available at https://cdn.jsdelivr.net/npm/quill@<version>/dist/.... There is no separate CDN upload step — CDN currency is a function of the npm release.


7. Security Analysis

Quill edits a contenteditable surface and imports external HTML on paste, which puts it on the XSS attack surface of any application that embeds it. Understand the boundaries before deploying.

7.1 Trust boundaries

Boundary Concern
Paste / drop input Arbitrary HTML from the clipboard (including from other apps) is parsed and normalized. Quill converts it to a Delta through matchers, which discards most active content, but integrators must not assume the result is a sanitizer for arbitrary attacker HTML.
dangerouslyPasteHTML Explicitly named to flag risk: it inserts HTML through clipboard conversion. Never feed it unsanitized, untrusted strings.
Stored Delta → rendered HTML If you persist Deltas and later render getSemanticHTML() (or your own renderer) into a page, the rendering site is responsible for output encoding/sanitization, especially for link, image, and video (URL/href/src) values.
Embeds (link, image, video) URL‑bearing formats. Validate/allow‑list schemes (e.g. reject javascript:) at your application layer; Quill does not guarantee scheme filtering for every path.

7.2 What Quill does and does not do

  • Does: parse paste HTML in a detached DOMParser document, strip to a structured Delta via the matcher pipeline, normalize Word/Google‑Docs markup, and constrain content to registered formats (when you set formats/registry).
  • Does not: act as a general‑purpose HTML sanitizer, validate URL schemes comprehensively, or protect a downstream renderer. Those are your responsibility.

Caution

Restrict allowed formats with the formats option and sanitize on render. The strongest defense against stored‑XSS is to (a) store Deltas, (b) constrain formats, and (c) sanitize/encode at the rendering boundary — not to rely on the editor alone.

7.3 Known issues from the community tracker

The issue tracker for this snapshot includes:

  • CVE‑2025‑15056 / GHSA‑v3m3‑f69x‑jf25 (open) — a request for a patched version and maintainer guidance. Track upstream for remediation status before deploying in high‑risk contexts.
  • getSemanticHTML correctness (#4509, open, heavily discussed) — semantic HTML export has edge cases; do not assume byte‑perfect output for complex documents (notably nested lists, #979/#4805).
  • Accessibility gaps (#4439, #4806) — toolbar keyboard navigation and certain tooltip controls have reported a11y limitations relevant to compliance reviews.

Warning

Several open issues question maintenance responsiveness (#4622, #4800, #4803). For security‑sensitive deployments, plan for the possibility that you may need to carry local patches or contribute fixes upstream.

7.4 Secrets and network

Quill has no secrets, no network calls, and no telemetry of its own. It does not phone home. The only network considerations are (a) the CDN you load it from and (b) the default uploader, which converts dropped images to inline data URLs client‑side (no upload occurs unless you supply a handler).


8. Code Quality & Conventions

Aspect Observation
Language TypeScript throughout the library, compiled with Babel (preset-env + preset-typescript) and type‑checked with tsc --noEmit.
Module style ES modules with explicit .js extensions in imports (enforced by eslint-plugin-require-extensions), enabling clean ESM output.
Separation of concerns A deliberately small core/ (quill, editor, selection, emitter, composition) with all features pushed into modules/. New behavior should be a module, not a core change.
Document model isolation Rendering and structure live entirely in Parchment blots (blots/, formats/); the editor never manipulates the DOM ad hoc — it goes through Scroll.
Testing rigor Three‑tier testing (unit + fuzz + e2e). The fuzz layer specifically guards OT invariants — a notable quality investment for an editor.
Type pragmatism The codebase contains a number of @ts-expect-error annotations around DOM/Parchment seams, reflecting the friction of typing live‑DOM editing. These are documented escape hatches, not silent anys.
Formatting Prettier (single quotes) + ESLint with import resolution, a11y, and prettier integration.

Note

The recurring @ts-expect-error // Fix me later comments are the clearest "tech debt" signal in the codebase — they mark spots where the type system and the DOM editing reality diverge. They are safe but worth tightening over time.


9. Integration & Operations Playbook

9.1 Embedding checklist

  • [ ] Choose full vs. core build deliberately (bundle size vs. convenience).
  • [ ] Include the theme stylesheet matching your theme option.
  • [ ] Pin the version (npm quill@2.0.3 or a versioned CDN URL) — avoid floating @latest in production.
  • [ ] Decide your storage format (store Deltas, not HTML).
  • [ ] Constrain allowed formats to what your product needs.
  • [ ] Define a sanitization strategy for any HTML you render from stored content.
  • [ ] If using syntax, ensure highlight.js loads before Quill.
  • [ ] Provide a real uploader.handler if you need server‑side image storage (the default inlines data URLs).

9.2 Performance tuning

Lever Effect
Core build + selective format/module registration Smaller bundle, less per‑keystroke work.
modules.syntax.interval Raise it to reduce re‑highlight frequency on large code blocks.
modules.history.maxStack Lower it to cap memory in long sessions.
Document size Split very large documents; the Delta diff cost grows with content.
Disable unused modules Set clipboard/keyboard/history/uploader to false only if you truly don't need them (most apps need clipboard + keyboard).

9.3 Upgrading

Quill 2.x changed the document/registry model versus 1.x (the website's upgrading-to-2-0 guide covers specifics). When upgrading:

  1. Review custom blots/formats against the Parchment 3 API.
  2. Re‑validate any custom clipboard matchers.
  3. Run your integration's e2e tests against the new build before shipping.

9.4 Diagnostics

Quill.debug('info'); // 'error' | 'warn' | 'log' | 'info' | true/false

Logging is namespaced (quill, quill:events, quill:selection, quill:clipboard, quill:keyboard, quill:toolbar). The default level is warn. Because Quill.debug is static, it affects every editor on the page.

Caution

Leaving debug at info/log in production is noisy and can leak document structure into the console. Keep it at warn (the default) in production builds.


10. Troubleshooting (Operational)

Build fails: TypeScript errors only with --skipLibCheck off

Cause. The library lints types with tsc --noEmit --skipLibCheck. Third‑party type mismatches can surface without skipLibCheck.

Solution. Match the project's lint command (lint:tsc) rather than a bespoke tsc invocation.

Website dev server shows the published Quill, not my local changes

Cause. The website only uses the local build when NEXT_PUBLIC_LOCAL_QUILL=true.

Solution. Use npm run start:website (which sets the flag) or npm start at the root, not a bare next dev.

Fuzz tests fail after editing Delta logic

Cause. A change to editor.ts, history.ts, or tableEmbed.ts broke an OT invariant (compose/transform/invert).

Solution. Treat fuzz failures as correctness regressions, not flakiness — the seed that failed encodes a concrete violating sequence. Reproduce and fix the invariant.

Cannot import {name}. Are you sure it was registered?

Cause. Quill.import(name) was called for a path never registered (common when mixing core build with full‑build assumptions).

Solution. Register the component first, or use the full build which registers all standard formats/modules.

Cannot load {name} module. Are you sure you registered it?

Cause. A module named in modules options isn't registered.

Solution. Register the module class under modules/{name} before construction, or remove the option.

Port conflict on dev start

Cause. The library dev server defaults to webpack port 9080 and the website to 9000 (from the root package.json config.ports).

Solution. Free the ports or override via the npm config port variables.


11. Quick Reference

Workspace scripts (root)

Command Action
npm start Library + website dev servers (parallel).
npm run build Build both packages.
npm run build:quill / build:website Build one package.
npm run lint Lint all workspaces.

Library scripts (packages/quill)

Command Action
npm run build Production webpack build → dist/.
npm start webpack‑dev‑server (port 9080).
npm test unit → fuzz → e2e.
npm run test:unit / test:fuzz / test:e2e Individual suites.
npm run lint ESLint + tsc --noEmit.

Distribution artifacts (dist/)

File Description
quill.js Full build (all formats/modules/themes).
quill.core.js Core build.
quill.core.css Core styling.
quill.snow.css Snow theme (includes core).
quill.bubble.css Bubble theme (includes core).

Key environment / config values

Name Where Meaning
QUILL_VERSION build‑time define Becomes Quill.version (falls back to 'dev').
NEXT_PUBLIC_LOCAL_QUILL website env true → site uses the local Quill build.
config.ports.webpack (9080) root package.json Library dev server port.
config.ports.website (9000) root package.json Website dev server port.
npm >= 8.2.3 engines Enforced minimum npm.

Error message → meaning

Message Meaning
Invalid Quill container Container selector matched nothing / null passed.
Invalid theme {name}. Did you register it? Unknown theme name.
Syntax module requires highlight.js… syntax enabled without highlight.js.
Cannot import {name}… Quill.import of an unregistered path.
Cannot load {name} module… Unregistered module in options.