使用Vditor将Markdown文档渲染成网页(Vite+JS+Vditor)

笔记哥 / 05-30 / 27点赞 / 0评论 / 391阅读
# 1. 引言 编写Markdown文档现在可以说是程序员的必备技能了,因为Markdown很好地实现了内容与排版分离,可以让程序员更专注于内容的创作。现在很多技术文档,博客发布甚至AI文字输出的内容都是以Markdown格式的形式输出的。那么,Markdown文档如何渲染成标准的Web网页呢?这就要借助于一些支持Markdown格式的编辑器组件了。开源的Markdown编辑器组件有不少,Vditor是笔者认为功能比较全的一款,在这里本文就通过Vditor来实现将一个Markdown文档渲染成网页的具体案例。 阅读本文可能需要的前置文章:[《使用Vite创建一个动态网页的前端项目》](https://charlee44.com/post.html?id=652e029025274721b6b3027718eb65f8)。 # 2. 实现 使用VS Code打开Vite初始化的工程,并且准备一个Markdown文档(笔者这里用的是Vditor的说明文档),文件组织如下所示: my-native-js-app ├── public │ └── demo.md ├── src │ ├── main.js │ └── style.css ├── index.html └── package.json 打开终端,输入如下指令,安装Vditor依赖包: ```shell npm install vditor --save ``` ## 2.1 基本配置 修改index.html中的内容: ```html Vite App
``` 其中,名称为md-content的元素就是用来显示Markdown文档的容器。接着是style.css: ```css #app { width: 800px; margin: 0 auto; } ``` 也非常简单,就是限制了显示Markdown文档的宽度以及设置居中显示。对于一个文字为主的网页来说,文档的宽度不宜太宽,现代主流的文档网页的设计都是600~800px左右。 最后就是关键的实现主要功能代码main.js: ```javascript import "./style.css"; import "vditor/dist/index.css"; import Vditor from "vditor"; async function initMarkdown() { try { const response = await fetch("/demo.md"); if (!response.ok) { throw new Error("网络无响应"); } const demoMd = await response.text(); // 显示内容 Vditor.preview(document.getElementById("md-content"), demoMd, { markdown: { toc: false, mark: true, //==高亮显示== footnotes: true, //脚注 autoSpace: true, //自动空格,适合中英文混合排版 }, math: { engine: "KaTeX", //支持latex公式 inlineDigit: true, //内联公式可以接数字 }, hljs: { style: "github", //代码段样式 lineNumber: true, //是否显示行号 }, anchor: 2, // 为标题添加锚点 0:不渲染;1:渲染于标题前;2:渲染于标题后 lang: "zh_CN", //中文 theme: { current: "light", //light,dark,light,wechat }, transform: (html) => { // 使用正则表达式替换图片路径,并添加居中样式及题注 return html.replace( /]*src="\.\/([^"]+)\.([a-zA-Z0-9]+)"\s*alt="([^"]*)"[^>]*>/g, (match, p1, p2, altText) => { // const newSrc = `${backendUrl}/blogs/resources/images/${postId}/${p1}.${p2}`; const newSrc = `${p1}.${p2}`; const imgWithCaption = `
${altText}

${altText}

`; return imgWithCaption; } ); }, }); } catch (error) { console.error("初始化Markdown失败:", error); } } document.addEventListener("DOMContentLoaded", initMarkdown); ``` 实现的过程很简单,就是在以文本的形式`fetch`远端的Markdown文档数据,然后使用`Vditor.preview`接口将获取的文本数据初始化到HTML的`md-content`元素中。关键是这个接口的初始化配置参数,具体的代表的功能笔者已经注释到代码中。其他的配置参数非常简单,按需进行配置即可;有点特别的是这个`transform`参数: ```javascript transform: (html) => { // 使用正则表达式替换图片路径,并添加居中样式及题注 return html.replace( /]*src="\.\/([^"]+)\.([a-zA-Z0-9]+)"\s*alt="([^"]*)"[^>]*>/g, (match, p1, p2, altText) => { // const newSrc = `${backendUrl}/blogs/resources/images/${postId}/${p1}.${p2}`; const newSrc = `${p1}.${p2}`; const imgWithCaption = `
${altText}

${altText}

