mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-21 01:53:26 +00:00
Resize and optimize ogimage and favicons (#2980)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Optimize favicons and og:image using the image resizer
|
||||
@@ -13,6 +13,7 @@ import { buildVersion } from '@/lib/build';
|
||||
import { isSiteIndexable } from '@/lib/seo';
|
||||
|
||||
import { GITBOOK_API_PUBLIC_URL, GITBOOK_ASSETS_URL, GITBOOK_ICONS_URL } from '@v2/lib/env';
|
||||
import { getResizedImageURL } from '@v2/lib/images';
|
||||
import { ClientContexts } from './ClientContexts';
|
||||
import { RocketLoaderDetector } from './RocketLoaderDetector';
|
||||
|
||||
@@ -96,33 +97,43 @@ export async function generateSiteLayoutViewport(context: GitBookSiteContext): P
|
||||
}
|
||||
|
||||
export async function generateSiteLayoutMetadata(context: GitBookSiteContext): Promise<Metadata> {
|
||||
const { site, customization, linker } = context;
|
||||
const { site, customization, linker, imageResizer } = context;
|
||||
const customIcon = 'icon' in customization.favicon ? customization.favicon.icon : null;
|
||||
|
||||
const faviconSize = 48;
|
||||
const icons = [
|
||||
{
|
||||
url: customIcon?.light
|
||||
? await getResizedImageURL(imageResizer, customIcon.light, {
|
||||
width: faviconSize,
|
||||
height: faviconSize,
|
||||
})
|
||||
: linker.toAbsoluteURL(
|
||||
linker.toPathInContent('~gitbook/icon?size=small&theme=light')
|
||||
),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: light)',
|
||||
},
|
||||
{
|
||||
url: customIcon?.dark
|
||||
? await getResizedImageURL(imageResizer, customIcon.dark, {
|
||||
width: faviconSize,
|
||||
height: faviconSize,
|
||||
})
|
||||
: linker.toAbsoluteURL(
|
||||
linker.toPathInContent('~gitbook/icon?size=small&theme=dark')
|
||||
),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: dark)',
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
title: site.title,
|
||||
generator: `GitBook (${buildVersion()})`,
|
||||
icons: {
|
||||
icon: [
|
||||
{
|
||||
url:
|
||||
customIcon?.light ??
|
||||
linker.toAbsoluteURL(
|
||||
linker.toPathInContent('~gitbook/icon?size=small&theme=light')
|
||||
),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: light)',
|
||||
},
|
||||
{
|
||||
url:
|
||||
customIcon?.dark ??
|
||||
linker.toAbsoluteURL(
|
||||
linker.toPathInContent('~gitbook/icon?size=small&theme=dark')
|
||||
),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: dark)',
|
||||
},
|
||||
],
|
||||
icon: icons,
|
||||
apple: icons,
|
||||
},
|
||||
robots: (await isSiteIndexable(context)) ? 'index, follow' : 'noindex, nofollow',
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PageBody, PageCover } from '@/components/PageBody';
|
||||
import { getPagePath } from '@/lib/pages';
|
||||
import { isPageIndexable, isSiteIndexable } from '@/lib/seo';
|
||||
|
||||
import { getResizedImageURL } from '@v2/lib/images';
|
||||
import { PageClientLayout } from './PageClientLayout';
|
||||
import { type PagePathParams, fetchPageData, getPathnameParam, normalizePathname } from './fetch';
|
||||
|
||||
@@ -118,7 +119,7 @@ export async function generateSitePageMetadata(props: SitePageProps): Promise<Me
|
||||
}
|
||||
|
||||
const { page, ancestors } = pageTarget;
|
||||
const { site, customization, pages, linker } = context;
|
||||
const { site, customization, pages, linker, imageResizer } = context;
|
||||
|
||||
return {
|
||||
title: [page.title, site.title].filter(Boolean).join(' | '),
|
||||
@@ -131,8 +132,12 @@ export async function generateSitePageMetadata(props: SitePageProps): Promise<Me
|
||||
},
|
||||
openGraph: {
|
||||
images: [
|
||||
customization.socialPreview.url ??
|
||||
linker.toAbsoluteURL(linker.toPathInContent(`~gitbook/ogimage/${page.id}`)),
|
||||
customization.socialPreview.url
|
||||
? await getResizedImageURL(imageResizer, customization.socialPreview.url, {
|
||||
width: 1200,
|
||||
height: 630,
|
||||
})
|
||||
: linker.toAbsoluteURL(linker.toPathInContent(`~gitbook/ogimage/${page.id}`)),
|
||||
],
|
||||
},
|
||||
robots:
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { notFound, redirect } from 'next/navigation';
|
||||
import { ImageResponse } from 'next/og';
|
||||
|
||||
import { getEmojiForCode } from '@/lib/emojis';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import { getResizedImageURL } from '@v2/lib/images';
|
||||
|
||||
const SIZES = {
|
||||
/** Size for a favicon */
|
||||
@@ -25,11 +26,24 @@ const SIZES = {
|
||||
/**
|
||||
* Generate an icon for a site content.
|
||||
*/
|
||||
export function serveIcon(context: GitBookSiteContext, req: Request) {
|
||||
export async function serveIcon(context: GitBookSiteContext, req: Request) {
|
||||
const options = getOptions(req.url);
|
||||
const size = SIZES[options.size];
|
||||
|
||||
const { site, customization } = context;
|
||||
const customIcon = 'icon' in customization.favicon ? customization.favicon.icon : null;
|
||||
|
||||
// If the site has a custom icon, redirect to it
|
||||
if (customIcon) {
|
||||
const iconUrl = options.theme === 'light' ? customIcon.light : customIcon.dark;
|
||||
redirect(
|
||||
await getResizedImageURL(context.imageResizer, iconUrl, {
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const contentTitle = site.title;
|
||||
|
||||
return new ImageResponse(
|
||||
|
||||
@@ -7,6 +7,7 @@ import { type PageParams, fetchPageData } from '@/components/SitePage';
|
||||
import { getAssetURL } from '@/lib/assets';
|
||||
import { filterOutNullable } from '@/lib/typescript';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import { getResizedImageURL } from '@v2/lib/images';
|
||||
|
||||
const googleFontsMap: { [fontName in CustomizationDefaultFont]: string } = {
|
||||
[CustomizationDefaultFont.Inter]: 'Inter',
|
||||
@@ -31,12 +32,17 @@ const googleFontsMap: { [fontName in CustomizationDefaultFont]: string } = {
|
||||
*/
|
||||
export async function serveOGImage(baseContext: GitBookSiteContext, params: PageParams) {
|
||||
const { context, pageTarget } = await fetchPageData(baseContext, params);
|
||||
const { customization, site, linker } = context;
|
||||
const { customization, site, linker, imageResizer } = context;
|
||||
const page = pageTarget?.page;
|
||||
|
||||
// If user configured a custom social preview, we redirect to it.
|
||||
if (customization.socialPreview.url) {
|
||||
redirect(customization.socialPreview.url);
|
||||
redirect(
|
||||
await getResizedImageURL(imageResizer, customization.socialPreview.url, {
|
||||
width: 1200,
|
||||
height: 630,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Compute all text to load only the necessary fonts
|
||||
|
||||
Reference in New Issue
Block a user