Skip to content

Commit c51076e

Browse files
authored
Fix links to other spaces in embeddable view (#3819)
1 parent 38e34dc commit c51076e

File tree

7 files changed

+69
-49
lines changed

7 files changed

+69
-49
lines changed

.changeset/social-berries-visit.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"gitbook": patch
3+
---
4+
5+
Fix links to other spaces and root page in embeddable view.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { describe, expect, it } from 'bun:test';
2+
import { getEmbeddableLinker } from './embeddable';
3+
import { createLinker } from './links';
4+
5+
describe('getEmbeddableLinker', () => {
6+
it('withOtherSiteSpace should resolve future links within the embed namespace', () => {
7+
const root = createLinker({
8+
host: 'docs.company.com',
9+
spaceBasePath: '/',
10+
siteBasePath: '/',
11+
});
12+
13+
const embeddableLinker = getEmbeddableLinker(root);
14+
15+
const otherSpaceEmbeddableLinker = embeddableLinker.withOtherSiteSpace({
16+
spaceBasePath: '/section/variant',
17+
});
18+
19+
expect(otherSpaceEmbeddableLinker.toPathInSpace('some/path')).toBe(
20+
'/section/variant/~gitbook/embed/page/some/path'
21+
);
22+
});
23+
});

packages/gitbook/src/lib/embeddable.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,12 @@ export function getEmbeddableLinker(linker: GitBookLinker): GitBookLinker {
4848

4949
return linker.toPathInSpace(embedPagePath) + (anchor ? `#${anchor}` : '');
5050
},
51+
52+
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker {
53+
return linker.withOtherSiteSpace({
54+
// We make sure that links in the other site space will be shown in the embeddeable view.
55+
spaceBasePath: joinPath(override.spaceBasePath, '~gitbook/embed/page'),
56+
});
57+
},
5158
};
5259
}

packages/gitbook/src/lib/links.test.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { describe, expect, it } from 'bun:test';
2-
import {
3-
createLinker,
4-
linkerForPublishedURL,
5-
linkerWithAbsoluteURLs,
6-
linkerWithOtherSpaceBasePath,
7-
} from './links';
2+
import { createLinker, linkerForPublishedURL, linkerWithAbsoluteURLs } from './links';
83

94
const root = createLinker({
105
host: 'docs.company.com',
@@ -122,9 +117,9 @@ describe('linkerWithAbsoluteURLs', () => {
122117
});
123118
});
124119

