mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-16 23:55:20 +00:00
Fix links to other spaces in embeddable view (#3819)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Fix links to other spaces and root page in embeddable view.
|
||||
@@ -0,0 +1,23 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import { getEmbeddableLinker } from './embeddable';
|
||||
import { createLinker } from './links';
|
||||
|
||||
describe('getEmbeddableLinker', () => {
|
||||
it('withOtherSiteSpace should resolve future links within the embed namespace', () => {
|
||||
const root = createLinker({
|
||||
host: 'docs.company.com',
|
||||
spaceBasePath: '/',
|
||||
siteBasePath: '/',
|
||||
});
|
||||
|
||||
const embeddableLinker = getEmbeddableLinker(root);
|
||||
|
||||
const otherSpaceEmbeddableLinker = embeddableLinker.withOtherSiteSpace({
|
||||
spaceBasePath: '/section/variant',
|
||||
});
|
||||
|
||||
expect(otherSpaceEmbeddableLinker.toPathInSpace('some/path')).toBe(
|
||||
'/section/variant/~gitbook/embed/page/some/path'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -48,5 +48,12 @@ export function getEmbeddableLinker(linker: GitBookLinker): GitBookLinker {
|
||||
|
||||
return linker.toPathInSpace(embedPagePath) + (anchor ? `#${anchor}` : '');
|
||||
},
|
||||
|
||||
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker {
|
||||
return linker.withOtherSiteSpace({
|
||||
// We make sure that links in the other site space will be shown in the embeddeable view.
|
||||
spaceBasePath: joinPath(override.spaceBasePath, '~gitbook/embed/page'),
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import {
|
||||
createLinker,
|
||||
linkerForPublishedURL,
|
||||
linkerWithAbsoluteURLs,
|
||||
linkerWithOtherSpaceBasePath,
|
||||
} from './links';
|
||||
import { createLinker, linkerForPublishedURL, linkerWithAbsoluteURLs } from './links';
|
||||
|
||||
const root = createLinker({
|
||||
host: 'docs.company.com',
|
||||
@@ -122,9 +117,9 @@ describe('linkerWithAbsoluteURLs', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkerWithOtherSpaceBasePath', () => {
|
||||
describe('linker.withOtherSiteSpace', () => {
|
||||
it('should return a new linker that resolves links relative to a new spaceBasePath in the current site', () => {
|
||||
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(root, {
|
||||
const otherSpaceBasePathLinker = root.withOtherSiteSpace({
|
||||
spaceBasePath: '/section/variant',
|
||||
});
|
||||
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe(
|
||||
@@ -133,7 +128,7 @@ describe('linkerWithOtherSpaceBasePath', () => {
|
||||
});
|
||||
|
||||
it('should return a new linker that resolves links relative to a new spaceBasePath in the current site', () => {
|
||||
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(root, {
|
||||
const otherSpaceBasePathLinker = root.withOtherSiteSpace({
|
||||
spaceBasePath: '/section/variant',
|
||||
});
|
||||
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe(
|
||||
@@ -142,14 +137,14 @@ describe('linkerWithOtherSpaceBasePath', () => {
|
||||
});
|
||||
|
||||
it('should use a basepath relative to the site', () => {
|
||||
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(siteGitBookIO, {
|
||||
const otherSpaceBasePathLinker = siteGitBookIO.withOtherSiteSpace({
|
||||
spaceBasePath: 'a/b',
|
||||
});
|
||||
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe('/sitename/a/b/some/path');
|
||||
});
|
||||
|
||||
it('should use a basepath relative to the site (with trailing slash)', () => {
|
||||
const otherSpaceBasePathLinker = linkerWithOtherSpaceBasePath(siteGitBookIO, {
|
||||
const otherSpaceBasePathLinker = siteGitBookIO.withOtherSiteSpace({
|
||||
spaceBasePath: '/a/b',
|
||||
});
|
||||
expect(otherSpaceBasePathLinker.toPathInSpace('some/path')).toBe('/sitename/a/b/some/path');
|
||||
|
||||
@@ -60,6 +60,11 @@ export interface GitBookLinker {
|
||||
*/
|
||||
fork(override: { spaceBasePath: string }): GitBookLinker;
|
||||
|
||||
/**
|
||||
* Create a new linker that resolves links relative to a new space in the current site.
|
||||
*/
|
||||
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker;
|
||||
|
||||
/**
|
||||
* Site base path used to create this linker.
|
||||
*/
|
||||
@@ -156,6 +161,25 @@ export function createLinker(
|
||||
|
||||
return rawURL;
|
||||
},
|
||||
|
||||
withOtherSiteSpace(override: { spaceBasePath: string }): GitBookLinker {
|
||||
const newLinker: GitBookLinker = {
|
||||
...linker,
|
||||
toPathInSpace(relativePath: string): string {
|
||||
return linker.toPathInSite(joinPaths(override.spaceBasePath, relativePath));
|
||||
},
|
||||
// implementation matches the base linker toPathForPage, but decouples from using `this` to
|
||||
// ensure we always use the updates `toPathInSpace` method.
|
||||
toPathForPage({ pages, page, anchor }) {
|
||||
return (
|
||||
newLinker.toPathInSpace(getPagePath(pages, page)) +
|
||||
(anchor ? `#${anchor}` : '')
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return newLinker;
|
||||
},
|
||||
};
|
||||
|
||||
return linker;
|
||||
@@ -204,35 +228,6 @@ export function linkerWithAbsoluteURLs(linker: GitBookLinker): GitBookLinker {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new linker that resolves links relative to a new spaceBasePath in the current site.
|
||||
*/
|
||||
export function linkerWithOtherSpaceBasePath(
|
||||
linker: GitBookLinker,
|
||||
{
|
||||
spaceBasePath,
|
||||
}: {
|
||||
/**
|
||||
* The base path of the space. It should be relative to the root of the site.
|
||||
*/
|
||||
spaceBasePath: string;
|
||||
}
|
||||
): GitBookLinker {
|
||||
const newLinker: GitBookLinker = {
|
||||
...linker,
|
||||
toPathInSpace(relativePath: string): string {
|
||||
return linker.toPathInSite(joinPaths(spaceBasePath, relativePath));
|
||||
},
|
||||
// implementation matches the base linker toPathForPage, but decouples from using `this` to
|
||||
// ensure we always use the updates `toPathInSpace` method.
|
||||
toPathForPage({ pages, page, anchor }) {
|
||||
return newLinker.toPathInSpace(getPagePath(pages, page)) + (anchor ? `#${anchor}` : '');
|
||||
},
|
||||
};
|
||||
|
||||
return newLinker;
|
||||
}
|
||||
|
||||
function joinPaths(prefix: string, path: string): string {
|
||||
const prefixPath = prefix.endsWith('/') ? prefix : `${prefix}/`;
|
||||
const suffixPath = path.startsWith('/') ? path.slice(1) : path;
|
||||
|
||||
@@ -10,12 +10,7 @@ import {
|
||||
getRevisionReusableContent,
|
||||
ignoreDataThrownError,
|
||||
} from '@/lib/data';
|
||||
import {
|
||||
type GitBookLinker,
|
||||
createLinker,
|
||||
linkerWithAbsoluteURLs,
|
||||
linkerWithOtherSpaceBasePath,
|
||||
} from '@/lib/links';
|
||||
import { type GitBookLinker, createLinker, linkerWithAbsoluteURLs } from '@/lib/links';
|
||||
import type {
|
||||
ContentRef,
|
||||
RevisionFile,
|
||||
@@ -448,7 +443,7 @@ async function createContextForSpace(
|
||||
|
||||
if (bestTargetSpace?.siteSpace && 'site' in context) {
|
||||
// If we found the space ID in the current site context, we can resolve links relative to it in the site.
|
||||
linker = linkerWithOtherSpaceBasePath(context.linker, {
|
||||
linker = context.linker.withOtherSiteSpace({
|
||||
spaceBasePath: getFallbackSiteSpacePath(context, bestTargetSpace.siteSpace),
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -590,10 +590,10 @@ function encodePathInSiteContent(rawPathname: string): {
|
||||
}
|
||||
|
||||
// If the pathname is an embedded page
|
||||
const embedPage = pathname.match(/^~gitbook\/embed\/page\/(\S+)$/);
|
||||
const embedPage = pathname.match(/^~gitbook\/embed\/page(\/(\S*))?$/);
|
||||
if (embedPage) {
|
||||
return {
|
||||
pathname: `~gitbook/embed/page/${encodeURIComponent(embedPage[1]!)}`,
|
||||
pathname: `~gitbook/embed/page/${encodeURIComponent(embedPage[1] || '/')}`,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user