给marked增加TOC(Table of content)
来源:互联网 发布:linux服务器维护教程 编辑:程序博客网 时间:2024/06/06 20:55
一直使用marked库解析Markdown,现在想给它增加TOC功能
使用marked解析markdown文本是很简单的,如:marked(markdownText)就可以得到解析后的html内容
初始化marked
引入库
var marked = require('marked');
重写renderer.heading
tocObj后面再介绍,返回的header中包含了用于定位的锚点。当然你也可以直接将锚点写在h标签中,我这里单独用一个a标签是为了解决,网站有固定的导航头的时候,定位锚点的时候标题被遮盖的问题,如:点击带锚点的网址后,如何让网页位置向下偏移一小段距离
var renderer = new marked.Renderer();renderer.heading = function(text, level, raw) { var anchor = tocObj.add(text, level); return `<a id=${anchor} class="anchor-fix"></a><h${level}>${text}</h${level}>\n`;};
设置参数
highlight是我用来处理代码高亮的,这里不考虑。
marked.setOptions({ renderer: renderer, highlight: function(code) { return require("highlight.js").highlightAuto(code).value; },});
保存marked解析后的header信息
在renderer.heading使用tocObj保存h标签的text和level并且返回一个生产的锚点,text即标签的内容,level是几级标题,如:h1,h2,h3等
产生toc的html代码
有了header信息就可以生成toc了,toc是根据h标签的等级层次来生成的,跟目录树是一样的,并不是一个单纯的列表平铺下来的。
我们目前拿到的数据是这样的,数字是level,标题是text,它们按顺序存放在数组中
h1一级标题h1一级标题 h2二级标题 h2二级标题 h3三级标题 h2二级标题h1一级标题
现在要把这些数据转换成html标签的形式
用ul和li标签来表示,就存在ul中嵌套ul的情况,如下:
<ul> <li>一级标题</li> <li>一级标题</li> <ul> <li>二级标题</li> <li>二级标题</li> <ul> <li>三级标题</li> </ul> <li>二级标题</li> </ul> <li>一级标题</li></ul>
转换代码
const tocObj = { add: function(text, level) { var anchor = `#toc${level}${++this.index}`; this.toc.push({ anchor: anchor, level: level, text: text }); return anchor; }, // 使用堆栈的方式处理嵌套的ul,li,level即ul的嵌套层次,1是最外层 // <ul> // <li></li> // <ul> // <li></li> // </ul> // <li></li> // </ul> toHTML: function() { let levelStack = []; let result = ''; const addStartUL = () => { result += '<ul>'; }; const addEndUL = () => { result += '</ul>\n'; }; const addLI = (anchor, text) => { result += '<li><a href="#'+anchor+'">'+text+'<a></li>\n'; }; this.toc.forEach(function (item) { let levelIndex = levelStack.indexOf(item.level); // 没有找到相应level的ul标签,则将li放入新增的ul中 if (levelIndex === -1) { levelStack.unshift(item.level); addStartUL(); addLI(item.anchor, item.text); } // 找到了相应level的ul标签,并且在栈顶的位置则直接将li放在此ul下 else if (levelIndex === 0) { addLI(item.anchor, item.text); } // 找到了相应level的ul标签,但是不在栈顶位置,需要将之前的所有level出栈并且打上闭合标签,最后新增li else { while (levelIndex--) { levelStack.shift(); addEndUL(); } addLI(item.anchor, item.text); } }); // 如果栈中还有level,全部出栈打上闭合标签 while(levelStack.length) { levelStack.shift(); addEndUL(); } // 清理先前数据供下次使用 this.toc = []; this.index = 0; return result; }, toc: [], index: 0};
最后的代码实现
post表示文章对象,content是markdown内容,调用marked的时候renderer.heading中就已经往tocObj中写入文章的标题信息了,最后只需要调用一下toHTML就可以产生toc的html代码了。
post2html: function(post) { if (post) { post.content = marked(post.content); post.toc = tocObj.toHTML(); }}
锚点定位偏移css
20px是被导航条遮住的高度
.anchor-fix { display: block; height: 20px; /*same height as header*/ margin-top: -20px; /*same height as header*/ visibility: hidden;}
阅读全文
0 0
- 给marked增加TOC(Table of content)
- TOC(Table of Content)数据结构
- TOC(Table of Content)数据结构
- Table of Content
- !!!Table of Content
- the table of content-type
- JS给Table增加行
- "Apress.Pro.BizTalk.2006" Table of Content
- JQuery给table动态增加样式
- jsp中给table增加删除、修改
- 给table增加水平滚动条
- jquery方法给table动态增加行
- Some indexes or index [sub]partitions of table SYS.WRH$_ACTIVE_SESSION_HISTORY have been marked unus
- How to use outline levels to create a table of contents (TOC) in Word 2003 and in Word 2002
- Confluence 内容列表区域(Table of Content Zone)宏
- jquery之table:给table动态增加行、清空table
- C# 给GRIDVIEW增加行(虚拟table建立)
- JQUERY方法给TABLE动态增加 删除行
- 登录后自动跳转到登录前的页面
- 谷歌AI系统写的机器学习代码,完爆程序员
- 《JavaScript编程精粹》——函数篇
- opencv学习笔记(1)
- 面试linux运维一定会问到Shell脚本这24个问题
- 给marked增加TOC(Table of content)
- 200000元马哥教育&摩拜联名月卡免费领啦!
- 打劫房屋 III-LintCode
- Mybatis(Mapper映射开发)
- 错过等半年 | 年薪30万都要学的Linux云计算课程,即将满80人班
- koa2给所有页面渲染全局数据
- 常用的git命令(2):远程仓库、分支和标签
- nodejs批量ping
- Java String源码之类声明与构造函数(二)