diff --git a/src/.vuepress/config.ts b/src/.vuepress/config.ts index 9528f4870..2504221ec 100644 --- a/src/.vuepress/config.ts +++ b/src/.vuepress/config.ts @@ -1,21 +1,12 @@ import { defineUserConfig } from "vuepress"; import theme from "./theme.js"; -import { searchPlugin } from "@vuepress/plugin-search"; +import { contentSearchPlugin } from "./search.js"; import { shikiPlugin } from "@vuepress/plugin-shiki"; import path from "path"; export default defineUserConfig({ base: "/", plugins: [ - searchPlugin({ - locales: { - "/": { - placeholder: "Search", - }, - "/zh/": { - placeholder: "搜索", - }, - }, - }), + contentSearchPlugin(), shikiPlugin({ theme: "dracula", langs: [ diff --git a/src/.vuepress/search.ts b/src/.vuepress/search.ts new file mode 100644 index 000000000..eb642ee4e --- /dev/null +++ b/src/.vuepress/search.ts @@ -0,0 +1,29 @@ +import { searchPlugin } from "@vuepress/plugin-search"; +import type { Plugin } from "vuepress"; + +export const contentSearchPlugin = (): Plugin => { + let decodeEntity: (entity: string) => string; + + return { + ...searchPlugin({ + locales: { + "/": { placeholder: "Search" }, + "/zh/": { placeholder: "搜索" }, + }, + // 标题由插件索引;正文包含 @include 内容,去掉标签后还原 HTML 实体。 + getExtraFields: (page) => [ + page.contentRendered + .replace(/]*>[\s\S]*?<\/h[1-6]>/gi, "") + .replace(/|<[^>]*>/g, "") + .replace(/&(?:#x[\da-f]+|#\d+|[a-z][\da-z]*);/gi, decodeEntity) + .replace(/\s+/g, " ") + .trim(), + ], + }), + name: "@vuepress/plugin-search", + // Markdown 配置先于搜索索引生成,复用其实体解码,不新增依赖。 + extendsMarkdown(markdown) { + decodeEntity = markdown.utils.unescapeAll; + }, + }; +};