From 60b1477be89cd3ce56023c4ad83896f5804053bc Mon Sep 17 00:00:00 2001 From: eivmosn Date: Fri, 17 Apr 2026 16:18:46 +0800 Subject: [PATCH] feat(vant-cli): add global static search across documents. --- packages/vant-cli/site/desktop/App.vue | 5 + .../site/desktop/components/Header.vue | 10 + .../site/desktop/components/Search.vue | 530 ++++++++++++++++++ .../site/desktop/components/index.vue | 2 + .../src/compiler/gen-site-desktop-shared.ts | 2 + .../src/compiler/gen-site-search-index.ts | 89 +++ packages/vant/vant.config.mjs | 1 + 7 files changed, 639 insertions(+) create mode 100644 packages/vant-cli/site/desktop/components/Search.vue create mode 100644 packages/vant-cli/src/compiler/gen-site-search-index.ts diff --git a/packages/vant-cli/site/desktop/App.vue b/packages/vant-cli/site/desktop/App.vue index f5ca431ff59..2e4b48cf182 100644 --- a/packages/vant-cli/site/desktop/App.vue +++ b/packages/vant-cli/site/desktop/App.vue @@ -9,6 +9,7 @@ :has-simulator="hasSimulator" :lang-configs="langConfigs" :dark-mode-class="darkModeClass" + :search="search" >
@@ -79,6 +80,10 @@ export default { versions() { return config.site.versions || null; }, + + search() { + return Boolean(config.site?.search); + }, }, watch: { diff --git a/packages/vant-cli/site/desktop/components/Header.vue b/packages/vant-cli/site/desktop/components/Header.vue index 3ae7406f703..c73dcd54780 100644 --- a/packages/vant-cli/site/desktop/components/Header.vue +++ b/packages/vant-cli/site/desktop/components/Header.vue @@ -11,6 +11,10 @@
    +
  • + +
  • +
  • import { packageVersion } from 'site-desktop-shared'; import { getDefaultTheme, syncThemeToChild } from '../../common/iframe-sync'; +import VanDocSearch from './Search.vue'; export default { name: 'VanDocHeader', + components: { + VanDocSearch, + }, + props: { lang: String, config: Object, versions: Array, langConfigs: Array, darkModeClass: String, + search: Boolean, }, data() { diff --git a/packages/vant-cli/site/desktop/components/Search.vue b/packages/vant-cli/site/desktop/components/Search.vue new file mode 100644 index 00000000000..ab34181cc25 --- /dev/null +++ b/packages/vant-cli/site/desktop/components/Search.vue @@ -0,0 +1,530 @@ + + + + + diff --git a/packages/vant-cli/site/desktop/components/index.vue b/packages/vant-cli/site/desktop/components/index.vue index ed51ca7dd18..bc359a41e70 100644 --- a/packages/vant-cli/site/desktop/components/index.vue +++ b/packages/vant-cli/site/desktop/components/index.vue @@ -6,6 +6,7 @@ :versions="versions" :lang-configs="langConfigs" :dark-mode-class="darkModeClass" + :search="search" @switch-version="$emit('switch-version', $event)" /> @@ -43,6 +44,7 @@ export default { langConfigs: Array, hasSimulator: Boolean, darkModeClass: String, + search: Boolean, config: { type: Object, required: true, diff --git a/packages/vant-cli/src/compiler/gen-site-desktop-shared.ts b/packages/vant-cli/src/compiler/gen-site-desktop-shared.ts index 22d234c932b..120dce376cb 100644 --- a/packages/vant-cli/src/compiler/gen-site-desktop-shared.ts +++ b/packages/vant-cli/src/compiler/gen-site-desktop-shared.ts @@ -2,6 +2,7 @@ import glob from 'fast-glob'; import { join, parse } from 'node:path'; import { existsSync, readFileSync, readdirSync } from 'node:fs'; import { pascalize, getVantConfig, normalizePath } from '../common/index.js'; +import { genSiteSearchIndex } from './gen-site-search-index.js'; import { SRC_DIR, DOCS_DIR, @@ -109,6 +110,7 @@ ${genVantConfigContent()} ${genExportConfig()} ${genExportDocuments(documents)} +${genSiteSearchIndex()} ${genExportVersion()} `; diff --git a/packages/vant-cli/src/compiler/gen-site-search-index.ts b/packages/vant-cli/src/compiler/gen-site-search-index.ts new file mode 100644 index 00000000000..d06dd1a34bc --- /dev/null +++ b/packages/vant-cli/src/compiler/gen-site-search-index.ts @@ -0,0 +1,89 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { getVantConfig } from '../common/index.js'; +import { DOCS_DIR, SRC_DIR } from '../common/constant.js'; + +type SearchIndexItem = { + lang: string; + title: string; + path: string; + group: string; + content: string; +}; + +function getDocumentPath(path: string, lang: string, defaultLang: string) { + const componentDoc = + lang === defaultLang + ? join(SRC_DIR, path, 'README.md') + : join(SRC_DIR, path, `README.${lang}.md`); + + if (existsSync(componentDoc)) { + return componentDoc; + } + + const staticDoc = join(DOCS_DIR, 'markdown', `${path}.${lang}.md`); + if (existsSync(staticDoc)) { + return staticDoc; + } + + const fallbackStaticDoc = join(DOCS_DIR, 'markdown', `${path}.md`); + if (existsSync(fallbackStaticDoc)) { + return fallbackStaticDoc; + } + + return ''; +} + +function stripMarkdown(content: string) { + return content + .replace(/```[\s\S]*?```/g, ' ') + .replace(/`([^`]+)`/g, '$1') + .replace(/<[^>]+>/g, ' ') + .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') + .replace(/[>#*_~|]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); +} + +export function genSiteSearchIndex() { + const vantConfig = getVantConfig(); + const { locales, defaultLang } = vantConfig.site; + const index: SearchIndexItem[] = []; + + Object.keys(locales || {}).forEach((lang) => { + const locale = locales[lang]; + const nav = locale.nav || []; + + nav.forEach( + (group: { + title: string; + items: { path?: string; title?: string }[]; + }) => { + group.items.forEach((item) => { + if (!item.path || !item.title) { + return; + } + + const documentPath = getDocumentPath(item.path, lang, defaultLang); + if (!documentPath) { + return; + } + + const source = readFileSync(documentPath, 'utf-8'); + const path = + item.path === 'home' ? `/${lang}` : `/${lang}/${item.path}`; + + index.push({ + lang, + title: item.title, + path, + group: group.title, + content: stripMarkdown(`${item.title} ${group.title} ${source}`), + }); + }); + }, + ); + }); + + return `export const searchIndex = ${JSON.stringify(index)};`; +} diff --git a/packages/vant/vant.config.mjs b/packages/vant/vant.config.mjs index 571896a700f..1725dc12fa8 100644 --- a/packages/vant/vant.config.mjs +++ b/packages/vant/vant.config.mjs @@ -25,6 +25,7 @@ export default { darkModeClass: 'van-theme-dark', lightModeClass: 'van-theme-light', enableVConsole: false, + search: true, versions: [ { label: 'v1', link: '/vant/v1/' }, { label: 'v2', link: '/vant/v2/' },