mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-05-19 15:04:23 +02:00
Compare commits
No commits in common. "f301eca9a72953aee5a65e55dfeaaa9c4b1b2516" and "c5a8b199ae833f974b3c1cac253039fcf9758423" have entirely different histories.
f301eca9a7
...
c5a8b199ae
@ -107,35 +107,27 @@ export const myImage: SocialImageOptions["imageStructure"] = (...) => {
|
|||||||
> import fs from "fs"
|
> import fs from "fs"
|
||||||
> import path from "path"
|
> import path from "path"
|
||||||
>
|
>
|
||||||
> const newsreaderFontPath = joinSegments(QUARTZ, "static", "Newsreader.woff2")
|
> const headerFont = joinSegments(QUARTZ, "static", "Newsreader.woff2")
|
||||||
> export async function getSatoriFonts(headerFont: FontSpecification, bodyFont: FontSpecification) {
|
> const bodyFont = joinSegments(QUARTZ, "static", "Newsreader.woff2")
|
||||||
> // ... rest of implementation remains same
|
|
||||||
> const fonts: SatoriOptions["fonts"] = [
|
|
||||||
> ...headerFontData.map((data, idx) => ({
|
|
||||||
> name: headerFontName,
|
|
||||||
> data,
|
|
||||||
> weight: headerWeights[idx],
|
|
||||||
> style: "normal" as const,
|
|
||||||
> })),
|
|
||||||
> ...bodyFontData.map((data, idx) => ({
|
|
||||||
> name: bodyFontName,
|
|
||||||
> data,
|
|
||||||
> weight: bodyWeights[idx],
|
|
||||||
> style: "normal" as const,
|
|
||||||
> })),
|
|
||||||
> {
|
|
||||||
> name: "Newsreader",
|
|
||||||
> data: await fs.promises.readFile(path.resolve(newsreaderFontPath)),
|
|
||||||
> weight: 400,
|
|
||||||
> style: "normal" as const,
|
|
||||||
> },
|
|
||||||
> ]
|
|
||||||
>
|
>
|
||||||
> return fonts
|
> export async function getSatoriFont(cfg: GlobalConfiguration): Promise<SatoriOptions["fonts"]> {
|
||||||
|
> const headerWeight: FontWeight = 700
|
||||||
|
> const bodyWeight: FontWeight = 400
|
||||||
|
>
|
||||||
|
> const [header, body] = await Promise.all(
|
||||||
|
> [headerFont, bodyFont].map((font) =>
|
||||||
|
> fs.promises.readFile(path.resolve(font))
|
||||||
|
> ),
|
||||||
|
> )
|
||||||
|
>
|
||||||
|
> return [
|
||||||
|
> { name: cfg.theme.typography.header, data: header, weight: headerWeight, style: "normal" },
|
||||||
|
> { name: cfg.theme.typography.body, data: body, weight: bodyWeight, style: "normal" },
|
||||||
|
> ]
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> This font then can be used with your custom structure.
|
> This font then can be used with your custom structure
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -250,25 +250,15 @@ async function partialRebuildFromEntrypoint(
|
|||||||
([_node, vfile]) => !toRemove.has(vfile.data.filePath!),
|
([_node, vfile]) => !toRemove.has(vfile.data.filePath!),
|
||||||
)
|
)
|
||||||
|
|
||||||
const emitted = await emitter.emit(ctx, files, staticResources)
|
const emittedFps = await emitter.emit(ctx, files, staticResources)
|
||||||
if (Symbol.asyncIterator in emitted) {
|
|
||||||
// Async generator case
|
|
||||||
for await (const file of emitted) {
|
|
||||||
emittedFiles++
|
|
||||||
if (ctx.argv.verbose) {
|
if (ctx.argv.verbose) {
|
||||||
|
for (const file of emittedFps) {
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
console.log(`[emit:${emitter.name}] ${file}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Array case
|
|
||||||
emittedFiles += emitted.length
|
|
||||||
if (ctx.argv.verbose) {
|
|
||||||
for (const file of emitted) {
|
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
emittedFiles += emittedFps.length
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,24 +280,15 @@ async function partialRebuildFromEntrypoint(
|
|||||||
.filter((file) => !toRemove.has(file))
|
.filter((file) => !toRemove.has(file))
|
||||||
.map((file) => contentMap.get(file)!)
|
.map((file) => contentMap.get(file)!)
|
||||||
|
|
||||||
const emitted = await emitter.emit(ctx, upstreamContent, staticResources)
|
const emittedFps = await emitter.emit(ctx, upstreamContent, staticResources)
|
||||||
if (Symbol.asyncIterator in emitted) {
|
|
||||||
// Async generator case
|
|
||||||
for await (const file of emitted) {
|
|
||||||
emittedFiles++
|
|
||||||
if (ctx.argv.verbose) {
|
if (ctx.argv.verbose) {
|
||||||
|
for (const file of emittedFps) {
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
console.log(`[emit:${emitter.name}] ${file}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Array case
|
emittedFiles += emittedFps.length
|
||||||
emittedFiles += emitted.length
|
|
||||||
if (ctx.argv.verbose) {
|
|
||||||
for (const file of emitted) {
|
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { QuartzEmitterPlugin } from "../types"
|
|||||||
import { i18n } from "../../i18n"
|
import { i18n } from "../../i18n"
|
||||||
import { unescapeHTML } from "../../util/escape"
|
import { unescapeHTML } from "../../util/escape"
|
||||||
import { FullSlug, getFileExtension } from "../../util/path"
|
import { FullSlug, getFileExtension } from "../../util/path"
|
||||||
import { ImageOptions, SocialImageOptions, defaultImage, getSatoriFonts } from "../../util/og"
|
import { ImageOptions, SocialImageOptions, defaultImage, getSatoriFont } from "../../util/og"
|
||||||
import { getFontSpecificationName } from "../../util/theme"
|
import { getFontSpecificationName } from "../../util/theme"
|
||||||
import sharp from "sharp"
|
import sharp from "sharp"
|
||||||
import satori from "satori"
|
import satori from "satori"
|
||||||
@ -54,9 +54,9 @@ export const CustomOgImages: QuartzEmitterPlugin<Partial<SocialImageOptions>> =
|
|||||||
},
|
},
|
||||||
async *emit(ctx, content, _resources) {
|
async *emit(ctx, content, _resources) {
|
||||||
const cfg = ctx.cfg.configuration
|
const cfg = ctx.cfg.configuration
|
||||||
const headerFont = cfg.theme.typography.header
|
const headerFont = getFontSpecificationName(cfg.theme.typography.header)
|
||||||
const bodyFont = cfg.theme.typography.body
|
const bodyFont = getFontSpecificationName(cfg.theme.typography.body)
|
||||||
const fonts = await getSatoriFonts(headerFont, bodyFont)
|
const fonts = await getSatoriFont(headerFont, bodyFont)
|
||||||
|
|
||||||
for (const [_tree, vfile] of content) {
|
for (const [_tree, vfile] of content) {
|
||||||
// if this file defines socialImage, we can skip
|
// if this file defines socialImage, we can skip
|
||||||
|
@ -20,7 +20,9 @@ export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
|
|||||||
const emitted = await emitter.emit(ctx, content, staticResources)
|
const emitted = await emitter.emit(ctx, content, staticResources)
|
||||||
if (Symbol.asyncIterator in emitted) {
|
if (Symbol.asyncIterator in emitted) {
|
||||||
// Async generator case
|
// Async generator case
|
||||||
|
const files: string[] = []
|
||||||
for await (const file of emitted) {
|
for await (const file of emitted) {
|
||||||
|
files.push(file)
|
||||||
emittedFiles++
|
emittedFiles++
|
||||||
if (ctx.argv.verbose) {
|
if (ctx.argv.verbose) {
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
console.log(`[emit:${emitter.name}] ${file}`)
|
||||||
|
@ -2,49 +2,29 @@ import { FontWeight, SatoriOptions } from "satori/wasm"
|
|||||||
import { GlobalConfiguration } from "../cfg"
|
import { GlobalConfiguration } from "../cfg"
|
||||||
import { QuartzPluginData } from "../plugins/vfile"
|
import { QuartzPluginData } from "../plugins/vfile"
|
||||||
import { JSXInternal } from "preact/src/jsx"
|
import { JSXInternal } from "preact/src/jsx"
|
||||||
import { FontSpecification, ThemeKey } from "./theme"
|
import { ThemeKey } from "./theme"
|
||||||
|
|
||||||
const defaultHeaderWeight = [700]
|
/**
|
||||||
const defaultBodyWeight = [400]
|
* Get an array of `FontOptions` (for satori) given google font names
|
||||||
export async function getSatoriFonts(headerFont: FontSpecification, bodyFont: FontSpecification) {
|
* @param headerFontName name of google font used for header
|
||||||
// Get all weights for header and body fonts
|
* @param bodyFontName name of google font used for body
|
||||||
const headerWeights: FontWeight[] = (
|
* @returns FontOptions for header and body
|
||||||
typeof headerFont === "string"
|
*/
|
||||||
? defaultHeaderWeight
|
export async function getSatoriFont(headerFontName: string, bodyFontName: string) {
|
||||||
: (headerFont.weights ?? defaultHeaderWeight)
|
const headerWeight = 700 as FontWeight
|
||||||
) as FontWeight[]
|
const bodyWeight = 400 as FontWeight
|
||||||
const bodyWeights: FontWeight[] = (
|
|
||||||
typeof bodyFont === "string" ? defaultBodyWeight : (bodyFont.weights ?? defaultBodyWeight)
|
|
||||||
) as FontWeight[]
|
|
||||||
|
|
||||||
const headerFontName = typeof headerFont === "string" ? headerFont : headerFont.name
|
// Fetch fonts
|
||||||
const bodyFontName = typeof bodyFont === "string" ? bodyFont : bodyFont.name
|
const [headerFont, bodyFont] = await Promise.all([
|
||||||
|
fetchTtf(headerFontName, headerWeight),
|
||||||
// Fetch fonts for all weights
|
fetchTtf(bodyFontName, bodyWeight),
|
||||||
const headerFontPromises = headerWeights.map((weight) => fetchTtf(headerFontName, weight))
|
|
||||||
const bodyFontPromises = bodyWeights.map((weight) => fetchTtf(bodyFontName, weight))
|
|
||||||
|
|
||||||
const [headerFontData, bodyFontData] = await Promise.all([
|
|
||||||
Promise.all(headerFontPromises),
|
|
||||||
Promise.all(bodyFontPromises),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
// Convert fonts to satori font format and return
|
// Convert fonts to satori font format and return
|
||||||
const fonts: SatoriOptions["fonts"] = [
|
const fonts: SatoriOptions["fonts"] = [
|
||||||
...headerFontData.map((data, idx) => ({
|
{ name: headerFontName, data: headerFont, weight: headerWeight, style: "normal" },
|
||||||
name: headerFontName,
|
{ name: bodyFontName, data: bodyFont, weight: bodyWeight, style: "normal" },
|
||||||
data,
|
|
||||||
weight: headerWeights[idx],
|
|
||||||
style: "normal" as const,
|
|
||||||
})),
|
|
||||||
...bodyFontData.map((data, idx) => ({
|
|
||||||
name: bodyFontName,
|
|
||||||
data,
|
|
||||||
weight: bodyWeights[idx],
|
|
||||||
style: "normal" as const,
|
|
||||||
})),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return fonts
|
return fonts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ interface Colors {
|
|||||||
darkMode: ColorScheme
|
darkMode: ColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FontSpecification =
|
type FontSpecification =
|
||||||
| string
|
| string
|
||||||
| {
|
| {
|
||||||
name: string
|
name: string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user