From 1ab8dffd0deb1fc48c7fa9c2092f7d1cd0ba68c3 Mon Sep 17 00:00:00 2001 From: Ben Schlegel Date: Fri, 29 Sep 2023 17:24:25 +0200 Subject: [PATCH] feat: option for users to provide own image struct (satori) This allows users to pass their own jsx for generating the default og image --- quartz/cfg.ts | 2 +- quartz/components/Head.tsx | 12 ++++-------- quartz/util/defaultImage.tsx | 1 - quartz/util/imageHelper.ts | 22 ++++++++++++++++------ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/quartz/cfg.ts b/quartz/cfg.ts index c6eea8e68..4d1ac664d 100644 --- a/quartz/cfg.ts +++ b/quartz/cfg.ts @@ -37,7 +37,7 @@ export interface GlobalConfiguration { /** * Wether to generate and use social images (Open Graph and Twitter standard) for link previews */ - generateSocialImages: boolean | SocialImageOptions + generateSocialImages: boolean | Partial theme: Theme } diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx index e3e433d11..1c95091f4 100644 --- a/quartz/components/Head.tsx +++ b/quartz/components/Head.tsx @@ -14,16 +14,11 @@ import { unescapeHTML } from "../util/escape" * @param opts options for generating image */ async function generateSocialImage(opts: ImageOptions, userOpts: SocialImageOptions) { - const { cfg, description, fileName, fontsPromise, title, imageHtml } = opts + const { cfg, description, fileName, fontsPromise, title } = opts const fonts = await fontsPromise - const defaultImg = defaultImage(cfg, userOpts, title, description, fonts) - - // If imageHtml was passed, use it. otherwise, use default image element - let imageElement: JSXInternal.Element = defaultImg - if (imageHtml) { - imageElement = imageHtml(cfg, title, description, fonts) - } + // JSX that will be used to generate satori svg + const imageElement = userOpts.imageStructure(cfg, userOpts, title, description, fonts) const svg = await satori(imageElement, { width: userOpts.width, @@ -46,6 +41,7 @@ const defaultOptions: SocialImageOptions = { colorScheme: "lightMode", width: 1200, height: 676, + imageStructure: defaultImage, } export default (() => { diff --git a/quartz/util/defaultImage.tsx b/quartz/util/defaultImage.tsx index 88b18f978..ec65b5943 100644 --- a/quartz/util/defaultImage.tsx +++ b/quartz/util/defaultImage.tsx @@ -2,7 +2,6 @@ import { SatoriOptions } from "satori/wasm" import { GlobalConfiguration } from "../cfg" import { SocialImageOptions } from "./imageHelper" -// TODO: proper typing export const defaultImage = ( cfg: GlobalConfiguration, userOpts: SocialImageOptions, diff --git a/quartz/util/imageHelper.ts b/quartz/util/imageHelper.ts index 30353a040..062fadcf6 100644 --- a/quartz/util/imageHelper.ts +++ b/quartz/util/imageHelper.ts @@ -63,6 +63,22 @@ export type SocialImageOptions = { * Width to generate image with in pixels (should be around 1200px) */ width: number + /** + * JSX to use for generating image. See satori docs for more info (https://github.com/vercel/satori) + * @param cfg global quartz config + * @param userOpts options that can be set by user + * @param title title of current page + * @param description description of current page + * @param fonts global font that can be used for styling + * @returns prepared jsx to be used for generating image + */ + imageStructure: ( + cfg: GlobalConfiguration, + userOpts: SocialImageOptions, + title: string, + description: string, + fonts: SatoriOptions["fonts"], + ) => JSXInternal.Element } export type ImageOptions = { @@ -94,10 +110,4 @@ export type ImageOptions = { * `GlobalConfiguration` of quartz (used for theme/typography) */ cfg: GlobalConfiguration - imageHtml?: ( - cfg: GlobalConfiguration, - title: string, - description: string, - fonts: SatoriOptions["fonts"], - ) => JSXInternal.Element }