diff --git a/quartz.config.ts b/quartz.config.ts index ae5d9893c..b20884793 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -77,7 +77,9 @@ const config: QuartzConfig = { // ![alt text](image.jpg) // *caption text* // ``` - Plugin.FigureCaptions() + Plugin.FigureCaptions(), + // Adds image lightbox support + Plugin.Lightbox(), ], filters: [Plugin.RemoveDrafts()], emitters: [ diff --git a/quartz/plugins/transformers/index.ts b/quartz/plugins/transformers/index.ts index b06f9df97..e3db3d1f3 100644 --- a/quartz/plugins/transformers/index.ts +++ b/quartz/plugins/transformers/index.ts @@ -11,4 +11,5 @@ export { SyntaxHighlighting } from "./syntax" export { TableOfContents } from "./toc" export { HardLineBreaks } from "./linebreaks" export { RoamFlavoredMarkdown } from "./roam" -export { FigureCaptions } from "./figcaptions" \ No newline at end of file +export { FigureCaptions } from "./figcaptions" +export { Lightbox } from "./lightbox" \ No newline at end of file diff --git a/quartz/plugins/transformers/lightbox.ts b/quartz/plugins/transformers/lightbox.ts new file mode 100644 index 000000000..0ec1aa6d6 --- /dev/null +++ b/quartz/plugins/transformers/lightbox.ts @@ -0,0 +1,69 @@ +import { QuartzTransformerPlugin } from "../types" +import { visit } from "unist-util-visit" +import { Root } from "hast" + +// Options supported here should be in sync with what GLightbox supports: +// https://github.com/biati-digital/glightbox +interface Options { + /** Name of the effect on lightbox open. */ + openEffect: "zoom" | "fade" | "none", + /** Name of the effect on lightbox close. */ + closeEffect: "zoom" | "fade" | "none", + /** Name of the effect on slide change. */ + slideEffect: "slide" | "zoom" | "fade" | "none", + /** Show or hide the close button. */ + closeButton: boolean +} + +const defaultOptions: Options = { + openEffect: "zoom", + closeEffect: "zoom", + slideEffect: "slide", + closeButton: false +} + +export const Lightbox: QuartzTransformerPlugin> = (userOpts) => { + const opts = { ...defaultOptions, ...userOpts } + return { + name: "Lightbox", + htmlPlugins(ctx) { + return [ + () => { + return (tree: Root, file) => { + visit(tree, "element", (node, _index, _parent) => { + if (node.tagName === "img" && + node.properties && + typeof node.properties.src === "string" + ) { + // Add Image Lightbox support + const classes = (node.properties.className ?? []) as string[]; + classes.push("glightbox"); + + node.properties.className = classes; + } + }) + } + } + ] + }, + externalResources() { + return { + css: [ + "https://cdnjs.cloudflare.com/ajax/libs/glightbox/3.3.0/css/glightbox.min.css" + ], + js: [ + { + src: "https://cdnjs.cloudflare.com/ajax/libs/glightbox/3.3.0/js/glightbox.min.js", + loadTime: "afterDOMReady", + contentType: "external", + }, + { + contentType: "inline", + loadTime: "afterDOMReady", + script: `const lightbox = GLightbox(${JSON.stringify(opts)});` + } + ] + } + } + } +} \ No newline at end of file