import { HtmlAst, HtmlAstVisitor, HtmlElementAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst, HtmlExpansionAst, HtmlExpansionCaseAst, htmlVisitAll } from '../html_ast'; import {BaseException} from '../facade/exceptions'; /** * Expands special forms into elements. * * For example, * * ``` * { messages.length, plural, * =0 {zero} * =1 {one} * =other {more than one} * } * ``` * * will be expanded into * * ``` * * ``` */ 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; constructor() {} visitElement(ast: HtmlElementAst, context: any): any { return new HtmlElementAst(ast.name, ast.attrs, htmlVisitAll(this, ast.children), ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan); } 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 { this.expanded = true; return ast.type == "plural" ? _expandPluralForm(ast) : _expandDefaultForm(ast); } visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any { throw new BaseException("Should not be reached"); } } function _expandPluralForm(ast: HtmlExpansionAst): HtmlElementAst { let children = ast.cases.map(c => { let expansionResult = expandNodes(c.expression); let i18nAttrs = expansionResult.expanded ? [] : [new HtmlAttrAst("i18n", `${ast.type}_${c.value}`, c.valueSourceSpan)]; 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); }); let switchAttr = new HtmlAttrAst("[ngPlural]", ast.switchValue, ast.switchValueSourceSpan); return new HtmlElementAst("ul", [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan); } function _expandDefaultForm(ast: HtmlExpansionAst): HtmlElementAst { let children = ast.cases.map(c => { let expansionResult = expandNodes(c.expression); let i18nAttrs = expansionResult.expanded ? [] : [new HtmlAttrAst("i18n", `${ast.type}_${c.value}`, c.valueSourceSpan)]; 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); }); let switchAttr = new HtmlAttrAst("[ngSwitch]", ast.switchValue, ast.switchValueSourceSpan); return new HtmlElementAst("ul", [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan); }