Vuepress 多个一级标题 自动生成sidebar的bug

377 阅读1分钟

问题:如果md中有多个一级标题,Vuepress 自动生成的侧边目录,只会包含一个一级标题

config.js使用自动生成侧栏配置

themeConfig: {
  sidebar: 'auto'
}

解决:修改源码。

  1. node_modules/@vuepress/core/lib/node/Page.js: 39行起,目的是支持h1~h4
constructor ({
  path: _path,
  meta,
  title,
  content,
  filePath,
  relative,
  permalink,
  frontmatter = {},
  permalinkPattern,
  // extractHeaders = ['h2', 'h3']
  // 改成如下:
  extractHeaders = ['h1', 'h2', 'h3', 'h4']
}
  1. node_modules/@vuepress/theme-default/util/index.js:171行groupHeaders函数重写。 所有标题按出现顺序排列:

image.png

核心思想是多轮遍历,第一轮:将h4全部归集到【最近的】h3的子目录。

同理第二轮将h3全部归集到h2的子目录。最后第三轮将h2归集到h1的子目录。

export function groupHeaders (headers) {
headers = headers.map(h => Object.assign({}, h))
  let lastH3   // 记录【当前】最靠后的h3
  headers.forEach(h => {    
    if (h.level === 3) {
      lastH3 = h
    } else if (lastH3 && h.level === 4) {
      (lastH3.children || (lastH3.children = [])).push(h)
    }
  })
  // group h3s under h2  
  let lastH2  // 记录【当前】最靠后的h2
  headers.forEach(h => {
    if (h.level === 2) {
      lastH2 = h
    } else if (lastH2 && h.level === 3) {
      // 如果有排在该h2后面的h3,放入其子目录列表
      (lastH2.children || (lastH2.children = [])).push(h)
    }
  })
  // group h2s under h1
  let lastH  // 记录【当前】最靠后的h1
  headers.forEach(h => {
    if (h.level === 1) {
      lastH = h
    } else if (lastH && h.level === 2) {
      (lastH.children || (lastH.children = [])).push(h)
    }
  })
  return headers.filter(h => h.level === 1)
}