refactor useTitleFormatter() hook

This commit is contained in:
sebastien 2025-04-11 16:03:07 +02:00
parent fffb5a7213
commit f414ebf442
5 changed files with 35 additions and 31 deletions

View file

@ -43,7 +43,7 @@ export {
export {DEFAULT_SEARCH_TAG} from './utils/searchUtils'; export {DEFAULT_SEARCH_TAG} from './utils/searchUtils';
export {useTitleFormatter} from './utils/generalUtils'; export {useTitleFormatter} from './utils/titleFormatterUtils';
export {useLocationChange} from './utils/useLocationChange'; export {useLocationChange} from './utils/useLocationChange';

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {DefaultTitleFormatter} from '../generalUtils'; import {DefaultTitleFormatter} from '../titleFormatterUtils';
describe('DefaultTitleFormatter', () => { describe('DefaultTitleFormatter', () => {
it('works', () => { it('works', () => {

View file

@ -10,7 +10,7 @@ import clsx from 'clsx';
import Head from '@docusaurus/Head'; import Head from '@docusaurus/Head';
import useRouteContext from '@docusaurus/useRouteContext'; import useRouteContext from '@docusaurus/useRouteContext';
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
import {useTitleFormatter} from './generalUtils'; import {useTitleFormatter} from './titleFormatterUtils';
type PageMetadataProps = { type PageMetadataProps = {
readonly title?: string; readonly title?: string;
@ -25,20 +25,21 @@ type PageMetadataProps = {
* Works in the same way as Helmet. * Works in the same way as Helmet.
*/ */
export function PageMetadata({ export function PageMetadata({
title, title: pageTitle,
description, description,
keywords, keywords,
image, image,
children, children,
}: PageMetadataProps): ReactNode { }: PageMetadataProps): ReactNode {
const pageTitle = useTitleFormatter(title); const titleFormatter = useTitleFormatter();
const {withBaseUrl} = useBaseUrlUtils(); const {withBaseUrl} = useBaseUrlUtils();
const pageImage = image ? withBaseUrl(image, {absolute: true}) : undefined; const pageImage = image ? withBaseUrl(image, {absolute: true}) : undefined;
const title = pageTitle ? titleFormatter.format(pageTitle) : undefined;
return ( return (
<Head> <Head>
{title && <title>{pageTitle}</title>} {title && <title>{title}</title>}
{title && <meta property="og:title" content={pageTitle} />} {title && <meta property="og:title" content={title} />}
{description && <meta name="description" content={description} />} {description && <meta name="description" content={description} />}
{description && <meta property="og:description" content={description} />} {description && <meta property="og:description" content={description} />}

View file

@ -27,12 +27,12 @@ export const DefaultTitleFormatter: TitleFormatterFn = ({
return `${trimmedTitle} ${titleDelimiter} ${siteTitle}`; return `${trimmedTitle} ${titleDelimiter} ${siteTitle}`;
}; };
type TitleFormatter = {format: (title?: string) => string}; type TitleFormatterUtils = {format: (title?: string) => string};
/** /**
* Returns a function to format the page title * Returns a function to format the page title
*/ */
export function useTitleFormatter(): TitleFormatter { export function useTitleFormatter(): TitleFormatterUtils {
const {siteConfig} = useDocusaurusContext(); const {siteConfig} = useDocusaurusContext();
const formatter = DefaultTitleFormatter; const formatter = DefaultTitleFormatter;
const {title: siteTitle, titleDelimiter} = siteConfig; const {title: siteTitle, titleDelimiter} = siteConfig;

View file

@ -25,11 +25,11 @@ import Link from '@docusaurus/Link';
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client'; import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
import { import {
HtmlClassNameProvider, HtmlClassNameProvider,
PageMetadata,
useEvent, useEvent,
usePluralForm, usePluralForm,
useSearchQueryString, useSearchQueryString,
} from '@docusaurus/theme-common'; } from '@docusaurus/theme-common';
import {useTitleFormatter} from '@docusaurus/theme-common/internal';
import Translate, {translate} from '@docusaurus/Translate'; import Translate, {translate} from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { import {
@ -160,6 +160,25 @@ type ResultDispatcher =
| {type: 'update'; value: ResultDispatcherState} | {type: 'update'; value: ResultDispatcherState}
| {type: 'advance'; value?: undefined}; | {type: 'advance'; value?: undefined};
function getSearchPageTitle(searchQuery: string | undefined): string {
return searchQuery
? translate(
{
id: 'theme.SearchPage.existingResultsTitle',
message: 'Search results for "{query}"',
description: 'The search page title for non-empty query',
},
{
query: searchQuery,
},
)
: translate({
id: 'theme.SearchPage.emptyResultsTitle',
message: 'Search the documentation',
description: 'The search page title for empty query',
});
}
function SearchPageContent(): ReactNode { function SearchPageContent(): ReactNode {
const { const {
i18n: {currentLocale}, i18n: {currentLocale},
@ -167,12 +186,13 @@ function SearchPageContent(): ReactNode {
const { const {
algolia: {appId, apiKey, indexName, contextualSearch}, algolia: {appId, apiKey, indexName, contextualSearch},
} = useAlgoliaThemeConfig(); } = useAlgoliaThemeConfig();
const processSearchResultUrl = useSearchResultUrlProcessor(); const processSearchResultUrl = useSearchResultUrlProcessor();
const documentsFoundPlural = useDocumentsFoundPlural(); const documentsFoundPlural = useDocumentsFoundPlural();
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers(); const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
const [searchQuery, setSearchQuery] = useSearchQueryString(); const [searchQuery, setSearchQuery] = useSearchQueryString();
const pageTitle = getSearchPageTitle(searchQuery);
const initialSearchResultState: ResultDispatcherState = { const initialSearchResultState: ResultDispatcherState = {
items: [], items: [],
query: null, query: null,
@ -310,24 +330,6 @@ function SearchPageContent(): ReactNode {
), ),
); );
const getTitle = () =>
searchQuery
? translate(
{
id: 'theme.SearchPage.existingResultsTitle',
message: 'Search results for "{query}"',
description: 'The search page title for non-empty query',
},
{
query: searchQuery,
},
)
: translate({
id: 'theme.SearchPage.emptyResultsTitle',
message: 'Search the documentation',
description: 'The search page title for empty query',
});
const makeSearch = useEvent((page: number = 0) => { const makeSearch = useEvent((page: number = 0) => {
if (contextualSearch) { if (contextualSearch) {
algoliaHelper.addDisjunctiveFacetRefinement('docusaurus_tag', 'default'); algoliaHelper.addDisjunctiveFacetRefinement('docusaurus_tag', 'default');
@ -380,8 +382,9 @@ function SearchPageContent(): ReactNode {
return ( return (
<Layout> <Layout>
<PageMetadata title={pageTitle} />
<Head> <Head>
<title>{useTitleFormatter(getTitle())}</title>
{/* {/*
We should not index search pages We should not index search pages
See https://github.com/facebook/docusaurus/pull/3233 See https://github.com/facebook/docusaurus/pull/3233
@ -390,7 +393,7 @@ function SearchPageContent(): ReactNode {
</Head> </Head>
<div className="container margin-vert--lg"> <div className="container margin-vert--lg">
<Heading as="h1">{getTitle()}</Heading> <Heading as="h1">{pageTitle}</Heading>
<form className="row" onSubmit={(e) => e.preventDefault()}> <form className="row" onSubmit={(e) => e.preventDefault()}>
<div <div