Skip to content

Commit 64f3596

Browse files
authored
Output generic alternates for page metadata (#3804)
1 parent 27d6c3a commit 64f3596

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

packages/gitbook/src/components/SitePage/SitePage.tsx

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,36 @@ export async function generateSitePageMetadata(props: SitePageProps): Promise<Me
160160

161161
const canonical = (
162162
pageMetaLinks?.canonical
163-
? new URL(pageMetaLinks.canonical).toString()
163+
? new URL(
164+
// If the canonical link is an absolute URL, use it as is.
165+
URL.canParse(pageMetaLinks.canonical)
166+
? pageMetaLinks.canonical
167+
: linker.toAbsoluteURL(pageMetaLinks.canonical)
168+
).toString()
164169
: // If no canonical is set, use the current page URL (default case)
165170
linker.toAbsoluteURL(linker.toPathForPage({ pages: revision.pages, page }))
166171
).replace(/\/+$/, ''); // Trim trailing slashes in canonical URL to match the redirect behavior
167172

168-
const languages = pageMetaLinks?.alternates.reduce(
173+
const alternates = pageMetaLinks?.alternates.reduce<{
174+
languages: Record<string, string>;
175+
generic: Array<{
176+
title?: string;
177+
url: string;
178+
}>;
179+
}>(
169180
(acc, alt) => {
170-
// TODO: We can only add language alternates for now as that's all Next.js API supports
171-
// generic alternates are not supported yet
172181
if (alt.space?.language) {
173-
acc[alt.space.language] = alt.href;
182+
acc.languages[alt.space.language] = URL.canParse(alt.href)
183+
? alt.href
184+
: linker.toAbsoluteURL(alt.href);
185+
} else {
186+
acc.generic.push({
187+
url: URL.canParse(alt.href) ? alt.href : linker.toAbsoluteURL(alt.href),
188+
});
174189
}
175190
return acc;
176191
},
177-
{} as Record<TranslationLanguage, string>
192+
{ languages: {}, generic: [] }
178193
);
179194

180195
return {
@@ -189,9 +204,13 @@ export async function generateSitePageMetadata(props: SitePageProps): Promise<Me
189204
description: page.description ?? '',
190205
alternates: {
191206
canonical,
192-
languages,
207+
languages: alternates?.languages,
193208
types: {
194209
'text/markdown': `${linker.toAbsoluteURL(linker.toPathInSpace(page.path))}.md`,
210+
// Currently it will output with an empty "type" like <link rel="alternate" href="..." type />
211+
// Team at Vercel is aware of this and will ensure it will be omitted when the value is empty in future versions of Next.js
212+
// https://gitbook.slack.com/archives/C04K6MV5W1K/p1763034072958419?thread_ts=1762937203.511629&cid=C04K6MV5W1K
213+
...(alternates?.generic ? { '': alternates?.generic } : {}),
195214
},
196215
},
197216
openGraph: {

0 commit comments

Comments
 (0)