From b9950f3d3ce957f7a752d5770253175209930e52 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 3 Jul 2017 23:18:45 +0800 Subject: [PATCH 1/5] fix: The first lf following the pre and textarea shuold be ignored. --- src/compiler/parser/html-parser.js | 18 ++++++++++++++---- test/unit/modules/compiler/parser.spec.js | 3 +-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js index b7c2f1d0e92..34fcb9403ff 100644 --- a/src/compiler/parser/html-parser.js +++ b/src/compiler/parser/html-parser.js @@ -59,6 +59,9 @@ const decodingMap = { const encodedAttr = /&(?:lt|gt|quot|amp);/g const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g +const ignoreFirstLFTagList = makeMap('pre,textarea', true) +const isIgnoreFirstLf = (tag, html) => tag && ignoreFirstLFTagList(tag.toLowerCase()) && html[0] === '\n' + function decodeAttr (value, shouldDecodeNewlines) { const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr return value.replace(re, match => decodingMap[match]) @@ -75,6 +78,10 @@ export function parseHTML (html, options) { last = html // Make sure we're not in a plaintext content element like script/style if (!lastTag || !isPlainTextElement(lastTag)) { + // #5992 + if (isIgnoreFirstLf(lastTag, html)) { + advance(1) + } let textEnd = html.indexOf('<') if (textEnd === 0) { // Comment: @@ -152,16 +159,19 @@ export function parseHTML (html, options) { options.chars(text) } } else { - var stackedTag = lastTag.toLowerCase() - var reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(]*>)', 'i')) - var endTagLength = 0 - var rest = html.replace(reStackedTag, function (all, text, endTag) { + let endTagLength = 0 + const stackedTag = lastTag.toLowerCase() + const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(]*>)', 'i')) + const rest = html.replace(reStackedTag, function (all, text, endTag) { endTagLength = endTag.length if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') { text = text .replace(//g, '$1') .replace(//g, '$1') } + if (isIgnoreFirstLf(stackedTag, text)) { + text = text.substring(1) + } if (options.chars) { options.chars(text) } diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index 171faf6672f..c36d5dc2019 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -530,8 +530,7 @@ describe('parser', () => { expect(whitespace.children.length).toBe(1) expect(whitespace.children[0].type).toBe(3) // textarea is whitespace sensitive - expect(whitespace.children[0].text).toBe(` -

Test 1

+ expect(whitespace.children[0].text).toBe(`

Test 1

test2 `) From e7a5764aa3e8238b755ba1db86510f1c6c73e694 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 3 Jul 2017 23:26:08 +0800 Subject: [PATCH 2/5] test: add proper test case --- src/compiler/parser/html-parser.js | 2 +- test/unit/modules/compiler/parser.spec.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js index 34fcb9403ff..23432fbf66e 100644 --- a/src/compiler/parser/html-parser.js +++ b/src/compiler/parser/html-parser.js @@ -59,6 +59,7 @@ const decodingMap = { const encodedAttr = /&(?:lt|gt|quot|amp);/g const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g +// #5992 const ignoreFirstLFTagList = makeMap('pre,textarea', true) const isIgnoreFirstLf = (tag, html) => tag && ignoreFirstLFTagList(tag.toLowerCase()) && html[0] === '\n' @@ -78,7 +79,6 @@ export function parseHTML (html, options) { last = html // Make sure we're not in a plaintext content element like script/style if (!lastTag || !isPlainTextElement(lastTag)) { - // #5992 if (isIgnoreFirstLf(lastTag, html)) { advance(1) } diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index c36d5dc2019..c85530c7877 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -495,6 +495,21 @@ describe('parser', () => { expect(span.children[0].text).toBe(' ') }) + // #5992 + it('ignore the first LF in
 tag', function () {
+    const options = extend({}, baseOptions)
+    const ast = parse('
\nabc
\ndef
\n\nabc
', options) + const pre = ast.children[0] + expect(pre.children[0].type).toBe(3) + expect(pre.children[0].text).toBe('abc') + const text = ast.children[1] + expect(text.type).toBe(3) + expect(text.text).toBe('\ndef') + const pre2 = ast.children[2] + expect(pre2.children[0].type).toBe(3) + expect(pre2.children[0].text).toBe('\nabc') + }) + it('forgivingly handle < in plain text', () => { const options = extend({}, baseOptions) const ast = parse('

1 < 2 < 3

', options) From 992d902701baf120d136c4dd97e130b8e53408d7 Mon Sep 17 00:00:00 2001 From: defcc Date: Tue, 4 Jul 2017 08:40:33 +0800 Subject: [PATCH 3/5] refactor: remove useless toLowerCase check --- src/compiler/parser/html-parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js index 23432fbf66e..5b01bfaa11b 100644 --- a/src/compiler/parser/html-parser.js +++ b/src/compiler/parser/html-parser.js @@ -61,7 +61,7 @@ const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g // #5992 const ignoreFirstLFTagList = makeMap('pre,textarea', true) -const isIgnoreFirstLf = (tag, html) => tag && ignoreFirstLFTagList(tag.toLowerCase()) && html[0] === '\n' +const isIgnoreFirstLf = (tag, html) => tag && ignoreFirstLFTagList(tag) && html[0] === '\n' function decodeAttr (value, shouldDecodeNewlines) { const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr From 94b4eb78aabdd25e8fb8b6b13b7d8b29e5ffc958 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Jul 2017 21:38:04 +0800 Subject: [PATCH 4/5] Update html-parser.js --- src/compiler/parser/html-parser.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js index 5b01bfaa11b..670ee3ddf15 100644 --- a/src/compiler/parser/html-parser.js +++ b/src/compiler/parser/html-parser.js @@ -60,8 +60,8 @@ const encodedAttr = /&(?:lt|gt|quot|amp);/g const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g // #5992 -const ignoreFirstLFTagList = makeMap('pre,textarea', true) -const isIgnoreFirstLf = (tag, html) => tag && ignoreFirstLFTagList(tag) && html[0] === '\n' +const isIgnoreNewlineTag = makeMap('pre,textarea', true) +const shouldIgnoreFirstNewline = (tag, html) => tag && isIgnoreNewlineTag(tag) && html[0] === '\n' function decodeAttr (value, shouldDecodeNewlines) { const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr @@ -79,7 +79,7 @@ export function parseHTML (html, options) { last = html // Make sure we're not in a plaintext content element like script/style if (!lastTag || !isPlainTextElement(lastTag)) { - if (isIgnoreFirstLf(lastTag, html)) { + if (shouldIgnoreFirstNewline(lastTag, html)) { advance(1) } let textEnd = html.indexOf('<') @@ -169,8 +169,8 @@ export function parseHTML (html, options) { .replace(//g, '$1') .replace(//g, '$1') } - if (isIgnoreFirstLf(stackedTag, text)) { - text = text.substring(1) + if (shouldIgnoreFirstNewline(stackedTag, text)) { + text = text.slice(1) } if (options.chars) { options.chars(text) From 962b6140fce34899adb6efcc4b474a0f70a4f8b1 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Jul 2017 21:38:25 +0800 Subject: [PATCH 5/5] Update parser.spec.js --- test/unit/modules/compiler/parser.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index c85530c7877..71e032f15b9 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -496,7 +496,7 @@ describe('parser', () => { }) // #5992 - it('ignore the first LF in
 tag', function () {
+  it('ignore the first newline in 
 tag', function () {
     const options = extend({}, baseOptions)
     const ast = parse('
\nabc
\ndef
\n\nabc
', options) const pre = ast.children[0]