写点什么

搞一搞明白 Vitepress 的文档渲染基础

作者:小鑫同学
  • 2022-10-17
    北京
  • 本文字数:2577 字

    阅读完需:约 1 分钟

搞一搞明白Vitepress的文档渲染基础

1. 前言

大家好,我是小鑫同学。一位从事过 Android 开发混合开发,现在长期从事前端开发的编程爱好者,我觉得在编程之路上最重要的是知识的分享,所谓三人行必有我师。所以我开始在社区持续输出我所了解到、学习到、工作中遇到的各种编程知识,欢迎有想法、有同感的伙伴加我fe-xiaoxin微信交流~


Vitepress 的文档渲染目的就是将程序员日常所写的 Markdown 文件编译为 Html 文件,并添加了更多的插件来丰富 MD 文件的功能,就比如说 Vuejs 组件在 MD 文件中渲染等等,为了我们可以在使用 Vitepress 的时候可以更随心所欲的定制一些功能,我们要先搞一搞明白 Vitepress 是如何将 MD 文档渲染成 HTML 的~

看完可以明白这 3 点?

  • MD 文档转 HTML 文档流程;

  • 如何支持代码块高亮;

  • 如何实现自定义容器;


演示链接


演示地址

2. 实现 MD 文档转 HTML 文档

2.1 请按如下项目结构准备我们的实验环境~

├─markdown-it-demo│  ├─src│  │  ├─index.ts│  │  ├─temp.md│  ├─index.html└─ └─package.json
复制代码

2.2 利用 markdown-it 模块实现文档转换:

markdown-it 是目前比较通用的 MD 语法解析模块,快速且易于扩展,遵循 COmmonMark 规范,且有大量的社区插件~


  1. 执行安装模块命令:pnpm i markdown-it @types/markdown-it -D

  2. 导入markdown-it模块并实例化 md 对象;


import markdownIt from "markdown-it";
// 实例化md-it对象const md = new markdownIt();
复制代码


  1. 通过fs-extra模块读取放置在src下的temp.md文件,读取后的 Buffer 数组通过toString()转为字符串;


const rawMd = fs.readFileSync(path.resolve(__dirname, "temp.md")).toString();
复制代码


  1. 利用 md 对象的render函数来讲rawMd进行转换;


const output = md.render(rawMd);
复制代码


  1. 转换完成后将output内容输出到index.html文件中;


fs.writeFileSync(path.resolve(__dirname, "../index.html"), `${output}`);
复制代码


  1. 在转换完成后可以利用child_process.exec(root-path)自动在浏览器打开 index.html 文档;

3. 实现 MD 支持代码块高亮

代码块高亮所使用的模块时 highlight.js,该模块同时内置了很多常见的代码块样式文件可供选择~

3.1 第一步改造 markdownIt 对象的构造函数:

highlight属性配置的函数传入 code 片段代码方言两部分,通过在 hljs 库中查找对应的方言来利用 hljs 库实现代码的快速高亮,当无法查找到对应的方言时将返回仅仅转义后的 html 片段~


const md = new markdownIt({    highlight: (str: string, lang: string) => {        const defaultCode: string = `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`;        if (lang && hljs.getLanguage(lang)) {            try {                return `<pre class="hljs"><code>${hljs.highlight(str, { language: lang, ignoreIllegals: true }).value}</code></pre>`            } catch (__) {                return defaultCode;            }        }        return defaultCode;    }});
复制代码

3.2 第二部整合 output 内容和高亮样式文本:

第一步的操作仅仅完成了由 code 片段html 结构的转换,但是完成高亮还需要样式配合渲染,我们这里可以通过在输出 output 内容到 index.html 时将 hljs 中喜欢的样式文档路径传入到 html 文件来加载~


const output = md.render(rawMd);const styles = `<link rel="stylesheet" href="./node_modules/highlight.js/styles/a11y-dark.css">`;// 输出html文本fs.writeFileSync(path.resolve(__dirname, "../index.html"), `${styles}${output}`);
复制代码


更多的样式文档可以在./node_modules/highlight.js/styles选择~

4. 实现 MD 支持自定义容器

自定义容器是 MD 文档默认并不支持的一种语法,在 Vuejs 的文档有很多的应用,实现自定义容易需要用到markdown-it-container模块~


  1. markdownIt通过插件的形式利用markdown-it-container来实现自定义容器,通过配置validate来做渲染前的语法校验,通过render函数来组中容器部分的HTML结构~


::: warning*here be dragons*:::
↓↓↓↓↓↓↓↓↓↓转换为↓↓↓↓↓↓↓↓↓↓
<div class="warning"><em>here be dragons</em></div>
复制代码


md.use(require("markdown-it-container"), "warning", {    validate: (params: string) => {        return params.trim().match(/^warning+(.*)$/m);    },    render: (tokens: Array<Token>, idx: number) => {        const m = tokens[idx].info.trim().match(/^warning+(.*)$/m);        if (tokens[idx].nesting === 1) {            return `<div class="warning">${md.utils.escapeHtml(m ? m[1] : '')}`        } else {            return '</div>\n';        }    }})
复制代码


提示:通过tokens[idx]取到的数据如下图所示~


  1. 上面的处理依旧是 MD HTML 结构的转换,在自定义容器的时候我们预留的 css 名称,我们还是需要在输出index.html文件的时候自定义样式文档~


const output = md.render(rawMd);const styles = `<link rel="stylesheet" href="./node_modules/highlight.js/styles/a11y-dark.css"><style>    .warning{        margin: 28px 0;        padding: 10px 14px 4px 22px;        border-radius: 8px;        overflow-x: auto;        transition: color .5s,background-color .5s;        position: relative;        font-size: 14px;        line-height: 1.6;        font-weight: 500;        color: #0000008c;        background-color: #f9f9f9;        border: 1px solid #ffc517;    }    .hljs {        padding: 5px 8px;        border-radius: 5px;    }</style>`;// 输出html文本fs.writeFileSync(path.resolve(__dirname, "../index.html"), `${styles}${output}`);
复制代码

5. 总结

通过使用markdown-ithighlight.jsmarkdown-it-container模块实现了 Markdown HTML 的文档转换,代码块高亮和自定义容器,Vitepress 搭建的组件库文档中的组件渲染和源码展示功能就需要用到自定义容器的解析和组装自定义的 Vue 组件实现高级功能~


示例已推送至 GitHub,欢迎克隆演示:git clone https://github.com/OSpoon/awesome-examples.git


如果看完觉得有收获,欢迎点赞、评论、分享支持一下。你的支持和肯定,是我坚持写作的动力~最后可以关注我 @小鑫同学。欢迎点此扫码加我微信fe-xiaoxin交流,共同进步(还可以帮你 fix🐛)~


发布于: 刚刚阅读数: 3
用户头像

小鑫同学

关注

⚡InfoQ签约作者 2018-12-10 加入

⚡来【IT200.cn】找我

评论

发布
暂无评论
搞一搞明白Vitepress的文档渲染基础_前端_小鑫同学_InfoQ写作社区