slab/quill · error · Error
Syntax module requires highlight.js. Please include the libr
Error message
Syntax module requires highlight.js. Please include the library on the page before Quill.
What it means
The Syntax module tokenizes code blocks with highlight.js. Its DEFAULTS.hljs is captured as window.hljs at module-evaluation time (packages/quill/src/modules/syntax.ts:336-338), and the constructor throws if this.options.hljs is still null when the module is constructed. Unlike formula, you can inject the library via the module options instead of relying on the global.
Source
Thrown at packages/quill/src/modules/syntax.ts:218
}
return lib.highlight(language, text).value;
};
class Syntax extends Module<SyntaxOptions> {
static DEFAULTS: SyntaxOptions & { hljs: any };
static register() {
Quill.register(CodeToken, true);
Quill.register(SyntaxCodeBlock, true);
Quill.register(SyntaxCodeBlockContainer, true);
}
languages: Record<string, true>;
constructor(quill: Quill, options: Partial<SyntaxOptions>) {
super(quill, options);
if (this.options.hljs == null) {
throw new Error(
'Syntax module requires highlight.js. Please include the library on the page before Quill.',
);
}
// @ts-expect-error Fix me later
this.languages = this.options.languages.reduce(
(memo: Record<string, unknown>, { key }) => {
memo[key] = true;
return memo;
},
{},
);
this.highlightBlot = this.highlightBlot.bind(this);
this.initListener();
this.initTimer();
}
initListener() {
this.quill.on(Quill.events.SCROLL_BLOT_MOUNT, (blot: Blot) => {View on GitHub (pinned to 539cbffd0a)
Solutions
- Pass the highlight.js instance explicitly via module options so the global capture is bypassed: modules: { syntax: { hljs } }.
- Import highlight.js and expose it globally before Quill initializes: import hljs from 'highlight.js'; (window as any).hljs = hljs;.
- Include the highlight.js <script> synchronously before the Quill init script.
- If code highlighting is optional, gate the syntax module behind a feature flag and only enable it when hljs is available.
Example fix
// before - relies on window.hljs captured at module-eval time
new Quill(el, { modules: { syntax: true } }); // throws if hljs missing
// after - inject hljs explicitly via options (preferred)
import hljs from 'highlight.js';
new Quill(el, {
modules: { syntax: { hljs } },
});
// or expose globally before construction
import hljs from 'highlight.js';
(window as any).hljs = hljs;
new Quill(el, { modules: { syntax: true } }); Defensive patterns
Strategy: validation
Validate before calling
// Ensure highlight.js is available before enabling the syntax module
function resolveHljs(explicitHljs) {
const hljs = explicitHljs ?? (typeof window !== 'undefined' ? window.hljs : undefined);
if (hljs == null) {
throw new Error(
'Syntax module requires highlight.js. Pass it via modules.syntax.hljs or load window.hljs before Quill.',
);
}
return hljs;
}
// usage
const hljs = resolveHljs(myHljsInstance);
new Quill(el, { modules: { syntax: { hljs } } }); Type guard
function hasHljs(explicitHljs) {
const hljs = explicitHljs ?? (typeof window !== 'undefined' ? window.hljs : undefined);
return hljs != null && typeof hljs.highlight === 'function';
}
// usage
if (hasHljs()) {
new Quill(el, { modules: { syntax: true } });
} else {
// skip syntax highlighting, or import highlight.js then retry
new Quill(el, {});
} Try / catch
try {
new Quill(el, { modules: { syntax: { hljs } } });
} catch (err) {
if (String(err?.message).includes('highlight.js')) {
// hljs missing - initialize Quill without the syntax module
console.warn('Syntax module disabled: highlight.js not available.');
new Quill(el, { modules: { syntax: false } });
} else {
throw err;
}
} Prevention
- Pass the highlight.js instance explicitly via modules.syntax.hljs rather than relying on the global captured at module-eval time.
- In bundler setups, import highlight.js and assign window.hljs at app entry before Quill initializes.
- Load the highlight.js script tag synchronously before the Quill init script.
- Gate the syntax module behind a hasHljs() check so it is only enabled when the dependency is present.
When it happens
Trigger: new Quill(el, { modules: { syntax: true } }) when window.hljs was undefined at the time Syntax.DEFAULTS was evaluated; highlight.js loaded asynchronously after Quill initializes; bundler/SSR environment with no window.hljs and no explicit hljs option passed; hljs option omitted from module config.
Common situations: Forgot the highlight.js script tag; highlight.js imported as a module but never assigned to window; tree-shaking dropping the side effect; Quill initialized before highlight.js finished loading; SSR rendering where window is absent.
Related errors
AI-assisted analysis of slab/quill@539cbffd0a (2026-08-12).
Data as JSON: /api/errors/4ea6514045e9af31.
Report an issue: GitHub.