From bfda08e65973ece0520d7396d0deba74f8fb988d Mon Sep 17 00:00:00 2001 From: Zenith Rifle <84105075+eli32-vlc@users.noreply.github.com> Date: Sun, 4 Jan 2026 13:39:22 +0800 Subject: [PATCH] Your local exact search (#4535) * Initial plan * Add fuzzy/exact search toggle to VPLocalSearchBox Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com> * Complete fuzzy/exact search toggle implementation with screenshots Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com> * Add minisearch dependency and update screenshots with actual interface Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com> * Remove temporary comment and restore web fonts preset Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- docs/.vitepress/config.mts | 6 + docs/.vitepress/constants.ts | 2 +- .../theme/components/VPLocalSearchBox.vue | 923 ++++++++++++++++++ package.json | 3 + pnpm-lock.yaml | 60 ++ 5 files changed, 993 insertions(+), 1 deletion(-) create mode 100644 docs/.vitepress/theme/components/VPLocalSearchBox.vue diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 8b73fb0be..04326b833 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -98,6 +98,12 @@ export default defineConfig({ replacement: fileURLToPath( new URL('./theme/components/ThemeDropdown.vue', import.meta.url) ) + }, + { + find: /^.*VPLocalSearchBox\.vue$/, + replacement: fileURLToPath( + new URL('./theme/components/VPLocalSearchBox.vue', import.meta.url) + ) } ] }, diff --git a/docs/.vitepress/constants.ts b/docs/.vitepress/constants.ts index fb22ca7fb..108d4359d 100644 --- a/docs/.vitepress/constants.ts +++ b/docs/.vitepress/constants.ts @@ -121,7 +121,7 @@ export const search: DefaultTheme.Config['search'] = { }, searchOptions: { combineWith: 'AND', - fuzzy: true, + fuzzy: false, // @ts-ignore boostDocument: (documentId, term, storedFields: Record) => { const titles = (storedFields?.titles as string[]) diff --git a/docs/.vitepress/theme/components/VPLocalSearchBox.vue b/docs/.vitepress/theme/components/VPLocalSearchBox.vue new file mode 100644 index 000000000..94ec1709b --- /dev/null +++ b/docs/.vitepress/theme/components/VPLocalSearchBox.vue @@ -0,0 +1,923 @@ + + + + + + + + + + + + + + + + + + + + -1 && (showDetailedList = !showDetailedList) + " + > + + + + + ~ + = + + + + + + + + + + + + + + # + + + + + + + + + + + + + + + + + + + + + {{ translate('modal.noResultsText') }} "{{ filterText }}" + + + + + + + + + + + + {{ translate('modal.footer.navigateText') }} + + + + + + {{ translate('modal.footer.selectText') }} + + + esc + {{ translate('modal.footer.closeText') }} + + + + + + + + diff --git a/package.json b/package.json index eb8e4f4fc..43cad16ef 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,12 @@ "@headlessui/vue": "^1.7.23", "@resvg/resvg-js": "^2.6.2", "@vueuse/core": "^14.1.0", + "@vueuse/integrations": "^14.1.0", "consola": "^3.4.2", "feed": "^5.1.0", "itty-fetcher": "^1.0.10", + "mark.js": "^8.11.1", + "minisearch": "^7.2.0", "nitro-cors": "^0.7.1", "nitropack": "^2.12.9", "nprogress": "^0.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d479c575..868915f9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@vueuse/core': specifier: ^14.1.0 version: 14.1.0(vue@3.5.25(typescript@5.9.3)) + '@vueuse/integrations': + specifier: ^14.1.0 + version: 14.1.0(focus-trap@7.6.6)(nprogress@0.2.0)(vue@3.5.25(typescript@5.9.3)) consola: specifier: ^3.4.2 version: 3.4.2 @@ -32,6 +35,12 @@ importers: itty-fetcher: specifier: ^1.0.10 version: 1.0.10 + mark.js: + specifier: ^8.11.1 + version: 8.11.1 + minisearch: + specifier: ^7.2.0 + version: 7.2.0 nitro-cors: specifier: ^0.7.1 version: 0.7.1 @@ -2222,6 +2231,48 @@ packages: universal-cookie: optional: true + '@vueuse/integrations@14.1.0': + resolution: {integrity: sha512-eNQPdisnO9SvdydTIXnTE7c29yOsJBD/xkwEyQLdhDC/LKbqrFpXHb3uS//7NcIrQO3fWVuvMGp8dbK6mNEMCA==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 || ^8 + vue: ^3.5.0 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + '@vueuse/metadata@12.8.2': resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} @@ -6851,6 +6902,15 @@ snapshots: transitivePeerDependencies: - typescript + '@vueuse/integrations@14.1.0(focus-trap@7.6.6)(nprogress@0.2.0)(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@vueuse/core': 14.1.0(vue@3.5.25(typescript@5.9.3)) + '@vueuse/shared': 14.1.0(vue@3.5.25(typescript@5.9.3)) + vue: 3.5.25(typescript@5.9.3) + optionalDependencies: + focus-trap: 7.6.6 + nprogress: 0.2.0 + '@vueuse/metadata@12.8.2': {} '@vueuse/metadata@14.1.0': {}