fix(compiler): do not lex `}}` when interpolation is disabled (#13531)
* doc(compiler): fix the ICU expander API docs * test(compiler): add lexer and parser specs * fix(compiler): do not lex `}}` when interpolation is disabled fix #13525
This commit is contained in:
parent
a23fa94ca8
commit
e78508507d
|
@ -30,9 +30,9 @@ const PLURAL_CASES: string[] = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|||
*
|
||||
* ```
|
||||
* <ng-container [ngPlural]="messages.length">
|
||||
* <template ngPluralCase="=0">zero</ng-container>
|
||||
* <template ngPluralCase="=1">one</ng-container>
|
||||
* <template ngPluralCase="other">more than one</ng-container>
|
||||
* <template ngPluralCase="=0">zero</template>
|
||||
* <template ngPluralCase="=1">one</template>
|
||||
* <template ngPluralCase="other">more than one</template>
|
||||
* </ng-container>
|
||||
* ```
|
||||
*/
|
||||
|
|
|
@ -133,7 +133,7 @@ class _Tokenizer {
|
|||
} else {
|
||||
this._consumeTagOpen(start);
|
||||
}
|
||||
} else if (!this._tokenizeIcu || !this._tokenizeExpansionForm()) {
|
||||
} else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
|
||||
this._consumeText();
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -586,8 +586,8 @@ class _Tokenizer {
|
|||
parts.push(this._interpolationConfig.start);
|
||||
this._inInterpolation = true;
|
||||
} else if (
|
||||
this._interpolationConfig && this._attemptStr(this._interpolationConfig.end) &&
|
||||
this._inInterpolation) {
|
||||
this._interpolationConfig && this._inInterpolation &&
|
||||
this._attemptStr(this._interpolationConfig.end)) {
|
||||
parts.push(this._interpolationConfig.end);
|
||||
this._inInterpolation = false;
|
||||
} else {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {beforeEach, describe, expect, it} from '../../../core/testing/testing_internal';
|
||||
import * as html from '../../src/ml_parser/ast';
|
||||
import {HtmlParser, ParseTreeResult, TreeError} from '../../src/ml_parser/html_parser';
|
||||
import {TokenType} from '../../src/ml_parser/lexer';
|
||||
|
@ -304,6 +303,18 @@ export function main() {
|
|||
]))).toEqual([[html.Text, 'One {{message}}', 0]]);
|
||||
});
|
||||
|
||||
it('should parse out expansion forms', () => {
|
||||
const parsed =
|
||||
parser.parse(`<div><span>{a, plural, =0 {b}}</span></div>`, 'TestComp', true);
|
||||
|
||||
expect(humanizeDom(parsed)).toEqual([
|
||||
[html.Element, 'div', 0],
|
||||
[html.Element, 'span', 1],
|
||||
[html.Expansion, 'a', 'plural', 2],
|
||||
[html.ExpansionCase, '=0', 3],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse out nested expansion forms', () => {
|
||||
const parsed = parser.parse(
|
||||
`{messages.length, plural, =0 { {p.gender, select, male {m}} }}`, 'TestComp', true);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {describe, expect, it} from '../../../core/testing/testing_internal';
|
||||
import * as html from '../../src/ml_parser/ast';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
import {ExpansionResult, expandNodes} from '../../src/ml_parser/icu_ast_expander';
|
||||
|
@ -96,6 +95,20 @@ export function main() {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion form as a tag single child', () => {
|
||||
const res = expand(`<div><span>{a, b, =4 {c}}</span></div>`);
|
||||
|
||||
expect(humanizeNodes(res.nodes)).toEqual([
|
||||
[html.Element, 'div', 0],
|
||||
[html.Element, 'span', 1],
|
||||
[html.Element, 'ng-container', 2],
|
||||
[html.Attribute, '[ngSwitch]', 'a'],
|
||||
[html.Element, 'template', 3],
|
||||
[html.Attribute, 'ngSwitchCase', '=4'],
|
||||
[html.Text, 'c', 4],
|
||||
]);
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
it('should error on unknown plural cases', () => {
|
||||
expect(humanizeErrors(expand('{n, plural, unknown {-}}').errors)).toEqual([
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {describe, expect, it} from '../../../core/testing/testing_internal';
|
||||
import {getHtmlTagDefinition} from '../../src/ml_parser/html_tags';
|
||||
import {InterpolationConfig} from '../../src/ml_parser/interpolation_config';
|
||||
import * as lex from '../../src/ml_parser/lexer';
|
||||
|
@ -524,7 +523,15 @@ export function main() {
|
|||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should treat expansion form as text when they are not parsed', () => {
|
||||
expect(tokenizeAndHumanizeParts('<span>{a, b, =4 {c}}</span>', false)).toEqual([
|
||||
[lex.TokenType.TAG_OPEN_START, null, 'span'],
|
||||
[lex.TokenType.TAG_OPEN_END],
|
||||
[lex.TokenType.TEXT, '{a, b, =4 {c}}'],
|
||||
[lex.TokenType.TAG_CLOSE, null, 'span'],
|
||||
[lex.TokenType.EOF],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('raw text', () => {
|
||||
|
@ -672,6 +679,26 @@ export function main() {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion form as a tag single child', () => {
|
||||
expect(tokenizeAndHumanizeParts('<div><span>{a, b, =4 {c}}</span></div>', true)).toEqual([
|
||||
[lex.TokenType.TAG_OPEN_START, null, 'div'],
|
||||
[lex.TokenType.TAG_OPEN_END],
|
||||
[lex.TokenType.TAG_OPEN_START, null, 'span'],
|
||||
[lex.TokenType.TAG_OPEN_END],
|
||||
[lex.TokenType.EXPANSION_FORM_START],
|
||||
[lex.TokenType.RAW_TEXT, 'a'],
|
||||
[lex.TokenType.RAW_TEXT, 'b'],
|
||||
[lex.TokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[lex.TokenType.EXPANSION_CASE_EXP_START],
|
||||
[lex.TokenType.TEXT, 'c'],
|
||||
[lex.TokenType.EXPANSION_CASE_EXP_END],
|
||||
[lex.TokenType.EXPANSION_FORM_END],
|
||||
[lex.TokenType.TAG_CLOSE, null, 'span'],
|
||||
[lex.TokenType.TAG_CLOSE, null, 'div'],
|
||||
[lex.TokenType.EOF],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion forms with elements in it', () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four <b>a</b>}}', true)).toEqual([
|
||||
[lex.TokenType.EXPANSION_FORM_START],
|
||||
|
|
Loading…
Reference in New Issue