2016-05-31 18:22:59 -04:00
|
|
|
import {BaseException} from '../facade/exceptions';
|
2016-06-08 19:38:52 -04:00
|
|
|
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '../html_ast';
|
|
|
|
|
2016-04-12 14:46:49 -04:00
|
|
|
|
2016-04-13 19:01:25 -04:00
|
|
|
|
2016-04-12 14:46:49 -04:00
|
|
|
/**
|
|
|
|
* Expands special forms into elements.
|
|
|
|
*
|
|
|
|
* For example,
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* { messages.length, plural,
|
|
|
|
* =0 {zero}
|
|
|
|
* =1 {one}
|
|
|
|
* =other {more than one}
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* will be expanded into
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <ul [ngPlural]="messages.length">
|
|
|
|
* <template [ngPluralCase]="0"><li i18n="plural_0">zero</li></template>
|
|
|
|
* <template [ngPluralCase]="1"><li i18n="plural_1">one</li></template>
|
|
|
|
* <template [ngPluralCase]="other"><li i18n="plural_other">more than one</li></template>
|
|
|
|
* </ul>
|
|
|
|
* ```
|
|
|
|
*/
|
2016-04-13 19:01:25 -04:00
|
|
|
export function expandNodes(nodes: HtmlAst[]): ExpansionResult {
|
|
|
|
let e = new _Expander();
|
|
|
|
let n = htmlVisitAll(e, nodes);
|
|
|
|
return new ExpansionResult(n, e.expanded);
|
|
|
|
}
|
|
|
|
|
|
|
|
export class ExpansionResult {
|
|
|
|
constructor(public nodes: HtmlAst[], public expanded: boolean) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _Expander implements HtmlAstVisitor {
|
|
|
|
expanded: boolean = false;
|
2016-04-12 14:46:49 -04:00
|
|
|
constructor() {}
|
|
|
|
|
|
|
|
visitElement(ast: HtmlElementAst, context: any): any {
|
2016-06-08 19:38:52 -04:00
|
|
|
return new HtmlElementAst(
|
|
|
|
ast.name, ast.attrs, htmlVisitAll(this, ast.children), ast.sourceSpan, ast.startSourceSpan,
|
|
|
|
ast.endSourceSpan);
|
2016-04-12 14:46:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
visitAttr(ast: HtmlAttrAst, context: any): any { return ast; }
|
|
|
|
|
|
|
|
visitText(ast: HtmlTextAst, context: any): any { return ast; }
|
|
|
|
|
|
|
|
visitComment(ast: HtmlCommentAst, context: any): any { return ast; }
|
|
|
|
|
|
|
|
visitExpansion(ast: HtmlExpansionAst, context: any): any {
|
2016-04-13 19:01:25 -04:00
|
|
|
this.expanded = true;
|
2016-06-08 19:38:52 -04:00
|
|
|
return ast.type == 'plural' ? _expandPluralForm(ast) : _expandDefaultForm(ast);
|
2016-04-12 14:46:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any {
|
2016-06-08 19:38:52 -04:00
|
|
|
throw new BaseException('Should not be reached');
|
2016-04-12 14:46:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function _expandPluralForm(ast: HtmlExpansionAst): HtmlElementAst {
|
2016-04-13 19:01:25 -04:00
|
|
|
let children = ast.cases.map(c => {
|
|
|
|
let expansionResult = expandNodes(c.expression);
|
|
|
|
let i18nAttrs = expansionResult.expanded ?
|
2016-06-08 19:38:52 -04:00
|
|
|
[] :
|
|
|
|
[new HtmlAttrAst('i18n', `${ast.type}_${c.value}`, c.valueSourceSpan)];
|
2016-04-13 19:01:25 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
return new HtmlElementAst(
|
|
|
|
`template`,
|
|
|
|
[
|
|
|
|
new HtmlAttrAst('ngPluralCase', c.value, c.valueSourceSpan),
|
|
|
|
],
|
|
|
|
[new HtmlElementAst(
|
|
|
|
`li`, i18nAttrs, expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan)],
|
|
|
|
c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
2016-04-13 19:01:25 -04:00
|
|
|
});
|
2016-06-08 19:38:52 -04:00
|
|
|
let switchAttr = new HtmlAttrAst('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan);
|
|
|
|
return new HtmlElementAst(
|
|
|
|
'ul', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
2016-04-12 14:46:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function _expandDefaultForm(ast: HtmlExpansionAst): HtmlElementAst {
|
2016-04-13 19:01:25 -04:00
|
|
|
let children = ast.cases.map(c => {
|
|
|
|
let expansionResult = expandNodes(c.expression);
|
|
|
|
let i18nAttrs = expansionResult.expanded ?
|
2016-06-08 19:38:52 -04:00
|
|
|
[] :
|
|
|
|
[new HtmlAttrAst('i18n', `${ast.type}_${c.value}`, c.valueSourceSpan)];
|
2016-04-13 19:01:25 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
return new HtmlElementAst(
|
|
|
|
`template`,
|
|
|
|
[
|
|
|
|
new HtmlAttrAst('ngSwitchWhen', c.value, c.valueSourceSpan),
|
|
|
|
],
|
|
|
|
[new HtmlElementAst(
|
|
|
|
`li`, i18nAttrs, expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan)],
|
|
|
|
c.sourceSpan, c.sourceSpan, c.sourceSpan);
|
2016-04-13 19:01:25 -04:00
|
|
|
});
|
2016-06-08 19:38:52 -04:00
|
|
|
let switchAttr = new HtmlAttrAst('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan);
|
|
|
|
return new HtmlElementAst(
|
|
|
|
'ul', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
|
2016-04-28 20:50:03 -04:00
|
|
|
}
|