The original Upstream provided the Viewer.js integration; fork-specific fixes preserve compatibility with the Quartz 5 YAML plugin loader and SPA router.
Repository
- Fork: https://github.com/ruhanirabin/quartz-lightbox
- Upstream: https://github.com/quartz-plugins/quartz-lightbox
- Branch:
main, trackingorigin/main - Fixed version:
0.1.1 - Fix commit:
505d113
Failure and Root Cause
The original plugin worked on the first page but failed after SPA navigation with:
Uncaught TypeError: Cannot read properties of null (reading 'removeChild')Quartz runs registered cleanup callbacks before replacing the body, clears its
cleanup registry, patches the DOM, and then emits nav. The original plugin
registered Viewer cleanup only once. After a later navigation, its stale Viewer
still referenced an article that Quartz had detached. Calling
currentViewer.destroy() then caused Viewer.js to remove a child from a missing
parent, aborting initialization on the new page.
The original dynamically injected Viewer.js script and stylesheet also lacked
Quartz’s data-persist marker, so SPA head patching could remove them. Its
configurable selector affected hover CSS but did not restrict Viewer eligibility,
and its resource-only transformer shape was rejected by the current Quartz YAML
loader without a Quartz core compatibility change.
Fork Fixes
- Destroy Viewer on
prenav, before Quartz detaches the old article. - Re-register
window.addCleanup()every time Viewer is initialized. - Treat teardown as defensive and always clear the stale Viewer reference.
- Reinitialize on every Quartz
navevent. - Give Viewer.js assets stable IDs and
data-persistmarkers, preventing removal or duplication across SPA navigation. - Apply the configured selector through
image.matches()as well as CSS. - Provide an empty
htmlPlugins()method so Quartz accepts the transformer without modifying Quartz core. - Generate
dist/index.d.ts, includedist/in package output, and declare the published@quartz-community/typesand Node type dependencies. - Update the YAML installation instructions for the maintained fork.
Testing and Packaging
The dependency-free Node lifecycle test executes the emitted browser script
against a small DOM and Viewer harness. It verifies initial setup and three
consecutive Quartz-style prenav, cleanup, DOM replacement, and nav cycles.
It also checks selector filtering, persistent assets, duplicate prevention, and
successful destruction of each prior Viewer instance.
Validation for 0.1.1 passed:
- JavaScript and declaration builds;
- lifecycle regression test;
- TypeScript compilation;
- repository-wide Prettier check;
- whitespace validation; and
- npm package dry run containing compiled JavaScript, source map, and types.
Current Integration
Digital Mind loads the fork from github:ruhanirabin/quartz-lightbox in
quartz.config.yaml.