From cfd73c2386623341fdbb3ac636c4baf84ea89c2c Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 26 Oct 2017 16:01:12 +0200 Subject: [PATCH] fix: handle encoded tabs and newlines in attributes for Chrome a[href] and IE/Edge fix #6828, fix #6916 --- flow/compiler.js | 3 ++- src/compiler/parser/html-parser.js | 13 +++++++------ src/compiler/parser/index.js | 1 + src/platforms/web/entry-runtime-with-compiler.js | 3 ++- src/platforms/web/util/compat.js | 16 +++++++++------- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/flow/compiler.js b/flow/compiler.js index 89473789b00..a5ebc5f3862 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -14,7 +14,8 @@ declare type CompilerOptions = { preserveWhitespace?: boolean; isFromDOM?: boolean; shouldDecodeTags?: boolean; - shouldDecodeNewlines?: boolean; + shouldDecodeNewlines?: boolean; + shouldDecodeNewlinesForHref?: boolean; // for ssr optimization compiler scopeId?: string; diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js index f9f78d5ccf8..86955e0e7ab 100644 --- a/src/compiler/parser/html-parser.js +++ b/src/compiler/parser/html-parser.js @@ -39,10 +39,11 @@ const decodingMap = { '>': '>', '"': '"', '&': '&', - ' ': '\n' + ' ': '\n', + ' ': '\t' } const encodedAttr = /&(?:lt|gt|quot|amp);/g -const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g +const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g // #5992 const isIgnoreNewlineTag = makeMap('pre,textarea', true) @@ -233,12 +234,12 @@ export function parseHTML (html, options) { if (args[5] === '') { delete args[5] } } const value = args[3] || args[4] || args[5] || '' + const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' + ? options.shouldDecodeNewlinesForHref + : options.shouldDecodeNewlines attrs[i] = { name: args[1], - value: decodeAttr( - value, - options.shouldDecodeNewlines - ) + value: decodeAttr(value, shouldDecodeNewlines) } } diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index ceedce70aef..cba12d1cd47 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -107,6 +107,7 @@ export function parse ( isUnaryTag: options.isUnaryTag, canBeLeftOpenTag: options.canBeLeftOpenTag, shouldDecodeNewlines: options.shouldDecodeNewlines, + shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref, shouldKeepComment: options.comments, start (tag, attrs, unary) { // check namespace. diff --git a/src/platforms/web/entry-runtime-with-compiler.js b/src/platforms/web/entry-runtime-with-compiler.js index 5ca67b6e8e2..1ebc102df71 100644 --- a/src/platforms/web/entry-runtime-with-compiler.js +++ b/src/platforms/web/entry-runtime-with-compiler.js @@ -6,8 +6,8 @@ import { mark, measure } from 'core/util/perf' import Vue from './runtime/index' import { query } from './util/index' -import { shouldDecodeNewlines } from './util/compat' import { compileToFunctions } from './compiler/index' +import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat' const idToTemplate = cached(id => { const el = query(id) @@ -64,6 +64,7 @@ Vue.prototype.$mount = function ( const { render, staticRenderFns } = compileToFunctions(template, { shouldDecodeNewlines, + shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, this) diff --git a/src/platforms/web/util/compat.js b/src/platforms/web/util/compat.js index 144d68afb6d..d95759cce31 100644 --- a/src/platforms/web/util/compat.js +++ b/src/platforms/web/util/compat.js @@ -3,12 +3,14 @@ import { inBrowser } from 'core/util/index' // check whether current browser encodes a char inside attribute values -function shouldDecode (content: string, encoded: string): boolean { - const div = document.createElement('div') - div.innerHTML = `
` - return div.innerHTML.indexOf(encoded) > 0 +let div +function getShouldDecode (href: boolean): boolean { + div = div || document.createElement('div') + div.innerHTML = href ? `` : `
` + return div.innerHTML.indexOf(' ') > 0 } -// #3663 -// IE encodes newlines inside attribute values while other browsers don't -export const shouldDecodeNewlines = inBrowser ? shouldDecode('\n', ' ') : false +// #3663: IE encodes newlines inside attribute values while other browsers don't +export const shouldDecodeNewlines = inBrowser ? getShouldDecode(false) : false +// #6828: chrome encodes content in a[href] +export const shouldDecodeNewlinesForHref = inBrowser ? getShouldDecode(true) : false