From 4c6a7e87493d61ad8c3383b1d63f82bb49ec37e8 Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 12 Nov 2017 00:07:58 +0800 Subject: [PATCH] fix(markdown): escape all emphasis-like text (#3246) * fix(markdown): escape all emphasis-like text * test: add test case --- src/printer-markdown.js | 20 +++++- .../__snapshots__/jsfmt.spec.js.snap | 72 +++++++++---------- .../__snapshots__/jsfmt.spec.js.snap | 4 ++ tests/markdown_word/escape.md | 2 + 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/printer-markdown.js b/src/printer-markdown.js index c2185ebb..960f1780 100644 --- a/src/printer-markdown.js +++ b/src/printer-markdown.js @@ -12,12 +12,18 @@ const align = docBuilders.align; const docPrinter = require("./doc-printer"); const printDocToString = docPrinter.printDocToString; const escapeStringRegexp = require("escape-string-regexp"); +const getCjkRegex = require("cjk-regex"); // http://spec.commonmark.org/0.25/#ascii-punctuation-character const asciiPunctuationPattern = escapeStringRegexp( "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" ); +const punctuationPattern = `(?:${[ + getCjkRegex.punctuations().source, + `[${asciiPunctuationPattern}]` +].join("|")})`; + const SINGLE_LINE_NODE_TYPES = [ "heading", "tableCell", @@ -86,8 +92,18 @@ function genericPrint(path, options, print) { return getAncestorNode(path, "inlineCode") ? node.value : node.value - .replace(/(^|[^\\])\*/g, "$1\\*") // escape all unescaped `*` and `_` - .replace(/\b(^|[^\\])_\b/g, "$1\\_"); // `1_2_3` is not considered emphasis + .replace(/[*]/g, "\\*") // escape all `*` + .replace( + new RegExp( + `(^|${punctuationPattern})(_+)|(_+)(${punctuationPattern}|$)`, + "g" + ), + (_, text1, underscore1, underscore2, text2) => + (underscore1 + ? `${text1}${underscore1}` + : `${underscore2}${text2}` + ).replace(/_/g, "\\_") + ); // escape all `_` except concating with non-punctuation, e.g. `1_2_3` is not considered emphasis case "whitespace": { const parentNode = path.getParentNode(); const index = parentNode.children.indexOf(node); diff --git a/tests/markdown_spec/__snapshots__/jsfmt.spec.js.snap b/tests/markdown_spec/__snapshots__/jsfmt.spec.js.snap index 2336f30f..8236588a 100644 --- a/tests/markdown_spec/__snapshots__/jsfmt.spec.js.snap +++ b/tests/markdown_spec/__snapshots__/jsfmt.spec.js.snap @@ -123,7 +123,7 @@ exports[`example-14.md 1`] = ` ** __ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- \\** _\\_ +-- \\*\\* \\_\\_ `; @@ -155,7 +155,7 @@ exports[`example-17.md 1`] = ` Foo *** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Foo \\**\\* +Foo \\*\\*\\* `; @@ -3304,7 +3304,7 @@ exports[`example-284.md 1`] = ` exports[`example-285.md 1`] = ` \\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\\`\\{\\|\\}\\~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^_\\\`\\{\\|\\}\\~ +\\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\\`\\{\\|\\}\\~ `; @@ -3698,7 +3698,7 @@ exports[`example-336.md 1`] = ` exports[`example-337.md 1`] = ` aa_"bb"_cc ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -aa_"bb"_cc +aa\\_"bb"\\_cc `; @@ -3712,7 +3712,7 @@ foo-_(bar)_ exports[`example-339.md 1`] = ` _foo* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo\\* +\\_foo\\* `; @@ -3762,21 +3762,21 @@ _foo bar _ exports[`example-346.md 1`] = ` _(_foo) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\_(_foo) +\\_(\\_foo) `; exports[`example-347.md 1`] = ` _(_foo_)_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_(_foo_)_ +_(\\_foo_)\\_ `; exports[`example-348.md 1`] = ` _foo_bar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo_bar +\\_foo_bar `; @@ -4010,21 +4010,21 @@ _foo **bar** baz_ exports[`example-381.md 1`] = ` _foo _bar_ baz_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo _bar_ baz_ +_foo \\_bar_ baz\\_ `; exports[`example-382.md 1`] = ` __foo_ bar_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\__foo_ bar_ +\\__foo_ bar\\_ `; exports[`example-383.md 1`] = ` *foo *bar** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*foo *bar\\** +*foo *bar\\*\\* `; @@ -4073,14 +4073,14 @@ exports[`example-390.md 1`] = ` exports[`example-391.md 1`] = ` ** is not an empty emphasis ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\** is not an empty emphasis +\\*\\* is not an empty emphasis `; exports[`example-392.md 1`] = ` **** is not an empty strong emphasis ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\**\\** is not an empty strong emphasis +\\*\\*\\*\\* is not an empty strong emphasis `; @@ -4116,14 +4116,14 @@ __foo __bar__ baz__ exports[`example-397.md 1`] = ` ____foo__ bar__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\_**_foo** bar__ +\\_**\\_foo** bar\\_\\_ `; exports[`example-398.md 1`] = ` **foo **bar**** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**foo **bar\\**\\** +**foo **bar\\*\\*\\*\\* `; @@ -4173,28 +4173,28 @@ exports[`example-404.md 1`] = ` exports[`example-405.md 1`] = ` __ is not an empty emphasis ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_\\_ is not an empty emphasis +\\_\\_ is not an empty emphasis `; exports[`example-406.md 1`] = ` ____ is not an empty strong emphasis ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -____ is not an empty strong emphasis +\\_\\_\\_\\_ is not an empty strong emphasis `; exports[`example-407.md 1`] = ` foo *** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -foo \\**\\* +foo \\*\\*\\* `; exports[`example-408.md 1`] = ` foo *\\** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -foo \\**\\* +foo \\*\\*\\* `; @@ -4229,7 +4229,7 @@ exports[`example-413.md 1`] = ` exports[`example-414.md 1`] = ` *foo** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\*foo\\** +\\*foo\\*\\* `; @@ -4250,21 +4250,21 @@ exports[`example-417.md 1`] = ` exports[`example-418.md 1`] = ` *foo**** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\*foo\\**\\** +\\*foo\\*\\*\\*\\* `; exports[`example-419.md 1`] = ` foo ___ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -foo ___ +foo \\_\\_\\_ `; exports[`example-420.md 1`] = ` foo _\\__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -foo ___ +foo \\_\\_\\_ `; @@ -4306,35 +4306,35 @@ __foo_ exports[`example-426.md 1`] = ` _foo__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo__ +\\_foo\\_\\_ `; exports[`example-427.md 1`] = ` ___foo__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**_foo** +**\\_foo** `; exports[`example-428.md 1`] = ` ____foo_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\____foo_ +\\__\\_\\_foo_ `; exports[`example-429.md 1`] = ` __foo___ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**foo_** +**foo\\_** `; exports[`example-430.md 1`] = ` _foo____ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo____ +\\_foo\\_\\_\\_\\_ `; @@ -4369,21 +4369,21 @@ _*foo*_ exports[`example-435.md 1`] = ` ****foo**** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\***\\*foo\\**** +\\***\\*foo\\*\\*** `; exports[`example-436.md 1`] = ` ____foo____ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\\_**_foo__** +\\_**\\_foo\\_\\_** `; exports[`example-437.md 1`] = ` ******foo****** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**\\****foo**\\**** +**\\*\\***foo**\\*\\*** `; @@ -4404,7 +4404,7 @@ _____foo_____ exports[`example-440.md 1`] = ` *foo _bar* baz_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_foo _bar_ baz_ +_foo \\_bar_ baz\\_ `; @@ -4418,14 +4418,14 @@ exports[`example-441.md 1`] = ` exports[`example-442.md 1`] = ` *foo __bar *baz bim__ bam* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*foo __bar *baz bim__ bam\\* +*foo \\_\\_bar *baz bim\\_\\_ bam\\* `; exports[`example-443.md 1`] = ` **foo **bar baz** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**foo **bar baz\\** +**foo **bar baz\\*\\* `; @@ -4481,7 +4481,7 @@ _a \`_\`\\* exports[`example-451.md 1`] = ` _a \`_\`_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -_a \`_\`_ +_a \`_\`\\_ `; @@ -5652,7 +5652,7 @@ Foo exports[`example-581.md 1`] = ` <33> <__> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -<33> <_\\_> +<33> <\\_\\_> `; diff --git a/tests/markdown_word/__snapshots__/jsfmt.spec.js.snap b/tests/markdown_word/__snapshots__/jsfmt.spec.js.snap index e6214eec..a9d669bf 100644 --- a/tests/markdown_word/__snapshots__/jsfmt.spec.js.snap +++ b/tests/markdown_word/__snapshots__/jsfmt.spec.js.snap @@ -16,6 +16,8 @@ asd & asd „ 123 123*123*123 123 * 123 * 123 + +## 类的 prototype 属性和\\_\\_proto\\_\\_属性 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hello \\* world \\_ ~~ ya @@ -33,4 +35,6 @@ asd & asd „ 123 123 _ 123 _ 123 +## 类的 prototype 属性和 \\_\\_proto\\_\\_ 属性 + `; diff --git a/tests/markdown_word/escape.md b/tests/markdown_word/escape.md index 170d2643..e4bc5601 100644 --- a/tests/markdown_word/escape.md +++ b/tests/markdown_word/escape.md @@ -13,3 +13,5 @@ asd & asd „ 123 123*123*123 123 * 123 * 123 + +## 类的 prototype 属性和\_\_proto\_\_属性