Skip to content

Commit

Permalink
fix: handle encoded tabs and newlines in attributes for Chrome a[href…
Browse files Browse the repository at this point in the history
…] and IE/Edge

fix vuejs#6828, fix vuejs#6916
  • Loading branch information
yyx990803 authored and aJean committed Aug 19, 2020
1 parent d89a5ff commit b37202c
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 15 deletions.
3 changes: 2 additions & 1 deletion flow/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 7 additions & 6 deletions src/compiler/parser/html-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/compiler/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/web/entry-runtime-with-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -64,6 +64,7 @@ Vue.prototype.$mount = function (

const { render, staticRenderFns } = compileToFunctions(template, {
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
Expand Down
16 changes: 9 additions & 7 deletions src/platforms/web/util/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = `<div a="${content}"/>`
return div.innerHTML.indexOf(encoded) > 0
let div
function getShouldDecode (href: boolean): boolean {
div = div || document.createElement('div')
div.innerHTML = href ? `<a href="\n"/>` : `<div a="\n"/>`
return div.innerHTML.indexOf('&#10;') > 0
}

// #3663
// IE encodes newlines inside attribute values while other browsers don't
export const shouldDecodeNewlines = inBrowser ? shouldDecode('\n', '&#10;') : 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

0 comments on commit b37202c

Please sign in to comment.