From d2fef5d8f6f00aca13b5594c6084a54e1c8c3b18 Mon Sep 17 00:00:00 2001 From: Franck Abgrall Date: Mon, 21 Oct 2019 17:36:21 +0200 Subject: [PATCH] feat($markdown): `extractHeaders` option (close: #1903) (#1945) --- packages/@vuepress/core/lib/node/App.js | 1 + packages/@vuepress/core/lib/node/Page.js | 9 ++++++--- .../core/lib/node/webpack/createBaseConfig.js | 3 ++- packages/@vuepress/markdown-loader/index.js | 4 ++-- .../theme-default/components/SidebarLink.vue | 7 +++++-- packages/docs/docs/theme/default-theme-config.md | 11 +++++++++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/@vuepress/core/lib/node/App.js b/packages/@vuepress/core/lib/node/App.js index 1fdc615785..e21c8ce29b 100755 --- a/packages/@vuepress/core/lib/node/App.js +++ b/packages/@vuepress/core/lib/node/App.js @@ -344,6 +344,7 @@ module.exports = class App { async addPage (options) { options.permalinkPattern = this.siteConfig.permalink + options.extractHeaders = this.siteConfig.markdown && this.siteConfig.markdown.extractHeaders const page = new Page(options, this) await page.process({ markdown: this.markdown, diff --git a/packages/@vuepress/core/lib/node/Page.js b/packages/@vuepress/core/lib/node/Page.js index 0ea0242d84..99cb6d4eaa 100644 --- a/packages/@vuepress/core/lib/node/Page.js +++ b/packages/@vuepress/core/lib/node/Page.js @@ -45,7 +45,8 @@ module.exports = class Page { relative, permalink, frontmatter = {}, - permalinkPattern + permalinkPattern, + extractHeaders = ['h2', 'h3'] }, context) { this.title = title this._meta = meta @@ -54,6 +55,7 @@ module.exports = class Page { this._permalink = permalink this.frontmatter = frontmatter this._permalinkPattern = permalinkPattern + this._extractHeaders = extractHeaders this._context = context if (relative) { @@ -111,12 +113,13 @@ module.exports = class Page { this.title = title } - // headers + // extract headers const headers = extractHeaders( this._strippedContent, - ['h2', 'h3'], + this._extractHeaders, markdown ) + if (headers.length) { this.headers = headers } diff --git a/packages/@vuepress/core/lib/node/webpack/createBaseConfig.js b/packages/@vuepress/core/lib/node/webpack/createBaseConfig.js index d1e989629b..93723c260a 100644 --- a/packages/@vuepress/core/lib/node/webpack/createBaseConfig.js +++ b/packages/@vuepress/core/lib/node/webpack/createBaseConfig.js @@ -34,6 +34,7 @@ module.exports = function createBaseConfig (context, isServer) { const inlineLimit = 10000 const config = new Config() + const extractHeaders = siteConfig.markdown && siteConfig.markdown.extractHeaders config .mode(isProd && !env.isDebug ? 'production' : 'development') @@ -118,7 +119,7 @@ module.exports = function createBaseConfig (context, isServer) { mdRule .use('markdown-loader') .loader(require.resolve('@vuepress/markdown-loader')) - .options({ sourceDir, markdown }) + .options({ sourceDir, markdown, extractHeaders }) config.module .rule('pug') diff --git a/packages/@vuepress/markdown-loader/index.js b/packages/@vuepress/markdown-loader/index.js index 4861d2c55e..9b87dd4b18 100644 --- a/packages/@vuepress/markdown-loader/index.js +++ b/packages/@vuepress/markdown-loader/index.js @@ -22,7 +22,7 @@ module.exports = function (src) { const isServer = this.target === 'node' const options = getOptions(this) const loader = Object.create(this) - const { sourceDir } = options + const { sourceDir, extractHeaders: extractHeadersPattern = ['h2', 'h3'] } = options let { markdown } = options if (!markdown) { markdown = md() @@ -43,7 +43,7 @@ module.exports = function (src) { if (!isProd && !isServer) { const inferredTitle = inferTitle(frontmatter.data, frontmatter.content) - const headers = extractHeaders(content, ['h2', 'h3'], markdown) + const headers = extractHeaders(content, extractHeadersPattern, markdown) delete frontmatter.content // diff frontmatter and title, since they are not going to be part of the diff --git a/packages/@vuepress/theme-default/components/SidebarLink.vue b/packages/@vuepress/theme-default/components/SidebarLink.vue index 5183aa6f2e..4efb0f2039 100644 --- a/packages/@vuepress/theme-default/components/SidebarLink.vue +++ b/packages/@vuepress/theme-default/components/SidebarLink.vue @@ -54,7 +54,7 @@ export default { } } -function renderLink (h, to, text, active) { +function renderLink (h, to, text, active, level) { return h('router-link', { props: { to, @@ -64,6 +64,9 @@ function renderLink (h, to, text, active) { class: { active, 'sidebar-link': true + }, + style: { + 'padding-left': level + 'rem' } }, text) } @@ -73,7 +76,7 @@ function renderChildren (h, children, path, route, maxDepth, depth = 1) { return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => { const active = isActive(route, path + '#' + c.slug) return h('li', { class: 'sidebar-sub-header' }, [ - renderLink(h, path + '#' + c.slug, c.title, active), + renderLink(h, path + '#' + c.slug, c.title, active, c.level - 1), renderChildren(h, c.children, path, route, maxDepth, depth + 1) ]) })) diff --git a/packages/docs/docs/theme/default-theme-config.md b/packages/docs/docs/theme/default-theme-config.md index a1d8b3c117..c24bf8b894 100644 --- a/packages/docs/docs/theme/default-theme-config.md +++ b/packages/docs/docs/theme/default-theme-config.md @@ -169,6 +169,17 @@ module.exports = { } ``` +### Extract Headers + While preparing the page, headers are extracted from the Markdown file and stored in `this.$page.headers`. By default, VuePress will extract `h2` and `h3` elements for you. + You can override the headers it pulls out in your `markdown` options. + ``` js +module.exports = { + markdown: { + extractHeaders: [ 'h2', 'h3', 'h4' ] + } +} +``` + ### Active Header Links By default, the nested header links and the hash in the URL are updated as the user scrolls to view the different sections of the page. This behavior can be disabled with the following theme config: