diff --git a/packages/gitbook/src/components/SitePage/SitePage.test.ts b/packages/gitbook/src/components/SitePage/SitePage.test.ts new file mode 100644 index 000000000..9ceec6580 --- /dev/null +++ b/packages/gitbook/src/components/SitePage/SitePage.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from 'bun:test'; + +import type { RevisionPageDocument } from '@gitbook/api'; + +import { getPageFullTitle } from './title'; +import type { GitBookSiteContext } from '@/lib/context'; + +function makeContext(siteTitle: string, sectionTitle = ''): GitBookSiteContext { + return { + site: { title: siteTitle }, + visibleSections: sectionTitle + ? { + current: { title: sectionTitle, default: false }, + list: [{ object: 'site-section' }, { object: 'site-section' }], + } + : undefined, + visibleSiteSpaces: [], + } as unknown as GitBookSiteContext; +} + +function makePage(title: string, tagTitle?: string): RevisionPageDocument { + return { title, tagTitle } as unknown as RevisionPageDocument; +} + +describe('getPageFullTitle', () => { + it('uses tagTitle as the first segment', () => { + expect(getPageFullTitle(makeContext('GitBook'), makePage('Page title', 'SEO title'))).toBe( + 'SEO title | GitBook' + ); + }); + + it('falls back to the page title when tagTitle is absent', () => { + expect(getPageFullTitle(makeContext('GitBook'), makePage('Page title'))).toBe( + 'Page title | GitBook' + ); + }); + + it('deduplicates the section title against tagTitle', () => { + expect( + getPageFullTitle(makeContext('GitBook', 'Section'), makePage('Page title', 'Section')) + ).toBe('Section | GitBook'); + }); + + it('deduplicates the site title against tagTitle', () => { + expect( + getPageFullTitle(makeContext('SEO title'), makePage('Page title', 'SEO title')) + ).toBe('SEO title'); + }); +}); diff --git a/packages/gitbook/src/components/SitePage/SitePage.tsx b/packages/gitbook/src/components/SitePage/SitePage.tsx index 6ab1b65b7..49f313eec 100644 --- a/packages/gitbook/src/components/SitePage/SitePage.tsx +++ b/packages/gitbook/src/components/SitePage/SitePage.tsx @@ -4,7 +4,6 @@ import { notFound, redirect } from 'next/navigation'; import { CustomizationDefaultThemeMode, CustomizationHeaderPreset, - type RevisionPageDocument, SiteInsightsDisplayContext, type TranslationLanguage, } from '@gitbook/api'; @@ -18,6 +17,7 @@ import { getPathnameParam, } from './fetch'; import { PageClientLayout } from './PageClientLayout'; +import { getPageFullTitle } from './title'; import { UpdatesFilterProvider } from '@/components/DocumentView/UpdatesFilter'; import { UpdatesFilterScript } from '@/components/DocumentView/UpdatesFilterScript'; import { PageAside } from '@/components/PageAside'; @@ -33,11 +33,7 @@ import { getResizedImageURL } from '@/lib/images'; import { getPagePath } from '@/lib/pages'; import { resolveContentRef } from '@/lib/references'; import { isPageIndexable, isSiteIndexable } from '@/lib/seo'; -import { - getSiteSpacePagePaths, - getSiteStructureTitle, - resolveSiteSpaceCustomHomePage, -} from '@/lib/sites'; +import { getSiteSpacePagePaths, resolveSiteSpaceCustomHomePage } from '@/lib/sites'; import { tcls } from '@/lib/tailwind'; import { generateUpdatesFilterCSS, @@ -45,6 +41,8 @@ import { updatesFilterStyleHref, } from '@/lib/updates'; +export { getPageFullTitle } from './title'; + export type SitePageProps = { context: GitBookSiteContext; pageParams: PagePathParams; @@ -421,20 +419,3 @@ async function resolvePageMetaLinks( alternates: [], }; } - -/** - * Get the