From 6140e7e19ad8acbf791eb09e4b5e907ba3f290f7 Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Fri, 11 May 2018 22:30:09 +0800 Subject: [PATCH 1/6] feat: allow no v-pre on code blocks --- docs/guide/using-vue.md | 32 ++++++++++++++++++++++++++++++++ docs/zh/guide/using-vue.md | 32 ++++++++++++++++++++++++++++++++ lib/markdown/highlight.js | 18 +++++++++++++----- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/docs/guide/using-vue.md b/docs/guide/using-vue.md index 87703f5d60..30264fb49f 100644 --- a/docs/guide/using-vue.md +++ b/docs/guide/using-vue.md @@ -76,6 +76,38 @@ The compiled component does not have any private data but does have access to th } ``` +### Interpolation in Code Blocks + +By default, Vuepress will add `v-pre` directive to the code block to avoid it being compiled by Vue. If you really want to use interpolation in code blocks, add `:v` after the language identifier, or just use `:v` as the language identifier. For example: + +**Input** + +```` md +``` vue:v +{{ 1 + 1 }} +``` +```` + +```` md +``` :v +{{ 1 + 2 }} +``` +```` + +**Output** + +``` vue:v +{{ 1 + 1 }} +``` + +``` :v +{{ 1 + 2 }} +``` + +::: warning IMPORTANT +For some language identifiers, the highlighter will add extra `` tag around `{` and `}`, in which cases `:v` won't work. Suggest to use `:v` after `text`, `md`, `vue`, `html` or use it alone. +::: + ## Escaping By default, fenced code blocks are automatically wrapped with `v-pre`. If you want to display raw mustaches or Vue-specific syntax inside inline code snippets or plain text, you need to wrap a paragraph with the `v-pre` custom container: diff --git a/docs/zh/guide/using-vue.md b/docs/zh/guide/using-vue.md index 3a9dbca08c..1c9fea3d05 100644 --- a/docs/zh/guide/using-vue.md +++ b/docs/zh/guide/using-vue.md @@ -76,6 +76,38 @@ export default { } ``` +### 在代码块中插值 + +Vuepress默认会在代码块添加`v-pre`指令,使其避免被Vue编译。如果你确实需要在代码块中使用插值,可以在代码块的语言标记后面添加`:v`,或者直接把`:v`作为语言标记。例如: + +**Input** + +```` md +``` vue:v +{{ 1 + 1 }} +``` +```` + +```` md +``` :v +{{ 1 + 2 }} +``` +```` + +**Output** + +``` vue:v +{{ 1 + 1 }} +``` + +``` :v +{{ 1 + 2 }} +``` + +::: warning 重要! +Markdown在解析某些语言的代码块时,为了支持代码高亮,会在`{`和`}`外添加额外的``标签,这将导致Vue的模板插值失效。建议仅在`text`, `md`, `vue`, `html`等语言后使用`:v`,或单独使用它。 +::: + ## Escaping 默认情况下,块级 (block) 的代码块将会被自动包裹在 `v-pre` 中。如果你想要在内联 (inline) 的代码块或者普通文本中显示原始的大括号,或者一些 Vue 特定的语法,你需要使用自定义容器 `v-pre` 来包裹: diff --git a/lib/markdown/highlight.js b/lib/markdown/highlight.js index ae25350361..97434be1dc 100644 --- a/lib/markdown/highlight.js +++ b/lib/markdown/highlight.js @@ -3,19 +3,27 @@ const prism = require('prismjs') const loadLanguages = require('prismjs/components/index') const escapeHtml = require('escape-html') +const vPreRE = /^(.*):v$/ + // required to make embedded highlighting work... loadLanguages(['markup', 'css', 'javascript']) -function wrap (code, lang) { +function wrap (code, lang, useVPre = true) { if (lang === 'text') { code = escapeHtml(code) } - return `
${code}
` + const vPreAttr = useVPre ? 'v-pre' : '' + return `
${code}
` } module.exports = (str, lang) => { + const vPreMatch = lang.match(vPreRE) + const useVPre = vPreMatch === null + if (!useVPre) { + lang = vPreMatch[1] + } if (!lang) { - return wrap(str, 'text') + return wrap(str, 'text', useVPre) } lang = lang.toLowerCase() const rawLang = lang @@ -34,7 +42,7 @@ module.exports = (str, lang) => { } if (prism.languages[lang]) { const code = prism.highlight(str, prism.languages[lang], lang) - return wrap(code, rawLang) + return wrap(code, rawLang, useVPre) } - return wrap(str, 'text') + return wrap(str, 'text', useVPre) } From 697ea1c1039878a9105899865147998f7ca6bc22 Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Fri, 11 May 2018 22:38:51 +0800 Subject: [PATCH 2/6] docs: tweaks --- docs/guide/using-vue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/using-vue.md b/docs/guide/using-vue.md index 30264fb49f..40f82c4607 100644 --- a/docs/guide/using-vue.md +++ b/docs/guide/using-vue.md @@ -78,7 +78,7 @@ The compiled component does not have any private data but does have access to th ### Interpolation in Code Blocks -By default, Vuepress will add `v-pre` directive to the code block to avoid it being compiled by Vue. If you really want to use interpolation in code blocks, add `:v` after the language identifier, or just use `:v` as the language identifier. For example: +By default, Vuepress will add `v-pre` directive to code blocks to avoid it being compiled by Vue. If you really want to use interpolation in code blocks, add `:v` after the language identifier, or just use `:v` as the language identifier. For example: **Input** From 29b46d97e79b9bd2bb1d771ea6b765bcb4d05b84 Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Wed, 1 Aug 2018 16:08:01 +0800 Subject: [PATCH 3/6] feat: use {no-v-pre} to disable vue-pre in code blocks --- lib/markdown/highlight.js | 43 ++++++++++++++++++++++++++++---------- lib/markdown/preWrapper.js | 10 +++++++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/markdown/highlight.js b/lib/markdown/highlight.js index 4da5951ad1..d349d1ef04 100644 --- a/lib/markdown/highlight.js +++ b/lib/markdown/highlight.js @@ -4,29 +4,41 @@ const loadLanguages = require('prismjs/components/index') const escapeHtml = require('escape-html') const logger = require('../util/logger') -const vPreRE = /^(.*):v$/ +const noVPreRE = /^(.*){no-v-pre}$/ + +// highlight will be disabled with {no-v-pre} except for these languages +const highlightableLanguagesWithNoVPre = [ + 'markup', + 'markdown' +] // required to make embedded highlighting work... loadLanguages(['markup', 'css', 'javascript']) -function wrap (code, lang, useVPre = true) { +function wrap (code, lang, noVPre = false) { if (lang === 'text') { code = escapeHtml(code) } - const vPreAttr = useVPre ? 'v-pre' : '' + const vPreAttr = noVPre ? '' : 'v-pre' return `
${code}
` } module.exports = (str, lang) => { - const vPreMatch = lang.match(vPreRE) - const useVPre = vPreMatch === null - if (!useVPre) { - lang = vPreMatch[1] + // check if {no-v-pre} appears + const noVPreMatch = lang.match(noVPreRE) + const noVPre = noVPreMatch !== null + if (noVPre) { + lang = noVPreMatch[1] } + + // normalize the language name for prism + lang = lang.toLowerCase() + + // if no language is specified, treat as 'text' if (!lang) { - return wrap(str, 'text', useVPre) + return wrap(str, 'text', noVPre) } - lang = lang.toLowerCase() + const rawLang = lang if (lang === 'vue' || lang === 'html') { lang = 'markup' @@ -40,6 +52,13 @@ module.exports = (str, lang) => { if (lang === 'py') { lang = 'python' } + + // if the language is not supported highlighting with {no-v-pre} + if (noVPre && !highlightableLanguagesWithNoVPre.includes(lang)) { + return wrap(str, 'text', noVPre) + } + + // try to highlighting the code if (!prism.languages[lang]) { try { loadLanguages([lang]) @@ -49,7 +68,9 @@ module.exports = (str, lang) => { } if (prism.languages[lang]) { const code = prism.highlight(str, prism.languages[lang], lang) - return wrap(code, rawLang, useVPre) + return wrap(code, rawLang, noVPre) } - return wrap(str, 'text', useVPre) + + // if the language is not supported by prism, treat as 'text' + return wrap(str, 'text', noVPre) } diff --git a/lib/markdown/preWrapper.js b/lib/markdown/preWrapper.js index 8f1b1d7396..9e650e841a 100644 --- a/lib/markdown/preWrapper.js +++ b/lib/markdown/preWrapper.js @@ -1,19 +1,25 @@ // markdown-it plugin for wrapping
 ... 
. // -// If your plugin was chained before preWrapper, you can add additional eleemnt directly. +// If your plugin was chained before preWrapper, you can add additional element directly. // If your plugin was chained after preWrapper, you can use these slots: // 1. // 2. // 3. // 4. +const noVPreRE = /^(.*){no-v-pre}$/ + module.exports = md => { const fence = md.renderer.rules.fence md.renderer.rules.fence = (...args) => { const [tokens, idx] = args const token = tokens[idx] const rawCode = fence(...args) - return `
` + + let lang = token.info.replace(noVPreRE, '$1').trim() + if (!lang) { + lang = 'text' + } + return `
` + `${rawCode}
` } } From 369e2ec3422c5725a356f2bf21981b6efa0ebbf7 Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Wed, 1 Aug 2018 16:24:44 +0800 Subject: [PATCH 4/6] docs: add no-v-pre --- docs/guide/using-vue.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/guide/using-vue.md b/docs/guide/using-vue.md index aa0f1444ee..f02b9be7d7 100644 --- a/docs/guide/using-vue.md +++ b/docs/guide/using-vue.md @@ -78,34 +78,39 @@ The compiled component does not have any private data but does have access to th ### Interpolation in Code Blocks -By default, Vuepress will add `v-pre` directive to code blocks to avoid it being compiled by Vue. If you really want to use interpolation in code blocks, add `:v` after the language identifier, or just use `:v` as the language identifier. For example: +By default, Vuepress will add `v-pre` directive to code blocks to avoid it being compiled by Vue. If you really want to use interpolation in code blocks, add `{no-v-pre}` after the language identifier, or just use `{no-v-pre}` as the language identifier. For example: **Input** ```` md -``` vue:v -{{ 1 + 1 }} +``` vue{no-v-pre} +
+ Current Time: {{ (new Date()).toLocaleString() }} +
``` ```` ```` md -``` :v +``` {no-v-pre} {{ 1 + 2 }} ``` ```` **Output** -``` vue:v -{{ 1 + 1 }} +``` vue{no-v-pre} +
+ Current Time: {{ (new Date()).toUTCString() }} +
``` -``` :v +``` {no-v-pre} {{ 1 + 2 }} ``` ::: warning IMPORTANT -For some language identifiers, the highlighter will add extra `` tag around `{` and `}`, in which cases `:v` won't work. Suggest to use `:v` after `text`, `md`, `vue`, `html` or use it alone. +For some languages, the highlighter will add extra `` tag around `{` and `}`, in which cases `{no-v-pre}` won't work. If you use `{no-v-pre}` with those languages, Vuepress will disable syntax highlighting when compiling that code block. If you need syntax highlighting anyway, you have to process it youself in your client code for now. +Currently, `{no-v-pre}` and syntax highlighting only works with `md`, `markdown`, `vue`, `html`, `markup`. ::: ## Escaping From 0c77c13c689651ad5a6a5452d81a211f0d7d708b Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Wed, 1 Aug 2018 16:25:21 +0800 Subject: [PATCH 5/6] test: add no-v-pre --- test/markdown/__snapshots__/noVPre.spec.js.snap | 6 ++++++ test/markdown/fragments/code-no-v-pre.md | 3 +++ test/markdown/noVPre.spec.js | 12 ++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 test/markdown/__snapshots__/noVPre.spec.js.snap create mode 100644 test/markdown/fragments/code-no-v-pre.md create mode 100644 test/markdown/noVPre.spec.js diff --git a/test/markdown/__snapshots__/noVPre.spec.js.snap b/test/markdown/__snapshots__/noVPre.spec.js.snap new file mode 100644 index 0000000000..97c0aba4ce --- /dev/null +++ b/test/markdown/__snapshots__/noVPre.spec.js.snap @@ -0,0 +1,6 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`no-v-pre should not have v-pre with {no-v-pre} 1`] = ` +
{{ 1 + 1 }}
+
+`; diff --git a/test/markdown/fragments/code-no-v-pre.md b/test/markdown/fragments/code-no-v-pre.md new file mode 100644 index 0000000000..4c706e0047 --- /dev/null +++ b/test/markdown/fragments/code-no-v-pre.md @@ -0,0 +1,3 @@ +``` vue{no-v-pre} +{{ 1 + 1 }} +``` diff --git a/test/markdown/noVPre.spec.js b/test/markdown/noVPre.spec.js new file mode 100644 index 0000000000..5eaaa1727d --- /dev/null +++ b/test/markdown/noVPre.spec.js @@ -0,0 +1,12 @@ +import { Md, getFragment } from './util' +import highlight from '@/markdown/highlight.js' + +const md = Md().set({ highlight }) + +describe('no-v-pre', () => { + test('should not have v-pre with {no-v-pre}', async () => { + const input = await getFragment('code-no-v-pre') + const output = md.render(input) + expect(output).toMatchSnapshot() + }) +}) From ab2182d1c566f719913615d1d5e3a2692add5598 Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Wed, 1 Aug 2018 16:41:01 +0800 Subject: [PATCH 6/6] docs: refine the docs --- docs/guide/using-vue.md | 8 ++++---- docs/zh/guide/using-vue.md | 25 +++++++++++++++---------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/guide/using-vue.md b/docs/guide/using-vue.md index f02b9be7d7..6ea43a2f62 100644 --- a/docs/guide/using-vue.md +++ b/docs/guide/using-vue.md @@ -85,14 +85,14 @@ By default, Vuepress will add `v-pre` directive to code blocks to avoid it being ```` md ``` vue{no-v-pre}
- Current Time: {{ (new Date()).toLocaleString() }} + One plus two equals: {{ 1 + 2 }}
``` ```` ```` md ``` {no-v-pre} -{{ 1 + 2 }} +One plus two equals: {{ 1 + 2 }} ``` ```` @@ -100,12 +100,12 @@ By default, Vuepress will add `v-pre` directive to code blocks to avoid it being ``` vue{no-v-pre}
- Current Time: {{ (new Date()).toUTCString() }} + One plus two equals: {{ 1 + 2 }}
``` ``` {no-v-pre} -{{ 1 + 2 }} +One plus two equals: {{ 1 + 2 }} ``` ::: warning IMPORTANT diff --git a/docs/zh/guide/using-vue.md b/docs/zh/guide/using-vue.md index 85e821e599..fde0f0fe59 100644 --- a/docs/zh/guide/using-vue.md +++ b/docs/zh/guide/using-vue.md @@ -78,34 +78,39 @@ export default { ### 在代码块中插值 -Vuepress默认会在代码块添加`v-pre`指令,使其避免被Vue编译。如果你确实需要在代码块中使用插值,可以在代码块的语言标记后面添加`:v`,或者直接把`:v`作为语言标记。例如: +Vuepress默认会在代码块添加`v-pre`指令,使其避免被Vue编译。如果你确实需要在代码块中使用插值,可以在代码块的语言标记后面添加`{no-v-pre}`,或者直接把`{no-v-pre}`作为语言标记。例如: **Input** ```` md -``` vue:v -{{ 1 + 1 }} +``` vue{no-v-pre} +
+ 一加二等于: {{ 1 + 2 }} +
``` ```` ```` md -``` :v -{{ 1 + 2 }} +``` {no-v-pre} +一加二等于:{{ 1 + 2 }} ``` ```` **Output** -``` vue:v -{{ 1 + 1 }} +``` vue{no-v-pre} +
+ 一加二等于: {{ 1 + 2 }} +
``` -``` :v -{{ 1 + 2 }} +``` {no-v-pre} +一加二等于:{{ 1 + 2 }} ``` ::: warning 重要! -Markdown在解析某些语言的代码块时,为了支持代码高亮,会在`{`和`}`外添加额外的``标签,这将导致Vue的模板插值失效。建议仅在`text`, `md`, `vue`, `html`等语言后使用`:v`,或单独使用它。 +Markdown在解析某些语言的代码块时,为了支持代码高亮,会在`{`和`}`外添加额外的``标签,这将导致Vue的模板插值失效。如果你在这些语言的代码块上使用`{no-v-pre}`,Vuepress默认会在解析代码块时禁用代码高亮。如果你一定要在这些语言中使用模板插值和代码高亮的话,你需要在客户端代码中进行额外的代码高亮处理。 +目前,`{no-v-pre}`和代码高亮可以在这些语言中共同使用:`md`, `markdown`, `vue`, `html`, `markup` ::: ## Escaping