import {BaseException} from '../facade/exceptions'; import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '../html_ast'; /** * 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); }