Skip to content

仅需引入一个 js 文件,即可得到 Markdown 目录、对应标题高亮且自适应滚动、平滑滚动(目录及点击)

License

Notifications You must be signed in to change notification settings

YutHelloWorld/markdown-toc

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

markdown-toc

选择的是 marked.js 库进行解析,配合 highlight.js 进行代码高亮。

在线浏览效果实例,建议 PC 端,Chrome 最佳

一、用法

直接引入 markdown-toc.js 即可。index.html 为使用示例。

二、功能

  • 生成 Markdown 的目录
  • 浏览文章内容时:
    • 对应目标标题高亮
    • 若目录标题过多:
      • 目录区域会自动滚动
      • 高亮标题置于中间(首尾除外)
  • 目录区域可手动滚动
  • 点击文章目录标题后:
    • 页面滚动至对应文章内容
    • 目录标题颜色切换
    • 修改 window.location.hash
  • 均平滑滚动(smooth)
  • Markdown CSS( zhangjikai/markdown-css && github-markdown-css
    • 修改与整理:.markdown-body
    • 目录样式:自行添加了 .markdown-toc
    • 自适应:px, em, rem,lib-flexible,px2rem-loader
  • 无标题情况

平滑滚动功能仅测试了 Chrome

三、注意事项

建议使用 marked.js 库来解析 HTML ,示例中 getMarkdownHTML() 这个方法,你会获得 Markdown 的对应 HTML ,以及生成目录所需要的数据( {text, level, anchor} )。

marked.js 在生成目录的过程中的作用:获得目录数据。

四、美化

zhangjikai/markdown-css 的基础上,结合 github-markdown-css 进行配置。

  • 修改与整理:.markdown-body
  • 目录样式:自行添加了 .markdown-toc
  • 自适应:px, em, rem:lib-flexible和px2rem-loader

五、锚点唯一性

此部分查看源码后一举击破,库本身就提供了此功能。

之前自己确定锚点的唯一性是靠标题顺序(1,2,3...),但这次查看源码后,发现自己欠缺很多考虑,源码中调用 slugger.slug 有很多数据预处理,并提供了锚点唯一值。

因为之后要添加目录,于是新增了 toc.push({text, level, anchor}) ,其中的 toc 是用于存放各级标题数据的:

 renderer.heading = function (text, level, raw, slugger) {
    if (this.options.headerIds) {
      // 遵循 options,如果 headerIds = false,也没必要制作 toc 了
      let anchor = this.options.headerPrefix + slugger.slug(raw)
      toc.push({text, level, anchor})
      return `<h${level} id="#${anchor}">${text}</h${level}>`
    }
    // ignore IDs
    return `<h${level}>${text}</h${level}>`
  };

六、TOC 思路

考虑的情况:标题并不是按顺序写的,也就是说,顺序是乱的:开局一个二级标题,接下来就是五级标题,三级标题这样。

对应数组

toc.push({text, level, anchor})

0: {text: "1 一级标题", level: 1}
1: {text: "1.1 二级标题", level: 2}
2: {text: "2 一级标题", level: 1}
3: {text: "2.1.1 三级标题", level: 3}
4: {text: "2.1.2 三级标题", level: 3}

生成的 HTML 结构

<ul>
	<li>1 一级标题
		<ul>
			<li>1.1 二级标题</li>
		</ul>
	</li>
	<li>2 一级标题
		<ul>
            <li>
                <ul> 
                    <li>2.1.1 三级标题</li>
                    <li>2.1.2 三级标题</li>
                </ul>
            </li>
		</ul>
    </li>
</ul>		

规则

* [index].level==当前level:栈顶如果是</li>,则弹出栈;输入<li>+text;推</li>入栈;index++。
* [index].level>当前level:如果栈顶是</ul>,则输入<li><ul>,推</li>入栈,推</ul>入栈;如果栈顶不是</ul>,则输入<ul>,推</ul>入栈;level++。
* [index].level<当前level:弹出 [(当前level-匹配level) * 2+1] 个值出栈;level=[index].level。
* index 达到最大,栈内数据全弹出。

示例

最右一列为栈,第一行为栈底。

</ul>(10) 表示,在第10行的时候弹出了 </ul> ,弹出时,以由下至上的顺序,若此行为多个标签,则以由右至左的顺序弹出。

且其对应行数,表示其在第几个循环被推入栈。

7 行的 </li></ul>(10) 表示,在第 7 个循环,先推入 </li> 入栈,再推入 </ul> 入栈;在第 10 行(所有循环已结束,次数所有数据均匹配完成,要打上闭合标签)时,先弹出 </ul>, 再弹出 </li>

行数 index [index].level 当前level bool
    (10)
    1 0 1 1 ==
  • 1 一级标题
  • 已匹配(4)
    2 1 2 1 >
      已匹配(4)
      3 1 2 2 ==
    • 1.1 二级标题
    • 已匹配(4)
      4 2 1 2 <
      5 2 1 1 ==
    • 2 一级标题
    • (10)
      6 3 3 1 >
        (10)
        7 3 3 2 >
        • (10)
          8 3 3 3 ==
        • 2.1.1 三级标题
        • 已匹配(9)
          9 4 3 3 ==
        • 2.1.2 三级标题
        • (10)
          - - - 全弹出,从下至上,从右至左

          详细请查看代码:markdown-toc_note.js 文件,里面含有大量注释。

          About

          仅需引入一个 js 文件,即可得到 Markdown 目录、对应标题高亮且自适应滚动、平滑滚动(目录及点击)

          Resources

          License

          Stars

          Watchers

          Forks

          Releases

          No releases published

          Packages

          No packages published

          Languages

          • JavaScript 75.4%
          • CSS 14.9%
          • HTML 9.7%