前言

我的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

相关地址

GitHub:https://github.com/Deali-Axy/editor.md-ext

NPM:https://www.npmjs.com/package/editor.md-ext

魔改editormd组件,优化ToC渲染效果的更多相关文章

  1. 魔改了一下bootstrap-treeview组件,发布个NPM包体验一下

    前言 之前在这篇文章 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示 中说到,我为了让文章分类列表支持层级结构,用了一个树形组件,不过这个组件太老了,使用的Boots ...

  2. [7b2美化]柒比贰 魔改系列|7B2-分类封面添加波浪效果&每日诗词

    本文转载自:钻芒博客 https://www.zmki.cn/5105.html 效果如图: 代码: 首先在style.css样式表里添加波浪样式 /*浪来了*/ .lang { overflow: ...

  3. Android性能优化之渲染

    Google近期在Udacity上发布了Android性能优化的在线课程,目前有三个篇章,分别从渲染,运算与内存,电量三个方面介绍了如何去优化性能,这些课程是Google之前在Youtube上发布的A ...

  4. Android性能优化之渲染篇

    下面是渲染篇章的学习笔记,部分内容和前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Why Rendering Performance Matters 现在有不少App为了达到很华丽的视觉效果, ...

  5. 【转载】Android性能优化之渲染篇

    下面是渲染篇章的学习笔记,欢迎大家一起学习交流! 1)Why Rendering Performance Matters 现在有不少App为了达到很华丽的视觉效果,会需要在界面上层叠很多的视图组件,但 ...

  6. Hexo博客美化之蝴蝶(butterfly)主题魔改

      Hexo是轻量级的极客博客,因为它简便,轻巧,扩展性强,搭建部署方便深受广大人们的喜爱.各种琳琅满路的Hexo主题也是被各种大佬开发出来,十分钦佩,向大佬仰望,大声称赞:流批!!! 我在翻看各种主 ...

  7. 魔改——MFC MDI程序 定制 文档模板 运行时全部打开 禁用关闭按钮

    ==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...

  8. 转 cocos2d-x 优化(纹理渲染优化、资源缓存、内存优化)

    概述 包括以下5种优化:引擎底层优化.纹理优化.渲染优化.资源缓存.内存优化   引擎优化 2.0版本比1.0版本在算法上有所优化,效率更高.2.0版本使用OpenGl ES 2.0图形库,1.0版本 ...

  9. vue2.0使用动态组件实现tab切换效果(vue-cli)

    <template> <div> <div>#动态组件实现tab切换效果#</div><br><br><br> &l ...

随机推荐

  1. docker + Umami + Postgresql 网站访问分析

    1 # docker + Umami + Postgresql 2 # 官方安装文档:https://umami.is/docs/install 3 # 一.创建数据库 4 # 1.创建用户 5 CR ...

  2. BMP位图之4位位图(二)

    起始结构 typedef struct tagBITMAPFILEHEADER { WORD bfType; //类型名,字符串"BM", DWORD bfSize; //文件大小 ...

  3. WorkflowAsCode 来了,Apache DolphinScheduler 2.0.2 惊喜发布

    文章目录 前言 01 新功能 1 WorkflowAsCode 2 企业微信告警方式支持群聊消息推送 02 优化 1 简化元数据初始化流程 2 删除补数日期中的"+1"(天) 03 ...

  4. 操作系统学习笔记4 | CPU管理 && 多进程图像

    操作系统的核心功能就是管理计算机硬件,而CPU就是计算机中最核心的硬件.而通过学习笔记3的简史回顾,操作系统通过多进程图像实现对CPU的管理.所以多进程图像是操作系统的核心图像. 参考资料: 课程:哈 ...

  5. PlayCover for mac-Mac 上全屏运行 iOS 应用程序

    前言 如何在Mac电脑运行ios应用呢?PlayCover for Mac一款彻底解放苹果电脑的iOS软件安装工具,无需付费,操作简单,可以安装ipa文件,可以通过鼠标.键盘和控制器 在Mac上全屏运 ...

  6. [NOI2021] 密码箱 (平衡树,连分数,Stern-Brocot 树,矩阵)

    题面 记忆犹新 题解 f f f 函数值给得非常明显,一看就给人一种熟悉感--这不是连分数吗? 众所周知,连分数有个递推公式,即 p i = a i p i − 1 + p i − 2 q i = a ...

  7. KingbaseES V8R6 ksql 关闭自动提交

    背景 用过oracle或mysql的人都知道,做一个dml语句,如果发现做错了,还可以rollback,但在Kingbase ksql 中,如果执行一个dml,没有先运行begin; 的话,一执行完就 ...

  8. LIMIT和OFFSET分页性能差!今天来介绍如何高性能分页

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 前言 之前的大多数人分页采用的都是这样: SELEC ...

  9. HCIA-STP原理与配置

    STP协议生成树协议: 为了保证网络可靠,所以在组网时需要设置冗余链路和设备,从而在物理结构上形成结构,又因为交换机的工作特点导致二层网络中产生广播风暴和MAC地址表震荡现象,影响用户体验. 广播风暴 ...

  10. 【设计模式】Java设计模式 - 模板模式

    Java设计模式 - 模板模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...