diff --git a/README.md b/README.md index 1122981a..02b79d8d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Quartz v4 features a from-the-ground rewrite focusing on end-user extensibility **If you are looking for Quartz v3, you can find it on the [`hugo` branch](https://github.com/jackyzha0/quartz/tree/hugo).** -🔗 Read the documentation and get started: https://four.quartz.jzhao.xyz/ +🔗 Read the documentation and get started: https://quartz.jzhao.xyz/ [Join the Discord Community](https://discord.gg/cRFFHYye7t) diff --git a/quartz/bootstrap-cli.mjs b/quartz/bootstrap-cli.mjs index 616f2ef7..d068cd89 100755 --- a/quartz/bootstrap-cli.mjs +++ b/quartz/bootstrap-cli.mjs @@ -255,7 +255,7 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. outro(`You're all set! Not sure what to do next? Try: • Customizing Quartz a bit more by editing \`quartz.config.ts\` • Running \`npx quartz build --serve\` to preview your Quartz locally - • Hosting your Quartz online (see: https://quartz.jzhao.xyz/setup/hosting) + • Hosting your Quartz online (see: https://quartz.jzhao.xyz/hosting) `) }) .command("update", "Get the latest Quartz updates", CommonArgv, async (argv) => { @@ -394,8 +394,15 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. const buildMutex = new Mutex() const timeoutIds = new Set() + let firstBuild = true const build = async (clientRefresh) => { - await buildMutex.acquire() + const release = await buildMutex.acquire() + if (firstBuild) { + firstBuild = false + } else { + console.log(chalk.yellow("Detected a source code change, doing a hard rebuild...")) + } + const result = await ctx.rebuild().catch((err) => { console.error(`${chalk.red("Couldn't parse Quartz configuration:")} ${fp}`) console.log(`Reason: ${chalk.grey(err)}`) @@ -418,7 +425,7 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. const { default: buildQuartz } = await import(cacheFile + `?update=${randomUUID()}`) await buildQuartz(argv, clientRefresh) clientRefresh() - buildMutex.release() + release() } const rebuild = (clientRefresh) => { @@ -455,6 +462,12 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. await serveHandler(req, res, { public: argv.output, directoryListing: false, + headers: [ + { + source: "**/*.html", + headers: [{ key: "Content-Disposition", value: "inline" }], + }, + ], }) const status = res.statusCode const statusString = @@ -526,7 +539,6 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. ignoreInitial: true, }) .on("all", async () => { - console.log(chalk.yellow("Detected a source code change, doing a hard rebuild...")) rebuild(clientRefresh) }) } else { diff --git a/quartz/build.ts b/quartz/build.ts index 78437f8a..0af39d00 100644 --- a/quartz/build.ts +++ b/quartz/build.ts @@ -108,12 +108,13 @@ async function startServing( toRemove.add(filePath) } - timeoutIds.forEach((id) => clearTimeout(id)) - // debounce rebuilds every 250ms timeoutIds.add( setTimeout(async () => { - await buildMutex.acquire() + const release = await buildMutex.acquire() + timeoutIds.forEach((id) => clearTimeout(id)) + timeoutIds.clear() + const perf = new PerfTimer() console.log(chalk.yellow("Detected change, rebuilding...")) try { @@ -134,6 +135,8 @@ async function startServing( contentMap.delete(fp) } + // TODO: we can probably traverse the link graph to figure out what's safe to delete here + // instead of just deleting everything await rimraf(argv.output) const parsedFiles = [...contentMap.values()] const filteredContent = filterContent(ctx, parsedFiles) @@ -146,7 +149,7 @@ async function startServing( clientRefresh() toRebuild.clear() toRemove.clear() - buildMutex.release() + release() }, 250), ) } diff --git a/quartz/components/Graph.tsx b/quartz/components/Graph.tsx index 0c54bdb4..e159aa54 100644 --- a/quartz/components/Graph.tsx +++ b/quartz/components/Graph.tsx @@ -47,8 +47,8 @@ const defaultOptions: GraphOptions = { export default ((opts?: GraphOptions) => { function Graph() { - const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph, } - const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph, } + const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph } + const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph } return (

Graph View

diff --git a/quartz/components/scripts/search.inline.ts b/quartz/components/scripts/search.inline.ts index 038566cb..adcd06ab 100644 --- a/quartz/components/scripts/search.inline.ts +++ b/quartz/components/scripts/search.inline.ts @@ -1,7 +1,7 @@ import { Document } from "flexsearch" import { ContentDetails } from "../../plugins/emitters/contentIndex" import { registerEscapeHandler, removeAllChildren } from "./util" -import { FullSlug, getFullSlug, resolveRelative, simplifySlug } from "../../util/path" +import { FullSlug, resolveRelative } from "../../util/path" interface Item { id: number @@ -64,6 +64,7 @@ function highlight(searchTerm: string, text: string, trim?: boolean) { } const encoder = (str: string) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])/) +let prevShortcutHandler: ((e: HTMLElementEventMap["keydown"]) => void) | undefined = undefined document.addEventListener("nav", async (e: unknown) => { const currentSlug = (e as CustomEventMap["nav"]).detail.url @@ -159,8 +160,12 @@ document.addEventListener("nav", async (e: unknown) => { displayResults(finalResults) } - document.removeEventListener("keydown", shortcutHandler) + if (prevShortcutHandler) { + document.removeEventListener("keydown", prevShortcutHandler) + } + document.addEventListener("keydown", shortcutHandler) + prevShortcutHandler = shortcutHandler searchIcon?.removeEventListener("click", showSearch) searchIcon?.addEventListener("click", showSearch) searchBar?.removeEventListener("input", onType) diff --git a/quartz/styles/variables.scss b/quartz/styles/variables.scss index f0505e4d..30004aa7 100644 --- a/quartz/styles/variables.scss +++ b/quartz/styles/variables.scss @@ -1,6 +1,6 @@ $pageWidth: 750px; $mobileBreakpoint: 600px; $tabletBreakpoint: 1200px; -$sidePanelWidth: 400px; +$sidePanelWidth: 380px; $topSpacing: 6rem; $fullPageWidth: $pageWidth + 2 * $sidePanelWidth;