功能扩展
Markdown 功能加强
Vitepress 已经为 Markdown 添加了许多功能扩展(如 emoji,代码高亮,代码组等)了,详见 官方文档。
但还是有一些实用的功能并没有被支持,比如 taskLists:
- [ ] todo
- [x] finished所幸 Vitepress 使用 markdown-it 作为 Markdown 渲染引擎,所以所有 markdown-it 的插件我们都可以在 Vitepress 中使用,官方教程在 这里。下面我会演示一下我是如何添加 taskList 支持的:
// .vitepress/config.mts
import taskLists from 'markdown-it-task-lists'
let config = defineConfig({
..., // 其他配置
markdown: {
config: (md) => {
// use more markdown-it plugins!
md.use(taskLists)
}
},
}
export default config添加完后,上述的例子将会被渲染这样:
- todo
- finished
Vitepress 集成 Mermaid
使用现成插件 vitepress-plugin-mermaid。
首先安装插件:
npm i vitepress-plugin-mermaid mermaid -D然后编辑配置文件:
import { withMermaid } from 'vitepress-plugin-mermaid'
let config = defineConfig({
..., // 其他配置
// optionally, you can pass MermaidConfig
mermaid: {
// refer for options:
// https://mermaid.js.org/config/setup/modules/mermaidAPI.html#mermaidapi-configuration-defaults
},
// optionally set additional config for plugin itself with MermaidPluginConfig
mermaidPlugin: {
// set additional css class for mermaid container
class: "mermaid"
}
}
config = withMermaid(config)
export default config然后就可以像在 Typora 里写 mermaid 一样了。
``` mermaid
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
```COS 图床 + PicGo 上传
这个网站中的图片存储是个麻烦事。直接存到项目里的话,图片太多太乱而且 git 也不好管理。找个图床存的话,又总担心图床跑路。最后看了半天,还是决定掏点小钱去买个 COS 服务来存图片。
配置过程我也都参考的网上的资料,我就不再赘述一遍了,简单罗列几篇文章在下面:
将 COS、PicGo 配置好之后就可以使用 COS 当图床,用 PicGo 来快捷上传了。可以根据平时写文章的软件再多配置一下 VSCode 和 Typora。
INFO
使用 PicGo 上传图片之后,如果在本地(markdown 中)又删除了这张图片,那么 COS 中的图片不会随之删除。 这会造成 COS 存储空间的浪费,并带来额外费用。(很少很少)
自动生成 Sidebar
有些文章集合需要一个 Sidebar 来当目录,我通过一个 generateSidebar 函数来实现这个功能。原理图如下:
实现代码
import { readdirSync, statSync } from 'fs'
import { join, parse } from 'path'
import matter from 'gray-matter'
import { DefaultTheme } from 'vitepress'
type SidebarItem = DefaultTheme.SidebarItem
function generateSidebar(dir: string) {
// 初始化 SidebarItem
let sidebar: SidebarItem = {
base: `/${dir}/`,
// text 初始值为目录名
text: `${parse(dir).name}`,
items: []
}
// 遍历目录
let files = readdirSync(dir)
let subDirs: string[] = []
files.forEach((file) => {
let path = join(dir, file)
let stat = statSync(path)
if (stat.isDirectory()) {
// 稍后处理子文件夹
subDirs.push(file)
} else {
// 处理 md 文件
if (file.endsWith('.md')) {
let { data } = matter.read(path)
let { title } = data
if (!title) {
// frontmatter 中没有 title,就用文件名作为 title
title = file.replace(/\.md$/, '')
}
if (file == 'index.md') {
// 如果有 index 文件,就把它作为 Sidebar 的标题
sidebar['text'] = title
sidebar['link'] = file.replace(/\.md$/, '')
return
}
// 一般不是 index 的文件,就作为 Sidebar 的子项
let item: SidebarItem = {
text: title,
link: file.replace(/\.md$/, '')
}
sidebar.items!.push(item)
}
}
})
subDirs.forEach((subDir) => {
let subSidebar = generateSidebar(join(dir, subDir))
sidebar.items!.push(subSidebar)
})
return sidebar
}使用:
// My separate sidebar file.
let sidebar = {
'/examples/': [
{
base: '/examples/',
text: 'Examples',
items: [
{ text: 'Markdown Examples', link: 'markdown-examples' },
{ text: 'Runtime API Examples', link: 'api-examples' }
]
}
],
'/articles/50projects50days/': [ generateSidebar('articles/50projects50days') ],
'/articles/initial/': [ generateSidebar('articles/initial') ],
}
export default sidebarinitial
├── 1-build.md
├── 2-deploy.md
├── 3-guide.md
├── 4-enhance.md
└── index.md最终效果就像在本页面看到的一样,Sidebar 会作为几篇文章的一个目录,如果在某一级目录下有 index.md 那么这个这一级目录的标题将可以点击并跳转到这个 index.md。