mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-22 10:33:22 +00:00
Fix links to other spaces in a section (#3409)
Co-authored-by: Steven H <steven@gitbook.io>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Fix links to other spaces within a section.
|
||||
@@ -3,7 +3,7 @@
|
||||
import type { GitBookBaseContext, GitBookSiteContext } from '@/lib/context';
|
||||
import { resolvePageId } from '@/lib/pages';
|
||||
import { fetchServerActionSiteContext, getServerActionBaseContext } from '@/lib/server-actions';
|
||||
import { findSiteSpaceById, getSiteStructureSections } from '@/lib/sites';
|
||||
import { findSiteSpaceBy } from '@/lib/sites';
|
||||
import { filterOutNullable } from '@/lib/typescript';
|
||||
import type {
|
||||
Revision,
|
||||
@@ -256,24 +256,20 @@ async function searchSiteContent(
|
||||
return (
|
||||
await Promise.all(
|
||||
searchResults.map(async (spaceItem) => {
|
||||
const sections = getSiteStructureSections(structure).flatMap((item) =>
|
||||
item.object === 'site-section-group' ? [item, ...item.sections] : item
|
||||
const found = findSiteSpaceBy(
|
||||
structure,
|
||||
(siteSpace) => siteSpace.space.id === spaceItem.id
|
||||
);
|
||||
const siteSpace = findSiteSpaceById(structure, spaceItem.id);
|
||||
const siteSection = sections.find(
|
||||
(section) => section.id === siteSpace?.section
|
||||
) as SiteSection;
|
||||
const siteSectionGroup = siteSection?.sectionGroup
|
||||
? sections.find((sectionGroup) => sectionGroup.id === siteSection.sectionGroup)
|
||||
: null;
|
||||
const siteSection = found?.siteSection;
|
||||
const siteSectionGroup = found?.siteSectionGroup;
|
||||
|
||||
return Promise.all(
|
||||
spaceItem.pages.map((pageItem) =>
|
||||
transformSitePageResult(context, {
|
||||
pageItem,
|
||||
spaceItem,
|
||||
space: siteSpace?.space,
|
||||
spaceURL: siteSpace?.urls.published,
|
||||
space: found?.siteSpace.space,
|
||||
spaceURL: found?.siteSpace.urls.published,
|
||||
siteSection: siteSection ?? undefined,
|
||||
siteSectionGroup: (siteSectionGroup as SiteSectionGroup) ?? undefined,
|
||||
})
|
||||
@@ -313,8 +309,11 @@ async function transformAnswer(
|
||||
}
|
||||
|
||||
// Find the siteSpace in case it is nested in a site section so we can resolve the URL appropriately
|
||||
const siteSpace = findSiteSpaceById(context.structure, source.space);
|
||||
const spaceURL = siteSpace?.urls.published;
|
||||
const found = findSiteSpaceBy(
|
||||
context.structure,
|
||||
(siteSpace) => siteSpace.space.id === source.space
|
||||
);
|
||||
const spaceURL = found?.siteSpace.urls.published;
|
||||
|
||||
const href = spaceURL
|
||||
? joinPathWithBaseURL(spaceURL, page.page.path)
|
||||
|
||||
@@ -33,7 +33,7 @@ import { PageIcon } from '@/components/PageIcon';
|
||||
import { getGitBookAppHref } from './app';
|
||||
import { getBlockById, getBlockTitle } from './document';
|
||||
import { resolvePageId } from './pages';
|
||||
import { findSiteSpaceById, getFallbackSiteSpacePath } from './sites';
|
||||
import { findSiteSpaceBy, getFallbackSiteSpacePath } from './sites';
|
||||
import type { ClassValue } from './tailwind';
|
||||
import { filterOutNullable } from './typescript';
|
||||
|
||||
@@ -315,9 +315,12 @@ async function getBestTargetSpace(
|
||||
// In the context of sites, we try to find our target space in the site structure.
|
||||
// because the url of this space will be in the same site.
|
||||
if ('site' in context) {
|
||||
const siteSpace = findSiteSpaceById(context.structure, spaceId);
|
||||
if (siteSpace) {
|
||||
return { space: siteSpace.space, siteSpace };
|
||||
const found = findSiteSpaceBy(
|
||||
context.structure,
|
||||
(siteSpace) => siteSpace.space.id === spaceId
|
||||
);
|
||||
if (found) {
|
||||
return { space: found.siteSpace.space, siteSpace: found.siteSpace };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,18 +48,46 @@ export function listAllSiteSpaces(siteStructure: SiteStructure) {
|
||||
/**
|
||||
* Find a site space by its spaceId in a site structure.
|
||||
*/
|
||||
export function findSiteSpaceById(siteStructure: SiteStructure, spaceId: string): SiteSpace | null {
|
||||
export function findSiteSpaceBy(
|
||||
siteStructure: SiteStructure,
|
||||
predicate: (siteSpace: SiteSpace) => boolean
|
||||
): {
|
||||
siteSpace: SiteSpace;
|
||||
siteSection: SiteSection | null;
|
||||
siteSectionGroup: SiteSectionGroup | null;
|
||||
} | null {
|
||||
if (siteStructure.type === 'siteSpaces') {
|
||||
return siteStructure.structure.find((siteSpace) => siteSpace.space.id === spaceId) ?? null;
|
||||
const siteSpace = siteStructure.structure.find(predicate) ?? null;
|
||||
if (siteSpace) {
|
||||
return {
|
||||
siteSpace,
|
||||
siteSection: null,
|
||||
siteSectionGroup: null,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const section of siteStructure.structure) {
|
||||
const siteSpace =
|
||||
section.object === 'site-section'
|
||||
? findSiteSpaceByIdInSiteSpaces(section.siteSpaces, spaceId)
|
||||
: findSiteSpaceByIdInSections(section.sections, spaceId);
|
||||
if (siteSpace) {
|
||||
return siteSpace;
|
||||
for (const sectionOrGroup of siteStructure.structure) {
|
||||
if (sectionOrGroup.object === 'site-section') {
|
||||
const siteSpace = findSiteSpaceByIdInSiteSpaces(sectionOrGroup.siteSpaces, predicate);
|
||||
if (siteSpace) {
|
||||
return {
|
||||
siteSpace,
|
||||
siteSection: sectionOrGroup,
|
||||
siteSectionGroup: null,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
const found = findSiteSpaceByIdInSections(sectionOrGroup.sections, predicate);
|
||||
if (found) {
|
||||
return {
|
||||
siteSpace: found.siteSpace,
|
||||
siteSection: found.siteSection,
|
||||
siteSectionGroup: sectionOrGroup,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,25 +122,37 @@ export function getSiteSpaceURL(context: GitBookSiteContext, siteSpace: SiteSpac
|
||||
|
||||
/**
|
||||
* Get the path of a site space in the current site.
|
||||
* This doesn't return the most optimized path, as it doesn't take into account which one is the default one.
|
||||
*/
|
||||
export function getFallbackSiteSpacePath(context: GitBookSiteContext, siteSpace: SiteSpace) {
|
||||
const { sections } = context;
|
||||
return sections?.current ? joinPath(sections.current.path, siteSpace.path) : siteSpace.path;
|
||||
const found = findSiteSpaceBy(context.structure, (entry) => entry.id === siteSpace.id);
|
||||
// don't include the path for the default site space
|
||||
const siteSpacePath = siteSpace.default ? '' : siteSpace.path;
|
||||
|
||||
// for non-default site sections, include the section path.
|
||||
if (found?.siteSection && !found?.siteSection.default) {
|
||||
return joinPath(found.siteSection.path, siteSpacePath);
|
||||
}
|
||||
|
||||
return siteSpacePath;
|
||||
}
|
||||
|
||||
function findSiteSpaceByIdInSections(sections: SiteSection[], spaceId: string): SiteSpace | null {
|
||||
for (const section of sections) {
|
||||
const siteSpace =
|
||||
section.siteSpaces.find((siteSpace) => siteSpace.space.id === spaceId) ?? null;
|
||||
function findSiteSpaceByIdInSections(
|
||||
sections: SiteSection[],
|
||||
predicate: (siteSpace: SiteSpace) => boolean
|
||||
): { siteSpace: SiteSpace; siteSection: SiteSection } | null {
|
||||
for (const siteSection of sections) {
|
||||
const siteSpace = siteSection.siteSpaces.find(predicate) ?? null;
|
||||
if (siteSpace) {
|
||||
return siteSpace;
|
||||
return { siteSpace, siteSection };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function findSiteSpaceByIdInSiteSpaces(siteSpaces: SiteSpace[], spaceId: string): SiteSpace | null {
|
||||
return siteSpaces.find((siteSpace) => siteSpace.space.id === spaceId) ?? null;
|
||||
function findSiteSpaceByIdInSiteSpaces(
|
||||
siteSpaces: SiteSpace[],
|
||||
predicate: (siteSpace: SiteSpace) => boolean
|
||||
): SiteSpace | null {
|
||||
return siteSpaces.find(predicate) ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user