title formatter

This commit is contained in:
sebastien 2025-04-11 15:51:36 +02:00
parent 5b944d6b64
commit fffb5a7213
4 changed files with 85 additions and 52 deletions

View file

@ -1,33 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import {renderHook} from '@testing-library/react-hooks';
import {Context} from '@docusaurus/core/src/client/docusaurusContext';
import {useTitleFormatter} from '../generalUtils';
import type {DocusaurusContext} from '@docusaurus/types';
describe('useTitleFormatter', () => {
const createUseTitleFormatterMock =
(context: DocusaurusContext) => (title?: string) =>
renderHook(() => useTitleFormatter(title), {
wrapper: ({children}) => (
<Context.Provider value={context}>{children}</Context.Provider>
),
}).result.current;
it('works', () => {
const mockUseTitleFormatter = createUseTitleFormatterMock({
siteConfig: {
title: 'my site',
titleDelimiter: '·',
},
} as DocusaurusContext);
expect(mockUseTitleFormatter('a page')).toBe('a page · my site');
expect(mockUseTitleFormatter(undefined)).toBe('my site');
expect(mockUseTitleFormatter(' ')).toBe('my site');
});
});

View file

@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {DefaultTitleFormatter} from '../generalUtils';
describe('DefaultTitleFormatter', () => {
it('works', () => {
expect(
DefaultTitleFormatter({
title: 'a page',
siteTitle: 'my site',
titleDelimiter: '·',
}),
).toBe('a page · my site');
});
it('ignores empty title', () => {
expect(
DefaultTitleFormatter({
title: ' ',
siteTitle: 'my site',
titleDelimiter: '·',
}),
).toBe('my site');
});
it('does not duplicate site title', () => {
// Users may pass <Layout title={siteTitle}> leading to duplicate titles
// By default it's preferable to avoid duplicate siteTitle
// See also https://github.com/facebook/docusaurus/issues/5878#issuecomment-961505856
expect(
DefaultTitleFormatter({
title: 'my site',
siteTitle: 'my site',
titleDelimiter: '·',
}),
).toBe('my site');
});
});

View file

@ -1,19 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
/**
* Formats the page's title based on relevant site config and other contexts.
*/
export function useTitleFormatter(title?: string | undefined): string {
const {siteConfig} = useDocusaurusContext();
const {title: siteTitle, titleDelimiter} = siteConfig;
return title?.trim().length
? `${title.trim()} ${titleDelimiter} ${siteTitle}`
: siteTitle;
}

View file

@ -0,0 +1,42 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
type TitleFormatterParams = {
title: string | undefined;
siteTitle: string;
titleDelimiter: string;
};
type TitleFormatterFn = (params: TitleFormatterParams) => string;
export const DefaultTitleFormatter: TitleFormatterFn = ({
title,
siteTitle,
titleDelimiter,
}: TitleFormatterParams): string => {
const trimmedTitle = title?.trim();
if (!trimmedTitle || trimmedTitle === siteTitle) {
return siteTitle;
}
return `${trimmedTitle} ${titleDelimiter} ${siteTitle}`;
};
type TitleFormatter = {format: (title?: string) => string};
/**
* Returns a function to format the page title
*/
export function useTitleFormatter(): TitleFormatter {
const {siteConfig} = useDocusaurusContext();
const formatter = DefaultTitleFormatter;
const {title: siteTitle, titleDelimiter} = siteConfig;
return {
format: (title) => formatter({title, siteTitle, titleDelimiter}),
};
}