diff --git a/.changeset/thick-cups-shout.md b/.changeset/thick-cups-shout.md new file mode 100644 index 0000000000..3aabb9ad40 --- /dev/null +++ b/.changeset/thick-cups-shout.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Fix crash during rendering of ogimage for VA sites with default icon. diff --git a/packages/gitbook/src/routes/icon.tsx b/packages/gitbook/src/routes/icon.tsx index 03a6f35224..ab3429d631 100644 --- a/packages/gitbook/src/routes/icon.tsx +++ b/packages/gitbook/src/routes/icon.tsx @@ -24,6 +24,11 @@ const SIZES = { }, }; +type RenderIconOptions = { + size: keyof typeof SIZES; + theme: 'light' | 'dark'; +}; + /** * Generate an icon for a site content. */ @@ -31,7 +36,7 @@ export async function serveIcon(context: GitBookSiteContext, req: Request) { const options = getOptions(req.url); const size = SIZES[options.size]; - const { site, customization } = context; + const { customization } = context; const customIcon = 'icon' in customization.favicon ? customization.favicon.icon : null; // If the site has a custom icon, redirect to it @@ -45,17 +50,45 @@ export async function serveIcon(context: GitBookSiteContext, req: Request) { ); } + return new ImageResponse(, { + width: size.width, + height: size.height, + headers: { + 'cache-tag': [ + getCacheTag({ + tag: 'site', + site: context.site.id, + }), + ].join(','), + }, + }); +} + +/** + * Render the icon as a React node. + */ +export function SiteDefaultIcon(props: { + context: GitBookSiteContext; + options: RenderIconOptions; + style?: React.CSSProperties; + tw?: string; +}) { + const { context, options, style, tw } = props; + const size = SIZES[options.size]; + + const { site, customization } = context; const contentTitle = site.title; - return new ImageResponse( + return (

-

, - { - width: size.width, - height: size.height, - headers: { - 'cache-tag': [ - getCacheTag({ - tag: 'site', - site: context.site.id, - }), - ].join(','), - }, - } + ); } diff --git a/packages/gitbook/src/routes/ogimage.tsx b/packages/gitbook/src/routes/ogimage.tsx index ce3f8a7d67..f79b86948f 100644 --- a/packages/gitbook/src/routes/ogimage.tsx +++ b/packages/gitbook/src/routes/ogimage.tsx @@ -20,13 +20,14 @@ import { getResizedImageURL, resizeImage, } from '@v2/lib/images'; +import { SiteDefaultIcon } from './icon'; /** * Render the OpenGraph image for a site content. */ export async function serveOGImage(baseContext: GitBookSiteContext, params: PageParams) { const { context, pageTarget } = await fetchPageData(baseContext, params); - const { customization, site, linker, imageResizer } = context; + const { customization, site, imageResizer } = context; const page = pageTarget?.page; // If user configured a custom social preview, we redirect to it. @@ -148,34 +149,36 @@ export async function serveOGImage(baseContext: GitBookSiteContext, params: Page } const faviconLoader = async () => { + if (customization.header.logo) { + // Don't load the favicon if we have a logo + // as it'll not be used. + return null; + } + + const faviconSize = { + width: 48, + height: 48, + }; + if ('icon' in customization.favicon) return ( Icon ); - if ('emoji' in customization.favicon) - return ( - - {String.fromCodePoint(Number.parseInt(`0x${customization.favicon.emoji}`))} - - ); - const iconImage = await fetchImage( - linker.toAbsoluteURL( - linker.toPathInSpace( - `~gitbook/icon?size=medium&theme=${customization.themes.default}` - ) - ) - ); - if (!iconImage) { - throw new Error('Icon image should always be fetchable'); - } - return Icon; + return ( + + ); }; const logoLoader = async () => { @@ -226,9 +229,9 @@ export async function serveOGImage(baseContext: GitBookSiteContext, params: Page Logo ) : ( -
+
{favicon} -

{transformText(site.title)}

+

{transformText(site.title)}

)}