diff --git a/packages/compiler/src/ml_parser/parser.ts b/packages/compiler/src/ml_parser/parser.ts index 9451de9ff9..e617156536 100644 --- a/packages/compiler/src/ml_parser/parser.ts +++ b/packages/compiler/src/ml_parser/parser.ts @@ -11,7 +11,7 @@ import {ParseError, ParseSourceSpan} from '../parse_util'; import * as html from './ast'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './interpolation_config'; import * as lex from './lexer'; -import {TagDefinition, getNsPrefix, mergeNsAndName} from './tags'; +import {TagDefinition, getNsPrefix, isNgContainer, mergeNsAndName} from './tags'; export class TreeError extends ParseError { static create(elementName: string|null, span: ParseSourceSpan, msg: string): TreeError { @@ -352,11 +352,12 @@ class _TreeBuilder { * * `` elements are skipped as they are not rendered as DOM element. */ - private _getParentElementSkippingContainers(): {parent: html.Element, container: html.Element} { - let container: html.Element = null !; + private _getParentElementSkippingContainers(): + {parent: html.Element, container: html.Element|null} { + let container: html.Element|null = null; for (let i = this._elementStack.length - 1; i >= 0; i--) { - if (this._elementStack[i].name !== 'ng-container') { + if (!isNgContainer(this._elementStack[i].name)) { return {parent: this._elementStack[i], container}; } container = this._elementStack[i]; @@ -382,7 +383,7 @@ class _TreeBuilder { * @internal */ private _insertBeforeContainer( - parent: html.Element, container: html.Element, node: html.Element) { + parent: html.Element, container: html.Element|null, node: html.Element) { if (!container) { this._addToParent(node); this._elementStack.push(node); diff --git a/packages/compiler/src/ml_parser/tags.ts b/packages/compiler/src/ml_parser/tags.ts index bcdca5647f..0a882b6c51 100644 --- a/packages/compiler/src/ml_parser/tags.ts +++ b/packages/compiler/src/ml_parser/tags.ts @@ -12,7 +12,6 @@ export enum TagContentType { PARSABLE_DATA } -// TODO(vicb): read-only when TS supports it export interface TagDefinition { closedByParent: boolean; requiredParents: {[key: string]: boolean}; @@ -42,6 +41,21 @@ export function splitNsName(elementName: string): [string | null, string] { return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; } +// `` tags work the same regardless the namespace +export function isNgContainer(tagName: string): boolean { + return splitNsName(tagName)[1] === 'ng-container'; +} + +// `` tags work the same regardless the namespace +export function isNgContent(tagName: string): boolean { + return splitNsName(tagName)[1] === 'ng-content'; +} + +// `` tags work the same regardless the namespace +export function isNgTemplate(tagName: string): boolean { + return splitNsName(tagName)[1] === 'ng-template'; +} + export function getNsPrefix(fullName: string): string export function getNsPrefix(fullName: null): null; export function getNsPrefix(fullName: string | null): string | diff --git a/packages/compiler/src/schema/dom_element_schema_registry.ts b/packages/compiler/src/schema/dom_element_schema_registry.ts index 8c8486be8a..a235bb6d74 100644 --- a/packages/compiler/src/schema/dom_element_schema_registry.ts +++ b/packages/compiler/src/schema/dom_element_schema_registry.ts @@ -6,9 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ -import {AUTO_STYLE, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata, SecurityContext} from '@angular/core'; -import {CompilerInjectable} from '../injectable'; +import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata, SecurityContext} from '@angular/core'; +import {CompilerInjectable} from '../injectable'; +import {isNgContainer, isNgContent} from '../ml_parser/tags'; import {dashCaseToCamelCase} from '../util'; import {SECURITY_SCHEMA} from './dom_security_schema'; @@ -288,7 +289,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry { } if (tagName.indexOf('-') > -1) { - if (tagName === 'ng-container' || tagName === 'ng-content') { + if (isNgContainer(tagName) || isNgContent(tagName)) { return false; } @@ -309,7 +310,7 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry { } if (tagName.indexOf('-') > -1) { - if (tagName === 'ng-container' || tagName === 'ng-content') { + if (isNgContainer(tagName) || isNgContent(tagName)) { return true; } diff --git a/packages/compiler/src/template_parser/template_parser.ts b/packages/compiler/src/template_parser/template_parser.ts index fccec81903..6a7f86c266 100644 --- a/packages/compiler/src/template_parser/template_parser.ts +++ b/packages/compiler/src/template_parser/template_parser.ts @@ -7,7 +7,8 @@ */ import {Inject, InjectionToken, Optional, SchemaMetadata, ɵConsole as Console} from '@angular/core'; -import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, identifierName} from '../compile_metadata'; + +import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTokenMetadata, CompileTypeMetadata, identifierName} from '../compile_metadata'; import {CompilerConfig} from '../config'; import {AST, ASTWithSource, EmptyExpr} from '../expression_parser/ast'; import {Parser} from '../expression_parser/parser'; @@ -18,13 +19,14 @@ import * as html from '../ml_parser/ast'; import {ParseTreeResult} from '../ml_parser/html_parser'; import {expandNodes} from '../ml_parser/icu_ast_expander'; import {InterpolationConfig} from '../ml_parser/interpolation_config'; -import {splitNsName} from '../ml_parser/tags'; +import {isNgTemplate, splitNsName} from '../ml_parser/tags'; import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util'; import {ProviderElementContext, ProviderViewContext} from '../provider_analyzer'; import {ElementSchemaRegistry} from '../schema/element_schema_registry'; import {CssSelector, SelectorMatcher} from '../selector'; import {isStyleUrlResolvable} from '../style_url_resolver'; import {syntaxError} from '../util'; + import {BindingParser, BoundProperty} from './binding_parser'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from './template_ast'; import {PreparsedElementType, preparseElement} from './template_preparser'; @@ -53,7 +55,6 @@ const IDENT_PROPERTY_IDX = 9; // Group 10 = identifier inside () const IDENT_EVENT_IDX = 10; -const NG_TEMPLATE_ELEMENT = 'ng-template'; // deprecated in 4.x const TEMPLATE_ELEMENT = 'template'; // deprecated in 4.x @@ -891,9 +892,8 @@ function isEmptyExpression(ast: AST): boolean { function isTemplate( el: html.Element, enableLegacyTemplate: boolean, reportDeprecation: (m: string, span: ParseSourceSpan) => void): boolean { + if (isNgTemplate(el.name)) return true; const tagNoNs = splitNsName(el.name)[1]; - // `` is an angular construct and is lower case - if (tagNoNs === NG_TEMPLATE_ELEMENT) return true; // `