This commit is contained in:
松浦 知也 Matsuura Tomoya 2025-12-09 02:23:58 +07:00 committed by GitHub
commit a1dd294ca7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 46 deletions

View File

@ -261,35 +261,35 @@ async function rebuild(changes: ChangeEvent[], clientRefresh: () => void, buildD
.map((file) => file.content),
)
let emittedFiles = 0
for (const emitter of cfg.plugins.emitters) {
// Try to use partialEmit if available, otherwise assume the output is static
const emitFn = emitter.partialEmit ?? emitter.emit
const emitted = await emitFn(ctx, processedFiles, staticResources, changeEvents)
if (emitted === null) {
continue
}
if (Symbol.asyncIterator in emitted) {
// Async generator case
for await (const file of emitted) {
emittedFiles++
if (ctx.argv.verbose) {
console.log(`[emit:${emitter.name}] ${file}`)
}
const emittedFiles = await Promise.all(
cfg.plugins.emitters.map(async (emitter) => {
const emitFn = emitter.partialEmit ?? emitter.emit
const emitted = emitFn(ctx, processedFiles, staticResources, changeEvents)
if (emitted === null) {
return 0
}
} else {
// Array case
emittedFiles += emitted.length
if (ctx.argv.verbose) {
for (const file of emitted) {
console.log(`[emit:${emitter.name}] ${file}`)
if (Symbol.asyncIterator in emitted) {
let emittedFiles = 0
// Async generator case
for await (const file of emitted) {
emittedFiles++
if (ctx.argv.verbose) {
console.log(`[emit:${emitter.name}] ${file}`)
}
}
return emittedFiles
} else {
// Array case
return await Promise.all(
(await emitted).map((file) => {
console.log(`[emit:${emitter.name}] ${file}`)
}),
).then((files) => files.length)
}
}
}
console.log(`Emitted ${emittedFiles} files to \`${argv.output}\` in ${perf.timeSince("rebuild")}`)
}),
)
const sumFiles = emittedFiles.reduce((a, b) => a + b)
console.log(`Emitted ${sumFiles} files to \`${argv.output}\` in ${perf.timeSince("rebuild")}`)
console.log(styleText("green", `Done rebuilding in ${perf.timeSince()}`))
changes.splice(0, numChangesInBuild)
clientRefresh()

View File

@ -1,7 +1,14 @@
import { QuartzEmitterPlugin } from "../types"
import { i18n } from "../../i18n"
import { unescapeHTML } from "../../util/escape"
import { FullSlug, getFileExtension, isAbsoluteURL, joinSegments, QUARTZ } from "../../util/path"
import {
FilePath,
FullSlug,
getFileExtension,
isAbsoluteURL,
joinSegments,
QUARTZ,
} from "../../util/path"
import { ImageOptions, SocialImageOptions, defaultImage, getSatoriFonts } from "../../util/og"
import sharp from "sharp"
import satori, { SatoriOptions } from "satori"
@ -109,16 +116,20 @@ export const CustomOgImages: QuartzEmitterPlugin<Partial<SocialImageOptions>> =
getQuartzComponents() {
return []
},
async *emit(ctx, content, _resources) {
async emit(ctx, content, _resources): Promise<FilePath[]> {
const cfg = ctx.cfg.configuration
const headerFont = cfg.theme.typography.header
const bodyFont = cfg.theme.typography.body
const fonts = await getSatoriFonts(headerFont, bodyFont)
for (const [_tree, vfile] of content) {
if (vfile.data.frontmatter?.socialImage !== undefined) continue
yield processOgImage(ctx, vfile.data, fonts, fullOptions)
}
return Promise.all(
content
.filter(
([_tree, vfile]) =>
vfile.data.frontmatter?.socialImage === undefined &&
vfile.data.filePath !== undefined,
)
.map(([_tree, vfile]) => processOgImage(ctx, vfile.data, fonts, fullOptions)),
)
},
async *partialEmit(ctx, _content, _resources, changeEvents) {
const cfg = ctx.cfg.configuration

View File

@ -13,14 +13,14 @@ export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
log.start(`Emitting files`)
let emittedFiles = 0
const staticResources = getStaticResourcesFromPlugins(ctx)
await Promise.all(
const emittedFiles = await Promise.all(
cfg.plugins.emitters.map(async (emitter) => {
try {
const emitted = await emitter.emit(ctx, content, staticResources)
const emitted = emitter.emit(ctx, content, staticResources)
if (Symbol.asyncIterator in emitted) {
// Async generator case
let emittedFiles = 0
for await (const file of emitted) {
emittedFiles++
if (ctx.argv.verbose) {
@ -29,22 +29,27 @@ export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
log.updateText(`${emitter.name} -> ${styleText("gray", file)}`)
}
}
return emittedFiles
} else {
// Array case
emittedFiles += emitted.length
for (const file of emitted) {
if (ctx.argv.verbose) {
console.log(`[emit:${emitter.name}] ${file}`)
} else {
log.updateText(`${emitter.name} -> ${styleText("gray", file)}`)
}
}
return (
await Promise.all(
(await emitted).map((file) => {
if (ctx.argv.verbose) {
console.log(`[emit:${emitter.name}] ${file}`)
} else {
log.updateText(`${emitter.name} -> ${styleText("gray", file)}`)
}
}),
)
).length
}
} catch (err) {
trace(`Failed to emit from plugin \`${emitter.name}\``, err as Error)
return 0
}
}),
)
log.end(`Emitted ${emittedFiles} files to \`${argv.output}\` in ${perf.timeSince()}`)
const sumFiles = emittedFiles.reduce((a, b) => a + b)
log.end(`Emitted ${sumFiles} files to \`${argv.output}\` in ${perf.timeSince()}`)
}