Skip to content

Commit d362d64

Browse files
committed
update entities encoding/decoding (fix vuejs#3899)
1 parent a675221 commit d362d64

File tree

13 files changed

+31
-47
lines changed

13 files changed

+31
-47
lines changed

build/config.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const builds = {
3838
env: 'development',
3939
banner,
4040
alias: {
41-
entities: './entity-decoder'
41+
he: './entity-decoder'
4242
}
4343
},
4444
// Runtime+compiler standalone production build.
@@ -49,22 +49,22 @@ const builds = {
4949
env: 'production',
5050
banner,
5151
alias: {
52-
entities: './entity-decoder'
52+
he: './entity-decoder'
5353
}
5454
},
5555
// Web compiler (CommonJS).
5656
'web-compiler': {
5757
entry: path.resolve(__dirname, '../src/entries/web-compiler.js'),
5858
dest: path.resolve(__dirname, '../packages/vue-template-compiler/build.js'),
5959
format: 'cjs',
60-
external: ['entities', 'de-indent']
60+
external: ['he', 'de-indent']
6161
},
6262
// Web server renderer (CommonJS).
6363
'web-server-renderer': {
6464
entry: path.resolve(__dirname, '../src/entries/web-server-renderer.js'),
6565
dest: path.resolve(__dirname, '../packages/vue-server-renderer/build.js'),
6666
format: 'cjs',
67-
external: ['stream', 'module', 'vm', 'entities', 'de-indent']
67+
external: ['stream', 'module', 'vm', 'he', 'de-indent']
6868
}
6969
}
7070

flow/modules.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
declare module 'entities' {
2-
declare function encodeHTML(html: string): string;
3-
declare function decodeHTML(html: string): string;
1+
declare module 'he' {
2+
declare function escape(html: string): string;
3+
declare function decode(html: string): string;
44
}
55

66
declare module 'source-map' {

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@
6161
"codecov.io": "^0.1.6",
6262
"cross-spawn": "^4.0.0",
6363
"de-indent": "^1.0.2",
64-
"entities": "^1.1.1",
6564
"es6-promise": "^3.2.1",
6665
"eslint": "^3.4.0",
6766
"eslint-config-vue": "^1.1.0",
6867
"eslint-loader": "^1.3.0",
6968
"eslint-plugin-flowtype": "^2.16.0",
7069
"eslint-plugin-html": "^1.5.2",
7170
"flow-bin": "^0.32.0",
71+
"he": "^1.1.0",
7272
"http-server": "^0.9.0",
7373
"jasmine": "2.4.x",
7474
"jasmine-core": "2.4.x",

packages/vue-server-renderer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"url": "https://github.com/vuejs/vue/issues"
1919
},
2020
"dependencies": {
21-
"entities": "^1.1.1",
21+
"he": "^1.1.0",
2222
"de-indent": "^1.0.2"
2323
},
2424
"homepage": "https://github.com/vuejs/vue#readme"

packages/vue-template-compiler/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"homepage": "https://github.com/vuejs/vue#readme",
2020
"dependencies": {
21-
"de-indent": "^1.0.2",
22-
"entities": "^1.1.1"
21+
"he": "^1.1.0",
22+
"de-indent": "^1.0.2"
2323
}
2424
}

src/compiler/parser/entity-decoder.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const decoder = document.createElement('div')
44

