50 lines
1.2 KiB
JavaScript
50 lines
1.2 KiB
JavaScript
|
import toString from 'mdast-util-to-string'
|
||
|
import visit from 'unist-util-visit'
|
||
|
|
||
|
export default function attacher () {
|
||
|
return transformer
|
||
|
|
||
|
function transformer (tree, vfile) {
|
||
|
const headings = []
|
||
|
|
||
|
visit(tree, 'heading', onHeading)
|
||
|
|
||
|
vfile.data.toc = createTree(headings)
|
||
|
|
||
|
function onHeading (node) {
|
||
|
const heading = {
|
||
|
depth: node.depth,
|
||
|
label: toString(node)
|
||
|
}
|
||
|
if (node.data !== undefined && node.data.id != null) {
|
||
|
heading.value = `#${node.data.id}`
|
||
|
}
|
||
|
headings.push(heading)
|
||
|
}
|
||
|
|
||
|
function createTree (headings) {
|
||
|
const root = { depth: 0 }
|
||
|
const parents = []
|
||
|
let previous = root
|
||
|
|
||
|
headings.forEach((heading) => {
|
||
|
if (heading.depth > previous.depth) {
|
||
|
if (previous.children === undefined) {
|
||
|
previous.children = []
|
||
|
}
|
||
|
parents.push(previous)
|
||
|
} else if (heading.depth < previous.depth) {
|
||
|
while (parents[parents.length - 1].depth >= heading.depth) {
|
||
|
parents.pop()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
parents[parents.length - 1].children.push(heading)
|
||
|
previous = heading
|
||
|
})
|
||
|
|
||
|
return root.children
|
||
|
}
|
||
|
}
|
||
|
}
|