Skip to content

Commit 9fee554

Browse files
zonemeenbrc-dd
andauthored
feat(search): support minisearch customization (#2576)
Co-authored-by: Divyansh Singh <[email protected]>
1 parent e8074e6 commit 9fee554

File tree

4 files changed

+87
-16
lines changed

4 files changed

+87
-16
lines changed

Diff for: docs/reference/default-theme-search.md

+36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
---
2+
outline: deep
3+
---
4+
15
# Search
26

37
## Local Search
@@ -58,6 +62,38 @@ export default defineConfig({
5862
})
5963
```
6064

65+
### miniSearch options
66+
67+
You can configure MiniSearch like this:
68+
69+
```ts
70+
import { defineConfig } from 'vitepress'
71+
72+
export default defineConfig({
73+
themeConfig: {
74+
search: {
75+
provider: 'local',
76+
options: {
77+
miniSearch: {
78+
/**
79+
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
80+
*/
81+
options: { /* ... */ },
82+
/**
83+
* @type {import('minisearch').SearchOptions}
84+
* @default
85+
* { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
86+
*/
87+
searchOptions: { /* ... */ }
88+
}
89+
}
90+
}
91+
}
92+
})
93+
```
94+
95+
Learn more in [MiniSearch docs](https://lucaong.github.io/minisearch/classes/_minisearch_.minisearch.html).
96+
6197
## Algolia Search
6298

6399
VitePress supports searching your docs site using [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Refer their getting started guide. In your `.vitepress/config.ts` you'll need to provide at least the following to make it work:

Diff for: src/client/theme-default/components/VPLocalSearchBox.vue

+26-8
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,12 @@ const searchIndex = computedAsync(async () =>
8080
searchOptions: {
8181
fuzzy: 0.2,
8282
prefix: true,
83-
boost: { title: 4, text: 2, titles: 1 }
84-
}
83+
boost: { title: 4, text: 2, titles: 1 },
84+
...(theme.value.search?.provider === 'local' &&
85+
theme.value.search.options?.miniSearch?.searchOptions)
86+
},
87+
...(theme.value.search?.provider === 'local' &&
88+
theme.value.search.options?.miniSearch?.options)
8589
}
8690
)
8791
)
@@ -396,8 +400,16 @@ function formMarkRegex(terms: Set<string>) {
396400
<div class="backdrop" @click="$emit('close')" />
397401

398402
<div class="shell">
399-
<form class="search-bar" @pointerup="onSearchBarClick($event)" @submit.prevent="">
400-
<label :title="placeholder" id="localsearch-label" for="localsearch-input">
403+
<form
404+
class="search-bar"
405+
@pointerup="onSearchBarClick($event)"
406+
@submit.prevent=""
407+
>
408+
<label
409+
:title="placeholder"
410+
id="localsearch-label"
411+
for="localsearch-input"
412+
>
401413
<svg
402414
class="search-icon"
403415
width="18"
@@ -454,7 +466,9 @@ function formMarkRegex(terms: Set<string>) {
454466
class="toggle-layout-button"
455467
:class="{ 'detailed-list': showDetailedList }"
456468
:title="$t('modal.displayDetails')"
457-
@click="selectedIndex > -1 && (showDetailedList = !showDetailedList)"
469+
@click="
470+
selectedIndex > -1 && (showDetailedList = !showDetailedList)
471+
"
458472
>
459473
<svg
460474
width="18"
@@ -527,7 +541,11 @@ function formMarkRegex(terms: Set<string>) {
527541
<div>
528542
<div class="titles">
529543
<span class="title-icon">#</span>
530-
<span v-for="(t, index) in p.titles" :key="index" class="title">
544+
<span
545+
v-for="(t, index) in p.titles"
546+
:key="index"
547+
class="title"
548+
>
531549
<span class="text" v-html="t" />
532550
<svg width="18" height="18" viewBox="0 0 24 24">
533551
<path
@@ -547,7 +565,7 @@ function formMarkRegex(terms: Set<string>) {
547565

548566
<div v-if="showDetailedList" class="excerpt-wrapper">
549567
<div v-if="p.text" class="excerpt" inert>
550-
<div class="vp-doc" v-html="p.text" />
568+
<div class="vp-doc" v-html="p.text" />
551569
</div>
552570
<div class="excerpt-gradient-bottom" />
553571
<div class="excerpt-gradient-top" />
@@ -726,7 +744,7 @@ function formMarkRegex(terms: Set<string>) {
726744
}
727745
728746
.search-actions button.clear-button:disabled {
729-
opacity: 0.37;
747+
opacity: 0.37;
730748
}
731749
732750
.search-keyboard-shortcuts {

Diff for: src/node/plugins/localSearchPlugin.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import path from 'node:path'
2-
import type { Plugin, ViteDevServer } from 'vite'
3-
import MiniSearch from 'minisearch'
4-
import fs from 'fs-extra'
51
import _debug from 'debug'
2+
import fs from 'fs-extra'
3+
import MiniSearch from 'minisearch'
4+
import path from 'path'
5+
import type { Plugin, ViteDevServer } from 'vite'
66
import type { SiteConfig } from '../config'
77
import type { MarkdownEnv } from '../markdown'
88
import { createMarkdownRenderer } from '../markdown'
9-
import { resolveSiteDataByRoute, slash } from '../shared'
9+
import { resolveSiteDataByRoute, slash, type DefaultTheme } from '../shared'
1010

1111
const debug = _debug('vitepress:local-search')
1212

@@ -21,7 +21,7 @@ interface IndexObject {
2121
}
2222

2323
export async function localSearchPlugin(
24-
siteConfig: SiteConfig
24+
siteConfig: SiteConfig<DefaultTheme.Config>
2525
): Promise<Plugin> {
2626
if (siteConfig.site.themeConfig?.search?.provider !== 'local') {
2727
return {
@@ -63,7 +63,9 @@ export async function localSearchPlugin(
6363
if (!index) {
6464
index = new MiniSearch<IndexObject>({
6565
fields: ['title', 'titles', 'text'],
66-
storeFields: ['title', 'titles']
66+
storeFields: ['title', 'titles'],
67+
...(siteConfig.site.themeConfig?.search?.provider === 'local' &&
68+
siteConfig.site.themeConfig.search.options?.miniSearch?.options)
6769
})
6870
indexByLocales.set(locale, index)
6971
}

Diff for: types/default-theme.d.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { type ComputedRef, type Ref } from 'vue'
1+
import type { Options as MiniSearchOptions } from 'minisearch'
2+
import type { ComputedRef, Ref } from 'vue'
23
import type { DocSearchProps } from './docsearch.js'
34
import type { LocalSearchTranslations } from './local-search.js'
45
import type { PageData } from './shared.js'
@@ -335,6 +336,20 @@ export namespace DefaultTheme {
335336

336337
translations?: LocalSearchTranslations
337338
locales?: Record<string, Partial<Omit<LocalSearchOptions, 'locales'>>>
339+
340+
miniSearch?: {
341+
/**
342+
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#options
343+
*/
344+
options?: Pick<
345+
MiniSearchOptions,
346+
'extractField' | 'tokenize' | 'processTerm'
347+
>
348+
/**
349+
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchoptions-1
350+
*/
351+
searchOptions?: MiniSearchOptions['searchOptions']
352+
}
338353
}
339354

340355
// algolia -------------------------------------------------------------------

0 commit comments

Comments
 (0)