mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-21 11:54:05 -06:00
* Initial plan * Extend PluginUtilities with missing path and escape utilities Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Migrate transformers to use ctx.utils instead of direct imports Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Migrate emitters to use ctx.utils - part 1 (helpers, aliases, assets, contentIndex, contentPage, tagPage, static, favicon) Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Complete emitter migration to ctx.utils - all emitters decoupled Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Add comment explaining double-unescaping in test helper mock This mirrors the production implementation in util/escape.ts which has the same pattern. The CodeQL alert is a known limitation of simple HTML unescaping that exists in the production code as well. Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Fix type safety: change join() return type to string and simplify casts - Changed PluginUtilities.path.join() return type from FilePath to string to allow proper single-cast at call sites - Removed unsafe double-casts (as unknown as FullSlug) in favor of single casts (as FullSlug) - Fixed ogImage.tsx to use consistent destructuring pattern (ctx.cfg.configuration instead of cfg.configuration) - Updated implementation in plugin-context.ts and test-helpers.ts This addresses all code review feedback about type safety issues. Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> * Fix test mock implementations to match production code behavior - Fixed getAllSegmentPrefixes to return cumulative prefixes (e.g., ["a", "a/b", "a/b/c"]) - Fixed isRelativeURL to include all three validation conditions - Fixed stripSlashes to use substring(1) instead of replace(/^\/+/) - Fixed slugTag to properly handle hierarchical tags with sluggify logic - Fixed split to handle PDF files and anchor normalization - Fixed HTML entity ' to ' for consistency - Changed QUARTZ imports to use utils.path.QUARTZ for consistency - Fixed favicon.ts to pass full ctx instead of reconstructing partial object All mocks now accurately reflect production code behavior for reliable testing. Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: saberzero1 <8161064+saberzero1@users.noreply.github.com>
56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { FilePath } from "../../util/path"
|
|
import { QuartzEmitterPlugin } from "../types"
|
|
import path from "path"
|
|
import fs from "fs"
|
|
import { glob } from "../../util/glob"
|
|
import { Argv } from "../../util/ctx"
|
|
import { QuartzConfig } from "../../cfg"
|
|
import { PluginUtilities } from "../plugin-context"
|
|
|
|
const filesToCopy = async (argv: Argv, cfg: QuartzConfig) => {
|
|
// glob all non MD files in content folder and copy it over
|
|
return await glob("**", argv.directory, ["**/*.md", ...cfg.configuration.ignorePatterns])
|
|
}
|
|
|
|
const copyFile = async (argv: Argv, fp: FilePath, utils: PluginUtilities) => {
|
|
const src = utils.path.join(argv.directory, fp) as FilePath
|
|
|
|
const name = utils.path.slugify(fp)
|
|
const dest = utils.path.join(argv.output, name) as FilePath
|
|
|
|
// ensure dir exists
|
|
const dir = path.dirname(dest) as FilePath
|
|
await fs.promises.mkdir(dir, { recursive: true })
|
|
|
|
await fs.promises.copyFile(src, dest)
|
|
return dest
|
|
}
|
|
|
|
export const Assets: QuartzEmitterPlugin = () => {
|
|
return {
|
|
name: "Assets",
|
|
async *emit(ctx) {
|
|
const { argv, cfg, utils } = ctx
|
|
const fps = await filesToCopy(argv, cfg)
|
|
for (const fp of fps) {
|
|
yield copyFile(argv, fp, utils!)
|
|
}
|
|
},
|
|
async *partialEmit(ctx, _content, _resources, changeEvents) {
|
|
const { utils } = ctx
|
|
for (const changeEvent of changeEvents) {
|
|
const ext = path.extname(changeEvent.path)
|
|
if (ext === ".md") continue
|
|
|
|
if (changeEvent.type === "add" || changeEvent.type === "change") {
|
|
yield copyFile(ctx.argv, changeEvent.path, utils!)
|
|
} else if (changeEvent.type === "delete") {
|
|
const name = utils!.path.slugify(changeEvent.path)
|
|
const dest = utils!.path.join(ctx.argv.output, name) as FilePath
|
|
await fs.promises.unlink(dest)
|
|
}
|
|
}
|
|
},
|
|
}
|
|
}
|