feat: add post toc
This commit is contained in:
parent
0aeafc6129
commit
45a027b6cb
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<aside
|
||||
<nav
|
||||
v-outside="collapseMenu"
|
||||
class="one-nav"
|
||||
:class="{ expanded }"
|
||||
@ -52,7 +52,7 @@
|
||||
{{ label }}<small>{{ sub }}</small>
|
||||
</template>
|
||||
</veui-menu>
|
||||
</aside>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
27
components/OneToc.vue
Normal file
27
components/OneToc.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<nav class="one-toc">
|
||||
<veui-anchor
|
||||
:items="items"
|
||||
sticky
|
||||
/>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Anchor } from 'veui'
|
||||
|
||||
export default {
|
||||
name: 'one-toc',
|
||||
components: {
|
||||
'veui-anchor': Anchor
|
||||
},
|
||||
props: {
|
||||
items: Array
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.one-toc
|
||||
float right
|
||||
</style>
|
@ -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)
|
||||
|
@ -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') {
|
||||
|
49
one/build/remark-extract-toc.js
Normal file
49
one/build/remark-extract-toc.js
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
---
|
||||
toc: false
|
||||
---
|
||||
# VEUI
|
||||
|
||||
:::oss-badges
|
||||
|
@ -1,3 +1,6 @@
|
||||
---
|
||||
toc: false
|
||||
---
|
||||
# VEUI
|
||||
|
||||
:::oss-badges
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<article class="content ${style}">
|
||||
<article ref="article" class="content ${style}"><!-- if: ${toc} -->
|
||||
<one-toc :items="toc"/><!-- /if -->
|
||||
${content | raw}
|
||||
<section class="meta">
|
||||
<one-edit-link path="${path}"/>
|
||||
@ -11,18 +12,25 @@ import { htmlAttrs } from '~/common/i18n'<!-- for: ${components} as ${component}
|
||||
import ${component} from '~/components/${component}'<!-- /for --><!-- for: ${demos} as ${demo}, ${index} -->
|
||||
import Demo${index} from '${demo.src}'<!-- /for --><!-- if: ${demos.length} -->
|
||||
import OneDemo from '~/components/OneDemo'<!-- /if --><!-- if: ${path} -->
|
||||
import OneEditLink from '~/components/OneEditLink'<!-- /if --><!-- if: ${alert} -->
|
||||
import OneEditLink from '~/components/OneEditLink'<!-- /if --><!-- if: ${toc} -->
|
||||
import OneToc from '~/components/OneToc'<!-- /if --><!-- if: ${alert} -->
|
||||
import { VeuiAlert } from 'veui'<!-- /if -->
|
||||
|
||||
export default {
|
||||
components: {
|
||||
<!-- for: ${components} as ${component}, ${index} -->${component}<!-- if: (${index} < ${component.length} - 1) && ${demos.length} -->,
|
||||
<!-- /if--><!-- /for --><!-- for: ${demos} as ${demo}, ${index} -->'${demo.name}': Demo${index},
|
||||
<!-- /for --><!-- if: ${demos.length} -->OneDemo<!-- /if --><!-- if: (${components.length} || ${demos.length}) && ${alert} -->,<!-- /if --><!-- if: ${alert} -->
|
||||
VeuiAlert<!-- /if --><!-- if: (${components.length} || ${demos.length}) || ${alert} && ${path} -->,<!-- /if --><!-- if: ${path} -->
|
||||
OneEditLink<!-- /if -->
|
||||
<!-- for: ${components} as ${component}, ${index} -->${component},
|
||||
<!-- /for --><!-- for: ${demos} as ${demo}, ${index} -->'${demo.name}': Demo${index},
|
||||
<!-- /for --><!-- if: ${demos.length} -->OneDemo,<!-- /if --><!-- if: ${alert} -->
|
||||
VeuiAlert,<!-- /if --><!-- if: ${toc} -->
|
||||
OneToc,<!-- /if --><!-- if: ${path} -->
|
||||
OneEditLink,<!-- /if -->
|
||||
},
|
||||
mixins: [htmlAttrs]
|
||||
mixins: [htmlAttrs]<!-- if: ${toc} -->,
|
||||
data () {
|
||||
return {
|
||||
toc: ${toc | raw}
|
||||
}
|
||||
}<!-- /if -->
|
||||
}
|
||||
</script><!-- else -->
|
||||
<script>
|
||||
|
45
package-lock.json
generated
45
package-lock.json
generated
@ -10141,6 +10141,12 @@
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
|
||||
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
|
||||
"dev": true
|
||||
},
|
||||
"get-port-please": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-2.2.0.tgz",
|
||||
@ -12398,9 +12404,9 @@
|
||||
}
|
||||
},
|
||||
"mdast-util-to-string": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz",
|
||||
"integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
|
||||
"integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
|
||||
"dev": true
|
||||
},
|
||||
"mdn-data": {
|
||||
@ -16307,6 +16313,14 @@
|
||||
"github-slugger": "^1.0.0",
|
||||
"mdast-util-to-string": "^1.0.0",
|
||||
"unist-util-visit": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mdast-util-to-string": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz",
|
||||
"integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"remark-stringify": {
|
||||
@ -17487,6 +17501,31 @@
|
||||
"is-hexadecimal": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"stringify-object": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
|
||||
"integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-own-enumerable-property-symbols": "^3.0.0",
|
||||
"is-obj": "^1.0.1",
|
||||
"is-regexp": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
"is-regexp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
|
||||
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
|
@ -50,6 +50,7 @@
|
||||
"less-plugin-est": "^3.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lowlight": "^1.9.2",
|
||||
"mdast-util-to-string": "^2.0.0",
|
||||
"mkdirp": "^0.5.5",
|
||||
"moment": "^2.22.2",
|
||||
"nuxt": "^2.15.7",
|
||||
@ -70,6 +71,7 @@
|
||||
"remark-shortcodes": "^0.1.5",
|
||||
"remark-slug": "^4.2.3",
|
||||
"short-circuit-loader": "0.0.1-alpha.2",
|
||||
"stringify-object": "^3.3.0",
|
||||
"stylelint": "^13.6.1",
|
||||
"stylelint-plugin-stylus": "^0.9.0",
|
||||
"stylus": "^0.54.5",
|
||||
|
Loading…
Reference in New Issue
Block a user