+}
+```
+
+**例:**
+
+```vue
+
+
+
+ サイドバーがあるときだけ表示
+
+```
diff --git a/docs/ja/reference/default-theme-edit-link.md b/docs/ja/reference/default-theme-edit-link.md
new file mode 100644
index 000000000..a5b40dbd6
--- /dev/null
+++ b/docs/ja/reference/default-theme-edit-link.md
@@ -0,0 +1,60 @@
+# 編集リンク {#edit-link}
+
+## サイトレベルの設定 {#site-level-config}
+
+編集リンクは、GitHub や GitLab などの Git 管理サービスでそのページを編集できるリンクを表示します。有効化するには、設定に `themeConfig.editLink` オプションを追加します。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
+ }
+ }
+}
+```
+
+`pattern` オプションはリンクの URL 構造を定義します。`:path` はページパスに置き換えられます。
+
+また、引数に [`PageData`](./runtime-api#usedata) を受け取り、URL 文字列を返す純粋関数を指定することもできます。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: ({ filePath }) => {
+ if (filePath.startsWith('packages/')) {
+ return `https://github.com/acme/monorepo/edit/main/${filePath}`
+ } else {
+ return `https://github.com/acme/monorepo/edit/main/docs/${filePath}`
+ }
+ }
+ }
+ }
+}
+```
+
+この関数はブラウザでシリアライズされ実行されるため、副作用を持たず、スコープ外のものへアクセスしないでください。
+
+既定では、ドキュメント下部に「Edit this page」というリンクテキストが表示されます。`text` オプションでこの文言をカスタマイズできます。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
+ text: 'GitHub でこのページを編集'
+ }
+ }
+}
+```
+
+## フロントマターでの設定 {#frontmatter-config}
+
+ページごとに無効化するには、フロントマターで `editLink` オプションを使用します。
+
+```yaml
+---
+editLink: false
+---
+```
diff --git a/docs/ja/reference/default-theme-footer.md b/docs/ja/reference/default-theme-footer.md
new file mode 100644
index 000000000..f8226c89f
--- /dev/null
+++ b/docs/ja/reference/default-theme-footer.md
@@ -0,0 +1,55 @@
+# フッター {#footer}
+
+`themeConfig.footer` を設定すると、ページ下部にグローバルフッターが表示されます。
+
+```ts
+export default {
+ themeConfig: {
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2019-present Evan You'
+ }
+ }
+}
+```
+
+```ts
+export interface Footer {
+ // 著作権表示の直前に表示されるメッセージ
+ message?: string
+
+ // 実際の著作権表記
+ copyright?: string
+}
+```
+
+上記の設定は HTML 文字列にも対応しています。たとえば、フッター内のテキストにリンクを含めたい場合は、次のように設定できます。
+
+```ts
+export default {
+ themeConfig: {
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2019-present Evan You'
+ }
+ }
+}
+```
+
+::: warning
+`message` と `copyright` は `` 要素内にレンダリングされるため、
+使用できるのはインライン要素のみです。ブロック要素を追加したい場合は、
+[`layout-bottom`](../guide/extending-default-theme#layout-slots) スロットの利用を検討してください。
+:::
+
+なお、[SideBar](./default-theme-sidebar) が表示されている場合はフッターは表示されません。
+
+## フロントマターでの設定 {#frontmatter-config}
+
+ページ単位で無効化するには、フロントマターの `footer` オプションを使用します。
+
+```yaml
+---
+footer: false
+---
+```
diff --git a/docs/ja/reference/default-theme-home-page.md b/docs/ja/reference/default-theme-home-page.md
new file mode 100644
index 000000000..011456f81
--- /dev/null
+++ b/docs/ja/reference/default-theme-home-page.md
@@ -0,0 +1,189 @@
+# ホームページ {#home-page}
+
+VitePress のデフォルトテーマにはホームページ用レイアウトが用意されています([このサイトのトップページ](../) でも使われています)。[フロントマター](./frontmatter-config) に `layout: home` を指定すれば、任意のページで利用できます。
+
+```yaml
+---
+layout: home
+---
+```
+
+ただし、この指定だけでは多くのことは起きません。`hero` や `features` などの追加オプションを設定して、ホームページにあらかじめ用意された複数の「セクション」を配置できます。
+
+## ヒーローセクション {#hero-section}
+
+ヒーローセクションはホームページの最上部に表示されます。設定例は次のとおりです。
+
+```yaml
+---
+layout: home
+
+hero:
+ name: VitePress
+ text: Vite & Vue powered static site generator.
+ tagline: 概要テキスト...
+ image:
+ src: /logo.png
+ alt: VitePress
+ actions:
+ - theme: brand
+ text: はじめる
+ link: /guide/what-is-vitepress
+ - theme: alt
+ text: GitHub で見る
+ link: https://github.com/vuejs/vitepress
+---
+```
+
+```ts
+interface Hero {
+ // `text` の上に表示される短い文字列。ブランドカラーで表示。
+ // 製品名のような短い文言を想定。
+ name?: string
+
+ // ヒーローセクションのメインテキスト。`h1` として出力。
+ text: string
+
+ // `text` の下に表示されるタグライン。
+ tagline?: string
+
+ // テキストとタグラインの横に表示する画像。
+ image?: ThemeableImage
+
+ // ヒーローに表示するアクションボタン。
+ actions?: HeroAction[]
+}
+
+type ThemeableImage =
+ | string
+ | { src: string; alt?: string }
+ | { light: string; dark: string; alt?: string }
+
+interface HeroAction {
+ // ボタンのカラーテーマ。既定は `brand`。
+ theme?: 'brand' | 'alt'
+
+ // ボタンのラベル。
+ text: string
+
+ // ボタンのリンク先。
+ link: string
+
+ // a 要素の target 属性。
+ target?: string
+
+ // a 要素の rel 属性。
+ rel?: string
+}
+```
+
+### name の色をカスタマイズする {#customizing-the-name-color}
+
+`name` にはブランドカラー(`--vp-c-brand-1`)が使われますが、`--vp-home-hero-name-color` 変数を上書きして色を変更できます。
+
+```css
+:root {
+ --vp-home-hero-name-color: blue;
+}
+```
+
+さらに、`--vp-home-hero-name-background` を組み合わせると、`name` にグラデーションを適用できます。
+
+```css
+:root {
+ --vp-home-hero-name-color: transparent;
+ --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
+}
+```
+
+## フィーチャーセクション {#features-section}
+
+フィーチャーセクションでは、ヒーロー直下に任意の数の機能説明を並べられます。フロントマターに `features` オプションを指定して設定します。
+
+各フィーチャーにはアイコン(絵文字または画像)を指定できます。アイコンが画像(svg, png, jpeg など)の場合は、**適切な幅・高さ** を指定してください。必要に応じて説明テキストや実サイズ、ライト/ダーク用の差し替えも指定できます。
+
+```yaml
+---
+layout: home
+
+features:
+ - icon: 🛠️
+ title: いつでもシンプル&ミニマル
+ details: 概要テキスト...
+ - icon:
+ src: /cool-feature-icon.svg
+ title: もうひとつの便利機能
+ details: 概要テキスト...
+ - icon:
+ dark: /dark-feature-icon.svg
+ light: /light-feature-icon.svg
+ title: さらに別の機能
+ details: 概要テキスト...
+---
+```
+
+```ts
+interface Feature {
+ // 各フィーチャーボックスに表示するアイコン。
+ icon?: FeatureIcon
+
+ // フィーチャーのタイトル。
+ title: string
+
+ // フィーチャーの詳細説明。
+ details: string
+
+ // フィーチャーをクリックしたときのリンク(内部・外部どちらも可)。
+ //
+ // 例: `guide/reference/default-theme-home-page` や `https://example.com`
+ link?: string
+
+ // フィーチャー内に表示するリンクテキスト。
+ // `link` と併用するのが最適。
+ //
+ // 例: `Learn more`, `Visit page` など
+ linkText?: string
+
+ // `link` 用の rel 属性。
+ //
+ // 例: `external`
+ rel?: string
+
+ // `link` 用の target 属性。
+ target?: string
+}
+
+type FeatureIcon =
+ | string
+ | { src: string; alt?: string; width?: string; height: string }
+ | {
+ light: string
+ dark: string
+ alt?: string
+ width?: string
+ height: string
+ }
+```
+
+## Markdown コンテンツ {#markdown-content}
+
+`---` で区切るフロントマターの下に Markdown を書くだけで、ホームページに追加コンテンツを表示できます。
+
+````md
+---
+layout: home
+
+hero:
+ name: VitePress
+ text: Vite & Vue powered static site generator.
+---
+
+## はじめに
+
+`npx` を使えば、すぐに VitePress を始められます!
+
+```sh
+npm init
+npx vitepress init
+```
+````
diff --git a/docs/ja/reference/default-theme-last-updated.md b/docs/ja/reference/default-theme-last-updated.md
new file mode 100644
index 000000000..82dfc6de7
--- /dev/null
+++ b/docs/ja/reference/default-theme-last-updated.md
@@ -0,0 +1,46 @@
+# 最終更新日時 {#last-updated}
+
+ページ右下に、コンテンツの最終更新時刻を表示できます。有効化するには、設定に `lastUpdated` オプションを追加します。
+
+::: info
+VitePress は各ファイルの **直近の Git コミットのタイムスタンプ** を用いて「最終更新」を表示します。これを有効にするには、対象の Markdown ファイルが Git にコミットされている必要があります。
+
+内部的には、各ファイルに対して `git log -1 --pretty="%ai"` を実行してタイムスタンプを取得します。すべてのページで同じ更新時刻が表示される場合、(CI 環境でよくある)**浅いクローン(shallow clone)** により Git の履歴が取得できていない可能性があります。
+
+**GitHub Actions** での修正例は次のとおりです。
+
+```yaml{4}
+- name: Checkout
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+```
+
+他の CI/CD プラットフォームでも同様の設定が用意されています。
+
+もしそのようなオプションが使えない場合は、`package.json` のビルドスクリプトで手動フェッチを前置してください。
+
+```json
+"docs:build": "git fetch --unshallow && vitepress build docs"
+```
+:::
+
+## サイトレベルの設定 {#site-level-config}
+
+```js
+export default {
+ lastUpdated: true
+}
+```
+
+## フロントマターでの設定 {#frontmatter-config}
+
+ページ単位で無効化するには、フロントマターで `lastUpdated` を指定します。
+
+```yaml
+---
+lastUpdated: false
+---
+```
+
+より詳しくは [デフォルトテーマ: 最終更新](./default-theme-config#lastupdated) を参照してください。テーマレベルで truthy な値を設定すると、サイトまたはページで明示的に無効化しない限り、この機能は有効になります。
diff --git a/docs/ja/reference/default-theme-layout.md b/docs/ja/reference/default-theme-layout.md
new file mode 100644
index 000000000..e241d03ec
--- /dev/null
+++ b/docs/ja/reference/default-theme-layout.md
@@ -0,0 +1,62 @@
+# レイアウト {#layout}
+
+ページの [フロントマター](./frontmatter-config) の `layout` オプションでページのレイアウトを選択できます。利用可能なレイアウトは `doc`、`page`、`home` の 3 種類です。何も指定しない場合は `doc` として扱われます。
+
+```yaml
+---
+layout: doc
+---
+```
+
+## Doc レイアウト {#doc-layout}
+
+`doc` は既定のレイアウトで、Markdown 全体を「ドキュメント」風にスタイリングします。コンテンツ全体を `vp-doc` という CSS クラスでラップし、その配下の要素にスタイルを適用します。
+
+`p` や `h2` などほぼすべての汎用要素に特別なスタイルが当たります。そのため、Markdown 内にカスタム HTML を追加した場合も、これらのスタイルの影響を受ける点に注意してください。
+
+また、以下のようなドキュメント特有の機能も提供します。これらはこのレイアウトでのみ有効になります。
+
+- 編集リンク(Edit Link)
+- 前後リンク(Prev / Next Link)
+- アウトライン(Outline)
+- [Carbon 広告](./default-theme-carbon-ads)
+
+## Page レイアウト {#page-layout}
+
+`page` は「ブランクページ」として扱われます。Markdown はパースされ、[Markdown 拡張](../guide/markdown) も `doc` と同様に機能しますが、既定のスタイルは適用されません。
+
+このレイアウトでは、VitePress テーマにマークアップを干渉させず、すべてを自分でスタイルできます。独自のカスタムページを作成したい場合に便利です。
+
+なお、このレイアウトでも、ページがサイドバー設定に一致する場合はサイドバーが表示されます。
+
+## Home レイアウト {#home-layout}
+
+`home` はテンプレート化された「ホームページ」を生成します。このレイアウトでは、`hero` や `features` などの追加オプションでコンテンツをさらにカスタマイズできます。詳しくは [デフォルトテーマ: ホームページ](./default-theme-home-page) を参照してください。
+
+## レイアウトなし {#no-layout}
+
+レイアウトを一切適用したくない場合は、フロントマターで `layout: false` を指定します。これは(既定でサイドバー/ナビバー/フッターなしの)完全にカスタマイズ可能なランディングページを作りたい場合に役立ちます。
+
+## カスタムレイアウト {#custom-layout}
+
+カスタムレイアウトを使用することもできます。
+
+```md
+---
+layout: foo
+---
+```
+
+これは、コンテキストに登録された `foo` という名前のコンポーネントを探します。たとえば、`.vitepress/theme/index.ts` でグローバル登録できます。
+
+```ts
+import DefaultTheme from 'vitepress/theme'
+import Foo from './Foo.vue'
+
+export default {
+ extends: DefaultTheme,
+ enhanceApp({ app }) {
+ app.component('foo', Foo)
+ }
+}
+```
diff --git a/docs/ja/reference/default-theme-nav.md b/docs/ja/reference/default-theme-nav.md
new file mode 100644
index 000000000..207bf9e91
--- /dev/null
+++ b/docs/ja/reference/default-theme-nav.md
@@ -0,0 +1,215 @@
+# ナビゲーション {#nav}
+
+ナビはページ上部に表示されるナビゲーションバーです。サイトタイトル、グローバルメニューリンクなどを含みます。
+
+## サイトタイトルとロゴ {#site-title-and-logo}
+
+既定では、ナビには [`config.title`](./site-config#title) の値が表示されます。ナビに表示する文字列を変更したい場合は、`themeConfig.siteTitle` にカスタム文字列を指定します。
+
+```js
+export default {
+ themeConfig: {
+ siteTitle: 'My Custom Title'
+ }
+}
+```
+
+サイトのロゴがある場合は、画像へのパスを渡すと表示できます。ロゴは `public` 直下に配置し、絶対パスで指定してください。
+
+```js
+export default {
+ themeConfig: {
+ logo: '/my-logo.svg'
+ }
+}
+```
+
+ロゴを追加すると、サイトタイトルと並んで表示されます。ロゴだけを表示したい場合は、`siteTitle` を `false` に設定してタイトル文字列を非表示にできます。
+
+```js
+export default {
+ themeConfig: {
+ logo: '/my-logo.svg',
+ siteTitle: false
+ }
+}
+```
+
+ダーク/ライトモードでロゴを切り替えたり、`alt` 属性を付けたい場合は、ロゴにオブジェクトを渡すこともできます。詳細は [`themeConfig.logo`](./default-theme-config#logo) を参照してください。
+
+## ナビゲーションリンク {#navigation-links}
+
+`themeConfig.nav` オプションでナビにリンクを追加できます。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ { text: 'Guide', link: '/guide' },
+ { text: 'Config', link: '/config' },
+ { text: 'Changelog', link: 'https://github.com/...' }
+ ]
+ }
+}
+```
+
+`text` はナビに表示される文字列、`link` はクリック時に遷移するリンクです。内部リンクは `.md` 拡張子を付けず、必ず `/` で始めるようにしてください。
+
+`link` には、[`PageData`](./runtime-api#usedata) を受け取ってパスを返す関数を指定することもできます。
+
+ナビリンクはドロップダウンメニューにもできます。リンクオプションに `items` を設定してください。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ { text: 'Guide', link: '/guide' },
+ {
+ text: 'Dropdown Menu',
+ items: [
+ { text: 'Item A', link: '/item-1' },
+ { text: 'Item B', link: '/item-2' },
+ { text: 'Item C', link: '/item-3' }
+ ]
+ }
+ ]
+ }
+}
+```
+
+なお、ドロップダウンのタイトル(上の例の `Dropdown Menu`)には `link` は設定できません。ドロップダウンを開くボタンになるためです。
+
+さらに、ドロップダウン内を「セクション」に分けることもできます(入れ子の `items` を使います)。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ { text: 'Guide', link: '/guide' },
+ {
+ text: 'Dropdown Menu',
+ items: [
+ {
+ // セクションのタイトル
+ text: 'Section A Title',
+ items: [
+ { text: 'Section A Item A', link: '...' },
+ { text: 'Section B Item B', link: '...' }
+ ]
+ }
+ ]
+ },
+ {
+ text: 'Dropdown Menu',
+ items: [
+ {
+ // タイトルは省略することも可能
+ items: [
+ { text: 'Section A Item A', link: '...' },
+ { text: 'Section B Item B', link: '...' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+### リンクの「アクティブ」状態をカスタマイズ {#customize-link-s-active-state}
+
+現在のページが特定のパス配下にあるとき、該当するナビ項目がハイライトされます。一致させるパスをカスタマイズしたい場合は、`activeMatch` に **正規表現文字列** を指定します。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ // ユーザーが `/config/` 配下にいるときにアクティブになる
+ {
+ text: 'Guide',
+ link: '/guide',
+ activeMatch: '/config/'
+ }
+ ]
+ }
+}
+```
+
+::: warning
+`activeMatch` は正規表現 **オブジェクト** ではなく、**文字列** で指定してください。ビルド時のシリアライズの都合で `RegExp` は使用できません。
+:::
+
+### リンクの `target` と `rel` をカスタマイズ {#customize-link-s-target-and-rel-attributes}
+
+既定では、リンクが外部かどうかに応じて VitePress が `target` と `rel` を自動設定します。必要であれば明示的に指定することもできます。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ {
+ text: 'Merchandise',
+ link: 'https://www.thegithubshop.com/',
+ target: '_self',
+ rel: 'sponsored'
+ }
+ ]
+ }
+}
+```
+
+## ソーシャルリン� {#social-links}
+
+[`socialLinks`](./default-theme-config#sociallinks) を参照してください。
+
+## カスタムコンポーネント {#custom-components}
+
+`component` オプションを使って、ナビゲーションバーにカスタムコンポーネントを配置できます。`component` には Vue コンポーネント名を指定し、[Theme.enhanceApp](../guide/custom-theme#theme-interface) で **グローバル登録** しておく必要があります。
+
+```js [.vitepress/config.js]
+export default {
+ themeConfig: {
+ nav: [
+ {
+ text: 'My Menu',
+ items: [
+ {
+ component: 'MyCustomComponent',
+ // コンポーネントに渡す任意の props
+ props: {
+ title: 'My Custom Component'
+ }
+ }
+ ]
+ },
+ {
+ component: 'AnotherCustomComponent'
+ }
+ ]
+ }
+}
+```
+
+次に、コンポーネントをグローバル登録します。
+
+```js [.vitepress/theme/index.js]
+import DefaultTheme from 'vitepress/theme'
+
+import MyCustomComponent from './components/MyCustomComponent.vue'
+import AnotherCustomComponent from './components/AnotherCustomComponent.vue'
+
+/** @type {import('vitepress').Theme} */
+export default {
+ extends: DefaultTheme,
+ enhanceApp({ app }) {
+ app.component('MyCustomComponent', MyCustomComponent)
+ app.component('AnotherCustomComponent', AnotherCustomComponent)
+ }
+}
+```
+
+コンポーネントはナビゲーションバー内にレンダリングされます。VitePress は次の追加 props をコンポーネントに提供します。
+
+- `screenMenu`: モバイルのナビメニュー内にあるかどうかを示す任意の boolean
+
+e2e テスト内の例は[こちら](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)を参照してください。
diff --git a/docs/ja/reference/default-theme-prev-next-links.md b/docs/ja/reference/default-theme-prev-next-links.md
new file mode 100644
index 000000000..7b15d699c
--- /dev/null
+++ b/docs/ja/reference/default-theme-prev-next-links.md
@@ -0,0 +1,43 @@
+# 前/次リンク {#prev-next-links}
+
+ドキュメントのフッターに表示される「前のページ」「次のページ」のテキストとリンクをカスタマイズできます。サイドバーに表示しているタイトルとは別の文言を使いたい場合や、フッターを無効化したり、サイドバーに含まれていないページへリンクしたい場合に便利です。
+
+## prev
+
+- 型: `string | false | { text?: string; link?: string }`
+
+- 詳細:
+
+ 前のページへのリンクに表示するテキスト/リンクを指定します。フロントマターで設定しない場合は、サイドバー設定から自動推測されます。
+
+- 例:
+
+ - テキストだけをカスタマイズ:
+
+ ```yaml
+ ---
+ prev: 'Get Started | Markdown'
+ ---
+ ```
+
+ - テキストとリンクの両方をカスタマイズ:
+
+ ```yaml
+ ---
+ prev:
+ text: 'Markdown'
+ link: '/guide/markdown'
+ ---
+ ```
+
+ - 前のページを非表示にする:
+
+ ```yaml
+ ---
+ prev: false
+ ---
+ ```
+
+## next
+
+`prev` と同様ですが、次のページ用の設定です。
diff --git a/docs/ja/reference/default-theme-search.md b/docs/ja/reference/default-theme-search.md
new file mode 100644
index 000000000..f77603611
--- /dev/null
+++ b/docs/ja/reference/default-theme-search.md
@@ -0,0 +1,360 @@
+---
+outline: deep
+---
+
+# 検索 {#search}
+
+## ローカル検索 {#local-search}
+
+VitePress は、[minisearch](https://github.com/lucaong/minisearch/) によるブラウザ内インデックスを使った曖昧一致の全文検索をサポートします。有効化するには、`.vitepress/config.ts` で `themeConfig.search.provider` を `'local'` に設定します。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local'
+ }
+ }
+})
+```
+
+表示例:
+
+
+
+代わりに [Algolia DocSearch](#algolia-search) や、次のコミュニティ製プラグインを使うこともできます。
+
+-
+-
+-
+-
+
+### i18n {#local-search-i18n}
+
+多言語検索を行う設定例です。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ locales: {
+ ja: { // 既定ロケールを翻訳する場合は `root` にしてください
+ translations: {
+ button: {
+ buttonText: '検索',
+ buttonAriaLabel: '検索'
+ },
+ modal: {
+ displayDetails: '詳細一覧を表示',
+ resetButtonTitle: '検索をリセット',
+ backButtonTitle: '検索を閉じる',
+ noResultsText: '結果が見つかりません',
+ footer: {
+ selectText: '選択',
+ selectKeyAriaLabel: 'Enter',
+ navigateText: '移動',
+ navigateUpKeyAriaLabel: '上矢印',
+ navigateDownKeyAriaLabel: '下矢印',
+ closeText: '閉じる',
+ closeKeyAriaLabel: 'Esc'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+### miniSearch のオプション {#minisearch-options}
+
+MiniSearch の設定例です。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ miniSearch: {
+ /**
+ * @type {Pick}
+ */
+ options: {
+ /* ... */
+ },
+ /**
+ * @type {import('minisearch').SearchOptions}
+ * @default
+ * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
+ */
+ searchOptions: {
+ /* ... */
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+詳しくは [MiniSearch のドキュメント](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html) を参照してください。
+
+### コンテンツレンダラーのカスタマイズ {#custom-content-renderer}
+
+インデックス前に Markdown コンテンツをレンダリングする関数をカスタマイズできます。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ /**
+ * @param {string} src
+ * @param {import('vitepress').MarkdownEnv} env
+ * @param {import('markdown-it-async')} md
+ */
+ async _render(src, env, md) {
+ // HTML 文字列を返す
+ }
+ }
+ }
+ }
+})
+```
+
+この関数はクライアント側のサイトデータからは除外されるため、Node.js の API を使用できます。
+
+#### 例: 検索対象からページを除外する {#example-excluding-pages-from-search}
+
+フロントマターに `search: false` を追加すると、そのページを検索対象から除外できます。あるいは次のようにもできます。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ async _render(src, env, md) {
+ const html = await md.renderAsync(src, env)
+ if (env.frontmatter?.search === false) return ''
+ if (env.relativePath.startsWith('some/path')) return ''
+ return html
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning 注意
+カスタムの `_render` 関数を提供する場合、`search: false` の処理は自分で行う必要があります。また、`env` は `md.renderAsync` の呼び出し前には完全ではないため、`frontmatter` などの任意プロパティのチェックはその後に行ってください。
+:::
+
+#### 例: コンテンツの変換 — 見出しアンカーを追加 {#example-transforming-content-adding-anchors}
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ async _render(src, env, md) {
+ const html = await md.renderAsync(src, env)
+ if (env.frontmatter?.title)
+ return (await md.renderAsync(`# ${env.frontmatter.title}`)) + html
+ return html
+ }
+ }
+ }
+ }
+})
+```
+
+## Algolia 検索 {#algolia-search}
+
+VitePress は [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch) によるサイト検索をサポートします。導入は公式のガイドを参照してください。`.vitepress/config.ts` では最低限次の設定が必要です。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...'
+ }
+ }
+ }
+})
+```
+
+### i18n {#algolia-search-i18n}
+
+多言語検索の設定例です。
+
+
+クリックして展開
+
+<<< @/snippets/algolia-i18n.ts
+
+
+
+詳しくは[公式 Algolia ドキュメント](https://docsearch.algolia.com/docs/api#translations)を参照してください。すぐに始めるには、このサイトで使っている翻訳を[GitHub リポジトリ](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code)からコピーすることもできます。
+
+### Algolia Ask AI のサポート {#ask-ai}
+
+**Ask AI** を有効にするには、`options` 内に `askAi` オプション(またはその一部)を指定します。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ // askAi: "あなたのアシスタントID"
+ // または
+ askAi: {
+ // 最低限、Algolia から受け取った assistantId を指定する必要があります
+ assistantId: 'XXXYYY',
+ // 任意の上書き — 省略した場合は上位の appId/apiKey/indexName を再利用
+ // apiKey: '...',
+ // appId: '...',
+ // indexName: '...'
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning 注意
+キーワード検索を既定にして Ask AI を使わない場合は、`askAi` を指定しないでください。
+:::
+
+### Ask AI サイドパネル {#ask-ai-side-panel}
+
+DocSearch v4.5+ はオプションの **Ask AI サイドパネル**をサポートしています。有効にすると、デフォルトで **Ctrl/Cmd+I** で開くことができます。[サイドパネル API リファレンス](https://docsearch.algolia.com/docs/sidepanel/api-reference)にオプションの完全なリストがあります。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ // @docsearch/sidepanel-js SidepanelProps API をミラー
+ panel: {
+ variant: 'floating', // または 'inline'
+ side: 'right',
+ width: '360px',
+ expandedWidth: '580px',
+ suggestedQuestions: true
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+キーボードショートカットを無効にする必要がある場合は、サイドパネルの `keyboardShortcuts` オプションを使用してください:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ keyboardShortcuts: {
+ 'Ctrl/Cmd+I': false
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+#### モード (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
+
+VitePress がキーワード検索と Ask AI を統合する方法をオプションで制御できます:
+
+- `mode: 'auto'`(デフォルト):キーワード検索が設定されている場合は `hybrid` を推論し、それ以外の場合は Ask AI サイドパネルが設定されている場合は `sidePanel` を推論します。
+- `mode: 'sidePanel'`:サイドパネルのみを強制(キーワード検索ボタンを非表示)。
+- `mode: 'hybrid'`:キーワード検索モーダル + Ask AI サイドパネルを有効化(キーワード検索設定が必要)。
+- `mode: 'modal'`:Ask AI を DocSearch モーダル内に保持(サイドパネルを設定した場合でも)。
+
+#### Ask AI のみ(キーワード検索なし) {#ask-ai-only}
+
+**Ask AI サイドパネルのみ**を使用する場合は、トップレベルのキーワード検索設定を省略し、`askAi` の下に認証情報を提供できます:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ mode: 'sidePanel',
+ askAi: {
+ assistantId: 'XXXYYY',
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ sidePanel: true
+ }
+ }
+ }
+ }
+})
+```
+
+### クローラー設定 {#crawler-config}
+
+このサイトで使用している設定を元にした例です。
+
+<<< @/snippets/algolia-crawler.js
diff --git a/docs/ja/reference/default-theme-sidebar.md b/docs/ja/reference/default-theme-sidebar.md
new file mode 100644
index 000000000..ddd87383c
--- /dev/null
+++ b/docs/ja/reference/default-theme-sidebar.md
@@ -0,0 +1,180 @@
+# サイドバー {#sidebar}
+
+サイドバーはドキュメントの主要なナビゲーションブロックです。[`themeConfig.sidebar`](./default-theme-config#sidebar) でメニューを設定できます。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Guide',
+ items: [
+ { text: 'Introduction', link: '/introduction' },
+ { text: 'Getting Started', link: '/getting-started' },
+ ...
+ ]
+ }
+ ]
+ }
+}
+```
+
+## 基本 {#the-basics}
+
+最もシンプルな構成は、リンクの配列を 1 つ渡す方法です。第 1 階層のアイテムがサイドバーの「セクション」を表します。各セクションは `text`(セクションのタイトル)と、実際のナビゲーションリンクである `items` を持ちます。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ items: [
+ { text: 'Item A', link: '/item-a' },
+ { text: 'Item B', link: '/item-b' },
+ ...
+ ]
+ },
+ {
+ text: 'Section Title B',
+ items: [
+ { text: 'Item C', link: '/item-c' },
+ { text: 'Item D', link: '/item-d' },
+ ...
+ ]
+ }
+ ]
+ }
+}
+```
+
+各 `link` は `/` で始まる実ファイルへのパスを指定します。リンクの末尾を `/` で終わらせると、対応するディレクトリの `index.md` が表示されます。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Guide',
+ items: [
+ // `/guide/index.md` を表示
+ { text: 'Introduction', link: '/guide/' }
+ ]
+ }
+ ]
+ }
+}
+```
+
+サイドバーのアイテムは、ルートから数えて最大 6 階層まで入れ子にできます。7 階層以上は無視され、表示されません。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Level 1',
+ items: [
+ {
+ text: 'Level 2',
+ items: [
+ {
+ text: 'Level 3',
+ items: [
+ ...
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+## 複数のサイドバー {#multiple-sidebars}
+
+ページのパスに応じて異なるサイドバーを表示できます。たとえば、このサイトのように「Guide」セクションと「Config」セクションでナビゲーションを分けたい場合に便利です。
+
+まず、対象のセクションごとにディレクトリを分けてページを配置します。
+
+```
+.
+├─ guide/
+│ ├─ index.md
+│ ├─ one.md
+│ └─ two.md
+└─ config/
+ ├─ index.md
+ ├─ three.md
+ └─ four.md
+```
+
+次に、各セクション用のサイドバーを設定します。この場合、配列ではなくオブジェクトを渡します。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: {
+ // ユーザーが `guide` ディレクトリ配下にいるときに表示
+ '/guide/': [
+ {
+ text: 'Guide',
+ items: [
+ { text: 'Index', link: '/guide/' },
+ { text: 'One', link: '/guide/one' },
+ { text: 'Two', link: '/guide/two' }
+ ]
+ }
+ ],
+
+ // ユーザーが `config` ディレクトリ配下にいるときに表示
+ '/config/': [
+ {
+ text: 'Config',
+ items: [
+ { text: 'Index', link: '/config/' },
+ { text: 'Three', link: '/config/three' },
+ { text: 'Four', link: '/config/four' }
+ ]
+ }
+ ]
+ }
+ }
+}
+```
+
+## 折りたたみ可能なサイドバーグループ {#collapsible-sidebar-groups}
+
+サイドバーグループに `collapsed` オプションを追加すると、各セクションの開閉トグルが表示されます。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ collapsed: false,
+ items: [...]
+ }
+ ]
+ }
+}
+```
+
+既定ではすべてのセクションが「開いた」状態です。初回表示時に「閉じた」状態にしたい場合は、`collapsed` を `true` に設定します。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ collapsed: true,
+ items: [...]
+ }
+ ]
+ }
+}
+```
diff --git a/docs/ja/reference/default-theme-team-page.md b/docs/ja/reference/default-theme-team-page.md
new file mode 100644
index 000000000..5f02d4d0d
--- /dev/null
+++ b/docs/ja/reference/default-theme-team-page.md
@@ -0,0 +1,255 @@
+
+
+# チームページ {#team-page}
+
+チームを紹介したい場合は、Team コンポーネント群を使ってチームページを構成できます。使い方は 2 通りあり、ドキュメントページに埋め込む方法と、専用のチームページを作成する方法があります。
+
+## ページ内にメンバー一覧を表示する {#show-team-members-in-a-page}
+
+任意のページでチームメンバーの一覧を表示するには、`vitepress/theme` からエクスポートされている `` コンポーネントを使用します。
+
+```html
+
+
+# 私たちのチーム
+
+私たちの素晴らしいチームを紹介します。
+
+
+```
+
+上記のように、カード風の要素でメンバーが表示されます。下図のような見た目になります。
+
+
+
+`` コンポーネントには `small` と `medium` の 2 種類のサイズがあります。好みによりますが、ドキュメントページ内で使う場合は `small` が馴染みやすいことが多いでしょう。各メンバーに「説明文」や「スポンサー」ボタンなど、追加のプロパティを付けることもできます。詳細は [``](#vpteammembers) を参照してください。
+
+小規模なチームで専用ページまでは不要な場合や、文脈上の参考として一部のメンバーのみを紹介したい場合は、ドキュメントページへ埋め込む方法が適しています。
+
+メンバーが多い場合や、より広いスペースで紹介したい場合は、[専用のチームページを作成する](#専用のチームページを作成する) ことを検討してください。
+
+## 専用のチームページを作成する {#create-a-full-team-page}
+
+ドキュメントページにメンバーを追加する代わりに、カスタムの [ホームページ](./default-theme-home-page) と同様、専用のチームページを作成することもできます。
+
+まず新しい md ファイルを作成します。ファイル名は任意ですが、ここでは `team.md` とします。このファイルでフロントマターに `layout: page` を設定し、その後 `TeamPage` コンポーネント群を使ってページを構成します。
+
+```html
+---
+layout: page
+---
+
+
+
+
+
+ 私たちのチーム
+
+
+ VitePress の開発は国際的なチームによって主導されています。
+ その一部を以下に紹介します。
+
+
+
+
+```
+
+専用のチームページを作る際は、必ずすべてのチーム関連コンポーネントを `` でラップしてください。レイアウトや余白などが適切に適用されます。
+
+`` はページタイトルのセクションを追加します。タイトルは `` 見出しになります。`#title` と `#lead` スロットでチームについて説明を書きましょう。
+
+`` はドキュメントページで使う場合と同様に、メンバー一覧を表示します。
+
+### セクションを追加してメンバーを分ける {#add-sections-to-divide-team-members}
+
+チームページに「セクション」を追加できます。たとえば、コアメンバーとコミュニティパートナーなど、役割ごとにメンバーを分けて説明しやすくできます。
+
+そのためには、先ほど作成した `team.md` に `` コンポーネントを追加します。
+
+```html
+---
+layout: page
+---
+
+
+
+
+ 私たちのチーム
+ ...
+
+
+
+ パートナー
+ ...
+
+
+
+
+
+```
+
+`` は `VPTeamPageTitle` と同様に `#title` と `#lead` のスロットを持ち、さらにメンバー表示用の `#members` スロットを備えます。
+
+`#members` スロット内に `` を配置するのを忘れないでください。
+
+## ``
+
+`` コンポーネントは、与えられたメンバー配列を表示します。
+
+```html
+
+```
+
+```ts
+interface Props {
+ // 各メンバーカードのサイズ。既定は `medium`。
+ size?: 'small' | 'medium'
+
+ // 表示するメンバー一覧。
+ members: TeamMember[]
+}
+
+interface TeamMember {
+ // メンバーのアバター画像
+ avatar: string
+
+ // メンバー名
+ name: string
+
+ // 名前の下に表示する肩書き(例: Developer, Software Engineer など)
+ title?: string
+
+ // 所属組織名
+ org?: string
+
+ // 所属組織への URL
+ orgLink?: string
+
+ // メンバーの説明
+ desc?: string
+
+ // ソーシャルリンク(例: GitHub, Twitter など)
+ // Social Links オブジェクトを渡せます。
+ // 参照: https://vitepress.dev/reference/default-theme-config.html#sociallinks
+ links?: SocialLink[]
+
+ // メンバーのスポンサー用 URL
+ sponsor?: string
+
+ // スポンサーボタンのテキスト。既定は 'Sponsor'
+ actionText?: string
+}
+```
+
+## ``
+
+専用のチームページを作成する際のルートコンポーネントです。単一のスロットのみを受け取り、渡されたチーム関連コンポーネント全体に適切なスタイルを適用します。
+
+## ``
+
+ページの「タイトル」セクションを追加します。`` の直下に置くのが最適です。`#title` と `#lead` のスロットを受け取ります。
+
+```html
+
+
+
+ 私たちのチーム
+
+
+ VitePress の開発は国際的なチームによって主導されています。
+ その一部を以下に紹介します。
+
+
+
+```
+
+## ``
+
+チームページ内に「セクション」を作成します。`#title`、`#lead`、`#members` の各スロットを受け取ります。`` の中に必要な数だけ追加できます。
+
+```html
+
+ ...
+
+ パートナー
+ Lorem ipsum...
+
+
+
+
+
+```
diff --git a/docs/ja/reference/frontmatter-config.md b/docs/ja/reference/frontmatter-config.md
new file mode 100644
index 000000000..e6b8b5ca1
--- /dev/null
+++ b/docs/ja/reference/frontmatter-config.md
@@ -0,0 +1,240 @@
+---
+outline: deep
+---
+
+# フロントマター設定 {#frontmatter-config}
+
+フロントマターはページ単位の設定を可能にします。各 Markdown ファイルで、サイト全体やテーマレベルの設定を上書きできます。フロントマターでしか定義できない項目もあります。
+
+使用例:
+
+```md
+---
+title: Docs with VitePress
+editLink: true
+---
+```
+
+Vue の式内では、グローバル `$frontmatter` を介してフロントマターデータにアクセスできます。
+
+```md
+{{ $frontmatter.title }}
+```
+
+## title
+
+- 型: `string`
+
+ページのタイトルです。[config.title](./site-config#title) と同じ意味で、サイトレベルの設定を上書きします。
+
+```yaml
+---
+title: VitePress
+---
+```
+
+## titleTemplate
+
+- 型: `string | boolean`
+
+タイトルのサフィックスです。[config.titleTemplate](./site-config#titletemplate) と同じ意味で、サイトレベルの設定を上書きします。
+
+```yaml
+---
+title: VitePress
+titleTemplate: Vite & Vue powered static site generator
+---
+```
+
+## description
+
+- 型: `string`
+
+ページの説明です。[config.description](./site-config#description) と同じ意味で、サイトレベルの設定を上書きします。
+
+```yaml
+---
+description: VitePress
+---
+```
+
+## head
+
+- 型: `HeadConfig[]`
+
+現在のページに追加で挿入する `` タグを指定します。サイトレベル設定で挿入されたタグの後に追加されます。
+
+```yaml
+---
+head:
+ - - meta
+ - name: description
+ content: hello
+ - - meta
+ - name: keywords
+ content: super duper SEO
+---
+```
+
+```ts
+type HeadConfig =
+ | [string, Record]
+ | [string, Record, string]
+```
+
+## デフォルトテーマ専用 {#default-theme-only}
+
+以下のフロントマター項目は、デフォルトテーマ使用時にのみ適用されます。
+
+### layout
+
+- 型: `doc | home | page`
+- 既定値: `doc`
+
+ページのレイアウトを決めます。
+
+- `doc` — Markdown コンテンツにドキュメント向けの既定スタイルを適用します。
+- `home` — 「ホームページ」用の特別なレイアウト。`hero` や `features` を追加指定して、ランディングページを素早く構築できます。
+- `page` — `doc` と似ていますが、コンテンツにスタイルを適用しません。完全にカスタムなページを作りたい場合に便利です。
+
+```yaml
+---
+layout: doc
+---
+```
+
+### hero
+
+`layout: home` のときのヒーローセクションの内容を定義します。詳しくは [デフォルトテーマ: ホームページ](./default-theme-home-page) を参照。
+
+### features
+
+`layout: home` のときのフィーチャーセクションに表示する項目を定義します。詳しくは [デフォルトテーマ: ホームページ](./default-theme-home-page) を参照。
+
+### navbar
+
+- 型: `boolean`
+- 既定値: `true`
+
+[ナビゲーションバー](./default-theme-nav) を表示するかどうか。
+
+```yaml
+---
+navbar: false
+---
+```
+
+### sidebar
+
+- 型: `boolean`
+- 既定値: `true`
+
+[サイドバー](./default-theme-sidebar) を表示するかどうか。
+
+```yaml
+---
+sidebar: false
+---
+```
+
+### aside
+
+- 型: `boolean | 'left'`
+- 既定値: `true`
+
+`doc` レイアウトでの aside コンポーネントの位置を定義します。
+
+この値を `false` にすると aside コンテナを表示しません。\
+`true` にすると右側に表示します。\
+`'left'` にすると左側に表示します。
+
+```yaml
+---
+aside: false
+---
+```
+
+### outline
+
+- 型: `number | [number, number] | 'deep' | false`
+- 既定値: `2`
+
+ページのアウトラインに表示する見出しレベルです。[config.themeConfig.outline.level](./default-theme-config#outline) と同じ意味で、サイトレベルの設定を上書きします。
+
+```yaml
+---
+outline: [2, 4]
+---
+```
+
+### lastUpdated
+
+- 型: `boolean | Date`
+- 既定値: `true`
+
+現在のページのフッターに[最終更新](./default-theme-last-updated)を表示するかどうか。日時を指定した場合は、その日時が Git の最終更新時刻の代わりに表示されます。
+
+```yaml
+---
+lastUpdated: false
+---
+```
+
+### editLink
+
+- 型: `boolean`
+- 既定値: `true`
+
+現在のページのフッターに[編集リンク](./default-theme-edit-link)を表示するかどうか。
+
+```yaml
+---
+editLink: false
+---
+```
+
+### footer
+
+- 型: `boolean`
+- 既定値: `true`
+
+[フッター](./default-theme-footer) を表示するかどうか。
+
+```yaml
+---
+footer: false
+---
+```
+
+### pageClass
+
+- 型: `string`
+
+特定のページに追加のクラス名を付与します。
+
+```yaml
+---
+pageClass: custom-page-class
+---
+```
+
+その後、`.vitepress/theme/custom.css` でこのページ専用のスタイルを記述できます。
+
+```css
+.custom-page-class {
+ /* ページ固有のスタイル */
+}
+```
+
+### isHome
+
+- 型: `boolean`
+
+デフォルトテーマは通常、`frontmatter.layout === 'home'` のチェックに基づいてホームページかどうかを判断します。\
+カスタムレイアウトでホームページ用の要素を強制的に表示したい場合に便利です。
+
+```yaml
+---
+isHome: true
+---
+```
diff --git a/docs/ja/reference/runtime-api.md b/docs/ja/reference/runtime-api.md
new file mode 100644
index 000000000..afcad68d8
--- /dev/null
+++ b/docs/ja/reference/runtime-api.md
@@ -0,0 +1,173 @@
+# ランタイム API {#runtime-api}
+
+VitePress には、アプリのデータへアクセスするための組み込み API がいくつか用意されています。さらに、グローバルに使用できる組み込みコンポーネントも提供されています。
+
+ヘルパーメソッドは `vitepress` からグローバルインポートでき、主にカスタムテーマの Vue コンポーネントで使われます。Markdown ファイルは Vue の [Single File Component](https://vuejs.org/guide/scaling-up/sfc.html) にコンパイルされるため、`.md` ファイル内でも使用できます。
+
+`use*` で始まるメソッドは [Vue 3 Composition API](https://vuejs.org/guide/introduction.html#composition-api) の関数(Composable)で、`setup()` または `
+
+
+ {{ theme.footer.copyright }}
+
+```
+
+## `useRoute`
+
+現在のルートオブジェクトを返します。型は次のとおりです。
+
+```ts
+interface Route {
+ path: string
+ data: PageData
+ component: Component | null
+}
+```
+
+## `useRouter`
+
+VitePress のルーターインスタンスを返し、プログラムで別ページへ遷移できます。
+
+```ts
+interface Router {
+ /**
+ * 現在のルート
+ */
+ route: Route
+ /**
+ * 新しい URL へ遷移
+ */
+ go: (to?: string) => Promise
+ /**
+ * ルートが変わる前に呼ばれる。`false` を返すと遷移をキャンセル
+ */
+ onBeforeRouteChange?: (to: string) => Awaitable
+ /**
+ * ページコンポーネントが読み込まれる前(履歴が更新された後)に呼ばれる。
+ * `false` を返すと遷移をキャンセル
+ */
+ onBeforePageLoad?: (to: string) => Awaitable
+ /**
+ * ページコンポーネントが読み込まれた後(更新前)に呼ばれる
+ */
+ onAfterPageLoad?: (to: string) => Awaitable
+ /**
+ * ルートが変わった後に呼ばれる
+ */
+ onAfterRouteChange?: (to: string) => Awaitable
+}
+```
+
+## `withBase`
+
+- **型**: `(path: string) => string`
+
+設定された [`base`](./site-config#base) を指定の URL パスに付与します。[Base URL](../guide/asset-handling#base-url) も参照。
+
+## ``
+
+レンダリング済みの Markdown コンテンツを表示します。[独自テーマの作成時](../guide/custom-theme) に便利です。
+
+```vue
+
+ Custom Layout!
+
+
+```
+
+## ``
+
+スロット内容をクライアント側でのみレンダリングします。
+
+VitePress アプリは静的ビルド時に Node.js 上でサーバーレンダリングされるため、Vue の使用はユニバーサルコードの要件に従う必要があります。要するに、ブラウザ/DOM API へのアクセスは beforeMount / mounted フック内に限定してください。
+
+SSR 非対応(例: カスタムディレクティブを含む)なコンポーネントを使用・デモする場合は、`ClientOnly` でラップできます。
+
+```vue-html
+
+
+
+```
+
+- 関連: [SSR 互換性](../guide/ssr-compat)
+
+## `$frontmatter`
+
+Vue の式内で現在ページの [フロントマター](../guide/frontmatter) に直接アクセスします。
+
+```md
+---
+title: Hello
+---
+
+# {{ $frontmatter.title }}
+```
+
+## `$params`
+
+Vue の式内で現在ページの [動的ルートのパラメータ](../guide/routing#dynamic-routes) に直接アクセスします。
+
+```md
+- package name: {{ $params.pkg }}
+- version: {{ $params.version }}
+```
diff --git a/docs/ja/reference/site-config.md b/docs/ja/reference/site-config.md
new file mode 100644
index 000000000..acea9ca7f
--- /dev/null
+++ b/docs/ja/reference/site-config.md
@@ -0,0 +1,722 @@
+---
+outline: deep
+---
+
+# サイト設定 {#site-config}
+
+サイト設定では、サイト全体のグローバル設定を定義します。アプリ設定オプションは、使用するテーマに関係なく、すべての VitePress サイトに適用されます。たとえば、ベースディレクトリやサイトのタイトルなどです。
+
+## 概要 {#overview}
+
+### 設定ファイルの解決 {#config-resolution}
+
+設定ファイルは常に `/.vitepress/config.[ext]` から解決されます。`` は VitePress の[プロジェクトルート](../guide/routing#root-and-source-directory)で、`[ext]` にはサポートされる拡張子が入ります。TypeScript はそのまま使えます。サポートされる拡張子は `.js`、`.ts`、`.mjs`、`.mts` です。
+
+設定ファイルでは ES Modules 構文の使用を推奨します。設定オブジェクトをデフォルトエクスポートしてください。
+
+```ts
+export default {
+ // アプリレベルの設定
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+ ...
+}
+```
+
+::: details 動的(非同期)設定
+
+設定を動的に生成する必要がある場合は、関数をデフォルトエクスポートすることもできます。例:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default async () => {
+ const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
+
+ return defineConfig({
+ // アプリレベル設定
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+
+ // テーマレベル設定
+ themeConfig: {
+ sidebar: [
+ ...posts.map((post) => ({
+ text: post.name,
+ link: `/posts/${post.name}`
+ }))
+ ]
+ }
+ })
+}
+```
+
+トップレベル `await` も使用できます。例:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
+
+export default defineConfig({
+ // アプリレベル設定
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+
+ // テーマレベル設定
+ themeConfig: {
+ sidebar: [
+ ...posts.map((post) => ({
+ text: post.name,
+ link: `/posts/${post.name}`
+ }))
+ ]
+ }
+})
+```
+
+:::
+
+### 設定のインテリセンス {#config-intellisense}
+
+`defineConfig` ヘルパーを使うと、TypeScript による補完が効きます。対応 IDE であれば、JavaScript と TypeScript のどちらでも動作します。
+
+```js
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ // ...
+})
+```
+
+### 型付きのテーマ設定 {#typed-theme-config}
+
+デフォルトでは、`defineConfig` はデフォルトテーマのテーマ設定型を想定します。
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ // 型は `DefaultTheme.Config`
+ }
+})
+```
+
+カスタムテーマを使用しており、そのテーマ設定に型チェックを効かせたい場合は、代わりに `defineConfigWithTheme` を使い、ジェネリクスでカスタムテーマの設定型を渡してください。
+
+```ts
+import { defineConfigWithTheme } from 'vitepress'
+import type { ThemeConfig } from 'your-theme'
+
+export default defineConfigWithTheme({
+ themeConfig: {
+ // 型は `ThemeConfig`
+ }
+})
+```
+
+### Vite・Vue・Markdown の設定 {#vite-vue-markdown-config}
+
+- **Vite**
+
+ Vite の設定は VitePress 設定の [vite](#vite) オプションで行えます。別途 Vite の設定ファイルを作る必要はありません。
+
+- **Vue**
+
+ VitePress には公式の Vue プラグイン([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))が同梱されています。オプションは VitePress 設定の [vue](#vue) から指定できます。
+
+- **Markdown**
+
+ 既定の [Markdown-It](https://github.com/markdown-it/markdown-it) インスタンスは、VitePress 設定の [markdown](#markdown) オプションでカスタマイズできます。
+
+## サイトメタデータ {#site-metadata}
+
+### title
+
+- 型: `string`
+- 既定値: `VitePress`
+- ページ単位での上書き: [frontmatter](./frontmatter-config#title)
+
+サイトのタイトル。デフォルトテーマではナビバーに表示されます。
+
+[`titleTemplate`](#titletemplate) を定義していない場合、個々のページタイトルの既定のサフィックスとしても使われます。各ページの最終タイトルは、そのページの最初の `` 見出しのテキストに、グローバルの `title` をサフィックスとして結合したものになります。次の設定とページ内容の例:
+
+```ts
+export default {
+ title: 'My Awesome Site'
+}
+```
+
+```md
+# Hello
+```
+
+このページのタイトルは `Hello | My Awesome Site` になります。
+
+### titleTemplate
+
+- 型: `string | boolean`
+- ページ単位での上書き: [frontmatter](./frontmatter-config#titletemplate)
+
+各ページタイトルのサフィックス、またはタイトル全体のカスタマイズができます。例:
+
+```ts
+export default {
+ title: 'My Awesome Site',
+ titleTemplate: 'Custom Suffix'
+}
+```
+
+```md
+# Hello
+```
+
+このページのタイトルは `Hello | Custom Suffix` になります。
+
+タイトルの描画方法を完全にカスタマイズするには、`titleTemplate` 内で `:title` シンボルを使います。
+
+```ts
+export default {
+ titleTemplate: ':title - Custom Suffix'
+}
+```
+
+ここで `:title` はページ先頭の `` から推論されたテキストに置き換えられます。先ほどの例では `Hello - Custom Suffix` になります。
+
+`false` を設定するとタイトルのサフィックスを無効にできます。
+
+### description
+
+- 型: `string`
+- 既定値: `A VitePress site`
+- ページ単位での上書き: [frontmatter](./frontmatter-config#description)
+
+サイトの説明。ページの HTML に `` タグとして出力されます。
+
+```ts
+export default {
+ description: 'A VitePress site'
+}
+```
+
+### head
+
+- 型: `HeadConfig[]`
+- 既定値: `[]`
+- ページ単位での追加: [frontmatter](./frontmatter-config#head)
+
+ページ HTML の `` に追加で出力する要素。ユーザーが追加したタグは、VitePress のタグの後、`` の直前にレンダリングされます。
+
+```ts
+type HeadConfig =
+ | [string, Record]
+ | [string, Record, string]
+```
+
+#### 例: favicon を追加 {#example-adding-a-favicon}
+
+```ts
+export default {
+ head: [['link', { rel: 'icon', href: '/favicon.ico' }]]
+} // favicon.ico は public に配置。base を設定している場合は /base/favicon.ico を利用
+
+/* 出力結果:
+
+*/
+```
+
+#### 例: Google Fonts を追加 {#example-adding-google-fonts}
+
+```ts
+export default {
+ head: [
+ [
+ 'link',
+ { rel: 'preconnect', href: 'https://fonts.googleapis.com' }
+ ],
+ [
+ 'link',
+ { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }
+ ],
+ [
+ 'link',
+ { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' }
+ ]
+ ]
+}
+
+/* 出力結果:
+
+
+
+*/
+```
+
+#### 例: Service Worker を登録 {#example-registering-a-service-worker}
+
+```ts
+export default {
+ head: [
+ [
+ 'script',
+ { id: 'register-sw' },
+ `;(() => {
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('/sw.js')
+ }
+ })()`
+ ]
+ ]
+}
+
+/* 出力結果:
+
+*/
+```
+
+#### 例: Google Analytics を使用 {#example-using-google-analytics}
+
+```ts
+export default {
+ head: [
+ [
+ 'script',
+ { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' }
+ ],
+ [
+ 'script',
+ {},
+ `window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+ gtag('js', new Date());
+ gtag('config', 'TAG_ID');`
+ ]
+ ]
+}
+
+/* 出力結果:
+
+
+*/
+```
+
+### lang
+
+- 型: `string`
+- 既定値: `en-US`
+
+サイトの言語属性。ページ HTML の `` として出力されます。
+
+```ts
+export default {
+ lang: 'en-US'
+}
+```
+
+### base
+
+- 型: `string`
+- 既定値: `/`
+
+サイトをデプロイするベース URL。GitHub Pages などサブパス配下にデプロイする場合に設定が必要です。たとえば `https://foo.github.io/bar/` にデプロイする場合、`base` は `'/bar/'` にします。先頭と末尾は必ずスラッシュにしてください。
+
+`/` で始まる他のオプション内の URL には、この `base` が自動的に付与されます。1 回設定すれば十分です。
+
+```ts
+export default {
+ base: '/base/'
+}
+```
+
+## ルーティング {#routing}
+
+### cleanUrls
+
+- 型: `boolean`
+- 既定値: `false`
+
+`true` にすると、URL の末尾の `.html` を削除します。あわせて [クリーン URL の生成](../guide/routing#generating-clean-url) も参照してください。
+
+::: warning サーバ設定が必要
+ホスティング環境によっては追加の設定が必要です。`/foo` へのアクセス時に **リダイレクトなしで** `/foo.html` を返せるサーバ設定が必要です。
+:::
+
+### rewrites
+
+- 型: `Record`
+
+ディレクトリと URL のカスタム対応を定義します。詳しくは [ルーティング: ルートのリライト](../guide/routing#route-rewrites) を参照。
+
+```ts
+export default {
+ rewrites: {
+ 'source/:page': 'destination/:page'
+ }
+}
+```
+
+## ビルド {#build}
+
+### srcDir
+
+- 型: `string`
+- 既定値: `.`
+
+Markdown ページを置くディレクトリ(プロジェクトルートからの相対パス)。[ルートとソースディレクトリ](../guide/routing#root-and-source-directory) も参照。
+
+```ts
+export default {
+ srcDir: './src'
+}
+```
+
+### srcExclude
+
+- 型: `string[]`
+- 既定値: `undefined`
+
+ソースとして除外したい Markdown ファイルにマッチする [glob パターン](https://github.com/mrmlnc/fast-glob#pattern-syntax)。
+
+```ts
+export default {
+ srcExclude: ['**/README.md', '**/TODO.md']
+}
+```
+
+### outDir
+
+- 型: `string`
+- 既定値: `./.vitepress/dist`
+
+ビルド出力先([プロジェクトルート](../guide/routing#root-and-source-directory) からの相対パス)。
+
+```ts
+export default {
+ outDir: '../public'
+}
+```
+
+### assetsDir
+
+- 型: `string`
+- 既定値: `assets`
+
+生成されるアセットを配置するサブディレクトリ名。パスは [`outDir`](#outdir) の内部で、相対解決されます。
+
+```ts
+export default {
+ assetsDir: 'static'
+}
+```
+
+### cacheDir
+
+- 型: `string`
+- 既定値: `./.vitepress/cache`
+
+キャッシュファイル用ディレクトリ([プロジェクトルート](../guide/routing#root-and-source-directory) からの相対パス)。参考: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)
+
+```ts
+export default {
+ cacheDir: './.vitepress/.vite'
+}
+```
+
+### ignoreDeadLinks
+
+- 型: `boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[]`
+- 既定値: `false`
+
+`true` にすると、デッドリンクがあってもビルド失敗にしません。
+
+`'localhostLinks'` にすると、`localhost` へのリンクはチェック対象外にしつつ、その他のデッドリンクではビルドを失敗させます。
+
+```ts
+export default {
+ ignoreDeadLinks: true
+}
+```
+
+正確な URL 文字列、正規表現、カスタムフィルタ関数の配列として指定することもできます。
+
+```ts
+export default {
+ ignoreDeadLinks: [
+ // 正確に "/playground" を無視
+ '/playground',
+ // すべての localhost リンクを無視
+ /^https?:\/\/localhost/,
+ // パスに "/repl/" を含むリンクを無視
+ /\/repl\//,
+ // カスタム関数: "ignore" を含むリンクを無視
+ (url) => {
+ return url.toLowerCase().includes('ignore')
+ }
+ ]
+}
+```
+
+### metaChunk
+
+- 型: `boolean`
+- 既定値: `false`
+
+`true` にすると、各ページのメタデータを初期 HTML にインラインせず、別の JavaScript チャンクに抽出します。これにより各ページの HTML ペイロードが小さくなり、メタデータをキャッシュ可能にすることで、多数のページがあるサイトでサーバ帯域を削減できます。
+
+### mpa
+
+- 型: `boolean`
+- 既定値: `false`
+
+`true` にすると、本番アプリは [MPA モード](../guide/mpa-mode) でビルドされます。MPA モードは既定でクライアント JavaScript を 0kb で配信する代わりに、クライアントサイドのナビゲーションを無効にし、相互作用には明示的な opt-in が必要です。
+
+## テーマ関連 {#theming}
+
+### appearance
+
+- 型: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions`
+- 既定値: `true`
+
+ダークモードを有効にするか(`` に `.dark` クラスを付与)。
+
+- `true` の場合、ユーザーの環境設定に従います。
+- `dark` の場合、ユーザーが切り替えない限りダークを既定にします。
+- `false` の場合、ユーザーはテーマを切り替えできません。
+- `'force-dark'` の場合、常にダークで固定(切替不可)。
+- `'force-auto'` の場合、常にユーザーの環境設定に従い(切替不可)。
+
+このオプションは、ローカルストレージの `vitepress-theme-appearance` から設定を復元するインラインスクリプトを挿入します。これにより、ページ描画前に `.dark` クラスを適用してフリッカを防ぎます。
+
+`appearance.initialValue` は `'dark' | undefined` のみサポート。Ref や getter は使えません。
+
+### lastUpdated
+
+- 型: `boolean`
+- 既定値: `false`
+
+Git を使って各ページの最終更新時刻を取得します。タイムスタンプは各ページのデータに含まれ、[`useData`](./runtime-api#usedata) から参照できます。
+
+デフォルトテーマ使用時にこのオプションを有効にすると、各ページの最終更新時刻が表示されます。テキストは [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) でカスタマイズ可能です。
+
+## カスタマイズ {#customization}
+
+### markdown
+
+- 型: `MarkdownOption`
+
+Markdown パーサの設定。VitePress はパーサに [Markdown-it](https://github.com/markdown-it/markdown-it)、構文ハイライトに [Shiki](https://github.com/shikijs/shiki) を使用しています。必要に応じて Markdown 関連の各種オプションを指定できます。
+
+```js
+export default {
+ markdown: {...}
+}
+```
+
+利用可能なオプションは [型定義と JSDoc](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) を参照してください。
+
+### vite
+
+- 型: `import('vite').UserConfig`
+
+内部の Vite 開発サーバ/バンドラへ生の [Vite Config](https://vitejs.dev/config/) を渡します。
+
+```js
+export default {
+ vite: {
+ // Vite の設定
+ }
+}
+```
+
+### vue
+
+- 型: `import('@vitejs/plugin-vue').Options`
+
+内部の `@vitejs/plugin-vue` インスタンスへオプションをそのまま渡します。
+
+```js
+export default {
+ vue: {
+ // @vitejs/plugin-vue のオプション
+ }
+}
+```
+
+## ビルドフック {#build-hooks}
+
+VitePress のビルドフックを使うと、サイトに機能や振る舞いを追加できます。
+
+- サイトマップ
+- 検索インデックス
+- PWA
+- Teleport
+
+### buildEnd
+
+- 型: `(siteConfig: SiteConfig) => Awaitable`
+
+`buildEnd` はビルド CLI フックです。ビルド(SSG)が完了した後、VitePress CLI プロセスが終了する前に実行されます。
+
+```ts
+export default {
+ async buildEnd(siteConfig) {
+ // ...
+ }
+}
+```
+
+### postRender
+
+- 型: `(context: SSGContext) => Awaitable`
+
+`postRender` は SSG のレンダリング完了時に呼ばれるビルドフックです。SSG 中の teleport コンテンツの処理に利用できます。
+
+```ts
+export default {
+ async postRender(context) {
+ // ...
+ }
+}
+```
+
+```ts
+interface SSGContext {
+ content: string
+ teleports?: Record
+ [key: string]: any
+}
+```
+
+### transformHead
+
+- 型: `(context: TransformContext) => Awaitable`
+
+`transformHead` は、各ページを生成する前に head を変換するためのビルドフックです。設定ファイルでは静的に追加できない head 要素を追加できます。追加分のみ返せば、既存のものと自動でマージされます。
+
+::: warning
+`context` 内の値は変更しないでください。
+:::
+
+```ts
+export default {
+ async transformHead(context) {
+ // ...
+ }
+}
+```
+
+```ts
+interface TransformContext {
+ page: string // 例: index.md(srcDir からの相対)
+ assets: string[] // 解決済みの公開 URL(非 js/css アセット)
+ siteConfig: SiteConfig
+ siteData: SiteData
+ pageData: PageData
+ title: string
+ description: string
+ head: HeadConfig[]
+ content: string
+}
+```
+
+このフックは静的サイト生成時のみ呼ばれ、開発中には呼ばれません。開発中に動的な head 要素を追加したい場合は、代わりに [`transformPageData`](#transformpagedata) を使用できます。
+
+```ts
+export default {
+ transformPageData(pageData) {
+ pageData.frontmatter.head ??= []
+ pageData.frontmatter.head.push([
+ 'meta',
+ {
+ name: 'og:title',
+ content:
+ pageData.frontmatter.layout === 'home'
+ ? `VitePress`
+ : `${pageData.title} | VitePress`
+ }
+ ])
+ }
+}
+```
+
+#### 例: 正規 URL の `` を追加 {#example-adding-a-canonical-url-link}
+
+```ts
+export default {
+ transformPageData(pageData) {
+ const canonicalUrl = `https://example.com/${pageData.relativePath}`
+ .replace(/index\.md$/, '')
+ .replace(/\.md$/, '.html')
+
+ pageData.frontmatter.head ??= []
+ pageData.frontmatter.head.push([
+ 'link',
+ { rel: 'canonical', href: canonicalUrl }
+ ])
+ }
+}
+```
+
+### transformHtml
+
+- 型: `(code: string, id: string, context: TransformContext) => Awaitable`
+
+`transformHtml` は、各ページの内容をディスクへ保存する前に変換するためのビルドフックです。
+
+::: warning
+`context` 内の値は変更しないでください。また、HTML を変更すると実行時のハイドレーション問題を引き起こす可能性があります。
+:::
+
+```ts
+export default {
+ async transformHtml(code, id, context) {
+ // ...
+ }
+}
+```
+
+### transformPageData
+
+- 型: `(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>`
+
+`transformPageData` は各ページの `pageData` を変換するためのフックです。`pageData` を直接変更するか、変更値を返してマージさせることができます。
+
+::: warning
+`context` 内の値は変更しないでください。ネットワークリクエストや重い計算(画像生成など)を行うと開発サーバのパフォーマンスに影響します。`process.env.NODE_ENV === 'production'` を用いた条件分岐を検討してください。
+:::
+
+```ts
+export default {
+ async transformPageData(pageData, { siteConfig }) {
+ pageData.contributors = await getPageContributors(pageData.relativePath)
+ }
+
+ // あるいはマージ用の値を返す
+ async transformPageData(pageData, { siteConfig }) {
+ return {
+ contributors: await getPageContributors(pageData.relativePath)
+ }
+ }
+}
+```
+
+```ts
+interface TransformPageContext {
+ siteConfig: SiteConfig
+}
+```
diff --git a/docs/ko/config.ts b/docs/ko/config.ts
index 78b5c3f3d..4a076036c 100644
--- a/docs/ko/config.ts
+++ b/docs/ko/config.ts
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineAdditionalConfig({
- lang: 'ko-KR',
description: 'Vite 및 Vue 기반 정적 사이트 생성기.',
themeConfig: {
@@ -74,6 +73,10 @@ function nav(): DefaultTheme.NavItem[] {
{
text: pkg.version,
items: [
+ {
+ text: '1.6.4',
+ link: 'https://vuejs.github.io/vitepress/v1/ko/'
+ },
{
text: '변경 로그',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
@@ -220,7 +223,6 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial {
return {
- placeholder: '문서 검색',
translations: {
button: {
buttonText: '검색',
@@ -228,34 +230,136 @@ function searchOptions(): Partial {
},
modal: {
searchBox: {
- resetButtonTitle: '검색 지우기',
- resetButtonAriaLabel: '검색 지우기',
- cancelButtonText: '취소',
- cancelButtonAriaLabel: '취소'
+ clearButtonTitle: '지우기',
+ clearButtonAriaLabel: '검색어 지우기',
+ closeButtonText: '닫기',
+ closeButtonAriaLabel: '닫기',
+ placeholderText: '문서를 검색하거나 Ask AI에 질문',
+ placeholderTextAskAi: '다른 질문하기...',
+ placeholderTextAskAiStreaming: '답변 중...',
+ searchInputLabel: '검색',
+ backToKeywordSearchButtonText: '키워드 검색으로 돌아가기',
+ backToKeywordSearchButtonAriaLabel: '키워드 검색으로 돌아가기',
+ newConversationPlaceholder: '질문하기',
+ conversationHistoryTitle: '내 대화 기록',
+ startNewConversationText: '새 대화 시작',
+ viewConversationHistoryText: '대화 기록',
+ threadDepthErrorPlaceholder: '대화 한도에 도달했습니다'
},
- startScreen: {
- recentSearchesTitle: '검색 기록',
- noRecentSearchesText: '최근 검색 없음',
- saveRecentSearchButtonTitle: '검색 기록에 저장',
- removeRecentSearchButtonTitle: '검색 기록에서 삭제',
- favoriteSearchesTitle: '즐겨찾기',
- removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제'
- },
- errorScreen: {
- titleText: '결과를 가져올 수 없습니다',
- helpText: '네트워크 연결을 확인하세요'
+ newConversation: {
+ newConversationTitle: '오늘 무엇을 도와드릴까요?',
+ newConversationDescription:
+ '문서를 검색해 설정 가이드, 기능 설명, 문제 해결 팁을 빠르게 찾아드립니다.'
},
footer: {
selectText: '선택',
- navigateText: '탐색',
+ submitQuestionText: '질문 제출',
+ selectKeyAriaLabel: 'Enter 키',
+ navigateText: '이동',
+ navigateUpKeyAriaLabel: '위 화살표',
+ navigateDownKeyAriaLabel: '아래 화살표',
closeText: '닫기',
- searchByText: '검색 기준'
+ backToSearchText: '검색으로 돌아가기',
+ closeKeyAriaLabel: 'Escape 키',
+ poweredByText: '제공'
+ },
+ errorScreen: {
+ titleText: '결과를 불러올 수 없습니다',
+ helpText: '네트워크 연결을 확인해 주세요.'
+ },
+ startScreen: {
+ recentSearchesTitle: '최근',
+ noRecentSearchesText: '최근 검색이 없습니다',
+ saveRecentSearchButtonTitle: '이 검색 저장',
+ removeRecentSearchButtonTitle: '기록에서 이 검색 제거',
+ favoriteSearchesTitle: '즐겨찾기',
+ removeFavoriteSearchButtonTitle: '즐겨찾기에서 이 검색 제거',
+ recentConversationsTitle: '최근 대화',
+ removeRecentConversationButtonTitle: '기록에서 이 대화 제거'
},
noResultsScreen: {
- noResultsText: '결과를 찾을 수 없습니다',
- suggestedQueryText: '새로운 검색을 시도할 수 있습니다',
- reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?',
- reportMissingResultsLinkText: '피드백 보내기 클릭'
+ noResultsText: '다음에 대한 결과를 찾을 수 없습니다',
+ suggestedQueryText: '다음을 검색해 보세요',
+ reportMissingResultsText: '이 검색은 결과가 있어야 하나요?',
+ reportMissingResultsLinkText: '알려주세요.'
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'AI에게 묻기: ',
+ noResultsAskAiPlaceholder: '문서에서 찾지 못했나요? Ask AI에 문의: '
+ },
+ askAiScreen: {
+ disclaimerText:
+ '답변은 AI가 생성하며 오류가 있을 수 있습니다. 확인해 주세요.',
+ relatedSourcesText: '관련 출처',
+ thinkingText: '생각 중...',
+ copyButtonText: '복사',
+ copyButtonCopiedText: '복사됨!',
+ copyButtonTitle: '복사',
+ likeButtonTitle: '좋아요',
+ dislikeButtonTitle: '싫어요',
+ thanksForFeedbackText: '피드백 감사합니다!',
+ preToolCallText: '검색 중...',
+ duringToolCallText: '검색 중...',
+ afterToolCallText: '검색함',
+ stoppedStreamingText: '이 응답을 중지했습니다',
+ errorTitleText: '채팅 오류',
+ threadDepthExceededMessage:
+ '정확성을 유지하기 위해 이 대화는 종료되었습니다.',
+ startNewConversationButtonText: '새 대화 시작'
+ }
+ }
+ },
+ askAi: {
+ sidePanel: {
+ button: {
+ translations: {
+ buttonText: 'AI에게 묻기',
+ buttonAriaLabel: 'AI에게 묻기'
+ }
+ },
+ panel: {
+ translations: {
+ header: {
+ title: 'AI에게 묻기',
+ conversationHistoryTitle: '내 대화 기록',
+ newConversationText: '새 대화 시작',
+ viewConversationHistoryText: '대화 기록'
+ },
+ promptForm: {
+ promptPlaceholderText: '질문하기',
+ promptAnsweringText: '답변 중...',
+ promptAskAnotherQuestionText: '다른 질문하기',
+ promptDisclaimerText:
+ '답변은 AI가 생성하며 오류가 있을 수 있습니다.',
+ promptLabelText: 'Enter로 전송, Shift+Enter로 줄바꿈.',
+ promptAriaLabelText: '프롬프트 입력'
+ },
+ conversationScreen: {
+ preToolCallText: '검색 중...',
+ searchingText: '검색 중...',
+ toolCallResultText: '검색함',
+ conversationDisclaimer:
+ '답변은 AI가 생성하며 오류가 있을 수 있습니다. 확인해 주세요.',
+ reasoningText: '추론 중...',
+ thinkingText: '생각 중...',
+ relatedSourcesText: '관련 출처',
+ stoppedStreamingText: '이 응답을 중지했습니다',
+ copyButtonText: '복사',
+ copyButtonCopiedText: '복사됨!',
+ likeButtonTitle: '좋아요',
+ dislikeButtonTitle: '싫어요',
+ thanksForFeedbackText: '피드백 감사합니다!',
+ errorTitleText: '채팅 오류'
+ },
+ newConversationScreen: {
+ titleText: '오늘 무엇을 도와드릴까요?',
+ introductionText:
+ '문서를 검색해 설정 가이드, 기능 설명, 문제 해결 팁을 빠르게 찾아드립니다.'
+ },
+ logo: {
+ poweredByText: '제공'
+ }
+ }
}
}
}
diff --git a/docs/ko/guide/deploy.md b/docs/ko/guide/deploy.md
index 7a57a8ad1..d2e622284 100644
--- a/docs/ko/guide/deploy.md
+++ b/docs/ko/guide/deploy.md
@@ -105,13 +105,13 @@ Cache-Control: max-age=31536000,immutable
## 플랫폼 가이드 {#platform-guides}
-### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
+### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
새 프로젝트를 설정하고 대시보드를 사용하여 다음 설정을 변경하세요:
- **빌드 명령어:** `npm run docs:build`
- **출력 디렉토리:** `docs/.vitepress/dist`
-- **노드 버전:** `18` (또는 그 이상)
+- **노드 버전:** `20` (또는 그 이상)
::: warning
HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는 Vue에 의미가 있는 주석을 출력에서 제거할 것입니다. 제거되면 하이드레이션 불일치 오류가 발생할 수 있습니다.
@@ -152,17 +152,17 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0 # lastUpdated가 활성화되지 않은 경우 필요하지 않음
- # - uses: pnpm/action-setup@v3 # pnpm을 사용하는 경우 주석 해제
+ # - uses: pnpm/action-setup@v4 # pnpm을 사용하는 경우 주석 해제
# with:
# version: 9
# - uses: oven-sh/setup-bun@v1 # Bun을 사용하는 경우 주석 해제
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
- node-version: 22
+ node-version: 24
cache: npm # 또는 pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v4
@@ -220,7 +220,7 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
- main
```
-### Azure 정적 Web 앱 {#azure-static-web-apps}
+### Azure
1. [공식 문서](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)를 따르세요.
@@ -230,7 +230,11 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
-### Firebase {#firebase}
+### CloudRay
+
+[CloudRay](https://cloudray.io/)로 VitePress 프로젝트를 배포하려면 이 [지침](https://cloudray.io/articles/how-to-deploy-vitepress-site)을 따르세요.
+
+### Firebase
1. 프로젝트 루트에 `firebase.json`과 `.firebaserc`를 생성하세요:
@@ -261,14 +265,6 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
firebase deploy
```
-### Surge
-
-1. `npm run docs:build`를 실행한 후, 배포하기 위해 이 명령어를 실행하세요:
-
- ```sh
- npx surge docs/.vitepress/dist
- ```
-
### Heroku
1. [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static)에 제공된 문서와 가이드를 따르세요.
@@ -281,11 +277,11 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
}
```
-### Edgio
+### Hostinger
-[Edgio에 VitePress 앱 생성 및 배포하기](https://docs.edg.io/guides/vitepress)를 참고하세요.
+[Hostinger](https://www.hostinger.com/web-apps-hosting)로 VitePress 프로젝트를 배포하려면 이 [지침](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/)을 따르세요. 빌드 설정을 구성할 때 프레임워크로 VitePress를 선택하고 루트 디렉터리를 `./docs`로 조정하세요.
-### Kinsta 정적 사이트 호스팅 {#kinsta-static-site-hosting}
+### Kinsta
[VitePress](https://kinsta.com/static-site-hosting/) 웹사이트를 [Kinsta](https://kinsta.com/static-site-hosting/)에 배포하려면 이 [지침](https://kinsta.com/docs/vitepress-static-site-example/)을 따르세요.
@@ -293,6 +289,14 @@ HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는
[VitePress](https://stormkit.io) 프로젝트를 [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 압축, VitePress 사이트의 정적 파일을 적절한 캐싱 헤더와 함께 제공하는 규칙 및 `cleanUrls: true`를 처리하는 규칙을 포함합니다.
diff --git a/docs/ko/guide/extending-default-theme.md b/docs/ko/guide/extending-default-theme.md
index 0207e0494..b8b795e6f 100644
--- a/docs/ko/guide/extending-default-theme.md
+++ b/docs/ko/guide/extending-default-theme.md
@@ -252,6 +252,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
{
duration: 300,
easing: 'ease-in',
+ fill: 'forwards',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
diff --git a/docs/ko/guide/getting-started.md b/docs/ko/guide/getting-started.md
index ac7e7ca61..632e90788 100644
--- a/docs/ko/guide/getting-started.md
+++ b/docs/ko/guide/getting-started.md
@@ -19,39 +19,19 @@ VitePress는 단독으로 사용하거나 기존 프로젝트에 설치할 수
::: code-group
```sh [npm]
-$ npm add -D vitepress
+$ npm add -D vitepress@next
```
```sh [pnpm]
-$ pnpm add -D vitepress
+$ pnpm add -D vitepress@next
```
```sh [yarn]
-$ yarn add -D vitepress
-```
-
-```sh [yarn (pnp)]
-$ yarn add -D vitepress vue
+$ yarn add -D vitepress@next vue
```
```sh [bun]
-$ bun add -D vitepress
-```
-
-:::
-
-::: details "missing peer deps" 경고가 표시되나요?
-PNPM을 사용하는 경우 `@docsearch/js`에 대한 "missing peer deps" 경고가 표시됩니다. 이는 VitePress가 작동하는 것을 방해하지 않습니다. 이 경고를 억제하려면 `package.json`에 다음을 추가합니다:
-
-```json
-"pnpm": {
- "peerDependencyRules": {
- "ignoreMissing": [
- "@algolia/client-search",
- "search-insights"
- ]
- }
-}
+$ bun add -D vitepress@next
```
:::
diff --git a/docs/ko/guide/markdown.md b/docs/ko/guide/markdown.md
index 5f03bbf6d..4584d1bda 100644
--- a/docs/ko/guide/markdown.md
+++ b/docs/ko/guide/markdown.md
@@ -255,11 +255,11 @@ export default defineConfig({
}
```
- 이것은 기본적으로 [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector)를 사용합니다. 다음과 같이 옵션을 전달할 수 있습니다:
+ 다음과 같이 옵션을 전달할 수 있습니다:
```js
postcssIsolateStyles({
- includeFiles: [/vp-doc\.css/] // 기본값은 /base\.css/
+ includeFiles: [/custom\.css/] // 기본값은 [/vp-doc\.css/, /base\.css/]
})
```
@@ -771,7 +771,7 @@ export default config
## Basics
-
+
```
**해당 파일** (`parts/basics.md`)
@@ -807,7 +807,7 @@ Can be created using `.foorc.json`.
## Basics
-
+
```
**해당 파일** (`parts/basics.md`)
@@ -843,8 +843,8 @@ Can be created using `.foorc.json`.
## Basics
-
-
+
+
```
**해당 파일** (`parts/basics.md`)
@@ -880,7 +880,7 @@ Can be created using `.foorc.json`.
선택 사항입니다. 활성화하려면 `markdown-it-mathjax3`를 설치하고 설정 파일에서 `markdown.math`를 `true`로 설정해야 합니다:
```sh
-npm add -D markdown-it-mathjax3
+npm add -D markdown-it-mathjax3@^4
```
```ts [.vitepress/config.ts]
diff --git a/docs/ko/guide/what-is-vitepress.md b/docs/ko/guide/what-is-vitepress.md
index 9ad43c451..d6c7d6307 100644
--- a/docs/ko/guide/what-is-vitepress.md
+++ b/docs/ko/guide/what-is-vitepress.md
@@ -12,7 +12,7 @@ VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해
- **문서화**
- VitePress는 기술 문서를 위해 설계된 기본 테마가 함께 제공됩니다. 지금 읽고 있는 이 페이지와 [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) 및 [다양한 프로젝트](https://www.vuetelescope.com/explore?framework.slug=vitepress) 문서는 모두 이 테마를 기반으로 합니다.
+ VitePress는 기술 문서를 위해 설계된 기본 테마가 함께 제공됩니다. 지금 읽고 있는 이 페이지와 [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) 및 [다양한 프로젝트](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code) 문서는 모두 이 테마를 기반으로 합니다.
[Vue.js 공식 문서](https://vuejs.org/)도 VitePress 기반으로 되어 있으며, 여러 번역본에 걸쳐 공유되는 커스텀 테마를 사용합니다.
diff --git a/docs/ko/index.md b/docs/ko/index.md
index ae7df4c8f..aa8be95b7 100644
--- a/docs/ko/index.md
+++ b/docs/ko/index.md
@@ -8,10 +8,10 @@ hero:
actions:
- theme: brand
text: VitePress란 무엇인가?
- link: /ko/guide/what-is-vitepress
+ link: ./guide/what-is-vitepress
- theme: alt
text: 빠른 시작
- link: /ko/guide/getting-started
+ link: ./guide/getting-started
- theme: alt
text: GitHub
link: https://github.com/vuejs/vitepress
diff --git a/docs/ko/reference/default-theme-config.md b/docs/ko/reference/default-theme-config.md
index b0df33617..66b2f4e01 100644
--- a/docs/ko/reference/default-theme-config.md
+++ b/docs/ko/reference/default-theme-config.md
@@ -89,7 +89,7 @@ type NavItem = NavItemWithLink | NavItemWithChildren
interface NavItemWithLink {
text: string
- link: string
+ link: string | ((payload: PageData) => string)
activeMatch?: string
target?: string
rel?: string
diff --git a/docs/ko/reference/default-theme-nav.md b/docs/ko/reference/default-theme-nav.md
index cdfdc7eff..433c2e074 100644
--- a/docs/ko/reference/default-theme-nav.md
+++ b/docs/ko/reference/default-theme-nav.md
@@ -55,6 +55,8 @@ export default {
`text`는 네비게이션 바에 표시되는 실제 텍스트이며, `link`는 텍스트를 클릭했을 때 이동할 링크입니다. 링크의 경로는 `.md` 접미사 없이 실제 파일 경로로 설정하며, 항상 `/`로 시작해야 합니다.
+`link`는 또한 [`PageData`](./runtime-api#usedata)를 인자로 받아 경로를 반환하는 함수가 될 수도 있습니다.
+
네비게이션 바 링크는 드롭다운 메뉴가 될 수 있습니다. 이를 위해 `link` 옵션에 `items` 키를 설정합니다.
```js
diff --git a/docs/ko/reference/default-theme-search.md b/docs/ko/reference/default-theme-search.md
index 69b633aa1..0ee68e365 100644
--- a/docs/ko/reference/default-theme-search.md
+++ b/docs/ko/reference/default-theme-search.md
@@ -39,7 +39,7 @@ export default defineConfig({
provider: 'local',
options: {
locales: {
- ko: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오.
+ ko: { // 기본 로케일을 번역하려면 `root`로 설정하세요
translations: {
button: {
buttonText: '검색',
@@ -47,17 +47,17 @@ export default defineConfig({
},
modal: {
displayDetails: '상세 목록 표시',
- resetButtonTitle: '검색 지우기',
+ resetButtonTitle: '검색 재설정',
backButtonTitle: '검색 닫기',
- noResultsText: '결과를 찾을 수 없습니다',
+ noResultsText: '결과가 없습니다',
footer: {
selectText: '선택',
- selectKeyAriaLabel: '선택하기',
- navigateText: '탐색',
- navigateUpKeyAriaLabel: '위로',
- navigateDownKeyAriaLabel: '아래로',
+ selectKeyAriaLabel: 'Enter',
+ navigateText: '이동',
+ navigateUpKeyAriaLabel: '위쪽 화살표',
+ navigateDownKeyAriaLabel: '아래쪽 화살표',
closeText: '닫기',
- closeKeyAriaLabel: 'esc'
+ closeKeyAriaLabel: 'Esc'
}
}
}
@@ -69,7 +69,7 @@ export default defineConfig({
})
```
-### MiniSearch 옵션 {#mini-search-options}
+### MiniSearch 옵션 {#minisearch-options}
MiniSearch를 다음과 같이 구성할 수 있습니다:
@@ -123,7 +123,7 @@ export default defineConfig({
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
- // return html string
+ // HTML 문자열을 반환
}
}
}
@@ -174,7 +174,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
}
}
@@ -208,6 +208,19 @@ export default defineConfig({
다국어 검색을 사용하려면 다음과 같이 구성해야 합니다:
+
+클릭하여 펼치기
+
+<<< @/snippets/algolia-i18n.ts
+
+
+
+자세한 내용은 [공식 Algolia 문서](https://docsearch.algolia.com/docs/api#translations)를 참고하세요. 빠르게 시작하려면 이 사이트에서 사용하는 번역을 [GitHub 저장소](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code)에서 복사할 수도 있습니다.
+
+### Algolia Ask AI 지원 {#ask-ai}
+
+**Ask AI** 기능을 사용하려면 `askAi` 옵션을 추가하세요:
+
```ts
import { defineConfig } from 'vitepress'
@@ -219,46 +232,51 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
- locales: {
- ko: {
- placeholder: '문서 검색',
- translations: {
- button: {
- buttonText: '검색',
- buttonAriaLabel: '검색'
- },
- modal: {
- searchBox: {
- resetButtonTitle: '검색 지우기',
- resetButtonAriaLabel: '검색 지우기',
- cancelButtonText: '취소',
- cancelButtonAriaLabel: '취소'
- },
- startScreen: {
- recentSearchesTitle: '검색 기록',
- noRecentSearchesText: '최근 검색 없음',
- saveRecentSearchButtonTitle: '검색 기록에 저장',
- removeRecentSearchButtonTitle: '검색 기록에서 삭제',
- favoriteSearchesTitle: '즐겨찾기',
- removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제'
- },
- errorScreen: {
- titleText: '결과를 가져올 수 없습니다',
- helpText: '네트워크 연결을 확인하세요'
- },
- footer: {
- selectText: '선택',
- navigateText: '탐색',
- closeText: '닫기',
- searchByText: '검색 기준'
- },
- noResultsScreen: {
- noResultsText: '결과를 찾을 수 없습니다',
- suggestedQueryText: '새로운 검색을 시도할 수 있습니다',
- reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?',
- reportMissingResultsLinkText: '피드백 보내기 클릭'
- }
- }
+ // askAi: "내-어시스턴트-ID"
+ // 또는
+ askAi: {
+ // 최소한 Algolia에서 받은 assistantId를 제공해야 합니다
+ assistantId: 'XXXYYY',
+ // 선택적 재정의 — 생략하면 상위 appId/apiKey/indexName 값이 재사용됩니다
+ // apiKey: '...',
+ // appId: '...',
+ // indexName: '...'
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning 참고
+Ask AI를 사용하지 않으려면 `askAi` 옵션을 생략하면 됩니다.
+:::
+
+### Ask AI 사이드 패널 {#ask-ai-side-panel}
+
+DocSearch v4.5+는 선택적 **Ask AI 사이드 패널**을 지원합니다. 활성화되면 기본적으로 **Ctrl/Cmd+I**로 열 수 있습니다. [사이드 패널 API 참조](https://docsearch.algolia.com/docs/sidepanel/api-reference)에 전체 옵션 목록이 있습니다.
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ // @docsearch/sidepanel-js SidepanelProps API 반영
+ panel: {
+ variant: 'floating', // 또는 'inline'
+ side: 'right',
+ width: '360px',
+ expandedWidth: '580px',
+ suggestedQuestions: true
}
}
}
@@ -268,112 +286,70 @@ export default defineConfig({
})
```
-[이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 재작성 할 수 있습니다. 이에 대해 자세히 알고 싶다면 Algolia 공식 문서를 참고하세요.
+키보드 단축키를 비활성화해야 하는 경우 사이드 패널의 `keyboardShortcuts` 옵션을 사용하세요:
-### 크롤러 구성 {#crawler-config}
+```ts
+import { defineConfig } from 'vitepress'
-이 사이트에서 사용하는 예제 구성을 소개합니다:
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ keyboardShortcuts: {
+ 'Ctrl/Cmd+I': false
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+#### 모드 (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
+
+VitePress가 키워드 검색과 Ask AI를 통합하는 방식을 선택적으로 제어할 수 있습니다:
+
+- `mode: 'auto'` (기본값): 키워드 검색이 구성된 경우 `hybrid`를 추론하고, 그렇지 않으면 Ask AI 사이드 패널이 구성된 경우 `sidePanel`을 추론합니다.
+- `mode: 'sidePanel'`: 사이드 패널만 강제 (키워드 검색 버튼 숨김).
+- `mode: 'hybrid'`: 키워드 검색 모달 + Ask AI 사이드 패널 활성화 (키워드 검색 구성 필요).
+- `mode: 'modal'`: Ask AI를 DocSearch 모달 내부에 유지 (사이드 패널을 구성한 경우에도).
+
+#### Ask AI만 (키워드 검색 없음) {#ask-ai-only}
+
+**Ask AI 사이드 패널만** 사용하려면 최상위 키워드 검색 구성을 생략하고 `askAi` 아래에 자격 증명을 제공할 수 있습니다:
```ts
-new Crawler({
- appId: '...',
- apiKey: '...',
- rateLimit: 8,
- startUrls: ['https://vitepress.dev/'],
- renderJavaScript: false,
- sitemaps: [],
- exclusionPatterns: [],
- ignoreCanonicalTo: false,
- discoveryPatterns: ['https://vitepress.dev/**'],
- schedule: 'at 05:10 on Saturday',
- actions: [
- {
- indexName: 'vitepress',
- pathsToMatch: ['https://vitepress.dev/**'],
- recordExtractor: ({ $, helpers }) => {
- return helpers.docsearch({
- recordProps: {
- lvl1: '.content h1',
- content: '.content p, .content li',
- lvl0: {
- selectors: 'section.has-active div h2',
- defaultValue: 'Documentation'
- },
- lvl2: '.content h2',
- lvl3: '.content h3',
- lvl4: '.content h4',
- lvl5: '.content h5'
- },
- indexHeadings: true
- })
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ mode: 'sidePanel',
+ askAi: {
+ assistantId: 'XXXYYY',
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ sidePanel: 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: '',
- highlightPostTag: '',
- minWordSizefor1Typo: 3,
- minWordSizefor2Typos: 7,
- allowTyposOnNumericTokens: false,
- minProximity: 1,
- ignorePlurals: true,
- advancedSyntax: true,
- attributeCriteriaComputedByMinProximity: true,
- removeWordsIfNoResults: 'allOptional'
- }
}
})
```
+
+### 크롤러 구성 {#crawler-config}
+
+이 사이트에서 사용하는 예제 구성을 소개합니다:
+
+<<< @/snippets/algolia-crawler.js
diff --git a/docs/ko/reference/runtime-api.md b/docs/ko/reference/runtime-api.md
index e9a8e5307..ee7a4ba3c 100644
--- a/docs/ko/reference/runtime-api.md
+++ b/docs/ko/reference/runtime-api.md
@@ -49,7 +49,7 @@ interface PageData {
titleTemplate?: string | boolean
description: string
relativePath: string
- filePath: string,
+ filePath: string
headers: Header[]
frontmatter: Record
params?: Record
diff --git a/docs/ko/reference/site-config.md b/docs/ko/reference/site-config.md
index 25dbcc017..ba02bd590 100644
--- a/docs/ko/reference/site-config.md
+++ b/docs/ko/reference/site-config.md
@@ -439,7 +439,7 @@ export default {
### ignoreDeadLinks
-- 타입: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
+- 타입: `boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[]`
- 기본값: `false`
`true`로 설정하면, 빌드 시 죽은 링크로 인해 실패하지 않습니다.
diff --git a/docs/lunaria.config.json b/docs/lunaria.config.json
index 4f93f4dca..2de958b9e 100644
--- a/docs/lunaria.config.json
+++ b/docs/lunaria.config.json
@@ -44,6 +44,10 @@
{
"label": "فارسی",
"lang": "fa"
+ },
+ {
+ "label": "日本語",
+ "lang": "ja"
}
],
"outDir": ".vitepress/dist/_translations",
diff --git a/docs/package.json b/docs/package.json
index 98f666051..62f5a4bf5 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -15,7 +15,7 @@
"open-cli": "^8.0.0",
"postcss-rtlcss": "^5.7.1",
"vitepress": "workspace:*",
- "vitepress-plugin-group-icons": "^1.6.0",
- "vitepress-plugin-llms": "^1.5.1"
+ "vitepress-plugin-group-icons": "^1.7.1",
+ "vitepress-plugin-llms": "^1.11.0"
}
}
diff --git a/docs/pt/config.ts b/docs/pt/config.ts
index 4926e697f..5f71d84fa 100644
--- a/docs/pt/config.ts
+++ b/docs/pt/config.ts
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineAdditionalConfig({
- lang: 'pt-BR',
description: 'Gerador de Site Estático desenvolvido com Vite e Vue.',
themeConfig: {
@@ -74,6 +73,10 @@ function nav(): DefaultTheme.NavItem[] {
{
text: pkg.version,
items: [
+ {
+ text: '1.6.4',
+ link: 'https://vuejs.github.io/vitepress/v1/pt/'
+ },
{
text: 'Registro de Mudanças',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
@@ -175,43 +178,150 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial {
return {
- placeholder: 'Pesquisar documentos',
translations: {
button: {
- buttonText: 'Pesquisar',
- buttonAriaLabel: 'Pesquisar'
+ buttonText: 'Buscar',
+ buttonAriaLabel: 'Buscar'
},
modal: {
searchBox: {
- resetButtonTitle: 'Limpar pesquisa',
- resetButtonAriaLabel: 'Limpar pesquisa',
- cancelButtonText: 'Cancelar',
- cancelButtonAriaLabel: 'Cancelar'
+ clearButtonTitle: 'Limpar',
+ clearButtonAriaLabel: 'Limpar a consulta',
+ closeButtonText: 'Fechar',
+ closeButtonAriaLabel: 'Fechar',
+ placeholderText: 'Buscar na documentação ou perguntar ao Ask AI',
+ placeholderTextAskAi: 'Faça outra pergunta...',
+ placeholderTextAskAiStreaming: 'Respondendo...',
+ searchInputLabel: 'Buscar',
+ backToKeywordSearchButtonText:
+ 'Voltar para a busca por palavra-chave',
+ backToKeywordSearchButtonAriaLabel:
+ 'Voltar para a busca por palavra-chave',
+ newConversationPlaceholder: 'Faça uma pergunta',
+ conversationHistoryTitle: 'Meu histórico de conversas',
+ startNewConversationText: 'Iniciar uma nova conversa',
+ viewConversationHistoryText: 'Histórico de conversas',
+ threadDepthErrorPlaceholder: 'Limite de conversa atingido'
},
- startScreen: {
- recentSearchesTitle: 'Histórico de Pesquisa',
- noRecentSearchesText: 'Nenhuma pesquisa recente',
- saveRecentSearchButtonTitle: 'Salvar no histórico de pesquisas',
- removeRecentSearchButtonTitle: 'Remover do histórico de pesquisas',
- favoriteSearchesTitle: 'Favoritos',
- removeFavoriteSearchButtonTitle: 'Remover dos favoritos'
- },
- errorScreen: {
- titleText: 'Não foi possível obter resultados',
- helpText: 'Verifique a sua conexão de rede'
+ newConversation: {
+ newConversationTitle: 'Como posso ajudar hoje?',
+ newConversationDescription:
+ 'Eu busco na sua documentação para ajudar a encontrar guias de configuração, detalhes de funcionalidades e dicas de solução de problemas rapidamente.'
},
footer: {
selectText: 'Selecionar',
+ submitQuestionText: 'Enviar pergunta',
+ selectKeyAriaLabel: 'Tecla Enter',
navigateText: 'Navegar',
+ navigateUpKeyAriaLabel: 'Seta para cima',
+ navigateDownKeyAriaLabel: 'Seta para baixo',
closeText: 'Fechar',
- searchByText: 'Pesquisa por'
+ backToSearchText: 'Voltar à busca',
+ closeKeyAriaLabel: 'Tecla Escape',
+ poweredByText: 'Com tecnologia de'
+ },
+ errorScreen: {
+ titleText: 'Não foi possível obter resultados',
+ helpText: 'Talvez você queira verificar sua conexão de rede.'
+ },
+ startScreen: {
+ recentSearchesTitle: 'Recentes',
+ noRecentSearchesText: 'Nenhuma pesquisa recente',
+ saveRecentSearchButtonTitle: 'Salvar esta pesquisa',
+ removeRecentSearchButtonTitle: 'Remover esta pesquisa do histórico',
+ favoriteSearchesTitle: 'Favoritos',
+ removeFavoriteSearchButtonTitle:
+ 'Remover esta pesquisa dos favoritos',
+ recentConversationsTitle: 'Conversas recentes',
+ removeRecentConversationButtonTitle:
+ 'Remover esta conversa do histórico'
},
noResultsScreen: {
- noResultsText: 'Não foi possível encontrar resultados',
- suggestedQueryText: 'Você pode tentar uma nova consulta',
+ noResultsText: 'Nenhum resultado encontrado para',
+ suggestedQueryText: 'Tente pesquisar por',
reportMissingResultsText:
- 'Deveriam haver resultados para essa consulta?',
- reportMissingResultsLinkText: 'Clique para enviar feedback'
+ 'Acha que esta consulta deveria retornar resultados?',
+ reportMissingResultsLinkText: 'Avise-nos.'
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Perguntar à IA: ',
+ noResultsAskAiPlaceholder:
+ 'Não encontrou nos documentos? Peça ajuda ao Ask AI: '
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'As respostas são geradas por IA e podem conter erros. Verifique.',
+ relatedSourcesText: 'Fontes relacionadas',
+ thinkingText: 'Pensando...',
+ copyButtonText: 'Copiar',
+ copyButtonCopiedText: 'Copiado!',
+ copyButtonTitle: 'Copiar',
+ likeButtonTitle: 'Curtir',
+ dislikeButtonTitle: 'Não curtir',
+ thanksForFeedbackText: 'Obrigado pelo seu feedback!',
+ preToolCallText: 'Buscando...',
+ duringToolCallText: 'Buscando...',
+ afterToolCallText: 'Pesquisado',
+ stoppedStreamingText: 'Você interrompeu esta resposta',
+ errorTitleText: 'Erro no chat',
+ threadDepthExceededMessage:
+ 'Esta conversa foi encerrada para manter respostas precisas.',
+ startNewConversationButtonText: 'Iniciar uma nova conversa'
+ }
+ }
+ },
+ askAi: {
+ sidePanel: {
+ button: {
+ translations: {
+ buttonText: 'Perguntar à IA',
+ buttonAriaLabel: 'Perguntar à IA'
+ }
+ },
+ panel: {
+ translations: {
+ header: {
+ title: 'Perguntar à IA',
+ conversationHistoryTitle: 'Meu histórico de conversas',
+ newConversationText: 'Iniciar uma nova conversa',
+ viewConversationHistoryText: 'Histórico de conversas'
+ },
+ promptForm: {
+ promptPlaceholderText: 'Faça uma pergunta',
+ promptAnsweringText: 'Respondendo...',
+ promptAskAnotherQuestionText: 'Faça outra pergunta',
+ promptDisclaimerText:
+ 'As respostas são geradas por IA e podem conter erros.',
+ promptLabelText:
+ 'Pressione Enter para enviar ou Shift+Enter para nova linha.',
+ promptAriaLabelText: 'Entrada do prompt'
+ },
+ conversationScreen: {
+ preToolCallText: 'Buscando...',
+ searchingText: 'Buscando...',
+ toolCallResultText: 'Pesquisado',
+ conversationDisclaimer:
+ 'As respostas são geradas por IA e podem conter erros. Verifique.',
+ reasoningText: 'Raciocinando...',
+ thinkingText: 'Pensando...',
+ relatedSourcesText: 'Fontes relacionadas',
+ stoppedStreamingText: 'Você interrompeu esta resposta',
+ copyButtonText: 'Copiar',
+ copyButtonCopiedText: 'Copiado!',
+ likeButtonTitle: 'Curtir',
+ dislikeButtonTitle: 'Não curtir',
+ thanksForFeedbackText: 'Obrigado pelo seu feedback!',
+ errorTitleText: 'Erro no chat'
+ },
+ newConversationScreen: {
+ titleText: 'Como posso ajudar hoje?',
+ introductionText:
+ 'Eu busco na sua documentação para ajudar a encontrar guias de configuração, detalhes de funcionalidades e dicas de solução de problemas rapidamente.'
+ },
+ logo: {
+ poweredByText: 'Com tecnologia de'
+ }
+ }
}
}
}
diff --git a/docs/pt/guide/deploy.md b/docs/pt/guide/deploy.md
index b112bf7d5..7821c7ab8 100644
--- a/docs/pt/guide/deploy.md
+++ b/docs/pt/guide/deploy.md
@@ -105,13 +105,13 @@ Nota: o arquivo `vercel.json` deve ser colocado na raiz do seu **repositório**.
## Guias de Plataforma {#platform-guides}
-### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
+### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
Configure um novo projeto e altere estas configurações usando seu painel:
- **Comando de Compilação:** `npm run docs:build`
- **Diretório de Saída:** `docs/.vitepress/dist`
-- **Versão do Node:** `18` (ou superior)
+- **Versão do Node:** `20` (ou superior)
::: warning
Não ative opções como _Auto Minify_ para código HTML. Isso removerá comentários da saída que têm significado para Vue. Haverão erros de incompatibilidade de hidratação se forem removidos.
@@ -153,26 +153,24 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0 # Não necessário se lastUpdated não estiver habilitado
- # - uses: pnpm/action-setup@v3 # Descomente isso se estiver usando pnpm
+ # - uses: pnpm/action-setup@v4 # Descomente isso se estiver usando pnpm
# with:
# version: 9
# - uses: oven-sh/setup-bun@v1 # Descomente isso se estiver usando Bun
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
- node-version: 22
+ node-version: 24
cache: npm # ou pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: npm ci # ou pnpm install / yarn install / bun install
- - name: Build with VitePress
- run: |
- npm run docs:build # ou pnpm docs:build / yarn docs:build / bun run docs:build
- touch docs/.vitepress/dist/.nojekyll
+ - name: Build with VitePress
+ run: npm run docs:build # ou pnpm docs:build / yarn docs:build / bun run docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
@@ -202,7 +200,7 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
### GitLab Pages
-1. Defina `outDir` na configuração VitePress como `../public`. Configure a opção `base` para `'//'` se você deseja implantar em `https://.gitlab.io//`.
+1. Defina `outDir` na configuração VitePress como `../public`. Configure a opção `base` para `'//'` se você deseja implantar em `https://.gitlab.io//`. Você não precisa de `base` se estiver implantando em um domínio personalizado, páginas de usuário ou grupo, ou se a configuração "Use unique domain" estiver habilitada no GitLab.
2. Crie um arquivo chamado `.gitlab-ci.yml` na raiz do seu projeto com o conteúdo abaixo. Isso construirá e implantará seu site sempre que você fizer alterações no conteúdo:
@@ -223,7 +221,7 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
- main
```
-### Azure Static Web Apps {#azure-static-web-apps}
+### Azure
1. Siga a [documentação oficial](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration).
@@ -233,7 +231,11 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
-### Firebase {#firebase}
+### CloudRay
+
+Você pode implantar seu projeto VitePress com a [CloudRay](https://cloudray.io/) seguindo estas [instruções](https://cloudray.io/articles/how-to-deploy-vitepress-site).
+
+### Firebase
1. Crie `firebase.json` e `.firebaserc` na raiz do seu projeto:
@@ -264,14 +266,6 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
firebase deploy
```
-### Surge
-
-1. Após executar `npm run docs:build`, execute este comando para implantar:
-
- ```sh
- npx surge docs/.vitepress/dist
- ```
-
### Heroku
1. Siga a documentação e o guia fornecidos em [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static).
@@ -284,10 +278,66 @@ Não ative opções como _Auto Minify_ para código HTML. Isso removerá coment
}
```
-### Edgio
+### Hostinger
-Consulte [Criar e Implantar um Aplicativo VitePress no Edgio](https://docs.edg.io/guides/vitepress).
+Você pode implantar seu projeto VitePress com a [Hostinger](https://www.hostinger.com/web-apps-hosting) seguindo estas [instruções](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/). Ao configurar as opções de build, escolha VitePress como framework e ajuste o diretório raiz para `./docs`.
-### Kinsta Static Site Hosting {#kinsta-static-site-hosting}
+### Kinsta
Você pode implantar seu site VitePress em [Kinsta](https://kinsta.com/static-site-hosting/) seguindo estas [instruções](https://kinsta.com/docs/vitepress-static-site-example/).
+
+### Stormkit
+
+Você pode implantar seu projeto VitePress na [Stormkit](https://www.stormkit.io) seguindo estas [instruções](https://stormkit.io/blog/how-to-deploy-vitepress).
+
+### Surge
+
+1. Após executar `npm run docs:build`, execute este comando para implantar:
+
+ ```sh
+ npx surge docs/.vitepress/dist
+ ```
+
+### Nginx
+
+Aqui está um exemplo de configuração de bloco de servidor Nginx. Essa configuração inclui compressão gzip para ativos comuns baseados em texto, regras para servir os arquivos estáticos do seu site VitePress com cabeçalhos de cache apropriados, assim como lidar com `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";
+ }
+ }
+}
+```
+
+Essa configuração presume que o site VitePress compilado está localizado no diretório `/app` no seu servidor. Ajuste a diretiva `root` de acordo caso os arquivos do site estejam em outro lugar.
+
+::: warning Não use index.html por padrão
+A resolução de try_files não deve padronizar para index.html como em outras aplicações Vue. Isso resultará em um estado de página inválido.
+:::
+
+Mais informações podem ser encontradas na [documentação oficial do nginx](https://nginx.org/en/docs/), nestas issues [#2837](https://github.com/vuejs/vitepress/discussions/2837), [#3235](https://github.com/vuejs/vitepress/issues/3235) assim como neste [post do blog](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings) de Mehdi Merah.
diff --git a/docs/pt/guide/extending-default-theme.md b/docs/pt/guide/extending-default-theme.md
index aa918b487..f3175f836 100644
--- a/docs/pt/guide/extending-default-theme.md
+++ b/docs/pt/guide/extending-default-theme.md
@@ -251,6 +251,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
{
duration: 300,
easing: 'ease-in',
+ fill: 'forwards',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
diff --git a/docs/pt/guide/getting-started.md b/docs/pt/guide/getting-started.md
index e6668cb2f..c0dba3a9a 100644
--- a/docs/pt/guide/getting-started.md
+++ b/docs/pt/guide/getting-started.md
@@ -18,39 +18,19 @@ VitePress pode ser usado sozinho, ou ser instalado em um projeto já existente.
::: code-group
```sh [npm]
-$ npm add -D vitepress
+$ npm add -D vitepress@next
```
```sh [pnpm]
-$ pnpm add -D vitepress
+$ pnpm add -D vitepress@next
```
```sh [yarn]
-$ yarn add -D vitepress
-```
-
-```sh [yarn (pnp)]
-$ yarn add -D vitepress vue
+$ yarn add -D vitepress@next vue
```
```sh [bun]
-$ bun add -D vitepress
-```
-
-:::
-
-::: details Está recebendo avisos sobre dependências correspondentes ausentes?
-Se usar PNPM, você perceberá um aviso de ausência de `@docsearch/js`. Isso não evita que o VitePress funcione. Se você deseja suprimir este aviso, adicione o seguinte no seu `package.json`:
-
-```json
-"pnpm": {
- "peerDependencyRules": {
- "ignoreMissing": [
- "@algolia/client-search",
- "search-insights"
- ]
- }
-}
+$ bun add -D vitepress@next
```
:::
diff --git a/docs/pt/guide/markdown.md b/docs/pt/guide/markdown.md
index b52452598..bfcc591f6 100644
--- a/docs/pt/guide/markdown.md
+++ b/docs/pt/guide/markdown.md
@@ -255,11 +255,11 @@ A classe `vp-raw` também pode ser usada diretamente em elementos. O isolamento
}
```
- Ele utiliza [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) internamente. Você pode passar opções assim:
+ Você pode passar opções assim:
```js
postcssIsolateStyles({
- includeFiles: [/vp-doc\.css/] // o padrão é /base\.css/
+ includeFiles: [/custom\.css/] // o padrão é [/vp-doc\.css/, /base\.css/]
})
```
@@ -771,7 +771,7 @@ Por exemplo, você pode incluir um arquivo markdown relativo usando isto:
## Conceitos Básicos
-
+
```
**Arquivo da Parte** (`parts/basics.md`)
@@ -807,7 +807,7 @@ Também suporta a seleção de um intervalo de linhas:
## Conceitos Básicos
-
+
```
**Arquivo da Parte** (`parts/basics.md`)
@@ -843,7 +843,7 @@ Observe que isso não gera erros se o arquivo não estiver presente. Portanto, a
Isso é atualmente opcional. Para ativá-lo, você precisa instalar `markdown-it-mathjax3` e definir `markdown.math` como `true` no seu arquivo de configuração:
```sh
-npm add -D markdown-it-mathjax3
+npm add -D markdown-it-mathjax3@^4
```
```ts [.vitepress/config.ts]
diff --git a/docs/pt/guide/using-vue.md b/docs/pt/guide/using-vue.md
index 226d90d21..a034108d9 100644
--- a/docs/pt/guide/using-vue.md
+++ b/docs/pt/guide/using-vue.md
@@ -128,7 +128,7 @@ Se um componente for usado na maioria das páginas, eles podem ser registrados g
Certifique-se de que o nome de um componente personalizado contenha um hífen ou esteja em PascalCase. Caso contrário, ele será tratado como um elemento alinhado e envolvido dentro de uma tag ``, o que levará a uma incompatibilidade de hidratação pois `
` não permite que elementos de bloco sejam colocados dentro dele.
:::
-### Usando Componentes Em Cabeçalhos {#using-components-in-headers}
+### Usando Componentes Em Cabeçalhos {#using-components-in-headers}
Você pode usar componentes Vue nos cabeçalhos, mas observe a diferença entre as seguintes sintaxes:
diff --git a/docs/pt/guide/what-is-vitepress.md b/docs/pt/guide/what-is-vitepress.md
index 734cd4178..2ccd319d0 100644
--- a/docs/pt/guide/what-is-vitepress.md
+++ b/docs/pt/guide/what-is-vitepress.md
@@ -12,7 +12,7 @@ Quer apenas experimentar? Pule para o [Início Rápido](./getting-started).
- **Documentação**
- VitePress vem com um tema padrão projetado para documentação técnica. Ele alimenta esta página que você está lendo agora, juntamente com a documentação [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) e [muitos outros](https://www.vuetelescope.com/explore?framework.slug=vitepress).
+ VitePress vem com um tema padrão projetado para documentação técnica. Ele alimenta esta página que você está lendo agora, juntamente com a documentação [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) e [muitos outros](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code).
A [documentação oficial Vue.js](https://vuejs.org/) também é baseada em VitePress, mas usa um tema personalizado compartilhado entre várias traduções.
diff --git a/docs/pt/index.md b/docs/pt/index.md
index 67cab365b..236d7c006 100644
--- a/docs/pt/index.md
+++ b/docs/pt/index.md
@@ -8,10 +8,10 @@ hero:
actions:
- theme: brand
text: O que é VitePress?
- link: /pt/guide/what-is-vitepress
+ link: ./guide/what-is-vitepress
- theme: alt
text: Iniciar
- link: /pt/guide/getting-started
+ link: ./guide/getting-started
- theme: alt
text: GitHub
link: https://github.com/vuejs/vitepress
diff --git a/docs/pt/reference/default-theme-config.md b/docs/pt/reference/default-theme-config.md
index 54e53e4a6..a1ac180f4 100644
--- a/docs/pt/reference/default-theme-config.md
+++ b/docs/pt/reference/default-theme-config.md
@@ -89,7 +89,7 @@ type NavItem = NavItemWithLink | NavItemWithChildren
interface NavItemWithLink {
text: string
- link: string
+ link: string | ((payload: PageData) => string)
activeMatch?: string
target?: string
rel?: string
diff --git a/docs/pt/reference/default-theme-nav.md b/docs/pt/reference/default-theme-nav.md
index 5f0d23997..fefc96618 100644
--- a/docs/pt/reference/default-theme-nav.md
+++ b/docs/pt/reference/default-theme-nav.md
@@ -55,6 +55,8 @@ export default {
`text` é o próprio texto mostrado na navegação, e o `link` é o link para o qual será navegado quando o texto for clicado. Para o link, defina o caminho para o próprio arquivo sem o prefixo `.md` e sempre comece com `/`.
+O `link` também pode ser uma função que aceita [`PageData`](./runtime-api#usedata) como argumento e retorna o caminho.
+
Links de navegação também podem ser menus _dropdown_. Para fazer isso, defina a chave `items` na opção do link.
```js
diff --git a/docs/pt/reference/default-theme-search.md b/docs/pt/reference/default-theme-search.md
index c16406cb2..44c5b8acc 100644
--- a/docs/pt/reference/default-theme-search.md
+++ b/docs/pt/reference/default-theme-search.md
@@ -39,18 +39,25 @@ export default defineConfig({
provider: 'local',
options: {
locales: {
- zh: {
+ pt: { // torne isto `root` se quiser traduzir a localidade padrão
translations: {
button: {
- buttonText: '搜索文档',
- buttonAriaLabel: '搜索文档'
+ buttonText: 'Pesquisar',
+ buttonAriaLabel: 'Pesquisar'
},
modal: {
- noResultsText: '无法找到相关结果',
- resetButtonTitle: '清除查询条件',
+ displayDetails: 'Mostrar lista detalhada',
+ resetButtonTitle: 'Redefinir pesquisa',
+ backButtonTitle: 'Fechar pesquisa',
+ noResultsText: 'Nenhum resultado',
footer: {
- selectText: '选择',
- navigateText: '切换'
+ selectText: 'Selecionar',
+ selectKeyAriaLabel: 'Enter',
+ navigateText: 'Navegar',
+ navigateUpKeyAriaLabel: 'Seta para cima',
+ navigateDownKeyAriaLabel: 'Seta para baixo',
+ closeText: 'Fechar',
+ closeKeyAriaLabel: 'Esc'
}
}
}
@@ -62,7 +69,7 @@ export default defineConfig({
})
```
-### Opções MiniSearch {#mini-search-options}
+### Opções MiniSearch {#minisearch-options}
Você pode configurar o MiniSearch assim:
@@ -116,7 +123,7 @@ export default defineConfig({
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
- // retorne a string HTML
+ // retorna uma string HTML
}
}
}
@@ -141,7 +148,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 +174,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 +204,23 @@ export default defineConfig({
})
```
-### i18n {#algolia-search-i18n} {#algolia-search-i18n}
+### i18n {#algolia-search-i18n}
Você pode usar uma configuração como esta para usar a pesquisa multilínguas:
+
+Clique para expandir
+
+<<< @/snippets/algolia-i18n.ts
+
+
+
+Consulte a [documentação oficial da Algolia](https://docsearch.algolia.com/docs/api#translations) para saber mais. Para começar rapidamente, você também pode copiar as traduções usadas por este site do [nosso repositório no GitHub](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code).
+
+### Suporte ao Algolia Ask AI {#ask-ai}
+
+Se quiser incluir o **Ask AI**, adicione `askAi` em `options`:
+
```ts
import { defineConfig } from 'vitepress'
@@ -212,46 +232,51 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
- locales: {
- zh: {
- placeholder: '搜索文档',
- translations: {
- button: {
- buttonText: '搜索文档',
- buttonAriaLabel: '搜索文档'
- },
- modal: {
- searchBox: {
- resetButtonTitle: '清除查询条件',
- resetButtonAriaLabel: '清除查询条件',
- cancelButtonText: '取消',
- cancelButtonAriaLabel: '取消'
- },
- startScreen: {
- recentSearchesTitle: '搜索历史',
- noRecentSearchesText: '没有搜索历史',
- saveRecentSearchButtonTitle: '保存至搜索历史',
- removeRecentSearchButtonTitle: '从搜索历史中移除',
- favoriteSearchesTitle: '收藏',
- removeFavoriteSearchButtonTitle: '从收藏中移除'
- },
- errorScreen: {
- titleText: '无法获取结果',
- helpText: '你可能需要检查你的网络连接'
- },
- footer: {
- selectText: '选择',
- navigateText: '切换',
- closeText: '关闭',
- searchByText: '搜索提供者'
- },
- noResultsScreen: {
- noResultsText: '无法找到相关结果',
- suggestedQueryText: '你可以尝试查询',
- reportMissingResultsText: '你认为该查询应该有结果?',
- reportMissingResultsLinkText: '点击反馈'
- }
- }
+ // askAi: "SEU-ID-DO-ASSISTENTE"
+ // OU
+ askAi: {
+ // no mínimo, você deve fornecer o assistantId recebido da Algolia
+ assistantId: 'XXXYYY',
+ // substituições opcionais — se omitidas, os valores appId/apiKey/indexName de nível superior são reutilizados
+ // apiKey: '...',
+ // appId: '...',
+ // indexName: '...'
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning Nota
+Caso queira apenas a pesquisa por palavra-chave, omita `askAi`.
+:::
+
+### Painel Lateral do Ask AI {#ask-ai-side-panel}
+
+O DocSearch v4.5+ suporta um **painel lateral do Ask AI** opcional. Quando habilitado, pode ser aberto com **Ctrl/Cmd+I** por padrão. A [Referência da API do Painel Lateral](https://docsearch.algolia.com/docs/sidepanel/api-reference) contém a lista completa de opções.
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ // Espelha a API do @docsearch/sidepanel-js SidepanelProps
+ panel: {
+ variant: 'floating', // ou 'inline'
+ side: 'right',
+ width: '360px',
+ expandedWidth: '580px',
+ suggestedQuestions: true
}
}
}
@@ -261,112 +286,70 @@ export default defineConfig({
})
```
-[Essas opções](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) podem ser sobrepostas. Consulte a documentação oficial Algolia para obter mais informações sobre elas.
+Se precisar desabilitar o atalho de teclado, use a opção `keyboardShortcuts` do painel lateral:
-### Configuração _Crawler_ {#crawler-config}
+```ts
+import { defineConfig } from 'vitepress'
-Aqui está um exemplo de configuração baseado na qual este site usa:
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ keyboardShortcuts: {
+ 'Ctrl/Cmd+I': false
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+#### Modo (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
+
+Você pode controlar opcionalmente como o VitePress integra a pesquisa por palavra-chave e o Ask AI:
+
+- `mode: 'auto'` (padrão): infere `hybrid` quando a pesquisa por palavra-chave está configurada, caso contrário `sidePanel` quando o painel lateral do Ask AI está configurado.
+- `mode: 'sidePanel'`: força apenas o painel lateral (oculta o botão de pesquisa por palavra-chave).
+- `mode: 'hybrid'`: habilita o modal de pesquisa por palavra-chave + painel lateral do Ask AI (requer configuração de pesquisa por palavra-chave).
+- `mode: 'modal'`: mantém o Ask AI dentro do modal do DocSearch (mesmo se você configurou o painel lateral).
+
+#### Apenas Ask AI (sem pesquisa por palavra-chave) {#ask-ai-only}
+
+Se quiser usar **apenas o painel lateral do Ask AI**, você pode omitir a configuração de pesquisa por palavra-chave de nível superior e fornecer as credenciais em `askAi`:
```ts
-new Crawler({
- appId: '...',
- apiKey: '...',
- rateLimit: 8,
- startUrls: ['https://vitepress.dev/'],
- renderJavaScript: false,
- sitemaps: [],
- exclusionPatterns: [],
- ignoreCanonicalTo: false,
- discoveryPatterns: ['https://vitepress.dev/**'],
- schedule: 'at 05:10 on Saturday',
- actions: [
- {
- indexName: 'vitepress',
- pathsToMatch: ['https://vitepress.dev/**'],
- recordExtractor: ({ $, helpers }) => {
- return helpers.docsearch({
- recordProps: {
- lvl1: '.content h1',
- content: '.content p, .content li',
- lvl0: {
- selectors: 'section.has-active div h2',
- defaultValue: 'Documentation'
- },
- lvl2: '.content h2',
- lvl3: '.content h3',
- lvl4: '.content h4',
- lvl5: '.content h5'
- },
- indexHeadings: true
- })
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ mode: 'sidePanel',
+ askAi: {
+ assistantId: 'XXXYYY',
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ sidePanel: 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: '',
- highlightPostTag: '',
- minWordSizefor1Typo: 3,
- minWordSizefor2Typos: 7,
- allowTyposOnNumericTokens: false,
- minProximity: 1,
- ignorePlurals: true,
- advancedSyntax: true,
- attributeCriteriaComputedByMinProximity: true,
- removeWordsIfNoResults: 'allOptional'
- }
}
})
```
+
+### Configuração _Crawler_ {#crawler-config}
+
+Aqui está um exemplo de configuração baseado na qual este site usa:
+
+<<< @/snippets/algolia-crawler.js
diff --git a/docs/pt/reference/runtime-api.md b/docs/pt/reference/runtime-api.md
index ed6476ac4..559e2fed5 100644
--- a/docs/pt/reference/runtime-api.md
+++ b/docs/pt/reference/runtime-api.md
@@ -45,7 +45,7 @@ interface PageData {
titleTemplate?: string | boolean
description: string
relativePath: string
- filePath: string,
+ filePath: string
headers: Header[]
frontmatter: Record
params?: Record
diff --git a/docs/pt/reference/site-config.md b/docs/pt/reference/site-config.md
index 092819014..662813115 100644
--- a/docs/pt/reference/site-config.md
+++ b/docs/pt/reference/site-config.md
@@ -24,7 +24,7 @@ export default {
}
```
-:::details Configuração Dinâmica (Assíncrona)
+::: details Configuração Dinâmica (Assíncrona)
Se você precisar gerar dinamicamente a configuração, também pode exportar por padrão uma função. Por exemplo:
@@ -439,7 +439,7 @@ export default {
### ignoreDeadLinks
-- Tipo: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
+- Tipo: `boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[]`
- Padrão: `false`
Quando definido como `true`, VitePress não falhará na compilação devido a links quebrados.
@@ -594,7 +594,7 @@ export default {
`transformHead` é um gancho de compilação para transformar o cabeçalho antes de gerar cada página. Isso permite adicionar entradas no cabeçalho que não podem ser adicionadas estaticamente à configuração VitePress. Você só precisa retornar entradas extras, que serão mescladas automaticamente com as existentes.
-:::warning
+::: warning
Não faça mutações em qualquer item dentro de `context`.
:::
@@ -662,7 +662,7 @@ export default {
- Tipo: `(code: string, id: string, context: TransformContext) => Awaitable`
`transformHtml` é um gancho de compilação para transformar o conteúdo de cada página antes de salvá-lo no disco.
-:::warning
+::: warning
Não faça mutações em qualquer item dentro de `context`. Além disso, modificar o conteúdo HTML pode causar problemas de hidratação em tempo de execução.
:::
@@ -679,7 +679,7 @@ export default {
`transformPageData` é um gancho para transformar os dados de cada página. Você pode fazer mutações diretamente em `pageData` ou retornar valores alterados que serão mesclados nos dados da página.
-:::warning
+::: warning
Não faça mutações em qualquer item dentro de `context` e tenha cuidado pois isso pode impactar no desempenho do servidor de desenvolvimento, especialmente se você tiver algumas solicitações de rede ou computações pesadas (como gerar imagens) no gancho. Você pode verificar `process.env.NODE_ENV === 'production'` para lógica condicional.
:::
diff --git a/docs/ru/config.ts b/docs/ru/config.ts
index 739cfbf2a..515cffba4 100644
--- a/docs/ru/config.ts
+++ b/docs/ru/config.ts
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineAdditionalConfig({
- lang: 'ru-RU',
description: 'Генератор статических сайтов на основе Vite и Vue.',
themeConfig: {
@@ -72,6 +71,10 @@ function nav(): DefaultTheme.NavItem[] {
{
text: pkg.version,
items: [
+ {
+ text: '1.6.4',
+ link: 'https://vuejs.github.io/vitepress/v1/ru/'
+ },
{
text: 'Изменения',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
@@ -175,7 +178,6 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial {
return {
- placeholder: 'Поиск в документации',
translations: {
button: {
buttonText: 'Поиск',
@@ -183,35 +185,141 @@ function searchOptions(): Partial {
},
modal: {
searchBox: {
- resetButtonTitle: 'Сбросить поиск',
- resetButtonAriaLabel: 'Сбросить поиск',
- cancelButtonText: 'Отменить поиск',
- cancelButtonAriaLabel: 'Отменить поиск'
+ clearButtonTitle: 'Очистить',
+ clearButtonAriaLabel: 'Очистить запрос',
+ closeButtonText: 'Закрыть',
+ closeButtonAriaLabel: 'Закрыть',
+ placeholderText: 'Поиск по документации или задайте вопрос Ask AI',
+ placeholderTextAskAi: 'Задайте другой вопрос...',
+ placeholderTextAskAiStreaming: 'Отвечаю...',
+ searchInputLabel: 'Поиск',
+ backToKeywordSearchButtonText: 'Назад к поиску по ключевым словам',
+ backToKeywordSearchButtonAriaLabel:
+ 'Назад к поиску по ключевым словам',
+ newConversationPlaceholder: 'Задайте вопрос',
+ conversationHistoryTitle: 'Моя история разговоров',
+ startNewConversationText: 'Начать новый разговор',
+ viewConversationHistoryText: 'История разговоров',
+ threadDepthErrorPlaceholder: 'Достигнут лимит разговора'
},
- startScreen: {
- recentSearchesTitle: 'История поиска',
- noRecentSearchesText: 'Нет истории поиска',
- saveRecentSearchButtonTitle: 'Сохранить в истории поиска',
- removeRecentSearchButtonTitle: 'Удалить из истории поиска',
- favoriteSearchesTitle: 'Избранное',
- removeFavoriteSearchButtonTitle: 'Удалить из избранного'
+ newConversation: {
+ newConversationTitle: 'Чем могу помочь сегодня?',
+ newConversationDescription:
+ 'Я ищу по вашей документации, чтобы быстро помочь найти руководства по настройке, детали функций и советы по устранению неполадок.'
+ },
+ footer: {
+ selectText: 'Выбрать',
+ submitQuestionText: 'Отправить вопрос',
+ selectKeyAriaLabel: 'Клавиша Enter',
+ navigateText: 'Навигация',
+ navigateUpKeyAriaLabel: 'Стрелка вверх',
+ navigateDownKeyAriaLabel: 'Стрелка вниз',
+ closeText: 'Закрыть',
+ backToSearchText: 'Назад к поиску',
+ closeKeyAriaLabel: 'Клавиша Escape',
+ poweredByText: 'При поддержке'
},
errorScreen: {
- titleText: 'Невозможно получить результаты',
- helpText: 'Вам может потребоваться проверить подключение к Интернету'
+ titleText: 'Не удалось получить результаты',
+ helpText: 'Возможно, стоит проверить подключение к сети.'
},
- footer: {
- selectText: 'выбрать',
- navigateText: 'перейти',
- closeText: 'закрыть',
- searchByText: 'поставщик поиска'
+ startScreen: {
+ recentSearchesTitle: 'Недавние',
+ noRecentSearchesText: 'Нет недавних поисков',
+ saveRecentSearchButtonTitle: 'Сохранить этот поиск',
+ removeRecentSearchButtonTitle: 'Удалить этот поиск из истории',
+ favoriteSearchesTitle: 'Избранное',
+ removeFavoriteSearchButtonTitle: 'Удалить этот поиск из избранного',
+ recentConversationsTitle: 'Недавние разговоры',
+ removeRecentConversationButtonTitle:
+ 'Удалить этот разговор из истории'
},
noResultsScreen: {
- noResultsText: 'Нет результатов для',
- suggestedQueryText: 'Вы можете попытаться узнать',
+ noResultsText: 'Не найдено результатов для',
+ suggestedQueryText: 'Попробуйте поискать',
reportMissingResultsText:
- 'Считаете, что поиск даёт ложные результаты?',
- reportMissingResultsLinkText: 'Нажмите на кнопку «Обратная связь»'
+ 'Считаете, что по этому запросу должны быть результаты?',
+ reportMissingResultsLinkText: 'Сообщите нам.'
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Спросить ИИ: ',
+ noResultsAskAiPlaceholder:
+ 'Не нашли в документации? Попросите Ask AI помочь: '
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'Ответы генерируются ИИ и могут содержать ошибки. Проверьте их.',
+ relatedSourcesText: 'Связанные источники',
+ thinkingText: 'Думаю...',
+ copyButtonText: 'Копировать',
+ copyButtonCopiedText: 'Скопировано!',
+ copyButtonTitle: 'Копировать',
+ likeButtonTitle: 'Нравится',
+ dislikeButtonTitle: 'Не нравится',
+ thanksForFeedbackText: 'Спасибо за отзыв!',
+ preToolCallText: 'Ищу...',
+ duringToolCallText: 'Ищу...',
+ afterToolCallText: 'Искал',
+ stoppedStreamingText: 'Вы остановили этот ответ',
+ errorTitleText: 'Ошибка чата',
+ threadDepthExceededMessage:
+ 'Этот разговор закрыт, чтобы сохранить точность ответов.',
+ startNewConversationButtonText: 'Начать новый разговор'
+ }
+ }
+ },
+ 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: 'При поддержке'
+ }
+ }
}
}
}
diff --git a/docs/ru/guide/deploy.md b/docs/ru/guide/deploy.md
index ff12be6c9..3b310524a 100644
--- a/docs/ru/guide/deploy.md
+++ b/docs/ru/guide/deploy.md
@@ -105,7 +105,7 @@ 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}
Создайте новый проект и измените эти настройки с помощью панели управления:
@@ -117,7 +117,7 @@ Cache-Control: max-age=31536000,immutable
Не включайте такие опции, как _Auto Minify_ для HTML-кода. Он удалит из вывода комментарии, которые имеют значение для Vue. При их удалении могут возникать ошибки несоответствия гидратации.
:::
-### GitHub Pages {#github-pages}
+### GitHub Pages
1. Создайте файл с именем `deploy.yml` в директории `.github/workflows` вашего проекта с примерно таким содержанием:
@@ -153,17 +153,17 @@ Cache-Control: max-age=31536000,immutable
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0 # Не требуется, если функция lastUpdated не включена
- # - uses: pnpm/action-setup@v3 # Раскомментируйте, если вы используете pnpm
+ # - uses: pnpm/action-setup@v4 # Раскомментируйте, если вы используете pnpm
# with:
# version: 9
# - uses: oven-sh/setup-bun@v1 # Раскомментируйте, если вы используете Bun
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
- node-version: 22
+ node-version: 24
cache: npm # или pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v4
@@ -198,7 +198,7 @@ Cache-Control: max-age=31536000,immutable
3. Внесите свои изменения в ветку `main` и дождитесь завершения процесса GitHub Actions. Вы должны увидеть, что ваш сайт развёрнут по адресу `https://.github.io/[repository]/` или `https:///` в зависимости от ваших настроек. Ваш сайт будет автоматически разворачиваться при каждом внесении изменений в ветке `main`.
-### GitLab Pages {#gitlab-pages}
+### GitLab Pages
1. Установите значение `../public` для параметра `outDir` в конфигурации VitePress. Настройте опцию `base` на `'/<репозиторий>/'`, если вы хотите развернуть ваш проект по адресу `https://<имя пользователя>.gitlab.io/<репозиторий>/`. Вам не нужна опция `base`, если вы выполняете развёртывание на личном домене, страницах пользователя или группы, или если в GitLab включен параметр «Использовать уникальный домен».
@@ -221,7 +221,7 @@ Cache-Control: max-age=31536000,immutable
- main
```
-### Статические веб-приложения Azure {#azure-static-web-apps}
+### Azure
1. Следуйте [официальной документации](https://docs.microsoft.com/ru-ru/azure/static-web-apps/build-configuration).
@@ -231,7 +231,11 @@ Cache-Control: max-age=31536000,immutable
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
-### Firebase {#firebase}
+### CloudRay
+
+Вы можете развернуть свой проект VitePress с [CloudRay](https://cloudray.io/), следуя этим [инструкциям](https://cloudray.io/articles/how-to-deploy-vitepress-site).
+
+### Firebase
1. Создайте `firebase.json` и `.firebaserc` в корне вашего проекта:
@@ -262,15 +266,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).
@@ -282,11 +278,11 @@ Cache-Control: max-age=31536000,immutable
}
```
-### Edgio {#edgio}
+### Hostinger
-См. [Создание и развёртывание приложения VitePress в Edgio](https://docs.edg.io/applications/v6/sites_frameworks/getting_started/vitepress).
+Вы можете развернуть свой проект 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 {#kinsta-static-site-hosting}
+### Kinsta
Вы можете развернуть свой сайт VitePress на [Kinsta](https://kinsta.com/static-site-hosting/), следуя этим [инструкциям](https://kinsta.com/docs/vitepress-static-site-example/).
@@ -294,6 +290,14 @@ Cache-Control: max-age=31536000,immutable
Вы можете развернуть свой проект VitePress на [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 для общих текстовых ресурсов, правила обслуживания статических файлов вашего сайта VitePress с правильными заголовками кэширования и обработку параметра `cleanUrls: true`.
diff --git a/docs/ru/guide/extending-default-theme.md b/docs/ru/guide/extending-default-theme.md
index 4443b8828..b1497ced1 100644
--- a/docs/ru/guide/extending-default-theme.md
+++ b/docs/ru/guide/extending-default-theme.md
@@ -253,6 +253,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
{
duration: 300,
easing: 'ease-in',
+ fill: 'forwards',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
diff --git a/docs/ru/guide/getting-started.md b/docs/ru/guide/getting-started.md
index 21e8dcb03..4ca5ff8c6 100644
--- a/docs/ru/guide/getting-started.md
+++ b/docs/ru/guide/getting-started.md
@@ -18,39 +18,19 @@ VitePress можно использовать самостоятельно ил
::: code-group
```sh [npm]
-$ npm add -D vitepress
+$ npm add -D vitepress@next
```
```sh [pnpm]
-$ pnpm add -D vitepress
+$ pnpm add -D vitepress@next
```
```sh [yarn]
-$ yarn add -D vitepress
-```
-
-```sh [yarn (pnp)]
-$ yarn add -D vitepress vue
+$ yarn add -D vitepress@next vue
```
```sh [bun]
-$ bun add -D vitepress
-```
-
-:::
-
-::: details Получаете предупреждения об отсутствующих зависимостях?
-Если вы используете PNPM, вы заметите предупреждение об отсутствующем пакете `@docsearch/js`. Это не мешает работе VitePress. Если вы хотите подавить это предупреждение, добавьте следующее в ваш `package.json`:
-
-```json
-"pnpm": {
- "peerDependencyRules": {
- "ignoreMissing": [
- "@algolia/client-search",
- "search-insights"
- ]
- }
-}
+$ bun add -D vitepress@next
```
:::
diff --git a/docs/ru/guide/markdown.md b/docs/ru/guide/markdown.md
index dbb398ac9..6e0cd5670 100644
--- a/docs/ru/guide/markdown.md
+++ b/docs/ru/guide/markdown.md
@@ -281,11 +281,11 @@ console.log('Привет, VitePress!')
}
```
- Он использует [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) под капотом. Вы можете передать ему параметры следующим образом:
+ Вы можете передать ему параметры следующим образом:
```js
postcssIsolateStyles({
- includeFiles: [/vp-doc\.css/] // по умолчанию /base\.css/
+ includeFiles: [/custom\.css/] // по умолчанию [/vp-doc\.css/, /base\.css/]
})
```
@@ -795,7 +795,7 @@ export default config
## Основы
-
+
```
**Файл части** (`parts/basics.md`)
@@ -831,7 +831,7 @@ export default config
## Основы
-
+
```
**Файл части** (`parts/basics.md`)
@@ -867,8 +867,8 @@ export default config
## Основы
-
-
+
+
```
**Часть файла** (`parts/basics.md`)
@@ -919,7 +919,7 @@ export default config
```md
## Мой дополнительный раздел
-
+
```
**Соответствующий код**
@@ -943,7 +943,7 @@ export default config
и включить его следующим образом:
```md
-
+
```
## Математические уравнения {#math-equations}
@@ -951,7 +951,7 @@ export default config
В настоящее время эта фича предоставляется по желанию. Чтобы включить её, вам нужно установить `markdown-it-mathjax3` и установить значение `true` для опции `markdown.math` в вашем файле конфигурации:
```sh
-npm add -D markdown-it-mathjax3
+npm add -D markdown-it-mathjax3@^4
```
```ts [.vitepress/config.ts]
diff --git a/docs/ru/guide/what-is-vitepress.md b/docs/ru/guide/what-is-vitepress.md
index 1bcc3e18e..90b07e9e5 100644
--- a/docs/ru/guide/what-is-vitepress.md
+++ b/docs/ru/guide/what-is-vitepress.md
@@ -1,6 +1,6 @@
# Что такое VitePress? {#what-is-vitepress}
-VitePress — это [Генератор статических сайтов](https://en.wikipedia.org/wiki/Static_site_generator) (ГСС), предназначенный для быстрого создания сайтов, ориентированных на контент. В двух словах, VitePress берёт ваш исходный контент, написанный в [Markdown](https://ru.wikipedia.org/wiki/Markdown), применяет к нему тему и генерирует статические HTML-страницы, которые можно легко развернуть в любом месте.
+VitePress — это [Генератор статических сайтов](https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B_%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2) (ГСС), предназначенный для быстрого создания сайтов, ориентированных на контент. В двух словах, VitePress берёт ваш исходный контент, написанный на [Markdown](https://ru.wikipedia.org/wiki/Markdown), применяет к нему тему и генерирует статические HTML-страницы, которые можно легко развернуть в любом месте.
@@ -12,13 +12,13 @@ VitePress — это [Генератор статических сайтов](ht
- **Документация**
- VitePress поставляется с темой по умолчанию, предназначенной для технической документации. Она содержит эту страницу, которую вы сейчас читаете, а также документацию по [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) и [многое другое](https://www.vuetelescope.com/explore?framework.slug=vitepress).
+ VitePress поставляется с темой по умолчанию, предназначенной для технической документации. Именно она обеспечивает работу этой страницы, которую вы сейчас читаете, а также документации для [Vite](https://vite-docs.ru/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia-ru.netlify.app), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) и [многих других](https://github.com/search?q=/%22vitepress%22:+/+path:/(?:package%7Cdeno)%5C.jsonc?$/+NOT+is:fork+NOT+is:archived&type=code).
- [Официальная документация Vue.js](https://vuejs.org/) также основана на VitePress, но использует пользовательскую тему, разделяемую между несколькими переводами.
+ [Официальная документация Vue.js](https://vuejs.org/) также основана на VitePress, но использует кастомную тему, общую для нескольких переводов.
- **Блоги, портфолио и маркетинговые сайты**
- VitePress поддерживает [полностью кастомизированные темы](./custom-theme), при этом разработчики могут использовать стандартное приложение Vite + Vue. То, что он построен на базе Vite, также означает, что вы можете напрямую использовать плагины Vite из его богатой экосистемы. Кроме того, VitePress предоставляет гибкие API для [загрузки данных](./data-loading) (локальной или удаленной) и [динамической генерации маршрутов](./routing#dynamic-routes). С его помощью можно построить практически всё, что угодно, если данные могут быть определены во время сборки.
+ VitePress поддерживает [полностью кастомизированные темы](./custom-theme), при этом разработчики могут использовать стандартное приложение Vite + Vue. То, что он построен на базе Vite, также означает, что вы можете напрямую использовать плагины Vite из его богатой экосистемы. Кроме того, VitePress предоставляет гибкие API для [загрузки данных](./data-loading) (локальной или удалённой) и [динамической генерации маршрутов](./routing#dynamic-routes). С его помощью можно построить практически всё, что угодно, если данные могут быть определены во время сборки.
Официальный [блог Vue.js](https://blog.vuejs.org/) — это простой блог, который генерирует свою индексную страницу на основе локального контента.
@@ -50,8 +50,8 @@ VitePress стремится обеспечить отличные возмож
## Что насчёт VuePress? {#what-about-vuepress}
-VitePress — это духовный наследник VuePress. Оригинальный VuePress был основан на Vue 2 и webpack. Благодаря Vue 3 и Vite под капотом, VitePress обеспечивает значительно лучший опыт разработки, лучшую производительность, более отточенную тему по умолчанию и более гибкий API для настройки.
+VitePress — это духовный наследник VuePress 1. Оригинальный VuePress 1 основывался на Vue 2 и webpack. Благодаря Vue 3 и Vite под капотом, VitePress обеспечивает значительно лучший опыт разработки (DX), более высокую производительность в продакшене, более отполированную тему по умолчанию и более гибкий API для кастомизации.
-Разница в API между VitePress и VuePress заключается в основном в тематическом оформлении и настройке. Если вы используете VuePress 1 с темой по умолчанию, то переход на VitePress будет относительно простым.
+Различия в API между VitePress и VuePress 1 в основном касаются тем и настройки. Если вы используете VuePress 1 с темой по умолчанию, миграция на VitePress должна пройти относительно просто.
-Также были приложены усилия для создания VuePress 2, который также поддерживает Vue 3 и Vite с большей совместимостью с VuePress 1. Однако поддерживать два генератора параллельно не представляется возможным, поэтому команда Vue решила сосредоточиться на VitePress как основном рекомендуемом генераторе статических сайтов в долгосрочной перспективе.
+Поддерживать два SSG параллельно нецелесообразно, поэтому команда Vue решила сосредоточиться на VitePress как на основном рекомендуемом SSG в долгосрочной перспективе. Теперь VuePress 1 объявлен устаревшим, а VuePress 2 передан команде сообщества VuePress для дальнейшей разработки и поддержки.
diff --git a/docs/ru/index.md b/docs/ru/index.md
index e5bc77327..faa45e785 100644
--- a/docs/ru/index.md
+++ b/docs/ru/index.md
@@ -8,10 +8,10 @@ hero:
actions:
- theme: brand
text: Что такое VitePress?
- link: /ru/guide/what-is-vitepress
+ link: ./guide/what-is-vitepress
- theme: alt
text: Первые шаги
- link: /ru/guide/getting-started
+ link: ./guide/getting-started
- theme: alt
text: GitHub
link: https://github.com/vuejs/vitepress
diff --git a/docs/ru/reference/default-theme-config.md b/docs/ru/reference/default-theme-config.md
index 2eb955709..27b704438 100644
--- a/docs/ru/reference/default-theme-config.md
+++ b/docs/ru/reference/default-theme-config.md
@@ -89,7 +89,7 @@ type NavItem = NavItemWithLink | NavItemWithChildren
interface NavItemWithLink {
text: string
- link: string
+ link: string | ((payload: PageData) => string)
activeMatch?: string
target?: string
rel?: string
diff --git a/docs/ru/reference/default-theme-last-updated.md b/docs/ru/reference/default-theme-last-updated.md
index 4a0509f42..88c91afe0 100644
--- a/docs/ru/reference/default-theme-last-updated.md
+++ b/docs/ru/reference/default-theme-last-updated.md
@@ -11,7 +11,7 @@ VitePress отображает время «последнего обновле
```yaml{4}
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0
```
diff --git a/docs/ru/reference/default-theme-nav.md b/docs/ru/reference/default-theme-nav.md
index 41257de85..edfb9a9e0 100644
--- a/docs/ru/reference/default-theme-nav.md
+++ b/docs/ru/reference/default-theme-nav.md
@@ -55,6 +55,8 @@ export default {
`text` — это текст, отображаемый в навигации, а `link` — это ссылка, на которую будет осуществлён переход при нажатии на текст. Для ссылки задайте путь к фактическому файлу без префикса `.md` и всегда начинайте с `/`.
+`link` также может быть функцией, которая принимает [`PageData`](./runtime-api#usedata) в качестве аргумента и возвращает путь.
+
Навигационные ссылки также могут быть выпадающими меню. Для этого установите ключ `items` вместо ключа `link`:
```js
diff --git a/docs/ru/reference/default-theme-search.md b/docs/ru/reference/default-theme-search.md
index bab3fa9e7..16bad58d3 100644
--- a/docs/ru/reference/default-theme-search.md
+++ b/docs/ru/reference/default-theme-search.md
@@ -29,6 +29,7 @@ export default defineConfig({
-
-
-
+-
### i18n {#local-search-i18n}
@@ -43,25 +44,25 @@ export default defineConfig({
provider: 'local',
options: {
locales: {
- ru: { // используйте ключ `root`, если хотите перевести локаль по умолчанию
+ ru: { // используйте `root`, если хотите перевести локаль по умолчанию
translations: {
button: {
buttonText: 'Поиск',
buttonAriaLabel: 'Поиск'
},
modal: {
- displayDetails: 'Отобразить подробный список',
+ displayDetails: 'Показать подробный список',
resetButtonTitle: 'Сбросить поиск',
backButtonTitle: 'Закрыть поиск',
- noResultsText: 'Нет результатов по запросу',
+ noResultsText: 'Нет результатов',
footer: {
- selectText: 'выбрать',
- selectKeyAriaLabel: 'выбрать',
- navigateText: 'перейти',
- navigateUpKeyAriaLabel: 'стрелка вверх',
- navigateDownKeyAriaLabel: 'стрелка вниз',
- closeText: 'закрыть',
- closeKeyAriaLabel: 'esc'
+ selectText: 'Выбрать',
+ selectKeyAriaLabel: 'Enter',
+ navigateText: 'Навигация',
+ navigateUpKeyAriaLabel: 'Стрелка вверх',
+ navigateDownKeyAriaLabel: 'Стрелка вниз',
+ closeText: 'Закрыть',
+ closeKeyAriaLabel: 'Esc'
}
}
}
@@ -127,7 +128,7 @@ export default defineConfig({
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
- // возвращаем html
+ // вернуть строку HTML
}
}
}
@@ -178,7 +179,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
}
}
@@ -212,6 +213,19 @@ export default defineConfig({
Пример конфигурации для использования многоязычного поиска:
+
+Нажмите, чтобы развернуть
+
+<<< @/snippets/algolia-i18n.ts
+
+
+
+Подробности см. в [официальной документации Algolia](https://docsearch.algolia.com/docs/api#translations). Чтобы быстрее начать, можно также скопировать переводы, используемые на этом сайте, из [нашего репозитория GitHub](https://github.com/search?q=repo:vuejs/vitepress+%22function+searchOptions%22&type=code).
+
+### Поддержка Ask AI в Algolia {#ask-ai}
+
+Если вы хотите добавить функцию **Ask AI**, передайте параметр `askAi` (или любые из его отдельных полей) внутри объекта `options`:
+
```ts
import { defineConfig } from 'vitepress'
@@ -223,49 +237,51 @@ export default defineConfig({
appId: '...',
apiKey: '...',
indexName: '...',
- locales: {
- ru: {
- placeholder: 'Поиск в документации',
- translations: {
- button: {
- buttonText: 'Поиск',
- buttonAriaLabel: 'Поиск'
- },
- modal: {
- searchBox: {
- resetButtonTitle: 'Сбросить поиск',
- resetButtonAriaLabel: 'Сбросить поиск',
- cancelButtonText: 'Отменить поиск',
- cancelButtonAriaLabel: 'Отменить поиск'
- },
- startScreen: {
- recentSearchesTitle: 'История поиска',
- noRecentSearchesText: 'Нет истории поиска',
- saveRecentSearchButtonTitle: 'Сохранить в истории поиска',
- removeRecentSearchButtonTitle: 'Удалить из истории поиска',
- favoriteSearchesTitle: 'Избранное',
- removeFavoriteSearchButtonTitle: 'Удалить из избранного'
- },
- errorScreen: {
- titleText: 'Невозможно получить результаты',
- helpText:
- 'Вам может потребоваться проверить подключение к Интернету'
- },
- footer: {
- selectText: 'выбрать',
- navigateText: 'перейти',
- closeText: 'закрыть',
- searchByText: 'поставщик поиска'
- },
- noResultsScreen: {
- noResultsText: 'Нет результатов для',
- suggestedQueryText: 'Вы можете попытаться узнать',
- reportMissingResultsText:
- 'Считаете, что поиск даёт ложные результаты?',
- reportMissingResultsLinkText:
- 'Нажмите на кнопку «Обратная связь»'
- }
- }
+ // askAi: "ВАШ-ID-АССИСТЕНТА"
+ // ИЛИ
+ askAi: {
+ // как минимум нужно указать assistantId, полученный от Algolia
+ assistantId: 'XXXYYY',
+ // необязательные переопределения — если их нет, используются значения appId/apiKey/indexName верхнего уровня
+ // apiKey: '...',
+ // appId: '...',
+ // indexName: '...'
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning Примечание
+Если вы хотите использовать обычный поиск по ключевым словам без Ask AI, просто не указывайте свойство `askAi`
+:::
+
+### Боковая панель Ask AI {#ask-ai-side-panel}
+
+DocSearch v4.5+ поддерживает опциональную **боковую панель Ask AI**. Когда она включена, её можно открыть с помощью **Ctrl/Cmd+I** по умолчанию. [Справочник API боковой панели](https://docsearch.algolia.com/docs/sidepanel/api-reference) содержит полный список опций.
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ // Отражает API @docsearch/sidepanel-js SidepanelProps
+ panel: {
+ variant: 'floating', // или 'inline'
+ side: 'right',
+ width: '360px',
+ expandedWidth: '580px',
+ suggestedQuestions: true
}
}
}
@@ -275,112 +291,70 @@ export default defineConfig({
})
```
-[Эти параметры](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts) можно переопределить. Чтобы узнать о них больше, обратитесь к официальной документации Algolia.
+Если вам нужно отключить сочетание клавиш, используйте опцию `keyboardShortcuts` боковой панели:
-### Конфигурация поискового робота {#crawler-config}
+```ts
+import { defineConfig } from 'vitepress'
-Вот пример конфигурации, основанной на той, что используется на этом сайте:
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ askAi: {
+ assistantId: 'XXXYYY',
+ sidePanel: {
+ keyboardShortcuts: {
+ 'Ctrl/Cmd+I': false
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+#### Режим (auto / sidePanel / hybrid / modal) {#ask-ai-mode}
+
+Вы можете опционально контролировать, как VitePress интегрирует поиск по ключевым словам и Ask AI:
+
+- `mode: 'auto'` (по умолчанию): выводит `hybrid`, когда настроен поиск по ключевым словам, иначе `sidePanel`, когда настроена боковая панель Ask AI.
+- `mode: 'sidePanel'`: принудительно использовать только боковую панель (скрывает кнопку поиска по ключевым словам).
+- `mode: 'hybrid'`: включает модальное окно поиска по ключевым словам + боковую панель Ask AI (требует настройки поиска по ключевым словам).
+- `mode: 'modal'`: сохраняет Ask AI внутри модального окна DocSearch (даже если вы настроили боковую панель).
+
+#### Только Ask AI (без поиска по ключевым словам) {#ask-ai-only}
+
+Если вы хотите использовать **только боковую панель Ask AI**, вы можете опустить конфигурацию поиска по ключевым словам верхнего уровня и предоставить учётные данные в `askAi`:
```ts
-new Crawler({
- appId: '...',
- apiKey: '...',
- rateLimit: 8,
- startUrls: ['https://vitepress.dev/'],
- renderJavaScript: false,
- sitemaps: [],
- exclusionPatterns: [],
- ignoreCanonicalTo: false,
- discoveryPatterns: ['https://vitepress.dev/**'],
- schedule: 'at 05:10 on Saturday',
- actions: [
- {
- indexName: 'vitepress',
- pathsToMatch: ['https://vitepress.dev/**'],
- recordExtractor: ({ $, helpers }) => {
- return helpers.docsearch({
- recordProps: {
- lvl1: '.content h1',
- content: '.content p, .content li',
- lvl0: {
- selectors: 'section.has-active div h2',
- defaultValue: 'Documentation'
- },
- lvl2: '.content h2',
- lvl3: '.content h3',
- lvl4: '.content h4',
- lvl5: '.content h5'
- },
- indexHeadings: true
- })
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ mode: 'sidePanel',
+ askAi: {
+ assistantId: 'XXXYYY',
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ sidePanel: 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: '',
- highlightPostTag: '',
- minWordSizefor1Typo: 3,
- minWordSizefor2Typos: 7,
- allowTyposOnNumericTokens: false,
- minProximity: 1,
- ignorePlurals: true,
- advancedSyntax: true,
- attributeCriteriaComputedByMinProximity: true,
- removeWordsIfNoResults: 'allOptional'
- }
}
})
```
+
+### Конфигурация поискового робота {#crawler-config}
+
+Вот пример конфигурации, основанной на той, что используется на этом сайте:
+
+<<< @/snippets/algolia-crawler.js
diff --git a/docs/ru/reference/site-config.md b/docs/ru/reference/site-config.md
index 50bd132cd..74508e044 100644
--- a/docs/ru/reference/site-config.md
+++ b/docs/ru/reference/site-config.md
@@ -24,7 +24,7 @@ export default {
}
```
-:::details Динамическая (асинхронная) конфигурация
+::: details Динамическая (асинхронная) конфигурация
Если вам нужно генерировать конфигурацию динамически, вы также можете экспортировать функцию по умолчанию. Например:
@@ -439,7 +439,7 @@ export default {
### ignoreDeadLinks {#ignoredeadlinks}
-- Тип: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
+- Тип: `boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[]`
- По умолчанию: `false`
Если установлено значение `true`, VitePress не будет завершать сборку из-за неработающих ссылок.
diff --git a/docs/snippets/algolia-crawler.js b/docs/snippets/algolia-crawler.js
new file mode 100644
index 000000000..054afa56c
--- /dev/null
+++ b/docs/snippets/algolia-crawler.js
@@ -0,0 +1,101 @@
+new Crawler({
+ appId: '...',
+ apiKey: '...',
+ rateLimit: 8,
+ startUrls: ['https://vitepress.dev/'],
+ renderJavaScript: false,
+ sitemaps: [],
+ exclusionPatterns: [],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://vitepress.dev/**'],
+ schedule: 'at 05:10 on Saturday',
+ actions: [
+ {
+ indexName: 'vitepress',
+ pathsToMatch: ['https://vitepress.dev/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl1: '.content h1',
+ content: '.content p, .content li',
+ lvl0: {
+ selectors: 'section.has-active div h2',
+ defaultValue: 'Documentation'
+ },
+ lvl2: '.content h2',
+ lvl3: '.content h3',
+ lvl4: '.content h4',
+ lvl5: '.content h5'
+ },
+ indexHeadings: true
+ })
+ }
+ }
+ ],
+ initialIndexSettings: {
+ vitepress: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content'
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)'
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom'
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional'
+ }
+ }
+})
diff --git a/docs/snippets/algolia-i18n.ts b/docs/snippets/algolia-i18n.ts
new file mode 100644
index 000000000..c57816c38
--- /dev/null
+++ b/docs/snippets/algolia-i18n.ts
@@ -0,0 +1,155 @@
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...',
+ locales: {
+ zh: {
+ translations: {
+ button: {
+ buttonText: '搜索',
+ buttonAriaLabel: '搜索'
+ },
+ modal: {
+ searchBox: {
+ clearButtonTitle: '清除',
+ clearButtonAriaLabel: '清除查询',
+ closeButtonText: '关闭',
+ closeButtonAriaLabel: '关闭',
+ placeholderText: '搜索文档或向 AI 提问',
+ placeholderTextAskAi: '再问一个问题...',
+ placeholderTextAskAiStreaming: '正在回答...',
+ searchInputLabel: '搜索',
+ backToKeywordSearchButtonText: '返回关键词搜索',
+ backToKeywordSearchButtonAriaLabel: '返回关键词搜索',
+ newConversationPlaceholder: '提问',
+ conversationHistoryTitle: '我的对话历史',
+ startNewConversationText: '开始新的对话',
+ viewConversationHistoryText: '对话历史',
+ threadDepthErrorPlaceholder: '对话已达上限'
+ },
+ newConversation: {
+ newConversationTitle: '我今天能帮你什么?',
+ newConversationDescription:
+ '我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
+ },
+ footer: {
+ selectText: '选择',
+ submitQuestionText: '提交问题',
+ selectKeyAriaLabel: '回车键',
+ navigateText: '导航',
+ navigateUpKeyAriaLabel: '向上箭头',
+ navigateDownKeyAriaLabel: '向下箭头',
+ closeText: '关闭',
+ backToSearchText: '返回搜索',
+ closeKeyAriaLabel: 'Esc 键',
+ poweredByText: '由…提供支持'
+ },
+ errorScreen: {
+ titleText: '无法获取结果',
+ helpText: '你可能需要检查网络连接。'
+ },
+ startScreen: {
+ recentSearchesTitle: '最近',
+ noRecentSearchesText: '暂无最近搜索',
+ saveRecentSearchButtonTitle: '保存此搜索',
+ removeRecentSearchButtonTitle: '从历史记录中移除此搜索',
+ favoriteSearchesTitle: '收藏',
+ removeFavoriteSearchButtonTitle: '从收藏中移除此搜索',
+ recentConversationsTitle: '最近对话',
+ removeRecentConversationButtonTitle: '从历史记录中移除此对话'
+ },
+ noResultsScreen: {
+ noResultsText: '未找到相关结果',
+ suggestedQueryText: '尝试搜索',
+ reportMissingResultsText: '认为此查询应该有结果?',
+ reportMissingResultsLinkText: '告诉我们。'
+ },
+ resultsScreen: {
+ askAiPlaceholder: '询问 AI:',
+ noResultsAskAiPlaceholder: '文档里没找到?让 Ask AI 帮忙:'
+ },
+ askAiScreen: {
+ disclaimerText: '回答由 AI 生成,可能会出错。请核实。',
+ relatedSourcesText: '相关来源',
+ thinkingText: '思考中...',
+ copyButtonText: '复制',
+ copyButtonCopiedText: '已复制!',
+ copyButtonTitle: '复制',
+ likeButtonTitle: '喜欢',
+ dislikeButtonTitle: '不喜欢',
+ thanksForFeedbackText: '感谢你的反馈!',
+ preToolCallText: '搜索中...',
+ duringToolCallText: '搜索中...',
+ afterToolCallText: '已搜索',
+ stoppedStreamingText: '你已停止此回复',
+ errorTitleText: '聊天错误',
+ threadDepthExceededMessage: '为保持回答准确,此对话已关闭。',
+ startNewConversationButtonText: '开始新的对话'
+ }
+ }
+ },
+ askAi: {
+ sidePanel: {
+ button: {
+ translations: {
+ buttonText: '询问 AI',
+ buttonAriaLabel: '询问 AI'
+ }
+ },
+ panel: {
+ translations: {
+ header: {
+ title: '询问 AI',
+ conversationHistoryTitle: '我的对话历史',
+ newConversationText: '开始新的对话',
+ viewConversationHistoryText: '对话历史'
+ },
+ promptForm: {
+ promptPlaceholderText: '提问',
+ promptAnsweringText: '正在回答...',
+ promptAskAnotherQuestionText: '再问一个问题',
+ promptDisclaimerText: '回答由 AI 生成,可能会出错。',
+ promptLabelText: '按回车发送,Shift+回车换行。',
+ promptAriaLabelText: '问题输入'
+ },
+ conversationScreen: {
+ preToolCallText: '搜索中...',
+ searchingText: '搜索中...',
+ toolCallResultText: '已搜索',
+ conversationDisclaimer:
+ '回答由 AI 生成,可能会出错。请核实。',
+ reasoningText: '推理中...',
+ thinkingText: '思考中...',
+ relatedSourcesText: '相关来源',
+ stoppedStreamingText: '你已停止此回复',
+ copyButtonText: '复制',
+ copyButtonCopiedText: '已复制!',
+ likeButtonTitle: '喜欢',
+ dislikeButtonTitle: '不喜欢',
+ thanksForFeedbackText: '感谢你的反馈!',
+ errorTitleText: '聊天错误'
+ },
+ newConversationScreen: {
+ titleText: '我今天能帮你什么?',
+ introductionText:
+ '我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
+ },
+ logo: {
+ poweredByText: '由…提供支持'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+})
diff --git a/docs/zh/config.ts b/docs/zh/config.ts
index 22fb8b951..91687c542 100644
--- a/docs/zh/config.ts
+++ b/docs/zh/config.ts
@@ -5,7 +5,6 @@ const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineAdditionalConfig({
- lang: 'zh-Hans',
description: '由 Vite 和 Vue 驱动的静态站点生成器',
themeConfig: {
@@ -25,7 +24,7 @@ export default defineAdditionalConfig({
footer: {
message: '基于 MIT 许可发布',
- copyright: `版权所有 © 2019-${new Date().getFullYear()} 尤雨溪`
+ copyright: '版权所有 © 2019-至今 尤雨溪'
},
docFooter: {
@@ -74,6 +73,10 @@ function nav(): DefaultTheme.NavItem[] {
{
text: pkg.version,
items: [
+ {
+ text: '1.6.4',
+ link: 'https://vuejs.github.io/vitepress/v1/zh/'
+ },
{
text: '更新日志',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
@@ -168,42 +171,139 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
function searchOptions(): Partial {
return {
- placeholder: '搜索文档',
translations: {
button: {
- buttonText: '搜索文档',
- buttonAriaLabel: '搜索文档'
+ buttonText: '搜索',
+ buttonAriaLabel: '搜索'
},
modal: {
searchBox: {
- resetButtonTitle: '清除查询条件',
- resetButtonAriaLabel: '清除查询条件',
- cancelButtonText: '取消',
- cancelButtonAriaLabel: '取消'
- },
- startScreen: {
- recentSearchesTitle: '搜索历史',
- noRecentSearchesText: '没有搜索历史',
- saveRecentSearchButtonTitle: '保存至搜索历史',
- removeRecentSearchButtonTitle: '从搜索历史中移除',
- favoriteSearchesTitle: '收藏',
- removeFavoriteSearchButtonTitle: '从收藏中移除'
+ clearButtonTitle: '清除',
+ clearButtonAriaLabel: '清除查询',
+ closeButtonText: '关闭',
+ closeButtonAriaLabel: '关闭',
+ placeholderText: '搜索文档或向 AI 提问',
+ placeholderTextAskAi: '再问一个问题...',
+ placeholderTextAskAiStreaming: '正在回答...',
+ searchInputLabel: '搜索',
+ backToKeywordSearchButtonText: '返回关键词搜索',
+ backToKeywordSearchButtonAriaLabel: '返回关键词搜索',
+ newConversationPlaceholder: '提问',
+ conversationHistoryTitle: '我的对话历史',
+ startNewConversationText: '开始新的对话',
+ viewConversationHistoryText: '对话历史',
+ threadDepthErrorPlaceholder: '对话已达上限'
},
- errorScreen: {
- titleText: '无法获取结果',
- helpText: '你可能需要检查你的网络连接'
+ newConversation: {
+ newConversationTitle: '我今天能帮你什么?',
+ newConversationDescription:
+ '我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
footer: {
selectText: '选择',
- navigateText: '切换',
+ submitQuestionText: '提交问题',
+ selectKeyAriaLabel: '回车键',
+ navigateText: '导航',
+ navigateUpKeyAriaLabel: '向上箭头',
+ navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
- searchByText: '搜索提供者'
+ backToSearchText: '返回搜索',
+ closeKeyAriaLabel: 'Esc 键',
+ poweredByText: '由…提供支持'
+ },
+ errorScreen: {
+ titleText: '无法获取结果',
+ helpText: '你可能需要检查网络连接。'
+ },
+ startScreen: {
+ recentSearchesTitle: '最近',
+ noRecentSearchesText: '暂无最近搜索',
+ saveRecentSearchButtonTitle: '保存此搜索',
+ removeRecentSearchButtonTitle: '从历史记录中移除此搜索',
+ favoriteSearchesTitle: '收藏',
+ removeFavoriteSearchButtonTitle: '从收藏中移除此搜索',
+ recentConversationsTitle: '最近对话',
+ removeRecentConversationButtonTitle: '从历史记录中移除此对话'
},
noResultsScreen: {
- noResultsText: '无法找到相关结果',
- suggestedQueryText: '你可以尝试查询',
- reportMissingResultsText: '你认为该查询应该有结果?',
- reportMissingResultsLinkText: '点击反馈'
+ noResultsText: '未找到相关结果',
+ suggestedQueryText: '尝试搜索',
+ reportMissingResultsText: '认为此查询应该有结果?',
+ reportMissingResultsLinkText: '告诉我们。'
+ },
+ resultsScreen: {
+ askAiPlaceholder: '询问 AI:',
+ noResultsAskAiPlaceholder: '文档里没找到?让 Ask AI 帮忙:'
+ },
+ askAiScreen: {
+ disclaimerText: '回答由 AI 生成,可能会出错。请核实。',
+ relatedSourcesText: '相关来源',
+ thinkingText: '思考中...',
+ copyButtonText: '复制',
+ copyButtonCopiedText: '已复制!',
+ copyButtonTitle: '复制',
+ likeButtonTitle: '喜欢',
+ dislikeButtonTitle: '不喜欢',
+ thanksForFeedbackText: '感谢你的反馈!',
+ preToolCallText: '搜索中...',
+ duringToolCallText: '搜索中...',
+ afterToolCallText: '已搜索',
+ stoppedStreamingText: '你已停止此回复',
+ errorTitleText: '聊天错误',
+ threadDepthExceededMessage: '为保持回答准确,此对话已关闭。',
+ startNewConversationButtonText: '开始新的对话'
+ }
+ }
+ },
+ askAi: {
+ sidePanel: {
+ button: {
+ translations: {
+ buttonText: '询问 AI',
+ buttonAriaLabel: '询问 AI'
+ }
+ },
+ panel: {
+ translations: {
+ header: {
+ title: '询问 AI',
+ conversationHistoryTitle: '我的对话历史',
+ newConversationText: '开始新的对话',
+ viewConversationHistoryText: '对话历史'
+ },
+ promptForm: {
+ promptPlaceholderText: '提问',
+ promptAnsweringText: '正在回答...',
+ promptAskAnotherQuestionText: '再问一个问题',
+ promptDisclaimerText: '回答由 AI 生成,可能会出错。',
+ promptLabelText: '按回车发送,Shift+回车换行。',
+ promptAriaLabelText: '问题输入'
+ },
+ conversationScreen: {
+ preToolCallText: '搜索中...',
+ searchingText: '搜索中...',
+ toolCallResultText: '已搜索',
+ conversationDisclaimer: '回答由 AI 生成,可能会出错。请核实。',
+ reasoningText: '推理中...',
+ thinkingText: '思考中...',
+ relatedSourcesText: '相关来源',
+ stoppedStreamingText: '你已停止此回复',
+ copyButtonText: '复制',
+ copyButtonCopiedText: '已复制!',
+ likeButtonTitle: '喜欢',
+ dislikeButtonTitle: '不喜欢',
+ thanksForFeedbackText: '感谢你的反馈!',
+ errorTitleText: '聊天错误'
+ },
+ newConversationScreen: {
+ titleText: '我今天能帮你什么?',
+ introductionText:
+ '我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
+ },
+ logo: {
+ poweredByText: '由…提供支持'
+ }
+ }
}
}
}
diff --git a/docs/zh/guide/deploy.md b/docs/zh/guide/deploy.md
index 54ed13d41..c0fafe388 100644
--- a/docs/zh/guide/deploy.md
+++ b/docs/zh/guide/deploy.md
@@ -105,7 +105,7 @@ Cache-Control: max-age=31536000,immutable
## 各平台部署指南 {#platform-guides}
-### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
+### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render {#generic}
使用仪表板创建新项目并更改这些设置:
@@ -153,17 +153,17 @@ Cache-Control: max-age=31536000,immutable
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0 # 如果未启用 lastUpdated,则不需要
- # - uses: pnpm/action-setup@v3 # 如果使用 pnpm,请取消此区域注释
+ # - uses: pnpm/action-setup@v4 # 如果使用 pnpm,请取消此区域注释
# with:
# version: 9
# - uses: oven-sh/setup-bun@v1 # 如果使用 Bun,请取消注释
- name: Setup Node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
- node-version: 22
+ node-version: 24
cache: npm # 或 pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v4
@@ -200,7 +200,7 @@ Cache-Control: max-age=31536000,immutable
### GitLab Pages
-1. 如果你想部署到 `https:// .gitlab.io/ /`,将 VitePress 配置中的 `outDir` 设置为 `../public`。将 `base` 选项配置为 `'//'`。
+1. 如果你想部署到 `https:// .gitlab.io/ /`,将 VitePress 配置中的 `outDir` 设置为 `../public`。将 `base` 选项配置为 `'//'`。如果你部署到自定义域名、用户或组织页面,或在 GitLab 中启用了“Use unique domain”设置,则不需要 `base`。
2. 在项目的根目录中创建一个名为 `.gitlab-ci.yml` 的文件,其中包含以下内容。每当你更改内容时,这都会构建和部署你的站点:
@@ -221,7 +221,7 @@ Cache-Control: max-age=31536000,immutable
- main
```
-### Azure 静态 web 应用 {#azure-static-web-apps}
+### Azure
1. 参考[官方文档](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)。
@@ -231,7 +231,11 @@ Cache-Control: max-age=31536000,immutable
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
-### Firebase {#firebase}
+### CloudRay
+
+你可以按照这些[说明](https://cloudray.io/articles/how-to-deploy-vitepress-site)使用 [CloudRay](https://cloudray.io/) 部署你的 VitePress 项目。
+
+### Firebase
1. 在项目的根目录下创建 `firebase.json` 和 `.firebaserc`:
@@ -262,14 +266,6 @@ Cache-Control: max-age=31536000,immutable
firebase deploy
```
-### Surge
-
-1. 运行 `npm run docs:build` 后,运行此命令进行部署:
-
- ```sh
- npx surge docs/.vitepress/dist
- ```
-
### Heroku
1. 参考 [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static) 中给出的文档和指南。
@@ -282,11 +278,11 @@ Cache-Control: max-age=31536000,immutable
}
```
-### Edgio
+### Hostinger
-请参阅[创建并部署 VitePress 应用程序到 Edgio](https://docs.edg.io/guides/vitepress)。
+你可以按照这些[说明](https://www.hostinger.com/support/how-to-deploy-a-nodejs-website-in-hostinger/)使用 [Hostinger](https://www.hostinger.com/web-apps-hosting) 部署你的 VitePress 项目。在配置构建设置时,选择 VitePress 作为框架,并将根目录调整为 `./docs`。
-### Kinsta 静态站点托管 {#kinsta-static-site-hosting}
+### Kinsta
你可以按照这些[说明](https://kinsta.com/docs/vitepress-static-site-example/) 在 [Kinsta](https://kinsta.com/static-site-hosting/) 上部署 VitePress 站点。
@@ -294,6 +290,14 @@ Cache-Control: max-age=31536000,immutable
你可以按照这些[说明](https://stormkit.io/blog/how-to-deploy-vitepress)将你的 VitePress 项目部署到 [Stormkit](https://www.stormkit.io)。
+### Surge
+
+1. 运行 `npm run docs:build` 后,运行此命令进行部署:
+
+ ```sh
+ npx surge docs/.vitepress/dist
+ ```
+
### Nginx
下面是一个 Nginx 服务器块配置示例。此配置包括对基于文本的常见资源的 gzip 压缩、使用适当缓存头为 VitePress 站点静态文件提供服务的规则以及处理 `cleanUrls: true` 的方法。
@@ -308,20 +312,20 @@ server {
index index.html;
location / {
- # content location
+ # 内容位置
root /app;
- # exact matches -> reverse clean urls -> folders -> not found
+ # 完全匹配 -> 反向清理 url -> 文件夹 -> 没有发现
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
+ # 在此设置中,如果文件夹没有 index.html,就会引发 403 错误
error_page 403 /404.html;
- # adjust caching headers
- # files in the assets folder have hashes filenames
+ # 调整缓存标头
+ # assets 文件夹中的文件都有哈希文件名
location ~* ^/assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
diff --git a/docs/zh/guide/extending-default-theme.md b/docs/zh/guide/extending-default-theme.md
index 4d19eea29..6218247d2 100644
--- a/docs/zh/guide/extending-default-theme.md
+++ b/docs/zh/guide/extending-default-theme.md
@@ -14,7 +14,7 @@ VitePress 默认的主题已经针对文档进行了优化,并且可以进行
这些高级自定义配置将需要使用自定义主题来“拓展”默认主题。
-:::tip
+::: tip
在继续之前,请确保首先阅读[自定义主题](./custom-theme)以了解其工作原理。
:::
@@ -55,8 +55,8 @@ export default DefaultTheme
```css
/* .vitepress/theme/my-fonts.css */
:root {
- --vp-font-family-base: /* normal text font */
- --vp-font-family-mono: /* code font */
+ --vp-font-family-base: /* 普通文本字体 */
+ --vp-font-family-mono: /* 代码字体 */
}
```
@@ -251,6 +251,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
{
duration: 300,
easing: 'ease-in',
+ fill: 'forwards',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
@@ -288,7 +289,7 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
```
-Result (**warning!**: flashing colors, sudden movements, bright lights):
+结果(**注意!**:画面闪烁、快速闪现、强光刺激):
Demo
diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md
index 2d6453c95..183b32df6 100644
--- a/docs/zh/guide/getting-started.md
+++ b/docs/zh/guide/getting-started.md
@@ -18,39 +18,19 @@ VitePress 可以单独使用,也可以安装到现有项目中。在这两种
::: code-group
```sh [npm]
-$ npm add -D vitepress
+$ npm add -D vitepress@next
```
```sh [pnpm]
-$ pnpm add -D vitepress
+$ pnpm add -D vitepress@next
```
```sh [yarn]
-$ yarn add -D vitepress
-```
-
-```sh [yarn (pnp)]
-$ yarn add -D vitepress vue
+$ yarn add -D vitepress@next vue
```
```sh [bun]
-$ bun add -D vitepress
-```
-
-:::
-
-::: details 遇到了 missing peer deps 警告?
-如果使用 PNPM,会注意到对 `@docsearch/js` 的 missing peer deps 警告。这不会影响 VitePress 运行。如果希望禁止显示此警告,请将以下内容添加到 `package.json`:
-
-```json
-"pnpm": {
- "peerDependencyRules": {
- "ignoreMissing": [
- "@algolia/client-search",
- "search-insights"
- ]
- }
-}
+$ bun add -D vitepress@next
```
:::
@@ -89,7 +69,7 @@ $ bun vitepress init
<<< @/snippets/init.ansi
-:::tip Vue 作为 peer dependency
+::: tip Vue 作为 peer dependency
如果打算使用 Vue 组件或 API 进行自定义,还应该明确地将 `vue` 安装为 dependency。
:::
@@ -112,7 +92,7 @@ $ bun vitepress init
`docs` 目录作为 VitePress 站点的项目**根目录**。`.vitepress` 目录是 VitePress 配置文件、开发服务器缓存、构建输出和可选主题自定义代码的位置。
-:::tip
+::: tip
默认情况下,VitePress 将其开发服务器缓存存储在 `.vitepress/cache` 中,并将生产构建输出存储在 `.vitepress/dist` 中。如果使用 Git,应该将它们添加到 `.gitignore` 文件中。也可以手动[配置](../reference/site-config#outdir)这些位置。
:::
diff --git a/docs/zh/guide/markdown.md b/docs/zh/guide/markdown.md
index 308c49dfe..8f4694682 100644
--- a/docs/zh/guide/markdown.md
+++ b/docs/zh/guide/markdown.md
@@ -255,11 +255,11 @@ Wraps in a ``
}
```
- 它在底层使用 [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config)。你可以像这样传递它的选项:
+ 你可以像这样传递它的选项:
```js
postcssIsolateStyles({
- includeFiles: [/vp-doc\.css/] // 默认为 /base\.css/
+ includeFiles: [/custom\.css/] // 默认为 [/vp-doc\.css/, /base\.css/]
})
```
@@ -343,7 +343,7 @@ export default {
在 Shiki 的代码仓库中,可以找到[合法的编程语言列表](https://shiki.style/languages)。
-还可以全局配置中自定义语法高亮主题。有关详细信息,参见 [`markdown` 选项](../reference/site-config#markdown)得到更多信息。
+还可以在全局配置中自定义语法高亮主题、配置语言别名和自定义语言标签。有关详细信息,参见 [`markdown` 选项](../reference/site-config#markdown)得到更多信息。
## 在代码块中实现行高亮 {#line-highlighting-in-code-blocks}
@@ -771,7 +771,7 @@ export default config
## Basics
-
+
```
**Part file** (`parts/basics.md`)
@@ -807,7 +807,7 @@ Can be created using `.foorc.json`.
## Basics
-
+
```
**Part file** (`parts/basics.md`)
@@ -843,7 +843,7 @@ Can be created using `.foorc.json`.
现在这是可选的。要启用它,需要安装 `markdown-it-mathjax3`,在配置文件中设置`markdown.math` 为 `true`:
```sh
-npm add -D markdown-it-mathjax3
+npm add -D markdown-it-mathjax3@^4
```
```ts [.vitepress/config.ts]
diff --git a/docs/zh/guide/routing.md b/docs/zh/guide/routing.md
index 563323171..c48722ad0 100644
--- a/docs/zh/guide/routing.md
+++ b/docs/zh/guide/routing.md
@@ -123,7 +123,7 @@ src/getting-started.md --> /getting-started.html
## 生成简洁的 URL {#generating-clean-url}
-:::warning 需要服务器支持
+::: warning 需要服务器支持
要使 VitePress 提供简洁 URL,需要服务器端支持。
:::
diff --git a/docs/zh/guide/using-vue.md b/docs/zh/guide/using-vue.md
index be181feea..f9acaad49 100644
--- a/docs/zh/guide/using-vue.md
+++ b/docs/zh/guide/using-vue.md
@@ -67,7 +67,7 @@ The count is: {{ count }}
```
-:::warning 避免在 Markdown 中使用 `
diff --git a/src/client/theme-default/components/VPDocFooterLastUpdated.vue b/src/client/theme-default/components/VPDocFooterLastUpdated.vue
index 5ec3cfeb1..576a87d41 100644
--- a/src/client/theme-default/components/VPDocFooterLastUpdated.vue
+++ b/src/client/theme-default/components/VPDocFooterLastUpdated.vue
@@ -1,26 +1,38 @@
@@ -28,7 +40,7 @@ onMounted(() => {
{{ theme.lastUpdated?.text || theme.lastUpdatedText || 'Last updated' }}:
-
+
diff --git a/src/client/theme-default/components/VPDocOutlineItem.vue b/src/client/theme-default/components/VPDocOutlineItem.vue
index c945fc21a..4cff1b384 100644
--- a/src/client/theme-default/components/VPDocOutlineItem.vue
+++ b/src/client/theme-default/components/VPDocOutlineItem.vue
@@ -5,18 +5,12 @@ defineProps<{
headers: DefaultTheme.OutlineItem[]
root?: boolean
}>()
-
-function onClick({ target: el }: Event) {
- const id = (el as HTMLAnchorElement).href!.split('#')[1]
- const heading = document.getElementById(decodeURIComponent(id))
- heading?.focus({ preventScroll: true })
-}
-
-
+
{{ title }}
diff --git a/src/client/theme-default/components/VPFeature.vue b/src/client/theme-default/components/VPFeature.vue
index ff36fe978..e0e49b186 100644
--- a/src/client/theme-default/components/VPFeature.vue
+++ b/src/client/theme-default/components/VPFeature.vue
@@ -41,8 +41,10 @@ defineProps<{
/>
-
-
+
+
{{ linkText }}
@@ -105,6 +107,11 @@ defineProps<{
color: var(--vp-c-text-2);
}
+ul.details {
+ list-style-type: disc;
+ padding-left: 14px;
+}
+
.link-text {
padding-top: 8px;
}
diff --git a/src/client/theme-default/components/VPFlyout.vue b/src/client/theme-default/components/VPFlyout.vue
index 7ce561622..c05c579cf 100644
--- a/src/client/theme-default/components/VPFlyout.vue
+++ b/src/client/theme-default/components/VPFlyout.vue
@@ -1,4 +1,5 @@
-
diff --git a/src/client/theme-default/components/VPLocalNav.vue b/src/client/theme-default/components/VPLocalNav.vue
index e14db10e6..f80bb3611 100644
--- a/src/client/theme-default/components/VPLocalNav.vue
+++ b/src/client/theme-default/components/VPLocalNav.vue
@@ -32,7 +32,7 @@ const classes = computed(() => {
VPLocalNav: true,
'has-sidebar': hasSidebar.value,
empty: !hasLocalNav.value,
- fixed: !hasLocalNav.value && !hasSidebar.value,
+ fixed: !hasLocalNav.value && !hasSidebar.value
}
})
@@ -98,12 +98,6 @@ const classes = computed(() => {
}
}
-@media (min-width: 1440px) {
- .VPLocalNav.has-sidebar {
- padding-left: calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width));
- }
-}
-
.container {
display: flex;
justify-content: space-between;
@@ -113,7 +107,6 @@ const classes = computed(() => {
.menu {
display: flex;
align-items: center;
- padding: 12px 24px 11px;
line-height: 24px;
font-size: 12px;
font-weight: 500;
@@ -126,12 +119,6 @@ const classes = computed(() => {
transition: color 0.25s;
}
-@media (min-width: 768px) {
- .menu {
- padding: 0 32px;
- }
-}
-
@media (min-width: 960px) {
.menu {
display: none;
@@ -143,12 +130,14 @@ const classes = computed(() => {
font-size: 14px;
}
-.VPOutlineDropdown {
+.menu,
+:deep(.VPLocalNavOutlineDropdown > button) {
padding: 12px 24px 11px;
}
@media (min-width: 768px) {
- .VPOutlineDropdown {
+ .menu,
+ :deep(.VPLocalNavOutlineDropdown > button) {
padding: 12px 32px 11px;
}
}
diff --git a/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue b/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
index 83a17b310..cf842baa3 100644
--- a/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
+++ b/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
@@ -92,16 +92,6 @@ function scrollToTop() {
diff --git a/src/client/theme-default/components/VPNavBarExtra.vue b/src/client/theme-default/components/VPNavBarExtra.vue
index 988a814a9..3bc788bcf 100644
--- a/src/client/theme-default/components/VPNavBarExtra.vue
+++ b/src/client/theme-default/components/VPNavBarExtra.vue
@@ -31,7 +31,13 @@ const hasExtraContent = computed(
{{ currentLang.label }}
-
+
diff --git a/src/client/theme-default/components/VPNavBarMenuGroup.vue b/src/client/theme-default/components/VPNavBarMenuGroup.vue
index 12e8cf6fd..85350d47c 100644
--- a/src/client/theme-default/components/VPNavBarMenuGroup.vue
+++ b/src/client/theme-default/components/VPNavBarMenuGroup.vue
@@ -11,31 +11,36 @@ const props = defineProps<{
const { page } = useData()
-const isChildActive = (navItem: DefaultTheme.NavItem) => {
+const isActiveGroup = computed(() => {
+ if (props.item.activeMatch) {
+ return isActive(page.value.relativePath, props.item.activeMatch, true)
+ }
+ return isChildActive(props.item)
+})
+
+function isChildActive(navItem: DefaultTheme.NavItem): boolean {
if ('component' in navItem) return false
if ('link' in navItem) {
+ const href =
+ typeof navItem.link === 'function'
+ ? navItem.link(page.value)
+ : navItem.link
+
return isActive(
page.value.relativePath,
- navItem.link,
- !!props.item.activeMatch
+ navItem.activeMatch || href,
+ !!navItem.activeMatch
)
}
return navItem.items.some(isChildActive)
}
-
-const childrenActive = computed(() => isChildActive(props.item))
diff --git a/src/client/theme-default/components/VPNavBarMenuLink.vue b/src/client/theme-default/components/VPNavBarMenuLink.vue
index 6f5047918..bb51a364d 100644
--- a/src/client/theme-default/components/VPNavBarMenuLink.vue
+++ b/src/client/theme-default/components/VPNavBarMenuLink.vue
@@ -1,27 +1,35 @@
-import '@docsearch/css'
import { onKeyStroke } from '@vueuse/core'
import type { DefaultTheme } from 'vitepress/theme'
-import {
- defineAsyncComponent,
- onMounted,
- onUnmounted,
- ref
-} from 'vue'
+import { computed, defineAsyncComponent, onMounted, ref } from 'vue'
import { useData } from '../composables/data'
+import { resolveMode, resolveOptionsForLanguage } from '../support/docsearch'
+import { smartComputed } from '../support/reactivity'
+import VPNavBarAskAiButton from './VPNavBarAskAiButton.vue'
import VPNavBarSearchButton from './VPNavBarSearchButton.vue'
const VPLocalSearchBox = __VP_LOCAL_SEARCH__
@@ -19,7 +16,37 @@ const VPAlgoliaSearchBox = __ALGOLIA__
? defineAsyncComponent(() => import('./VPAlgoliaSearchBox.vue'))
: () => null
-const { theme } = useData()
+const { theme, localeIndex, lang } = useData()
+const provider = __ALGOLIA__ ? 'algolia' : __VP_LOCAL_SEARCH__ ? 'local' : ''
+
+// #region Algolia Search
+
+const algoliaOptions = smartComputed(() => {
+ return resolveOptionsForLanguage(
+ theme.value.search?.options || {},
+ localeIndex.value,
+ lang.value
+ )
+})
+
+const resolvedMode = computed(() => resolveMode(algoliaOptions.value))
+
+const askAiSidePanelConfig = computed(() => {
+ if (!resolvedMode.value.useSidePanel) return null
+ const askAi = algoliaOptions.value.askAi
+ if (!askAi || typeof askAi === 'string') return null
+ if (!askAi.sidePanel) return null
+ return askAi.sidePanel === true ? {} : askAi.sidePanel
+})
+
+const askAiShortcutEnabled = computed(() => {
+ return askAiSidePanelConfig.value?.keyboardShortcuts?.['Ctrl/Cmd+I'] !== false
+})
+
+type OpenTarget = 'search' | 'askAi' | 'toggleAskAi'
+type OpenRequest = { target: OpenTarget; nonce: number }
+const openRequest = ref(null)
+let openNonce = 0
// to avoid loading the docsearch js upfront (which is more than 1/3 of the
// payload), we delay initializing it until the user has actually clicked or
@@ -27,86 +54,74 @@ const { theme } = useData()
const loaded = ref(false)
const actuallyLoaded = ref(false)
-const preconnect = () => {
+onMounted(() => {
+ if (!__ALGOLIA__) return
+
const id = 'VPAlgoliaPreconnect'
+ if (document.getElementById(id)) return
+
+ const appId =
+ algoliaOptions.value.appId ||
+ (typeof algoliaOptions.value.askAi === 'object'
+ ? algoliaOptions.value.askAi?.appId
+ : undefined)
+
+ if (!appId) return
const rIC = window.requestIdleCallback || setTimeout
rIC(() => {
const preconnect = document.createElement('link')
preconnect.id = id
preconnect.rel = 'preconnect'
- preconnect.href = `https://${
- ((theme.value.search?.options as DefaultTheme.AlgoliaSearchOptions) ??
- theme.value.algolia)!.appId
- }-dsn.algolia.net`
+ preconnect.href = `https://${appId}-dsn.algolia.net`
preconnect.crossOrigin = ''
document.head.appendChild(preconnect)
})
-}
-
-onMounted(() => {
- if (!__ALGOLIA__) {
- return
- }
-
- preconnect()
+})
- const handleSearchHotKey = (event: KeyboardEvent) => {
+if (__ALGOLIA__) {
+ onKeyStroke('k', (event) => {
if (
- (event.key?.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey)) ||
- (!isEditingContent(event) && event.key === '/')
+ resolvedMode.value.showKeywordSearch &&
+ (event.ctrlKey || event.metaKey)
) {
event.preventDefault()
- load()
- remove()
+ loadAndOpen('search')
}
- }
-
- const remove = () => {
- window.removeEventListener('keydown', handleSearchHotKey)
- }
+ })
- window.addEventListener('keydown', handleSearchHotKey)
+ onKeyStroke('i', (event) => {
+ if (
+ askAiSidePanelConfig.value &&
+ askAiShortcutEnabled.value &&
+ (event.ctrlKey || event.metaKey)
+ ) {
+ event.preventDefault()
+ loadAndOpen('askAi')
+ }
+ })
- onUnmounted(remove)
-})
+ onKeyStroke('/', (event) => {
+ if (resolvedMode.value.showKeywordSearch && !isEditingContent(event)) {
+ event.preventDefault()
+ loadAndOpen('search')
+ }
+ })
+}
-function load() {
+function loadAndOpen(target: OpenTarget) {
if (!loaded.value) {
loaded.value = true
- setTimeout(poll, 16)
}
-}
-
-function poll() {
- // programmatically open the search box after initialize
- const e = new Event('keydown') as any
- e.key = 'k'
- e.metaKey = true
-
- window.dispatchEvent(e)
-
- setTimeout(() => {
- if (!document.querySelector('.DocSearch-Modal')) {
- poll()
- }
- }, 16)
+ // This will either be handled immediately if DocSearch is ready,
+ // or queued by the AlgoliaSearchBox until its instances become ready.
+ openRequest.value = { target, nonce: ++openNonce }
}
-function isEditingContent(event: KeyboardEvent): boolean {
- const element = event.target as HTMLElement
- const tagName = element.tagName
-
- return (
- element.isContentEditable ||
- tagName === 'INPUT' ||
- tagName === 'SELECT' ||
- tagName === 'TEXTAREA'
- )
-}
+// #endregion
-// Local search
+// #region Local Search
const showSearch = ref(false)
@@ -126,37 +141,60 @@ if (__VP_LOCAL_SEARCH__) {
})
}
-const provider = __ALGOLIA__ ? 'algolia' : __VP_LOCAL_SEARCH__ ? 'local' : ''
+// #endregion
+
+function isEditingContent(event: KeyboardEvent): boolean {
+ const element = event.target as HTMLElement
+ const tagName = element.tagName
+
+ return (
+ element.isContentEditable ||
+ tagName === 'INPUT' ||
+ tagName === 'SELECT' ||
+ tagName === 'TEXTAREA'
+ )
+}
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
diff --git a/src/client/theme-default/components/VPNavBarSearchButton.vue b/src/client/theme-default/components/VPNavBarSearchButton.vue
index 7a6e16f94..7169390b8 100644
--- a/src/client/theme-default/components/VPNavBarSearchButton.vue
+++ b/src/client/theme-default/components/VPNavBarSearchButton.vue
@@ -1,213 +1,67 @@
-
-
diff --git a/src/client/theme-default/components/VPNavBarTranslations.vue b/src/client/theme-default/components/VPNavBarTranslations.vue
index a92aad8c9..e6850d4c5 100644
--- a/src/client/theme-default/components/VPNavBarTranslations.vue
+++ b/src/client/theme-default/components/VPNavBarTranslations.vue
@@ -19,7 +19,13 @@ const { localeLinks, currentLang } = useLangs({ correspondingLink: true })
{{ currentLang.label }}
-
+
diff --git a/src/client/theme-default/components/VPNavScreen.vue b/src/client/theme-default/components/VPNavScreen.vue
index fec143d86..7256d66d1 100644
--- a/src/client/theme-default/components/VPNavScreen.vue
+++ b/src/client/theme-default/components/VPNavScreen.vue
@@ -1,7 +1,6 @@
@@ -21,7 +19,7 @@ const isLocked = useScrollLock(inBrowser ? document.body : null)
@enter="isLocked = true"
@after-leave="isLocked = false"
>
-
+
diff --git a/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue b/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue
index 283cec7c9..0ed634c0f 100644
--- a/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue
+++ b/src/client/theme-default/components/VPNavScreenMenuGroupLink.vue
@@ -1,19 +1,38 @@
diff --git a/src/client/theme-default/components/VPSidebar.vue b/src/client/theme-default/components/VPSidebar.vue
index c2de0a0d8..7e6e25287 100644
--- a/src/client/theme-default/components/VPSidebar.vue
+++ b/src/client/theme-default/components/VPSidebar.vue
@@ -119,7 +119,7 @@ watch(
@media (min-width: 960px) {
.curtain {
position: sticky;
- top: -64px;
+ top: calc(var(--vp-nav-height) * -1);
left: 0;
z-index: 1;
margin-top: calc(var(--vp-nav-height) * -1);
diff --git a/src/client/theme-default/components/VPSkipLink.vue b/src/client/theme-default/components/VPSkipLink.vue
index ad56622d4..965ffdcc2 100644
--- a/src/client/theme-default/components/VPSkipLink.vue
+++ b/src/client/theme-default/components/VPSkipLink.vue
@@ -8,39 +8,18 @@ const route = useRoute()
const backToTop = ref()
watch(() => route.path, () => backToTop.value.focus())
-
-function focusOnTargetAnchor({ target }: Event) {
- const el = document.getElementById(
- decodeURIComponent((target as HTMLAnchorElement).hash).slice(1)
- )
-
- if (el) {
- const removeTabIndex = () => {
- el.removeAttribute('tabindex')
- el.removeEventListener('blur', removeTabIndex)
- }
-
- el.setAttribute('tabindex', '-1')
- el.addEventListener('blur', removeTabIndex)
- el.focus()
- window.scrollTo(0, 0)
- }
-}
-
+
{{ theme.skipToContentLabel || 'Skip to content' }}