You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/docs/ko/reference/default-theme-search.md

387 lines
11 KiB

---
outline: deep
---
# 검색 {#search}
## 로컬 검색 {#local-search}
VitePress는 [minisearch](https://github.com/lucaong/minisearch/)를 통해 브라우저 내 인덱스를 사용한 퍼지 전문 검색을 지원합니다. 이 기능을 활성화하려면, `.vitepress/config.ts` 파일 내에서 `themeConfig.search.provider` 옵션을 `'local'`로 설정하면 됩니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local'
}
}
})
```
예시 결과:
![검색 모달의 스크린샷](/search.png)
또는, [Algolia DocSearch](#algolia-search)나 <https://www.npmjs.com/package/vitepress-plugin-search>, <https://www.npmjs.com/package/vitepress-plugin-pagefind>과 같은 커뮤니티 플러그인을 사용할 수 있습니다.
### i18n {#local-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
zh: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오.
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
displayDetails: '显示详细列表',
resetButtonTitle: '重置搜索',
backButtonTitle: '关闭搜索',
noResultsText: '没有结果',
footer: {
selectText: '选择',
selectKeyAriaLabel: '输入',
navigateText: '导航',
navigateUpKeyAriaLabel: '上箭头',
navigateDownKeyAriaLabel: '下箭头',
closeText: '关闭',
closeKeyAriaLabel: 'esc'
}
}
}
}
}
}
}
}
})
```
### miniSearch 옵션 {#mini-search-options}
다음과 같이 MiniSearch를 구성할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
miniSearch: {
/**
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
*/
options: {
/* ... */
},
/**
* @type {import('minisearch').SearchOptions}
* @default
* { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
*/
searchOptions: {
/* ... */
}
}
}
}
}
})
```
[MiniSearch 문서](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)에서 더 많은 정보를 얻을 수 있습니다.
### 사용자 정의 콘텐츠 렌더러 {#custom-content-renderer}
색인 생성 전에 마크다운 콘텐츠를 렌더링하는 데 사용되는 함수를 커스터마이즈할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
/**
* @param {string} src
* @param {import('vitepress').MarkdownEnv} env
* @param {import('markdown-it')} md
*/
_render(src, env, md) {
// return html string
}
}
}
}
})
```
이 함수는 클라이언트 사이드 사이트 데이터에서 제거될 것이므로, 여기서 Node.js API를 사용할 수 있습니다.
#### 예시: 검색에서 페이지 제외 {#example-excluding-pages-from-search}
페이지에서 `search: false`를 프론트매터에 추가하여 검색에서 페이지를 제외할 수 있습니다. 또는 다음과 같이 합니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})
```
::: warning 참고
사용자 정의 `_render` 함수를 제공하는 경우, `search: false` 프론트매터를 직접 처리해야 합니다. 또한, `md.render`가 호출되기 전에는 `env` 객체가 완전히 채워지지 않으므로, `frontmatter`와 같은 선택적 `env` 속성에 대한 검사는 그 이후에 수행해야 합니다.
:::
#### 예시: 콘텐츠 변환 - 앵커 추가 {#example-transforming-content-adding-anchors}
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.title)
return md.render(`# ${env.frontmatter.title}`) + html
return html
}
}
}
}
})
```
## Algolia 검색 {#algolia-search}
VitePress는 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트 검색을 지원합니다. 시작 가이드를 참조하세요. 작동하게 하려면 `.vitepress/config.ts`에서 최소한 다음 정보를 제공해야 합니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})
```
### i18n {#algolia-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
},
modal: {
searchBox: {
resetButtonTitle: '清除查询条件',
resetButtonAriaLabel: '清除查询条件',
cancelButtonText: '取消',
cancelButtonAriaLabel: '取消'
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '没有搜索历史',
saveRecentSearchButtonTitle: '保存至搜索历史',
removeRecentSearchButtonTitle: '从搜索历史中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查你的网络连接'
},
footer: {
selectText: '选择',
navigateText: '切换',
closeText: '关闭',
searchByText: '搜索提供者'
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为该查询应该有结果?',
reportMissingResultsLinkText: '点击反馈'
}
}
}
}
}
}
}
}
})
```
[이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 덮어쓸 수 있습니다. 공식 Algolia 문서에서 더 많은 정보를 알아보세요.
### 크롤러 구성 {#crawler-config}
이 사이트가 사용하는 것을 기반으로 한 예제 구성입니다:
```ts
new Crawler({
appId: '...',
apiKey: '...',
rateLimit: 8,
startUrls: ['https://vitepress.dev/'],
renderJavaScript: false,
sitemaps: [],
exclusionPatterns: [],
ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'],
schedule: '매주 토요일 05:10에',
actions: [
{
indexName: 'vitepress',
pathsToMatch: ['https://vitepress.dev/**'],
recordExtractor: ({ $, helpers }) => {
return helpers.docsearch({
recordProps: {
lvl1: '.content h1',
content: '.content p, .content li',
lvl0: {
selectors: '',
defaultValue: '문서'
},
lvl2: '.content h2',
lvl3: '.content h3',
lvl4: '.content h4',
lvl5: '.content h5'
},
indexHeadings: true
})
}
}
],
initialIndexSettings: {
vitepress: {
attributesForFaceting: ['type', 'lang'],
attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
attributesToSnippet: ['content:10'],
camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
searchableAttributes: [
'unordered(hierarchy_radio_camel.lvl0)',
'unordered(hierarchy_radio.lvl0)',
'unordered(hierarchy_radio_camel.lvl1)',
'unordered(hierarchy_radio.lvl1)',
'unordered(hierarchy_radio_camel.lvl2)',
'unordered(hierarchy_radio.lvl2)',
'unordered(hierarchy_radio_camel.lvl3)',
'unordered(hierarchy_radio.lvl3)',
'unordered(hierarchy_radio_camel.lvl4)',
'unordered(hierarchy_radio.lvl4)',
'unordered(hierarchy_radio_camel.lvl5)',
'unordered(hierarchy_radio.lvl5)',
'unordered(hierarchy_radio_camel.lvl6)',
'unordered(hierarchy_radio.lvl6)',
'unordered(hierarchy_camel.lvl0)',
'unordered(hierarchy.lvl0)',
'unordered(hierarchy_camel.lvl1)',
'unordered(hierarchy.lvl1)',
'unordered(hierarchy_camel.lvl2)',
'unordered(hierarchy.lvl2)',
'unordered(hierarchy_camel.lvl3)',
'unordered(hierarchy.lvl3)',
'unordered(hierarchy_camel.lvl4)',
'unordered(hierarchy.lvl4)',
'unordered(hierarchy_camel.lvl5)',
'unordered(hierarchy.lvl5)',
'unordered(hierarchy_camel.lvl6)',
'unordered(hierarchy.lvl6)',
'content'
],
distinct: true,
attributeForDistinct: 'url',
customRanking: [
'desc(weight.pageRank)',
'desc(weight.level)',
'asc(weight.position)'
],
ranking: [
'words',
'filters',
'typo',
'attribute',
'proximity',
'exact',
'custom'
],
highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
highlightPostTag: '</span>',
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: 'allOptional'
}
}
})
```
<style>
img[src="/search.png"] {
width: 100%;
aspect-ratio: 1 / 1;
}
</style>