diff --git a/src/app/(space)/ClientContexts.tsx b/src/app/(space)/ClientContexts.tsx index a1a8f9720..862079b45 100644 --- a/src/app/(space)/ClientContexts.tsx +++ b/src/app/(space)/ClientContexts.tsx @@ -19,7 +19,7 @@ export function ClientContexts(props: { /** * A bug in ThemeProvider is causing the nonce to be included incorrectly * on the client-side. Original issue: https://github.com/pacocoursey/next-themes/issues/218 - * + * * This is a workaround for it, until next-themes fixes it in their library. There is already * a PR: https://github.com/pacocoursey/next-themes/pull/223 */ diff --git a/src/lib/pages.ts b/src/lib/pages.ts index a448c08c8..123d37b4f 100644 --- a/src/lib/pages.ts +++ b/src/lib/pages.ts @@ -98,6 +98,7 @@ export function resolvePrevNextPages( /** * Resolve a page to its canonical path. + * The path will NOT start with "/". */ export function getPagePath( rootPages: Revision['pages'], diff --git a/src/lib/references.ts b/src/lib/references.ts index 32da6c822..8116992f0 100644 --- a/src/lib/references.ts +++ b/src/lib/references.ts @@ -11,7 +11,7 @@ import { ignoreAPIError, } from './api'; import { gitbookAppHref, pageHref, PageHrefContext } from './links'; -import { resolvePageId } from './pages'; +import { getPagePath, resolvePageId } from './pages'; export interface ResolvedContentRef { /** Text to render in the content ref */ @@ -27,9 +27,29 @@ export interface ResolvedContentRef { } export interface ContentRefContext extends PageHrefContext { + /** + * Base URL to use to prepend to relative URLs. + */ + baseUrl?: string; + + /** + * Space in which we are resolving the content reference. + */ space: Space; + + /** + * Revision in which we are resolving the content reference. + */ revisionId: string; + + /** + * Pages in the revision. + */ pages: Revision['pages']; + + /** + * Page in which the content reference is being resolved. + */ page?: RevisionPageDocument; } @@ -38,8 +58,10 @@ export interface ContentRefContext extends PageHrefContext { */ export async function resolveContentRef( contentRef: ContentRef, - { space, revisionId, pages, page: activePage, ...linksContext }: ContentRefContext, + context: ContentRefContext, ): Promise { + const { space, revisionId, pages, page: activePage, ...linksContext } = context; + switch (contentRef.kind) { case 'url': { return { @@ -87,8 +109,21 @@ export async function resolveContentRef( } const isCurrentPage = page.id === activePage?.id; + let href = ''; + if (context.baseUrl) { + // Page in another content + href = new URL(getPagePath(pages, page), context.baseUrl).toString(); + + if (contentRef.anchor) { + href += '#' + contentRef.anchor; + } + } else { + // Page in the current content + href = pageHref(pages, page, linksContext, contentRef.anchor); + } + return { - href: pageHref(pages, page, linksContext, contentRef.anchor), + href, text: (isCurrentPage ? '' : page.title) + '#' + contentRef.anchor, emoji: isCurrentPage ? undefined : page.emoji, active: false, @@ -173,9 +208,17 @@ async function resolveContentRefInSpace(spaceId: string, contentRef: ContentRef) } const { space, pages } = result; + + // Base URL to use to prepend to relative URLs. + let baseUrl = space.urls.published ?? space.urls.app; + if (!baseUrl.endsWith('/')) { + baseUrl += '/'; + } + return resolveContentRef(contentRef, { space, revisionId: space.revision, pages, + baseUrl, }); }