| | |
| | | import styles from "../../styles/custom.scss" |
| | | import popoverStyle from "../../components/styles/popover.scss" |
| | | import { BuildCtx } from "../../util/ctx" |
| | | import { StaticResources } from "../../util/resources" |
| | | import { QuartzComponent } from "../../components/types" |
| | | import { googleFontHref, joinStyles } from "../../util/theme" |
| | | import { Features, transform } from "lightningcss" |
| | |
| | | return res.code |
| | | } |
| | | |
| | | function addGlobalPageResources( |
| | | ctx: BuildCtx, |
| | | staticResources: StaticResources, |
| | | componentResources: ComponentResources, |
| | | ) { |
| | | function addGlobalPageResources(ctx: BuildCtx, componentResources: ComponentResources) { |
| | | const cfg = ctx.cfg.configuration |
| | | const reloadScript = ctx.argv.serve |
| | | |
| | | // popovers |
| | | if (cfg.enablePopovers) { |
| | |
| | | |
| | | if (cfg.analytics?.provider === "google") { |
| | | const tagId = cfg.analytics.tagId |
| | | staticResources.js.push({ |
| | | src: `https://www.googletagmanager.com/gtag/js?id=${tagId}`, |
| | | contentType: "external", |
| | | loadTime: "afterDOMReady", |
| | | }) |
| | | componentResources.afterDOMLoaded.push(` |
| | | const gtagScript = document.createElement("script") |
| | | gtagScript.src = "https://www.googletagmanager.com/gtag/js?id=${tagId}" |
| | | gtagScript.async = true |
| | | document.head.appendChild(gtagScript) |
| | | |
| | | window.dataLayer = window.dataLayer || []; |
| | | function gtag() { dataLayer.push(arguments); } |
| | | gtag("js", new Date()); |
| | |
| | | document.dispatchEvent(event) |
| | | `) |
| | | } |
| | | |
| | | let wsUrl = `ws://localhost:${ctx.argv.wsPort}` |
| | | |
| | | if (ctx.argv.remoteDevHost) { |
| | | wsUrl = `wss://${ctx.argv.remoteDevHost}:${ctx.argv.wsPort}` |
| | | } |
| | | |
| | | if (reloadScript) { |
| | | staticResources.js.push({ |
| | | loadTime: "afterDOMReady", |
| | | contentType: "inline", |
| | | script: ` |
| | | const socket = new WebSocket('${wsUrl}') |
| | | // reload(true) ensures resources like images and scripts are fetched again in firefox |
| | | socket.addEventListener('message', () => document.location.reload(true)) |
| | | `, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | interface Options { |
| | | fontOrigin: "googleFonts" | "local" |
| | | } |
| | | |
| | | const defaultOptions: Options = { |
| | | fontOrigin: "googleFonts", |
| | | } |
| | | |
| | | export const ComponentResources: QuartzEmitterPlugin<Options> = (opts?: Partial<Options>) => { |
| | | const { fontOrigin } = { ...defaultOptions, ...opts } |
| | | // This emitter should not update the `resources` parameter. If it does, partial |
| | | // rebuilds may not work as expected. |
| | | export const ComponentResources: QuartzEmitterPlugin = () => { |
| | | return { |
| | | name: "ComponentResources", |
| | | getQuartzComponents() { |
| | | return [] |
| | | }, |
| | | async getDependencyGraph(ctx, content, _resources) { |
| | | // This emitter adds static resources to the `resources` parameter. One |
| | | // important resource this emitter adds is the code to start a websocket |
| | | // connection and listen to rebuild messages, which triggers a page reload. |
| | | // The resources parameter with the reload logic is later used by the |
| | | // ContentPage emitter while creating the final html page. In order for |
| | | // the reload logic to be included, and so for partial rebuilds to work, |
| | | // we need to run this emitter for all markdown files. |
| | | const graph = new DepGraph<FilePath>() |
| | | |
| | | for (const [_tree, file] of content) { |
| | | const sourcePath = file.data.filePath! |
| | | const slug = file.data.slug! |
| | | graph.addEdge(sourcePath, joinSegments(ctx.argv.output, slug + ".html") as FilePath) |
| | | } |
| | | |
| | | return graph |
| | | async getDependencyGraph(_ctx, _content, _resources) { |
| | | return new DepGraph<FilePath>() |
| | | }, |
| | | async emit(ctx, _content, resources): Promise<FilePath[]> { |
| | | async emit(ctx, _content, _resources): Promise<FilePath[]> { |
| | | const promises: Promise<FilePath>[] = [] |
| | | const cfg = ctx.cfg.configuration |
| | | // component specific scripts and styles |
| | | const componentResources = getComponentResources(ctx) |
| | | let googleFontsStyleSheet = "" |
| | | if (fontOrigin === "local") { |
| | | if (cfg.theme.fontOrigin === "local") { |
| | | // let the user do it themselves in css |
| | | } else if (fontOrigin === "googleFonts") { |
| | | if (cfg.theme.cdnCaching) { |
| | | resources.css.push(googleFontHref(cfg.theme)) |
| | | } else { |
| | | } else if (cfg.theme.fontOrigin === "googleFonts" && !cfg.theme.cdnCaching) { |
| | | // when cdnCaching is true, we link to google fonts in Head.tsx |
| | | let match |
| | | |
| | | const fontSourceRegex = /url\((https:\/\/fonts.gstatic.com\/s\/[^)]+\.(woff2|ttf))\)/g |
| | |
| | | ) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // important that this goes *after* component scripts |
| | | // as the "nav" event gets triggered here and we should make sure |
| | | // that everyone else had the chance to register a listener for it |
| | | addGlobalPageResources(ctx, resources, componentResources) |
| | | addGlobalPageResources(ctx, componentResources) |
| | | |
| | | const stylesheet = joinStyles( |
| | | ctx.cfg.configuration.theme, |