This reverts commit 8a54896a91
.
PR Close #43033
This commit is contained in:
parent
6f05dd8062
commit
ea5ed4e4d4
|
@ -396,12 +396,12 @@ class _Visitor implements html.Visitor {
|
||||||
if (nodes.length == 0) {
|
if (nodes.length == 0) {
|
||||||
translatedAttributes.push(new html.Attribute(
|
translatedAttributes.push(new html.Attribute(
|
||||||
attr.name, '', attr.sourceSpan, undefined /* keySpan */, undefined /* valueSpan */,
|
attr.name, '', attr.sourceSpan, undefined /* keySpan */, undefined /* valueSpan */,
|
||||||
undefined /* valueTokens */, undefined /* i18n */));
|
undefined /* i18n */));
|
||||||
} else if (nodes[0] instanceof html.Text) {
|
} else if (nodes[0] instanceof html.Text) {
|
||||||
const value = (nodes[0] as html.Text).value;
|
const value = (nodes[0] as html.Text).value;
|
||||||
translatedAttributes.push(new html.Attribute(
|
translatedAttributes.push(new html.Attribute(
|
||||||
attr.name, value, attr.sourceSpan, undefined /* keySpan */,
|
attr.name, value, attr.sourceSpan, undefined /* keySpan */,
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */));
|
undefined /* valueSpan */, undefined /* i18n */));
|
||||||
} else {
|
} else {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
el,
|
el,
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
import {AstPath} from '../ast_path';
|
import {AstPath} from '../ast_path';
|
||||||
import {I18nMeta} from '../i18n/i18n_ast';
|
import {I18nMeta} from '../i18n/i18n_ast';
|
||||||
import {ParseSourceSpan} from '../parse_util';
|
import {ParseSourceSpan} from '../parse_util';
|
||||||
import {Token} from './lexer';
|
|
||||||
|
|
||||||
interface BaseNode {
|
interface BaseNode {
|
||||||
sourceSpan: ParseSourceSpan;
|
sourceSpan: ParseSourceSpan;
|
||||||
|
@ -24,8 +23,7 @@ export abstract class NodeWithI18n implements BaseNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Text extends NodeWithI18n {
|
export class Text extends NodeWithI18n {
|
||||||
constructor(
|
constructor(public value: string, sourceSpan: ParseSourceSpan, i18n?: I18nMeta) {
|
||||||
public value: string, sourceSpan: ParseSourceSpan, public tokens: Token[], i18n?: I18nMeta) {
|
|
||||||
super(sourceSpan, i18n);
|
super(sourceSpan, i18n);
|
||||||
}
|
}
|
||||||
override visit(visitor: Visitor, context: any): any {
|
override visit(visitor: Visitor, context: any): any {
|
||||||
|
@ -57,8 +55,8 @@ export class ExpansionCase implements BaseNode {
|
||||||
export class Attribute extends NodeWithI18n {
|
export class Attribute extends NodeWithI18n {
|
||||||
constructor(
|
constructor(
|
||||||
public name: string, public value: string, sourceSpan: ParseSourceSpan,
|
public name: string, public value: string, sourceSpan: ParseSourceSpan,
|
||||||
readonly keySpan: ParseSourceSpan|undefined, public valueSpan: ParseSourceSpan|undefined,
|
readonly keySpan: ParseSourceSpan|undefined, public valueSpan?: ParseSourceSpan,
|
||||||
public valueTokens: Token[]|undefined, i18n: I18nMeta|undefined) {
|
i18n?: I18nMeta) {
|
||||||
super(sourceSpan, i18n);
|
super(sourceSpan, i18n);
|
||||||
}
|
}
|
||||||
override visit(visitor: Visitor, context: any): any {
|
override visit(visitor: Visitor, context: any): any {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
import * as html from './ast';
|
import * as html from './ast';
|
||||||
import {NGSP_UNICODE} from './entities';
|
import {NGSP_UNICODE} from './entities';
|
||||||
import {Token, TokenType} from './lexer';
|
|
||||||
import {ParseTreeResult} from './parser';
|
import {ParseTreeResult} from './parser';
|
||||||
|
|
||||||
export const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
|
export const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
|
||||||
|
@ -75,13 +74,8 @@ export class WhitespaceVisitor implements html.Visitor {
|
||||||
(context.prev instanceof html.Expansion || context.next instanceof html.Expansion);
|
(context.prev instanceof html.Expansion || context.next instanceof html.Expansion);
|
||||||
|
|
||||||
if (isNotBlank || hasExpansionSibling) {
|
if (isNotBlank || hasExpansionSibling) {
|
||||||
// Process the whitespace in the tokens of this Text node
|
return new html.Text(
|
||||||
const tokens = text.tokens.map(
|
replaceNgsp(text.value).replace(WS_REPLACE_REGEXP, ' '), text.sourceSpan, text.i18n);
|
||||||
token => token.type === TokenType.TEXT ? createTextTokenAfterWhitespaceProcessing(token) :
|
|
||||||
token);
|
|
||||||
// Process the whitespace of the value of this Text node
|
|
||||||
const value = processWhitespace(text.value);
|
|
||||||
return new html.Text(value, text.sourceSpan, tokens, text.i18n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -100,14 +94,6 @@ export class WhitespaceVisitor implements html.Visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTextTokenAfterWhitespaceProcessing(token: Token): Token {
|
|
||||||
return new Token(token.type, [processWhitespace(token.parts[0])], token.sourceSpan);
|
|
||||||
}
|
|
||||||
|
|
||||||
function processWhitespace(text: string): string {
|
|
||||||
return replaceNgsp(text).replace(WS_REPLACE_REGEXP, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeWhitespaces(htmlAstWithErrors: ParseTreeResult): ParseTreeResult {
|
export function removeWhitespaces(htmlAstWithErrors: ParseTreeResult): ParseTreeResult {
|
||||||
return new ParseTreeResult(
|
return new ParseTreeResult(
|
||||||
html.visitAll(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes),
|
html.visitAll(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes),
|
||||||
|
|
|
@ -102,15 +102,14 @@ function _expandPluralForm(ast: html.Expansion, errors: ParseError[]): html.Elem
|
||||||
errors.push(...expansionResult.errors);
|
errors.push(...expansionResult.errors);
|
||||||
|
|
||||||
return new html.Element(
|
return new html.Element(
|
||||||
`ng-template`,
|
`ng-template`, [new html.Attribute(
|
||||||
[new html.Attribute(
|
'ngPluralCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */,
|
||||||
'ngPluralCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */,
|
undefined /* valueSpan */, undefined /* i18n */)],
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)],
|
|
||||||
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
||||||
});
|
});
|
||||||
const switchAttr = new html.Attribute(
|
const switchAttr = new html.Attribute(
|
||||||
'[ngPlural]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */,
|
'[ngPlural]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */,
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */);
|
undefined /* valueSpan */, undefined /* i18n */);
|
||||||
return new html.Element(
|
return new html.Element(
|
||||||
'ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
'ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
||||||
}
|
}
|
||||||
|
@ -124,23 +123,21 @@ function _expandDefaultForm(ast: html.Expansion, errors: ParseError[]): html.Ele
|
||||||
if (c.value === 'other') {
|
if (c.value === 'other') {
|
||||||
// other is the default case when no values match
|
// other is the default case when no values match
|
||||||
return new html.Element(
|
return new html.Element(
|
||||||
`ng-template`,
|
`ng-template`, [new html.Attribute(
|
||||||
[new html.Attribute(
|
'ngSwitchDefault', '', c.valueSourceSpan, undefined /* keySpan */,
|
||||||
'ngSwitchDefault', '', c.valueSourceSpan, undefined /* keySpan */,
|
undefined /* valueSpan */, undefined /* i18n */)],
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)],
|
|
||||||
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new html.Element(
|
return new html.Element(
|
||||||
`ng-template`,
|
`ng-template`, [new html.Attribute(
|
||||||
[new html.Attribute(
|
'ngSwitchCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */,
|
||||||
'ngSwitchCase', `${c.value}`, c.valueSourceSpan, undefined /* keySpan */,
|
undefined /* valueSpan */, undefined /* i18n */)],
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */)],
|
|
||||||
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
||||||
});
|
});
|
||||||
const switchAttr = new html.Attribute(
|
const switchAttr = new html.Attribute(
|
||||||
'[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */,
|
'[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan, undefined /* keySpan */,
|
||||||
undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */);
|
undefined /* valueSpan */, undefined /* i18n */);
|
||||||
return new html.Element(
|
return new html.Element(
|
||||||
'ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
'ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,6 @@ class _TreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _consumeText(token: lex.Token) {
|
private _consumeText(token: lex.Token) {
|
||||||
const tokens = [token];
|
|
||||||
const startSpan = token.sourceSpan;
|
const startSpan = token.sourceSpan;
|
||||||
let text = token.parts[0];
|
let text = token.parts[0];
|
||||||
if (text.length > 0 && text[0] == '\n') {
|
if (text.length > 0 && text[0] == '\n') {
|
||||||
|
@ -224,15 +223,14 @@ class _TreeBuilder {
|
||||||
if (parent != null && parent.children.length == 0 &&
|
if (parent != null && parent.children.length == 0 &&
|
||||||
this.getTagDefinition(parent.name).ignoreFirstLf) {
|
this.getTagDefinition(parent.name).ignoreFirstLf) {
|
||||||
text = text.substring(1);
|
text = text.substring(1);
|
||||||
tokens[0] = {type: token.type, sourceSpan: token.sourceSpan, parts: [text]};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For now recombine text, interpolation and entity tokens
|
||||||
while (this._peek.type === lex.TokenType.INTERPOLATION ||
|
while (this._peek.type === lex.TokenType.INTERPOLATION ||
|
||||||
this._peek.type === lex.TokenType.TEXT ||
|
this._peek.type === lex.TokenType.TEXT ||
|
||||||
this._peek.type === lex.TokenType.ENCODED_ENTITY) {
|
this._peek.type === lex.TokenType.ENCODED_ENTITY) {
|
||||||
token = this._advance();
|
token = this._advance();
|
||||||
tokens.push(token);
|
|
||||||
if (token.type === lex.TokenType.INTERPOLATION) {
|
if (token.type === lex.TokenType.INTERPOLATION) {
|
||||||
// For backward compatibility we decode HTML entities that appear in interpolation
|
// For backward compatibility we decode HTML entities that appear in interpolation
|
||||||
// expressions. This is arguably a bug, but it could be a considerable breaking change to
|
// expressions. This is arguably a bug, but it could be a considerable breaking change to
|
||||||
|
@ -250,8 +248,8 @@ class _TreeBuilder {
|
||||||
const endSpan = token.sourceSpan;
|
const endSpan = token.sourceSpan;
|
||||||
this._addToParent(new html.Text(
|
this._addToParent(new html.Text(
|
||||||
text,
|
text,
|
||||||
new ParseSourceSpan(startSpan.start, endSpan.end, startSpan.fullStart, startSpan.details),
|
new ParseSourceSpan(
|
||||||
tokens));
|
startSpan.start, endSpan.end, startSpan.fullStart, startSpan.details)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,17 +372,16 @@ class _TreeBuilder {
|
||||||
|
|
||||||
// Consume the attribute value
|
// Consume the attribute value
|
||||||
let value = '';
|
let value = '';
|
||||||
const valueTokens: lex.Token[] = [];
|
|
||||||
let valueStartSpan: ParseSourceSpan|undefined = undefined;
|
let valueStartSpan: ParseSourceSpan|undefined = undefined;
|
||||||
let valueEnd: ParseLocation|undefined = undefined;
|
let valueEnd: ParseLocation|undefined = undefined;
|
||||||
if (this._peek.type === lex.TokenType.ATTR_VALUE_TEXT) {
|
if (this._peek.type === lex.TokenType.ATTR_VALUE_TEXT) {
|
||||||
valueStartSpan = this._peek.sourceSpan;
|
valueStartSpan = this._peek.sourceSpan;
|
||||||
valueEnd = this._peek.sourceSpan.end;
|
valueEnd = this._peek.sourceSpan.end;
|
||||||
|
// For now recombine text, interpolation and entity tokens
|
||||||
while (this._peek.type === lex.TokenType.ATTR_VALUE_TEXT ||
|
while (this._peek.type === lex.TokenType.ATTR_VALUE_TEXT ||
|
||||||
this._peek.type === lex.TokenType.ATTR_VALUE_INTERPOLATION ||
|
this._peek.type === lex.TokenType.ATTR_VALUE_INTERPOLATION ||
|
||||||
this._peek.type === lex.TokenType.ENCODED_ENTITY) {
|
this._peek.type === lex.TokenType.ENCODED_ENTITY) {
|
||||||
const valueToken = this._advance();
|
let valueToken = this._advance();
|
||||||
valueTokens.push(valueToken);
|
|
||||||
if (valueToken.type === lex.TokenType.ATTR_VALUE_INTERPOLATION) {
|
if (valueToken.type === lex.TokenType.ATTR_VALUE_INTERPOLATION) {
|
||||||
// For backward compatibility we decode HTML entities that appear in interpolation
|
// For backward compatibility we decode HTML entities that appear in interpolation
|
||||||
// expressions. This is arguably a bug, but it could be a considerable breaking change to
|
// expressions. This is arguably a bug, but it could be a considerable breaking change to
|
||||||
|
@ -411,8 +408,7 @@ class _TreeBuilder {
|
||||||
return new html.Attribute(
|
return new html.Attribute(
|
||||||
fullName, value,
|
fullName, value,
|
||||||
new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart),
|
new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart),
|
||||||
attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined,
|
attrName.sourceSpan, valueSpan);
|
||||||
undefined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getParentElement(): html.Element|null {
|
private _getParentElement(): html.Element|null {
|
||||||
|
|
|
@ -52,16 +52,12 @@ class _Humanizer implements html.Visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
visitAttribute(attribute: html.Attribute, context: any): any {
|
visitAttribute(attribute: html.Attribute, context: any): any {
|
||||||
const valueTokens = attribute.valueTokens ?? [];
|
const res = this._appendContext(attribute, [html.Attribute, attribute.name, attribute.value]);
|
||||||
const res = this._appendContext(attribute, [
|
|
||||||
html.Attribute, attribute.name, attribute.value, ...valueTokens.map(token => token.parts)
|
|
||||||
]);
|
|
||||||
this.result.push(res);
|
this.result.push(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitText(text: html.Text, context: any): any {
|
visitText(text: html.Text, context: any): any {
|
||||||
const res = this._appendContext(
|
const res = this._appendContext(text, [html.Text, text.value, this.elDepth]);
|
||||||
text, [html.Text, text.value, this.elDepth, ...text.tokens.map(token => token.parts)]);
|
|
||||||
this.result.push(res);
|
this.result.push(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,31 +24,31 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
describe('parse', () => {
|
describe('parse', () => {
|
||||||
describe('text nodes', () => {
|
describe('text nodes', () => {
|
||||||
it('should parse root level text nodes', () => {
|
it('should parse root level text nodes', () => {
|
||||||
expect(humanizeDom(parser.parse('a', 'TestComp'))).toEqual([[html.Text, 'a', 0, ['a']]]);
|
expect(humanizeDom(parser.parse('a', 'TestComp'))).toEqual([[html.Text, 'a', 0]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse text nodes inside regular elements', () => {
|
it('should parse text nodes inside regular elements', () => {
|
||||||
expect(humanizeDom(parser.parse('<div>a</div>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<div>a</div>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'div', 0], [html.Text, 'a', 1, ['a']]
|
[html.Element, 'div', 0], [html.Text, 'a', 1]
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse text nodes inside <ng-template> elements', () => {
|
it('should parse text nodes inside <ng-template> elements', () => {
|
||||||
expect(humanizeDom(parser.parse('<ng-template>a</ng-template>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<ng-template>a</ng-template>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'ng-template', 0], [html.Text, 'a', 1, ['a']]
|
[html.Element, 'ng-template', 0], [html.Text, 'a', 1]
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse CDATA', () => {
|
it('should parse CDATA', () => {
|
||||||
expect(humanizeDom(parser.parse('<![CDATA[text]]>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<![CDATA[text]]>', 'TestComp'))).toEqual([
|
||||||
[html.Text, 'text', 0, ['text']]
|
[html.Text, 'text', 0]
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should normalize line endings within CDATA', () => {
|
it('should normalize line endings within CDATA', () => {
|
||||||
const parsed = parser.parse('<![CDATA[ line 1 \r\n line 2 ]]>', 'TestComp');
|
const parsed = parser.parse('<![CDATA[ line 1 \r\n line 2 ]]>', 'TestComp');
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Text, ' line 1 \n line 2 ', 0, [' line 1 \n line 2 ']],
|
[html.Text, ' line 1 \n line 2 ', 0],
|
||||||
]);
|
]);
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -76,8 +76,8 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
expect(humanizeDom(parser.parse('<link rel="author license" href="/about">', 'TestComp')))
|
expect(humanizeDom(parser.parse('<link rel="author license" href="/about">', 'TestComp')))
|
||||||
.toEqual([
|
.toEqual([
|
||||||
[html.Element, 'link', 0],
|
[html.Element, 'link', 0],
|
||||||
[html.Attribute, 'rel', 'author license', ['author license']],
|
[html.Attribute, 'rel', 'author license'],
|
||||||
[html.Attribute, 'href', '/about', ['/about']],
|
[html.Attribute, 'href', '/about'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -106,9 +106,9 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
it('should close void elements on text nodes', () => {
|
it('should close void elements on text nodes', () => {
|
||||||
expect(humanizeDom(parser.parse('<p>before<br>after</p>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<p>before<br>after</p>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'p', 0],
|
[html.Element, 'p', 0],
|
||||||
[html.Text, 'before', 1, ['before']],
|
[html.Text, 'before', 1],
|
||||||
[html.Element, 'br', 1],
|
[html.Element, 'br', 1],
|
||||||
[html.Text, 'after', 1, ['after']],
|
[html.Text, 'after', 1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -116,9 +116,9 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Element, 'p', 1],
|
[html.Element, 'p', 1],
|
||||||
[html.Text, '1', 2, ['1']],
|
[html.Text, '1', 2],
|
||||||
[html.Element, 'p', 1],
|
[html.Element, 'p', 1],
|
||||||
[html.Text, '2', 2, ['2']],
|
[html.Text, '2', 2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -200,12 +200,12 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
'TestComp')))
|
'TestComp')))
|
||||||
.toEqual([
|
.toEqual([
|
||||||
[html.Element, 'p', 0],
|
[html.Element, 'p', 0],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
[html.Element, 'textarea', 0],
|
[html.Element, 'textarea', 0],
|
||||||
[html.Element, 'pre', 0],
|
[html.Element, 'pre', 0],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
[html.Element, 'listing', 0],
|
[html.Element, 'listing', 0],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -214,28 +214,28 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
parsed = parser.parse('<title> line 1 \r\n line 2 </title>', 'TestComp');
|
parsed = parser.parse('<title> line 1 \r\n line 2 </title>', 'TestComp');
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'title', 0],
|
[html.Element, 'title', 0],
|
||||||
[html.Text, ' line 1 \n line 2 ', 1, [' line 1 \n line 2 ']],
|
[html.Text, ' line 1 \n line 2 ', 1],
|
||||||
]);
|
]);
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
|
||||||
parsed = parser.parse('<script> line 1 \r\n line 2 </script>', 'TestComp');
|
parsed = parser.parse('<script> line 1 \r\n line 2 </script>', 'TestComp');
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'script', 0],
|
[html.Element, 'script', 0],
|
||||||
[html.Text, ' line 1 \n line 2 ', 1, [' line 1 \n line 2 ']],
|
[html.Text, ' line 1 \n line 2 ', 1],
|
||||||
]);
|
]);
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
|
||||||
parsed = parser.parse('<div> line 1 \r\n line 2 </div>', 'TestComp');
|
parsed = parser.parse('<div> line 1 \r\n line 2 </div>', 'TestComp');
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, ' line 1 \n line 2 ', 1, [' line 1 \n line 2 ']],
|
[html.Text, ' line 1 \n line 2 ', 1],
|
||||||
]);
|
]);
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
|
||||||
parsed = parser.parse('<span> line 1 \r\n line 2 </span>', 'TestComp');
|
parsed = parser.parse('<span> line 1 \r\n line 2 </span>', 'TestComp');
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'span', 0],
|
[html.Element, 'span', 0],
|
||||||
[html.Text, ' line 1 \n line 2 ', 1, [' line 1 \n line 2 ']],
|
[html.Text, ' line 1 \n line 2 ', 1],
|
||||||
]);
|
]);
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -245,22 +245,8 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
it('should parse attributes on regular elements case sensitive', () => {
|
it('should parse attributes on regular elements case sensitive', () => {
|
||||||
expect(humanizeDom(parser.parse('<div kEy="v" key2=v2></div>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<div kEy="v" key2=v2></div>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Attribute, 'kEy', 'v', ['v']],
|
[html.Attribute, 'kEy', 'v'],
|
||||||
[html.Attribute, 'key2', 'v2', ['v2']],
|
[html.Attribute, 'key2', 'v2'],
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse attributes containing interpolation', () => {
|
|
||||||
expect(humanizeDom(parser.parse('<div foo="1{{message}}2"></div>', 'TestComp'))).toEqual([
|
|
||||||
[html.Element, 'div', 0],
|
|
||||||
[html.Attribute, 'foo', '1{{message}}2', ['1'], ['{{', 'message', '}}'], ['2']]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse attributes containing encoded entities', () => {
|
|
||||||
expect(humanizeDom(parser.parse('<div foo="&"></div>', 'TestComp'))).toEqual([
|
|
||||||
[html.Element, 'div', 0],
|
|
||||||
[html.Attribute, 'foo', '&', [''], ['&', '&'], ['']],
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -273,10 +259,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
html.Element, 'div', 0, '<div foo="{{&}}"></div>', '<div foo="{{&}}">',
|
html.Element, 'div', 0, '<div foo="{{&}}"></div>', '<div foo="{{&}}">',
|
||||||
'</div>'
|
'</div>'
|
||||||
],
|
],
|
||||||
[
|
[html.Attribute, 'foo', '{{&}}', 'foo="{{&}}"']
|
||||||
html.Attribute, 'foo', '{{&}}', [''], ['{{', '&', '}}'], [''],
|
|
||||||
'foo="{{&}}"'
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -285,7 +268,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
parser.parse('<div key=" \r\n line 1 \r\n line 2 "></div>', 'TestComp');
|
parser.parse('<div key=" \r\n line 1 \r\n line 2 "></div>', 'TestComp');
|
||||||
expect(humanizeDom(result)).toEqual([
|
expect(humanizeDom(result)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Attribute, 'key', ' \n line 1 \n line 2 ', [' \n line 1 \n line 2 ']],
|
[html.Attribute, 'key', ' \n line 1 \n line 2 '],
|
||||||
]);
|
]);
|
||||||
expect(result.errors).toEqual([]);
|
expect(result.errors).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -300,7 +283,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
it('should parse attributes on svg elements case sensitive', () => {
|
it('should parse attributes on svg elements case sensitive', () => {
|
||||||
expect(humanizeDom(parser.parse('<svg viewBox="0"></svg>', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<svg viewBox="0"></svg>', 'TestComp'))).toEqual([
|
||||||
[html.Element, ':svg:svg', 0],
|
[html.Element, ':svg:svg', 0],
|
||||||
[html.Attribute, 'viewBox', '0', ['0']],
|
[html.Attribute, 'viewBox', '0'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -308,14 +291,14 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
expect(humanizeDom(parser.parse('<ng-template k="v"></ng-template>', 'TestComp')))
|
expect(humanizeDom(parser.parse('<ng-template k="v"></ng-template>', 'TestComp')))
|
||||||
.toEqual([
|
.toEqual([
|
||||||
[html.Element, 'ng-template', 0],
|
[html.Element, 'ng-template', 0],
|
||||||
[html.Attribute, 'k', 'v', ['v']],
|
[html.Attribute, 'k', 'v'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support namespace', () => {
|
it('should support namespace', () => {
|
||||||
expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp'))).toEqual([
|
expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp'))).toEqual([
|
||||||
[html.Element, ':svg:use', 0],
|
[html.Element, ':svg:use', 0],
|
||||||
[html.Attribute, ':xlink:href', 'Port', ['Port']],
|
[html.Attribute, ':xlink:href', 'Port'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -342,23 +325,23 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, 'before', 1, ['before']],
|
[html.Text, 'before', 1],
|
||||||
[html.Expansion, 'messages.length', 'plural', 1],
|
[html.Expansion, 'messages.length', 'plural', 1],
|
||||||
[html.ExpansionCase, '=0', 2],
|
[html.ExpansionCase, '=0', 2],
|
||||||
[html.ExpansionCase, '=1', 2],
|
[html.ExpansionCase, '=1', 2],
|
||||||
[html.Text, 'after', 1, ['after']],
|
[html.Text, 'after', 1],
|
||||||
]);
|
]);
|
||||||
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'You have ', 0, ['You have ']],
|
[html.Text, 'You have ', 0],
|
||||||
[html.Element, 'b', 0],
|
[html.Element, 'b', 0],
|
||||||
[html.Text, 'no', 1, ['no']],
|
[html.Text, 'no', 1],
|
||||||
[html.Text, ' messages', 0, [' messages']],
|
[html.Text, ' messages', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
||||||
[html.Text, 'One {{message}}', 0, ['One '], ['{{', 'message', '}}'], ['']]
|
[html.Text, 'One {{message}}', 0]
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -380,20 +363,20 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, '\n ', 1, ['\n ']],
|
[html.Text, '\n ', 1],
|
||||||
[html.Expansion, '\n messages.length', 'plural', 1],
|
[html.Expansion, '\n messages.length', 'plural', 1],
|
||||||
[html.ExpansionCase, '=0', 2],
|
[html.ExpansionCase, '=0', 2],
|
||||||
[html.ExpansionCase, '=1', 2],
|
[html.ExpansionCase, '=1', 2],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
]);
|
]);
|
||||||
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'You have \nno\n messages', 0, ['You have \nno\n messages']],
|
[html.Text, 'You have \nno\n messages', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
||||||
[html.Text, 'One {{message}}', 0, ['One '], ['{{', 'message', '}}'], ['']]
|
[html.Text, 'One {{message}}', 0]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -413,20 +396,20 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, '\n ', 1, ['\n ']],
|
[html.Text, '\n ', 1],
|
||||||
[html.Expansion, '\r\n messages.length', 'plural', 1],
|
[html.Expansion, '\r\n messages.length', 'plural', 1],
|
||||||
[html.ExpansionCase, '=0', 2],
|
[html.ExpansionCase, '=0', 2],
|
||||||
[html.ExpansionCase, '=1', 2],
|
[html.ExpansionCase, '=1', 2],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
]);
|
]);
|
||||||
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'You have \nno\n messages', 0, ['You have \nno\n messages']],
|
[html.Text, 'You have \nno\n messages', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
||||||
[html.Text, 'One {{message}}', 0, ['One '], ['{{', 'message', '}}'], ['']]
|
[html.Text, 'One {{message}}', 0]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -450,20 +433,20 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, '\n ', 1, ['\n ']],
|
[html.Text, '\n ', 1],
|
||||||
[html.Expansion, '\n messages.length', 'plural', 1],
|
[html.Expansion, '\n messages.length', 'plural', 1],
|
||||||
[html.ExpansionCase, '=0', 2],
|
[html.ExpansionCase, '=0', 2],
|
||||||
[html.ExpansionCase, '=1', 2],
|
[html.ExpansionCase, '=1', 2],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
]);
|
]);
|
||||||
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'You have \nno\n messages', 0, ['You have \nno\n messages']],
|
[html.Text, 'You have \nno\n messages', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
||||||
[html.Text, 'One {{message}}', 0, ['One '], ['{{', 'message', '}}'], ['']]
|
[html.Text, 'One {{message}}', 0]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -483,20 +466,20 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeDom(parsed)).toEqual([
|
expect(humanizeDom(parsed)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Text, '\n ', 1, ['\n ']],
|
[html.Text, '\n ', 1],
|
||||||
[html.Expansion, '\r\n messages.length', 'plural', 1],
|
[html.Expansion, '\r\n messages.length', 'plural', 1],
|
||||||
[html.ExpansionCase, '=0', 2],
|
[html.ExpansionCase, '=0', 2],
|
||||||
[html.ExpansionCase, '=1', 2],
|
[html.ExpansionCase, '=1', 2],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
]);
|
]);
|
||||||
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
const cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'You have \nno\n messages', 0, ['You have \nno\n messages']],
|
[html.Text, 'You have \nno\n messages', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(cases[1].expression, []))).toEqual([
|
||||||
[html.Text, 'One {{message}}', 0, ['One '], ['{{', 'message', '}}'], ['']]
|
[html.Text, 'One {{message}}', 0]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -529,7 +512,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
expect(humanizeDom(new ParseTreeResult(firstCase.expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(firstCase.expression, []))).toEqual([
|
||||||
[html.Expansion, 'p.gender', 'select', 0],
|
[html.Expansion, 'p.gender', 'select', 0],
|
||||||
[html.ExpansionCase, 'male', 1],
|
[html.ExpansionCase, 'male', 1],
|
||||||
[html.Text, ' ', 0, [' ']],
|
[html.Text, ' ', 0],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -557,10 +540,10 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
const expansion = parsed.rootNodes[0] as html.Expansion;
|
const expansion = parsed.rootNodes[0] as html.Expansion;
|
||||||
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'zero \n ', 0, ['zero \n ']],
|
[html.Text, 'zero \n ', 0],
|
||||||
[html.Expansion, '\n p.gender', 'select', 0],
|
[html.Expansion, '\n p.gender', 'select', 0],
|
||||||
[html.ExpansionCase, 'male', 1],
|
[html.ExpansionCase, 'male', 1],
|
||||||
[html.Text, '\n ', 0, ['\n ']],
|
[html.Text, '\n ', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -586,10 +569,10 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
const expansion = parsed.rootNodes[0] as html.Expansion;
|
const expansion = parsed.rootNodes[0] as html.Expansion;
|
||||||
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'zero \n ', 0, ['zero \n ']],
|
[html.Text, 'zero \n ', 0],
|
||||||
[html.Expansion, '\r\n p.gender', 'select', 0],
|
[html.Expansion, '\r\n p.gender', 'select', 0],
|
||||||
[html.ExpansionCase, 'male', 1],
|
[html.ExpansionCase, 'male', 1],
|
||||||
[html.Text, '\n ', 0, ['\n ']],
|
[html.Text, '\n ', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(parsed.errors).toEqual([]);
|
expect(parsed.errors).toEqual([]);
|
||||||
|
@ -615,10 +598,10 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
const expansion = parsed.rootNodes[0] as html.Expansion;
|
const expansion = parsed.rootNodes[0] as html.Expansion;
|
||||||
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
expect(humanizeDom(new ParseTreeResult(expansion.cases[0].expression, []))).toEqual([
|
||||||
[html.Text, 'zero \n ', 0, ['zero \n ']],
|
[html.Text, 'zero \n ', 0],
|
||||||
[html.Expansion, '\r\n p.gender', 'select', 0],
|
[html.Expansion, '\r\n p.gender', 'select', 0],
|
||||||
[html.ExpansionCase, 'male', 1],
|
[html.ExpansionCase, 'male', 1],
|
||||||
[html.Text, '\n ', 0, ['\n ']],
|
[html.Text, '\n ', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
@ -687,11 +670,11 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
'<div [prop]="v1" (e)="do()" attr="v2" noValue>\na\n</div>',
|
'<div [prop]="v1" (e)="do()" attr="v2" noValue>\na\n</div>',
|
||||||
'<div [prop]="v1" (e)="do()" attr="v2" noValue>', '</div>'
|
'<div [prop]="v1" (e)="do()" attr="v2" noValue>', '</div>'
|
||||||
],
|
],
|
||||||
[html.Attribute, '[prop]', 'v1', ['v1'], '[prop]="v1"'],
|
[html.Attribute, '[prop]', 'v1', '[prop]="v1"'],
|
||||||
[html.Attribute, '(e)', 'do()', ['do()'], '(e)="do()"'],
|
[html.Attribute, '(e)', 'do()', '(e)="do()"'],
|
||||||
[html.Attribute, 'attr', 'v2', ['v2'], 'attr="v2"'],
|
[html.Attribute, 'attr', 'v2', 'attr="v2"'],
|
||||||
[html.Attribute, 'noValue', '', 'noValue'],
|
[html.Attribute, 'noValue', '', 'noValue'],
|
||||||
[html.Text, '\na\n', 1, ['\na\n'], '\na\n'],
|
[html.Text, '\na\n', 1, '\na\n'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -712,9 +695,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
'{{&}}' +
|
'{{&}}' +
|
||||||
'{{▾}}' +
|
'{{▾}}' +
|
||||||
'{{▾}}' +
|
'{{▾}}' +
|
||||||
'{{&unknown;}}' +
|
|
||||||
'{{& (no semi-colon)}}' +
|
'{{& (no semi-colon)}}' +
|
||||||
'{{&#xyz; (invalid hex)}}' +
|
|
||||||
'{{BE; (invalid decimal)}}',
|
'{{BE; (invalid decimal)}}',
|
||||||
'TestComp')))
|
'TestComp')))
|
||||||
.toEqual([[
|
.toEqual([[
|
||||||
|
@ -722,48 +703,17 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
'{{&}}' +
|
'{{&}}' +
|
||||||
'{{\u25BE}}' +
|
'{{\u25BE}}' +
|
||||||
'{{\u25BE}}' +
|
'{{\u25BE}}' +
|
||||||
'{{&unknown;}}' +
|
|
||||||
'{{& (no semi-colon)}}' +
|
'{{& (no semi-colon)}}' +
|
||||||
'{{&#xyz; (invalid hex)}}' +
|
|
||||||
'{{BE; (invalid decimal)}}',
|
'{{BE; (invalid decimal)}}',
|
||||||
0,
|
0,
|
||||||
[''],
|
|
||||||
['{{', '&', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', '▾', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', '▾', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', '&unknown;', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', '& (no semi-colon)', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', '&#xyz; (invalid hex)', '}}'],
|
|
||||||
[''],
|
|
||||||
['{{', 'BE; (invalid decimal)', '}}'],
|
|
||||||
[''],
|
|
||||||
'{{&}}' +
|
'{{&}}' +
|
||||||
'{{▾}}' +
|
'{{▾}}' +
|
||||||
'{{▾}}' +
|
'{{▾}}' +
|
||||||
'{{&unknown;}}' +
|
|
||||||
'{{& (no semi-colon)}}' +
|
'{{& (no semi-colon)}}' +
|
||||||
'{{&#xyz; (invalid hex)}}' +
|
|
||||||
'{{BE; (invalid decimal)}}',
|
'{{BE; (invalid decimal)}}',
|
||||||
]]);
|
]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support interpolations in text', () => {
|
|
||||||
expect(
|
|
||||||
humanizeDomSourceSpans(parser.parse('<div> pre {{ value }} post </div>', 'TestComp')))
|
|
||||||
.toEqual([
|
|
||||||
[html.Element, 'div', 0, '<div> pre {{ value }} post </div>', '<div>', '</div>'],
|
|
||||||
[
|
|
||||||
html.Text, ' pre {{ value }} post ', 1, [' pre '], ['{{', ' value ', '}}'],
|
|
||||||
[' post '], ' pre {{ value }} post '
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set the end source span for void elements', () => {
|
it('should not set the end source span for void elements', () => {
|
||||||
expect(humanizeDomSourceSpans(parser.parse('<div><br></div>', 'TestComp'))).toEqual([
|
expect(humanizeDomSourceSpans(parser.parse('<div><br></div>', 'TestComp'))).toEqual([
|
||||||
[html.Element, 'div', 0, '<div><br></div>', '<div>', '</div>'],
|
[html.Element, 'div', 0, '<div><br></div>', '<div>', '</div>'],
|
||||||
|
@ -808,10 +758,10 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
html.Element, 'input', 0, '<input type="text" />', '<input type="text" />',
|
html.Element, 'input', 0, '<input type="text" />', '<input type="text" />',
|
||||||
'<input type="text" />'
|
'<input type="text" />'
|
||||||
],
|
],
|
||||||
[html.Attribute, 'type', 'text', ['text'], 'type="text"'],
|
[html.Attribute, 'type', 'text', 'type="text"'],
|
||||||
[html.Text, '\n\n\n ', 0, ['\n\n\n '], ''],
|
[html.Text, '\n\n\n ', 0, ''],
|
||||||
[html.Element, 'span', 0, '<span>\n</span>', '<span>', '</span>'],
|
[html.Element, 'span', 0, '<span>\n</span>', '<span>', '</span>'],
|
||||||
[html.Text, '\n', 1, ['\n'], ''],
|
[html.Text, '\n', 1, ''],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -824,9 +774,9 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
.toEqual([
|
.toEqual([
|
||||||
[html.Element, 'div', 0, '<div><li>A<li>B</div>', '<div>', '</div>'],
|
[html.Element, 'div', 0, '<div><li>A<li>B</div>', '<div>', '</div>'],
|
||||||
[html.Element, 'li', 1, '<li>', '<li>', null],
|
[html.Element, 'li', 1, '<li>', '<li>', null],
|
||||||
[html.Text, 'A', 2, ['A'], 'A'],
|
[html.Text, 'A', 2, 'A'],
|
||||||
[html.Element, 'li', 1, '<li>', '<li>', null],
|
[html.Element, 'li', 1, '<li>', '<li>', null],
|
||||||
[html.Text, 'B', 2, ['B'], 'B'],
|
[html.Text, 'B', 2, 'B'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -864,7 +814,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
describe('visitor', () => {
|
describe('visitor', () => {
|
||||||
it('should visit text nodes', () => {
|
it('should visit text nodes', () => {
|
||||||
const result = humanizeDom(parser.parse('text', 'TestComp'));
|
const result = humanizeDom(parser.parse('text', 'TestComp'));
|
||||||
expect(result).toEqual([[html.Text, 'text', 0, ['text']]]);
|
expect(result).toEqual([[html.Text, 'text', 0]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visit element nodes', () => {
|
it('should visit element nodes', () => {
|
||||||
|
@ -874,7 +824,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
it('should visit attribute nodes', () => {
|
it('should visit attribute nodes', () => {
|
||||||
const result = humanizeDom(parser.parse('<div id="foo"></div>', 'TestComp'));
|
const result = humanizeDom(parser.parse('<div id="foo"></div>', 'TestComp'));
|
||||||
expect(result).toContain([html.Attribute, 'id', 'foo', ['foo']]);
|
expect(result).toContain([html.Attribute, 'id', 'foo']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visit all nodes', () => {
|
it('should visit all nodes', () => {
|
||||||
|
@ -982,7 +932,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeNodes(rootNodes, true)).toEqual([
|
expect(humanizeNodes(rootNodes, true)).toEqual([
|
||||||
[html.Element, 'div', 0, '<div class="hi" sty', '<div class="hi" sty', null],
|
[html.Element, 'div', 0, '<div class="hi" sty', '<div class="hi" sty', null],
|
||||||
[html.Attribute, 'class', 'hi', ['hi'], 'class="hi"'],
|
[html.Attribute, 'class', 'hi', 'class="hi"'],
|
||||||
[html.Attribute, 'sty', '', 'sty'],
|
[html.Attribute, 'sty', '', 'sty'],
|
||||||
[html.Element, 'span', 0, '<span></span>', '<span>', '</span>'],
|
[html.Element, 'span', 0, '<span></span>', '<span>', '</span>'],
|
||||||
]);
|
]);
|
||||||
|
@ -997,7 +947,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
|
||||||
|
|
||||||
expect(humanizeNodes(rootNodes, true)).toEqual([
|
expect(humanizeNodes(rootNodes, true)).toEqual([
|
||||||
[html.Element, 'div', 0, '<div ', '<div ', null],
|
[html.Element, 'div', 0, '<div ', '<div ', null],
|
||||||
[html.Text, '"', 0, ['"'], '"'],
|
[html.Text, '"', 0, '"'],
|
||||||
[html.Element, 'span', 0, '<span></span>', '<span>', '</span>'],
|
[html.Element, 'span', 0, '<span></span>', '<span>', '</span>'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as html from '../../src/ml_parser/ast';
|
import * as html from '../../src/ml_parser/ast';
|
||||||
import {NGSP_UNICODE} from '../../src/ml_parser/entities';
|
|
||||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||||
import {PRESERVE_WS_ATTR_NAME, removeWhitespaces} from '../../src/ml_parser/html_whitespaces';
|
import {PRESERVE_WS_ATTR_NAME, removeWhitespaces} from '../../src/ml_parser/html_whitespaces';
|
||||||
import {TokenizeOptions} from '../../src/ml_parser/lexer';
|
import {TokenizeOptions} from '../../src/ml_parser/lexer';
|
||||||
|
@ -53,86 +52,48 @@ import {humanizeDom} from './ast_spec_utils';
|
||||||
expect(parseAndRemoveWS('<div><span>foo</span>&ngsp;<span>bar</span></div>')).toEqual([
|
expect(parseAndRemoveWS('<div><span>foo</span>&ngsp;<span>bar</span></div>')).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Element, 'span', 1],
|
[html.Element, 'span', 1],
|
||||||
[html.Text, 'foo', 2, ['foo']],
|
[html.Text, 'foo', 2],
|
||||||
[html.Text, ' ', 1, [''], [NGSP_UNICODE, '&ngsp;'], ['']],
|
[html.Text, ' ', 1],
|
||||||
[html.Element, 'span', 1],
|
[html.Element, 'span', 1],
|
||||||
[html.Text, 'bar', 2, ['bar']],
|
[html.Text, 'bar', 2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should replace multiple whitespaces with one space', () => {
|
it('should replace multiple whitespaces with one space', () => {
|
||||||
expect(parseAndRemoveWS('\n\n\nfoo\t\t\t')).toEqual([[html.Text, ' foo ', 0, [' foo ']]]);
|
expect(parseAndRemoveWS('\n\n\nfoo\t\t\t')).toEqual([[html.Text, ' foo ', 0]]);
|
||||||
expect(parseAndRemoveWS(' \n foo \t ')).toEqual([[html.Text, ' foo ', 0, [' foo ']]]);
|
expect(parseAndRemoveWS(' \n foo \t ')).toEqual([[html.Text, ' foo ', 0]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not replace ', () => {
|
it('should not replace ', () => {
|
||||||
expect(parseAndRemoveWS(' ')).toEqual([
|
expect(parseAndRemoveWS(' ')).toEqual([[html.Text, '\u00a0', 0]]);
|
||||||
[html.Text, '\u00a0', 0, [''], ['\u00a0', ' '], ['']]
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not replace sequences of ', () => {
|
it('should not replace sequences of ', () => {
|
||||||
expect(parseAndRemoveWS(' foo ')).toEqual([[
|
expect(parseAndRemoveWS(' foo ')).toEqual([
|
||||||
html.Text,
|
[html.Text, '\u00a0\u00a0foo\u00a0\u00a0', 0]
|
||||||
'\u00a0\u00a0foo\u00a0\u00a0',
|
]);
|
||||||
0,
|
|
||||||
[''],
|
|
||||||
['\u00a0', ' '],
|
|
||||||
[''],
|
|
||||||
['\u00a0', ' '],
|
|
||||||
['foo'],
|
|
||||||
['\u00a0', ' '],
|
|
||||||
[''],
|
|
||||||
['\u00a0', ' '],
|
|
||||||
[''],
|
|
||||||
]]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not replace single tab and newline with spaces', () => {
|
it('should not replace single tab and newline with spaces', () => {
|
||||||
expect(parseAndRemoveWS('\nfoo')).toEqual([[html.Text, '\nfoo', 0, ['\nfoo']]]);
|
expect(parseAndRemoveWS('\nfoo')).toEqual([[html.Text, '\nfoo', 0]]);
|
||||||
expect(parseAndRemoveWS('\tfoo')).toEqual([[html.Text, '\tfoo', 0, ['\tfoo']]]);
|
expect(parseAndRemoveWS('\tfoo')).toEqual([[html.Text, '\tfoo', 0]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should preserve single whitespaces between interpolations', () => {
|
it('should preserve single whitespaces between interpolations', () => {
|
||||||
expect(parseAndRemoveWS(`{{fooExp}} {{barExp}}`)).toEqual([[
|
expect(parseAndRemoveWS(`{{fooExp}} {{barExp}}`)).toEqual([
|
||||||
html.Text,
|
[html.Text, '{{fooExp}} {{barExp}}', 0],
|
||||||
'{{fooExp}} {{barExp}}',
|
]);
|
||||||
0,
|
|
||||||
[''],
|
|
||||||
['{{', 'fooExp', '}}'],
|
|
||||||
[' '],
|
|
||||||
['{{', 'barExp', '}}'],
|
|
||||||
[''],
|
|
||||||
]]);
|
|
||||||
expect(parseAndRemoveWS(`{{fooExp}}\t{{barExp}}`)).toEqual([
|
expect(parseAndRemoveWS(`{{fooExp}}\t{{barExp}}`)).toEqual([
|
||||||
[
|
[html.Text, '{{fooExp}}\t{{barExp}}', 0],
|
||||||
html.Text,
|
|
||||||
'{{fooExp}}\t{{barExp}}',
|
|
||||||
0,
|
|
||||||
[''],
|
|
||||||
['{{', 'fooExp', '}}'],
|
|
||||||
['\t'],
|
|
||||||
['{{', 'barExp', '}}'],
|
|
||||||
[''],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
expect(parseAndRemoveWS(`{{fooExp}}\n{{barExp}}`)).toEqual([
|
expect(parseAndRemoveWS(`{{fooExp}}\n{{barExp}}`)).toEqual([
|
||||||
[
|
[html.Text, '{{fooExp}}\n{{barExp}}', 0],
|
||||||
html.Text,
|
|
||||||
'{{fooExp}}\n{{barExp}}',
|
|
||||||
0,
|
|
||||||
[''],
|
|
||||||
['{{', 'fooExp', '}}'],
|
|
||||||
['\n'],
|
|
||||||
['{{', 'barExp', '}}'],
|
|
||||||
[''],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should preserve whitespaces around interpolations', () => {
|
it('should preserve whitespaces around interpolations', () => {
|
||||||
expect(parseAndRemoveWS(` {{exp}} `)).toEqual([
|
expect(parseAndRemoveWS(` {{exp}} `)).toEqual([
|
||||||
[html.Text, ' {{exp}} ', 0, [' '], ['{{', 'exp', '}}'], [' ']]
|
[html.Text, ' {{exp}} ', 0],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -140,10 +101,10 @@ import {humanizeDom} from './ast_spec_utils';
|
||||||
expect(parseAndRemoveWS(`<span> {a, b, =4 {c}} </span>`, {tokenizeExpansionForms: true}))
|
expect(parseAndRemoveWS(`<span> {a, b, =4 {c}} </span>`, {tokenizeExpansionForms: true}))
|
||||||
.toEqual([
|
.toEqual([
|
||||||
[html.Element, 'span', 0],
|
[html.Element, 'span', 0],
|
||||||
[html.Text, ' ', 1, [' ']],
|
[html.Text, ' ', 1],
|
||||||
[html.Expansion, 'a', 'b', 1],
|
[html.Expansion, 'a', 'b', 1],
|
||||||
[html.ExpansionCase, '=4', 2],
|
[html.ExpansionCase, '=4', 2],
|
||||||
[html.Text, ' ', 1, [' ']],
|
[html.Text, ' ', 1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -151,17 +112,17 @@ import {humanizeDom} from './ast_spec_utils';
|
||||||
expect(parseAndRemoveWS(`<pre><strong>foo</strong>\n<strong>bar</strong></pre>`)).toEqual([
|
expect(parseAndRemoveWS(`<pre><strong>foo</strong>\n<strong>bar</strong></pre>`)).toEqual([
|
||||||
[html.Element, 'pre', 0],
|
[html.Element, 'pre', 0],
|
||||||
[html.Element, 'strong', 1],
|
[html.Element, 'strong', 1],
|
||||||
[html.Text, 'foo', 2, ['foo']],
|
[html.Text, 'foo', 2],
|
||||||
[html.Text, '\n', 1, ['\n']],
|
[html.Text, '\n', 1],
|
||||||
[html.Element, 'strong', 1],
|
[html.Element, 'strong', 1],
|
||||||
[html.Text, 'bar', 2, ['bar']],
|
[html.Text, 'bar', 2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip whitespace trimming in <textarea>', () => {
|
it('should skip whitespace trimming in <textarea>', () => {
|
||||||
expect(parseAndRemoveWS(`<textarea>foo\n\n bar</textarea>`)).toEqual([
|
expect(parseAndRemoveWS(`<textarea>foo\n\n bar</textarea>`)).toEqual([
|
||||||
[html.Element, 'textarea', 0],
|
[html.Element, 'textarea', 0],
|
||||||
[html.Text, 'foo\n\n bar', 1, ['foo\n\n bar']],
|
[html.Text, 'foo\n\n bar', 1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -170,7 +131,7 @@ import {humanizeDom} from './ast_spec_utils';
|
||||||
expect(parseAndRemoveWS(`<div ${PRESERVE_WS_ATTR_NAME}><img> <img></div>`)).toEqual([
|
expect(parseAndRemoveWS(`<div ${PRESERVE_WS_ATTR_NAME}><img> <img></div>`)).toEqual([
|
||||||
[html.Element, 'div', 0],
|
[html.Element, 'div', 0],
|
||||||
[html.Element, 'img', 1],
|
[html.Element, 'img', 1],
|
||||||
[html.Text, ' ', 1, [' ']],
|
[html.Text, ' ', 1],
|
||||||
[html.Element, 'img', 1],
|
[html.Element, 'img', 1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,9 +29,9 @@ import {humanizeNodes} from './ast_spec_utils';
|
||||||
[html.Attribute, '[ngPlural]', 'messages.length'],
|
[html.Attribute, '[ngPlural]', 'messages.length'],
|
||||||
[html.Element, 'ng-template', 1],
|
[html.Element, 'ng-template', 1],
|
||||||
[html.Attribute, 'ngPluralCase', '=0'],
|
[html.Attribute, 'ngPluralCase', '=0'],
|
||||||
[html.Text, 'zero', 2, ['zero']],
|
[html.Text, 'zero', 2],
|
||||||
[html.Element, 'b', 2],
|
[html.Element, 'b', 2],
|
||||||
[html.Text, 'bold', 3, ['bold']],
|
[html.Text, 'bold', 3],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ import {humanizeNodes} from './ast_spec_utils';
|
||||||
[html.Attribute, '[ngSwitch]', 'p.gender'],
|
[html.Attribute, '[ngSwitch]', 'p.gender'],
|
||||||
[html.Element, 'ng-template', 3],
|
[html.Element, 'ng-template', 3],
|
||||||
[html.Attribute, 'ngSwitchCase', 'male'],
|
[html.Attribute, 'ngSwitchCase', 'male'],
|
||||||
[html.Text, 'm', 4, ['m']],
|
[html.Text, 'm', 4],
|
||||||
[html.Text, ' ', 2, [' ']],
|
[html.Text, ' ', 2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ import {humanizeNodes} from './ast_spec_utils';
|
||||||
[html.Attribute, '[ngSwitch]', 'person.gender'],
|
[html.Attribute, '[ngSwitch]', 'person.gender'],
|
||||||
[html.Element, 'ng-template', 1],
|
[html.Element, 'ng-template', 1],
|
||||||
[html.Attribute, 'ngSwitchCase', 'male'],
|
[html.Attribute, 'ngSwitchCase', 'male'],
|
||||||
[html.Text, 'm', 2, ['m']],
|
[html.Text, 'm', 2],
|
||||||
[html.Element, 'ng-template', 1],
|
[html.Element, 'ng-template', 1],
|
||||||
[html.Attribute, 'ngSwitchDefault', ''],
|
[html.Attribute, 'ngSwitchDefault', ''],
|
||||||
[html.Text, 'default', 2, ['default']],
|
[html.Text, 'default', 2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ import {humanizeNodes} from './ast_spec_utils';
|
||||||
[html.Attribute, '[ngSwitch]', 'a'],
|
[html.Attribute, '[ngSwitch]', 'a'],
|
||||||
[html.Element, 'ng-template', 3],
|
[html.Element, 'ng-template', 3],
|
||||||
[html.Attribute, 'ngSwitchCase', '=4'],
|
[html.Attribute, 'ngSwitchCase', '=4'],
|
||||||
[html.Text, 'c', 4, ['c']],
|
[html.Text, 'c', 4],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue