Buscar
Busqueda local
VitePress admite la búsqueda de texto completo utilizando un índice en el navegador gracias a minisearch. Para habilitar esta función, simplemente configure la opción themeConfig.search.provider como 'local' en el archivo .vitepress/config.ts:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local'
}
}
})Resultado de ejemplo:

Alternativamente, puedes usar Algolia DocSearch o algunos complementos comunitarios como https://www.npmjs.com/package/vitepress-plugin-search o https://www.npmjs.com/package/vitepress-plugin-pagefind.
i18n
Puede utilizar una configuración como esta para utilizar la búsqueda multilingüe:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
es: { // usa `root` si quieres traducir la configuración regional predeterminada
translations: {
button: {
buttonText: 'Buscar',
buttonAriaLabel: 'Buscar'
},
modal: {
displayDetails: 'Mostrar lista detallada',
resetButtonTitle: 'Restablecer búsqueda',
backButtonTitle: 'Cerrar búsqueda',
noResultsText: 'No hay resultados',
footer: {
selectText: 'Seleccionar',
selectKeyAriaLabel: 'Intro',
navigateText: 'Navegar',
navigateUpKeyAriaLabel: 'Flecha arriba',
navigateDownKeyAriaLabel: 'Flecha abajo',
closeText: 'Cerrar',
closeKeyAriaLabel: 'Esc'
}
}
}
}
}
}
}
}
})Opciones MiniSearch
Puedes configurar MiniSearch de esta manera:
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: {
/* ... */
}
}
}
}
}
})Obtenga más información en documentación de MiniSearch.
Presentador de contenido personalizado
Puedes personalizar la función utilizada para presentar el contenido de rebajas antes de indexarlo:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
/**
* @param {string} src
* @param {import('vitepress').MarkdownEnv} env
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
// devuelve una cadena HTML
}
}
}
}
})Esta función se eliminará de los datos del sitio web en el lado del cliente, por lo que podrá utilizar las API de Node.js en ella.
Ejemplo: Excluir páginas de la busqueda
Puedes excluir páginas de la busqueda adicionando search: false al principio de la página. Alternativamente:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})Nota
En este caso, una función _render se proporciona, es necesario manipular el search: false desde el frente por su cuenta. Además, el objeto env no estará completamente poblado antes que md.renderAsync se llama, luego verifica las propiedades opcionales env, como frontmatter, debe hacerse después de eso.
Ejemplo: Transformar contenido - agregar anclajes
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.title)
return await md.renderAsync(`# ${env.frontmatter.title}`) + html
return html
}
}
}
}
})Busqueda de Algolia
VitePress admite la búsqueda en su sitio de documentación utilizando Algolia DocSearch. Consulte su guía de introducción. en tu archivo .vitepress/config.ts, Deberá proporcionar al menos lo siguiente para que funcione:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})i18n
Puedes utilizar una configuración como esta para utilizar la búsqueda multilingüe:
Haz clic para expandir
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
searchBox: {
clearButtonTitle: '清除',
clearButtonAriaLabel: '清除查询',
closeButtonText: '关闭',
closeButtonAriaLabel: '关闭',
placeholderText: '搜索文档或向 AI 提问',
placeholderTextAskAi: '再问一个问题...',
placeholderTextAskAiStreaming: '正在回答...',
searchInputLabel: '搜索',
backToKeywordSearchButtonText: '返回关键词搜索',
backToKeywordSearchButtonAriaLabel: '返回关键词搜索',
newConversationPlaceholder: '提问',
conversationHistoryTitle: '我的对话历史',
startNewConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史',
threadDepthErrorPlaceholder: '对话已达上限'
},
newConversation: {
newConversationTitle: '我今天能帮你什么?',
newConversationDescription:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
footer: {
selectText: '选择',
submitQuestionText: '提交问题',
selectKeyAriaLabel: '回车键',
navigateText: '导航',
navigateUpKeyAriaLabel: '向上箭头',
navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
backToSearchText: '返回搜索',
closeKeyAriaLabel: 'Esc 键',
poweredByText: '由…提供支持'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查网络连接。'
},
startScreen: {
recentSearchesTitle: '最近',
noRecentSearchesText: '暂无最近搜索',
saveRecentSearchButtonTitle: '保存此搜索',
removeRecentSearchButtonTitle: '从历史记录中移除此搜索',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除此搜索',
recentConversationsTitle: '最近对话',
removeRecentConversationButtonTitle: '从历史记录中移除此对话'
},
noResultsScreen: {
noResultsText: '未找到相关结果',
suggestedQueryText: '尝试搜索',
reportMissingResultsText: '认为此查询应该有结果?',
reportMissingResultsLinkText: '告诉我们。'
},
resultsScreen: {
askAiPlaceholder: '询问 AI:',
noResultsAskAiPlaceholder: '文档里没找到?让 Ask AI 帮忙:'
},
askAiScreen: {
disclaimerText: '回答由 AI 生成,可能会出错。请核实。',
relatedSourcesText: '相关来源',
thinkingText: '思考中...',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
copyButtonTitle: '复制',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
preToolCallText: '搜索中...',
duringToolCallText: '搜索中...',
afterToolCallText: '已搜索',
stoppedStreamingText: '你已停止此回复',
errorTitleText: '聊天错误',
threadDepthExceededMessage: '为保持回答准确,此对话已关闭。',
startNewConversationButtonText: '开始新的对话'
}
}
},
askAi: {
sidePanel: {
button: {
translations: {
buttonText: '询问 AI',
buttonAriaLabel: '询问 AI'
}
},
panel: {
translations: {
header: {
title: '询问 AI',
conversationHistoryTitle: '我的对话历史',
newConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史'
},
promptForm: {
promptPlaceholderText: '提问',
promptAnsweringText: '正在回答...',
promptAskAnotherQuestionText: '再问一个问题',
promptDisclaimerText: '回答由 AI 生成,可能会出错。',
promptLabelText: '按回车发送,Shift+回车换行。',
promptAriaLabelText: '问题输入'
},
conversationScreen: {
preToolCallText: '搜索中...',
searchingText: '搜索中...',
toolCallResultText: '已搜索',
conversationDisclaimer:
'回答由 AI 生成,可能会出错。请核实。',
reasoningText: '推理中...',
thinkingText: '思考中...',
relatedSourcesText: '相关来源',
stoppedStreamingText: '你已停止此回复',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
errorTitleText: '聊天错误'
},
newConversationScreen: {
titleText: '我今天能帮你什么?',
introductionText:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
logo: {
poweredByText: '由…提供支持'
}
}
}
}
}
}
}
}
}
}
})Consulta la documentación oficial de Algolia para conocer más detalles. Para empezar rápidamente, también puedes copiar las traducciones usadas por este sitio desde nuestro repositorio de GitHub.
Algolia Ask AI Support
Si deseas incluir Ask AI, pasa la opción askAi (o alguno de sus campos parciales) dentro de options:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
// askAi: "TU-ID-DE-ASISTENTE"
// O
askAi: {
// como mínimo debes proporcionar el assistantId que recibiste de Algolia
assistantId: 'XXXYYY',
// anulaciones opcionales — si se omiten, se reutilizan los valores appId/apiKey/indexName de nivel superior
// apiKey: '...',
// appId: '...',
// indexName: '...'
}
}
}
}
})Nota
Si prefieres solo la búsqueda por palabra clave y no la Ask AI, simplemente omite askAi.
Panel lateral de Ask AI
DocSearch v4.5+ admite un panel lateral de Ask AI opcional. Cuando está habilitado, se puede abrir con Ctrl/Cmd+I por defecto. La Referencia de API del Panel Lateral contiene la lista completa de opciones.
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
// Refleja la API de @docsearch/sidepanel-js SidepanelProps
panel: {
variant: 'floating', // o 'inline'
side: 'right',
width: '360px',
expandedWidth: '580px',
suggestedQuestions: true
}
}
}
}
}
}
})Si necesitas deshabilitar el atajo de teclado, usa la opción keyboardShortcuts del panel lateral:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
keyboardShortcuts: {
'Ctrl/Cmd+I': false
}
}
}
}
}
}
})Modo (auto / sidePanel / hybrid / modal)
Puedes controlar opcionalmente cómo VitePress integra la búsqueda por palabra clave y Ask AI:
mode: 'auto'(por defecto): infierehybridcuando la búsqueda por palabra clave está configurada, de lo contrariosidePanelcuando el panel lateral de Ask AI está configurado.mode: 'sidePanel': fuerza solo el panel lateral (oculta el botón de búsqueda por palabra clave).mode: 'hybrid': habilita el modal de búsqueda por palabra clave + panel lateral de Ask AI (requiere configuración de búsqueda por palabra clave).mode: 'modal': mantiene Ask AI dentro del modal de DocSearch (incluso si configuraste el panel lateral).
Solo Ask AI (sin búsqueda por palabra clave)
Si quieres usar solo el panel lateral de Ask AI, puedes omitir la configuración de búsqueda por palabra clave de nivel superior y proporcionar las credenciales bajo askAi:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
mode: 'sidePanel',
askAi: {
assistantId: 'XXXYYY',
appId: '...',
apiKey: '...',
indexName: '...',
sidePanel: true
}
}
}
}
})Configuración Crawler
A continuación se muestra un ejemplo de la configuración que utiliza este sitio:
new Crawler({
appId: '...',
apiKey: '...',
rateLimit: 8,
startUrls: ['https://vitepress.dev/'],
renderJavaScript: false,
sitemaps: [],
exclusionPatterns: [],
ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'],
schedule: 'at 05:10 on Saturday',
actions: [
{
indexName: 'vitepress',
pathsToMatch: ['https://vitepress.dev/**'],
recordExtractor: ({ $, helpers }) => {
return helpers.docsearch({
recordProps: {
lvl1: '.content h1',
content: '.content p, .content li',
lvl0: {
selectors: 'section.has-active div h2',
defaultValue: 'Documentation'
},
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'
}
}
})