├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── config.yml └── workflows │ ├── check-docs.yml │ ├── docs.yml │ ├── issue-commented.yml │ ├── issue-daily.yml │ ├── issue-labeled.yml │ └── release.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .npmrc ├── .prettierignore ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── CONTRIBUTING_zh.md ├── LICENSE ├── README.md ├── docs ├── .vuepress │ ├── components │ │ └── NpmBadge.vue │ ├── config.ts │ ├── configs │ │ ├── head.ts │ │ ├── index.ts │ │ ├── meta.ts │ │ ├── navbar │ │ │ ├── en.ts │ │ │ ├── index.ts │ │ │ └── zh.ts │ │ └── sidebar │ │ │ ├── en.ts │ │ │ ├── index.ts │ │ │ └── zh.ts │ ├── public │ │ ├── browserconfig.xml │ │ ├── favicon.ico │ │ ├── images │ │ │ ├── cookbook │ │ │ │ └── extending-a-theme-01.png │ │ │ ├── guide │ │ │ │ ├── vuepress-architecture-overview.png │ │ │ │ └── vuepress-core-process.png │ │ │ ├── hero.png │ │ │ ├── icons │ │ │ │ ├── android-chrome-192x192.png │ │ │ │ ├── android-chrome-384x384.png │ │ │ │ ├── apple-touch-icon.png │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ ├── mstile-150x150.png │ │ │ │ └── safari-pinned-tab.svg │ │ │ └── logo.png │ │ ├── manifest.webmanifest │ │ └── new.html │ └── styles │ │ └── index.scss ├── README.md ├── advanced │ ├── architecture.md │ ├── cookbook │ │ ├── README.md │ │ ├── adding-extra-pages.md │ │ ├── making-a-theme-extendable.md │ │ ├── markdown-and-vue-sfc.md │ │ ├── passing-data-to-client-code.md │ │ ├── resolving-routes.md │ │ └── usage-of-client-config.md │ ├── plugin.md │ └── theme.md ├── guide │ ├── assets.md │ ├── bundler.md │ ├── configuration.md │ ├── deployment.md │ ├── getting-started.md │ ├── i18n.md │ ├── introduction.md │ ├── markdown.md │ ├── migration.md │ ├── page.md │ ├── plugin.md │ ├── theme.md │ └── troubleshooting.md ├── reference │ ├── bundler │ │ ├── vite.md │ │ └── webpack.md │ ├── cli.md │ ├── client-api.md │ ├── components.md │ ├── config.md │ ├── frontmatter.md │ ├── node-api.md │ ├── plugin-api.md │ └── theme-api.md └── zh │ ├── README.md │ ├── advanced │ ├── architecture.md │ ├── cookbook │ │ ├── README.md │ │ ├── adding-extra-pages.md │ │ ├── making-a-theme-extendable.md │ │ ├── markdown-and-vue-sfc.md │ │ ├── passing-data-to-client-code.md │ │ ├── resolving-routes.md │ │ └── usage-of-client-config.md │ ├── plugin.md │ └── theme.md │ ├── guide │ ├── assets.md │ ├── bundler.md │ ├── configuration.md │ ├── deployment.md │ ├── getting-started.md │ ├── i18n.md │ ├── introduction.md │ ├── markdown.md │ ├── migration.md │ ├── page.md │ ├── plugin.md │ ├── theme.md │ └── troubleshooting.md │ └── reference │ ├── bundler │ ├── vite.md │ └── webpack.md │ ├── cli.md │ ├── client-api.md │ ├── components.md │ ├── config.md │ ├── frontmatter.md │ ├── node-api.md │ ├── plugin-api.md │ └── theme-api.md ├── eslint.config.js ├── package.json ├── pnpm-lock.yaml ├── taze.config.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.txt text eol=crlf 3 | 4 | *.png binary 5 | *.jpg binary 6 | *.jpeg binary 7 | *.ico binary 8 | *.tff binary 9 | *.woff binary 10 | *.woff2 binary 11 | 12 | docs/.vuepress/** -linguist-documentation 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Create a report to help us improve 3 | title: '[Bug report] ' 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to fill out this bug report! 9 | - type: textarea 10 | id: bug-description 11 | attributes: 12 | label: Description 13 | description: A clear and concise description of what the bug is. If applicable, add screenshots to help explain your problem. If you intend to submit a PR for this issue, tell us in the description. Thanks! 14 | placeholder: Bug description 15 | validations: 16 | required: true 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question & Discussion 4 | url: https://github.com/vuepress/docs/discussions 5 | about: Please ask and answer questions here. 6 | -------------------------------------------------------------------------------- /.github/workflows/check-docs.yml: -------------------------------------------------------------------------------- 1 | name: check-docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | jobs: 13 | check-docs: 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | os: 18 | - ubuntu-latest 19 | - windows-latest 20 | - macos-latest 21 | node: 22 | - 20 23 | - 22 24 | bundler: 25 | - vite 26 | - webpack 27 | 28 | runs-on: ${{ matrix.os }} 29 | 30 | steps: 31 | - uses: actions/checkout@v4 32 | 33 | - name: Install pnpm 34 | uses: pnpm/action-setup@v4 35 | 36 | - name: Use Node.js ${{ matrix.node }} 37 | uses: actions/setup-node@v4 38 | with: 39 | node-version: ${{ matrix.node }} 40 | cache: pnpm 41 | 42 | - name: Install dependencies 43 | run: pnpm install --frozen-lockfile 44 | 45 | - name: Lint 46 | run: pnpm lint 47 | 48 | - name: Build docs with ${{ matrix.bundler }} 49 | run: pnpm docs:build 50 | env: 51 | DOCS_BUNDLER: ${{ matrix.bundler }} 52 | 53 | check-docs-result: 54 | if: ${{ always() }} 55 | name: check-docs result 56 | runs-on: ubuntu-latest 57 | needs: 58 | - check-docs 59 | steps: 60 | - if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} 61 | run: exit 1 62 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | jobs: 10 | docs: 11 | runs-on: ubuntu-latest 12 | 13 | env: 14 | DOCS_GA_ID: G-CTB8FQ7VMW 15 | NODE_VERSION: '22' 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Install pnpm 23 | uses: pnpm/action-setup@v4 24 | 25 | - name: Setup Node.js 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: ${{ env.NODE_VERSION }} 29 | cache: pnpm 30 | 31 | - name: Install dependencies 32 | run: pnpm install --frozen-lockfile 33 | 34 | - name: Build documentation site 35 | run: pnpm docs:build 36 | 37 | - name: Deploy to GitHub Pages 38 | uses: crazy-max/ghaction-github-pages@v4 39 | with: 40 | repo: vuepress/vuepress.github.io 41 | target_branch: main 42 | build_dir: docs/.vuepress/dist 43 | env: 44 | GH_PAT: ${{ secrets.GH_PAGES_TOKEN }} 45 | -------------------------------------------------------------------------------- /.github/workflows/issue-commented.yml: -------------------------------------------------------------------------------- 1 | name: issue-commented 2 | 3 | on: 4 | issue_comment: 5 | types: 6 | - created 7 | 8 | jobs: 9 | issue-commented: 10 | name: remove stale on commented 11 | if: contains(github.event.issue.labels.*.name, 'stale') 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions-cool/issues-helper@v3 15 | with: 16 | actions: 'remove-labels' 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | labels: 'stale' 19 | -------------------------------------------------------------------------------- /.github/workflows/issue-daily.yml: -------------------------------------------------------------------------------- 1 | name: issue-daily 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | issue-label-stale: 9 | name: label stale issues 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions-cool/issues-helper@v3 13 | with: 14 | actions: 'check-inactive' 15 | token: ${{ secrets.GITHUB_TOKEN }} 16 | inactive-day: 15 17 | inactive-label: 'stale' 18 | exclude-labels: 'bug, documentation, enhancement, feature, help wanted, need reproduction, need review, stale' 19 | body: | 20 | This issue is marked as `stale` because it has not had recent activity. Issues marked with `stale` will be closed if they have no activity within 7 days. 21 | 22 | issue-close-stale: 23 | name: close stale issues 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions-cool/issues-helper@v3 27 | with: 28 | actions: 'close-issues' 29 | token: ${{ secrets.GITHUB_TOKEN }} 30 | labels: 'stale' 31 | inactive-day: 7 32 | 33 | issue-close-need-reproduction: 34 | name: close need-reproduction issues 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions-cool/issues-helper@v3 38 | with: 39 | actions: 'close-issues' 40 | token: ${{ secrets.GITHUB_TOKEN }} 41 | labels: 'need reproduction' 42 | inactive-day: 7 43 | -------------------------------------------------------------------------------- /.github/workflows/issue-labeled.yml: -------------------------------------------------------------------------------- 1 | name: issue-labeled 2 | 3 | on: 4 | issues: 5 | types: [labeled] 6 | 7 | jobs: 8 | issue-invalid: 9 | name: close invalid issue 10 | if: github.event.label.name == 'invalid' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions-cool/issues-helper@v3 14 | with: 15 | actions: 'close-issue, create-comment' 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | body: | 18 | Hello @${{ github.event.issue.user.login }}. This issue is marked as `invalid` and closed. Please follow the issue template. 19 | 20 | issue-need-reproduction: 21 | name: need reproduction 22 | if: github.event.label.name == 'need reproduction' 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions-cool/issues-helper@v3 26 | with: 27 | actions: 'create-comment' 28 | token: ${{ secrets.GITHUB_TOKEN }} 29 | body: | 30 | Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or [vuepress.vuejs.org/new](https://vuepress.vuejs.org/new). Issues marked with `need reproduction` will be closed if they have no activity within 7 days. 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Push to release branch 19 | run: git push origin HEAD:release 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # VuePress files 2 | docs/.vuepress/.temp/ 3 | docs/.vuepress/.cache/ 4 | docs/.vuepress/dist/ 5 | 6 | # Node modules 7 | node_modules/ 8 | 9 | # MacOS Desktop Services Store 10 | .DS_Store 11 | 12 | # Log files 13 | *.log 14 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | pnpm commitlint --edit $1 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm nano-staged 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | message="build: version %s" 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | pnpm-lock.yaml 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "vue.volar" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "editor.insertSpaces": true, 5 | "editor.tabSize": 2, 6 | "files.encoding": "utf8", 7 | "files.eol": "\n", 8 | "files.trimFinalNewlines": true, 9 | "files.trimTrailingWhitespace": true, 10 | "[markdown]": { 11 | "files.trimTrailingWhitespace": false 12 | }, 13 | "typescript.tsdk": "node_modules/typescript/lib", 14 | "eslint.validate": [ 15 | "javascript", 16 | "javascriptreact", 17 | "typescript", 18 | "typescriptreact", 19 | "vue" 20 | ], 21 | "cSpell.words": [ 22 | "bumpp", 23 | "composables", 24 | "devtool", 25 | "docsearch", 26 | "envinfo", 27 | "esbuild", 28 | "frontmatter", 29 | "globby", 30 | "gtag", 31 | "mdit", 32 | "nprogress", 33 | "prefetch", 34 | "preload", 35 | "prismjs", 36 | "shiki", 37 | "shikiji", 38 | "slugify", 39 | "unmount", 40 | "vuejs", 41 | "vuepress", 42 | "vueuse", 43 | "zoomable" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # VuePress Documentation Contributing Guide 2 | 3 | ## Overview 4 | 5 | VuePress documentation is powered by VuePress itself, which is built from the source code of this repository. 6 | 7 | All the markdown source files are placed in `docs` directory. We are maintaining two translations: 8 | 9 | - English (en-US) in `/` path 10 | - Chinese (zh-CN) in `/zh/` path 11 | 12 | We have two different deployments: 13 | 14 | - Release deployment powered by [Netlify](https://www.netlify.com). This deployment is built from the latest released version, so users will not see unreleased changes. The domain name is [https://vuepress.vuejs.org](https://vuepress.vuejs.org). 15 | - Developer deployment powered by [GitHub Pages](https://pages.github.com). This deployment is built from the latest commit, so developers could preview the latest changes. The domain name is [https://vuepress.github.io](https://vuepress.github.io). 16 | -------------------------------------------------------------------------------- /CONTRIBUTING_zh.md: -------------------------------------------------------------------------------- 1 | # VuePress 文档贡献指南 2 | 3 | ## 概览 4 | 5 | VuePress 的文档是由 VuePress 自己驱动的,是由该仓库中的源码构建而来。 6 | 7 | 所有的 Markdown 源文件都放置在 `docs` 目录下。我们维护了两种翻译: 8 | 9 | - 英语 (en-US) 在 `/` 路径下 10 | - 中文 (zh-CN) 在 `/zh/` 路径下 11 | 12 | 我们部署了两套站点: 13 | 14 | - 在 [Netlify](https://www.netlify.com) 部署的 Release 版本。该站点是从最新发布的版本中构建而来,因此用户不会看到未发布的改动。域名为 [https://vuepress.vuejs.org](https://vuepress.vuejs.org)。 15 | - 在 [GitHub Pages](https://pages.github.com) 部署的 Developer 版本。该站点是从最新的提交中构建而来,因此开发者可以预览最新的改动。域名为 [https://vuepress.github.io](https://vuepress.github.io)。 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, VuePress Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VuePress Documentation 2 | 3 | [![github check-docs](https://github.com/vuepress/docs/workflows/check-docs/badge.svg)](https://github.com/vuepress/docs/actions/workflows/check-docs.yml) 4 | [![github docs](https://github.com/vuepress/docs/workflows/docs/badge.svg)](https://github.com/vuepress/docs/actions/workflows/docs.yml) 5 | [![license](https://badgen.net/github/license/vuepress/docs)](https://github.com/vuepress/docs/blob/main/LICENSE) 6 | 7 | VuePress documentation repository. 8 | 9 | ## Deployments 10 | 11 | - Release deployment: 12 | - Developer deployment: 13 | 14 | ## License 15 | 16 | [MIT](https://github.com/vuepress/docs/blob/main/LICENSE) 17 | -------------------------------------------------------------------------------- /docs/.vuepress/components/NpmBadge.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 44 | 45 | 50 | -------------------------------------------------------------------------------- /docs/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | import { createRequire } from 'node:module' 2 | import process from 'node:process' 3 | import { viteBundler } from '@vuepress/bundler-vite' 4 | import { webpackBundler } from '@vuepress/bundler-webpack' 5 | import { docsearchPlugin } from '@vuepress/plugin-docsearch' 6 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' 7 | import { registerComponentsPlugin } from '@vuepress/plugin-register-components' 8 | import { shikiPlugin } from '@vuepress/plugin-shiki' 9 | import { defaultTheme } from '@vuepress/theme-default' 10 | import { defineUserConfig } from 'vuepress' 11 | import { getDirname, path } from 'vuepress/utils' 12 | import { 13 | head, 14 | navbarEn, 15 | navbarZh, 16 | sidebarEn, 17 | sidebarZh, 18 | } from './configs/index.js' 19 | 20 | const __dirname = getDirname(import.meta.url) 21 | const require = createRequire(import.meta.url) 22 | const isProd = process.env.NODE_ENV === 'production' 23 | 24 | export default defineUserConfig({ 25 | // set site base to default value 26 | base: '/', 27 | 28 | // extra tags in `` 29 | head, 30 | 31 | // site-level locales config 32 | locales: { 33 | '/': { 34 | lang: 'en-US', 35 | title: 'VuePress', 36 | description: 'Vue-powered Static Site Generator', 37 | }, 38 | '/zh/': { 39 | lang: 'zh-CN', 40 | title: 'VuePress', 41 | description: 'Vue 驱动的静态网站生成器', 42 | }, 43 | }, 44 | 45 | // specify bundler via environment variable 46 | bundler: 47 | process.env.DOCS_BUNDLER === 'webpack' ? webpackBundler() : viteBundler(), 48 | 49 | // configure default theme 50 | theme: defaultTheme({ 51 | hostname: 'https://vuepress.vuejs.org', 52 | logo: '/images/hero.png', 53 | repo: 'vuepress/core', 54 | docsRepo: 'vuepress/docs', 55 | docsDir: 'docs', 56 | 57 | // theme-level locales config 58 | locales: { 59 | /** 60 | * English locale config 61 | * 62 | * As the default locale of @vuepress/theme-default is English, 63 | * we don't need to set all of the locale fields 64 | */ 65 | '/': { 66 | // navbar 67 | navbar: navbarEn, 68 | // sidebar 69 | sidebar: sidebarEn, 70 | // page meta 71 | editLinkText: 'Edit this page on GitHub', 72 | }, 73 | 74 | /** 75 | * Chinese locale config 76 | */ 77 | '/zh/': { 78 | // navbar 79 | navbar: navbarZh, 80 | selectLanguageName: '简体中文', 81 | selectLanguageText: '选择语言', 82 | selectLanguageAriaLabel: '选择语言', 83 | // sidebar 84 | sidebar: sidebarZh, 85 | // page meta 86 | editLinkText: '在 GitHub 上编辑此页', 87 | lastUpdatedText: '上次更新', 88 | contributorsText: '贡献者', 89 | // custom containers 90 | tip: '提示', 91 | warning: '注意', 92 | danger: '警告', 93 | // 404 page 94 | notFound: [ 95 | '这里什么都没有', 96 | '我们怎么到这来了?', 97 | '这是一个 404 页面', 98 | '看起来我们进入了错误的链接', 99 | ], 100 | backToHome: '返回首页', 101 | // a11y 102 | openInNewWindow: '在新窗口打开', 103 | toggleColorMode: '切换颜色模式', 104 | toggleSidebar: '切换侧边栏', 105 | }, 106 | }, 107 | 108 | themePlugins: { 109 | // only enable git plugin in production mode 110 | git: isProd, 111 | // use shiki plugin in production mode instead 112 | prismjs: !isProd, 113 | }, 114 | }), 115 | 116 | // configure markdown 117 | markdown: { 118 | importCode: { 119 | handleImportPath: (importPath) => { 120 | // handle @vuepress packages import path 121 | if (importPath.startsWith('@vuepress/')) { 122 | const packageName = importPath.match(/^(@vuepress\/[^/]*)/)![1] 123 | return importPath 124 | .replace( 125 | packageName, 126 | path.dirname(require.resolve(`${packageName}/package.json`)), 127 | ) 128 | .replace('/src/', '/lib/') 129 | .replace(/hotKey\.ts$/, 'hotKey.d.ts') 130 | } 131 | return importPath 132 | }, 133 | }, 134 | }, 135 | 136 | // use plugins 137 | plugins: [ 138 | docsearchPlugin({ 139 | appId: '34YFD9IUQ2', 140 | apiKey: '9a9058b8655746634e01071411c366b8', 141 | indexName: 'vuepress', 142 | searchParameters: { 143 | facetFilters: ['tags:v2'], 144 | }, 145 | locales: { 146 | '/zh/': { 147 | placeholder: '搜索文档', 148 | translations: { 149 | button: { 150 | buttonText: '搜索文档', 151 | buttonAriaLabel: '搜索文档', 152 | }, 153 | modal: { 154 | searchBox: { 155 | resetButtonTitle: '清除查询条件', 156 | resetButtonAriaLabel: '清除查询条件', 157 | cancelButtonText: '取消', 158 | cancelButtonAriaLabel: '取消', 159 | }, 160 | startScreen: { 161 | recentSearchesTitle: '搜索历史', 162 | noRecentSearchesText: '没有搜索历史', 163 | saveRecentSearchButtonTitle: '保存至搜索历史', 164 | removeRecentSearchButtonTitle: '从搜索历史中移除', 165 | favoriteSearchesTitle: '收藏', 166 | removeFavoriteSearchButtonTitle: '从收藏中移除', 167 | }, 168 | errorScreen: { 169 | titleText: '无法获取结果', 170 | helpText: '你可能需要检查你的网络连接', 171 | }, 172 | footer: { 173 | selectText: '选择', 174 | navigateText: '切换', 175 | closeText: '关闭', 176 | searchByText: '搜索提供者', 177 | }, 178 | noResultsScreen: { 179 | noResultsText: '无法找到相关结果', 180 | suggestedQueryText: '你可以尝试查询', 181 | reportMissingResultsText: '你认为该查询应该有结果?', 182 | reportMissingResultsLinkText: '点击反馈', 183 | }, 184 | }, 185 | }, 186 | }, 187 | }, 188 | }), 189 | googleAnalyticsPlugin({ 190 | // we have multiple deployments, which would use different id 191 | id: process.env.DOCS_GA_ID ?? '', 192 | }), 193 | registerComponentsPlugin({ 194 | componentsDir: path.resolve(__dirname, './components'), 195 | }), 196 | // only enable shiki plugin in production mode 197 | isProd 198 | ? shikiPlugin({ 199 | langs: ['bash', 'diff', 'json', 'md', 'ts', 'vue'], 200 | theme: 'dark-plus', 201 | }) 202 | : [], 203 | ], 204 | }) 205 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/head.ts: -------------------------------------------------------------------------------- 1 | import type { HeadConfig } from 'vuepress/core' 2 | 3 | // eslint-disable-next-line @typescript-eslint/naming-convention 4 | export const head: HeadConfig[] = [ 5 | [ 6 | 'link', 7 | { 8 | rel: 'icon', 9 | type: 'image/png', 10 | sizes: '16x16', 11 | href: `/images/icons/favicon-16x16.png`, 12 | }, 13 | ], 14 | [ 15 | 'link', 16 | { 17 | rel: 'icon', 18 | type: 'image/png', 19 | sizes: '32x32', 20 | href: `/images/icons/favicon-32x32.png`, 21 | }, 22 | ], 23 | ['link', { rel: 'manifest', href: '/manifest.webmanifest' }], 24 | ['meta', { name: 'application-name', content: 'VuePress' }], 25 | ['meta', { name: 'apple-mobile-web-app-title', content: 'VuePress' }], 26 | ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }], 27 | [ 28 | 'link', 29 | { rel: 'apple-touch-icon', href: `/images/icons/apple-touch-icon.png` }, 30 | ], 31 | [ 32 | 'link', 33 | { 34 | rel: 'mask-icon', 35 | href: '/images/icons/safari-pinned-tab.svg', 36 | color: '#3eaf7c', 37 | }, 38 | ], 39 | ['meta', { name: 'msapplication-TileColor', content: '#3eaf7c' }], 40 | ['meta', { name: 'theme-color', content: '#3eaf7c' }], 41 | ] 42 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './head.js' 2 | export * from './navbar/index.js' 3 | export * from './sidebar/index.js' 4 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/meta.ts: -------------------------------------------------------------------------------- 1 | import { createRequire } from 'node:module' 2 | import { fs } from 'vuepress/utils' 3 | 4 | const require = createRequire(import.meta.url) 5 | 6 | export const VERSION = ( 7 | fs.readJsonSync(require.resolve('vuepress/package.json')) as { 8 | version: string 9 | } 10 | ).version 11 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/navbar/en.ts: -------------------------------------------------------------------------------- 1 | import type { NavbarOptions } from '@vuepress/theme-default' 2 | import { VERSION } from '../meta.js' 3 | 4 | export const navbarEn: NavbarOptions = [ 5 | { 6 | text: 'Guide', 7 | children: [ 8 | '/guide/introduction.md', 9 | '/guide/getting-started.md', 10 | '/guide/configuration.md', 11 | '/guide/page.md', 12 | '/guide/markdown.md', 13 | '/guide/assets.md', 14 | '/guide/i18n.md', 15 | '/guide/deployment.md', 16 | '/guide/theme.md', 17 | '/guide/plugin.md', 18 | '/guide/bundler.md', 19 | '/guide/migration.md', 20 | '/guide/troubleshooting.md', 21 | ], 22 | }, 23 | { 24 | text: 'Reference', 25 | children: [ 26 | { 27 | text: 'Core', 28 | children: [ 29 | { 30 | text: 'CLI', 31 | link: '/reference/cli.html', 32 | }, 33 | '/reference/config.md', 34 | '/reference/frontmatter.md', 35 | '/reference/components.md', 36 | '/reference/plugin-api.md', 37 | '/reference/theme-api.md', 38 | '/reference/client-api.md', 39 | '/reference/node-api.md', 40 | ], 41 | }, 42 | { 43 | text: 'Bundlers', 44 | children: [ 45 | '/reference/bundler/vite.md', 46 | '/reference/bundler/webpack.md', 47 | ], 48 | }, 49 | { 50 | text: 'Ecosystem', 51 | children: [ 52 | { 53 | text: 'Default Theme', 54 | link: 'https://ecosystem.vuejs.press/themes/default/', 55 | }, 56 | { 57 | text: 'Plugins', 58 | link: 'https://ecosystem.vuejs.press/plugins/', 59 | }, 60 | ], 61 | }, 62 | ], 63 | }, 64 | 65 | { 66 | text: 'Learn More', 67 | children: [ 68 | { 69 | text: 'Advanced', 70 | children: [ 71 | '/advanced/architecture.md', 72 | '/advanced/plugin.md', 73 | '/advanced/theme.md', 74 | { 75 | text: 'Cookbook', 76 | link: '/advanced/cookbook/', 77 | }, 78 | ], 79 | }, 80 | { 81 | text: 'Resources', 82 | children: [ 83 | { 84 | text: 'Ecosystem', 85 | link: 'https://ecosystem.vuejs.press/', 86 | }, 87 | { 88 | text: 'MarketPlace', 89 | link: 'https://marketplace.vuejs.press', 90 | }, 91 | { 92 | text: 'Contributing Guide', 93 | link: 'https://github.com/vuepress/core/blob/main/CONTRIBUTING.md', 94 | }, 95 | ], 96 | }, 97 | ], 98 | }, 99 | { 100 | text: `v${VERSION}`, 101 | children: [ 102 | { 103 | text: 'Changelog', 104 | link: 'https://github.com/vuepress/core/blob/main/CHANGELOG.md', 105 | }, 106 | { 107 | text: 'v1.x', 108 | link: 'https://v1.vuepress.vuejs.org', 109 | }, 110 | { 111 | text: 'v0.x', 112 | link: 'https://v0.vuepress.vuejs.org', 113 | }, 114 | ], 115 | }, 116 | // TODO: remove the type assertion 117 | ] as NavbarOptions 118 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './en.js' 2 | export * from './zh.js' 3 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/navbar/zh.ts: -------------------------------------------------------------------------------- 1 | import type { NavbarOptions } from '@vuepress/theme-default' 2 | import { VERSION } from '../meta.js' 3 | 4 | export const navbarZh: NavbarOptions = [ 5 | { 6 | text: '指南', 7 | children: [ 8 | '/zh/guide/introduction.md', 9 | '/zh/guide/getting-started.md', 10 | '/zh/guide/configuration.md', 11 | '/zh/guide/page.md', 12 | '/zh/guide/markdown.md', 13 | '/zh/guide/assets.md', 14 | '/zh/guide/i18n.md', 15 | '/zh/guide/deployment.md', 16 | '/zh/guide/theme.md', 17 | '/zh/guide/plugin.md', 18 | '/zh/guide/bundler.md', 19 | '/zh/guide/migration.md', 20 | '/zh/guide/troubleshooting.md', 21 | ], 22 | }, 23 | { 24 | text: '参考', 25 | children: [ 26 | { 27 | text: '核心', 28 | children: [ 29 | '/zh/reference/cli.md', 30 | '/zh/reference/config.md', 31 | '/zh/reference/frontmatter.md', 32 | '/zh/reference/components.md', 33 | '/zh/reference/plugin-api.md', 34 | '/zh/reference/theme-api.md', 35 | '/zh/reference/client-api.md', 36 | '/zh/reference/node-api.md', 37 | ], 38 | }, 39 | { 40 | text: '打包工具', 41 | children: [ 42 | '/zh/reference/bundler/vite.md', 43 | '/zh/reference/bundler/webpack.md', 44 | ], 45 | }, 46 | { 47 | text: '生态系统', 48 | children: [ 49 | { 50 | text: '默认主题', 51 | link: 'https://ecosystem.vuejs.press/zh/themes/default/', 52 | }, 53 | { 54 | text: '插件', 55 | link: 'https://ecosystem.vuejs.press/zh/plugins/', 56 | }, 57 | ], 58 | }, 59 | ], 60 | }, 61 | { 62 | text: '了解更多', 63 | children: [ 64 | { 65 | text: '深入', 66 | children: [ 67 | '/zh/advanced/architecture.md', 68 | '/zh/advanced/plugin.md', 69 | '/zh/advanced/theme.md', 70 | { 71 | text: 'Cookbook', 72 | link: '/zh/advanced/cookbook/', 73 | }, 74 | ], 75 | }, 76 | { 77 | text: '其他资源', 78 | children: [ 79 | { 80 | text: '生态系统', 81 | link: 'https://ecosystem.vuejs.press/zh/', 82 | }, 83 | { 84 | text: '市场', 85 | link: 'https://marketplace.vuejs.press/zh/', 86 | }, 87 | { 88 | text: '贡献指南', 89 | link: 'https://github.com/vuepress/core/blob/main/CONTRIBUTING_zh.md', 90 | }, 91 | ], 92 | }, 93 | ], 94 | }, 95 | { 96 | text: `v${VERSION}`, 97 | children: [ 98 | { 99 | text: '更新日志', 100 | link: 'https://github.com/vuepress/core/blob/main/CHANGELOG.md', 101 | }, 102 | { 103 | text: 'v1.x', 104 | link: 'https://v1.vuepress.vuejs.org/zh/', 105 | }, 106 | { 107 | text: 'v0.x', 108 | link: 'https://v0.vuepress.vuejs.org/zh/', 109 | }, 110 | ], 111 | }, 112 | // TODO: remove the type assertion 113 | ] as NavbarOptions 114 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/sidebar/en.ts: -------------------------------------------------------------------------------- 1 | import type { SidebarOptions } from '@vuepress/theme-default' 2 | 3 | export const sidebarEn: SidebarOptions = { 4 | '/guide/': [ 5 | { 6 | text: 'Guide', 7 | children: [ 8 | '/guide/introduction.md', 9 | '/guide/getting-started.md', 10 | '/guide/configuration.md', 11 | '/guide/page.md', 12 | '/guide/markdown.md', 13 | '/guide/assets.md', 14 | '/guide/i18n.md', 15 | '/guide/deployment.md', 16 | '/guide/theme.md', 17 | '/guide/plugin.md', 18 | '/guide/bundler.md', 19 | '/guide/migration.md', 20 | '/guide/troubleshooting.md', 21 | ], 22 | }, 23 | ], 24 | '/advanced/': [ 25 | { 26 | text: 'Advanced', 27 | children: [ 28 | '/advanced/architecture.md', 29 | '/advanced/plugin.md', 30 | '/advanced/theme.md', 31 | ], 32 | }, 33 | { 34 | text: 'Cookbook', 35 | children: [ 36 | '/advanced/cookbook/README.md', 37 | '/advanced/cookbook/usage-of-client-config.md', 38 | '/advanced/cookbook/adding-extra-pages.md', 39 | '/advanced/cookbook/making-a-theme-extendable.md', 40 | '/advanced/cookbook/passing-data-to-client-code.md', 41 | '/advanced/cookbook/markdown-and-vue-sfc.md', 42 | '/advanced/cookbook/resolving-routes.md', 43 | ], 44 | }, 45 | ], 46 | '/reference/': [ 47 | { 48 | text: 'Core', 49 | collapsible: true, 50 | children: [ 51 | '/reference/cli.md', 52 | '/reference/config.md', 53 | '/reference/frontmatter.md', 54 | '/reference/components.md', 55 | '/reference/plugin-api.md', 56 | '/reference/theme-api.md', 57 | '/reference/client-api.md', 58 | '/reference/node-api.md', 59 | ], 60 | }, 61 | { 62 | text: 'Bundlers', 63 | children: ['/reference/bundler/vite.md', '/reference/bundler/webpack.md'], 64 | }, 65 | { 66 | text: 'Ecosystem', 67 | children: [ 68 | { 69 | text: 'Default Theme', 70 | link: 'https://ecosystem.vuejs.press/themes/default/', 71 | }, 72 | { 73 | text: 'Plugins', 74 | link: 'https://ecosystem.vuejs.press/plugins/', 75 | }, 76 | ], 77 | }, 78 | ], 79 | } 80 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/sidebar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './en.js' 2 | export * from './zh.js' 3 | -------------------------------------------------------------------------------- /docs/.vuepress/configs/sidebar/zh.ts: -------------------------------------------------------------------------------- 1 | import type { SidebarOptions } from '@vuepress/theme-default' 2 | 3 | export const sidebarZh: SidebarOptions = { 4 | '/zh/guide/': [ 5 | { 6 | text: '指南', 7 | children: [ 8 | '/zh/guide/introduction.md', 9 | '/zh/guide/getting-started.md', 10 | '/zh/guide/configuration.md', 11 | '/zh/guide/page.md', 12 | '/zh/guide/markdown.md', 13 | '/zh/guide/assets.md', 14 | '/zh/guide/i18n.md', 15 | '/zh/guide/deployment.md', 16 | '/zh/guide/theme.md', 17 | '/zh/guide/plugin.md', 18 | '/zh/guide/bundler.md', 19 | '/zh/guide/migration.md', 20 | '/zh/guide/troubleshooting.md', 21 | ], 22 | }, 23 | ], 24 | '/zh/advanced/': [ 25 | { 26 | text: '深入', 27 | children: [ 28 | '/zh/advanced/architecture.md', 29 | '/zh/advanced/plugin.md', 30 | '/zh/advanced/theme.md', 31 | ], 32 | }, 33 | { 34 | text: 'Cookbook', 35 | children: [ 36 | '/zh/advanced/cookbook/README.md', 37 | '/zh/advanced/cookbook/usage-of-client-config.md', 38 | '/zh/advanced/cookbook/adding-extra-pages.md', 39 | '/zh/advanced/cookbook/making-a-theme-extendable.md', 40 | '/zh/advanced/cookbook/passing-data-to-client-code.md', 41 | '/zh/advanced/cookbook/markdown-and-vue-sfc.md', 42 | '/zh/advanced/cookbook/resolving-routes.md', 43 | ], 44 | }, 45 | ], 46 | '/zh/reference/': [ 47 | { 48 | text: '核心', 49 | collapsible: true, 50 | children: [ 51 | '/zh/reference/cli.md', 52 | '/zh/reference/config.md', 53 | '/zh/reference/frontmatter.md', 54 | '/zh/reference/components.md', 55 | '/zh/reference/plugin-api.md', 56 | '/zh/reference/theme-api.md', 57 | '/zh/reference/client-api.md', 58 | '/zh/reference/node-api.md', 59 | ], 60 | }, 61 | { 62 | text: '打包工具', 63 | children: [ 64 | '/zh/reference/bundler/vite.md', 65 | '/zh/reference/bundler/webpack.md', 66 | ], 67 | }, 68 | { 69 | text: '生态系统', 70 | children: [ 71 | { 72 | text: '默认主题', 73 | link: 'https://ecosystem.vuejs.press/zh/themes/default/', 74 | }, 75 | { 76 | text: '插件', 77 | link: 'https://ecosystem.vuejs.press/zh/plugins/', 78 | }, 79 | ], 80 | }, 81 | ], 82 | } 83 | -------------------------------------------------------------------------------- /docs/.vuepress/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/public/images/cookbook/extending-a-theme-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/cookbook/extending-a-theme-01.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/guide/vuepress-architecture-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/guide/vuepress-architecture-overview.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/guide/vuepress-core-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/guide/vuepress-core-process.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/hero.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/android-chrome-384x384.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/icons/mstile-150x150.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/.vuepress/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuepress/docs/ef2a7f0980ec6ef4a1736044aef0601f067c986e/docs/.vuepress/public/images/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/public/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "VuePress", 3 | "short_name": "VuePress", 4 | "description": "Vue-powered Static Site Generator", 5 | "start_url": "/index.html", 6 | "display": "standalone", 7 | "background_color": "#fff", 8 | "theme_color": "#3eaf7c", 9 | "icons": [ 10 | { 11 | "src": "/images/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png" 14 | }, 15 | { 16 | "src": "/images/icons/android-chrome-384x384.png", 17 | "sizes": "384x384", 18 | "type": "image/png" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /docs/.vuepress/public/new.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | scroll-behavior: smooth; 3 | } 4 | 5 | @media (min-width: 751px) { 6 | #docsearch-container:lang(zh-CN) { 7 | min-width: 184.66px; 8 | } 9 | } 10 | 11 | // FIXME: Workaround solution 12 | div[class*='language-'] pre code { 13 | color: var(--code-c-text); 14 | } 15 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | title: Home 4 | heroImage: /images/hero.png 5 | actions: 6 | - text: Get Started 7 | link: /guide/getting-started.html 8 | type: primary 9 | 10 | - text: Introduction 11 | link: /guide/introduction.html 12 | type: secondary 13 | 14 | features: 15 | - title: Simplicity First 16 | details: Minimal setup with markdown-centered project structure helps you focus on writing. 17 | 18 | - title: Vue-Powered 19 | details: Enjoy the dev experience of Vue, use Vue components in markdown, and develop custom themes with Vue. 20 | 21 | - title: Performant 22 | details: VuePress generates pre-rendered static HTML for each page, and runs as an SPA once a page is loaded. 23 | 24 | - title: Themes 25 | details: Providing a default theme out of the box. You can also choose a community theme or create your own one. 26 | 27 | - title: Plugins 28 | details: Flexible plugin API, allowing plugins to provide lots of plug-and-play features for your site. 29 | 30 | - title: Bundlers 31 | details: Recommended bundler is Vite, while Webpack is also supported. Choose the one you like! 32 | 33 | footer: MIT Licensed | Copyright © 2018-present VuePress Community 34 | --- 35 | -------------------------------------------------------------------------------- /docs/advanced/architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | 3 | ## Overview 4 | 5 | ![vuepress-architecture-overview](/images/guide/vuepress-architecture-overview.png) 6 | 7 | The above figure shows a brief overview of the VuePress architecture: 8 | 9 | - Node App will generate temp files, including the pages, routes, etc. 10 | - Bundler will handle Client App together with the temp files, just like a common Vue app. 11 | 12 | As a developer, you must be aware of that VuePress has two main parts: **Node App** and **Client App**, which is important when developing plugins and themes: 13 | 14 | - The entry file of a plugin or a theme will be loaded in Node App. 15 | - Client files will be loaded in Client App, which will be handled by bundler. For example, components, client config files, etc. 16 | 17 | ## Core Process and Hooks 18 | 19 | ![vuepress-core-process](/images/guide/vuepress-core-process.png) 20 | 21 | The above figure shows the core process of VuePress Node App and the hooks of [Plugin API](../reference/plugin-api.md): 22 | 23 | - In the **init** stage: 24 | - Theme and plugins will be loaded. That means all the plugins should be used before initialization. 25 | - As we are using markdown-it to parse the markdown file, so we need to create markdown-it instance before loading pages: 26 | - [extendsMarkdownOptions](../reference/plugin-api.md#extendsmarkdownoptions) hook will be processed to create markdown-it instance. 27 | - [extendsMarkdown](../reference/plugin-api.md#extendsmarkdown) hook will be processed extends markdown-it instance. 28 | - Page files will be loaded: 29 | - [extendsPageOptions](../reference/plugin-api.md#extendspageoptions) hook will be processed to create pages. 30 | - [extendsPage](../reference/plugin-api.md#extendspage) hook will be processed to extends page object. 31 | - In the **prepare** stage: 32 | - Temp files will be generated, so all hooks related to client files will be processed here. 33 | - In the **dev / build** stage: 34 | - Bundler will be resolved: 35 | - [extendsBundlerOptions](../reference/plugin-api.md#extendsbundleroptions) hook will be processed to create bundler configuration. 36 | - [alias](../reference/plugin-api.md#alias) hook and [define](../reference/plugin-api.md#define) hook would be used in bundler configuration, so they will be processed here. 37 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## What's the Cookbook for? 4 | 5 | - We are introducing essential concepts in the **Guide**, but you may not know how to dig deeper. 6 | - We are listing APIs in the **Reference**, but you may not know how to take full advantage of them. 7 | 8 | So here comes the Cookbook. 9 | 10 | Each recipe will focus on one specific aspect, providing more detailed examples to show you the usages and possibilities of VuePress. 11 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/adding-extra-pages.md: -------------------------------------------------------------------------------- 1 | # Adding Extra Pages 2 | 3 | Sometimes you might want to add some extra pages without creating a markdown file in the source directory. 4 | 5 | With the help of [Plugin API](../../reference/plugin-api.md) and [Node API](../../reference/node-api.md), we can do that with ease. 6 | 7 | ## Add a Default Homepage 8 | 9 | As a theme author, you may not require users to create a `/README.md` file as the homepage, but you want to provide a default one: 10 | 11 | ```ts 12 | import { createPage } from 'vuepress/core' 13 | 14 | export default { 15 | // all pages have been loaded after initialization 16 | async onInitialized(app) { 17 | // if the homepage does not exist 18 | if (app.pages.every((page) => page.path !== '/')) { 19 | // create a homepage 20 | const homepage = await createPage(app, { 21 | path: '/', 22 | // set frontmatter 23 | frontmatter: { 24 | layout: 'Layout', 25 | }, 26 | // set markdown content 27 | content: `\ 28 | # Welcome to ${app.options.title} 29 | 30 | This is the default homepage 31 | `, 32 | }) 33 | // add it to `app.pages` 34 | app.pages.push(homepage) 35 | } 36 | }, 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/making-a-theme-extendable.md: -------------------------------------------------------------------------------- 1 | # Making a Theme Extendable 2 | 3 | Sometimes users might want make some minor changes to a theme, but they don't want to fork and modify the entire project. 4 | 5 | With the help of [Theme API](../../reference/theme-api.md), you can make your theme extendable, allowing users to make their own modifications easily. 6 | 7 | You must have known that how to [extend default theme](https://ecosystem.vuejs.press/themes/default/extending.html). Here we'll introduce how to make your own theme extendable like default theme. 8 | 9 | ## Layout Slots 10 | 11 | This approach requires you to determine which parts of your theme could be extended. It is more suitable for those common customizations like page footer or header. 12 | 13 | You just need to provide slots in your layouts, and tell users how to make use of them: 14 | 15 | ```vue 16 | 23 | ``` 24 | 25 | ## Component Aliases 26 | 27 | This approach requires you to consider which components of your theme should be replaceable, and you also need to split components into a suitable granularity. 28 | 29 | First, set `alias` for replaceable components of you theme: 30 | 31 | ```ts 32 | import type { Theme } from 'vuepress/core' 33 | import { getDirname } from 'vuepress/utils' 34 | 35 | const __dirname = getDirname(import.meta.url) 36 | 37 | export const fooTheme = (options): Theme => ({ 38 | name: 'vuepress-theme-foo', 39 | alias: { 40 | // set alias for replaceable components 41 | '@theme/Navbar.vue': path.resolve(__dirname, 'components/Navbar.vue'), 42 | '@theme/Sidebar.vue': path.resolve(__dirname, 'components/Sidebar.vue'), 43 | }, 44 | }) 45 | ``` 46 | 47 | Next, use those components via aliases in your theme: 48 | 49 | ```vue 50 | 54 | 55 | 62 | ``` 63 | 64 | Then, users can replace specific components by overriding the `alias` when extending or using your theme. 65 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/markdown-and-vue-sfc.md: -------------------------------------------------------------------------------- 1 | # Markdown and Vue SFC 2 | 3 | Each Markdown file is first compiled into HTML, and then converted to a Vue SFC. In other words, you can write a Markdown file like a Vue SFC: 4 | 5 | - Blocks ` 41 | 42 | 47 | ``` 48 | 49 | **Output** 50 | 51 | _Hello, {{ msg }}_ 52 | 53 | 54 | 55 | _Current count is: {{ count }}_ 56 | 57 | 58 | 59 | 60 | 61 | 75 | 76 | 81 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/passing-data-to-client-code.md: -------------------------------------------------------------------------------- 1 | # Passing Data to Client Code 2 | 3 | As we know, VuePress plugin entries and theme entries are processed in Node side, but sometimes you might need to pass data to client side. For example, you want to generate different data when users use different options. 4 | 5 | ## Use `define` Hook 6 | 7 | Plugin API provides a [define](../../reference/plugin-api.md#define) hook to define global constants for client code. You can make use of it to pass data to client. 8 | 9 | First, define some constants in `define` hook: 10 | 11 | ```ts 12 | export default (options) => ({ 13 | define: { 14 | __FOO__: options.foo || 'str', 15 | __OBJ__: { 16 | bar: options.bar || 123, 17 | }, 18 | }, 19 | }) 20 | ``` 21 | 22 | Then use them in client code directly: 23 | 24 | ```ts 25 | const foo = __FOO__ 26 | const obj = __OBJ__ 27 | ``` 28 | 29 | If you are using TypeScript in client code, you may need to declare the types of the global constants manually: 30 | 31 | ```ts 32 | declare const __FOO__: string 33 | declare const __OBJ__: { bar: number } 34 | ``` 35 | 36 | ## Write and Load Temp Files 37 | 38 | If you need to achieve some more complex features, you can write temp files and load them dynamically in client code. 39 | 40 | First, write a temp file `foo.js`, which will be generated in the [temp](../../reference/config.md#temp) directory: 41 | 42 | ```ts 43 | export default (options) => ({ 44 | async onPrepared(app) { 45 | // write temp file 46 | await app.writeTemp( 47 | 'foo.js', 48 | `export const foo = ${JSON.stringify(options.foo)}`, 49 | ) 50 | }, 51 | }) 52 | ``` 53 | 54 | Then, load the temp file via `@temp` alias in client code: 55 | 56 | ```ts 57 | import { foo } from '@temp/foo' 58 | ``` 59 | 60 | If you are using TypeScript in client code, you may need to declare the type of the temp module manually: 61 | 62 | ```ts 63 | declare module '@temp/foo' { 64 | export const foo: string 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/resolving-routes.md: -------------------------------------------------------------------------------- 1 | # Resolving Routes 2 | 3 | ## Getting all routes 4 | 5 | You can make use of [useRoutes](../../reference/client-api.md#useroutes) to get all routes information. 6 | 7 | The return value of `useRoutes` is a Ref object containing all routes. The keys are route paths of each route, and the values are the corresponding route information. 8 | 9 | ```ts 10 | import { useRoutes } from 'vuepress/client' 11 | 12 | const routes = useRoutes() 13 | // { 14 | // '/': { meta: { title: 'Home' }, loader: HomePageLoader }, 15 | // '/404.html': { meta: { title: 'Not Found' }, loader: NotFoundPageLoader }, 16 | // ... 17 | // } 18 | 19 | const routePaths = computed(() => Object.keys(routes.value)) 20 | // => ['/‘, '/404.html', '/foo/', '/bar/', ...] 21 | ``` 22 | 23 | ## Resolving route path 24 | 25 | You can make use of [resolveRoutePath](../../reference/client-api.md#resolveroutepath) to resolve the route path of the given link. 26 | 27 | `resolveRoutePath` receives a link and an optional base path, and returns the resolved route path: 28 | 29 | ```ts 30 | import { resolveRoutePath } from 'vuepress/client' 31 | 32 | const routePath = resolveRoutePath('/foo/') // => '/foo/' 33 | const routePath = resolveRoutePath('baz.html', '/foo/bar.html') // => '/foo/baz.html' 34 | ``` 35 | 36 | ## Resolving route information 37 | 38 | You can make use of [resolveRoute](../../reference/client-api.md#resolveroute) to resolve route information for a given link. 39 | 40 | `resolveRoute` receives a link and an optional base path, and returns the resolved route information: 41 | 42 | ```ts 43 | import { resolveRoute } from 'vuepress/client' 44 | 45 | const route = resolveRoute('/foo/') // => { notFound: false, path: '/foo/', meta: { title: 'Foo' }, loader: FooPageLoader } 46 | const route = resolveRoute('baz.html', '/foo/bar.html') // => { notFound: false, path: '/foo/baz.html', meta: { title: 'Baz' }, loader: BazPageLoader } 47 | const route = resolveRoute('/not-exist.html') // => { notFound: true, path: '/not-exist.html', meta: { title: 'Not Found' }, loader: NotFoundPageLoader } 48 | ``` 49 | 50 | There is a `notFound` field in the returned information, which is used to indicate whether a corresponding route exists for a given path. When the route does not exist, the `notFound` field would be `true`, the `path` field would be the normalized path, and the `meta` and `loader` fields would point to the default 404 page. 51 | -------------------------------------------------------------------------------- /docs/advanced/cookbook/usage-of-client-config.md: -------------------------------------------------------------------------------- 1 | # Usage of Client Config 2 | 3 | You can make use of the [client config file](../../guide/configuration.md#client-config-file) directly in your project, or specify the file path in your plugin or theme via [clientConfigFile](../../reference/plugin-api.md#clientconfigfile) hook: 4 | 5 | ```ts 6 | import { getDirname, path } from 'vuepress/utils' 7 | 8 | const __dirname = getDirname(import.meta.url) 9 | 10 | const pluginOrTheme = { 11 | clientConfigFile: path.resolve(__dirname, './path/to/clientConfig.ts'), 12 | } 13 | ``` 14 | 15 | Inside the client config file, `vuepress/client` provides a helper function [defineClientConfig](../../reference/client-api.md#defineclientconfig) to help you define the client config: 16 | 17 | ```ts 18 | import { defineClientConfig } from 'vuepress/client' 19 | 20 | export default defineClientConfig({ 21 | enhance({ app, router, siteData }) {}, 22 | setup() {}, 23 | layouts: {}, 24 | rootComponents: [], 25 | }) 26 | ``` 27 | 28 | ## enhance 29 | 30 | The `enhance` function could be either synchronous or asynchronous. It accepts a context param with following properties: 31 | 32 | - `app` is the Vue application instance that created by [createApp](https://vuejs.org/api/application.html#createapp). 33 | - `router` is the Vue Router instance that created by [createRouter](https://router.vuejs.org/api/#createrouter). 34 | - `siteData` is a ref of an object that generated from user config, including [base](../../reference/config.md#base), [lang](../../reference/config.md#lang), [title](../../reference/config.md#title), [description](../../reference/config.md#description), [head](../../reference/config.md#head) and [locales](../../reference/config.md#locales). 35 | 36 | The `enhance` function will be invoked after the client app is created. It's possible to implement any enhancements to the Vue application. 37 | 38 | ### Register Vue Components 39 | 40 | You can register global Vue components via the [app.component](https://vuejs.org/api/application.html#app-component) method: 41 | 42 | ```ts 43 | import { defineClientConfig } from 'vuepress/client' 44 | import MyComponent from './MyComponent.vue' 45 | 46 | export default defineClientConfig({ 47 | enhance({ app }) { 48 | app.component('MyComponent', MyComponent) 49 | }, 50 | }) 51 | ``` 52 | 53 | ### Use Non-SSR-Friendly Features 54 | 55 | VuePress will generate a SSR application to pre-render pages during build. Generally speaking, if a code snippet is using Browser / DOM APIs before client app is mounted, we call it non-SSR-friendly. 56 | 57 | We already provides a [ClientOnly](../../reference/components.md#clientonly) component to wrap non-SSR-friendly content. 58 | 59 | In the `enhance` function, you can make use of the [`__VUEPRESS_SSR__`](../../reference/client-api.md#ssr) flag for that purpose. 60 | 61 | ```ts 62 | import { defineClientConfig } from 'vuepress/client' 63 | 64 | export default defineClientConfig({ 65 | async enhance() { 66 | if (!__VUEPRESS_SSR__) { 67 | const nonSsrFriendlyModule = await import('non-ssr-friendly-module') 68 | // ... 69 | } 70 | }, 71 | }) 72 | ``` 73 | 74 | ### Use Router Methods 75 | 76 | You can make use of the [Router Methods](https://router.vuejs.org/api/#router-methods) that provided by vue-router. For example, add navigation guard: 77 | 78 | ```ts 79 | import { defineClientConfig } from 'vuepress/client' 80 | 81 | export default defineClientConfig({ 82 | enhance({ router }) { 83 | router.beforeEach((to) => { 84 | console.log('before navigation') 85 | }) 86 | 87 | router.afterEach((to) => { 88 | console.log('after navigation') 89 | }) 90 | }, 91 | }) 92 | ``` 93 | 94 | ::: warning 95 | It's not recommended to use `addRoute` method to add dynamic routes here, because those routes will **NOT** be pre-rendered in build mode. 96 | 97 | But you can still do that if you understand the drawback. 98 | ::: 99 | 100 | ## setup 101 | 102 | The `setup` function would be invoked inside the [setup](https://vuejs.org/api/composition-api-setup.html) hook of the client vue app. 103 | 104 | ### Use Composition API 105 | 106 | You can take the `setup` function as part of the [setup](https://vuejs.org/api/composition-api-setup.html) hook of the root component. Thus, all composition APIs are available here. 107 | 108 | ```ts 109 | import { provide, ref } from 'vue' 110 | import { useRoute, useRouter } from 'vue-router' 111 | import { defineClientConfig } from 'vuepress/client' 112 | 113 | export default defineClientConfig({ 114 | setup() { 115 | // get the current route location 116 | const route = useRoute() 117 | // get the vue-router instance 118 | const router = useRouter() 119 | // provide a value that can be injected by layouts, pages and other components 120 | const count = ref(0) 121 | provide('count', count) 122 | }, 123 | }) 124 | ``` 125 | 126 | ### Use Non-SSR-Friendly Features 127 | 128 | In the `setup` function, the [`__VUEPRESS_SSR__`](../../reference/client-api.md#ssr) flag is also available. 129 | 130 | Another way to use non-ssr-friendly features is to put them inside the [onMounted](https://vuejs.org/api/composition-api-lifecycle.html#onmounted) hook: 131 | 132 | ```ts 133 | import { onMounted } from 'vue' 134 | import { defineClientConfig } from 'vuepress/client' 135 | 136 | export default defineClientConfig({ 137 | setup() { 138 | onMounted(() => { 139 | // use DOM API after mounted 140 | document.querySelector('#app') 141 | }) 142 | }, 143 | }) 144 | ``` 145 | 146 | ## layouts 147 | 148 | The `layouts` options is to set layout components. After layout components are registered here, users can use it via [layout](../../reference/frontmatter.md#layout) frontmatter. 149 | 150 | ```ts 151 | import { defineClientConfig } from 'vuepress/client' 152 | import MyLayout from './layouts/MyLayout.vue' 153 | 154 | export default defineClientConfig({ 155 | layouts: { 156 | MyLayout, 157 | }, 158 | }) 159 | ``` 160 | 161 | ## rootComponents 162 | 163 | The `rootComponents` is a components array to be placed directly into the root node of the client vue app. 164 | 165 | Typical usage of this option is to put some global UI components, like global popup or so: 166 | 167 | ```ts 168 | import { defineClientConfig } from 'vuepress/client' 169 | import GlobalPopup from './components/GlobalPopup.vue' 170 | 171 | export default defineClientConfig({ 172 | rootComponents: [GlobalPopup], 173 | }) 174 | ``` 175 | -------------------------------------------------------------------------------- /docs/advanced/plugin.md: -------------------------------------------------------------------------------- 1 | # Writing a Plugin 2 | 3 | ::: tip 4 | Before reading this guide, you'd better learn the VuePress [architecture](./architecture.md) first. 5 | ::: 6 | 7 | ## Create a Plugin 8 | 9 | A plugin should be a plain JavaScript object that satisfies the [Plugin API](../reference/plugin-api.md), which is called a _Plugin Object_: 10 | 11 | ```ts 12 | const fooPlugin = { 13 | name: 'vuepress-plugin-foo', 14 | // ... 15 | } 16 | ``` 17 | 18 | A plugin could also be a function that receives the [app instance](../reference/node-api.md#app) as the param and returns a _Plugin Object_, which is called a _Plugin Function_: 19 | 20 | ```ts 21 | const barPlugin = (app) => ({ 22 | name: 'vuepress-plugin-bar', 23 | // ... 24 | }) 25 | ``` 26 | 27 | A plugin usually needs to allow user options, so we typically provide users with a function to receive options, and returns a _Plugin Object_ or a _Plugin Function_. Then your plugin should be converted like this: 28 | 29 | ```ts 30 | const fooPlugin = (options) => ({ 31 | name: 'vuepress-plugin-foo', 32 | // ... 33 | }) 34 | 35 | const barPlugin = (options) => (app) => ({ 36 | name: 'vuepress-plugin-bar', 37 | // ... 38 | }) 39 | ``` 40 | 41 | ## Publish to NPM 42 | 43 | After creating a plugin, you should follow some conventions in the [package.json](https://docs.npmjs.com/cli/v8/configuring-npm/package-json) file before publishing it to NPM: 44 | 45 | ```json 46 | { 47 | "name": "vuepress-plugin-foo", 48 | "keywords": ["vuepress-plugin"] 49 | } 50 | ``` 51 | 52 | - Set `name` to follow the naming convention, i.e. `vuepress-plugin-xxx` or `@org/vuepress-plugin-xxx`, which should be consistent with the [name](../reference/plugin-api.md#name) field of the _Plugin Object_. 53 | - Set `keywords` to include `vuepress-plugin`, so that users can search your plugin on NPM. 54 | -------------------------------------------------------------------------------- /docs/advanced/theme.md: -------------------------------------------------------------------------------- 1 | # Writing a Theme 2 | 3 | ::: tip 4 | Before reading this guide, you'd better learn the guide of [Writing a Plugin](./plugin.md) first. 5 | ::: 6 | 7 | ## Create a Theme 8 | 9 | A VuePress theme is a special plugin, which should satisfy the [Theme API](../reference/theme-api.md). Like plugins, a theme should also be a _Theme Object_ or a _Theme Function_, and could be wrapped with a function to receive options: 10 | 11 | ```ts 12 | import { getDirname, path } from 'vuepress/utils' 13 | 14 | const __dirname = getDirname(import.meta.url) 15 | 16 | const fooTheme = (options) => 17 | // returns a theme object 18 | ({ 19 | name: 'vuepress-theme-foo', 20 | 21 | // path to the client config of your theme 22 | clientConfigFile: path.resolve(__dirname, 'client.js'), 23 | 24 | // set custom dev / build template 25 | // if the template is not specified, the default template 26 | templateBuild: path.resolve(__dirname, 'templates/build.html'), 27 | templateDev: path.resolve(__dirname, 'templates/dev.html'), 28 | 29 | // use plugins 30 | plugins: [ 31 | // ... 32 | ], 33 | 34 | // other plugin APIs are also available 35 | }) 36 | 37 | const barTheme = 38 | (options) => 39 | // returns a theme function 40 | (app) => ({ 41 | name: 'vuepress-theme-bar', 42 | // ... 43 | }) 44 | ``` 45 | 46 | Then, create theme's client config file `client.js` : 47 | 48 | ```ts 49 | import { defineClientConfig } from 'vuepress/client' 50 | import Layout from './layouts/Layout.vue' 51 | import NotFound from './layouts/NotFound.vue' 52 | 53 | export default defineClientConfig({ 54 | layouts: { 55 | Layout, 56 | NotFound, 57 | }, 58 | }) 59 | ``` 60 | 61 | The `layouts` field declares the layouts provided by your theme. A theme must provide at least two layouts: `Layout` and `NotFound`. The former is to provide default layout for common pages, while the latter is to provide layout for 404-not-found page. 62 | 63 | The `Layout` layout should contain the [Content](../reference/components.md#content) component to display the markdown content: 64 | 65 | ```vue 66 | 71 | ``` 72 | 73 | The `NotFound` layout will be used for the `404.html` page: 74 | 75 | ```vue 76 | 79 | ``` 80 | 81 | You can provide more layouts, and users can change layout via [layout](../reference/frontmatter.md#layout) frontmatter. 82 | 83 | ## Publish to NPM 84 | 85 | Also, there are some conventions for theme in [package.json](https://docs.npmjs.com/cli/v8/configuring-npm/package-json): 86 | 87 | ```json 88 | { 89 | "name": "vuepress-theme-foo", 90 | "keywords": ["vuepress-theme"] 91 | } 92 | ``` 93 | 94 | - Set `name` to follow the naming convention: `vuepress-theme-xxx` or `@org/vuepress-theme-xxx`, which should be consistent with the [name](../reference/theme-api.md#name) field of the _Theme Object_. 95 | - Set `keywords` to include `vuepress-theme`, so that users can search your theme on NPM. 96 | -------------------------------------------------------------------------------- /docs/guide/assets.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | 3 | ## Relative URLs 4 | 5 | You can reference any assets using relative URLs in your Markdown content: 6 | 7 | ```md 8 | ![An image](./image.png) 9 | ``` 10 | 11 | or 12 | 13 | ```md 14 | ![An image](image.png) 15 | ``` 16 | 17 | This is generally the suggested way to import images, as users usually place images near the Markdown file that references them. 18 | 19 | ## Public Files 20 | 21 | You can put some static assets inside public directory, and they will be copied to the root of the generated directory. 22 | 23 | The default public directory is `.vuepress/public`, which can be changed by [public](../reference/config.md#public) option. 24 | 25 | It would be useful in some cases: 26 | 27 | - You may need to provide static assets that are not directly referenced in any of your Markdown files, for example, favicon and PWA icons. 28 | - You may need to serve some shared static assets, which may even be referenced outside your site, for example, logo images. 29 | - You may want to reference images using absolute URLs in your Markdown content. 30 | 31 | Take our documentation source files as an example, we are putting the logo of VuePress inside the public directory: 32 | 33 | ```bash 34 | └─ docs 35 | ├─ .vuepress 36 | | └─ public 37 | | └─ images 38 | | └─ hero.png # <- Logo file 39 | └─ guide 40 | └─ assets.md # <- Here we are 41 | ``` 42 | 43 | We can reference our logo in current page like this: 44 | 45 | **Input** 46 | 47 | ```md 48 | ![VuePress Logo](/images/hero.png) 49 | ``` 50 | 51 | **Output** 52 | 53 | ![VuePress Logo](/images/hero.png) 54 | 55 | ### Base Helper 56 | 57 | If your site is deployed to a non-root URL, for example, `https://foo.github.io/bar/`, then the [base](../reference/config.md#base) should be set to `'/bar/'`. Obviously, your public files would be served like `https://foo.github.io/bar/images/hero.png` after deployment. 58 | 59 | In most cases, you don't need to worry about the reference path of those public files, as VuePress will automatically handle `base` for you: 60 | 61 | ```md 62 | 63 | 64 | ![VuePress Logo](/images/hero.png) 65 | ``` 66 | 67 | ::: tip 68 | When using [webpack bundler](../reference/bundler/webpack.md), you need to set [markdown.assets.absolutePathPrependBase](../reference/config.md#markdown-assets) to `true` to automatically prepend base to markdown images. 69 | ::: 70 | 71 | However, sometimes you may have some dynamical links referencing public files, especially when you are authoring a custom theme. In such case, the `base` could not be handled automatically. To help with that, VuePress provides a [withBase](../reference/client-api.md#withbase) helper to prepend `base` for you: 72 | 73 | ```vue 74 | 80 | 81 | 84 | ``` 85 | 86 | You can also access the helper by `$withBase` directly: 87 | 88 | ```md 89 | VuePress Logo 90 | ``` 91 | 92 | ## Packages and Path Aliases 93 | 94 | Although it is not a common usage, you can reference images from dependent packages: 95 | 96 | ```bash 97 | npm install -D package-name 98 | ``` 99 | 100 | Since markdown image syntax regards image links as relative paths by default, you need to use `` tag: 101 | 102 | ```md 103 | Image from dependency 104 | ``` 105 | 106 | The path aliases that set in config file are also supported: 107 | 108 | ```ts 109 | import { getDirname, path } from 'vuepress/utils' 110 | 111 | const __dirname = getDirname(import.meta.url) 112 | 113 | export default { 114 | alias: { 115 | '@alias': path.resolve(__dirname, './path/to/some/dir'), 116 | }, 117 | } 118 | ``` 119 | 120 | ```md 121 | Image from path alias 122 | ``` 123 | 124 | ::: tip 125 | Config reference: [alias](../reference/plugin-api.md#alias) 126 | ::: 127 | -------------------------------------------------------------------------------- /docs/guide/bundler.md: -------------------------------------------------------------------------------- 1 | # Bundler 2 | 3 | VuePress supports using [Webpack](https://webpack.js.org/) or [Vite](https://vite.dev/) to dev and build sites. You can choose which bundler to use according to your preference, and no extra configuration is required. 4 | 5 | ## Install a Bundler 6 | 7 | When installing the [vuepress](https://www.npmjs.com/package/vuepress) package, no bundlers will be installed. You need to choose a bundler to install. 8 | 9 | ::: code-tabs#shell 10 | 11 | @tab pnpm 12 | 13 | ```bash 14 | # install vite bundler 15 | pnpm add -D vuepress@next @vuepress/bundler-vite@next 16 | # install webpack bundler 17 | pnpm add -D vuepress@next @vuepress/bundler-webpack@next 18 | ``` 19 | 20 | @tab yarn 21 | 22 | ```bash 23 | # install vite bundler 24 | yarn add -D vuepress@next @vuepress/bundler-vite@next 25 | # install webpack bundler 26 | yarn add -D vuepress@next @vuepress/bundler-webpack@next 27 | ``` 28 | 29 | @tab npm 30 | 31 | ```bash 32 | # install vite bundler 33 | npm install -D vuepress@next @vuepress/bundler-vite@next 34 | # install webpack bundler 35 | npm install -D vuepress@next @vuepress/bundler-webpack@next 36 | ``` 37 | 38 | ::: 39 | 40 | ## Use a Bundler 41 | 42 | Generally, you could use a bundler without extra configuration, because we have already configured them properly to work with VuePress. 43 | 44 | You can use a bundler via the [bundler](../reference/config.md#bundler) option: 45 | 46 | ```ts 47 | import { viteBundler } from '@vuepress/bundler-vite' 48 | // import { webpackBundler } from '@vuepress/bundler-webpack' 49 | 50 | export default { 51 | bundler: viteBundler(), 52 | // bundler: webpackBundler(), 53 | } 54 | ``` 55 | 56 | When you need to customize the bundler, you can set the corresponding options: 57 | 58 | - [Bundlers > Vite](../reference/bundler/vite.md) 59 | - [Bundlers > Webpack](../reference/bundler/webpack.md) 60 | -------------------------------------------------------------------------------- /docs/guide/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | ## Config File 4 | 5 | The essential file for configuring a VuePress site is `.vuepress/config.js`, while TypeScript config file is also supported. You can use `.vuepress/config.ts` instead to get better types hint for VuePress config. 6 | 7 | To be more specific, we have a convention for config file paths (in order of precedence): 8 | 9 | - In current working directory `cwd`: 10 | - `vuepress.config.ts` 11 | - `vuepress.config.js` 12 | - `vuepress.config.mjs` 13 | - In source directory `sourceDir`: 14 | - `.vuepress/config.ts` 15 | - `.vuepress/config.js` 16 | - `.vuepress/config.mjs` 17 | 18 | You can also specify the config file via `--config` option of [CLI](../reference/cli.md): 19 | 20 | ```bash 21 | vuepress dev docs --config my-config.ts 22 | ``` 23 | 24 | A basic config file looks like this: 25 | 26 | ```ts 27 | import { viteBundler } from '@vuepress/bundler-vite' 28 | import { defaultTheme } from '@vuepress/theme-default' 29 | import { defineUserConfig } from 'vuepress' 30 | 31 | export default defineUserConfig({ 32 | bundler: viteBundler(), 33 | theme: defaultTheme(), 34 | 35 | lang: 'en-US', 36 | title: 'Hello VuePress', 37 | description: 'Just playing around', 38 | }) 39 | ``` 40 | 41 | ::: tip 42 | Check out the [Config Reference](../reference/config.md) for a full list of VuePress config. 43 | ::: 44 | 45 | ## Client Config File 46 | 47 | In most cases, the config file is sufficient to configure your VuePress site. However, sometimes users may want to add some client-side code directly. To help with this, VuePress also supports a client config file: 48 | 49 | ``` 50 | ├─ docs 51 | │ ├─ .vuepress 52 | │ │ ├─ client.js <--- client config file 53 | │ │ └─ config.js <--- config file 54 | │ └─ README.md 55 | ├─ .gitignore 56 | └─ package.json 57 | ``` 58 | 59 | Similarly, we also have a convention for client config file paths (in order of precedence): 60 | 61 | - In current working directory `cwd`: 62 | - `vuepress.client.ts` 63 | - `vuepress.client.js` 64 | - `vuepress.client.mjs` 65 | - In source directory `sourceDir`: 66 | - `.vuepress/client.ts` 67 | - `.vuepress/client.js` 68 | - `.vuepress/client.mjs` 69 | 70 | A basic client config file looks like this: 71 | 72 | ```ts 73 | import { defineClientConfig } from 'vuepress/client' 74 | 75 | export default defineClientConfig({ 76 | enhance({ app, router, siteData }) {}, 77 | setup() {}, 78 | rootComponents: [], 79 | }) 80 | ``` 81 | 82 | ::: tip 83 | Unlike config file, client config file could not be specified via CLI options. 84 | 85 | To learn more about client config file, see [Advanced > Cookbook > Usage of Client Config](../advanced/cookbook/usage-of-client-config.md) 86 | ::: 87 | -------------------------------------------------------------------------------- /docs/guide/deployment.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | 3 | The following guides are based on some shared assumptions: 4 | 5 | - You are placing your Markdown source files inside the `docs` directory of your project; 6 | - You are using the default build output location (`.vuepress/dist`); 7 | - You are using [pnpm](https://pnpm.io) as package manager, while npm and yarn are also supported; 8 | - VuePress is installed as a local dependency in your project, and you have setup the following script in `package.json`: 9 | 10 | ```json 11 | { 12 | "scripts": { 13 | "docs:build": "vuepress build docs" 14 | } 15 | } 16 | ``` 17 | 18 | ## GitHub Pages 19 | 20 | 1. Set the correct [base](../reference/config.md#base) config. 21 | 22 | If you are deploying to `https://.github.io/`, you can omit this step as `base` defaults to `"/"`. 23 | 24 | If you are deploying to `https://.github.io//`, for example your repository is at `https://github.com//`, then set `base` to `"//"`. 25 | 26 | 2. Choose your preferred CI tools. Here we take [GitHub Actions](https://github.com/features/actions) as an example. 27 | 28 | Create `.github/workflows/docs.yml` to set up the workflow. 29 | 30 | ::: details Click to expand sample config 31 | 32 | ```yaml 33 | name: docs 34 | 35 | on: 36 | # trigger deployment on every push to main branch 37 | push: 38 | branches: [main] 39 | # trigger deployment manually 40 | workflow_dispatch: 41 | 42 | jobs: 43 | docs: 44 | runs-on: ubuntu-latest 45 | 46 | steps: 47 | - uses: actions/checkout@v4 48 | with: 49 | # fetch all commits to get last updated time or other git log info 50 | fetch-depth: 0 51 | 52 | - name: Setup pnpm 53 | uses: pnpm/action-setup@v4 54 | 55 | - name: Setup Node.js 56 | uses: actions/setup-node@v4 57 | with: 58 | # choose node.js version to use 59 | node-version: 22 60 | # cache deps for pnpm 61 | cache: pnpm 62 | 63 | - name: Install deps 64 | run: pnpm install --frozen-lockfile 65 | 66 | # run build script 67 | - name: Build VuePress site 68 | run: pnpm docs:build 69 | 70 | # please check out the docs of the workflow for more details 71 | # @see https://github.com/crazy-max/ghaction-github-pages 72 | - name: Deploy to GitHub Pages 73 | uses: crazy-max/ghaction-github-pages@v4 74 | with: 75 | # deploy to gh-pages branch 76 | target_branch: gh-pages 77 | # deploy the default output dir of VuePress 78 | build_dir: docs/.vuepress/dist 79 | env: 80 | # @see https://docs.github.com/en/actions/reference/authentication-in-a-workflow#about-the-github_token-secret 81 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 82 | ``` 83 | 84 | ::: 85 | 86 | ::: tip 87 | Please refer to [GitHub Pages official guide](https://pages.github.com/) for more details. 88 | ::: 89 | 90 | ## GitLab Pages 91 | 92 | 1. Set the correct [base](../reference/config.md#base) config. 93 | 94 | If you are deploying to `https://.gitlab.io/`, you can omit `base` as it defaults to `"/"`. 95 | 96 | If you are deploying to `https://.gitlab.io//`, for example your repository is at `https://gitlab.com//`, then set `base` to `"//"`. 97 | 98 | 2. Create `.gitlab-ci.yml` to set up [GitLab CI](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) workflow. 99 | 100 | ::: details Click to expand sample config 101 | 102 | ```yaml 103 | # choose a docker image to use 104 | image: node:18-buster 105 | 106 | pages: 107 | # trigger deployment on every push to main branch 108 | only: 109 | - main 110 | 111 | # cache node_modules 112 | cache: 113 | key: 114 | files: 115 | - pnpm-lock.yaml 116 | paths: 117 | - .pnpm-store 118 | 119 | # Install pnpm 120 | before_script: 121 | - curl -fsSL https://get.pnpm.io/install.sh | sh - 122 | - pnpm config set store-dir .pnpm-store 123 | 124 | # install dependencies and run build script 125 | script: 126 | - pnpm i --frozen-lockfile 127 | - pnpm docs:build --dest public 128 | 129 | artifacts: 130 | paths: 131 | - public 132 | ``` 133 | 134 | ::: 135 | 136 | ::: tip 137 | Please refer to [GitLab Pages official guide](https://docs.gitlab.com/ce/user/project/pages/#getting-started) for more details. 138 | ::: 139 | 140 | ## Google Firebase 141 | 142 | 1. Make sure you have [firebase-tools](https://www.npmjs.com/package/firebase-tools) installed. 143 | 144 | 2. Create `firebase.json` and `.firebaserc` at the root of your project with the following content: 145 | 146 | `firebase.json`: 147 | 148 | ```json 149 | { 150 | "hosting": { 151 | "public": "./docs/.vuepress/dist", 152 | "ignore": [] 153 | } 154 | } 155 | ``` 156 | 157 | `.firebaserc`: 158 | 159 | ```json 160 | { 161 | "projects": { 162 | "default": "" 163 | } 164 | } 165 | ``` 166 | 167 | 3. After running `pnpm docs:build`, deploy using the command `firebase deploy`. 168 | 169 | ::: tip 170 | Please refer to [Firebase CLI official guide](https://firebase.google.com/docs/cli) for more details. 171 | ::: 172 | 173 | ## Heroku 174 | 175 | 1. Install [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). 176 | 177 | 2. Create a Heroku account by [signing up](https://signup.heroku.com). 178 | 179 | 3. Run `heroku login` and fill in your Heroku credentials: 180 | 181 | ```bash 182 | heroku login 183 | ``` 184 | 185 | 4. Create a file called `static.json` in the root of your project with the below content: 186 | 187 | `static.json`: 188 | 189 | ```json 190 | { 191 | "root": "./docs/.vuepress/dist" 192 | } 193 | ``` 194 | 195 | This is the configuration of your site; read more at [heroku-buildpack-static](https://github.com/heroku/heroku-buildpack-static). 196 | 197 | ## Kinsta 198 | 199 | See [Set Up VuePress on Kinsta](https://kinsta.com/docs/vuepress-application/). 200 | 201 | ## Edgio 202 | 203 | See [Edgio Documentation > Framework Guides > VuePress](https://docs.edg.io/guides/vuepress). 204 | 205 | ## Netlify 206 | 207 | 1. On [Netlify](https://netlify.com), set up a new project from GitHub with the following settings: 208 | 209 | - **Build Command:** `pnpm docs:build` 210 | - **Publish directory:** `docs/.vuepress/dist` 211 | 212 | 2. Set [Environment variables](https://docs.netlify.com/configure-builds/environment-variables) to choose node version: 213 | 214 | - `NODE_VERSION`: 20 215 | 216 | 3. Hit the deploy button. 217 | 218 | ::: note 219 | 220 | You should disable Pretty URLs in the "Site Configuration" → "Build & Deploy" → "Post processing". 221 | 222 | ::: 223 | 224 | ## Vercel 225 | 226 | 1. Go to [Vercel](https://vercel.com), set up a new project from GitHub with the following settings: 227 | 228 | - **FRAMEWORK PRESET:** `Other` 229 | - **BUILD COMMAND:** `pnpm docs:build` 230 | - **OUTPUT DIRECTORY:** `docs/.vuepress/dist` 231 | 232 | 2. Hit the deploy button. 233 | -------------------------------------------------------------------------------- /docs/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ::: warning 4 | VuePress v2 is currently in RC (Release Candidate) stage. It's ready to be used for building your site, but the config and API are not stable enough, which is possibly to have minor breaking changes. So make sure to read the [changelog](https://github.com/vuepress/core/blob/main/CHANGELOG.md) carefully each time you upgrade a RC version. 5 | ::: 6 | 7 | ## Try It Online 8 | 9 | You can try VuePress directly in your browser on [StackBlitz](https://stackblitz.com/fork/vuepress). 10 | 11 | ## Installation 12 | 13 | ### Prerequisites 14 | 15 | - [Node.js v20.6.0+](https://nodejs.org/) 16 | - Package manager like [pnpm](https://pnpm.io), [yarn](https://classic.yarnpkg.com/en/), [npm](https://www.npmjs.com), etc. 17 | 18 | ::: tip 19 | 20 | - When using [pnpm](https://pnpm.io/), you need to install `vue` as peer-dependencies. 21 | - When using [yarn 2+](https://yarnpkg.com/), you need to set `nodeLinker: 'node-modules'` in your [`.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc#nodeLinker) file. 22 | 23 | ::: 24 | 25 | ### Project Setup 26 | 27 | #### Setup via CLI 28 | 29 | You can use [create-vuepress](https://www.npmjs.com/package/create-vuepress) to generate a template directly. 30 | 31 | ::: code-tabs#shell 32 | 33 | @tab pnpm 34 | 35 | ```bash 36 | pnpm create vuepress vuepress-starter 37 | ``` 38 | 39 | @tab yarn 40 | 41 | ```bash 42 | yarn create vuepress vuepress-starter 43 | ``` 44 | 45 | @tab npm 46 | 47 | ```bash 48 | npm init vuepress vuepress-starter 49 | ``` 50 | 51 | ::: 52 | 53 | #### Setup Manually 54 | 55 | This section will help you build a basic VuePress documentation site from ground up. 56 | 57 | - Create and change into a new directory 58 | 59 | ```bash 60 | mkdir vuepress-starter 61 | cd vuepress-starter 62 | ``` 63 | 64 | - Initialize your project 65 | 66 | ::: code-tabs#shell 67 | 68 | @tab pnpm 69 | 70 | ```bash 71 | git init 72 | pnpm init 73 | ``` 74 | 75 | @tab yarn 76 | 77 | ```bash 78 | git init 79 | yarn init 80 | ``` 81 | 82 | @tab npm 83 | 84 | ```bash 85 | git init 86 | npm init 87 | ``` 88 | 89 | ::: 90 | 91 | - Install VuePress 92 | 93 | ::: code-tabs#shell 94 | 95 | @tab pnpm 96 | 97 | ```bash 98 | # install vuepress and vue 99 | pnpm add -D vuepress@next vue 100 | # install bundler and theme 101 | pnpm add -D @vuepress/bundler-vite@next @vuepress/theme-default@next 102 | ``` 103 | 104 | @tab yarn 105 | 106 | ```bash 107 | # install vuepress 108 | yarn add -D vuepress@next 109 | # install bundler and theme 110 | yarn add -D @vuepress/bundler-vite@next @vuepress/theme-default@next 111 | ``` 112 | 113 | @tab npm 114 | 115 | ```bash 116 | # install vuepress 117 | npm install -D vuepress@next 118 | # install bundler and theme 119 | npm install -D @vuepress/bundler-vite@next @vuepress/theme-default@next 120 | ``` 121 | 122 | ::: 123 | 124 | - Create `docs` directory and `docs/.vuepress` directory 125 | 126 | ```bash 127 | mkdir docs 128 | mkdir docs/.vuepress 129 | ``` 130 | 131 | - Create the VuePress config file `docs/.vuepress/config.js` 132 | 133 | ```ts 134 | import { viteBundler } from '@vuepress/bundler-vite' 135 | import { defaultTheme } from '@vuepress/theme-default' 136 | import { defineUserConfig } from 'vuepress' 137 | 138 | export default defineUserConfig({ 139 | bundler: viteBundler(), 140 | theme: defaultTheme(), 141 | }) 142 | ``` 143 | 144 | - Create your first document 145 | 146 | ```bash 147 | echo '# Hello VuePress' > docs/README.md 148 | ``` 149 | 150 | ## Directory Structure 151 | 152 | After the setup, the minimal structure of your project should look like this: 153 | 154 | ``` 155 | ├─ docs 156 | │ ├─ .vuepress 157 | │ │ └─ config.js 158 | │ └─ README.md 159 | └─ package.json 160 | ``` 161 | 162 | The `docs` directory is where you put your markdown files, and it will be used as the source directory of VuePress. 163 | 164 | The `docs/.vuepress` directory, i.e. the `.vuepress` directory in the source directory, is where all VuePress-specific files will be placed. Currently there is only one config file in it. By default, the temp, cache and output directory will also be generated inside this directory. It is suggested to add them to your `.gitignore` file. 165 | 166 | ::: details Example `.gitignore` file 167 | 168 | ``` 169 | # VuePress default temp directory 170 | .vuepress/.temp 171 | # VuePress default cache directory 172 | .vuepress/.cache 173 | # VuePress default build output directory 174 | .vuepress/dist 175 | ``` 176 | 177 | ::: 178 | 179 | ## Work with VuePress 180 | 181 | ### Start Dev Server 182 | 183 | You can add some [scripts](https://classic.yarnpkg.com/en/docs/package-json#toc-scripts) to `package.json`: 184 | 185 | ```json 186 | { 187 | "scripts": { 188 | "docs:dev": "vuepress dev docs", 189 | "docs:build": "vuepress build docs" 190 | } 191 | } 192 | ``` 193 | 194 | Then, run `docs:dev` script to start the dev server: 195 | 196 | ::: code-tabs#shell 197 | 198 | @tab pnpm 199 | 200 | ```bash 201 | pnpm docs:dev 202 | ``` 203 | 204 | @tab yarn 205 | 206 | ```bash 207 | yarn docs:dev 208 | ``` 209 | 210 | @tab npm 211 | 212 | ```bash 213 | npm run docs:dev 214 | ``` 215 | 216 | ::: 217 | 218 | VuePress will start a hot-reloading development server at [http://localhost:8080](http://localhost:8080). When you modify your markdown files, the content in the browser will be auto updated. 219 | 220 | ### Build Your Site 221 | 222 | To build your site, run `docs:build` script: 223 | 224 | ::: code-tabs#shell 225 | 226 | @tab pnpm 227 | 228 | ```bash 229 | pnpm docs:build 230 | ``` 231 | 232 | @tab yarn 233 | 234 | ```bash 235 | yarn docs:build 236 | ``` 237 | 238 | @tab npm 239 | 240 | ```bash 241 | npm run docs:build 242 | ``` 243 | 244 | ::: 245 | 246 | You will see the generated static files in the `docs/.vuepress/dist` directory. You can check out [deployment](./deployment.md) for how to deploy them. 247 | 248 | ## Learn More about VuePress 249 | 250 | By now, you should have a basic but functional VuePress site. But you may still need to read the subsequent guide to learn more about VuePress. 251 | 252 | Next step, learn more about the [configuration](./configuration.md). 253 | -------------------------------------------------------------------------------- /docs/guide/i18n.md: -------------------------------------------------------------------------------- 1 | # I18n 2 | 3 | ## Site I18n Config 4 | 5 | To take advantage of multi-language support in VuePress, you first need to use the following file and directory structure: 6 | 7 | ``` 8 | docs 9 | ├─ README.md 10 | ├─ foo.md 11 | ├─ nested 12 | │  └─ README.md 13 | └─ zh 14 | ├─ README.md 15 | ├─ foo.md 16 | └─ nested 17 |    └─ README.md 18 | ``` 19 | 20 | Then, specify the `locales` option in your [config file](./configuration.md#config-file): 21 | 22 | ```ts 23 | export default { 24 | locales: { 25 | // The key is the path for the locale to be nested under. 26 | // As a special case, the default locale can use '/' as its path. 27 | '/': { 28 | lang: 'en-US', 29 | title: 'VuePress', 30 | description: 'Vue-powered Static Site Generator', 31 | }, 32 | '/zh/': { 33 | lang: 'zh-CN', 34 | title: 'VuePress', 35 | description: 'Vue 驱动的静态网站生成器', 36 | }, 37 | }, 38 | } 39 | ``` 40 | 41 | If a locale does not have a `lang`, `title`, `description` or `head`, VuePress will fallback to the root-level values. You can omit the root level config as long as they are provided in each locale. 42 | 43 | ::: tip 44 | Config reference: [locales](../reference/config.md#locales) 45 | ::: 46 | 47 | ## Theme I18n Config 48 | 49 | VuePress does not restrict how themes provide multi-language support, so each theme may have different way to handle i18n, and some themes may not provide multi-language support at all. You'd better refer to the theme documentation for detailed guide. 50 | 51 | If you are using default theme, the multi-language support is the same as above: 52 | 53 | ```ts 54 | import { defaultTheme } from '@vuepress/theme-default' 55 | import { defineUserConfig } from 'vuepress' 56 | 57 | export default defineUserConfig({ 58 | theme: defaultTheme({ 59 | locales: { 60 | '/': { 61 | selectLanguageName: 'English', 62 | }, 63 | '/zh/': { 64 | selectLanguageName: '简体中文', 65 | }, 66 | }, 67 | }), 68 | }) 69 | ``` 70 | 71 | ::: tip 72 | 73 | Config reference: 74 | 75 | - [Default Theme > Config](https://ecosystem.vuejs.press/themes/default/config.html) 76 | - [Default Theme > Locale config](https://ecosystem.vuejs.press/themes/default/locale.html) 77 | 78 | ::: 79 | -------------------------------------------------------------------------------- /docs/guide/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | VuePress is a markdown-centered static site generator. You can write your content (documentations, blogs, etc.) in [Markdown](https://en.wikipedia.org/wiki/Markdown), then VuePress will help you to generate a static site to host them. 4 | 5 | The purpose of creating VuePress was to support the documentation of Vue.js and its sub-projects, but now it has been helping a large amount of users to build their documentation, blogs, and other static sites. 6 | 7 | ## How It Works 8 | 9 | A VuePress site is in fact a single-page application (SPA) powered by [Vue](https://vuejs.org/) and [Vue Router](https://router.vuejs.org). 10 | 11 | Routes are generated according to the relative path of your markdown files. Each Markdown file is compiled into HTML with [markdown-it](https://github.com/markdown-it/markdown-it) and then processed as the template of a Vue component. This allows you to directly use Vue inside your Markdown files and is great when you need to embed dynamic content. 12 | 13 | During development, we start a normal dev-server, and serve the VuePress site as a normal SPA. If you’ve used Vue before, you will notice the familiar development experience when you are writing and developing with VuePress. 14 | 15 | During build, we create a server-rendered version of the VuePress site and render the corresponding HTML by virtually visiting each route. This approach is inspired by [Nuxt](https://nuxtjs.org/)'s `nuxt generate` command and other projects like [Gatsby](https://www.gatsbyjs.org/). 16 | 17 | ## Why Not ...? 18 | 19 | ### Nuxt 20 | 21 | Nuxt is an outstanding Vue SSR framework, and it is capable of doing what VuePress does. But Nuxt is designed for building applications, while VuePress is more lightweight and focused on content-centric static sites. 22 | 23 | ### VitePress 24 | 25 | VitePress is the little brother of VuePress. It's also created and maintained by our Vue.js team. It's even more lightweight and faster than VuePress. However, as a tradeoff, it's more opinionated and less configurable. For example, it does not support plugins. But VitePress is powerful enough to make your content online if you don't need advanced customizations. 26 | 27 | It might not be an appropriate comparison, but you can take VuePress and VitePress as Laravel and Lumen. 28 | 29 | ### Docsify / Docute 30 | 31 | Both are great projects and also Vue-powered. Except they are both fully runtime-driven and therefore not SEO-friendly. If you don’t care for SEO and don’t want to mess with installing dependencies, these are still great choices. 32 | 33 | ### Hexo 34 | 35 | Hexo has been serving the Vue 2.x docs well. The biggest problem is that its theming system is static and string-based - we want to take advantage of Vue for both the layout and the interactivity. Also, Hexo’s Markdown rendering isn’t the most flexible to configure. 36 | 37 | ### GitBook 38 | 39 | We’ve been using GitBook for most of our sub project docs. The primary problem with GitBook is that its development reload performance is intolerable with a large amount of files. The default theme also has a pretty limiting navigation structure, and the theming system is, again, not Vue based. The team behind GitBook is also more focused on turning it into a commercial product rather than an open-source tool. 40 | -------------------------------------------------------------------------------- /docs/guide/page.md: -------------------------------------------------------------------------------- 1 | # Page 2 | 3 | VuePress is markdown-centered. Each markdown file inside your project is a standalone page. 4 | 5 | ## Routing 6 | 7 | By default, the route path of a page is determined by the relative path of your markdown file. 8 | 9 | Assuming this is the directory structure of your markdown files: 10 | 11 | ``` 12 | └─ docs 13 | ├─ guide 14 | │ ├─ getting-started.md 15 | │ └─ README.md 16 | ├─ contributing.md 17 | └─ README.md 18 | ``` 19 | 20 | Take the `docs` directory as your [sourceDir](../reference/cli.md), e.g. you are running `vuepress dev docs` command. Then the route paths of your markdown files would be: 21 | 22 | | Relative Path | Route Path | 23 | | --------------------------- | ----------------------------- | 24 | | `/README.md` | `/` | 25 | | `/index.md` | `/` | 26 | | `/contributing.md` | `/contributing.html` | 27 | | `/guide/README.md` | `/guide/` | 28 | | `/guide/getting-started.md` | `/guide/getting-started.html` | 29 | 30 | ::: tip 31 | By default, both `README.md` and `index.md` would be converted to `index.html` and generate a slash-ending route path. However, it might cause conflicts if you want to keep both of the two files. 32 | 33 | In such case, you can set the [pagePatterns](../reference/config.md#pagepatterns) to avoid one of them being processed by VuePress, e.g. use `['**/*.md', '!**/README.md', '!.vuepress', '!node_modules']` to exclude all `README.md` files. 34 | 35 | Also, some symbols like `:` and `+` may have special meanings for vue-router, so you should avoid using them, see [vue-router docs](https://router.vuejs.org/guide/essentials/route-matching-syntax.html) for more details. 36 | ::: 37 | 38 | ## Frontmatter 39 | 40 | A markdown file could contain a [YAML](https://yaml.org/) frontmatter. The frontmatter must be at the top of the Markdown file and must be wrapped with a couple of triple-dashed lines. Here is a basic example: 41 | 42 | ```md 43 | --- 44 | lang: en-US 45 | title: Title of this page 46 | description: Description of this page 47 | --- 48 | ``` 49 | 50 | You must have noticed that those fields are similar with the [Site Config](./configuration.md#site-config) in the [Config File](./configuration.md#config-file). You can override `lang`, `title`, `description`, etc., of current page via frontmatter. So you can take frontmatter as page scope config. 51 | 52 | Also, VuePress has built-in support for some frontmatter fields, and your theme may have its own special frontmatter, too. 53 | 54 | ::: tip 55 | Check out the [Frontmatter Reference](../reference/frontmatter.md) for a full list of VuePress built-in frontmatter. 56 | 57 | Check out the [Default Theme > Frontmatter Reference](https://ecosystem.vuejs.press/themes/default/frontmatter.html) for the frontmatter of default theme. 58 | ::: 59 | 60 | ## Content 61 | 62 | The main content of your page is written in Markdown. VuePress will firstly transform your Markdown to HTML code, then treat the HTML code as `