5-
export function decodeHTML (html: string): string {
5+
export function decode (html: string): string {
66
decoder.innerHTML = html
77
return decoder.textContent
88
}

src/compiler/parser/html-parser.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,21 @@ const nlRE = /
/g
5454
const ampRE = /&/g
5555
const quoteRE = /"/g
5656

57-
function decodeAttr (value, shouldDecodeTags, shouldDecodeNewlines) {
58-
if (shouldDecodeTags) {
59-
value = value.replace(ltRE, '<').replace(gtRE, '>')
60-
}
57+
function decodeAttr (value, shouldDecodeNewlines) {
6158
if (shouldDecodeNewlines) {
6259
value = value.replace(nlRE, '\n')
6360
}
64-
return value.replace(ampRE, '&').replace(quoteRE, '"')
61+
return value
62+
.replace(ltRE, '<')
63+
.replace(gtRE, '>')
64+
.replace(ampRE, '&')
65+
.replace(quoteRE, '"')
6566
}
6667

6768
export function parseHTML (html, options) {
6869
const stack = []
6970
const expectHTML = options.expectHTML
7071
const isUnaryTag = options.isUnaryTag || no
71-
const isFromDOM = options.isFromDOM
7272
let index = 0
7373
let last, lastTag
7474
while (html) {
@@ -218,11 +218,10 @@ export function parseHTML (html, options) {
218218
const value = args[3] || args[4] || args[5] || ''
219219
attrs[i] = {
220220
name: args[1],
221-
value: isFromDOM ? decodeAttr(
221+
value: decodeAttr(
222222
value,
223-
options.shouldDecodeTags,
224223
options.shouldDecodeNewlines
225-
) : value
224+
)
226225
}
227226
}
228227

src/compiler/parser/index.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* @flow */
22

3-
import { decodeHTML } from 'entities'
3+
import { decode } from 'he'
44
import { parseHTML } from './html-parser'
55
import { parseText } from './text-parser'
66
import { cached, no, camelize } from 'shared/util'
@@ -24,7 +24,7 @@ const argRE = /:(.*)$/
2424
const modifierRE = /\.[^\.]+/g
2525
const specialNewlineRE = /\u2028|\u2029/g
2626

27-
const decodeHTMLCached = cached(decodeHTML)
27+
const decodeHTMLCached = cached(decode)
2828

2929
// configurable state
3030
let warn
@@ -61,8 +61,6 @@ export function parse (
6161
parseHTML(template, {
6262
expectHTML: options.expectHTML,
6363
isUnaryTag: options.isUnaryTag,
64-
isFromDOM: options.isFromDOM,
65-
shouldDecodeTags: options.shouldDecodeTags,
6664
shouldDecodeNewlines: options.shouldDecodeNewlines,
6765
start (tag, attrs, unary) {
6866
// check namespace.

src/entries/web-runtime-with-compiler.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import Vue from './web-runtime'
44
import { warn, cached } from 'core/util/index'
55
import { query } from 'web/util/index'
6-
import { shouldDecodeTags, shouldDecodeNewlines } from 'web/util/compat'
6+
import { shouldDecodeNewlines } from 'web/util/compat'
77
import { compileToFunctions } from 'web/compiler/index'
88

99
const idToTemplate = cached(id => {
@@ -30,15 +30,12 @@ Vue.prototype.$mount = function (
3030
// resolve template/el and convert to render function
3131
if (!options.render) {
3232
let template = options.template
33-
let isFromDOM = false
3433
if (template) {
3534
if (typeof template === 'string') {
3635
if (template.charAt(0) === '#') {
37-
isFromDOM = true
3836
template = idToTemplate(template)
3937
}
4038
} else if (template.nodeType) {
41-
isFromDOM = true
4239
template = template.innerHTML
4340
} else {
4441
if (process.env.NODE_ENV !== 'production') {
@@ -47,14 +44,11 @@ Vue.prototype.$mount = function (
4744
return this
4845
}
4946
} else if (el) {
50-
isFromDOM = true
5147
template = getOuterHTML(el)
5248
}
5349
if (template) {
5450
const { render, staticRenderFns } = compileToFunctions(template, {
5551
warn,
56-
isFromDOM,
57-
shouldDecodeTags,
5852
shouldDecodeNewlines,
5953
delimiters: options.delimiters
6054
}, this)

src/platforms/web/util/compat.js

-7
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ function shouldDecode (content: string, encoded: string): boolean {
99
return div.innerHTML.indexOf(encoded) > 0
1010
}
1111

12-
// According to
13-
// https://w3c.github.io/DOM-Parsing/#dfn-serializing-an-attribute-value
14-
// when serializing innerHTML, <, >, ", & should be encoded as entities.
15-
// However, only some browsers, e.g. PhantomJS, encodes < and >.
16-
// this causes problems with the in-browser parser.
17-
export const shouldDecodeTags = inBrowser ? shouldDecode('>', '&gt;') : false
18-
1912
// #3663
2013
// IE encodes newlines inside attribute values while other browsers don't
2114
export const shouldDecodeNewlines = inBrowser ? shouldDecode('\n', '&#10;') : false

src/server/render.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* @flow */
22

3-
import { encodeHTML } from 'entities'
3+
import { escape } from 'he'
44
import { compileToFunctions } from 'web/compiler/index'
55
import { createComponentInstanceForVnode } from 'core/vdom/create-component'
66

@@ -112,7 +112,7 @@ export function createRenderFunction (
112112
} else if (node.isComment) {
113113
write(`<!--${node.text}-->`, next)
114114
} else {
115-
write(node.raw ? node.text : encodeHTML(String(node.text)), next)
115+
write(node.raw ? node.text : escape(String(node.text)), next)
116116
}
117117
}
118118
}

test/ssr/ssr-bundle-render.spec.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('SSR: bundle renderer', () => {
3737
const context = { url: '/test' }
3838
renderer.renderToString(context, (err, res) => {
3939
expect(err).toBeNull()
40-
expect(res).toBe('<div server-rendered="true">&sol;test</div>')
40+
expect(res).toBe('<div server-rendered="true">/test</div>')
4141
expect(context.msg).toBe('hello')
4242
done()
4343
})
@@ -53,7 +53,7 @@ describe('SSR: bundle renderer', () => {
5353
res += chunk.toString()
5454
})
5555
stream.on('end', () => {
56-
expect(res).toBe('<div server-rendered="true">&sol;test</div>')
56+
expect(res).toBe('<div server-rendered="true">/test</div>')
5757
expect(context.msg).toBe('hello')
5858
done()
5959
})
@@ -99,7 +99,7 @@ describe('SSR: bundle renderer', () => {
9999
}
100100
}
101101
createRenderer('cache.js', renderer => {
102-
const expected = '<div server-rendered="true">&sol;test</div>'
102+
const expected = '<div server-rendered="true">/test</div>'
103103
const key = 'app::1'
104104
renderer.renderToString((err, res) => {
105105
expect(err).toBeNull()
@@ -142,7 +142,7 @@ describe('SSR: bundle renderer', () => {
142142
}
143143
}
144144
createRenderer('cache.js', renderer => {
145-
const expected = '<div server-rendered="true">&sol;test</div>'
145+
const expected = '<div server-rendered="true">/test</div>'
146146
const key = 'app::1'
147147
renderer.renderToString((err, res) => {
148148
expect(err).toBeNull()

test/ssr/ssr-string.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ describe('SSR: renderToString', () => {
9494
bar: '<span>rendering</span>'
9595
}
9696
}, result => {
97-
expect(result).toContain('<div server-rendered="true">server side &lt;span&gt;rendering&lt;&sol;span&gt;</div>')
97+
expect(result).toContain('<div server-rendered="true">server side &lt;span&gt;rendering&lt;/span&gt;</div>')
9898
done()
9999
})
100100
})
@@ -118,7 +118,7 @@ describe('SSR: renderToString', () => {
118118
text: '<span>foo</span>'
119119
}
120120
}, result => {
121-
expect(result).toContain('<div server-rendered="true">&lt;span&gt;foo&lt;&sol;span&gt;</div>')
121+
expect(result).toContain('<div server-rendered="true">&lt;span&gt;foo&lt;/span&gt;</div>')
122122
done()
123123
})
124124
})

0 commit comments

Comments
 (0)