feat: add post toc
This commit is contained in:
parent
0aeafc6129
commit
45a027b6cb
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<aside
|
<nav
|
||||||
v-outside="collapseMenu"
|
v-outside="collapseMenu"
|
||||||
class="one-nav"
|
class="one-nav"
|
||||||
:class="{ expanded }"
|
:class="{ expanded }"
|
||||||
@ -52,7 +52,7 @@
|
|||||||
{{ label }}<small>{{ sub }}</small>
|
{{ label }}<small>{{ sub }}</small>
|
||||||
</template>
|
</template>
|
||||||
</veui-menu>
|
</veui-menu>
|
||||||
</aside>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<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 html from 'rehype-stringify'
|
||||||
import highlight from 'rehype-highlight'
|
import highlight from 'rehype-highlight'
|
||||||
import etpl from 'etpl'
|
import etpl from 'etpl'
|
||||||
|
import stringifyObject from 'stringify-object'
|
||||||
import { readFileSync, writeFileSync, replaceExtSync } from './util'
|
import { readFileSync, writeFileSync, replaceExtSync } from './util'
|
||||||
import demo from './remark-demo'
|
import demo from './remark-demo'
|
||||||
import ref from './remark-ref'
|
import ref from './remark-ref'
|
||||||
import anchor from './remark-anchor'
|
import anchor from './remark-anchor'
|
||||||
import details from './remark-details'
|
import details from './remark-details'
|
||||||
import custom from './remark-custom'
|
import custom from './remark-custom'
|
||||||
|
import toc from './remark-extract-toc'
|
||||||
import extractFrontmatter from './remark-extract-frontmatter'
|
import extractFrontmatter from './remark-extract-frontmatter'
|
||||||
import rehypePreviewImg from './rehype-preview-img'
|
import rehypePreviewImg from './rehype-preview-img'
|
||||||
import rehypeLink from './rehype-link'
|
import rehypeLink from './rehype-link'
|
||||||
@ -40,6 +42,7 @@ const md = remark()
|
|||||||
.use(demo)
|
.use(demo)
|
||||||
.use(extractFrontmatter)
|
.use(extractFrontmatter)
|
||||||
.use(slug)
|
.use(slug)
|
||||||
|
.use(toc)
|
||||||
.use(remarkToRehype, { allowDangerousHTML: true })
|
.use(remarkToRehype, { allowDangerousHTML: true })
|
||||||
.use(raw)
|
.use(raw)
|
||||||
.use(rehypePreviewImg)
|
.use(rehypePreviewImg)
|
||||||
@ -67,14 +70,15 @@ export function renderDocToPage (file) {
|
|||||||
components = {},
|
components = {},
|
||||||
meta = {},
|
meta = {},
|
||||||
deps = {},
|
deps = {},
|
||||||
hasAlert = false
|
hasAlert = false,
|
||||||
|
toc
|
||||||
} = data
|
} = data
|
||||||
|
|
||||||
Object.keys(deps || {}).forEach(dep => {
|
Object.keys(deps || {}).forEach(dep => {
|
||||||
add({ [dep]: { [src]: true } })
|
add({ [dep]: { [src]: true } })
|
||||||
})
|
})
|
||||||
|
|
||||||
let { layout, style = 'post' } = meta
|
let { layout, style = 'post', toc: showToc } = meta
|
||||||
let componentList = Object.keys(components)
|
let componentList = Object.keys(components)
|
||||||
let demoList = Object.keys(demos)
|
let demoList = Object.keys(demos)
|
||||||
let result = renderPage({
|
let result = renderPage({
|
||||||
@ -87,7 +91,7 @@ export function renderDocToPage (file) {
|
|||||||
demos: demoList.map(name => {
|
demos: demoList.map(name => {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
src: join('@/components/demos', relative(DOCS_DIR, demos[name].path))
|
src: join('@/components/demos', relative(DOCS_DIR, demos[name].filePath))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
components: componentList,
|
components: componentList,
|
||||||
@ -95,7 +99,8 @@ export function renderDocToPage (file) {
|
|||||||
boilerplate: demoList.length || componentList.length || hasAlert || style === 'post',
|
boilerplate: demoList.length || componentList.length || hasAlert || style === 'post',
|
||||||
layout,
|
layout,
|
||||||
style,
|
style,
|
||||||
path: file
|
path: file,
|
||||||
|
toc: showToc !== false ? stringifyObject(toc[0].children) : null
|
||||||
})
|
})
|
||||||
|
|
||||||
writeFileSync(dest, result)
|
writeFileSync(dest, result)
|
||||||
|
@ -20,6 +20,7 @@ const KNOWN_SCOPES = Object.entries(KNOWN_SCOPES_CONFIG).reduce(
|
|||||||
export default function attacher () {
|
export default function attacher () {
|
||||||
return tree => {
|
return tree => {
|
||||||
let scope = null
|
let scope = null
|
||||||
|
|
||||||
visit(tree, (node, index, parent) => {
|
visit(tree, (node, index, parent) => {
|
||||||
const { type, depth, children, value, position } = node
|
const { type, depth, children, value, position } = node
|
||||||
if (type === 'heading') {
|
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
|
# VEUI
|
||||||
|
|
||||||
:::oss-badges
|
:::oss-badges
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
---
|
||||||
|
toc: false
|
||||||
|
---
|
||||||
# VEUI
|
# VEUI
|
||||||
|
|
||||||
:::oss-badges
|
:::oss-badges
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<article class="content ${style}">
|
<article ref="article" class="content ${style}"><!-- if: ${toc} -->
|
||||||
|
<one-toc :items="toc"/><!-- /if -->
|
||||||
${content | raw}
|
${content | raw}
|
||||||
<section class="meta">
|
<section class="meta">
|
||||||
<one-edit-link path="${path}"/>
|
<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 ${component} from '~/components/${component}'<!-- /for --><!-- for: ${demos} as ${demo}, ${index} -->
|
||||||
import Demo${index} from '${demo.src}'<!-- /for --><!-- if: ${demos.length} -->
|
import Demo${index} from '${demo.src}'<!-- /for --><!-- if: ${demos.length} -->
|
||||||
import OneDemo from '~/components/OneDemo'<!-- /if --><!-- if: ${path} -->
|
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 -->
|
import { VeuiAlert } from 'veui'<!-- /if -->
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
<!-- for: ${components} as ${component}, ${index} -->${component}<!-- if: (${index} < ${component.length} - 1) && ${demos.length} -->,
|
<!-- for: ${components} as ${component}, ${index} -->${component},
|
||||||
<!-- /if--><!-- /for --><!-- for: ${demos} as ${demo}, ${index} -->'${demo.name}': Demo${index},
|
<!-- /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} -->
|
<!-- /for --><!-- if: ${demos.length} -->OneDemo,<!-- /if --><!-- if: ${alert} -->
|
||||||
VeuiAlert<!-- /if --><!-- if: (${components.length} || ${demos.length}) || ${alert} && ${path} -->,<!-- /if --><!-- if: ${path} -->
|
VeuiAlert,<!-- /if --><!-- if: ${toc} -->
|
||||||
OneEditLink<!-- /if -->
|
OneToc,<!-- /if --><!-- if: ${path} -->
|
||||||
|
OneEditLink,<!-- /if -->
|
||||||
},
|
},
|
||||||
mixins: [htmlAttrs]
|
mixins: [htmlAttrs]<!-- if: ${toc} -->,
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
toc: ${toc | raw}
|
||||||
|
}
|
||||||
|
}<!-- /if -->
|
||||||
}
|
}
|
||||||
</script><!-- else -->
|
</script><!-- else -->
|
||||||
<script>
|
<script>
|
||||||
|
45
package-lock.json
generated
45
package-lock.json
generated
@ -10141,6 +10141,12 @@
|
|||||||
"has-symbols": "^1.0.1"
|
"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": {
|
"get-port-please": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-2.2.0.tgz",
|
||||||
@ -12398,9 +12404,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mdast-util-to-string": {
|
"mdast-util-to-string": {
|
||||||
"version": "1.1.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
|
||||||
"integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==",
|
"integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"mdn-data": {
|
"mdn-data": {
|
||||||
@ -16307,6 +16313,14 @@
|
|||||||
"github-slugger": "^1.0.0",
|
"github-slugger": "^1.0.0",
|
||||||
"mdast-util-to-string": "^1.0.0",
|
"mdast-util-to-string": "^1.0.0",
|
||||||
"unist-util-visit": "^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": {
|
"remark-stringify": {
|
||||||
@ -17487,6 +17501,31 @@
|
|||||||
"is-hexadecimal": "^1.0.0"
|
"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": {
|
"strip-ansi": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
"less-plugin-est": "^3.0.0",
|
"less-plugin-est": "^3.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lowlight": "^1.9.2",
|
"lowlight": "^1.9.2",
|
||||||
|
"mdast-util-to-string": "^2.0.0",
|
||||||
"mkdirp": "^0.5.5",
|
"mkdirp": "^0.5.5",
|
||||||
"moment": "^2.22.2",
|
"moment": "^2.22.2",
|
||||||
"nuxt": "^2.15.7",
|
"nuxt": "^2.15.7",
|
||||||
@ -70,6 +71,7 @@
|
|||||||
"remark-shortcodes": "^0.1.5",
|
"remark-shortcodes": "^0.1.5",
|
||||||
"remark-slug": "^4.2.3",
|
"remark-slug": "^4.2.3",
|
||||||
"short-circuit-loader": "0.0.1-alpha.2",
|
"short-circuit-loader": "0.0.1-alpha.2",
|
||||||
|
"stringify-object": "^3.3.0",
|
||||||
"stylelint": "^13.6.1",
|
"stylelint": "^13.6.1",
|
||||||
"stylelint-plugin-stylus": "^0.9.0",
|
"stylelint-plugin-stylus": "^0.9.0",
|
||||||
"stylus": "^0.54.5",
|
"stylus": "^0.54.5",
|
||||||
|
Loading…
Reference in New Issue
Block a user