mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-19 10:54:06 -06:00
Merge 6d8ecd33fa into bacd19c4ea
This commit is contained in:
commit
b43e3272cb
@ -11,7 +11,10 @@ Note that all static assets will then be accessible through its path on your gen
|
||||
> [!note]
|
||||
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
||||
|
||||
This plugin has no configuration options.
|
||||
This plugin accepts the following configuration options:
|
||||
|
||||
- `resizeImages`: A subset of the [Sharp resizing options](https://sharp.pixelplumbing.com/api-resize). Defaults to `{ width: 1700, fit: 'inside' }`.
|
||||
- `compressImages`: If `true` (default), enable image compression. Disable to copy images as-is without modification.
|
||||
|
||||
## API
|
||||
|
||||
|
||||
@ -1,19 +1,33 @@
|
||||
import { FilePath, joinSegments, slugifyFilePath } from "../../util/path"
|
||||
import { FilePath, joinSegments, slugifyFilePath, getFileExtension } from "../../util/path"
|
||||
import { QuartzEmitterPlugin } from "../types"
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
import sharp, { FitEnum } from "sharp"
|
||||
import { styleText } from "util"
|
||||
import { glob } from "../../util/glob"
|
||||
import { Argv } from "../../util/ctx"
|
||||
import { QuartzConfig } from "../../cfg"
|
||||
|
||||
interface Options {
|
||||
resizeImages?: { width?: number; height?: number; fit?: keyof FitEnum }
|
||||
compressImages?: boolean
|
||||
}
|
||||
|
||||
const defaultOptions: Options = {
|
||||
resizeImages: { width: 1700, fit: "inside" },
|
||||
compressImages: true,
|
||||
}
|
||||
|
||||
// Accepted Sharp formats https://sharp.pixelplumbing.com/#formats
|
||||
const imageExtensions = [".png", ".jpg", ".jpeg", ".webp", ".gif", ".avif", ".tif", ".tiff", ".svg"]
|
||||
|
||||
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) => {
|
||||
const copyFile = async (argv: Argv, fp: FilePath, opts: Options) => {
|
||||
const src = joinSegments(argv.directory, fp) as FilePath
|
||||
|
||||
const name = slugifyFilePath(fp)
|
||||
const dest = joinSegments(argv.output, name) as FilePath
|
||||
|
||||
@ -21,17 +35,48 @@ const copyFile = async (argv: Argv, fp: FilePath) => {
|
||||
const dir = path.dirname(dest) as FilePath
|
||||
await fs.promises.mkdir(dir, { recursive: true })
|
||||
|
||||
await fs.promises.copyFile(src, dest)
|
||||
const ext = getFileExtension(fp)?.toLowerCase()
|
||||
if (ext && imageExtensions.includes(ext)) {
|
||||
await copyImage(src, dest, opts)
|
||||
} else {
|
||||
await copyBlob(src, dest)
|
||||
}
|
||||
|
||||
return dest
|
||||
}
|
||||
|
||||
export const Assets: QuartzEmitterPlugin = () => {
|
||||
const copyImage = async (src: FilePath, dest: FilePath, opts: Options) => {
|
||||
if (!opts.compressImages) {
|
||||
await copyBlob(src, dest)
|
||||
} else if (opts.resizeImages) {
|
||||
await sharp(src).resize(opts.resizeImages).toFile(dest)
|
||||
} else {
|
||||
await sharp(src).toFile(dest)
|
||||
}
|
||||
}
|
||||
|
||||
const copyBlob = async (src: FilePath, dest: FilePath) => {
|
||||
await fs.promises.copyFile(src, dest)
|
||||
}
|
||||
|
||||
export const Assets: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
|
||||
opts = { ...defaultOptions, ...opts }
|
||||
|
||||
if ((opts.resizeImages?.width || opts.resizeImages?.height) && !opts.compressImages) {
|
||||
console.warn(
|
||||
styleText(
|
||||
"yellow",
|
||||
"Your asset resizing options are incompatible - enable compression to resize images",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
name: "Assets",
|
||||
async *emit({ argv, cfg }) {
|
||||
const fps = await filesToCopy(argv, cfg)
|
||||
for (const fp of fps) {
|
||||
yield copyFile(argv, fp)
|
||||
yield copyFile(argv, fp, opts)
|
||||
}
|
||||
},
|
||||
async *partialEmit(ctx, _content, _resources, changeEvents) {
|
||||
@ -40,7 +85,7 @@ export const Assets: QuartzEmitterPlugin = () => {
|
||||
if (ext === ".md") continue
|
||||
|
||||
if (changeEvent.type === "add" || changeEvent.type === "change") {
|
||||
yield copyFile(ctx.argv, changeEvent.path)
|
||||
yield copyFile(ctx.argv, changeEvent.path, opts)
|
||||
} else if (changeEvent.type === "delete") {
|
||||
const name = slugifyFilePath(changeEvent.path)
|
||||
const dest = joinSegments(ctx.argv.output, name) as FilePath
|
||||
|
||||
Loading…
Reference in New Issue
Block a user