From 362601084913baa3ffa422a0bb4dd6ce9ec3b9a5 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 3 Jun 2018 03:41:54 +0800 Subject: [PATCH 1/3] feat: support headers-badge --- docs/guide/markdown.md | 2 +- lib/app/app.js | 2 ++ lib/default-theme/Badge.vue | 30 +++++++++++++++++++++ lib/default-theme/styles/custom-blocks.styl | 2 ++ lib/default-theme/styles/theme.styl | 1 + lib/default-theme/styles/toc.styl | 3 +++ lib/markdown/index.js | 7 +++-- lib/util/index.js | 10 +++---- lib/util/parseHeaders.js | 24 +++++++++++------ lib/util/shared.js | 7 +++++ 10 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 lib/default-theme/Badge.vue create mode 100644 lib/default-theme/styles/toc.styl create mode 100644 lib/util/shared.js diff --git a/docs/guide/markdown.md b/docs/guide/markdown.md index 98513bd585..74bc6b9957 100644 --- a/docs/guide/markdown.md +++ b/docs/guide/markdown.md @@ -224,7 +224,7 @@ export default { } ``` -## Import Code Snippets +## Import Code Snippets **Input** diff --git a/lib/app/app.js b/lib/app/app.js index d8da7dccc0..1f64553e8a 100644 --- a/lib/app/app.js +++ b/lib/app/app.js @@ -2,6 +2,7 @@ import Vue from 'vue' import Router from 'vue-router' import Content from './Content' import OutboundLink from '../default-theme/OutboundLink.vue' +import Badge from '../default-theme/Badge.vue' import ClientOnly from './ClientOnly' import dataMixin from './dataMixin' import store from './store' @@ -30,6 +31,7 @@ Vue.mixin(dataMixin(siteData)) // component for rendering markdown content and setting title etc. Vue.component('Content', Content) Vue.component('OutboundLink', OutboundLink) +Vue.component('Badge', Badge) // component for client-only content Vue.component('ClientOnly', ClientOnly) diff --git a/lib/default-theme/Badge.vue b/lib/default-theme/Badge.vue new file mode 100644 index 0000000000..1a41d7e772 --- /dev/null +++ b/lib/default-theme/Badge.vue @@ -0,0 +1,30 @@ + + + diff --git a/lib/default-theme/styles/custom-blocks.styl b/lib/default-theme/styles/custom-blocks.styl index 3ccc2df2a2..c017c3f0f3 100644 --- a/lib/default-theme/styles/custom-blocks.styl +++ b/lib/default-theme/styles/custom-blocks.styl @@ -1,3 +1,5 @@ +@require "./config.styl" + .custom-block .custom-block-title font-weight 600 diff --git a/lib/default-theme/styles/theme.styl b/lib/default-theme/styles/theme.styl index a8c513cd5f..a733861fa6 100644 --- a/lib/default-theme/styles/theme.styl +++ b/lib/default-theme/styles/theme.styl @@ -4,6 +4,7 @@ @require './custom-blocks' @require './arrow' @require './wrapper' +@require './toc' html, body padding 0 diff --git a/lib/default-theme/styles/toc.styl b/lib/default-theme/styles/toc.styl new file mode 100644 index 0000000000..d3e71069ba --- /dev/null +++ b/lib/default-theme/styles/toc.styl @@ -0,0 +1,3 @@ +.table-of-contents + .badge + vertical-align middle diff --git a/lib/markdown/index.js b/lib/markdown/index.js index 370cee617f..2e7e6ff64f 100644 --- a/lib/markdown/index.js +++ b/lib/markdown/index.js @@ -8,14 +8,16 @@ const convertRouterLink = require('./link') const containers = require('./containers') const snippet = require('./snippet') const emoji = require('markdown-it-emoji') +const sup = require('markdown-it-sup') const anchor = require('markdown-it-anchor') const toc = require('markdown-it-table-of-contents') const _slugify = require('./slugify') -const parseHeaders = require('../util/parseHeaders') +const { parseHeaders, removeTailHtml } = require('../util/parseHeaders') +const { compose } = require('../util/shared') module.exports = ({ markdown = {}} = {}) => { // allow user config slugify - const slugify = markdown.slugify || _slugify + const slugify = markdown.slugify || compose(removeTailHtml, _slugify) const md = require('markdown-it')({ html: true, @@ -32,6 +34,7 @@ module.exports = ({ markdown = {}} = {}) => { }, markdown.externalLinks)) .use(hoistScriptStyle) .use(containers) + .use(sup) // 3rd party plugins .use(emoji) diff --git a/lib/util/index.js b/lib/util/index.js index 12caf0e7ac..8918ee3e6b 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -1,4 +1,4 @@ -const parseHeaders = require('./parseHeaders') +const { deeplyParseHeaders } = require('./parseHeaders') exports.normalizeHeadTag = function (tag) { if (typeof tag === 'string') { @@ -32,11 +32,11 @@ exports.inferTitle = function (frontmatter) { return 'Home' } if (frontmatter.data.title) { - return parseHeaders(frontmatter.data.title) + return deeplyParseHeaders(frontmatter.data.title) } const match = frontmatter.content.trim().match(/^#+\s+(.*)/) if (match) { - return parseHeaders(match[1]) + return deeplyParseHeaders(match[1]) } } @@ -68,11 +68,11 @@ exports.extractHeaders = function (content, include = [], md) { const res = [] tokens.forEach((t, i) => { if (t.type === 'heading_open' && include.includes(t.tag)) { - const title = parseHeaders(tokens[i + 1].content) + const title = tokens[i + 1].content const slug = t.attrs.find(([name]) => name === 'id')[1] res.push({ level: parseInt(t.tag.slice(1), 10), - title, + title: deeplyParseHeaders(title), slug: slug || md.slugify(title) }) } diff --git a/lib/util/parseHeaders.js b/lib/util/parseHeaders.js index 2a2c4fee4c..3837eeba39 100644 --- a/lib/util/parseHeaders.js +++ b/lib/util/parseHeaders.js @@ -1,3 +1,5 @@ +const { compose } = require('./shared') + const parseEmojis = str => { const emojiData = require('markdown-it-emoji/lib/data/full.json') return String(str).replace(/:(.+?):/g, (placeholder, key) => emojiData[key] || placeholder) @@ -17,13 +19,19 @@ const removeMarkdownToken = str => String(str) .replace(/\*(.*)\*/, '$1') // * .replace(/_(.*)_/, '$1') // _ -// put here to avoid circular references -const compose = (...processors) => { - if (processors.length === 0) return input => input - if (processors.length === 1) return processors[0] - return processors.reduce((prev, next) => { - return (...args) => next(prev(...args)) - }) +exports.removeTailHtml = (str) => { + return String(str).replace(/<.*>\s*$/g, '') } -module.exports = compose(unescapeHtml, parseEmojis, removeMarkdownToken) +// only remove some md tokens. +exports.parseHeaders = compose( + unescapeHtml, + parseEmojis, + removeMarkdownToken +) + +// also clean html in headers. +exports.deeplyParseHeaders = compose( + exports.parseHeaders, + exports.removeTailHtml +) diff --git a/lib/util/shared.js b/lib/util/shared.js new file mode 100644 index 0000000000..023f63bd1b --- /dev/null +++ b/lib/util/shared.js @@ -0,0 +1,7 @@ +exports.compose = (...processors) => { + if (processors.length === 0) return input => input + if (processors.length === 1) return processors[0] + return processors.reduce((prev, next) => { + return (...args) => next(prev(...args)) + }) +} From a1abc302e39b3dd85f006bce47f2d05f81e16a1b Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 3 Jun 2018 04:11:03 +0800 Subject: [PATCH 2/3] chore: tweaks --- lib/default-theme/styles/custom-blocks.styl | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/default-theme/styles/custom-blocks.styl b/lib/default-theme/styles/custom-blocks.styl index c017c3f0f3..3ccc2df2a2 100644 --- a/lib/default-theme/styles/custom-blocks.styl +++ b/lib/default-theme/styles/custom-blocks.styl @@ -1,5 +1,3 @@ -@require "./config.styl" - .custom-block .custom-block-title font-weight 600 From ee112daa3e8f7bad00fd7babc9c6a372e87eb211 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 3 Jun 2018 04:33:37 +0800 Subject: [PATCH 3/3] fix: CI failed --- lib/markdown/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/markdown/index.js b/lib/markdown/index.js index 2e7e6ff64f..06779ac5ef 100644 --- a/lib/markdown/index.js +++ b/lib/markdown/index.js @@ -8,7 +8,6 @@ const convertRouterLink = require('./link') const containers = require('./containers') const snippet = require('./snippet') const emoji = require('markdown-it-emoji') -const sup = require('markdown-it-sup') const anchor = require('markdown-it-anchor') const toc = require('markdown-it-table-of-contents') const _slugify = require('./slugify') @@ -34,7 +33,6 @@ module.exports = ({ markdown = {}} = {}) => { }, markdown.externalLinks)) .use(hoistScriptStyle) .use(containers) - .use(sup) // 3rd party plugins .use(emoji)