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:
- 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. - 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.
- 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):
expandConfig()resolves the container selector, picks the theme constructor, merges Quill defaults + theme defaults + your options + per‑module defaults, and resolves the registry (customregistry>formatsfilter > shared global).- The container is cleared, marked
.ql-container, and registered in a globalWeakMap(core/instances.ts) keyed by DOM node. - A
.ql-editorroot is created and the Scroll blot is instantiated from the registry. - Editor, Selection, and Composition are constructed around the Scroll.
- The theme is instantiated; it adds the default modules —
keyboard,clipboard,history,uploader, plusinputanduiNode— and any theme‑specific modules, then runstheme.init(). - Event wiring connects Scroll updates back into the Editor's Delta sync and toggles the
.ql-blankclass. - If the container had initial HTML, it is converted through the clipboard and set as the initial contents; history is cleared;
placeholder/readOnlyare applied.
Note
The shared
globalRegistry(aParchment.Registry) is created once at module load. Because it is shared across all editor instances by default, registering a format withQuill.registeraffects every editor on the page unless you pass a per‑instanceregistry.
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,fonthave style variants used during paste normalization).
Tip
Registering a format via
Quill.register(BlotOrAttributor)infers the name fromblotName/attrNameand adds it underformats/{name}. Anything registered underblots/orformats/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()storeschangeDelta.invert(oldDelta)). - Collaboration possible —
transformis operational transformation, letting concurrent edits be rebased. - Tables/embeds composable — embed handlers (
tableEmbed.ts) register customcompose/transform/invertlogic 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
linkhandler (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 whatimport '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/inverthold. Run it after any change toeditor.ts,history.ts, ortableEmbed.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
DOMParserdocument, strip to a structured Delta via the matcher pipeline, normalize Word/Google‑Docs markup, and constrain content to registered formats (when you setformats/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
formatsoption 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.
getSemanticHTMLcorrectness (#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 latercomments 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
themeoption. - [ ] Pin the version (npm
quill@2.0.3or a versioned CDN URL) — avoid floating@latestin 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.handlerif 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:
- Review custom blots/formats against the Parchment 3 API.
- Re‑validate any custom clipboard matchers.
- 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/login production is noisy and can leak document structure into the console. Keep it atwarn(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. |