Merge branch 'main' into code-block-title

pull/5007/head
bluwy 5 months ago
commit c59595835b

@ -1,3 +1,52 @@
## [2.0.0-alpha.17](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.16...v2.0.0-alpha.17) (2026-03-19)
### Bug Fixes
- **build:** `processIncludes` no longer swallows errors ([fb21fdf](https://github.com/vuejs/vitepress/commit/fb21fdf6759b7c88ac98456820b75286936fbf87))
- **build:** deterministic local search indexing and non-blocking initial scan (closes [#4081](https://github.com/vuejs/vitepress/issues/4081)) ([fc0f203](https://github.com/vuejs/vitepress/commit/fc0f203f0ac451ec039850b920f0684c1695d161))
- **client:** await `clipboard.writeText` so that fallback works in non-secure contexts ([#5119](https://github.com/vuejs/vitepress/issues/5119)) ([b544df8](https://github.com/vuejs/vitepress/commit/b544df802d256aef10d4da94631967b0fcab68d2))
- disable brotli compression in preview server ([ca1e875](https://github.com/vuejs/vitepress/commit/ca1e87512924acdd8d39ca0f530a424ad933b701))
- **theme:** add `rel="alternate"` and `hreflang` to links in language menu ([#5108](https://github.com/vuejs/vitepress/issues/5108)) ([f09593b](https://github.com/vuejs/vitepress/commit/f09593b073e42fa9d8de1e744a9f2a0e5c8170fc))
- **theme:** add margin to images in vp-doc (closes [#5136](https://github.com/vuejs/vitepress/issues/5136)) ([896e49a](https://github.com/vuejs/vitepress/commit/896e49a777bb983de2cbef82c1c295db2dba3dbe))
- **theme:** close sidebar on resize (closes [#5145](https://github.com/vuejs/vitepress/issues/5145)) ([17696c3](https://github.com/vuejs/vitepress/commit/17696c358b88335c4f6bb516bbcdf774aaf7deee))
- **theme:** disable text autospace in `<pre>` (closes [#5115](https://github.com/vuejs/vitepress/issues/5115)) ([21a5fb6](https://github.com/vuejs/vitepress/commit/21a5fb6a96549564fcf698d0e7256181eac3919b))
- **theme:** enable `line-break: strict` for `<li>` too ([f811d58](https://github.com/vuejs/vitepress/commit/f811d581a164fa330b17cdb85270effa39bdb3fd))
- **theme:** keep pnum,tnum features in Inter ([f1bef95](https://github.com/vuejs/vitepress/commit/f1bef95eee453bb18cc160741a11513678015cd6)), closes [#5096](https://github.com/vuejs/vitepress/issues/5096)
- **theme:** navbar menu group is incorrectly highlighted ([#5113](https://github.com/vuejs/vitepress/issues/5113)) ([b28667b](https://github.com/vuejs/vitepress/commit/b28667b6b03d50c4be0d509ec5e7d780f29f8042))
- **theme:** strip system-ui from font-family-base ([#4988](https://github.com/vuejs/vitepress/issues/4988)) ([8096eac](https://github.com/vuejs/vitepress/commit/8096eaca4f1d9eef00101e42f7159da1e12ca3de))
### Features
- **theme:** add `home-hero-actions-before-actions` slot ([#5151](https://github.com/vuejs/vitepress/issues/5151)) ([74a73d8](https://github.com/vuejs/vitepress/commit/74a73d869ca61f2c64f9dcbd9912a0461e8d4bfe))
- support text-fragments ([#5140](https://github.com/vuejs/vitepress/issues/5140)) ([44e2675](https://github.com/vuejs/vitepress/commit/44e2675889588b54dea771a0c82e2db64739364c))
- **theme:** add Japanese translation for "copied" label ([#5106](https://github.com/vuejs/vitepress/issues/5106)) ([a01bba0](https://github.com/vuejs/vitepress/commit/a01bba0cad70bb089918adab105f0a5b5ff85918))
- **theme:** enable text-autospace and text-spacing-trim (closes [#4996](https://github.com/vuejs/vitepress/issues/4996)) ([d7effff](https://github.com/vuejs/vitepress/commit/d7effffdbb9ea6bdeda31e26dea0f1ed32ddd51e))
- **theme:** support specifying list of details in home page features (closes [#5101](https://github.com/vuejs/vitepress/issues/5101)) ([3146ce4](https://github.com/vuejs/vitepress/commit/3146ce48ed3ad684ddfbf1194de3a2200082eb92))
### BREAKING CHANGES
Previously, the `<!-- @include: ./path/to/file -->` syntax silently ignored errors when files did not exist. This behavior was originally intended as an escape hatch while documenting includes, but better solutions now exist using Shiki transformers.
For most users, no code changes are required. If you now see errors, it means your includes are broken and were earlier not being reported.
Users who intentionally reference non-existent files or want to document includes without resolving them can configure `markdown.codeTransformers` with a `postprocess` hook. See `docs/.vitepress/config.ts` in this repo for an example.
## [2.0.0-alpha.16](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.15...v2.0.0-alpha.16) (2026-01-31)
### Bug Fixes
- always log error when failed to fetch page ([66cf64e](https://github.com/vuejs/vitepress/commit/66cf64e6d127dd8473e582d11e1133acda6c3bc8))
- **theme:** add fallback for `heroImageSlotExists` ([#5076](https://github.com/vuejs/vitepress/issues/5076)) ([f119b18](https://github.com/vuejs/vitepress/commit/f119b18e39b545f39e29358913fe9ed1fd69bc55))
- **theme:** align badges in h1 and h2 ([#5087](https://github.com/vuejs/vitepress/issues/5087)) (closes [#5063](https://github.com/vuejs/vitepress/issues/5063)) ([b200865](https://github.com/vuejs/vitepress/commit/b2008654ffaf0d8f8c425e88592e9ed2f8791506))
- **theme:** highlight active link in mobile nav menu ([#5086](https://github.com/vuejs/vitepress/issues/5086)) (closes [#5068](https://github.com/vuejs/vitepress/issues/5068), closes [#5074](https://github.com/vuejs/vitepress/issues/5074)) ([923aa90](https://github.com/vuejs/vitepress/commit/923aa902523739bfb9d77aed376ebc73c32eeb33))
- **theme:** overflow clip is buggy on safari ([8ed6ea0](https://github.com/vuejs/vitepress/commit/8ed6ea048cb49256e3302de2de0edfbe635afd32)), closes [#5050](https://github.com/vuejs/vitepress/issues/5050) [#5039](https://github.com/vuejs/vitepress/issues/5039) [#5027](https://github.com/vuejs/vitepress/issues/5027)
- **theme:** remove margin between code groups and blocks in markdown containers ([a28e171](https://github.com/vuejs/vitepress/commit/a28e171604605713a221d0eb2bbdce211930d94f)), closes [#5099](https://github.com/vuejs/vitepress/issues/5099)
### Features
- **theme:** upgrade DocSearch to 4.5 with sidepanel ([#5092](https://github.com/vuejs/vitepress/issues/5092)) ([0d646a6](https://github.com/vuejs/vitepress/commit/0d646a66cd44e97adef516a6a36e03365f179906))
- **theme:** use `@layer __vitepress_base` to wrap the styles in base.css ([#4905](https://github.com/vuejs/vitepress/issues/4905)) ([f8d8c0d](https://github.com/vuejs/vitepress/commit/f8d8c0d712fba4728c750e1f44c5ba9596979ba1))
## [2.0.0-alpha.15](https://github.com/vuejs/vitepress/compare/v2.0.0-alpha.14...v2.0.0-alpha.15) (2025-11-22)
### Bug Fixes

@ -26,3 +26,14 @@ Please make sure to read the [Contributing Guide](https://github.com/vuejs/vitep
[MIT](https://github.com/vuejs/vitepress/blob/main/LICENSE)
Copyright (c) 2019-present, Yuxi (Evan) You
## Special Thanks
This project would not be possible without the support of these amazing companies and tools.
| | | |
| ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <a href="https://voidzero.dev" target="_blank"><img alt="VoidZero's logo" src="https://github.com/voidzero-dev.png" width="80" /></a> | **[VoidZero](https://voidzero.dev)** | The company behind Vite, Vitest, Rolldown, and Oxc. VoidZero has been a long-time sponsor of VitePress. VitePress itself is built on top of this ecosystem of high-performance JavaScript tooling. |
| <a href="https://stackblitz.com" target="_blank"><img alt="StackBlitz's logo" src="https://github.com/stackblitz.png" width="80" /></a> | **[StackBlitz](https://stackblitz.com)** | Creators of WebContainers and a browser-based development platform. Their technology powers the VitePress playground and provides instant preview releases for our pull requests and commits. |
| <a href="https://algolia.com" target="_blank"><img alt="Algolia's logo" src="https://github.com/algolia.png" width="80" /></a> | **[Algolia](https://algolia.com)** | An AI-powered search platform that provides fast, scalable search. Algolia powers DocSearch for VitePress. Their team has been a long-time partner in building and maintaining our search integration. |
| <a href="https://browserstack.com" target="_blank"><img alt="BrowserStack's logo" src="https://github.com/browserstack.png" width="80" /></a> | **[BrowserStack](https://browserstack.com)** | A cloud-based testing platform for websites and mobile apps. BrowserStack provides the cross-browser and real-device infrastructure used to ensure VitePress works consistently across all browsers. |

@ -0,0 +1,14 @@
<script setup lang="ts">
import DefaultTheme from 'vitepress/theme'
import HomeHeroCopy from './HomeHeroCopy.vue'
const INSTALL_COMMAND = 'npx vitepress init'
</script>
<template>
<DefaultTheme.Layout>
<template #home-hero-actions-before-actions>
<HomeHeroCopy :command="INSTALL_COMMAND" />
</template>
</DefaultTheme.Layout>
</template>

@ -0,0 +1,210 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{
command: string
}>()
const copied = ref(false)
async function copy () {
try {
await navigator.clipboard.writeText(props.command)
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
} catch (error) {
console.error('Failed to copy', error)
}
}
</script>
<template>
<div
class="hero-copy-btn"
:class="{ copied }"
role="button"
tabindex="0"
@click="copy"
@keydown.enter="copy"
@keydown.space.prevent="copy"
>
<div class="content">
<span class="prompt">$</span>
<span class="command">{{ command }}</span>
</div>
<div class="icon-wrapper">
<transition mode="out-in" name="fade">
<svg
v-if="!copied"
class="lucide lucide-copy"
fill="none"
height="18"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="18"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="14"
rx="2"
ry="2"
width="14"
x="8"
y="8"
/>
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
</svg>
<svg
v-else
class="lucide lucide-check"
fill="none"
height="18"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="18"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M20 6 9 17l-5-5" />
</svg>
</transition>
</div>
<transition name="slide-up">
<div v-if="copied" class="tooltip">Copied!</div>
</transition>
</div>
</template>
<style scoped>
.hero-copy-btn {
margin-bottom: 32px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
background: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
padding: 0 16px;
height: 48px;
cursor: pointer;
transition: all 0.25s ease;
position: relative;
user-select: none;
max-width: calc(100vw - 2 * 24px);
width: 100%;
}
.hero-copy-btn:hover {
border-color: var(--vp-c-brand-1);
background: var(--vp-c-bg-mute);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-1px);
}
.hero-copy-btn:active {
transform: translateY(0);
}
.hero-copy-btn.copied {
border-color: var(--vp-c-green-1);
background: var(--vp-c-green-dimm-1);
}
.content {
display: flex;
align-items: center;
gap: 10px;
font-family: var(--vp-font-family-mono);
font-size: 14px;
color: var(--vp-c-text-2);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.prompt {
color: var(--vp-c-text-3);
user-select: none;
font-weight: 600;
}
.command {
color: var(--vp-c-text-1);
font-weight: 500;
}
.icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
color: var(--vp-c-text-3);
transition: color 0.2s;
flex-shrink: 0;
}
.hero-copy-btn:hover .icon-wrapper {
color: var(--vp-c-text-1);
}
.hero-copy-btn.copied .icon-wrapper {
color: var(--vp-c-green-1);
}
.tooltip {
position: absolute;
top: -36px;
right: 0;
background: var(--vp-c-text-1);
color: var(--vp-c-bg);
padding: 6px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
pointer-events: none;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 10;
}
/* Tooltip arrow */
.tooltip::after {
content: '';
position: absolute;
bottom: -4px;
right: 12px;
width: 8px;
height: 8px;
background: var(--vp-c-text-1);
transform: rotate(45deg);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: scale(0.8);
}
.slide-up-enter-active,
.slide-up-leave-active {
transition: all 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.slide-up-enter-from,
.slide-up-leave-to {
opacity: 0;
transform: translateY(10px);
}
</style>

@ -1,10 +1,12 @@
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import CustomLayout from './components/CustomLayout.vue'
import ApiPreference from './components/ApiPreference.vue'
import NavVersion from './components/NavVersion.vue'
export default {
extends: DefaultTheme,
Layout: CustomLayout,
enhanceApp({ app }) {
app.component('ApiPreference', ApiPreference)
app.component('NavVersion', NavVersion)

@ -6,6 +6,10 @@ title: VitePress
hero:
name: VitePress
text: Vite & Vue Powered Static Site Generator
image:
src: /vitepress-logo.svg
alt: VitePress
actions:
- theme: brand
text: Examples

@ -4,7 +4,7 @@ describe('local search', () => {
})
test('exclude content from search results', async () => {
await page.locator('#local-search button').click()
await page.locator('.VPNavBarSearchButton').click()
const input = await page.waitForSelector('input#localsearch-input')
await input.type('local')

@ -0,0 +1 @@
../../../art/vitepress-logo.svg

@ -5,8 +5,9 @@
"baseUrl": ".",
"types": ["node", "vitest/globals"],
"paths": {
"client/*": ["../src/client/*"],
"node/*": ["../src/node/*"],
"client/*": ["../src/client/*"]
"shared/*": ["../src/shared/*"]
}
}
}

@ -0,0 +1,196 @@
import {
buildAskAiConfig,
hasAskAi,
hasKeywordSearch,
mergeLangFacetFilters,
validateCredentials
} from 'client/theme-default/support/docsearch'
describe('client/theme-default/support/docsearch', () => {
describe('mergeLangFacetFilters', () => {
test('adds a lang facet filter when none is provided', () => {
expect(mergeLangFacetFilters(undefined, 'en')).toEqual(['lang:en'])
})
test('replaces existing lang facet filters', () => {
expect(mergeLangFacetFilters('lang:fr', 'en')).toEqual(['lang:en'])
expect(mergeLangFacetFilters(['foo', 'lang:fr'], 'en')).toEqual([
'foo',
'lang:en'
])
})
test('handles nested facet filters (OR conditions)', () => {
expect(
mergeLangFacetFilters([['tag:foo', 'tag:bar'], 'lang:fr'], 'en')
).toEqual([['tag:foo', 'tag:bar'], 'lang:en'])
})
test('removes empty nested arrays', () => {
expect(mergeLangFacetFilters([['lang:fr'], 'other'], 'en')).toEqual([
'other',
'lang:en'
])
})
test('handles multiple lang filters in nested arrays', () => {
expect(
mergeLangFacetFilters([['lang:fr', 'tag:foo'], 'bar'], 'en')
).toEqual([['tag:foo'], 'bar', 'lang:en'])
})
})
describe('hasKeywordSearch', () => {
test('returns true when all credentials are provided', () => {
expect(
hasKeywordSearch({
appId: 'app',
apiKey: 'key',
indexName: 'index'
})
).toBe(true)
})
test('returns false when any credential is missing', () => {
expect(
hasKeywordSearch({
appId: undefined,
apiKey: 'key',
indexName: 'index'
})
).toBe(false)
expect(
hasKeywordSearch({
appId: 'app',
apiKey: undefined,
indexName: 'index'
})
).toBe(false)
expect(
hasKeywordSearch({
appId: 'app',
apiKey: 'key',
indexName: undefined
})
).toBe(false)
})
})
describe('hasAskAi', () => {
test('returns true for valid string assistantId', () => {
expect(hasAskAi('assistant123')).toBe(true)
})
test('returns false for empty string assistantId', () => {
expect(hasAskAi('')).toBe(false)
})
test('returns true for object with assistantId', () => {
expect(hasAskAi({ assistantId: 'assistant123' } as any)).toBe(true)
})
test('returns false for object without assistantId', () => {
expect(hasAskAi({ assistantId: null } as any)).toBe(false)
expect(hasAskAi({} as any)).toBe(false)
})
test('returns false for undefined', () => {
expect(hasAskAi(undefined)).toBe(false)
})
})
describe('validateCredentials', () => {
test('validates complete credentials', () => {
const result = validateCredentials({
appId: 'app',
apiKey: 'key',
indexName: 'index'
})
expect(result.valid).toBe(true)
expect(result.appId).toBe('app')
expect(result.apiKey).toBe('key')
expect(result.indexName).toBe('index')
})
test('invalidates incomplete credentials', () => {
expect(
validateCredentials({
appId: undefined,
apiKey: 'key',
indexName: 'index'
}).valid
).toBe(false)
})
})
describe('buildAskAiConfig', () => {
test('builds config from string assistantId', () => {
const result = buildAskAiConfig(
'assistant123',
{
appId: 'app',
apiKey: 'key',
indexName: 'index'
} as any,
'en'
)
expect(result.assistantId).toBe('assistant123')
expect(result.appId).toBe('app')
expect(result.apiKey).toBe('key')
expect(result.indexName).toBe('index')
})
test('builds config from object with overrides', () => {
const result = buildAskAiConfig(
{
assistantId: 'assistant123',
appId: 'custom-app',
apiKey: 'custom-key',
indexName: 'custom-index'
} as any,
{
appId: 'default-app',
apiKey: 'default-key',
indexName: 'default-index'
} as any,
'en'
)
expect(result.assistantId).toBe('assistant123')
expect(result.appId).toBe('custom-app')
expect(result.apiKey).toBe('custom-key')
expect(result.indexName).toBe('custom-index')
})
test('merges facet filters with lang', () => {
const result = buildAskAiConfig(
{
assistantId: 'assistant123',
searchParameters: {
facetFilters: ['tag:docs']
}
} as any,
{
appId: 'app',
apiKey: 'key',
indexName: 'index'
} as any,
'en'
)
expect(result.searchParameters?.facetFilters).toContain('tag:docs')
expect(result.searchParameters?.facetFilters).toContain('lang:en')
})
test('always adds lang facet filter to searchParameters', () => {
const result = buildAskAiConfig(
'assistant123',
{
appId: 'app',
apiKey: 'key',
indexName: 'index'
} as any,
'en'
)
expect(result.searchParameters?.facetFilters).toEqual(['lang:en'])
})
})
})

@ -1,4 +1,7 @@
import { ensureStartingSlash } from 'client/theme-default/support/utils'
import {
ensureStartingSlash,
isLinkExternal
} from 'client/theme-default/support/utils'
describe('client/theme-default/utils', () => {
describe('ensureStartingSlash', () => {
@ -9,4 +12,22 @@ describe('client/theme-default/utils', () => {
expect(ensureStartingSlash('/path/nested')).toBe('/path/nested')
})
})
describe('isLinkExternal', () => {
test('it detects external links by default', () => {
expect(isLinkExternal('https://vite.dev')).toBe(true)
expect(isLinkExternal('/guide/')).toBe(false)
})
test('it treats _blank targets as external by default', () => {
expect(isLinkExternal('/guide/', '_blank')).toBe(true)
})
test('it allows callers to override external detection', () => {
expect(isLinkExternal('https://cn.vite.dev', undefined, false)).toBe(
false
)
expect(isLinkExternal('/guide/', undefined, true)).toBe(true)
})
})
})

@ -0,0 +1,26 @@
import { highlight } from 'node/markdown/plugins/highlight'
describe('node/markdown/plugins/highlight', () => {
test('passes color replacements through markdown options', async () => {
const [render, dispose] = await highlight(
{ light: 'github-light', dark: 'github-dark' },
{
colorReplacements: {
'github-light': {
'#005cc5': '#000000'
}
}
}
)
try {
const html = await render('const a = 1', 'js', '')
expect(html).toContain('--shiki-light:#000000')
expect(html).toContain('--shiki-dark:#79B8FF')
expect(html).not.toContain('--shiki-light:#005CC5')
} finally {
dispose()
}
})
})

@ -0,0 +1,51 @@
import { slugify } from '@mdit-vue/shared'
import { MarkdownItAsync } from 'markdown-it-async'
import { linkPlugin } from 'node/markdown/plugins/link'
describe('node/markdown/plugins/link', () => {
const md = new MarkdownItAsync()
linkPlugin(md, {}, '/', slugify)
test('preserves text-fragment hashes on markdown links', async () => {
const html = await md.renderAsync(
'[58-61](/resources/server/user#:~:text=58*,time%20authentication%20token)',
{ cleanUrls: false }
)
expect(html).toContain(
'href="/resources/server/user.html#:~:text=58*,time%20authentication%20token"'
)
})
// https://web.dev/articles/text-fragments#mixing_element_and_text_fragments
test('preserves mixed element and text-fragment hashes', async () => {
const html = await md.renderAsync(
'[Section](/guide/getting-started#Hello%20World:~:text=Hello%20World)',
{ cleanUrls: false }
)
expect(html).toContain(
'href="/guide/getting-started.html#hello-world:~:text=Hello%20World"'
)
})
test('continues to normalize regular heading hashes', async () => {
const html = await md.renderAsync(
'[Section](/guide/getting-started#Hello%20World)',
{ cleanUrls: false }
)
expect(html).toContain('href="/guide/getting-started.html#hello-world"')
})
test('does not break encoding for text-fragments', async () => {
const html = await md.renderAsync(
'[Section](/foo?title=Cat&oldid=916388819#:~:text=Claws-,Like%20almost,the%20Felidae%2C,-cats)',
{ cleanUrls: false }
)
expect(html).toContain(
'href="/foo.html?title=Cat&amp;oldid=916388819#:~:text=Claws-,Like%20almost,the%20Felidae%2C,-cats"'
)
})
})

@ -3,7 +3,6 @@ import {
findRegion,
rawPathToToken
} from 'node/markdown/plugins/snippet'
import { expect } from 'vitest'
const removeEmptyKeys = <T extends Record<string, unknown>>(obj: T) => {
return Object.fromEntries(

@ -12,6 +12,7 @@ export default defineConfig({
{ find: '@siteData', replacement: resolve(dir, './shims.ts') },
{ find: 'client', replacement: resolve(dir, '../../src/client') },
{ find: 'node', replacement: resolve(dir, '../../src/node') },
{ find: 'shared', replacement: resolve(dir, '../../src/shared') },
{
find: /^vitepress$/,
replacement: resolve(dir, '../../src/client/index.js')

@ -11,6 +11,20 @@ import {
import llmstxt from 'vitepress-plugin-llms'
const prod = !!process.env.NETLIFY
const siteUrl = 'https://vitepress.dev'
const ogImage = new URL('/vitepress-og.jpg', siteUrl).href
const localeToOgLocaleMap: Record<string, string> = {
root: 'en_US',
zh: 'zh_CN',
pt: 'pt_BR',
ru: 'ru_RU',
es: 'es_ES',
ko: 'ko_KR',
fa: 'fa_IR',
ja: 'ja_JP'
}
export default defineConfig({
title: 'VitePress',
@ -26,10 +40,13 @@ export default defineConfig({
markdown: {
math: true,
codeTransformers: [
// We use `[!!code` in demo to prevent transformation, here we revert it back.
// We use `[!!code` and `@@include` in demo to prevent transformation,
// here we revert it back.
{
postprocess(code) {
return code.replace(/\[\!\!code/g, '[!code')
return code
.replaceAll('[!!code', '[!code')
.replaceAll('@@include', '@include')
}
}
],
@ -68,41 +85,18 @@ export default defineConfig({
},
sitemap: {
hostname: 'https://vitepress.dev',
hostname: siteUrl,
transformItems(items) {
return items.filter((item) => !item.url.includes('migration'))
}
},
// prettier-ignore
head: [
[
'link',
{ rel: 'icon', type: 'image/svg+xml', href: '/vitepress-logo-mini.svg' }
],
[
'link',
{ rel: 'icon', type: 'image/png', href: '/vitepress-logo-mini.png' }
],
['link', { rel: 'icon', type: 'image/svg+xml', href: '/vitepress-logo-mini.svg' }],
['link', { rel: 'icon', type: 'image/png', href: '/vitepress-logo-mini.png' }],
['meta', { name: 'theme-color', content: '#5f67ee' }],
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:site_name', content: 'VitePress' }],
[
'meta',
{
property: 'og:image',
content: 'https://vitepress.dev/vitepress-og.jpg'
}
],
['meta', { property: 'og:url', content: 'https://vitepress.dev/' }],
[
'script',
{
src: 'https://cdn.usefathom.com/script.js',
'data-site': 'AZBRSFGG',
'data-spa': 'auto',
defer: ''
}
]
['script', { src: 'https://cdn.usefathom.com/script.js', 'data-site': 'AZBRSFGG', 'data-spa': 'auto', defer: '' }]
],
themeConfig: {
@ -118,7 +112,10 @@ export default defineConfig({
appId: '8J64VVRP8K',
apiKey: '52f578a92b88ad6abde815aae2b0ad7c',
indexName: 'vitepress',
askAi: 'YaVSonfX5bS8'
askAi: {
assistantId: 'YaVSonfX5bS8',
sidePanel: true
}
}
},
@ -147,28 +144,35 @@ export default defineConfig({
firebase: 'logos:firebase'
}
}),
prod &&
llmstxt({
workDir: 'en',
ignoreFiles: ['index.md']
})
prod && llmstxt({ workDir: 'en', ignoreFiles: ['index.md'] })
],
experimental: {
enableNativePlugin: true
}
},
transformPageData: prod
? (pageData, ctx) => {
const site = resolveSiteDataByRoute(
ctx.siteConfig.site,
pageData.relativePath
)
const title = `${pageData.title || site.title} | ${pageData.description || site.description}`
// prettier-ignore
transformPageData: prod ? (pageData, ctx) => {
const url = new URL(pageData.relativePath.replace(/(?:(^|\/)index)?\.md$/, '$1'), siteUrl).href
const site = resolveSiteDataByRoute(ctx.siteConfig.site, pageData.relativePath)
const title = pageData.title ? `${pageData.title} | VitePress` : site.title
const description = pageData.description || site.description
const locale = localeToOgLocaleMap[site.localeIndex || 'root']
;((pageData.frontmatter.head ??= []) as HeadConfig[]).push(
['meta', { property: 'og:locale', content: site.lang }],
['meta', { property: 'og:title', content: title }]
['meta', { property: 'og:url', content: url }],
['meta', { property: 'og:title', content: title }],
['meta', { property: 'og:description', content: description }],
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:locale', content: locale }],
['meta', { property: 'og:site_name', content: 'VitePress' }],
['meta', { property: 'og:image', content: ogImage }],
['meta', { property: 'og:image:secure_url', content: ogImage }],
['meta', { property: 'og:image:type', content: 'image/jpeg' }],
['meta', { property: 'og:image:width', content: '1280' }],
['meta', { property: 'og:image:height', content: '640' }],
['meta', { property: 'og:image:alt', content: 'VitePress' }],
['link', { rel: 'canonical', href: url }]
)
}
: undefined
} : undefined
})

@ -1,3 +1,7 @@
---
description: Learn how to reference and handle static assets such as images, media, and fonts in VitePress.
---
# Asset Handling
## Referencing Static Assets

@ -1,5 +1,6 @@
---
outline: deep
description: Connect VitePress to a headless CMS using dynamic routes and data loaders.
---
# Connecting to a CMS

@ -1,3 +1,7 @@
---
description: Create and use a custom theme in VitePress to fully control the look and feel of your site.
---
# Using a Custom Theme
## Theme Resolving

@ -1,3 +1,7 @@
---
description: Load arbitrary data at build time using VitePress data loaders and import it from pages or components.
---
# Build-Time Data Loading
VitePress provides a feature called **data loaders** that allows you to load arbitrary data and import it from pages or components. The data loading is executed **only at build time**: the resulting data will be serialized as JSON in the final JavaScript bundle.

@ -1,5 +1,6 @@
---
outline: deep
description: Deploy your VitePress site to popular platforms like Netlify, Vercel, GitHub Pages, and more.
---
# Deploy Your VitePress Site
@ -105,7 +106,7 @@ Note: the `vercel.json` file should be placed at the root of your **repository**
## Platform Guides
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
Set up a new project and change these settings using your dashboard:
@ -205,7 +206,7 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
2. Create a file named `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content:
```yaml [.gitlab-ci.yml]
image: node:18
image: node:24
pages:
cache:
paths:
@ -221,7 +222,9 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
- main
```
### Azure Static Web Apps
<!-- keep headings sorted alphabetically, leave nginx at the end -->
### Azure
1. Follow the [official documentation](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration).
@ -231,6 +234,10 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
### CloudRay
You can deploy your VitePress project with [CloudRay](https://cloudray.io/) by following these [instructions](https://cloudray.io/articles/how-to-deploy-vitepress-site).
### Firebase
1. Create `firebase.json` and `.firebaserc` at the root of your project:
@ -262,14 +269,6 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
firebase deploy
```
### Surge
1. After running `npm run docs:build`, run this command to deploy:
```sh
npx surge docs/.vitepress/dist
```
### Heroku
1. Follow documentation and guide given in [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static).
@ -282,11 +281,11 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
}
```
### Edgio
### Hostinger
Refer [Creating and Deploying a VitePress App To Edgio](https://docs.edg.io/guides/vitepress).
You can deploy your VitePress project with [Hostinger](https://www.hostinger.com/web-apps-hosting) by following these [instructions](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/). While configuring build settings, choose VitePress as the framework and adjust the root directory to `./docs`.
### Kinsta Static Site Hosting
### Kinsta
You can deploy your VitePress website on [Kinsta](https://kinsta.com/static-site-hosting/) by following these [instructions](https://kinsta.com/docs/vitepress-static-site-example/).
@ -294,9 +293,13 @@ You can deploy your VitePress website on [Kinsta](https://kinsta.com/static-site
You can deploy your VitePress project to [Stormkit](https://www.stormkit.io) by following these [instructions](https://stormkit.io/blog/how-to-deploy-vitepress).
### CloudRay
### Surge
You can deploy your VitePress project with [CloudRay](https://cloudray.io/) by following these [instructions](https://cloudray.io/articles/how-to-deploy-vitepress-site).
1. After running `npm run docs:build`, run this command to deploy:
```sh
npx surge docs/.vitepress/dist
```
### Nginx

@ -1,5 +1,6 @@
---
outline: deep
description: Customize and extend the VitePress default theme with custom CSS, components, layouts, and slots.
---
# Extending the Default Theme
@ -190,6 +191,7 @@ Full list of slots available in the default theme layout:
- `home-hero-info-before`
- `home-hero-info`
- `home-hero-info-after`
- `home-hero-actions-before-actions`
- `home-hero-actions-after`
- `home-hero-image`
- `home-hero-after`

@ -1,3 +1,7 @@
---
description: Learn how to use YAML frontmatter in VitePress Markdown files to control page-level metadata and behavior.
---
# Frontmatter
## Usage

@ -1,3 +1,7 @@
---
description: Get up and running with VitePress. Learn how to install, scaffold, and start developing your documentation site.
---
# Getting Started
## Try It Online
@ -8,7 +12,7 @@ You can try VitePress directly in your browser on [StackBlitz](https://vitepress
### Prerequisites
- [Node.js](https://nodejs.org/) version 18 or higher.
- [Node.js](https://nodejs.org/) version 20 or higher.
- Terminal for accessing VitePress via its command line interface (CLI).
- Text Editor with [Markdown](https://en.wikipedia.org/wiki/Markdown) syntax support.
- [VSCode](https://code.visualstudio.com/) is recommended, along with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar).

@ -1,3 +1,7 @@
---
description: Set up internationalization (i18n) in VitePress to support multiple languages for your site.
---
# Internationalization
To use the built-in i18n features, one needs to create a directory structure as follows:

@ -1,3 +1,7 @@
---
description: VitePress built-in Markdown extensions including custom containers, code blocks with syntax highlighting, line highlighting, code groups, and more.
---
# Markdown Extensions
VitePress comes with built in Markdown Extensions.
@ -811,7 +815,7 @@ For example, you can include a relative markdown file using this:
## Basics
<!--@include: ./parts/basics.md-->
<!--@@include: ./parts/basics.md-->
```
**Part file** (`parts/basics.md`)
@ -847,7 +851,7 @@ It also supports selecting a line range:
## Basics
<!--@include: ./parts/basics.md{3,}-->
<!--@@include: ./parts/basics.md{3,}-->
```
**Part file** (`parts/basics.md`)
@ -883,8 +887,8 @@ You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/co
## Basics
<!--@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}-->
<!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@@include: ./parts/basics.md#basic-usage{5,}-->
```
**Part file** (`parts/basics.md`)
@ -935,7 +939,7 @@ You can include the `My Base Section` section like this:
```md
## My Extended Section
<!--@include: ./parts/basics.md#my-base-section-->
<!--@@include: ./parts/basics.md#my-base-section-->
```
**Equivalent code**
@ -959,7 +963,7 @@ Here, `my-base-section` is the generated id of the heading element. In case it's
and include it like this:
```md
<!--@include: ./parts/basics.md#custom-id-->
<!--@@include: ./parts/basics.md#custom-id-->
```
## Math Equations

@ -1,3 +1,7 @@
---
description: Enable MPA (Multi-Page Application) mode in VitePress for zero-JavaScript pages with better initial performance.
---
# MPA Mode <Badge type="warning" text="experimental" />
MPA (Multi-Page Application) mode can be enabled via the command line via `vitepress build --mpa`, or via config through the `mpa: true` option.

@ -1,5 +1,6 @@
---
outline: deep
description: Understand VitePress file-based routing, dynamic routes, clean URLs, and path rewrites.
---
# Routing
@ -121,7 +122,7 @@ Alternatively, you can directly use the anchor tag syntax:
:::
## Generating Clean URL
## Generating Clean URLs
::: warning Server Support Required
To serve clean URLs with VitePress, server-side support is required.
@ -260,6 +261,30 @@ The generated HTML pages will be:
└─ bar.html
```
### Type-safe loader with `defineRoutes`
If you are using TypeScript, you can wrap the loader with `defineRoutes` from `vitepress` to get type hints for route hooks such as `paths`, `watch`, and `transformPageData`:
```ts
// packages/[pkg].paths.ts
import { defineRoutes } from 'vitepress'
export default defineRoutes({
watch: ['../data/**/*.json'],
async paths() {
return [
{ params: { pkg: 'foo' } },
{ params: { pkg: 'bar' } }
]
},
async transformPageData(pageData) {
pageData.title = `${pageData.title} · Packages`
}
})
```
`defineRoutes` is optional, but recommended when authoring `.paths.ts` files.
### Multiple Params
A dynamic route can contain multiple params:

@ -1,3 +1,7 @@
---
description: Generate a sitemap.xml file for your VitePress site to improve search engine discoverability.
---
# Sitemap Generation
VitePress comes with out-of-the-box support for generating a `sitemap.xml` file for your site. To enable it, add the following to your `.vitepress/config.js`:

@ -1,5 +1,6 @@
---
outline: deep
description: Ensure your VitePress theme components and custom code are compatible with server-side rendering.
---
# SSR Compatibility

@ -1,3 +1,7 @@
---
description: Use Vue components and dynamic templating features directly inside Markdown files in VitePress.
---
# Using Vue in Markdown
In VitePress, each Markdown file is compiled into HTML and then processed as a [Vue Single-File Component](https://vuejs.org/guide/scaling-up/sfc.html). This means you can use any Vue features inside the Markdown, including dynamic templating, using Vue components, or arbitrary in-page Vue component logic by adding a `<script>` tag.

@ -1,3 +1,7 @@
---
description: VitePress is a static site generator designed for building fast, content-centric websites powered by Vite and Vue.
---
# What is VitePress?
VitePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) designed for building fast, content-centric websites. In a nutshell, VitePress takes your source content written in [Markdown](https://en.wikipedia.org/wiki/Markdown), applies a theme to it, and generates static HTML pages that can be easily deployed anywhere.

@ -1,10 +1,11 @@
---
description: VitePress is a Vite & Vue powered static site generator that lets you create beautiful documentation sites from Markdown.
layout: home
hero:
name: VitePress
text: Vite & Vue Powered Static Site Generator
tagline: Markdown to Beautiful Docs in Minutes
tagline: Markdown to beautiful docs in minutes
actions:
- theme: brand
text: What is VitePress?
@ -21,7 +22,7 @@ hero:
features:
- icon: 📝
title: Focus on Your Content
title: Focus on your content
details: Effortlessly create beautiful documentation sites with just markdown.
- icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 256.32"><defs><linearGradient id="a" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"/><stop offset="100%" stop-color="#BD34FE"/></linearGradient><linearGradient id="b" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"/><stop offset="8.333%" stop-color="#FFDD35"/><stop offset="100%" stop-color="#FFA800"/></linearGradient></defs><path fill="url(#a)" d="M255.153 37.938 134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"/><path fill="url(#b)" d="M185.432.063 96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028 72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"/></svg>
title: Enjoy the Vite DX
@ -30,6 +31,6 @@ features:
title: Customize with Vue
details: Use Vue syntax and components directly in markdown, or build custom themes with Vue.
- icon: 🚀
title: Ship Fast Sites
title: Ship fast sites
details: Fast initial load with static HTML, fast post-load navigation with client-side routing.
---

@ -1,3 +1,7 @@
---
description: Reference of VitePress CLI commands including dev, build, preview, and init.
---
# Command Line Interface
## `vitepress dev`

@ -1,3 +1,7 @@
---
description: Use the Badge component to add status labels to headers in VitePress documentation.
---
# Badge
The badge lets you add status to your headers. For example, it could be useful to specify the section's type, or supported version.

@ -1,3 +1,7 @@
---
description: Integrate Carbon Ads into your VitePress site using the default theme's built-in support.
---
# Carbon Ads
VitePress has built in native support for [Carbon Ads](https://www.carbonads.net/). By defining the Carbon Ads credentials in config, VitePress will display ads on the page.

@ -1,3 +1,7 @@
---
description: Reference of all configuration options available for the VitePress default theme.
---
# Default Theme Config
Theme config lets you customize your theme. You can define theme config via the `themeConfig` option in the config file:

@ -1,3 +1,7 @@
---
description: Display an edit link on doc pages to let users suggest changes on GitHub or GitLab.
---
# Edit Link
## Site-Level Config

@ -1,3 +1,7 @@
---
description: Configure the global footer displayed at the bottom of VitePress pages.
---
# Footer
VitePress will display global footer at the bottom of the page when `themeConfig.footer` is present.

@ -1,3 +1,7 @@
---
description: Configure the VitePress default theme home page layout with hero sections, features, and custom content.
---
# Home Page
VitePress default theme provides a homepage layout, which you can also see used on [the homepage of this site](../). You may use it on any of your pages by specifying `layout: home` in the [frontmatter](./frontmatter-config).

@ -1,3 +1,7 @@
---
description: Show the last updated timestamp on VitePress pages based on Git commit history.
---
# Last Updated
The update time of the last content will be displayed in the lower right corner of the page. To enable it, add `lastUpdated` options to your config.

@ -1,3 +1,7 @@
---
description: Choose between doc, page, and home layouts in the VitePress default theme.
---
# Layout
You may choose the page layout by setting `layout` option to the page [frontmatter](./frontmatter-config). There are 3 layout options, `doc`, `page`, and `home`. If nothing is specified, then the page is treated as `doc` page.

@ -1,3 +1,7 @@
---
description: Configure the navigation bar in the VitePress default theme including site title, logo, and menu links.
---
# Nav
The Nav is the navigation bar displayed on top of the page. It contains the site title, global menu links, etc.

@ -1,3 +1,7 @@
---
description: Customize the previous and next page links displayed at the bottom of doc pages in VitePress.
---
# Prev Next Links
You can customize the text and link for the previous and next pages (shown at doc footer). This is helpful if you want a different text there than what you have on your sidebar. Additionally, you may find it useful to disable the footer or link to a page that is not included in your sidebar.

@ -1,5 +1,6 @@
---
outline: deep
description: Set up local or Algolia-powered search for your VitePress site.
---
# Search
@ -179,7 +180,7 @@ export default defineConfig({
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 (await md.renderAsync(`# ${env.frontmatter.title}`)) + html
return html
}
}
@ -190,7 +191,7 @@ export default defineConfig({
## Algolia Search
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:
VitePress supports searching your docs site using [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Refer to their getting started guide. In your `.vitepress/config.ts` you'll need to provide at least the following to make it work:
```ts
import { defineConfig } from 'vitepress'
@ -213,6 +214,19 @@ export default defineConfig({
You can use a config like this to use multilingual search:
<details>
<summary>View full example</summary>
<<< @/snippets/algolia-i18n.ts
</details>
Refer [official Algolia docs](https://docsearch.algolia.com/docs/api#translations) to learn more about them. To quickly get started, you can also copy the translations used by this site from [our GitHub repo](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code).
### Algolia Ask AI Support {#ask-ai}
If you would like to include **Ask AI**, pass the `askAi` option (or any of the partial fields) inside `options`:
```ts
import { defineConfig } from 'vitepress'
@ -224,79 +238,52 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
},
modal: {
searchBox: {
clearButtonTitle: '清除查询条件',
clearButtonAriaLabel: '清除查询条件',
closeButtonText: '关闭',
closeButtonAriaLabel: '关闭',
placeholderText: '搜索文档',
placeholderTextAskAi: '向 AI 提问:',
placeholderTextAskAiStreaming: '回答中...',
searchInputLabel: '搜索',
backToKeywordSearchButtonText: '返回关键字搜索',
backToKeywordSearchButtonAriaLabel: '返回关键字搜索'
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '没有搜索历史',
saveRecentSearchButtonTitle: '保存至搜索历史',
removeRecentSearchButtonTitle: '从搜索历史中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除',
recentConversationsTitle: '最近的对话',
removeRecentConversationButtonTitle: '从历史记录中删除对话'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查你的网络连接'
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为该查询应该有结果?',
reportMissingResultsLinkText: '点击反馈'
},
resultsScreen: {
askAiPlaceholder: '向 AI 提问: '
},
askAiScreen: {
disclaimerText: '答案由 AI 生成,可能不准确,请自行验证。',
relatedSourcesText: '相关来源',
thinkingText: '思考中...',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
copyButtonTitle: '复制',
likeButtonTitle: '赞',
dislikeButtonTitle: '踩',
thanksForFeedbackText: '感谢你的反馈!',
preToolCallText: '搜索中...',
duringToolCallText: '搜索 ',
afterToolCallText: '已搜索'
},
footer: {
selectText: '选择',
submitQuestionText: '提交问题',
selectKeyAriaLabel: 'Enter 键',
navigateText: '切换',
navigateUpKeyAriaLabel: '向上箭头',
navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
backToSearchText: '返回搜索',
closeKeyAriaLabel: 'Esc 键',
poweredByText: '搜索提供者'
// askAi: "YOUR-ASSISTANT-ID"
// OR
askAi: {
// at minimum you must provide the assistantId you received from Algolia
assistantId: 'XXXYYY',
// optional overrides if omitted, the top-level appId/apiKey/indexName values are reused
// apiKey: '...',
// appId: '...',
// indexName: '...'
}
}
}
}
})
```
::: warning Note
If you want to default to keyword search and do not want to use Ask AI, omit the `askAi` property.
:::
### Ask AI Side Panel {#ask-ai-side-panel}
DocSearch v4.5+ supports an optional **Ask AI side panel**. When enabled, it can be opened with **Ctrl/Cmd+I** by default. The [Sidepanel API Reference](https://docsearch.algolia.com/docs/sidepanel/api-reference) contains the full list of options.
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
panel: {
variant: 'floating', // or 'inline'
side: 'right',
width: '360px',
expandedWidth: '580px',
suggestedQuestions: true
}
}
}
}
}
@ -304,11 +291,7 @@ export default defineConfig({
})
```
[These options](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) can be overridden. Refer official Algolia docs to learn more about them.
### Algolia Ask AI Support {#ask-ai}
If you would like to include **Ask AI**, pass the `askAi` option (or any of the partial fields) inside `options`:
If you need to disable the keyboard shortcut, use the `keyboardShortcuts` option at the sidepanel root level:
```ts
import { defineConfig } from 'vitepress'
@ -321,15 +304,13 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
// askAi: "YOUR-ASSISTANT-ID"
// OR
askAi: {
// at minimum you must provide the assistantId you received from Algolia
assistantId: 'XXXYYY',
// optional overrides if omitted, the top-level appId/apiKey/indexName values are reused
// apiKey: '...',
// appId: '...',
// indexName: '...'
sidePanel: {
keyboardShortcuts: {
'Ctrl/Cmd+I': false
}
}
}
}
}
@ -337,116 +318,43 @@ export default defineConfig({
})
```
::: warning Note
If want to default to keyword search and do not want to use Ask AI, just omit the `askAi` property
:::
#### Mode (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
The translations for the Ask AI UI live under `options.translations.modal.askAiScreen` and `options.translations.resultsScreen` — see the [type definitions](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) for all keys.
You can optionally control how VitePress integrates keyword search and Ask AI:
### Crawler Config
- `mode: 'auto'` (default): infer `hybrid` when keyword search is configured, otherwise `sidePanel` when Ask AI side panel is configured.
- `mode: 'sidePanel'`: force side panel only (hides the keyword search button).
- `mode: 'hybrid'`: enable keyword search modal + Ask AI side panel (requires keyword search configuration).
- `mode: 'modal'`: keep Ask AI inside the DocSearch modal (even if you configured the side panel).
Here is an example config based on what this site uses:
#### Ask AI only (no keyword search) {#ask-ai-only}
If you want to use **Ask AI side panel only**, you can omit top-level keyword search config and provide credentials under `askAi`:
```ts
new Crawler({
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
mode: 'sidePanel',
askAi: {
assistantId: 'XXXYYY',
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'
indexName: '...',
sidePanel: true
}
}
}
}
})
```
### Crawler Config
Here is an example config based on what this site uses:
<<< @/snippets/algolia-crawler.js

@ -1,3 +1,7 @@
---
description: Configure the sidebar navigation in the VitePress default theme with groups, collapsible sections, and multiple sidebars.
---
# Sidebar
The sidebar is the main navigation block for your documentation. You can configure the sidebar menu in [`themeConfig.sidebar`](./default-theme-config#sidebar).

@ -1,3 +1,7 @@
---
description: Create team pages with member profiles using VitePress built-in team components.
---
<script setup>
import { VPTeamMembers } from 'vitepress/theme'

@ -1,5 +1,6 @@
---
outline: deep
description: Reference of all available frontmatter configuration options for VitePress Markdown pages.
---
# Frontmatter Config

@ -1,3 +1,7 @@
---
description: Reference of VitePress runtime APIs including composables, helper functions, and built-in components.
---
# Runtime API
VitePress offers several built-in APIs to let you access app data. VitePress also comes with a few built-in components that can be used globally.
@ -49,7 +53,7 @@ interface PageData {
titleTemplate?: string | boolean
description: string
relativePath: string
filePath: string,
filePath: string
headers: Header[]
frontmatter: Record<string, any>
params?: Record<string, any>

@ -1,5 +1,6 @@
---
outline: deep
description: Complete reference of VitePress site configuration options including app-level settings, theming, and build options.
---
# Site Config
@ -350,7 +351,7 @@ export default {
- Type: `boolean`
- Default: `false`
When set to `true`, VitePress will remove the trailing `.html` from URLs. Also see [Generating Clean URL](../guide/routing#generating-clean-url).
When set to `true`, VitePress will remove the trailing `.html` from URLs. Also see [Generating Clean URLs](../guide/routing#generating-clean-urls).
::: warning Server Support Required
Enabling this may require additional configuration on your hosting platform. For it to work, your server must be able to serve `/foo.html` when visiting `/foo` **without a redirect**.

@ -181,7 +181,6 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial<DefaultTheme.AlgoliaSearchOptions> {
return {
placeholder: 'Buscar documentos',
translations: {
button: {
buttonText: 'Buscar',
@ -189,46 +188,72 @@ function searchOptions(): Partial<DefaultTheme.AlgoliaSearchOptions> {
},
modal: {
searchBox: {
clearButtonTitle: 'Limpiar búsqueda',
clearButtonAriaLabel: 'Limpiar búsqueda',
clearButtonTitle: 'Limpiar',
clearButtonAriaLabel: 'Borrar la consulta',
closeButtonText: 'Cerrar',
closeButtonAriaLabel: 'Cerrar',
placeholderText: undefined,
placeholderTextAskAi: undefined,
placeholderText: 'Buscar en la documentación o preguntar a Ask AI',
placeholderTextAskAi: 'Haz otra pregunta...',
placeholderTextAskAiStreaming: 'Respondiendo...',
searchInputLabel: 'Buscar',
backToKeywordSearchButtonText:
'Volver a la búsqueda por palabras clave',
backToKeywordSearchButtonAriaLabel:
'Volver a la búsqueda por palabras clave'
'Volver a la búsqueda por palabras clave',
newConversationPlaceholder: 'Haz una pregunta',
conversationHistoryTitle: 'Mi historial de conversaciones',
startNewConversationText: 'Iniciar una nueva conversación',
viewConversationHistoryText: 'Historial de conversaciones',
threadDepthErrorPlaceholder: 'Se alcanzó el límite de conversación'
},
newConversation: {
newConversationTitle: '¿Cómo puedo ayudarte hoy?',
newConversationDescription:
'Busco en tu documentación para ayudarte a encontrar guías de configuración, detalles de funciones y consejos de solución de problemas rápidamente.'
},
footer: {
selectText: 'Seleccionar',
submitQuestionText: 'Enviar pregunta',
selectKeyAriaLabel: 'Tecla Enter',
navigateText: 'Navegar',
navigateUpKeyAriaLabel: 'Flecha arriba',
navigateDownKeyAriaLabel: 'Flecha abajo',
closeText: 'Cerrar',
backToSearchText: 'Volver a la búsqueda',
closeKeyAriaLabel: 'Tecla Escape',
poweredByText: 'Con la tecnología de'
},
errorScreen: {
titleText: 'No se pueden obtener resultados',
helpText: 'Puede que quieras comprobar tu conexión de red.'
},
startScreen: {
recentSearchesTitle: 'Historial de búsqueda',
noRecentSearchesText: 'Ninguna búsqueda reciente',
saveRecentSearchButtonTitle: 'Guardar en el historial de búsqueda',
removeRecentSearchButtonTitle: 'Borrar del historial de búsqueda',
recentSearchesTitle: 'Recientes',
noRecentSearchesText: 'No hay búsquedas recientes',
saveRecentSearchButtonTitle: 'Guardar esta búsqueda',
removeRecentSearchButtonTitle: 'Eliminar esta búsqueda del historial',
favoriteSearchesTitle: 'Favoritos',
removeFavoriteSearchButtonTitle: 'Borrar de favoritos',
removeFavoriteSearchButtonTitle:
'Eliminar esta búsqueda de favoritos',
recentConversationsTitle: 'Conversaciones recientes',
removeRecentConversationButtonTitle:
'Eliminar esta conversación del historial'
},
errorScreen: {
titleText: 'No fue posible obtener resultados',
helpText: 'Verifique su conexión de red'
},
noResultsScreen: {
noResultsText: 'No fue posible encontrar resultados',
suggestedQueryText: 'Puede intentar una nueva búsqueda',
noResultsText: 'No se encontraron resultados para',
suggestedQueryText: 'Intenta buscar',
reportMissingResultsText:
'¿Deberían haber resultados para esta consulta?',
reportMissingResultsLinkText: 'Click para enviar feedback'
'¿Crees que esta consulta debería devolver resultados?',
reportMissingResultsLinkText: 'Avísanos.'
},
resultsScreen: {
askAiPlaceholder: 'Preguntar a la IA: '
askAiPlaceholder: 'Preguntar a la IA: ',
noResultsAskAiPlaceholder:
'¿No lo encontraste en la documentación? Pide ayuda a Ask AI: '
},
askAiScreen: {
disclaimerText:
'Las respuestas son generadas por IA y pueden contener errores. Verifica las respuestas.',
'Las respuestas se generan con IA y pueden contener errores. Verifícalas.',
relatedSourcesText: 'Fuentes relacionadas',
thinkingText: 'Pensando...',
copyButtonText: 'Copiar',
@ -236,23 +261,70 @@ function searchOptions(): Partial<DefaultTheme.AlgoliaSearchOptions> {
copyButtonTitle: 'Copiar',
likeButtonTitle: 'Me gusta',
dislikeButtonTitle: 'No me gusta',
thanksForFeedbackText: '¡Gracias por tu opinión!',
thanksForFeedbackText: '¡Gracias por tu comentario!',
preToolCallText: 'Buscando...',
duringToolCallText: 'Buscando ',
afterToolCallText: 'Búsqueda de',
aggregatedToolCallText: 'Búsqueda de'
duringToolCallText: 'Buscando...',
afterToolCallText: 'Buscado',
stoppedStreamingText: 'Has detenido esta respuesta',
errorTitleText: 'Error de chat',
threadDepthExceededMessage:
'Esta conversación se ha cerrado para mantener respuestas precisas.',
startNewConversationButtonText: 'Iniciar una nueva conversación'
}
}
},
footer: {
selectText: 'Seleccionar',
submitQuestionText: 'Enviar pregunta',
selectKeyAriaLabel: 'Tecla Enter',
navigateText: 'Navegar',
navigateUpKeyAriaLabel: 'Flecha arriba',
navigateDownKeyAriaLabel: 'Flecha abajo',
closeText: 'Cerrar',
backToSearchText: 'Volver a la búsqueda',
closeKeyAriaLabel: 'Tecla Escape',
poweredByText: 'Búsqueda por'
askAi: {
sidePanel: {
button: {
translations: {
buttonText: 'Preguntar a la IA',
buttonAriaLabel: 'Preguntar a la IA'
}
},
panel: {
translations: {
header: {
title: 'Preguntar a la IA',
conversationHistoryTitle: 'Mi historial de conversaciones',
newConversationText: 'Iniciar una nueva conversación',
viewConversationHistoryText: 'Historial de conversaciones'
},
promptForm: {
promptPlaceholderText: 'Haz una pregunta',
promptAnsweringText: 'Respondiendo...',
promptAskAnotherQuestionText: 'Haz otra pregunta',
promptDisclaimerText:
'Las respuestas se generan con IA y pueden contener errores.',
promptLabelText:
'Pulsa Enter para enviar, o Shift+Enter para una nueva línea.',
promptAriaLabelText: 'Entrada de prompt'
},
conversationScreen: {
preToolCallText: 'Buscando...',
searchingText: 'Buscando...',
toolCallResultText: 'Buscado',
conversationDisclaimer:
'Las respuestas se generan con IA y pueden contener errores. Verifícalas.',
reasoningText: 'Razonando...',
thinkingText: 'Pensando...',
relatedSourcesText: 'Fuentes relacionadas',
stoppedStreamingText: 'Has detenido esta respuesta',
copyButtonText: 'Copiar',
copyButtonCopiedText: '¡Copiado!',
likeButtonTitle: 'Me gusta',
dislikeButtonTitle: 'No me gusta',
thanksForFeedbackText: '¡Gracias por tu comentario!',
errorTitleText: 'Error de chat'
},
newConversationScreen: {
titleText: '¿Cómo puedo ayudarte hoy?',
introductionText:
'Busco en tu documentación para ayudarte a encontrar guías de configuración, detalles de funciones y consejos de solución de problemas rápidamente.'
},
logo: {
poweredByText: 'Con la tecnología de'
}
}
}
}
}

@ -1,3 +1,7 @@
---
description: Aprende cómo referenciar y manejar recursos estáticos como imágenes, medios y fuentes en VitePress.
---
# Manejo de Assets {#asset-handling}
## Referenciando Assets Estáticos {#referencing-static-assets}

@ -1,4 +1,5 @@
---
description: Conecta VitePress a un CMS headless usando rutas dinámicas y cargadores de datos.
outline: deep
---

@ -1,3 +1,7 @@
---
description: Crea y usa un tema personalizado en VitePress para controlar completamente la apariencia y el estilo de tu sitio.
---
# Usando un Tema Personalizado {#using-a-custom-theme}
## Carga de Tema {#theme-resolving}

@ -1,3 +1,7 @@
---
description: Carga datos arbitrarios en tiempo de compilación usando cargadores de datos de VitePress e impórtalos desde páginas o componentes.
---
# Carga de Datos en Tiempo de Compilacion {#build-time-data-loading}
VitePress proporciona un recurso llamado **cargadores de dato** que permite cargar datos arbitrarios e importarlos desde páginas o componentes. La carga de datos es ejecutada **apenas en el tiempo del build** los datos resultantes serán serializados como JSON en el paquete de JavaScript final.

@ -1,4 +1,5 @@
---
description: Despliega tu sitio VitePress en plataformas populares como Netlify, Vercel, GitHub Pages y más.
outline: deep
---
@ -105,13 +106,13 @@ Nota: el archivo `vercel.json` debe ser colocado en la raiz de su **repositório
## Guias de Plataforma {#platform-guides}
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
Configure un nuevo proyecto y altere estas configuraciones usando su panel:
- **Comando de Compilación:** `npm run docs:build`
- **directorio de Salida:** `docs/.vitepress/dist`
- **Versión de Node:** `18` (o superior)
- **Versión de Node:** `20` (o superior)
::: warning
No active opciones como _Auto Minify_ para código HTML. Eso removera comentarios de salida que tiene significado para Vue. Habrán errores de incompatibilidad de hidratación se fueran removidos.
@ -170,9 +171,7 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
- name: Install dependencies
run: npm ci # o pnpm install / yarn install / bun install
- name: Build with VitePress
run: |
npm run docs:build # o pnpm docs:build / yarn docs:build / bun run docs:build
touch docs/.vitepress/dist/.nojekyll
run: npm run docs:build # o pnpm docs:build / yarn docs:build / bun run docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
@ -192,6 +191,7 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
uses: actions/deploy-pages@v4
```
::: warning
Asegurese de que la opción `base` en su VitePress esté configurada correctamentse. Vea [Configuranco un Path base Público](#setting-a-public-base-path) para más detalles.
:::
@ -201,12 +201,12 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
### GitLab Pages
1. Defina `outDir` en la configuración VitePress como `../public`. Configure la opción `base` para `'/<repository>/'` se desea implantar en `https://<username>.gitlab.io/<repository>/`.
1. Defina `outDir` en la configuración VitePress como `../public`. Configure la opción `base` para `'/<repository>/'` se desea implantar en `https://<username>.gitlab.io/<repository>/`. No necesita `base` si está implementando en un dominio personalizado, páginas de usuario o grupo, o si la configuración "Use unique domain" está habilitada en GitLab.
2. Cree un archivo llamado `.gitlab-ci.yml` en la raiz del proyecto con el contenido abajo. Esto construirá e implantará su sitio siempre que haga alteraciones en el contenido.
```yaml [.gitlab-ci.yml]
image: node:18
image: node:24
pages:
cache:
paths:
@ -222,7 +222,7 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
- main
```
### Azure Static Web Apps {#azure-static-web-apps}
### Azure
1. Siga la [documentación oficial](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration).
@ -232,7 +232,11 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
### Firebase {#firebase}
### CloudRay
Puedes desplegar tu proyecto VitePress con [CloudRay](https://cloudray.io/) siguiendo estas [instrucciones](https://cloudray.io/articles/how-to-deploy-vitepress-site).
### Firebase
1. Cree `firebase.json` y `.firebaserc` en la raiz de su proyecto:
@ -263,14 +267,6 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
firebase deploy
```
### Surge
1. Después de ejecutar `npm run docs:build`, ejecute este comando para implantar:
```sh
npx surge docs/.vitepress/dist
```
### Heroku
1. Siga la documentación y el guia proporcionados por [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static).
@ -283,10 +279,66 @@ No active opciones como _Auto Minify_ para código HTML. Eso removera comentario
}
```
### Edgio
### Hostinger
Consulte [Crear e Implantar una Aplicación VitePress en Edgio](https://docs.edg.io/guides/vitepress).
Puedes desplegar tu proyecto VitePress con [Hostinger](https://www.hostinger.com/web-apps-hosting) siguiendo estas [instrucciones](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/). Al configurar los ajustes de compilación, elige VitePress como framework y ajusta el directorio raíz a `./docs`.
### Kinsta Static Site Hosting {#kinsta-static-site-hosting}
### Kinsta
Puede implantar su sitio VitePress em [Kinsta](https://kinsta.com/static-site-hosting/) siguiendo estas [instrucciones](https://kinsta.com/docs/vitepress-static-site-example/).
### Stormkit
Puedes desplegar tu proyecto VitePress en [Stormkit](https://www.stormkit.io) siguiendo estas [instrucciones](https://stormkit.io/blog/how-to-deploy-vitepress).
### Surge
1. Después de ejecutar `npm run docs:build`, ejecute este comando para implantar:
```sh
npx surge docs/.vitepress/dist
```
### Nginx
Aquí hay un ejemplo de configuración de bloque de servidor Nginx. Esta configuración incluye compresión gzip para recursos comunes basados en texto, reglas para servir los archivos estáticos de su sitio VitePress con encabezados de caché adecuados, así como el manejo de `cleanUrls: true`.
```nginx
server {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
listen 80;
server_name _;
index index.html;
location / {
# content location
root /app;
# exact matches -> reverse clean urls -> folders -> not found
try_files $uri $uri.html $uri/ =404;
# non existent pages
error_page 404 /404.html;
# a folder without index.html raises 403 in this setup
error_page 403 /404.html;
# adjust caching headers
# files in the assets folder have hashes filenames
location ~* ^/assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
```
Esta configuración asume que su sitio VitePress compilado está ubicado en el directorio `/app` de su servidor. Ajuste la directiva `root` según corresponda si los archivos de su sitio se encuentran en otro lugar.
::: warning No predeterminar index.html
La resolución de try_files no debe predeterminar index.html como en otras aplicaciones Vue. Esto resultará en un estado de página inválido.
:::
Se puede encontrar más información en la [documentación oficial de nginx](https://nginx.org/en/docs/), en estos issues [#2837](https://github.com/vuejs/vitepress/discussions/2837), [#3235](https://github.com/vuejs/vitepress/issues/3235) así como en este [post del blog](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings) de Mehdi Merah.

@ -1,4 +1,5 @@
---
description: Personaliza y extiende el tema predeterminado de VitePress con CSS personalizado, componentes, layouts y slots.
outline: deep
---
@ -189,6 +190,8 @@ Lista completa de _slots_ disponibles en el layout del tema por defecto:
- `home-hero-before`
- `home-hero-info-before`
- `home-hero-info`
- `home-hero-info-after`
- `home-hero-actions-before-actions`
- `home-hero-actions-after`
- `home-hero-image`
- `home-hero-after`

@ -1,3 +1,7 @@
---
description: Aprende cómo usar frontmatter YAML en archivos Markdown de VitePress para controlar los metadatos y el comportamiento a nivel de página.
---
# Frontmatter
## Uso {#usage}

@ -1,3 +1,7 @@
---
description: Comienza a trabajar con VitePress. Aprende cómo instalar, crear la estructura y comenzar a desarrollar tu sitio de documentación.
---
# Iniciando {#getting-started}
## Experimente Online {#try-it-online}
@ -8,7 +12,7 @@ Puede experimentar VitePress directamente en su navegador en [StackBlitz](https:
### Prerrequisitos {#prerequisites}
- [Node.js](https://nodejs.org/) versión 18 o superior.
- [Node.js](https://nodejs.org/) versión 20 o superior.
- Terminal para acessar VitePress a través de su interfaz de linea de comando (CLI).
- Editor de texto con soporte a sintaxis [Markdown](https://en.wikipedia.org/wiki/Markdown).
- [VSCode](https://code.visualstudio.com/) es recomendado, junto con la [extensión oficial Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar).

@ -1,3 +1,7 @@
---
description: Configura la internacionalización (i18n) en VitePress para soportar múltiples idiomas en tu sitio.
---
# Internacionalización {#internationalization}
Para usar recursos de i18n integrados, es necesario crear una estructura de directorios de la siguiente forma:

@ -1,3 +1,7 @@
---
description: Extensiones Markdown integradas en VitePress, incluyendo contenedores personalizados, bloques de código con resaltado de sintaxis, resaltado de líneas, grupos de código y más.
---
# Extensiones Markdown {#markdown-extensions}
VitePress viene con Extensiones embutidas.
@ -773,7 +777,7 @@ Por ejemplo, puede incluir un archivo markdown relativo usando esto:
## Conceptos Básicos
<!--@include: ./parts/basics.md-->
<!--@@include: ./parts/basics.md-->
```
**Archivo de Parte** (`parts/basics.md`)
@ -809,7 +813,7 @@ También soporta la selección de un intervalo de lineas:
## Conceptos Básicos
<!--@include: ./parts/basics.md{3,}-->
<!--@@include: ./parts/basics.md{3,}-->
```
**Archivo de Parte** (`parts/basics.md`)

@ -1,3 +1,7 @@
---
description: Habilita el modo MPA (Aplicación de Múltiples Páginas) en VitePress para páginas sin JavaScript con mejor rendimiento inicial.
---
# Modo MPA <Badge type="warning" text="experimental" /> {#mpa-mode}
El modo MPA (Aplicación de multiples páginas) puede ser habilitado por la linea de comandos con `vitepress build --mpa`, o a través de la configuración por la opción `mpa: true`.

@ -1,4 +1,5 @@
---
description: Comprende el enrutamiento basado en archivos de VitePress, rutas dinámicas, URLs limpias y reescritura de rutas.
outline: deep
---
@ -121,7 +122,7 @@ Alternativamente, puede usarse directamente la sintaxis de tag anchor:
:::
## Generación de URL Limpia {#generating-clean-url}
## Generación de URLs Limpias {#generating-clean-urls}
::: warning Soporte del Servidor Necesario
Para servir URLs limpias con VitePress, es necesario soporte en el lado del servidor.

@ -1,3 +1,7 @@
---
description: Genera un archivo sitemap.xml para tu sitio VitePress para mejorar la visibilidad en motores de búsqueda.
---
# Generación de Sitemap {#sitemap-generation}
VitePress viene con soporte embutido para generar un archivo `sitemap.xml` para su sitio. Para habilitar, adicione lo siguiente a su `.vitepress/config.js`:

@ -1,4 +1,5 @@
---
description: Asegura que los componentes del tema y el código personalizado de VitePress sean compatibles con el renderizado del lado del servidor.
outline: deep
---

@ -1,3 +1,7 @@
---
description: Usa componentes Vue y funciones de plantillas dinámicas directamente dentro de archivos Markdown en VitePress.
---
# Usando Vue en Markdown {#using-vue-in-markdown}
En VitePress, cada archivo Markdown es compilado para HTML y entonces procesado como un [Componente de Archivo Único de Vue](https://vuejs.org/guide/scaling-up/sfc.html). Esto significa que puede usar cualquier funcionalidad de Vue dentro del Markdown, incluyendo la interpolación dinámica, usar componentes Vue o lógica arbitrária de componentes Vue dentro de la página adicionando una tag `<script>`.

@ -1,3 +1,7 @@
---
description: VitePress es un generador de sitios estáticos diseñado para crear sitios web rápidos y centrados en el contenido, impulsado por Vite y Vue.
---
# ¿Qué es VitePress? {#what-is-vitepress}
VitePress es un [Generador de Sitios Estáticos](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) diseñado para construir sitios web rápidos y enfocados en el contenido. En pocas palabras, VitePress toma tu contenido fuente escrito en [Markdown](https://en.wikipedia.org/wiki/Markdown), le aplica un tema y genera páginas HTML estáticas que se pueden desplegar fácilmente en cualquier lugar.

@ -1,4 +1,5 @@
---
description: VitePress es un generador de sitios estáticos impulsado por Vite y Vue que te permite crear hermosos sitios de documentación a partir de Markdown.
layout: home
hero:

@ -1,3 +1,7 @@
---
description: Referencia de los comandos CLI de VitePress, incluyendo dev, build, preview e init.
---
# Intefaz de Linea de Comando {#command-line-interface}
## `vitepress dev`

@ -1,3 +1,7 @@
---
description: Usa el componente Badge para agregar etiquetas de estado a los encabezados en la documentación de VitePress.
---
# Badge {#badge}
Los Badge te permite agregar estados a tus encabezados. Por ejemplo, podría resultar útil especificar el tipo de sección o la version compatible.

@ -1,3 +1,7 @@
---
description: Integra Carbon Ads en tu sitio VitePress usando el soporte integrado del tema predeterminado.
---
# Carbon Ads {#carbon-ads}
VitePress ha incorporado soporte nativo para [Carbon Ads](https://www.carbonads.net/). Al definir las credenciales de Carbon Ads en la configuración, VitePress mostrará anuncios en la página.

@ -1,3 +1,7 @@
---
description: Referencia de todas las opciones de configuración disponibles para el tema predeterminado de VitePress.
---
# Configuración del Tema Predeterminado {#default-theme-config}
La configuración del tema te permite personalizar tu tema. puedes definir la configuración del tema a través de la opción `themeConfig` en el archivo de configuración:

@ -1,3 +1,7 @@
---
description: Muestra un enlace de edición en las páginas de documentación para permitir a los usuarios sugerir cambios en GitHub o GitLab.
---
# Editar Link {#edit-link}
## Configuración a nivel de sitio {#site-level-config}

@ -1,3 +1,7 @@
---
description: Configura el pie de página global que se muestra en la parte inferior de las páginas de VitePress.
---
# Pie de página {#footer}
VitePress mostrará un pie de página global en la parte inferior de la página cuando `themeConfig.footer` está presente.

@ -1,3 +1,7 @@
---
description: Configura el diseño de la página de inicio del tema predeterminado de VitePress con secciones hero, características y contenido personalizado.
---
# Página Inicial {#home-page}
El tema predeterminado de VitePress proporciona un diseño de página de inicio, que también puedes ver en uso [en la página de inicio de este sitio web](../). Puedes usarlo en cualquiera de sus páginas especificando `layout: home` en [frontmatter](./frontmatter-config).

@ -1,3 +1,7 @@
---
description: Muestra la marca de tiempo de la última actualización en las páginas de VitePress basada en el historial de commits de Git.
---
# Última Actualización {#last-updated}
La hora en que se actualizó el contenido por última vez se mostrará en la esquina inferior derecha de la página. Para habilitar, agregue la opción `lastUpdated` en su confirguración.

@ -1,3 +1,7 @@
---
description: Elige entre los layouts doc, page y home en el tema predeterminado de VitePress.
---
# Layout {#layout}
Puedes elegir el layout de la página definiendo una opción de `layout` para el [frontmatter](./frontmatter-config) De la página. Hay tres opciones de layout: `doc`, `page` y `home`. Si no se especifica nada, la página será tratada como una página. `doc`.

@ -1,3 +1,7 @@
---
description: Configura la barra de navegación en el tema predeterminado de VitePress, incluyendo el título del sitio, el logotipo y los enlaces del menú.
---
# Navegación {#nav}
Refiriéndose a la barra de navegación que se muestra en la parte superior de la página. Contiene el título del sitio, enlaces del menú global, etc.

@ -1,3 +1,7 @@
---
description: Personaliza los enlaces de página anterior y siguiente que se muestran en la parte inferior de las páginas de documentación en VitePress.
---
# Links Anterior y Próximo {#prev-next-links}
Puede personalizar el texto y el enlace de los botones Anterior y Siguiente que se muestran en la parte inferior de la página. Esto es útil cuando desea mostrar un texto diferente al que tiene en la barra lateral. Además, puede resultarle útil desactivar el pie de página o el enlace a la página para que no se incluya en la barra lateral.

@ -1,4 +1,5 @@
---
description: Configura la búsqueda local o con Algolia para tu sitio VitePress.
outline: deep
---
@ -39,18 +40,25 @@ export default defineConfig({
provider: 'local',
options: {
locales: {
zh: {
es: { // usa `root` si quieres traducir la configuración regional predeterminada
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
buttonText: 'Buscar',
buttonAriaLabel: 'Buscar'
},
modal: {
noResultsText: '无法找到相关结果',
resetButtonTitle: '清除查询条件',
displayDetails: 'Mostrar lista detallada',
resetButtonTitle: 'Restablecer búsqueda',
backButtonTitle: 'Cerrar búsqueda',
noResultsText: 'No hay resultados',
footer: {
selectText: '选择',
navigateText: '切换'
selectText: 'Seleccionar',
selectKeyAriaLabel: 'Intro',
navigateText: 'Navegar',
navigateUpKeyAriaLabel: 'Flecha arriba',
navigateDownKeyAriaLabel: 'Flecha abajo',
closeText: 'Cerrar',
closeKeyAriaLabel: 'Esc'
}
}
}
@ -62,7 +70,7 @@ export default defineConfig({
})
```
### Opciones MiniSearch {#mini-search-options}
### Opciones MiniSearch {#minisearch-options}
Puedes configurar MiniSearch de esta manera:
@ -116,7 +124,7 @@ export default defineConfig({
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
// retorne un string HTML
// devuelve una cadena HTML
}
}
}
@ -141,7 +149,7 @@ export default defineConfig({
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('algum/caminho')) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
@ -167,7 +175,7 @@ export default defineConfig({
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 (await md.renderAsync(`# ${env.frontmatter.title}`)) + html
return html
}
}
@ -197,10 +205,23 @@ export default defineConfig({
})
```
### i18n {#algolia-search-i18n} {#algolia-search-i18n}
### i18n {#algolia-search-i18n}
Puedes utilizar una configuración como esta para utilizar la búsqueda multilingüe:
<details>
<summary>Haz clic para expandir</summary>
<<< @/snippets/algolia-i18n.ts
</details>
Consulta la [documentación oficial de Algolia](https://docsearch.algolia.com/docs/api#translations) para conocer más detalles. Para empezar rápidamente, también puedes copiar las traducciones usadas por este sitio desde [nuestro repositorio de GitHub](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code).
### Algolia Ask AI Support {#ask-ai}
Si deseas incluir **Ask AI**, pasa la opción `askAi` (o alguno de sus campos parciales) dentro de `options`:
```ts
import { defineConfig } from 'vitepress'
@ -212,73 +233,52 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: { buttonText: '搜索文档', buttonAriaLabel: '搜索文档' },
modal: {
searchBox: {
clearButtonTitle: '清除查询条件',
clearButtonAriaLabel: '清除查询条件',
closeButtonText: '关闭',
closeButtonAriaLabel: '关闭',
placeholderText: '搜索文档',
placeholderTextAskAi: '向 AI 提问:',
placeholderTextAskAiStreaming: '回答中...',
searchInputLabel: '搜索',
backToKeywordSearchButtonText: '返回关键字搜索',
backToKeywordSearchButtonAriaLabel: '返回关键字搜索'
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '没有搜索历史',
saveRecentSearchButtonTitle: '保存至搜索历史',
removeRecentSearchButtonTitle: '从搜索历史中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除',
recentConversationsTitle: '最近的对话',
removeRecentConversationButtonTitle: '从历史记录中删除对话'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查你的网络连接'
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为该查询应该有结果?',
reportMissingResultsLinkText: '点击反馈'
},
resultsScreen: { askAiPlaceholder: '向 AI 提问: ' },
askAiScreen: {
disclaimerText: '答案由 AI 生成,可能不准确,请自行验证。',
relatedSourcesText: '相关来源',
thinkingText: '思考中...',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
copyButtonTitle: '复制',
likeButtonTitle: '赞',
dislikeButtonTitle: '踩',
thanksForFeedbackText: '感谢你的反馈!',
preToolCallText: '搜索中...',
duringToolCallText: '搜索 ',
afterToolCallText: '已搜索'
},
footer: {
selectText: '选择',
submitQuestionText: '提交问题',
selectKeyAriaLabel: 'Enter 键',
navigateText: '切换',
navigateUpKeyAriaLabel: '向上箭头',
navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
backToSearchText: '返回搜索',
closeKeyAriaLabel: 'Esc 键',
poweredByText: '搜索提供者'
// 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: '...'
}
}
}
}
})
```
::: warning Nota
Si prefieres solo la búsqueda por palabra clave y no la Ask AI, simplemente omite `askAi`.
:::
### Panel lateral de Ask AI {#ask-ai-side-panel}
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](https://docsearch.algolia.com/docs/sidepanel/api-reference) contiene la lista completa de opciones.
```ts
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
}
}
}
}
@ -287,132 +287,70 @@ export default defineConfig({
})
```
### Algolia Ask AI Support {#ask-ai}
Si deseas incluir **Ask AI**, pasa la opción `askAi` (o alguno de sus campos parciales) dentro de `options`:
Si necesitas deshabilitar el atajo de teclado, usa la opción `keyboardShortcuts` del panel lateral:
```ts
options: {
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
// askAi: 'TU-ASSISTANT-ID'
askAi: {
assistantId: 'XXXYYY'
assistantId: 'XXXYYY',
sidePanel: {
keyboardShortcuts: {
'Ctrl/Cmd+I': false
}
}
}
}
}
}
}
})
```
::: warning Nota
Si prefieres solo la búsqueda por palabra clave y no la Ask AI, simplemente omite `askAi`.
:::
#### Modo (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
[Estas opciones](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) se pueden superponer. Consulte la documentación oficial de Algolia para obtener más información sobre ellos.
Puedes controlar opcionalmente cómo VitePress integra la búsqueda por palabra clave y Ask AI:
### Configuración _Crawler_ {#crawler-config}
- `mode: 'auto'` (por defecto): infiere `hybrid` cuando la búsqueda por palabra clave está configurada, de lo contrario `sidePanel` cuando 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).
A continuación se muestra un ejemplo de la configuración que utiliza este sitio:
#### Solo Ask AI (sin búsqueda por palabra clave) {#ask-ai-only}
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`:
```ts
new Crawler({
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
mode: 'sidePanel',
askAi: {
assistantId: 'XXXYYY',
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'
indexName: '...',
sidePanel: true
}
}
}
}
})
```
### Configuración _Crawler_ {#crawler-config}
A continuación se muestra un ejemplo de la configuración que utiliza este sitio:
<<< @/snippets/algolia-crawler.js

@ -1,3 +1,7 @@
---
description: Configura la navegación de la barra lateral en el tema predeterminado de VitePress con grupos, secciones colapsables y múltiples barras laterales.
---
# Barra Lateral {#sidebar}
La barra lateral es el bloque de navegación principal de su documentación. Puede configurar el menú de la barra lateral en [`themeConfig.sidebar`](./default-theme-config#sidebar).

@ -1,3 +1,7 @@
---
description: Crea páginas de equipo con perfiles de miembros usando los componentes de equipo integrados de VitePress.
---
<script setup>
import { VPTeamMembers } from 'vitepress/theme'

@ -1,4 +1,5 @@
---
description: Referencia de todas las opciones de configuración de frontmatter disponibles para páginas Markdown de VitePress.
outline: deep
---

@ -1,3 +1,7 @@
---
description: Referencia de las APIs en tiempo de ejecución de VitePress, incluyendo composables, funciones auxiliares y componentes integrados.
---
# API en Tiempo de Ejecución {#runtime-api}
VitePress ofrece varias API integradas para permitir el acceso a los datos de la aplicación. VitePress también viene con algunos componentes integrados que se pueden utilizar globalmente.
@ -45,7 +49,7 @@ interface PageData {
titleTemplate?: string | boolean
description: string
relativePath: string
filePath: string,
filePath: string
headers: Header[]
frontmatter: Record<string, any>
params?: Record<string, any>

@ -1,4 +1,5 @@
---
description: Referencia completa de las opciones de configuración del sitio VitePress, incluyendo ajustes a nivel de aplicación, temas y opciones de compilación.
outline: deep
---
@ -350,7 +351,7 @@ export default {
- Tipo: `boolean`
- Predeterminado: `false`
Cuando se establece en `true`, VitePress eliminará el `.html` al final de las URLs. Consulte también [Generar URL Limpia](../guide/routing#generating-clean-url).
Cuando se establece en `true`, VitePress eliminará el `.html` al final de las URLs. Consulte también [Generación de URLs Limpias](../guide/routing#generating-clean-urls).
::: warning Soporte de Servidor Requerido
Habilitar esto puede requerir configurar adicional en su plataforma de alojamiento. Para funcionar, su servidor debe poder servir `/foo.html` cuando visite `/foo` **sin redirección**.

@ -182,7 +182,6 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial<DefaultTheme.AlgoliaSearchOptions> {
return {
placeholder: 'جستجوی مستندات',
translations: {
button: {
buttonText: 'جستجو',
@ -190,67 +189,139 @@ function searchOptions(): Partial<DefaultTheme.AlgoliaSearchOptions> {
},
modal: {
searchBox: {
clearButtonTitle: 'پاک کردن جستجو',
clearButtonAriaLabel: 'پاک کردن جستجو',
clearButtonTitle: 'پاک کردن',
clearButtonAriaLabel: 'پاک کردن عبارت جستجو',
closeButtonText: 'بستن',
closeButtonAriaLabel: 'بستن',
placeholderText: 'جستجوی مستندات',
placeholderTextAskAi: 'از هوش مصنوعی بپرسید: ',
placeholderTextAskAiStreaming: 'در حال پاسخ...',
placeholderText: 'در مستندات جستجو کنید یا از Ask AI بپرسید',
placeholderTextAskAi: 'سؤال دیگری بپرسید...',
placeholderTextAskAiStreaming: 'در حال پاسخ گویی...',
searchInputLabel: 'جستجو',
backToKeywordSearchButtonText: 'بازگشت به جستجوی کلیدواژه',
backToKeywordSearchButtonAriaLabel: 'بازگشت به جستجوی کلیدواژه'
backToKeywordSearchButtonAriaLabel: 'بازگشت به جستجوی کلیدواژه',
newConversationPlaceholder: 'یک سؤال بپرسید',
conversationHistoryTitle: 'تاریخچه گفت وگوی من',
startNewConversationText: 'شروع گفت وگوی جدید',
viewConversationHistoryText: 'تاریخچه گفت وگو',
threadDepthErrorPlaceholder: 'محدودیت گفت وگو رسید'
},
startScreen: {
recentSearchesTitle: 'جستجوهای اخیر',
noRecentSearchesText: 'هیچ جستجوی اخیر',
saveRecentSearchButtonTitle: 'ذخیره در تاریخچه جستجو',
removeRecentSearchButtonTitle: 'حذف از تاریخچه جستجو',
favoriteSearchesTitle: 'علاقه‌مندی‌ها',
removeFavoriteSearchButtonTitle: 'حذف از علاقه‌مندی‌ها',
recentConversationsTitle: 'گفتگوهای اخیر',
removeRecentConversationButtonTitle: 'حذف این گفتگو از تاریخچه'
newConversation: {
newConversationTitle: 'امروز چگونه می توانم کمک کنم؟',
newConversationDescription:
'در مستندات شما جستجو می کنم تا سریع راهنماهای راه اندازی، جزئیات ویژگی ها و نکات رفع اشکال را پیدا کنم.'
},
footer: {
selectText: 'انتخاب',
submitQuestionText: 'ارسال سؤال',
selectKeyAriaLabel: 'کلید Enter',
navigateText: 'پیمایش',
navigateUpKeyAriaLabel: 'پیکان بالا',
navigateDownKeyAriaLabel: 'پیکان پایین',
closeText: 'بستن',
backToSearchText: 'بازگشت به جستجو',
closeKeyAriaLabel: 'کلید Escape',
poweredByText: 'قدرت گرفته از'
},
errorScreen: {
titleText: 'عدم امکان دریافت نتایج',
helpText: 'اتصال شبکه خود را بررسی کنید'
titleText: 'امکان دریافت نتایج وجود ندارد',
helpText: 'ممکن است لازم باشد اتصال شبکه را بررسی کنید.'
},
startScreen: {
recentSearchesTitle: 'اخیر',
noRecentSearchesText: 'جستجوی اخیر وجود ندارد',
saveRecentSearchButtonTitle: 'ذخیره این جستجو',
removeRecentSearchButtonTitle: 'حذف این جستجو از تاریخچه',
favoriteSearchesTitle: 'علاقه مندی ها',
removeFavoriteSearchButtonTitle: 'حذف این جستجو از علاقه مندی ها',
recentConversationsTitle: 'گفت وگوهای اخیر',
removeRecentConversationButtonTitle: 'حذف این گفت وگو از تاریخچه'
},
noResultsScreen: {
noResultsText: 'هیچ نتیجه‌ای یافت نشد',
suggestedQueryText: 'می‌توانید جستجوی دیگری امتحان کنید',
reportMissingResultsText: 'فکر می‌کنید باید نتیجه‌ای نمایش داده شود؟',
reportMissingResultsLinkText: 'برای ارسال بازخورد کلیک کنید'
noResultsText: 'هیچ نتیجه ای برای',
suggestedQueryText: 'سعی کنید جستجو کنید',
reportMissingResultsText:
'فکر می کنید این جستجو باید نتیجه داشته باشد؟',
reportMissingResultsLinkText: 'به ما اطلاع دهید.'
},
resultsScreen: {
askAiPlaceholder: 'از هوش مصنوعی بپرسید: '
askAiPlaceholder: 'از هوش مصنوعی بپرسید: ',
noResultsAskAiPlaceholder:
'در مستندات پیدا نکردید؟ از Ask AI کمک بگیرید: '
},
askAiScreen: {
disclaimerText:
'پاسخها توسط هوش مصنوعی تولید می‌شوند و ممکن است خطا داشته باشند. لطفاً بررسی کنید.',
'پاسخ ها توسط هوش مصنوعی تولید می شوند و ممکن است اشتباه باشند. بررسی کنید.',
relatedSourcesText: 'منابع مرتبط',
thinkingText: 'در حال پردازش...',
thinkingText: 'در حال فکر کردن...',
copyButtonText: 'کپی',
copyButtonCopiedText: 'کپی شد!',
copyButtonTitle: 'کپی',
likeButtonTitle: 'پسندیدم',
dislikeButtonTitle: 'نپسندیدم',
thanksForFeedbackText: 'از بازخورد شما سپاسگزاریم!',
thanksForFeedbackText: 'از بازخورد شما متشکریم!',
preToolCallText: 'در حال جستجو...',
duringToolCallText: 'در حال جستجو برای ',
afterToolCallText: 'جستجو انجام شد',
aggregatedToolCallText: 'جستجو انجام شد'
duringToolCallText: 'در حال جستجو...',
afterToolCallText: 'جستجو برای',
stoppedStreamingText: 'شما این پاسخ را متوقف کردید',
errorTitleText: 'خطای گفتگو',
threadDepthExceededMessage:
'برای حفظ دقت پاسخ ها، این گفت وگو بسته شد.',
startNewConversationButtonText: 'شروع گفت وگوی جدید'
}
}
},
footer: {
selectText: 'انتخاب',
submitQuestionText: 'ارسال پرسش',
selectKeyAriaLabel: 'کلید Enter',
navigateText: 'حرکت',
navigateUpKeyAriaLabel: 'کلید جهت بالا',
navigateDownKeyAriaLabel: 'کلید جهت پایین',
closeText: 'بستن',
backToSearchText: 'بازگشت به جستجو',
closeKeyAriaLabel: 'کلید Escape',
poweredByText: 'جستجو توسط'
askAi: {
sidePanel: {
button: {
translations: {
buttonText: 'از هوش مصنوعی بپرسید',
buttonAriaLabel: 'از هوش مصنوعی بپرسید'
}
},
panel: {
translations: {
header: {
title: 'از هوش مصنوعی بپرسید',
conversationHistoryTitle: 'تاریخچه گفت وگوی من',
newConversationText: 'شروع گفت وگوی جدید',
viewConversationHistoryText: 'تاریخچه گفت وگو'
},
promptForm: {
promptPlaceholderText: 'یک سؤال بپرسید',
promptAnsweringText: 'در حال پاسخ گویی...',
promptAskAnotherQuestionText: 'سؤال دیگری بپرسید',
promptDisclaimerText:
'پاسخ ها توسط هوش مصنوعی تولید می شوند و ممکن است اشتباه باشند.',
promptLabelText:
'برای ارسال Enter را بزنید، یا برای خط جدید Shift+Enter.',
promptAriaLabelText: 'ورودی پرسش'
},
conversationScreen: {
preToolCallText: 'در حال جستجو...',
searchingText: 'در حال جستجو...',
toolCallResultText: 'جستجو برای',
conversationDisclaimer:
'پاسخ ها توسط هوش مصنوعی تولید می شوند و ممکن است اشتباه باشند. بررسی کنید.',
reasoningText: 'در حال استدلال...',
thinkingText: 'در حال فکر کردن...',
relatedSourcesText: 'منابع مرتبط',
stoppedStreamingText: 'شما این پاسخ را متوقف کردید',
copyButtonText: 'کپی',
copyButtonCopiedText: 'کپی شد!',
likeButtonTitle: 'پسندیدم',
dislikeButtonTitle: 'نپسندیدم',
thanksForFeedbackText: 'از بازخورد شما متشکریم!',
errorTitleText: 'خطای گفتگو'
},
newConversationScreen: {
titleText: 'امروز چگونه می توانم کمک کنم؟',
introductionText:
'در مستندات شما جستجو می کنم تا سریع راهنماهای راه اندازی، جزئیات ویژگی ها و نکات رفع اشکال را پیدا کنم.'
},
logo: {
poweredByText: 'قدرت گرفته از'
}
}
}
}
}

@ -1,3 +1,7 @@
---
description: نحوه ارجاع و مدیریت منابع ایستا مانند تصاویر، رسانه‌ها و فونت‌ها در ویت‌پرس.
---
# مدیریت منابع {#asset-handling}
## ارجاع به منابع ایستا {#referencing-static-assets}

@ -1,5 +1,6 @@
---
outline: deep
description: اتصال ویت‌پرس به یک سیستم مدیریت محتوای هدلس با استفاده از مسیرهای پویا و بارگذارهای داده.
---
# اتصال به یک سیستم مدیریت محتوا (CMS) {#connecting-to-a-cms}

@ -1,5 +1,6 @@
---
outline: deep
description: ایجاد و استفاده از تم سفارشی در ویت‌پرس برای کنترل کامل ظاهر و احساس سایت شما.
---
# استفاده از یک تم سفارشی {#using-a-custom-theme}

@ -1,3 +1,7 @@
---
description: بارگذاری داده‌های دلخواه در زمان ساخت با استفاده از بارگذارهای داده ویت‌پرس و وارد کردن آن‌ها در صفحات یا کامپوننت‌ها.
---
# بارگذاری داده در زمان ساخت {#build-time-data-loading}
ویت‌پرس یک ویژگی به نام **بارگذارهای داده** ارائه می‌دهد که به شما این امکان را می‌دهد که داده‌های دلخواه را بارگیری کنید و آن‌ها را از صفحات یا اجزا وارد کنید. بارگذاری داده فقط **در زمان ساخت** اجرا می‌شود: داده‌های حاصل به صورت JSON در بسته JavaScript نهایی سریالیزه می‌شوند.

@ -1,5 +1,6 @@
---
outline: deep
description: استقرار سایت ویت‌پرس خود بر روی پلتفرم‌های محبوب مانند Netlify، Vercel، GitHub Pages و سایر سرویس‌ها.
---
# استقرار وب‌سایت ویت‌پرس شما {#deploy-your-vitepress-site}
@ -105,13 +106,13 @@ Cache-Control: max-age=31536000,immutable
## راهنمای‌های پلتفرم {#platform-guides}
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#netlify-vercel-cloudflare-pages-aws-amplify-render}
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
یک پروژه جدید راه‌اندازی کرده و این تنظیمات را با استفاده از داشبورد خود تغییر دهید:
- **دستور ساخت:** `npm run docs:build`
- **دایرکتوری خروجی:** `docs/.vitepress/dist`
- **نسخه Node:** `18` (یا بالاتر)
- **نسخه Node:** `20` (یا بالاتر)
::: warning هشدار
گزینه‌هایی مانند _Auto Minify_ را برای کد HTML فعال نکنید. این گزینه‌ها ممکن است توضیحاتی را که به Vue معنا دارد، از خروجی حذف کنند. ممکن است خطاهای ناسازگاری را در اجرا ببینید اگر حذف شوند.
@ -198,12 +199,12 @@ Cache-Control: max-age=31536000,immutable
### صفحات GitLab {#gitlab-pages}
1. `outDir` را در پیکربندی ویت‌پرس به `../public` تنظیم کنید. گزینه `base` را به `'/<repository>/'` تنظیم کنید اگر می‌خواهید در `https://<username>.gitlab.io/<repository>/` انتشار دهید.
1. `outDir` را در پیکربندی ویت‌پرس به `../public` تنظیم کنید. گزینه `base` را به `'/<repository>/'` تنظیم کنید اگر می‌خواهید در `https://<username>.gitlab.io/<repository>/` انتشار دهید. اگر روی دامنه سفارشی، صفحات کاربر یا گروه منتشر می‌کنید یا تنظیمات "Use unique domain" در GitLab فعال است، نیازی به `base` ندارید.
2. یک فایل به نام `.gitlab-ci.yml` در ریشه پروژه خود با محتوای زیر ایجاد کنید. این کار به ساخت و انتشار وب‌سایت شما هر زمانی که تغییری در محتوا ایجاد می‌کنید، می‌پردازد:
```yaml [.gitlab-ci.yml]
image: node:18
image: node:24
pages:
cache:
paths:
@ -219,7 +220,7 @@ Cache-Control: max-age=31536000,immutable
- main
```
### Azure Static Web Apps {#azure-static-web-apps}
### Azure
1. دستورالعمل [رسمی](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration) را دنبال کنید.
@ -229,7 +230,11 @@ Cache-Control: max-age=31536000,immutable
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
### Firebase {#firebase}
### CloudRay
می‌توانید پروژه ویت‌پرس خود را با [CloudRay](https://cloudray.io/) با دنبال کردن این [دستورالعمل‌ها](https://cloudray.io/articles/how-to-deploy-vitepress-site) منتشر کنید.
### Firebase
1. فایل‌های `firebase.json` و `.firebaserc` را در ریشه پروژه خود ایجاد کنید:
@ -260,15 +265,7 @@ Cache-Control: max-age=31536000,immutable
firebase deploy
```
### Surge {#surge}
1. بعد از اجرای `npm run docs:build`، دستور زیر را برای انتشار اجرا کنید:
```sh
npx surge docs/.vitepress/dist
```
### Heroku {#heroku}
### Heroku
1. دستورالعمل و راهنماها را در [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static) دنبال کنید.
@ -280,11 +277,11 @@ Cache-Control: max-age=31536000,immutable
}
```
### Edgio {#edgio}
### Hostinger
به [ایجاد و انتشار یک برنامه ویت‌پرس در Edgio](https://docs.edg.io/guides/vitepress) مراجعه کنید.
می‌توانید پروژه ویت‌پرس خود را با [Hostinger](https://www.hostinger.com/web-apps-hosting) با دنبال کردن این [دستورالعمل‌ها](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/) منتشر کنید. هنگام پیکربندی تنظیمات ساخت، VitePress را به عنوان فریم‌ورک انتخاب کنید و ریشه دایرکتوری را به `./docs` تنظیم کنید.
### Kinsta Static Site Hosting {#kinsta-static-site-hosting}
### Kinsta
شما می‌توانید وب‌سایت ویت‌پرس خود را بر روی [Kinsta](https://kinsta.com/static-site-hosting/) با دنبال کردن این [دستورالعمل‌ها](https://kinsta.com/docs/vitepress-static-site-example/) انتشار دهید.
@ -292,6 +289,14 @@ Cache-Control: max-age=31536000,immutable
شما می‌توانید پروژه ویت‌پرس خود را به [Stormkit](https://www.stormkit.io) با دنبال کردن این [دستورالعمل‌ها](https://stormkit.io/blog/how-to-deploy-vitepress) انتشار دهید.
### Surge
1. بعد از اجرای `npm run docs:build`، دستور زیر را برای انتشار اجرا کنید:
```sh
npx surge docs/.vitepress/dist
```
### Nginx
اینجا یک مثال از پیکربندی بلوک سرور Nginx است. این تنظیم شامل فشرده‌سازی gzip برای فایل‌های متن معمولی، قوانین برای سرویس فایل‌های ایستا سایت ویت‌پرس شما با هدرهای مناسب برای حافظه‌نگهداری مناسب است و همچنین مدیریت `cleanUrls: true` می‌کند.

@ -1,5 +1,6 @@
---
outline: deep
description: سفارشی‌سازی و گسترش تم پیش‌فرض ویت‌پرس با CSS سفارشی، کامپوننت‌ها، طرح‌بندی‌ها و اسلات‌ها.
---
# گسترش تم پیش‌فرض {#extending-the-default-theme}
@ -191,6 +192,7 @@ export default {
- `home-hero-info-before`
- `home-hero-info`
- `home-hero-info-after`
- `home-hero-actions-before-actions`
- `home-hero-actions-after`
- `home-hero-image`
- `home-hero-after`

@ -1,3 +1,7 @@
---
description: نحوه استفاده از frontmatter YAML در فایل‌های Markdown ویت‌پرس برای کنترل متاداده و رفتار صفحه.
---
# Frontmatter
## استفاده {#usage}

@ -1,3 +1,7 @@
---
description: نصب و راه‌اندازی ویت‌پرس. یاد بگیرید چگونه سایت مستندات خود را نصب، ایجاد و توسعه دهید.
---
# شروع کار {#getting-started}
## تست آنلاین {#try-it-online}
@ -8,7 +12,7 @@
### پیش‌نیازها {#prerequisites}
- [Node.js](https://nodejs.org/) نسخه 18 یا بالاتر.
- [Node.js](https://nodejs.org/) نسخه 20 یا بالاتر.
- ترمینال برای دسترسی به ویت‌پرس از طریق رابط خط فرمان (CLI).
- ویرایشگر متنی با پشتیبانی از [Markdown](https://en.wikipedia.org/wiki/Markdown).
- [VSCode](https://code.visualstudio.com/) به همراه [افزونه رسمی Vue](https://marketplace.visualstudio.com/items?itemName=Vue.volar).

@ -1,3 +1,7 @@
---
description: راه‌اندازی بین‌المللی‌سازی (i18n) در ویت‌پرس برای پشتیبانی از چندین زبان در سایت شما.
---
# بین‌المللی‌سازی {#internationalization}
برای استفاده از ویژگی‌های داخلی بین‌المللی‌سازی، نیاز است که یک ساختار دایرکتوری به شکل زیر ایجاد کنید:

@ -1,3 +1,7 @@
---
description: افزونه‌های داخلی Markdown در ویت‌پرس شامل کانتینرهای سفارشی، بلوک‌های کد با هایلایت، گروه‌های کد و موارد دیگر.
---
# افزونه‌های Markdown {#markdown-extensions}
ویت‌پرس با افزونه‌های markdown داخلی ارائه شده است.
@ -724,7 +728,7 @@ export default config
## مبانی
<!--@include: ./parts/basics.md-->
<!--@@include: ./parts/basics.md-->
```
**قسمت فایل** (`parts/basics.md`)
@ -760,7 +764,7 @@ export default config
## مبانی
<!--@include: ./parts/basics.md{3,}-->
<!--@@include: ./parts/basics.md{3,}-->
```
**قسمت فایل** (`parts/basics.md`)
@ -796,8 +800,8 @@ export default config
## مبانی
<!--@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}-->
<!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@@include: ./parts/basics.md#basic-usage{5,}-->
```
**قسمت فایل** (`parts/basics.md`)

@ -1,3 +1,7 @@
---
description: فعال‌سازی حالت MPA (برنامه چند صفحه) در ویت‌پرس برای صفحات بدون جاوااسکریپت با عملکرد اولیه بهتر.
---
# حالت MPA <Badge type="warning" text="آزمایشی" /> {#mpa-mode}
حالت MPA (برنامه چند صفحه) می‌تواند از طریق خط فرمان با `vitepress build --mpa` فعال شود، یا از طریق تنظیمات با گزینه `mpa: true`.

@ -1,5 +1,6 @@
---
outline: deep
description: آشنایی با مسیریابی مبتنی بر فایل، مسیرهای پویا، URLهای تمیز و بازنویسی مسیر در ویت‌پرس.
---
# مسیریابی {#routing}
@ -121,7 +122,7 @@ src/getting-started.md --> /getting-started.html
:::
## تولید URLهای تمیز {#generating-clean-url}
## تولید URLهای تمیز {#generating-clean-urls}
::: warning نیازمندی پشتیبانی سرور

@ -1,3 +1,7 @@
---
description: تولید فایل sitemap.xml برای سایت ویت‌پرس جهت بهبود قابلیت کشف توسط موتورهای جستجو.
---
# جنریت کردن Sitemap {#sitemap-generation}
ویت‌پرس با پشتیبانی بیرونی برای تولید فایل `sitemap.xml` برای سایت شما ارائه می‌شود. برای فعال‌سازی آن، موارد زیر را به فایل `.vitepress/config.js` خود اضافه کنید:

@ -1,5 +1,6 @@
---
outline: deep
description: اطمینان از سازگاری کامپوننت‌های تم و کد سفارشی ویت‌پرس با رندرینگ سمت سرور (SSR).
---
# تطابق SSR {#ssr-compatibility}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save