写博客一般离不开标签,比如 Hexo 的 标签插件(Tag Plugins),可以在文章中快速插入特定内容的插件。但是,如你所见,本站是基于 VitePress
的,它支持的插件可以说基本上没有,所以需要自定义。
遂去查看文档,在 Markdown 扩展 一节中有这么一段:
VitePress
使用markdown-it
作为 Markdown 渲染器。上面提到的很多扩展功能都是通过自定义插件实现的。可以使用.vitepress/config.js
中的 markdown 选项来进一步自定义 markdown-it 实例。
那么就好办了,去找找如何在 markdown-it
中自定义标签就行了。但是问题又出现了,相关的教程几乎没有 😢,没办法,只能在 Github 以及 StackOverflow 的相关问题中慢慢摸索,再结合一下 ChatGPT,也算是实现了一些标签。
基础配置
首先,得先确保在 .vitepress/config.js
中添加了 markdown
配置项:
export default {
markdown: {
// 一些基础配置...
// 在这里使用相关插件和自定义标签
config: (md) => {
// ...
},
},
};
安装插件
在基础配置完成后,得先安装 markdown-it-container 插件,它允许你自定义容器标签。
pnpm add markdown-it-container -D
然后在配置文件中引入它:
import container from "markdown-it-container";
export default {
markdown: {
// ...
config: (md) => {
// 一个简单的示例
md.use(container, "demo");
},
},
};
自定义标签
准备工作完成后,就可以开始自定义标签了。
首先,比如你想实现一个按钮标签,那么你得先在 md 文档中这样写:
::: button
这是一个按钮
:::
然后,你得在配置文件中这样写:
import container from "markdown-it-container";
export default {
markdown: {
config: (md) => {
md.use(container, "button", {
render: (tokens, idx, _options, env) => {
const token = tokens[idx];
if (token.nesting === 1) {
return "<button>";
} else {
return "</button>";
}
},
});
},
},
};
来详细看下这个配置文件都做了些什么:
md.use(container, "button")
这一行是告诉 markdown-it 实例 "button" 将用作自定义容器的名称,在 Markdown 文档中匹配所有
::: button
形式的内容。{ render: (tokens, idx, _options, env) => { ... } }
render
属性是一个渲染函数,它定义了如何将自定义容器转换成 HTML。这个函数接受四个参数:tokens
是一个 token 数组,表示 Markdown 解析器生成的标记( tokens ),表示来源的标记流。idx
是当前 token 在数组中的索引。_options
是可选的,表示传递给 markdown-it-container 插件的选项,这里用下划线前缀表示它是未使用的。env
是关于整个 Markdown 解析环境的信息。
const token = tokens[idx]
这一步从 tokens 数组中获取当前的 token,即当前正在处理的 Markdown 部分。
if (token.nesting === 1)
这条 if 语句检查
nesting
属性。在 markdown-it-container 插件中,nesting 可以是 1、-1 或 0:- 如果
nesting
是 1,表示这是容器的开始标记。 - 如果
nesting
是 -1,表示这是容器的结束标记。 - 如果
nesting
是 0,表示这是一个不可嵌套的自闭合标记。
- 如果
后面配置就是将自定义元素返回,并且根据
nesting
值添加开始和结束标签。
最终,会在页面中渲染出这样的 HTML:
<button>这是一个按钮</button>
接下来就可以进行自定义样式等操作了。
使用参数
有些时候还想在自定义标签中使用一些参数,比如按钮的颜色、大小等。
::: button red
这是一个红色按钮
:::
那么配置文件应该这样写:
module.exports = {
// ...
markdown: {
config: (md) => {
md.use(container, "button", {
render: (tokens, idx) => {
const token = tokens[idx];
if (token.nesting === 1) {
const color = tokens[idx].info.trim().replace("button ", "");
return `<button class="buttom ${color}">`;
}
return "</button>";
},
});
},
},
};
与上面的配置文件不同的是,多了这一句:
const color = tokens[idx].info.trim().replace("button ", "");
这一句将 button
部分从 ::: button red
中去除,这样就能得到 red
参数了,然后将 red
参数作为 class
添加到按钮中,然后就可以设置相应的样式来实现了。
结束
这就是一些最基础的配置方法了,更高级的用法还没学会,以后再更新吧。