From d6a463d6f9b169a30db787f92738c159a2b63865 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Mon, 16 Mar 2026 11:38:49 +0800 Subject: [PATCH 1/4] feat: add pageTitleFormatter option for customizable document title --- docs/configuration.md | 18 ++++++++++++++++++ src/core/config.js | 1 + src/core/event/index.js | 12 ++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index d9cdfd05b1..68a8cfcd45 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -275,6 +275,24 @@ window.$docsify = { }; ``` +## pageTitleFormatter + +- Type: `Function | null` +- Default: `null` + +Optional function to customize how the site `name` is used when composing the document title. If provided, Docsify will call this function with the configured `name` (which may contain HTML) and use the returned string as the title portion for the site name — Docsify will not automatically strip HTML or otherwise modify the value. If not provided, Docsify falls back to the default behavior of stripping HTML tags from `name`. + +Basic example — strip HTML and trim (equivalent to Docsify's default behavior): + +```js +window.$docsify = { + name: 'My Site', + pageTitleFormatter(name) { + return name ? name.replace(/<[^>]+>/g, '').trim() : ''; + }, +}; +``` + ## hideSidebar - Type : `Boolean` diff --git a/src/core/config.js b/src/core/config.js index f433b33d06..b2e2fdb9e2 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -27,6 +27,7 @@ const defaultDocsifyConfig = () => ({ fallbackLanguages: /** @type {null | string[]} */ (null), fallbackDefaultLanguage: '', formatUpdated: /** @type {string | ((updatedAt: string) => string)} */ (''), + pageTitleFormatter: /** @type {null | ((name: string) => string)} */ (null), /** For the frontmatter plugin. */ frontMatter: /** @type {Record | null} */ (null), hideSidebar: false, diff --git a/src/core/event/index.js b/src/core/event/index.js index 1fd7abce9b..8880195b88 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -323,13 +323,21 @@ export function Events(Base) { * @void */ onRender() { - const { name } = this.config; + const { name, pageTitleFormatter } = this.config; const currentPath = this.router.toURL(this.router.getCurrentPath()); const currentSection = dom .find(`.sidebar a[href='${currentPath}']`) ?.getAttribute('title'); - const plainName = name ? name.replace(/<[^>]+>/g, '').trim() : name; + // If a pageTitleFormatter is provided, let the user format the name + // (no automatic HTML stripping). Otherwise, default to stripping + // HTML tags from the configured name. + const plainName = + typeof pageTitleFormatter === 'function' + ? pageTitleFormatter(name) + : name + ? name.replace(/<[^>]+>/g, '').trim() + : name; const currentTitle = plainName ? currentSection ? `${currentSection} - ${plainName}` From d50e476d717209b09cb3a31417cd8115c64bc630 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Mon, 16 Mar 2026 11:39:31 +0800 Subject: [PATCH 2/4] fix: adjust indentation for page title formatting logic --- src/core/event/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/event/index.js b/src/core/event/index.js index 8880195b88..040c5b7148 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -336,8 +336,8 @@ export function Events(Base) { typeof pageTitleFormatter === 'function' ? pageTitleFormatter(name) : name - ? name.replace(/<[^>]+>/g, '').trim() - : name; + ? name.replace(/<[^>]+>/g, '').trim() + : name; const currentTitle = plainName ? currentSection ? `${currentSection} - ${plainName}` From 836488a23b48455f28e76fcb45ef4412ee93ca50 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Mon, 16 Mar 2026 11:53:32 +0800 Subject: [PATCH 3/4] fix: ensure pageTitleFormatter is called with a valid string name --- src/core/event/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/event/index.js b/src/core/event/index.js index 040c5b7148..e9c446cee0 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -333,7 +333,7 @@ export function Events(Base) { // (no automatic HTML stripping). Otherwise, default to stripping // HTML tags from the configured name. const plainName = - typeof pageTitleFormatter === 'function' + typeof pageTitleFormatter === 'function' && typeof name === 'string' ? pageTitleFormatter(name) : name ? name.replace(/<[^>]+>/g, '').trim() From 44768053d7da84c10c92432a5e4660eed8514cd4 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Mon, 16 Mar 2026 12:02:04 +0800 Subject: [PATCH 4/4] docs: update pageTitleFormatter type to reflect required function --- docs/configuration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 68a8cfcd45..7b61752984 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -277,7 +277,7 @@ window.$docsify = { ## pageTitleFormatter -- Type: `Function | null` +- Type: `Function` - Default: `null` Optional function to customize how the site `name` is used when composing the document title. If provided, Docsify will call this function with the configured `name` (which may contain HTML) and use the returned string as the title portion for the site name — Docsify will not automatically strip HTML or otherwise modify the value. If not provided, Docsify falls back to the default behavior of stripping HTML tags from `name`. @@ -474,7 +474,7 @@ window.$docsify = { ## name -- Type: `Boolean | String` +- Type: `Boolean|String` Website name as it appears in the sidebar.