mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-05-18 06:24:22 +02:00
Compare commits
3 Commits
eb1002c85e
...
95d57ad29e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
95d57ad29e | ||
![]() |
7be47742a6 | ||
![]() |
2e299c67cc |
40
ambient.d.ts
vendored
Normal file
40
ambient.d.ts
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
declare module "*.scss" {
|
||||
const content: string
|
||||
export = content
|
||||
}
|
||||
|
||||
declare module "$config" {
|
||||
import { QuartzConfig } from "./quartz"
|
||||
|
||||
const config: QuartzConfig
|
||||
export = config
|
||||
}
|
||||
|
||||
declare module "$layout" {
|
||||
import { SharedLayout, PageLayout } from "./quartz/cfg"
|
||||
|
||||
export const sharedPageComponents: SharedLayout
|
||||
export const defaultContentPageLayout: PageLayout
|
||||
export const defaultListPageLayout: PageLayout
|
||||
}
|
||||
|
||||
declare module "$styles" {
|
||||
const content: string
|
||||
export = content
|
||||
}
|
||||
|
||||
declare module "quartz" {
|
||||
// without this the export below does nothing for some reason
|
||||
// sometimes TS is funn
|
||||
import("./quartz")
|
||||
|
||||
export * from "./quartz"
|
||||
}
|
||||
|
||||
// dom custom event
|
||||
interface CustomEventMap {
|
||||
nav: CustomEvent<{ url: FullSlug }>
|
||||
themechange: CustomEvent<{ theme: "light" | "dark" }>
|
||||
}
|
||||
|
||||
declare const fetchData: Promise<ContentIndex>
|
@ -17,7 +17,7 @@ This question is best answered by tracing what happens when a user (you!) runs `
|
||||
1. A WebSocket server on port 3001 to handle hot-reload signals. This tracks all inbound connections and sends a 'rebuild' message a server-side change is detected (either content or configuration).
|
||||
2. An HTTP file-server on a user defined port (normally 8080) to serve the actual website files.
|
||||
4. If the `--serve` flag is set, it also starts a file watcher to detect source-code changes (e.g. anything that is `.ts`, `.tsx`, `.scss`, or packager files). On a change, we rebuild the module (step 2 above) using esbuild's [rebuild API](https://esbuild.github.io/api/#rebuild) which drastically reduces the build times.
|
||||
5. After transpiling the main Quartz build module (`quartz/build.ts`), we write it to a cache file `.quartz-cache/transpiled-build.mjs` and then dynamically import this using `await import(cacheFile)`. However, we need to be pretty smart about how to bust Node's [import cache](https://github.com/nodejs/modules/issues/307) so we add a random query string to fake Node into thinking it's a new module. This does, however, cause memory leaks so we just hope that the user doesn't hot-reload their configuration too many times in a single session :)) (it leaks about ~350kB memory on each reload). After importing the module, we then invoke it, passing in the command line arguments we parsed earlier along with a callback function to signal the client to refresh.
|
||||
5. After transpiling the main Quartz build module (`quartz/build.ts`), we write it to a cache file `node_modules/.cache/quartz/transpiled-build.mjs` and then dynamically import this using `await import(cacheFile)`. However, we need to be pretty smart about how to bust Node's [import cache](https://github.com/nodejs/modules/issues/307) so we add a random query string to fake Node into thinking it's a new module. This does, however, cause memory leaks so we just hope that the user doesn't hot-reload their configuration too many times in a single session :)) (it leaks about ~350kB memory on each reload). After importing the module, we then invoke it, passing in the command line arguments we parsed earlier along with a callback function to signal the client to refresh.
|
||||
4. In `build.ts`, we start by installing source map support manually to account for the query string cache busting hack we introduced earlier. Then, we start processing content:
|
||||
1. Clean the output directory.
|
||||
2. Recursively glob all files in the `content` folder, respecting the `.gitignore`.
|
||||
|
12
index.d.ts
vendored
12
index.d.ts
vendored
@ -1,12 +0,0 @@
|
||||
declare module "*.scss" {
|
||||
const content: string
|
||||
export = content
|
||||
}
|
||||
|
||||
// dom custom event
|
||||
interface CustomEventMap {
|
||||
nav: CustomEvent<{ url: FullSlug }>
|
||||
themechange: CustomEvent<{ theme: "light" | "dark" }>
|
||||
}
|
||||
|
||||
declare const fetchData: Promise<ContentIndex>
|
27
package-lock.json
generated
27
package-lock.json
generated
@ -34,7 +34,7 @@
|
||||
"mdast-util-to-hast": "^13.2.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"micromorph": "^0.4.5",
|
||||
"pixi.js": "^8.6.6",
|
||||
"pixi.js": "^8.7.3",
|
||||
"preact": "^10.25.4",
|
||||
"preact-render-to-string": "^6.5.13",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
@ -79,10 +79,10 @@
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^22.10.6",
|
||||
"@types/node": "^22.12.0",
|
||||
"@types/pretty-time": "^1.1.5",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/ws": "^8.5.13",
|
||||
"@types/ws": "^8.5.14",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"esbuild": "^0.24.2",
|
||||
"prettier": "^3.4.2",
|
||||
@ -1914,10 +1914,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz",
|
||||
"integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==",
|
||||
"version": "22.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz",
|
||||
"integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
@ -1943,10 +1944,11 @@
|
||||
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||
"integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
|
||||
"version": "8.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz",
|
||||
"integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@ -5583,9 +5585,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pixi.js": {
|
||||
"version": "8.6.6",
|
||||
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.6.6.tgz",
|
||||
"integrity": "sha512-o5pw7G2yuIrnBx0G4npBlmFp+XGNcapI/Ufs62rRj/4XKxc1Zo74YJr/BtEXcXTraTKd+pQvYOLvnfxRjxBMvQ==",
|
||||
"version": "8.7.3",
|
||||
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.7.3.tgz",
|
||||
"integrity": "sha512-wfWlhJYnGx1s4f2yoouevQjaeacbJ12LTkJGa+n9AIYNIjOnmJylBtZ2mARX7iFk3mr2xv0wuo//XPe2hk5OBw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pixi/colord": "^2.9.6",
|
||||
"@types/css-font-loading-module": "^0.0.12",
|
||||
|
@ -34,6 +34,7 @@
|
||||
"bin": {
|
||||
"quartz": "./quartz/bootstrap-cli.mjs"
|
||||
},
|
||||
"types": "./ambient.d.ts",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.9.1",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
@ -60,7 +61,7 @@
|
||||
"mdast-util-to-hast": "^13.2.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"micromorph": "^0.4.5",
|
||||
"pixi.js": "^8.6.6",
|
||||
"pixi.js": "^8.7.3",
|
||||
"preact": "^10.25.4",
|
||||
"preact-render-to-string": "^6.5.13",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
@ -102,10 +103,10 @@
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^22.10.6",
|
||||
"@types/node": "^22.12.0",
|
||||
"@types/pretty-time": "^1.1.5",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/ws": "^8.5.13",
|
||||
"@types/ws": "^8.5.14",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"esbuild": "^0.24.2",
|
||||
"prettier": "^3.4.2",
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { QuartzConfig } from "./quartz/cfg"
|
||||
import * as Plugin from "./quartz/plugins"
|
||||
import { QuartzConfig, Plugin } from "quartz"
|
||||
|
||||
/**
|
||||
* Quartz 4.0 Configuration
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { PageLayout, SharedLayout } from "./quartz/cfg"
|
||||
import * as Component from "./quartz/components"
|
||||
import { Component, PageLayout, SharedLayout } from "quartz"
|
||||
|
||||
// components shared across all pages
|
||||
export const sharedPageComponents: SharedLayout = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
import workerpool from "workerpool"
|
||||
const cacheFile = "./.quartz-cache/transpiled-worker.mjs"
|
||||
const cacheFile = process.argv[2]
|
||||
const { parseMarkdown, processHtml } = await import(cacheFile)
|
||||
workerpool.worker({
|
||||
parseMarkdown,
|
||||
|
@ -8,7 +8,7 @@ import chalk from "chalk"
|
||||
import { parseMarkdown } from "./processors/parse"
|
||||
import { filterContent } from "./processors/filter"
|
||||
import { emitContent } from "./processors/emit"
|
||||
import cfg from "../quartz.config"
|
||||
import cfg from "$config"
|
||||
import { FilePath, FullSlug, joinSegments, slugifyFilePath } from "./util/path"
|
||||
import chokidar from "chokidar"
|
||||
import { ProcessedContent } from "./plugins/vfile"
|
||||
@ -42,12 +42,13 @@ function newBuildId() {
|
||||
return Math.random().toString(36).substring(2, 8)
|
||||
}
|
||||
|
||||
async function buildQuartz(argv: Argv, mut: Mutex, clientRefresh: () => void) {
|
||||
async function buildQuartz(quartzRoot: string, argv: Argv, mut: Mutex, clientRefresh: () => void) {
|
||||
const ctx: BuildCtx = {
|
||||
buildId: newBuildId(),
|
||||
argv,
|
||||
cfg,
|
||||
allSlugs: [],
|
||||
quartzRoot,
|
||||
}
|
||||
|
||||
const perf = new PerfTimer()
|
||||
@ -413,9 +414,9 @@ async function rebuildFromEntrypoint(
|
||||
release()
|
||||
}
|
||||
|
||||
export default async (argv: Argv, mut: Mutex, clientRefresh: () => void) => {
|
||||
export default async (quartzRoot: string, argv: Argv, mut: Mutex, clientRefresh: () => void) => {
|
||||
try {
|
||||
return await buildQuartz(argv, mut, clientRefresh)
|
||||
return await buildQuartz(quartzRoot, argv, mut, clientRefresh)
|
||||
} catch (err) {
|
||||
trace("\nExiting Quartz due to a fatal error", err as Error)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import path from "path"
|
||||
import { readFileSync } from "fs"
|
||||
import { accessSync, readFileSync } from "fs"
|
||||
|
||||
/**
|
||||
* All constants relating to helpers or handlers
|
||||
@ -7,9 +7,26 @@ import { readFileSync } from "fs"
|
||||
export const ORIGIN_NAME = "origin"
|
||||
export const UPSTREAM_NAME = "upstream"
|
||||
export const QUARTZ_SOURCE_BRANCH = "v4"
|
||||
|
||||
export const cwd = process.cwd()
|
||||
export const cacheDir = path.join(cwd, ".quartz-cache")
|
||||
export const cacheFile = "./quartz/.quartz-cache/transpiled-build.mjs"
|
||||
export const fp = "./quartz/build.ts"
|
||||
export const { version } = JSON.parse(readFileSync("./package.json").toString())
|
||||
|
||||
function selectCacheDir() {
|
||||
try {
|
||||
const node_modules = path.join(cwd, "node_modules")
|
||||
accessSync(node_modules) // check if node_modules exists
|
||||
return path.join(node_modules, ".cache", "quartz")
|
||||
} catch {
|
||||
// standalone quartz bin?
|
||||
return path.join(cwd, ".quartz-cache")
|
||||
}
|
||||
}
|
||||
|
||||
export const cacheDir = selectCacheDir()
|
||||
export const cacheFile = path.join(cacheDir, "transpiled-build.mjs")
|
||||
export const contentCacheFolder = path.join(cacheDir, "content-cache")
|
||||
|
||||
export const quartzRoot = path.resolve(import.meta.dirname, "..")
|
||||
export const fp = path.join(quartzRoot, "build.ts")
|
||||
export const { version } = JSON.parse(
|
||||
readFileSync(path.resolve(quartzRoot, "..", "package.json")).toString(),
|
||||
)
|
||||
|
@ -31,7 +31,9 @@ import {
|
||||
fp,
|
||||
cacheFile,
|
||||
cwd,
|
||||
quartzRoot,
|
||||
} from "./constants.js"
|
||||
import { pathToFileURL } from "url"
|
||||
|
||||
/**
|
||||
* Handles `npx quartz create`
|
||||
@ -232,6 +234,12 @@ export async function handleBuild(argv) {
|
||||
metafile: true,
|
||||
sourcemap: true,
|
||||
sourcesContent: false,
|
||||
alias: {
|
||||
$config: path.join(cwd, "quartz.config.ts"),
|
||||
$layout: path.join(cwd, "quartz.layout.ts"),
|
||||
$styles: path.join(cwd, "styles.scss"),
|
||||
quartz: path.resolve(quartzRoot, ".."),
|
||||
},
|
||||
plugins: [
|
||||
sassPlugin({
|
||||
type: "css-text",
|
||||
@ -303,8 +311,9 @@ export async function handleBuild(argv) {
|
||||
release()
|
||||
|
||||
if (argv.bundleInfo) {
|
||||
const outputFileName = "quartz/.quartz-cache/transpiled-build.mjs"
|
||||
const meta = result.metafile.outputs[outputFileName]
|
||||
// metafile.outputs always uses /
|
||||
const output = path.relative(cwd, cacheFile).replaceAll("\\", "/")
|
||||
const meta = result.metafile.outputs[output]
|
||||
console.log(
|
||||
`Successfully transpiled ${Object.keys(meta.inputs).length} files (${prettyBytes(
|
||||
meta.bytes,
|
||||
@ -313,12 +322,14 @@ export async function handleBuild(argv) {
|
||||
console.log(await esbuild.analyzeMetafile(result.metafile, { color: true }))
|
||||
}
|
||||
|
||||
// absolute path on windows has to be a file:// url
|
||||
const url = pathToFileURL(cacheFile)
|
||||
// bypass module cache
|
||||
// https://github.com/nodejs/modules/issues/307
|
||||
const { default: buildQuartz } = await import(`../../${cacheFile}?update=${randomUUID()}`)
|
||||
// ^ this import is relative, so base "cacheFile" path can't be used
|
||||
url.searchParams.set("update", randomUUID())
|
||||
const { default: buildQuartz } = await import(url)
|
||||
|
||||
cleanupBuild = await buildQuartz(argv, buildMutex, clientRefresh)
|
||||
cleanupBuild = await buildQuartz(quartzRoot, argv, buildMutex, clientRefresh)
|
||||
clientRefresh()
|
||||
}
|
||||
|
||||
|
4
quartz/index.ts
Normal file
4
quartz/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * as Component from "./components"
|
||||
export * as Plugin from "./plugins"
|
||||
export * from "./i18n"
|
||||
export * from "./cfg"
|
@ -4,7 +4,7 @@ import BodyConstructor from "../../components/Body"
|
||||
import { pageResources, renderPage } from "../../components/renderPage"
|
||||
import { FullPageLayout } from "../../cfg"
|
||||
import { FilePath, FullSlug } from "../../util/path"
|
||||
import { sharedPageComponents } from "../../../quartz.layout"
|
||||
import { sharedPageComponents } from "$layout"
|
||||
import { NotFound } from "../../components"
|
||||
import { defaultProcessedContent } from "../vfile"
|
||||
import { write } from "./helpers"
|
||||
|
@ -14,6 +14,7 @@ import { Features, transform } from "lightningcss"
|
||||
import { transform as transpile } from "esbuild"
|
||||
import { write } from "./helpers"
|
||||
import DepGraph from "../../depgraph"
|
||||
import path from "path"
|
||||
|
||||
type ComponentResources = {
|
||||
css: string[]
|
||||
@ -183,8 +184,13 @@ export const ComponentResources: QuartzEmitterPlugin = () => {
|
||||
getQuartzComponents() {
|
||||
return []
|
||||
},
|
||||
async getDependencyGraph(_ctx, _content, _resources) {
|
||||
return new DepGraph<FilePath>()
|
||||
async getDependencyGraph(ctx, _content, _resources) {
|
||||
const graph = new DepGraph<FilePath>()
|
||||
graph.addEdge(
|
||||
path.join(ctx.argv.output, "index.css") as FilePath,
|
||||
path.join(process.cwd(), "styles.scss") as FilePath,
|
||||
)
|
||||
return graph
|
||||
},
|
||||
async emit(ctx, _content, _resources): Promise<FilePath[]> {
|
||||
const promises: Promise<FilePath>[] = []
|
||||
@ -245,6 +251,7 @@ export const ComponentResources: QuartzEmitterPlugin = () => {
|
||||
googleFontsStyleSheet,
|
||||
...componentResources.css,
|
||||
styles,
|
||||
await import("$styles").then((s) => s.default ?? s).catch(() => ""),
|
||||
)
|
||||
const [prescript, postscript] = await Promise.all([
|
||||
joinScripts(componentResources.beforeDOMLoaded),
|
||||
|
@ -10,7 +10,7 @@ import { pageResources, renderPage } from "../../components/renderPage"
|
||||
import { FullPageLayout } from "../../cfg"
|
||||
import { Argv } from "../../util/ctx"
|
||||
import { FilePath, isRelativeURL, joinSegments, pathToRoot } from "../../util/path"
|
||||
import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
|
||||
import { defaultContentPageLayout, sharedPageComponents } from "$layout"
|
||||
import { Content } from "../../components"
|
||||
import chalk from "chalk"
|
||||
import { write } from "./helpers"
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
pathToRoot,
|
||||
simplifySlug,
|
||||
} from "../../util/path"
|
||||
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
|
||||
import { defaultListPageLayout, sharedPageComponents } from "$layout"
|
||||
import { FolderContent } from "../../components"
|
||||
import { write } from "./helpers"
|
||||
import { i18n } from "../../i18n"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FilePath, QUARTZ, joinSegments } from "../../util/path"
|
||||
import { FilePath, joinSegments } from "../../util/path"
|
||||
import { QuartzEmitterPlugin } from "../types"
|
||||
import fs from "fs"
|
||||
import { glob } from "../../util/glob"
|
||||
@ -9,10 +9,10 @@ export const Static: QuartzEmitterPlugin = () => ({
|
||||
getQuartzComponents() {
|
||||
return []
|
||||
},
|
||||
async getDependencyGraph({ argv, cfg }, _content, _resources) {
|
||||
async getDependencyGraph({ argv, cfg, quartzRoot }, _content, _resources) {
|
||||
const graph = new DepGraph<FilePath>()
|
||||
|
||||
const staticPath = joinSegments(QUARTZ, "static")
|
||||
const staticPath = joinSegments(quartzRoot, "static")
|
||||
const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns)
|
||||
for (const fp of fps) {
|
||||
graph.addEdge(
|
||||
@ -23,8 +23,8 @@ export const Static: QuartzEmitterPlugin = () => ({
|
||||
|
||||
return graph
|
||||
},
|
||||
async emit({ argv, cfg }, _content, _resources): Promise<FilePath[]> {
|
||||
const staticPath = joinSegments(QUARTZ, "static")
|
||||
async emit({ argv, cfg, quartzRoot }, _content, _resources): Promise<FilePath[]> {
|
||||
const staticPath = joinSegments(quartzRoot, "static")
|
||||
const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns)
|
||||
await fs.promises.cp(staticPath, joinSegments(argv.output, "static"), {
|
||||
recursive: true,
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
joinSegments,
|
||||
pathToRoot,
|
||||
} from "../../util/path"
|
||||
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
|
||||
import { defaultListPageLayout, sharedPageComponents } from "$layout"
|
||||
import { TagContent } from "../../components"
|
||||
import { write } from "./helpers"
|
||||
import { i18n } from "../../i18n"
|
||||
|
@ -7,7 +7,7 @@ import { Root as HTMLRoot } from "hast"
|
||||
import { MarkdownContent, ProcessedContent } from "../plugins/vfile"
|
||||
import { PerfTimer } from "../util/perf"
|
||||
import { read } from "to-vfile"
|
||||
import { FilePath, FullSlug, QUARTZ, slugifyFilePath } from "../util/path"
|
||||
import { FilePath, FullSlug, slugifyFilePath } from "../util/path"
|
||||
import path from "path"
|
||||
import workerpool, { Promise as WorkerPromise } from "workerpool"
|
||||
import { QuartzLogger } from "../util/log"
|
||||
@ -49,20 +49,28 @@ function* chunks<T>(arr: T[], n: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function transpileWorkerScript() {
|
||||
// transpile worker script
|
||||
const cacheFile = "./.quartz-cache/transpiled-worker.mjs"
|
||||
const fp = "./quartz/worker.ts"
|
||||
return esbuild.build({
|
||||
async function transpileWorkerScript(ctx: BuildCtx): Promise<string> {
|
||||
// import.meta.dirname is the cache folder, because we're in transpiled-build.mjs atm technically
|
||||
const cacheFile = path.join(import.meta.dirname, "transpiled-worker.mjs")
|
||||
const fp = path.join(ctx.quartzRoot, "worker.ts")
|
||||
await esbuild.build({
|
||||
entryPoints: [fp],
|
||||
outfile: path.join(QUARTZ, cacheFile),
|
||||
outfile: cacheFile,
|
||||
bundle: true,
|
||||
keepNames: true,
|
||||
minifyWhitespace: true,
|
||||
minifySyntax: true,
|
||||
platform: "node",
|
||||
format: "esm",
|
||||
packages: "external",
|
||||
sourcemap: true,
|
||||
sourcesContent: false,
|
||||
alias: {
|
||||
$config: path.join(process.cwd(), "quartz.config.ts"),
|
||||
$layout: path.join(process.cwd(), "quartz.layout.ts"),
|
||||
$styles: path.join(process.cwd(), "styles.scss"),
|
||||
quartz: path.resolve(ctx.quartzRoot, ".."),
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
name: "css-and-scripts-as-text",
|
||||
@ -79,6 +87,7 @@ async function transpileWorkerScript() {
|
||||
},
|
||||
],
|
||||
})
|
||||
return cacheFile
|
||||
}
|
||||
|
||||
export function createFileParser(ctx: BuildCtx, fps: FilePath[]) {
|
||||
@ -164,11 +173,12 @@ export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<Pro
|
||||
throw error
|
||||
}
|
||||
} else {
|
||||
await transpileWorkerScript()
|
||||
const pool = workerpool.pool("./quartz/bootstrap-worker.mjs", {
|
||||
const transpiledWorker = await transpileWorkerScript(ctx)
|
||||
const pool = workerpool.pool(path.join(ctx.quartzRoot, "bootstrap-worker.mjs"), {
|
||||
minWorkers: "max",
|
||||
maxWorkers: concurrency,
|
||||
workerType: "thread",
|
||||
workerThreadOpts: { argv: [transpiledWorker] },
|
||||
})
|
||||
const errorHandler = (err: any) => {
|
||||
console.error(`${err}`.replace(/^error:\s*/i, ""))
|
||||
@ -177,7 +187,7 @@ export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<Pro
|
||||
|
||||
const mdPromises: WorkerPromise<[MarkdownContent[], FullSlug[]]>[] = []
|
||||
for (const chunk of chunks(fps, CHUNK_SIZE)) {
|
||||
mdPromises.push(pool.exec("parseMarkdown", [ctx.buildId, argv, chunk]))
|
||||
mdPromises.push(pool.exec("parseMarkdown", [ctx.buildId, ctx.quartzRoot, argv, chunk]))
|
||||
}
|
||||
const mdResults: [MarkdownContent[], FullSlug[]][] =
|
||||
await WorkerPromise.all(mdPromises).catch(errorHandler)
|
||||
@ -187,7 +197,9 @@ export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<Pro
|
||||
ctx.allSlugs.push(...extraSlugs)
|
||||
}
|
||||
for (const [mdChunk, _] of mdResults) {
|
||||
childPromises.push(pool.exec("processHtml", [ctx.buildId, argv, mdChunk, ctx.allSlugs]))
|
||||
childPromises.push(
|
||||
pool.exec("processHtml", [ctx.buildId, ctx.quartzRoot, argv, mdChunk, ctx.allSlugs]),
|
||||
)
|
||||
}
|
||||
const results: ProcessedContent[][] = await WorkerPromise.all(childPromises).catch(errorHandler)
|
||||
|
||||
|
@ -18,4 +18,5 @@ export interface BuildCtx {
|
||||
argv: Argv
|
||||
cfg: QuartzConfig
|
||||
allSlugs: FullSlug[]
|
||||
quartzRoot: string
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ export const clone = rfdc()
|
||||
|
||||
// this file must be isomorphic so it can't use node libs (e.g. path)
|
||||
|
||||
export const QUARTZ = "quartz"
|
||||
|
||||
/// Utility type to simulate nominal types in TypeScript
|
||||
type SlugLike<T> = string & { __brand: T }
|
||||
|
||||
|
@ -6,7 +6,7 @@ export const options: sourceMapSupport.Options = {
|
||||
// source map hack to get around query param
|
||||
// import cache busting
|
||||
retrieveSourceMap(source) {
|
||||
if (source.includes(".quartz-cache")) {
|
||||
if (source.includes("?update")) {
|
||||
let realSource = fileURLToPath(source.split("?", 2)[0] + ".map")
|
||||
return {
|
||||
map: fs.readFileSync(realSource, "utf8"),
|
||||
|
@ -1,6 +1,5 @@
|
||||
import sourceMapSupport from "source-map-support"
|
||||
sourceMapSupport.install(options)
|
||||
import cfg from "../quartz.config"
|
||||
import { Argv, BuildCtx } from "./util/ctx"
|
||||
import { FilePath, FullSlug } from "./util/path"
|
||||
import {
|
||||
@ -12,9 +11,12 @@ import {
|
||||
import { options } from "./util/sourcemap"
|
||||
import { MarkdownContent, ProcessedContent } from "./plugins/vfile"
|
||||
|
||||
import cfg from "$config"
|
||||
|
||||
// only called from worker thread
|
||||
export async function parseMarkdown(
|
||||
buildId: string,
|
||||
quartzRoot: string,
|
||||
argv: Argv,
|
||||
fps: FilePath[],
|
||||
): Promise<[MarkdownContent[], FullSlug[]]> {
|
||||
@ -27,6 +29,7 @@ export async function parseMarkdown(
|
||||
cfg,
|
||||
argv,
|
||||
allSlugs,
|
||||
quartzRoot,
|
||||
}
|
||||
return [await createFileParser(ctx, fps)(createMdProcessor(ctx)), allSlugs]
|
||||
}
|
||||
@ -34,6 +37,7 @@ export async function parseMarkdown(
|
||||
// only called from worker thread
|
||||
export function processHtml(
|
||||
buildId: string,
|
||||
quartzRoot: string,
|
||||
argv: Argv,
|
||||
mds: MarkdownContent[],
|
||||
allSlugs: FullSlug[],
|
||||
@ -43,6 +47,7 @@ export function processHtml(
|
||||
cfg,
|
||||
argv,
|
||||
allSlugs,
|
||||
quartzRoot,
|
||||
}
|
||||
return createMarkdownParser(ctx, mds)(createHtmlProcessor(ctx))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user