mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-02 19:57:25 +02:00
implement TitleFormatterProvider
This commit is contained in:
parent
f414ebf442
commit
1460e06d21
3 changed files with 79 additions and 18 deletions
|
@ -43,7 +43,10 @@ export {
|
||||||
|
|
||||||
export {DEFAULT_SEARCH_TAG} from './utils/searchUtils';
|
export {DEFAULT_SEARCH_TAG} from './utils/searchUtils';
|
||||||
|
|
||||||
export {useTitleFormatter} from './utils/titleFormatterUtils';
|
export {
|
||||||
|
TitleFormatterProvider,
|
||||||
|
useTitleFormatter,
|
||||||
|
} from './utils/titleFormatterUtils';
|
||||||
|
|
||||||
export {useLocationChange} from './utils/useLocationChange';
|
export {useLocationChange} from './utils/useLocationChange';
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {DefaultTitleFormatter} from '../titleFormatterUtils';
|
import {TitleFormatterFnDefault} from '../titleFormatterUtils';
|
||||||
|
|
||||||
describe('DefaultTitleFormatter', () => {
|
describe('TitleFormatterFnDefault', () => {
|
||||||
it('works', () => {
|
it('works', () => {
|
||||||
expect(
|
expect(
|
||||||
DefaultTitleFormatter({
|
TitleFormatterFnDefault({
|
||||||
title: 'a page',
|
title: 'a page',
|
||||||
siteTitle: 'my site',
|
siteTitle: 'my site',
|
||||||
titleDelimiter: '·',
|
titleDelimiter: '·',
|
||||||
|
@ -20,7 +20,7 @@ describe('DefaultTitleFormatter', () => {
|
||||||
|
|
||||||
it('ignores empty title', () => {
|
it('ignores empty title', () => {
|
||||||
expect(
|
expect(
|
||||||
DefaultTitleFormatter({
|
TitleFormatterFnDefault({
|
||||||
title: ' ',
|
title: ' ',
|
||||||
siteTitle: 'my site',
|
siteTitle: 'my site',
|
||||||
titleDelimiter: '·',
|
titleDelimiter: '·',
|
||||||
|
@ -33,7 +33,7 @@ describe('DefaultTitleFormatter', () => {
|
||||||
// By default it's preferable to avoid duplicate siteTitle
|
// By default it's preferable to avoid duplicate siteTitle
|
||||||
// See also https://github.com/facebook/docusaurus/issues/5878#issuecomment-961505856
|
// See also https://github.com/facebook/docusaurus/issues/5878#issuecomment-961505856
|
||||||
expect(
|
expect(
|
||||||
DefaultTitleFormatter({
|
TitleFormatterFnDefault({
|
||||||
title: 'my site',
|
title: 'my site',
|
||||||
siteTitle: 'my site',
|
siteTitle: 'my site',
|
||||||
titleDelimiter: '·',
|
titleDelimiter: '·',
|
||||||
|
|
|
@ -5,21 +5,48 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {createContext, useContext, useMemo} from 'react';
|
||||||
|
import type {ReactNode} from 'react';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
import {ReactContextError} from './reactUtils';
|
||||||
|
|
||||||
type TitleFormatterParams = {
|
type TitleFormatterParams = {
|
||||||
title: string | undefined;
|
/**
|
||||||
|
* The page title to format
|
||||||
|
* Usually provided through <PageMetadata> component
|
||||||
|
* But also when using useTitleFormatter().format(title)
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
/**
|
||||||
|
* The siteConfig.title value
|
||||||
|
*/
|
||||||
siteTitle: string;
|
siteTitle: string;
|
||||||
|
/**
|
||||||
|
* The siteConfig.titleDelimiter value
|
||||||
|
*/
|
||||||
titleDelimiter: string;
|
titleDelimiter: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TitleFormatterFn = (params: TitleFormatterParams) => string;
|
/**
|
||||||
|
* This is the full formatting function
|
||||||
|
* Can be customized through React context with the provider
|
||||||
|
*/
|
||||||
|
export type TitleFormatterFn = (params: TitleFormatterParams) => string;
|
||||||
|
|
||||||
export const DefaultTitleFormatter: TitleFormatterFn = ({
|
/**
|
||||||
|
* The default formatter is provided in params for convenience
|
||||||
|
*/
|
||||||
|
export type TitleFormatterFnWithDefaultFormatter = (
|
||||||
|
params: TitleFormatterParams & {
|
||||||
|
defaultFormatter: (params: TitleFormatterParams) => string;
|
||||||
|
},
|
||||||
|
) => string;
|
||||||
|
|
||||||
|
export const TitleFormatterFnDefault: TitleFormatterFn = ({
|
||||||
title,
|
title,
|
||||||
siteTitle,
|
siteTitle,
|
||||||
titleDelimiter,
|
titleDelimiter,
|
||||||
}: TitleFormatterParams): string => {
|
}): string => {
|
||||||
const trimmedTitle = title?.trim();
|
const trimmedTitle = title?.trim();
|
||||||
if (!trimmedTitle || trimmedTitle === siteTitle) {
|
if (!trimmedTitle || trimmedTitle === siteTitle) {
|
||||||
return siteTitle;
|
return siteTitle;
|
||||||
|
@ -27,16 +54,47 @@ export const DefaultTitleFormatter: TitleFormatterFn = ({
|
||||||
return `${trimmedTitle} ${titleDelimiter} ${siteTitle}`;
|
return `${trimmedTitle} ${titleDelimiter} ${siteTitle}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TitleFormatterUtils = {format: (title?: string) => string};
|
/**
|
||||||
|
* This is the simpler API exposed to theme/users
|
||||||
|
*/
|
||||||
|
type TitleFormatter = {format: (title: string) => string};
|
||||||
|
|
||||||
|
const TitleFormatterContext = createContext<TitleFormatter | null>(null);
|
||||||
|
|
||||||
|
export function TitleFormatterProvider({
|
||||||
|
formatter,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
formatter: TitleFormatterFnWithDefaultFormatter;
|
||||||
|
}): ReactNode {
|
||||||
|
const {siteConfig} = useDocusaurusContext();
|
||||||
|
const {title: siteTitle, titleDelimiter} = siteConfig;
|
||||||
|
const value: TitleFormatter = useMemo(() => {
|
||||||
|
return {
|
||||||
|
format: (title: string) =>
|
||||||
|
formatter({
|
||||||
|
title,
|
||||||
|
siteTitle,
|
||||||
|
titleDelimiter,
|
||||||
|
defaultFormatter: TitleFormatterFnDefault,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}, [formatter, siteTitle, titleDelimiter]);
|
||||||
|
return (
|
||||||
|
<TitleFormatterContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</TitleFormatterContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a function to format the page title
|
* Returns a function to format the page title
|
||||||
*/
|
*/
|
||||||
export function useTitleFormatter(): TitleFormatterUtils {
|
export function useTitleFormatter(): TitleFormatter {
|
||||||
const {siteConfig} = useDocusaurusContext();
|
const value = useContext(TitleFormatterContext);
|
||||||
const formatter = DefaultTitleFormatter;
|
if (value === null) {
|
||||||
const {title: siteTitle, titleDelimiter} = siteConfig;
|
throw new ReactContextError('TitleFormatterProvider');
|
||||||
return {
|
}
|
||||||
format: (title) => formatter({title, siteTitle, titleDelimiter}),
|
return value;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue