Fix PDF export page URL for /~space/ URLs (#4065)

This commit is contained in:
Greg Bergé
2026-03-02 09:49:22 +01:00
committed by GitHub
parent cb71511cda
commit 38a1c85fee
4 changed files with 56 additions and 13 deletions
@@ -21,16 +21,15 @@ export async function getSpacePDFContext(
const apiToken = await getAPITokenFromMiddleware();
const basePath = getPDFRoutePath(params);
const linker = createLinker({
spaceBasePath: basePath,
siteBasePath: basePath,
});
const dataFetcher = createDataFetcher({
apiToken: apiToken,
});
const baseContext: GitBookBaseContext = {
linker,
linker: createLinker({
spaceBasePath: basePath,
siteBasePath: basePath,
}),
dataFetcher,
};
@@ -63,12 +63,16 @@ describe('createPDFLinker', () => {
it('keeps links to non-exported pages on the published domain', () => {
const baseLinker = createLinker({
host: 'docs.vectra.ai',
siteBasePath: '/',
spaceBasePath: '/deployment',
host: 'open-2v.gitbook.com',
siteBasePath: '/~space/HJ1ltuWFvsArFWtevnRn~gitbook/pdf',
spaceBasePath: '/~space/HJ1ltuWFvsArFWtevnRn~gitbook/pdf',
});
const linker = createPDFLinker(baseLinker, [{ page: createDocumentPage('included', '') }]);
const linker = createPDFLinker(
baseLinker,
[{ page: createDocumentPage('included', '') }],
'https://docs.vectra.ai/deployment/'
);
expect(
linker.toPathForPage({
@@ -81,6 +85,31 @@ describe('createPDFLinker', () => {
).toBe('https://docs.vectra.ai/deployment/respond');
});
it('preserves anchors for non-exported pages on the published domain', () => {
const baseLinker = createLinker({
host: 'open-2v.gitbook.com',
siteBasePath: '/~space/HJ1ltuWFvsArFWtevnRn~gitbook/pdf',
spaceBasePath: '/~space/HJ1ltuWFvsArFWtevnRn~gitbook/pdf',
});
const linker = createPDFLinker(
baseLinker,
[{ page: createDocumentPage('included', '') }],
'https://docs.vectra.ai/deployment/'
);
expect(
linker.toPathForPage({
pages: [
createDocumentPage('included', ''),
createDocumentPage('outside', 'respond'),
],
page: createDocumentPage('outside', 'respond'),
anchor: 'faq',
})
).toBe('https://docs.vectra.ai/deployment/respond#faq');
});
it('returns a local placeholder link for group pages not included in the PDF export', () => {
const baseLinker = createLinker({
host: 'docs.vectra.ai',
@@ -66,7 +66,7 @@ export async function PDFPage(props: {
);
// Build a linker that create anchor links for the pages rendered in the PDF page.
const linker = createPDFLinker(baseContext.linker, pages);
const linker = createPDFLinker(baseContext.linker, pages, baseContext.space.urls.published);
const context: GitBookSpaceContext = {
...baseContext,
+18 -3
View File
@@ -2,6 +2,8 @@ import type { Revision, RevisionPageDocument, RevisionPageGroup } from '@gitbook
import { RevisionPageType } from '@gitbook/api';
import type { GitBookLinker } from '@/lib/links';
import { getPagePath } from '@/lib/pages';
import { withTrailingSlash } from '@/lib/paths';
/**
* Create the HTML ID for the container of a page or a given anchor in it.
@@ -23,16 +25,19 @@ export function getPagePDFContainerId(
* This linker generates in-document anchor links for pages that are included
* in the current PDF export, using `getPagePDFContainerId` to build the
* target element ID. For pages that are not part of the exported PDF, it
* falls back to absolute URLs pointing to the published site, preserving
* navigability for external content.
* falls back to URLs pointing to the published site if `publishedSpaceURL` is
* provided, preserving navigability for external content. Otherwise, it uses
* absolute URLs from the base linker.
*
* @param baseLinker - The base GitBook linker used to resolve standard paths and URLs.
* @param pages - The list of pages that are included in the current PDF export.
* @param publishedSpaceURL - Optional URL of the published space for external page links.
* @returns A `GitBookLinker` configured to generate PDF-friendly links.
*/
export function createPDFLinker(
baseLinker: GitBookLinker,
pages: Array<{ page: Revision['pages'][number] }>
pages: Array<{ page: Revision['pages'][number] }>,
publishedSpaceURL?: string
): GitBookLinker {
return {
...baseLinker,
@@ -45,6 +50,16 @@ export function createPDFLinker(
}
// For pages that are not embedded in this PDF export, keep links on the published site.
if (publishedSpaceURL) {
const pagePath = getPagePath(input.pages, input.page);
const pageURL = new URL(pagePath, withTrailingSlash(publishedSpaceURL));
if (input.anchor) {
pageURL.hash = input.anchor;
}
return pageURL.toString();
}
return baseLinker.toAbsoluteURL(baseLinker.toPathForPage(input));
},
};