`; return imgWithCaption; } ); }, ``` ## 2.2 图片居中+题注 这个配置参数是用来配置渲染成HTML页面前的回调函数,我们可以用这个回调函数做什么呢?很简单,可以用来实现一些特殊的元素设计。比如说,Markdown格式标准非常简陋,只规定了如何引入图片,但是没有规定如何设置图片的样式。HTML的文档流是从上到下、从左到右的线性布局的,默认情况下图片是放在新的一行的最左边的。但是实际上更最美观的实现是图片居中展示,并且显示题注。 例如,在这里笔者的Markdown文档中图片相关的内容及最终实现效果是: ![使用VS Code展示Markdown文档图片相关的内容](https://cdn.res.knowhub.vip/c/2505/30/3c9e3cb3.jpg?G1cAAER17rxgXdmI%2bJ14oAaFBJoBizSCSgnrde891ynyfI2gxeuvfbT14Te1jyYKwBRC0OEIIYHUZOXQHKjm6oaS4zsb) 在transform指定的回调函数中,也就是这里的html其实是个HTML字符串: ```js

图片

![alt 文本](https://cdn.res.knowhub.vip/c/2505/30/c4915739.png?CwqAaHR0cDovL2ltYWdlLXBhdGgucG5nAw%3d%3d)
![alt 文本](https://cdn.res.knowhub.vip/c/2505/30/a1d111fc.png "图片 Title 值"?ixOAaHR0cDovL2ltYWdlLXBhdGgucG5nICLlm77niYcgVGl0bGUg5YC8IgM%3d)

案例图片

``` 要实现图片居中,并且增加图片题注就很简单了,通过正则表达式搜索到图片的元素`案例图片`,将其替换成带题注并且居中的`div`元素,也就是: ```csharp const imgWithCaption = `
${altText}

${altText}

`; ``` 最终,这个Markdown文档的图片的网页渲染效果就是: ![自定义Markdown文档图片元素的默认样式](https://cdn.res.knowhub.vip/c/2505/30/2604dd9a.jpg?G1cAAER17rxgbYEQ%2fU48pgaFBJoBizSCSgnrde8912n2fC4ox%2btvffj68JvWhxsBZMIEFRSEkCAx46hEYCoSCab4Tgc%3d) ## 2.3 图片源更换 笔者实现的另外一个定制功能就是实现更换图片源地址。如果我们经常编写Markdown文档就知道,因为Markdown格式是文字与图片分离的,因此对图片资源的管理是件很麻烦的事情:如果使用base64编码嵌到Markdown文档里,就会影响可读性;如果使用在线图床,要么花钱要么花精力,要么既花钱又花精力。所以笔者还是推荐使用本地相对地址,例如: ```csharp ![自定义Markdown文档图片元素的默认样式](https://cdn.res.knowhub.vip/c/2505/30/d37a28de.jpg?CwOALi8yLmpwZwM%3d) ``` 这样的写法,先保证本地文档能正常工作。但是Markdown文档在渲染成网页后这个相对地址就不一样生效了,往往需要对图片地址进行更换。更关键的是,像图片这种稍微重一点的资源最好放到CDN上,所以图片源地址的更换就是个强需求,也就是这部分代码的意思: ```javascript return html.replace( /]*src="\.\/([^"]+)\.([a-zA-Z0-9]+)"\s*alt="([^"]*)"[^>]*>/g, (match, p1, p2, altText) => { // const newSrc = `${backendUrl}/blogs/resources/images/${postId}/${p1}.${p2}`; const newSrc = `${p1}.${p2}`; //... } ); ``` 先用正则表达式找到图片元素的内容,然后对图片地址进行更换,更换成域内的短地址,也可以使用域外的长地址。也就是不要在Markdown文档本身下功夫,保证本地可以正常显示即可,更多的具体的定制功能通过Vditor渲染前回调来实现。 # 3. 结语 这个案例最终的显示效果如下所示: ![Vditor将Markdown渲染成网页的效果](https://cdn.res.knowhub.vip/c/2505/30/07531e6a.jpg?G1YAAER17rxgXRkE%2fU48pgaFBJoBiSyCSgnrde891ynyfE7Q4vW3Pnx9%2bEvrw0UBmEIIZmQEn0CqsZSjhgISNTHHdzo%3d) 甚至可以表现脑图、流程图、时序图、甘特图、图表、五线谱、流程图等: ![Vditor将Markdown渲染成网页的效果](https://cdn.res.knowhub.vip/c/2505/30/d86887b5.jpg?G1YAAMTW3DgpD4JHbaMNVGfpnTYDElkElRLW6957rpPo%2bUIgmq%2b%2f9RHrw19aH0EMQBkkEIMh%2bQIRVhWvniof7pWt5HcG) 不得不说Vditor不一定是所有Markdown编辑器中最好用,但一定是功能比较全的编辑器了,至少比笔者使用过的tui.editor要强不少。其实通过这个功能,你就可以大致实现一个技术博客网站了。具体思路是:把这个渲染过程工具化,将Markdown格式的博客文档批量生成静态网页,然后通过Web服务器进行发布;其实这也是一些静态博客网站工具的实现思路。 [实现代码](https://download.csdn.net/download/charlee44/90941109)