feat(HtmlLexer): add support for alphabetic cases
This commit is contained in:
@ -485,62 +485,98 @@ export function main() {
|
||||
|
||||
});
|
||||
|
||||
describe('expansion forms', () => {
|
||||
it('should parse an expansion form', () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four} =5 {five} }', true)).toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START], [HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'], [HtmlTokenType.EXPANSION_CASE_VALUE, '4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START], [HtmlTokenType.TEXT, 'four'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_CASE_VALUE, '5'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START], [HtmlTokenType.TEXT, 'five'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
describe("expansion forms", () => {
|
||||
it("should parse an expansion form", () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four} =5 {five} foo {bar} }', true))
|
||||
.toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'four'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=5'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'five'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, 'foo'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'bar'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion form with text elements surrounding it', () => {
|
||||
expect(tokenizeAndHumanizeParts('before{one.two, three, =4 {four}}after', true)).toEqual([
|
||||
[HtmlTokenType.TEXT, 'before'], [HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'], [HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '4'], [HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'four'], [HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END], [HtmlTokenType.TEXT, 'after'], [HtmlTokenType.EOF]
|
||||
]);
|
||||
it("should parse an expansion form with text elements surrounding it", () => {
|
||||
expect(tokenizeAndHumanizeParts('before{one.two, three, =4 {four}}after', true))
|
||||
.toEqual([
|
||||
[HtmlTokenType.TEXT, "before"],
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'four'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.TEXT, "after"],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion forms with elements in it', () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four <b>a</b>}}', true)).toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START], [HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'], [HtmlTokenType.EXPANSION_CASE_VALUE, '4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START], [HtmlTokenType.TEXT, 'four '],
|
||||
[HtmlTokenType.TAG_OPEN_START, null, 'b'], [HtmlTokenType.TAG_OPEN_END],
|
||||
[HtmlTokenType.TEXT, 'a'], [HtmlTokenType.TAG_CLOSE, null, 'b'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
it("should parse an expansion forms with elements in it", () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four <b>a</b>}}', true))
|
||||
.toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'four '],
|
||||
[HtmlTokenType.TAG_OPEN_START, null, 'b'],
|
||||
[HtmlTokenType.TAG_OPEN_END],
|
||||
[HtmlTokenType.TEXT, 'a'],
|
||||
[HtmlTokenType.TAG_CLOSE, null, 'b'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse an expansion forms with interpolation in it', () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four {{a}}}}', true)).toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START], [HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'], [HtmlTokenType.EXPANSION_CASE_VALUE, '4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START], [HtmlTokenType.TEXT, 'four {{a}}'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
it("should parse an expansion forms with interpolation in it", () => {
|
||||
expect(tokenizeAndHumanizeParts('{one.two, three, =4 {four {{a}}}}', true))
|
||||
.toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'four {{a}}'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EOF]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse nested expansion forms', () => {
|
||||
it("should parse nested expansion forms", () => {
|
||||
expect(tokenizeAndHumanizeParts(`{one.two, three, =4 { {xx, yy, =x {one}} }}`, true))
|
||||
.toEqual([
|
||||
[HtmlTokenType.EXPANSION_FORM_START], [HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'], [HtmlTokenType.EXPANSION_CASE_VALUE, '4'],
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'one.two'],
|
||||
[HtmlTokenType.RAW_TEXT, 'three'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=4'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
|
||||
[HtmlTokenType.EXPANSION_FORM_START], [HtmlTokenType.RAW_TEXT, 'xx'],
|
||||
[HtmlTokenType.RAW_TEXT, 'yy'], [HtmlTokenType.EXPANSION_CASE_VALUE, 'x'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START], [HtmlTokenType.TEXT, 'one'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_START],
|
||||
[HtmlTokenType.RAW_TEXT, 'xx'],
|
||||
[HtmlTokenType.RAW_TEXT, 'yy'],
|
||||
[HtmlTokenType.EXPANSION_CASE_VALUE, '=x'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_START],
|
||||
[HtmlTokenType.TEXT, 'one'],
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END],
|
||||
[HtmlTokenType.EXPANSION_FORM_END],
|
||||
[HtmlTokenType.TEXT, ' '],
|
||||
|
||||
[HtmlTokenType.EXPANSION_CASE_EXP_END], [HtmlTokenType.EXPANSION_FORM_END],
|
||||
|
@ -1,9 +1,15 @@
|
||||
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '@angular/compiler/src/html_ast';
|
||||
import {HtmlTokenType} from '@angular/compiler/src/html_lexer';
|
||||
import {HtmlParseTreeResult, HtmlParser, HtmlTreeError} from '@angular/compiler/src/html_parser';
|
||||
import {ParseError, ParseLocation} from '@angular/compiler/src/parse_util';
|
||||
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {HtmlParser, HtmlParseTreeResult, HtmlTreeError} from '@angular/compiler/src/html_parser';
|
||||
import {
|
||||
HtmlElementAst,
|
||||
HtmlAttrAst,
|
||||
HtmlTextAst,
|
||||
HtmlCommentAst,
|
||||
HtmlExpansionAst,
|
||||
HtmlExpansionCaseAst
|
||||
} from '@angular/compiler/src/html_ast';
|
||||
import {ParseError} from '@angular/compiler/src/parse_util';
|
||||
import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn} from './html_ast_spec_utils';
|
||||
|
||||
export function main() {
|
||||
@ -232,12 +238,15 @@ export function main() {
|
||||
`<div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div>`,
|
||||
'TestComp', true);
|
||||
|
||||
expect(humanizeDom(parsed)).toEqual([
|
||||
[HtmlElementAst, 'div', 0], [HtmlTextAst, 'before', 1],
|
||||
[HtmlExpansionAst, 'messages.length', 'plural'], [HtmlExpansionCaseAst, '0'],
|
||||
[HtmlExpansionCaseAst, '1'], [HtmlTextAst, 'after', 1]
|
||||
]);
|
||||
|
||||
expect(humanizeDom(parsed))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'div', 0],
|
||||
[HtmlTextAst, 'before', 1],
|
||||
[HtmlExpansionAst, 'messages.length', 'plural'],
|
||||
[HtmlExpansionCaseAst, '=0'],
|
||||
[HtmlExpansionCaseAst, '=1'],
|
||||
[HtmlTextAst, 'after', 1],
|
||||
]);
|
||||
let cases = (<any>parsed.rootNodes[0]).children[1].cases;
|
||||
|
||||
expect(humanizeDom(new HtmlParseTreeResult(cases[0].expression, []))).toEqual([
|
||||
@ -254,20 +263,20 @@ export function main() {
|
||||
it('should parse out nested expansion forms', () => {
|
||||
let parsed = parser.parse(
|
||||
`{messages.length, plural, =0 { {p.gender, gender, =m {m}} }}`, 'TestComp', true);
|
||||
|
||||
|
||||
expect(humanizeDom(parsed)).toEqual([
|
||||
[HtmlExpansionAst, 'messages.length', 'plural'],
|
||||
[HtmlExpansionCaseAst, '0'],
|
||||
]);
|
||||
expect(humanizeDom(parsed))
|
||||
.toEqual([
|
||||
[HtmlExpansionAst, 'messages.length', 'plural'],
|
||||
[HtmlExpansionCaseAst, '=0'],
|
||||
]);
|
||||
|
||||
let firstCase = (<any>parsed.rootNodes[0]).cases[0];
|
||||
|
||||
expect(humanizeDom(new HtmlParseTreeResult(firstCase.expression, []))).toEqual([
|
||||
[HtmlExpansionAst, 'p.gender', 'gender'],
|
||||
[HtmlExpansionCaseAst, 'm'],
|
||||
[HtmlTextAst, ' ', 0],
|
||||
]);
|
||||
expect(humanizeDom(new HtmlParseTreeResult(firstCase.expression, [])))
|
||||
.toEqual([
|
||||
[HtmlExpansionAst, 'p.gender', 'gender'],
|
||||
[HtmlExpansionCaseAst, '=m'],
|
||||
[HtmlTextAst, ' ', 0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should error when expansion form is not closed', () => {
|
||||
|
@ -175,41 +175,52 @@ export function main() {
|
||||
|
||||
it('should handle the plural expansion form', () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('zero<ph name="e1">bold</ph>', 'plural_0', null))] =
|
||||
translations[id(new Message('zero<ph name="e1">bold</ph>', "plural_=0", null))] =
|
||||
'ZERO<ph name="e1">BOLD</ph>';
|
||||
|
||||
let res = parse(`{messages.length, plural,=0 {zero<b>bold</b>}}`, translations);
|
||||
|
||||
expect(humanizeDom(res)).toEqual([
|
||||
[HtmlElementAst, 'ul', 0], [HtmlAttrAst, '[ngPlural]', 'messages.length'],
|
||||
[HtmlElementAst, 'template', 1], [HtmlAttrAst, 'ngPluralCase', '0'],
|
||||
[HtmlElementAst, 'li', 2], [HtmlTextAst, 'ZERO', 3], [HtmlElementAst, 'b', 3],
|
||||
[HtmlTextAst, 'BOLD', 4]
|
||||
]);
|
||||
expect(humanizeDom(res))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngPlural]', 'messages.length'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, 'ngPluralCase', '=0'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
[HtmlTextAst, 'ZERO', 3],
|
||||
[HtmlElementAst, 'b', 3],
|
||||
[HtmlTextAst, 'BOLD', 4],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle nested expansion forms', () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('m', 'gender_m', null))] = 'M';
|
||||
translations[id(new Message('m', "gender_=m", null))] = 'M';
|
||||
|
||||
let res = parse(`{messages.length, plural, =0 { {p.gender, gender, =m {m}} }}`, translations);
|
||||
|
||||
expect(humanizeDom(res)).toEqual([
|
||||
[HtmlElementAst, 'ul', 0], [HtmlAttrAst, '[ngPlural]', 'messages.length'],
|
||||
[HtmlElementAst, 'template', 1], [HtmlAttrAst, 'ngPluralCase', '0'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
expect(humanizeDom(res))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngPlural]', 'messages.length'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, 'ngPluralCase', '=0'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
|
||||
[HtmlElementAst, 'ul', 3], [HtmlAttrAst, '[ngSwitch]', 'p.gender'],
|
||||
[HtmlElementAst, 'template', 4], [HtmlAttrAst, 'ngSwitchWhen', 'm'],
|
||||
[HtmlElementAst, 'li', 5], [HtmlTextAst, 'M', 6],
|
||||
[HtmlElementAst, 'ul', 3],
|
||||
[HtmlAttrAst, '[ngSwitch]', 'p.gender'],
|
||||
[HtmlElementAst, 'template', 4],
|
||||
[HtmlAttrAst, 'ngSwitchWhen', '=m'],
|
||||
[HtmlElementAst, 'li', 5],
|
||||
[HtmlTextAst, 'M', 6],
|
||||
|
||||
[HtmlTextAst, ' ', 3]
|
||||
]);
|
||||
[HtmlTextAst, ' ', 3]
|
||||
]);
|
||||
});
|
||||
|
||||
it('should correctly set source code positions', () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('<ph name="e0">bold</ph>', 'plural_0', null))] =
|
||||
translations[id(new Message('<ph name="e0">bold</ph>', "plural_=0", null))] =
|
||||
'<ph name="e0">BOLD</ph>';
|
||||
|
||||
let nodes = parse(`{messages.length, plural,=0 {<b>bold</b>}}`, translations).rootNodes;
|
||||
@ -230,15 +241,15 @@ export function main() {
|
||||
expect(switchExp.sourceSpan.end.col).toEqual(16);
|
||||
|
||||
let template: HtmlElementAst = <HtmlElementAst>ul.children[0];
|
||||
expect(template.sourceSpan.start.col).toEqual(26);
|
||||
expect(template.sourceSpan.start.col).toEqual(25);
|
||||
expect(template.sourceSpan.end.col).toEqual(41);
|
||||
|
||||
let switchCheck = template.attrs[0];
|
||||
expect(switchCheck.sourceSpan.start.col).toEqual(26);
|
||||
expect(switchCheck.sourceSpan.start.col).toEqual(25);
|
||||
expect(switchCheck.sourceSpan.end.col).toEqual(28);
|
||||
|
||||
let li: HtmlElementAst = <HtmlElementAst>template.children[0];
|
||||
expect(li.sourceSpan.start.col).toEqual(26);
|
||||
expect(li.sourceSpan.start.col).toEqual(25);
|
||||
expect(li.sourceSpan.end.col).toEqual(41);
|
||||
|
||||
let b: HtmlElementAst = <HtmlElementAst>li.children[0];
|
||||
@ -248,18 +259,19 @@ export function main() {
|
||||
|
||||
it('should handle other special forms', () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('m', 'gender_male', null))] = 'M';
|
||||
translations[id(new Message('m', "gender_=male", null))] = 'M';
|
||||
|
||||
let res = parse(`{person.gender, gender,=male {m}}`, translations);
|
||||
|
||||
expect(humanizeDom(res)).toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngSwitch]', 'person.gender'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, 'ngSwitchWhen', 'male'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
[HtmlTextAst, 'M', 3],
|
||||
]);
|
||||
expect(humanizeDom(res))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngSwitch]', 'person.gender'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, 'ngSwitchWhen', '=male'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
[HtmlTextAst, 'M', 3],
|
||||
]);
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
|
@ -151,22 +151,23 @@ export function main() {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should extract messages from special forms', () => {
|
||||
let res = extractor.extract(
|
||||
`
|
||||
it("should extract messages from expansion forms", () => {
|
||||
let res = extractor.extract(`
|
||||
<div>
|
||||
{messages.length, plural,
|
||||
=0 {You have <b>no</b> messages}
|
||||
=1 {You have one message}
|
||||
other {You have messages}
|
||||
}
|
||||
</div>
|
||||
`,
|
||||
'someurl');
|
||||
</div>`,
|
||||
"someurl");
|
||||
|
||||
expect(res.messages).toEqual([
|
||||
new Message('You have <ph name="e1">no</ph> messages', 'plural_0', null),
|
||||
new Message('You have one message', 'plural_1', null)
|
||||
]);
|
||||
expect(res.messages)
|
||||
.toEqual([
|
||||
new Message('You have <ph name="e1">no</ph> messages', "plural_=0", null),
|
||||
new Message('You have one message', "plural_=1", null),
|
||||
new Message('You have messages', "plural_other", null),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should remove duplicate messages', () => {
|
||||
|
Reference in New Issue
Block a user