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]
|
> [!note]
|
||||||
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
|
> 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
|
## 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 { QuartzEmitterPlugin } from "../types"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
import sharp, { FitEnum } from "sharp"
|
||||||
|
import { styleText } from "util"
|
||||||
import { glob } from "../../util/glob"
|
import { glob } from "../../util/glob"
|
||||||
import { Argv } from "../../util/ctx"
|
import { Argv } from "../../util/ctx"
|
||||||
import { QuartzConfig } from "../../cfg"
|
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) => {
|
const filesToCopy = async (argv: Argv, cfg: QuartzConfig) => {
|
||||||
// glob all non MD files in content folder and copy it over
|
// glob all non MD files in content folder and copy it over
|
||||||
return await glob("**", argv.directory, ["**/*.md", ...cfg.configuration.ignorePatterns])
|
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 src = joinSegments(argv.directory, fp) as FilePath
|
||||||
|
|
||||||
const name = slugifyFilePath(fp)
|
const name = slugifyFilePath(fp)
|
||||||
const dest = joinSegments(argv.output, name) as FilePath
|
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
|
const dir = path.dirname(dest) as FilePath
|
||||||
await fs.promises.mkdir(dir, { recursive: true })
|
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
|
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 {
|
return {
|
||||||
name: "Assets",
|
name: "Assets",
|
||||||
async *emit({ argv, cfg }) {
|
async *emit({ argv, cfg }) {
|
||||||
const fps = await filesToCopy(argv, cfg)
|
const fps = await filesToCopy(argv, cfg)
|
||||||
for (const fp of fps) {
|
for (const fp of fps) {
|
||||||
yield copyFile(argv, fp)
|
yield copyFile(argv, fp, opts)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async *partialEmit(ctx, _content, _resources, changeEvents) {
|
async *partialEmit(ctx, _content, _resources, changeEvents) {
|
||||||
@ -40,7 +85,7 @@ export const Assets: QuartzEmitterPlugin = () => {
|
|||||||
if (ext === ".md") continue
|
if (ext === ".md") continue
|
||||||
|
|
||||||
if (changeEvent.type === "add" || changeEvent.type === "change") {
|
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") {
|
} else if (changeEvent.type === "delete") {
|
||||||
const name = slugifyFilePath(changeEvent.path)
|
const name = slugifyFilePath(changeEvent.path)
|
||||||
const dest = joinSegments(ctx.argv.output, name) as FilePath
|
const dest = joinSegments(ctx.argv.output, name) as FilePath
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user