递归大法好,30 行代码为 Markdown 生成目录树

目录

前言

本以为我的博客程序是没有 [TOC] 这样东西来自动生成目录树的,都已经把代码写好了,一看文档就懵逼了。原来文档最后一条写明了,[TOC] 以及其用法,是我自己没好好看文档,心痛。

不过既然写完了,那就把原理分享出来吧,反正也就 30 行代码。千万别钻牛角尖跟我说超过了 30 行,你硬是觉得括号占一行也算行的话我也没办法。

第一步、提取标题

既然要为 Markdown 生成目录树,那么第一个步骤就是提取 Markdown 中的所有标题。因为 Markdown 本身语法非常简单,由若各个 # 符号开头,所以可以用一个正则表达式 /^(#+)[ \t](.*)$/ 进行匹配提取。(#+) 用来提取是第几级的标题,(.*) 用来提取出具体标题内容。因为很多 Markdown 实现里面都要求标题的 # 符号后面要跟空格或者 tab 来进行分隔,所以我们也按照这样的标准,用 [ \t]+ 来强制要求至少有一个空格或者 tab 进行分隔。

下面这个 getHeaders 就是用来提取一个 Markdown 里面标题的,具体过程如下:

  1. 将 Markdown 文件用 split('\n') 分成一个行数组。
  2. 将行数组里面的每一行用 /^(#+)[ \t](.*)$/ 进行匹配和提取标题。
  3. 过滤掉不匹配的行。
  4. 最后将提取出来的字符整理成一个级数和标题的对象。
const getHeaders = text =>
    text
        .split('\n')
        .map(line => line.match(/^(#+)[ \t]+(.*)$/))
        .filter(header => header !== null)
        .map(([, prefix, title]) => ({ level: prefix.length, title }))

getHeaders 函数会提取出一个 Markdown 文件里面所有的标题信息,这个标题信息里面包含了标题的级数和标题内容。

Read more   2018/1/22 posted in  技术分享