为Markdown/HTML文档生成一个简易目录
2022-11-22 17:01
835
0
现在阅览文章的网页往往都带有一个目录,方便点击跳转。目录一般都是根据文档中的标题级别直接生成的。
现在我们也来模仿一个简单的,无非就是把<h1><h2>...
的序列转化成树嘛
思路是这样,我们首先找到所有文章的所有标题并且标记上,然后开始从前往后遍历标题,如果如果遇到同一级的标题,那就直接添加这个标题到后面,如果遇到级别更低的标题(h2 遇到 h3),说明从h3开始都是我的子目录,我们递归进入h2的子目录,直到遇到下一个高级别的标题(递归中找到更高的h2),说明完整的子目录生成完成,可以返回了。每一个新的子目录<ul>
都是原<li>
的子目录。
// 函数的含义是,在第index个标题处生成目录树,该标题级别为hLevel function genFromTitle(hLevel, index){ let ele = '' while (index < $('.isTitle').length) { let t = $('.isTitle').eq(index) if (t.attr('hLevel') > hLevel) { // 遇到更小的标题,递归生成 let nt = genFromTitle(t.attr('hLevel'), index) ele += `<li>${nt.ele}</li>` // 从nt.index到index-1的标题都处理完毕,更新index index = nt.index } else if (t.attr('hLevel') < hLevel) break // 遇到更大的标题,向上返回 else { // 相同等级平行关系,直接添加标题项,下一个 ele += `<li> <a> ${ t.text() } </a> </li>`; index ++; } } ele = `<ul>${ele}</ul>` return {ele, index} //index 也要返回去,父函数继续往后生成 } // elEssay为文档挂载点,elContent为生成的目录挂载点 function makeEssayContent(elEssay, elContent) { // 首先标记所有标题 for (let i = 1; i <= 6; i++) { elEssay.find('h'+i).addClass('isTitle').attr('hLevel', i) } elContent.html(genFromTitle(1, 0).ele);//从第一个一级标题开始生成 }
对于下面的标题,可以生成正确结果:
数据结构复习
一、线性结构
1.栈和队列
2.链表
二、树形结构
1.二叉排序树
三、排序
<ul> <li><a> 数据结构复习 </a></li> <li> <ul> <li><a> 一、线性结构</a></li> <li> <ul> <li><a> 1.栈和队列 </a></li> <li><a> 2.链表</a></li> </ul> </li> <li><a> 二、树形结构 </a></li> <li> <ul> <li><a> 1.二叉排序树 </a></li> </ul> </li> <li><a> 三、排序 </a></li> </ul> </li> </ul>
添加跳转功能
不能跳转的目录是没有什么用的,我们知道网页可以通过锚点直接跳转到对应的id,所以只要给每个标题添加一个id,再给对应的目录项设置跳转点就可以了
else { t.attr('id', 'tp'+index) // 恰好每个标题有唯一index 直接拿来用 ele += `<li> <a href="#tp${index}"> ${ t.text() } </a> </li>`; index ++; }
添加折叠功能
根据上面的图,每个ul
外面的li
的上一个元素就是这个ul
的父元素,所以可以在这个父元素设置标记,点击时将ul
折叠即可。
//econtent是我的外包裹元素,这里选中所有符合条件的父元素(能展开和收缩的) $('.econtent li ul').parent().prev().before($('<span class="foldable">></span>')) //添加一个标记 $('.foldable').on("click", (this)=>{ $(this).next().next().slideToggle() $(this).toggleClass('collapsed') })
标记有各种方法,我直接使用了一个大于号,在点击的时候旋转一下,就有生动的效果:
.foldable{ display: inline; float: left; margin-left: -1rem; /* 左移一个字符,与没有子项的同级标题对齐 */ transition: all .2s; } .collapsed{ transform: rotate(90deg); transform-origin: center; }
最终效果:见左侧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步