125-
describe('linkerWithOtherSpaceBasePath', () => {
120+
describe('linker.withOtherSiteSpace', () => {
126121
it('should return a new linker that resolves links relative to a new spaceBasePath in the current site', () => {
127-
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(root, {
122+
const otherSpaceBasePathLinker = root.withOtherSiteSpace({
128123
spaceBasePath: '/section/variant',
129124
});
130125
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe(
@@ -133,7 +128,7 @@ describe('linkerWithOtherSpaceBasePath', () => {
133128
});
134129

135130
it('should return a new linker that resolves links relative to a new spaceBasePath in the current site', () => {
136-
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(root, {
131+
const otherSpaceBasePathLinker = root.withOtherSiteSpace({
137132
spaceBasePath: '/section/variant',
138133
});
139134
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe(
@@ -142,14 +137,14 @@ describe('linkerWithOtherSpaceBasePath', () => {
142137
});
143138

144139
it('should use a basepath relative to the site', () => {
145-
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(siteGitBookIO, {
140+
const otherSpaceBasePathLinker = siteGitBookIO.withOtherSiteSpace({
146141
spaceBasePath: 'a/b',
147142
});
148143
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe('/sitename/a/b/some/path');
149144
});
150145

151146
it('should use a basepath relative to the site (with trailing slash)', () => {
152-
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(siteGitBookIO, {
147+
const otherSpaceBasePathLinker = siteGitBookIO.withOtherSiteSpace({
153148
spaceBasePath: '/a/b',
154149
});
155150
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe('/sitename/a/b/some/path');

packages/gitbook/src/lib/links.ts

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ export interface GitBookLinker {
6060
*/
6161
fork(override: { spaceBasePath: string }): GitBookLinker;
6262

63+
/**
64+
* Create a new linker that resolves links relative to a new space in the current site.
65+
*/
66+
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker;
67+
6368
/**
6469
* Site base path used to create this linker.
6570
*/
@@ -156,6 +161,25 @@ export function createLinker(
156161

157162
return rawURL;
158163
},
164+
165+
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker {
166+
const newLinker: GitBookLinker = {
167+
...linker,
168+
toPathInSpace(relativePath: string): string {
169+
return linker.toPathInSite(joinPaths(override.spaceBasePath, relativePath));
170+
},
171+
// implementation matches the base linker toPathForPage, but decouples from using `this` to
172+
// ensure we always use the updates `toPathInSpace` method.
173+
toPathForPage({ pages, page, anchor }) {
174+
return (
175+
newLinker.toPathInSpace(getPagePath(pages, page)) +
176+
(anchor ? `#${anchor}` : '')
177+
);
178+
},
179+
};
180+
181+
return newLinker;
182+
},
159183
};
160184

161185
return linker;
@@ -204,35 +228,6 @@ export function linkerWithAbsoluteURLs(linker: GitBookLinker): GitBookLinker {
204228
};
205229
}
206230

207-
/**
208-
* Create a new linker that resolves links relative to a new spaceBasePath in the current site.
209-
*/
210-
export function linkerWithOtherSpaceBasePath(
211-
linker: GitBookLinker,
212-
{
213-
spaceBasePath,
214-
}: {
215-
/**
216-
* The base path of the space. It should be relative to the root of the site.
217-
*/
218-
spaceBasePath: string;
219-
}
220-
): GitBookLinker {
221-
const newLinker: GitBookLinker = {
222-
...linker,
223-
toPathInSpace(relativePath: string): string {
224-
return linker.toPathInSite(joinPaths(spaceBasePath, relativePath));
225-
},
226-
// implementation matches the base linker toPathForPage, but decouples from using `this` to
227-
// ensure we always use the updates `toPathInSpace` method.
228-
toPathForPage({ pages, page, anchor }) {
229-
return newLinker.toPathInSpace(getPagePath(pages, page)) + (anchor ? `#${anchor}` : '');
230-
},
231-
};
232-
233-
return newLinker;
234-
}
235-
236231
function joinPaths(prefix: string, path: string): string {
237232
const prefixPath = prefix.endsWith('/') ? prefix : `${prefix}/`;
238233
const suffixPath = path.startsWith('/') ? path.slice(1) : path;

packages/gitbook/src/lib/references.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ import {
1010
getRevisionReusableContent,
1111
ignoreDataThrownError,
1212
} from '@/lib/data';
13-
import {
14-
type GitBookLinker,
15-
createLinker,
16-
linkerWithAbsoluteURLs,
17-
linkerWithOtherSpaceBasePath,
18-
} from '@/lib/links';
13+
import { type GitBookLinker, createLinker, linkerWithAbsoluteURLs } from '@/lib/links';
1914
import type {
2015
ContentRef,
2116
RevisionFile,
@@ -448,7 +443,7 @@ async function createContextForSpace(
448443

449444
if (bestTargetSpace?.siteSpace && 'site' in context) {
450445
// If we found the space ID in the current site context, we can resolve links relative to it in the site.
451-
linker = linkerWithOtherSpaceBasePath(context.linker, {
446+
linker = context.linker.withOtherSiteSpace({
452447
spaceBasePath: getFallbackSiteSpacePath(context, bestTargetSpace.siteSpace),
453448
});
454449
} else {

packages/gitbook/src/middleware.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,10 +590,10 @@ function encodePathInSiteContent(rawPathname: string): {
590590
}
591591

592592
// If the pathname is an embedded page
593-
const embedPage = pathname.match(/^~gitbook\/embed\/page\/(\S+)$/);
593+
const embedPage = pathname.match(/^~gitbook\/embed\/page(\/(\S*))?$/);
594594
if (embedPage) {
595595
return {
596-
pathname: `~gitbook/embed/page/${encodeURIComponent(embedPage[1]!)}`,
596+
pathname: `~gitbook/embed/page/${encodeURIComponent(embedPage[1] || '/')}`,
597597
};
598598
}
599599

0 commit comments

Comments
 (0)