From be666ebd59027eb2fc96595c1a6054ecf62832e8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 8 Apr 2020 16:44:32 -0400 Subject: [PATCH 01/21] fix(compiler): should only strip leading newline directly in pre tag --- packages/compiler-core/src/parse.ts | 2 +- packages/compiler-dom/__tests__/parse.spec.ts | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index 1e94d6451..1fbd7d5c2 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -223,7 +223,7 @@ function parseChildren( } } } - } else { + } else if (parent && context.options.isPreTag(parent.tag)) { // remove leading newline per html spec // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element const first = nodes[0] diff --git a/packages/compiler-dom/__tests__/parse.spec.ts b/packages/compiler-dom/__tests__/parse.spec.ts index 58e377530..8e88d1495 100644 --- a/packages/compiler-dom/__tests__/parse.spec.ts +++ b/packages/compiler-dom/__tests__/parse.spec.ts @@ -141,12 +141,24 @@ describe('DOM parser', () => { // #908 test('
 tag should remove leading newline', () => {
-      const rawText = `\nhello`
+      const rawText = `\nhello
\nbye
` const ast = parse(`
${rawText}
`, parserOptions) - expect((ast.children[0] as ElementNode).children[0]).toMatchObject({ - type: NodeTypes.TEXT, - content: rawText.slice(1) - }) + expect((ast.children[0] as ElementNode).children).toMatchObject([ + { + type: NodeTypes.TEXT, + content: `hello` + }, + { + type: NodeTypes.ELEMENT, + children: [ + { + type: NodeTypes.TEXT, + // should not remove the leading newline for nested elements + content: `\nbye` + } + ] + } + ]) }) }) From 8c17535a470501f7f4ec3747cd3de25d9169c505 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 8 Apr 2020 17:33:07 -0400 Subject: [PATCH 02/21] fix(compiler): should not condense   fix #945 --- packages/compiler-core/src/parse.ts | 4 ++-- packages/compiler-dom/__tests__/parse.spec.ts | 14 ++++++++++++-- packages/compiler-dom/src/parserOptionsStandard.ts | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index 1fbd7d5c2..bb4e3e4a6 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -194,7 +194,7 @@ function parseChildren( for (let i = 0; i < nodes.length; i++) { const node = nodes[i] if (node.type === NodeTypes.TEXT) { - if (!node.content.trim()) { + if (!/[^\t\r\n\f ]/.test(node.content)) { const prev = nodes[i - 1] const next = nodes[i + 1] // If: @@ -219,7 +219,7 @@ function parseChildren( node.content = ' ' } } else { - node.content = node.content.replace(/\s+/g, ' ') + node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ') } } } diff --git a/packages/compiler-dom/__tests__/parse.spec.ts b/packages/compiler-dom/__tests__/parse.spec.ts index 8e88d1495..73a27e205 100644 --- a/packages/compiler-dom/__tests__/parse.spec.ts +++ b/packages/compiler-dom/__tests__/parse.spec.ts @@ -8,9 +8,9 @@ import { InterpolationNode } from '@vue/compiler-core' import { - parserOptionsMinimal as parserOptions, + parserOptionsStandard as parserOptions, DOMNamespaces -} from '../src/parserOptionsMinimal' +} from '../src/parserOptionsStandard' describe('DOM parser', () => { describe('Text', () => { @@ -160,6 +160,16 @@ describe('DOM parser', () => { } ]) }) + + // #945 + test('  should not be condensed', () => { + const nbsp = String.fromCharCode(160) + const ast = parse(`foo  bar`, parserOptions) + expect(ast.children[0]).toMatchObject({ + type: NodeTypes.TEXT, + content: `foo${nbsp}${nbsp}bar` + }) + }) }) describe('Interpolation', () => { diff --git a/packages/compiler-dom/src/parserOptionsStandard.ts b/packages/compiler-dom/src/parserOptionsStandard.ts index 0fe9bfded..b0bb70e4e 100644 --- a/packages/compiler-dom/src/parserOptionsStandard.ts +++ b/packages/compiler-dom/src/parserOptionsStandard.ts @@ -2,6 +2,8 @@ import { ParserOptions } from '@vue/compiler-core' import { parserOptionsMinimal } from './parserOptionsMinimal' import namedCharacterReferences from './namedChars.json' +export { DOMNamespaces } from './parserOptionsMinimal' + export const parserOptionsStandard: ParserOptions = { // extends the minimal options with more spec-compliant overrides ...parserOptionsMinimal, From 1f6e72b11051561abe270fa233cf52d5aba01d6b Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 8 Apr 2020 18:51:25 -0400 Subject: [PATCH 03/21] fix(compiler): support full range of entity decoding in browser builds BREAKING CHANGE: compiler options have been adjusted. - new option `decodeEntities` is added. - `namedCharacterReferences` option has been removed. - `maxCRNameLength` option has been rmeoved. --- .../__snapshots__/parse.spec.ts.snap | 1328 ----------------- .../compiler-core/__tests__/parse.spec.ts | 272 +--- packages/compiler-core/src/errors.ts | 21 - packages/compiler-core/src/options.ts | 8 +- packages/compiler-core/src/parse.ts | 178 +-- packages/compiler-dom/__tests__/parse.spec.ts | 79 +- packages/compiler-dom/src/decodeHtml.ts | 133 ++ .../compiler-dom/src/decodeHtmlBrowser.ts | 6 + packages/compiler-dom/src/index.ts | 7 +- ...rserOptionsMinimal.ts => parserOptions.ts} | 5 +- .../compiler-dom/src/parserOptionsStandard.ts | 17 - 11 files changed, 245 insertions(+), 1809 deletions(-) create mode 100644 packages/compiler-dom/src/decodeHtml.ts create mode 100644 packages/compiler-dom/src/decodeHtmlBrowser.ts rename packages/compiler-dom/src/{parserOptionsMinimal.ts => parserOptions.ts} (92%) delete mode 100644 packages/compiler-dom/src/parserOptionsStandard.ts diff --git a/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap index c7af84fff..998b00ab7 100644 --- a/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap @@ -210,634 +210,6 @@ Object { } `; -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 35, - "line": 1, - "offset": 34, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [ - Object { - "loc": Object { - "end": Object { - "column": 23, - "line": 1, - "offset": 22, - }, - "source": "attr=\\"c\\"", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "name": "attr", - "type": 6, - "value": Object { - "content": "c", - "loc": Object { - "end": Object { - "column": 23, - "line": 1, - "offset": 22, - }, - "source": "\\"c\\"", - "start": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - }, - "type": 2, - }, - }, - ], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 35, - "line": 1, - "offset": 34, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 34, - "line": 1, - "offset": 33, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [ - Object { - "loc": Object { - "end": Object { - "column": 22, - "line": 1, - "offset": 21, - }, - "source": "attr=\\"&#a;\\"", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "name": "attr", - "type": 6, - "value": Object { - "content": "&#a;", - "loc": Object { - "end": Object { - "column": 22, - "line": 1, - "offset": 21, - }, - "source": "\\"&#a;\\"", - "start": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - }, - "type": 2, - }, - }, - ], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 34, - "line": 1, - "offset": 33, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 36, - "line": 1, - "offset": 35, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [ - Object { - "loc": Object { - "end": Object { - "column": 24, - "line": 1, - "offset": 23, - }, - "source": "attr=\\"ÿ\\"", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "name": "attr", - "type": 6, - "value": Object { - "content": "ÿ", - "loc": Object { - "end": Object { - "column": 24, - "line": 1, - "offset": 23, - }, - "source": "\\"ÿ\\"", - "start": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - }, - "type": 2, - }, - }, - ], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 36, - "line": 1, - "offset": 35, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 35, - "line": 1, - "offset": 34, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [ - Object { - "loc": Object { - "end": Object { - "column": 23, - "line": 1, - "offset": 22, - }, - "source": "attr=\\"&#xg;\\"", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "name": "attr", - "type": 6, - "value": Object { - "content": "&#xg;", - "loc": Object { - "end": Object { - "column": 23, - "line": 1, - "offset": 22, - }, - "source": "\\"&#xg;\\"", - "start": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - }, - "type": 2, - }, - }, - ], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 35, - "line": 1, - "offset": 34, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "c", - "loc": Object { - "end": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - "source": "c", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "&#a;", - "loc": Object { - "end": Object { - "column": 15, - "line": 1, - "offset": 14, - }, - "source": "&#a;", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "ÿ", - "loc": Object { - "end": Object { - "column": 17, - "line": 1, - "offset": 16, - }, - "source": "ÿ", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 28, - "line": 1, - "offset": 27, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 28, - "line": 1, - "offset": 27, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "&#xg;", - "loc": Object { - "end": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - "source": "&#xg;", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - exports[`compiler: parse Errors CDATA_IN_HTML_CONTENT 1`] = ` Object { "cached": 0, @@ -1002,216 +374,6 @@ Object { } `; -exports[`compiler: parse Errors CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "�", - "loc": Object { - "end": Object { - "column": 21, - "line": 1, - "offset": 20, - }, - "source": "�", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 32, - "line": 1, - "offset": 31, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 32, - "line": 1, - "offset": 31, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors CONTROL_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "", - "loc": Object { - "end": Object { - "column": 18, - "line": 1, - "offset": 17, - }, - "source": "", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 29, - "line": 1, - "offset": 28, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 29, - "line": 1, - "offset": 28, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors CONTROL_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "", - "loc": Object { - "end": Object { - "column": 17, - "line": 1, - "offset": 16, - }, - "source": "", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 28, - "line": 1, - "offset": 27, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 28, - "line": 1, - "offset": 27, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - exports[`compiler: parse Errors DUPLICATE_ATTRIBUTE 1`] = ` Object { "cached": 0, @@ -4698,216 +3860,6 @@ Object { } `; -exports[`compiler: parse Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "(", - "loc": Object { - "end": Object { - "column": 15, - "line": 1, - "offset": 14, - }, - "source": "(", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "@", - "loc": Object { - "end": Object { - "column": 16, - "line": 1, - "offset": 15, - }, - "source": "@", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 27, - "line": 1, - "offset": 26, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "&", - "loc": Object { - "end": Object { - "column": 15, - "line": 1, - "offset": 14, - }, - "source": "&", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 26, - "line": 1, - "offset": 25, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - exports[`compiler: parse Errors MISSING_WHITESPACE_BETWEEN_ATTRIBUTES 1`] = ` Object { "cached": 0, @@ -5481,286 +4433,6 @@ Object { } `; -exports[`compiler: parse Errors NONCHARACTER_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "🿿", - "loc": Object { - "end": Object { - "column": 20, - "line": 1, - "offset": 19, - }, - "source": "🿿", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 31, - "line": 1, - "offset": 30, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 31, - "line": 1, - "offset": 30, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors NONCHARACTER_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "￾", - "loc": Object { - "end": Object { - "column": 19, - "line": 1, - "offset": 18, - }, - "source": "￾", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 30, - "line": 1, - "offset": 29, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 30, - "line": 1, - "offset": 29, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors NULL_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "�", - "loc": Object { - "end": Object { - "column": 18, - "line": 1, - "offset": 17, - }, - "source": "�", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 29, - "line": 1, - "offset": 28, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 29, - "line": 1, - "offset": 28, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - -exports[`compiler: parse Errors SURROGATE_CHARACTER_REFERENCE 1`] = ` -Object { - "cached": 0, - "children": Array [ - Object { - "children": Array [ - Object { - "content": "�", - "loc": Object { - "end": Object { - "column": 19, - "line": 1, - "offset": 18, - }, - "source": "�", - "start": Object { - "column": 11, - "line": 1, - "offset": 10, - }, - }, - "type": 2, - }, - ], - "codegenNode": undefined, - "isSelfClosing": false, - "loc": Object { - "end": Object { - "column": 30, - "line": 1, - "offset": 29, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "ns": 0, - "props": Array [], - "tag": "template", - "tagType": 0, - "type": 1, - }, - ], - "codegenNode": undefined, - "components": Array [], - "directives": Array [], - "helpers": Array [], - "hoists": Array [], - "imports": Array [], - "loc": Object { - "end": Object { - "column": 30, - "line": 1, - "offset": 29, - }, - "source": "", - "start": Object { - "column": 1, - "line": 1, - "offset": 0, - }, - }, - "temps": 0, - "type": 0, -} -`; - exports[`compiler: parse Errors UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME 1`] = ` Object { "cached": 0, diff --git a/packages/compiler-core/__tests__/parse.spec.ts b/packages/compiler-core/__tests__/parse.spec.ts index 4b0992a5f..d556a1070 100644 --- a/packages/compiler-core/__tests__/parse.spec.ts +++ b/packages/compiler-core/__tests__/parse.spec.ts @@ -9,7 +9,6 @@ import { NodeTypes, Position, TextNode, - AttributeNode, InterpolationNode } from '../src/ast' @@ -163,114 +162,6 @@ describe('compiler: parse', () => { } }) }) - - test('HTML entities compatibility in text (https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state).', () => { - const spy = jest.fn() - const ast = baseParse('&ersand;', { - namedCharacterReferences: { amp: '&' }, - onError: spy - }) - const text = ast.children[0] as TextNode - - expect(text).toStrictEqual({ - type: NodeTypes.TEXT, - content: '&ersand;', - loc: { - start: { offset: 0, line: 1, column: 1 }, - end: { offset: 11, line: 1, column: 12 }, - source: '&ersand;' - } - }) - expect(spy.mock.calls).toMatchObject([ - [ - { - code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, - loc: { - start: { offset: 4, line: 1, column: 5 } - } - } - ] - ]) - }) - - test('HTML entities compatibility in attribute (https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state).', () => { - const spy = jest.fn() - const ast = baseParse( - '
', - { - namedCharacterReferences: { amp: '&', 'amp;': '&' }, - onError: spy - } - ) - const element = ast.children[0] as ElementNode - const text1 = (element.props[0] as AttributeNode).value - const text2 = (element.props[1] as AttributeNode).value - const text3 = (element.props[2] as AttributeNode).value - - expect(text1).toStrictEqual({ - type: NodeTypes.TEXT, - content: '&ersand;', - loc: { - start: { offset: 7, line: 1, column: 8 }, - end: { offset: 20, line: 1, column: 21 }, - source: '"&ersand;"' - } - }) - expect(text2).toStrictEqual({ - type: NodeTypes.TEXT, - content: '&ersand;', - loc: { - start: { offset: 23, line: 1, column: 24 }, - end: { offset: 37, line: 1, column: 38 }, - source: '"&ersand;"' - } - }) - expect(text3).toStrictEqual({ - type: NodeTypes.TEXT, - content: '&!', - loc: { - start: { offset: 40, line: 1, column: 41 }, - end: { offset: 47, line: 1, column: 48 }, - source: '"&!"' - } - }) - expect(spy.mock.calls).toMatchObject([ - [ - { - code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, - loc: { - start: { offset: 45, line: 1, column: 46 } - } - } - ] - ]) - }) - - test('Some control character reference should be replaced.', () => { - const spy = jest.fn() - const ast = baseParse('†', { onError: spy }) - const text = ast.children[0] as TextNode - - expect(text).toStrictEqual({ - type: NodeTypes.TEXT, - content: '†', - loc: { - start: { offset: 0, line: 1, column: 1 }, - end: { offset: 6, line: 1, column: 7 }, - source: '†' - } - }) - expect(spy.mock.calls).toMatchObject([ - [ - { - code: ErrorCodes.CONTROL_CHARACTER_REFERENCE, - loc: { - start: { offset: 0, line: 1, column: 1 } - } - } - ] - ]) - }) }) describe('Interpolation', () => { @@ -1652,12 +1543,10 @@ foo expect(baz.loc.end).toEqual({ line: 2, column: 28, offset }) }) - describe('namedCharacterReferences option', () => { + describe('decodeEntities option', () => { test('use the given map', () => { const ast: any = baseParse('&∪︀', { - namedCharacterReferences: { - 'cups;': '\u222A\uFE00' // UNION with serifs - }, + decodeEntities: text => text.replace('∪︀', '\u222A\uFE00'), onError: () => {} // Ignore errors }) @@ -1756,60 +1645,6 @@ foo errors: [] } ], - ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - }, - { - code: '', - errors: [] - }, - { - code: '', - errors: [] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE, - loc: { offset: 16, line: 1, column: 17 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE, - loc: { offset: 16, line: 1, column: 17 } - } - ] - }, - { - code: '', - errors: [] - }, - { - code: '', - errors: [] - } - ], CDATA_IN_HTML_CONTENT: [ { code: '', @@ -1825,37 +1660,6 @@ foo errors: [] } ], - CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - } - ], - CONTROL_CHARACTER_REFERENCE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.CONTROL_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.CONTROL_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - } - ], DUPLICATE_ATTRIBUTE: [ { code: '', @@ -2412,36 +2216,6 @@ foo ] } ], - MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE: [ - { - code: '', - options: { namedCharacterReferences: { amp: '&' } }, - errors: [ - { - type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, - loc: { offset: 14, line: 1, column: 15 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, - loc: { offset: 14, line: 1, column: 15 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, - loc: { offset: 15, line: 1, column: 16 } - } - ] - } - ], MISSING_WHITESPACE_BETWEEN_ATTRIBUTES: [ { code: '', @@ -2500,48 +2274,6 @@ foo ] } ], - NONCHARACTER_CHARACTER_REFERENCE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - }, - { - code: '', - errors: [ - { - type: ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - } - ], - NULL_CHARACTER_REFERENCE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.NULL_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - } - ], - SURROGATE_CHARACTER_REFERENCE: [ - { - code: '', - errors: [ - { - type: ErrorCodes.SURROGATE_CHARACTER_REFERENCE, - loc: { offset: 10, line: 1, column: 11 } - } - ] - } - ], UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME: [ { code: "", diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts index 5d66ddcf1..63c0bb095 100644 --- a/packages/compiler-core/src/errors.ts +++ b/packages/compiler-core/src/errors.ts @@ -32,10 +32,7 @@ export function createCompilerError( export const enum ErrorCodes { // parse errors ABRUPT_CLOSING_OF_EMPTY_COMMENT, - ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE, CDATA_IN_HTML_CONTENT, - CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE, - CONTROL_CHARACTER_REFERENCE, DUPLICATE_ATTRIBUTE, END_TAG_WITH_ATTRIBUTES, END_TAG_WITH_TRAILING_SOLIDUS, @@ -49,12 +46,8 @@ export const enum ErrorCodes { INVALID_FIRST_CHARACTER_OF_TAG_NAME, MISSING_ATTRIBUTE_VALUE, MISSING_END_TAG_NAME, - MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE, MISSING_WHITESPACE_BETWEEN_ATTRIBUTES, NESTED_COMMENT, - NONCHARACTER_CHARACTER_REFERENCE, - NULL_CHARACTER_REFERENCE, - SURROGATE_CHARACTER_REFERENCE, UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME, UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE, UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME, @@ -101,14 +94,8 @@ export const enum ErrorCodes { export const errorMessages: { [code: number]: string } = { // parse errors [ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.', - [ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE]: - 'Illegal numeric character reference: invalid character.', [ErrorCodes.CDATA_IN_HTML_CONTENT]: 'CDATA section is allowed only in XML context.', - [ErrorCodes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE]: - 'Illegal numeric character reference: too big.', - [ErrorCodes.CONTROL_CHARACTER_REFERENCE]: - 'Illegal numeric character reference: control character.', [ErrorCodes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.', [ErrorCodes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.', [ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.", @@ -124,17 +111,9 @@ export const errorMessages: { [code: number]: string } = { "Illegal tag name. Use '<' to print '<'.", [ErrorCodes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.', [ErrorCodes.MISSING_END_TAG_NAME]: 'End tag name was expected.', - [ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE]: - 'Semicolon was expected.', [ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]: 'Whitespace was expected.', [ErrorCodes.NESTED_COMMENT]: "Unexpected '