魔改editormd组件,优化ToC渲染效果
前言 我的StarBlog博客目前使用 editor.md 组件在前端渲染markdown文章,但这个组件自动生成的ToC(内容目录)不是很美观,我之前魔改过一个树形组件 BootStrap-TreeView,所以就想要用这个树形组件来展示ToC。 原本的效果是这样的 image-20221020112752560 我魔改完的效果 image-20221020112914518 先分析一波 首先看
目录7 个章节
前言
我的StarBlog博客目前使用 editor.md 组件在前端渲染markdown文章,但这个组件自动生成的ToC(内容目录)不是很美观,我之前魔改过一个树形组件 BootStrap-TreeView,所以就想要用这个树形组件来展示ToC。
原本的效果是这样的

我魔改完的效果

先分析一波
首先看一下 editor.md 这个组件如何渲染 markdown,根据官方的例子
先写个 textarea 把 markdown 放进去
<div id="post-markdown-content" class="post-content">
<textarea style="display:none;">@Model.Content</textarea>
</div>
还要一个 div 来放目录
<div id="post-toc-container"></div>
然后用js调用它的渲染方法
let editorMdView = editormd.markdownToHTML("post-markdown-content", {
htmlDecode: true,
tocm: true, // Using [TOCM]
tocContainer: "#toc-container", // 自定义 ToC 容器层
emoji: true,
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
});
这样文章内容和目录就都出来了
我一开始想的是,既然它可以渲染出来目录,那一定是有一个目录树的结构可以用
结果在控制台 console.log 半天都没看到这个树结构
editormd.markdownToHTML 方法返回的数据就单纯是一个 div 元素的对象……
开始折腾
无语,没办法我只能去看源码
整个组件的源码都在一个 js 文件内,幸好可读性还行~
直接找到 markdownToHTML 方法的定义,在3885行开始,然后找到里面有个变量 markdownToC ,应该就是我们要的了,打印一下看看,大致结构如下
[
{"text": "Node1", "slug": "node1", "level": 2},
{"text": "Django-Dev", "slug": "django-dev", "level": 3},
{"text": "Java-Dev", "slug": "java-dev", "level": 3},
{"text": "Spring-Dev", "slug": "spring-dev", "level": 3}
]
不是树结构,就是个array
就是简单的对整个markdown文档进行遍历,level 字段根据标题类型来确定,也就是 # 的数量。
而我之前魔改的 Bootstrap-Treeview 组件需要传入一个树结构的对象进行渲染,所以我需要进一步处理。
处理树结构
一开始我头铁,直接把 editor.md 生成的那坨东西丢进递归里面
结果没搞出来
后面换了思路,先把这个 array 改一下,给每个 item 加上 id 和 pid,这样再来递归生成树就好处理得多了~
先定义节点对象,这个就是 Bootstrap-Treeview 需要用的数据结构
class TocNode {
constructor(text, href, tags, nodes) {
this.text = text
this.href = href
this.tags = tags
this.nodes = nodes
}
}
然后来把 markdownToC 那坨东西遍历一遍,顶层节点的 pid 设置成 -1,每个节点从 0 开始按顺序赋值 id,然后每个节点往前面找 level 少 1 的节点,找到就是父节点,设置 pid ,完事~
let toc = markdownToC
for (let i = 0; i < toc.length; i++) {
let item = toc[i]
item.id = i
item.pid = -1
for (let j = i; j >= 0; j--) {
let preItem = toc[j]
if (item.level === preItem.level + 1) {
item.pid = j
break
}
}
}
生成树结构,很简单不多说了
function getNodes(pid = -1) {
let nodes = toc.filter(item => item.pid === pid)
if (nodes.length === 0) return null
return nodes.map(item => new TocNode(item.text, `#${item.text}`, null, getNodes(item.id)))
}
搞定~
魔改
然后就是根据这个思路,fork了一份代码进行魔改。
原版是在 markdownToHTML 方法执行完直接返回一个 div 元素,我则是在返回的 div 元素上添加了两个属性,然后再返回 div:
div.markdownToc = markdownToC
div.markdownTocTree = editormd.tocListToTree(markdownToC)
return div
这样在使用的时候就可以方便的将 Bootstrap-Treeview 组件整合进来了。
用法
先安装我发布的NPM包
// 魔改的 editor.md 组件
npm i editor.md-ext
// 魔改的树形列表组件
npm i bootstrap5-treeview
页面上引入 CSS
<link rel="stylesheet" href="~/lib/editormd/css/editormd.preview.css">
引入 JS
<!-- jQuery -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<!-- 树形列表组件 -->
<script src="~/js/bootstrap-treeview.js"></script>
<!-- editor.md 需要的依赖 -->
<script src="~/lib/editormd/lib/marked.min.js"></script>
<script src="~/lib/editormd/lib/prettify.min.js"></script>
<script src="~/lib/editormd/lib/raphael.min.js"></script>
<script src="~/lib/editormd/lib/underscore.min.js"></script>
<script src="~/lib/editormd/lib/sequence-diagram.min.js"></script>
<script src="~/lib/editormd/lib/flowchart.min.js"></script>
<script src="~/lib/editormd/lib/jquery.flowchart.min.js"></script>
<script src="~/lib/editormd/editormd.js"></script>
准备一个 div 作为目录容器
<div id="post-toc-container"></div>
准备一个 div 存放文章内容,把 Markdown 内容放进这个 textarea 里面。
<div id="post-markdown-content" class="post-content">
<textarea style="display:none;">@Model.Content</textarea>
</div>
写一段 JS 代码来启用渲染
$(function () {
// 渲染文章
let editorMdView = editormd.markdownToHTML("post-markdown-content", {
htmlDecode: true,
tocm: true, // Using [TOCM]
emoji: true,
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
});
// 渲染目录
$('#post-toc-container').treeview({
data: editorMdView.markdownTocTree,
levels: 2,
enableLinks: true,
highlightSelected: false,
showTags: true,
})
})
关于树形列表组件的用法可以看我的 GitHub :https://github.com/Deali-Axy/bootstrap5-treeview
相关地址
_EOF_
魔改editormd组件,优化ToC渲染效果
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
配置Chrome支持网页内的frame跨域
前言 跨域限制可以保证安全,但是调试的时候关掉会更方便,然而现在网络上能找到的关闭跨域限制方法,在新版的Chrome浏览器上根本没用…… 经过一番摸索,发现用旧版的Chrome就可以绕过跨域限制,刚好我做的这个需要跨域内嵌frame的网页只是单纯展示的,所以这个正好符合我的需求,奥利给! 然后我找到了旧版的Chrome软件,解压出来是绿色版的可以直接运行,不过运行后发现直接把系统的Chrome给调
2021-12-18 · Web前端 · 约 1 分钟
Next.js路由段配置选项笔记
Next.js的路由段配置选项?真有这么简单?官方文档写得倒是分散,自己整理下倒也罢了。动态渲染还是静态?缓存策略又该怎么定?开发者还是得自己琢磨。
2025-10-30 · Web前端 · 约 1 分钟
使用 swagger-typescript-api 在前端项目里生成请求代码
swagger-typescript-api?文档写得像草稿,还得自己摸索。那些花哨的模块化选项除了报错还能干嘛?老老实实生成单文件,配个客户端封装,省得每次折腾。
2025-11-03 · Web前端 · 约 1 分钟
在Next.js中集成swagger文档
Next.js 本来就不能直接用 Swagger,非要用还得自己折腾 API Routes?自动生成工具?手动写 Spec?这简直是在侮辱开发者。手动注释?这操作简直是在挑战耐心极限。
2025-09-01 · Web前端 · 约 1 分钟
讨论
共 0 条加载评论中…