feat: add post toc

This commit is contained in:
Justineo
2021-10-25 20:19:04 +08:00
parent 0aeafc6129
commit 45a027b6cb
10 changed files with 154 additions and 17 deletions

View File

@@ -9,12 +9,14 @@ import raw from 'rehype-raw'
import html from 'rehype-stringify'
import highlight from 'rehype-highlight'
import etpl from 'etpl'
import stringifyObject from 'stringify-object'
import { readFileSync, writeFileSync, replaceExtSync } from './util'
import demo from './remark-demo'
import ref from './remark-ref'
import anchor from './remark-anchor'
import details from './remark-details'
import custom from './remark-custom'
import toc from './remark-extract-toc'
import extractFrontmatter from './remark-extract-frontmatter'
import rehypePreviewImg from './rehype-preview-img'
import rehypeLink from './rehype-link'
@@ -40,6 +42,7 @@ const md = remark()
.use(demo)
.use(extractFrontmatter)
.use(slug)
.use(toc)
.use(remarkToRehype, { allowDangerousHTML: true })
.use(raw)
.use(rehypePreviewImg)
@@ -67,14 +70,15 @@ export function renderDocToPage (file) {
components = {},
meta = {},
deps = {},
hasAlert = false
hasAlert = false,
toc
} = data
Object.keys(deps || {}).forEach(dep => {
add({ [dep]: { [src]: true } })
})
let { layout, style = 'post' } = meta
let { layout, style = 'post', toc: showToc } = meta
let componentList = Object.keys(components)
let demoList = Object.keys(demos)
let result = renderPage({
@@ -87,7 +91,7 @@ export function renderDocToPage (file) {
demos: demoList.map(name => {
return {
name,
src: join('@/components/demos', relative(DOCS_DIR, demos[name].path))
src: join('@/components/demos', relative(DOCS_DIR, demos[name].filePath))
}
}),
components: componentList,
@@ -95,7 +99,8 @@ export function renderDocToPage (file) {
boilerplate: demoList.length || componentList.length || hasAlert || style === 'post',
layout,
style,
path: file
path: file,
toc: showToc !== false ? stringifyObject(toc[0].children) : null
})
writeFileSync(dest, result)

View File

@@ -20,6 +20,7 @@ const KNOWN_SCOPES = Object.entries(KNOWN_SCOPES_CONFIG).reduce(
export default function attacher () {
return tree => {
let scope = null
visit(tree, (node, index, parent) => {
const { type, depth, children, value, position } = node
if (type === 'heading') {

View File

@@ -0,0 +1,49 @@
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
}
}
}