--- url: /index.md --- # Vuepress Theme Plume ::: center ![GitHub Repo stars](https://img.shields.io/github/stars/pengzhanbo/vuepress-theme-plume){.no-view} ![npm version](https://img.shields.io/npm/v/vuepress-theme-plume?color=32A9C3\&labelColor=1B3C4A\&label=npm){.no-view} ![npm downloads](https://img.shields.io/npm/dm/vuepress-theme-plume?color=32A9C3\&labelColor=1B3C4A\&label=downloads){.no-view} ![npm downloads](https://img.shields.io/npm/dt/vuepress-theme-plume?color=32A9C3\&labelColor=1B3C4A\&label=downloads){.no-view} ![github license](https://img.shields.io/github/license/pengzhanbo/vuepress-theme-plume?color=32A9C3\&labelColor=1B3C4A){.no-view} ![peer dependency](https://img.shields.io/npm/dependency-version/vuepress-theme-plume/peer/vuepress?color=32A9C3\&labelColor=1B3C4A){.no-view} ![codecov](https://codecov.io/gh/pengzhanbo/vuepress-theme-plume/graph/badge.svg?token=W6KYBX7WO5){.no-view} ::: ### 使用 使用以下命令,快速创建一个新的使用本主题的 ==VuePress== 项目。 :::npm-to ```sh npm create vuepress-theme-plume@latest ``` ::: ### 启动项目 ::: npm-to ```sh npm run docs:dev ``` ::: ### 更新记录 [Changelog](./changelog.md) ### 贡献者 感谢所有的贡献者! --- --- url: /article/0lk24ty5/index.md --- # 标题H1 ## 标题H2 ### 标题H3 #### 标题H4 ##### 标题H5 ###### 标题H6 ## 标题2 Badge ### 标题3 Badge #### 标题4 Badge 正文内容。 `@property` CSS at-rule是 [CSS Houdini API](https://developer.mozilla.org/zh-CN/docs/Web/Guide/Houdini) 的一部分,它允许开发者显式地定义他们的 [CSS 自定义属性](https://developer.mozilla.org/zh-CN/docs/Web/CSS/--*), 允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。 `@property` 的出现,极大的增强了 CSS 的能力。 加粗:**加粗文字** 斜体: *斜体文字* \~~删除文字~~ 内容 ==标记== 数学表达式: $-(2^{n-1})$ ~ $2^{n-1} -1$ $\frac {\partial^r} {\partial \omega^r} \left(\frac {y^{\omega}} {\omega}\right) \= \left(\frac {y^{\omega}} {\omega}\right) \left{(\log y)^r + \sum\_{i=1}^r \frac {(-1)^ Ir \cdots (r-i+1) (\log y)^{ri}} {\omega^i} \right}$ 19^th^ H~2~O ::: center 内容居中 ::: ::: right 内容右对齐 ::: * 无序列表1 * 无序列表2 * 无序列表3 1. 有序列表1 2. 有序列表2 3. 有序列表3 * \[ ] 任务列表1 * \[ ] 任务列表2 * \[x] 任务列表3 * \[x] 任务列表4 | Tables | Are | Cool | | ------------- |:-------------:| -----:| | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | > 引用内容 > > 引用内容 [链接](/) [外部链接](https://github.com/pengzhanbo) ![plume](/plume.png) **Badge:** **图标:** * home - * vscode - * twitter - **demo wrapper:** ::: demo-wrapper title="示例" no-padding height="200px" ::: **代码:** ```js whitespace const a = 1 const b = 2 const c = a + b // [!code word:obj] const obj = { toLong: { deep: { deep: { deep: { value: 'this is to long text. this is to long text. this is to long text. this is to long text.', // [!code highlight] } } } } } ``` **Code Blocks TwoSlash:** ```ts twoslash // @errors: 2339 const welcome = 'Tudo bem gente?' const words = welcome.contains(' ') ``` ```ts twoslash import express from 'express' const app = express() app.get('/', (req, res) => { res.send }) app.listen(3000) ``` ```ts twoslash import { createHighlighter } from 'shiki' const highlighter = await createHighlighter({ themes: ['nord'], langs: ['javascript'] }) // @log: Custom log message const a = 1 // @error: Custom error message const b = 1 // @warn: Custom warning message const c = 1 // @annotate: Custom annotation message ``` ```ts twoslash // @errors: 2540 interface Todo { title: string } const todo: Readonly = { title: 'Delete inactive users'.toUpperCase(), // ^? } todo.title = 'Hello' Number.parseInt('123', 10) // ^| // // ``` ```vue twoslash ``` **代码分组:** ::: code-tabs @tab tab1 ```js const a = 1 const b = 2 const c = a + b ``` @tab tab2 ```ts const a: number = 1 const b: number = 2 const c: number = a + b ``` ::: **代码块高亮:** ```ts function foo() { const a = 1 // [!code highlight] console.log(a) const b = 2 // [!code ++] const c = 3 // [!code --] console.log(a + b + c) // [!code error] console.log(a + b) // [!code warning] } ``` **代码块聚焦:** ```ts function foo() { const a = 1 // [!code focus] } ``` ::: tip 仅标题 ::: ::: note 注释 注释内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: info 信息 信息内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: tip 提示 提示内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: warning 警告 警告内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: caution 错误 错误内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: important 重要 重要内容 [link](https://github.com/pengzhanbo) `inline code` ```js const a = 1 const b = 2 const c = a + b ``` ::: ::: details 详细标题 这里是内容。 ::: **GFM alert:** > \[!note] > note > \[!info] > info > \[!tip] > tip > \[!warning] > warning > \[!caution] > caution > \[!important] > important **代码演示:** :::: demo title="常规示例" desc="一个常规示例" ::: code-tabs @tab HTML ```html

vuepress-theme-plume

``` @tab Javascript ```js const a = 'So Awesome!' const app = document.querySelector('#app') app.appendChild(window.document.createElement('small')).textContent = a ``` @tab CSS ```css #app { font-size: 2em; text-align: center; } ``` ::: :::: **选项卡:** ::: tabs @tab 标题1 内容区块 @tab 标题2 内容区块 ::: :::: warning ::: tabs @tab 标题1 内容区块 @tab 标题2 内容区块 ::: :::: **脚注:** 脚注 1 链接\[^first]。 脚注 2 链接[^second]。 行内的脚注^\[行内脚注文本] 定义。 重复的页脚定义[^second]。 \[^first]: 脚注 **可以包含特殊标记** ``` 也可以由多个段落组成 ``` [^second]: 脚注文字。 --- --- url: /article/2z59hh8g/index.md --- # 内容水印 ## 概述 不过最需要强调的便是它的可读性。一份使用 Markdown 格式撰写的文件应该可以直接以纯文字发佈,并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响, 包括 [Setext][1]、[atx][2]、[Textile][3]、[reStructuredText][4]、[Grutatext][5] 和 [EtText][6],然而最大灵感来源其实是纯文字的电子邮件格式。 因此 Markdown 的语法全由标点符号所组成,并经过严谨慎选,是为了让它们看起来就像所要表达的意思。像是在文字两旁加上星号,看起来就像\*强调\*。Markdown 的列表看起来,嗯,就是列表。假如你有使用过电子邮件,引言写法看起来就真的像是引用一段文字。 Markdown 具有一系列衍生版本,用于扩展 Markdown 的功能 (如表格、脚注、内嵌 HTML 等等) , 这些功能原初的 Markdown 尚不具备,它们能让 Markdown 转换成更多的格式,例如 LaTeX,Docbook。 Markdown 增强版中比较有名的有 Markdown Extra、MultiMarkdown、 Maruku 等。这些衍生版本要么基于工具,如 Pandoc;要么基于网站,如 GitHub 和 Wikipedia,在语法上基本兼容,但在一些语法和渲染效果上有改动。 ## 用途 Markdown 的语法有个主要的目的: 用来作为一种网络内容的*写作*用语言。Markdown 的重点在于,它能让文件更容易阅读、编写。因此,Markdown 的格式语法只涵盖纯文字可以涵盖的范围。 Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多人用它写博客。世界上最流行的博客平台 WordPress 能很好的支持 Markdown。 用于编写说明文档,并且以 `README.md` 的文件名保存在软件的目录下面。 除此之外,我们还可以快速将 Markdown 转化为演讲 PPT、Word 产品文档、LaTex 论文甚至是用非常少量的代码完成最小可用原型。在数据科学领域,Markdown 已经广泛使用,极大地推进了动态可重复性研究的历史进程。 ### 行内 HTML 不在 Markdown 涵盖范围之外的标签,都可以直接在文件里面用 HTML 撰写。不需要额外标注这是 HTML 或是 Markdown;只要直接加标签就可以了。 只有块元素 ── 比如 `
`、``、`
`、`

` 等标签,必须在前后加上空行,以利与内容区隔。 而且这些 (元素) 的开始与结尾标签,不可以用 tab 或是空白来缩进。Markdown 的解析器有智慧型判断,可以避免在块标签前后加上没有必要的 `

` 标签。 举例来说,在 Markdown 文件里加上一段 HTML 表格: ```md This is a regular paragraph.

Foo
This is another regular paragraph. ``` 请注意,Markdown 语法在 HTML 块标签中将不会被进行处理。例如,你无法在 HTML 块内使用 Markdown 形式的 `*强调*`。 ### 特殊字元自动转换 在 HTML 文件中,有两个字元需要特殊处理: `<` 和 `&` 。 `<` 符号用于起始标签,`&` 符号则用于标记 HTML 实体,如果你只是想要使用这些符号,你必须要使用实体的形式,像是 `<` 和 `&`。 `&` 符号其实很容易让写作网络文件的人感到困扰,如果你要打「AT\&T」 ,你必须要写成「`AT&T`」 ,还得转换网址内的 `&` 符号,如果你要链接到 `http://images.google.com/images?num=30&q=larry+bird` 你必须要把网址转成: ```html http://images.google.com/images?num=30&q=larry+bird ``` 才能放到链接标签的 `href` 属性里。不用说也知道这很容易忘记,这也可能是 HTML 标准检查所检查到的错误中,数量最多的。 Markdown 允许你直接使用这些符号,但是你要小心跳脱字元的使用,如果你是在 HTML 实体中使用 `&` 符号的话,它不会被转换,而在其它情形下,它则会被转换成 `&`。所以你如果要在文件中插入一个著作权的符号,你可以这样写: ```md © ``` Markdown 将不会对这段文字做修改,但是如果你这样写: ```md AT&T ``` Markdown 就会将它转为: ```html AT&T ``` 类似的状况也会发生在 `<` 符号上,因为 Markdown 支持 [行内 HTML](#行内-html) ,如果你是使用 `<` 符号作为 HTML 标签使用,那 Markdown 也不会对它做任何转换,但是如果你是写: ```md 4 < 5 ``` Markdown 将会把它转换为: ```html 4 < 5 ``` 不过需要注意的是,code 范围内,不论是行内还是块, `<` 和 `&` 两个符号都*一定*会被转换成 HTML 实体, 这项特性让你可以很容易地用 Markdown 写 HTML code (和 HTML 相对而言, HTML 语法中, 你要把所有的 `<` 和 `&` 都转换为 HTML 实体,才能在 HTML 文件里面写出 HTML code。) [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ --- --- url: /article/30995vcd/index.md --- # 照片类作品示例 ## 单列照片 ```md :no-line-numbers ``` ## 双列照片 ```md :no-line-numbers ``` ## 三列照片 ```md :no-line-numbers ``` ## 不同尺寸设备适配 调整窗口大小以观察效果 ```md :no-line-numbers ``` --- --- url: /article/5vjshyi9/index.md --- # 1.0.0-rc.73 至 rc.77 更新说明 近期的这几个版本主要围绕 **实现单独的主题配置文件** ,监听并支持热更新。 ## Breaking Changes 以下内置插件被移除: * 移除 `@vuepress-plume/plugin-blog-data` 插件 * 移除 `@vuepress-plume/plugin-notes-data` 插件 * 移除 `@vuepress-plume/plugin-auto-frontmatter` 插件 以上插件的功能全部移动到 `vuepress-theme-plume` 主题包内部重新实现。原因是,单独的主题配置文件, 在异步加载完配置、以及配置热更新时,需要对这些插件所实现的功能进行重载,为了使流程更加清晰可控, 在主题内重新实现了这些功能,并移除了相关插件。 **但相关的配置项并没有发生变更,因此版本更新后用户无需修改配置。** ## 主要更新 ### 新增 主题配置文件 一般我们在使用 `VuePress` 构建站点时,通常会在 `.vuepress/config.js` 中引入主题并进行主题配置: ```ts :no-line-numbers import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 主题配置 }), }) ``` 主题配置 通常会包括 如 导航栏、侧边导航栏、多语言相关等的配置。 当我们启动了 VuePress 服务后,对 `.vuepress/config.js` 的修改会引起 VuePress 服务的重启, 这对于 VuePress 相关的配置而言是合理的行为。 但对于 主题相关的配置而言,大部分的配置更新是没有必要 重启 VuePress 服务的。 特别是当我们频繁的更新主题配置时,还可能引起 VuePress 服务崩溃, 这对于我们在编写站点内容时带来的体验是非常糟糕的。 因此,主题新增了一个 `plume.config.js` 的主题配置文件,将主题配置进行单独的维护。 该配置文件主要用于管理主题配置中与 构建流无关的配置。你对他的任意修改,都将以热更新的方式, 更新主题,并同步到 客户端站点实现无刷新更新,完全避免了 VuePress 服务多次重启的问题。 你可以直接在 VuePress 配置文件的相同目录下直接创建 `plume.config.js` ,主题会自动加载该文件, 也可以使用 `plume.config.ts` 文件,以获取更好的类型提示。 ::: code-tabs @tab .vuepress/config.ts ```ts :no-line-numbers import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme() }) ``` @tab .vuepress/plume.config.ts ```ts :no-line-numbers import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ // 主题配置 }) ``` ::: ### 新增 编译缓存 VuePress 在每次启动时,都需要全量编译所有的 `markdown` 文件,在站点内容比较少,且内容不复杂时, 这一过程不算特别耗时,但是当 站点的内容越来越多,内容越来越复杂时,启动等待的时间就会变得越来越久。 以本主题的文档站点为例,虽然主题文档的内容并不算特别多,但是由于使用了 `shiki` 语法高亮,并支持了 `twoslash` 功能,由于 `twoslash` 需要对代码块进行类型编译,非常耗时,这导致 主题文档站点的启动时间 达到了夸张的 `15s` 以上! 为了缓解这一问题,主题对 `markdown` 文件的编译做了一层缓存,在首次启用 `VuePress` 服务时,主题会 对所有的 `markdown` 文件的编译结果进行缓存,在二次启动时,直接从缓存中读取 `markdown` 文件的编译结果。 且仅在 `markdown` 文件有发生变更时,才会重新编译。 **通过编译缓存,主题文档站点的启动耗时,从 `15s` 降低到了 `1.2s` 左右 !** 另一方面, markdown 编译过程中耗时较为严重的是对 **代码块** 的编译,特别是 代码块使用了 `twoslash` 时。 主题原来的 `15s` 耗时主要就是由于 `twoslash` 的编译时间过长导致的。 主题同样对 代码块 进行了特殊的缓存处理,只有当 代码块 发生变化时,才会重新编译当前的代码块。 ### 新增 autoFrontmatter 配置 在过去的版本,主题会自动为每个 `markdown` 文件添加了 `frontmatter` 配置,用户无法更改这个行为, 但部分用户可能不喜欢这一行为、或者只想给 部分 markdown 文件添加 `frontmatter` 配置、或者 只生成 部分的 `frontmatter` 配置。 为此,主题添加 `autoFrontmatter` 配置,用于控制是否自动为每个 `markdown` 文件添加 `frontmatter` 配置。 包括可以通过 `glob` 模式匹配过滤 `markdown` 文件,控制自动生成哪些 字段。 ```ts :no-line-numbers interface AutoFrontmatterOptions { /** * glob 匹配,被匹配的文件将会自动生成 frontmatter * * @default ['**\/*.md'] */ include?: string | string[] /** * glob 匹配,被匹配的文件将不会自动生成 frontmatter */ exclude?: string | string[] /** * 是否自动生成 permalink * * @default true */ permalink?: boolean /** * 是否自动生成 createTime * * 默认读取 文件创建时间,`createTitme` 比 vuepress 默认的 `date` 时间更精准到秒 */ createTime?: boolean /** * 是否自动生成 title * * 默认读取文件名作为标题 */ title?: boolean } ``` --- --- url: /article/6pa64b1n/index.md --- # 1.0.0-rc.102 至 rc.103 更新说明 这两个版本做了一些 破坏性的更新,主要围绕以下两个方面: * 适配 [Vuepress Guidelines](https://ecosystem.vuejs.press/zh/themes/guidelines.html) * 更新 vuepress-plugin-md-enhance 插件,并迁移其中的部分功能,改用 VuePress 官方插件 ## 适配 VuePress Guidelines VuePress 推出了 [主题开发指南](https://ecosystem.vuejs.press/zh/themes/guidelines.html)。 这一举措旨在规范化主题开发流程,并提出了主题开发过程中需要遵守的几个约定,这包括: * 约定 CSS 变量命名规范,并约束 主要 CSS 变量的命名,如 `--vp-c-accent`,`--vp-c-text` 等。 * 约定 主要的 HTML 元素容器应添加指定的 属性名,如 `vp-content`, `vp-navbar` 等。 * 约定 双主题模式应使用 `[data-theme="light"]` 和 `[data-theme="dark"]` 来区分。 围绕这几个约定,可以使得 VuePress 的 开发者们,可以很方便的 开发出 更具通用性的 主题和插件。 `plume` 主题也同样适配了这些约定: * **CSS 变量命名的变更** 和 **HTML 元素添加属性**,对于用户是无感知的,您无需关注这方面是否会有影响。 * **双主题模式**,对于有自定义主题需求的用户而言,如果您有重新定义深色模式下的样式,则需要做出一些调整: 在 CSS 中的 `.dark` 类应替换为 `[data-theme="dark"]`,请不用担心替换会带来额外的副作用,它们在 CSS 中的 优先级是相同的,您可以安全的执行替换操作。 ## vuepress-plugin-md-enhance 插件迁移 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 提供了非常多的功能支持,但与之带来的困难是, 它变得越来越臃肿,变得难以维护了。 我在 [#4130](https://github.com/vuepress-theme-hope/vuepress-theme-hope/issues/4130) 中提出了拆分迁移的计划。 因此从 `@2.0.0-rc.53` 版本开始,逐步开始拆分迁移的计划。 截止到 `@2.0.0-rc.54` 版本,已经拆分出了以下插件: * [@vuepress/plugin-markdown-hint](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-hint.html) * [@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-image.html) * [@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-math.html) * [@vuepress/plugin-markdown-tab](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-tab.html) 当前主题也将 vuepress-plugin-md-enhance 更新到 `@2.0.0-rc.54` 版本,因此,也重新接入了上述的插件。 * `@vuepress/plugin-markdown-hint` 提供了 提示容器 和 `github alerts` 支持,主题已内置了该插件,对于该插件的迁移, 用户是无需做任何修改的,您可以继续使用这些功能。 * `@vuepress/plugin-markdown-image` 提供了图片支持,主题已内置了该插件,但不启用该插件的默认功能, 因此,如果您使用了如 `plugins.mdEnhance.imgSize` 配置项,您需要通过`plugins.markdownImage` 重新进行配置。 * `@vuepress/plugin-markdown-math` 提供了数学公式支持,主题已内置了该插件,并默认启用了 `katex` 支持。 * `@vuepress/plugin-markdown-tab` 提供了 Tab 容器 和 代码分组支持,主题重写了插件部分内容,对 `code-tabs` 容器 做了一些调整,支持在 代码分组标题中显示 相关联的图标。 ## 其它更新 * **文件树** 现在支持 不同的图标方案,可在 `:::file-tree` 后跟随 `:simple-icon` / `:colored-icon` 切换。 默认为 colored-icon,如果切换为 simple-icon,则不再根据 文件夹名和文件扩展名匹配不同的图标,仅显示默认的 文件夹图标和文件图标。 * **代码块分组** 的标题现在支持显示 图标。当作为 文件名时,与 **文件树** 采用相同的图标解析规则,还额外支持 不同的技术、框架、语言的名称图标。 * 优化了 容器、任务列表、脚注、等的样式。 --- --- url: /article/97s6ha1e/index.md --- # 全屏水印 ## 概述 不过最需要强调的便是它的可读性。一份使用 Markdown 格式撰写的文件应该可以直接以纯文字发佈,并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响, 包括 [Setext][1]、[atx][2]、[Textile][3]、[reStructuredText][4]、[Grutatext][5] 和 [EtText][6],然而最大灵感来源其实是纯文字的电子邮件格式。 因此 Markdown 的语法全由标点符号所组成,并经过严谨慎选,是为了让它们看起来就像所要表达的意思。像是在文字两旁加上星号,看起来就像\*强调\*。Markdown 的列表看起来,嗯,就是列表。假如你有使用过电子邮件,引言写法看起来就真的像是引用一段文字。 Markdown 具有一系列衍生版本,用于扩展 Markdown 的功能 (如表格、脚注、内嵌 HTML 等等) , 这些功能原初的 Markdown 尚不具备,它们能让 Markdown 转换成更多的格式,例如 LaTeX,Docbook。 Markdown 增强版中比较有名的有 Markdown Extra、MultiMarkdown、 Maruku 等。这些衍生版本要么基于工具,如 Pandoc;要么基于网站,如 GitHub 和 Wikipedia,在语法上基本兼容,但在一些语法和渲染效果上有改动。 ## 用途 Markdown 的语法有个主要的目的: 用来作为一种网络内容的*写作*用语言。Markdown 的重点在于,它能让文件更容易阅读、编写。因此,Markdown 的格式语法只涵盖纯文字可以涵盖的范围。 Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多人用它写博客。世界上最流行的博客平台 WordPress 能很好的支持 Markdown。 用于编写说明文档,并且以 `README.md` 的文件名保存在软件的目录下面。 除此之外,我们还可以快速将 Markdown 转化为演讲 PPT、Word 产品文档、LaTex 论文甚至是用非常少量的代码完成最小可用原型。在数据科学领域,Markdown 已经广泛使用,极大地推进了动态可重复性研究的历史进程。 ### 行内 HTML 不在 Markdown 涵盖范围之外的标签,都可以直接在文件里面用 HTML 撰写。不需要额外标注这是 HTML 或是 Markdown;只要直接加标签就可以了。 只有块元素 ── 比如 `
`、``、`
`、`

` 等标签,必须在前后加上空行,以利与内容区隔。 而且这些 (元素) 的开始与结尾标签,不可以用 tab 或是空白来缩进。Markdown 的解析器有智慧型判断,可以避免在块标签前后加上没有必要的 `

` 标签。 举例来说,在 Markdown 文件里加上一段 HTML 表格: ```md This is a regular paragraph.

Foo
This is another regular paragraph. ``` 请注意,Markdown 语法在 HTML 块标签中将不会被进行处理。例如,你无法在 HTML 块内使用 Markdown 形式的 `*强调*`。 ### 特殊字元自动转换 在 HTML 文件中,有两个字元需要特殊处理: `<` 和 `&` 。 `<` 符号用于起始标签,`&` 符号则用于标记 HTML 实体,如果你只是想要使用这些符号,你必须要使用实体的形式,像是 `<` 和 `&`。 `&` 符号其实很容易让写作网络文件的人感到困扰,如果你要打「AT\&T」 ,你必须要写成「`AT&T`」 ,还得转换网址内的 `&` 符号,如果你要链接到 `http://images.google.com/images?num=30&q=larry+bird` 你必须要把网址转成: ```html http://images.google.com/images?num=30&q=larry+bird ``` 才能放到链接标签的 `href` 属性里。不用说也知道这很容易忘记,这也可能是 HTML 标准检查所检查到的错误中,数量最多的。 Markdown 允许你直接使用这些符号,但是你要小心跳脱字元的使用,如果你是在 HTML 实体中使用 `&` 符号的话,它不会被转换,而在其它情形下,它则会被转换成 `&`。所以你如果要在文件中插入一个著作权的符号,你可以这样写: ```md © ``` Markdown 将不会对这段文字做修改,但是如果你这样写: ```md AT&T ``` Markdown 就会将它转为: ```html AT&T ``` 类似的状况也会发生在 `<` 符号上,因为 Markdown 支持 [行内 HTML](#行内-html) ,如果你是使用 `<` 符号作为 HTML 标签使用,那 Markdown 也不会对它做任何转换,但是如果你是写: ```md 4 < 5 ``` Markdown 将会把它转换为: ```html 4 < 5 ``` 不过需要注意的是,code 范围内,不论是行内还是块, `<` 和 `&` 两个符号都*一定*会被转换成 HTML 实体, 这项特性让你可以很容易地用 Markdown 写 HTML code (和 HTML 相对而言, HTML 语法中, 你要把所有的 `<` 和 `&` 都转换为 HTML 实体,才能在 HTML 文件里面写出 HTML code。) [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ --- --- url: /article/ecxnxxd0/index.md --- ::: info 说明 本文 翻译 [Introduction to YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) 的部分内容。 用于简单说明如何在 markdown 文件中使用 frontmatter。 如果您具有良好的英语阅读基础,为避免翻译可能存在的内容失真,建议您阅读原文。 原文地址: 。 ::: ## 介绍 YAML 是一种数据序列化语言,通常用于配置文件,例如 [Open API 规范](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/api-with-examples.yaml) 或 [CI/CD 管道](https://docs.gitlab.com/ee/ci/yaml/)。 ::: note 有趣的事实!🤓 根据 [YAML 1.0 规范文档 (2001-05-26)](https://yaml.org/spec/history/2001-05-26.html) 首字母缩略词 “YAML” 代表 “Yet Another Markup Language”, 但后来在 [2002-04-07 规范](https://yaml.org/spec/history/2002-04-07.html) 中更改为递归首字母缩略词“YAML Ain't Markup Language”。 ::: 正如最新规范中所述,**YAML** 旨在 **对处理数据的人友好**,并通过 **最大限度地减少结构字符的使用来实现“独特的干净度”**, 允许数据以自然和有意义的方式显示。 最新规范还指出,YAML *1.2 作为官方子集符合 JSON* ,这意味着大多数 JSON 文档都可以解析为 YAML。 YAML 通过使用基于缩进的范围界定(类似于 Python)轻松检查数据结构。 ::: note 另一个有趣的事实!🤓 DEV.to 文章使用 YAML 来定义自定义变量,如标题、描述、标签等。 ::: ## 基本语法 YAML 文档基本上是 **键值对的集合**,其中值可以像字符串一样简单,也可以像树一样复杂。 以下是有关 YAML 语法的一些说明: * **缩进用于表示结构**。不允许使用制表符,只要子节点的缩进量比父节点大,空格的数量就无关紧要。 * 允许使用 UTF-8、UTF-16 和 UTF-32 编码。 ### 字符串 ```md --- # 字符串不需要引号: title: Introduction to YAML # 但你仍可使用它们: title-w-quotes: 'Introduction to YAML' # 多行字符串以 | 开头 execute: | npm ci npm build npm test --- ``` 上面的代码将转换为 JSON 为: ```json { "title": "Introduction to YAML", "title-w-quotes": "Introduction to YAML", "execute": "npm ci\nnpm build\nnpm test\n" } ``` ### 数字 ```md --- # 整数: age: 29 # 浮点数: price: 15.99 # 科学计数法: population: 2.89e+6 --- ``` 上面的代码将转换为 JSON 为: ```json { "age": 29, "price": 15.99, "population": 2890000 } ``` ### 布尔值 ```md --- # 布尔值可以有不同的表示方式: published: false published: False published: FALSE --- ``` 以上所有内容都将转换为 JSON,如下所示: ```json { "published": false } ``` ### Null 值 ```md --- # Null 值可以通过不设置值来表示: null-value: # 或者更明确地说: null-value: null null-value: NULL null-value: Null --- ``` 以上所有内容都将转换为 JSON,如下所示: ```json { "null-value": null } ``` ### 日期和时间戳 可以使用 ISO 格式的日期,如下所示: ```md --- date: 2002-12-14 canonical: 2001-12-15T02:59:43.1Z iso8601: 2001-12-14t21:59:43.10-05:00 spaced: 2001-12-14 21:59:43.10 -5 --- ``` ### Sequences 序列 序列允许我们在 YAML 中定义列表: ```md --- # 使用连字符的数字列表: numbers: - one - two - three # 内联版本: numbers: [ one, two, three ] --- ``` 上述两个序列都将解析为 JSON,如下所示: ```json { "numbers": [ "one", "two", "three" ] } ``` ### 嵌套值 我们可以使用上述所有类型来创建具有嵌套值的对象,如下所示: ```md --- # 一九八四小说数据。 nineteen-eighty-four: author: George Orwell published-at: 1949-06-08 page-count: 328 description: | A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell. It was published in June 1949 by Secker & Warburg as Orwell's ninth and final book. --- ``` 这将转换为 JSON : ```json { "nineteen-eighty-four": { "author": "George Orwell", "published-at": "1949-06-08T00:00:00.000Z", "page-count": 328, "description": "A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell.\nIt was published in June 1949 by Secker & Warburg as Orwell's ninth and final book.\n" } } ``` ### 对象列表 将序列和嵌套值组合在一起,我们可以创建一个对象列表。 ```md --- # Let's list books: - nineteen-eighty-four: author: George Orwell published-at: 1949-06-08 page-count: 328 description: | A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell. - the-hobbit: author: J. R. R. Tolkien published-at: 1937-09-21 page-count: 310 description: | The Hobbit, or There and Back Again is a children's fantasy novel by English author J. R. R. Tolkien. --- ``` ## 独特特性 以下是一些引起我注意的 **更复杂的功能** ,它们也使 YAML 与 JSON 区分开来。 ### 注释 你可能已经在我前面的示例中注意到,YAML 允许以 `#` 开头的注释。 ```md --- # 这是一个非常有用的注释。 --- ``` ### 锚点的可重用性 节点锚点用于 **标记一个节点** 以供将来引用,从而允许我们重复使用该节点。 要标记一个节点,我们使用 `&` 字符,要引用它,我们使用 `*` : 在下面的示例中,我们将定义一个书籍列表并重用作者数据,因此我们只需要定义一次: ```md --- # 作者数据: author: &gOrwell name: George last-name: Orwell # 一些书籍: books: - 1984: author: *gOrwell - animal-farm: author: *gOrwell --- ``` 解析为 JSON 后,上面的代码将如下所示: ```json { "author": { "name": "George", "last-name": "Orwell" }, "books": [ { "1984": { "author": { "name": "George", "last-name": "Orwell" } } }, { "animal-farm": { "author": { "name": "George", "last-name": "Orwell" } } } ] } ``` ### 带有标签的显式数据类型 正如我们在之前的示例中所见,YAML 会自动检测我们值的类型,但我们也可以 **指定所需的类型** 。 我们通过在值前加上 `!!` 类型来指定它。 以下是一些示例: ```md --- # 以下值应为整数,无论何种情况: should-be-int: !!int 3.2 # 解析任何值为字符串: should-be-string: !!str 30.25 # 我需要下一个值为布尔类型: should-be-boolean: !!bool yes --- ``` 这将转换为 JSON: ```json { "should-be-int": 3, "should-be-string": "30.25", "should-be-boolean": true } ``` --- --- url: /article/enx7c9s/index.md --- # 加密文章,密码:123456 这是一篇 示例文章。 无内容。 --- --- url: /article/f1khd14n/index.md --- # 1.0.0-rc.144 更新说明 ::: warning 当前版本包含了破坏性的更新。 ::: ## Breaking Changes ### 移除 `node18` 支持 主题从 `1.0.0-rc.144` 开始,不再支持 `node18` 。最低支持的 node 版本为 `20.6.0` 。 ### 图标语法 在 主题 `1.0.0-rc.144` 版本之前,图标语法如下: ```md :[collect:name]: :[collect:name size/color]: ``` 该语法支持所有的 `iconify` 图标,然而该语法存在一些问题: * 书写体验不友好,标记语法中的字符 `:[` 和 `]:` 从键盘布局和输入顺序上,不适合快速输入 * `size/color` 不严谨,很容易解析错误 如果使用 `rgb(34 12 64 / 60%)`、 `hsl(30 100% 50% / 60%)`、`hwb(90 10% 10% / 0.5)` 等颜色值,由于包含了 `/` 会错误的将 `/` 之前的部分解析为 `size`,从而导致解析错误。 * 仅能支持 `iconify` 来源的图标,无法支持 `iconfont` / `fontawesome` / `lucide` 等图标库的图标 **由于上述原因,主题决定弃用该语法,修改为下述语法:** ```md ::collect:name:: ::collect:name =size /color:: ``` * 标记符号 `:[`、 `]:` 替换为 `::`,这是的可以连续敲击同一个按键以实现快速输入 * `=size` 代表图标的大小,`/color` 代表图标的颜色,使用明确的前置符号来区分 `size` 和 `color` :::info 更多图表来源支持 当前版本依然仅支持 `iconify` 图标,主题计划在后续版本中支持 `iconfont` / `fontawesome` / `lucide` 等图标库, 更用户更灵活的选择。 ::: ::: warning 为了方便从旧语法迁移到新语法,在当前版本中,旧的语法依然能够正确渲染图标, 主题会在控制台输出警告信息和修改建议,请根据修改建议进行调整。 ::: ### 重写 `file-tree` 容器 在新的版本中,主题重写了 `file-tree` 容器的 markdown-it 插件, 使用全局的解析方法解析文件树内容,并改进了文件树的显示效果和交互行为。 此破坏性更新为主题内部调整,语法保持不变,用户无需对内容进行调整。 ## 新功能 ### 版权信息配置调整 在 `themeConfig` 的 `copyright` 配置中,新增 `author` 和 `creation` 配置项。 * `author` 全局配置文章的默认的版权所有者。 * `creation` 全局配置文章的默认的创作方式。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ copyright: { author: 'pengzhanbo', // [!code ++:2] creation: 'original', license: 'MIT' } }) }) ``` --- --- url: /article/i4cuuonn/index.md --- # 图片水印 ## 概述 不过最需要强调的便是它的可读性。一份使用 Markdown 格式撰写的文件应该可以直接以纯文字发佈,并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响, 包括 [Setext][1]、[atx][2]、[Textile][3]、[reStructuredText][4]、[Grutatext][5] 和 [EtText][6],然而最大灵感来源其实是纯文字的电子邮件格式。 因此 Markdown 的语法全由标点符号所组成,并经过严谨慎选,是为了让它们看起来就像所要表达的意思。像是在文字两旁加上星号,看起来就像\*强调\*。Markdown 的列表看起来,嗯,就是列表。假如你有使用过电子邮件,引言写法看起来就真的像是引用一段文字。 Markdown 具有一系列衍生版本,用于扩展 Markdown 的功能 (如表格、脚注、内嵌 HTML 等等) , 这些功能原初的 Markdown 尚不具备,它们能让 Markdown 转换成更多的格式,例如 LaTeX,Docbook。 Markdown 增强版中比较有名的有 Markdown Extra、MultiMarkdown、 Maruku 等。这些衍生版本要么基于工具,如 Pandoc;要么基于网站,如 GitHub 和 Wikipedia,在语法上基本兼容,但在一些语法和渲染效果上有改动。 ## 用途 Markdown 的语法有个主要的目的: 用来作为一种网络内容的*写作*用语言。Markdown 的重点在于,它能让文件更容易阅读、编写。因此,Markdown 的格式语法只涵盖纯文字可以涵盖的范围。 Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多人用它写博客。世界上最流行的博客平台 WordPress 能很好的支持 Markdown。 用于编写说明文档,并且以 `README.md` 的文件名保存在软件的目录下面。 除此之外,我们还可以快速将 Markdown 转化为演讲 PPT、Word 产品文档、LaTex 论文甚至是用非常少量的代码完成最小可用原型。在数据科学领域,Markdown 已经广泛使用,极大地推进了动态可重复性研究的历史进程。 ### 行内 HTML 不在 Markdown 涵盖范围之外的标签,都可以直接在文件里面用 HTML 撰写。不需要额外标注这是 HTML 或是 Markdown;只要直接加标签就可以了。 只有块元素 ── 比如 `
`、``、`
`、`

` 等标签,必须在前后加上空行,以利与内容区隔。 而且这些 (元素) 的开始与结尾标签,不可以用 tab 或是空白来缩进。Markdown 的解析器有智慧型判断,可以避免在块标签前后加上没有必要的 `

` 标签。 举例来说,在 Markdown 文件里加上一段 HTML 表格: ```md This is a regular paragraph.

Foo
This is another regular paragraph. ``` 请注意,Markdown 语法在 HTML 块标签中将不会被进行处理。例如,你无法在 HTML 块内使用 Markdown 形式的 `*强调*`。 ### 特殊字元自动转换 在 HTML 文件中,有两个字元需要特殊处理: `<` 和 `&` 。 `<` 符号用于起始标签,`&` 符号则用于标记 HTML 实体,如果你只是想要使用这些符号,你必须要使用实体的形式,像是 `<` 和 `&`。 `&` 符号其实很容易让写作网络文件的人感到困扰,如果你要打「AT\&T」 ,你必须要写成「`AT&T`」 ,还得转换网址内的 `&` 符号,如果你要链接到 `http://images.google.com/images?num=30&q=larry+bird` 你必须要把网址转成: ```html http://images.google.com/images?num=30&q=larry+bird ``` 才能放到链接标签的 `href` 属性里。不用说也知道这很容易忘记,这也可能是 HTML 标准检查所检查到的错误中,数量最多的。 Markdown 允许你直接使用这些符号,但是你要小心跳脱字元的使用,如果你是在 HTML 实体中使用 `&` 符号的话,它不会被转换,而在其它情形下,它则会被转换成 `&`。所以你如果要在文件中插入一个著作权的符号,你可以这样写: ```md © ``` Markdown 将不会对这段文字做修改,但是如果你这样写: ```md AT&T ``` Markdown 就会将它转为: ```html AT&T ``` 类似的状况也会发生在 `<` 符号上,因为 Markdown 支持 [行内 HTML](#行内-html) ,如果你是使用 `<` 符号作为 HTML 标签使用,那 Markdown 也不会对它做任何转换,但是如果你是写: ```md 4 < 5 ``` Markdown 将会把它转换为: ```html 4 < 5 ``` 不过需要注意的是,code 范围内,不论是行内还是块, `<` 和 `&` 两个符号都*一定*会被转换成 HTML 实体, 这项特性让你可以很容易地用 Markdown 写 HTML code (和 HTML 相对而言, HTML 语法中, 你要把所有的 `<` 和 `&` 都转换为 HTML 实体,才能在 HTML 文件里面写出 HTML code。) [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ --- --- url: /article/mcgayb5w/index.md --- ## 标题锚点 标题会自动应用锚点。 ### 自定义锚点 要为标题指定自定义锚点而不是使用自动生成的锚点,请向标题添加后缀: ```md # 使用自定义锚点 {#my-anchor} ``` 这允许将标题链接为 `#my-anchor`,而不是默认的 `#使用自定义锚点`。 ## 链接 内部和外部链接都会被特殊处理。 主题默认对每个 md 文件自动生成一个新的 链接,并保存在对应的 md 文件的 frontmatter 的 `permalink` 中。 你可以随时修改它们。你也可以通过 `theme.autoFrontmatter` 选项来禁用这个功能,这时会恢复为 VuePress 的默认行为。 ### 内部链接 有三种方式来使用内部链接: * 使用 生成的 `permalink` 作为内部链接的目标。 * 使用 md 文件的相对路径作为内部链接的目标。 * 使用 md 文件的绝对路径作为内部链接的目标, 绝对路径 `/` 表示从 `${sourceDir}` 目录开始。 ```md [Markdown](/guide/markdown/) [Markdown](./markdown基础.md) ``` 渲染为: [Markdown](/guide/markdown/) [Markdown](./markdown基础.md) #### 外部链接 外部链接带有 `target="_blank" rel="noreferrer"` : [VuePress](https://v2.vuepress.vuejs.org/) ## Github风格的表格 **输入:** ```md | Tables | Are | Cool | | ------------- | :-----------: | ----: | | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | ``` **输出:** | Tables | Are | Cool | | ------------- | :-----------: | ----: | | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | ## Emoji :tada: **输入:** ```md :tada: :100: ``` **输出:** :tada: :100: 这里可以找到 [所有支持的 emoji 列表](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)。 ## 目录表 **输入:** ```md [[TOC]] ``` **输出:** \[\[TOC]] ## 自定义容器 自定义容器可以通过它们的类型、标题和内容来定义。 ### 默认标题 **输入:** ```md ::: note This is a note box ::: ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: caution This is a dangerous warning. ::: ::: details This is a details block. ::: ``` **输出:** ::: note This is a note box ::: ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: caution This is a dangerous warning. ::: ::: details This is a details block. ::: ### 自定义标题 可以通过在容器的 "type" 之后附加文本来设置自定义标题。 **输入:** ````md ::: caution STOP 危险区域,请勿继续 ::: ::: details 点我查看代码 ```js console.log('Hello, VitePress!') ``` ::: ```` **输出:** ::: caution STOP 危险区域,请勿继续 ::: ::: details 点我查看代码 ```js console.log('Hello, VitePress!') ``` ::: ## GitHub 风格的警报 主题 同样支持以标注的方式渲染 [GitHub 风格的警报](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)。它们和[自定义容器](#自定义容器)的渲染方式相同。 **输入:** ```md > [!NOTE] > 强调用户在快速浏览文档时也不应忽略的重要信息。 > [!TIP] > 有助于用户更顺利达成目标的建议性信息。 > [!IMPORTANT] > 对用户达成目标至关重要的信息。 > [!WARNING] > 因为可能存在风险,所以需要用户立即关注的关键内容。 > [!CAUTION] > 行为可能带来的负面影响。 ``` **输出:** > \[!NOTE] > 强调用户在快速浏览文档时也不应忽略的重要信息。 > \[!TIP] > 有助于用户更顺利达成目标的建议性信息。 > \[!IMPORTANT] > 对用户达成目标至关重要的信息。 > \[!WARNING] > 因为可能存在风险,所以需要用户立即关注的关键内容。 > \[!CAUTION] > 行为可能带来的负面影响。 ## 代码块中的语法高亮 主题 使用 [Shiki](https://github.com/shikijs/shiki) 在 Markdown 代码块中使用彩色文本实现语法高亮。 Shiki 支持多种编程语言。需要做的就是将有效的语言别名附加到代码块的开头: **输入:** ```` ```js export default { name: 'MyComponent', // ... } ``` ```` ```` ```html
  • {{ todo.text }}
``` ```` **输出:** ```js export default { name: 'MyComponent', // ... } ``` ```html
  • {{ todo.text }}
``` 在 Shiki 的代码仓库中,可以找到 [合法的编程语言列表](https://shiki.style/languages)。 ## 在代码块中实现行高亮 **输入:** ```` ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` ```` **输出:** ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` 除了单行之外,还可以指定多个单行、多行,或两者均指定: * 多行:例如 `{5-8}`、`{3-10}`、`{10-17}` * 多个单行:例如 `{4,7,9}` * 多行与单行:例如 `{4,7-13,16,23-27,40}` **输入:** ```` ```js{1,4,6-8} export default { // Highlighted data () { return { msg: `Highlighted! This line isn't highlighted, but this and the next 2 are.`, motd: 'VitePress is awesome', lorem: 'ipsum' } } } ``` ```` **输出:** ```js{1,4,6-8} export default { // Highlighted data () { return { msg: `Highlighted! This line isn't highlighted, but this and the next 2 are.`, motd: 'VitePress is awesome', lorem: 'ipsum' } } } ``` 也可以使用 `// [!code highlight]` 注释实现行高亮。 **输入:** ```` ```js export default { data () { return { msg: 'Highlighted!' // [\!code highlight] } } } ``` ```` **输出:** ```js export default { data() { return { msg: 'Highlighted!' // [!code highlight] } } } ``` ## 代码块中聚焦 在某一行上添加 `// [!code focus]` 注释将聚焦它并模糊代码的其他部分。 此外,可以使用 `// [!code focus:]` 定义要聚焦的行数。 **输入:** ```` ```js export default { data () { return { msg: 'Focused!' // [\!code focus] } } } ``` ```` **输出:** ```js export default { data() { return { msg: 'Focused!' // [!code focus] } } } ``` ## 代码块中的颜色差异 在某一行添加 `// [!code --]` 或 `// [!code ++]` 注释将会为该行创建 diff,同时保留代码块的颜色。 **输入:** ```` ```js export default { data () { return { remove: 'Removed', // [\!code --] add: 'Added' // [\!code ++] } } } ``` ```` **输出:** ```js export default { data() { return { remove: 'Removed', // [!code --] add: 'Added' // [!code ++] } } } ``` ## 高亮“错误”和“警告” 在某一行添加 `// [!code warning]` 或 `// [!code error]` 注释将会为该行相应的着色。 **输入:** ```` ```js export default { data () { return { error: 'Error', // [\!code error] warning: 'Warning' // [\!code warning] } } } ``` ```` **输出:** ```js export default { data() { return { error: 'Error', // [!code error] warning: 'Warning' // [!code warning] } } } ``` ## 代码块中 词高亮 **输入:** ```` ```ts export function foo() { // [\!code word:Hello] const msg = 'Hello World' console.log(msg) // prints Hello World } ``` ```` **输出:** ```ts export function foo() { // [!code word:Hello] const msg = 'Hello World' console.log(msg) // prints Hello World } ``` 你还可以指定高亮显示的次数,例如 `[!code word:options:2]` 会高亮显示近两个 `options`。 **输入:** ```` ```ts // [\!code word:options:2] const options = { foo: 'bar' } options.foo = 'baz' console.log(options.foo) // 这个不会被高亮显示 ``` ```` **输出:** ```ts // [!code word:options:2] const options = { foo: 'bar' } options.foo = 'baz' console.log(options.foo) // 这个不会被高亮显示 ``` ## 代码组 可以像这样对多个代码块进行分组: **输入:** ````md ::: code-tabs @tab config.js ```js /** * @type {import('vuepress').UserConfig} */ const config = { // .. } export default config ``` @tab config.ts ```ts import type { UserConfig } from 'vuepress' const config: UserConfig = { // .. } export default config ``` ::: ```` **输出:** ::: code-tabs @tab config.js ```js /** * @type {import('vuepress').UserConfig} */ const config = { // .. } export default config ``` @tab config.ts ```ts import type { UserConfig } from 'vuepress' const config: UserConfig = { // .. } export default config ``` ::: 你还可以通过 `@tab:active` ## 导入代码块 **输入:** 你可以使用下面的语法,从文件中导入代码块: ```md @[code](../snippet/snippet-1.js) ``` **输出:** @[code](../../snippet/snippet-1.js) 如果你只想导入这个文件的一部分: ```md @[code{1-10}](../snippet/snippet-1.js) ``` 代码语言会根据文件扩展名进行推断,但我们建议你显式指定: ```md @[code js](../snippet/snippet-1.js) @[code js{2,4-5}](../foo.js) ``` ## 数学方程 **输入:** ``` When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | ``` **输出:** When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}, +, \frac1c, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -, \frac1c, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | *wha?* | ## 标记 使用 `== ==` 进行标记。请注意两边需要有空格。 **输入:** ```md vuepress-theme-plume 是一个 ==简洁美观== 的 主题 ``` **输出:** vuepress-theme-plume 是一个 ==简洁美观== 的 主题 ## 上下角标 * 使用 `^ ^` 进行上角标标注。 * 使用 `~ ~` 进行下角标标注。 **输入:** ```md - 19^th^ - H~2~O ``` **输出:** * 19^th^ * H~2~O ## 自定义对齐 **输入:** ```md ::: left 左对齐的内容 ::: ::: center 居中的内容 ::: ::: right 右对齐的内容 ::: ``` **输出:** ::: left 左对齐的内容 ::: ::: center 居中的内容 ::: ::: right 右对齐的内容 ::: ## 属性支持 你可以使用特殊标记为 Markdown 元素添加属性。 **为图片添加属性:** 这将为图片添加 一个 名为 `full-width` 的 class 属性,以及一个 `width` 属性,值为 `100%`。 ```md ![](/plume.png){.full-width width="100%"} ``` 同时也支持其他属性: ```md 一个包含文字的段落。 {#p .a .b align=center customize-attr="content with spaces"} ``` 这将被渲染为: ```html

一个包含文字的段落。

``` ## 任务列表 **输入:** ```md - [ ] 任务 1 - [x] 任务 2 - [ ] 任务 3 ``` **输出:** * \[ ] 任务 1 * \[x] 任务 2 * \[ ] 任务 3 ## 脚注 **输入:** ```md 人生自古谁无死,留取丹心照汗青[^脚注1]。 [^脚注1]: 出自 宋·文天祥 **《过零丁洋》** ``` **输出:** 人生自古谁无死,留取丹心照汗青\[^脚注1]。 \[^脚注1]: 出自 宋·文天祥 **《过零丁洋》** --- --- url: /article/mcz1csb4/index.md --- Markdown 是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式。 Markdown 的目标是实现「易读易写」。 ## 概述 不过最需要强调的便是它的可读性。一份使用 Markdown 格式撰写的文件应该可以直接以纯文字发佈,并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响, 包括 [Setext][1]、[atx][2]、[Textile][3]、[reStructuredText][4]、[Grutatext][5] 和 [EtText][6],然而最大灵感来源其实是纯文字的电子邮件格式。 因此 Markdown 的语法全由标点符号所组成,并经过严谨慎选,是为了让它们看起来就像所要表达的意思。像是在文字两旁加上星号,看起来就像\*强调\*。Markdown 的列表看起来,嗯,就是列表。假如你有使用过电子邮件,引言写法看起来就真的像是引用一段文字。 Markdown 具有一系列衍生版本,用于扩展 Markdown 的功能 (如表格、脚注、内嵌 HTML 等等) , 这些功能原初的 Markdown 尚不具备,它们能让 Markdown 转换成更多的格式,例如 LaTeX,Docbook。 Markdown 增强版中比较有名的有 Markdown Extra、MultiMarkdown、 Maruku 等。这些衍生版本要么基于工具,如 Pandoc;要么基于网站,如 GitHub 和 Wikipedia,在语法上基本兼容,但在一些语法和渲染效果上有改动。 ## 用途 Markdown 的语法有个主要的目的: 用来作为一种网络内容的*写作*用语言。Markdown 的重点在于,它能让文件更容易阅读、编写。因此,Markdown 的格式语法只涵盖纯文字可以涵盖的范围。 Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多人用它写博客。世界上最流行的博客平台 WordPress 能很好的支持 Markdown。 用于编写说明文档,并且以 `README.md` 的文件名保存在软件的目录下面。 除此之外,我们还可以快速将 Markdown 转化为演讲 PPT、Word 产品文档、LaTex 论文甚至是用非常少量的代码完成最小可用原型。在数据科学领域,Markdown 已经广泛使用,极大地推进了动态可重复性研究的历史进程。 ### 行内 HTML 不在 Markdown 涵盖范围之外的标签,都可以直接在文件里面用 HTML 撰写。不需要额外标注这是 HTML 或是 Markdown;只要直接加标签就可以了。 只有块元素 ── 比如 `
`、``、`
`、`

` 等标签,必须在前后加上空行,以利与内容区隔。 而且这些 (元素) 的开始与结尾标签,不可以用 tab 或是空白来缩进。Markdown 的解析器有智慧型判断,可以避免在块标签前后加上没有必要的 `

` 标签。 举例来说,在 Markdown 文件里加上一段 HTML 表格: ```md This is a regular paragraph.

Foo
This is another regular paragraph. ``` 请注意,Markdown 语法在 HTML 块标签中将不会被进行处理。例如,你无法在 HTML 块内使用 Markdown 形式的 `*强调*`。 ### 特殊字元自动转换 在 HTML 文件中,有两个字元需要特殊处理: `<` 和 `&` 。 `<` 符号用于起始标签,`&` 符号则用于标记 HTML 实体,如果你只是想要使用这些符号,你必须要使用实体的形式,像是 `<` 和 `&`。 `&` 符号其实很容易让写作网络文件的人感到困扰,如果你要打「AT\&T」 ,你必须要写成「`AT&T`」 ,还得转换网址内的 `&` 符号,如果你要链接到 `http://images.google.com/images?num=30&q=larry+bird` 你必须要把网址转成: ```html http://images.google.com/images?num=30&q=larry+bird ``` 才能放到链接标签的 `href` 属性里。不用说也知道这很容易忘记,这也可能是 HTML 标准检查所检查到的错误中,数量最多的。 Markdown 允许你直接使用这些符号,但是你要小心跳脱字元的使用,如果你是在 HTML 实体中使用 `&` 符号的话,它不会被转换,而在其它情形下,它则会被转换成 `&`。所以你如果要在文件中插入一个著作权的符号,你可以这样写: ```md © ``` Markdown 将不会对这段文字做修改,但是如果你这样写: ```md AT&T ``` Markdown 就会将它转为: ```html AT&T ``` 类似的状况也会发生在 `<` 符号上,因为 Markdown 支持 [行内 HTML](#行内-html) ,如果你是使用 `<` 符号作为 HTML 标签使用,那 Markdown 也不会对它做任何转换,但是如果你是写: ```md 4 < 5 ``` Markdown 将会把它转换为: ```html 4 < 5 ``` 不过需要注意的是,code 范围内,不论是行内还是块, `<` 和 `&` 两个符号都*一定*会被转换成 HTML 实体, 这项特性让你可以很容易地用 Markdown 写 HTML code (和 HTML 相对而言, HTML 语法中, 你要把所有的 `<` 和 `&` 都转换为 HTML 实体,才能在 HTML 文件里面写出 HTML code。) *** ## 块元素 ### 段落和换行 一个段落是由一个以上相连接的行句组成,而一个以上的空行则会切分出不同的段落 (空行的定义是显示上看起来像是空行,便会被视为空行。比方说,若某一行只包含空白和 tab,则该行也会被视为空行) ,一般的段落不需要用空白或断行缩进。 「一个以上相连接的行句组成」这句话其实暗示了 Markdown 允许段落内的强迫断行, 这个特性和其他大部分的 text-to-HTML 格式不一样 (包括 MovableType 的「Convert Line Breaks」选项) , 其它的格式会把每个断行都转成 `
` 标签。 如果你*真的*想要插入 `
` 标签的话,在行尾加上两个以上的空格 (` `) 或斜线 (`/`),然后按 Enter。 是的,这确实需要花比较多功夫来插入 `
` ,但是「每个换行都转换为 `
`」的方法在 Markdown 中并不适合, Markdown 中 email 式的 [块引言][bq] 和多段落的 [列表][l] 在使用换行来排版的时候,不但更好用,还更好阅读。 ### 标题 标题能显示出文章的结构。 Markdown 支持两种标题的语法,[Setext][1] 和 [atx][2] 形式。 Setext 形式是用底线的形式,利用 `=` (最高阶标题) 和 `-` (第二阶标题) ,例如: ```md # This is an H1 ## This is an H2 ``` 任何数量的 `=` 和 `-` 都可以有效果。 Atx (推荐)形式则是在行首插入 1 到 6 个 `#` ,对应到标题 1 到 6 阶,例如: * H1: `# Header 1` * H2: `## Header 2` * H3: `### Header 3` * H4: `#### Header 4` * H5: `##### Header 5` * H6: `###### Header 6` ### Blockquotes Markdown 使用 email 形式的块引言,如果你很熟悉如何在 email 信件中引言,你就知道怎么在 Markdown 文件中建立一个块引言,那会看起来像是你强迫断行,然后在每行的最前面加上 `>` : ```md > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse > id sem consectetuer libero luctus adipiscing. ``` Markdown 也允许你只在整个段落的第一行最前面加上 `>` : ```md > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse > id sem consectetuer libero luctus adipiscing. ``` 块引言可以有阶层 (例如: 引言内的引言) ,只要根据层数加上不同数量的 `>` : ```md > This is the first level of quoting. > > > This is nested blockquote. > > Back to the first level. ``` 引言的块内也可以使用其他的 Markdown 语法,包括标题、列表、代码块等: ```md > ## This is a header. > > 1. This is the first list item. > 1. This is the second list item. > > Here's some example code: > > return shell_exec("echo $input | $markdown_script"); ``` 任何标准的文字编辑器都能简单地建立 email 样式的引言,例如 BBEdit ,你可以选取文字后然后从选单中选择*增加引言阶层*。 ### 列表 Markdown 支持有序列表和无序列表。 无序列表使用减号作为列表标记(也可使用星号、加号): ```md - Red - Green - Blue ``` 也可以(不建议): ```md - Red - Green - Blue * Red * Green * Blue ``` 有序列表则使用数字接着一个英文句点: ```md 1. Bird 2. McHale 3. Parish ``` 很重要的一点是,你在列表标记上使用的数字并不会影响输出的 HTML 结果,上面的列表所产生的 HTML 标记为: ```html
  1. Bird
  2. McHale
  3. Parish
``` 如果你的列表标记写成: ```md 1. Bird 1. McHale 1. Parish ``` 你都会得到完全相同的 HTML 输出。重点在于,你可以让 Markdown 文件的列表数字和输出的结果相同,或是你懒一点都写作 `1` 你可以完全不用在意数字的正确性。 列表项目标记通常是放在最左边,但是其实也可以缩进,最多三个空白,项目标记后面则一定要接着至少一个空白或 tab。 要让列表看起来更漂亮,你可以把内容用固定的缩进整理好: ```md - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 但是如果你很懒,那也不一定需要: ```md - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 如果列表项目间用空行分开, Markdown 会把项目的内容在输出时用 `

` 标签包起来,举例来说: ```md - Bird - Magic ``` 会被转换为: ```html

  • Bird
  • Magic
``` 但是这个: ```md - Bird - Magic ``` 会被转换为: ```html
  • Bird

  • Magic

``` 列表项目可以包含多个段落,每个项目下的段落都必须缩进 4 个空白或是一个 tab : ```md 1. This is a list item with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. Donec sit amet nisl. Aliquam semper ipsum sit amet velit. 2. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 如果你每行都有缩进,看起来会看好很多,当然,再次地,如果你很懒惰,Markdown 也允许: ```md - This is a list item with two paragraphs. This is the second paragraph in the list item. You're only required to indent the first line. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Another item in the same list. ``` 如果要在列表项目内放进引言,那 `>` 就需要缩进: ```md - A list item with a blockquote: > This is a blockquote > inside a list item. ``` 当然,项目列表很可能会不小心产生,像是下面这样的写法: ```md 1986. What a great season. ``` 换句话说,也就是在行首出现*数字-句点-空白*,要避免这样的状况,你可以在句点前面加上反斜线。 ```md 1986\. What a great season. ``` ### 代码块 和代码相关的写作或是标签语言原始码通常会有已经排版好的代码块,通常这些块我们并不希望它以一般段落文件的方式去排版,而是照原来的样子显示,Markdown 会用 `
` 和 `` 标签来把代码块包起来。

要在 Markdown 中建立代码块很简单,只要简单地缩进 4 个空白或是 1 个 tab 就可以,例如,下面的输入:

```md
This is a normal paragraph:

This is a code block.
```

Markdown 会转换成:

```html

This is a normal paragraph:

  This is a code block.
``` 这里的缩进 (4 个空白或是 1 个 tab) ,都会被移除,例如: ```md Here is an example of AppleScript: tell application "Foo" beep end tell ``` 会被转换为: ```html

Here is an example of AppleScript:

tell application "Foo"
  beep
end tell
``` 一个代码块会一直持续到没有缩进的那一行 (或是文件结尾) 。 在代码块里面, `&` 、 `<` 和 `>` 会自动转成 HTML 实体,这样的方式让你非常容易使用 Markdown 插入范例用的 HTML 原始码,只需要复制粘贴,再加上缩进就可以了,剩下的 Markdown 都会帮你处理,例如: ````md ``` ``` ```` 会被转换为: ```html
  <div class="footer">
  &copy; 2004 Foo Corporation
</div>
``` 代码块中,一般的 Markdown 语法不会被转换,像是星号便只是星号,这表示你可以很容易地以 Markdown 语法撰写 Markdown 语法相关的文件。 如果你想要在代码块里输入用 Markdown 表示的代码库,你可以进行嵌套。 `````md ````md ```js const a = 1 ``` ```` ````` 会渲染为 ````md ```js const a = 1 ``` ```` ### 分隔线 你可以在一行中用三个或以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。你也可以在星号中间插入空白。下面每种写法都可以建立分隔线: ```html ---(建议) * * * *** ***** - - - --------------------------------------- ``` ## 行内元素 ### 链接 Markdown 支持两种形式的链接语法: *行内*和*参考*两种形式。 不管是哪一种,链接的文字都是用 `[方括号]` 来标记。 要建立一个行内形式的链接,只要在方块括号后面马上接着括号并插入网址链接即可,如果你还想要加上链接的 title 文字,只要在网址后面,用双引号把 title 文字包起来即可,例如: ```html This is [an example](http://example.com/ "Title") inline link. [This link](http://example.net/) has no title attribute. ``` 会产生: ```html

This is an example inline link.

This link has no title attribute.

``` 如果你是要链接到同样主机的资源,你可以使用相对路径: ```md See my [About](/about/) page for details. ``` 参考形式的链接使用另外一个方括号接在链接文字的括号后面,而在第二个方括号里面要填入用以辨识链接的标签: ```md This is [an example][id] reference-style link. ``` 接着,在文件的任意处,你可以把这个标签的链接内容定义出来: ```md [id]: http://example.com/ "Optional Title Here" ``` 链接定义的形式为: * 方括号,输入链接的标识 ID * 冒号 * 一个以上的空白或 tab * 链接的网址 * 选择性地添加 title 内容,可以用单引号、双引号或是括号包括 下面这三种链接的定义相同: ```md [foo]: http://example.com/ "Optional Title Here" [foo]: http://example.com/ "Optional Title Here" [foo]: http://example.com/ "Optional Title Here" ``` **请注意:** 有一个已知的问题是 Markdown.pl 1.0.1 会忽略单引号包起来的链接 title。 链接网址也可以用方括号包起来: ```md [id]: http://example.com/ "Optional Title Here" ``` 你也可以把 title 属性放到下一行,也可以加一些缩进,网址太长的话,这样会比较好看: ```md [id]: http://example.com/longish/path/to/resource/here "Optional Title Here" ``` 网址定义只有在产生链接的时候用到,并不会直接出现在文件之中。 链接辨识标签可以有字母、数字、空白和标点符号,但是并**不**区分大小写,因此下面两个链接是一样的: ```md [link text][a] [link text][a] ``` *预设的链接标签*功能让你可以省略指定链接标签,这种情形下,链接标签和链接文字会视为相同,要用预设链接标签只要在链接文字后面加上一个空的方括号,如果你要让 "Google" 链接到 google.com,你可以简化成: ```md [Google][] ``` 然后定义链接内容: ```md [google]: http://google.com/ ``` 由于链接文字可能包含空白,所以这种简化的标签内也可以包含多个文字: ```md Visit [Daring Fireball][] for more information. ``` 然后接着定义链接: ```md [daring fireball]: http://daringfireball.net/ ``` 链接的定义可以放在文件中的任何一个地方,我比较偏好直接放在链接出现段落的后面,你也可以把它放在文件最后面,就像是注解一样。 下面是一个参考式链接的范例: ```md I get 10 times more traffic from [Google][1] than from [Yahoo][2] or [MSN][3]. [1]: http://google.com/ "Google" [2]: http://search.yahoo.com/ "Yahoo Search" [3]: http://search.msn.com/ "MSN Search" ``` 如果改成用链接名称的方式写: ```md I get 10 times more traffic from [Google][] than from [Yahoo][] or [MSN][]. [google]: http://google.com/ "Google" [yahoo]: http://search.yahoo.com/ "Yahoo Search" [msn]: http://search.msn.com/ "MSN Search" ``` 上面两种写法都会产生下面的 HTML。 ```html

I get 10 times more traffic from Google than from Yahoo or MSN.

``` 下面是用行内形式写的同样一段内容的 Markdown 文件,提供作为比较之用: ```md I get 10 times more traffic from [Google](http://google.com/ "Google") than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or [MSN](http://search.msn.com/ "MSN Search"). ``` 参考式的链接其实重点不在于它比较好写,而是它比较好读,比较一下上面的范例,使用参考式的文章本身只有 81 个字元,但是用行内形式的链接却会增加到 176 个字元,如果是用纯 HTML 格式来写,会有 234 个字元,在 HTML 格式中,标签比文字还要多。 使用 Markdown 的参考式链接,可以让文件更像是浏览器最后产生的结果,让你可以把一些标记相关的资讯移到段落文字之外,你就可以增加链接而不让文章的阅读感觉被打断。 ### 强调 Markdown 使用星号 (`*`) 和底线 (`_`) 作为标记强调字词的符号,被 `*` 或 `_` 包围的字词会被转成用 `` 标签包围,用两个 `*` 或 `_` 包起来的话,则会被转成 ``,例如: ```md **double asterisks** (建议) **double underscores** (建议) _single asterisks_ _single underscores_ ``` 会转成: ```html single asterisks single underscores double asterisks double underscores ``` 你可以随便用你喜欢的样式,唯一的限制是,你用什么符号开启标签,就要用什么符号结束。 强调也可以直接插在文字中间: ```md un*frigging*believable ``` 但是如果你的 `*` 和 `_` 两边都有空白的话,它们就只会被当成普通的符号。 如果要在文字前后直接插入普通的星号或底线,你可以用反斜线: ```md \*this text is surrounded by literal asterisks\* ``` ### 代码 如果要标记一小段行内代码,你可以用反引号把它包起来 (`` ` ``) ,例如: ```md Use the `printf()` function. ``` 会产生: ```md

Use the printf() function.

``` 如果要在代码内插入反引号,你可以用多个反引号来开启和结束行内代码: ```md ``There is a literal backtick (`) here.`` ``` 这段语法会产生: ```html

There is a literal backtick (`) here.

``` 代码码区段的起始和结束端都可以放入一个空白,起始端后面一个,结束端前面一个,这样你就可以在区段的一开始就插入反引号: ```md A single backtick in a code span: `` ` `` A backtick-delimited string in a code span: `` `foo` `` ``` 会产生: ```html

A single backtick in a code span: `

A backtick-delimited string in a code span: `foo`

``` 在代码码区段内,`&` 和方括号都会被转成 HTML 实体,这样会比较容易插入 HTML 原始码,Markdown 会把下面这段: ```md Please don't use any `` tags. ``` 转为: ```html

Please don't use any <blink> tags.

``` 你也可以这样写: ```md `—` is the decimal-encoded equivalent of `—`. ``` 以产生: ```html

&#8212; is the decimal-encoded equivalent of &mdash;.

``` ### 图片 很明显地,要在纯文字应用中设计一个「自然」的语法来插入图片是有一定难度的。 Markdown 使用一种和链接很相似的语法来标记图片,同样也允许两种样式: *行内* 和 *参考*。 行内图片的语法看起来像是: ```md ![Alt text](/path/to/img.jpg) ![Alt text](/path/to/img.jpg "Optional title") ``` 详细叙述如下: * 一个惊叹号 `!` * 一个方括号,里面放上图片的替代文字 * 一个普通括号,里面放上图片的网址,最后还可以用引号包住并加上 选择性的 title 文字。 参考式的图片语法则长得像这样: ```md ![Alt text][id] ``` 「id」是图片参考的名称,图片参考的定义方式则和链接参考一样: ```md [id]: url/to/image "Optional title attribute" ``` 到目前为止, Markdown 还没有办法指定图片的宽高,如果你需要的话,你可以使用普通的 `` 标签。 ### 其他文本样式 * 删除:`~~delete~~` * 段落: 段落之间空一行 * 换行符: 一行结束时输入两个空格 *** ## 其它 ### 自动链接 Markdown 支持比较简短的自动链接形式来处理网址和电子邮件信箱,只要是用方括号包起来, Markdown 就会自动把它转成链接,链接的文字就和链接位置一样,例如: ```md ``` Markdown 会转为: ```html http://example.com/ ``` 自动的邮件链接也很类似,只是 Markdown 会先做一个编码转换的过程,把文字字元转成 16 进位码的 HTML 实体,这样的格式可以混淆一些不好的信箱地址收集机器人,例如: ```md ``` Markdown 会转成: ```html address@example.com ``` 在浏览器里面,这段字串会变成一个可以点击的 链接。 (这种作法虽然可以混淆不少的机器人,但并无法全部挡下来,不过这样也比什么都不做好些。无论如何,公开你的信箱终究会引来广告信件的。) ### 转义字符 Markdown 可以利用反斜线来插入一些在语法中有其它意义的符号,例如: 如果你想要用星号加在文字旁边的方式来做出强调效果 (但不用 `` 标签) ,你可以在星号的前面加上反斜线: ```md \*literal asterisks\* ``` Markdown 支持在下面这些符号前面加上反斜线来帮助插入普通的符号: * `\` 反斜线 * `` ` `` 反引号 * `*` 星号 * `_` 底线 * `{}` 大括号 * `[]` 方括号 * `()` 括号 * `#` 井字号 * `+` 加号 * `-` 减号 * `.` 英文句点 * `!` 惊叹号 ## 快捷键 | 输出后的效果 | Markdown | 快捷键 | | ------------- | ---------- | -------------- | | **Bold** | `**text**` | Ctrl/⌘ + B | | *Emphasize* | `*text*` | Ctrl/⌘ + I | | `Inline Code` | \`code\` | 选中后 `` ` `` | ## 表格 | 居中 | 右对齐 | 左对齐 | | :-----------: | -------------: | :------------- | | 居中使用`:-:` | 右对齐使用`-:` | 左对齐使用`:-` | | b | aaaaaaaaa | aaaa | | c | aaaa | a | [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ [bq]: #blockquotes [l]: #列表 --- --- url: /article/r532eavn/index.md --- # 1.0.0-rc.120 更新说明 当前版本包含了一些破坏性的更新,因此做一些说明。 ## vuepress-plugin-md-enhance 插件迁移 在 [1.0.0-rc.103](./102-103.md#vuepress-plugin-md-enhance-插件迁移) 版本中, 主题完成了一部分功能到 vuepress 官方插件的迁移工作。但依然还有部分功能尚未完成。 在当前版本更新中,主题对这项工作进行了新的推进,将 `markdownEnhance.include` 功能迁移到了 [`@vuepress/plugin-markdown-include`](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-include.html) 插件。 因此,与之关联的配置项 `plugins.markdownEnhance.include` 将被移除,并迁移到 `plugins.markdownInclude` 进行配置。 **如果你有自定义配置,请注意需要进行迁移。** ## 功能修复 ### @vuepress/plugin-git 在 `1.0.0-rc.119` 版本中,我重构了 [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) ,使插件能够获得更多的 git 信息,如 每个文件的 创建时间,最后修改时间,作者、提交历史记录等。 但与此同时也引入了新的 bug,该 bug 会导致在 私有 git 托管服务中进行构建时,在不能自动获取 贡献者头像使用 sha256 自动生成临时头像时会导致构建失败。 ( [#334](https://github.com/pengzhanbo/vuepress-theme-plume/issues/334), [#349](https://github.com/pengzhanbo/vuepress-theme-plume/issues/349) ) 另外的一个 隐性问题是,如果项目的提交记录过多,拥有数千条以上的记录时,由于读取的 git log 过多会导致内存占用过高。 可能会导致构建时间过长甚至失败。 我在 [vuepress/ecosystem#292](https://github.com/vuepress/ecosystem/pull/292) 修复了相关问题,并在 主题 `1.0.0-rc.120` 版本中进行了修复。 --- --- url: /article/xld23tu1/index.md --- # 示例文章 这是一篇 示例文章。 无内容。 --- --- url: /article/yw0dmwcm/index.md --- # 1.0.0-rc.154 更新说明 **在本次更新中,主题移除了 `vuepress-plugin-md-enhance` 插件。** 由该插件提供支持的 图表 `Chartjs` `ECharts` `mermaid` `flowchart` `plantuml` 功能,迁移到 `@vuepress/plugin-markdown-chart` 插件。 因此主题也同步完成了插件的迁移。 至此,在主题中,由 `vuepress-plugin-md-enhance` 插件提供的相关功能,已全部迁移至官方 `vuepress/ecosystem` 仓库的相关插件。因此主题将从 `1.0.0-rc.154` 开始,安全的移除 `vuepress-plugin-md-enhance` 插件。 受此影响,如果你在 `.vuepress/client.ts` 中,有使用从 `vuepress-plugin-md-enhance` 导入的功能: ```ts title=".vuepress/client.ts" import { defineMermaidConfig } from 'vuepress-plugin-md-enhance/client' defineMermaidConfig({ theme: 'dark' }) ``` 需要进行修改: ```ts title=".vuepress/client.ts" import { defineMermaidConfig } from '@vuepress/plugin-markdown-chart/client' // [!code ++] import { defineMermaidConfig } from 'vuepress-plugin-md-enhance/client' // [!code --] defineMermaidConfig({ theme: 'dark' }) ``` 如果您有在 `.vuepress/config.ts` 的主题配置中,使用 `plugins.mdEnhance` 配置,需要进行修改: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ plugins: { mdEnhance: { mermaid: true, chartjs: true, // ... } } }) }) ``` 需要进行修改: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ plugins: { mdEnhance: { // [!code --:5] mermaid: true, chartjs: true, // ... } }, markdown: { // [!code ++:5] mermaid: true, chartjs: true, // ... } }) }) ``` **如果您在使用过程中遇到问题,请在 [GitHub Issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues) 上反馈。** --- --- url: /article/z8zvx0ru/index.md --- # 示例文章9 :::go-repl ```go package main import ( "fmt" ) func main() { fmt.Println("Hello World") } ``` ::: :::go-repl ```go package main import ( "fmt" "math/rand" "time" ) func main() { for i := 0; i < 10; i++ { dur := time.Duration(rand.Intn(1000)) * time.Millisecond fmt.Printf("Sleeping for %v\n", dur) // Sleep for a random duration between 0-1000ms time.Sleep(dur) } fmt.Println("Done!") } ``` ::: ::: go-repl ```go package main import ( "fmt" "io" "log" "net" "net/http" "os" ) func main() { http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, playground") }) log.Println("Starting server...") l, err := net.Listen("tcp", "localhost:8080") if err != nil { log.Fatal(err) } go func() { log.Fatal(http.Serve(l, nil)) }() log.Println("Sending request...") res, err := http.Get("http://localhost:8080/hello") if err != nil { log.Fatal(err) } log.Println("Reading response...") if _, err := io.Copy(os.Stdout, res.Body); err != nil { log.Fatal(err) } } ``` ::: ::: kotlin-repl ```kotlin class Contact(val id: Int, var email: String) fun main(args: Array) { val contact = Contact(1, "mary@gmail.com") println(contact.id) } ``` ::: ::: kotlin-repl ```kotlin fun mul(a: Int, b: Int): Int { return a * b } fun main(args: Array) { print(mul(-2, 4)) } ``` ::: ::: rust-repl ```rust fn main() { println!("Hello, world!"); } ``` ::: ::: rust-repl ```rust fn main() { printlnl!("Hello, world!"); } ``` ::: --- --- url: /blog/dk58a4t2/index.md --- # ⚠️ 1.0.0-rc.165 破坏性更新说明:博客与笔记功能迁移至“集合” :::important ‼️ 本次更新为破坏性更新!博客与笔记功能已整体迁移至全新的“集合”架构。‼️ ::: ## 设计动机:为什么引入“集合”? [跳转至迁移指南 👇👇👇](#迁移指南){.read-more} ### 背景与问题分析 主题最初仅支持**博客**功能,将 `docs` 源目录下的所有 Markdown 文件识别为博客文章。随着版本迭代,我们新增了**笔记/知识库**功能,默认将 `notes` 目录作为笔记根目录,并将其内容从博客列表中排除。 这种分阶段实现导致了**架构上的不平衡**:博客成为“一等公民”,而笔记功能则显得边缘化。这给用户带来了以下困扰: * **路径冗余**:笔记文件必须存放在 `notes/` 目录下,增加了不必要的目录层级 * **链接复杂**:未开启 `autoFrontmatter` 时,URL 会强制包含 `/notes/` 前缀 * **概念混淆**:用户常困惑于“笔记”与“文档”的功能区别 * **配置繁琐**:需要额外调整 `notes.dir` 配置才能实现标准文档站结构 这些设计缺陷源于历史迭代的遗留问题,我们对此深表歉意。 ### 解决方案:统一的内容抽象 经过对主流静态站点生成器(如 Hugo、VitePress)和全栈框架(如 Nuxt)的调研,我们从 `@nuxt/content` 的 `collection` 概念中获得灵感。 我们决定引入**集合**作为统一的内容组织单元。无论是博客、笔记、文档还是知识库,本质上都是 Markdown 文件的特定集合,只是在呈现方式上有所差异。 :::important 核心洞察:通过“集合”抽象,统一各类内容的组织形式,同时保留各自的展示特性。 ::: 基于内容特征,我们定义了两种集合类型: * **`post` 类型**:适用于碎片化、关联性弱的内容(如博客、专栏),提供文章列表作为导航入口 * **`doc` 类型**:适用于结构化、关联性强的内容(如文档、手册),提供侧边栏进行快速导航 这一设计既解决了历史架构问题,又为未来扩展更多内容类型奠定了基础。 ## 迁移指南 ### 核心概念 * **集合**:通过 `collection.dir` 指定目录,该目录下所有 Markdown 文件均归属该集合 * **集合类型**: * `post`:碎片化内容,支持文章列表导航 * `doc`:结构化内容,支持侧边栏导航 ### 配置迁移 替换原有的 `blog` 和 `notes` 配置: ```ts twoslash // @noErrors import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // [!code --:9] // 移除旧的 blog 和 notes 配置 blog: { /* 博客配置 */ }, notes: { link: '/', dir: '/notes/', notes: [ { dir: 'typescript', link: '/typescript/', sidebar: 'auto' } ] }, // [!code ++:17] // 使用 collections 配置 collections: [ { type: 'post', // 替代原博客功能 dir: 'blog', // 指向 docs/blog 目录 title: '博客' // 集合显示名称 // 原博客配置继续保留 // ... }, { type: 'doc', // 替代原笔记功能 dir: 'typescript', // 指向 docs/typescript 目录 title: 'TypeScript笔记', linkPrefix: '/typescript/', // 页面链接前缀、侧边栏判断依据 sidebar: 'auto', // 自动生成侧边栏 }, ] }) }) ``` ### 目录结构调整 按照以下步骤迁移文件: **操作步骤:** 1. 将 `notes` 目录下的子目录直接移至 `docs` 根目录 2. 创建 `blog` 目录,将原博客文章移入其中 3. 移除空的 `notes` 目录 :::: flex ::: file-tree title="迁移前结构" * docs * \-- notes * typescript * basic.md * advanced.md * blog-cate-1 * post-1.md * blog-cate-2 * post-2.md * blog-post.md * README.md ::: :::file-tree title="迁移后结构" * docs * typescript * basic.md * advanced.md * ++ blog * blog-cate-1 * post-1.md * blog-cate-2 * post-2.md * blog-post.md * README.md ::: :::: ### 帮助函数 * `defineCollection`:用于定义单个 collection 配置的帮助函数 * `defineCollections`:用于定义多个 collection 配置的帮助函数 ```ts twoslash import { defineCollection, defineCollections } from 'vuepress-theme-plume' export const blog = defineCollection({ type: 'post', dir: 'blog', title: '博客' }) export const typescript = defineCollection({ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }) export const collections = defineCollections([ blog, typescript ]) ``` ## 详细文档 [集合文档](../../guide/quick-start/collection.md){.read-more} [post 集合](../../guide/quick-start/collection-post.md){.read-more} [doc 集合](../../guide/quick-start/collection-doc.md){.read-more} --- --- url: /changelog/index.md --- # Changelog --- --- url: /config/collections/index.md --- # 集合配置 ## 概述 **Collections(集合)** 是主题中用于组织和管理文档的核心概念。每个集合指向源目录下的特定文件夹,将其中的所有 Markdown 文件作为一个逻辑单元进行管理。 通过灵活的集合配置,您可以轻松构建多种内容体系: * **博客** - 个人随笔与技术分享 * **专栏** - 专题系列文章 * **使用手册** - 产品使用文档 * **笔记** - 学习笔记与知识整理 * **产品文档** - 完整的项目文档 * **知识库** - 团队知识管理体系 集合主要分为两种类型,适应不同的内容组织需求: * **`post` 类型**:适用于碎片化内容,文章间关联较弱,如博客、专栏等 * **`doc` 类型**:适用于结构化文档,内容关联紧密,如使用手册、产品文档、知识库等 ::: tip 配置位置 集合配置支持在 `.vuepress/config.ts` 或独立的 `plume.config.ts` 文件中进行配置。 ::: ## 基础配置 假设您的项目采用以下目录结构: ::: file-tree title="项目结构" * docs * **blog** * post-1.md * post-2.md * **typescript** * basic * intro.md * variable.md * types.md ::: 对应的集合配置示例如下: ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 集合配置 // [!code focus:7] collections: [ // 注册 post 类型集合,实现博客功能 { type: 'post', dir: 'blog', title: '博客' }, // 注册 doc 类型集合,实现 TypeScript 文档功能 { type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' } ], }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ // 独立配置文件中的集合配置 // [!code focus:7] collections: [ { type: 'post', dir: 'blog', title: '博客' }, { type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' } ], }) ``` ::: ## 多语言配置 对于多语言项目,您可以在 `locales` 字段中为每种语言单独配置集合: ::: file-tree title="多语言项目结构" * docs * **blog/** * post-1.md * post-2.md * **typescript/** * basic * intro.md * variable.md * types.md * en * **blog/** * post-1.md * post-2.md * **typescript/** * basic * intro.md * variable.md * types.md ::: ::: code-tabs#configs @tab .vuepress/config.ts ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ locales: { '/': { // 中文集合配置 // [!code focus:4] collections: [ { type: 'post', dir: 'blog', title: '博客' }, { type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' } ], }, '/en/': { // 英文集合配置 // [!code focus:4] collections: [ { type: 'post', dir: 'blog', title: 'Blog' }, { type: 'doc', dir: 'typescript', title: 'TypeScript Note', sidebar: 'auto' } ], } } }) }) ``` @tab .vuepress/plume.config.ts ```ts import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ locales: { '/': { // 中文集合配置 // [!code focus:4] collections: [ { type: 'post', dir: 'blog', title: '博客' }, { type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' } ], }, '/en/': { // 英文集合配置 // [!code focus:4] collections: [ { type: 'post', dir: 'blog', title: 'Blog' }, { type: 'doc', dir: 'typescript', title: 'TypeScript Note', sidebar: 'auto' } ], } } }) ``` ::: ## Post 集合详解 Post 集合专为博客、专栏等碎片化内容设计,提供完整的文章管理体系: ### 核心功能 * **文章列表页** - 支持文章置顶、封面图、摘要显示、个人信息等 * **文章分类页** - 基于目录结构自动生成分类 * **文章标签页** - 灵活的标签管理 * **文章归档页** - 按时间维度组织内容 ### 配置示例 ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ collections: [ // 博客集合配置 { type: 'post', dir: 'blog', title: '博客', link: '/blog/', // 列表页链接 linkPrefix: '/article/', // 文章链接前缀 postCover: 'top', // 封面图位置 autoFrontmatter: { permalink: true }, // 自动 frontmatter }, // 面试专栏配置 { type: 'post', dir: 'interview', title: '面试专栏', link: '/interview/', // 列表页链接 } ] }) ``` ## Doc 集合详解 Doc 集合适用于结构化文档,强调内容间的逻辑关系: ### 核心功能 * **侧边导航栏** - 提供清晰的文档结构导航 * **自动生成目录** - 基于文件结构智能生成侧边栏 * **多级嵌套支持** - 支持复杂的文档层次结构 ### 配置示例 ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ collections: [ // TypeScript 笔记 - 自动生成侧边栏 { type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }, // Python 笔记 - 手动配置侧边栏 { type: 'doc', dir: 'python', title: 'Python 笔记', sidebar: [ { text: '基础语法', link: 'basic' }, { text: 'API 文档', items: [ { text: 'asyncio', link: 'asyncio' } ] }, 'advanced' // 简写形式 ] } ] }) ``` ## 配置类型声明 ### 基础集合配置 ```ts /* 集合配置数组 */ type ThemeCollections = ThemeCollectionItem[] /* 单个集合项 */ type ThemeCollectionItem = ThemePostCollection | ThemeDocCollection /* 集合公共配置 */ interface ThemeBaseCollection { /** * 集合类型 * - `post`: 文章列表(博客、专栏) * - `doc`: 结构化文档(笔记、知识库) */ type: 'post' | 'doc' /** * 文档目录(相对于源目录) */ dir: string /** * 文章链接前缀 */ linkPrefix?: string /** * 集合标题(用于面包屑导航) */ title: string /** * 标签颜色主题 * @default 'colored' */ tagsTheme?: 'colored' | 'gray' | 'brand' /** * 自动生成 frontmatter */ autoFrontmatter?: AutoFrontmatterOptions | false } ``` ### Post 集合专用配置 ```ts title="Post 集合配置" interface ThemePostCollection extends ThemeBaseCollection { type: 'post' /** * 包含文件规则(glob 模式) * @default ['**\/*.md'] */ include?: string[] /** * 排除文件规则(glob 模式) * @default [] */ exclude?: string[] /** * 分页配置 */ pagination?: false | number | { /** * 每页文章数量 * @default 15 */ perPage?: number } /** * 文章列表页链接 * @default '/{dir}/' */ link?: string /** * 是否启用文章列表页 * @default true */ postList?: boolean /** * 是否启用标签页 * @default true */ tags?: boolean /** * 标签页链接 * @default '/{link}/tags/' */ tagsLink?: string /** * 标签页文本 */ tagsText?: string /** * 是否启用归档页 * @default true */ archives?: boolean /** * 归档页链接 * @default '/{link}/archives/' */ archivesLink?: string /** * 归档页文本 */ archivesText?: string /** * 是否启用分类功能 * @default true */ categories?: boolean /** * 分类页链接 * @default '/{link}/categories/' */ categoriesLink?: string /** * 分类页文本 */ categoriesText?: string /** * 分类展开深度 * @default 'deep' */ categoriesExpand?: number | 'deep' /** * 分类列表转换函数 */ categoriesTransform?: (categories: PostsCategoryItem[]) => PostsCategoryItem[] /** * 文章封面图配置 * @default 'right' */ postCover?: PostsCoverLayout | PostsCoverStyle /** * 个人信息配置 */ profile?: ProfileOptions | false /** * 社交账号配置 */ social?: SocialLink[] | false } /* 文章分类项 */ interface PostsCategoryItem { id: string sort: number name: string } /* 封面图布局 */ type PostsCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top' /* 封面图样式 */ interface PostsCoverStyle { layout?: PostsCoverLayout ratio?: number | `${number}:${number}` | `${number}/${number}` width?: number compact?: boolean } /* 社交链接图标 */ type SocialLinkIcon = SocialLinkIconUnion | { svg: string, name?: string } /* 社交链接 */ interface SocialLink { icon: SocialLinkIcon link: string ariaLabel?: string } /** * 个人资料 */ export interface ProfileOptions { /** * 头像链接地址 */ avatar?: string /** * 名称 */ name?: string /** * 描述 / 简介 / 座右铭 / 签名 */ description?: string /** * 是否显示为圆形头像 */ circle?: boolean /** * 地理位置 */ location?: string /** * 组织,公司 */ organization?: string /** * 布局位置,左侧或者右侧 * @default 'right' */ layout?: 'left' | 'right' } ``` ### Doc 集合专用配置 ```ts title="Doc 集合配置" interface ThemeDocCollection extends ThemeBaseCollection { type: 'doc' /** * 侧边栏配置 */ sidebar?: 'auto' | (string | ThemeSidebarItem)[] /** * 是否显示侧边栏滚动条 * @default true */ sidebarScrollbar?: boolean /** * 侧边栏默认折叠状态 * @default false */ sidebarCollapsed?: boolean } /* 侧边栏项配置 */ interface ThemeSidebarItem { text?: string link?: string icon?: ThemeIcon badge?: string | ThemeBadge items?: 'auto' | (string | ThemeSidebarItem)[] collapsed?: boolean prefix?: string rel?: string target?: string } /* 图标类型 */ type ThemeIcon = string | { svg: string } /* 徽章配置 */ export interface ThemeBadge { text?: string type?: string color?: string bgColor?: string borderColor?: string } ``` ### 自动侧边栏生成 将 Doc 集合的 `sidebar` 设置为 `'auto'` 时,系统会根据目录结构自动生成侧边栏导航。排序规则遵循[文件夹命名约定](../guide/quick-start/write.md#文件夹命名约定)。 ### 侧边栏图标配置 主题支持两种方式配置侧边栏图标: * **在侧边栏配置中直接定义**: ```ts sidebar: [ { text: '介绍', link: 'intro', icon: 'mdi:tooltip-text-outline' } ] ``` * **在文档 frontmatter 中定义**: ```md --- title: 主题介绍 icon: mdi:tooltip-text-outline --- ``` 两种方式具有相同的效果,您可以根据具体场景选择使用。 如需了解侧边栏的完整配置选项和使用技巧,请参阅[侧边栏配置指南](../guide/quick-start/sidebar.md)。 --- --- url: /config/frontmatter/article/index.md --- # posts文章 ## 概述 适用于 集合类型为 post 的文章。 示例: ```md --- title: 文章标题 tags: - tag1 - tag2 --- ``` ## 配置 ### sticky * 类型: `boolean | number` * 默认值: `false` 是否在文章列表中,置顶当前文章。 如果为 `number` ,则数字越大,文章置顶的位置越靠前。 ### article * 类型: `boolean` * 默认值: `true` 是否在文章列表中显示当前文章。 ### draft * 类型: `boolean` * 默认值: `false` 标记文章是否为草稿。被标记为草稿的文章,仅在 **开发环境时显示在文章列表中**,生产环境不会显示。 ### tags * 类型: `string[]` * 默认值: `[]` 文章标签。 ### cover * 类型: `string` * 默认值: `''` 文章封面图。 封面图仅显示在 文章列表页。 仅支持 绝对路径 以及 远程图片地址。 ### coverStyle * 类型: `BlogPostCoverStyle` * 默认值: \`null 封面图配置。 ```ts interface PostCoverStyle { /** * 博客文章封面图的位置 */ layout?: 'left' | 'right' | 'odd-left' | 'odd-right' | 'top' /** * 博客文章封面图的比例 * * @default '4:3' */ ratio?: number | `${number}:${number}` /** * 封面图的宽度, 仅在 layout 为 'left' 或 'right' 时生效 * * @default 240 */ width?: number /** * 是否使用紧凑模式,紧凑模式下,封面图紧贴容器边缘 * @default false */ compact?: boolean } ``` --- --- url: /config/frontmatter/basic/index.md --- # 通用配置 ## 概述 通用 Frontmatter 配置,适用于 所有的文章。 示例: ```md --- title: 标题 createTime: 2024/03/02 20:01:09 permalink: /config/frontmatter/basic/ --- ``` ## 配置 ### pageLayout * 类型: `false | 'home' | 'doc' | 'custom' | 'page' | 'friends' | string` * 默认值: `doc` * 详情: 页面布局方式。 * `'home'`: 主页布局 * `'doc'`: 文章页布局,包括左侧侧边栏、文章内容、右侧侧边栏、导航栏、评论等 * `'page'`: 仅包含导航栏 和 MD 文件内容,可以使用此布局方式自定义页面内容 * `'friends'`: 友链页布局 * `'custom'`: 仅包含 MD 文件内容,可以使用此布局方式完全自定义页面内容 * `false`: 等同于 `custom` * `string`: 可以传入一个全局组件组件名,该组件将被应用为布局组件 ### pageClass * 类型: `string` * 默认值: `''` * 详情: 自定义页面额外的 类名。 ### title * 类型: `string` * 默认值: `''` * 详情: 文章标题。 主题会在文件创建时,自动填充 当前文件名作为 文章标题。 ### badge * 类型: `string | { text: string, type?: 'info' | 'tip' | 'warning' | 'danger' }` 在文章标题右侧显示 徽章。 ### createTime * 类型: `string` * 默认值: `''` * 详情: 文章创建时间。 主题会在文件创建时,自动填充 当前时间作为 文章创建时间。 ### permalink * 类型: `string` * 默认值: `''` * 详情: 文章永久链接。 主题会在文件创建时: * 博客类型的文章,自动填充 `/article/` + `nanoid 生成的 8 位随机字符串` 作为 文章永久链接 * notes 目录下的文章,会根据 notes 的配置,自动填充 文章永久链接 ### externalLinkIcon * 类型: `boolean` * 默认值: `true` * 详情: 当前文章内的 外部链接是否显示 外部链接图标。 ### backToTop * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 显示 回到顶部 的按钮。 ### comments * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 可评论。 仅在启用了评论功能的情况下生效。 ### aside * 类型: `boolean | 'left'` * 默认值: `true` * 详情: 当前文章是否 显示 右侧边栏。 当设置为 `'left'` 时,右侧边栏将显示在左侧。 ### navbar * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 显示 导航栏。 ### outline * 类型: `false | number | [number, number] | 'deep'` * 默认值: `[2, 3]` * 详情: 要显示的标题级别。 单个数字表示只显示该级别的标题。 如果传递的是一个元组,第一个数字是最小级别,第二个数字是最大级别。 `'deep'` 与 `[2, 6]` 相同,将显示从 `

` 到 `

` 的所有标题。 ### prev * 类型: `string | { text: string, link: string, icon?: string }` * 默认值: `''` * 详情: 自定义当前文章的上一篇文章。 * 博客类型的文章,主题根据时间排序,自动填充上一篇文章的标题和链接。 * notes 类型的文章,主题根据 note sidebar 配置,自动填充上一篇文章的标题和链接。 ### next * 类型: `string | { text: string, link: string, icon?: string }` * 默认值: `''` * 详情: 自定义当前文章的下一篇文章。 * 博客类型的文章,主题根据时间排序,自动填充下一篇文章的标题和链接。 * notes 类型的文章,主题根据 note sidebar 配置,自动填充下一篇文章的标题和链接。 ### readingTime * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 显示 阅读时长。 ### lastUpdated * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 显示 最后更新时间。 最后更新时间 根据 git 提交时间自动填充。 ### contributors * 类型: `boolean` * 默认值: `true | string | string[]` * 详情: 当前文章是否 显示 贡献者。 贡献者 根据 git 提交者自动填充。 如果您的文章来源于第三方, git 提交不能完整列出所有的作者,您可以在此处补充贡献者。 额外信息补充请查看 [contributors](../../guide/features/contributors.md#info) ### changelog * 类型: `boolean` * 默认值: `false` * 详情: 当前页面是否显示页面变更历史。 ### copyright * 类型: `boolean | CopyrightLicense | CopyrightFrontmatter` * 默认值: `false` * 详情: 当前文章是否 显示 版权信息。 完整信息请查看 [copyright](../../guide/features/copyright.md) ### editLink * 类型: `boolean` * 默认值: `true` * 详情: 当前文章是否 显示 文章编辑 按钮。 ### watermark * 类型: `boolean | WatermarkOptions` * 默认值: `undefined` 主题不启用水印,或不启用全局水印时,默认值为 `false`,启用全局水印则为 `true`。 * 详情: 配置当前文章 水印。 当类型为 boolean 时,表示是否启用水印。 当类型为 WatermarkOptions 时,表示当前页面水印配置。 可以参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) 。 --- --- url: /config/frontmatter/friends/index.md --- # 友情链接页 ## 概述 适用于友情链接页。 示例: ```md --- pageLayout: friends title: 友情链接 list: - name: pengzhanbo link: https://github.com/pengzhanbo avatar: https://github.com/pengzhanbo.png location: 广州,中国 organization: VuePress desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。 socials: - icon: github link: https://github.com/pengzhanbo - icon: twitter link: https://twitter.com/pengzhanbo --- ``` ## 配置 ### friends * 类型: `boolean` * 默认值: `false` * 详情: 当前页面是否为友情链接页。 ### pageLayout * 类型:`'friends'` * 详情: 声明当前页面为 友情链接页。 ### title * 类型: `string` * 默认值: `友情链接` 友情链接页的标题 ### description * 类型: `string` 友情链接页的描述 ### contentPosition * 类型: `'before' | 'after'` * 默认值: `'after'` markdown 内容在友情链接列表之前还是之后,默认插入到列表之后。 ### list * 类型: `FriendsItem[]` * 默认值: `[]` 友情链接列表 ```ts interface FriendsItem { /** * 友情链接名 */ name: string /** * 友情链接 */ link: string /** * 友情链接头像 */ avatar?: string /** * 友情链接描述 */ desc?: string /** * 地理位置 */ location?: string /** * 组织、公司 */ organization?: string /** * 社交链接 */ socials?: SocialLink[] /** * 背景色 */ backgroundColor?: string | { light: string, dark: string } /** * 字体颜色 */ color?: string | { light: string, dark: string } /** * 名字颜色 */ nameColor?: string | { light: string, dark: string } } ``` 社交链接配置请查看 [配置/主题配置/社交链接](../../config/theme.md#social)。 ### groups * 类型: `FriendsGroup[]` * 默认值: `[]` 友情链接分组 ```ts interface FriendsGroup { /** * 分组名 */ title?: string /** * 分组描述 */ desc?: string /** * 友情链接列表 */ list?: FriendsItem[] } ``` --- --- url: /config/frontmatter/home/index.md --- # 首页 ## 概述 仅适用于 首页。在 `{sourceDir}/README.md` 中进行配置。 示例: ```md --- pageLayout: home config: - type: banner - type: custom --- ``` ## 配置 ### home * 类型: `boolean` * 详情: 声明是否为 首页。 已弃用,请使用 `pageLayout: 'home'` 代替。 ### pageLayout * 类型:`'home'` * 详情: 声明当前页面为 首页。 ### config * 类型: `PlumeHomeConfig[]` 定义 首页 区域 ```ts interface PlumeHomeConfigBase { /** * 该区域的类型,根据类型应用不同的组件 */ type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom' | string /** * 该区域是否占满全屏 */ full?: boolean /** * 该区域的背景图片 * 你可以定义在 浅色/暗色 模式下的背景图片 */ backgroundImage?: string | { light: string, dark: string } /** * 该区域的背景 定位方式 */ backgroundAttachment?: 'fixed' | 'local' } ``` 更多详细配置请参考 [自定义首页](../../guide/custom/home.md) ### signDown * 类型: `boolean` * 默认值: `false` * 详情: 是否显示向下前头的标志。 --- --- url: /config/intro/index.md --- # 配置说明 ## 概述 \==vuepress-theme-plume== 是基于 [VuePress](https://v2.vuepress.vuejs.org/) 开发的主题,其配置完全遵循 VuePress 的配置规范。 **VuePress 提供三种配置类型:** * **站点配置**:在配置文件(如 `.vuepress/config.ts`)中直接导出的对象 * **主题配置**:传递给 `plumeTheme()` 函数的参数对象 * **页面配置**:基于 YAML 语法在页面 Frontmatter 中定义 ## VuePress 配置文件 VuePress 的基础配置文件通常是 `.vuepress/config.js`,同时也支持 TypeScript 配置文件。使用 `.vuepress/config.ts` 可以获得更完善的类型提示。 VuePress 按以下优先顺序解析配置文件: **当前工作目录 (cwd) 下:** * `vuepress.config.ts` * `vuepress.config.js` * `vuepress.config.mjs` **源文件目录 (sourceDir) 下:** * `.vuepress/config.ts` * `.vuepress/config.js` * `.vuepress/config.mjs` **基础配置示例:** ```ts title=".vuepress/config.ts" twoslash import { viteBundler } from '@vuepress/bundler-vite' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ // [!code hl:5] // VuePress 基础配置 lang: 'zh-CN', title: '你好, VuePress !', description: '这是我的第一个 VuePress 站点', // ... // 使用 Vite 作为构建工具 bundler: viteBundler(), // 启用 Plume 主题 theme: plumeTheme({ // [!code ++:4] // 主题配置项 // ... }), }) ``` ## 主题配置文件 通常我们在 `.vuepress/config.ts` 中配置主题: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 主题配置 }), // ... }) ``` 然而,修改此文件会导致 VuePress 服务重启并全量刷新。对于小型站点,这个过程很快;但对于内容较多的站点,每次重启都需要较长时间。 频繁修改配置文件还容易导致 VuePress ==服务崩溃=={.caution} ::twemoji:angry-face::,需要手动重启服务,严重影响内容编写效率。 **解决方案:主题热更新配置**: 主题提供了 `plume.config.ts` 配置文件,==对该文件的修改支持热更新,无需重启服务=={.tip} ::twemoji:confetti-ball::。 你可以在其中配置支持热更新的字段,如 `navbar`、`profile` 等。 ::: tip 这些字段仍可在 VuePress 配置文件的 `theme` 中配置,但主题配置文件的设置最终会合并到主配置中。 为避免数据重复,请勿在两地同时配置同一字段。 ::: ::: details 什么是热更新? **热更新** 是一种开发技术,在 VuePress 中体现为: * 配置修改实时生效,无需重启服务,浏览器不刷新页面 * 页面修改实时生效,浏览器无刷新更新内容 ::: ### 配置方法 在 VuePress 配置文件同级目录下创建 `plume.config.ts` 文件: ::: file-tree * docs * .vuepress * config.ts * **plume.config.ts** ::: ```ts title="plume.config.ts" twoslash // @filename: ./navbar.ts export default [] // ---cut--- import { defineThemeConfig } from 'vuepress-theme-plume' import navbar from './navbar' export default defineThemeConfig({ // 主题配置 profile: { name: 'Your name', }, navbar, }) ``` `defineThemeConfig(config)` 函数提供完整的类型提示。除 `plugins` 外,大多数配置都可在此文件中定义。 ::: warning 注意事项 * 主题配置文件仅支持部分热更新字段 * 避免在 VuePress 配置文件中重复配置已在主题配置文件中设置的字段 ::: ### 自定义配置文件路径 如需使用非默认路径,可在 VuePress 配置中指定: ```ts title=".vuepress/config.ts" twoslash import path from 'node:path' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 自定义配置文件路径 configFile: path.join(__dirname, 'custom/config.ts'), // [!code ++] }), }) ``` ::: warning 新手不建议自定义路径,可能引发意外问题 ::: ## 页面配置 通过页面顶部的 YAML Frontmatter,可为每个页面单独配置主题: ```md {1,5} title="article.md" --- title: 文章标题 createTime: 2024/09/08 22:53:34 permalink: /article/xxx/ --- ``` 在 Markdown 文件顶部,使用 `---` 分隔符包裹的部分即为 Frontmatter,采用 YAML 语法配置。 :::tip 如需了解 YAML 基础语法,可参考[这篇博客](/article/ecxnxxd0/) ::: --- --- url: /config/locales/index.md --- # 多语言配置 这些选项用于配置与语言相关的文本。 如果你的站点是以非内置语言支持以外的其他语言提供服务的,你应该为每个语言设置这些选项来提供翻译。 ## 内置语言支持 主题内置了以下语言支持,包括: * 简体中文 (`zh-CN`) - `/zh/` * 繁体中文 (`zh-TW`) - `/zh-tw/` * 英语 (`en-US`) - `/en/` * 法语 (`fr-FR`) - `/fr/` * 德语 (`de-DE`) - `/de/` * 俄语 (`ru-RU`) - `/ru/` * 日语 (`ja-JP`) - `/ja/` * 韩语 (`ko-KR`) - `/ko/` ## 配置 您应该将配置写入到 `theme.locales` 中。 您可以在 `.vuepress/config.ts` ,或者在 `.vuepress/plume.config.ts` 中进行配置: ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ locales: { // 非内置语言的语言代码 '/xxx/': { // 语言配置 } } }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ locales: { // 非内置语言的语言代码 '/xxx/': { // 语言配置 } } }) ``` ::: 详细配置方法请参考:[国际化](../guide/quick-start/locales.md) ### appearanceText * 类型: `string` * 默认值: `'Appearance'` * 详情: 导航栏中的主题切换按钮的文本。 ### selectLanguageName * 类型: `string` * 默认值: `''` * 详情: Locale 的语言名称。 该配置项 **仅能在主题配置的 [locales](./theme.md#locales) 的内部生效** 。它将被用作 locale 的语言名称,展示在 *选择语言菜单* 内。 ### selectLanguageText * 类型: `string` * 默认值: `''` * 详情: *选择语言菜单* 的文本。 如果你在站点配置中设置了多个 [locales](./theme.md#locales) ,那么 *选择语言菜单* 就会显示在导航栏中仓库按钮的旁边。 ### selectLanguageAriaLabel * 类型: `string` * 默认值: `''` * 详情: *选择语言菜单 的 `aria-label` 属性。* 它主要是为了站点的可访问性 (a11y) 。 ### homeText * 类型: `string` * 默认值: `'Home'` * 详情: 主页链接的文本。 * 主题默认导航栏中的首页链接的文本。 * 面包屑导航中的首页链接的文本。 ### postsText * 类型: `string` * 默认值: `'Posts'` * 详情: 文章列表页链接的文本。 * 主题默认导航栏中的文章列表页链接的文本。 * 面包屑导航中的文章列表页链接的文本。 ### tagText * 类型: `string` * 默认值: `'Tags'` * 详情: 标签链接的文本。 * 主题默认导航栏中的标签链接的文本。 * 博客页中的标签链接的文本。 * 博客标签页中的标题。 ### categoryText * 类型: `string` * 默认值: `'Categories'` * 详情: 分类链接的文本。 * 主题默认导航栏中的分类链接的文本。 * 博客页中的分类链接的文本。 * 博客分类页中的标题。 ### archiveText * 类型: `string` * 默认值: `'Archives'` * 详情: 归档链接的文本。 * 主题默认导航栏中的归档链接的文本。 * 博客页中的归档链接的文本。 * 博客归档页中的标题。 ### archiveTotalText * 类型: `string` * 默认值: `'{count} articles'` * 详情: 归档页中的总文章数的文本。 ### sidebarMenuLabel * 类型: `string` * 默认值: `'Menu'` * 详情: 移动设备下的导航栏中 菜单选项的文本。 ### returnToTopLabel * 类型: `string` * 默认值: `'return to top'` * 详情: 移动设备下的导航栏中返回顶部的文本。 ### outlineLabel * 类型: `string` * 默认值: `'On this page'` * 详情: 移动设备下的导航栏中大纲标题的文本 ### editLinkText * 类型: `string` * 默认值: `'Edit this page'` * 详情: 编辑链接文本 ### latestUpdatedText * 类型: `string` * 默认值: `'Latest Updated'` * 详情: 最近更新时间 的文本 ### contributorsText * 类型: `string` * 默认值: `'Contributors'` * 详情: 贡献者的文本 ### changelogText * 类型: `string` * 默认值: `'Changelog'` * 详情: 变更记录的文本 ### changelogOnText * 类型: `string` * 默认值: `'On'` * 详情: 单次变更记录的时间文本 ### changelogButtonText * 类型: `string` * 默认值: `'View All Changelog'` * 详情: 变更记录的按钮文本 ### copyrightText * 类型: `string` * 默认值: `'Copyright'` * 详情: 版权所有的文本 ### copyrightAuthorText * 类型: `string` * 默认值: `'Copyright Ownership:'` * 详情: 版权所有者的文本 ### copyrightCreationOriginalText * 类型: `string` * 默认值: `'This article link:'` * 详情: 本文链接的文本 ### copyrightCreationTranslateText * 类型: `string` * 默认值: `'This article translated from:'` * 详情: 本文翻译的文本 ### copyrightCreationReprintText * 类型: `string` * 默认值: `'This article reprint from:'` * 详情: 本文转载的文本 ### copyrightLicenseText * 类型: `string` * 默认值: `'License under:'` * 详情: 版权许可证的文本 ### prevPageLabel * 类型: `string` * 默认值: `'Previous Page'` * 详情: 上一页的文本 ### nextPageLabel * 类型: `string` * 默认值: `'Next Page'` * 详情: 下一页的文本 ### notFound * 类型: `NotFound | undefined` * 默认值: `undefined` * 详情: 404 页面配置 ```ts interface NotFound { code?: string title?: string quote?: string linkLabel?: string linkText?: string } ``` --- --- url: /config/markdown/index.md --- # Markdown 配置 ## 概述 Markdown 配置用于控制 Markdown 的行为。此配置聚合了主题为 markdown 增强的各种功能的配置。 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // [!code ++:3] markdown: { // 在这里配置 markdown }, }), }) ``` ::: warning 不要和 [VuePress](https://v2.vuepress.vuejs.org/) 的 [markdown](https://v2.vuepress.vuejs.org/zh/reference/config.html#markdown) 配置混淆。 二者是相互独立的,不要在 [VuePress > markdown](https://v2.vuepress.vuejs.org/zh/reference/config.html#markdown) 中配置主题的 markdown 配置,反之亦然。 ::: **默认配置:** ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // [!code focus:11] markdown: { hint: true, alert: true, fileTree: true, plot: true, icons: true, math: { type: 'katex' }, include: { // ...option }, }, }), }) ``` ## 配置项 ::: tip `hint` 和 `alter` 的功能由 [@vuepress/plugin-markdown-hint](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-hint.html) 插件实现。 ::: ### hint * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否启用提示容器 ### alert * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否启用 Github 风格的警告语法 *** ::: tip `image` 配置由 [@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-image.html) 插件实现。 ::: ### image * **类型**: `boolean | MarkdownImagePluginOptions` * **默认值**: `false` * **详情**: 是否启用图片增强语法 *** ::: tip `math` 配置由 [@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-math.html) 插件实现。 ::: ### math * **类型**: `boolean | MarkdownMathPluginOptions` * **默认值**: `{ type: 'katex' }` * **详情**: 是否启用数学支持 *** ### include ::: tip `include` 配置由 [@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-include.html) 插件实现。 ::: * **类型**: `boolean | MarkdownIncludePluginOptions` * **默认值**: `true` * **详情**: 是否启用 Markdown 文件导入 *** ::: tip 以下配置字段由 [vuepress-plugin-md-power](./plugins/markdown-power.md) 插件实现。 ::: ### annotation * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用内容注释 ### abbr * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用缩写语法 ### mark * **类型**: `MarkOptions` * **默认值**: `'eager'` * **详情**: 设置 `==马克笔==` 的动画播放模式 ### codeTabs * **类型**: `boolean | CodeTabsOptions` * **默认值**: `true` * **详情**: 是否启用代码块分组 ### tabs * **类型**: `boolean | TabsOptions` * **默认值**: `true` * **详情**: 是否启用 分组 ### npmTo * **类型**: `boolean | NpmToOptions` * **默认值**: `false` * **详情**: 是否启用 `npm-to` 容器 ### icon * **类型**: `IconOptions` * **默认值**: `{ provider: 'iconify' }` * **详情**: 图标配置 [查看 **icon** 使用说明](../../theme/guide/features/icon.md){.read-more} ### plot * **类型**: `boolean | PlotOptions` * **默认值**: `true` * **详情**: 是否启用隐秘文本语法 ### fileTree * **类型**: `boolean | FileTreeOptions` * **默认值**: `true` * **详情**: 是否启用文件树容器语法 ### field * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用字段容器 ### table * **类型**: `boolean | TableContainerOptions` * **默认值**: `false` * **详情**: 是否启用表格增强容器 ### timeline * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用时间线容器语法 ### collapse * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用折叠面板容器语法 ### chat * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用对话记录容器 ### demo * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Demo 容器 ### pdf * **类型**: `boolean | PdfOptions` * **默认值**: `false` * **详情**: 是否启用 PDF 嵌入语法 ### bilibili * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Bilibili 视频嵌入语法 ### youtube * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 YouTube 视频嵌入语法 ### artPlayer * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 ArtPlayer 视频嵌入语法 ### audioReader * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Audio Reader 音频嵌入语法 ### codepen * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 CodePen 嵌入语法 ### codeSandbox * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 CodeSandbox 嵌入语法 ### jsfiddle * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 JS Fiddle 嵌入语法 ### repl * **类型**: `boolean | ReplOptions` * **默认值**: `false` * **详情**: 是否启用 Repl 容器语法 ### caniuse * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Can I Use 嵌入语法 ### imageSize * **类型**: `boolean | 'local' | 'all'` * **默认值**: `false` * **详情**: 是否启用 自动填充图片宽高属性 *** ::: tip 以下配置字段由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-chart/) 插件实现。 ::: ### chartjs * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Chart.js 图表嵌入语法 ### echarts * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 ECharts 图表嵌入语法 ### mermaid * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Mermaid 图表嵌入语法 ### markmap * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Markmap 图表嵌入语法 ### plantuml * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 PlantUML 图表嵌入语法 ### flowchart * **类型**: `boolean` * **默认值**: `false` * **详情**: 是否启用 Flowchart 图表嵌入语法 --- --- url: /config/navigation/index.md --- # 导航栏配置 ## 概述 ::: tip 导航栏配置支持在 `.vuepress/config.ts` ,或者在 `plume.config.ts` 中进行配置。 ::: 主题默认会自动生成最简单的导航栏配置,仅包括 **首页** 和 **文章列表页** 。 你也可以自己配置导航栏,覆盖默认的的导航栏配置。 默认配置如下: ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ navbar: [ { text: '首页', link: '/' }, { text: '博客', link: '/blog/' }, { text: '标签', link: '/blog/tags/' }, { text: '归档', link: '/blog/archives/' } ] }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ navbar: [ { text: '首页', link: '/' }, { text: '博客', link: '/blog/' }, { text: '标签', link: '/blog/tags/' }, { text: '归档', link: '/blog/archives/' } ] }) ``` ::: 当开启了 多语言配置,则会生成对应语言的导航栏的默认配置: ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ lang: 'zh-CN', locales: { '/': { lang: 'zh-CN', title: '博客' }, // 简体中文 '/en/': { lang: 'en-US', title: 'Blog' }, // English }, theme: plumeTheme({ locales: { '/': { navbar: [ { text: '首页', link: '/' }, { text: '博客', link: '/blog/' }, { text: '标签', link: '/blog/tags/' }, { text: '归档', link: '/blog/archives/' } ] }, '/en/': { navbar: [ { text: '首页', link: '/en/' }, { text: '博客', link: '/en/blog/' }, { text: '标签', link: '/en/blog/tags/' }, { text: '归档', link: '/en/blog/archives/' } ] } } }) }) ``` 随着站点内容变得越来越丰富,如通过 集合 配置了 博客、笔记、文档、友情链接、 外部链接等等, 默认生成的导航栏配置满足不了您的需求。 这时候,您可以通过 `navbar` 字段来完全自定义导航栏,它将直接覆盖默认的导航栏配置。 ## 配置 类型: `NavItem[]` ```ts interface ThemeBadge { /* 徽章文本 */ text?: string /* 徽章类型,内置: 'info' | 'tip' | 'danger' | 'warning' */ type?: string /* 文本颜色 */ color?: string /* 背景颜色 */ bgColor?: string /* 边框颜色 */ borderColor?: string } type NavItem = string | { /** * 导航栏文本 */ text: string /** * 导航栏链接 * - 可以是外部链接 * - 可以是 frontmatter 中的 permalink * - 可以是相对于 `sourceDir` 的 markdown文件路径,请注意需要以 `/` 开头 */ link: string /** * 图标名称,或者 svg 图标 */ icon?: string | { svg: string } /** * 徽章,支持自定义徽章样式 */ badge?: string | ThemeBadge /** * 控制元素何时被激活 */ activeMatch?: string /** * * 当前分组的页面链接前缀 */ prefix?: string /** * 最大深度为 2,生成嵌套的导航栏 */ items?: NavItem[] } ``` ### 嵌套配置示例 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ navbar: [ { text: '首页', link: '/', icon: 'material-symbols:home-outline' }, { text: '博客', link: '/blog/', icon: 'material-symbols:article-outline' }, { text: '技术文档', icon: 'mdi:idea', items: [ { text: 'Vuepress Theme', icon: 'icon-park-solid:theme', items: [ { text: 'vuepress-theme-plume', link: '/vuepress-theme-plume/', icon: 'mdi:paper-airplane', badge: '徽章' }, ], }, { text: 'Vuepress Plugin', icon: 'mingcute:plugin-2-fill', badge: { text: '徽章', type: 'warning' }, items: [ { text: 'caniuse', link: '/vuepress-plugin/caniuse/', icon: 'pajamas:feature-flag', }, { text: 'auto-frontmatter', link: '/vuepress-plugin/auto-frontmatter/', icon: 'material-symbols:move-selection-down-rounded', }, { text: 'blog-data', link: '/vuepress-plugin/blog-data/', icon: 'ic:baseline-post-add', }, { text: 'notes-data', link: '/vuepress-plugin/notes-data/', icon: 'material-symbols:note-alt-rounded', }, { text: 'shiki', link: '/vuepress-plugin/shiki/', icon: 'material-symbols-light:code-blocks-outline-rounded', }, ], }, ], }, ] }) }) ``` ### `activeMatch` `activeMatch` 用于控制当前链接元素何时被激活。其值为一个类正则表达式的字符串。 **示例:** `activeMatch: '^/(blog|article)/'` 这表示,以 `/blog/` 或 `/article/` 开头的页面链接地址,该链接元素将被激活。 ### 图标 支持通过 [markdown -> icon](../guide/features/icon.md) 配置的来源的图标。 * 当 `markdown.icon.provide` 为 `iconify` 时,支持 [iconify](https://iconify.design/) 图标 * 当 `markdown.icon.provide` 为 `iconfont` 时,支持 [iconfont](https://www.iconfont.cn/) 图标 * 当 `markdown.icon.provide` 为 `fontawesome` 时,支持 [fontawesome](https://fontawesome.com/) 图标 `markdown.icon.provide` 为非 `iconify` 值时,可以在 图标名称前加上 `iconify` 前缀,强制使用 [iconify](https://iconify.design/) 图标。 ```ts const item = { text: '首页', link: '/', icon: 'iconify carbon:home' } ``` ## 配置帮助函数 主题提供了 `defineNavbarConfig(config)` 函数,为主题使用者提供导航栏配置的类型帮助。 便于将 `navbar` 配置分离到独立的配置文件中。 ```ts title="navbar.ts" twoslash import { defineNavbarConfig } from 'vuepress-theme-plume' export default defineNavbarConfig([ { text: '首页', link: '/' }, { text: '博客', link: '/blog/' }, // ... more ]) ``` --- --- url: /config/plugins/index.md --- # 介绍 主题内置的使用的插件,扩展了主题的众多功能,你可以在 `plugins` 配置中, 实现对内部使用的各个插件的自定义配置。 ## 配置 所有主题内部使用的插件, 均在 `plugins` 字段中进行配置。 ```js title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ plugins: { // more options... // [!code ++] } }), }) ``` ## 插件列表 * [@vuepress/plugin-nprogress](https://ecosystem.vuejs.press/zh/plugins/features/nprogress.html) - 页面加载进度条 * [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/zh/plugins/features/photo-swipe.html) - 图片预览 * [@vuepress/plugin-reading-time](https://ecosystem.vuejs.press/zh/plugins/development/reading-time.html) - 文章阅读时间 * [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html) - 文章水印 * [@vuepress-plume/plugin-search](./search.md) - 本地搜索 * [@vuepress/plugin-docsearch](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html) - Algolia 文档搜索 * [@vuepress/plugin-copy-code](https://ecosystem.vuejs.press/zh/plugins/features/copy-code.html) - 代码复制 * [@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html) - 代码高亮 * [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) - 文章评论 * [@vuepress/plugin-markdown-hint](https://ecosystem.vuejs.press/zh/plugins/markdown/hint.html) - Markdown 提示 * [@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/zh/plugins/markdown/image.html) - Markdown 图片 * [@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/zh/plugins/markdown/math.html) - Markdown 数学公式 * [@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/zh/plugins/markdown/include.html) - Markdown 导入文件 * [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-chart/) - Markdown 图表 chartjs / echarts / mermaid / flowchart / markmap / plantUML * [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/zh/plugins/tools/replace-assets.html) - 资源链接替换 * [vuepress-plugin-md-power](./markdown-power.md) - Markdown Power * [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) - git 提交信息 * [@vuepress/plugin-cache](https://ecosystem.vuejs.press/zh/plugins/tools/cache.html) - 页面编译缓存 * [@vuepress/plugin-seo](https://ecosystem.vuejs.press/zh/plugins/seo/seo/) - SEO 优化 * [@vuepress/plugin-sitemap](https://ecosystem.vuejs.press/zh/plugins/seo/sitemap/) - 站点地图 :::tip 您无需重复安装这些内置插件,也无需在 [vuepress配置 > plugins](https://v2.vuepress.vuejs.org/zh/reference/config.html#plugins) 中添加它们。主题已在内部完成了这些工作。 ::: --- --- url: /config/plugins/code-highlight/index.md --- # 代码高亮 ## 概述 主题内置的代码高亮插件, 对代码块进行代码高亮。 关联插件:[@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html) 主题 使用 [Shiki](https://github.com/shikijs/shiki) 在 Markdown 代码块中使用彩色文本实现语法高亮。 Shiki 支持多种编程语言。 在 Shiki 的代码仓库中,可以找到 [合法的编程语言列表](https://shiki.style/languages) 。 ## 特性 * [代码块标题](../../guide/code/features.md#代码块标题) * [代码行高亮](../../guide/code/features.md#在代码块中实现行高亮) * [代码聚焦](../../guide/code/features.md#代码块中聚焦) * [代码对比差异](../../guide/code/features.md#代码块中的颜色差异) * [代码高亮“错误”和“警告”](../../guide/code/features.md#高亮-错误-和-警告) * [代码词高亮](../../guide/code/features.md#代码块中-词高亮) * [代码块折叠](../../guide/code/features.md#折叠代码块) * [twoslash](../../guide/code/twoslash.md#twoslash) :在代码块内提供内联类型提示。 ## 配置 默认配置: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ codeHighlighter: { themes: { light: 'vitesse-light', dark: 'vitesse-dark' }, notationDiff: true, notationErrorLevel: true, notationFocus: true, notationHighlight: true, notationWordHighlight: true, highlightLines: true, collapsedLines: false, lineNumbers: true, }, // 也可以通过 plugins.shiki 配置,但不推荐 plugins: { shiki: {} } }), }) ``` ### themes * 类型: `{ light: string, dark: string }` * 默认值: `{ light: 'vitesse-light', dark: 'vitesse-dark' }` 代码高亮主题,支持 浅色/暗色 双主题。 可在 支持的 [主题列表](https://shiki.style/themes) 中选择你喜欢的主题。 ### langs * 类型: `string[]` * 默认值: `[]` 需要高亮的编程语言, 例如 `javascript`、`typescript`、`python`、`java`、`c++`、`c#`等。 默认会根据代码块的语言自动识别。 在 Shiki 的代码仓库中,可以找到 [合法的编程语言列表](https://shiki.style/languages) 。 ### defaultLang * 类型: `string` * 默认值: `text` 指定的语言不可用时所使用的备选语言。 ### lineNumbers * 类型:`boolean | number` * 默认值: `true` 是否显示行号。 `true`: 显示行号\ `false`: 不显示行号\ `number`: 指定需要显式代码行号的最小行数。 ### twoslash * 类型: `boolean | ShikiTwoslashOptions` * 默认值: `false` 是否启用 对 `typescript` 和 `vue` 语言的 类型提示 支持。 ### whitespace * 类型: `boolean | 'all' | 'boundary' | 'trailing'` * 默认值: `false` 将空白字符(Tab 和空格)渲染为单独的标签(具有 tab 或 space 类名)。 效果: ### collapsedLines * 类型: `boolean | number` * 默认值: `false` 将代码块折叠到指定行数。 ### transformers * 类型: `ShikiTransformer[]` * 默认值: `[]` 代码转换器, 查看 [shiki transformers](https://shiki.style/guide/transformers) 了解更多信息。 --- --- url: /config/plugins/llmstxt/index.md --- # LLMs txt ## 概述 为站点添加 [llms.txt](https://llmstxt.org/),以提供对 LLM 友好的内容。 **关联插件**: [@vuepress/plugin-llms](https://ecosystem.vuejs.press/zh/plugins/ai/llms.html) ## 为什么需要 llms.txt? 大型语言模型越来越依赖网站信息,但面临一个关键限制:上下文窗口太小,无法完整处理大多数网站。将包含导航、广告和 JavaScript 的复杂 HTML 页面转换为适合 LLM 的纯文本既困难又不精确。 虽然网站同时为人类读者和 LLM 服务,但后者受益于在一个可访问的位置收集的更简洁、专家级的信息。这对于开发环境等使用案例尤其重要,因为 LLM 需要快速访问编程文档和 API。 向网站添加 `/llms.txt` Markdown 文件,以提供对 LLM 友好的内容。此文件提供了简短的背景信息、指南和指向详细 Markdown 文件的链接。 ## 功能 插件通过检索你的文档源目录中的所有 Markdown 文件,并将其转换为 LLM 友好的纯文本文件。 ::: file-tree * .vuepress/dist * llms.txt * llms-full.txt * markdown-examples.html * markdown-examples.md * … ::: 点击以下链接查看本文档站点的 llms.txt 文件: * [llms.txt](/llms.txt){.no-icon} * [llms-full.txt](/llms-full.txt){.no-icon} ::: tip 插件仅在生产构建时,即执行 `vuepress build` 命令时,生成 `llms.txt` 文件,以及其它 LLM 友好的文档文件,并将它们输出到 `.vuepress/dist` 目录中。 ::: [完整功能说明请查看 **插件官方文档**](https://ecosystem.vuejs.press/zh/plugins/ai/llms.html#%E6%8F%92%E4%BB%B6%E5%8A%9F%E8%83%BD){.read-more} ## 配置 主题默认不启用此功能,你可以通过 `llmstxt` 配置项启用它: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 使用主题内置的默认配置 // llmstxt: true, // 使用自定义配置 llmstxt: { locale: '/', // ...其它配置 }, // 也可以在 `plugins.llmstxt` 配置,但不推荐 plugins: { llmstxt: true } }), }) ``` [完整配置项说明请查看 **插件官方文档**](https://ecosystem.vuejs.press/zh/plugins/ai/llms.html#options){.read-more} ## 组件 为进一步增强 文档站点 与 LLMs 的互动,你可以在文档站点中添加 `` 组件。 该组件不作为内置组件,而是主题额外的 `features` 实现,因此你需要手动引入它, 并在合适的位置,通过 [组件插槽](../../guide/custom/slots.md) 添加到文档站点中: ```ts title=".vuepress/client.ts" import { defineAsyncComponent, h } from 'vue' import { Layout } from 'vuepress-theme-plume/client' import PageContextMenu from 'vuepress-theme-plume/features/PageContextMenu.vue' // [!code ++] import { defineClientConfig } from 'vuepress/client' export default defineClientConfig({ layouts: { Layout: h(Layout, null, { // 将 PageContextMenu 添加到 doc-title-after 插槽,即文章标题的右侧 'doc-title-after': () => h(PageContextMenu), // [!code ++] }), }, }) ``` 你可以在当前页面的标题的右侧,体验该组件的功能。 ::: important 此组件完全依赖于 `@vuepress/plugin-llms` 插件,仅当你启用了此插件功能后,才能使用它。 因此,此组件提供的功能 **仅在构建后的生产包中才可用** 。 ::: --- --- url: /config/plugins/markdown-enhance/index.md --- # Markdown Enhance ::: danger 从 `1.0.0-rc.154` 开始,该插件已从主题中移除 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 提供的,在主题中明确受到支持 的功能,已迁移到 `vuepress/ecosystem` 仓库的其他插件中,因此,主题将从 `1.0.0-rc.154` 开始,安全的 移除 `vuepress-plugin-md-enhance` 插件。 ::: ## 概述 提供 Markdown 增强功能。 关联插件:[vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 默认配置: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // 以下可选项在 主题中默认不启用, // 请在主题中自行配置 // stylize: true, // 对行内语法进行样式化以创建代码片段 // playground: true, // 交互演示 // kotlinPlayground: true, // Kotlin 交互演示 // vuePlayground: true, // Vue 交互演示 // sandpack: true, // sandpack 交互演示 }, }), }) ``` ## 配置 详见 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/config.html) --- --- url: /config/plugins/markdown-image/index.md --- # Markdown Image ## 概述 为 Markdown 图像添加附加功能。 关联插件:[@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-image.html) ## 配置 插件默认不启用任何功能,你需要手动开启它们。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { image: { // 启用 figure // figure: true, // 启用图片懒加载 // lazyload: true, // 启用图片标记 // mark: true, // 启用图片大小 // size: true, } }, // 也可以在 `plugins.markdownImage` 配置,但不推荐 plugins: { markdownImage: {} } }), }) ``` --- --- url: /config/plugins/markdown-include/index.md --- # Markdown Include ## 概述 在 Markdown 文件中导入其他 markdown 文件内容。 关联插件:[@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-include.html) ## 配置 主题默认启用 `markdownInclude`。你还可以通过配置来自定义行为。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { include: { // ... options } }, // 也可以在 `plugins.markdownInclude` 中配置,但不推荐 plugins: { markdownInclude: {}, } }) }) ``` ### resolvePath * 类型:`(path: string, cwd: string | null) => string` * 默认值:`(path) => path` * 详情:处理 include 文件路径。 ### deep * 类型:`boolean` * 详情:是否启用图片 Figure 支持。 ### useComment * 类型:`boolean` * 默认值:`true` * 详情:是否使用 `` 代替 `@include: xxx` 导入文件。 ### resolveImagePath * 类型:`boolean` * 默认值:`true` * 详情:是否解析包含的 Markdown 文件的里的相对图像路径。 ### resolveLinkPath * 类型:`boolean` * 默认值:`true` * 详情:是否解析包含的 Markdown 文件的里的文件相对路径。 --- --- url: /config/plugins/markdown-math/index.md --- # Markdown Math ## 概述 为 Markdown 添加数学支持。 关联插件:[@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-math.html) 此插件允许你使用 mathjax 或 katex 在 Markdown 中渲染 $\TeX$ 内容。 ## 配置 插件默认启用 `katex`。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { math: { type: 'katex', } }, // 也可以在 `plugins.markdownMath` 中进行配置,但不推荐 plugins: { markdownMath: {} } }), }) ``` --- --- url: /config/plugins/markdown-power/index.md --- ## 概述 为 主题 提供 Markdown 增强功能。 关联插件: [vuepress-plugin-md-power](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-md-power) ## 配置 默认配置: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { fileTree: true, // :::file-tree 文件树容器 plot: true, // !!plot!! 隐秘文本 icons: true, // ::collect:name:: 内联 iconify 图标 // 默认不启用以下功能,你需要手动开启它们 // npmTo: true, // :::npm-to // demo: true, // :::demo // pdf: true, // @[pdf](url) 嵌入 PDF 文件 // bilibili: true, // @[bilibili](bvid) 嵌入 bilibili 视频 // acfun: true, // @[acfun](id) 嵌入 AcFun 视屏 // youtube: true, // @[youtube](id) 嵌入 youtube 视频 // codepen: true, // @[codepen](user/slash) 嵌入 codepen // replit: true, // @[replit](user/repl-name) 嵌入 Replit // codeSandbox: true, // @[codesandbox](id) 嵌入 CodeSandbox // jsfiddle: true, // @[jsfiddle](id) 嵌入 jsfiddle // caniuse: true, // @[caniuse](feature) 嵌入 caniuse // repl: true, // :::go-repl :::kotlin-repl :::rust-repl // imageSize: true, // 在构建阶段为 图片添加 width/height 属性 }, // 也可以在 `plugins.markdownPower` 中配置,但不推荐 plugins: { markdownPower: {} } }), }) ``` ## 功能 ### 嵌入 PDF 插件默认不启用该功能,你需要手动设置 `pdf` 为 `true` **语法:** ```md @[pdf](url) ``` 请查看 [完整使用文档](../../guide/embed/pdf.md) ### iconify 图标 插件默认不启用该功能,你需要手动设置 `icons` 为 `true` 得益于 [iconify](https://iconify.design/), 你可以在 Markdown 中使用 iconify **200k+** 的图标 **语法:** ```md ::collect:name:: ``` 请查看 [完整使用文档](../../guide/markdown/icons.md) ### bilibili 视频 插件默认不启用该功能,你需要手动设置 `bilibili` 为 `true` **语法:** ```md @[bilibili](bvid) ``` 请查看 [完整使用文档](../../guide/embed/bilibili.md) ### AcFun 视频 插件默认不启用该功能,你需要手动设置 `acfun` 为 `true` **语法:** ```md @[acfun](id) ``` 请查看 [完整使用文档](../../guide/embed/video/acfun.md) ### youtube 视频 插件默认不启用该功能,你需要手动设置 `youtube` 为 `true` **语法:** ```md @[youtube](id) ``` 请查看 [完整使用文档](../../guide/embed/youtube.md) ### codePen 代码演示 插件默认不启用该功能,你需要手动设置 `codepen` 为 `true` **语法:** ```md @[codepen](user/slash) ``` 请查看 [完整使用文档](../../guide/repl/codepen.md) ### codeSandbox 代码演示 插件默认不启用该功能,你需要手动设置 `codeSandbox` 为 `true` **语法:** ```md @[codesandbox](id) ``` 请查看 [完整使用文档](../../guide/repl/codeSandbox.md) ### jsfiddle 代码演示 插件默认不启用该功能,你需要手动设置 `jsfiddle` 为 `true` **语法:** ```md @[jsfiddle](id) ``` 请查看 [完整使用文档](../../guide/repl/jsFiddle.md) ### caniuse 浏览器支持 插件默认不启用该功能,你需要手动设置 `caniuse` 为 `true` **语法:** ```md @[caniuse](feature) ``` 请查看 [完整使用文档](../../guide/markdown/caniuse.md) ### Repl 代码演示容器 插件默认不启用该功能,你需要手动设置 `repl` 为 `true` 支持在线运行 Rust、Golang、Kotlin 代码,还支持在线编辑。 或者开启部分功能,如下所示 ```ts export default defineUserConfig({ theme: plumeTheme({ plugins: { markdownPower: { repl: { rust: true, go: true, kotlin: true, }, }, } }) }) ``` **语法:** ````md ::: rust-repl ```rust // rust code ``` ::: ::: go-repl ```go // go code ``` ::: ::: kotlin-repl ```kotlin // kotlin code ``` ::: ::: python-repl ```python # python code ``` ::: ```` 请查看完整使用文档: * [代码演示 > Rust](../../guide/repl/rust.md) * [代码演示 > Golang](../../guide/repl/golang.md) * [代码演示 > Kotlin](../../guide/repl/kotlin.md) * [代码演示 > Python](../../guide/repl/python.md) ### Plot 隐秘文本 插件默认不启用该功能,你需要手动设置 `plot` 为 `true` **语法:** ```md !!content!! ``` 请查看 [完整使用文档](../../guide/markdown/plot.md) ### 文件树 插件默认不启用该功能,你需要手动设置 `fileTree` 为 `true` **语法:** ```md ::: file-tree - folder1 - file1.md - file2.ts - folder2 - file3.md - folder3 ::: ``` 请查看 [完整使用文档](../../guide/markdown/file-tree.md) ### 图片尺寸 该功能会为 markdown 文件中的 图片引用 添加当前图片的 `width` 和 `height` 属性。 通过读取 图片的原始尺寸大小,为 图片设置默认的 图片尺寸 和 比例。 从而解决页面在图片加载未完成到完成时,布局闪烁的问题。 插件默认不启用该功能,你需要手动设置 `imageSize`: * 如果 `imageSize` 为 `true`,则插件仅处理本地图片,等同于 `local` 选项; * 如果 `imageSize` 为 `'local'`,则插件仅处理本地图片; * 如果 `imageSize` 为 `'all'`,则插件同时处理本地图片和远程图片。 ::: important **此功能仅在构建生产包时生效。** 请谨慎 使用 `'all'` 选项,由于该选项会在 构建生产包时,请求远程图片资源,这会使得构建时间变长。 虽然主题做了优化仅会加载图片 **几 KB** 的数据包 用于分析尺寸,但还是会实际影响构建时间。 ::: --- --- url: /config/plugins/reading-time/index.md --- # 阅读统计 ## 概述 为每个页面生成字数统计与预计阅读时间。 关联插件: [@vuepress/plugin-reading-time](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html) 默认配置: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ readingTime: { wordPerMinute: 300 }, // 也可以通过 plugins.readingTime 配置,但不推荐 plugins: { readingTime: {} } }), }) ``` ## 配置 ### wordPerMinute * 类型:`number` * 默认值:`300` 每分钟阅读字数。 ### locales * 类型: `ReadingTimePluginLocaleConfig` 阅读时间插件的国际化配置。 ```ts interface ReadingTimePluginLocaleData { /** * 字数模板,模板中 `$word` 会被自动替换为字数 */ word: string /** * 小于一分钟文字 */ less1Minute: string /** * 时间模板 */ time: string } interface ReadingTimePluginLocaleConfig { [localePath: string]: ReadingTimePluginLocaleData } ``` ## 禁用 可以通过配置 `readingTime` 为 `false` 禁用该功能。 禁用后,文章页不会显示字数统计与预计阅读时间。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ readingTime: false }), }) ``` --- --- url: /config/plugins/search/index.md --- # 内容搜索 ## 本地搜索 ### 概述 为站点添加本地搜索。 关联插件: [@vuepress-plume/plugin-search](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-search) 该插件使用 [minisearch](https://github.com/lucaong/minisearch) 进行内容搜索。 默认配置: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ search: { provider: 'local', // [!code hl] // more options... }, // 也可以通过 plugins.search 配置,但不推荐 plugins: { search: {}, } }) }) ``` ### 配置 ```ts interface SearchOptions { /** * 本地搜索 国际化 */ locales?: { [locale: string]: SearchBoxLocale } /** * 文章是否可被搜索,默认为 `() => true` */ isSearchable?: (page: Page) => boolean } interface SearchBoxLocale { placeholder: string buttonText: string resetButtonTitle: string backButtonTitle: string noResultsText: string footer: { selectText: string selectKeyAriaLabel: string navigateText: string navigateUpKeyAriaLabel: string navigateDownKeyAriaLabel: string closeText: string closeKeyAriaLabel: string } } ``` ## Algolia DocSearch ### 概述 使用 [Algolia DocSearch](https://docsearch.algolia.com/) 提供支持的网站内容搜索插件 关联插件:[@vuepress/plugin-docsearch](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html) 查看 [Algolia DocSearch 参考](/guide/features/content-search/#algolia-docsearch) 获取更多信息。 ### 启用 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ search: { provider: 'algolia', // [!code hl] appId: 'YOUR_APP_ID', apiKey: 'YOUR_API_KEY', indexName: 'YOUR_INDEX_NAME', // more options }, // 也可以通过 plugins.docsearch 配置,但不推荐 plugins: { docsearch: {}, } }) }) ``` --- --- url: /config/sidebar/index.md --- # 侧边栏配置 ## 概述 侧边栏是主题中位于页面最左侧的核心导航区域,承担着引导用户在不同页面间跳转的重要功能。 在 VuePress 生态中,默认主题 `@vuepress/theme-default` 通过 `sidebar` 配置项管理侧边栏。本主题在保留这一经典配置方式的基础上,还提供了更为灵活的集合(Collections)级侧边栏配置方案。 ## 集合级侧边栏配置 集合(Collections)是主题中组织系列文档的核心概念。当集合类型设置为 `doc` 时,您可以在 `collection.sidebar` 中定义专属的侧边栏导航。 以下示例展示了如何在 `docs` 目录下创建类型为 `doc` 的集合,并配置其侧边栏: ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { defineCollection, plumeTheme } from 'vuepress-theme-plume' // 定义文档集合配置 // [!code hl:10] const demo = defineCollection({ type: 'doc', dir: 'demo', // 文档目录 title: 'Demo', // 集合名称 sidebar: [ // 侧边栏配置 // [!code ++:4] { text: 'one item', link: 'one' }, { text: 'two item', link: 'two' }, ] }) export default defineUserConfig({ theme: plumeTheme({ collections: [demo], // 注册集合 // [!code hl] }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineCollection, defineThemeConfig } from 'vuepress-theme-plume' // 使用独立配置文件定义集合 // [!code hl:10] const demo = defineCollection({ type: 'doc', dir: 'demo', title: 'Demo', sidebar: [ { text: 'one item', link: 'one' }, { text: 'two item', link: 'two' }, ] }) export default defineThemeConfig({ collections: [demo], // [!code hl] }) ``` ::: 主题提供的 `defineCollection` 工具函数简化了集合配置过程。如需了解完整的集合配置选项,请参阅[集合配置文档](./collections.md)。 ## 全局侧边栏配置 如果您希望采用传统的全局配置方式管理侧边栏,可以直接在主题配置中使用 `sidebar` 选项。这种方式适合不需要按集合分组导航的场景。 ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 全局侧边栏配置 // [!code hl:7] sidebar: { '/config/': [ // 匹配/config/路径 { text: '侧边栏配置', link: 'sidebar-1' }, { text: '侧边栏配置', link: 'sidebar-2' }, ] } }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ // 在独立配置文件中定义全局侧边栏 // [!code hl:7] sidebar: { '/config/': [ { text: '侧边栏配置', link: 'sidebar-1' }, { text: '侧边栏配置', link: 'sidebar-2' }, ] } }) ``` ::: 两种配置方式各有优势:集合级配置适合模块化文档结构,全局配置则便于统一管理简单项目的导航。 如需了解侧边栏的完整配置选项和使用技巧,请参阅[侧边栏配置指南](../guide/quick-start/sidebar.md)。 --- --- url: /config/theme/index.md --- # 主题配置 ## 概述 主题配置用于定制主题的各项功能,以控制主题的行为, 您可以在 `.vuepress/config.ts` 或者 `.vuepress/plume.config.ts` 中进行配置。 当字段说明包含以下声明时,表示该字段不支持在 `.vuepress/plume.config.ts` 中进行配置: ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: 无以上声明的字段,你可以在 `.vuepress/config.ts` 或者 `.vuepress/plume.config.ts` 的任意一个文件中 进行配置,一般情况下建议在 `.vuepress/plume.config.ts` 中进行配置。 ::: warning 已经在一个配置文件中进行配置的字段,尽量不要在另一个配置文件中重复配置 ::: ::: code-tabs#configs @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 主题配置 }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ // 主题配置 }) ``` ::: ## 基础配置 ### configFile * **类型:** `string` * **默认值:** `''` * **详情:** 自定义主题配置文件的路径。 查看 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 了解更多。 ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### plugins * **类型:**`PlumeThemePluginOptions` * **默认值:** `{}` * **详情:** 对主题内部使用的插件进行自定义配置。 主题使用的插件默认已进行了配置,大多数情况下您不需要进行修改,如果需要使用到细致的定制化,请查阅 [此文档](./plugins/README.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### markdown * **类型:** `MarkdownOptions` * **默认值:** `{}` * **详情:** Markdown 功能配置, 参考 [此文档](./markdown.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### codeHighlighter * **类型:** `false | ShikiPluginOptions` * **默认值:** `{}` * **详情:** 代码高亮配置, 参考 [此文档](../guide/code/intro.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### search * **类型:** `false | SearchOptions` * **默认值:** `{ provider: 'local' }` * **详情:** 搜索配置, 参考 [此文档](../guide/features/search.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### comment * **类型:** `false | CommentPluginOptions` * **默认值:** `false` * **详情:** 评论配置, 参考 [此文档](../guide/features/comments.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### watermark * **类型:** `false | WatermarkPluginOptions` * **默认值:** `false` * **详情:** 水印配置, 参考 [此文档](../guide/features/watermark.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### readingTime * **类型:** `false | ReadingTimePluginOptions` * **默认值:** `false` * **详情:** 阅读时长配置, 参考 [此文档](./plugins/reading-time.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### copyCode * **类型:** `false | CopyCodePluginOptions` * **默认值:** `{}` * **详情:** 复制代码配置, 参考 [此文档](../guide/code/copy-code.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### replaceAssets * **类型:** `false | ReplaceAssetsPluginOptions` * **默认值:** `false` * **详情:** 替换资源配置, 参考 [此文档](../guide/features/replace-assets.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### hostname * **类型:** `string` * **默认值:** `''` * **详情:** 部署站点域名。 当 `hostname` 配置为有效域名时,主题将会生成 `sitemap` 和 `seo` 相关的内容。 ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### autoFrontmatter * **类型:** `false | AutoFrontmatterOptions` * **详情:** 是否为 markdown 文件自动添加 frontmatter 配置 ```ts interface AutoFrontmatterOptions { /** * 是否自动生成 permalink * * @default true */ permalink?: boolean /** * 是否自动生成 createTime * * 默认读取 文件创建时间,`createTitme` 比 vuepress 默认的 `date` 时间更精准到秒 */ createTime?: boolean /** * 是否自动生成 title * * 默认读取文件名作为标题 */ title?: boolean } ``` ### cache * **类型:** `false | 'memory' | 'filesystem'` * **默认值:** `filesystem` * **详情:** 是否启用 编译缓存,或配置缓存方式 此配置项用于解决 VuePress 启动速度慢的问题,在首次启动服务时,对编译结果进行缓存,二次启动时 直接读取缓存,跳过编译,从而加快启动速度。 * `false`:禁用 缓存 * `'memory'`:使用内存缓存,此方式可获得更快的启动速度,但随着项目文件数量增加,内存占用会增加, 适合文章数量较少的项目使用 * `'filesystem'`:使用文件系统缓存,此方式可获得相对快且稳定的启动速度,更适合内容多的项目使用 ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 为了使缓存能够生效,您应该 **删除** `package.json` 中 `vuepress dev` 开发服务启动脚本中的 `--clean-cache` 参数。 ::: ### docsRepo * **类型:** `string` * **默认值:** `''` * **详情:** 文档仓库配置, 用于生成 `Edit this page` 链接。 ### docsBranch * **类型:** `string` * **默认值:** `''` * **详情:** 文档仓库分支配置,用于生成 `Edit this page` 链接。 ### docsDir * **类型:** `string` * **默认值:** `''` * **详情:** 文档仓库目录配置,用于生成 `Edit this page` 链接。 ### editLink * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否启用 编辑链接 ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### lastUpdated * **类型:** `false | LastUpdatedOptions` * **默认值:** `{ formatOptions: { dateStyle: 'short', timeStyle: 'short' } }` * **详情:** 最后更新时间 ```ts interface LastUpdatedOptions { /** * 设置最后更新时间格式的选项。 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options * * @default * { dateStyle: 'short', timeStyle: 'short' } */ formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean } } ``` ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### contributors * **类型:** `boolean | ContributorsOptions` * **默认值:** `true` * **详情:** 是否显示贡献者 更多配置请参考 [此文档](../guide/features/contributors.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### changelog * **类型:** `boolean | ChangelogOptions` * **默认值:** `false` * **详情:** 是否显示页面变更历史 更多配置请参考 [此文档](../guide/features/changelog.md) ::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。 ::: ### locales * **类型:** `Record` * **默认值:** `{}` * **详情:** 多语言配置 不同语言的文本配置,参考 [此文档](./locales.md) 多语言配置支持以下 [Locale](#locale-配置) 所有配置选项以控制不同语言下的主题行为。 ## Locale 配置 ::: tip 以下所有字段也均是基础配置字段,可以与 `locales` 等字段平级配置。 ::: ### home * **类型:** `false | string` * **默认值:** `/` * **详情:** 首页的路径, 它将被用于: * 导航栏中 logo的链接; * 404页面的 *返回首页* 的链接; ### logo * 类型: `false | string` * **默认值:** `false` * **详情:** 导航栏中的logo。 ### logoDark * 类型 `false | string` * **默认值:** `false` * **详情:** Dark模式下,导航栏中的logo。 ### appearance * **类型:** `boolean | 'dark' | 'force-dark` * **默认值:** `true` 是否启用 深色模式。 * 如果该选项设置为 `true`,则默认主题将由用户的首选配色方案决定。 * 如果该选项设置为 `dark`,则默认情况下主题将是深色的,除非用户手动切换它。 * 如果该选项设置为 `false`,用户将无法切换主题。 * 如果该选项设置为 `force-dark`,则用户将无法切换主题,但会强制将主题更改为深色。 此选项注入一个内联脚本,从本地存储恢复用户设置。这确保在呈现页面之前应用 `[data-theme="dark"]` 以避免闪烁。 ### profile * **类型:** `ProfileOptions` * **默认值:** `{}` * **详情:** 配置站点博主的个人信息 * `profile.avatar`: 头像地址,用于右侧博主信息展示 * `profile.name`: 名称, 用于右侧博主信息展示 * `profile.description`: 个人描述,用于右侧博主信息展示 * `profile.circle`: 是否为圆形头像 * `profile.location`: 用户地理位置 * `profile.organization`: 用户所在组织/公司 * `profile.layout`: 个人信息展示在左侧还是右侧,`'left' | 'right'` 示例: ```ts export default defineUserConfig({ theme: plumeTheme({ profile: { avatar: '/avatar.jpg', name: '张三', description: '此处无银三百两,隔壁王二不曾偷', circle: true, location: '杭州,中国', organization: 'xxx公司', layout: 'right', } }) }) ``` ### social * **类型:** `false | SocialLink[]` * **默认值:** `false` * **详情:** 个人社交信息配置。 将作为 图标链接 展示在 导航栏最右侧。 图标可选值: * `'github'` * `'gitlab'` * `'npm'` * `'docker'` * `'discord'` * `'telegram'` * `'facebook'` * `'instagram'` * `'linkedin'` * `'mastodon'` * `'slack'` * `'twitter'` * `'x'` * `'youtube'` * `'juejin'` * `'stackoverflow'` * `'qq'` * `'weibo'` * `'bilibili'` * `'zhihu'` * `'douban'` * `'steam'` * `'xbox'` * `{ svg: string, name?: string }`: 自定义图标,传入 svg 源码字符串,可选 `name` 字段,用于配置 [`navbarSocialInclude`](#navbarsocialinclude) 示例: ```ts export default defineUserConfig({ theme: plumeTheme({ social: [ { icon: 'github', link: 'https://github.com/zhangsan' }, { icon: { svg: 'xxxxx', name: 'xxx' }, link: 'https://xxx.com' }, ] }) }) ``` ### navbarSocialInclude * **类型:** `string[]` * **默认值:** `['github', 'twitter', 'discord', 'facebook']` * **详情:** 允许显示在导航栏的社交链接。 该配置仅在 PC 端下有效。 如果 [`social`](#social) 配置为 `{ svg: string, name: string}` 则可将 `name` 作为 `navbarSocialInclude` 的值。 ### navbar * **类型:** `NavItem[]` * **默认值:** `[]` * **详情:** 导航栏配置。 为了配置导航栏元素,你可以将其设置为 导航栏数组 ,其中的每个元素是 `string` 或 `NavItem` 对象 * `NavItem` 对象应该有一个 text 字段和一个 link 字段,还有一个可选的 `activeMatch` 字段。 * `string` 表示是一个页面文件路径,或者是一个页面的访问路径。 ```ts type NavItem = string | { text: string link: string /** * 当前分组的页面前缀 */ prefix?: string /** * 该分组下的导航项 */ items?: NavItem[] /** * 支持 iconify 图标,直接使用 iconify name 即可自动加载 * * @see https://icon-sets.iconify.design/ */ icon: string /** * 控制元素何时被激活 */ activeMatch?: string } ``` * 示例1: ```js export default defineUserConfig({ theme: plumeTheme({ navbar: [ // NavbarItem { text: 'Foo', link: '/foo/' }, // NavbarGroup { text: 'Group', prefix: '/group/', items: ['foo/', 'bar/'], }, // 字符串 - 页面文件路径 '/bar', // 可以直接省略后缀 `.md` ], }), }) ``` * 示例2: ```js export default defineUserConfig({ theme: plumeTheme({ navbar: [ // 嵌套 Group - 最大深度为 2 { text: 'Group', items: [ { text: 'SubGroup', items: ['/group/sub/', '/group/sub/bar/'], }, ], }, // 控制元素何时被激活 { text: 'Group 2', items: [ { text: 'Always active', link: '/', // 该元素将一直处于激活状态 activeMatch: '/', }, { text: 'Active on /foo/', link: '/not-foo/', // 该元素在当前路由路径是 /foo/ 开头时激活 // 支持正则表达式 activeMatch: '^/foo/', }, ], }, ], }), }) ``` ### collections * **类型:** `ThemeCollectionItem[]` * **默认值:** `[]` * **详情:** 文档集合配置 [查看 **集合指南**](../guide/quick-start/collection.md){.read-more} [查看 **集合配置** 了解更多](./collections.md){.read-more} ### sidebar * **类型:** `false | SidebarMulti` * **详情:** 侧边栏配置。**主题更推荐在 [collections 配置](./collections.md) 中进行侧边栏配置。** 配置对象的 `key` 为侧边栏公共访问路径前缀。 对于 `value`: * `'auto'` 表示自动根据目录结构生成侧边栏 * `string` 表示侧边栏对应的页面文件路径 * `SidebarItem` 表示侧边栏单项配置 ```ts type ThemeIcon = string | { svg: string } type SidebarMulti = Record< string, | 'auto' | (string | SidebarItem)[] | { items: 'auto' | (string | SidebarItem)[], prefix?: string } > interface SidebarItem { /** * 侧边栏文本 */ text?: string /** * 侧边栏链接 */ link?: string /** * 侧边栏图标 */ icon?: ThemeIcon /** * 次级侧边栏分组 */ items?: 'auto' | (string | SidebarItem)[] /** * 如果未指定,组不可折叠。 * 如果为`true`,组可折叠,并默认折叠。 * 如果为`false`,组可折叠,但默认展开。 */ collapsed?: boolean /** * 当前分组的链接前缀 */ prefix?: string rel?: string target?: string } ``` ### sidebarScrollbar * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否显示侧边栏滚动条 设置为 `false` 时,仅隐藏滚动条,但不改变滚动行为。 ### aside * **类型:** `boolean | 'left'` * **默认值:** `true` * **详情:** 是否显示侧边栏 * `false` 表示禁用 右侧边栏 * `true` 表示启用 右侧边栏 * `'left` 表示将有侧边栏移动到文章内容左侧,sidebar 右侧 每个页面可以通过 [frontmatter aside](./frontmatter/basic.md#aside) 覆盖层级配置。 ### outline * **类型:** `false | number | [number, number] | 'deep'` * **默认值:** `[2, 3]` * **详情:** 要显示的标题级别。 单个数字表示只显示该级别的标题。 如果传递的是一个元组,第一个数字是最小级别,第二个数字是最大级别。 `'deep'` 与 `[2, 6]` 相同,将显示从 `

` 到 `

` 的所有标题。 当 [aside](#aside) 被禁用时,`outline` 也会被禁用 每个页面可以通过 [frontmatter outline](./frontmatter/basic.md#outline) 覆盖层级配置。 ### transition * **类型:** `boolean | TransitionOptions` * **默认值:** `true` * **详情:** 是否启用过渡动画。 传入 `boolean` 类型时,`true` 代表启用,`false` 代表禁用。 也可以传入一个对象,具体配置见下 ```ts interface TransitionOptions { /** * 是否启用 页面间跳转过渡动画 * @default true */ page?: boolean /** * 是否启用 博客文章列表过渡动画 * @default true */ postList?: boolean /** * 是否启用 深色/浅色 模式切换过渡动画, * 或配置过渡动画类型 * @default 'fade' */ appearance?: boolean | 'fade' | 'circle-clip' | 'horizontal-clip' | 'vertical-clip' | 'skew-clip' | 'blinds-vertical' | 'blinds-horizontal' | 'soft-blur-fade' | 'diamond-reveal' } ``` ### footer * **类型:** `false | { message: string; copyright: string }` * **默认值:** `false` * **详情:** 页脚配置。 ### bulletin * **类型:** `boolean | BulletinOptions` * **默认值:** `false` * **详情:** 公告板配置 详情请参考 [公告板](../guide/features/bulletin.md) ### editLinkPattern * **类型:** `string` * **默认值:** `''` * **详情:** 编辑链接的正则表达式 示例: `':repo/edit/:branch/:path'` ### copyright * **类型:** `boolean | CopyrightLicense | CopyrightOptions` * **默认值:** `false` * **详情:** 版权配置 详情请参考 [版权所有](../guide/features/copyright.md) ### prevPage * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否显示上一页 ### nextPage * **类型:** `boolean` * **默认值:** `true` * **详情:** 是否显示下一页 ### createTime * **类型:** `boolean | 'only-posts'` * **默认值:** `true` * **详情:** 是否显示创建时间 * `false` - 不显示 * `'only-posts'` - 只显示在文章列表页面 * `true` - 显示在所有文章页面 --- --- url: /config/watermark/index.md --- # 水印 ## 概述 主题内置的 水印插件,为 全站,或者 单个页面 添加水印。 关联插件:[@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html) ## 使用 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // watermark: true, watermark: { // enabled: false, // boolean 类型控制是否全局启用 enabled: page => true, // function 类型 过滤哪些页面启用水印 /** * 是否全屏水印,默认为 `true`, * 设置为 `false` 时,水印仅在 内容区域中显示。 */ fullPage: true, /** @see https://zhensherlock.github.io/watermark-js-plus/zh/config/ */ watermarkOptions: { content: 'your watermark', // ... } }, // 也可以通过 plugins.watermark 配置,但不推荐 plugins: { watermark: {} } }) }) ``` ## 配置项 ### enabled * 类型: `boolean | ((page: Page) => boolean)` * 默认值: `false` * 详情: 指定哪些页面需要添加水印。 拥有 `true` 值的页面将会被添加水印。 ### watermarkOptions * 类型: `WatermarkOptions` * 默认值: `undefined` * 详情: 配置项请参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/)。 #### watermarkOptions.parent * 类型: `string` * 默认值: `body` * 详情:添加水印的父元素选择器。 默认插入到 body 中,可以指定插入到页面的某个元素中。 ## Frontmatter ### watermark * 类型: `boolean | WatermarkOptions` * 详情: 当类型为 `boolean` 时,表示是否启用水印。 当类型为 `WatermarkOptions` 时,表示当前页面水印配置。 可以参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) 。 ```md --- watermark: width: 200 height: 200 content: Your content opacity: 0.5 --- ``` --- --- url: /contributing/index.md --- # 贡献指南 --- --- url: /demos/index.md --- # 案例 :::important 你可以随时通过 ==PR== 添加你的 文档 或 博客 到这个页面。 站点预览图片请放到 `docs/.vuepress/public/images/demos` 目录下。推荐使用远程链接,以便可以随时更新它。 图片请尽量使用 `.jpg` 格式,体积较大的请使用 [tinypng](https://tinypng.com/) 进行压缩。 ::: [前往 **Github Pull Request** 提交站点](https://github.com/pengzhanbo/vuepress-theme-plume/edit/main/docs/demos.md){.read-more} ## 文档 ## 博客 --- --- url: /faq/index.md --- # 常见问题 本文主要包含了使用主题的过程中可能会遇到的常见问题与解决方法。 如果您遇到任何问题,您可以先在以下内容中寻找是否有相关的问题和解决方法。 如果没有找到,您可以先通过 Github [Discussions](https://github.com/pengzhanbo/vuepress-theme-plume/discussions/new?category=q-a) 与我们讨论。 如果您确定某处确实存在问题,请在 Github [Open an issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new?assignees=pengzhanbo\&labels=bug\&projects=\&template=bug-report.zh-CN.yml\&title=%5BBug%5D), 在 Issue 中说明该问题的具体细节,如有必要,请尽量提供一个 最小重现包,我们会尽快解决。 ::: details 发起讨论或提出问题需要注意什么? 我们欢迎你发起讨论或提出任何问题,无论它是否简单,积极提问是好事。但请确保以下三点: 1. 你已经尝试搜索过相关文档; 2. 你在讨论中提供了详细的描述; 3. 你不是在问与 VuePress 无关的问题,也不是在寻求技术支持。 我们不会回答 “我如何在我自己的项目中单独使用主题的某个功能” 、“我怎么在我的自己项目中实现主题的某个功能” 这种 问题。 ::: ## 怎么更新主题? 你可以通过 `vp-update` 命令来更新主题。 `vp-update` 是 VuePress 官方维护的 CLI 工具,它可以帮助你检查项目内与 VuePress 相关的主题、插件等的 最新版本,并自动为你安装依赖。 复制以下命令到你的项目中运行: ::: npm-to ```sh npx vp-update ``` ::: ## 为什么更新主题版本后新的功能没有生效? 由于 VuePress 在启动开发服务时,全量编译源目录中的的 `markdown` 文件耗时较长,主题对 `markdown` 的编译进行了 缓存,以提高启动速度。主题更新后重启开发服务时,由于源目录中的 `markdown` 文件没有变化,跳过了编译直接使用缓存, 这会导致与 markdown 有关的新功能没有生效。 **只需要删除缓存文件,并重启即可**: 1. 方法一:直接删除 `.vuepress/.cache` 目录。 2. 方法二:在启动开发服务命令后面,添加 `--clean-cache` 参数: ```sh vuepress dev docs --clean-cache ``` ## 为什么修改主题插件的配置没有生效? 这个文件常见于修改 `plugins.markdownEnhance` 、`plugins.markdownPower` 、`plugins.markdownImage` 和 `plugins.markdownMath` 的配置。它与 [为什么更新主题版本后新的功能没有生效?](#为什么更新主题版本后新的功能没有生效) 的原因相同。因此 **只需要删除缓存文件,并重启即可**: 1. 方法一:直接删除 `.vuepress/.cache` 目录。 2. 方法二:在启动开发服务命令后面,添加 `--clean-cache` 参数: ```sh vuepress dev docs --clean-cache ``` ## 更新依赖后重启提示 `import "xxxx" not exist` 有时候更新主题以及相关依赖后,可能会存在 包管理器未能正确生成新的依赖树的问题,导致了 导入一些依赖时,提示找不到该依赖的错误。 这时候的 依赖锁定文件如 `package-lock.json` 或 `pnpm-lock.yaml` 已经被污染。 请直接删除 `package-lock.json` 或 `pnpm-lock.yaml` 等依赖锁定文件,以及删除 `node_modules` 目录,然后重新安装依赖。 --- --- url: /guide/api/client/index.md --- # 客户端 ## 使用 ```ts import { Layout } from 'vuepress-theme-plume/client' ``` ## 布局组件 * ``: 页面布局组件 * `` : 404 页面布局组件 ```ts import { Layout, NotFound } from 'vuepress-theme-plume/client' ``` ## 通用组件 * `` : 链接组件 * ``: 按钮组件 * ``: 图标组件 * ``: 徽标组件 * ``: 图片组件 * ``: 首页布局组件 更多其他组件请查看 [源代码](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/components) ```ts import VPButton from 'vuepress-theme-plume/components/VPButton.vue' import VPLink from 'vuepress-theme-plume/components/VPLink.vue' ``` ## 组合式 API ### `useDarkMode()` * 类型: `() => Ref` * 详情: 获取 是否是深色模式的响应式数据。 ```ts import { useDarkMode } from 'vuepress-theme-plume/composables' const isDark = useDarkMode() // 切换为深色模式 isDark.value = true // 切换为浅色模式 isDark.value = false ``` ### `useData()` * 类型: `() => Data` * 详情: 获取 主题 的各项响应式数据。 ```ts interface Data { // 主题配置 theme: ThemeLocaleDataRef // 当前页面数据 page: PageDataRef // 当前 页面 frontmatter frontmatter: PageFrontmatterRef> // 当前语言 lang: Ref // 站点数据 site: SiteLocaleDataRef // 是否是深色模式 isDark: Ref } ``` ```ts import { useData } from 'vuepress-theme-plume/composables' const { site, page, frontmatter, isDark, lang } = useData() // 当前页面标题 console.log(frontmatter.value.title) ``` ### `useLocalePostList()` * 类型: `() => Ref` * 详情: 获取 文章列表的响应式数据。 ```ts interface PostItem { path: string title: string excerpt: string tags: string[] sticky: boolean categoryList: CategoryItem[] createTime: string lang: string encrypt?: boolean } interface CategoryItem { type: string | number name: string } ``` ```ts import { useLocalePostList } from 'vuepress-theme-plume/composables' const postList = useLocalePostList() ``` ### 更多 其它 组合式 API 请查看 [源代码](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/composables) 。 --- --- url: /guide/api/node/index.md --- # Node ## 使用 ```ts import { plumeTheme } from 'vuepress-theme-plume' ``` ## `plumeTheme(options)` **options** : `PlumeThemeOptions` 主题配置函数。 查看 [主题配置](../config/theme.md) 了解更多。 ## `defineThemeConfig(options)` 主题配置帮助函数,用于在单独的 `plume.config.ts` 中使用。 查看 [主题配置文件](../config/intro.md#主题配置文件) 了解更多。 ## `defineNavbarConfig(options)` 主题导航栏配置类型帮助函数。 查看 [主题配置](../config/navbar.md) 了解更多。 ## `defineCollections(options)` **options:** `(ThemePostCollection | ThemeDocCollection)[]` 主题 collections 配置类型帮助函数 查看 [主题配置](../config/collection.md) 了解更多。 ## `defineCollection(options)` **options:** `ThemePostCollection | ThemeDocCollection` 主题 单个 collection 配置类型帮助函数 查看 [主题配置](../config/collection.md) 了解更多。 --- --- url: /guide/chart/chartjs/index.md --- # chart.js [chart.js]: https://www.chartjs.org/docs/latest/ ## 概述 主题支持在 文章中 嵌入由 [chart.js] 图表。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 你需要在你的项目中安装 [chart.js] 库。 ::: npm-to ```sh npm install chart.js ``` ::: 然后在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { chartjs: true, // [!code ++] }, }) }) ``` ## 语法 ````md ::: chartjs 标题 ```json { // 此处为图表配置 } ``` ::: ```` 图标配置请查看 [chart.js] 文档 。 ## 示例 ::: note 示例 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/chartjs.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ### 块状图 **输入:** **输出:** ### 气泡图 **输入:** **输出:** ### 折线图 **输入:** **输出:** ### 玫瑰图 **输入:** **输出:** ### 雷达图 **输入:** **输出:** ### 散点图 **输入:** **输出:** --- --- url: /guide/chart/echarts/index.md --- # ECharts ## 概述 主题支持在文章中嵌入 [ECharts](https://echarts.apache.org/zh/index.html) 图表。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 你需要在你的项目中安装 [ECharts](https://echarts.apache.org/zh/index.html) 库。 ::: npm-to ```sh npm install echarts ``` ::: 然后在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { echarts: true, // [!code ++] }, }) }) ``` ::: note 以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/echarts.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 语法 ### JSON 配置 如果你可以很轻松的生成数据,你可以直接通过一个 JSON 代码块来提供 Echarts 配置: ````md ::: echarts 标题 ```json { // 此处为 ECharts 图表配置 } ``` ::: ```` ### JavaScript 配置 如果你需要通过脚本来获取数据,你可以使用 js 和 javascript 的代码块。 我们将通过 `echarts` 变量暴露 Echarts 实例,并且你应该将 Echart 配置赋值给 `option` 变量。 同时,你也可以赋值 `width` 和 `height` 来设置图表大小。 ````md ::: echarts Title ```js const option = { // 此处为 ECharts 图表配置 } ``` ::: ```` :::tip 你可以使用顶级 `await` 和 `fetch` 来从网络请求中获取数据。 ::: 相关配置,详见 [ECharts 文档](https://echarts.apache.org/handbook/zh/get-started/) ## 高级 你可以在 [客户端配置文件](https://vuejs.press/zh/guide/configuration.html##使用脚本) 中导入并使用 `defineEchartsConfig` 来自定义 Echarts: ```ts import { defineEchartsConfig } from '@vuepress/plugin-markdown-chart/client' import { defineClientConfig } from 'vuepress/client' defineEchartsConfig({ options: { // 全局 Echarts 配置 }, setup: async () => { // Echarts 设置 // 例如: await import("echarts-wordcloud") }, }) export default defineClientConfig({ // ... }) ``` ## 示例 ### 线图 **输入:** :::: details 查看代码 :::: **输出:** ### 柱状图 **输入:** :::: details 查看代码 :::: **输出:** ### 饼图 **输入:** :::: details 查看代码 :::: **输出:** ### 散点图 **输入:** :::: details 查看代码 :::: **输出:** ### 极坐标图 **输入:** :::: details 查看代码 :::: **输出:** ### 烛台图 **输入:** :::: details 查看代码 :::: **输出:** ### 雷达图 **输入:** :::: details 查看代码 :::: **输出:** ### 热力图 **输入:** :::: details 查看代码 :::: **输出:** ### 树图 **输入:** :::: details 查看代码 :::: **输出:** ### 多图 **输入:** :::: details 查看代码 :::: **输出:** --- --- url: /guide/chart/flowchart/index.md --- # flowchart ## 概述 主题支持在 文章中 嵌入由 [flowchart](http://flowchart.js.org/) 。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 你需要在你的项目中安装 [flowchart.ts](http://flowchart.js.org/) 库。 ::: npm-to ```sh npm install flowchart.ts ``` ::: 然后在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { flowchart: true, // [!code ++] }, }) }) ``` ::: note 以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/flowchart.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 语法 ````md ```flow:preset ``` ```` 目前可用的预设: * vue (默认) * ant * pie ## 演示 ::: demo markdown title="Vue 主题" ````md ```flow st=>start: 开始|past:>http://www.google.com[blank] e=>end: 结束|future:>http://www.google.com op1=>operation: 操作1|past op2=>operation: 操作2|current sub1=>subroutine: 子程序|invalid cond=>condition: 是/否?|approved:>http://www.google.com c2=>condition: 判断2|rejected io=>inputoutput: 进行反思...|future st->op1(right)->cond cond(yes, right)->c2 cond(no)->sub1(left)->op1 c2(yes)->io->e c2(no)->op2->e ``` ```` ::: ::: demo markdown title="Ant 主题" ````md ```flow:ant st=>start: 开始|past:>http://www.google.com[blank] e=>end: 结束|future:>http://www.google.com op1=>operation: 操作1|past op2=>operation: 操作2|current sub1=>subroutine: 子程序|invalid cond=>condition: 是/否?|approved:>http://www.google.com c2=>condition: 判断2|rejected io=>inputoutput: 进行反思...|future st->op1(right)->cond cond(yes, right)->c2 cond(no)->sub1(left)->op1 c2(yes)->io->e c2(no)->op2->e ``` ```` ::: ::: demo markdown title="Pie 主题" ````md ```flow:pie st=>start: 开始|past:>http://www.google.com[blank] e=>end: 结束|future:>http://www.google.com op1=>operation: 操作1|past op2=>operation: 操作2|current sub1=>subroutine: 子程序|invalid cond=>condition: 是/否?|approved:>http://www.google.com c2=>condition: 判断2|rejected io=>inputoutput: 进行反思...|future st->op1(right)->cond cond(yes, right)->c2 cond(no)->sub1(left)->op1 c2(yes)->io->e c2(no)->op2->e ``` ```` ::: ## 流程图介绍 ### 节点类型 定义了结点形状。 #### 开始 & 结束 * `[Variable]->start: [Text]` 被用于流程开始的第一个节点。 默认文字为 `Start`. * `[Variable]->end: [Text]` 被用于流程结束的最后一个节点。 默认文字为 `End`. ::: demo markdown title="开始 & 结束" ````md ```flow st=>start: 开始 e=>end: 结束 st->e ``` ```` ::: #### 操作 `[Variable]->operation: [Text]` ::: demo markdown title="操作" ````md ```flow process=>operation: 操作 e=>end: 结束 process->e ``` ```` ::: #### 输入输出 `[Variable]->inputoutput: [Text]` :::demo markdown title="输入输出" ````md ```flow process=>inputoutput: 输入输出 e=>end: 结束 process->e ``` ```` ::: #### 子程序 `[Variable]->subroutine: [Text]` ::: demo markdown title="子程序" ````md ```flow process=>subroutine: 子程序 e=>end: 结束 process->e ``` ```` ::: #### 条件 * `[Variable]->condition: [Text]` * `[Variable]([yesText])->[Position]` * `[Variable]([noText])->[Position]` ::: demo markdown title="条件" ````md ```flow cond=>condition: 是否执行操作? process=>operation: 操作 e=>end: 结束 cond(yes)->process->e cond(no)->e ``` ```` ::: #### 平行 定义同时开始的多个程序。 * `[Variable]->parallel: [Text]` * `[Variable](path1, direction)->[Position]` * `[Variable](path1, direction)->[Position]` ::: demo markdown title="平行" ````md ```flow para=>parallel: 平行任务 process=>operation: 操作 e=>end: 结束 para(path1, bottom)->process->e para(path2)->e ``` ```` ::: ### 链接 连接方式在流程图中节点定义后描述,使用 `->` 指定一个节点之间的链接,例如 `nodeVar1->nodeVar2->nodeVar3` 流程可以被分开: ```md nodeVar1->nodeVar2 nodeVar2->nodeVar3 ``` 连接格式定义如下: `[([, [[([, ]` 在 `[]` 中的项是可选的。 ### 方向 以下方向可用,并定义了连接将从节点离开的方向。如果指定符不止一个,则总是最后一个。所有节点都有默认方向,这使其成为可选规范。`` 的可选值为: * `left` * `right` * `top` * `bottom` ### 节点特定说明符 每个节点变量都有可选的说明符,例如方向,有些变量有特殊的说明符,具体取决于下面定义的节点类型。在 `()` 中的变量名后添加说明符,并用`,` 分隔,例如 `nodeVar (spec1,spec2)`。 * **start** **operation** **inputoutput** **subroutine** 可选方向 `startVar()->nextNode` `operationVar()->nextNode` `inputoutputVar()->nextNode` `subroutineVar()->nextNode` * **condition** 必需指定 `yes` or `no` 可选方向 ```md conditionalVar(yes, )->nextNode1 conditionalVar(no, )->nextNode2 ``` * **parallel** 必需指定路径方向 `path1`, `path2`, 或 `path3` 可选方向 ```md parallelVar(path1, )->nextNode1 parallelVar(path2, )->nextNode2 parallelVar(path3, )->nextNode3 ``` ### 网址 可以使用 `:>` 运算符将外部链接添加到节点。 `[blank]` 指定打开新的页面 ```md st=>start: Start:>http://www.google.com[blank] e=>end: End:>http://www.yahoo.com ``` ### 建议 文本中可能不应该使用的符号: `=>`、`->`、 `:>`、`|`、`@>` 和 `:$` 如果要在流程图中强调特定路径,则可以另外定义它,如下所示: ``` st@>op1({"stroke":"Red"})@>cond({"stroke":"Red","stroke-width":6,"arrow-end":"classic-wide-long"})@>c2({"stroke":"Red"})@>op2({"stroke":"Red"})@>e({"stroke":"Red"}) ``` --- --- url: /guide/chart/markmap/index.md --- ## 概述 主题支持在 文章中 嵌入由 [markmap](https://markmap.js.org/) 。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 你需要在你的项目中安装 `markmap-lib`, `markmap-toolbar` and `markmap-view`: ::: npm-to ```sh npm i markmap-lib markmap-toolbar markmap-view ``` ::: 然后在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { markmap: true, // [!code ++] }, }) }) ``` ::: note 以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/markmap.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 语法 ````md ```markmap ``` ```` 支持通过 Frontmatter 语法进行配置。 ## 案例 ::: demo markdown title="markmap" `````md ````markmap --- markmap: colorFreezeLevel: 2 --- # markmap ## 链接 - - [GitHub](https://github.com/markmap/markmap) ## 功能 - 链接 - **强调** ~~删除线~~ *斜体* ==高亮== - 多行 文字 - `行内代码` - ```js console.log('code block'); ``` - Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$ - 现在我们可以通过 `maxWidth` 选项自动换行非常非常非常非常非常非常非常非常非常非常长的内容 ```` ````` ::: --- --- url: /guide/chart/mermaid/index.md --- # mermaid ## 概述 主题支持在 文章中 嵌入由 [Mermaid](https://mermaid.js.org/) 。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 你需要在你的项目中安装 [mermaid](https://mermaid.js.org/) 库。 ::: npm-to ```sh npm install mermaid ``` ::: 然后在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { mermaid: true, // [!code ++] }, }) }) ``` ::: note 以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/mermaid.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 语法 ````md ```mermaid ``` ```` 除了使用 mermaid 代码块,你也可以直接使用以下代码块: * class: `classDiagram` * c4c: `C4Context` * er: `erDiagram` * gantt: `gantt` * git-graph: `gitGraph` * journey: `journey` * mindmap: `mindmap` * pie: `pie` * quadrant: `quadrantChart` * requirement: `requirementDiagram` * sankey: `sankey-beta` * sequence: `sequenceDiagram` * state: `stateDiagram-v2` * timeline: `timeline` * xy: `xychart-beta` 你不需要再声明图表类型,也不需要缩进图表代码。 当图表支持设置标题时,你可以直接在代码块信息后添加标题: ````md ```sequence 代码标题 ``` ```` 配置文档详见 [Mermaid 文档](https://mermaid.js.org/) ## 高级 你可以在 [客户端配置文件](https://vuejs.press/zh/guide/configuration.html#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) 中导入并使用 `defineMermaidConfig` 来自定义 Mermaid 配置: ```ts import { defineMermaidConfig } from '@vuepress/plugin-markdown-chart/client' import { defineClientConfig } from 'vuepress/client' defineMermaidConfig({ // 在此设置 mermaid 选项 }) export default defineClientConfig({ // ... }) ``` ## 示例 ### 流程图 **输入:** **输出:** ### 循序图 **输入:** **输出:** ### 类图 **输入:** **输出:** ### 状态图 **输入:** **输出:** ### 关系图 **输入:** **输出:** ### 用户日记图 **输入:** **输出:** ### 甘特图 **输入:** :::: details 查看代码 :::: **输出:** ### 饼图 **输入:** ````md ```pie title What Voldemort doesn't have? "FRIENDS" : 2 "FAMILY" : 3 "NOSE" : 45 ``` ```` **输出:** ```pie title What Voldemort doesn't have? "FRIENDS" : 2 "FAMILY" : 3 "NOSE" : 45 ``` ### Git 图表 **输入:** :::: details 查看代码 :::: **输出:** ### C4C 图表 **输入:** :::: details 查看代码 :::: **输出:** ### 思维导图 **输入:** **输出:** ### 时序图 **输入:** **输出:** ### 桑基图 **输入:** :::: details 查看代码 :::: **输出:** ### 依赖图 **输入:** **输出:** ### 象限图 **输入:** **输出:** ### XY图 **输入:** **输出:** ### 块图 **输入:** **输出:** ### 复杂例子 **输入:** :::: details 查看代码 :::: **输出:** --- --- url: /guide/chart/plantuml/index.md --- ## 概述 主题支持在 文章中 嵌入由 [PlantUML](https://plantuml.com/) 。 该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。 ## 配置 主题默认不启用该功能。 在 `.vuepress/config.ts` 配置文件中,启用该功能: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { plantuml: true, // [!code ++] }, }) }) ``` ::: note 以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/plantuml.html), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 格式 你可以插入[plantuml](https://plantuml.com/) 支持的相同内容,例如: ```md @startuml 内容 @enduml ``` ## 示例 ::: demo markdown title="序列图" ```md @startuml Alice -> Bob: 认证请求 alt 成功情况 Bob -> Alice: 认证接受 else 某种失败情况 Bob -> Alice: 认证失败 group 我自己的标签 Alice -> Log : 开始记录攻击日志 loop 1000次 Alice -> Bob: DNS 攻击 end Alice -> Log : 结束记录攻击日志 end else 另一种失败 Bob -> Alice: 请重复 end @enduml ``` ::: ::: demo markdown title="用例图" ```md @startuml :Main Admin: as Admin (Use the application) as (Use) User -> (Start) User --> (Use) Admin ---> (Use) note right of Admin : This is an example. note right of (Use) A note can also be on several lines end note note "This note is connected\nto several objects." as N2 (Start) .. N2 N2 .. (Use) @enduml ``` ::: ::: demo markdown title="类图" ```md @startuml abstract class AbstractList abstract AbstractCollection interface List interface Collection List <|-- AbstractList Collection <|-- AbstractCollection Collection <|- List AbstractCollection <|- AbstractList AbstractList <|-- ArrayList class ArrayList { Object[] elementData size() } enum TimeUnit { DAYS HOURS MINUTES } annotation SuppressWarnings annotation Annotation { annotation with members String foo() String bar() } @enduml ``` ::: ::: demo markdown title="活动图" ```md @startuml start :ClickServlet.handleRequest(); :new page; if (Page.onSecurityCheck) then (true) :Page.onInit(); if (isForward?) then (no) :Process controls; if (continue processing?) then (no) stop endif if (isPost?) then (yes) :Page.onPost(); else (no) :Page.onGet(); endif :Page.onRender(); endif else (false) endif if (do redirect?) then (yes) :redirect process; else if (do forward?) then (yes) :Forward request; else (no) :Render page template; endif endif stop @enduml ``` ::: ::: demo markdown title="组件图" ```md @startuml package "Some Group" { HTTP - [First Component] [Another Component] } node "Other Groups" { FTP - [Second Component] [First Component] --> FTP } cloud { [Example 1] } database "MySql" { folder "This is my folder" { [Folder 3] } frame "Foo" { [Frame 4] } } [Another Component] --> [Example 1] [Example 1] --> [Folder 3] [Folder 3] --> [Frame 4] @enduml ``` ::: ::: demo markdown title="状态图" ```md @startuml state start1 <> state choice1 <> state fork1 <> state join2 <> state end3 <> [*] --> choice1 : from start\nto choice start1 --> choice1 : from start stereo\nto choice choice1 --> fork1 : from choice\nto fork choice1 --> join2 : from choice\nto join choice1 --> end3 : from choice\nto end stereo fork1 ---> State1 : from fork\nto state fork1 --> State2 : from fork\nto state State2 --> join2 : from state\nto join State1 --> [*] : from state\nto end join2 --> [*] : from join\nto end @enduml ``` ::: ::: demo markdown title="对象图" ```md @startuml object London object Washington object Berlin object NewYork map CapitalCity { UK *-> London USA *--> Washington Germany *---> Berlin } NewYork --> CapitalCity::USA @enduml ``` ::: ::: demo markdown title="部署图" ```md @startuml node node1 node node2 node node3 node node4 node node5 node1 -- node2 : label1 node1 .. node3 : label2 node1 ~~ node4 : label3 node1 == node5 @enduml ``` ::: ::: demo markdown title="时序图" ```md @startuml scale 5 as 150 pixels clock clk with period 1 binary "启用" as en binary "读/写" as rw binary "数据有效" as dv concise "数据总线" as db concise "地址总线" as addr @6 as :write_beg @10 as :write_end @15 as :read_beg @19 as :read_end @0 en is low db is "0x0" addr is "0x03f" rw is low dv is 0 @:write_beg-3 en is high @:write_beg-2 db is "0xDEADBEEF" @:write_beg-1 dv is 1 @:write_beg rw is high @:write_end rw is low dv is low @:write_end+1 rw is low db is "0x0" addr is "0x23" @12 dv is high @13 db is "0xFFFF" @20 en is low dv is low @21 db is "0x0" highlight :write_beg to :write_end #Gold:写 highlight :read_beg to :read_end #lightBlue:读 db@:write_beg-1 <-> @:write_end : 设置时间 db@:write_beg-1 -> addr@:write_end+1 : 保持 @enduml ``` ::: ::: demo markdown title="正则图" ```md @startregex /([\s\S]+)<\/style> @endregex ``` ::: ::: demo markdown title="网络图" ```md @startuml nwdiag { network dmz { address = "210.x.x.x/24" web01 [address = "210.x.x.1"]; web02 [address = "210.x.x.2"]; } network internal { address = "172.x.x.x/24"; web01 [address = "172.x.x.1"]; web02 [address = "172.x.x.2"]; db01; db02; } } @enduml ``` ::: ::: demo markdown title="图形界面" ```md @startsalt {+ {/ 通用 | 全屏 | 行为 | 保存 } { { 图片打开模式: | ^智能模式^ } [X] 缩放时平滑显示图片 [X] 图片删除确认 [ ] 显示隐藏图片 } [关闭] } @endsalt ``` ::: ::: demo markdown title="架构图" ```md @startuml skinparam rectangle<> { roundCorner 25 } sprite $bProcess jar:archimate/business-process sprite $aService jar:archimate/application-service sprite $aComponent jar:archimate/application-component rectangle "Handle claim" as HC <<$bProcess>><> #Business rectangle "Capture Information" as CI <<$bProcess>><> #Business rectangle "Notify\nAdditional Stakeholders" as NAS <<$bProcess>><> #Business rectangle "Validate" as V <<$bProcess>><> #Business rectangle "Investigate" as I <<$bProcess>><> #Business rectangle "Pay" as P <<$bProcess>><> #Business HC *-down- CI HC *-down- NAS HC *-down- V HC *-down- I HC *-down- P CI -right->> NAS NAS -right->> V V -right->> I I -right->> P rectangle "Scanning" as scanning <<$aService>><> #Application rectangle "Customer admnistration" as customerAdministration <<$aService>><> #Application rectangle "Claims admnistration" as claimsAdministration <<$aService>><> #Application rectangle Printing <<$aService>><> #Application rectangle Payment <<$aService>><> #Application scanning -up-> CI customerAdministration -up-> CI claimsAdministration -up-> NAS claimsAdministration -up-> V claimsAdministration -up-> I Payment -up-> P Printing -up-> V Printing -up-> P rectangle "Document\nManagement\nSystem" as DMS <<$aComponent>> #Application rectangle "General\nCRM\nSystem" as CRM <<$aComponent>> #Application rectangle "Home & Away\nPolicy\nAdministration" as HAPA <<$aComponent>> #Application rectangle "Home & Away\nFinancial\nAdministration" as HFPA <<$aComponent>> #Application DMS .up.|> scanning DMS .up.|> Printing CRM .up.|> customerAdministration HAPA .up.|> claimsAdministration HFPA .up.|> Payment legend left Example from the "Archisurance case study" (OpenGroup). See ==== <$bProcess> :business process ==== <$aService> : application service ==== <$aComponent> : application component endlegend @enduml ``` ::: ::: demo markdown title="甘特图" ```md @startgantt Project starts the 2020-12-01 [Task1] requires 10 days sunday are closed note bottom memo1 ... memo2 ... explanations1 ... explanations2 ... end note [Task2] requires 20 days [Task2] starts 10 days after [Task1]'s end -- Separator title -- [M1] happens on 5 days after [Task1]'s end -- end -- @endgantt ``` ::: ::: demo markdown title="思维导图" ```md @startmindmap caption figure 1 title My super title * <&flag>Debian ** <&globe>Ubuntu *** Linux Mint *** Kubuntu *** Lubuntu *** KDE Neon ** <&graph>LMDE ** <&pulse>SolydXK ** <&people>SteamOS ** <&star>Raspbian with a very long name *** Raspmbc => OSMC *** Raspyfi => Volumio header My super header endheader center footer My super footer legend right Short legend endlegend @endmindmap ``` ::: ::: demo markdown title="工作分解结构图" ```md @startwbs + New Job ++ Decide on Job Requirements +++ Identity gaps +++ Review JDs ++++ Sign-Up for courses ++++ Volunteer ++++ Reading ++- Checklist +++- Responsibilities +++- Location ++ CV Upload Done +++ CV Updated ++++ Spelling & Grammar ++++ Check dates ---- Skills +++ Recruitment sites chosen @endwbs ``` ::: ::: demo markdown title="JSON" ```md @startjson #highlight "lastName" #highlight "address" / "city" #highlight "phoneNumbers" / "0" / "number" { "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 28, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": [], "spouse": null } @endjson ``` ::: ::: demo markdown title="YAML" ```md @startyaml doe: "a deer, a female deer" ray: "a drop of golden sun" pi: 3.14159 xmas: true french-hens: 3 calling-birds: - huey - dewey - louie - fred xmas-fifth-day: calling-birds: four french-hens: 3 golden-rings: 5 partridges: count: 1 location: "a pear tree" turtle-doves: two @endyaml ``` ::: --- --- url: /guide/code/code-pen/index.md --- # Code Pen 主题支持在 Markdown 文件中嵌入 [CodePen](https://codepen.io/)。 ## 配置 此功能默认不启用,你可以在配置文件中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { codepen: true, // [!code highlight] }, }) }) ``` ## 语法 简单语法: ```md @[codepen](user/slash) ``` 更多选项支持: ```md @[codepen preview editable tab="css,result" theme="dark" height="500px" width="100%"](user/slash) ``` * `preview`: 是否渲染为预览模式 * `editable`: 是否可编辑 * `tab`: 默认显示的标签, 默认为 `result`,多个使用 `,` 分隔 * `theme`: 主题, 可选值 `dark` 和 `light` * `height`: 容器高度, 默认为 `400px` * `width`: 容器宽度, 默认为 `100%` * `user`: CodePen 用户名 * `slash`: CodePen 代码文件名 ## 示例 输入: ```md @[codepen](leimapapa/RwOZQOW) ``` 输出: @[codepen](leimapapa/RwOZQOW) **预览模式:** 输入: ```md @[codepen preview](leimapapa/RwOZQOW) ``` 输出: @[codepen preview](leimapapa/RwOZQOW) **编辑模式:** 输入: ```md @[codepen editable tab="html,result"](leimapapa/RwOZQOW) ``` 输出: @[codepen editable tab="html,result"](leimapapa/RwOZQOW) --- --- url: /guide/code/code-sandbox/index.md --- # Code Sandbox 主题支持在 Markdown 文件中嵌入 [Code Sandbox](https://codesandbox.io)。 ## 配置 此功能默认不启用,你可以在配置文件中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { codesandbox: true, // [!code highlight] }, }) }) ``` ## 语法 ### 简单语法 将 Code Sandbox 嵌入到页面中 ```md @[codesandbox](id) ``` 使用 Code Sandbox 跳转按钮 ```md @[codesandbox button](workspace/id) ``` ### 更多选项 ```md @[codesanbox title="xxx" layout="Editor+Preview" height="500px" navbar="false" console](id#filepath) ``` * `id`: Code Sandbox ID * `title`: Code Sandbox 标题 * `layout`: 代码预览布局 可选值: `Preview`, `Editor`, `Editor+Preview` * `height`: 代码预览高度 * `navbar`: 是否显示导航栏,默认为 true * `console`: 是否显示控制台,默认为 false * `filepath`: 文件路径 ## 示例 codeSandbox 跳转按钮: ```md @[codesandbox button](reaction/5wyzu) ``` 输出: @[codesandbox button](reaction/5wyzu) codeSandbox 内嵌到页面中: ```md @[codesandbox](5wyzu) ``` 输出: @[codesandbox](5wyzu) --- --- url: /guide/code/copy-code/index.md --- # 代码复制 ## 概述 该功能由 [@vuepress/plugin-copy-code](https://ecosystem.vuejs.press/zh/plugins/features/copy-code.html) 提供支持。 主题默认启用了代码复制功能。支持 一键复制 在 文章中 展示的代码。 默认情况下, 主题会为每一个 代码块 添加一个复制按钮。该按钮仅在桌面端显示。 当鼠标悬停在 代码块 上时,在右上角会出现一个复制按钮。 ## 配置 在 `.vuepress/config.ts` 配置文件中,修改 代码复制的行为: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ // copyCode: false // 禁用代码复制 copyCode: { // ...更多配置 } }) }) ``` ### showInMobile * **类型:** `boolean` * **默认值:** `false` 是否在移动端显示复制按钮。 ### ignoreSelector * **类型:** `string | string[]` * **默认值:** `[]` 代码块中的元素选择器,用于在复制时忽略相关元素。 例如: `['.token.comment']` 将忽略代码块中类名为 `.token.comment` 的节点 (这会在 prismjs 中忽略注释)。 ### inlineSelector * **类型:** `string | string[] | boolean` * **默认值:** `false` 是否在双击时复制行内代码内容。 `boolean`: 是否在双击时复制行内代码内容。 `string[] | string`: 选择器,表示需要复制的行内代码内容。 ### transform * **类型:** `(preElement: HTMLPreElement) => void` * **默认值:** `null` 一个转换器,用于在复制之前对 `
` 中代码块内容进行修改。该选项仅在使用 `useCopyCode()` 时有效。

## 组合式 API

该功能的组合式 API 可以在 `.vuepress/client.ts` 中配置:

```ts title=".vuepress/client.ts"
import { defineClientConfig } from '@vuepress/client'
import { useCopyCode } from '@vuepress/plugin-copy-code/client'

export default defineClientConfig({
  setup() {
    useCopyCode({
      // ...
    })
  },
})
```

### 示例

代码复制时,添加 copyright 信息

```ts title=".vuepress/client.ts"
import { defineClientConfig } from '@vuepress/client'
import { useCopyCode } from '@vuepress/plugin-copy-code/client'

export default defineClientConfig({
  setup() {
    useCopyCode({
      transform: (preElement) => {
        // 插入版权信息
        pre.innerHTML += `\n Copied by vuepress-theme-plume`
      },
    })
  },
})
```

---

---
url: /guide/code/features/index.md
---
# 特性支持
主题在代码高亮功能上,进一步支持了更多的特性,它们能够帮助你的代码块更加具备表达力。

## 代码块标题 

在 \`\`\` \[lang] 之后添加 `title="xxxx"` ,可以为当前代码块添加标题

**输入:**

````md {1}
```json title="package.json"
{
  "name": "vuepress-theme-plume"
}
```
````

**输出:**

```json title="package.json"
{
  "name": "vuepress-theme-plume"
}
```

## 代码行号

主题默认显示代码行号,它通过 `codeHighlighter.line-numbers` 来控制。

```ts title=".vuepress/config.ts"
export default defineUserConfig({
  theme: plumeTheme({
    codeHighlighter: {
      lineNumbers: true, // [!code ++]
    }
  })
})
```

你还可以通过 `:line-numbers` / `:no-line-numbers` 来控制当前代码块是否显示代码行号。
还可以通过在 `:line-numbers` 之后添加 `=` 来自定义起始行号,例如 `:line-numbers=2` 表示代码块中的行号从 `2` 开始。

**输入:**

````
```ts:line-numbers
// 启用行号
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```

```ts:no-line-numbers
// 行号已禁用
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```

```ts:line-numbers=2
// 行号已启用,并从 2 开始
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```
````

**输出:**

```ts:line-numbers
// 启用行号
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```

```ts:no-line-numbers
// 行号已禁用
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```

```ts:line-numbers=2
// 行号已启用,并从 2 开始
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```

## 在代码块中实现行高亮

在 `[lang]` 之后紧跟随 `{xxxx}` ,可以实现行高亮,其中 `xxx` 表示要高亮的行号。

**输入:**

````
```js{4}
export default {
  data () {
    return {
      msg: 'Highlighted!'
    }
  }
}
```
````

**输出:**

```js{4}
export default {
  data () {
    return {
      msg: 'Highlighted!'
    }
  }
}
```

除了单行之外,还可以指定多个单行、多行,或两者均指定:

* 多行:例如 `{5-8}`、`{3-10}`、`{10-17}`
* 多个单行:例如 `{4,7,9}`
* 多行与单行:例如 `{4,7-13,16,23-27,40}`

**输入:**

````
```js{1,4,6-8}
export default { // Highlighted
  data () {
    return {
      msg: `Highlighted!
      This line isn't highlighted,
      but this and the next 2 are.`,
      motd: 'VitePress is awesome',
      lorem: 'ipsum'
    }
  }
}
```
````

**输出:**

```js{1,4,6-8}
export default { // Highlighted
  data () {
    return {
      msg: `Highlighted!
      This line isn't highlighted,
      but this and the next 2 are.`,
      motd: 'VitePress is awesome',
      lorem: 'ipsum'
    }
  }
}
```

也可以使用 `// [!code highlight]` 注释实现行高亮。

**输入:**

````
```js
export default {
  data () {
    return {
      msg: 'Highlighted!' // [\!code highlight]
    }
  }
}
```
````

**输出:**

```js
export default {
  data() {
    return {
      msg: 'Highlighted!' // [!code highlight]
    }
  }
}
```

## 代码块中聚焦

在某一行上添加 `// [!code focus]` 注释将聚焦它并模糊代码的其他部分。

此外,可以使用 `// [!code focus:]` 定义要聚焦的行数。

**输入:**

````
```js
export default {
  data () {
    return {
      msg: 'Focused!' // [\!code focus]
    }
  }
}
```
````

**输出:**

```js
export default {
  data() {
    return {
      msg: 'Focused!' // [!code focus]
    }
  }
}
```

::: tip 在不同的语言代码块中,应该使用该语言的有效的行注释语法
比如在 bash 代码块中,应该使用 `# [!code focus]`

````md
```bash
mkdir hello && cd hello  # [\!code focus]
pnpm install
```
````

```bash
mkdir hello && cd hello  # [!code focus]
pnpm install
```

:::

## 代码块中的颜色差异

在某一行添加 `// [!code --]` 或 `// [!code ++]` 注释将会为该行创建 diff,同时保留代码块的颜色。

**输入:**

````
```js
export default {
  data () {
    return {
      error: 'Removed', // [\!code --]
      warning: 'Added' // [\!code ++]
    }
  }
}
```
````

**输出:**

```js
export default {
  data() {
    return {
      error: 'Removed', // [!code --]
      warning: 'Added' // [!code ++]
    }
  }
}
```

::: tip 在不同的语言代码块中,应该使用该语言的有效的行注释语法
比如在 bash 代码块中,应该使用 `# [!code ++]`

````md
```bash
mkdir hello && cd hello  # [\!code ++]
```
````

```bash
mkdir hello && cd hello  # [!code ++]
```

:::

## 高亮“错误”和“警告”

在某一行添加 `// [!code warning]` 或 `// [!code error]` 注释将会为该行相应的着色。

**输入:**

````
```js
export default {
  data () {
    return {
      error: 'Error', // [\!code error]
      warning: 'Warning' // [\!code warning]
    }
  }
}
```
````

**输出:**

```js
export default {
  data() {
    return {
      error: 'Error', // [!code error]
      warning: 'Warning' // [!code warning]
    }
  }
}
```

::: tip 在不同的语言代码块中,应该使用该语言的有效的行注释语法
比如在 bash 代码块中,应该使用 `# [!code warning]`

````md
```bash
mkdir hello && cd hello  # [\!code warning]
```
````

```bash
mkdir hello && cd hello  # [!code warning]
```

:::

## 代码块中 词高亮

**输入:**

````
```ts
export function foo() { // [\!code word:Hello]
  const msg = 'Hello World'
  console.log(msg) // prints Hello World
}
```
````

**输出:**

```ts
export function foo() { // [!code word:Hello]
  const msg = 'Hello World'
  console.log(msg) // prints Hello World
}
```

你还可以指定高亮显示的次数,例如 `[!code word:options:2]` 会高亮显示近两个 `options`。

**输入:**

````
```ts
// [\!code word:options:2]
const options = { foo: 'bar' }
options.foo = 'baz'
console.log(options.foo) // 这个不会被高亮显示
```
````

**输出:**

```ts
// [!code word:options:2]
const options = { foo: 'bar' }
options.foo = 'baz'
console.log(options.foo) // 这个不会被高亮显示
```

:::tip 在不同的语言代码块中,应该使用该语言的有效的行注释语法
比如在 bash 代码块中,应该使用 `# [!code word:hello]`

````md
```bash
mkdir hello && cd hello  # [\!code word:hello]
```
````

```bash
mkdir hello && cd hello  # [!code word:hello]
```

:::

## 代码块中的 空白符

将空白字符(Tab 和空格)渲染为可见状态。

在 代码块 后面添加 `:whitespace`。

还可以在 `codeHighlighter` 中全局启用 `whitespace` 功能:

```ts title=".vuepress/config.ts"
export default defineUserConfig({
  theme: plumeTheme({
    codeHighlighter: {
      whitespace: true, // [!code ++]
    }
  })
})
```

全局启用时,可以使用 `:no-whitespace` 来单独为某一代码块禁用 `whitespace` 功能。

## 折叠代码块

有时候,代码块会很长,对于阅读其它部分的内容时,会显得很麻烦,影响阅读体验,这时候可以折叠代码块。

在 代码块 后面添加 `:collapsed-lines`,即可折叠代码块,默认从第 15 行开始折叠。

**输入:**

````txt
```css :collapsed-lines
html {
  margin: 0;
  background: black;
  height: 100%;
}

... more code
```
````

**输出:**

```css :collapsed-lines
html {
  margin: 0;
  background: black;
  height: 100%;
}

body {
  margin: 0;
  width: 100%;
  height: inherit;
}

/* the three main rows going down the page */

body > div {
  height: 25%;
}

.thumb {
  float: left;
  width: 25%;
  height: 100%;
  object-fit: cover;
}

.main {
  display: none;
}

.blowup {
  display: block;
  position: absolute;
  object-fit: contain;
  object-position: center;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2000;
}

.darken {
  opacity: 0.4;
}
```

还可以指定起始折叠行。`:collapsed-lines=10` 表示从第十行开始折叠。

**输入:**

````txt
```css :collapsed-lines=10
html {
  margin: 0;
  background: black;
  height: 100%;
}

... more code
```
````

**输出:**

```css :collapsed-lines=10
html {
  margin: 0;
  background: black;
  height: 100%;
}

body {
  margin: 0;
  width: 100%;
  height: inherit;
}

/* the three main rows going down the page */

body > div {
  height: 25%;
}

.thumb {
  float: left;
  width: 25%;
  height: 100%;
  object-fit: cover;
}

.main {
  display: none;
}

.blowup {
  display: block;
  position: absolute;
  object-fit: contain;
  object-position: center;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2000;
}

.darken {
  opacity: 0.4;
}
```

还可以在 `codeHighlighter` 中全局启用 `collapsed-lines` 功能:

::: code-tabs
@tab .vuepress/config.ts

```ts
export default defineUserConfig({
  theme: plumeTheme({
    codeHighlighter: {
      collapsedLines: true // [!code ++]
    }
  })
})
```

:::

全局启用时,可以使用 `:no-collapsed-lines` 来单独为某一代码块禁用 `collapsed-lines` 功能。

---

---
url: /guide/code/group/index.md
---
# 代码分组
## 概述

代码组(Code Tabs)是 主题 中用于并排展示多个相关代码片段的强大功能。
通过标签页形式组织代码,您可以清晰对比不同技术栈、配置方案或语言版本的实现差异。

## 基础语法

### 多代码块分组

使用代码组语法将多个代码块组织在同一标签容器中:

**输入:**

````md
::: code-tabs
@tab config.js
```js
/**
 * @type {import('vuepress').UserConfig}
 */
const config = {
  // ..
}

export default config
```

@tab config.ts
```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
  // ..
}

export default config
```
:::
````

**输出:**

::: code-tabs
@tab config.js

```js
/**
 * @type {import('vuepress').UserConfig}
 */
const config = {
  // ..
}

export default config
```

@tab config.ts

```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
  // ..
}

export default config
```

:::

### 设置默认激活标签

通过 `@tab:active` 语法指定默认显示的代码标签:

**输入:**

````md
::: code-tabs
@tab config.js
```js
/**
 * @type {import('vuepress').UserConfig}
 */
const config = {
  // ..
}

export default config
```

@tab:active config.ts 
```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
  // ..
}

export default config
```
:::
````

**输出:**

::: code-tabs
@tab config.js

```js
/**
 * @type {import('vuepress').UserConfig}
 */
const config = {
  // ..
}

export default config
```

@tab:active config.ts

```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
  // ..
}

export default config
```

:::

## 标签图标支持 

主题为代码组标签提供智能图标显示功能,基于标签标题自动匹配相关技术图标。

### 自动图标识别

主题内置了主流技术和语言的图标映射:

**输入:**

````md
::: code-tabs
@tab pnpm

```sh
pnpm i
```

@tab yarn

```sh
yarn
```

@tab npm

```sh
npm install
```

:::
````

**输出:**

::: code-tabs
@tab pnpm

```sh
pnpm i
```

@tab yarn

```sh
yarn
```

@tab npm

```sh
npm install
```

:::

### 支持的图标类别

主题默认适配以下技术栈的图标:

* **运行环境**:Node.js、Deno、Bun
* **包管理器**:pnpm、yarn、npm
* **前端框架**:Vue、React、Angular、Svelte、Solid、Next.js、Nuxt
* **编程语言**:TypeScript、JavaScript、C、C++、Java、Python、Rust、Kotlin、Swift、Go

::: info 图标支持反馈
如果您使用的技术栈未能正确显示图标,欢迎提交 [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new) 告知我们,我们将尽快添加相关图标支持。
:::

## 图标配置选项

通过 `markdown.codeTabs` 配置项精确控制图标显示行为:

```ts
export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      codeTabs: {
        icon: true, // 启用图标功能
      }
    },
  })
})
```

配置接口定义:

```ts
export interface CodeTabsOptions {
  icon?: boolean | {
    named?: false | string[]
    extensions?: false | string[]
  }
}
```

### 配置示例

**禁用所有图标**:

```ts
export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      codeTabs: {
        icon: false
      }
    }
  })
})
```

**仅显示指定技术栈图标**:

```ts
export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      codeTabs: {
        icon: {
          named: ['pnpm', 'yarn', 'npm'], // 仅匹配这些技术名称
          extensions: false // 禁用文件扩展名匹配
        }
      }
    }
  })
})
```

**配置说明**:

* `named`:精确匹配技术名称(如 `pnpm`、`vue`、`react`)
* `extensions`:匹配文件扩展名(如 `.ts`、`.js`、`.py`)
* 设置为 `false` 禁用对应匹配方式
* 空数组使用默认匹配规则
* 字符串匹配区分大小写

## 性能优化说明

::: tip 图标体积优化
您无需担心图标资源对构建体积的影响。代码组图标基于 Iconify 体系实现,配合本地安装的 `@iconify/json` 包,主题会自动:

* 解析并提取实际使用的图标数据
* 生成优化的本地图标资源
* 确保相同图标仅打包一次

每个彩色图标的平均体积仅为 1-2KB,即使大量使用不同图标,对最终构建体积的影响也微乎其微。
:::

通过合理的配置和使用,代码组功能能够显著提升技术文档的可读性和用户体验,帮助读者更高效地理解不同技术方案间的差异。

---

---
url: /guide/code/import/index.md
---
# 导入代码
## 概述

导入代码 可以让你在 md 文件中 导入另一个文件的 代码,并为其高亮显示。

它可以帮助你在文章中引用其他文件的代码,避免编写重复的代码。

## 语法

你可以使用下面的语法,从文件中导入代码块:

**输入:**

```md
@[code](../snippet/snippet-1.js)
```

**输出:**

@[code](../../snippet/snippet-1.js)

如果你只想导入这个文件的一部分:

```md

@[code{1-10}](../snippet/snippet-1.js)
```

代码语言会根据文件扩展名进行推断,但我们建议你显式指定:

```md

@[code js](../snippet/snippet-1.js)


@[code js{2,4-5}](../foo.js)
```

---

---
url: /guide/code/intro/index.md
---
# 介绍
## 概述

主题 使用 [Shiki](https://shiki.style/) 在 Markdown 代码块实现语法高亮。

::: important 重要变更 

从 ==1.0.0-rc.136== 版本开始,主题已将代码高亮插件从主题内部实现的 `@vuepress-plume/plugin-shikiji` 迁移
到了 [vuepress ecosystem](https://github.com/vuepress/ecosystem) 提供的 [@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html)。

*(无需担心变化太大,我也是 `@vuepress/plugin-shiki` 的主要开发者之一,它实现了与主题原插件一致的功能)*

其中涉及到部分配置项需要调整变更:

* `languages` 配置变更为 `langs` 选项。无需再手动添加你所使用的语言,插件将会自动识别并按需加载语言包。
* `themes` 配置变更为:
  * 当使用单主题配置时,使用 `theme` 配置代码块主题
  * 当使用双主题配置时,使用 `themes` 配置代码块主题。

:::

## 语言

[Shiki](https://shiki.style/) 支持 超过 190+ 种语言,
你可以在 [languages](https://shiki.style/languages) 查看所有支持的语言列表。

你可以通过以下语法为你使用的 语言所编写的代码 实现高亮效果:

````md
``` [lang]

```
````

其中,`[lang]` 为你使用的语言。

示例:

````md
// [!code word:js]
``` js
const a = 1
console.log(a)
```
````

```js
const a = 1
console.log(a)
```

## 高亮主题

[Shiki](https://shiki.style/) 支持 超过 40+ 种高亮主题。

你可以在 [Themes](https://shiki.style/themes) 找到所有支持的主题列表,根据个人的喜欢自定义
高亮主题。

Theme Plume 默认为 代码块使用的主题配置:

```ts
export default defineUserConfig({
  theme: plumeTheme({
    codeHighlighter: {
      themes: { light: 'vitesse-light', dark: 'vitesse-dark' }, // [!code highlight]
    }
  })
})
```

默认配置支持在 亮色/暗色 模式分别使用 `vitesse-light`/`vitesse-dark` 主题。

## 更多支持

得益于 [Shiki](https://shiki.style/) 的强大能力,Theme Plume 还为 代码块
提供了 更多的 [特性支持](./features.md),它们让 代码块具备更强的表达能力。

同时,为了方便 更好的 完成 代码演示,Theme Plume 还提供了嵌入 [CodePen](../repl/codepen.md),
[Js Fiddle](../repl/jsFiddle.md),[Code Sandbox](../repl/codeSandbox.md),
[Replit](../repl/replit.md) 的语法支持,你可以很方便的嵌入代码演示。

## 示例

---

---
url: /guide/code/jsfiddle/index.md
---
# Js Fiddle
主题支持在 Markdown 文件中嵌入 [JS Fiddle](https://jsfiddle.net/)。

## 配置

此功能默认不启用,你可以在配置文件中启用它。

```ts title=".vuepress/config.ts"
export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      jsfiddle: true, // [!code highlight]
    },
  })
})
```

## 语法

### 简单语法

```md
@[jsfiddle](user/id)
```

### 更多选项

```md
@[jsfiddle theme="dark" tab="js,css,html,result" height="500px"](user/id)
```

* `user`: 用户
* `id`: jsfiddle id
* `theme`: 主题模式, 可选值: `"light" | "dark"`
* `tab`: 选项卡, 可选值:`"js" | "css" | "html" | "result"`, 多个用 `","` 分割,
  顺序将决定选项卡的排序,默认为 `js,css,html,result`
* `height`: 高度

## 示例

输入:

```md
@[jsfiddle](pengzhanbo/1xbwz2p9)
```

输出:

@[jsfiddle](pengzhanbo/1xbwz2p9)

输入:

```md
@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)
```

输出:

@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)

---

---
url: /guide/code/replit/index.md
---
# Replit
\~~主题支持在 Markdown 文件中嵌入 [Replit](https://replit.com/)。~~

## 配置

此功能默认不启用,你可以在配置文件中启用它。

```ts title=".vuepress/config.ts"
export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      replit: true, // [!code ++]
    },
  })
})
```

## 语法

简单的语法

```md
@[replit](user/repl-name)
```

更多选项

```md
@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath)
```

* `title`: 标题
* `width`: 容器宽度
* `height`: 容器高度
* `theme`: 主题, 可选值 `dark` 和 `light`
* `user`: Replit 用户名
* `repl-name`: Replit repl 名称
* `filepath`: Replit 默认打开的文件路径

## 示例

输入:

```md
@[replit](@TechPandaPro/Cursor-Hangout#package.json)
```

输出:

@[replit](@TechPandaPro/Cursor-Hangout#package.json)

---

---
url: /guide/collection/index.md
---
# 集合
## 概述

\==Collections(集合)== 是主题中用于组织和管理文档的核心概念。
每个集合指向源目录下的特定文件夹,将其中的所有 Markdown 文件作为一个逻辑单元进行管理。

通过灵活的集合配置,您可以轻松构建多种内容体系:

* **博客** - 个人随笔与技术分享
* **专栏** - 专题系列文章
* **使用手册** - 产品使用文档
* **笔记** - 学习笔记与知识整理
* **产品文档** - 完整的项目文档
* **知识库** - 团队知识管理体系
* 更多...

## 创建集合

一个普通的 VuePress 静态站点的文件结构大致如下:

:::file-tree

* my-site
  * docs # 源目录
    * .vuepress/
    * …
    * README.md # 首页
  * package.json

:::

当你想要添加一个用于 **博客** 的集合:

:::: steps

* **创建 blog 目录**

  :::file-tree

  * docs
    * blog
      * post-1.md
      * post-2.md
      * …
    * …
      :::

* **在主题配置中添加类型为 `post` 的集合**

  将 `dir` 配置项指向 `blog` 目录

  ::: code-tabs#config:

  @tab .vuepress/config.ts

  ```ts twoslash
  import { defineUserConfig } from 'vuepress'
  import { plumeTheme } from 'vuepress-theme-plume'

  export default defineUserConfig({
    theme: plumeTheme({
      collections: [
        // [!code word:type]
        { type: 'post', dir: 'blog', title: '博客' } // [!code word:dir]
      ]
    })
  })
  ```

  @tab .vuepress/plume.config.ts

  ```ts twoslash
  import { defineThemeConfig } from 'vuepress-theme-plume'

  export default defineThemeConfig({
    collections: [
      // [!code word:type]
      { type: 'post', dir: 'blog', title: '博客' } // [!code word:dir]
    ]
  })
  ```

  :::

  `blog` 目录下的 markdown 文章,在 post 集合中读取为文章列表,并生成列表页、分类页、标签页等页面。

* **完成**
  ::::

在这其中,需要注意的是:

* **dir 配置项**

  集合配置中的 `dir` 指向源目录下的某个文件夹,该文件夹下的所有 markdown 文件都将归属于该集合。

* **type 配置项**

  集合配置中的 `type` 指定了集合的类型。

  集合的类型决定了该集合下的文档将会提供哪些功能,当前主题支持的类型如下:

  * `post`:表示碎片化文章的集合,文章之间不存在关联关系或弱关联关系。
  * `doc`: 表示结构化文章的集合,文章之间存在结构化的强关联关系,作为一个整体。

* **title 配置项**

  集合配置中的 `title` 指定了集合的名称。

  在主题中,`title` 用于页面的面包屑导航中。

## 集合类型

集合的类型决定了该集合下的文档将会提供哪些功能。

### post 集合

post 集合提供了以下的功能实现:

* 文章列表页 - 文章置顶、文章封面图、文章摘要等。
* 文章分类页 - 根据目录结构自动生成分类。
* 文章标签页 - 根据页面 `frontmatter.tags` 生成标签。
* 文章归档页 - 根据页面 `frontmatter.createTime` 生成归档。

### doc 集合

doc 集合提供了以下的功能实现:

* **侧边导航栏** - 提供清晰的文档结构导航
* **自动生成目录** - 基于文件结构智能生成侧边栏
* **多级嵌套支持** - 支持复杂的文档层次结构

## 集合配置

---

---
url: /guide/collection/doc/index.md
---
# doc 集合
## 概述

**doc 集合**专为管理结构化文档而设计,适用于文章间存在强关联关系、需要整体呈现的场景。典型应用包括:

* API 技术文档
* 产品使用教程
* 专题开发指南
* 知识体系笔记

该集合通过**智能侧边导航栏**实现文档间的快速跳转与内容组织。

::: info 主题支持配置多个独立的 doc 集合
:::

## 创建 doc 集合

通过三个步骤快速创建文档集合:

:::: steps

* **创建文档目录**

  ::: file-tree

  * docs
    * ++ guide
      * ++ intro.md
      * ++ install.md
      * ++ …
        :::

* **配置集合参数**

  ::: code-tabs#config

  @tab .vuepress/config.ts

  ```ts twoslash
  import { defineUserConfig } from 'vuepress'
  import { plumeTheme } from 'vuepress-theme-plume'

  export default defineUserConfig({
    theme: plumeTheme({
      collections: [ // [!code focus:3]
        { type: 'doc', dir: 'guide', title: '指南' }
      ]
    })
  })
  ```

  @tab .vuepress/plume.config.ts

  ```ts twoslash
  import { defineThemeConfig } from 'vuepress-theme-plume'

  export default defineThemeConfig({
    collections: [ // [!code focus:3]
      { type: 'doc', dir: 'guide', title: '指南' }
    ]
  })
  ```

  :::

* **完成配置**
  ::::

### 多语言支持

为不同语言版本配置独立的文档集合:

::: file-tree

* docs
  * guide
    * intro.md
    * install.md
    * …
  * en
    * guide
      * intro.md
      * install.md
      * …
        :::

::: code-tabs#config

@tab .vuepress/config.ts

```ts twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    locales: {
      '/': { // [!code focus:5]
        collections: [
          { type: 'doc', dir: 'guide', title: '指南' }
        ]
      },
      '/en/': { // [!code focus:5]
        collections: [
          { type: 'doc', dir: 'guide', title: 'Guide' }
        ]
      }
    }
  })
})
```

@tab .vuepress/plume.config.ts

```ts twoslash
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  locales: {
    '/': { // [!code focus:5]
      collections: [
        { type: 'doc', dir: 'guide', title: '指南' }
      ]
    },
    '/en/': { // [!code focus:5]
      collections: [
        { type: 'doc', dir: 'guide', title: 'Guide' }
      ]
    }
  }
})
```

:::

## 目录结构配置

`dir` 参数定义文档源文件位置,支持相对和绝对路径:

```ts
dir: 'guide' // 指向 docs/guide
dir: '/guide/' // 等效写法
dir: './guide/' // 等效写法
dir: '/team/guide/' // 指向 docs/team/guide
```

::: info 多语言环境下路径相对于对应的语言目录
:::

## 自动 Frontmatter 生成

::: info 仅在执行 `vuepress dev` 或 `vuepress build` 后生效
:::

支持自动生成文档元数据,可自定义处理逻辑:

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'doc',
        dir: 'guide',
        title: '指南',
        // [!code hl:10]
        autoFrontmatter: {
          title: true, // 自动生成标题
          createTime: true, // 自动生成创建时间
          permalink: true, // 自动生成永久链接
          transform: (data, context, locale) => { // 自定义转换
            data.foo ??= 'foo'
            return data
          }
        }
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'doc',
      dir: 'guide',
      title: '指南',
      // [!code hl:10]
      autoFrontmatter: {
        title: true, // 自动生成标题
        createTime: true, // 自动生成创建时间
        permalink: true, // 自动生成永久链接
        transform: (data, context, locale) => { // 自定义转换
          data.foo ??= 'foo'
          return data
        }
      }
    }
  ]
})
```

:::

生成效果:

```md title="docs/guide/install.md"
---
title: install
createTime: 2025/03/24 20:15:12
permalink: /guide/a1b2c3d4/
---
```

## 侧边栏配置

提供灵活的侧边栏导航配置选项:

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'doc',
        dir: 'guide',
        title: '指南',
        // [!code hl:5]
        sidebar: [ // 手动配置导航项
          'intro',
          'install',
        ],
        sidebarScrollbar: true, // 显示侧边栏滚动条
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'doc',
      dir: 'guide',
      title: '指南',
      // [!code hl:5]
      sidebar: [ // 手动配置导航项
        'intro',
        'install',
      ],
      sidebarScrollbar: true, // 显示侧边栏滚动条
    }
  ]
})
```

:::

### 自动生成侧边栏

设置 `sidebar: 'auto'` 自动基于目录结构生成导航:

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'doc',
        dir: 'guide',
        title: '指南',
        // [!code hl]
        sidebar: 'auto', // 自动生成导航结构
        sidebarCollapsed: undefined, // 折叠状态:true-折叠 false-展开
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'doc',
      dir: 'guide',
      title: '指南',
      // [!code hl]
      sidebar: 'auto', // 自动生成导航结构
      sidebarCollapsed: undefined, // 折叠状态:true-折叠 false-展开
    }
  ]
})
```

:::

### 手动配置侧边栏

[查看**侧边栏**详细配置说明](./sidebar.md){.read-more}

## 集合首页定制

目录下的 `README.md` 自动作为集合首页,支持转换为功能丰富的门户布局:

```md title="typescript/README.md"
---
pageLayout: home
config:
  - type: hero
    title: TypeScript 完全指南
    description: 从基础到进阶的 TypeScript 学习路径
  - type: features
    features:
      - title: 类型系统
        details: 深入理解 TypeScript 类型系统
        icon: mdi:code-braces
      - title: 高级特性
        details: 掌握泛型、装饰器等高级功能
        icon: mdi:rocket-launch
---
```

---

---
url: /guide/collection/post/index.md
---
# post 集合
## 概述

**post 集合**用于管理碎片化的多篇文章集合。这里的"碎片化"指文章间无强关联关系,或仅需扁平化展示的场景,典型应用包括:

* 博客系统
* 专题专栏
* 新闻资讯
* 随笔记录

该集合提供完整的文章管理功能:

* **文章列表页** - 支持置顶、封面图、摘要展示
* **文章分类页** - 基于目录结构自动生成分类
* **文章标签页** - 根据页面 `frontmatter.tags` 生成标签
* **文章归档页** - 基于 `frontmatter.createTime` 生成时间线归档

各页面均预留个人信息展示区域,支持个人简介或组织信息配置。

::: info 主题支持配置多个 post 集合
:::

## 创建 post 集合

通过三个简单步骤即可完成 post 集合创建:

:::: steps

* **创建文章目录**

  ::: file-tree

  * docs
    * ++ blog
      * ++ post-1.md
      * ++ post-2.md
      * ++ …
        :::

* **配置集合参数**

  ::: code-tabs#config

  @tab .vuepress/config.ts

  ```ts twoslash
  import { defineUserConfig } from 'vuepress'
  import { plumeTheme } from 'vuepress-theme-plume'

  export default defineUserConfig({
    theme: plumeTheme({
      collections: [ // [!code focus:3]
        { type: 'post', dir: 'blog', title: '博客' }
      ]
    })
  })
  ```

  @tab .vuepress/plume.config.ts

  ```ts twoslash
  import { defineThemeConfig } from 'vuepress-theme-plume'

  export default defineThemeConfig({
    collections: [ // [!code focus:3]
      { type: 'post', dir: 'blog', title: '博客' }
    ]
  })
  ```

  :::

* **完成**

::::

配置完成后,主题自动扫描 `docs/blog` 目录并生成以下页面:

* 文章列表页:`/blog/`
* 文章分类页:`/blog/categories/`
* 文章标签页:`/blog/tags/`
* 文章归档页:`/blog/archives/`

启用 `autoFrontmatter` 后,系统自动为 Markdown 文件生成永久链接:

```md title="docs/blog/post-1.md"
---
title: post-1
createTime: 2025/03/24 20:15:12
permalink: /blog/a1b2c3d4/
---
```

### 多语言支持

在主题多语言配置中定义不同语言的 post 集合:

::: code-tabs#config

@tab .vuepress/config.ts

```ts twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    locales: {
      '/': { // [!code focus:5]
        collections: [
          { type: 'post', dir: 'blog', title: '博客' }
        ]
      },
      '/en/': { // [!code focus:5]
        collections: [
          { type: 'post', dir: 'blog', title: 'Blog' }
        ]
      }
    }
  })
})
```

@tab .vuepress/plume.config.ts

```ts twoslash
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  locales: {
    '/': { // [!code focus:5]
      collections: [
        { type: 'post', dir: 'blog', title: '博客' }
      ]
    },
    '/en/': { // [!code focus:5]
      collections: [
        { type: 'post', dir: 'blog', title: 'Blog' }
      ]
    }
  }
})
```

:::

## 集合目录配置

`dir` 参数指定集合的源文件目录,支持绝对路径和相对路径(均相对于源目录):

```ts
dir: 'blog' // 指向 docs/blog
dir: '/blog/' // 等效写法
dir: './blog/' // 等效写法
dir: '/team/blog/' // 指向 docs/team/blog
```

::: info 在多语言下,则相对于多语言目录
:::

### 文件过滤

通过 `include` 和 `exclude` 配置过滤 Markdown 文件,
使用 [picomatch ::quill:search::](https://chat.baidu.com/search?word=picomatch+%E7%9A%84+glob+pattern+%E8%A7%84%E5%88%99){.no-icon} 模式匹配:

::: code-tabs#config

@tab .vuepress/config.ts

```ts twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        // [!code hl:4]
        include: ['**/*.md'], // 包含所有 .md 文件
        exclude: ['**/*.snippet.md'] // 排除代码片段文件
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts twoslash
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'post',
      dir: 'blog',
      title: '博客',
      // [!code hl:4]
      include: ['**/*.md'], // 包含所有 .md 文件
      exclude: ['**/*.snippet.md'] // 排除代码片段文件
    }
  ]
})
```

:::

## 页面生成配置

默认基于 `dir` 配置生成页面路径,支持完整自定义:

::: code-tabs#config

@tab .vuepress/config.ts

```ts twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        // [!code hl:16]
        postList: true, // 启用文章列表页
        link: '/blog/', // 列表页链接
        linkPrefix: '/blog/', // 文章链接前缀
        tags: true, // 启用标签页
        tagsLink: '/blog/tags/', // 标签页链接
        tagsTheme: 'colored', // 标签主题 colored|gray|brand
        tagsText: '标签', // 标签页标题
        archives: true, // 启用归档页
        archivesLink: '/blog/archives/', // 归档页链接
        archivesText: '归档', // 归档页标题
        categories: true, // 启用分类页
        categoriesLink: '/blog/categories/', // 分类页链接
        categoriesText: '分类', // 分类页标题
        categoriesExpand: 'deep', // 分类展开层级 number|'deep'
        categoriesTransform: categories => categories, // 分类转换函数
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts twoslash
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'post',
      dir: 'blog',
      title: '博客',
      // [!code hl:16]
      postList: true, // 启用文章列表页
      link: '/blog/', // 列表页链接
      linkPrefix: '/blog/', // 文章链接前缀
      tags: true, // 启用标签页
      tagsLink: '/blog/tags/', // 标签页链接
      tagsTheme: 'colored', // 标签主题 colored|gray|brand
      tagsText: '标签', // 标签页标题
      archives: true, // 启用归档页
      archivesLink: '/blog/archives/', // 归档页链接
      archivesText: '归档', // 归档页标题
      categories: true, // 启用分类页
      categoriesLink: '/blog/categories/', // 分类页链接
      categoriesText: '分类', // 分类页标题
      categoriesExpand: 'deep', // 分类展开层级 number|'deep'
      categoriesTransform: categories => categories, // 分类转换函数
    }
  ]
})
```

:::

## 自动 Frontmatter 生成

::: info 仅在执行 `vuepress dev` 或 `vuepress build` 后生效
:::

支持集合级别的 frontmatter 自动生成,可自定义转换逻辑:

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        // [!code hl:10]
        autoFrontmatter: {
          title: true, // 自动生成标题
          createTime: true, // 自动生成创建时间
          permalink: true, // 自动生成永久链接
          transform: (data, context, locale) => { // 自定义转换
            data.foo ??= 'foo'
            return data
          }
        }
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'post',
      dir: 'blog',
      title: '博客',
      // [!code hl:10]
      autoFrontmatter: {
        title: true, // 自动生成标题
        createTime: true, // 自动生成创建时间
        permalink: true, // 自动生成永久链接
        transform: (data, context, locale) => { // 自定义转换
          data.foo ??= 'foo'
          return data
        }
      }
    }
  ]
})
```

:::

生成示例:

```md title="docs/blog/post-1.md"
---
title: post-1
createTime: 2025/03/24 20:15:12
permalink: /blog/a1b2c3d4/
---
```

## 个人信息配置

每个 post 集合支持独立配置个人信息展示区域。未配置时继承[主题默认 profile 设置](../../config/theme.md#profile)。

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        // [!code hl:10]
        profile: {
          avatar: '/avatar.jpg', // 头像路径
          name: '张三', // 显示名称
          description: '个人简介', // 简介文本
          circle: true, // 圆形头像
          location: '广州', // 所在地
          organization: '组织名称', // 所属组织
          layout: 'right', // 布局位置 left|right
        }
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'post',
      dir: 'blog',
      title: '博客',
      // [!code hl:10]
      profile: {
        avatar: '/avatar.jpg', // 头像路径
        name: '张三', // 显示名称
        description: '个人简介', // 简介文本
        circle: true, // 圆形头像
        location: '广州', // 所在地
        organization: '组织名称', // 所属组织
        layout: 'right', // 布局位置 left|right
      }
    }
  ]
})
```

:::

## 社交链接

个人信息区域支持社交链接配置,未配置时继承[主题默认 social 设置](../../config/theme.md#social)。

::: code-tabs#config

@tab .vuepress/config.ts

```ts
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        // [!code hl:4]
        social: [
          { icon: 'github', link: 'https://github.com/pengzhanbo' },
        ],
      }
    ]
  })
})
```

@tab .vuepress/plume.config.ts

```ts
import { defineThemeConfig } from 'vuepress-theme-plume'

export default defineThemeConfig({
  collections: [
    {
      type: 'post',
      dir: 'blog',
      title: '博客',
      // [!code hl:4]
      social: [
        { icon: 'github', link: 'https://github.com/pengzhanbo' },
      ],
    }
  ]
})
```

:::

### 内置图标库

::: flex

* discord
* telegram
* facebook
* github
* instagram
* linkedin
* mastodon
* npm
* slack
* twitter
* x
* youtube

- qq
- weibo
- bilibili
- gitlab
- docker
- juejin
- zhihu
- douban
- steam
- stackoverflow
- xbox

:::

## 文章封面配置

文章列表页支持封面图展示,提供多种布局和尺寸选项。

### 基础配置

在 frontmatter 中定义封面图路径:

```md{3}
---
title: 文章标题
cover: /images/cover.jpg
---
```

**路径规范**:仅支持绝对路径或远程 URL。本地图片需放置在 `.vuepress/public` 目录:

::: file-tree

* docs
  * .vuepress
    * public
      * images
        * cover.jpg
    * config.ts
  * article.md
    :::

默认展示效果:

### 高级布局

调整封面图位置和尺寸:

```md{4-7}
---
title: 文章标题
cover: /images/cover.jpg
coverStyle:
  layout: left
  ratio: 16:9
  width: 300
---
```

效果展示:

### 紧凑模式

无摘要时启用紧凑布局:

```md{8}
---
title: 文章标题
cover: /images/cover.jpg
coverStyle:
  layout: left
  ratio: 16:9
  width: 300
  compact: true
---
```

效果展示:

::: warning `compact: true` 仅在无摘要时生效
:::

### 顶部大图布局

```md{5}
---
title: 文章标题
cover: /images/cover.jpg
coverStyle:
  layout: top
  ratio: 16:9
  width: 300
---
```

效果展示:

### 预设配置

为保持视觉统一,支持集合级封面图预设:

```ts title=".vuepress/config.ts" twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      {
        type: 'post',
        dir: 'blog',
        title: '博客',
        postCover: {
          layout: 'left',
          ratio: '16:9',
          width: 300,
          compact: true
        }
      }
    ],
  })
})
```

布局模式说明:

```ts
type PostCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'

interface PostCoverStyle {
  layout?: PostCoverLayout // 布局位置
  ratio?: number | `${number}:${number}` // 宽高比,默认 '4:3'
  width?: number // 宽度(左右布局生效),默认 240
  compact?: boolean // 紧凑模式,默认 false
}
```

特殊布局模式:

* `odd-left` - 奇数项居左,偶数项居右
* `odd-right` - 奇数项居右,偶数项居左

`odd-left` 布局效果:

::: warning 移动端适配
窄屏设备上自动切换为 `top` 布局以确保显示效果
:::

## 文章元数据

通过 frontmatter 配置文章元数据:

```md
---
title: 文章标题
createTime: 2024/01/01 00:00:00
tags:
  - tag1
  - tag2
---
```

`title` 和 `createTime` 在文件创建时自动生成,支持手动修改。

### 可用属性

| 属性       | 类型                | 默认值   | 说明                       |
| ---------- | ------------------- | -------- | -------------------------- |
| title      | `string`            | 文件名   | 文章标题                   |
| createTime | `string`            | 当前时间 | 创建时间                   |
| tags       | `string[]`          | `[]`     | 文章标签                   |
| sticky     | `boolean \| number` | false    | 置顶标识,数字越大排序越前 |
| draft      | `boolean`           | false    | 草稿模式,构建后隐藏       |
| cover      | `string`            | `''`     | 封面图路径                 |
| coverStyle | `PostCoverStyle`    | `null`   | 封面样式配置               |
| excerpt    | `boolean \| string` | ''       | 摘要内容,支持自动提取     |

同时支持[通用 frontmatter 配置](../../config/frontmatter/basic.md)中的所有字段。

## 文章摘要配置

### 自动提取

使用 `` 标记摘要截断点:

```md
---
title: 标题
---

摘要内容区域



正文剩余部分
```

### 手动定义

通过 excerpt 字段自定义摘要:

```md
---
title: 标题
excerpt: 自定义摘要内容
---
```

**配置说明**:

* `excerpt: false` - 禁用摘要(忽略 ``)
* `excerpt: string` - 自定义内容(忽略 ``)

::: tip 推荐使用 \ 注释定义摘要
:::

## 配置到站点首页

主题提供了两种方式来设置 post 集合 的文章列表页 到站点主页,满足不同的需求场景:

* **方式一:配置 主页的 `pageLayout` 属性为 `posts`**

```md title="docs/README.md"
---
pageLayout: posts
---
```

还可以通过 `collection` 配置项来指定读取哪个集合的文章列表页,默认读取第一个集合的文章列表页。

`collection` 需要与集合配置的 `dir` 的值相同。

```md title="docs/README.md"
---
pageLayout: posts
collection: blog
---
```

此配置会直接将页面应用 `posts` 布局,显示博客文章列表。

这是将主页修改为 博客页的 最简单的方式,但缺点是 缺少灵活性。

* **方式二:配置 主页的 `pageLayout` 属性为 `home`, 添加 `type: posts` 的首页区域类型**

```md title="docs/README.md"
---
pageLayout: home
config:
  - type: posts
    collection: blog
---
```

使用这种方式,你不仅可以在首页中添加 文章列表,还可以灵活的在页面的其他区域添加不同的内容。

比如,配置首屏为 `banner`,然后紧跟着 博客文章列表:

```md title="docs/README.md"
---
pageLayout: home
config:
  - type: banner
  - type: posts
---
```

更多自定义配置,请参考 [自定义首页](../custom/home.md)。

当使用以上两种方式 将首页配置为 文章列表页后,由于主题默认依然会生成 文章列表页,
这导致存在了重复功能的页面。为此,你可能需要在 集合配置中,
**关闭自动生成博客文章列表页**:

(还可以重新修改 分类页/标签页/归档页的链接地址)

```ts title=".vuepress/config.ts" twoslash
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'

export default defineUserConfig({
  theme: plumeTheme({
    collections: [
      { type: 'post', dir: 'blog', title: '博客', postList: false }
    ],
  })
})
```

---

---
url: /guide/component-overrides/index.md
---
# 组件覆写
## 概述

布局插槽十分实用,但有时候你可能会觉得它不够灵活。主题同样提供了单个组件覆写的能力。

::: warning
在使用此功能前,你应该首先熟悉本主题的源代码,了解 主题内置的各个组件,以便 安全的 覆写他们。

主题的组件源代码托管在 [GitHub](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/components),遵循 MIT 协议。
:::

## 使用

主题将所有 非全局的组件 都注册了一个带 `@theme` 前缀的 [alias](https://v2.vuepress.vuejs.org/zh/reference/plugin-api.html#alias) 。
例如,`VPFooter.vue` 的别名是 `@theme/VPFooter.vue` 。

如果你想要覆写 `VPFooter.vue` 组件,只需要在配置文件 `.vuepress/config.ts` 中覆盖这个别名即可:

```ts title=".vuepress/config.ts"
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'
import { getDirname, path } from 'vuepress/utils'

const __dirname = getDirname(import.meta.url)

export default defineUserConfig({
  theme: plumeTheme(),

  alias: {
    '@theme/VPFooter.vue': path.resolve(
      __dirname,
      './components/MyFooter.vue',
    ),
  },
})
```

---

---
url: /guide/components/badge/index.md
---
# 徽章
## 概述 

使用 `` 组件来显示 行内信息,如状态或标签。

将你想显示的内容传递给 `` 组件的 `text` 属性。

## Props

:::: field-group

::: field name="type" type="'info' | 'tip' | 'warning' | 'danger' | string" default="'tip'" optional
徽章类型,不同的类型使用不同的颜色方案。支持自定义类型
:::

::: field name="text" type="string" default="''" optional
徽章文本
:::

::: field name="color" type="string" optional
自定义徽章文本颜色
:::

::: field name="bgColor" type="string" optional
自定义徽章背景颜色
:::

::: field name="borderColor" type="string" optional
自定义徽章边框颜色
:::

::::

## 示例

**输入:**

```md :no-line-numbers
- VuePress - 
- VuePress - 
- VuePress - 
- VuePress - 
- VuePress - 
```

**输出:**

* VuePress - 
* VuePress - 
* VuePress - 
* VuePress - 
* VuePress - 

使用自定义`type`,可以实现更丰富的表现。

**输入:**

1. 在主题 [自定义样式文件](../custom/style.md.md) 中,添加预定的样式:

   ```css
   /* 浅色主题 */
   .vp-badge.important {
     color: #8e5cd9;
     background-color: rgba(159, 122, 234, 0.14);
     border-color: transparent;
   }

   /* 深色主题 */
   [data-theme="dark"] .vp-badge.important {
     color: #8e5cd9;
     background-color: rgba(159, 122, 234, 0.16);
     border-color: transparent;
   }

   /**
   important 为自定义 type 类型
   */
   ```

2. 使用自定义`type`:

   ```md :no-line-numbers
   VuePress - 
   ```

   **输出:**

   VuePress - 

---

---
url: /guide/components/card-grid/index.md
---
# 卡片容器
## 概述

当你需要将多个卡片排列,可以使用 `` 组件。在空间足够时,多个卡片会自动排列。

## Props

:::: field-group
::: field name="cols" type="number | { sm: number, md: number, lg: number }" default="2"

卡片排列列数。

组件默认会根据屏幕宽度自动调整列数。在空间足够时,默认显示双列,小屏幕下显示单列。

你可以通过 `cols` 配置列数。当传入 `number` 时,所有尺寸均显示为 `number` 个卡片。
传入 `{ sm: number, md: number, lg: number }` 时,根据屏幕宽度自动调整列数。

* `sm` : `< 768px`
* `md` : `>= 768px < 960px`
* `lg` : `>= 960px`

建议传入的 `number` 不超过 `3`。

:::
::::

## 示例

**输入:**

```md :no-line-numbers

  
    这里是卡片内容。
  
  
    这里是卡片内容。
  



  
  

```

**输出:**

---

---
url: /guide/components/card-masonry/index.md
---
# 瀑布流容器
## 概述

瀑布流容器是一个 通用的容器组件,你可以把任何内容放到 `` 里面,容器会自动计算每一个 **项** 的高度,
然后将它们按照瀑布流的方式进行排列。

::: details 什么是项 ?

项 表示的是一个单独的内容,可以是图片、文字、视频等等。

* 从 markdown 的语法而言,独占一行的可以被认为是一个项。(该行的前后应该有空行)
* 从 html 的结构而言,容器下的每一个子元素都会被认为是一个项。

:::

```md


...




```

## Props

:::: field-group

::: field name="cols" type="number | { sm: number, md: number, lg: number }" optional
列数。

组件默认会根据屏幕宽度自动调整列数。在空间足够时,默认显示三列,小屏幕下显示双列。

你可以通过 `cols` 配置列数。当传入 `number` 时,所有尺寸均显示为 `number` 个卡片。
传入 `{ sm: number, md: number, lg: number }` 时,根据屏幕宽度自动调整列数。

* `sm` : `< 640px`
* `md` : `>= 640px < 960px`
* `lg` : `>= 960px`
  :::

::: field name="gap" type="number" optional default="16"
列之间的间距。
:::

::::

## Markdown 语法支持

在 markdown 中,可以使用 `::: card-masonry` 容器代替 ``。

```md
::: card-masonry cols="3" gap="16" 

![](/images/1.png)



::: 
```

## 示例

### 图片瀑布流

瀑布流特别适合用于展示图片,你可以直接在将 `![](image_url)` 写到 `::: card-masonry` 中。

**输入:**

```md
::: card-masonry

![](image_url)

![](image_url)

![](image_url)

![](image_url)

![](image_url)

![](image_url)

:::
```

**输出:**

::: card-masonry
![a](https://images.unsplash.com/photo-1719937051124-91c677bc58fc?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDF8MHxmZWF0dXJlZC1waG90b3MtZmVlZHwxfHx8ZW58MHx8fHx8)

![b](https://plus.unsplash.com/premium_photo-1731329153355-1015daf2cb92?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHwyfHx8ZW58MHx8fHx8)

![c](https://images.unsplash.com/photo-1731323036230-fb37b4d9ed71?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHwzfHx8ZW58MHx8fHx8)

![a](https://images.unsplash.com/photo-1730630906214-1256b57d65b7?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw0fHx8ZW58MHx8fHx8)

![b](https://plus.unsplash.com/premium_photo-1733864822156-f3cf26187fd9?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw2fHx8ZW58MHx8fHx8)

![a](https://images.unsplash.com/photo-1731756748993-85e1513dfc76?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw3fHx8ZW58MHx8fHx8)

![b](https://images.unsplash.com/photo-1733705879328-a18f2a025c67?w=800\&auto=format\&fit=crop\&q=60\&ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw4fHx8ZW58MHx8fHx)
:::

### 卡片瀑布流

瀑布流也适合用于展示卡片,你可以直接在将 `::: card` 写到 `::: card-masonry` 中。

**输入:**

```md :collapsed-lines
:::: card-masonry

::: card title="卡片1"
卡片内容
:::

::: card title="卡片2"
卡片内容

卡片内容
:::

::: card title="卡片3"
卡片内容
:::

::: card title="卡片4"
卡片内容
:::

::: card title="卡片5"
卡片内容

卡片内容
:::

::: card title="卡片6"
卡片内容
:::

::::
```

**输出:**

:::: card-masonry

::: card title="卡片1"
卡片内容
:::

::: card title="卡片2"
卡片内容

卡片内容
:::

::: card title="卡片3"
卡片内容
:::

::: card title="卡片4"
卡片内容
:::

::: card title="卡片5"
卡片内容

卡片内容
:::

::: card title="卡片6"
卡片内容
:::

::::

### 代码块瀑布流

**输入:**

````md :collapsed-lines
:::card-masonry

```ts
const a = 1
```

```json
{
  "name": "John"
}
```

```css
p {
  color: red;
}
```

```html

  
    

Hello world

``` ```ts const a = 12 const b = 1 ``` ```rust fn main() { println!("Hello, world!"); } ``` ::: ```` **输出:** :::card-masonry ```ts const a = 1 ``` ```json { "name": "John" } ``` ```css p { color: red; } ``` ```html

Hello world

``` ```ts const a = 12 const b = 1 ``` ```rust fn main() { println!("Hello, world!"); } ``` ::: --- --- url: /guide/components/card/index.md --- # 卡片 ## 概述 使用 `` 组件在页面中显示卡片。 也可以使用 markdown [卡片容器](../markdown/card.md) 语法,替代 `` 组件。 ## Props :::: field-group ::: field name="title" type="string" default="''" optional 卡片标题 ::: ::: field name="icon" type="string | { svg: string }" default="''" optional 显示在标题左侧的图标,支持 iconify 所有图标,也可以使用 图片链接 ::: :::: ## 插槽 | 名称 | 说明 | | ------- | ---------- | | default | 卡片内容 | | title | 自定义标题 | ## 示例 **输入:** ```md :no-line-numbers 这里是卡片内容。 这里是卡片内容。 ``` **输出:** :::info 在插槽内也可以使用 markdown 语法,但需要注意的是,markdown 语法需要与 标签之间间隔一行。 否则将被识别为普通文本。 ::: --- --- url: /guide/components/github-repo-card/index.md --- # Repo 卡片 ## 概述 Repo 卡片组件 用于显示 GitHub / Gitee 仓库信息。 ## 使用 使用该组件需要你手动导入 `RepoCard` 组件: ```md :no-line-numbers ``` 注册为全局组件: ```ts title=".vuepress/client.ts" import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue' import { defineClientConfig } from 'vuepress/client' export default defineClientConfig({ enhance({ app }) { app.component('RepoCard', RepoCard) }, }) ``` 全局组件可在 其他任意 markdown 文件中使用 ```md ``` ### Props :::: field-group ::: field name="repo" type="string" required 仓库地址,格式为 `owner/repo` ::: ::: field name="provider" type="github | gitee" optional default="'github'" 仓库所属平台,当前仅支持 `github / gitee` 。 ::: ::: field name="fullname" type="boolean" optional 是否显示完整的仓库名称。 完整的仓库名称为 `owner/repo`。 * 如果 owner 为个人,则默认不显示完整的仓库名称,仅显示 `repo`。 * 如果 owner 为组织,则默认显示完整的仓库名称。 ::: :::: ## 示例 ### 单卡片 **输入:** ```md ``` **输出:** ### 多卡片 如果希望以紧凑的方式并排展示多个卡片,可以使用 `CardGrid` 组件。 **输入:** ```md ``` **输出:** **输入:** ```md ``` **输出:** --- --- url: /guide/components/home-box/index.md --- # 首页布局容器 ## 首页布局容器 自定义首页时,使用 `` 提供给 区域 的 包装容器。 ## Props :::: field-group ::: field name="type" type="string" default="''" optional 区域类型 ::: ::: field name="full" type="boolean" default="false" optional 是否全屏 ::: ::: field name="background-image" type="string" default="''" optional 区域背景图片 ::: ::: field name="background-attachment" type="'fixed' | 'local'" default="'local'" optional 区域背景定位方式 ::: :::: --- --- url: /guide/components/icon/index.md --- # 图标 ## 概述 图标组件 ``,根据 `markdown.icon` 配置,从不同的图标库加载图标。 [主题还提供了 markdown 语法支持,点击了解更多](../markdown/icons.md){.read-more} ## 配置 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // [!code ++:3] icon: { provider: 'iconify' } // 默认支持 } }) }) ``` ```ts interface IconOptions { /** * 图标提供商 */ provider: 'iconify' | 'iconfont' | 'fontawesome' /** * 图标默认前缀,不同的提供商默认前缀不同 * - iconify - 默认为 `''` * - iconfont - 默认为 `iconfont icon-` * - fontawesome - 默认为 `fas` */ prefix?: string /** * 图标资源地址 */ assets?: IconAssetLink | IconAssetLink[] size?: string | number color?: string } ``` ## Props :::: field-group ::: field name="name" type="string" default="''" optional 图标名称,当 `markdown.icon.prefix` 有值时,`name` 中的前缀可以省略 ::: ::: field name="color" type="string" default="'currentcolor'" optional 图标颜色 ::: ::: field name="size" type="string" default="'1em'" optional 图标大小 ::: :::: ## 示例 **输入:** ```md :no-line-numbers - home - - vscode - - twitter - ``` **输出:** * home - * vscode - * twitter - --- --- url: /guide/components/image-card/index.md --- # 图片卡片 ## 概述 使用 `` 组件在页面中显示图片卡片。 图片卡片 有别于 markdown 的 普通插入图片方式,它展示与图片相关的更多信息,包括标题、描述、作者、链接等。 适用于如 摄影作品、设计作品、宣传海报 等场景。 ## Props :::: field-group ::: field name="image" type="string" required 图片链接地址,本地图片必须使用绝对路径,即以 `/` 开头的路径,指向 `/public` 目录 ::: ::: field name="title" type="string" optional 图片标题 ::: ::: field name="description" type="string" optional 图片描述信息 ::: ::: field name="author" type="string" optional 图片作者 ::: ::: field name="href" type="string" optional 点击图片标题后的跳转链接 ::: ::: field name="date" type="string | Date | number" optional 图片 创作日期 ::: ::: field name="width" type="string | number" optional 图片宽度 ::: ::: field name="center" type="boolean" optional 图片宽度不满屏时是否居中 ::: :::: ## 示例 **输入:** ```md :no-line-numbers ``` **输出:** 还可以放到 `` 组件中。 **输入:** ```md :no-line-numbers ``` **输出:** [查看 照片类作品示例](../../../../1.示例/照片类作品示例.md) --- --- url: /guide/components/link-card/index.md --- # 链接卡片 ## 概述 使用 `` 组件在页面中显示链接卡片。 ## Props :::: field-group ::: field name="title" type="string" default="''" optional 链接卡片标题 ::: ::: field name="icon" type="string | { svg: string }" default="''" optional 显示在标题左侧的图标,支持 [markdown.icon](../features/icon.md) 配置的提供商的图标,也可以使用 图片链接 ::: ::: field name="href" type="string" default="''" optional 链接卡片跳转地址 ::: ::: field name="description" type="string" default="''" optional 链接卡片描述,建议使用组件默认插槽添加描述内容 ::: ::: field name="target" type="string" default="''" optional 链接跳转方式 ::: :::: ## 插槽 | 名称 | 说明 | | ------- | ------------ | | default | 卡片详情内容 | | title | 自定义标题 | ## 示例 **输入:** ```md :no-line-numbers ``` **输出:** 使用组件插槽,可以实现更丰富的表现。 **输入:** ```md :no-line-numbers - 这里是卡片内容 - 这里是卡片内容 - 这里是卡片内容 - 这里是卡片内容 ``` **输出:** * 这里是卡片内容 * 这里是卡片内容 - 这里是卡片内容 - 这里是卡片内容 :::info 在插槽内也可以使用 markdown 语法,但需要注意的是,markdown 语法需要与 标签之间间隔一行。 否则将被识别为普通文本。 ::: --- --- url: /guide/components/npm-badge/index.md --- # Npm 徽章 ## 概述 Npm 徽章组件 用于显示 npm 包信息,并提供相关的链接。 徽章由 提供支持。 ## 使用 使用该组件需要你手动导入 `NpmBadge` 或 `NpmBadgeGroup` 组件: ```md :no-line-numbers ``` ## `` 单个 npm badge ### Props :::: field-group ::: field name="name" type="string" optional npm 包名,为空则从 `repo` 中获取 ::: ::: field name="repo" type="string" 包 github 仓库地址,格式为 `owner/repo`,当 `name` 为空时必填 ::: ::: field name="type" type="NpmBadgeType" 徽章类型 ::: ::: field name="theme" type="NpmBadgeTheme" optional default="'flat'" 徽章主题 ::: ::: field name="label" type="string" optional 徽章标签 ::: ::: field name="color" type="string" optional default="'#32A9C3'" 徽章颜色 ::: ::: field name="labelColor" type="string" optional default="'#1B3C4A'" 徽章标签颜色 ::: ::: field name="branch" type="string" optional default="'main'" 仓库分支 ::: ::: field name="dir" type="string" optional 包所在仓库目录,适用于 monorepo 项目 ::: :::: ### Types ```ts type NpmBadgeType // github = | 'source' // github source | 'stars' // github stars | 'forks' // github forks | 'license' // github license // npm | 'version' // npm version | 'dt' // alias d18m | 'd18m' // npm downloads last 18 months | 'dw' // npm downloads weekly | 'dm' // npm downloads monthly | 'dy' // npm downloads yearly type NpmBadgeTheme = 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' | 'social' ``` ### 示例 * `` - * `` - * `` - * `` - * `` - * `` - * `` - * `` - * `` - * `` - ## `` 组合多个 npm badge ### Props :::: field-group ::: field name="name" type="string" optional npm 包名,为空则从 `repo` 中获取 ::: ::: field name="repo" type="string" 包 github 仓库地址,格式为 `owner/repo`,当 `name` 为空时必填 ::: ::: field name="items" type="string | NpmBadgeType\[]" optional default="\[]" 徽章类型列表, 传入 `string` 时用 `','`分隔,会自动转换为 `NpmBadgeType[]` ::: ::: field name="theme" type="NpmBadgeTheme" optional 徽章主题 ::: ::: field name="color" type="string" optional 徽章颜色 ::: ::: field name="labelColor" type="string" optional 徽章标签颜色 ::: ::: field name="branch" type="string" optional 仓库分支 ::: ::: field name="dir" type="string" optional 包所在仓库目录,适用于 monorepo 项目 ::: :::: ### Slots `` 支持传入 多个 `` 组件。 `` 声明的 `Props` 将被注入到 `` 组件中。通过这种方式来实现和简化徽章组合。 ### 示例 **输入:** ```md :no-line-numbers ``` **输出:** 使用 `` 灵活定义徽章组合: **输入:** ```md :no-line-numbers ``` **输出:** --- --- url: /guide/components/plot/index.md --- # “隐秘”文本 ## 概述 使用 `` 组件显示 [“隐秘”文本](../markdown/plot.md) ,能够更灵活的控制行为。 该组件默认不启用,你需要在 theme 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { plot: true, }, }) }) ``` ## Props :::: field-group ::: field name="trigger" type="'hover' | 'click'" default="'hover'" optional 鼠标悬停触发,或者点击触发 ::: ::: field name="effect" type="'blur' | 'mask'" default="'mask'" optional 遮罩层效果,或者文本模糊效果 ::: :::: ## 示例 **输入:** ```md :no-line-numbers - 鼠标悬停 - 悬停时可见 - 点击 - 点击时可见 ``` **输出:** * 鼠标悬停 - 悬停时可见 * 点击 - 点击时可见 --- --- url: /guide/components/swiper/index.md --- # 轮播图 ## 概述 使用 `` 组件在 页面中显示轮播图片。 ## 使用 使用该组件,首先需要手动安装 `swiper` 库: ::: npm-to ```sh npm install swiper ``` ::: 然后,手动导入 `Swiper` 组件: ```md ``` 注册为全局组件: ```ts title=".vuepress/client.ts" import Swiper from 'vuepress-theme-plume/features/Swiper.vue' import { defineClientConfig } from 'vuepress/client' export default defineClientConfig({ enhance({ app }) { app.component('Swiper', Swiper) }, }) ``` 全局组件可在 其他任意 markdown 文件中使用 ```md ``` **示例:** ## Props | 名称 | 类型 | 默认值 | 说明 | | ----------------- | ---------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------- | | items | `string \| { link: string; href?: string; alt?: string}[]` | `[]` | 图片链接数组,传入对象时,`link`表示图片链接,`href`表示跳转链接,`alt`表示图片描述 | | width | `number \| string` | `100%` | 轮播区域宽度 | | height | `number \| string` | `100%` | 轮播区域高度 | | mode | `'banner' \| 'carousel' \| 'broadcast'` | `'banner'` | 轮播模式, `banner`: 轮播图; `carousel`: 走马灯; `broadcast`: 信息展播 | | navigation | `boolean` | `true` | 是否显示导航按钮 | | effect | `'slide' \| 'fade' \| 'cube' \| 'coverflow' \| 'flip' \| 'cards' \| 'creative'` | `'slide'` | 轮播效果 | | delay | `number` | `3000` | 轮播间隔时间, 仅当 `mode: 'banner'` 时生效,单位 `ms` | | speed | `number` | `300` | 动画持续时间,单位 `ms` | | loop | `boolean` | `true` | 是否循环 | | pauseOnMouseEnter | `boolean` | `false` | 是否鼠标悬停时暂停轮播 | | swipe | `boolean` | `true` | 是否开启手势滑动 | 更多 props 请参考 [Swiper 文档](https://swiperjs.com/swiper-api#parameters) ## 参考示例 ### 预设动画效果 **cube:** :::details 查看代码 ```md ``` ::: **fade:** :::details 查看代码 ```md ``` ::: **coverflow:** :::details 查看代码 ```md ``` ::: **flip:** :::details 查看代码 ```md ``` ::: **cards:** :::details 查看代码 ```md ``` ::: ### 自定义动画效果 **示例 1:** ::: details 查看代码 ```md ``` ::: **示例 2:** :::details 查看代码 ```md ``` ::: **示例 3:** :::details 查看代码 ```md ``` ::: **示例 4:** :::details 查看代码 ```md ``` ::: ### 走马灯 :::details 查看代码 ```md ``` ::: ### 信息展播 :::details 查看代码 ```md ``` ::: --- --- url: /guide/custom-home/index.md --- # 自定义首页 ## 概述 主题提供了十分灵活的方式来自定义首页。你可以根据你的需求来定制你的首页。 主题通过 `frontmatter` 来定义你的首页。在 `sourceDir` 的 `README.md` 文件中,编写 `frontmatter`。 ```md title="README.md" --- home: true config: - type: custom --- ``` 主题 遵循 流式布局的方式来渲染首页,将 首页 在 垂直方向上划分为一个个独立的区域,每个区域应用不同的组件。 通过 `config` 属性,以 数组 的形式,可以定义多个区域。通过 `type` 字段,可以定义该区域的类型。 主题内置了 `banner`, `hero`,`text-image`,`image-text`,`features`,`profile`,`custom` 等不同的类型, 你可以随意组合使用它们,组装成你的自定义首页。 如果它们均不满足你的需求,你也可以 编写自定义组件,来自定义你的首页。 ## 配置 ### home * 类型: `boolean` 声明该页面是否为首页 ### config * 类型: `PlumeHomeConfig[]` * 默认值: `[]` 根据数组的顺序定义页面的区域内容。 ```ts interface PlumeHomeConfigBase { /** * 该区域的类型,根据类型应用不同的组件 */ type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom' | string /** * 该区域是否占满全屏 */ full?: boolean /** * 该区域的背景图片 * 你可以定义在 浅色/暗色 模式下的背景图片 */ backgroundImage?: string | { light: string, dark: string } /** * 该区域的背景 定位方式 */ backgroundAttachment?: 'fixed' | 'local' } ``` ## 区域类型 ### banner * 类型: `PlumeThemeHomeBanner` 大屏 banner, 适用于放置在 首页的 首位。 ```ts interface PlumeThemeHomeBanner extends PlumeHomeConfigBase { type: 'banner' /** * 背景大图 */ banner?: string /** * 取值范围: 0 - 1。配置首页 banner 大图的遮罩蒙版不透明度。 * 支持配置 浅色/深色 模式下 的不同值。当值为 0 时,不显示遮罩蒙版。 * 这在首页首屏大图比较亮时,可以适当使图片看起来暗一些。 */ bannerMask?: number | { light?: number, dark?: number } hero?: { name: string tagline?: string text?: string actions?: { theme?: 'brand' | 'alt' text: string link?: string } } } ``` **示例:** ```md --- home: true config: - type: banner banner: https://api.pengzhanbo.cn/wallpaper/bing bannerMask: light: 0.1 dark: 0.3 hero: name: 鹏展博 tagline: Front End Developer text: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。 actions: - text: 我的博客 link: /blog/ theme: brand - text: Github link: https://github.com/pengzhanbo theme: alt --- ``` **效果:** :::demo-wrapper img no-padding ![banner](/images/custom-banner.jpg) ::: ### hero * 类型: `PlumeThemeHomeHero` 适用于 文档 类型站点,放置于 首位。 ```ts interface PlumeThemeHomeHero extends PlumeHomeConfigBase { type: 'hero' hero: { name: string tagline?: string text?: string actions?: { theme?: 'brand' | 'alt' | 'sponsor' text: string link?: string icon?: string // 文本左侧图标 suffixIcon?: string // 文本右侧图标 target?: '_blank' | '_self' | string rel?: string } } /** * 主题内置的背景效果,如果为非预设背景效果,则可以传入背景图片链接地址 */ effect?: 'tint-plate' | 'prism' | 'pixel-blast' | 'hyper-speed' | 'liquid-ether' | 'dot-grid' | 'iridescence' | 'orb' | 'beams' | 'lightning' | string /** * 背景效果配置项,根据 `effect` 值不同,配置项不同 */ effectConfig?: any /** * 如果是非预设背景,可以设置背景图片的滤镜效果 */ filter?: string } ``` [查看 **背景效果 配置 & 演示** 了解更多](./home-hero-effect.md){.read-more} 主题还支持自定义 `name`, `tagline`, `text` 的颜色。 通过 `CSS Vars` 进行配置。 ```css /* 默认设置,可以在 `index.css` 中覆盖 */ :root { /* home hero name 背景色,通过背景色裁剪的方式定义文本颜色, 因此,可以设置渐变背景的方式使文本更具表现力 */ --vp-bg-home-hero-name: linear-gradient(315deg, var(--vp-c-purple-1) 15%, var(--vp-c-brand-2) 65%, var(--vp-c-brand-2) 100%); --vp-c-home-hero-tagline: var(--vp-c-text-2); --vp-c-home-hero-text: var(--vp-c-text-3); } ``` ### doc-hero * 类型: `PlumeThemeHomeDocHero` 适用于 文档 类型站点,放置于 首位。 ```ts interface PlumeThemeHomeDocHero { type: 'doc-hero' hero: { name: string tagline?: string text?: string image?: string | { src: string, alt?: string } | { dark: string, light: string, alt?: string } actions?: { theme?: 'brand' | 'alt' | 'sponsor' text: string link?: string icon?: string // 文本左侧图标 suffixIcon?: string // 文本右侧图标 target?: '_blank' | '_self' | string rel?: string } } } ``` **示例:** ```md --- home: true config: - type: doc-hero hero: name: Theme Plume text: VuePress Next Theme tagline: 一个简约易用的,功能丰富的 vuepress 文档&博客 主题 image: /plume.png actions: - theme: brand text: 快速开始 → link: /guide/intro/ - theme: alt text: Github link: https://github.com/pengzhanbo/vuepress-theme-plume --- ``` **效果:** :::demo-wrapper img no-padding ::: 主题还支持自定义 `name`, `tagline`, `text` 的颜色,以及 `image` 的背景色。 通过 `CSS Vars` 进行配置。 ```css /* 默认设置,可以在 `index.css` 中覆盖 */ :root { --vp-home-hero-name-color: transparent; --vp-home-hero-name-background: linear-gradient(120deg, var(--vp-c-purple-1) 30%, var(--vp-c-brand-2)); --vp-home-hero-tagline: var(--vp-c-text-2); --vp-home-hero-text: var(--vp-c-text-1); --vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-soft) 50%, var(--vp-c-brand-2) 50%); --vp-home-hero-image-filter: blur(44px); } ``` ### features * 类型: `PlumeThemeHomeFeatures` 适用于展示 特性、功能、等。 ```ts interface PlumeThemeHomeFeatures extends PlumeHomeConfigBase { type: 'features' title?: string description?: string features: PlumeThemeHomeFeature[] } interface PlumeThemeHomeFeature { /** * 图标,也支持传入 iconify 图标名 */ icon?: FeatureIcon title: string details?: string link?: string linkText?: string rel?: string target?: string } type FeatureIcon = string | { src: string alt?: string width?: string height?: string wrap?: boolean } | { light: string dark: string alt?: string width?: string height?: string wrap?: boolean } ``` **示例:** ```md --- home: true config: - type: features features: - title: 响应式布局 icon: 💻 details: 适配移动设备,PC,平板 - title: 博客 & 文档 icon: 📖 details: 无论是想写博客,或想写产品文档,或者两者兼顾 - title: 开箱即用 icon: 🚀 details: 支持零配置即可使用,也支持丰富的自定义配置 - title: 多语言 icon: ⚖ details: 内置了 中文/英文支持,还可以自定义添加更多的语言支持 - title: 双色主题 icon: 👨‍💻 details: 支持 浅色/深色 主题,包括代码高亮 - title: 插件 icon: 📦 details: 内置丰富的插件,一站式解决网站一般需求 - title: 搜索、评论 icon: 🔍 details: 支持多种评论系统,支持本地搜索、Algolia搜索 - title: 加密 icon: 🔒 details: 支持全站加密、部分加密(加密目录、加密文章) - title: Markdown 增强 icon: 📝 details: 支持 Markdown 语法,支持 代码块分组、提示容器、任务列表、数学公式、代码演示等 --- ``` **效果:** :::demo-wrapper img no-padding ::: ### text-image | image-text * 类型: `PlumeThemeHomeTextImage` 左右布局的 文本 和 图片。 ```ts interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase { type: 'text-image' | 'image-text' image: PlumeThemeImage width?: number | string title?: string description?: string list: (string | { title?: string, description?: string })[] } type PlumeThemeImage = | string | { src: string, alt?: string } | { dark: string, light: string, alt?: string } ``` **示例:** ```md --- home: true config: - type: image-text title: 功能 description: 内置丰富的功能,满足网站一般需求。 image: /images/plume-1.svg list: - title: 文章信息 description: 为文章添加标签、分类、字数统计、阅读时间、写作日期等信息。 - title: 评论 description: 支持 4 种评论系统,你可以自由选择符合你的需求的评论系统。 - title: 搜索 description: 支持基于 minisearch 的本地搜索, 支持Algolia搜索。 - title: 加密 description: 支持全站加密、部分加密(加密目录、加密文章)。 - title: 代码复制 description: 一键复制代码块中的内容 - type: text-image title: 博客 description: 主题默认支持博客,生成你的个人博客。 image: /images/plume-2.svg list: - title: 文章列表 description: 通过文章写作日期,自动排序并生成博客文章列表页。 - title: 博主信息 description: 自定义名称、座右铭、头像,社交媒体链接。 - title: 标签、归档 description: 自动生成标签页,为文章根据年份进行归档。 --- ``` **效果:** :::demo-wrapper img no-padding ::: :::demo-wrapper img no-padding ::: ### posts 将 post 集合文章列表页 作为一个单独区域,插入到 首页中。 ```ts interface PlumeThemeHomePosts extends PlumeHomeConfigBase { type: 'posts' collection?: string } ``` 当存在多个 post 集合时,默认读取第一个集合的文章列表页。 还可以通过 `collection` 配置项来指定读取哪个集合的文章列表页。 `collection` 的值应该与 集合的 `dir` 值相同。 **示例:** ```md --- home: true config: - type: posts collection: blog --- ``` ### profile * 类型: `PlumeThemeHomeProfile` 展示个人信息。 ```ts interface PlumeThemeHomeProfile extends PlumeHomeConfigBase { type: 'profile' name?: string description?: string avatar?: PlumeThemeImage circle?: boolean } type PlumeThemeImage = | string | { src: string, alt?: string } | { dark: string, light: string, alt?: string } ``` **示例:** ```md --- home: true config: - type: profile name: pengzhanbo description: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。 avatar: /images/avatar.png --- ``` **效果:** :::demo-wrapper img no-padding ::: ### custom * 类型: `PlumeThemeHomeCustom` 自定义内容,在 `README.md` 的 文件中,编写的 markdown 内容,将会被插入到 对应的区域。 ```ts interface PlumeThemeHomeCustom extends PlumeHomeConfigBase { type: 'custom' } ``` **示例:** ````md --- home: true config: - type: custom --- ### 安装 :::code-tabs @tab pnpm ```sh pnpm add vuepress@next vuepress-theme-plume vue ``` @tab npm ```sh npm install vuepress@next vuepress-theme-plume ``` @tab yarn ```sh yarn add vuepress@next vuepress-theme-plume ``` ::: ```` **效果:** :::demo-wrapper img no-padding ::: ## 自定义区域类型 当主题内置的区域类型不足以满足你的需求时,你可以自定义区域类型。 每一个自定义区域类型,本质上都是一个组件。 一个 简单的实例如下: ::: code-tabs @tab your-component.vue ```vue ``` ::: 在 `.vuepress/client.ts` 在 `enhance` 钩子中添加 组件 ::: code-tabs @tab .vuepress/client.ts ```ts import { defineClientConfig } from 'vuepress/client' import YourComponent from 'your-component.vue' export default defineClientConfig({ enhance({ app }) { app.component('your-component', YourComponent) }, }) ``` ::: 然后,你就可以在 `README.md` 中使用 `your-component` 了。 ```md --- home: true config: - type: 'your-component' # ... --- ``` --- --- url: /guide/custom-home/hero-effect/index.md --- # Hero 背景效果 ## 概述 对于大多数的站点而言,一个 **炫酷好看** 首页首屏,能够更容易的吸引用户停留下来。 但实现 **炫酷好看** 往往需要比较复杂的技术成本,以及一些不错的灵感。 主题对 **首页** 的 **Hero** 部分,内置了一系列 **炫酷好看** 的背景效果, 通过简单的配置即可应用到你的站点首页中: ```md {6,8-10} --- pageLayout: home home: true config: - type: hero full: true effect: tint-plate effectConfig: key: value --- ``` ::: important 当且仅当 `type: hero` 时,主题会应用 `effect` 配置的效果。 ::: `effect` 支持以下可选值: * [tint-plate](#tint-plate) * [prism](#prism) * [pixel-blast](#pixel-blast) * [hyper-speed](#hyper-speed) * [liquid-ether](#liquid-ether) * [dot-grid](#dot-grid) * [iridescence](#iridescence) * [orb](#orb) * [beams](#beams) * [lightning](#lightning) * [dark-veil](#dark-veil) `effectConfig` 需要根据不同的 `effect` 值,进行不同的配置。通常你不需要配置,主题会自动应用预设配置。 :::important 重要说明 主题内置的效果,得益于优秀开源项目 [vue-bits](https://vue-bits.dev/)。 遵循 MIT 协议,复制并修改其中的代码到主题中。 ::: ## 强制深色模式 大部分背景效果在 **深色模式** 下表现更加出色,因此建议开启 [深色模式](../../config/theme.md#appearance) 以获得最佳体验。 但对于文档部分,也许 **浅色模式** 才是你想要的,因此主题在 `hero` 中提供了 `forceDark` 选项, 仅强制将首页强制变更为 **深色模式**,而不影响其他页面的颜色模式。 ```md {8} --- pageLayout: home home: true config: - type: hero full: true forceDark: true effect: lightning --- ``` ## 背景动态效果 ::: important 不同的效果可能会依赖 `three` 或 `gsap` 或 `ogl`,你需要根据所使用的效果,手动安装相应的依赖包。 主题通过 **按需加载** 的方式动态加载这些效果, 因此不用担心最终打包后的文档体积过大。 ::: ### tint-plate #### 效果预览 ![tint-plate](/images/hero-effects/tint-plate.png) #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: tint-plate --- ``` #### 配置项 `effectConfig` 用于配置 RGB 值: * 配置为单个值时,表示配置 red,green,blue 三个颜色值为相同值,范围: 0 - 255。示例: `210`。 * 配置为三个值时,表示配置 red,green,blue 三个颜色值为不同值,范围: 0 - 255。示例: `210,210,210`。 * 配置为 `TintPlate`,则可以更加灵活的控制每个颜色值和对应的偏移量。 * 还可以配置为 `{ light: TintPlate, dark: TintPlate }`,在深色模式和浅色模式下使用不同的颜色值。 ```ts interface TintPlate { r: { value: number, offset: number } // value 表示色值,offset 表示偏移量 g: { value: number, offset: number } b: { value: number, offset: number } } ``` **示例**: ::: code-tabs @tab 单个值 ```md {8,9} --- pageLayout: home home: true config: - type: hero full: true effect: tint-plate effectConfig: 210 --- ``` @tab 三个值 ```md {8,9} --- pageLayout: home home: true config: - type: hero full: true effect: tint-plate effectConfig: 210,210,210 --- ``` @tab TintPlate ```md {8-18} --- pageLayout: home home: true config: - type: hero full: true effect: tint-plate effectConfig: r: value: 210 offset: 0 g: value: 210 offset: 0 b: value: 210 offset: 0 --- ``` ::: ::: info 为了便于用户配置 美观的个性化的背景,主题还提供了 [首页背景色板配置工具](../../tools/home-hero-tint-plate.md) 进行可视化操作,生成配置内容,你可以直接复制它们用于自己的项目中。 ::: ### prism #### 效果预览 ![prism](/images/hero-effects/prism.png) #### 安装依赖 :::npm-to ```sh npm i ogl ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: prism --- ``` #### 配置项 :::: field-group :::field name="height" type="number" optional default="3.5" 棱柱的顶点高度(world units) ::: :::field name="baseWidth" type="number" optional default="5.5" X/Z轴总基准宽度(world units) ::: :::field name="animationType" type="'rotate' | 'hover' | '3drotate'" optional default="'rotate'" 动画模式:着色器摆动、指针悬停倾斜或完全三维旋转。 ::: :::field name="glow" type="number" optional default="1" 发光/溢出强度乘数。 ::: :::field name="offset" type="{ x?: number, y?: number }" optional default="{ x: 0, y: 0 }" 画布内的像素偏移(x → 向右,y → 向下)。 ::: :::field name="noise" type="number" optional default="0" 最终颜色中添加的颗粒噪声量(0表示禁用)。 ::: :::field name="transparent" type="boolean" optional default="true" 画布是否具有Alpha通道(透明背景)。 ::: :::field name="scale" type="number" optional default="3.6" 棱镜的整体屏幕空间比例(数值越大,显示尺寸越大)。 ::: :::field name="hueShift" type="number" optional default="0" 色调旋转(弧度)应用于最终颜色。 ::: :::field name="colorFrequency" type="number" optional default="1" 控制颜色变化的内部正弦带频率。 ::: :::field name="hoverStrength" type="number" optional default="2" 悬停倾斜(俯仰/偏航幅度)灵敏度。 ::: :::field name="inertia" type="number" optional default="0.05" 悬停缓动因子(`0 ~ 1`,数值越大响应越灵敏)。 ::: :::field name="bloom" type="number" optional default="1" 在光泽之上叠加额外的绽放效果层次。 ::: :::field name="suspendWhenOffscreen" type="boolean" optional default="true" 当元素不在视口内时暂停渲染。 ::: :::field name="timeScale" type="number" optional default="0.5" 动画全局时间倍率(0=冻结,1=正常)。 ::: :::: **示例**: ```md {8-26} --- pageLayout: home home: true config: - type: hero full: true effect: prism effectConfig: height: 3.5, baseWidth: 5.5 animationType: rotate glow: 1 offset: x: 0 y: 0 noise: 0 transparent: true scale: 3.6 hueShift: 0 colorFrequency: 1 hoverStrength: 2 inertia: 0.05 bloom: 1 suspendWhenOffscreen: true timeScale: 0.5 --- ``` ### pixel-blast #### 效果预览 ![pixel-blast](/images/hero-effects/pixel-blast.png) #### 安装依赖 :::npm-to ```sh npm i three postprocessing ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: pixel-blast --- ``` #### 配置项 ::::field-group :::field name="variant" type="'square' | 'circle' | 'triangle' | 'diamond'" optional default="'square'" 像素形状变体 ::: :::field name="pixelSize" type="number" optional default="4" 基础像素尺寸(根据DPI自动缩放)。 ::: :::field name="color" type="string" optional default="'#5086a1'" 像素颜色 ::: :::field name="antialias" type="boolean" optional default="true" 是否启用抗锯齿 ::: :::field name="patternScale" type="number" optional default="2" 噪声/图案比例 ::: :::field name="patternDensity" type="number" optional default="1" 调整图案密度 ::: :::field name="liquid" type="boolean" optional default="false" 是否启用液体扭曲效果。 ::: :::field name="liquidStrength" type="number" optional default="0.1" 液体扭曲强度 ::: :::field name="liquidRadius" type="number" optional default="1" 液体触摸笔刷半径比例。 ::: :::field name="liquidWobbleSpeed" type="number" optional default="4.5" 液体晃动频率 ::: :::field name="pixelSizeJitter" type="number" optional default="0" 应用于覆盖范围的随机抖动 ::: :::field name="enableRipples" type="boolean" optional default="true" 启用点击涟漪效果 ::: :::field name="rippleIntensityScale" type="number" optional default="1" 纹波强度乘数 ::: :::field name="rippleThickness" type="number" optional default="0.1" 纹波环厚度 ::: :::field name="rippleSpeed" type="number" optional default="0.3" 纹波传播速度 ::: :::field name="autoPauseOffscreen" type="boolean" optional default="true" 当元素不在视口内时自动暂停渲染 ::: :::field name="speed" type="number" optional default="0.5" 动画时间缩放比例 ::: :::field name="transparent" type="boolean" optional default="true" 透明背景 ::: :::field name="edgeFade" type="number" optional default="0.5" 边缘淡入距离(`0-1`)。 ::: :::field name="noiseAmount" type="number" optional default="0" 噪声强度 ::: :::field name="className" type="string" optional 容器自定义类名 ::: :::field name="style" type="CSSProperties" optional 容器自定义样式 ::: :::field name="backgroundImage" type="string" optional 背景图像 URL ::: :::: **示例**: ```md {8-29} --- pageLayout: home home: true config: - type: hero full: true effect: pixel-blast effectConfig: variant: square pixelSize: 4 color: #5086a1 antialias: true patternScale: 2 patternDensity: 1 liquid: false liquidStrength: 0.1 liquidRadius: 1 pixelSizeJitter: 0 enableRipples: true rippleIntensityScale: 1 rippleThickness: 0.1 rippleSpeed: 0.3 liquidWobbleSpeed: 4.5 autoPauseOffscreen: true speed: 0.5 transparent: true edgeFade: 0.5 noiseAmount: 0 --- ``` ### hyper-speed #### 效果预览 ![hyper-speed](/images/hero-effects/hyper-speed.png) #### 安装依赖 :::npm-to ```sh npm i three postprocessing ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed --- ``` #### 配置项 ```ts interface ThemeHomeHeroHyperSpeedDistortion { uniforms: Record getDistortion: string } interface ThemeHomeHeroHyperSpeedColors { roadColor: number islandColor: number background: number shoulderLines: number brokenLines: number leftCars: number[] rightCars: number[] sticks: number } interface ThemeHomeHeroHyperSpeed { distortion?: string | ThemeHomeHeroHyperSpeedDistortion length: number roadWidth: number islandWidth: number lanesPerRoad: number fov: number fovSpeedUp: number speedUp: number carLightsFade: number totalSideLightSticks: number lightPairsPerRoadWay: number shoulderLinesWidthPercentage: number brokenLinesWidthPercentage: number brokenLinesLengthPercentage: number lightStickWidth: [number, number] lightStickHeight: [number, number] movingAwaySpeed: [number, number] movingCloserSpeed: [number, number] carLightsLength: [number, number] carLightsRadius: [number, number] carWidthPercentage: [number, number] carShiftX: [number, number] carFloorSeparation: [number, number] colors: ThemeHomeHeroHyperSpeedColors isHyper?: boolean } ``` :::warning [vue-bits](https://vue-bits.dev/backgrounds/hyperspeed) 未提供详细配置项说明,请谨慎使用。 ::: 可以使用以下预设配置,直接复制到你的 markdown 文件中: :::code-tabs @tab Cyberpunk ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: turbulentDistortion length: 400 roadWidth: 10 islandWidth: 2 lanesPerRoad: 3 fov: 90 fovSpeedUp: 150 speedUp: 2 carLightsFade: 0.4 totalSideLightSticks: 20 lightPairsPerRoadWay: 40 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.12, 0.5] lightStickHeight: [1.3, 1.7] movingAwaySpeed: [60, 80] movingCloserSpeed: [-120, -160] carLightsLength: [12, 80] carLightsRadius: [0.05, 0.14] carWidthPercentage: [0.3, 0.5] carShiftX: [-0.8, 0.8] carFloorSeparation: [0, 5] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318 leftCars: [0xd856bf, 0x6750a2, 0xc247ac] rightCars: [0x03b3c3, 0x0e5ea5, 0x324555] sticks: 0x03b3c3 --- ``` @tab Akira ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: mountainDistortion length: 400 roadWidth: 9 islandWidth: 2 lanesPerRoad: 3 fov: 90 fovSpeedUp: 150 speedUp: 2 carLightsFade: 0.4 totalSideLightSticks: 50 lightPairsPerRoadWay: 50 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.12, 0.5] lightStickHeight: [1.3, 1.7] movingAwaySpeed: [60, 80] movingCloserSpeed: [-120, -160] carLightsLength: [20, 60] carLightsRadius: [0.05, 0.14] carWidthPercentage: [0.3, 0.5] carShiftX: [-0.2, 0.2] carFloorSeparation: [0.05, 1] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318 leftCars: [0xff102a, 0xeb383e, 0xff102a] rightCars: [0xdadafa, 0xbebae3, 0x8f97e4] sticks: 0xdadafa --- ``` @tab Golden ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: xyDistortion length: 400 roadWidth: 9 islandWidth: 2 lanesPerRoad: 3 fov: 90 fovSpeedUp: 150 speedUp: 3 carLightsFade: 0.4 totalSideLightSticks: 50 lightPairsPerRoadWay: 30 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.02, 0.05] lightStickHeight: [0.3, 0.7] movingAwaySpeed: [20, 50] movingCloserSpeed: [-150, -230] carLightsLength: [20, 80] carLightsRadius: [0.03, 0.08] carWidthPercentage: [0.1, 0.5] carShiftX: [-0.5, 0.5] carFloorSeparation: [0, 0.1] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318, leftCars: [0x7d0d1b, 0xa90519, 0xff102a] rightCars: [0xf1eece, 0xe6e2b1, 0xdfd98a] sticks: 0xf1eece --- ``` @tab Split ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: LongRaceDistortion length: 400 roadWidth: 10 islandWidth: 5 lanesPerRoad: 2 fov: 90 fovSpeedUp: 150 speedUp: 2 carLightsFade: 0.4 totalSideLightSticks: 50 lightPairsPerRoadWay: 70 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.12, 0.5] lightStickHeight: [1.3, 1.7] movingAwaySpeed: [60, 80] movingCloserSpeed: [-120, -160] carLightsLength: [20, 60] carLightsRadius: [0.05, 0.14] carWidthPercentage: [0.3, 0.5] carShiftX: [-0.2, 0.2] carFloorSeparation: [0.05, 1] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318 leftCars: [0xff5f73, 0xe74d60, 0xff102a] rightCars: [0xa4e3e6, 0x80d1d4, 0x53c2c6] sticks: 0xa4e3e6 --- ``` @tab Highway ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: turbulentDistortion length: 400 roadWidth: 9 islandWidth: 2 lanesPerRoad: 3 fov: 90 fovSpeedUp: 150 speedUp: 2 carLightsFade: 0.4 totalSideLightSticks: 50 lightPairsPerRoadWay: 50 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.12, 0.5] lightStickHeight: [1.3, 1.7] movingAwaySpeed: [60, 80] movingCloserSpeed: [-120, -160] carLightsLength: [20, 60] carLightsRadius: [0.05, 0.14] carWidthPercentage: [0.3, 0.5] carShiftX: [-0.2, 0.2] carFloorSeparation: [0.05, 1] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318 leftCars: [0xdc5b20, 0xdca320, 0xdc2020] rightCars: [0x334bf7, 0xe5e6ed, 0xbfc6f3] sticks: 0xc5e8eb --- ``` @tab Deep ```md --- pageLayout: home home: true config: - type: hero full: true effect: hyper-speed effectConfig: distortion: deepDistortion length: 400 roadWidth: 18 islandWidth: 2 lanesPerRoad: 3 fov: 90 fovSpeedUp: 150 speedUp: 2 carLightsFade: 0.4 totalSideLightSticks: 50 lightPairsPerRoadWay: 50 shoulderLinesWidthPercentage: 0.05 brokenLinesWidthPercentage: 0.1 brokenLinesLengthPercentage: 0.5 lightStickWidth: [0.12, 0.5] lightStickHeight: [1.3, 1.7] movingAwaySpeed: [60, 80] movingCloserSpeed: [-120, -160] carLightsLength: [20, 60] carLightsRadius: [0.05, 0.14] carWidthPercentage: [0.3, 0.5] carShiftX: [-0.2, 0.2] carFloorSeparation: [0.05, 1] colors: roadColor: 0x080808 islandColor: 0x0a0a0a background: 0x000000 shoulderLines: 0x131318 brokenLines: 0x131318 leftCars: [0xff322f, 0xa33010, 0xa81508] rightCars: [0xfdfdf0, 0xf3dea0, 0xe2bb88] sticks: 0xfdfdf0 --- ``` ::: ### liquid-ether #### 效果预览 ![liquid-ether](/images/hero-effects/liquid-ether.png) #### 安装依赖 :::npm-to ```sh npm i three ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: liquid-ether --- ``` #### 配置项 ::::field-group :::field name="mouseForce" type="number" optional default="20" 鼠标/触摸移动注入速度时的强度系数。 ::: :::field name="cursorSize" type="number" optional default="100" 光标半径(以基本分辨率的像素为单位)。 ::: :::field name="isViscous" type="boolean" optional default="false" 启用迭代性质量解决方案(更平滑,更粗糙的运动)。 ::: :::field name="viscous" type="number" optional default="30" 当 `isViscous` 为 `true` 时使用的粘性系数。 ::: :::field name="iterationsViscous" type="number" optional default="32" 粘性的高斯-塞德尔迭代次数(值越大 = 更平滑,更慢)。 ::: :::field name="iterationsPoisson" type="number" optional default="32" 用于确保不可压缩性的压力泊松迭代次数。 ::: :::field name="dt" type="number" optional default="0.014" 内部的对流/扩散迭代中使用固定的模拟时间步长。 ::: :::field name="BFECC" type="boolean" optional default="true" 启用 BFECC 传输(错误补偿)以获得更清晰的流动,禁用以获得稍微的性能提升。 ::: :::field name="resolution" type="number" optional default="0.5" 相对于画布大小的仿真纹理缩放(值越小,更好的性能、更模糊)。 ::: :::field name="isBounce" type="boolean" optional default="false" 如果为 true,显示弹跳边界(速度在边缘上限)。 ::: :::field name="colors" type="string\[]" optional default="\['#5227FF', '#FF9FFC', '#B19EEF']" 用于构建速度-颜色映射调色板的十六进制颜色停止点数组。 ::: :::field name="autoDemo" type="boolean" optional default="true" 启用无用户交互时的自动驾驶指针。 ::: :::field name="autoSpeed" type="number" optional default="0.5" 自动指针运动的速度(标准化单位/秒)。 ::: :::field name="autoIntensity" type="number" optional default="2.2" 在自动模式下应用于速度增量的乘数。 ::: :::field name="takeoverDuration" type="number" optional default="2.5" 在用户移动鼠标时从自动指针插值到实际光标的秒数。 ::: :::field name="autoResumeDelay" type="number" optional default="1000" 在自动模式恢复之前的不活动时间(毫秒)。 ::: :::field name="autoRampDuration" type="number" optional default="0.6" 在激活后从 0 开始加速自动移动速度的秒数。 ::: :::field name="className" type="string" optional 应用于容器上的 CSS 类名。 ::: :::field name="style" type="CSSProperties" optional 应用于容器上的 CSS 样式。 ::: :::: **示例**: ```md --- pageLayout: home home: true config: - type: hero full: true effect: liquid-ether effectConfig: mouseForce: 20 cursorSize: 100 isViscous: false viscous: 30 iterationsViscous: 32 iterationsPoisson: 32 dt: 0.014 BFECC: true resolution: 0.5 isBounce: false colors: [#5227FF, #FF9FFC, #B19EEF] autoDemo: true autoSpeed: 0.5 autoIntensity: 2.2 takeoverDuration: 0.25 autoResumeDelay: 1000 autoRampDuration: 0.6 --- ``` ### dot-grid #### 效果预览 ![dot-grid](/images/hero-effects/dot-grid.png) #### 安装依赖 :::npm-to ```sh npm i three gsap ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: dot-grid --- ``` #### 配置项 ::::field-group :::field name="dotSize" type="number" optional default="5" 每个点的尺寸(像素)。 ::: :::field name="gap" type="number" optional default="15" 每个点之间的间隙(像素)。 ::: :::field name="baseColor" type="string" optional default="'#ebebf5'" 点的基本颜色。 ::: :::field name="activeColor" type="string" optional default="'#8cccd5'" 鼠标悬停或激活时点的颜色。 ::: :::field name="proximity" type="number" optional default="120" 鼠标指针周围的半径,在此范围内点会响应 ::: :::field name="speedTrigger" type="number" optional default="100" 触发惯性效果的鼠标速度阈值。 ::: :::field name="shockRadius" type="number" optional default="250" 点击时的震动波半径。 ::: :::field name="shockStrength" type="number" optional default="5" 点击时震动波的强度。 ::: :::field name="maxSpeed" type="number" optional default="5000" 惯性计算的最大速度。 ::: :::field name="resistance" type="number" optional default="750" 惯性效果的阻力 ::: :::field name="returnDuration" type="number" optional default="1.5" 惯性后点返回原始位置的持续时间。 ::: :::field name="className" type="string" optional 应用于容器上的 CSS 类名。 ::: :::field name="style" type="CSSProperties" optional 应用于容器上的 CSS 样式。 ::: :::: **示例**: ```md --- pageLayout: home home: true config: - type: hero full: true effect: dot-grid effectConfig: dotSize: 5 gap: 15 baseColor: #ebebf5 activeColor: #8cccd5 proximity: 120 speedTrigger: 100 shockRadius: 250 shockStrength: 5 maxSpeed: 5000 resistance: 750 returnDuration: 1.5 --- ``` ### iridescence #### 效果预览 ![iridescence](/images/hero-effects/iridescence.png) #### 安装依赖 :::npm-to ```sh npm i ogl ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: iridescence --- ``` #### 配置项 ::::field-group :::field name="color" type="readonly \[number, number, number]" optional default="\[1, 1, 1]" 基准色以 RGB 值数组形式表示(每个数值范围在 `0` 到 `1` 之间)。 ::: :::field name="speed" type="number" optional default="1" 动画的速度乘数 ::: :::field name="amplitude" type="number" optional default="0.1" 鼠标驱动效果的振幅。 ::: :::field name="mouseReact" type="boolean" optional default="true" 启用或禁用鼠标与着色器的交互 ::: :::: **示例**: ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: iridescence effectConfig: color: [1, 1, 1] speed: 1.0 amplitude: 0.1 mouseReact: true --- ``` ### orb #### 效果预览 ![orb](/images/hero-effects/orb.png) #### 安装依赖 :::npm-to ```sh npm i ogl ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: orb --- ``` #### 配置项 ::::field-group :::field name="hue" type="number" optional default="0" 球的基本色调(度)。 ::: :::field name="hoverIntensity" type="number" optional default="0.2" 控制悬停扭曲效果的强度。 ::: :::field name="rotateOnHover" type="boolean" optional default="true" 启用或禁用悬停时的持续旋转。 ::: :::field name="forceHoverState" type="boolean" optional default="false" 即使没有悬停,也强制启用悬停动画。 ::: :::field name="className" type="string" optional 应用于容器上的 CSS 类名。 ::: :::: **示例**: ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: orb effectConfig: hue: 0 hoverIntensity: 0.2 rotateOnHover: true forceHoverState: false --- ``` ### beams #### 效果预览 ![beams](/images/hero-effects/beams.png) #### 安装依赖 :::npm-to ```sh npm i three ``` ::: #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: beams --- ``` #### 配置项 ::::field-group :::field name="beamWidth" type="number" optional default="2" 每个激光束的宽度。 ::: :::field name="beamHeight" type="number" optional default="15" 每个激光束的高度。 ::: :::field name="beamNumber" type="number" optional default="12" 要显示的激光束数量。 ::: :::field name="lightColor" type="string" optional default="#fff" 方向光的颜色。 ::: :::field name="speed" type="number" optional default="2" 动画的速度。 ::: :::field name="noiseIntensity" type="number" optional default="1.75" 噪音效果的强度。 ::: :::field name="scale" type="number" optional default="0.2" 噪音模式的缩放比例。 ::: :::field name="rotation" type="number" optional default="0" 整个激光束系统的旋转角度(度)。 ::: :::: **示例**: ```md --- pageLayout: home home: true config: - type: hero full: true effect: beams effectConfig: beamWidth: 2 beamHeight: 15 beamNumber: 12 lightColor: #fff speed: 2 noiseIntensity: 1.75 scale: 0.2 rotation: 0 --- ``` ### lightning #### 效果预览 ![lightning](/images/hero-effects/lightning.png) #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: lightning --- ``` #### 配置项 ::::field-group :::field name="hue" type="number" optional default="255" 光束的色调(度)(0到360)。 ::: :::field name="xOffset" type="number" optional default="0" 光束的水平偏移量(标准化单位)。 ::: :::field name="speed" type="number" optional default="1" 光束的动画速度乘数。 ::: :::field name="intensity" type="number" optional default="1" 光束的亮度乘数。 ::: :::field name="size" type="number" optional default="1" 光束的缩放因子。 ::: :::: **示例**: ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: lightning effectConfig: hue: 255 xOffset: 0 speed: 1 intensity: 1 size: 1 --- ``` ### dark-veil #### 效果预览 ![dark-veil](/images/hero-effects/dark-veil.png) #### 使用方法 ```md {8} --- pageLayout: home home: true config: - type: hero full: true effect: dark-veil --- ``` #### 配置项 ::::field-group :::field name="hueShift" type="number" optional default="0" 调整整个动画的色调。 ::: :::field name="noiseIntensity" type="number" optional default="0" 噪声/颗粒效果的强度。 ::: :::field name="scanlineIntensity" type="number" optional default="0" 扫描线效果的强度。 ::: :::field name="speed" type="number" optional default="0.5" 动画速度。 ::: :::field name="scanlineFrequency" type="number" optional default="0" 扫描线的频率。 ::: :::field name="warpAmount" type="number" optional default="0" 应用于效果的扭曲变形量。 ::: :::field name="resolutionScale" type="number" optional default="1" 分辨率缩放比例。 ::: :::: **示例**: ```md --- pageLayout: home home: true config: - type: hero full: true effect: dark-veil effectConfig: hueShift: 0 noiseIntensity: 0 scanlineIntensity: 0 speed: 0.5 scanlineFrequency: 0 warpAmount: 0 resolutionScale: 1 --- ``` --- --- url: /guide/custom-style/index.md --- # 自定义样式 ## 主题定制 支持自定义样式。 主题虽然使用 [SASS](https://sass-lang.com/) 作为 CSS 预处理器,但所有的颜色使用的是 `CSS Vars` 定义, 因此,你可以创建 一个 css 文件 或 scss 文件,进行覆盖。 首先,在 `.vuepress` 目录中,创建一个 `styles/index.css` 文件, 然后在 [客户端配置文件](https://v2.vuepress.vuejs.org/zh/guide/configuration.html#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) 中,引入该文件即可。 :::code-tabs @tab .vuepress/client.ts ```ts import { defineClientConfig } from 'vuepress/client' import './styles/index.css' // [!code ++] export default defineClientConfig({ // ... }) ``` @tab .vuepress/styles/index.css ```css :root { --vp-c-brand-1: #5086a1; } ``` ::: ## Style 文件 在 `.vuepress` 目录中,创建一个如 `custom.css` 的文件, 在这里添加额外的样式,或者覆盖默认样式: ```scss :root { scroll-behavior: smooth; } ``` 你也可以利用它来覆盖默认主题的预定义 CSS 变量。 以下是部分预定义变量, 完整列表请参考 [vars.css](https://github.com/pengzhanbo/vuepress-theme-plume/blob/main/theme/src/client/styles/vars.css) ```scss :root { /** 主题颜色 */ --vp-c-brand-1: #5086a1; --vp-c-brand-2: #6aa1b7; --vp-c-brand-3: #8cccd5; --vp-c-brand-soft: rgba(131, 208, 218, 0.314); /** 背景颜色 */ --vp-c-bg: #ffffff; --vp-c-bg-alt: #f6f6f7; --vp-c-bg-elv: #ffffff; --vp-c-bg-soft: #f6f6f7; /** 文本颜色 */ --vp-c-text-1: rgba(60, 60, 67); --vp-c-text-2: rgba(60, 60, 67, 0.78); --vp-c-text-3: rgba(60, 60, 67, 0.56); } [data-theme="dark"] { --vp-c-brand-1: #8cccd5; --vp-c-brand-2: #6aa1b7; --vp-c-brand-3: #5086a1; --vp-c-brand-soft: rgba(131, 208, 218, 0.314); --vp-c-bg: #1b1b1f; --vp-c-bg-alt: #161618; --vp-c-bg-elv: #202127; --vp-c-bg-soft: #202127; --vp-c-text-1: rgba(255, 255, 245, 0.86); --vp-c-text-2: rgba(235, 235, 245, 0.6); --vp-c-text-3: rgba(235, 235, 245, 0.38); } ``` ::: tip 主题提供了 [主题颜色工具](../../../tools/custom-theme.md) , 你可以使用它来创建自定义颜色。 ::: --- --- url: /guide/deployment/index.md --- ::: tip 此文档 fork 自 [vuepress official doc](https://v2.vuepress.vuejs.org/zh/guide/deployment.html)。 ::: 下述的指南基于以下条件: * Markdown 源文件放置在你项目的 `docs` 目录; * 使用的是默认的构建输出目录 (`.vuepress/dist`) ; * 使用 [pnpm](https://pnpm.io/zh/) 作为包管理器,当然也支持使用 npm 或 yarn 。 * VuePress 作为项目依赖安装,并在 `package.json` 中配置了如下脚本: ```json { "scripts": { "docs:build": "vuepress build docs" } } ``` ## GitHub Pages ::: steps 1. 设置正确的 [base](https://v2.vuepress.vuejs.org/zh/reference/config.html#base) 选项。 如果你准备发布到 `https://.github.io/` ,你可以省略这一步,因为 `base` 默认就是 `"/"` 。 如果你准备发布到 `https://.github.io//` ,也就是说你的仓库地址是 `https://github.com//` ,则将 `base` 设置为 `"//"`。 2. 选择你想要使用的 CI 工具。这里我们以 [GitHub Actions](https://github.com/features/actions) 为例。 创建 `.github/workflows/docs.yml` 文件来配置工作流。 ::: ::: details 点击展开配置样例 ```yaml name: docs on: # 每当 push 到 main 分支时触发部署 push: branches: [main] # 手动触发部署 workflow_dispatch: jobs: docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: # “最近更新时间” 等 git 日志相关信息,需要拉取全部提交记录 fetch-depth: 0 - name: Setup pnpm uses: pnpm/action-setup@v4 with: # 选择要使用的 pnpm 版本 version: 10 # 使用 pnpm 安装依赖 run_install: true - name: Setup Node.js uses: actions/setup-node@v4 with: # 选择要使用的 node 版本 node-version: 22 # 缓存 pnpm 依赖 cache: pnpm # 运行构建脚本 - name: Build VuePress site run: pnpm docs:build # 查看 workflow 的文档来获取更多信息 # @see https://github.com/crazy-max/ghaction-github-pages - name: Deploy to GitHub Pages uses: crazy-max/ghaction-github-pages@v4 with: # 部署到 gh-pages 分支 target_branch: gh-pages # 部署目录为 VuePress 的默认输出目录 build_dir: docs/.vuepress/dist env: # @see https://docs.github.com/cn/actions/reference/authentication-in-a-workflow#about-the-github_token-secret GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` ::: ::: tip 请参考 [GitHub Pages 官方指南](https://pages.github.com/) 来获取更多信息。 ::: ## GitLab Pages ::: steps 1. 设置正确的 [base](https://v2.vuepress.vuejs.org/zh/reference/config.html#base) 选项。 如果你准备发布到 `https://.gitlab.io/` ,你可以省略这一步,因此 `base` 默认就是 `"/"` 。 如果你准备发布到 `https://.gitlab.io//` ,也就是说你的仓库地址是 `https://gitlab.com//` ,则将 `base` 设置为 `"//"`。 2. 创建 `.gitlab-ci.yml` 文件来配置 [GitLab CI](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) 工作流。 ::: ::: details 点击展开配置样例 ```yaml # 选择你要使用的 docker 镜像 image: node:22-buster pages: # 每当 push 到 main 分支时触发部署 only: - main # 缓存 node_modules cache: key: files: - pnpm-lock.yaml paths: - .pnpm-store # 安装 pnpm before_script: - curl -fsSL https://get.pnpm.io/install.sh | sh - - pnpm config set store-dir .pnpm-store # 安装依赖并运行构建脚本 script: - pnpm install --frozen-lockfile - pnpm docs:build --dest public artifacts: paths: - public ``` ::: ::: tip 请参考 [GitLab Pages 官方指南](https://docs.gitlab.com/ce/user/project/pages/#getting-started) 来获取更多信息。 ::: ## Google Firebase ::: steps 1. 请确保你已经安装了 [firebase-tools](https://www.npmjs.com/package/firebase-tools)。 2. 在你项目的根目录下创建 `firebase.json` 和 `.firebaserc`,并包含以下内容: ```json title="firebase.json" { "hosting": { "public": "./docs/.vuepress/dist", "ignore": [] } } ``` ```json title=".firebaserc" { "projects": { "default": "" } } ``` 3. 在执行了 `pnpm docs:build` 后, 使用 `firebase deploy` 指令来部署。 ::: ::: tip 请参考 [Firebase CLI 官方指南](https://firebase.google.com/docs/cli) 来获取更多信息。 ::: ## Heroku ::: steps 1. 首先安装 [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli); 2. [在这里](https://signup.heroku.com) 注册一个 Heroku 账号; 3. 运行 `heroku login` 并填写你的 Heroku 认证信息: ```bash heroku login ``` 4. 在你的项目根目录中,创建一个名为 `static.json` 的文件,并包含下述内容: ```json title="static.json" { "root": "./docs/.vuepress/dist" } ``` 这里是你项目的配置,请参考 [heroku-buildpack-static](https://github.com/heroku/heroku-buildpack-static) 来获取更多信息。 ::: ## Kinsta 请查看 [Set Up VuePress on Kinsta](https://kinsta.com/docs/vuepress-application/) 。 ## Edgio 请查看 [Edgio Documentation > Framework Guides > VuePress](https://docs.edg.io/guides/vuepress) 。 ## Netlify ::: steps 1. 前往 [Netlify](https://netlify.com) ,从 GitHub 创建一个新项目,并进行如下配置: * **Build Command:** `pnpm docs:build` * **Publish directory:** `docs/.vuepress/dist` 2. 设置 [Environment variables](https://docs.netlify.com/configure-builds/environment-variables) 来选择 Node 版本: * `NODE_VERSION`: 22 3. 点击 deploy 按钮。 ::: ## Vercel ::: steps 1. 前往 [Vercel](https://vercel.com) ,从 GitHub 创建一个新项目,并进行如下配置: * **FRAMEWORK PRESET:** `Other` * **BUILD COMMAND:** `pnpm docs:build` * **OUTPUT DIRECTORY:** `docs/.vuepress/dist` 2. 点击 deploy 按钮。 ::: ## 云开发 CloudBase [云开发 CloudBase](https://cloudbase.net/?site=vuepress) 是一个云原生一体化的 Serverless 云平台, 支持静态网站、容器等多种托管能力,并提供简便的部署工具 [CloudBase Framework](https://cloudbase.net/framework.html?site=vuepress) 来一键部署应用。 ::: steps 1. 全局安装 CloudBase CLI : ```bash pnpm install -g @cloudbase/cli ``` 2. 在项目根目录运行以下命令一键部署 VuePress 应用,在部署之前可以先 [开通环境](https://console.cloud.tencent.com/tcb/env/index?tdl_anchor=ad\&tdl_site=vuejs): ```bash cloudbase init --without-template cloudbase framework:deploy ``` ::: CloudBase CLI 首先会跳转到控制台进行登录授权,然后将会交互式进行确认。 确认信息后会立即进行部署,部署完成后,可以获得一个自动 SSL,CDN 加速的网站应用,你也可以搭配使用 GitHub Action 来持续部署 GitHub 上的 VuePress 应用。 也可以使用 `cloudbase init --template vuepress` 快速创建和部署一个新的 VuePress 应用。 ::: tip 更多详细信息请查看 CloudBase Framework 的[部署项目示例](https://github.com/TencentCloudBase/cloudbase-framework?site=vuepress#%E9%A1%B9%E7%9B%AE%E7%A4%BA%E4%BE%8B) ::: ## 21 云盒子 请查看 [21 云盒子 - 部署一个 VuePress 静态网页](https://www.21yunbox.com/docs/#/deploy-vuepress)。 --- --- url: /guide/embed/audio/reader/index.md --- # Audio Reader 音频 ## 概述 主题支持在文档中嵌入 音频阅读 。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 **音频阅读** 并不是一个音乐播放器,它仅是在内容中嵌入一个( @[audioReader](https://sensearch.baidu.com/gettts?lan=en\&spd=3\&source=alading\&text=audio) )按钮,点击后播放一段音频。 它适合用于播放一些短时间的音频,比如 **单词标音** 。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { audioReader: true, // [!code ++] }, }) }) ``` ## markdown 语法 音频嵌入 markdown 语法是一个 行内语法,因此你可以在 markdown 的任何地方中使用。 ```md @[audioReader](src) ``` 添加配置项: ```md @[audioReader type="audio/mpeg" title="title" autoplay start-time="0" end-time="10" volume="0.7"](src) ``` **配置说明:** * `type`:音频类型,格式如:`audio/mpeg` , 默认根据音频链接地址的文件扩展名推断,如果链接地址中不包含扩展名,请手动声明。 * `title`: 音频标题,显示在音频图标之前。 * `autoplay`:是否自动播放,不建议启用。 * `start-time`:音频起始播放时间点,单位为 秒。 * `end-time`:音频结束播放时间点,单位为 秒。 * `volume`:音频播放音量,范围为 `0 ~ 1` 。 ## 全局组件 主题提供了全局组件 `` 以支持更灵活丰富的使用方式。 ### Props | 字段 | 类型 | 描述 | | --------- | --------- | ----------------------------------- | | src | `string` | 必填,音频播放地址 | | type | `string` | 选填,音频格式,默认从 `src` 中截取 | | autoplay | `boolean` | 选填,是否自动播放,不建议启用 | | startTime | `number` | 选填,音频起始播放时间点,单位为 秒 | | endTime | `number` | 选填,音频结束播放时间点,单位为 秒 | | volume | `number` | 选填,音频播放音量,范围为 `0 ~ 1` | ## 示例 **输入:** ```md audio 美 [ˈɔːdioʊ] @[audioReader](/audio/audio.mp3) ``` **输出:** audio 美 \[ˈɔːdioʊ] @[audioReader](https://sensearch.baidu.com/gettts?lan=en\&spd=3\&source=alading\&text=audio) **输入:** ```md audio 美 @[audioReader title="[ˈɔːdioʊ]"](/audio/audio.mp3) ``` **输出:** audio 美 @[audioReader title="\[ˈɔːdioʊ\]"](https://sensearch.baidu.com/gettts?lan=en\&spd=3\&source=alading\&text=audio) **输入:** ```md audio 美 [ˈɔːdioʊ] ``` **输出:** audio 美 \[ˈɔːdioʊ] --- --- url: /guide/embed/pdf/index.md --- # PDF 阅读 ## 概述 主题支持在 markdown 中嵌入 PDF 文件,它能够在页面中直接阅读 PDF 。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { pdf: true, // [!code ++] }, }) }) ``` ## 语法 最简单的语法如下: ```md @[pdf](url) ``` 当需要打开特定页面时,在 `pdf` 后面跟随一个 页数。 ```md @[pdf 2](url) ``` 还可以添加更多的 选项到 `@[pdf ]` 中,更灵活的控制行为。 ```md @[pdf 2 no-toolbar width="100%" height="400px" ratio="16:9" zoom="100"](url) ``` * `no-toolbar` - 不显示工具栏 * `width` - 宽度,默认为 100% * `height` - 高度,默认为 `auto` * `ratio` - 宽高比, 默认为 `16:9`, 仅当未指定高度时生效 * `zoom` - 缩放比例, 百分比。 ## 示例 ### 默认 输入: ```md @[pdf](https://plume.pengzhanbo.cn/files/sample.pdf) ``` 输出: @[pdf](/files/sample.pdf) ### 设置页码为 2 输入: ```md @[pdf 2](https://plume.pengzhanbo.cn/files/sample.pdf) ``` 输出: @[pdf 2 zoom="95"](/files/sample.pdf) ### 不显示工具栏 输入: ```md @[pdf no-toolbar](https://plume.pengzhanbo.cn/files/sample.pdf) ``` 输出: @[pdf no-toolbar](/files/sample.pdf) ### 缩放比 90% 输入: ```md @[pdf zoom="90"](https://plume.pengzhanbo.cn/files/sample.pdf) ``` 输出: @[pdf zoom="90"](/files/sample.pdf) ### 宽高比 21:29 输入: ```md @[pdf zoom="95" ratio="21:29"](https://plume.pengzhanbo.cn/files/sample.pdf) ``` 输出: @[pdf zoom="95" ratio="21:29"](/files/sample.pdf) --- --- url: /guide/embed/video/acfun/index.md --- # AcFun 视频 ## 概述 主题提供了 嵌入 AcFun 视频 的功能。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { acfun: true, // [!code ++] }, }) }) ``` ## 语法 简单的语法: ```md @[acfun](id) ``` 更多选项: ```md @[acfun width="100%" height="400px" ratio="16:9"](id) ``` **选项说明:** * id: 视频 ID * width: 视频宽度 * height: 视频高度 * ratio: 视频比例,默认 `16:9` ## 示例 ### 宽频视频 输入: ```md @[acfun](ac47431669) ``` 输出: @[acfun](ac47431669) --- --- url: /guide/embed/video/artplayer/index.md --- # ArtPlayer 视频 ## 概述 主题提供嵌入 自定义来源视频 的功能。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { artPlayer: true, // [!code ++] }, }) }) ``` ## 安装 该功能依赖于 `artplayer` 播放器实现,主题默认不安装该依赖,在启用 `artPlayer` 功能时,需要 进行手动安装 ::: npm-to ```sh npm i artplayer ``` ::: artPlayer 播放器默认支持 `'mp4'`, `'mp3'`, `'webm'`, `'ogg'` 格式的视频格式。 同时还支持扩展其他格式的支持。 如果您的视频格式为 `'mpd'`, `'dash'`, 还需要再手动安装 `dashjs` : ::: npm-to ```sh npm i dashjs ``` ::: 如果您的视频格式为 `'m3u8'`, `'hls'`, 还需要再手动安装 `hls.js` : ::: npm-to ```sh npm i hls.js ``` ::: 如果您的视频格式为 `'ts'`, `'flv'`, 还需要再手动安装 `mpegts.js` : ::: npm-to ```sh npm i mpegts.js ``` ::: ## markdown 语法 ```md @[artPlayer](src) ``` 添加配置项: ```md @[artPlayer muted autoplay loop width="100%" height="400px" ratio="16:9"](src) ``` * `src`: 视频链接地址 **配置项说明:** * `width`: 视频宽度 * `height`: 视频高度 * `ratio`: 视频比例,默认 `16:9` * `type`: 视频格式,默认从视频链接的文件地址中解析获取 * `autoplay`: 是否自动播放 * `muted`: 是否静音,autoplay 时,默认为 `true` * `volume`: 音量大小,范围为 `0 - 1` * `poster`:视频封面图链接地址 * `auto-mini`: 当播放器滚动到浏览器视口以外时,自动进入 `迷你播放` 模式 ## 全局组件 主题提供了全局组件 `` 以支持更灵活丰富的使用方式。 ### Props |字段 |类型 |描述 | | -- | -- | -- | | src | `string` | 必填,视频播放地址 | | type | `string` | 选填,视频格式,默认从 `src` 中截取 | | width | `string` | 选填, 宽度, 默认 `100%` | | height | `string` | 选填,高度 | | ratio | `string` | 选填,宽高比,默认 `16:9` | 更多 `Props` 请参考 [artPlayer 文档](https://artplayer.org/document/start/option.html) 主题支持所有选项。 ## 示例 ::: tip 说明 示例中的视频资源来自 [artplayer.org](https://artplayer.org) 。 ::: **输入:** ```md @[artPlayer](https://artplayer.org/assets/sample/video.mp4) ``` **输出:** @[artPlayer](https://artplayer.org/assets/sample/video.mp4) **输入:** ```md ``` **输出:** ## 说明 markdown 语法 `@[artPlayer](src)` 在主题内部转换为了 `` 组件,它等价于 ```md ``` --- --- url: /guide/embed/video/bilibili/index.md --- # Bilibili 视频 ## 概述 主题提供了 嵌入 Bilibili 视频 的功能。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdownPower.md) 提供支持。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { bilibili: true, // [!code ++] }, }) }) ``` ## 语法 简单的语法: ```md @[bilibili](bvid) ``` 带 分P 的视频,在 `bilibili` 后跟随 `p1`、`p2`、`p3` 等选项 ```md @[bilibili p1](aid cid) ``` 更多选项: ```md @[bilibili p1 autoplay time="0" width="100%" height="400px" ratio="16:9"](bvid aid cid) ``` **选项说明:** * bvid: 视频 BV ID * aid: 视频 AID * cid: 视频 CID * autoplay: 是否自动播放 * time: 视频开始播放时间点,单位为秒, 也可以使用 `mm:ss` 或 `hh:mm:ss` 格式 * width: 视频宽度 * height: 视频高度 * ratio: 视频比例,默认 `16:9` 对于分P的视频,可以省略传入 `bvid`,但需要传入 `aid` 和 `cid` ## 示例 ### 宽频视频 输入: ```md @[bilibili](BV1EZ42187Hg) ``` 输出: @[bilibili](BV1EZ42187Hg) ### 竖屏视频 输入: ```md @[bilibili width="320px" ratio="9:16"](BV1zr42187eg) ``` 输出: @[bilibili width="320px" ratio="9:16"](BV1zr42187eg) --- --- url: /guide/embed/video/youtube/index.md --- # Youtube 视频 ## 概述 主题提供了 嵌入 Youtube 视频 的功能。 该功能由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 ## 配置 该功能默认不启用。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { youtube: true, // [!code ++] }, }) }) ``` ## 语法 简单的语法: ```md @[youtube](id) ``` 更多选项: ```md @[youtube autoplay loop start="0" end="0" width="100%" height="400px" ratio="16:9"](id) ``` **选项说明:** * id: 视频 ID * autoplay: 是否自动播放 * loop: 是否循环播放 * start: 视频开始播放时间点,单位为秒, 也可以使用 `mm:ss` 或 `hh:mm:ss` 格式 * end: 视频结束播放时间点,单位为秒, 也可以使用 `mm:ss` 或 `hh:mm:ss` 格式 * width: 视频宽度 * height: 视频高度 * ratio: 视频比例,默认 `16:9` ## 示例 ### 宽频视频 输入: ```md @[youtube](0JJPfz5dg20) ``` 输出: @[youtube](0JJPfz5dg20) --- --- url: /guide/features/bulletin/index.md --- # 公告板 ## 概述 公告板是一个实时通知组件,可以实现在站点中方便的展示一些通知信息。 如右上角的公告板。 ## 使用 主题提供了非常方便且灵活的 公告板 使用方法。你可以根据自己的需求,选择合适的方式进行配置。 ### 配置说明 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ bulletin: { // more options... } }) }) ``` ```ts interface BulletinOptions { /** * 公告位置 * @default 'top-right' */ layout?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center' /** * 是否显示渐变边框 * * @default true */ border?: boolean /** * 在哪些页面显示公告 * * - `true` 表示所有页面 * - `false` 表示不显示 * - 传入一个函数,返回 `true` 时显示 */ enablePage?: boolean | ((page: Page) => boolean) /** * 公告持续时间 * * @default 'always' * * - `'session'` 表示在会话周期内关闭公告后不再显示,在新的会话周期重新显示,刷新页面不会重新显示 * - `'always'` 表示总是显示,关闭公告后刷新页面会重新显示 * - `'once'` 表示在仅在当前周期内显示,关闭公告后不再显示,新的会话和刷新页面都不会重新显示 */ lifetime?: 'session' | 'always' | 'once' /** * 公告 ID * * 公告持续时间 需要根据 `id` 作为唯一标识 */ id?: string /** * 公告标题 */ title?: string /** * 公告内容 * * 可以使用 markdown 语法 或者 使用 html 文本, * 使用 markdown 时需要声明 `contentType` 为 `markdown` */ content?: string /** * 公告内容 类型 * * - `markdown` 表示使用 markdown 语法 * - `text` 表示使用 普通文本 (可以是 html 内容) * * @default 'text' */ contentType?: 'markdown' | 'text' /** * 传入一个 `markdown` 或 `html` 文件路径,并使用文件内容作为公告内容 * * - 使用 `.md` 文件时,将会解析 markdown 语法 * - 使用 `.html` 文件时,只能包含公告内容,请不要使用 `` `` ` ``` ## 自定义公告板样式 您可以直接通过 css 覆盖公告板的样式。 通过修改以下 css 变量,可方便的控制公告板的样式。 ```css :root { --vp-bulletin-bg-color: var(--vp-c-bg); --vp-bulletin-text-color: var(--vp-c-text-1); --vp-bulletin-title-color: var(--vp-c-text-1); --vp-bulletin-font-size: 16px; --vp-bulletin-title-font-size: 18px; --vp-bulletin-line-height: 24px; --vp-bulletin-border-width: 2px; --vp-bulletin-border: conic-gradient(var(--vp-c-important-3), var(--vp-c-danger-3), var(--vp-c-success-3), var(--vp-c-important-3)); --vp-bulletin-width: 320px; } ``` 或者通过 `.vp-bulletin` 全局样式覆盖公告板的样式。 ```css .vp-bulletin { /* 公告板样式 */ } ``` ## 完全自定义公告板 当您完全不想使用主题内置的公告板时,可以通过注册全局组件 `Bulletin` 来完全自定义公告板。 ::: code-tabs @tab .vuepress/client.ts ```ts import { defineClientConfig } from '@vuepress/client' import Bulletin from './components/Bulletin.vue' export default defineClientConfig({ enhance: ({ app }) => { app.component('Bulletin', Bulletin) } }) ``` ::: 接下来,编写 `Bulletin.vue` 组件 ::: code-tabs @tab .vuepress/components/Bulletin.vue ```vue ``` ::: 您需要重头开始编写公告板组件,为方便编写公告板,主题提供了 composable API `useBulletinControl()`, 您可以直接在 `Bulletin.vue` 组件中使用它。 ```ts import { useBulletinControl } from 'vuepress-theme-plume/composables' const { bulletin, // 公告板配置, 从主题配置中读取 showBulletin, // 是否显示公告板 enableBulletin, // 当前页面是否启用公告板 close, // 关闭公告板 } = useBulletinControl() ``` ## 相关说明 ### 公告板唯一标识 公告板的唯一标识由 `bulletin.id` 配置。 唯一标识是用于区分公告板,并根据 该表示 决定 `bulletin.lifetime` 的有效期。 ```ts export default defineUserConfig({ theme: plumeTheme({ bulletin: { layout: 'top-right', title: '公告板标题', id: 'my-bulletin', // [!code hl] } }) }) ``` 当你未显式配置 `bulletin.id` 时,主题会根据 `bulletin` 对象生成一个 hash 值作为唯一标识。 ### 公告持续时间 公告板的持续时间由 `bulletin.lifetime` 配置。 * `session` 表示在 当前会话周期内,如果用户没有关闭公告板,则会一直显示,这包括到下个会话周期。 而当用户关闭公告板,则表示公告板已过期,在当前会话周期内不再显示,但在下一个会话周期会重新显示。 * `always` 表示公告板即使被用户关闭,不仅下一个会话周期也会重新显示,刷新页面也会重新显示。 * `once` 表示公告板在当前会话周期内一旦被关闭,之后都不再显示。 ::: details 什么是会话? **会话** 表示当您访问某个站点时,在您停留在这个站点的时间内,只要站点所在的浏览器标签页没有被关闭, 那么这个站点就会保持为同一个会话,即使页面刷新也依然保持为同一个会话。 ::: ### 公告板的位置 公告板的位置由 `bulletin.layout` 配置。 * `top-left`:顶部居左 * `top-right`:顶部居右 * `bottom-left`:底部居左 * `bottom-right`:底部居右 * `center`:顶部居中 ### 公告板显示的页面 公告板的显示页面由 `bulletin.enablePage` 配置。 * `true` 表示所有页面 * `false` 表示不显示 * 传入一个函数,返回 `true` 时显示 ```ts export default defineUserConfig({ theme: plumeTheme({ bulletin: { layout: 'top-right', title: '公告板标题', enablePage: (page) => { return page.path === '/custom-path/' } } }) }) ``` --- --- url: /guide/features/changelog/index.md --- # 文章变更历史 ## 概述 主题支持为文章添加 文章变更历史,以便更好的了解您的文章修改历史。 文章变更历史 通过 git 提交记录获取。 该功能由 [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) 提供支持。 ::: warning 注意 该功能由于需要通过 `git log` 命令获取每个 md 文件的提交记录,是一个相对比较耗时的操作,特别是对于大型项目,提交记录数量较多的情况。因此该功能在开发环境中不会启用,仅在生产环境中启用。 但你仍然可以通过设置 `theme.plugins.git` 为 `true` 来启用该功能,以便在开发环境中测试。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ plugins: { git: true } }) }) ``` ::: ## 使用 主题已内置 [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) 插件,你无需重新安装即可使用。 在主题配置文件中启用该功能: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 默认 不启用,仅当 plugins.git 为 true 时生效 // 此配置在 plume.config.ts 中无效 changelog: true, plugins: { // 如果您在此处直接声明为 true,则表示开发环境和生产环境都启用该功能 git: process.env.NODE_ENV === 'production' } }) }) ``` ## 配置 ```ts interface ChangelogOptions { /** * 最大变更记录条数, 默认获取所有记录 */ maxCount?: number /** * git 仓库的访问地址,例如:https://github.com/vuepress/ecosystem */ repoUrl?: string /** * 提交记录访问地址模式 * * - `:repo` - git 仓库的访问地址 * - `:hash` - 提交记录的 hash * * @default ':repo/commit/:hash' */ commitUrlPattern?: string /** * issue 访问地址模式 * * - `:repo` - git 仓库的访问地址 * - `:issue` - issue 的 id * * @default ':repo/issues/:issue' */ issueUrlPattern?: string /** * tag 访问地址模式, * 默认值:':repo/releases/tag/:tag' * * - `:repo` - git 仓库的访问地址 * - `:tag` - tag 的名称 * * @default ':repo/releases/tag/:tag' */ tagUrlPattern?: string } ``` ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ changelog: { maxCount: 10, repoUrl: 'https://github.com/vuepress/vuepress', commitUrlPattern: ':repo/commit/:hash', issueUrlPattern: ':repo/issues/:issue', tagUrlPattern: ':repo/releases/tag/:tag' }, }) }) ``` ::: warning 注意 请确保 `changelog.repoUrl` 配置正确, 默认值为 [docsRepo](../../config/theme.md#docsrepo)。 主题默认适配了 `github/gitlab/gitee/bitbucket` git 托管服务的相关访问地址模式。 如果您使用的是内建的托管服务或者其他,请自行配置 `commitUrlPattern`、`issueUrlPattern`、`tagUrlPattern`。 ::: ## 注意 该功能要求你的项目在 [Git 仓库](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) 下,这样它才能从提交历史记录中收集信息。 **在构建站点时,你应该确保所有的提交记录是可以获取到的。** 举例来说, CI 工作流通常会在克隆你的仓库时添加 `--depth 1` 参数来避免拉取全部的提交记录,因此你需要禁用这个功能,以便该插件在 CI 可以中正常使用。 类似于 `github actions` 、`Netlify` 、 `Vercel` 等服务,默认是不会拉取全部的提交记录的。 在 `github actions` 中,可以通过添加 `--depth 0` 参数来使得 `github actions` 可以正确获取到所有的提交记录。 ```yaml title=".github/workflows/deploy.yml" jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # [!code focus:3] with: # [!code ++:2] fetch-depth: 0 ``` 在 `Netlify` 、 `Vercel` 等服务中,处理方法则会相对复杂一些。这时候您可以先在 `github actions` 完成构建后 输出将产物输出到另一个单独的分支,然后在 `Netlify` 或者 `Vercel` 中直接使用该分支进行部署。 ::: info 通过主题的 `cli` 工具创建的项目,在选择部署方式为 `github action` 时,构建产物会输出到 `gh_pages` 分支中, 你可以在此基础上完成 `Netlify` 或者 `Vercel` 的部署。 ::: --- --- url: /guide/features/comments/index.md --- # 评论 ## 概述 文章评论由 [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) 提供支持。 主题已内置插件,你无需重新安装即可使用。 在本主题中,通过以下字段进行配置: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ comment: { // 服务提供商 provider: '', // "Artalk" | "Giscus" | "Twikoo" | "Waline" // 是否默认启用评论 comment: true, // 其它配置,根据服务提供商进行配置 // ... } }) }) ``` ### 服务提供商 [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) 支持 `"Artalk" | "Giscus" | "Twikoo" | "Waline"` 等多种不同的评论服务提供商。 你可以根据自己的需求进行配置。 * `Giscus` 是一个基于 GitHub Discussion 的评论系统,启用简便。[查看文档](https://ecosystem.vuejs.press/zh/plugins/blog/comment/giscus/) * `Waline` 是一个 需要后端的评论系统,安全性较高。[查看文档](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/) * `Twikoo` 一个简洁、安全、免费的静态网站评论系统,基于 腾讯云开发。[查看文档](https://ecosystem.vuejs.press/zh/plugins/blog/comment/twikoo/) * `Artalk` 是一款简洁的自托管评论系统,你可以在服务器上轻松部署并置入前端页面中。[查看文档](https://ecosystem.vuejs.press/zh/plugins/blog/comment/artalk/) ::: tip 推荐的评论服务 * 面向程序员和开发人员: Giscus * 面向公众: Waline ::: ::: note 示例 Fork 自 [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## Giscus Giscus 是一个基于 GitHub Discussion 的评论系统,启用简便。 ### 准备工作 ::: steps 1. 你需要创建一个公开仓库,并开启评论区,以作为评论存放的地点 2. 你需要安装 [Giscus App](https://github.com/apps/giscus),使其有权限访问对应仓库。 3. 在完成以上步骤后,请前往 [Giscus 页面](https://giscus.app/zh-CN) 获得你的设置。 你只需要填写仓库和 Discussion 分类,之后滚动到页面下部的 “启用 giscus” 部分, 获取 `data-repo`, `data-repo-id`, `data-category` 和 `data-category-id` 这四个属性。 ::: ### 配置 请配置 `provider: 'Giscus'` 并将 `data-repo`, `data-repo-id`, `data-category` 和 `data-category-id` 作为插件选项传入 `repo`, `repoId`, `category`, `categoryId` 。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ comment: { provider: 'Giscus', // "Artalk“ | "Giscus" | "Twikoo" | "Waline" comment: true, repo: 'Your_Repo', // [!code ++] repoId: 'Your_RepoId', // [!code ++] category: 'Your_Category', // [!code ++] categoryId: 'Your_CategoryId', // [!code ++] } }) }) ``` ### 主题 默认情况下,Giscus 使用 `light` 或 `dark` 主题 (基于夜间模式状态)。 如果你想在日间模式和夜间模式下自定义主题,你可以设置 `lightTheme` 和 `darkTheme` 选项, 使用内置主题关键字或以 `https://` 开头的自定义 css 链接。 ## Waline 一个有后端的安全评论系统。 ### 安装 如果你想要在主题中使用 Waline, 你需要先安装 `@waline/client`。 ::: npm-to ```sh npm i @waline/client ``` ::: ### LeanCloud 设置 (数据库) ::: steps 1. [登录](https://console.leancloud.app/login) 或 [注册](https://console.leancloud.app/register) `LeanCloud 国际版` 并进入 [控制台](https://console.leancloud.app/apps) 2. 点击左上角 [创建应用](https://console.leancloud.app/apps) 并起一个你喜欢的名字 (请选择免费的开发版): ![创建应用](https://ecosystem.vuejs.press/assets/leancloud-1-D6GvqV4-.png) 3. 进入应用,选择左下角的 `设置` > `应用 Key`。你可以看到你的 `APP ID`,`APP Key` 和 `Master Key`。 请记录它们,以便后续使用。 ![ID 和 Key](https://ecosystem.vuejs.press/assets/leancloud-2-B5wKvXiY.png) ::: ::: warning 国内版需要完成备案接入 如果你正在使用 Leancloud 国内版 ([leancloud.cn](https://leancloud.cn)),我们推荐你切换到国际版 ([leancloud.app](https://leancloud.app))。 否则,你需要为应用额外绑定**已备案**的域名,同时购买独立 IP 并完成备案接入: * 登录国内版并进入需要使用的应用 * 选择 `设置` > `域名绑定` > `API 访问域名` > `绑定新域名` > 输入域名 > `确定`。 * 按照页面上的提示按要求在 DNS 上完成 CNAME 解析。 * 购买独立 IP 并提交工单完成备案接入。(独立 IP 目前价格为 ¥ 50/个/月) ![域名设置](https://ecosystem.vuejs.press/assets/leancloud-3-D7gbeXS0.png) ::: ### Vercel 部署 (服务端) [![Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwalinejs%2Fwaline%2Ftree%2Fmain%2Fexample) :::: steps 1. 点击上方按钮,跳转至 Vercel 进行 Server 端部署。 ::: note 如果你未登录的话,Vercel 会让你注册或登录,请使用 GitHub 账户进行快捷登录。 ::: 2. 输入一个你喜欢的 Vercel 项目名称并点击 `Create` 继续: ![创建项目](https://ecosystem.vuejs.press/images/comment/vercel-1.png) 3. 此时 Vercel 会基于 Waline 模板帮助你新建并初始化仓库,仓库名为你之前输入的项目名。 ![deploy](https://ecosystem.vuejs.press/images/comment/vercel-3.png) 一两分钟后,满屏的烟花会庆祝你部署成功。此时点击 `Go to Dashboard` 可以跳转到应用的控制台。 ![deploy](https://ecosystem.vuejs.press/images/comment/vercel-4.png) 4. 点击顶部的 `Settings` - `Environment Variables` 进入环境变量配置页, 并配置三个环境变量 `LEAN_ID`, `LEAN_KEY` 和 `LEAN_MASTER_KEY` 。 它们的值分别对应上一步在 LeanCloud 中获得的 `APP ID`, `APP KEY`, `Master Key`。 ![设置环境变量](https://ecosystem.vuejs.press/images/comment/vercel-5.png) ::: note 如果你使用 LeanCloud 国内版,请额外配置 `LEAN_SERVER` 环境变量,值为你绑定好的域名。 ::: 5. 环境变量配置完成之后点击顶部的 `Deployments` 点击顶部最新的一次部署右侧的 `Redeploy` 按钮进行重新部署。该步骤是为了让刚才设置的环境变量生效。 ![redeploy](https://ecosystem.vuejs.press/images/comment/vercel-6.png) 6. 此时会跳转到 `Overview` 界面开始部署,等待片刻后 `STATUS` 会变成 `Ready`。此时请点击 `Visit` ,即可跳转到部署好的网站地址,此地址即为你的服务端地址。 ![redeploy success](https://ecosystem.vuejs.press/images/comment/vercel-7.png) :::: ### 绑定域名 (可选) ::: steps 1. 点击顶部的 `Settings` - `Domains` 进入域名配置页 2. 输入需要绑定的域名并点击 `Add` ![Add domain](https://ecosystem.vuejs.press/images/comment/vercel-8.png) 3. 在域名服务器商处添加新的 `CNAME` 解析记录 | Type | Name | Value | | ----- | ------- | -------------------- | | CNAME | example | cname.vercel-dns.com | 4. 等待生效,你可以通过自己的域名来访问了:tada: * 评论系统:example.your-domain.com * 评论管理:example.your-domain.com/ui ![success](https://ecosystem.vuejs.press/images/comment/vercel-9.png) ::: ### 客户端 #### 使用插件 在插件选项中设置 `provider: "Waline"`,同时设置服务端地址 `serverURL` 为上一步获取到的值。 此时,将 `` 组件放置在你网站中合适的位置 (通常是页面的底部),即可使用 Waline 评论功能。 ::: tip 你也可以传入其他 Waline 支持的选项 (除了 `el`)。详情请见 [Waline 配置](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/config.html) ::: ### 评论管理 (管理端) ::: steps 1. 部署完成后,请访问 `/ui/register` 进行注册。首个注册的人会被设定成管理员。 2. 管理员登陆后,即可看到评论管理界面。在这里可以修改、标记或删除评论。 3. 用户也可通过评论框注册账号,登陆后会跳转到自己的档案页。 ::: --- --- url: /guide/features/content-search/index.md --- # 内容搜索 主题提供了两种方式支持 内容搜索。 * 本地内容搜索 * Algolia DocSearch 注意,请勿同时配置使用两种方式,同时配置时,只有 本地内容搜索 生效。 ## 本地内容搜索 本地内容搜索由 [@vuepress-plume/plugin-search](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-search) 插件提供支持。 该插件使用 [minisearch](https://github.com/lucaong/minisearch) 进行内容搜索。 ### 启用 主题默认 启用 本地内容搜索 功能。您也可以对其进行自定义配置。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ search: { // [!code ++:4] provider: 'local', // more options } }) }) ``` 该插件会根据你的页面,在本地生成搜索索引,然后在用户访问站点时加载搜索索引文件。 换句话说,这是一个轻量级的内置搜索能力,不会进行任何外部请求。 然而,当你的站点包含大量页面时,搜索索引文件也会变得非常大,它可能会拖慢你的页面加载速度。 在这种情况下,我们建议你使用更成熟的解决方案 - [Algolia DocSearch](#algolia-docsearch) 。 ## Algolia DocSearch 使用 [Algolia DocSearch](https://docsearch.algolia.com/) 提供支持的网站内容搜索插件 ### 启用 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ search: { // [!code ++:4] provider: 'algolia', // more options } }) }) ``` ### 获取搜索索引 你需要 [提交你的网站 URL](https://docsearch.algolia.com/apply/) 来加入 DocSearch 项目。 当你的索引成功创建后, DocSearch 团队会将 `apiKey` 和 `indexName` 发送到你的邮箱。接下来,你就可以配置该插件,在 VuePress 中启用 DocSearch 了。 或者,你也可以 [运行你自己的爬虫](https://docsearch.algolia.com/docs/run-your-own/) 来创建索引, 然后使用你自己的 `appId` , `apiKey` 和 `indexName` 来配置该插件。 以下是本主题使用的 爬虫配置示例, 你可以前往 [Algolia Crawler](https://crawler.algolia.com/admin/crawlers/) 根据你的需求进行修改: ```ts new Crawler({ appId: 'YOUR_APP_ID', // [!code highlight] apiKey: 'YOUR_API_KEY', // [!code highlight] rateLimit: 8, startUrls: [ // 这是 Algolia 开始抓取网站的初始地址 // 如果你的网站被分为数个独立部分,你可能需要在此设置多个入口链接 'https://YOUR_WEBSITE_URL/', // [!code highlight] ], renderJavaScript: false, sitemaps: [ // 主题默认会生成 sitemap,这里需要替换为你的域名链接 'https://YOUR_WEBSITE_URL/sitemap.xml', // [!code highlight] ], ignoreCanonicalTo: true, discoveryPatterns: [ // 这是 Algolia 抓取 URL 的范围 'https://YOUR_WEBSITE_URL/**', // [!code highlight] ], // 爬虫执行的计划时间,可根据文档更新频率设置 schedule: 'at 02:00 every 1 day', actions: [ // 你可以拥有多个 action,特别是你在一个域名下部署多个文档时 { // 使用适当的名称为索引命名 indexName: 'YOUR_INDEX_NAME', // [!code highlight] // 索引生效的路径 pathsToMatch: ['https://YOUR_WEBSITE_URL/**'], // [!code highlight] recordExtractor: ({ helpers }) => { // vuepress-theme-plume 的选项 return helpers.docsearch({ recordProps: { // [!code highlight] lvl1: '.plume-content h1', // [!code highlight] content: '.plume-content p, .plume-content li', // [!code highlight] lvl0: { // [!code highlight] selectors: [ // [!code highlight] '.sidebar-item.is-active p', // [!code highlight] '.content-container .page-title', // [!code highlight] ], // [!code highlight] defaultValue: 'Documentation', // [!code highlight] }, // [!code highlight] lvl2: '.plume-content h2', // [!code highlight] lvl3: '.plume-content h3', // [!code highlight] lvl4: '.plume-content h4', // [!code highlight] lvl5: '.plume-content h5', // [!code highlight] }, // [!code highlight] indexHeadings: true, // [!code highlight] aggregateContent: true, // [!code highlight] recordVersion: 'v3', // [!code highlight] }) }, }, ], initialIndexSettings: { // 控制索引如何被初始化,这仅当索引尚未生成时有效 // 你可能需要在修改后手动删除并重新生成新的索引 YOUR_INDEX_NAME: { // [!code highlight] attributesForFaceting: ['type', 'lang'], // [!code highlight] attributesToRetrieve: [ 'hierarchy', 'content', 'anchor', 'url', 'url_without_anchor', 'type', ], attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'], attributesToSnippet: ['content:10'], camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'], searchableAttributes: [ 'unordered(hierarchy_radio_camel.lvl0)', 'unordered(hierarchy_radio.lvl0)', 'unordered(hierarchy_radio_camel.lvl1)', 'unordered(hierarchy_radio.lvl1)', 'unordered(hierarchy_radio_camel.lvl2)', 'unordered(hierarchy_radio.lvl2)', 'unordered(hierarchy_radio_camel.lvl3)', 'unordered(hierarchy_radio.lvl3)', 'unordered(hierarchy_radio_camel.lvl4)', 'unordered(hierarchy_radio.lvl4)', 'unordered(hierarchy_radio_camel.lvl5)', 'unordered(hierarchy_radio.lvl5)', 'unordered(hierarchy_radio_camel.lvl6)', 'unordered(hierarchy_radio.lvl6)', 'unordered(hierarchy_camel.lvl0)', 'unordered(hierarchy.lvl0)', 'unordered(hierarchy_camel.lvl1)', 'unordered(hierarchy.lvl1)', 'unordered(hierarchy_camel.lvl2)', 'unordered(hierarchy.lvl2)', 'unordered(hierarchy_camel.lvl3)', 'unordered(hierarchy.lvl3)', 'unordered(hierarchy_camel.lvl4)', 'unordered(hierarchy.lvl4)', 'unordered(hierarchy_camel.lvl5)', 'unordered(hierarchy.lvl5)', 'unordered(hierarchy_camel.lvl6)', 'unordered(hierarchy.lvl6)', 'content', ], distinct: true, attributeForDistinct: 'url', customRanking: [ 'desc(weight.pageRank)', 'desc(weight.level)', 'asc(weight.position)', ], ranking: [ 'words', 'filters', 'typo', 'attribute', 'proximity', 'exact', 'custom', ], highlightPreTag: '', highlightPostTag: '', minWordSizefor1Typo: 3, minWordSizefor2Typos: 7, allowTyposOnNumericTokens: false, minProximity: 1, ignorePlurals: true, advancedSyntax: true, attributeCriteriaComputedByMinProximity: true, removeWordsIfNoResults: 'allOptional', }, }, }) ``` `recordProps` 部分的配置选项用于本主题进行索引的爬取配置。 ### 配置项 完整配置请查看 [文档](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html) ### 配置示例 以下是本主题使用的配置: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ search: { // [!code ++:6] provider: 'algolia', appId: 'YOUR_APP_ID', apiKey: 'YOUR_API_KEY', indexName: 'YOUR_INDEX_NAME', } }) }) ``` --- --- url: /guide/features/contributors/index.md --- # 文章贡献者 ## 概述 主题支持为文章添加贡献者信息,以便更好的了解您的文章贡献者。 文章贡献者通过 git 提交记录获取。 该功能由 [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) 提供支持。 ::: warning 注意 该功能由于需要通过 `git log` 命令获取每个 md 文件的提交记录,是一个相对比较耗时的操作,特别是对于大型项目,提交记录数量较多的情况。因此该功能在开发环境中不会启用,仅在生产环境中启用。 但你仍然可以通过设置 `theme.plugins.git` 为 `true` 来启用该功能,以便在开发环境中测试。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ plugins: { git: true } }) }) ``` ::: ## 使用 主题已内置 [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) 插件,你无需重新安装即可使用。 在主题配置文件中启用该功能: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 默认启用,仅当 plugins.git 为 true 时生效 // 此配置在 plume.config.ts 中无效 contributors: true, plugins: { // 如果您在此处直接声明为 true,则表示开发环境和生产环境都启用该功能 git: process.env.NODE_ENV === 'production' } }) }) ``` ## 配置 ### mode * 类型:`'inline' | 'block'` * 默认值:`'inline'` * 描述: * `inline`:在文章页底部,与 最后更新时间,并列显示贡献者信息,该模式下仅显示 贡献者名称。 ![contributors inline](/images/contributors-inline.png) * `block`:在文章内容末尾插入贡献者信息,该模式下包含 贡献者名称、贡献者链接、贡献者头像。 (如当前页面内容结尾所示) 在 `block` 模式下,贡献者默认均会显示头像,即使您未填写头像地址。插件会从 `https://gravatar.com/` 根据 邮箱地址或用户名 生成头像地址。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', }, }) }) ``` ### info * 类型:`ContributorInfo[]` ```ts interface ContributorInfo { /** * 贡献者在 Git 托管服务中的用户名 */ username: string /** * 贡献者显示在页面上的名字, 默认为 `username` */ name?: string /** * 贡献者别名, 由于贡献者可能在本地 git 配置中保存的 用户名与 托管服务 用户名不一致, * 这时候可以通过别名映射到真实的用户名 */ alias?: string[] | string /** * 贡献者头像地址 * 如果 git 托管服务为 `github`,则可以忽略不填,由插件自动填充 */ avatar?: string /** * 贡献者访问地址 * 如果 git 托管服务为 `github`,则可以忽略不填,由插件自动填充 */ url?: string } ``` * 描述: 贡献者信息列表。 用户在本地 git 服务中配置的 用户名和邮箱 可能与 git 托管服务(如 github、gitlab、gitee)的用户信息不一致。 可以在此预先配置贡献者信息。 (对于非 github 的其他 git 托管服务,诸如 gitlab、gitee,由于不能通过用户名直接获取头像和用户地址,请在此 补充完善用户信息。) ::: code-tabs @tab Github ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', info: [ { username: 'pengzhanbo', // github username alias: ['peng_zhan_bo'], // 别名,本地 git 配置中的用户名 } ] }, }) }) ``` @tab Gitlab ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', info: [ { username: 'pengzhanbo', // gitlab username alias: ['peng_zhan_bo'], // 别名,本地 git 配置中的用户名 url: 'https://gitlab.com/pengzhanbo', avatar: 'https://gitlab.com/uploads/-/system/user/avatar/1/avatar.png', } ] }, }) }) ``` @tab Gitee ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', info: [ { username: 'pengzhanbo', // gitee username alias: ['peng_zhan_bo'], // 别名,本地 git 配置中的用户名 url: 'https://gitee.com/pengzhanbo', avatar: 'https://foruda.gitee.com/avatar/1234455/avatar.png', } ] }, }) }) ``` @tab Bitbucket ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', info: [ { username: 'pengzhanbo', // bitbucket username alias: ['peng_zhan_bo'], // 别名,本地 git 配置中的用户名 url: 'https://bitbucket.org/pengzhanbo', avatar: 'https://bitbucket.org/pengzhanbo/avatar/1234455/avatar.png', } ] }, }) }) ``` @tab 其它 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ contributors: { mode: 'block', info: [ { username: 'pengzhanbo', // username alias: ['peng_zhan_bo'], // 别名,本地 git 配置中的用户名 url: 'https://your-git.com/pengzhanbo', avatar: 'https://your-git.com/avatar.png', } ] }, }) }) ``` ::: ### avatar * 类型:`boolean` * 默认值:`true` * 描述:是否显示贡献者头像 ### avatarPattern * 类型:`string` * 默认值:`'https://github.com/:username.png'` * 描述:贡献者头像地址模式 `:username` 会被替换为贡献者的 用户名 ### transform(contributors) * 类型:`(contributors: GitContributor[]) => GitContributor[]` ```ts interface GitContributor { name: string // 显示的名字 username: string // git 托管服务 username email: string commits: number // 贡献者提交次数 avatar?: string } ``` * 描述: 贡献者转换函数。该函数需要返回新的 贡献者列表。 你可以在此处补充转换逻辑,比如进行排序、去重、或者补全信息等。 ## frontmatter ### contributors * 类型:`boolean | string[]` * 描述: 是否显示贡献者信息。 如果您的文章来源于第三方, git 提交不能完整列出所有的作者,您可以在此处补充贡献者。 ## 注意 该功能要求你的项目在 [Git 仓库](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) 下,这样它才能从提交历史记录中收集信息。 **在构建站点时,你应该确保所有的提交记录是可以获取到的。** 举例来说, CI 工作流通常会在克隆你的仓库时添加 `--depth 1` 参数来避免拉取全部的提交记录,因此你需要禁用这个功能,以便该插件在 CI 可以中正常使用。 类似于 `github actions` 、`Netlify` 、 `Vercel` 等服务,默认是不会拉取全部的提交记录的。 在 `github actions` 中,可以通过添加 `--depth 0` 参数来使得 `github actions` 可以正确获取到所有的提交记录。 ```yaml title=".github/workflows/deploy.yml" jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # [!code focus:3] with: # [!code ++:2] fetch-depth: 0 ``` 在 `Netlify` 、 `Vercel` 等服务中,处理方法则会相对复杂一些。这时候您可以先在 `github actions` 完成构建后 输出将产物输出到另一个单独的分支,然后在 `Netlify` 或者 `Vercel` 中直接使用该分支进行部署。 ::: info 通过主题的 `cli` 工具创建的项目,在选择部署方式为 `github action` 时,构建产物会输出到 `gh_pages` 分支中, 你可以在此基础上完成 `Netlify` 或者 `Vercel` 的部署。 ::: --- --- url: /guide/features/copyright/index.md --- # 文章版权所有 ## 概述 主题支持为文章添加 文章 **版权所有** 声明。 文章通常来源于 原创、转载、翻译等。针对于不同的来源,添加版权声明信息能够更好地保护知识产权, 以及避免产生版权纠纷。 ### Creative Commons 主题默认支持 [Creative Commons](https://creativecommons.org/) 许可协议的版权声明,包括: * [CC0 1.0 通用 (CC0)](https://creativecommons.org/publicdomain/zero/1.0/) * [署名 4.0 国际 (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/) * [署名-相同方式共享 4.0 国际 (CC-BY-SA-4.0)](https://creativecommons.org/licenses/by-sa/4.0/) * [署名-非商业性 4.0 国际 (CC-BY-NC-4.0)](https://creativecommons.org/licenses/by-nc/4.0/) * [署名-禁止演绎 4.0 国际 (CC-BY-ND-4.0)](https://creativecommons.org/licenses/by-nd/4.0/) * [署名-非商业性-相同方式共享 4.0 国际 (CC-BY-NC-SA-4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) * [署名-非商业性-禁止演绎 4.0 国际 (CC-BY-NC-ND-4.0)](https://creativecommons.org/licenses/by-nc-nd/4.0/) 您可以根据需要选择不同的许可协议,或者自定义许可协议。 ### 版权信息 版权信息包括: * 版权所有者,版权所有者链接 * 版权许可证,版权许可证链接 * 作品原文链接 这些信息将显示在文章的底部。 ::: tip 使用此功能建议同时启用 [贡献者](./contributors.md) 功能。对于原创文章,主题会自动将文章的第一位贡献者作为版权所有者。你也可以在文章 frontmatter 中手动指定版权所有者。 ::: ## 全局配置 您可以通过以下配置为您的站点的所有文章,声明版权许可证为 `CC-BY-4.0`: ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ copyright: 'CC-BY-4.0' // [!code hl] }) }) ``` 您可以通过以下配置为您的站点的所有文章 声明自定义的版权许可证: ```ts :no-line-numbers title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ copyright: { // [!code hl:6] license: { name: 'MIT', // 许可证名称 url: 'https://your-license-url' // 许可证地址 }, author: { name: 'Your Name', // 版权所有者名称 url: 'https://your-author-url' // 版权所有者地址 }, creation: 'reprint' // 创作方式 } }) }) ``` **配置类型:** ```ts export type CopyrightLicense = | 'CC-BY-4.0' | 'CC-BY-SA-4.0' | 'CC-BY-NC-4.0' | 'CC-BY-NC-SA-4.0' | 'CC-BY-ND-4.0' | 'CC-BY-NC-ND-4.0' | 'CC0' | string /** * - 配置为 `true` 时,默认为 `CC-BY-4.0` * - 配置为 `false` 时,不显示版权,但可以在文章 frontmatter.copyright 中覆盖配置 */ type CopyrightOptions = boolean | string | CopyrightLicense | { /** * 版权许可证 */ license?: CopyrightLicense | { name: CopyrightLicense | string url: string } /** * 版权所有者,未配置时,默认从 git 提交记录中获取 */ author?: { name: string url?: string } /** * 创作方式,原创、翻译、转载 * @default 'original' */ creation?: 'original' | 'translate' | 'reprint' } ``` ::: warning 全局配置只适用于 原创文章,对于非原创文章,您应该在文章 frontmatter 中配置版权信息。 ::: ## 文章 frontmatter 配置 您可以在文章 frontmatter 中为单个文章配置版权信息,以覆盖全局配置: ```md --- title: 我的文章 copyright: CC-BY-4.0 --- ``` **配置类型:** ```ts /** * 配置为 `false` 时,不显示版权 * 配置为 `true` 时,则默认为 全局配置的 copyright */ export type CopyrightFrontmatter = boolean | string | CopyrightLicense | { /** * 版权许可 */ license?: CopyrightLicense | { name: string, url: string } /** * 版权所有者 * - 原创文章时默认为文章的第一位贡献者 * - 非原创文章时需要声明版权所有者 */ author?: string | { name: string, url?: string } /** * 作品的创作方式, 原创、翻译、转载 * @default 'original' */ creation?: 'original' | 'translate' | 'reprint' /** * 原文地址,非原创作品时需要声明原文地址 * @default '' */ source?: string } ``` ## 文章配置示例 ### 原创文章 ```md --- title: 我的文章 copyright: CC-BY-4.0 --- ``` ### 转载文章 ```md --- title: 转载的文章 copyright: creation: reprint license: CC-BY-4.0 source: https://example.com/origin author: name: 转载者 url: https://example.com/author --- ``` ### 翻译文章 ```md --- title: 翻译的文章 copyright: creation: translate license: CC-BY-4.0 source: https://example.com/origin author: name: 原文作者 url: https://example.com/author --- ``` ### 自定义许可证 ```md --- title: 我的文章 copyright: license: name: MIT url: https://example.com/mit --- ``` --- --- url: /guide/features/encryption/index.md --- # 加密 ## 加密 在本主题中,支持 **全站加密** 和 **部分加密** 等多种灵活的加密方式。 ::: warning 提示 由于 `vuepress` 是静态站点,其自身限制的原因,**加密** 仅仅只是 看起来 看不到内容, 并且在 编译时,不再将 内容 预渲染到 `html` 中,但实际上 还是能够从 站点源文件 中获取到内容。 因此,不建议将 **加密** 功能 认为是 安全可靠的。 请尽量避免将 **加密功能** 应用于需要 **严格保密** 的内容 中。 ::: **已解锁的文章,仅在当前会话中可见。** ## 启用加密功能 在 主题配置中,添加 `encrypt` 选项。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ encrypt: { // more options... } }) }) ``` ## 全站加密 有些情况下,你可能 需要对 全站进行加密。 因此,你可以通过 `encrypt.global` 选项配置全站加密。 然后,通过配置 `encrypt.admin` 选项,设置一个或多个密码。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ encrypt: { global: true, admin: ['123456'], } }) }) ``` ## 部分加密 大多数情况下,你可能只需需要 加密 某一篇文章、某一个目录 等。 因此,你可以通过 `encrypt.rules` 选项配置部分加密。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ encrypt: { rules: { // 可以是 md 文件的相对路径,对该文件加密 '前端/基础.md': '123456', // 可以是 文件夹的路径,对该目录下所有文章加密 '/notes/vuepress-theme-plume/': '123456', // 可以是 访问地址的请求路径,对该访问路径下所有文章加密 '/vuepress-theme-plume/': '123456', // 可以是 具体的某个页面的请求路径,对该页面加密 '/article/f8dnci3/': '123456', // 如果是 `^` 开头,则匹配该正则表达式的页面也会加密 '^/(a|b)/': '123456', } } }) }) ``` `encrypt.rules` 的 **键** 将作为 匹配规则,**值** 将作为 该规则对应的密码,可以设置 一个或多个密码。 :::tip 说明 * 密码 必须是 普通的字符串。 * 如果是 加密的是 整个目录,解锁时也是解锁整个目录,而不是解锁该目录下的某个文章。 * `encrypt.admin` 也可用于解锁 **部分加密** 的页面。 * 使用 `encrypt.admin` 解锁后,被认为是管理员访问,其它未解锁页面也默认解锁。 ::: ### Frontmatter 在 Markdown 文件的 `Frontmatter` 中,可以使用 `password` 设置文章的密码。 ```md --- title: 加密的文章 password: 123456 --- ``` 还可以添加 `passwordHint` 选项,用于设置密码提示信息。 ```md --- title: 加密的文章 password: 123456 passwordHint: 密码是 123456 --- ``` ## 示例 点击访问 [加密文章,密码:123456](/article/enx7c9s/) ## 相关配置 以下配置支持在 [多语言配置](../../config/locales.md) 中使用。 ### encryptGlobalText * **类型**: `string` * **默认值**: `'Only password can access this site'` * **说明**: 全站加密时,提示信息。支持 HTML。如果你期望为访客提供获取密码的联系方式,你可能会需要这个配置。 ### encryptPageText * **类型**: `string` * **默认值**: `'Only password can access this page'` * **说明**: 部分加密时,提示信息。支持 HTML。如果你期望为访客提供获取密码的联系方式,你可能会需要这个配置。 ### encryptButtonText * **类型**: `string` * **默认值**: `'Confirm'` * **说明**: 确认按钮的文本 ### encryptPlaceholder * **类型**: `string` * **默认值**: `'Enter password'` * **说明**: 密码输入框的占位符 ### 示例 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ locales: { '/': { encryptButtonText: 'Confirm', encryptPlaceholder: 'Enter password', encryptGlobalText: 'Only password can access this site', encryptPageText: 'Only password can access this page', } } }) }) ``` --- --- url: /guide/features/icon/index.md --- # 图标 ## 概述 主题支持以下来源的图标: * [iconify](https://iconify.design/) - 默认支持 * [iconfont](https://www.iconfont.cn/) - 可选 * [fontawesome](https://fontawesome.com/) - 可选 在主题的以下功能中以相同的方式使用图标: * [导航栏图标](../../config/navbar.md#配置) * [侧边栏图标](../../guide/document.md#侧边栏图标) * [文件树图标](../../guide/markdown/file-tree.md) * [代码分组标题图标](../code/code-tabs.md#分组标题图标) 提供语法糖和组件支持: [Markdown 图标语法糖支持](../markdown/icons.md){.read-more} [图标组件支持](../components/icon.md){.read-more} ::: tip 主题对图标的优化 上述的不同的使用图标的方式,主题在内部都采取了相同的解析策略,即使您在不同的位置使用了相同的图标, 也不会重复加载相同的图标资源。 ::: ## 配置 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // [!code ++:3] icon: { provider: 'iconify' } // 默认支持 } }) }) ``` ## 配置项 ### provider * **类型**: `'iconify' | 'iconfont' | 'fontawesome'` * **默认值**: `'iconify'` 图标提供商 ### prefix * **类型**: `string` * **默认值**: `''` (不同的图标提供商有不同的默认值) * **详情**: 图标前缀 * 提供商为 `iconify` 时,默认为 `''`,设置 `iconify` 的图标集作为前缀,比如 `mdi` 。 * 提供商为 `iconfont` 时,默认为 `'iconfont icon-'` * 提供商为 `fontawesome` 时默认为 `'fas'`,可选值如下: ```ts type FontAwesomePrefix = | 'fas' | 's' // fa-solid fa-name | 'far' | 'r' // fa-regular fa-name | 'fal' | 'l' // fa-light fa-name | 'fat' | 't' // fa-thin fa-name | 'fads' | 'ds' // fa-duotone fa-solid fa-name | 'fass' | 'ss' // fa-sharp fa-solid fa-name | 'fasr' | 'sr' // fa-sharp fa-regular fa-name | 'fasl' | 'sl' // fa-sharp fa-light fa-name | 'fast' | 'st' // fa-sharp fa-thin fa-name | 'fasds' | 'sds' // fa-sharp-duotone fa-solid fa-name | 'fab' | 'b' // fa-brands fa-name ``` ### assets * **类型**: `(string | FontAwesomeAssetBuiltin)[] | string | FontAwesomeAssetBuiltin` ```ts type FontAwesomeAssetBuiltin = 'fontawesome' | 'fontawesome-with-brands' ``` * **默认值**: `undefined` * **详情**: * `iconify` 时,不需要设置; * `iconfont` 时,设置为 iconfont 的资源地址; * `fontawesome` 时,设置为 `fontawesome` 的资源地址,可选值为 `fontawesome` 或 `fontawesome-with-brands`, 或者自定义资源地址。 ### size * **类型**: `string | number` * **默认值**: `1em` * **详情**: 图标的默认尺寸 ### color * **类型**: `string` * **默认值**: `'currentColor'` * **详情**: 图标的默认颜色 --- --- url: /guide/features/image-preview/index.md --- # 图片预览 在主题中,图片默认支持点击后放大预览。通过查找 文档内容中的图片,形成图片预览列表。 该功能由 [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/zh/plugins/features/photo-swipe.html) 插件提供支持。 ## 配置 图片预览默认启用,也可以通过以下配置修改行为: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ plugins: { photoSwipe: { // 图片选择器 selector: '.vp-doc :not(a) > img:not([no-view],.no-view,.ignore)', download: true, // 是否显示下载按钮 fullscreen: true, // 是否显示全屏按钮 scrollToClose: true, // 是否在滚动时关闭当前图片 } } }) }) ``` 更多配置请参考 [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/zh/plugins/features/photo-swipe.html) ## 忽略图片预览 可以通过 `no-view` 或 `ignore` 类名,或者 `no-view` 属性来忽略图片预览。 ```md ![](path/to/image){.no-view} ![](path/to/image){.ignore} ![](path/to/image){no-view} ``` --- --- url: /guide/features/replace-assets/index.md --- # 资源链接替换 ## 概述 此功能由 [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/zh/plugins/tools/replace-assets.html) 插件提供。 替换站点内的本地资源链接,比如 图片、视频、音频、PDF 等资源的链接地址,将本地资源地址改写到新的地址。 ## 为什么需要这个功能? 不少用户会选择将站点的资源存放到 CDN 服务上,从而加速站点的访问速度,提升站点的可用性。 在这个过程中,通常需要先将资源上传到 CDN 服务,然后再获取 CDN 服务的资源链接,最后才在站点内容中使用。 这看起来并没有什么问题,然而在实际使用过程中,可能需要频繁的进行 ```txt 上传资源 -> 获取资源链接 -> 在内容中使用全量资源链接 ``` 在此过程中,内容创作被频繁的打断。 此功能旨在解决这个问题。在内容创作过程中,只需要直接使用本地资源地址,由主题内部在合适的阶段,完成资源地址的替换。 ::: important 此功能不会修改源文件,仅在编译后的内容中进行替换 ::: ## 使用 主题默认不启用该功能,你可以在配置中启用它: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // ReplaceAssetsPluginOptions replaceAssets: 'https://cdn.example.com' // [!code ++] }) }) ``` \==建议仅在生产构建时启用资源路径替换,在开发时直接使用本地资源路径=={.important} ```ts title=".vuepress/config.ts" twoslash import process from 'node:process' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' const isProd = process.env.NODE_ENV === 'production' // [!code ++] export default defineUserConfig({ theme: plumeTheme({ // 仅在生产环境时启用 replaceAssets: isProd ? 'https://cdn.example.com' : false // [!code ++] }) }) ``` ### 资源管理 **你应该将资源存放在 [.vuepress/public](https://v2.vuepress.vuejs.org/zh/guide/assets.html#public-%E6%96%87%E4%BB%B6) 目录下**: ```sh ./docs ├── .vuepress │ └── public # [!code hl:6] │ ├── images │ │ ├── foo.jpg │ │ └── bar.jpg │ └── medias │ └── foo.mp4 └── README.md ``` ::: tip 为什么需要存放在这个目录下? 当站点完成编译准备部署前,我们可以很方便地直接将这个目录下的文件上传到 CDN 。 ::: 在 markdown 中,直接使用本地资源地址: ```md ![foo](/images/foo.jpg) ``` 在 `javascript` 中: ```js const foo = '/images/foo.jpg' const img = document.createElement('img') img.src = '/images/foo.jpg' ``` 以及在 样式文件 中: ```css .foo { background: url('/images/foo.jpg'); } ``` 插件会正确识别这些资源,并在编译后的内容中进行替换。 :::warning 插件不支持识别 `'/images/' + 'foo.jpg'` 拼接的路径。 ::: ## 配置说明 ```ts /** * 资源链接替换配置 */ type ReplaceAssetsPluginOptions = | Replacement | ReplacementRule | ReplacementRule[] | ReplaceAssetsOptions /** * - `string`:拼接在原始资源链接的前面 * - `function`:返回替换后的资源链接 */ type Replacement = string | ((url: string) => string) interface ReplacementRule { /** * 匹配资源链接 */ find: RegExp | string /** * 资源链接替换 */ replacement: Replacement } interface ReplaceAssetsOptions { /** * 自定义资源替换规则 */ rules?: ReplacementRule | ReplacementRule[] /** * 内置的资源匹配规则替换 */ all?: Replacement /** * 内置的图片资源匹配规则替换 */ image?: Replacement /** * 内置的媒体资源匹配规则替换 */ media?: Replacement } ``` ## 内置的资源匹配规则 为便于使用,主题插件内部提供了内置的资源匹配规则,你可以直接使用它们。 * `image`: 查找图片资源,包括 `['apng','bmp','png','jpeg','jpg','jfif','pjpeg','pjp','gif','svg','ico','webp','avif','cur','jxl']` 格式的本地图片资源链接 * `media`: 查找媒体资源,包括 `['mp4','webm','ogg','mp3','wav','flac','aac','opus','mov','m4a','vtt','pdf']` 格式的本地媒体资源链接 * `all`: 查找 图片 和 媒体资源,即 `image` 和 `media` 的合集 直接传入 **资源链接前缀** 或 **资源链接替换函数** 时,主题使用 `all` 规则替换资源链接。 ```ts title=".vuepress/config.ts" import process from 'node:process' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // replaceAssets: 'https://cdn.example.com' // [!code hl] replaceAssets: url => `https://cdn.example.com${url}` // [!code ++] }) }) ``` 也可以针对不同的内置规则,应用不同的资源链接前缀或资源链接替换函数: ```ts title=".vuepress/config.ts" import process from 'node:process' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // replaceAssets: { // [!code hl:4] // image: 'https://image.cdn.com/', // media: 'https://media.cdn.com/' // }, replaceAssets: { // [!code ++:4] image: url => `https://image.cdn.com${url}`, media: url => `https://media.cdn.com${url}` } }) }) ``` ## 自定义资源匹配规则 你也可以自定义资源匹配规则: ```ts title=".vuepress/config.ts" import process from 'node:process' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ replaceAssets: { // [!code ++:4] find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/, replacement: url => `https://image.cdn.com${url}` } }) }) ``` 还可以自定义多个匹配规则: ```ts title=".vuepress/config.ts" import process from 'node:process' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ replaceAssets: [ // [!code ++:12] // 查找图片资源 { find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/, replacement: 'https://image.cdn.com' }, // 查找媒体资源 { find: /^\/medias\/.*\.(mp4|webm|ogg|mp3|wav|flac|aac|m3u8|m3u|flv|pdf)$/, replacement: url => `https://media.cdn.com${url}` }, ] }) }) ``` **`find` 字段说明** `find` 字段用于匹配资源链接,可以是一个 **正则表达式** 或 **字符串**。 当传入的是一个 `字符串` 时,如果是以 `^` 开头或者以 `$` 结尾的字符串,则会自动转换为一个 **正则表达式**。 否则则会检查资源链接是否 以 `find` 结尾 或者 以 `find` 开头。 ```txt '^/images/foo.jpg' -> /^\/images\/foo.jpg/ '/images/foo.jpg$' -> /^\/images\/foo.jpg$/ ``` ::: important 所有匹配的资源地址都是以 `/` 开头。 ::: --- --- url: /guide/features/watermark/index.md --- # 文章水印 ## 概述 文章水印由 [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html) 提供支持。 主题支持在文章中添加水印。支持 全屏水印 和 内容水印,同时还支持 图片水印 和 文字水印 。 ## 启用水印 主题默认不启用水印功能。你需要在主题配置中开启。 ```ts title=".vuepress/config.ts" import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // watermark: true, watermark: { // enabled: false, // boolean 类型控制是否全局启用 enabled: page => true, // function 类型 过滤哪些页面启用水印 delay: 500, // 添加水印的延时。以毫秒为单位。 /** * 是否全屏水印,默认为 `true`, * 设置为 `false` 时,水印仅在 内容区域中显示。 */ fullPage: true, /** @see https://zhensherlock.github.io/watermark-js-plus/zh/config/ */ watermarkOptions: { content: 'your watermark', // ... } } }) }) ``` ### 全局启用 当 `plugins.watermark` 配置为 `true` 时, 主题全局开启水印。 ```ts export default defineUserConfig({ theme: plumeTheme({ watermark: true, }) }) ``` ### 部分页面启用 主题提供了两种方式控制部分页面启用水印。 #### watermark.enabled ```ts export default defineUserConfig({ theme: plumeTheme({ watermark: { // 返回结果为 true 的将启用水印,否则禁用 enabled: page => page.path.includes('/article/'), } }) }) ``` #### frontmatter.watermark 在 md 文件中添加 `frontmatter.watermark` 为 `true` : ```md --- watermark: true --- ``` 还可以个性化配置当前页面的水印: ```md --- watermark: content: My Custom Content globalAlpha: 0.2 rotate: 45 --- ``` ## 图片水印 主题支持使用 图片 作为水印。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ watermark: { watermarkOptions: { contentType: 'image', image: '/images/watermark.png', width: 200, height: 200, imageWidth: 100, imageHeight: 100, } } }) }) ``` 也可以在 md 文件中添加配置,为当前页面设置水印: ```md --- watermark: contentType: image image: /images/watermark.png width: 200 height: 200 imageWidth: 100 imageHeight: 100 --- ``` ### 示例 [图片水印](/article/i4cuuonn/) ## 文字水印 主题支持使用 文字 作为水印。 ```ts import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ watermark: { watermarkOptions: { content: '自定义文字', fontColor: '#fff', // 文字颜色 } } }) }) ``` 也可以在 md 文件中添加配置,为当前页面设置水印: ```md --- watermark: content: 自定义文字 fontColor: #fff --- ``` ## Frontmatter 主题支持在 md 文件中添加 `frontmatter.watermark` 为单个页面设置水印。 ```md --- watermark: content: My Custom Content --- ``` 支持的配置项请参考:[watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) 同时,还额外支持 `fullPage` 控制是否全屏显示。 ```md --- watermark: fullPage: false --- ``` ## 示例 * [内容水印](/article/2z59hh8g/) * [全屏水印](/article/97s6ha1e/) --- --- url: /guide/friend-links/index.md --- # 友情链接页 ## 友情链接 友情链接页 不会自动生成,但你可以根据需要,创建它。 在你的 `{sourceDir}/` 目录下,创建 任意 `*.md` 文件,比如 `friends.md` 文件。 然后在这个文件中,通过 `frontmatter` 配置它。 ```md title="friends.md" --- friends: true title: 友情链接 description: 友情链接描述文本 permalink: /friends/ contentPosition: after list: - name: pengzhanbo link: https://github.com/pengzhanbo avatar: https://github.com/pengzhanbo.png desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。 - name: pengzhanbo link: https://github.com/pengzhanbo avatar: https://github.com/pengzhanbo.png desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。 --- 自定义内容 ``` 主题会根据 配置信息 生成友情链接页。 你需要自行将 友情链接页 的入口链接 配置到 `navbar` 的合适的位置中。 ### 配置 查看 [文档](../../config/frontmatter/friend.md) 更多配置信息。 --- --- url: /guide/intro/index.md --- # 主题介绍 \==vuepress-theme-plume== 是基于 VuePress 构建的现代化主题,无论您需要创建**技术博客**、**生活随笔**、**产品文档**、**知识库**还是**系列教程**,都能满足您的多样化需求。 我们在文本排版和图片展示方面进行了深度优化,特别是对 Markdown 语法进行了丰富扩展,让您能够轻松创作出**美观易读、表现力强**的专业内容。 ::: details 初次接触 VuePress? VuePress 是一个[静态站点生成器](https://en.wikipedia.org/wiki/Static_site_Generator) (SSG), 专门为构建高性能的内容型网站而设计。简而言之,它能将 Markdown 格式的内容通过主题渲染,生成可部署在任何地方的静态 HTML 页面。 ::: [前往 **VuePress 官网** 深入了解](https://v2.vuepress.vuejs.org/zh/){.read-more} ## 核心优势 相比 VuePress 默认主题,我们提供了显著的改进: ### 🎨 卓越的用户体验 全面优化界面设计和交互逻辑,打造更加美观、简洁且易用的阅读体验。 ### 🚀 丰富的功能特性 * **多样化布局**:支持完全自定义的==首页==,可选==文章列表==、==文档==模式 * **内容增强**:内置==全文搜索==、==文章评论==、==内容加密==、==文章水印==等实用功能 * **代码展示**:支持代码块==分组==、==折叠==、==聚焦==、==行高亮==、==差异对比==,可嵌入 CodePen、JSFiddle、CodeSandbox 等平台的==代码演示== * **图标系统**:集成 [iconify](https://icon-sets.iconify.d/) **200,000+** ==图标==,可选配 `iconfont` / `fontawesome` 图标库 * **媒体嵌入**:支持==PDF 嵌入==、==Bilibili/Youtube/本地视频==嵌入 * **图表渲染**:集成 chart.js、Echarts、Mermaid、Flowchart、Markmap、PlantUML 等多种==图表引擎== * **布局容器**:灵活的 Markdown 容器语法,提供==提示容器==、==文件树==、==代码树==、==卡片容器==、==瀑布流容器==等 * **扩展能力**:支持==布局插槽==、==组件覆写==、==自定义样式==,轻松实现个性化布局设计 ### 🎉 一切内容皆为 “集合” 将内容划分为多个==集合==,每个集合都有独立的目录,根据不同的集合类型,轻松实现如 **博客**、**专栏**、 **系列教程**、**知识库**、**产品文档** 等多样化需求。 ### ⚡ 高效的开发体验 引入编译缓存机制,缓存 Markdown 文件编译结果和复杂代码块解析结果,大幅提升构建速度。 ### 🔧 智能的配置管理 支持独立的主题配置文件,避免因配置修改导致 VuePress 服务频繁重启。在保持配置灵活性的同时,大幅简化配置流程,降低使用门槛。 ### 🌟 开箱即用的解决方案 \==plume 主题==预先集成了搭建站点所需的常用功能和配置,让您无需关注技术细节,能够**专注于内容创作**,充分发挥 Markdown 增强语法的优势,更好地表达想法。 ::: tip 版本说明 本主题基于 [vuepress-next](https://github.com/vuepress/vuepress-next) 开发,目前处于 RC 阶段。 当前版本的功能和 API 已趋于稳定,但未来更新中仍可能出现破坏性变更。 如果您在使用过程中遇到问题或有改进建议,欢迎在 [Issues](https://github.com/pengzhanbo/vuepress-theme-plume/issues) 中提出,也欢迎通过 [PR](https://github.com/pengzhanbo/vuepress-theme-plume/pulls) 参与主题完善。 ::: --- --- url: /guide/layout-slots/index.md --- # 布局插槽 ## 概述 主题通过 `` 和 `` 提供了 丰富的 布局插槽,可以通过这些插槽,在 页面 的不同位置注入内容。 以便用户可以个性化的使用主题。 ## 使用 以 `` 为例,首先,需要创建一个 客户端配置文件: `.vuepress/client.ts`: ```ts title=".vuepress/client.ts" import { defineClientConfig } from 'vuepress/client' import Layout from './layouts/Layout.vue' export default defineClientConfig({ layouts: { Layout, }, }) ``` ::: info `layouts` 中的 `Layout` 名是固定的,这是 js 的简写语法, 实际上为 `Layout: Layout`,它是实现 布局插槽的关键。 `NotFound` 也是相同的规则。 你传入的其它非 `Layout` / `NotFound` 的组件,被认为是自定义布局组件。 ::: 然后,创建一个 `.vuepress/layouts/Layout.vue`,作为布局插槽的默认组件,在该组件中引入 当前主题的 `` 组件。 ```vue {7-11} title=".vuepress/layouts/Layout.vue" ``` 也可以使用 渲染函数 实现注入内容,在 `.vuepress/client.ts` 中: ::: code-tabs @tab .vuepress/client.ts ```ts import { h } from 'vue' import { Layout } from 'vuepress-theme-plume/client' import { defineClientConfig } from 'vuepress/client' import CustomContent from './components/CustomContent.vue' export default defineClientConfig({ layouts: { Layout: () => h(Layout, null, { 'page-bottom': () => h(CustomContent), }), }, }) ``` @tab .vuepress/components/CustomContent.vue ```vue ``` ::: ## 插槽 ::: info 您可以预览 以查看所有可用的插槽在站点中的位置。 ::: ### `` 插槽 * 当 `pageLayout: doc` 时: * `doc-top` * `doc-bottom` * `doc-content-before` * `doc-footer-before` * `doc-before` * `doc-after` * `doc-title-before` * `doc-title-after` * `doc-meta-top` * `doc-meta-bottom` * `doc-meta-before` * `doc-meta-after` * `sidebar-nav-before` * `sidebar-nav-after` * `aside-top` * `aside-bottom` * `aside-outline-before` * `aside-outline-after` * 当 `pageLayout: page` 时: * `page-top` * `page-bottom` * 在 post 集合相关页面 中 (包括 文章列表页、标签页、归档页 均适用): * `posts-top` * `posts-bottom` * `posts-aside-top` * `posts-aside-bottom` * `posts-extract-before` * `posts-extract-after` * 在 文章列表页 中: * `posts-post-list-before` * `posts-post-list-after` * `posts-post-list-pagination-after` * 在 标签页 中: * `posts-tags-before` * `posts-tags-title-after` * `posts-tags-content-before` * `posts-tags-after` * 在 归档页 中: * `posts-archives-before` * `posts-archives-after` * 在 分类页 中: * `posts-categories-before` * `posts-categories-content-before` * `posts-categories-after` ### `` 插槽 * `not-found` ### 通用插槽 以下插槽在 `` 和 `` 中都支持: * `layout-top` * `layout-bottom` * `nav-bar-title-before` * `nav-bar-title-after` * `nav-bar-content-before` * `nav-bar-content-after` * `nav-bar-menu-before` * `nav-bar-menu-after` * `nav-screen-content-before` * `nav-screen-content-after` * `nav-screen-menu-before` * `nav-screen-menu-after` * `footer-content` * `bulletin-content` --- --- url: /guide/locales/index.md --- # 国际化 本指南将帮助您快速为 VuePress 主题配置多语言支持。通过简单的目录结构和配置调整,即可实现专业的国际化站点。 ## 目录结构规划 首先创建符合多语言要求的目录结构。以下示例展示支持中文、英文和法文的项目布局: ::: file-tree * docs * **en** # 英文文档目录 * foo.md * README.md # 英文首页 * **fr** # 法文文档目录 * foo.md * README.md # 法文首页 * foo.md * README.md # 中文首页 ::: **目录结构说明**: * `docs/en/` - 存储英文版本文档 * `docs/fr/` - 存储法文版本文档 * `docs/` - 存储默认语言(中文)文档 ::: important 保持文件结构一致性 在不同语言目录中,请保持相同的文件名和目录结构。这确保主题能够在语言切换时正确导航到对应语言的文档版本。 ::: ## VuePress 基础配置 ### 设置默认语言 在配置文件 `.vuepress/config.ts` 中声明默认语言: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' export default defineUserConfig({ // 设置默认语言代码 lang: 'zh-CN', // [!code ++] // 配置多语言支持 locales: { '/': { lang: 'zh-CN', title: '博客' }, // 简体中文作为默认语言 } }) ``` ### 添加其他语言支持 扩展 `locales` 配置来支持更多语言: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' export default defineUserConfig({ lang: 'zh-CN', locales: { '/': { lang: 'zh-CN', title: '博客' }, // 简体中文 '/en/': { lang: 'en-US', title: 'Blog' }, // 美式英语 // [!code ++] '/fr/': { lang: 'fr-FR', title: 'Le blog' }, // 法语 // [!code ++] } }) ``` **配置要点**: * `locales` 的键名(如 `/en/`)对应文档目录中的语言文件夹名称 * 这些键名同时作为各语言页面的访问路径前缀 * 每个语言必须设置正确的 `lang` 属性,即使只使用单一语言 ::: tip 语言代码规范 * **路径键名**:遵循 [ISO 639](https://zh.wikipedia.org/wiki/ISO_639-1) 标准(如英语使用 `/en/`) * **语言代码**:使用 [BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt) 标准格式(如英语使用 `en-US`) ::: ## 主题多语言配置 在主题配置中通过 `locales` 字段为每种语言定制化界面元素: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ lang: 'zh-CN', // [!code focus:6] locales: { '/': { lang: 'zh-CN', title: '博客' }, '/en/': { lang: 'en-US', title: 'Blog' }, '/fr/': { lang: 'fr-FR', title: 'Le blog' }, }, theme: plumeTheme({ // 主题级多语言配置 locales: { // [!code focus:20] // 简体中文配置 '/': { selectLanguageName: '简体中文', navbar: [ { text: '首页', link: '/' }, { text: '博客', link: '/blog/' }, ] }, // 英文配置 '/en/': { selectLanguageName: 'English', navbar: [ { text: 'Home', link: '/en/' }, { text: 'Blog', link: '/en/blog/' }, ] }, // 法文配置 '/fr/': { // [!code focus:7] selectLanguageName: 'Français', navbar: [ { text: 'Accueil', link: '/fr/' }, { text: 'Le Blog', link: '/fr/blog/' }, ] } } }) }) ``` **关键配置项**: * `selectLanguageName`:在语言选择器中显示的语言名称 * `navbar`:各语言独有的导航栏配置 * 所有主题配置项均支持在 `locales` 中按语言重写 ## 配置一致性要求 确保 VuePress 配置与主题配置的路径键名完全匹配: ```ts export default { // VuePress 配置 locales: { '/': { /* 中文配置 */ }, '/en/': { /* 英文配置 */ }, }, // 主题配置 theme: plumeTheme({ locales: { '/': { /* 中文主题配置 */ }, '/en/': { /* 英文主题配置 */ } } }) } ``` ## 扩展阅读 * [主题 Locales 配置](../../config/theme.md#locale-配置) - 了解各语言专属的主题行为配置 * [多语言文本配置](../../config/locales.md) - 掌握界面文本的国际化定制方法 通过以上配置,您的文档站点将具备完整的多语言支持能力,为用户提供更友好的国际化访问体验。 --- --- url: /guide/markdown/abbreviation/index.md --- # 缩写词 ## 概述 **缩写词** 是指在 Markdown 中使用的简称,例如 一些专业名词如 W3C 、 ECMA 等。 在 鼠标移动到缩写词上时,显示该名词的完整名称,还可以包括缩写词的定义、解释等。 ## 配置 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { abbr: true, // [!code ++] } }) }) ``` ## 语法 在 Markdown 中,在单独的一行中使用 `*[缩写词]: 描述` 来定义缩写词,描述可以包括缩写词的定义、解释等。 在 `[]` 中填写缩写词,在 `:` 后面填写描述,在描述中可以使用 Markdown 内联语法。 Markdown 普通文本中如果包含了定义的缩写词,则鼠标移动到该缩写词时自动显示缩写词的解释。 **输入:** ```md The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium ``` **输出:** The HTML specification is maintained by the W3C. \*\[HTML]: Hyper Text Markup Language \*\[W3C]: World Wide Web Consortium \*\[ECMA]: European Computer Manufacturers Association ::: warning 缩写词应该是独立的单词或词组。对于中文的缩写词,应该在词的左右加空格以区分。 ::: --- --- url: /guide/markdown/annotation/index.md --- # 内容注释 ## 描述 \==Annotation(注释)== 是 Markdown 中的一种特殊的语法,用于在文档中添加额外的信息、说明或者提示。 注释不会直接显示在文档中,需要用户手动点击才会显示。 ## 配置 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { annotation: true, // [!code ++] } }) }) ``` ## 语法 \==Annotation(注释)== 语法由两个部分组成: ### 行内注释 在行内通过 `[+label]` 语法插入注释标签。 注释标签由 `[+` + `label` + `]` 组成。为方便与内容做区分,在 `[+label]` 的左边边缘应该有一个空格。 `label` 为注释的标签,可以是任意字符串。 ::: important 符号 `+` 是必须的 ::: ### 定义注释 在文档的单独区域中使用 `[+label]:` 语法开始定义注释。 注释定义区域由 `[+` + `label` + `]:` + `内容` 组成。 `label` 应该与上述的 `[+label]` 一致,用于标记注释的标签。 **内容** 可以跟随在 `:` 之后开始写: ```md [+label]: 这里是内容,可以使用 **Markdown** 语法。 ``` **内容** 也可以从下一行开始写,但需要添加缩进,多行时应该保持一致的缩进。 ```md [+label]: 这里是内容。 缩进一致,此行也是内容。 即使上一行空行,但此行缩进也是一致的,也是内容。 可以使用 **Markdown** 语法。 此行不再缩进,该标签的注释定义在上一行结束。 ``` 定义注释的内容不会直接渲染在文档中,而是在 行内注释 的 `[+label]` 被点击后呈现。 ## 示例 ### 示例一 **输入:** ```md 站点由 VuePress [+vuepress] 驱动。 [+vuepress]: VuePress 是一个 [静态站点生成器](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) 。 专为构建快速、以内容为中心的站点而设计。 ``` **输出:** 站点由 VuePress \[+vuepress] 驱动。 \[+vuepress]: VuePress 是一个 [静态站点生成器](https://en.wikipedia.org/wiki/Static_site_generator) (SSG) 。 专为构建快速、以内容为中心的站点而设计。 ### 示例二 **同一个 `label` 定义多个注释,多个定义以列表的形式渲染。** **输入:** ```md 中国古代 **四大名著** [+名著] 家喻户晓。 [+名著]: **《三国演义》:** 以三国时期的历史为背景,描写了魏、蜀、吴三国之间的政治、军事斗争,塑造了诸葛亮、曹操、关羽、刘备等众多历史人物形象。 [+名著]: **《西游记》:** 讲述了唐僧师徒四人(孙悟空、猪八戒、沙僧、白龙马)西天取经的故事,充满了神话色彩和奇幻冒险。 [+名著]: **《红楼梦》:** 以贾、史、王、薛四大家族的兴衰为背景,描写了贾宝玉、林黛玉、薛宝钗等人的爱情悲剧,展现了封建社会的腐朽与没落。 [+名著]: **《水浒传》:** 描写了北宋末年以宋江为首的108位好汉在梁山泊聚义,反抗朝廷的故事,展现了官逼民反的社会现实。 ``` **输出:** 中国古代 **四大名著** [+名著] 家喻户晓。 [+名著]: **《三国演义》:** 以三国时期的历史为背景,描写了魏、蜀、吴三国之间的政治、军事斗争,塑造了诸葛亮、曹操、关羽、刘备等众多历史人物形象。 [+名著]: **《西游记》:** 讲述了唐僧师徒四人(孙悟空、猪八戒、沙僧、白龙马)西天取经的故事,充满了神话色彩和奇幻冒险。 [+名著]: **《红楼梦》:** 以贾、史、王、薛四大家族的兴衰为背景,描写了贾宝玉、林黛玉、薛宝钗等人的爱情悲剧,展现了封建社会的腐朽与没落。 [+名著]: **《水浒传》:** 描写了北宋末年以宋江为首的108位好汉在梁山泊聚义,反抗朝廷的故事,展现了官逼民反的社会现实。 --- --- url: /guide/markdown/basic/index.md --- ::: note 此文档 Fork 自 [vuepress-theme-hope](https://theme-hope.vuejs.press/zh/cookbook/markdown/), 遵循 [MIT](https://github.com/vuepress-theme-hope/vuepress-theme-hope/blob/main/LICENSE) 许可证。 ::: Markdown 是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式。 Markdown 的目标是实现「易读易写」。 ## 概述 不过最需要强调的便是它的可读性。一份使用 Markdown 格式撰写的文件应该可以直接以纯文字发佈, 并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响, 包括 [Setext][1]、[atx][2]、[Textile][3]、[reStructuredText][4]、[Grutatext][5] 和 [EtText][6], 然而最大灵感来源其实是纯文字的电子邮件格式。 因此 Markdown 的语法全由标点符号所组成,并经过严谨慎选,是为了让它们看起来就像所要表达的意思。 像是在文字两旁加上星号,看起来就像\*强调\*。Markdown 的列表看起来,嗯,就是列表。 假如你有使用过电子邮件,引言写法看起来就真的像是引用一段文字。 Markdown 具有一系列衍生版本,用于扩展 Markdown 的功能 (如表格、脚注、内嵌 HTML 等等) , 这些功能原初的 Markdown 尚不具备,它们能让 Markdown 转换成更多的格式,例如 LaTeX,Docbook。 Markdown 增强版中比较有名的有 Markdown Extra、MultiMarkdown、 Maruku 等。这些衍生版本要么基于工具, 如 Pandoc;要么基于网站,如 GitHub 和 Wikipedia,在语法上基本兼容,但在一些语法和渲染效果上有改动。 ## 用途 Markdown 的语法有个主要的目的: 用来作为一种网络内容的*写作*用语言。Markdown 的重点在于,它能让文件更容易阅读、编写。因此,Markdown 的格式语法只涵盖纯文字可以涵盖的范围。 Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多人用它写博客。世界上最流行的博客平台 WordPress 能很好的支持 Markdown。 用于编写说明文档,并且以 `README.md` 的文件名保存在软件的目录下面。 除此之外,我们还可以快速将 Markdown 转化为演讲 PPT、Word 产品文档、LaTex 论文甚至是用非常少量的代码完成最小可用原型。在数据科学领域,Markdown 已经广泛使用,极大地推进了动态可重复性研究的历史进程。 ### 行内 HTML 不在 Markdown 涵盖范围之外的标签,都可以直接在文件里面用 HTML 撰写。不需要额外标注这是 HTML 或是 Markdown;只要直接加标签就可以了。 只有块元素 ── 比如 `
`、``、`
`、`

` 等标签,必须在前后加上空行,以利与内容区隔。 而且这些 (元素) 的开始与结尾标签,不可以用 tab 或是空白来缩进。Markdown 的解析器有智慧型判断, 可以避免在块标签前后加上没有必要的 `

` 标签。 举例来说,在 Markdown 文件里加上一段 HTML 表格: ```md This is a regular paragraph.

Foo
This is another regular paragraph. ``` 请注意,Markdown 语法在 HTML 块标签中将不会被进行处理。例如,你无法在 HTML 块内使用 Markdown 形式的 `*强调*`。 ### 特殊字元自动转换 在 HTML 文件中,有两个字元需要特殊处理: `<` 和 `&` 。 `<` 符号用于起始标签,`&` 符号则用于标记 HTML 实体,如果你只是想要使用这些符号,你必须要使用实体的形式,像是 `<` 和 `&`。 `&` 符号其实很容易让写作网络文件的人感到困扰,如果你要打「AT\&T」 ,你必须要写成「`AT&T`」 ,还得转换网址内的 `&` 符号,如果你要链接到 `http://images.google.com/images?num=30&q=larry+bird` 你必须要把网址转成: ```html http://images.google.com/images?num=30&q=larry+bird ``` 才能放到链接标签的 `href` 属性里。不用说也知道这很容易忘记,这也可能是 HTML 标准检查所检查到的错误中,数量最多的。 Markdown 允许你直接使用这些符号,但是你要小心跳脱字元的使用,如果你是在 HTML 实体中使用 `&` 符号的话,它不会被转换,而在其它情形下,它则会被转换成 `&`。所以你如果要在文件中插入一个著作权的符号,你可以这样写: ```md © ``` Markdown 将不会对这段文字做修改,但是如果你这样写: ```md AT&T ``` Markdown 就会将它转为: ```html AT&T ``` 类似的状况也会发生在 `<` 符号上,因为 Markdown 支持 [行内 HTML](#行内-html) ,如果你是使用 `<` 符号作为 HTML 标签使用,那 Markdown 也不会对它做任何转换,但是如果你是写: ```md 4 < 5 ``` Markdown 将会把它转换为: ```html 4 < 5 ``` 不过需要注意的是,code 范围内,不论是行内还是块, `<` 和 `&` 两个符号都*一定*会被转换成 HTML 实体, 这项特性让你可以很容易地用 Markdown 写 HTML code (和 HTML 相对而言, HTML 语法中,你要把所有的 `<` 和 `&` 都转换为 HTML 实体,才能在 HTML 文件里面写出 HTML code。) *** ## 块元素 ### 段落和换行 一个段落是由一个以上相连接的行句组成,而一个以上的空行则会切分出不同的段落 (空行的定义是显示上看起来像是空行,便会被视为空行。比方说,若某一行只包含空白和 tab,则该行也会被视为空行) ,一般的段落不需要用空白或断行缩进。 「一个以上相连接的行句组成」这句话其实暗示了 Markdown 允许段落内的强迫断行, 这个特性和其他大部分的 text-to-HTML 格式不一样 (包括 MovableType 的「Convert Line Breaks」选项) , 其它的格式会把每个断行都转成 `
` 标签。 如果你*真的*想要插入 `
` 标签的话,在行尾加上两个以上的空格 (` `) 或斜线 (`/`),然后按 Enter。 是的,这确实需要花比较多功夫来插入 `
` ,但是「每个换行都转换为 `
`」的方法在 Markdown 中并不适合, Markdown 中 email 式的 [块引言][bq] 和多段落的 [列表][l] 在使用换行来排版的时候,不但更好用,还更好阅读。 ### 标题 标题能显示出文章的结构。 Markdown 支持两种标题的语法,[Setext][1] 和 [atx][2] 形式。 Setext 形式是用底线的形式,利用 `=` (最高阶标题) 和 `-` (第二阶标题) ,例如: ```md # This is an H1 ## This is an H2 ``` 任何数量的 `=` 和 `-` 都可以有效果。 Atx (推荐)形式则是在行首插入 1 到 6 个 `#` ,对应到标题 1 到 6 阶,例如: * H1: `# Header 1` * H2: `## Header 2` * H3: `### Header 3` * H4: `#### Header 4` * H5: `##### Header 5` * H6: `###### Header 6` ### Blockquotes Markdown 使用 email 形式的块引言,如果你很熟悉如何在 email 信件中引言,你就知道怎么在 Markdown 文件中建立一个块引言,那会看起来像是你强迫断行,然后在每行的最前面加上 `>` : ```md > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse > id sem consectetuer libero luctus adipiscing. ``` Markdown 也允许你只在整个段落的第一行最前面加上 `>` : ```md > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse > id sem consectetuer libero luctus adipiscing. ``` 块引言可以有阶层 (例如: 引言内的引言) ,只要根据层数加上不同数量的 `>` : ```md > This is the first level of quoting. > > > This is nested blockquote. > > Back to the first level. ``` 引言的块内也可以使用其他的 Markdown 语法,包括标题、列表、代码块等: ```md > ## This is a header. > > 1. This is the first list item. > 1. This is the second list item. > > Here's some example code: > > return shell_exec("echo $input | $markdown_script"); ``` 任何标准的文字编辑器都能简单地建立 email 样式的引言,例如 BBEdit ,你可以选取文字后然后从选单中选择*增加引言阶层*。 ### 列表 Markdown 支持有序列表和无序列表。 无序列表使用减号作为列表标记(也可使用星号、加号): ```md - Red - Green - Blue ``` 也可以(不建议): ```md - Red - Green - Blue * Red * Green * Blue ``` 有序列表则使用数字接着一个英文句点: ```md 1. Bird 2. McHale 3. Parish ``` 很重要的一点是,你在列表标记上使用的数字并不会影响输出的 HTML 结果,上面的列表所产生的 HTML 标记为: ```html
  1. Bird
  2. McHale
  3. Parish
``` 如果你的列表标记写成: ```md 1. Bird 1. McHale 1. Parish ``` 你都会得到完全相同的 HTML 输出。重点在于,你可以让 Markdown 文件的列表数字和输出的结果相同,或是你懒一点都写作 `1` 你可以完全不用在意数字的正确性。 列表项目标记通常是放在最左边,但是其实也可以缩进,最多三个空白,项目标记后面则一定要接着至少一个空白或 tab。 要让列表看起来更漂亮,你可以把内容用固定的缩进整理好: ```md - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 但是如果你很懒,那也不一定需要: ```md - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 如果列表项目间用空行分开, Markdown 会把项目的内容在输出时用 `

` 标签包起来,举例来说: ```md - Bird - Magic ``` 会被转换为: ```html

  • Bird
  • Magic
``` 但是这个: ```md - Bird - Magic ``` 会被转换为: ```html
  • Bird

  • Magic

``` 列表项目可以包含多个段落,每个项目下的段落都必须缩进 4 个空白或是一个 tab : ```md 1. This is a list item with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. Donec sit amet nisl. Aliquam semper ipsum sit amet velit. 2. Suspendisse id sem consectetuer libero luctus adipiscing. ``` 如果你每行都有缩进,看起来会看好很多,当然,再次地,如果你很懒惰,Markdown 也允许: ```md - This is a list item with two paragraphs. This is the second paragraph in the list item. You're only required to indent the first line. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Another item in the same list. ``` 如果要在列表项目内放进引言,那 `>` 就需要缩进: ```md - A list item with a blockquote: > This is a blockquote > inside a list item. ``` 当然,项目列表很可能会不小心产生,像是下面这样的写法: ```md 1986. What a great season. ``` 换句话说,也就是在行首出现*数字-句点-空白*,要避免这样的状况,你可以在句点前面加上反斜线。 ```md 1986\. What a great season. ``` ### 代码块 和代码相关的写作或是标签语言原始码通常会有已经排版好的代码块,通常这些块我们并不希望它以一般段落文件的方式去排版,而是照原来的样子显示,Markdown 会用 `
` 和 `` 标签来把代码块包起来。

要在 Markdown 中建立代码块很简单,只要简单地缩进 4 个空白或是 1 个 tab 就可以,例如,下面的输入:

```md
This is a normal paragraph:

This is a code block.
```

Markdown 会转换成:

```html

This is a normal paragraph:

  This is a code block.
``` 这里的缩进 (4 个空白或是 1 个 tab) ,都会被移除,例如: ```md Here is an example of AppleScript: tell application "Foo" beep end tell ``` 会被转换为: ```html

Here is an example of AppleScript:

tell application "Foo"
  beep
end tell
``` 一个代码块会一直持续到没有缩进的那一行 (或是文件结尾) 。 在代码块里面, `&` 、 `<` 和 `>` 会自动转成 HTML 实体,这样的方式让你非常容易使用 Markdown 插入范例用的 HTML 原始码,只需要复制粘贴,再加上缩进就可以了,剩下的 Markdown 都会帮你处理,例如: ````md ``` ``` ```` 会被转换为: ```html
  <div class="footer">
  &copy; 2004 Foo Corporation
</div>
``` 代码块中,一般的 Markdown 语法不会被转换,像是星号便只是星号,这表示你可以很容易地以 Markdown 语法撰写 Markdown 语法相关的文件。 如果你想要在代码块里输入用 Markdown 表示的代码库,你可以进行嵌套。 `````md ````md ```js const a = 1 ``` ```` ````` 会渲染为 ````md ```js const a = 1 ``` ```` ### 分隔线 你可以在一行中用三个或以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。你也可以在星号中间插入空白。下面每种写法都可以建立分隔线: ```html ---(建议) * * * *** ***** - - - --------------------------------------- ``` ## 行内元素 ### 链接 Markdown 支持两种形式的链接语法: *行内*和*参考*两种形式。 不管是哪一种,链接的文字都是用 `[方括号]` 来标记。 要建立一个行内形式的链接,只要在方块括号后面马上接着括号并插入网址链接即可,如果你还想要加上链接的 title 文字,只要在网址后面,用双引号把 title 文字包起来即可,例如: ```html This is [an example](http://example.com/ "Title") inline link. [This link](http://example.net/) has no title attribute. ``` 会产生: ```html

This is an example inline link.

This link has no title attribute.

``` 如果你是要链接到同样主机的资源,你可以使用相对路径: ```md See my [About](/about/) page for details. ``` 参考形式的链接使用另外一个方括号接在链接文字的括号后面,而在第二个方括号里面要填入用以辨识链接的标签: ```md This is [an example][id] reference-style link. ``` 接着,在文件的任意处,你可以把这个标签的链接内容定义出来: ```md [id]: http://example.com/ "Optional Title Here" ``` 链接定义的形式为: * 方括号,输入链接的标识 ID * 冒号 * 一个以上的空白或 tab * 链接的网址 * 选择性地添加 title 内容,可以用单引号、双引号或是括号包括 下面这三种链接的定义相同: ```md [foo]: http://example.com/ "Optional Title Here" [foo]: http://example.com/ "Optional Title Here" [foo]: http://example.com/ "Optional Title Here" ``` **请注意:** 有一个已知的问题是 Markdown.pl 1.0.1 会忽略单引号包起来的链接 title。 链接网址也可以用方括号包起来: ```md [id]: http://example.com/ "Optional Title Here" ``` 你也可以把 title 属性放到下一行,也可以加一些缩进,网址太长的话,这样会比较好看: ```md [id]: http://example.com/longish/path/to/resource/here "Optional Title Here" ``` 网址定义只有在产生链接的时候用到,并不会直接出现在文件之中。 链接辨识标签可以有字母、数字、空白和标点符号,但是并**不**区分大小写,因此下面两个链接是一样的: ```md [link text][a] [link text][a] ``` *预设的链接标签*功能让你可以省略指定链接标签,这种情形下,链接标签和链接文字会视为相同,要用预设链接标签只要在链接文字后面加上一个空的方括号,如果你要让 "Google" 链接到 google.com,你可以简化成: ```md [Google][] ``` 然后定义链接内容: ```md [google]: http://google.com/ ``` 由于链接文字可能包含空白,所以这种简化的标签内也可以包含多个文字: ```md Visit [Daring Fireball][] for more information. ``` 然后接着定义链接: ```md [daring fireball]: http://daringfireball.net/ ``` 链接的定义可以放在文件中的任何一个地方,我比较偏好直接放在链接出现段落的后面,你也可以把它放在文件最后面,就像是注解一样。 下面是一个参考式链接的范例: ```md I get 10 times more traffic from [Google][1] than from [Yahoo][2] or [MSN][3]. [1]: http://google.com/ "Google" [2]: http://search.yahoo.com/ "Yahoo Search" [3]: http://search.msn.com/ "MSN Search" ``` 如果改成用链接名称的方式写: ```md I get 10 times more traffic from [Google][] than from [Yahoo][] or [MSN][]. [google]: http://google.com/ "Google" [yahoo]: http://search.yahoo.com/ "Yahoo Search" [msn]: http://search.msn.com/ "MSN Search" ``` 上面两种写法都会产生下面的 HTML。 ```html

I get 10 times more traffic from Google than from Yahoo or MSN.

``` 下面是用行内形式写的同样一段内容的 Markdown 文件,提供作为比较之用: ```md I get 10 times more traffic from [Google](http://google.com/ "Google") than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or [MSN](http://search.msn.com/ "MSN Search"). ``` 参考式的链接其实重点不在于它比较好写,而是它比较好读,比较一下上面的范例,使用参考式的文章本身只有 81 个字元,但是用行内形式的链接却会增加到 176 个字元,如果是用纯 HTML 格式来写,会有 234 个字元,在 HTML 格式中,标签比文字还要多。 使用 Markdown 的参考式链接,可以让文件更像是浏览器最后产生的结果,让你可以把一些标记相关的资讯移到段落文字之外,你就可以增加链接而不让文章的阅读感觉被打断。 ### 强调 Markdown 使用星号 (`*`) 和底线 (`_`) 作为标记强调字词的符号,被 `*` 或 `_` 包围的字词会被转成用 `` 标签包围,用两个 `*` 或 `_` 包起来的话,则会被转成 ``,例如: ```md **double asterisks** (建议) **double underscores** (建议) _single asterisks_ _single underscores_ ``` 会转成: ```html single asterisks single underscores double asterisks double underscores ``` 你可以随便用你喜欢的样式,唯一的限制是,你用什么符号开启标签,就要用什么符号结束。 强调也可以直接插在文字中间: ```md un*frigging*believable ``` 但是如果你的 `*` 和 `_` 两边都有空白的话,它们就只会被当成普通的符号。 如果要在文字前后直接插入普通的星号或底线,你可以用反斜线: ```md \*this text is surrounded by literal asterisks\* ``` ### 代码 如果要标记一小段行内代码,你可以用反引号把它包起来 (`` ` ``) ,例如: ```md Use the `printf()` function. ``` 会产生: ```md

Use the printf() function.

``` 如果要在代码内插入反引号,你可以用多个反引号来开启和结束行内代码: ```md ``There is a literal backtick (`) here.`` ``` 这段语法会产生: ```html

There is a literal backtick (`) here.

``` 代码码区段的起始和结束端都可以放入一个空白,起始端后面一个,结束端前面一个,这样你就可以在区段的一开始就插入反引号: ```md A single backtick in a code span: `` ` `` A backtick-delimited string in a code span: `` `foo` `` ``` 会产生: ```html

A single backtick in a code span: `

A backtick-delimited string in a code span: `foo`

``` 在代码码区段内,`&` 和方括号都会被转成 HTML 实体,这样会比较容易插入 HTML 原始码,Markdown 会把下面这段: ```md Please don't use any `` tags. ``` 转为: ```html

Please don't use any <blink> tags.

``` 你也可以这样写: ```md `—` is the decimal-encoded equivalent of `—`. ``` 以产生: ```html

&#8212; is the decimal-encoded equivalent of &mdash;.

``` ### 图片 很明显地,要在纯文字应用中设计一个「自然」的语法来插入图片是有一定难度的。 Markdown 使用一种和链接很相似的语法来标记图片,同样也允许两种样式: *行内* 和 *参考*。 行内图片的语法看起来像是: ```md ![Alt text](/path/to/img.jpg) ![Alt text](/path/to/img.jpg "Optional title") ``` 详细叙述如下: * 一个惊叹号 `!` * 一个方括号,里面放上图片的替代文字 * 一个普通括号,里面放上图片的网址,最后还可以用引号包住并加上 选择性的 title 文字。 参考式的图片语法则长得像这样: ```md ![Alt text][id] ``` 「id」是图片参考的名称,图片参考的定义方式则和链接参考一样: ```md [id]: url/to/image "Optional title attribute" ``` 到目前为止, Markdown 还没有办法指定图片的宽高,如果你需要的话,你可以使用普通的 `` 标签。 ### 其他文本样式 * 删除:`~~delete~~` * 段落: 段落之间空一行 * 换行符: 一行结束时输入两个空格 *** ## 其它 ### 自动链接 Markdown 支持比较简短的自动链接形式来处理网址和电子邮件信箱,只要是用方括号包起来, Markdown 就会自动把它转成链接,链接的文字就和链接位置一样,例如: ```md ``` Markdown 会转为: ```html http://example.com/ ``` 自动的邮件链接也很类似,只是 Markdown 会先做一个编码转换的过程,把文字字元转成 16 进位码的 HTML 实体,这样的格式可以混淆一些不好的信箱地址收集机器人,例如: ```md ``` Markdown 会转成: ```html address@example.com ``` 在浏览器里面,这段字串会变成一个可以点击的 链接。 (这种作法虽然可以混淆不少的机器人,但并无法全部挡下来,不过这样也比什么都不做好些。无论如何,公开你的信箱终究会引来广告信件的。) ### 转义字符 Markdown 可以利用反斜线来插入一些在语法中有其它意义的符号,例如: 如果你想要用星号加在文字旁边的方式来做出强调效果 (但不用 `` 标签) ,你可以在星号的前面加上反斜线: ```md \*literal asterisks\* ``` Markdown 支持在下面这些符号前面加上反斜线来帮助插入普通的符号: * `\` 反斜线 * `` ` `` 反引号 * `*` 星号 * `_` 底线 * `{}` 大括号 * `[]` 方括号 * `()` 括号 * `#` 井字号 * `+` 加号 * `-` 减号 * `.` 英文句点 * `!` 惊叹号 ## 快捷键 | 输出后的效果 | Markdown | 快捷键 | | ------------- | ---------- | -------------- | | **Bold** | `**text**` | Ctrl/⌘ + B | | *Emphasize* | `*text*` | Ctrl/⌘ + I | | `Inline Code` | \`code\` | 选中后 `` ` `` | ## 表格 | 居中 | 右对齐 | 左对齐 | | :-----------: | -------------: | :------------- | | 居中使用`:-:` | 右对齐使用`-:` | 左对齐使用`:-` | | b | aaaaaaaaa | aaaa | | c | aaaa | a | [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ [bq]: #blockquotes [l]: #列表 --- --- url: /guide/markdown/caniuse/index.md --- # Can I Use ## 概述 在编写文章时, 提供嵌入 [can-i-use](https://caniuse.com/) WEB feature 各平台支持说明 的功能。 方便在描述某个 WEB feature 时,能更直观的表述 该特性的支持程度。 ## 配置 此功能默认不启用,你可以在配置文件中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdownP: { caniuse: true, // [!code ++] }, }) }) ``` 在你的 文章 markdown文件中,使用以下格式: ```md @[caniuse](feature) ``` 为了方便使用,主题提供了工具支持:[caniuse 特性搜索](../../../tools/caniuse.md),你可以直接使用该工具 帮助生成 markdown 代码。 ## 语法 ```md @[caniuse](feature) @[caniuse{browser_versions}](feature) @[caniuse embed_type](feature) @[caniuse embed_type{browser_versions}](feature) ``` * `feature` 必填。 正确取值请参考 [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN) * `{browser_versions}` 可选。当前特性在多个版本中的支持情况。 默认值为: `{-2,1}` 格式: `{past,future}` 取值范围为 `-5 ~ 3` * 小于`0` 表示低于当前浏览器版本的支持情况 * `0` 表示当前浏览器版本的支持情况 * 大于`0` 表示高于当前浏览器版本的支持情况 * `embed_type` 可选。 资源嵌入的类型。 类型: `'embed' | 'image'` 默认值为:`'embed'` :::caution 不再推荐使用 image 类型,建议使用 embed 类型,主题更换了 embed 实现技术方案, 现在的 embed 类型优势已远远超过 image 类型,加载速度更快,体积更小,交互体验更好。 ::: ## 示例 **获取 css 伪类选择器 `:dir()` 在各个浏览器的支持情况:** ```md @[caniuse](css-matches-pseudo) ``` 效果: @[caniuse](css-matches-pseudo) **以图片的形式,获取 css 伪类选择器 `:dir()` 在各个浏览器的支持情况:** ```md @[caniuse image](css-matches-pseudo) ``` 效果: @[caniuse image](css-matches-pseudo) **获取 css 伪类选择器 `:dir()` 特定范围浏览器的支持情况:** ```md @[caniuse{-2,3}](css-matches-pseudo) ``` 效果: @[caniuse{-2,3}](css-matches-pseudo) --- --- url: /guide/markdown/card/index.md --- # 卡片 ## 概述 对于想要突出显示的内容,可以将其放在 卡片容器 `::: card` 中。 当需要在空间足够时并排显示多个卡片,可以使用 `card-grid` 容器,包裹 多个卡片。 ## 语法 ```md ::: card title="标题" icon="twemoji:astonished-face" 这里是卡片内容。 ::: :::: card-grid ::: card title="卡片标题 1" icon="twemoji:astonished-face" 这里是卡片内容。 ::: ::: card title="卡片标题 2" icon="twemoji:astonished-face" 这里是卡片内容。 ::: :::: ``` ## Props :::: field-group ::: field name="title" type="string" optional default="''" 卡片标题 ::: ::: field name="icon" type="string" optional 卡片图标 支持传入图片链接,还可以传入 [iconify](https://icon-sets.iconify.design/) 图标名。 :::: ## 示例 **输入:** ```md ::: card title="卡片标题" icon="twemoji:astonished-face" 这里是卡片内容。 ::: ``` **输出:** ::: card title="卡片标题" icon="twemoji:astonished-face" 这里是卡片内容。 ::: **输入:** ```md :::: card-grid ::: card title="卡片标题 1" icon="twemoji:astonished-face" 这里是卡片内容。 ::: ::: card title="卡片标题 2" icon="twemoji:astonished-face" 这里是卡片内容。 ::: :::: ``` **输出:** :::: card-grid ::: card title="卡片标题 1" icon="twemoji:astonished-face" 这里是卡片内容。 ::: ::: card title="卡片标题 2" icon="twemoji:astonished-face" 这里是卡片内容。 ::: :::: ::: info 如果你更喜欢通过组件的方式使用 卡片,你可以查看 [卡片组件](/guide/features/component/#card) 。 ::: --- --- url: /guide/markdown/chat/index.md --- # 对话记录 ## 前言 ::: chat title="阿 B" {:2025-03-24 10:15:00} {阿 B} 在文档里放聊天记录截图还是太难看了,有没有更好的方法?\[doge] {.} 有的,兄弟,包有的 {.} 但是挂聊天记录真的没问题吗? {阿 B} 祖安对线,战绩可查 \[doge] {:2025-03-24 15:32:00} {.} 好消息:文档支持聊天记录了! {.} 坏消息:我把你挂出来了 \[doge] {阿 B} ??? ::: ## 概述 在 Markdown 中,使用 `:: chat` 容器包裹带有特定标记的文本内容,可以在文档中显示 ==聊天记录==。 ::: warning 这是一个大多数时候都用不上的功能,需要使用时请斟酌是否要这么做,对于涉及隐私的内容请自行过滤。 ::: ## 启用 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { chat: true, // [!code ++] } }) }) ``` ## 使用 在 `::: chat` 容器中,使用特定的标记,标识消息的发送者和发送时间,然后在文档中显示聊天记录。 ```md ::: chat title="标题" {:date} {username} xxx {.} xxx ::: ``` * `{:date}` 标记起始时间 (可选)。使用 `{:` + date + `}` 标记,date 可以为常见的日期格式。 主题不对 `date` 做任何处理,只是简单的渲染。 * `{username}` 标记后续内容的发送者,使用 `{` + username + `}` 标记,username 可以为任意字符串。 * `{.}` 标记为本人发送 ## 示例 **输入:** ```md ::: chat title="标题" {:2025-03-24 10:15:00} {用户一} 用户一的消息 {.} 本人的消息 {用户二} 用户二的消息 {.} 本人的消息 ::: ``` **输出:** ::: chat title="标题" {:2025-03-24 10:15:00} {用户一} 用户一的消息 {.} 本人的消息 {用户二} 用户二的消息 {.} 本人的消息 ::: --- --- url: /guide/markdown/code-tree/index.md --- # 代码树 ## 概述 在 markdown 中,使用 `::: code-tress` 容器,或者使用 `@[code-tree](dir_path)`, 可以显示一个带有文件树的代码块区域。 相比于 代码块分组,代码树 可以更加清晰地展示代码文件的组织结构,以及文件的依赖关系。 ## 启用 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { codeTree: true, // [!code ++] } }) }) ``` ## 使用 主题提供了 两种使用方式: ### code-tree 容器 ````md ::: code-tree title="Project Name" height="400px" entry="filepath" ```lang title="filepath" :active ``` ```lang title="filepath" ``` ::: ```` 使用 `::: code-tree` 容器包裹多个代码块。 * 在 `::: code-tree` 后使用 `title="Project Name"` 声明代码树的标题 * 在 `::: code-tree` 后使用 `height="400px"` 声明代码树的高度 * 在 `::: code-tree` 后使用 `entry="filepath"` 声明默认展开的文件路径 * 在代码块 \`\`\` lang 后使用 `title="filepath"` 声明当前代码块的文件路径 * 如果在 `::: code-tree` 未声明 `entry="filepath"`,可以在代码块 \`\`\` lang 后使用 `:active` 声明当前代码块为展开状态 * 如果未指定展开的文件路径,默认展开第一个文件 ::: details 代码块上为什么是 `title="filepath"` 而不是 `filepath="filepath"` ? 因为主题已经在 [代码块上提供了标题语法的支持](../code/features.md#代码块标题) ,沿用已有的语法支持 可以减少学习成本。 ::: **输入:** ````md :collapsed-lines ::: code-tree title="Vue App" height="400px" entry="src/main.ts" ```vue title="src/components/HelloWorld.vue" ``` ```vue title="src/App.vue" ``` ```ts title="src/main.ts" import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app') ``` ```json title="package.json" { "name": "Vue App", "scripts": { "dev": "vite" } } ``` ::: ```` **输出:** ::: code-tree title="Vue App" height="400px" entry="src/main.ts" ```vue title="src/components/HelloWorld.vue" ``` ```vue title="src/App.vue" ``` ```ts title="src/main.ts" import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app') ``` ```json title="package.json" { "name": "Vue App", "scripts": { "dev": "vite" } } ``` ::: ### 从目录导入 code-tree 主题支持通过以下语法从目录导入 `code-tree`: ```md @[code-tree](dir_path) @[code-tree title="Project Name" height="400px" entry="filepath"](dir_path) ``` * **dir\_path**: 当传入绝对路径,即以 `/` 开头时,从文档站点的 源目录 开始查找。 当传入相对路径时,即以 `.` 开头时,表示相对于当前 markdown 文件。 * **title**: 代码树标题,可选,默认为空 * **height**: 代码树高度,可选,默认为空 * **entry**: 默认展开的文件路径,可选,默认为第一个文件 **输入:** ```md @[code-tree title="Collections 配置" height="400px" entry="index.ts"](/.vuepress/collections) ``` **输出:** @[code-tree title="Collections 配置" height="400px" entry="index.ts"](/.vuepress/collections) --- --- url: /guide/markdown/collapse/index.md --- # 折叠面板 ## 概述 在 markdown 中,使用 `::: collapse` 容器,包含 markdown 无序列表语法,实现 ==折叠面板== 。 * 支持通过 `accordion` 设置为 ==手风琴== 模式 ## 启用 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { collapse: true, // [!code ++] } }) }) ``` ## 使用 在 markdown 中,使用 `::: collapse` 容器,包含 markdown 无序列表语法,每一项为一个单独的可折叠区域。 ```md title="collapse.md" ::: collapse - 标题 1 内容 - 标题 2 内容 ::: ``` 对于列表的每一个项: * 从 **首行开始** 到 **首个空行**,均为 **标题** * **首个空行之后**: 正文内容 :::important 请注意添加正确的缩进 ::: **一个简单的例子:** **输入:** ```md ::: collapse - 标题 1 正文内容 - 标题 2 正文内容 ::: ``` **输出:** ::: collapse * 标题 1 正文内容 * 标题 2 正文内容 ::: ## 配置 在 `::: collapse` 容器语法之后,跟随配置项: * `accordion` :折叠面板设置为 ==手风琴== 模式,在手风琴模式下,只允许展开一个面板,点击其他面板会关闭之前的面板。 * `expand` :默认展开面板,在手风琴模式下无效。 在列表项,标题之前,可通过特殊标记 `:+` / `:-` 来设置当前项是否 **展开 / 折叠**。 ## 示例 ### 基本用法 **输入:** ```md ::: collapse - 标题 1 正文内容 - 标题 2 正文内容 ::: ``` **输出:** ::: collapse * 标题 1 正文内容 * 标题 2 正文内容 ::: ### 默认全部展开 添加 `expand` 选项,默认展开所有面板 **输入:** ```md /expand/ ::: collapse expand - 标题 1 正文内容 - 标题 2 正文内容 ::: ``` **输出:** ::: collapse expand * 标题 1 正文内容 * 标题 2 正文内容 ::: ### 手风琴模式 添加 `accordion` 选项,设置为手风琴模式,只允许展开一个面板,点击其他面板会关闭之前的面板 ```md /accordion/ ::: collapse accordion - 标题 1 正文内容 - 标题 2 正文内容 - 标题 3 正文内容 ::: ``` **输出:** ::: collapse accordion * 标题 1 正文内容 * 标题 2 正文内容 * 标题 3 正文内容 ::: ### `:+` 标记项为展开 折叠面板默认全部关闭,可以使用 `:+` 标记项初始状态为展开。 **输入:** ```md /:+/ ::: collapse - 标题 1 正文内容 - :+ 标题 2 正文内容 - :+ 标题 3 正文内容 ::: ``` **输出:** ::: collapse * 标题 1 正文内容 * :+ 标题 2 正文内容 * :+ 标题 3 正文内容 ::: ### `:-` 标记项为折叠 折叠面板配置 `expand` 时默认全部展开,可以使用 `:-` 标记项初始状态为折叠。 **输入:** ```md /:-/ ::: collapse expand - 标题 1 正文内容 - :- 标题 2 正文内容 - 标题 3 正文内容 ::: ``` **输出:** ::: collapse expand * 标题 1 正文内容 * :- 标题 2 正文内容 * 标题 3 正文内容 ::: --- --- url: /guide/markdown/demo-wrapper/index.md --- # 示例容器 ## 概述 有时候,你可能需要在 内容中补充一些 示例,但期望能与 其它内容 分隔开来呈现。 主题支持在 Markdown 文件中添加示例容器。 ## 语法 ```md ::: demo-wrapper 添加你的示例 ::: ``` ## 选项 * `title="xxx"`:标题 * `no-padding`:不添加内边距 * `img`: 仅包含图片时使用 * `height="xxx"`: 高度 ## 示例 仅包含图片: ```md ::: demo-wrapper img no-padding ![hero](/images/custom-hero.jpg) ::: ``` **输出:** ::: demo-wrapper img no-padding ![hero](/images/custom-hero.jpg) ::: 包含 markdown 语法: ```md ::: demo-wrapper title="标题" ### 三级标题 这是示例容器中的内容。 ::: ``` **输出:** ::: demo-wrapper title="标题" ### 三级标题 这是示例容器中的内容。 ::: 包含 html /vue 代码: ```md ::: demo-wrapper

这是标题

这是段落

::: ``` **输出:** ::: demo-wrapper ::: --- --- url: /guide/markdown/extensions/index.md --- ## 标题锚点 标题会自动应用锚点。 ### 自定义锚点 要为标题指定自定义锚点而不是使用自动生成的锚点,请向标题添加后缀: ```md # 使用自定义锚点 {#my-anchor} ``` 这允许将标题链接为 `#my-anchor`,而不是默认的 `#使用自定义锚点`。 ## 链接 内部和外部链接都会被特殊处理。 主题默认对每个 md 文件自动生成一个新的 链接,并保存在对应的 md 文件的 frontmatter 的 `permalink` 中。 你可以随时修改它们。你也可以通过 `theme.autoFrontmatter` 选项来禁用这个功能,这时会恢复为 VuePress 的默认行为。 ### 内部链接 有三种方式来使用内部链接: * 使用 生成的 `permalink` 作为内部链接的目标。 * 使用 md 文件的相对路径作为内部链接的目标。 * 使用 md 文件的绝对路径作为内部链接的目标, 绝对路径 `/` 表示从 `${sourceDir}` 目录开始。 ```md [Markdown](/guide/markdown/) [Markdown](./basic.md) ``` 渲染为: [Markdown](/guide/markdown/) [Markdown](./basic.md) ### 外部链接 外部链接带有 `target="_blank" rel="noreferrer"` : [VuePress](https://v2.vuepress.vuejs.org/) ## Github风格的表格 **输入:** ```md | Tables | Are | Cool | | ------------- | :-----------: | ----: | | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | ``` **输出:** | Tables | Are | Cool | | ------------- | :-----------: | ----: | | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | ## Emoji :tada: **输入:** ```md :tada: :100: ``` **输出:** :tada: :100: 这里可以找到 [所有支持的 emoji 列表](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)。 ## 目录表 **输入:** ```md [[TOC]] ``` **输出:** \[\[TOC]] ## 自定义容器 自定义容器可以通过它们的类型、标题和内容来定义。 ### 默认标题 **输入:** ```md ::: note This is a note box ::: ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: caution This is a dangerous warning. ::: ::: details This is a details block. ::: ``` **输出:** ::: note This is a note box ::: ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: caution This is a dangerous warning. ::: ::: details This is a details block. ::: ### 自定义标题 可以通过在容器的 "type" 之后附加文本来设置自定义标题。 **输入:** ````md ::: caution STOP 危险区域,请勿继续 ::: ::: details 点我查看代码 ```js console.log('Hello, VitePress!') ``` ::: ```` **输出:** ::: caution STOP 危险区域,请勿继续 ::: ::: details 点我查看代码 ```js console.log('Hello, VitePress!') ``` ::: ## GitHub 风格的警报 主题 同样支持以标注的方式渲染 [GitHub 风格的警报](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)。它们和[自定义容器](#自定义容器)的渲染方式相同。 **输入:** ```md > [!NOTE] > 强调用户在快速浏览文档时也不应忽略的重要信息。 > [!TIP] > 有助于用户更顺利达成目标的建议性信息。 > [!IMPORTANT] > 对用户达成目标至关重要的信息。 > [!WARNING] > 因为可能存在风险,所以需要用户立即关注的关键内容。 > [!CAUTION] > 行为可能带来的负面影响。 ``` **输出:** > \[!NOTE] > 强调用户在快速浏览文档时也不应忽略的重要信息。 > \[!TIP] > 有助于用户更顺利达成目标的建议性信息。 > \[!IMPORTANT] > 对用户达成目标至关重要的信息。 > \[!WARNING] > 因为可能存在风险,所以需要用户立即关注的关键内容。 > \[!CAUTION] > 行为可能带来的负面影响。 ## 数学方程 **输入:** ``` When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | ``` **输出:** When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}, +, \frac1c, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -, \frac1c, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | *wha?* | ## 上下角标 * 使用 `^ ^` 进行上角标标注。 * 使用 `~ ~` 进行下角标标注。 **输入:** ```md - 19^th^ - H~2~O ``` **输出:** * 19^th^ * H~2~O ## 自定义对齐 **输入:** ```md ::: left 左对齐的内容 ::: ::: center 居中的内容 ::: ::: right 右对齐的内容 ::: ``` **输出:** ::: left 左对齐的内容 ::: ::: center 居中的内容 ::: ::: right 右对齐的内容 ::: ## 属性支持 你可以使用特殊标记为 Markdown 元素添加属性。 **为图片添加属性:** 这将为图片添加 一个 名为 `full-width` 的 class 属性,以及一个 `width` 属性,值为 `100%`。 ```md ![](/plume.png){.full-width width="100%"} ``` 同时也支持其他属性: ```md 一个包含文字的段落。 {#p .a .b align=center customize-attr="content with spaces"} ``` 这将被渲染为: ```html

一个包含文字的段落。

``` ## 任务列表 **输入:** ```md - [ ] 任务 1 - [x] 任务 2 - [ ] 任务 3 ``` **输出:** * \[ ] 任务 1 * \[x] 任务 2 * \[ ] 任务 3 ## 脚注 **输入:** ```md 人生自古谁无死,留取丹心照汗青[^脚注1]。 [^脚注1]: 出自 宋·文天祥 **《过零丁洋》** ``` **输出:** 人生自古谁无死,留取丹心照汗青\[^脚注1]。 \[^脚注1]: 出自 宋·文天祥 **《过零丁洋》** --- --- url: /guide/markdown/field/index.md --- # 字段容器 ## 概述 在 markdown 中,使用 `::: field` 容器,用于描述字段信息,包括字段名称、字段类型、是否必填、默认值、详情等信息。 它适用于 描述配置中的字段、组件的 Props 等场景。 还可以使用额外的 `:::: field-group` 容器,用于组合多个 `::: field`。 ## 启用 该功能默认不启用,您需要在 `theme` 配置中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { field: true, // [!code ++] }, }) }) ``` ## 语法 ```md ::: field name="字段名" type="类型" required default="默认值" 字段描述信息 ::: :::: field-group ::: field name="字段名" type="类型" required default="默认值" 字段描述信息 ::: ::: field name="字段名" type="类型" required default="默认值" 字段描述信息 ::: :::: ``` ## 属性 :::: field-group ::: field name="name" required type="string" 字段名称 ::: ::: field name="type" type="string" optional 字段的类型 ::: ::: field name="required" type="boolean" optional 是否必填 ::: ::: field name="optional" type="boolean" optional 是否可选 ::: ::: field name="deprecated" type="boolean" optional 是否弃用 ::: ::: field name="default" type="string" optional 默认值, 如果为空字符串,应该使用 `default="''"` ::: :::: ## 示例 **输入:** ```md ::: field name="theme" type="ThemeConfig" required default="{}" 主题配置 ::: ::: field name="enabled" type="boolean" optional default="true" 是否启用 ::: ``` **输出:** ::: field name="theme" type="ThemeConfig" required default="{}" 主题配置 ::: ::: field name="enabled" type="boolean" optional default="true" 是否启用 ::: **输入:** ```md :::: field-group ::: field name="theme" type="ThemeConfig" required default="{ base: '/' }" 主题配置 ::: ::: field name="enabled" type="boolean" optional default="true" 是否启用 ::: ::: field name="callback" type="(...args: any[]) => void" optional default="() => {}" 回调函数 ::: ::: field name="other" type="string" deprecated 已弃用属性 ::: :::: ``` **输出:** :::: field-group ::: field name="theme" type="ThemeConfig" required default="{ base: '/' }" 主题配置 ::: ::: field name="enabled" type="boolean" optional default="true" 是否启用 ::: ::: field name="callback" type="(...args: any\[]) => void" optional default="() => {}" 回调函数 ::: ::: field name="other" type="string" deprecated 已弃用属性 ::: :::: --- --- url: /guide/markdown/file-tree/index.md --- # 文件树 ## 概述 在 Markdown 中,你可以使用 `file-tree` 容器 来显示带有文件图标和可折叠子目录的目录结构。 ## 语法 在 `::: file-tree` 容器,使用内置的 **Markdown 无序列表语法** 指定文件和目录的组织结构。 使用嵌套的列表项创建子目录;若希望某个目录不显示具体内容,只需在列表项末尾添加斜杠 `/` 即可。 以下语法可用于自定义文件树的外观: * 通过加粗文件名或目录名来突出显示,例如 `**README.md**` * 通过在名称后添加更多文本来为文件或目录添加注释 * 通过在名称前添加 `++` 或 `--` 来标记文件或目录为 **新增** 或 **删除** * 使用 `...` 或 `…` 作为名称来添加占位符文件和目录。 * 在 `:::file-tree` 后添加 `icon="simple"` 或 添加 `icon="colored"` 可以切换为简单图标或彩色图标,默认为彩色图标。 * 在 `:::file-tree` 后添加 `title="xxxx"` 可以为文件树添加标题。 **输入:** ```md /++/ /--/ ::: file-tree - docs - .vuepress - ++ config.ts - -- page1.md - README.md - theme 一个 **主题** 目录 - client - components - **Navbar.vue** - composables - useNavbar.ts - styles - navbar.css - config.ts - node/ - package.json - pnpm-lock.yaml - .gitignore - README.md - … ::: ``` **输出:** ::: file-tree * docs * .vuepress * ++ config.ts * \-- page1.md * README.md * theme 一个 **主题** 目录 * client * components * **Navbar.vue** * composables * useNavbar.ts * styles * navbar.css * config.ts * node/ * package.json * pnpm-lock.yaml * .gitignore * README.md * … ::: ## 使用简单图标 **输入:** ```md ::: file-tree icon="simple" - docs - .vuepress - config.ts - page1.md - README.md - package.json ::: ``` **输出:** ::: file-tree icon="simple" * docs * .vuepress * config.ts * page1.md * README.md * package.json ::: ## 配置 你可以在 `markdown.fileTree` 选项中配置 文件树的图标默认类型: ::: code-tabs @tab .vuepress/config.ts ```ts export default defineUserConfig({ theme: plumeTheme({ markdown: { fileTree: { icon: 'simple', // 'simple' | 'colored' } }, }) }) ``` ::: ::: tip 担心彩色图标会影响构建包体积? 您无需担心,文件树的彩色图标 也是从 `iconify` 解析获取,推荐您在本地安装 `@iconify/json` 项目, 主题会自动将 `@iconify/json` 中的图标数据解析为本地图标资源,即使您在不同的页面 多次使用,这包括了 导航栏、侧边栏、图标组件等,相同图标仅会存在一份资源! 每个彩色图标的大小约在 `1kb ~ 2kb` 之间,即使您的文件树非常夸张的使用了 100+ 不同的图标,对最终的构建包体积影响 也不会很大。 ::: --- --- url: /guide/markdown/flex/index.md --- # Flex 容器 ## 概述 Flex 弹性容器 `::: flex` 提供一种便捷的方式,在 markdown 中对 块级内容 应用 Flex 布局。 ## 用法 ```md ::: flex [center|between|around] [start|center|end] [gap="20"] [column] ::: ``` ## 属性 * 在 主轴 方向上,使用 `center` / `between` / `around` 指定对齐方式; * 在 交叉轴 方向上,使用 `start` / `center` / `end` 指定对齐方式; * 使用 `gap="20"` 指定间距; * 使用 `column` 指定主轴方向为垂直方向。 ## 示例 ### 表格居中对齐 **输入:** ```md ::: flex center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: ``` **输出:** ::: flex center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: ### 两个表格左右对齐 **输入:** ```md ::: flex between center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: ``` **输出:** ::: flex between center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: ### 平均排列两个表格 **输入:** ```md ::: flex around center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: ``` **输出:** ::: flex around center | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | | 列 1 | 列 2 | 列 3 | | ---- | ---- | ---- | | 1 | 2 | 3 | | 4 | 5 | 6 | ::: --- --- url: /guide/markdown/icon/index.md --- # 图标 ::: warning 图标语法糖在 `1.0.0-rc.144` 版本中进行了破坏性变更。 `:[collect:name size/color]:` 语法糖已弃用,请使用 `::collect:name =size /color::` 代替。 主题计划在未来的版本中,支持如 `iconfont` / `fontawesome` / `lucide` 等图标库的图标,原有语法糖 不足以支持新的扩展,因此此破坏性变更是必要的。 旧的语法在近期的版本中依然支持,但不再推荐使用,且在未来会删除。 主题会检测是否使用旧的语法,如果使用,会在控制台输出警告信息和修改建议,请根据修改建议进行调整。 ::: ## 概述 主题支持在 Markdown 文件中以下来源的图标: * [iconify](https://iconify.design/) - 默认支持 * [iconfont](https://www.iconfont.cn/) - 可选 * [fontawesome](https://fontawesome.com/) - 可选 主题提供图标 markdown 语法支持,使用简单灵活的方式在 Markdown 中插入图标。 [主题还提供了 `` 组件支持,点击了解更多](../components/icon.md){.read-more} ## 语法 图标语法为行内语法,可以在段落中与其他 markdown 语法混合使用。 **基础语法**,使用 `::` 包裹图标名称: ```md ::name:: ``` **设置图标大小和颜色**:(注意空格不可缺少) ```md ::name =size:: ::name /color:: ::name =size /color:: ``` * `=size`: 设置图标大小 * `=16`: 图标的宽高为 `16px` * `=24x16`: 图标的宽为 `24px`,高为 `16px` * `=x16`: 图标的高为 `16px`,宽为自适应 * `=1.2em`: 图标的宽高为 `1.2em` * `=1.2emx1.5em`: 图标的宽为 `1.2em`,高为 `1.5em` * `/color`: 设置图标颜色,支持 `hex`/ `rgb` / `rgba` / `hsl` / `hsla` 等合法颜色色值 * `/#fff` : 图标的颜色为 `#fff` * `/rgb(255,0,0)`: 图标的颜色为 `rgb(255,0,0)` ## Iconify [iconify](https://iconify.design/) 提供了 **200K +** 的开源图标支持,足以满足大多数项目的需求。 主题将 **iconify** 作为默认的图标来源支持。 在 Markdown 中使用 `::collect:name` 语法来插入图标。 ### 配置 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // [!code ++:3] icon: { provider: 'iconify' } // 默认支持 } }) }) ``` ```ts interface IconOptions { provider: 'iconify' prefix?: string } ``` ### 使用 ::: steps * 从 [iconify search](https://icon-sets.iconify.design/) 搜索想要使用的图标,复制图标名称: ![iconify](/images/icon/iconify-1.png) * 在 Markdown 中使用 `::collect:name` 语法来插入图标 ```md ::carbon:home:: ``` **输出:** ::carbon:home:: ::: 在 Iconify 中,图标被分为不同的 `collect`,每个 `collect` 下有若干个图标。 在 `::collect:name` 语法中,使用 `:` 来分隔 `collect` 和 `name`。 如果你主要使用某个 `collect` 下的图标,可以在配置中指定 `prefix`, 以便在 `::collect:name` 语法中省略 `collect` 前缀: ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { icon: { provider: 'iconify', prefix: 'carbon', // 默认使用 `collect` 图标集合 // [!code ++] } } }) }) ``` ```md ::home:: ::solar:user-bold:: ``` **输出:** ::carbon:home:: ::solar:user-bold:: ### 安装 对于企业内部项目,或无法访问外部网络资源的情况下,主题推荐安装 `@iconify/json` 依赖。 主题自动解析 `@iconify/json` 中的图标数据,将已使用的图标打包为本地资源。 ::: npm-to ```sh npm install @iconify/json ``` ::: ### 示例 输入: ```md github: ::tdesign:logo-github-filled:: 修改颜色:::tdesign:logo-github-filled /#f00:: 修改大小:::tdesign:logo-github-filled =36px:: 修改大小颜色:::tdesign:logo-github-filled =36px /#f00:: 彩色图标 ::skill-icons:vscode-dark =36px:: ``` 输出: github: ::tdesign:logo-github-filled:: 修改颜色:::tdesign:logo-github-filled /#f00:: 修改大小:::tdesign:logo-github-filled =36px:: 修改大小颜色:::tdesign:logo-github-filled =36px /#f00:: 彩色图标 ::skill-icons:vscode-dark =36px:: ## Iconfont [iconfont](https://www.iconfont.cn/) 是提供了海量的图标支持。 ### 配置 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // [!code ++:3] icon: { provider: 'iconfont', assets: 'https://at.alicdn.com/t/c/xxxx.css' // 示例地址 } } }) }) ``` ```ts interface IconOptions { provider: 'iconfont' /** * 图标前缀 * @default 'iconfont icon-' */ prefix?: string /** * iconfont 资源地址 */ assets: string | string[] } ``` ### 使用 [前往 **iconfont 帮助中心** 了解 **创建项目**和 **添加图标**](https://www.iconfont.cn/help/detail){.read-more} :::steps * 从 iconfont 获取项目的资源地址,复制并粘贴到 `assets` 配置中: ![iconfont assets](/images/icon/iconfont-1.png) ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { icon: { provider: 'iconfont', assets: 'https://at.alicdn.com/t/c/xxxx.css' // 示例地址 // [!code ++] } } }) }) ``` 也可以选择下载至本地,将资源存放到 `.vuepress/public` 目录中,然后在 `assets` 配置中填写本地文件路径。 * 检查 iconfont 的项目配置,获取 `prefix` 配置: ![iconfont prefix](/images/icon/iconfont-2.png) 其中 `prefix` 配置由 `font family` 和 `font class` 前缀组成,如果 iconfont 的项目配置为默认配置, 则 `prefix` 为 `iconfont icon-`,此时你可以忽略此步骤。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { icon: { provider: 'iconfont', prefix: 'iconfont icon-', // 默认值 // [!code ++] } } }) }) ``` * 在 Markdown 中使用 `::name::` 语法来插入图标: ![iconfont name](/images/icon/iconfont-3.png) 将图片中的 `font class` 填入 `::name::` 语法中: ```md ::hot:: ::hot =24px:: ::hot =24px /#f00:: ``` 输出: ::: ## Fontawesome [Fontawesome](https://fontawesome.com/) 提供了 免费 和 付费 的图标支持,付费图标需要进行订阅。 [查看 **Fontawesome** 官方文档](https://docs.fontawesome.com/web/setup/get-started){.read-more} ### 配置 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ markdown: { // [!code ++:3] icon: { provider: 'fontawesome', assets: 'fontawesome' // 预设资源地址,从 CDN 加载 } } }) }) ``` ```ts interface IconOptions { provider: 'fontawesome' /** * 图标前缀 * @default 'fas' */ prefix?: FontAwesomePrefix /** * iconfont 资源地址 */ assets: (FontAwesomeAssetBuiltin | string)[] } type FontAwesomeAssetBuiltin = 'fontawesome' | 'fontawesome-with-brands' type FontAwesomePrefix = | 'fas' | 's' // fa-solid fa-name | 'far' | 'r' // fa-regular fa-name | 'fal' | 'l' // fa-light fa-name | 'fat' | 't' // fa-thin fa-name | 'fads' | 'ds' // fa-duotone fa-solid fa-name | 'fass' | 'ss' // fa-sharp fa-solid fa-name | 'fasr' | 'sr' // fa-sharp fa-regular fa-name | 'fasl' | 'sl' // fa-sharp fa-light fa-name | 'fast' | 'st' // fa-sharp fa-thin fa-name | 'fasds' | 'sds' // fa-sharp-duotone fa-solid fa-name | 'fab' | 'b' // fa-brands fa-name ``` [在 **Fontawesome** 中,图标通过 families + styles 控制样式,**查看详情**](https://docs.fontawesome.com/web/add-icons/how-to#setting-different-families--styles){.read-more} 为便于管理,可以通过 `::prefix:name::` 语法,通过前缀设置 families + styles,默认前缀为 `fas`,可以省略它: ```md ::name:: ::fas:name:: ::s:name:: ``` 可以通过配置 `markdown.icon.prefix` 修改默认前缀。 ::: tip Fontawesome 的免费图标仅支持 `solid` 、部分 `regular` 以及 `brands`, 对于免费版本,前缀仅支持 `fas` / `far` / `fab` 和它们的缩写前缀。 ::: ### 使用 [前往 **https://fontawesome.com/search?ic=free** 搜索免费图标](https://fontawesome.com/search?ic=free){.read-more} :::steps * 复制图标名称: ![fontawesome name](/images/icon/fontawesome-1.png) * 在 Markdown 中使用 `::prefix:name::` 语法插入图标: ```md ::circle-user:: ::fas:circle-user:: ::s:circle-user:: ``` ::: ### 示例 ```md ::circle-user:: ::circle-user =24px:: ::circle-user =24px /#f00:: ``` 输出: [为 Fontawesome 添加更多样式支持](https://docs.fontawesome.com/web/style/styling){.read-more} ``` ::circle-user 2xl:: ::circle-user rotate-90:: ::circle-user beat:: ::circle-user border:: ::circle-user 2xl beat:: ``` 输出: ## 其它说明 当 `markdown.icon.provider` 设置为非 `iconify` 时,`iconify` 作为默认支持,依然可以在 markdown 中插入 iconify 图标: 在 `::collect:name::` 语法中,在开始位置添加 `iconify`: ```md /iconify / ::iconify carbon:home:: ``` 输出: ::iconify carbon:home:: --- --- url: /guide/markdown/include/index.md --- # 导入文件 ## 概述 主题支持在 Markdown 文件中导入文件切片。 导入文件 默认启用,你还可以通过配置来自定义行为。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { include: { // [!code ++:3] // ... options }, } }) }) ``` ## 语法 使用 `` 导入文件。 如果要部分导入文件,你可以指定导入的行数: * `` * `` * `` 同时你也可以导入文件区域: * `` ::::tip 文件区域 文件区域是 vscode 中的一个概念,区域内容被 `#region` 和 `#endregion` 注释包围。 :::: ## 配置 你还可以设置一个对象来自定义包含文件路径和包含行为。 ```ts interface IncludeOptions { /** * 处理 include 文件路径 * * @default (path) => path */ resolvePath?: (path: string, cwd: string | null) => string /** * 是否深度导入包含的 Markdown 文件 * * @default false */ deep?: boolean /** * 是否使用 `` 代替 `@include: xxx` 导入文件 * * @default true */ useComment?: boolean /** * 是否解析包含的 Markdown 文件的里的相对图像路径 * * @default true */ resolveImagePath?: boolean /** * 是否解析包含的 Markdown 文件的里的文件相对路径 * * @default true */ resolveLinkPath?: boolean } ``` 例如: 你可以使用 `@src` 作为源文件夹的别名。 ```ts{5-11} title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { include: { resolvePath: (file) => { if (file.startsWith('@src')) return file.replace('@src', path.resolve(__dirname, '..')) return file }, }, } }) }) ``` 此外,如果你想将 Markdown 文件直接放在实际文件旁边,但不希望它们呈现为页面, 你可以在 VuePress 配置中设置 `pagePatterns` 选项。 有关详细信息,请参阅 [pagePatterns](https://vuejs.press/zh/reference/config.html#pagepatterns)。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ // 现在任何带有 `.snippet.md` 扩展名的文件都不会呈现为页面 pagePatterns: ['**/*.md', '!**/*.snippet.md', '!.vuepress', '!node_modules'], // [!code ++] theme: plumeTheme({ markdown: { include: true } }) }) ``` ## 示例 在项目中有一个 `foo.snippet.md` 文件: :::: code-tabs @tab foo.snippet.md ```md ### 三级标题 这是 foo.snippet.md 文件中的内容。 ::: info 提示容器包括的内容 ::: 这里是被 `` 包裹的内容。 通过 `` 来引入。 ``` :::: 使用 `` 导入文件: :::: demo-wrapper title="Include by file" :::: 使用 `` 导入文件内的 5 到 7 行: :::: demo-wrapper title="Include by lines" :::: 使用 `` 导入 `snippet` 区域 :::: demo-wrapper title="Include by file region" :::: --- --- url: /guide/markdown/mark/index.md --- # 马克笔 ## 概述 \==马克笔== 是对 Markdown 中的的标记语法 `==Mark==` 的扩展,支持在内容中使用多种不同的颜色来标记文本, 还可以方便灵活的自定义更多不同的马克笔颜色。 ## 语法 ### 常规 使用 `== ==` 进行标记。请注意两边需要有空格。 **输入:** ```md vuepress-theme-plume 是一个 ==简洁美观== 的 主题 ``` **输出:** vuepress-theme-plume 是一个 ==简洁美观== 的 主题 ### 配色 不同颜色的马克笔通过 [Markdown 属性语法](./extensions.md#属性支持) 进行设置。 在 标记语法 `==Mark==` 之后紧跟 `{.classname}`,可以为马克笔设置不同的颜色。 **输入:** ```md ==一个提示=={.tip} ==一个警告=={.warning} ==一个错误=={.danger} ==重要内容=={.important} ``` **输出:** \==一个提示=={.tip} ==一个警告=={.warning} ==一个错误=={.danger} ==重要内容=={.important} ## 内置配色 主题内置了以下的配置方案: * **default**: `==Default==` - ==Default== * **info**: `==Info=={.info}` - ==Info=={.info} * **note**: `==Note=={.note}` - ==Note=={.note} * **tip**: `==Tip=={.tip}` - ==Tip=={.tip} * **warning**: `==Warning=={.warning}` - ==Warning=={.warning} * **danger**: `==Danger=={.danger}` - ==Danger=={.danger} * **caution**: `==Caution=={.caution}` - ==Caution=={.caution} * **important**: `==Important=={.important}` - ==Important=={.important} ## 自定义配色 马克笔可以通过 [自定义样式](../custom/style.md) 的方式进行自定义。 你可以完全自定义你的马克笔颜色,包括内置的配置方案也可以进行修改。 在主题内部,马克笔通过 `类名` + `CSS 变量` 的方式进行设置。 以下是与马克笔相关的 `CSS 变量`: * `--vp-mark-text` - 马克笔的文本颜色 * `--vp-mark-bg` - 马克笔的背景颜色 * `--vp-mark-linear-color` - 渐变颜色,仅用于内置的 `--vp-mark-bg-image` 中 * `--vp-mark-bg-shift` - 马克笔的内置渐变背景偏移 * `--vp-mark-bg-image` - 马克笔的背景图片 ### 修改内置配色 以下是主题内置的马克笔颜色配置,你可以把它们复制到你的 [样式文件](../custom/style.md#style-文件) 中进行修改。 ```css :collapsed-lines mark { --vp-mark-text: currentcolor; --vp-mark-bg: transparent; --vp-mark-bg-shift: 0.55lh; --vp-mark-linear-color: var(--vp-c-brand-3); --vp-mark-bg-image: linear-gradient(to right, var(--vp-mark-linear-color) 50%, transparent 50%); animation: var(--vp-mark-animation, mark-highlight 1.5s 0.5s forwards); } [data-mark-mode="lazy"] mark { --vp-mark-animation: none; } [data-mark-mode="lazy"] mark.vp-mark-visible { animation: mark-highlight 1.5s 0.2s forwards; } mark.note { --vp-mark-linear-color: #ff0; } mark.info { --vp-mark-linear-color: var(--vp-c-default-1); } mark.tip { --vp-mark-linear-color: #39ff14; } mark.warning { --vp-mark-linear-color: #fc0; } mark.caution, mark.danger { --vp-mark-linear-color: #f99; } mark.important { --vp-mark-linear-color: #ccf; } [data-theme="dark"] mark.note { --vp-mark-linear-color: #660; } [data-theme="dark"] mark.tip { --vp-mark-linear-color: #063; } [data-theme="dark"] mark.warning { --vp-mark-linear-color: #c60; } [data-theme="dark"] mark.caution, [data-theme="dark"] mark.danger { --vp-mark-linear-color: #c66; } [data-theme="dark"] mark.important { --vp-mark-linear-color: #66c; } ``` ### 添加配色 在 [样式文件](../custom/style.md#style-文件) 中,通过以下格式添加新的配色: ```css mark.classname { --vp-mark-text: marktext; /* 文本颜色 */ --vp-mark-bg-image: none; /* 背景图片 */ --vp-mark-bg: mark; /* 背景颜色 */ --vp-mark-linear-color: mark; /* 渐变颜色 */ } ``` 然后在 Markdown 中使用 `==Mark=={.classname}` 进行标记。 你可以随意命名 `classname`,除了修改 CSS 变量,也可以添加其他的 CSS 样式属性。 ## 动画模式 默认情况下,马克笔会在页面渲染时立即播放描线动画。 如果希望在滚动到可视区域后再播放动画,可以在主题配置中将 `markdown.mark` 设置为 `'lazy'`: ```ts title=".vuepress/config.ts" {5} export default defineUserConfig({ theme: plumeTheme({ markdown: { mark: 'lazy', }, }), }) ``` --- --- url: /guide/markdown/npm-to/index.md --- # npmTo 容器 ## 概述 npmTo 容器用于将 npm 命令行转换为 `pnpm / yarn / deno / bun` 的命令行,并它们作为 代码块组呈现在页面。 在 `::: npm-to` 容器中,只需要写 一次 npm 命令 代码块即可。 ::: details 为什么需要 npmTo 容器 ? 在我编写文档时,常常需要提供 `pnpm / yarn / npm` 等不同运行环境的命令,需要写多个代码块并包装在 `::: code-tabs` 容器中。它占据了我不少的工作量,而且还占据了 markdown 内容中的很长一部分空间,体验并不友好。 因此我编写了这个 `::: npm-to` 容器以解决这个问题。 ::: ## 用法 ````md{1,5} ::: npm-to ``` sh npm install -D vuepress vuepress-theme-plume ``` ::: ```` 将 包含 `npm` 命令行的代码块,包裹在 `::: npm-to` 容器中即可。 ::: warning npm-to 容器仅支持存在单个代码块,不能包含其他内容 ::: 上述代码在内部会被转换为: ````md ::: code-tabs @tab pnpm ``` sh pnpm add -D vuepress vuepress-theme-plume ``` @tab yarn ``` sh yarn add -D vuepress vuepress-theme-plume ``` @tab npm ``` sh npm install -D vuepress vuepress-theme-plume ``` ::: ```` 最终会在页面中呈现为: ::: npm-to ```sh npm install -D vuepress vuepress-theme-plume ``` ::: 还可以控制 代码块组中的代码块的显示顺序,如下所示: **输入:** ````md {1,5} ::: npm-to tabs="npm,yarn,pnpm,bun,deno" ``` sh npm install -D vuepress vuepress-theme-plume ``` ::: ```` **输出:** ::: npm-to tabs="npm,yarn,pnpm,bun,deno" ```sh npm install -D vuepress vuepress-theme-plume ``` ::: ## 配置 该功能默认不启用,您需要在 `theme` 配置中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { // npmTo: true, // 启用,并使用默认配置 npmTo: { tabs: ['npm', 'yarn', 'pnpm'], // 代码块组默认显示顺序 } }, }) }) ``` `npm-to` 支持将 `npm` 命令行转换为 `pnpm / yarn / deno / bun` 的命令行。可以根据需求进行配置 `tabs` 。 ## 命令行支持 `npmTo` 并不对 `npm` 的所有命令行提供支持,以下是支持的列表: * `npm install` / `npm i` * `npm run` / `npm run-script` * `npm init` * `npm create` * `npm uninstall` / `npm rm` / `npm remove` / `npm un` / `npm unlink` * `npm ci` * `npx` ::: info 对于不支持的命令行,`npmTo` 不会处理它们,仅将它们复制到其他的代码块中。 ::: ## 示例 **输入:** ````md ::: npm-to ```sh npm install && npm run docs:dev ``` ::: ```` **输出:** ::: npm-to ```sh npm install && npm run docs:dev ``` ::: **输入:** ````md ::: npm-to ```sh npm i -D vue npm i --save-peer vuepress npm i typescript ``` ::: ```` **输出:** ::: npm-to ```sh npm i -D vue npm i --save-peer vuepress npm i typescript ``` ::: **输入:** ````md ::: npm-to ```sh npm run docs:dev -- --clean-cache ``` ::: ```` **输出:** ::: npm-to ```sh npm run docs:dev -- --clean-cache ``` ::: **输入:** ````md ::: npm-to tabs="pnpm,yarn,npm,bun,deno" ```sh npm ci ``` ::: ```` **输出:** ::: npm-to tabs="pnpm,yarn,npm,bun,deno" ```sh npm ci ``` ::: --- --- url: /guide/markdown/plot/index.md --- # 隐秘文本 ## 概述 有时候,你不想直接把文本内容毫无保留的展示出来,想要保留一些 隐秘性, 可能是为了引起读者的好奇心,也可能纯粹是故意增加点阅读障碍,让文章变得更加有趣。 为了满足这种小小的心思,主题提供了一个 **“隐秘”文本** 的有趣小功能。它看起来像这样: :::demo-wrapper 你知道吗, !!鲁迅!! 曾说过:“ !!我没说过这句话!!! ” 令我醍醐灌顶,深受启发,浑身迸发出无可匹敌的 力量!于是,!!我在床上翻了个身!! ! ::: 读者不能直接阅读到完整的内容,部分的内容被 “遮住”,需要鼠标悬停到内容上,才能看到被遮住的内容。 ## 配置 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { plot: true, // [!code ++] } }) }) ``` `markdownPower.plot` 支持传入 `boolean | PlotOptions` 类型,该配置用于控制该功能的默认行为。 ```ts interface PlotOptions { /** * 触发方式 * * @default 'hover' */ trigger?: 'hover' | 'click' /** * 遮罩层效果 * * @default 'mask' */ effect?: 'mask' | 'blur' } ``` ## 语法 ```md !!需要隐秘的内容!! ``` 还可以通过属性语法控制行为: ```md !!需要隐秘的内容!!{.click} !!需要隐秘的内容!!{.hover} !!需要隐秘的内容!!{.mask} !!需要隐秘的内容!!{.blur} !!需要隐秘的内容!!{.blur .click} ``` * `.click` - 点击触发 * `.hover` - 鼠标悬停触发 * `.mask` - 遮罩层效果 * `.blur` - 文本模糊效果 ::: info 你也可以使用 [``](../components/plot.md) 组件替代。 ::: ## Frontmatter 在 Frontmatter 中使用 `plot` 选项来控制在当前页面中该功能的默认行为: ``` --- plot: trigger: hover effect: blur --- ``` ## 示例 **输入**: ```md 你知道吗, !!鲁迅!! 曾说过:“ !!我没说过这句话!!! ” 令我醍醐灌顶,深受启发,浑身迸发出无可匹敌的 力量!于是,!!我在床上翻了个身!! ! ``` **输出**: :::demo-wrapper 你知道吗, !!鲁迅!! 曾说过:“ !!我没说过这句话!!!” 令我醍醐灌顶,深受启发,浑身迸发出无可匹敌的 力量!于是,!!我在床上翻了个身!! ! ::: **输入**: ```md 遮罩层效果 + 鼠标悬停:!!鼠标悬停看到我了!!{.mask .hover} 遮罩层效果 + 点击:!!点击看到我了!!{.mask .click} 文本模糊效果 + 鼠标悬停:!!鼠标悬停看到我了!!{.blur .hover} 文本模糊效果 + 点击:!!点击看到我了!!{.blur .click} ``` **输出**: :::demo-wrapper 遮罩层效果 + 鼠标悬停:!!鼠标悬停看到我了!!{.mask .hover} 遮罩层效果 + 点击:!!点击看到我了!!{.mask .click} 文本模糊效果 + 鼠标悬停:!!鼠标悬停看到我了!!{.blur .hover} 文本模糊效果 + 点击:!!点击看到我了!!{.blur .click} ::: --- --- url: /guide/markdown/steps/index.md --- # 步骤 ## 概述 有时候,你需要将内容 划分为递进的步骤展示,你可以使用 `steps` 容器 实现。 ## 语法 在 `steps` 容器内,使用 有序列表 (或无序列表) 来表示步骤。你可以在 容器内使用 任意 markdown 语法。 ```md ::: steps 1. 步骤 1 相关内容 2. 步骤 2 相关内容 ::: ``` ## 示例 输入: ````md :::: steps 1. 步骤 1 ```ts console.log('Hello World!') ``` 2. 步骤 2 这里是步骤 2 的相关内容 3. 步骤 3 ::: tip 提示容器 ::: 4. 结束 :::: ```` 输出: :::: steps 1. 步骤 1 ```ts console.log('Hello World!') ``` 2. 步骤 2 这里是步骤 2 的相关内容 3. 步骤 3 ::: tip 提示容器 ::: 4. 结束 :::: --- --- url: /guide/markdown/table/index.md --- # table 增强 ## 概述 markdown 默认的表格功能相对比较简单,但在实际使用场景中,常常需要在表格中添加一些额外的信息,比如表格的标题; 或者额外的功能,如复制表格的内容等。 在不破坏表格语法的前提下,主题提供了 `::: table` 容器,可以方便的对表格进行扩展。 ::: tip 表格增强容器在持续开发中,如果有其他的功能建议请在 [Issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues) 中反馈。 ::: ## 配置 该功能默认不启用,您需要在 `theme` 配置中启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { // table: true, // 启用默认功能 table: { // 表格默认对齐方式 'left' | 'center' | 'right' align: 'left', // 表格宽度是否为最大内容宽度 // 行内元素不再自动换行,超出容器宽度时表格显示滚动条 maxContent: false, // 表格宽度默认占据整行 fullWidth: false, /** * 复制为 html/markdown * true 相当于 `all`,相当于同时启用 html 和 markdown */ copy: true, // true | 'all' | 'html' | 'md' } }, }) }) ``` ## 语法 直接将 表格 包裹在 `:::table` 中即可。 ```md :::table title="标题" align="center" max-content copy="all" | xx | xx | xx | | -- | -- | -- | | xx | xx | xx | ::: ``` ### Props :::: field-group ::: field name="title" type="string" optional 表格标题,显示在表格的下方 ::: ::: field name="align" type="'left' | 'center' | 'right'" optional default="'left'" 表格对齐方式 ::: ::: field name="copy" type="boolean | 'all' | 'html' | 'md'" optional default="true" 在表格的右上角显示复制按钮,可以复制为 html / markdown * `true` 等同于 `all` * `false` 不显示复制按钮 * `all` 同时启用 `html` 和 `md` * `html` 启用复制为 html * `md` 启用复制为 markdown ::: ::: field name="maxContent" type="boolean" optional default="false" 行内元素不再自动换行,超出容器宽度时表格显示滚动条 ::: ::: field name="fullWidth" type="boolean" optional default="false" 表格宽度默认占据整行 ::: ::: field name="hl-rows" type="string" optional 配置表格中的行高亮。 值使用 `type:row1,row2` 的格式,可以使用 `;` 组合多个 type row。 示例: * `hl-rows="warning:1"`: 将第一行设置为 warning 颜色 * `hl-rows="danger:1,2"`: 将第一行和第二行设置为 danger 颜色 * `hl-rows="warning:1,2;danger:3,4"`: 将第一行和第二行设置为 warning 颜色,第三行和第四行设置为 danger 颜色 `type` 内置支持:`tip/note/info/success/warning/danger/caution/important`。 `row` 从 1 开始计数。 ::: ::: field name="hl-cols" type="string" optional 配置表格中的列高亮。 值使用 `type:col1,col2` 的格式,可以使用 `;` 组合多个 type col。 示例: * `hl-cols="warning:1"`: 将第一列设置为 warning 颜色 * `hl-cols="danger:1,2"`: 将第一列和第二列设置为 danger 颜色 * `hl-cols="warning:1,2;danger:3,4"`: 将第一列和第二列设置为 warning 颜色,第三列和第四列设置为 danger 颜色 `type` 内置支持:`tip/note/info/success/warning/danger/caution/important`。 `col` 从 1 开始计数。 ::: ::: field name="hl-cells" type="string" optional 配置表格中的单元格高亮。 值使用 `type:(row,col)` 的格式,可以使用 `;` 组合多个 type cell。 示例: * `hl-cells="warning:(1,1)"`: 将第一行第一列设置为 warning 颜色 * `hl-cells="danger:(1,1)(2,2)"`: 将第一行第一列,第二行第二列设置为 danger 颜色 * `hl-cells="warning:(1,1)(2,2);danger:(3,3)(4,4)"`: 将第一行第一列,第二行第二列设置为 warning 颜色,第三行第三列,第四行第四列设置为 danger 颜色 `type` 内置支持:`tip/note/info/success/warning/danger/caution/important`。 `row` 从 1 开始计数,`col` 从 1 开始计数。 ::: :::: ## 示例 ### 表格标题 **输入:** ```md ::: table title="这是表格标题" | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ``` **输出:** ::: table title="这是表格标题" | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ### 表格对齐 **输入:** ```md ::: table title="这是表格标题" align="center" | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ``` **输出:** ::: table title="这是表格标题" align="center" | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ### 表格内容宽度 **输入:** ```md :::table title="这是表格标题" max-content | ID | Description | Status | |----|-----------------------------------------------------------------------------|--------------| | 1 | This is an extremely long description that should trigger text wrapping in most table implementations. | In Progress | | 2 | Short text | ✅ Completed | ::: ``` **输出:** :::table title="这是表格标题" max-content | ID | Description | Status | |----|-----------------------------------------------------------------------------|--------------| | 1 | This is an extremely long description that should trigger text wrapping in most table implementations. | In Progress | | 2 | Short text | ✅ Completed | ::: **输入:** ```md ::: table full-width | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ``` **输出:** ::: table full-width | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Cell 1 | Cell 2 | Cell 3 | | Row 2 | Data | Info | ::: ### 表格行高亮 **输入:** ```md ::: table title="这是表格标题" hl-rows="tip:1;warning:2;important:3,4" | row1 | row1 | row1 | | ---- | ---- | ---- | | row2 | row2 | row2 | | row3 | row3 | row3 | | row4 | row4 | row4 | ::: ``` **输出:** ::: table title="这是表格标题" hl-rows="tip:1;warning:2;important:3,4" | row1 | row1 | row1 | | ---- | ---- | ---- | | row2 | row2 | row2 | | row3 | row3 | row3 | | row4 | row4 | row4 | ::: ### 表格列高亮 **输入:** ```md ::: table title="这是表格标题" hl-cols="success:1;warning:2;danger:3,4" | col1 | col2 | col3 | col4 | | ---- | ---- | ---- | ---- | | col1 | col2 | col3 | col4 | | col1 | col2 | col3 | col4 | | col1 | col2 | col3 | col4 | ::: ``` **输出:** ::: table title="这是表格标题" hl-cols="success:1;warning:2;danger:3,4" | col1 | col2 | col3 | col4 | | ---- | ---- | ---- | ---- | | col1 | col2 | col3 | col4 | | col1 | col2 | col3 | col4 | | col1 | col2 | col3 | col4 | ::: ### 表格单元格高亮 **输入:** ```md ::: table title="这是表格标题" hl-cells="danger:(1,1)(2,2);success:(3,3)(4,4);warning:(1,4)(2,3);important:(3,2)(4,1)" | (1,1) | (1,2) | (1,3) | (1,4) | | ----- | ----- | ----- | ----- | | (2,1) | (2,2) | (2,3) | (2,4) | | (3,1) | (3,2) | (3,3) | (3,4) | | (4,1) | (4,2) | (4,3) | (4,4) | ::: ``` **输出:** ::: table title="这是表格标题" hl-cells="danger:(1,1)(2,2);success:(3,3)(4,4);warning:(1,4)(2,3);important:(3,2)(4,1)" | (1,1) | (1,2) | (1,3) | (1,4) | | ----- | ----- | ----- | ----- | | (2,1) | (2,2) | (2,3) | (2,4) | | (3,1) | (3,2) | (3,3) | (3,4) | | (4,1) | (4,2) | (4,3) | (4,4) | ::: ## 自定义高亮类型 在 [自定义 CSS 样式](../custom/style.md) 中,通过以下格式可以自定义高亮类型: ```css .vp-table table th.type, .vp-table table td.type { color: #000; background-color: #fff; } ``` 比如,添加一个 `blue` 的高亮类型: ```css .vp-table table th.blue, .vp-table table td.blue { color: #4a7cb9; background-color: #a3c6e5; } ``` 然后就可以在表格中使用: ```md ::: table hl-rows="blue:1" hl-cols="blue:1" hl-cells="blue:(3,3)" | Header 1 | Header 2 | Header 3 | | -------- | -------- | -------- | | Cell 1 | Cell 2 | Cell 3 | | Cell 4 | Cell 5 | Cell 6 | ::: ``` ::: table hl-rows="blue:1" hl-cols="blue:1" hl-cells="blue:(3,3)" | Header 1 | Header 2 | Header 3 | | -------- | -------- | -------- | | Cell 1 | Cell 2 | Cell 3 | | Cell 4 | Cell 5 | Cell 6 | ::: --- --- url: /guide/markdown/tabs/index.md --- # 选项组 ## 概述 在 Markdown 中支持选项卡。 ## 语法 你需要将选项卡包装在 `tabs` 容器中。 你可以在 `tabs` 容器中添加一个 id 后缀,该后缀将用作选项卡 id。 所有具有相同 id 的选项卡将共享相同的切换事件。 ```md ::: tabs#fruit ::: ``` 在这个容器内,你应该使用 `@tab` 标记来标记和分隔选项卡内容。 在 `@tab` 标记后,你可以添加文本 `:active` 默认激活选项卡,之后的文本将被解析为选项卡标题。 ```md ::: tabs @tab 标题 1 @tab 标题 2 @tab:active 标题 3 ::: ``` 默认情况下,标题将用作选项卡的值,但你可以使用 id 后缀覆盖它。 ```md ::: tabs @tab 标题 1 @tab 标题 2#值 2 ::: ``` 你可以在每个选项卡中使用 Vue 语法和组件,并且你可以访问 value 和 isActive, 表示选项卡的绑定值和选项卡是否处于激活状态。 ## 示例 **输入:** ```` ::: tabs @tab npm npm 应该与 Node.js 被一同安装。 @tab pnpm ```sh corepack enable corepack use pnpm@8 ``` ::: ```` **输出:** ::: tabs @tab npm npm 应该与 Node.js 被一同安装。 @tab pnpm ```sh corepack enable corepack use pnpm@8 ``` ::: --- --- url: /guide/markdown/timeline/index.md --- # 时间线 ## 概述 在 markdown 中,使用 `::: timeline` 容器,包含 markdown 无序列表语法,即可实现 ==时间线== 的 渲染效果。 * 支持 ==水平方向== 和 ==垂直方向== * 垂直方向支持 **左对齐**,**右对齐** 和 **两端对齐** * 支持 **图标** 和 **线条样式** * 支持 通过预设 **类型** 设置 **颜色**,支持自定义颜色 ## 启用 该功能默认不启用,你需要在 `theme` 配置中启用。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { timeline: true, // [!code ++] } }) }) ``` ## 使用 在 `::: timeline` 容器中,使用 markdown 无序列表语法,列表的每一个项即 时间线上的每一个点。 ```md{1,9} title="timeline.md" ::: timeline 配置 - 标题 配置 正文内容 - 标题 配置 正文内容 ::: ``` 对于列表的每一个项: * 从 **首行开始** 到 **首个空行**,均为 **标题** ,在标题后紧跟随的一行,用于 **配置** 当前项的行为 * **首个空行之后**: 正文内容 :::important 请注意添加正确的缩进 ::: **一个简单的例子:** **输入:** ```md ::: timeline - 节点一 time=2025-03-20 type=success 正文内容 - 节点二 time=2025-02-21 type=warning 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 ::: ``` **输出:** ::: timeline * 节点一 time=2025-03-20 type=success 正文内容 * 节点二 time=2025-02-21 type=warning 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 ::: ::: important 时间线默认为垂直方向 ::: ## 配置 **时间线** 支持非常灵活且灵活的配置项,配置主要分为两个部分: * **容器配置**: 在 `::: timeline` 容器上的配置,配置项跟随在 `::: timeline` 之后,如: `::: timeline horizontal` 表示 渲染为 水平方向的时间线。 * **列表项配置**: 列表的每一个项的配置,紧跟随在标题之后的一行,如: ```md ::: timeline - 标题 也是标题 time=2025-03-20 type=success 正文内容 ::: ``` ### 容器配置 :::: field-group ::: field name="horizontal" type="boolean" default="false" optional 渲染为 水平方向 的时间线 ::: ::: field name="card" type="boolean" default="false" optional 每个时间节点默认渲染为卡片样式(可在列表项配置中覆盖) ::: ::: field name="placement" type="'left' | 'right' | 'between'" default="'left'" optional 时间节点的对齐方式。==仅在垂直方向时生效=={.warning} * `left` : 时间轴左侧对齐 * `right` : 时间轴右侧对齐 * `between` : 时间轴两端对齐 (通过列表项配置中的 `placement` 定义位置,默认为 `left`) ::: ::: field name="line" type="'solid' | 'dashed' | 'dotted'" default="'solid'" optional 线条样式(可在列表项配置中覆盖) ::: :::: ### 列表项配置 :::: field-group ::: field name="time" type="string" default="''" optional 时间点,可以是任何字符串,比如 `2025-03-20`, `Q1` 等。 ::: ::: field name="type" type="'info' | 'tip' | 'success' | 'warning' | 'danger' | 'caution' | 'important'" default="'info'" optional 时间节点的类型。 ::: ::: field name="card" type="boolean" default="false" optional 当前 时间节点渲染为卡片样式。默认值从 容器配置 `card` 中继承 ::: ::: field name="line" type="'solid' | 'dashed' | 'dotted'" default="'solid'" optional 线条样式。 默认值从 容器配置 `line` 中继承 ::: ::: field name="icon" type="string" default="''" optional 时间节点的图标,支持所有的 [iconify](https://icon-sets.iconify.design/) 图标。 ::: ::: field name="placement" type="'left' | 'right'" default="'left'" optional 当 容器配置 `placement` 为 `between` 时,定义当前时间节点的位置。 * `left` : 在时间轴左侧 * `right` : 在时间轴右侧 ::: ::: field name="color" type="string" default="''" optional 时间节点线条颜色,可以是任何有效的颜色值。 ::: :::: ## 示例 ### 水平方向 在 `:::timeline` 后跟随声明 `horizontal` , 即可将时间线渲染为 水平方向。 **输入:** ```md /horizontal/ ::: timeline horizontal - 节点一 time=2025-03-20 正文内容 - 节点二 time=2025-04-20 type=success 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 - 节点四 time=2025-01-22 type=important 正文内容 ::: ``` **输出:** ::: timeline horizontal * 节点一 time=2025-03-20 正文内容 * 节点二 time=2025-04-20 type=success 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 * 节点四 time=2025-01-22 type=important 正文内容 ::: ### 右对齐 在 `:::timeline` 后跟随声明 `placement="right"` , 即可将时间线渲染为 右对齐。 **输入:** ```md /placement="right"/ ::: timeline placement="right" - 节点一 time=2025-03-20 正文内容 - 节点二 time=2025-04-20 type=success 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 - 节点四 time=2025-01-22 type=important 正文内容 ::: ``` **输出:** ::: timeline placement="right" * 节点一 time=2025-03-20 正文内容 * 节点二 time=2025-04-20 type=success 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 * 节点四 time=2025-01-22 type=important 正文内容 ::: ### 两端对齐 在 `:::timeline` 后跟随声明 `placement="between"` , 即可将时间线渲染为 两端对齐。 列表项默认位于时间线的左侧,可以通过 `placement="right"` 为列表项设置右侧位置。 **输入:** ```md /placement="between"/ /placement=right/ ::: timeline placement="between" - 节点一 time=2025-03-20 placement=right 正文内容 - 节点二 time=2025-04-20 type=success 正文内容 - 节点三 time=2025-01-22 type=danger placement=right 正文内容 - 节点四 time=2025-01-22 type=important 正文内容 ::: ``` **输出:** ::: timeline placement="between" * 节点一 time=2025-03-20 placement=right 正文内容 * 节点二 time=2025-04-20 type=success 正文内容 * 节点三 time=2025-01-22 type=danger placement=right 正文内容 * 节点四 time=2025-01-22 type=important 正文内容 ::: ### 节点类型 在列表项配置中,添加 `type=节点类型` 可以为当前节点设置节点类型。 **输入:** ```md /type=success/ /type=warning/ /type=danger/ /type=important/ ::: timeline - 节点一 time=2025-03-20 type=success 正文内容 - 节点二 time=2025-04-20 type=warning 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 - 节点四 time=2025-01-22 type=important 正文内容 ::: ``` **输出:** ::: timeline * 节点一 time=2025-03-20 type=success 正文内容 * 节点二 time=2025-04-20 type=warning 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 * 节点四 time=2025-01-22 type=important 正文内容 ::: ### 线条风格 * 在容器配置中添加 `line=线条风格` 可以为所有节点设置默认线条风格。 * 在列表项配置中,添加 `line=线条风格` 可以为节点设置线条风格。 **输入:** ```md /line="dotted"/ /line=solid/ /line=dashed/ ::: timeline line="dotted" - 节点一 time=2025-03-20 正文内容 - 节点二 time=2025-04-20 type=success 正文内容 - 节点三 time=2025-01-22 type=danger line=dashed 正文内容 - 节点四 time=2025-01-22 type=important line=solid 正文内容 ::: ``` **输出:** ::: timeline line="dotted" * 节点一 time=2025-03-20 正文内容 * 节点二 time=2025-04-20 type=success 正文内容 * 节点三 time=2025-01-22 type=danger line=dashed 正文内容 * 节点四 time=2025-01-22 type=important line=solid 正文内容 ::: ### 带图标的节点 在列表项配置中,添加 `icon=图标名称` 可以为节点添加图标。 图标名称支持 [iconify](https://icon-sets.iconify.design/) 的图标名称。 **输入:** ```md /icon=mdi:balloon/ /icon=mdi:bookmark/ ::: timeline placement="between" - 节点一 time=2025-03-20 placement=right icon=mdi:balloon 正文内容 - 节点二 time=2025-04-20 type=success icon=mdi:bookmark 正文内容 - 节点三 time=2025-01-22 type=danger placement=right icon=mdi:bullhorn-variant-outline 正文内容 - 节点四 time=2025-01-22 type=important card=true icon="mdi:cake-variant-outline" 正文内容 ::: ``` **输出:** ::: timeline placement="between" * 节点一 time=2025-03-20 placement=right icon=mdi:balloon 正文内容 * 节点二 time=2025-04-20 type=success icon=mdi:bookmark 正文内容 * 节点三 time=2025-01-22 type=danger placement=right icon=mdi:bullhorn-variant-outline 正文内容 * 节点四 time=2025-01-22 type=important card=true icon="mdi:cake-variant-outline" 正文内容 ::: ### 卡片节点 卡片节点可以很灵活的进行控制: * 在 容器配置中添加 `card` 即可使每个列表项都是卡片节点。 * 在列表项配置中,添加 `card=true` 即可为节点设置为卡片节点。 * 在列表项配置中,添加 `card=false` 即可为节点设置为非卡片节点。 卡片节点的样式会受到 `type` 配置的影响。 ::: tip 在列表项配置中添加 `card=true` / `card=false` 可以覆盖容器节点的 `card` 配置 ::: **输入:** ```md{1} /card=false/ ::: timeline card - 节点一 time=2025-03-20 正文内容 - 节点二 time=2025-04-20 type=success card=false 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 - 节点四 time=2025-01-22 type=important 正文内容 ::: ``` **输出:** ::: timeline card * 节点一 time=2025-03-20 正文内容 * 节点二 time=2025-04-20 type=success card=false 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 * 节点四 time=2025-01-22 type=important 正文内容 ::: ## 自定义节点类型 时间轴的节点类型是通过 CSS Variables 控制的,主题提供了以下的 CSS 变量: ```css :root { --vp-timeline-c-line: var(--vp-c-border); /* 线条颜色 */ --vp-timeline-c-point: var(--vp-c-border); /* 点颜色 */ --vp-timeline-c-title: var(--vp-c-text-1); /* 标题文本颜色 */ --vp-timeline-c-text: var(--vp-c-text-1); /* 正文文本颜色 */ --vp-timeline-c-time: var(--vp-c-text-3); /* 时间文本颜色 */ --vp-timeline-c-icon: var(--vp-c-bg); /* 图标颜色 */ --vp-timeline-bg-card: var(--vp-c-bg-soft); /* 卡片节点的背景颜色 */ } ``` 比如主题内置的节点类型 `tip`: ```css /.tip/ .vp-timeline-item.tip { --vp-timeline-c-line: var(--vp-c-tip-1); --vp-timeline-c-point: var(--vp-c-tip-1); --vp-timeline-bg-card: var(--vp-c-tip-soft); } ``` 可以在 [自定义样式](../custom/style.md) 中,覆盖内置的类型,或者添加新的类型。 **示例:** ```css title=".vuepress/styles/index.css" .vp-timeline-item.your-type { --vp-timeline-c-line: #3cf; --vp-timeline-c-point: #3cf; --vp-timeline-bg-card: rgba(60, 252, 255, 0.314); } ``` ```md /type=your-type/ ::: timeline - 节点一 time=2025-03-20 正文内容 - 节点二 time=2025-04-20 type=your-type card=true 正文内容 - 节点三 time=2025-01-22 type=danger 正文内容 ::: ``` ::: timeline * 节点一 time=2025-03-20 正文内容 * 节点二 time=2025-04-20 type=your-type card=true 正文内容 * 节点三 time=2025-01-22 type=danger 正文内容 ::: --- --- url: /guide/markdown/twoslash/index.md --- # Two Slash ## 概述 为代码块添加支持 [TypeScript TwoSlash](https://www.typescriptlang.org/dev/twoslash/) 支持。 在代码块内提供内联类型提示。 该功能由 [shiki](https://shiki.style/) 和 [@shikijs/twoslash](https://shiki.style/packages/twoslash) 提供支持, 并整合在 [@vuepress-plume/plugin-shikiji](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-shikiji) 中。 ::: important **twoslash** 是一个高级功能,您需要熟练掌握 [TypeScript](https://www.typescriptlang.org/) 的知识,并且了解 [twoslash 语法](https://twoslash.netlify.app/)。 ::: ::: warning `twoslash` 是一个比较耗时的功能,由于它需要对代码进行类型编译,如果代码引入的包 比较大,会花费较长时间。 特别的,由于 vuepress 启动时,会预编译所有的 markdown 文件,因此它会直接影响 vuepress 的启动时间, 如果 包含了比较多的 `twoslash` 代码块,这可能会使 vuepress 启动时间变得很长。 比如,在未使用 `twoslash` 时,vuepress 的启动时间区间大约在 `300ms ~ 1000ms` 之间,而在使用 `twoslash` 后, 可能某一个 `twoslash` 的代码块编译耗时就需要额外再等待 `500ms` 以上。 但不必担心 markdown 文件热更新时的编译耗时,主题针对 代码高亮编译 耗时做了优化,即使 单个 markdown 文件 中包含多个 代码块,主题也仅会对 **有变更的代码块** 进行编译,因此热更新的速度依然非常快。 ::: [twoslash](https://twoslash.netlify.app/) 是一种 `javascript` 和 `typescript` 标记语言。 你可以编写一个代码示例来描述整个 `javascript` 项目。 `twoslash` 将 **双斜杠注释** (`//`) 视为 代码示例的预处理器。 `twoslash` 使用与文本编辑器相同的编译器 API 来提供类型驱动的悬停信息、准确的错误和类型标注。 ## 功能预览 将鼠标悬停在 **变量** 或 **函数** 上查看效果: ```ts twoslash import { createHighlighter } from 'shiki' const highlighter = await createHighlighter({ themes: ['nord'], langs: ['javascript'] }) // ^? // // @log: Custom log message const a = 1 // @error: Custom error message const b = 1 // @warn: Custom warning message const c = 1 // @annotate: Custom annotation message ``` ## 配置 ### 启用功能 在启用功能前,您需要先安装 `@vuepress/shiki-twoslash` 包: ::: npm-to ```sh npm i @vuepress/shiki-twoslash ``` ::: 在 主题配置中,启用 `twoslash` 选项。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ codeHighlighter: { twoslash: true, }, }), }) ``` ::: important `twoslash` 对于大多数用户而言,不是必要的功能,且 `twoslash` 相关的依赖包体积较大, 因此将 `twoslash` 的相关实现均迁移到了 `@vuepress/shiki-twoslash` 中, 这可以有效减少主题的初始安装体积。 仅在您需要使用 `twoslash` 功能时,才需要安装 `@vuepress/shiki-twoslash`。 ::: ### 从 `node_modules` 中导入类型文件 **twoslash** 最大的特点就是对代码块进行类型编译,默认支持从项目的 `node_modules` 中导入类型文件。 例如,如果您需要使用 `express`的类型提示,你需要在项目中安装 `@types/express` 依赖: ::: npm-to ```sh npm i -D @types/express ``` ::: 然后,可以在 代码块中使用 `express` 的类型,如下所示: ````md ```ts twoslash import express from 'express' const app = express() ``` ```` ### 导入本地类型文件 对于导入本地类型文件,由于代码块中的代码在编译时,并不容易确定代码的真实路径,我们很难直观的在 代码块中通过 **相对路径** 导入类型文件。 #### 从 `tsconfig.json` 中读取路径映射 主题支持从项目根目录下的 `tsconfig.json`,读取 `compilerOptions.paths` 中的路径映射,来解决这个问题。 假设你的项目的 `tsconfig.json` 配置如下: ```json title="tsconfig.json" { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` 你可以直接在 代码块中使用 `@/` 开头的路径,导入 `src` 目录下的类型文件,如下所示: ````md ```ts twoslash import type { Foo } from '@/foo' const foo: Foo = 1 ``` ```` #### 从 `shiki.twoslash` 中读取路径映射 你可以在 `shiki.twoslash` 中配置 `compilerOptions`,来解决这个问题,如下所示: ```ts title=".vuepress/config.ts" import path from 'node:path' export default defineUserConfig({ theme: plumeTheme({ codeHighlighter: { twoslash: { compilerOptions: { // [!code hl:8] paths: { // 相对于工作目录 `process.cwd()` '@/*': ['./src/*'], // 使用绝对路径 '@@/*': [path.resolve(process.cwd(), './src/*')], } } } }, }), }) ``` 你可以直接在 代码块中使用 `@/` 开头的路径,导入 `src` 目录下的类型文件,如下所示: ````md ```ts twoslash import type { Foo } from '@/foo' const foo: Foo = 1 ``` ```` ::: important 使用 `plugins.shiki.twoslash.compilerOptions` 可以更灵活的配置 类型编译,你可以在这里修改 `baseUrl` 等配置选项。 [参考 CompilerOptions](https://www.typescriptlang.org/tsconfig/#compilerOptions) 通常您只需要配置 `paths` 选项,其它选项保持默认即可,除非您了解您在配置什么。 ::: ## 使用 ::: warning `twoslash` 仅支持 `typescript` 和 `vue` 的 代码块。 ::: 启用该功能后,你只需要在 原有的 markdown 代码块语法中,在代码语言声明后添加 `twoslash` 关键词即可: ````md{1} ```ts twoslash const a = 1 ``` ```` 主题仅会对有 `twoslash` 关键词的代码进行编译处理。 ## 语法参考 完整语法请参考 [ts-twoslasher](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher) 和 [shikijs-twoslash](https://twoslash.netlify.app/) `twoslash` 将 **双斜杠** 视为代码示例的预处理器。 因此,所有的标记都是在 `//` 之后添加的。 ### 符号标记 常用的 `twoslash` 标记: #### `^?` {#extract-type} 使用 `^?` 可以提取位于其上方代码行中特定标识符的类型信息。 **输入:** ````md ```ts twoslash const hi = 'Hello' const msg = `${hi}, world` // ^? ``` ```` **输出:** ```ts twoslash const hi = 'Hello' const msg = `${hi}, world` // ^? // ``` ::: important 符号 `^`必须正确指向需要突出显示类型的变量 ::: #### `^|` {#completions} 使用 `^|` ,可以提取特定位置的自动补全信息。 **输入:** ````md ```ts twoslash // @noErrors console.e // ^| ``` ```` **输出:** ```ts twoslash // @noErrors console.e // ^| // ``` ::: important 符号`^`必须正确指向需要进行内容预测的位置 ::: Twoslash 会向 TypeScript 请求获取在 `^` 位置的自动补全建议,然后根据 `.` 后面的字母过滤可能的输出。 最多会显示 5 个内联结果,如果某个补全项被标记为已弃用,输出中会予以体现。 因此,在这种情况下,Twoslash 向 TypeScript 请求 `console` 的补全建议,然后筛选出以 `e` 开头的补全项。 注意,设置 `// @noErrors` 编译器标志,因为 `console.e` 是一个失败的 TypeScript 代码示例,但我们并不关心这一点。 #### `^^^` {#highlighting} 使用 `^^^` 来突出显示其上方某行的特定范围。 **输入:** ````md ```ts twoslash function add(a: number, b: number) { // ^^^ return a + b } ``` ```` **输出:** ```ts twoslash function add(a: number, b: number) { // ^^^ return a + b } ``` ::: important 使用连续多个符号`^`正确指向需要突出显示的范围 ::: ### `@filename` {#import-files} `@filename: ` 用于声明后续的代码将来自哪个文件, 你可以在其他部分的代码中通过 `import` 导入该文件。 **输入:** ````md ```ts twoslash // @filename: sum.ts export function sum(a: number, b: number): number { return a + b } // @filename: ok.ts import { sum } from './sum' sum(1, 2) // @filename: error.ts // @errors: 2345 import { sum } from './sum' sum(4, 'woops') ``` ```` **输出:** ```ts twoslash // @filename: sum.ts export function sum(a: number, b: number): number { return a + b } // @filename: ok.ts import { sum } from './sum' sum(1, 2) // @filename: error.ts // @errors: 2345 import { sum } from './sum' sum(4, 'woops') ``` ### 剪切代码 #### `---cut-before---` {#cut-before} 在 TypeScript 生成项目并提取所有编辑器信息(如标识符、查询、高亮等)后,剪切操作会修正所有偏移量和行号, 以适应较小的输出。 用户所见的内容为 `// ---cut-before---` 以下的部分。此外,还可使用简写形式 `// ---cut---` 。 **输入:** ````md ```ts twoslash const level: string = 'Danger' // ---cut--- console.log(level) ```` **输出:** ```ts twoslash const level: string = 'Danger' // ---cut--- console.log(level) ``` 仅显示单个文件: **输入:** ````md ```ts twoslash // @filename: a.ts export const helloWorld: string = 'Hi' // ---cut--- // @filename: b.ts import { helloWorld } from './a' console.log(helloWorld) ``` ```` **输出:** ```ts twoslash // @filename: a.ts export const helloWorld: string = 'Hi' // ---cut--- // @filename: b.ts import { helloWorld } from './a' console.log(helloWorld) ``` 只显示最后两行,但对 TypeScript 来说,这是一个包含两个文件的程序,并且所有 IDE 信息在文件间都正确连接。 这就是为什么 `// @filename: [file]` 是唯一不会被移除的 Twoslash 命令,因为如果不相关,它可以被 `---cut---` 掉。 #### `---cut-after---` {#cut-after} `---cut-before---` 的兄弟,用于修剪符号后的所有内容: **输入:** ````md ```ts twoslash const level: string = 'Danger' // ---cut-before--- console.log(level) // ---cut-after--- console.log('This is not shown') ``` ```` **输出:** ```ts twoslash const level: string = 'Danger' // ---cut-before--- console.log(level) // ---cut-after--- console.log('This is not shown') ``` #### `---cut-start---` 和 `---cut-end---` {#cut-start-end} 你也可以使用 `---cut-start---` 和 `---cut-end---` 对来剪切两个符号之间的代码段。 **输入:** ````md ```ts twoslash const level: string = 'Danger' // ---cut-start--- console.log(level) // 这里是被剪切的 // ---cut-end--- console.log('This is shown') ``` ```` **输出:** ```ts twoslash const level: string = 'Danger' // ---cut-start--- console.log(level) // 这里是被剪切的 // ---cut-end--- console.log('This is shown') ``` 支持多个实例以剪切多个部分,但符号必须成对出现。 ### 自定义输出信息 {id=twoslash-custom-message} `@log`, `@error`, `@warn` 和 `@annotate` 用于向用户输出不同级别的自定义信息 ````md ```ts twoslash // @log: Custom log message const a = 1 // @error: Custom error message const b = 1 // @warn: Custom warning message const c = 1 // @annotate: Custom annotation message ``` ```` ```ts twoslash // @log: Custom log message const a = 1 // @error: Custom error message const b = 1 // @warn: Custom warning message const c = 1 // @annotate: Custom annotation message ``` ### 输出已编译文件 运行 Twoslash 代码示例会触发完整的 TypeScript 编译运行,该运行会在虚拟文件系统中创建文件。 你可以将代码示例的内容替换为对项目运行TypeScript后的结果。 #### `@showEmit` `// @showEmit` 是 告诉 Twoslash 你希望将代码示例的输出替换为等效的 ·.js· 文件的主要命令。 **输入:** ````md ```ts twoslash // @showEmit const level: string = 'Danger' ``` ```` **输出:** ```ts twoslash // @showEmit const level: string = 'Danger' ``` 结果将显示此 `.ts` 文件所对应的 `.js` 文件。 可以看到 TypeScript 输出的内容中移除了 `: string` ,并添加了 `export {}`。 #### `@showEmittedFile: [file]` 虽然 `.js` 文件可能是开箱即用最有用的文件,但 TypeScript 确实会在启用正确标志时发出其他文件(`.d.ts`和 `.map`), 并且在有多文件代码示例时,你可能需要告诉 Twoslash 显示哪个文件。 对于所有这些情况,你也可以添加 `@showEmittedFile: [file]` 来告诉 Twoslash 你想显示哪个文件。 **显示TypeScript代码示例的 `.d.ts` 文件:** **输入:** ````md ```ts twoslash // @declaration // @showEmit // @showEmittedFile: index.d.ts export const hello = 'world' ``` ```` **输出:** ```ts twoslash // @declaration // @showEmit // @showEmittedFile: index.d.ts export const hello = 'world' ``` **显示 JavaScript 到 TypeScript 的 `.map` 文件:** **输入:** ````md ```ts twoslash // @sourceMap // @showEmit // @showEmittedFile: index.js.map export const hello = 'world' ``` ```` **输出:** ```ts twoslash // @sourceMap // @showEmit // @showEmittedFile: index.js.map export const hello = 'world' ``` **显示 `.d.ts` 文件的 `.map`(主要用于项目引用):** **输入:** ````md ```ts twoslash // @declaration // @declarationMap // @showEmit // @showEmittedFile: index.d.ts.map export const hello: string = 'world' ``` ```` **输出:** ```ts twoslash // @declaration // @declarationMap // @showEmit // @showEmittedFile: index.d.ts.map export const hello: string = 'world' ``` **为 `b.ts` 生成 `.js` 文件:** **输入:** ````md ```ts twoslash // @showEmit // @showEmittedFile: b.js // @filename: a.ts export const helloWorld: string = 'Hi' // @filename: b.ts import { helloWorld } from './a' console.log(helloWorld) ``` ```` **输出:** ```ts twoslash // @showEmit // @showEmittedFile: b.js // @filename: a.ts export const helloWorld: string = 'Hi' // @filename: b.ts import { helloWorld } from './a' console.log(helloWorld) ``` ### `@errors` `@errors: ` 显示代码是如何出现错误的: **输入:** ````md ```ts twoslash // @errors: 2322 2588 const str: string = 1 str = 'Hello' ```` **输出:** ```ts twoslash // @errors: 2322 2588 const str: string = 1 str = 'Hello' ``` 你需要在 `@errors` 后面,声明对应的 `typescript` 错误码。使用空格分隔多个错误代码。 ::: note 如果你不知道应该添加哪个 错误码,你可以先尝试直接编写好代码,然后等待编译失败, 你应该能够在控制台中查看到相关的错误信息,然后在错误信息的 `description` 中找到对应的错误码。 然后再将错误码添加到 `@errors` 中。 不用担心变异失败会终止进程,主题会在编译失败时显示错误信息,同时在代码块中输出未编译的代码。 ::: ### `@noErrors` 在代码中屏蔽所有错误。你还可以提供错误代码来屏蔽特定错误。 **输入:** ````md ```ts twoslash // @noErrors const str: string = 1 str = 'Hello' ``` ```` **输出:** ```ts twoslash // @noErrors const str: string = 1 str = 'Hello' ``` ### `@noErrorsCutted` 忽略在剪切代码中发生的错误。 **输入:** ````md ```ts twoslash // @noErrorsCutted const hello = 'world' // ---cut-after--- hello = 'hi' // 本应为错误,但因被截断而忽略。 ``` ```` **输出:** ```ts twoslash // @noErrorsCutted const hello = 'world' // ---cut-after--- hello = 'hi' // 本应为错误,但因被截断而忽略。 ``` ### `@noErrorValidation` 禁用错误验证,错误信息仍将呈现,但 Twoslash 不会抛出编译时代码中的错误。 **输入:** ````md ```ts twoslash // @noErrorValidation const str: string = 1 ``` ```` **输出:** ```ts twoslash // @noErrorValidation const str: string = 1 ``` ### `@keepNotations` 告知Twoslash不要移除任何注释,并保持原始代码不变。节点将包含原始代码的位置信息。 **输入:** ````md ```ts twoslash // @keepNotations // @module: esnext // @errors: 2322 const str: string = 1 ``` ```` **输出:** ```ts twoslash // @keepNotations // @module: esnext // @errors: 2322 const str: string = 1 ``` ### 覆盖编译器选项 使用 `// @name` 和 `// @name: value` 注释来覆盖 TypeScript 的[编译器选项](https://www.typescriptlang.org/tsconfig#compilerOptions)。 这些注释将从输出中移除。 **输入:** ````md ```ts twoslash // @noImplicitAny: false // @target: esnext // @lib: esnext // 这本应抛出一个错误, // 但由于我们禁用了noImplicitAny,所以不会抛出错误。 const fn = a => a + 1 ``` ```` **输出:** ```ts twoslash // @noImplicitAny: false // @target: esnext // @lib: esnext // 这本应抛出一个错误, // 但由于我们禁用了noImplicitAny,所以不会抛出错误。 const fn = a => a + 1 ``` --- --- url: /guide/optimize-build/index.md --- # 构建优化 ## 图片尺寸优化 在 Markdown 文档中通过 `![alt](url)` 或 `` 嵌入图片时,虽然能够正常显示内容,但潜在的布局稳定性问题往往被忽视。 ### 布局抖动问题分析 当图片体积较小或网络状况良好时,页面布局抖动并不明显。然而,面对大体积图片或较差的网络环境,图片加载过程中的布局重排问题就会凸显: 1. **加载前**:图片占位空间未被预留,后续内容向上挤压 2. **加载后**:图片突然占据空间,迫使后续内容重新排列 3. **用户体验**:频繁的布局变化导致视觉跳动和操作卡顿 ### 解决方案:预计算图片尺寸 根据 [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img#height)的建议,同时指定 `height` 和 `width` 属性能够让浏览器提前计算图片宽高比,预留显示空间,从根本上消除布局偏移。 主题提供的自动化解决方案: ```ts export default defineUserConfig({ theme: plumeTheme({ plugins: { markdownPower: { imageSize: true, // 可选 'local' | 'all' }, } }) }) ``` **配置选项说明**: * `'local'` 或 `true`:仅为本地图片添加尺寸属性 * `'all'`:同时处理本地和远程图片资源 **实现机制**: * 构建时自动分析图片原始尺寸 * 为 `` 标签注入精确的 `width` 和 `height` 属性 * 基于图片宽高比预留显示空间 ::: important 性能注意事项 * 此功能仅在**生产环境构建**时生效,避免开发阶段性能损耗 * 使用 `'all'` 选项时会请求所有远程图片资源,可能显著增加构建时间 * 优化策略:并发请求 + 头部信息分析,在获取尺寸数据后立即终止连接 ::: ## 图标加载优化 ### Iconify 集成优势 主题深度集成 [Iconify](https://icon-sets.iconify.design/) 项目,提供超过 20 万枚图标的选择灵活性。虽然本地安装 `@iconify/json` 包需要约 70MB 存储空间,但实际构建时仅包含使用到的图标资源,实现按需加载。 ### 性能瓶颈与解决方案 **问题根源**: 图标按集合(collection)组织,每个集合包含 100-1000+ 个图标的 JSON 文件。当使用多个不同集合的图标时,频繁的 I/O 读取和 JSON 解析会产生显著性能开销。 **实际案例**: * 使用 54 个图标集合中的 160+ 个图标 * 初始构建:约 500ms 图标解析时间 * 用户体验:开发服务器启动缓慢 **缓存优化机制**: ```mermaid graph LR A[首次构建] --> B[解析使用图标] B --> C[生成缓存文件] C --> D[二次构建] D --> E[读取缓存] E --> F[20ms 完成加载] ``` **优化效果**: * 构建时间从 500ms 降至 20ms * 开发服务器启动速度显著提升 * 资源利用率最大化 ### 最佳实践建议 1. **图标使用规划**: * 优先选择同一集合内的图标 * 避免过度分散使用不同集合 2. **开发体验优化**: * 首次启动后缓存自动生效 * 新增图标时缓存智能更新 * 无需手动干预缓存管理 3. **生产构建保障**: * 缓存机制不影响最终输出 * 保持图标资源的按需加载特性 * 确保构建产物的最优体积 通过这两项优化措施,主题在保持功能丰富性的同时,确保了优秀的构建性能和运行时体验。 --- --- url: /guide/project-structure/index.md --- 本指南详细说明使用 VuePress 和 Plume 主题创建的项目文件结构,帮助您更好地组织和管理项目文件。 通过[命令行工具创建](./usage.md#命令行安装)的项目,其典型文件结构如下: ::: file-tree * .git/ * **docs** # 文档源目录 * .vuepress # VuePress 配置目录 * public/ # 静态资源 * client.ts # 客户端配置(可选) * collections.ts # Collections 配置(可选) * config.ts # VuePress 主配置 * navbar.ts # 导航栏配置(可选) * plume.config.ts # 主题配置文件(可选) * demo # `doc` 类型 collection * foo.md * bar.md * blog # `post` 类型 collection * preview # 博客分类 * markdown.md # 分类文章 * article.md # 博客文章 * README.md # 站点首页 * … * package.json * pnpm-lock.yaml * .gitignore * README.md ::: ::: tip 手动创建的项目也可参考此结构进行组织 ::: ## 文档源目录 **文档源目录**包含站点的所有 Markdown 源文件。在使用命令行工具启动 VuePress 时需指定此目录: ```sh # [!code word:docs] vuepress dev docs # ↑ 文档源目录 ``` 对应的 package.json 脚本配置: ```json title="package.json" { "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } } ``` VuePress 仅处理文档源目录内的文件,其他目录将被忽略。 ## `.vuepress` 配置目录 `.vuepress/` 是 VuePress 的核心配置目录,您可在此配置项目、创建自定义组件和样式。 ### `client.ts` - 客户端配置 用于扩展 VuePress 客户端功能,如注册全局组件: ```ts title=".vuepress/client.ts" import { defineClientConfig } from 'vuepress/client' export default defineClientConfig({ enhance({ app, router, siteData }) { // app: Vue 应用实例 // router: Vue Router 实例 // siteData: 站点数据 // 注册全局组件 app.component('MyComponent', MyComponent) }, setup() { // Vue 根组件的 setup 方法 } }) ``` ### `config.ts` - 主配置文件 VuePress 的核心配置文件,设置主题、插件和构建工具: ```ts title=".vuepress/config.ts" twoslash import { viteBundler } from '@vuepress/bundler-vite' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ lang: 'zh-CN', theme: plumeTheme({ // 主题配置... }), bundler: viteBundler(), }) ``` ### `plume.config.ts` - 主题配置 专为主题提供的配置文件,支持热更新,修改后无需重启服务: ::: code-tabs @tab .vuepress/plume.config.ts ```ts twoslash // @filename: ./navbar.ts export default [] // @filename: ./collections.ts export default [] // ---cut--- import { defineThemeConfig } from 'vuepress-theme-plume' import collections from './collections' import navbar from './navbar' export default defineThemeConfig({ logo: '/logo.svg', profile: { name: 'Theme Plume', }, navbar, collections, // 更多配置... }) ``` @tab .vuepress/navbar.ts ```ts twoslash import { defineNavbarConfig } from 'vuepress-theme-plume' export default defineNavbarConfig([ // 导航项配置... ]) ``` @tab .vuepress/collections.ts ```ts twoslash import { defineCollections } from 'vuepress-theme-plume' export default defineCollections([ { type: 'post', dir: 'blog', title: '博客', link: '/blog/' }, { type: 'doc', dir: 'demo', linkPrefix: '/demo/', title: '文档示例', sidebar: 'auto' }, ]) ``` ::: --- --- url: /guide/repl/frontend-deprecated/index.md --- ::: caution 弃用说明 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 在 未来的版本会将 `demo` 相关的 功能迁移至 [vuepress/ecosystem](https://github.com/vuepress/ecosystem), 详细进度请查看 [ecosystem#293](https://github.com/vuepress/ecosystem/pull/293) 。 但在基于用户反馈后发现,此功能在实际场景中使用表现不符合预期。存在以下问题: * `vue-demo` 仅能用于简单的组件演示,不能支持如 组件库、`composables-api` 等外部依赖的演示。 * 演示代码仅能内联在 markdown 文件中,对于代码量较大的演示的编写体验不佳。 * 在浏览器运行时通过异步加载 `babel` 转换源代码,一方面需要额外的等待时间,另一方面对于企业内网环境可能不支持。 主题重新对 前端代码演示 功能进行了重新设计和重构,请查看新的 [前端代码演示](./frontend.md) 。 ::: ## 概述 前端代码演示 由 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 提供支持。 前端 代码演示 默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { oldDemo: true, }, }) }) ``` ## 语法 ````md ::: [类型]-demo 可选的标题文字 ```html ``` ```json // json block 作为插件配置存放处 { // 放置你的配置 (可选的) } ``` ::: ```` ::: tip 提示 JSON 块是可选的,可用的配置详见[配置](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/config.html) ::: 插件支持三种类型 * normal(默认) * vue * react ## 可用的语言 你可以在演示块中使用不同语言。 当你设置一些不能在浏览器上直接运行的语言时,由于插件无法解析它们,因此网页演示将被禁用。插件只显示代码。同时提供一个 "在 CodePen 中打开" 按钮允许用户直接在 CodePen 打开并浏览代码。 可用的 HTML 语言: * `"html"` (默认) * `"slim"` * `"haml"` * `"markdown"` 可用的 JS 语言: * `"javascript"` (default) * `"coffeescript"` * `"babel"` * `"livescript"` * `"typescript"` > 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls。` 可用的 CSS 语言: * `"css"` (default) * `"less"` * `"scss"` * `"sass"` * `"stylus"` ## 不支持的语言 ::: normal-demo 一个使用浏览器不支持解析语言 Demo ```md # 标题 十分强大 ``` ```ts const message: string = 'VuePress Theme Hope' document.querySelector('h1').innerHTML = message ``` ```scss h1 { font-style: italic; + p { color: red; } } ``` ::: :::: details 代码 ````md ::: normal-demo 一个使用浏览器不支持解析语言 Demo ```md # 标题 十分强大 ``` ```ts const message: string = 'VuePress Theme Hope' document.querySelector('h1').innerHTML = message ``` ```scss h1 { font-style: italic; + p { color: red; } } ``` ::: ```` :::: ## 普通代码演示 格式: ````md ::: normal-demo 可选的标题文字 ```html ``` ```js // js code ``` ```css /* css code */ ``` ```json // 配置 (可选) { "jsLib": [ // ... ], "cssLib": [ // ... ] } ``` ::: ```` ::: warning 注意事项 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document,请访问` `window.document`。 ::: ## 例子 ::: normal-demo Demo 演示 ```html

Hello Word!

非常强大!

``` ```js document.querySelector('#very').addEventListener('click', () => { alert('非常强大') }) ``` ```css span { color: red; } ``` ::: :::: details 代码 ````md ::: normal-demo Demo 演示 ```html

Hello Word!

非常强大!

``` ```js document.querySelector('#very').addEventListener('click', () => { alert('非常强大') }) ``` ```css span { color: red; } ``` ::: ```` :::: ### Vue 代码演示 #### 格式 ````md ::: vue-demo 可选的标题文字 ```vue ``` ```json // 配置 (可选) {} ``` ::: ```` ::: warning 注意事项 * 你只能使用 `Vue3`。 * 必须将组件通过 `export default` 默认导出 * 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。 ::: #### 演示 ::: vue-demo 一个 Vue Composition 演示 ```vue ``` ::: :::: details 代码 ````md ::: vue-demo 一个 Vue Composition 演示 ```vue ``` ::: ```` :::: ### React 代码演示 #### 格式 ````md ::: react-demo 可选的标题文字 ```js // 放置脚本,并通过 `export default` 导出你的 react 组件 ``` ```css /* 你的 css 内容 */ ``` ```json // 配置 (可选) {} ``` ::: ```` ::: warning 注意事项 * 使用 React 的时候,为了解析 JSX 必须引入 Babel,此过程由插件自动完成。 * 必须将组件通过 `export default` 默认导出 * 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。 ::: #### 演示 ::: react-demo 一个函数式 React Demo ```js const { useState } = React export default () => { const [message, setMessage] = useState(' 强大') const handler = () => { setMessage(`十分${message}`) } return (
Hello Word ! {message}
) } ``` ```css .box #powerful { color: blue; } ``` ::: :::: details 代码 ````md ::: react-demo 一个函数式 React Demo ```js const { useState } = React export default () => { const [message, setMessage] = useState(' 强大') const handler = () => { setMessage(`十分${message}`) } return (
Hello Word ! {message}
) } ``` ```css .box #powerful { color: blue; } ``` ::: ```` :::: --- --- url: /guide/repl/frontend/index.md --- ::: important 旧的前端代码演示 已弃用,请迁移至此新的方案。 旧的方案由 [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/zh/) 提供,感谢在过去 提供的代码演示的支持,在 `vuepress-plugin-md-enhance` 中代码演示功能也将迁移至 [vuepress/ecosystem](https://github.com/vuepress/ecosystem), 详情请查看 [vuepress/ecosystem#293](https://github.com/vuepress/ecosystem/pull/293) 。 ::: ::: details 为什么要重新设计? 前端代码演示是一个很有用的功能,但是在旧的方案中,所实现的功能与实际使用场景预期不符。 旧的方案中,比如 `vue-demo` 仅能支持一些简单的 vue 组件演示,且不能直接导入项目中的依赖,仅能通过 加载外部脚本支持更多功能,且并没提供对 `vue sfc` 的完全支持,仅能进行简单的代码演示。 而且对脚本代码的编译是在浏览器运行时,先从 CDN 请求加载 `babel`,完成后再通过 `babel` 进行转换, 这需要额外的等待时间完成,同时对于企业内部的项目,在内网环境中无法请求外部资源,导致演示无法正常展示。 在新的方案中,所有的演示代码均是在 nodejs 运行时进行编译转换,因此在浏览器运行时可直接展示演示代码,无需额外的等待时间。 且得益于 nodejs 强大的能力,可以完全支持 `vue sfc` 的完整功能,且可以直接导入项目中的依赖,让你的演示更加丰富。 更符合实际的使用场景。 ::: ## 概述 此功能支持在 页面中 嵌入 代码演示 功能。前端代码演示由两个主要区域组成: \==渲染区== 和 ==代码区== 。 其中,**渲染区** 用于展示代码的执行结果,包括 UI 渲染和 交互;**代码区** 用于展示源代码,默认是折叠的。 主题提供了 三种不同的 前端代码演示支持: * \==vue 组件演示==: 支持 `vue` 组件的演示,像编写一个 `vue` 组件一样编写你的演示代码,可以用于演示如 组件库、`composables-api` 等外部依赖。 * \==markdown 演示==:支持 `markdown` 的演示。 * \==普通代码演示== :支持原生的 `HTML` + `JS/TS` + `CSS/Less/Sass/Stylus` 的代码演示,像编写一个网页一样编写你的演示代码。 主题还提供了 两种不同的使用方式编写演示代码: * 嵌入演示代码文件: ```md @[demo type](url) ``` 可以通过简单的嵌入语法,从文件中导入演示代码。 * demo 容器内联演示代码: ````md ::: demo type ``` [lang] code ``` ::: ```` 直接在 markdown 文件中编写演示代码,使用 `demo` 容器包裹即可。 ## 配置 前端代码演示 由 [vuepress-plugin-md-power](../../config/plugins/markdown-power.md) 提供支持。 前端 代码演示 默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { demo: true, // [!code ++] }, }) }) ``` ## 语言支持 代码演示支持以下 语言: * javascript * typescript * html * css * less * sass * stylus 对于 css 预处理语言,你需要在项目中安装对应的预处理器,如 `less` 、 `sass` 、 `stylus` 等。 ## 嵌入语法 不同的代码演示均使用相同的嵌入语法,你可以快速掌握它们的使用方法。 ```md @[demo](url) @[demo [type]](url) @[demo [type] title="" desc="" expanded code-setting=""](url) ``` `@[demo](url)` 是一个固定的语法格式。 `[type]` 表示类型,支持 三个不同的值: * `normal`: 普通代码演示类型。当不传入 `[type]` 参数时,默认为 `normal` 类型。 * `vue`: vue 组件演示类型。 * `markdown`: markdown 演示类型。 `url` 表示演示代码文件的路径,可以是相对路径或绝对路径, * 相对路径,以 `./` 或 `../` 开头,表示相对于当前的 markdown 文件路径。 * 绝对路径,以 `/` 开头,表示从 [vuepress 源目录路径](../quick-start/project-structure.md#文档源目录) 开始。 ```md @[demo](./demo/normal.html) @[demo normal](./demo/normal.html) @[demo](/.vuepress/demo/normal.html) @[demo vue](./demo/Counter.vue) @[demo vue](./demo/Counter.ts) @[demo](/.vuepress/demo/Counter.vue) @[demo markdown](./demo/example.md) @[demo markdown](/.vuepress/demo/example.md) ``` 其它额外参数: * `title="xxx"` :演示标题 * `desc="xxx"`:演示描述 * `expanded`:展开代码区域 * `code-setting="xxx"`:代码设置,值将被拼接在 ` ``` [lang]` 之后,用于给代码块添加配置。 `code-setting=":lines-number"`,则会在代码块后面添加 `:lines-number`,使代码块支持显示行号。 `code-setting=":collapsed-lines=10"`,则会在代码块后面添加 `:collapsed-lines=10`,使代码块从第 10 行开始折叠。 ```md @[demo vue expanded title="标题" desc="描述" code-setting=":collapsed-lines=10"](./demo/Counter.vue) ``` ## demo 容器内联演示 demo 容器内联演示 使用 `demo` 容器包裹演示代码,可以在 markdown 文件中快速地编写演示代码,如下: ```md ::: demo [type] title="" desc="" expanded ::: ``` 所有参数与 `@[demo](url)` 语法相同。 ````md ::: demo ```html ``` ``` js // js 代码 ``` ``` css /* css 代码 */ ``` ::: ::: demo vue ``` vue ``` ::: ::: demo markdown ``` md ``` ::: ```` 还可以在 `::: demo` 容器中 使用 `::: code-tabs` 容器包裹代码块,以获得更好的交互效果。 ````md :::: demo ::: code-tabs @tab HTML ```html ``` @tab javascript ``` js // js 代码 ``` @tab css ``` css /* css 代码 */ ``` :::: ```` 当期望使用 Typescript 或 `Less/Sass/Stylus` 时,通过修改 ` ``` [lang]` 的值即可: ````md :::: demo ::: code-tabs @tab HTML ```html ``` @tab Typescript ``` ts // ts 代码 ``` @tab Scss ``` scss /* scss 代码 */ ``` :::: ```` ## vue 组件演示 vue 组件演示 是一个很强大的功能,对于演示代码不做任何限制,这甚至完全取决于 `bundler` 对于 vue 的支持。 你还可以直接在演示代码中导入项目中安装的依赖,就像你在写一个 vue 项目的组件一样。 因此,你可以直接使用它来为 你的组件库 提供演示示例,或者为你的 `composables-api` 提供演示示例。 ### 嵌入语法 你可以直接使用以下方式在页面中嵌入一个 vue 组件演示: **输入:** ```md @[demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1"](./demo/Counter.vue) ``` ::: details 查看 `./demo/Counter.vue` 代码 @[code](./demo/Counter.vue) ::: **输出:** @[demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1"](./demo/Counter.vue) *** 也可以嵌入一个 `.ts` 编写的 vue 组件: **输入:** ```md @[demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1"](./demo/Counter.ts) ``` ::: details 查看 `./demo/Counter.ts` 代码 ::: code-tabs @tab Counter.ts @[code](./demo/Counter.ts) @tab Counter.module.css @[code](./demo/Counter.module.css) ::: **输出:** @[demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1"](./demo/Counter.ts) :::info 对于 `.js/.ts` 编写的组件,请使用 `css module` 来编写样式以实现样式隔离 ::: *** 可以在演示代码中导入外部依赖, 以导入 `@vueuse/core` 中的 `useToggle()` 为例: **输入:** ```md @[demo vue title="useToggle" desc="useToggle() 演示"](./demo/Toggle.vue) ``` ::: details ./demo/Toggle.vue @[code](./demo/Toggle.vue) ::: **输出:** @[demo vue title="useToggle" desc="useToggle() 演示"](./demo/Toggle.vue) ### 容器语法 在 markdown 文件中使用 `demo` 容器包裹演示代码,可以快速地编写演示代码,如下: **输入:** :::: details 展开查看完整代码 ````md ::: demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1" ```vue ``` ::: ```` :::: **输出:** ::: demo vue title="计数器" desc="点击 +1 按钮,计数器自增 1" ```vue ``` ::: :::::: warning vue demo 容器语法虽然也支持 使用 `.js/ts + css` 的方式来嵌入演示代码, 但主题不推荐这样做。因为 样式无法被隔离,这可能导致样式污染。 ::::: details 参考示例 ````md :::: demo vue title="标题" desc="描述" ::: code-tabs @tab Counter.ts ```ts import { defineComponent, ref } from 'vue' export default defineComponent({ // code }) ``` @tab Counter.css ```css /* css code */ ``` ::: :::: ```` ::::: :::::: ## 普通代码演示 普通代码演示支持 `html` 、 `css/less/sass/stylus` 、 `js/ts` 语言。 适合于相对简单的代码演示,比如 一个样式渲染效果,一个交互效果,一个功能 等。 普通代码演示还支持跳转到 `codePen` 和 `jsFiddle` 中查看。 同时,也支持通过 外部链接 的方式引入 第三方的库,比如 `jQuery` , `dayjs` 等。 ::: warning 不建议过于复杂的演示。 ::: ### 嵌入语法 使用嵌入语法时,对于导入的 代码演示文件,使用 `.html` 作为文件后缀。在 `.html` 文件中, 你可以像编写一个 HTML 页面一样编写 演示代码: ```html
演示内容
``` 每一个区域的内容都是可选的。但请注意,不支持存在多个相同的区域。区域的顺序无要求。 除了 `` 内使用 `json` 格式声明要加载的其他依赖资源。 比如,加载 `jQuery`, 以及 `normalize.css`: ```html
xxxx
``` *** 一个常规的示例: **输入:** ```md @[demo title="示例" desc="这是一个常规演示"](./demo/normal.html) ``` ::: details 查看 `./demo/normal.html`代码 @[code](./demo/normal.html) ::: **输出:** @[demo title="示例" desc="这是一个常规演示"](./demo/normal.html) *** 引入 `jQuery` , `dayjs` 和 `normalize.css` 的示例: **输入:** ```md @[demo title="示例" desc="这是一个常规演示"](./demo/normal-lib.html) ``` ::: details 查看 `./demo/normal-lib.html`代码 @[code](./demo/normal-lib.html) ::: **输出:** @[demo title="示例" desc="这是一个常规演示"](./demo/normal-lib.html) ### 容器语法 在 markdown 文件中使用 demo 容器包裹演示代码,可以快速地编写演示代码,如下: :::: details 展开查看完整示例代码 `````md ::: demo title="示例" desc="描述" expanded ```json { "jsLib": [], "cssLib": [] } ``` ```html ``` ```js // js 代码 ``` ```css /* css 代码 */ ``` ::: ``` :::: 还可以在 `::: demo` 中包裹 `::: code-tabs` 以获得更好的代码块展示效果: ::::: details 展开查看完整示例代码 ````md :::: demo title="示例" desc="描述" expanded ```json { "jsLib": [], "cssLib": [] } ``` ::: code-tabs @tab HTML ```html ``` @tab Javascript ```js // js 代码 ``` @tab CSS ```css /* css 代码 */ ``` ::: :::: ``` ::::: --- 一个常规的 容器示例: **输入:** ::::: details 展开查看完整示例代码 ````md :::: demo title="常规示例" desc="一个常规示例" ::: code-tabs @tab HTML ```html

vuepress-theme-plume

``` @tab Javascript ```js const a = 'So Awesome!' const app = document.querySelector('#app') app.appendChild(document.createElement('small')).textContent = a ``` @tab CSS ```css #app { font-size: 2em; text-align: center; } ``` ::: :::: ````` ::::: **输出:** :::: demo title="常规示例" desc="一个常规示例" ::: code-tabs @tab HTML ```html

vuepress-theme-plume

``` @tab Javascript ```js const a = 'So Awesome!' const app = document.querySelector('#app') app.appendChild(document.createElement('small')).textContent = a ``` @tab CSS ```css #app { font-size: 2em; text-align: center; } ``` ::: :::: *** 引入 jQuery , dayjs 和 normalize.css 的示例: **输入:** ::::: details 展开查看完整示例代码 ````md :::: demo title="常规示例" desc="一个常规示例" ```json { "jsLib": [ "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js", "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js" ], "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"] } ``` ::: code-tabs @tab HTML ```html

vuepress-theme-plume

``` @tab Javascript ```js $('#message').text('So Awesome!') const datetime = $('#datetime') setInterval(() => { datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss')) }, 1000) ``` @tab CSS ```css #app { font-size: 2em; text-align: center; } ``` ::: :::: ```` ::::: **输出:** :::: demo title="常规示例" desc="一个常规示例" ```json { "jsLib": [ "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js", "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js" ], "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"] } ``` ::: code-tabs @tab HTML ```html

vuepress-theme-plume

``` @tab Javascript ```js $('#message').text('So Awesome!') const datetime = $('#datetime') setInterval(() => { datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss')) }, 1000) ``` @tab CSS ```css #app { font-size: 2em; text-align: center; } ``` ::: :::: ## Markdown 演示 在页面中演示 markdown 源代码 和渲染结果。 ### 嵌入语法 **输入:** ```md @[demo markdown title="公告板" desc="公告板代码示例"](/.vuepress/bulletin.md) ``` ::: details 展开查看 `/.vuepress/bulletin.md` 代码 @[code](../../.vuepress/bulletin.md) ::: **输出:** @[demo markdown title="公告板" desc="公告板代码示例"](/.vuepress/bulletin.md) ### 容器语法 **输入:** :::::: details 展开查看完整代码 ````md :::: demo markdown title="公告板" desc="公告板代码示例" ```md ::: center **QQ 交流群:** [792882761](https://qm.qq.com/q/FbPPoOIscE) ![QQ qr_code](/images/qq_qrcode.png){width="618" height="616" style="width: 200px"} 您在使用过程中遇到任何问题,欢迎通过 [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose) 反馈。也欢迎加入我们的 QQ 交流群一起讨论。 ::: ``` :::: ```` :::::: **输出:** :::: demo markdown title="公告板" desc="公告板代码示例" ```md ::: center **QQ 交流群:** [792882761](https://qm.qq.com/q/FbPPoOIscE) ![QQ qr_code](/images/qq_qrcode.png){width="618" height="616" style="width: 200px"} 您在使用过程中遇到任何问题,欢迎通过 [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose) 反馈。也欢迎加入我们的 QQ 交流群一起讨论。 ::: ``` :::: --- --- url: /guide/repl/golang/index.md --- # Golang ## 概述 主题提供了 Golang 代码演示,支持 在线运行 Go 代码。 ::: important 该功能通过将 代码提交到 服务器 进行 编译并执行。 因此,请不要使用此功能 执行 过于复杂的代码,也不要过于频繁的进行执行请求。 ::: ## 配置 该功能默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { repl: { go: true, }, }, }) }) ``` ## 使用 使用 `::: go-repl` 容器语法 将 Go 代码块包裹起来。主题会检查代码块并添加执行按钮。 ### 只读代码演示 golang 代码演示默认是只读的,不可编辑。 ````md ::: go-repl title="自定义标题" ```go // your go code ``` ::: ```` ### 可编辑代码演示 如果需要在线编辑并执行,需要将代码块包裹在 `::: go-repl editable` 容器语法中 ````md ::: go-repl editable title="自定义标题" ```go // your go code ``` ::: ```` ## 示例 ### 打印内容 **输入:** ````md :::go-repl ```go package main import ( "fmt" ) func main() { fmt.Println("Hello World") } ``` ::: ```` **输出:** :::go-repl ```go package main import ( "fmt" ) func main() { fmt.Println("Hello World") } ``` ::: ### 可编辑代码演示 **输入:** ````md :::go-repl editable ```go package main import ( "fmt" ) func main() { fmt.Println("Hello World") } ``` ::: ```` **输出:** :::go-repl editable ```go package main import ( "fmt" ) func main() { fmt.Println("Hello World") } ``` ::: ### 循环随机延迟打印 **输入:** ````md :::go-repl ```go package main import ( "fmt" "math/rand" "time" ) func main() { for i := 0; i < 10; i++ { dur := time.Duration(rand.Intn(1000)) * time.Millisecond fmt.Printf("Sleeping for %v\n", dur) // Sleep for a random duration between 0-1000ms time.Sleep(dur) } fmt.Println("Done!") } ``` ::: ```` **输出:** :::go-repl ```go package main import ( "fmt" "math/rand" "time" ) func main() { for i := 0; i < 10; i++ { dur := time.Duration(rand.Intn(1000)) * time.Millisecond fmt.Printf("Sleeping for %v\n", dur) // Sleep for a random duration between 0-1000ms time.Sleep(dur) } fmt.Println("Done!") } ``` ::: ### 网络请求 ::: go-repl ```go package main import ( "fmt" "io" "log" "net" "net/http" "os" ) func main() { http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, playground") }) log.Println("Starting server...") l, err := net.Listen("tcp", "localhost:8080") if err != nil { log.Fatal(err) } go func() { log.Fatal(http.Serve(l, nil)) }() log.Println("Sending request...") res, err := http.Get("http://localhost:8080/hello") if err != nil { log.Fatal(err) } log.Println("Reading response...") if _, err := io.Copy(os.Stdout, res.Body); err != nil { log.Fatal(err) } } ``` ::: ### 多文件 ::: go-repl ```go{10-12} package main import ( "play.ground/foo" ) func main() { foo.Bar() } -- go.mod -- module play.ground -- foo/foo.go -- package foo import "fmt" func Bar() { fmt.Println("This function lives in an another file!") } ``` ::: --- --- url: /guide/repl/kotlin/index.md --- # Kotlin ## 概述 主题提供了 Kotlin 代码演示,支持 在线运行 Kotlin 代码。 ::: important 该功能通过将 代码提交到 服务器 进行 编译并执行,且一次只能提交单个代码文件。 因此,请不要使用此功能 执行 过于复杂的代码,也不要过于频繁的进行执行请求。 ::: ## 配置 该功能默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { repl: { kotlin: true, }, }, }) }) ``` ## 使用 使用 `::: kotlin-repl` 容器语法 将 kotlin 代码块包裹起来。主题会检查代码块并添加执行按钮。 ### 只读代码演示 kotlin 代码演示默认是只读的,不可编辑。 ````md ::: kotlin-repl title="自定义标题" ```kotlin // your kotlin code ``` ::: ```` ### 可编辑代码演示 如果需要在线编辑并执行,需要将代码块包裹在 `::: kotlin-repl editable` 容器语法中 ````md ::: kotlin-repl editable title="自定义标题" ```kotlin // your kotlin code ``` ::: ```` ## 示例 ### 打印内容 **输入:** ````md ::: kotlin-repl ```kotlin class Contact(val id: Int, var email: String) fun main(args: Array) { val contact = Contact(1, "mary@gmail.com") println(contact.id) } ``` ::: ```` **输出:** ::: kotlin-repl ```kotlin class Contact(val id: Int, var email: String) fun main(args: Array) { val contact = Contact(1, "mary@gmail.com") println(contact.id) } ``` ::: ### 运算 ::: kotlin-repl ```kotlin fun mul(a: Int, b: Int): Int { return a * b } fun main(args: Array) { print(mul(-2, 4)) } ``` ::: ### 可编辑代码演示 **输入:** ````md ::: kotlin-repl editable ```kotlin class Contact(val id: Int, var email: String) fun main(args: Array) { val contact = Contact(1, "mary@gmail.com") println(contact.id) } ``` ::: ```` **输出:** ::: kotlin-repl editable ```kotlin class Contact(val id: Int, var email: String) fun main(args: Array) { val contact = Contact(1, "mary@gmail.com") println(contact.id) } ``` ::: --- --- url: /guide/repl/python/index.md --- # Python ## 概述 主题提供了 Python 代码演示,支持在线运行 Python 代码。 ## 安装 python 在线执行由 [pyodide](https://pyodide.org/en/latest/) 提供,使用前请确保有 `pyodide` 可用 ::: npm-to ```sh npm install pyodide ``` ::: ## 配置 该功能默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { repl: { python: true, }, }, }) }) ``` ## 使用 使用 `::: python-repl` 容器语法 将 python 代码块包裹起来。主题会检查代码块并添加执行按钮。 ::: warning python-repl 的支持是有限的,目前只支持: * 基本 Python 语法的执行(不依赖后端) * 可导入 Python 基本库 * 标准输出流(stdout)捕获输出 * 最后一条语句是一个表达式(且代码不以分号结尾),则会返回该表达式的值。 * 异常信息输出 ::: ### 只读代码演示 Python 代码演示默认是只读的,不可编辑。 ````md ::: python-repl title="自定义标题" ```python // your python code ``` ::: ```` ### 可编辑代码演示 如果需要在线编辑并执行,需要将代码块包裹在 `::: python-repl editable` 容器语法中。 ````md ::: python-repl editable title="自定义标题" ```python // your python code ``` ::: ```` ## 示例 ### 打印内容 **输入:** ````md ::: python-repl ```python def hello_world(): return 'Hello World!' hello_world() ``` ::: ```` **输出:** ::: python-repl ```python def hello_world(): print('Hello World!') hello_world() ``` ::: ### 运算 ::: python-repl ```python def mul(a: int, b: int) -> int: return a * b print(mul(-2, 4)) ``` ::: ### 可编辑代码演示 **输入:** ````md ::: python-repl editable ```python class Contact: def __init__(self, id: int, email: str): self.id = id self.email = email contact = Contact(1, 'mary@gmail.com') print(contact.id) ``` ::: ```` **输出:** ::: python-repl editable ```python class Contact: def __init__(self, id: int, email: str): self.id = id self.email = email contact = Contact(1, 'mary@gmail.com') print(contact.id) ``` ::: --- --- url: /guide/repl/rust/index.md --- # Rust ## 概述 主题提供了 Rust 代码演示,支持 在线运行 Rust 代码。 ::: important 该功能通过将 代码提交到 服务器 进行 编译并执行,且一次只能提交单个代码文件。 因此,请不要使用此功能 执行 过于复杂的代码,也不要过于频繁的进行执行请求。 ::: ## 配置 该功能默认不启用,你可以通过配置来启用它。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ markdown: { repl: { rust: true, }, }, }) }) ``` ## 使用 使用 `::: rust-repl` 容器语法 将 Rust 代码块包裹起来。主题会检查代码块并添加执行按钮。 ### 只读代码演示 rust 代码演示默认是只读的,不可编辑。 ````md ::: rust-repl title="自定义标题" ```rust // your rust code ``` ::: ```` ### 可编辑代码演示 如果需要在线编辑并执行,需要将代码块包裹在 `::: rust-repl editable` 容器语法中 ````md ::: rust-repl editable title="自定义标题" ```rust // your rust code ``` ::: ```` ## 示例 ### 打印内容 **输入:** ````md ::: rust-repl title="打印内容" ```rust fn main() { println!("Hello, world!"); } ``` ::: ```` **输出:** ::: rust-repl title="打印内容" ```rust fn main() { println!("Hello, world!"); } ``` ::: 点击 执行 按钮,即可执行代码。 ### 打印错误信息 **输入:** ````md ::: rust-repl ```rust fn main() { printlnl!("Hello, world!"); } ``` ::: ```` **输出:** ::: rust-repl ```rust fn main() { printlnl!("Hello, world!"); } ``` ::: ### 等待子进程执行 **输入:** ````md ::: rust-repl ```rust use std::process::Command; fn main() { let mut child = Command::new("sleep").arg("5").spawn().unwrap(); let _result = child.wait().unwrap(); println!("reached end of main"); } ``` ::: ```` **输出:** ::: rust-repl ```rust use std::process::Command; fn main() { let mut child = Command::new("sleep").arg("5").spawn().unwrap(); let _result = child.wait().unwrap(); println!("reached end of main"); } ``` ::: ### 可编辑的演示 **输入:** ````md ::: rust-repl editable ```rust fn main() { println!("Hello, world!"); } ``` ::: ```` **输出:** ::: rust-repl editable ```rust fn main() { println!("Hello, world!"); } ``` ::: --- --- url: /guide/seo/index.md --- # SEO ## 使用 主题提供了开箱即用的配置,为 站点 启用 SEO 优化功能。 要启用它,需要进行以下配置: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ hostname: 'http://your_site_url', }) }) ``` 如需要自定义 SEO 优化,可以通过 `plugins.seo` 配置来实现。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ plugins: { seo: { // ... seo 配置 } } }) }) ``` 完整配置请查看 [文档](https://ecosystem.vuejs.press/zh/plugins/seo/seo/config.html) ::: note 示例 Fork 自 [@vuepress/plugin-seo](https://ecosystem.vuejs.press/zh/plugins/seo/seo/), 遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。 ::: ## 指南 主题会通过向网站 `` 注入标签,让你的网站完全支持 [开放内容协议 OGP](https://ogp.me/) 和 [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/),以全面增强站点的搜索引擎优化性。 默认情况下,插件会读取站点配置、主题配置与页面的 frontmatter 来尽可能自动生成。 诸如站点名称,页面标题,页面类型,写作日期,最后更新日期,文章标签均会自动生成。 ## 默认的 OGP 生成逻辑 | 属性名称 | 值 | | :----------------------: | :------------------------------------------------------------------------------------------------: | | `og:url` | `options.hostname` + `path` | | `og:site_name` | `siteConfig.title` | | `og:title` | `page.title` | | `og:description` | `page.frontmatter.description` || 自动生成 (当插件选项中的 `autoDescription` 为 `true` 时) | | `og:type` | `"article"` | | `og:image` | `options.hostname` + `page.frontmatter.image` || 页面的第一张图片|| 插件选项的 `fallbackImage` | | `og:updated_time` | `page.git.updatedTime` | | `og:locale` | `page.lang` | | `og:locale:alternate` | `siteData.locales` 包含的其他语言 | | `twitter:card` | `"summary_large_image"` (仅在找到图片时) | | `twitter:image:alt` | `page.title` (仅在找到图片时) | | `article:author` | `page.frontmatter.author` || `options.author` | | `article:tag` | `page.frontmatter.tags` || `page.frontmatter.tag` | | `article:published_time` | `page.frontmatter.date` || `page.git.createdTime` | | `article:modified_time` | `page.git.updatedTime` | ## 默认的 JSON-LD 生成逻辑 | 属性名 | 值 | | :-------------: | :------------------------------------------------------------: | | `@context` | `"https://schema.org"` | | `@type` | `"NewsArticle"` | | `headline` | `page.title` | | `image` | 页面中的图片|| `options.hostname` + `page.frontmatter.image` | | `datePublished` | `page.frontmatter.date` || `page.git.createdTime` | | `dateModified` | `page.git.updatedTime` | | `author` | `page.frontmatter.author` || `options.author` | ## SEO 介绍 搜索引擎优化 (**S**earch **E**ngine **O**ptimization),是一种透过了解搜索引擎的运作规则来调整网站, 以及提高目的网站在有关搜索引擎内排名的方式。由于不少研究发现,搜索引擎的用户往往只会留意搜索结果最 前面的几个条目,所以不少网站都希望透过各种形式来影响搜索引擎的排序,让自己的网站可以有优秀的搜索排名。 所谓“针对搜索引擎作最优化的处理”,是指为了要让网站更容易被搜索引擎接受。搜索引擎会将网站彼此间的内容做 一些相关性的资料比对,然后再由浏览器将这些内容以最快速且接近最完整的方式,呈现给搜索者。 搜索引擎优化就是通过搜索引擎的规则进行优化,为用户打造更好的用户体验,最终的目的就是做好用户体验。 ## 相关文档 * [开放内容协议 OGP](https://ogp.me/) (**O**pen **G**raph **Pr**otocal) 本插件完美支持该协议,会自动生成符合该协议的 `` 标签。 * [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/) 本插件会为文章类页面生成 NewsArticle 类标签。 * [RDFa 1.1](https://www.w3.org/TR/rdfa-primer/) RDFa 主要标记 HTML 结构。 * [Schema.Org](https://schema.org/) 结构标记的 Schema 定义站点 --- --- url: /guide/sidebar/index.md --- # 侧边栏 ## 概述 侧边栏是文档常见的页面导航方式,可以快速定位到文档内容。 主题提供了两种方式配置侧边栏,包括: * 通过主题配置的 `sidebar` 选项配置侧边栏 * 在 [类型为 `doc` 的集合](./collection-doc.md) 中配置侧边栏 ## 文件结构与基础配置 ### 目录结构设计 典型的项目结构可能如下: ::: file-tree * docs * typescript # TypeScript 学习笔记 * basic.md * types.md * rust # Rust 编程笔记 * tuple.md * struct.md * README.md # 站点首页 ::: ### 通过`sidebar` 配置 这种方式适用于简单小巧的文档站点。 ::: code-tabs#config @tab .vuepress/config.ts ```ts twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ sidebar: { '/typescript/': [ 'basic', 'types' ], '/rust/': [ 'tuple', 'struct' ] } }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ sidebar: { '/typescript/': [ 'basic', 'types' ], '/rust/': [ 'tuple', 'struct' ] } }) ``` ::: ### 通过 `collection` 配置 `collections` (集合)可以灵活的组织和管理站点中的不同类别的文档,这种方式适用于复杂的站点。 ::: code-tabs#config @tab .vuepress/config.ts ```js twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ collections: [ { type: 'doc', dir: 'typescript', linkPrefix: '/typescript/', title: 'TypeScript 笔记', sidebar: ['basic', 'types'], }, { type: 'doc', dir: 'rust', linkPrefix: '/rust/', title: 'Rust 笔记', sidebar: ['tuple', 'struct'], } ], }) }) ``` @tab .vuepress/plume.config.ts ```ts twoslash import { defineThemeConfig } from 'vuepress-theme-plume' export default defineThemeConfig({ collections: [ { type: 'doc', dir: 'typescript', linkPrefix: '/typescript/', title: 'TypeScript 笔记', sidebar: ['basic', 'types'], }, { type: 'doc', dir: 'rust', linkPrefix: '/rust/', title: 'Rust 笔记', sidebar: ['tuple', 'struct'], } ], }) ``` ::: ::: tip 配置时机建议 在创建文档文件前完成笔记配置。主题的 [auto-frontmatter](../../config/theme.md#autofrontmatter) 功能会根据配置自动生成永久链接和侧边栏结构。 ::: ## 进阶配置管理 ### 模块化配置方案 对于复杂项目,推荐使用主题提供的类型安全配置工具: ::: code-tabs @tab .vuepress/collections.ts ```ts twoslash import { defineCollection, defineCollections } from 'vuepress-theme-plume' // 单个集合配置 const typescript = defineCollection({ type: 'doc', dir: 'typescript', title: 'TypeScript 笔记', linkPrefix: '/typescript/', sidebar: [ 'guide/intro.md', 'guide/getting-start.md', 'config/config-file.md', ] }) // 导出所有集合配置 export default defineCollections([ typescript ]) ``` @tab .vuepress/config.ts ```ts twoslash // @filename: ./collections.ts export default [] // ---cut--- import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' import collections from './collections' // [!code ++] export default defineUserConfig({ theme: plumeTheme({ collections // [!code ++] }), }) ``` ::: ### 大型项目配置拆分 当集合数量较多时,可采用模块化配置结构: ::: file-tree * docs * .vuepress * collections * typescript.ts * rust.ts * index.ts * … * typescript/ * rust/ ::: 配置代码组织示例: ::: code-tabs @tab .vuepress/config.ts ```ts twoslash // @filename: ./collections/index.ts export default [] // ---cut--- import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' import collections from './collections/index.ts' // [!code ++] export default defineUserConfig({ theme: plumeTheme({ collections // [!code ++] }), }) ``` @tab .vuepress/collections/index.ts ```ts twoslash // @filename: ./rust.ts export default {} // @filename: ./typescript.ts export default {} // ---cut--- import { defineCollections } from 'vuepress-theme-plume' import rust from './rust' // [!code ++] import typescript from './typescript' // [!code ++] export default defineCollections([ rust, typescript, ]) ``` @tab .vuepress/collections/typescript.ts ```ts import { defineCollection } from 'vuepress-theme-plume' export default defineCollection({ type: 'doc', dir: 'typescript', link: '/typescript/', title: 'TypeScript 笔记', sidebar: [ 'guide/intro.md', 'guide/getting-start.md', 'config/config-file.md', ] }) ``` ::: ## 侧边栏配置详解 ### 文件结构示例 假设 TypeScript 笔记 包含以下结构: ::: file-tree * docs * typescript * guide * intro.md * getting-start.md * config * config-file.md * configuration.md * reference * basic.md * syntax.md * modules.md * built-in * types * Required.md * Omit.md * README.md ::: ### 自动生成侧边栏 最简单的配置方式使用自动生成: ```ts import { defineCollection } from 'vuepress-theme-plume' export default defineCollection({ type: 'doc', dir: 'typescript', sidebar: 'auto' // 自动生成侧边栏 // [!code ++] }) ``` 主题根据目录结构自动配置侧边栏。 **排序控制**:通过数字前缀管理显示顺序 ::: file-tree * typescript * 1.guide * 1.intro.md * 2.getting-start.md * 2.config * 1.config-file.md * 2.configuration.md * … ::: 数字前缀仅用于排序,不会在侧边栏中显示。 **自动折叠**:默认情况下,侧边栏不会自动折叠,可以通过配置 `sidebarCollapsed` 开启自动折叠: ```ts import { defineCollection } from 'vuepress-theme-plume' export default defineCollection({ type: 'doc', dir: 'typescript', sidebar: 'auto', sidebarCollapsed: true, // [!code ++] }) ``` `sidebarCollapsed` 有以下可选值: * `undefined`: 默认,不自动折叠 * `true`: 默认全部折叠 * `false`: 默认全部展开 ### 自动生成次级侧边栏 为了更加灵活的控制侧边栏,减少配置的复杂度,主题允许配置仅自动生成次级侧边栏: ```ts import { defineCollection } from 'vuepress-theme-plume' export default defineCollection({ type: 'doc', dir: 'typescript', sidebar: [ // 次级 items 自动读取 typescript/guide 目录 { text: '指南', prefix: 'guide', items: 'auto' }, // 次级 items 自动读取 typescript/config 目录 { text: '配置', prefix: 'config', items: 'auto' }, ], }) ``` ### 自定义侧边栏配置 #### 基础配置类型 ```ts interface SidebarItem { text?: string // 显示文本 link?: string // 链接地址 icon?: ThemeIcon // 图标配置 badge?: string | ThemeBadge // 徽章 prefix?: string // 链接前缀 items?: 'auto' | (string | SidebarItem)[] // 下一级侧边栏 collapsed?: boolean // 折叠状态 } ``` #### 配置示例 **基础链接配置**: 采用简写形式,可以传入 md 文件的路径或 页面链接地址, 主题会自动读取文件的 `frontmatter` 配置作为侧边栏配置。 ```ts sidebar: [ // 绝对路径时, // 在 themeConfig.sidebar 中是相对于 `key` 前缀的路径 // 在 collection 中是相对于 `dir` 的路径 '/guide/intro.md', // markdown 文件地址 '/guide/getting-start/', // 页面链接地址 '/config/config-file', // 可以省略 `.md` 后缀 ] ``` **完整对象配置**: ```ts sidebar: [ { text: '介绍', link: '/guide/intro' }, { text: '快速上手', link: '/guide/getting-start' }, ] ``` **嵌套分组配置**: ```ts sidebar: [ { text: '指南', prefix: '/guide', items: [ { text: '介绍', link: 'intro' }, 'getting-start', // 简写形式 ], }, { text: '配置', prefix: '/config', items: 'auto', // 自动生成该分组下的侧边栏 }, ] ``` ### Prefix 路径处理规则 `prefix` 用于简化相同前缀的链接配置: ```ts const sidebarItem: SidebarItem = { prefix: '/guide', items: [ 'intro', // → /guide/intro.md '/config/config-file', // → /config/config-file.md (绝对路径) { link: '/blog/' }, // → /guide/blog/ { link: '/config/' } // → /config.md (绝对路径) ] } ``` **路径判断规则**: * 以 `/` 开头:绝对路径,不拼接 prefix * 其他情况:相对路径,与 prefix 拼接 **多级嵌套示例**: ```ts const sidebarItem: SidebarItem = { prefix: '/guide', items: [ 'intro', // → /guide/intro.md { prefix: '/config', // 绝对路径,抛弃上级的 prefix items: ['config-file'] // → /config/config-file.md }, { prefix: 'blog', // 相对路径,拼接上级的 prefix items: ['intro'] // → /guide/blog/intro.md } ] } ``` ::: warning 层级深度限制 避免超过 3 层嵌套的侧边栏配置,过深的层级会影响用户体验和界面美观。 ::: ## 视觉增强功能 ### 图标配置 支持多种图标源,通过 `markdown.icon.provide` 配置: ```ts sidebar: [ { text: '指南', prefix: '/guide', icon: 'ep:guide', // Iconify 图标 items: [ { text: '介绍', link: 'intro', icon: 'ph:info-light' }, ], }, ] ``` **本地图标配置**: ```ts const sidebarItem: SidebarItem = { text: '指南', icon: '/images/guide.png', // 本地图片 items: [ { text: '介绍', icon: 'https://example.com/icon.png' // 远程图片 }, ] } ``` ::: important 本地资源路径 本地图片路径应从 `/` 开始,对应 `.vuepress/public/` 目录: ::: file-tree * docs * .vuepress * public * images * guide.png * info.png ::: ### 徽章功能 通过徽章提供额外信息提示: ```ts sidebar: [ { text: '指南', badge: { text: '新', type: 'danger' }, // 对象形式 items: [ { text: '介绍', badge: '推荐' }, // 字符串简写 ], }, ] ``` **Frontmatter 配置**: ```md --- title: 介绍 badge: text: 新功能 type: danger --- ``` ### 分组分隔符 在复杂侧边栏中添加视觉分隔: ```ts sidebar: [ { text: '指南', items: [ '项目 1', '项目 2', { text: '高级功能', link: '---' }, // 分隔符 '项目 3', '项目 4', ], }, ] ``` **分隔符特征**:`link` 字段包含至少三个连续的 `-` --- --- url: /guide/sitemap/index.md --- # sitemap ## 使用 主题提供了开箱即用的配置,为 站点生成 `sitemap.xml` 文件。 要启用它,需要进行以下配置: ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ hostname: 'http://your_site_url', }) }) ``` 如需要自定义 sitemap,可以通过 `plugins.sitemap` 配置来实现。 ```ts title=".vuepress/config.ts" export default defineUserConfig({ theme: plumeTheme({ plugins: { sitemap: { // ... sitemap 配置 } } }) }) ``` 完整配置请查看 [文档](https://ecosystem.vuejs.press/zh/plugins/seo/sitemap/config.html) --- --- url: /guide/usage/index.md --- # 安装与使用 ## 环境要求 * [Node.js](https://nodejs.org/):**^20.6.0 或 >= 22.0.0** \[+node-versions] * 包管理器:[npm 8+](https://www.npmjs.com/)、[pnpm 8+](https://pnpm.io/zh/) 或 [Yarn 2+](https://yarnpkg.com/) \[+node-versions]: **^20.6.0:** `20.6.0` 及以上但低于 `21.0.0` 的版本 \[+node-versions]: **>= 22.0.0:** `22.0.0` 及以上的版本 :::: details 如何安装环境依赖? ::: steps 1. **下载 Node.js** 访问 [Node.js 官网](https://nodejs.org/zh-cn) 下载最新稳定版,按照安装向导完成安装(通常保持默认设置即可)。 2. **启用 PNPM** 安装完成后打开终端,执行以下命令: ```sh corepack enable ``` 我们推荐使用 pnpm 作为包管理器。 3. **环境就绪** ::: :::: ## 命令行安装 我们提供了命令行工具,可快速搭建基础项目结构。执行以下命令启动安装向导: ::: npm-to ```sh npm create vuepress-theme-plume@latest ``` ::: 启动后只需回答几个简单问题即可完成配置: ::: details 命令行工具使用指南 以 Windows 系统为例: 1. 按下 `Win + R` 打开"运行"对话框 2. 输入 `cmd` 或 `powershell` 后按 Enter 如果当前目录不正确,可使用以下命令切换: ```sh D: # 切换到 D 盘(根据实际情况调整) cd open-source # 进入目标目录 ``` 此时执行 `pnpm create vuepress-theme-plume@latest` 即可创建项目,项目将位于 `D:\open-source\my-project` 目录。 ::: ## 手动安装 ::: info 注意事项 * 使用 [pnpm](https://pnpm.io/zh/) 时需额外安装 `vue` 作为 peer-dependencies * 使用 [Yarn 2+](https://yarnpkg.com/) 时需在 `.yarnrc.yml` 中设置 `nodeLinker: 'node-modules'` ::: 如需手动安装,请按以下步骤操作: :::: steps * ### 创建项目目录 ```sh mkdir my-blog cd my-blog ``` * ### 初始化项目 ::: npm-to ```sh git init npm init ``` ::: * ### 安装核心依赖 安装 `vuepress@next` 和主题包: ::: npm-to ```sh # 安装 VuePress npm i -D vuepress@next vue # 安装主题和构建工具 npm i -D vuepress-theme-plume @vuepress/bundler-vite@next ``` ::: ::: warning 版本兼容性 当前主题已适配至 vuepress@{{ vuepressVersion }},使用其他版本可能存在兼容性问题。 ::: * ### 配置构建脚本 在 `package.json` 中添加: ```json title="package.json" { "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } } ``` VuePress 默认使用 `docs` 目录作为文档根目录。 * ### 配置 Git 忽略规则 ::: code-tabs @tab .gitignore ```txt node_modules .temp .cache ``` @tab sh ```sh echo 'node_modules' >> .gitignore echo '.temp' >> .gitignore echo '.cache' >> .gitignore ``` ::: * ### 配置主题 ```ts title="docs/.vuepress/config.ts" twoslash import { viteBundler } from '@vuepress/bundler-vite' import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ // 必须设置默认语言 lang: 'zh-CN', theme: plumeTheme({ // 主题配置... }), bundler: viteBundler(), }) ``` ::: warning 语言配置必填 无论是否使用多语言,都必须正确配置 `lang` 选项,主题依赖此设置确定文本语言环境。 ::: * ### 创建首页文档 ```md title="README.md" --- home: true --- ``` * ### 启动开发服务器 ::: npm-to ```sh npm run docs:dev ``` ::: VuePress 将在 启动开发服务器,支持 Markdown 文件的热重载。 * ### 安装完成 :::: ## 主题更新 使用以下命令检查并更新主题: ::: npm-to ```sh npx vp-update ``` ::: --- --- url: /guide/write/index.md --- # 编写文章 VuePress 完整支持 [标准 Markdown 语法](../markdown/basic.md),同时允许通过 [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) 格式的 Frontmatter 定义页面元数据(如标题、创建时间等)。 此外,主题还提供了丰富的 [Markdown 扩展语法](../markdown/extensions.md)。您不仅可以在 Markdown 中直接编写 HTML,还能使用 Vue 组件来增强内容表现力。 ## Frontmatter 页面配置 通过 Frontmatter 可以自定义每个页面的属性和行为。Frontmatter 位于文件顶部,由 `---` 分隔符包裹。 ```md title="post.md" --- title: 文章标题 createTime: 2024/09/08 22:53:34 permalink: /article/9eh4d6ao/ --- 页面正文内容位于第二个 `---` 之后。 ``` ::: details 什么是 Frontmatter? Frontmatter 是采用 [YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f) 格式的配置区块,位于 Markdown 文件顶部,通过 `---` 分隔符界定。 推荐阅读 [Frontmatter 详解](../../../../4.教程/frontmatter.md) 了解完整语法规范。 ::: ## 自动生成 Frontmatter 主题在开发服务器启动后,会自动为文档源目录中的 Markdown 文件生成必要的 Frontmatter 字段,包括:**标题**、**创建时间** 和 **永久链接**。 这一功能既减轻了内容创作者的重复工作负担,也为主题的后续功能提供了必要的数据支持。 ```md --- title: 标题 createTime: 2024/09/08 22:53:34 permalink: /article/9eh4d6ao/ --- ``` ### 标题生成规则 主题默认使用文件名作为文章标题。解析时会自动移除[文件命名约定](#文件夹命名约定)中的序号和扩展名,例如 `1.我的文章.md` 将生成标题 `我的文章`。 ### 创建时间 主题以文件的创建时间为基准,格式化为 `yyyy/MM/dd HH:mm:ss` 作为文章创建时间。 ### 永久链接 **永久链接**是文章发布后的固定访问地址。一旦生成,即使文件路径或名称发生变化,该链接仍保持不变。 预先设置永久链接有助于: * 提升 **SEO 效果**,避免收录地址频繁变动 * 保持整个站点链接风格的 **一致性** ### 禁用自动生成 如需完全手动控制 Frontmatter,可通过 [主题配置 > autoFrontmatter](../../config/theme.md#autofrontmatter) 禁用自动生成功能。 ```ts title=".vuepress/config.ts" twoslash import { defineUserConfig } from 'vuepress' import { plumeTheme } from 'vuepress-theme-plume' export default defineUserConfig({ theme: plumeTheme({ // 完全禁用所有自动生成 // autoFrontmatter: false, // 按需启用特定功能 autoFrontmatter: { permalink: true, // 生成永久链接 createTime: true, // 生成创建时间 title: true, // 生成标题 }, collections: [{ type: 'post', dir: 'blog', title: '博客', // 针对特定 collection 配置 autoFrontmatter: { permalink: true, createTime: true, title: true } }] }) }) ``` ## 文件组织约定 ::: info 说明 以下示例基于[项目结构](./project-structure.md)中的基准文件结构。 ::: 主题提供了灵活的文件组织方式,您可以在 `docs` 目录中按喜好创建任意命名的 Markdown 文件。 ### 文件夹命名约定 主题对 `docs` 目录中的文件夹命名采用以下规则: 对于 `post` 类型的 collection: * 文件夹名称作为文章的 **分类** * 支持多级目录,子目录作为父分类的子项 需要排序时,采用以下命名模式(适用于所有类型的 collection): ```ts :no-line-numbers const dir = /\d+\.[\s\S]+/ // 格式:数字 + . + 分类名称 // 示例:1.前端 ``` 数字部分将作为 **排序依据**。未带数字的目录按默认规则排序。 **示例结构:** ::: file-tree * docs * blog # post 类型 collection * 1.前端 * 1.html/ * 2.css/ * 3.javascript/ * 2.后端/ * 运维/ * typescript # doc 类型 collection * 1.基础 * 1.变量.md * 2.类型.md * 2.进阶.md ::: 主题将根据目录结构自动生成分类页面或者侧边栏。 ### 文件命名约定 文件命名遵循与[文件夹命名约定](#文件夹命名约定)相同的规则,为笔记功能的[自动生成侧边栏](../../config/notes.md#自动生成侧边栏)提供排序依据。 ## 开始写作 现在您可以在 `docs` 目录下创建 Markdown 文件开始写作了。关于 Markdown 扩展功能的完整说明,请参阅[扩展语法文档](../markdown/extensions.md)。 由于主题默认自动生成文章标题,正文内容的标题应从二级标题 `## 二级标题` 开始。如果禁用了 `autoFrontmatter.title`,则使用一级标题 `# 一级标题` 开始。 ### 文章标签 通过 `frontmatter.tags` 为文章添加标签: ```md --- title: 我的文章 tags: - 标签1 - 标签2 --- ``` --- --- url: /sponsor/index.md --- # 喝杯奶茶 :::important 作者的话 `vuepress-theme-plume` 是一款基于 MIT协议 的完全开源且免费的 vuepress 主题。 如果觉得主题还不错,欢迎通过 [Star](https://github.com/pengzhanbo/vuepress-theme-plume) 支持。 它源于个人的兴趣与需求,我将会长期维护它。 但持续维护也在不断地消耗我额外的精力,你能请杯奶茶为我续命吗? ![cat](/images/sponsor/cute-cat.jpg){width="64px"} ::: | ::bi:alipay:: AliPay | ::fa:wechat:: WeChat | | :------------------------------------: | :---------------------------------------: | | ![Alipay](https://static.pengzhanbo.cn/images/sponsor/ali_pay.jpg){width="300" height="300"} | ![WeChat](https://static.pengzhanbo.cn/images/sponsor/wechat_pay.jpg){width="300" height="300"} | ## 打赏记录 感谢大家对主题的大力支持! | 昵称 | 日期 | 金额 | 备注 | | ---- | ---------- | -----: | ---------------------------------------------- | | \*\*锋 | 2024-04-18 | 6.88 | 支持下作者,加油! | | *杰 | 2024-05-25 | 6.00 | 请你喝杯茶,加油 | | \*\*党 | 2024-08-22 | 8.80 | 感谢开源,加油 | | l*e | 2024-09-10 | 6.66 | 打赏 | | \*\*睿 | 2024-09-22 | 12.00 | - | | *鼠 | 2024-09-27 | 10.00 | 加油,很心怡这个项目,打算用了 | | D*y | 2024-10-15 | 10.00 | 看得出来作者真的花了很多的心思,文档和代码都维护得非常好,问题也定位得很及时。也很喜欢这种克制的界面设计。 | | G\*n | 2024-10-21 | 15.00 | 项目非常好,感谢作者一直回复我的问题,加油 | | \*健 | 2024-10-22 | 8.88 | 感觉不错 | | \*鼠 | 2024-10-23 | 50.00 | - | | *観 | 2024-10-31 | 10.00 | 好主题!也热心耐心! | | Hoey | 2024-10-31 | 9.90 | 文档写得非常详细,主题样式非常喜欢,作者加油。 | | *鼠 | 2024-11-01 | 200.00 | 感谢热心耐心的帮助 🙏 | | Y*n | 2024-11-03 | 10.00 | 开源不易,维护更不易,加油 | | T*e | 2024-11-30 | 18.80 | 谢谢一直在群里耐心回复我的问题。(一枝独秀) | | \*🌙 | 2024-12-01 | 10.00 | 作者,回复超快,有被感动 | | \*毛 | 2024-12-02 | 9.99 | 感谢 | | \*\*前 | 2024-12-03 | 50.00 | 支持 | | 🐰 | 2024-12-06 | 50.00 | 有问必答,请喝 Starbucks | | \**玉 | 2024-12-09 | 8.88 | 开源不易,加油 ✧٩(ˊωˋ*)و✧ | | \*杰 | 2025-01-27 | 18.80 | 祝新春快乐🐍 | | \*鼠 | 2025-01-31 | 18.88 | 新年快乐🎉 | | \*智 | 2025-02-09 | 16.00 | - | | *。 | 2025-03-08 | 6.66 | - | | *超 | 2025-04-03 | 18.88 | 感谢 | | n*l | 2025-04-22 | 18.88 | 感谢此主题为 fba 架构官方文档提供大力支持,作者回复和功能新增都迅如闪电,无一不令人惊叹,碉堡了! | | l*h | 2025-04-28 | 18.88 | 感谢 plume 开源主题为腾马科技官方文档提供的大力支持!开源不易,鼓励支持! | | \*羊 | 2025-04-29 | 50.00 | 不错不错👍🏻,支持一下 | | \*。 | 2025-05-07 | 18.88 | 大佬有问必答,请你喝杯奶茶。 | | \*꧂ | 2025-05-16 | 20.00 | - | | \*年 | 2025-05-23 | 10.00 | - | | *ω | 2025-06-01 | 2.33 | 学长加油 lol | | X*L | 2025-06-04 | 20.00 | 感谢大大付出,真的很好用啊!建议走商业化路线,比如出付费快速安装包,阿里云一键安装包,快速企业站等。个人脑洞,大大见笑了 | | \*\*豪 | 2025-06-06 | 6.66 | - | | \*\*然 | 2025-06-08 | 1.00 | - | | \*✨ | 2025-06-10 | 9.90 | 瑞幸 | | \*✨ | 2025-06-10 | 9.90 | 另一杯瑞幸 | | \*✨ | 2025-06-10 | 9.90 | 又一杯瑞幸 | | \*✨ | 2025-06-13 | 9.90 | 瑞幸 | | \*✨ | 2025-06-17 | 9.90 | 瑞幸 | | \*✨ | 2025-06-18 | 9.90 | 瑞幸 | | *✨ | 2025-06-21 | 9.90 | 瑞幸 | | *✨ | 2025-06-25 | 9.90 | 瑞幸 | | *啊 | 2025-07-11 | 6.66 | - | | \*\*闰 | 2025-07-19 | 9.99 | 很漂亮的主题,小小支持一下 | | G*k | 2025-08-21 | 20.00 | 请你喝一杯咖啡 | | g*y | 2025-09-09 | 20.00 | 用过的最棒的博客系统!作者也很积极耐心的解答问题 | | *士 | 2025-09-30 | 30.00 | 感谢大佬制作的漂亮好用的主题!希望 plume 越来越好 | | N*~ | 2025-10-12 | 27.00 | 一杯奶茶~ | | r*7 | 2025-10-12 | 10.00 | 秋天的第一杯🧋 | | \*\*邦 | 2025-10-13 | 50.00 | 用了一年多,刚发现还能请作者喝奶茶 | | \*。 | 2020-10-16 | 20.00 | - | --- --- url: /tools/index.md --- # 主题工具包 ## 概述 主题工具包 旨在帮助用户在使用本主题提供的一些功能时,降低其使用门槛。 ## 工具列表 ## 第三方工具 使用 **Unsplash** 图片,帮助生成高质量的博客封面。 --- --- url: /tools/caniuse/index.md --- # caniuse 特性搜索 除了使用本工具,你也可以直接访问 [caniuse.com/](https://caniuse.com/) 搜索特性, 在结果页中,点击 左侧的 `#` 按钮后,浏览器的地址栏会自动跳转,例如: 搜索 `@property`,点击 `#` 会跳转到 `https://caniuse.com/mdn-css_at-rules_property`, 可以直接复制 `mdn-css_at-rules_property` ,粘贴到 markdown 文件中: ```md @[caniuse](mdn-css_at-rules_property) ``` ## 工具 本工具用于帮助搜索 caniuse 中的特性。并生成 caniuse markdown 代码。 --- --- url: /tools/home-hero-tint-plate/index.md --- # 首页背景色板配置 为了更直观更方便的配置首页 Hero 区域 的 背景色板,主题提供了 色板配置工具, 帮助生成相对应的配置信息。 --- --- url: /tools/theme-colors/index.md --- # 主题颜色工具 ::: tip 这个工具可以帮助您快速创建自定义主题颜色。点击下方的按钮,选择您想要的主题颜色进行配置。 工具会自动应用您的修改到当前站点,您可以随意切换到任意页面查看效果。 本工具只能帮助您简单的创建主题颜色。如果您期望更加复杂的主题颜色配置,请查看 [styles/vars.css](https://github.com/pengzhanbo/vuepress-theme-plume/blob/main/theme/src/client/styles/vars.css) :::