---
url: /notes/dev/20250303-2.md
---
苏喵分享`vuepress-theme-hope`从编写到部署的整个过程

经过了至少一周的时间, 终于成功部署了这个属于自己的网站, 这里打算把使用`vuepress-theme-hope`编写到部署的整个过程记录分享一下

*注意: 本喵电脑为Windows, 因此不清楚其他操作系统如何操作*

*昨天(2025.6.21)某朋友惊奇的发现有人看到了我写的教程! 好开心~*

*可以加入咱的QQ群联系我喵~ `137287114`*

\[\[toc]]

***

## 1. 下载, 准备及安装

`vuepress-theme-hope`的官方网站为[点击跳转](https://theme-hope.vuejs.press/zh/), 在此页面, 我们点击`快速上手/创建项目`即可查询对应命令.

### 1.1 包管理器

这里推荐只用`pnpm`作为包管理器, 可以使用`Node.js安装程序`安装包管理器`npm`和`Node.js`, 之后使用`npm`来安装`pnpm`.

此外, 为了方便的管理node版本, 推荐使用`nvm(Node.js version manager)`进行安装和管理. `nvm`安装非常简单, 直接在Github Releases下载.exe文件即可.

`nvm`: <https://github.com/nvm-sh/nvm/releases>

```bash
nvm use 22
```

则`nvm`会自动下载并使用`22.*.*`版本, 此外, 可以使用`nvm`查看全部指令, 使用`nvm list`查看已安装版本.

之后, 使用如下指令安装`pnpm`.

```bash
npm install -g pnpm@latest-10
```

安装后, 准备一个文件夹并`cd`到此处, 使用如下指令可在此处创建一个新文件夹并在这个新文件夹中创建项目模板.

```bash
pnpm create vuepress-theme-hope <new floder>
```

### 1.2 初始化

输入指令后, 通过上下键和回车键依次选择/设置`语言: 简体中文`, `包管理器: pnpm`, `打包器: vite`, `应用名称`, `应用描述`, `版本号`, `协议`, `项目类型: blog`, `多语言: n`, `是否初始化 Git 仓库: y`, ` 是否需要一个自动部署文档到 GitHub Pages 的工作流: y`.

如果出现如下字样, 则证明初始化成功, 按y启动`Demo服务器`.

```bash
安装依赖...
这可能需要数分钟，请耐心等待.
我们无法正确输出子进程的进度条，所以进程可能会看似未响应
Packages: +379
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 441, reused 379, downloaded 0, added 379, done

devDependencies:
+ @vuepress/bundler-vite 2.0.0-rc.20
+ sass-embedded 1.85.1
+ vue 3.5.13
+ vuepress 2.0.0-rc.20
+ vuepress-theme-hope 2.0.0-rc.73

╭ Warning ───────────────────────────────────────────────────────────────────────────────────╮
│                                                                                            │
│   Ignored build scripts: esbuild.                                                          │
│   Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.   │
│                                                                                            │
╰────────────────────────────────────────────────────────────────────────────────────────────╯

Done in 12.5s using pnpm v10.4.1
模板已成功生成!
? 是否想要现在启动 Demo 查看? (Y/n)
```

随后会出现若干网址, 直接浏览器访问即可, 在终端按`Ctrl - C`可关闭服务器.

服务器关闭后, 可输入如下命令重新部署服务器:

```bash
pnpm vuepress-vite dev src
```

*若初始化时选用的其他配置, 可打开`package.json`文件, 有如下字样:*

```json
"scripts": {
    "docs:build": "vuepress-vite build src",
    "docs:clean-dev": "vuepress-vite dev src --clean-cache",
    "docs:dev": "vuepress-vite dev src",
    "docs:update-package": "pnpm dlx vp-update"
  },
```

该部分列出来服务器使用命令, 请参考[vuepress-theme-hope官方文档/快速上手/项目命令](https://theme-hope.vuejs.press/zh/get-started/command.html#常用命令)

### 1.3 禁用全局配置

关闭后, 如果直接删除文件夹, 或将文件悉数移动到新文件夹, 可能就无法再次部署/初始化, 因为pnpm配置文件是全局的.

在文件夹中新建名为`.npmrc`的文件, 输入如下内容配置镜像源为淘宝的镜像源.

```ini
registry=https://registry.npmmirror.com/
```

之后删除`node_modules`文件夹, 输入如下命令重新安装.

```bash
pnpm install
```

此时应该可以成功初始化.

### 1.4 自定义初始化

若已有项目文件夹, 可先安装`1.2`的方法进行初始化, 然后, 在所需的文件夹中添加`.npmrc`文件并按`1.3`配置.

若已有`.git`文件夹, 建议创建一个新分支, 然后删除所有文件(`.git`文件夹或`.idea`, `.vscode`文件夹除外), 如下:

```bash
git branch -a
gir branch <new branch>
git branch checkout <new branch>
```

手动删除全部文件(`.git`文件夹或`.idea`, `.vscode`文件夹除外), 并添加`.npmrc`文件.

```bash
git add .
git commit -m "<注释>"
```

然后在其他位置初始化一个项目, 复制项目文件夹下除`node_module文件夹`和`.git文件夹`外的所有文件(包括`.github文件夹 `, `pnpm-lock.yaml`, `.gitignore`, `src文件夹`, `package.json`, `tsconfig.json`), 之后`cd`到对应文件夹, 输入如下命令进行安装:

```bash
pnpm install
```

之后按照`1.2`的方法部署服务器.

若服务器可以成功运行, 关闭服务器, 将所以文件添加到`Git`中.

```bash
git add .
git commit -m "<注释>"
```

## 2. 文件结构

上述配置新建的项目文件结构如下:

```files-tree
<project floder>
├── .git
├── .github/workflows/deploy-docs.yml
├── node_module
├── src
|   ├── .vuepress
|   |   ├── .cache
|   |   ├── .temp
|   |   ├── public
|   |   ├── styles
|   |   ├── config.ts
|   |   ├── navbar.ts
|   |   ├── sidebar.ts
|   |   └── theme.ts
|   ├── demo
|   |   ├── disable.md
|   |   ├── encrypt.md
|   |   ├── layout.md
|   |   ├── markdown.md
|   |   ├── page.md
|   |   └── README.md
|   ├── posts
|   |   ├── apple
|   |   |   ├── 1.md
|   |   |   ├── 2.md
|   |   |   ├── 3.md
|   |   |   └── 4.md
|   |   ├── banana
|   |   |   ├── 1.md
|   |   |   ├── 2.md
|   |   |   ├── 3.md
|   |   |   └── 4.md
|   |   ├── cherry.md
|   |   ├── dragonfruit.md
|   |   ├── strawberry.md
|   |   └── tomato.md
|   ├── instro.md
|   └── README.md
├── .npmrc
├── .gitignore
├── package.json
├── pnpm-lock.yaml
└── tsconfig.json
```

下面我们一一介绍一下各个文件(文件夹)的作用.

### 2.1 根目录文件

* `.git`文件夹和`.gitignore`文件无需多言, `.github`文件夹为用于自动配置`Github Action`工作流的`yml`文件, 这些无需用户操作.

* `.npmrc`文件为用户创建, 初始化时并不存在, 上一节已做讲解.

* `node_module`文件夹是下载的资源, 也就是`vue`部分, 这个也无需用户管理, 它不会被添加到`Git`中, 删除后也可以使用`pnpm`重新下载.

* `src`文件夹稍后讲解, 这个是我们这个blog所有自定义部分的存储位置.

* `package.json`文件是包配置文件, 用于指导`pnpm`下载安装`node_module`, 或者更新插件/配置, 里面内容大致如下:

  ```json
  {
    "name": "demo",
    "description": "演示",
    "version": "2.0.0",
    "license": "MIT",
    "type": "module",
    "scripts": {
      "docs:build": "vuepress-vite build src",
      "docs:clean-dev": "vuepress-vite dev src --clean-cache",
      "docs:dev": "vuepress-vite dev src",
      "docs:update-package": "pnpm dlx vp-update"
    },
    "devDependencies": {
      "@vuepress/bundler-vite": "2.0.0-rc.20",
      "sass-embedded": "^1.85.0",
      "vue": "^3.5.13",
      "vuepress": "2.0.0-rc.20",
      "vuepress-theme-hope": "2.0.0-rc.73"
    }
  }
  ```

  注意到其中的`name`, `description`, `version`, `license`都与创建是填写的相同, 当然也可以自己修改, 之后使用`pnpm install`重新安装即可

  其中的`scripts`部分讲解了该项目对应命令, 分别是`构建项目`, `删除缓存并启动服务器`, `启动服务器`, `更新包`, 使用时, 直接在前面添加`pnpm`关键词即可, 即:

  ```bash
  pnpm vuepress-vite dev src
  ```

  该命令用于启动服务器, 如下提示意为启动成功.

  ```bash
  ✔ Initializing and preparing data - done in 259ms

    vite v6.1.1 dev server running at:

    ➜  Local:   http://localhost:8080/
    ➜  Network: http://**.**.**.**:****/
  ```

  `devDependencies`部分存储了该项目的相关依赖及版本, 类似`Rust`中`Cargo.toml`的`[dependencies]`, 当`node_module`文件丢失时, `pnpm`会根据这部分信息下载对应依赖.

* `tsconfig.json`我也不知道是干什么的, 能跑就别碰它, `pnpm-lock.yaml`也是.

### 2.2 src文件

`src`文件夹中, 每个MarkDown文件都对应着一个Blog中的一个页面(`.vuepress`文件夹中所有文件除外), 因此这里只讲解除`.vuepress`文件夹外的文件.

* `README.md`是一个特殊的名字, 因此`theme-hopee`把它作为每个页面都入口, 根目录下的`README.md`自然就是整个网站的入口, 类似`index.html`.

  `README.md`其中的内容我们稍后再讲, 总之, 它作为整个网站的入口, 应该有主页的样子, `theme-hope`中预设了`主页`(`博客主页`)布局, 我们稍后再讲.

* `intro.md`文件就是普通的页面文件了, 这里我们可以随便修改名称(`sidebar`和`navbar`中也要对应修改), 根目录下的其他md文件会被处理成直接在根目录的页面, 即`https://***.***/***.html`.

  这里的`intro.md`为档案首页, 默认是`江户川柯南`, 可自行修改, 稍后讲解.

* `dome`文件夹和`post`文件夹是更深一级的文件夹, 其中的文件对应个更深一级的文件, 例如其中的`README.md`对应的是`https://***.**/demo/`; 其中的普通md文件对应的是`https://***.**/demo/***.html`.

### 2.3 src/.vuepress文件

这里是除md外的页面配置文件.

* `.cache`文件夹和`.temp`文件夹无需多言, 它们都不在`Git`中.

* `public`文件夹存储着整个页面都资源文件, 例如, 若`public`文件夹下有`image/icon.png`, 则md中直接引用`image/icon.png`即可调用该图片.

* `styles`文件夹是可自定义的样式文件夹, 其中含有`index.scss`和`config.scss`, 如有自定义需求, 直接在`index.scss`中修改即可.

下面是几个`ts`文件的作用

* `config.ts`是网页的配置信息, 包括`语言`, `标题`和`描述`, 它们会出现在网页的`<title>`中.

  ```TypeScript
  import { defineUserConfig } from "vuepress";

  import theme from "./theme.js";

  export default defineUserConfig({
    base: "/",

    lang: "zh-CN",
    title: "博客演示",
    description: "vuepress-theme-hope 的博客演示",

    theme,

    // 和 PWA 一起启用
    // shouldPrefetch: false,
  });
  ```

  其中`title`和`description`自行修改, 其他配置项不要动.

* `navbar.ts`顾名思义为网页顶部的导航栏(手机端为右侧的按钮), 默认的`navbar.ts`如下所示:

  ```typescript
  import { navbar } from "vuepress-theme-hope"

  export default navbar([
    "/",
    "/demo/",
    {
      text: "博文",
      icon: "pen-to-square",
      prefix: "/posts/",
      children: [
        {
          text: "苹果",
          icon: "pen-to-square",
          prefix: "apple/",
          children: [
            { text: "苹果1", icon: "pen-to-square", link: "1" },
            { text: "苹果2", icon: "pen-to-square", link: "2" },
            "3",
            "4",
          ],
        },
        {
          text: "香蕉",
          icon: "pen-to-square",
          prefix: "banana/",
          children: [
            {
              text: "香蕉 1",
              icon: "pen-to-square",
              link: "1",
            },
            {
              text: "香蕉 2",
              icon: "pen-to-square",
              link: "2",
            },
            "3",
            "4",
          ],
        },
        { text: "樱桃", icon: "pen-to-square", link: "cherry" },
        { text: "火龙果", icon: "pen-to-square", link: "dragonfruit" },
        "tomato",
        "strawberry",
      ],
    },
    {
      text: "V2 文档",
      icon: "book",
      link: "https://theme-hope.vuejs.press/zh/",
    },
  ])
  ```

````

  其中`export default navbar()`内部传入一个数组, 也就是`navbar`中显示的各个项目, 每个元素对应着导航栏的一个按钮.

  - `"/"`: 根目录, 即`README.md`

  - `"/demo/"`: demo文件夹目录, 即`demo/README.md`

  - `{}`: 对象, 具体解释如下:

  ```typescript
  {
      text: "博文",
      icon: "pen-to-square",
      prefix: "/posts/",
      children: [
        {
          text: "苹果",
          icon: "pen-to-square",
          prefix: "apple/",
          children: [
            { text: "苹果1", icon: "pen-to-square", link: "1" },
            { text: "苹果2", icon: "pen-to-square", link: "2" },
            "3",
            "4",
          ],
        },
      ],
    },
````

* `text`: `navbar`栏显示文字.

* `icon`: `navbar`栏显示图标, 具体参考Vuepress-theme-hope官方文档[指南/页面/图标支持](https://theme-hope.vuejs.press/zh/guide/interface/icon.html)

* `prefix`: 为该目录对应位置, `/posts/`即`/posts/README.md`

* `children`: 可选, 如有, 则该按钮变为下拉按钮, 可选择其中的子页面.

  `children`中配置和`export default navbar()`配置一模一样, 也是传入一个数组, 该数组元素可以是`路径("/"或"/demo/")`, 也可以是`结构("{}", 内容和上述完全一样)`, 结构也支持继续进行`children`嵌套.

* 如果不使用`prefix`和`children`表明 位置, 还可以直接使用`link`链接到一个网络位置.

* `sidebar.ts`文件是网页的侧边栏, 咱网页的左边, 作为文档的导航, 默认的`sidebar.ts`如下所示:

  ```typescript
  import { sidebar } from "vuepress-theme-hope"

  export default sidebar({
    "/": [
      "",
      {
        text: "如何使用",
        icon: "laptop-code",
        prefix: "demo/",
        link: "demo/",
        children: "structure",
      },
      {
        text: "文章",
        icon: "book",
        prefix: "posts/",
        children: "structure",
      },
      "intro",
      {
        text: "幻灯片",
        icon: "person-chalkboard",
        link: "https://ecosystem.vuejs.press/zh/plugins/markdown/revealjs/demo.html",
      },
    ],
  })
  ```

  注意到`sidebar`中向`export default sidebar()`传入一个对象参数, 默认为`"/": []`, 在这个数组中, 可以填下自定义的内容, 形式和`navbar`并无太大区别.

  注意, 若设置`prefix: "posts/"`, `children: "structure"`, 则`sidebar`中会自动显示所有子文件, 若添加`collapsible: true`参数, 则该按钮可折叠.

  同理也可以直接使用`link`链接一个网络位置.

* `theme.ts`是整个项目的配置文件, 其中内置了大量可配置内容, 详细参考[Vuepress-theme-hope官方文档](https://theme-hope.vuejs.press/zh/guide/).

## 3. 主页

### 3.1 博客主页

进入网页, 第一个页面就是`主页(README.md)`. 该页面作为网页的门户, 一定要认知编写. 所幸的是, hope大佬给我们预制了一个很漂亮的主页模板, 默认的`README.md`便是一个成型的主页.

```yaml
---
home: true
layout: BlogHome
icon: house
title: 博客主页
heroImage: https://theme-hope-assets.vuejs.press/logo.svg
heroText: 你博客的名称
heroFullScreen: true
tagline: 你可以在这里放置你的口号与标语
projects:
  - icon: folder-open
    name: 项目名称
    desc: 项目详细描述
    link: https://你的项目链接

  - icon: link
    name: 链接名称
    desc: 链接详细描述
    link: https://链接地址

  - icon: book
    name: 书籍名称
    desc: 书籍详细描述
    link: https://你的书籍链接

  - icon: newspaper
    name: 文章名称
    desc: 文章详细描述
    link: https://你的文章链接

  - icon: user-group
    name: 伙伴名称
    desc: 伙伴详细介绍
    link: https://你的伙伴链接

  - icon: https://theme-hope-assets.vuejs.press/logo.svg
    name: 自定义项目
    desc: 自定义详细介绍
    link: https://你的自定义链接

footer: 自定义你的页脚文字
---

这是一个博客主页的案例。

要使用此布局，你应该在页面前端设置 `layout: BlogHome` 和 `home: true`。

相关配置文档请见 [博客主页](https://theme-hope.vuejs.press/zh/guide/blog/home.html)。

```

1. `Frontmatter`是每个md文件开头的一段参数文本, 该部分文本会使用预设的页面, 使用该部分的参数进行配置.

`Frontmatter`有部分为所有文件通用的参数, 当然也有每个页面(主要指预设页面)特有的参数.

* `home: true`和`layout: blogHome`为`博客主页`的标识, 要使用该页面预设, 需在文档顶部添加该字样.

* `icon: home`是该页面的图标, 更多图标请参考Vuepress-theme-hope官方文档[指南/页面/图标支持](https://theme-hope.vuejs.press/zh/guide/interface/icon.html)

* `title: 博客主页`为该页面在`navbar`和`sidebar`中显示的标题以及在页面标签页显示的子标题.

* `heroText: 你博客的名称`, `heroImage: ***`和`heroFullScreen: true`分别为页面中间的标题, 页面背景图片和背景图片是否全屏.

  页面背景图片可以传入`url`, 也可以传入位置, 位置只能以`.vuepress/public`文件夹为基准.

* `tagline`可以展示一条你的标语, 在主页头像下方.

  主页头像在这里无法修改, 相关数据存储在`.vuepress/theme.ts`中, 该文件上面并未详细讲解, 但我认为你看得懂.

2. 接下来有一个`projects`栏目, 下设若干小项目, 这个是也是主页预设的组件, 显示在主页一整面屏下方左侧, 博客上面.

每个小组件都有4个参数, 这里无需过多讲解.

```yaml
projects:
  - icon: heart
    name: 认识一下
    desc: 这里是Twisuki~
    link: intro.md

  - icon: pen-to-square
    name: 苏喵笔记
    desc: 随笔, 感想, 生活中的一点..小事
    link: /notes/

  - icon: gears
    name: 苏の百宝箱
    desc: 各种各样奇奇怪怪的小工具(?)
    link: /kits/

  - icon: bxl:github
    name: Github Profile
    desc: Github主页, 求fo喵~
    link: https://github.com/Twisuki

  - icon: user-group
    name: 苏喵的好朋友
    desc: 一起贴贴的小猫娘们~
    link: friend.md

  - icon: https://theme-hope-assets.vuejs.press/logo.svg
    name: 技术支持
    desc: vuepress-theme-hope官方主页
    link: https://theme-hope.vuejs.press/zh/
```

这是本喵博客首页下面的组件.

3. `footer`定义了页脚内容. 这里可以直接删去, 使用默认页脚. 默认页脚同样存储在`.vuepress/theme.ts`中.

4. 下面的`md`文件就是普通的`MarkDown`语法, 在这里的md将会渲染在网页最下面, 使用`theme-hope`内置的渲染样式进行渲染.

5. 主页一整面屏下方右侧是`博主信息`, 它们也存储在`.vuepress/theme.ts`中.

6. 主页下面是博客缩略展示, 整个文档的文章(配置`article: false`的除外)都会展示在这里.

### 3.2 档案主页

档案主页为在上述初始化项目中并没有自动生成, 如果初始化时`项目类型: blog`选为`docs`即可生成`主页`和`档案主页`两个预设页面.

Vuepress-theme-hope官方[案例/档案主页](https://theme-hope.vuejs.press/zh/demo/portfolio-home.html)

咱自己的档案主页配置如下

```yaml
---
containerClass: home
home: true
portfolio: true
icon: heart
sidebar: false
avatar: avatar.png
welcome: 你好, 这里是
name: Twisuki
titles:
  - Hi, this is Twisuki~
  - Welcome to my page meow~

---

# 介绍 intro
```

1. 要使用档案主页, `Frontmatter`中需存在`home: true`和`portfolio: true`参数. `icon`参数上面已经进行讲解.

2. 档案主页特殊`Frontmatter`参数有`avatar: ***`, `welcome: ***`, `name: ***`和`titles: ***`.

其中`avatar`是一个非常大的图片, 展示在屏幕左侧.

\`\`welcome: ***`, `name:***`和`titles: \*\*\*`为展示在右侧的三行文本, 其中`title`可以接入多个`\<li>\`参数, 页面会滚动展示这些文本.

3. `sidebar: false`为通用`Frontmatter`参数, 可隐藏`sidebar`, 此外, `navbar: true/false`同理, 这样的参数在初始化文档中`src/demo/disable.md`中已经说明.

4. 右侧三行文本下方是各个账号的信息, 无法在此处修改, 它们存储在`.vuepress/theme.ts`中.

5. `Frontmatter`下方可以使用普通的`MarkDown`语法进行其他内容的编写.

其中一级标题`#`的内容会被处理成`navbar`或者`sidebar`位置的标题.

## 4. 页面与侧边栏, 导航栏

### 4.1 页面

普通页面为一个`MarkDown`文档, 由`Frontmatter部分`和`md部分`两部分构成. 但个人认为中间特殊组件也可以算作一部分.

1. `Frontmatter`

这是初始化项目中`src/.vuepresss/demo/page.md`的`Frontmatter`部分:

```yaml
---
# 这是文章的标题
title: 页面配置
# 你可以自定义封面图片
cover: /assets/images/cover1.jpg
# 这是页面的图标
icon: file
# 这是侧边栏的顺序
order: 3
# 设置作者
author: Ms.Hope
# 设置写作时间
date: 2020-01-01
# 一个页面可以有多个分类
category:
  - 使用指南
# 一个页面可以有多个标签
tag:
  - 页面配置
  - 使用指南
# 此页面会在文章列表置顶
sticky: true
# 此页面会出现在星标文章中
star: true
# 你可以自定义页脚
footer: 这是测试显示的页脚
# 你可以自定义版权信息
copyright: 无版权
---
```

其中介绍了很多常用`Frontmatter`配置和参数, 正常编写中, 我们不需要那么多, 直接复制粘贴即可.

```yaml
---
title: Vuepress-theme-hope部署
icon: fa6-brands:markdown
date: 2025-03-03
category:
  - 开发
  - 前端技术
tag:
  - vuepress
  - hope
---
```

这是本页面的`Frontmatter`配置和参数, 正常页面也只需要这么多参数.

此外, 这是`src/.vuepresss/demo/disable.md`的`Frontmmatter`部分:

```yaml
---
title: 布局与功能禁用
icon: gears
order: 4
category:
  - 使用指南
tag:
  - 禁用

navbar: false
sidebar: false

breadcrumb: false
pageInfo: false
contributors: false
editLink: false
lastUpdated: false
prev: false
next: false
comment: false
footer: false

backtotop: false
---
```

这里配置了一些禁用项, 具体情况详见`src/.vuepresss/demo/disable.md`.

其他`Frontmatter`配置见Vuepress-theme-hope官方文档[配置/Frontmatter配置](https://theme-hope.vuejs.press/zh/config/frontmatter/)

2. 正文组件

   1. 摘要

   在`Frontmatter`下方添加`<!-- more -->`字样, 则之间的内容会被处理成摘要, 显示在主页下方.

   若无`<!-- more -->`摘要, 则会自动生成, 取正文部分开头的几行文字显示出来.

   2. 目录

   使用`[[toc]]`可生成一个该页面的目录(用于普通页面), 使用`<Catalog />`可生成该文件夹的目录(多用于`README.md`)

本页上方文本如下:

```md
苏喵分享`vuepress-theme-hope`从编写到部署的整个过程

<!-- more -->

经过了至少一周的时间, 终于成功部署了这个属于自己的网站, 这里打算把使用`vuepress-theme-hope`编写到部署的整个过程记录分享一下

_注意: 本喵电脑为Windows, 因此不清楚其他操作系统如何操作_

[[toc]]

---
```

*其中最下方的`---`并非内置的部分分割符, 单纯是`markdown`内置的分割符, 显示在文本中为`<hr/>`*

3. md正文

由于`Vuepress`使用`markdown-it`解析`markdown`内容, 因此除原生md语法外, 部分md语法拓展可直接使用.

如`Github风格的表格`, `删除线`, `Emoji`, `TOC(就是上述介绍的组件)`.

此外, 可以安装其他md解析库, 用以显示其他md内容.

详情请见Vuepress-theme-hope官方文档[指南/Markdown介绍](https://theme-hope.vuejs.press/zh/guide/markdown/intro.html)

以TeX支持为例, 首先安装`katex`或者`mathjax-full`, 这里以`katex`为例.

```bash
pnpm add -D katex
```

之后在`src/.vuepress/config.ts`中配置:

```ts
import { defineUserConfig } from "vuepress"
import { hopeTheme } from "vuepress-theme-hope"

export default defineUserConfig({
  theme: hopeTheme({
    markdown: {
      math: {
        type: "katex", // 或 'mathjax'
      },
    },
  }),
})
```

*摘自Vuepress-theme-hope官方文档[指南/Markdown/语法/数学公式](https://theme-hope.vuejs.press/zh/guide/markdown/grammar/math.html)*

此时即可正常显示`LaTeX`

$$
\text{例 解线性方程组:}
\begin{cases}
x\_1 + x\_2 + x\_3 = 1 \\
x\_1 + 2x\_1 - 5x\_3 = 2 \\
2x\_1 + 3x\_2 - 4x\_3 = 3
\end{cases}
\ \ \\
\text{解: 对方程组增广矩阵进行初等行变换:} \\

\overline{A} = \begin{pmatrix}
1 & 1 & 1 & 1 \\
1 & 2 & -5 & 2 \\
2 & 3 & -4 & 3
\end{pmatrix}
\xrightarrow\[r\_3 + (-2) \times r\_1]{r\_2 + (-1) \times r\_1}
\begin{pmatrix}
1 & 1 & 1 & 1 \\
0 & 1 & 6 & 1 \\
0 & 1 & -6 & 1
\end{pmatrix}
\xrightarrow\[r\_3 + (-1) \times r\_1]{r\_1 + (-1) \times r\_2}
\begin{pmatrix}
1 & 0 & 7 & 0 \\
0 & 1 & -6 & 1 \\
0 & 0 & 0 & 0
\end{pmatrix}
\ \ \\
\text{变换后对应阶梯线性方程组:} \\

\begin{cases}
x\_1 \ \ \ \ \ \ \ + 7x\_3 = 0 \\
\ \ \ \ \ \ \ x\_2 - 6x\_3 = 1
\end{cases}
\\
\text{它与原方程同解, 取} x\_3 = k \text{, 则} x\_1 = -7k, x\_2 = 1 + 6k \text{, 则原方程解为:}

\begin{cases}
x\_1 = -7k \\
x\_2 = 1 + 6k \\
x\_3 = k
\end{cases}
$$

代码如下:

```tex
$$
\text{例 解线性方程组:} 
\begin{cases}
  x_1 + x_2 + x_3 = 1 \\
  x_1 + 2x_1 - 5x_3 = 2 \\
  2x_1 + 3x_2 - 4x_3 = 3
\end{cases}
\\ \ \\
\text{解: 对方程组增广矩阵进行初等行变换:} \\

\overline{A} = \begin{pmatrix}
  1 & 1 & 1 & 1 \\
  1 & 2 & -5 & 2 \\
  2 & 3 & -4 & 3
\end{pmatrix}
\xrightarrow[r_3 + (-2) \times r_1]{r_2 + (-1) \times r_1}
\begin{pmatrix}
  1 & 1 & 1 & 1 \\
  0 & 1 & 6 & 1 \\
  0 & 1 & -6 & 1
\end{pmatrix}
\xrightarrow[r_3 + (-1) \times r_1]{r_1 + (-1) \times r_2}
\begin{pmatrix}
  1 & 0 & 7 & 0 \\
  0 & 1 & -6 & 1 \\
  0 & 0 & 0 & 0
\end{pmatrix}
\\ \ \\
\text{变换后对应阶梯线性方程组:} \\

\begin{cases}
  x_1 \ \ \ \ \ \ \ + 7x_3 = 0 \\
  \ \ \ \ \ \ \ x_2 - 6x_3 = 1
\end{cases}
\\
\text{它与原方程同解, 取} x_3 = k \text{, 则} x_1 = -7k, x_2 = 1 + 6k \text{, 则原方程解为:}

\begin{cases}
  x_1 = -7k \\
  x_2 = 1 + 6k \\
  x_3 = k
\end{cases}
$$
```

### 4.2 侧边栏

上述`2.3 src/.vuepress文件`已讲解`sidebar.ts`的文件结构, 这里只进行补充.

本项目文件结构(部分)如下:

```files-tree
src
├── .vuepress
├── notes
|   ├── dev
|   |   ├── README.md
|   |   └── 1.md
|   └── other
|       └── README.md
├── kits
└── README.md
```

对应`sidebar.ts`(部分)为:

```ts
import { sidebar } from "vuepress-theme-hope"

export default sidebar({
  "/": [
    "",
    {
      text: "笔记 notes",
      icon: "book",
      prefix: "notes/",
      link: "notes/",
      children: [
        {
          text: "开发",
          icon: "gear",
          prefix: "dev/",
          collapsible: true,
          children: "structure"
        },
        {
          text: "其他",
          icon: "fa6-brands:markdown",
          prefix: "other/",
          collapsible: true,
          children: "structure"
        }
      ],
    },
    {
      text: "工具 kites",
      icon: "gears",
      prefix: "kits/",
      collapsible: true,
      children: "structure",
    },
    {
      text: "项目 projects",
      icon: "star",
      collapsible: true,
      children: [
        {
          text: "弦月档案",
          icon: "link",
          link: "https://twis.uk/yisibite",
        },
      ],
    }
  ],
})
```

留空则默认为`README.md`, 文件但不留后缀则默认为`.md`, `/`结尾为文件夹(`README.md`省略了).

`children: "structure"`则将文件夹下属所有子文件全部列出, `collapsible: true`则使该列表成为下拉列表.

### 4.3 导航栏

本项目导航栏十分简单

```ts
import { navbar } from "vuepress-theme-hope"

export default navbar([
  "/",
  "intro",
  "/notes/",
  "/kits/",
  "friend",
  {
    text: "项目 projects",
    icon: "star",
    children: [
      {
        text: "弦月档案",
        icon: "link",
        link: "https://twis.uk/yisibite",
      },
      {
        text: "线代笔记",
        icon: "link",
        link: "https://twis.uk/Notes-on-Linear-Algebra"
      }
    ]
  }
])
```

使用对象来插入没有直接入口的内容.

## 5. 插件

`LaTeX`插件的安装和使用在`4.1.3`已有所讲解, 这里不定期更新, 讲解其他插件的安装/配置(如果需要)

### 5.1 `docsearch`搜索插件

搜索功能详见vuepress-theme-hope官方文档[指南/功能/搜索](https://theme-hope.vuejs.press/zh/guide/feature/search.html), 里面提供了三种不同的搜索插件支持, 这里讲解第一种, 使用`docsearch`插件添加搜索功能.

1. 安装`docsearch`插件

```bash
pnpm add -D @vuepress/plugin-docsearch@next
```

2. 配置`docsearch`

在`src/.vuepress/theme.ts`中, 找到`export default hopeTheme({})`中的`plugin: {}`项, 配置如下:

```ts
import { hopeTheme } from "vuepress-theme-hope"

export default {
  theme: hopeTheme({
    plugins: {
      docsearch: {
        appId: "",
        apiKey: "",
        indexName: "",
      },
    },
  }),
}
```

配置后重启`web服务器`, 之后即可在`navbar`中看到搜索框, 它的样式`vuepress-theme-hope`已经写好.

但此事搜索功能是无法使用的, 我们需要向`DocSearch`团队申请`appId`, `apiKey`和`indexName`.

3. 申请爬虫

直接到`DocSearch`的爬虫[申请网站](https://docsearch.algolia.com/apply/), 按要求输入`Blog URL`, `Email`, 并勾选下面三个勾选框, `Join the program`即可.

注意检查自己的邮箱, `algolia`团队会给你发送邮件, 该邮件仅用于通知.

两个工作日之内会收到第二封邮件, 该邮件中详细说明了部署方法和爬虫控制台网页链接.

控制台链接为<https://dashboard.algolia.com/>/data sources/crawler/..

邮件中, 介绍的部署方法都`JavaScript`部分如下:

```txt
JavaScript
Copy this snippet at the end of the HTML <body> tag:

<script src="https://cdn.jsdelivr.net/npm/@docsearch/js@3"></script>

<script type="text/javascript">

docsearch({

appId: "**",

apiKey: "**",

indexName: "**",

container: "### REPLACE ME WITH A CONTAINER (e.g. div) ###",

debug: false 

});

</script>
```

我们直接复制其中的`appId`, `apiKey`, `indexName`到`theme.ts`对应位置, 重启服务器即可.

但此时搜索仍不可用.

4. 爬虫配置

打开爬虫控制台<https://dashboard.algolia.com/>/data sources/crawler/..

进入爬虫`Overview`页面后, 点击`Editor`, 在编辑器中删去`apiKey`行(第三行)以下所有内容, 到vuepress-theme-hope官方文档[指南/功能/搜索/配置爬虫](https://theme-hope.vuejs.press/zh/guide/feature/search.html)中复制爬虫配置代码.

代码如下:

```ts
new Crawler({
  appId: "YOUR_APP_ID",
  apiKey: "YOUR_API_KEY",
  rateLimit: 8,
  startUrls: [
    // 这是 Algolia 开始抓取网站的初始地址
    // 如果你的网站被分为数个独立部分，你可能需要在此设置多个入口链接
    "https://YOUR_WEBSITE_URL/",
  ],
  sitemaps: [
    // 如果你在使用 Sitemap 插件 (如: @vuepress/plugin-sitemap)，你可以提供 Sitemap 链接
    "https://YOUR_WEBSITE_URL/sitemap.xml",
  ],
  ignoreCanonicalTo: false,
  exclusionPatterns: [
    // 你可以通过它阻止 Algolia 抓取某些 URL
  ],
  discoveryPatterns: [
    // 这是 Algolia 抓取 URL 的范围
    "https://YOUR_WEBSITE_URL/**",
  ],
  // 爬虫执行的计划时间，可根据文档更新频率设置
  schedule: "at 02:00 every 1 day",
  actions: [
    // 你可以拥有多个 action，特别是你在一个域名下部署多个文档时
    {
      // 使用适当的名称为索引命名
      indexName: "YOUR_INDEX_NAME",
      // 索引生效的路径
      pathsToMatch: ["https://YOUR_WEBSITE_URL/**"],
      // 控制 Algolia 如何抓取你的站点
      recordExtractor: ({ $, helpers }) => {
        // 以下是适用于 vuepress-theme-hope 的默认选项选项
        return helpers.docsearch({
          recordProps: {
            lvl0: {
              selectors: [".vp-sidebar-link.active", "[vp-content] h1"],
              defaultValue: "Documentation",
            },
            lvl1: "[vp-content] h1",
            lvl2: "[vp-content] h2",
            lvl3: "[vp-content] h3",
            lvl4: "[vp-content] h4",
            lvl5: "[vp-content] h5",
            lvl6: "[vp-content] h6",
            content: "[vp-content] p, [vp-content] li",
          },
          recordVersion: "v3",
        })
      },
    },
  ],
  initialIndexSettings: {
    // 控制索引如何被初始化，这仅当索引尚未生成时有效
    // 你可能需要在修改后手动删除并重新生成新的索引
    YOUR_INDEX_NAME: {
      attributesForFaceting: ["type", "lang"],
      attributesToRetrieve: ["hierarchy", "content", "anchor", "url"],
      attributesToHighlight: ["hierarchy", "hierarchy_camel", "content"],
      attributesToSnippet: ["content:10"],
      camelCaseAttributes: ["hierarchy", "hierarchy_radio", "content"],
      searchableAttributes: [
        "unordered(hierarchy_radio_camel.lvl0)",
        "unordered(hierarchy_radio.lvl0)",
        "unordered(hierarchy_radio_camel.lvl1)",
        "unordered(hierarchy_radio.lvl1)",
        "unordered(hierarchy_radio_camel.lvl2)",
        "unordered(hierarchy_radio.lvl2)",
        "unordered(hierarchy_radio_camel.lvl3)",
        "unordered(hierarchy_radio.lvl3)",
        "unordered(hierarchy_radio_camel.lvl4)",
        "unordered(hierarchy_radio.lvl4)",
        "unordered(hierarchy_radio_camel.lvl5)",
        "unordered(hierarchy_radio.lvl5)",
        "unordered(hierarchy_radio_camel.lvl6)",
        "unordered(hierarchy_radio.lvl6)",
        "unordered(hierarchy_camel.lvl0)",
        "unordered(hierarchy.lvl0)",
        "unordered(hierarchy_camel.lvl1)",
        "unordered(hierarchy.lvl1)",
        "unordered(hierarchy_camel.lvl2)",
        "unordered(hierarchy.lvl2)",
        "unordered(hierarchy_camel.lvl3)",
        "unordered(hierarchy.lvl3)",
        "unordered(hierarchy_camel.lvl4)",
        "unordered(hierarchy.lvl4)",
        "unordered(hierarchy_camel.lvl5)",
        "unordered(hierarchy.lvl5)",
        "unordered(hierarchy_camel.lvl6)",
        "unordered(hierarchy.lvl6)",
        "content",
      ],
      distinct: true,
      attributeForDistinct: "url",
      customRanking: [
        "desc(weight.pageRank)",
        "desc(weight.level)",
        "asc(weight.position)",
      ],
      ranking: [
        "words",
        "filters",
        "typo",
        "attribute",
        "proximity",
        "exact",
        "custom",
      ],
      highlightPreTag:
        "<span class=\"algolia-docsearch-suggestion--highlight\">",
      highlightPostTag: "</span>",
      minWordSizefor1Typo: 3,
      minWordSizefor2Typos: 7,
      allowTyposOnNumericTokens: false,
      minProximity: 1,
      ignorePlurals: true,
      advancedSyntax: true,
      attributeCriteriaComputedByMinProximity: true,
      removeWordsIfNoResults: "allOptional",
    },
  },
})
```

注意最上方三行不要冲突和错误, 复制到爬虫控制台中, 待自动保存和检查结束后, 点击`Review and Publish`.

结束后, 回到`Overview`页, 再点击`Resume crawling`运行爬虫, 等待一段时间即可.

此时搜索功能即可正常使用.
