mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-28 07:14:05 -06:00
refactor: make image generation cleaner
This commit is contained in:
parent
3a47f383b0
commit
bb9e857bf7
@ -14,21 +14,56 @@ export type SocialImageOptions = {
|
||||
colorScheme?: "lightMode" | "darkMode"
|
||||
}
|
||||
|
||||
type ImageOptions = {
|
||||
/**
|
||||
* what title to use as header in image
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* what description to use as body in image
|
||||
*/
|
||||
description: string
|
||||
/**
|
||||
* what fileName to use when writing to disk
|
||||
*/
|
||||
fileName: string
|
||||
/**
|
||||
* what directory to store image in
|
||||
*/
|
||||
fileDir: string
|
||||
/**
|
||||
* what file extension to use (should be `webp` unless you also change sharp conversion)
|
||||
*/
|
||||
fileExt: string
|
||||
/**
|
||||
* What height to generate image with (in px)
|
||||
*/
|
||||
imgHeight: number
|
||||
/**
|
||||
* What width to generate image with (in px)
|
||||
*/
|
||||
imgWidth: number
|
||||
/**
|
||||
* header + body font to be used when generating satori image (as promise to work around sync in component)
|
||||
*/
|
||||
fontsPromise: Promise<SatoriOptions["fonts"]>
|
||||
/**
|
||||
* `GlobalConfiguration` of quartz (used for theme/typography)
|
||||
*/
|
||||
cfg: GlobalConfiguration
|
||||
imageHtml?: (
|
||||
cfg: GlobalConfiguration,
|
||||
title: string,
|
||||
description: string,
|
||||
) => Parameters<typeof satori>["0"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates social image (OG/twitter standard) and saves it as `.web` inside the public folder
|
||||
* @param title what title to use
|
||||
* @param description what description to use
|
||||
* @param fileName what fileName to use when writing to disk
|
||||
* @param fontsPromise header + body font to be used when generating satori image (as promise to work around sync in component)
|
||||
* @param cfg `GlobalConfiguration` of quartz
|
||||
* @param opts options for generating image
|
||||
*/
|
||||
async function generateSocialImage(
|
||||
title: string,
|
||||
description: string,
|
||||
fileName: string,
|
||||
fontsPromise: Promise<SatoriOptions["fonts"]>,
|
||||
cfg: GlobalConfiguration,
|
||||
) {
|
||||
async function generateSocialImage(opts: ImageOptions) {
|
||||
const { cfg, description, fileName, fontsPromise, title, imageHtml } = opts
|
||||
const fonts = await fontsPromise
|
||||
|
||||
// How many characters are allowed before switching to smaller font
|
||||
@ -126,7 +161,8 @@ export default (() => {
|
||||
fontsPromise = getSatoriFont(cfg.theme.typography.header, cfg.theme.typography.body)
|
||||
}
|
||||
const slug = fileData.filePath
|
||||
const filePath = slug?.replaceAll("/", "-")
|
||||
// since "/" is not a valid character in file names, replace with "-"
|
||||
const fileName = slug?.replaceAll("/", "-")
|
||||
const title = fileData.frontmatter?.title ?? "Untitled"
|
||||
|
||||
// Get file description (priority: frontmatter > fileData > default)
|
||||
@ -141,8 +177,20 @@ export default (() => {
|
||||
fs.mkdirSync(imageDir, { recursive: true })
|
||||
}
|
||||
|
||||
// Generate social image (happens async)
|
||||
generateSocialImage(title, description, filePath as string, fontsPromise, cfg)
|
||||
if (fileName) {
|
||||
// Generate social image (happens async)
|
||||
generateSocialImage({
|
||||
title,
|
||||
description,
|
||||
fileName,
|
||||
fileDir: imageDir,
|
||||
imgHeight: ogHeight,
|
||||
imgWidth: ogWidth,
|
||||
fileExt: extension,
|
||||
fontsPromise,
|
||||
cfg,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const { css, js } = externalResources
|
||||
@ -157,10 +205,10 @@ export default (() => {
|
||||
const ogImageGeneratedPath = `https://${cfg.baseUrl}/${imageDir.replace(
|
||||
"public/",
|
||||
"",
|
||||
)}/${filePath}.${extension}`
|
||||
)}/${fileName}.${extension}`
|
||||
|
||||
// Use default og image if filePath doesnt exist (for autogenerated paths with no .md file)
|
||||
const useDefaultOgImage = filePath === undefined || !cfg.generateSocialImages
|
||||
const useDefaultOgImage = fileName === undefined || !cfg.generateSocialImages
|
||||
|
||||
// Path to og/social image (priority: frontmatter > generated image (if enabled) > default image)
|
||||
let ogImagePath = useDefaultOgImage ? ogImageDefaultPath : ogImageGeneratedPath
|
||||
@ -185,11 +233,11 @@ export default (() => {
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image:type" content={`image/${extension}`} />
|
||||
<meta property="og:image:alt" content={description} />
|
||||
<meta property="og:image:width" content={"" + ogWidth} />
|
||||
<meta property="og:image:height" content={"" + ogHeight} />
|
||||
<meta property="og:image:width" content={ogWidth.toString()} />
|
||||
<meta property="og:image:height" content={ogHeight.toString()} />
|
||||
<meta property="og:image:url" content={ogImagePath} />
|
||||
<meta property="og:width" content={"" + ogWidth} />
|
||||
<meta property="og:height" content={"" + ogHeight} />
|
||||
<meta property="og:width" content={ogWidth.toString()} />
|
||||
<meta property="og:height" content={ogHeight.toString()} />
|
||||
{cfg.baseUrl && (
|
||||
<>
|
||||
<meta name="twitter:image" content={ogImagePath} />
|
||||
|
||||
5
quartz/util/defaultImage.tsx
Normal file
5
quartz/util/defaultImage.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { GlobalConfiguration } from "../cfg"
|
||||
|
||||
export const defaultImage = (cfg: GlobalConfiguration, title: string, description: string) => (
|
||||
<div />
|
||||
)
|
||||
Loading…
Reference in New Issue
Block a user