UNPKG

@angular/compiler

Version:

Angular - the compiler library

713 lines • 133 kB
/** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import * as tslib_1 from "tslib"; import { identifierName } from '../compile_metadata'; import { ASTWithSource, EmptyExpr } from '../expression_parser/ast'; import { Identifiers, createTokenForExternalReference, createTokenForReference } from '../identifiers'; import * as html from '../ml_parser/ast'; import { ParseTreeResult } from '../ml_parser/html_parser'; import { removeWhitespaces, replaceNgsp } from '../ml_parser/html_whitespaces'; import { expandNodes } from '../ml_parser/icu_ast_expander'; import { InterpolationConfig } from '../ml_parser/interpolation_config'; import { isNgTemplate, splitNsName } from '../ml_parser/tags'; import { ParseError, ParseErrorLevel, ParseSourceSpan } from '../parse_util'; import { ProviderElementContext, ProviderViewContext } from '../provider_analyzer'; import { CssSelector, SelectorMatcher } from '../selector'; import { isStyleUrlResolvable } from '../style_url_resolver'; import { syntaxError } from '../util'; import { BindingParser } from './binding_parser'; import * as t from './template_ast'; import { PreparsedElementType, preparseElement } from './template_preparser'; var BIND_NAME_REGEXP = /^(?:(?:(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/; // Group 1 = "bind-" var KW_BIND_IDX = 1; // Group 2 = "let-" var KW_LET_IDX = 2; // Group 3 = "ref-/#" var KW_REF_IDX = 3; // Group 4 = "on-" var KW_ON_IDX = 4; // Group 5 = "bindon-" var KW_BINDON_IDX = 5; // Group 6 = "@" var KW_AT_IDX = 6; // Group 7 = the identifier after "bind-", "let-", "ref-/#", "on-", "bindon-" or "@" var IDENT_KW_IDX = 7; // Group 8 = identifier inside [()] var IDENT_BANANA_BOX_IDX = 8; // Group 9 = identifier inside [] var IDENT_PROPERTY_IDX = 9; // Group 10 = identifier inside () var IDENT_EVENT_IDX = 10; var TEMPLATE_ATTR_PREFIX = '*'; var CLASS_ATTR = 'class'; var _TEXT_CSS_SELECTOR; function TEXT_CSS_SELECTOR() { if (!_TEXT_CSS_SELECTOR) { _TEXT_CSS_SELECTOR = CssSelector.parse('*')[0]; } return _TEXT_CSS_SELECTOR; } var TemplateParseError = /** @class */ (function (_super) { tslib_1.__extends(TemplateParseError, _super); function TemplateParseError(message, span, level) { return _super.call(this, span, message, level) || this; } return TemplateParseError; }(ParseError)); export { TemplateParseError }; var TemplateParseResult = /** @class */ (function () { function TemplateParseResult(templateAst, usedPipes, errors) { this.templateAst = templateAst; this.usedPipes = usedPipes; this.errors = errors; } return TemplateParseResult; }()); export { TemplateParseResult }; var TemplateParser = /** @class */ (function () { function TemplateParser(_config, _reflector, _exprParser, _schemaRegistry, _htmlParser, _console, transforms) { this._config = _config; this._reflector = _reflector; this._exprParser = _exprParser; this._schemaRegistry = _schemaRegistry; this._htmlParser = _htmlParser; this._console = _console; this.transforms = transforms; } Object.defineProperty(TemplateParser.prototype, "expressionParser", { get: function () { return this._exprParser; }, enumerable: true, configurable: true }); TemplateParser.prototype.parse = function (component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) { var result = this.tryParse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces); var warnings = result.errors.filter(function (error) { return error.level === ParseErrorLevel.WARNING; }); var errors = result.errors.filter(function (error) { return error.level === ParseErrorLevel.ERROR; }); if (warnings.length > 0) { this._console.warn("Template parse warnings:\n" + warnings.join('\n')); } if (errors.length > 0) { var errorString = errors.join('\n'); throw syntaxError("Template parse errors:\n" + errorString, errors); } return { template: result.templateAst, pipes: result.usedPipes }; }; TemplateParser.prototype.tryParse = function (component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) { var htmlParseResult = typeof template === 'string' ? this._htmlParser.parse(template, templateUrl, true, this.getInterpolationConfig(component)) : template; if (!preserveWhitespaces) { htmlParseResult = removeWhitespaces(htmlParseResult); } return this.tryParseHtml(this.expandHtml(htmlParseResult), component, directives, pipes, schemas); }; TemplateParser.prototype.tryParseHtml = function (htmlAstWithErrors, component, directives, pipes, schemas) { var result; var errors = htmlAstWithErrors.errors; var usedPipes = []; if (htmlAstWithErrors.rootNodes.length > 0) { var uniqDirectives = removeSummaryDuplicates(directives); var uniqPipes = removeSummaryDuplicates(pipes); var providerViewContext = new ProviderViewContext(this._reflector, component); var interpolationConfig = undefined; if (component.template && component.template.interpolation) { interpolationConfig = { start: component.template.interpolation[0], end: component.template.interpolation[1] }; } var bindingParser = new BindingParser(this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors); var parseVisitor = new TemplateParseVisitor(this._reflector, this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry, schemas, errors); result = html.visitAll(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_ELEMENT_CONTEXT); errors.push.apply(errors, tslib_1.__spread(providerViewContext.errors)); usedPipes.push.apply(usedPipes, tslib_1.__spread(bindingParser.getUsedPipes())); } else { result = []; } this._assertNoReferenceDuplicationOnTemplate(result, errors); if (errors.length > 0) { return new TemplateParseResult(result, usedPipes, errors); } if (this.transforms) { this.transforms.forEach(function (transform) { result = t.templateVisitAll(transform, result); }); } return new TemplateParseResult(result, usedPipes, errors); }; TemplateParser.prototype.expandHtml = function (htmlAstWithErrors, forced) { if (forced === void 0) { forced = false; } var errors = htmlAstWithErrors.errors; if (errors.length == 0 || forced) { // Transform ICU messages to angular directives var expandedHtmlAst = expandNodes(htmlAstWithErrors.rootNodes); errors.push.apply(errors, tslib_1.__spread(expandedHtmlAst.errors)); htmlAstWithErrors = new ParseTreeResult(expandedHtmlAst.nodes, errors); } return htmlAstWithErrors; }; TemplateParser.prototype.getInterpolationConfig = function (component) { if (component.template) { return InterpolationConfig.fromArray(component.template.interpolation); } return undefined; }; /** @internal */ TemplateParser.prototype._assertNoReferenceDuplicationOnTemplate = function (result, errors) { var existingReferences = []; result.filter(function (element) { return !!element.references; }) .forEach(function (element) { return element.references.forEach(function (reference) { var name = reference.name; if (existingReferences.indexOf(name) < 0) { existingReferences.push(name); } else { var error = new TemplateParseError("Reference \"#" + name + "\" is defined several times", reference.sourceSpan, ParseErrorLevel.ERROR); errors.push(error); } }); }); }; return TemplateParser; }()); export { TemplateParser }; var TemplateParseVisitor = /** @class */ (function () { function TemplateParseVisitor(reflector, config, providerViewContext, directives, _bindingParser, _schemaRegistry, _schemas, _targetErrors) { var _this = this; this.reflector = reflector; this.config = config; this.providerViewContext = providerViewContext; this._bindingParser = _bindingParser; this._schemaRegistry = _schemaRegistry; this._schemas = _schemas; this._targetErrors = _targetErrors; this.selectorMatcher = new SelectorMatcher(); this.directivesIndex = new Map(); this.ngContentCount = 0; // Note: queries start with id 1 so we can use the number in a Bloom filter! this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1; directives.forEach(function (directive, index) { var selector = CssSelector.parse(directive.selector); _this.selectorMatcher.addSelectables(selector, directive); _this.directivesIndex.set(directive, index); }); } TemplateParseVisitor.prototype.visitExpansion = function (expansion, context) { return null; }; TemplateParseVisitor.prototype.visitExpansionCase = function (expansionCase, context) { return null; }; TemplateParseVisitor.prototype.visitText = function (text, parent) { var ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR()); var valueNoNgsp = replaceNgsp(text.value); var expr = this._bindingParser.parseInterpolation(valueNoNgsp, text.sourceSpan); return expr ? new t.BoundTextAst(expr, ngContentIndex, text.sourceSpan) : new t.TextAst(valueNoNgsp, ngContentIndex, text.sourceSpan); }; TemplateParseVisitor.prototype.visitAttribute = function (attribute, context) { return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan); }; TemplateParseVisitor.prototype.visitComment = function (comment, context) { return null; }; TemplateParseVisitor.prototype.visitElement = function (element, parent) { var _this = this; var queryStartIndex = this.contentQueryStartId; var elName = element.name; var preparsedElement = preparseElement(element); if (preparsedElement.type === PreparsedElementType.SCRIPT || preparsedElement.type === PreparsedElementType.STYLE) { // Skipping <script> for security reasons // Skipping <style> as we already processed them // in the StyleCompiler return null; } if (preparsedElement.type === PreparsedElementType.STYLESHEET && isStyleUrlResolvable(preparsedElement.hrefAttr)) { // Skipping stylesheets with either relative urls or package scheme as we already processed // them in the StyleCompiler return null; } var matchableAttrs = []; var elementOrDirectiveProps = []; var elementOrDirectiveRefs = []; var elementVars = []; var events = []; var templateElementOrDirectiveProps = []; var templateMatchableAttrs = []; var templateElementVars = []; var hasInlineTemplates = false; var attrs = []; var isTemplateElement = isNgTemplate(element.name); element.attrs.forEach(function (attr) { var parsedVariables = []; var hasBinding = _this._parseAttr(isTemplateElement, attr, matchableAttrs, elementOrDirectiveProps, events, elementOrDirectiveRefs, elementVars); elementVars.push.apply(elementVars, tslib_1.__spread(parsedVariables.map(function (v) { return t.VariableAst.fromParsedVariable(v); }))); var templateValue; var templateKey; var normalizedName = _this._normalizeAttributeName(attr.name); if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) { templateValue = attr.value; templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length); } var hasTemplateBinding = templateValue != null; if (hasTemplateBinding) { if (hasInlineTemplates) { _this._reportError("Can't have multiple template bindings on one element. Use only one attribute prefixed with *", attr.sourceSpan); } hasInlineTemplates = true; var parsedVariables_1 = []; _this._bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attr.sourceSpan, templateMatchableAttrs, templateElementOrDirectiveProps, parsedVariables_1); templateElementVars.push.apply(templateElementVars, tslib_1.__spread(parsedVariables_1.map(function (v) { return t.VariableAst.fromParsedVariable(v); }))); } if (!hasBinding && !hasTemplateBinding) { // don't include the bindings as attributes as well in the AST attrs.push(_this.visitAttribute(attr, null)); matchableAttrs.push([attr.name, attr.value]); } }); var elementCssSelector = createElementCssSelector(elName, matchableAttrs); var _a = this._parseDirectives(this.selectorMatcher, elementCssSelector), directiveMetas = _a.directives, matchElement = _a.matchElement; var references = []; var boundDirectivePropNames = new Set(); var directiveAsts = this._createDirectiveAsts(isTemplateElement, element.name, directiveMetas, elementOrDirectiveProps, elementOrDirectiveRefs, element.sourceSpan, references, boundDirectivePropNames); var elementProps = this._createElementPropertyAsts(element.name, elementOrDirectiveProps, boundDirectivePropNames); var isViewRoot = parent.isTemplateElement || hasInlineTemplates; var providerContext = new ProviderElementContext(this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs, references, isTemplateElement, queryStartIndex, element.sourceSpan); var children = html.visitAll(preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children, ElementContext.create(isTemplateElement, directiveAsts, isTemplateElement ? parent.providerContext : providerContext)); providerContext.afterElement(); // Override the actual selector when the `ngProjectAs` attribute is provided var projectionSelector = preparsedElement.projectAs != '' ? CssSelector.parse(preparsedElement.projectAs)[0] : elementCssSelector; var ngContentIndex = parent.findNgContentIndex(projectionSelector); var parsedElement; if (preparsedElement.type === PreparsedElementType.NG_CONTENT) { // `<ng-content>` element if (element.children && !element.children.every(_isEmptyTextNode)) { this._reportError("<ng-content> element cannot have content.", element.sourceSpan); } parsedElement = new t.NgContentAst(this.ngContentCount++, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); } else if (isTemplateElement) { // `<ng-template>` element this._assertAllEventsPublishedByDirectives(directiveAsts, events); this._assertNoComponentsNorElementBindingsOnTemplate(directiveAsts, elementProps, element.sourceSpan); parsedElement = new t.EmbeddedTemplateAst(attrs, events, references, elementVars, providerContext.transformedDirectiveAsts, providerContext.transformProviders, providerContext.transformedHasViewContainer, providerContext.queryMatches, children, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); } else { // element other than `<ng-content>` and `<ng-template>` this._assertElementExists(matchElement, element); this._assertOnlyOneComponent(directiveAsts, element.sourceSpan); var ngContentIndex_1 = hasInlineTemplates ? null : parent.findNgContentIndex(projectionSelector); parsedElement = new t.ElementAst(elName, attrs, elementProps, events, references, providerContext.transformedDirectiveAsts, providerContext.transformProviders, providerContext.transformedHasViewContainer, providerContext.queryMatches, children, hasInlineTemplates ? null : ngContentIndex_1, element.sourceSpan, element.endSourceSpan || null); } if (hasInlineTemplates) { // The element as a *-attribute var templateQueryStartIndex = this.contentQueryStartId; var templateSelector = createElementCssSelector('ng-template', templateMatchableAttrs); var directives = this._parseDirectives(this.selectorMatcher, templateSelector).directives; var templateBoundDirectivePropNames = new Set(); var templateDirectiveAsts = this._createDirectiveAsts(true, elName, directives, templateElementOrDirectiveProps, [], element.sourceSpan, [], templateBoundDirectivePropNames); var templateElementProps = this._createElementPropertyAsts(elName, templateElementOrDirectiveProps, templateBoundDirectivePropNames); this._assertNoComponentsNorElementBindingsOnTemplate(templateDirectiveAsts, templateElementProps, element.sourceSpan); var templateProviderContext = new ProviderElementContext(this.providerViewContext, parent.providerContext, parent.isTemplateElement, templateDirectiveAsts, [], [], true, templateQueryStartIndex, element.sourceSpan); templateProviderContext.afterElement(); parsedElement = new t.EmbeddedTemplateAst([], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts, templateProviderContext.transformProviders, templateProviderContext.transformedHasViewContainer, templateProviderContext.queryMatches, [parsedElement], ngContentIndex, element.sourceSpan); } return parsedElement; }; TemplateParseVisitor.prototype._parseAttr = function (isTemplateElement, attr, targetMatchableAttrs, targetProps, targetEvents, targetRefs, targetVars) { var name = this._normalizeAttributeName(attr.name); var value = attr.value; var srcSpan = attr.sourceSpan; var boundEvents = []; var bindParts = name.match(BIND_NAME_REGEXP); var hasBinding = false; if (bindParts !== null) { hasBinding = true; if (bindParts[KW_BIND_IDX] != null) { this._bindingParser.parsePropertyBinding(bindParts[IDENT_KW_IDX], value, false, srcSpan, targetMatchableAttrs, targetProps); } else if (bindParts[KW_LET_IDX]) { if (isTemplateElement) { var identifier = bindParts[IDENT_KW_IDX]; this._parseVariable(identifier, value, srcSpan, targetVars); } else { this._reportError("\"let-\" is only supported on ng-template elements.", srcSpan); } } else if (bindParts[KW_REF_IDX]) { var identifier = bindParts[IDENT_KW_IDX]; this._parseReference(identifier, value, srcSpan, targetRefs); } else if (bindParts[KW_ON_IDX]) { this._bindingParser.parseEvent(bindParts[IDENT_KW_IDX], value, srcSpan, targetMatchableAttrs, boundEvents); } else if (bindParts[KW_BINDON_IDX]) { this._bindingParser.parsePropertyBinding(bindParts[IDENT_KW_IDX], value, false, srcSpan, targetMatchableAttrs, targetProps); this._parseAssignmentEvent(bindParts[IDENT_KW_IDX], value, srcSpan, targetMatchableAttrs, boundEvents); } else if (bindParts[KW_AT_IDX]) { this._bindingParser.parseLiteralAttr(name, value, srcSpan, targetMatchableAttrs, targetProps); } else if (bindParts[IDENT_BANANA_BOX_IDX]) { this._bindingParser.parsePropertyBinding(bindParts[IDENT_BANANA_BOX_IDX], value, false, srcSpan, targetMatchableAttrs, targetProps); this._parseAssignmentEvent(bindParts[IDENT_BANANA_BOX_IDX], value, srcSpan, targetMatchableAttrs, boundEvents); } else if (bindParts[IDENT_PROPERTY_IDX]) { this._bindingParser.parsePropertyBinding(bindParts[IDENT_PROPERTY_IDX], value, false, srcSpan, targetMatchableAttrs, targetProps); } else if (bindParts[IDENT_EVENT_IDX]) { this._bindingParser.parseEvent(bindParts[IDENT_EVENT_IDX], value, srcSpan, targetMatchableAttrs, boundEvents); } } else { hasBinding = this._bindingParser.parsePropertyInterpolation(name, value, srcSpan, targetMatchableAttrs, targetProps); } if (!hasBinding) { this._bindingParser.parseLiteralAttr(name, value, srcSpan, targetMatchableAttrs, targetProps); } targetEvents.push.apply(targetEvents, tslib_1.__spread(boundEvents.map(function (e) { return t.BoundEventAst.fromParsedEvent(e); }))); return hasBinding; }; TemplateParseVisitor.prototype._normalizeAttributeName = function (attrName) { return /^data-/i.test(attrName) ? attrName.substring(5) : attrName; }; TemplateParseVisitor.prototype._parseVariable = function (identifier, value, sourceSpan, targetVars) { if (identifier.indexOf('-') > -1) { this._reportError("\"-\" is not allowed in variable names", sourceSpan); } targetVars.push(new t.VariableAst(identifier, value, sourceSpan)); }; TemplateParseVisitor.prototype._parseReference = function (identifier, value, sourceSpan, targetRefs) { if (identifier.indexOf('-') > -1) { this._reportError("\"-\" is not allowed in reference names", sourceSpan); } targetRefs.push(new ElementOrDirectiveRef(identifier, value, sourceSpan)); }; TemplateParseVisitor.prototype._parseAssignmentEvent = function (name, expression, sourceSpan, targetMatchableAttrs, targetEvents) { this._bindingParser.parseEvent(name + "Change", expression + "=$event", sourceSpan, targetMatchableAttrs, targetEvents); }; TemplateParseVisitor.prototype._parseDirectives = function (selectorMatcher, elementCssSelector) { var _this = this; // Need to sort the directives so that we get consistent results throughout, // as selectorMatcher uses Maps inside. // Also deduplicate directives as they might match more than one time! var directives = new Array(this.directivesIndex.size); // Whether any directive selector matches on the element name var matchElement = false; selectorMatcher.match(elementCssSelector, function (selector, directive) { directives[_this.directivesIndex.get(directive)] = directive; matchElement = matchElement || selector.hasElementSelector(); }); return { directives: directives.filter(function (dir) { return !!dir; }), matchElement: matchElement, }; }; TemplateParseVisitor.prototype._createDirectiveAsts = function (isTemplateElement, elementName, directives, props, elementOrDirectiveRefs, elementSourceSpan, targetReferences, targetBoundDirectivePropNames) { var _this = this; var matchedReferences = new Set(); var component = null; var directiveAsts = directives.map(function (directive) { var sourceSpan = new ParseSourceSpan(elementSourceSpan.start, elementSourceSpan.end, "Directive " + identifierName(directive.type)); if (directive.isComponent) { component = directive; } var directiveProperties = []; var boundProperties = _this._bindingParser.createDirectiveHostPropertyAsts(directive, elementName, sourceSpan); var hostProperties = boundProperties.map(function (prop) { return t.BoundElementPropertyAst.fromBoundProperty(prop); }); // Note: We need to check the host properties here as well, // as we don't know the element name in the DirectiveWrapperCompiler yet. hostProperties = _this._checkPropertiesInSchema(elementName, hostProperties); var parsedEvents = _this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan); _this._createDirectivePropertyAsts(directive.inputs, props, directiveProperties, targetBoundDirectivePropNames); elementOrDirectiveRefs.forEach(function (elOrDirRef) { if ((elOrDirRef.value.length === 0 && directive.isComponent) || (elOrDirRef.isReferenceToDirective(directive))) { targetReferences.push(new t.ReferenceAst(elOrDirRef.name, createTokenForReference(directive.type.reference), elOrDirRef.value, elOrDirRef.sourceSpan)); matchedReferences.add(elOrDirRef.name); } }); var hostEvents = parsedEvents.map(function (e) { return t.BoundEventAst.fromParsedEvent(e); }); var contentQueryStartId = _this.contentQueryStartId; _this.contentQueryStartId += directive.queries.length; return new t.DirectiveAst(directive, directiveProperties, hostProperties, hostEvents, contentQueryStartId, sourceSpan); }); elementOrDirectiveRefs.forEach(function (elOrDirRef) { if (elOrDirRef.value.length > 0) { if (!matchedReferences.has(elOrDirRef.name)) { _this._reportError("There is no directive with \"exportAs\" set to \"" + elOrDirRef.value + "\"", elOrDirRef.sourceSpan); } } else if (!component) { var refToken = null; if (isTemplateElement) { refToken = createTokenForExternalReference(_this.reflector, Identifiers.TemplateRef); } targetReferences.push(new t.ReferenceAst(elOrDirRef.name, refToken, elOrDirRef.value, elOrDirRef.sourceSpan)); } }); return directiveAsts; }; TemplateParseVisitor.prototype._createDirectivePropertyAsts = function (directiveProperties, boundProps, targetBoundDirectiveProps, targetBoundDirectivePropNames) { if (directiveProperties) { var boundPropsByName_1 = new Map(); boundProps.forEach(function (boundProp) { var prevValue = boundPropsByName_1.get(boundProp.name); if (!prevValue || prevValue.isLiteral) { // give [a]="b" a higher precedence than a="b" on the same element boundPropsByName_1.set(boundProp.name, boundProp); } }); Object.keys(directiveProperties).forEach(function (dirProp) { var elProp = directiveProperties[dirProp]; var boundProp = boundPropsByName_1.get(elProp); // Bindings are optional, so this binding only needs to be set up if an expression is given. if (boundProp) { targetBoundDirectivePropNames.add(boundProp.name); if (!isEmptyExpression(boundProp.expression)) { targetBoundDirectiveProps.push(new t.BoundDirectivePropertyAst(dirProp, boundProp.name, boundProp.expression, boundProp.sourceSpan)); } } }); } }; TemplateParseVisitor.prototype._createElementPropertyAsts = function (elementName, props, boundDirectivePropNames) { var _this = this; var boundElementProps = []; props.forEach(function (prop) { if (!prop.isLiteral && !boundDirectivePropNames.has(prop.name)) { var boundProp = _this._bindingParser.createBoundElementProperty(elementName, prop); boundElementProps.push(t.BoundElementPropertyAst.fromBoundProperty(boundProp)); } }); return this._checkPropertiesInSchema(elementName, boundElementProps); }; TemplateParseVisitor.prototype._findComponentDirectives = function (directives) { return directives.filter(function (directive) { return directive.directive.isComponent; }); }; TemplateParseVisitor.prototype._findComponentDirectiveNames = function (directives) { return this._findComponentDirectives(directives) .map(function (directive) { return identifierName(directive.directive.type); }); }; TemplateParseVisitor.prototype._assertOnlyOneComponent = function (directives, sourceSpan) { var componentTypeNames = this._findComponentDirectiveNames(directives); if (componentTypeNames.length > 1) { this._reportError("More than one component matched on this element.\n" + "Make sure that only one component's selector can match a given element.\n" + ("Conflicting components: " + componentTypeNames.join(',')), sourceSpan); } }; /** * Make sure that non-angular tags conform to the schemas. * * Note: An element is considered an angular tag when at least one directive selector matches the * tag name. * * @param matchElement Whether any directive has matched on the tag name * @param element the html element */ TemplateParseVisitor.prototype._assertElementExists = function (matchElement, element) { var elName = element.name.replace(/^:xhtml:/, ''); if (!matchElement && !this._schemaRegistry.hasElement(elName, this._schemas)) { var errorMsg = "'" + elName + "' is not a known element:\n"; errorMsg += "1. If '" + elName + "' is an Angular component, then verify that it is part of this module.\n"; if (elName.indexOf('-') > -1) { errorMsg += "2. If '" + elName + "' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message."; } else { errorMsg += "2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component."; } this._reportError(errorMsg, element.sourceSpan); } }; TemplateParseVisitor.prototype._assertNoComponentsNorElementBindingsOnTemplate = function (directives, elementProps, sourceSpan) { var _this = this; var componentTypeNames = this._findComponentDirectiveNames(directives); if (componentTypeNames.length > 0) { this._reportError("Components on an embedded template: " + componentTypeNames.join(','), sourceSpan); } elementProps.forEach(function (prop) { _this._reportError("Property binding " + prop.name + " not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the \"@NgModule.declarations\".", sourceSpan); }); }; TemplateParseVisitor.prototype._assertAllEventsPublishedByDirectives = function (directives, events) { var _this = this; var allDirectiveEvents = new Set(); directives.forEach(function (directive) { Object.keys(directive.directive.outputs).forEach(function (k) { var eventName = directive.directive.outputs[k]; allDirectiveEvents.add(eventName); }); }); events.forEach(function (event) { if (event.target != null || !allDirectiveEvents.has(event.name)) { _this._reportError("Event binding " + event.fullName + " not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the \"@NgModule.declarations\".", event.sourceSpan); } }); }; TemplateParseVisitor.prototype._checkPropertiesInSchema = function (elementName, boundProps) { var _this = this; // Note: We can't filter out empty expressions before this method, // as we still want to validate them! return boundProps.filter(function (boundProp) { if (boundProp.type === 0 /* Property */ && !_this._schemaRegistry.hasProperty(elementName, boundProp.name, _this._schemas)) { var errorMsg = "Can't bind to '" + boundProp.name + "' since it isn't a known property of '" + elementName + "'."; if (elementName.startsWith('ng-')) { errorMsg += "\n1. If '" + boundProp.name + "' is an Angular directive, then add 'CommonModule' to the '@NgModule.imports' of this component." + "\n2. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component."; } else if (elementName.indexOf('-') > -1) { errorMsg += "\n1. If '" + elementName + "' is an Angular component and it has '" + boundProp.name + "' input, then verify that it is part of this module." + ("\n2. If '" + elementName + "' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.") + "\n3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component."; } _this._reportError(errorMsg, boundProp.sourceSpan); } return !isEmptyExpression(boundProp.value); }); }; TemplateParseVisitor.prototype._reportError = function (message, sourceSpan, level) { if (level === void 0) { level = ParseErrorLevel.ERROR; } this._targetErrors.push(new ParseError(sourceSpan, message, level)); }; return TemplateParseVisitor; }()); var NonBindableVisitor = /** @class */ (function () { function NonBindableVisitor() { } NonBindableVisitor.prototype.visitElement = function (ast, parent) { var preparsedElement = preparseElement(ast); if (preparsedElement.type === PreparsedElementType.SCRIPT || preparsedElement.type === PreparsedElementType.STYLE || preparsedElement.type === PreparsedElementType.STYLESHEET) { // Skipping <script> for security reasons // Skipping <style> and stylesheets as we already processed them // in the StyleCompiler return null; } var attrNameAndValues = ast.attrs.map(function (attr) { return [attr.name, attr.value]; }); var selector = createElementCssSelector(ast.name, attrNameAndValues); var ngContentIndex = parent.findNgContentIndex(selector); var children = html.visitAll(this, ast.children, EMPTY_ELEMENT_CONTEXT); return new t.ElementAst(ast.name, html.visitAll(this, ast.attrs), [], [], [], [], [], false, [], children, ngContentIndex, ast.sourceSpan, ast.endSourceSpan); }; NonBindableVisitor.prototype.visitComment = function (comment, context) { return null; }; NonBindableVisitor.prototype.visitAttribute = function (attribute, context) { return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan); }; NonBindableVisitor.prototype.visitText = function (text, parent) { var ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR()); return new t.TextAst(text.value, ngContentIndex, text.sourceSpan); }; NonBindableVisitor.prototype.visitExpansion = function (expansion, context) { return expansion; }; NonBindableVisitor.prototype.visitExpansionCase = function (expansionCase, context) { return expansionCase; }; return NonBindableVisitor; }()); /** * A reference to an element or directive in a template. E.g., the reference in this template: * * <div #myMenu="coolMenu"> * * would be {name: 'myMenu', value: 'coolMenu', sourceSpan: ...} */ var ElementOrDirectiveRef = /** @class */ (function () { function ElementOrDirectiveRef(name, value, sourceSpan) { this.name = name; this.value = value; this.sourceSpan = sourceSpan; } /** Gets whether this is a reference to the given directive. */ ElementOrDirectiveRef.prototype.isReferenceToDirective = function (directive) { return splitExportAs(directive.exportAs).indexOf(this.value) !== -1; }; return ElementOrDirectiveRef; }()); /** Splits a raw, potentially comma-delimited `exportAs` value into an array of names. */ function splitExportAs(exportAs) { return exportAs ? exportAs.split(',').map(function (e) { return e.trim(); }) : []; } export function splitClasses(classAttrValue) { return classAttrValue.trim().split(/\s+/g); } var ElementContext = /** @class */ (function () { function ElementContext(isTemplateElement, _ngContentIndexMatcher, _wildcardNgContentIndex, providerContext) { this.isTemplateElement = isTemplateElement; this._ngContentIndexMatcher = _ngContentIndexMatcher; this._wildcardNgContentIndex = _wildcardNgContentIndex; this.providerContext = providerContext; } ElementContext.create = function (isTemplateElement, directives, providerContext) { var matcher = new SelectorMatcher(); var wildcardNgContentIndex = null; var component = directives.find(function (directive) { return directive.directive.isComponent; }); if (component) { var ngContentSelectors = component.directive.template.ngContentSelectors; for (var i = 0; i < ngContentSelectors.length; i++) { var selector = ngContentSelectors[i]; if (selector === '*') { wildcardNgContentIndex = i; } else { matcher.addSelectables(CssSelector.parse(ngContentSelectors[i]), i); } } } return new ElementContext(isTemplateElement, matcher, wildcardNgContentIndex, providerContext); }; ElementContext.prototype.findNgContentIndex = function (selector) { var ngContentIndices = []; this._ngContentIndexMatcher.match(selector, function (selector, ngContentIndex) { ngContentIndices.push(ngContentIndex); }); ngContentIndices.sort(); if (this._wildcardNgContentIndex != null) { ngContentIndices.push(this._wildcardNgContentIndex); } return ngContentIndices.length > 0 ? ngContentIndices[0] : null; }; return ElementContext; }()); export function createElementCssSelector(elementName, attributes) { var cssSelector = new CssSelector(); var elNameNoNs = splitNsName(elementName)[1]; cssSelector.setElement(elNameNoNs); for (var i = 0; i < attributes.length; i++) { var attrName = attributes[i][0]; var attrNameNoNs = splitNsName(attrName)[1]; var attrValue = attributes[i][1]; cssSelector.addAttribute(attrNameNoNs, attrValue); if (attrName.toLowerCase() == CLASS_ATTR) { var classes = splitClasses(attrValue); classes.forEach(function (className) { return cssSelector.addClassName(className); }); } } return cssSelector; } var EMPTY_ELEMENT_CONTEXT = new ElementContext(true, new SelectorMatcher(), null, null); var NON_BINDABLE_VISITOR = new NonBindableVisitor(); function _isEmptyTextNode(node) { return node instanceof html.Text && node.value.trim().length == 0; } export function removeSummaryDuplicates(items) { var map = new Map(); items.forEach(function (item) { if (!map.get(item.type.reference)) { map.set(item.type.reference, item); } }); return Array.from(map.values()); } function isEmptyExpression(ast) { if (ast instanceof ASTWithSource) { ast = ast.ast; } return ast instanceof EmptyExpr; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGVfcGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3RlbXBsYXRlX3BhcnNlci90ZW1wbGF0ZV9wYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HOztBQUVILE9BQU8sRUFBbUgsY0FBYyxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFJckssT0FBTyxFQUFNLGFBQWEsRUFBRSxTQUFTLEVBQThDLE1BQU0sMEJBQTBCLENBQUM7QUFFcEgsT0FBTyxFQUFDLFdBQVcsRUFBRSwrQkFBK0IsRUFBRSx1QkFBdUIsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3JHLE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxFQUFhLGVBQWUsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQ3JFLE9BQU8sRUFBQyxpQkFBaUIsRUFBRSxXQUFXLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUM3RSxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sK0JBQStCLENBQUM7QUFDMUQsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sbUNBQW1DLENBQUM7QUFDdEUsT0FBTyxFQUFDLFlBQVksRUFBRSxXQUFXLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsVUFBVSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDM0UsT0FBTyxFQUFDLHNCQUFzQixFQUFFLG1CQUFtQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFakYsT0FBTyxFQUFDLFdBQVcsRUFBRSxlQUFlLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDekQsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDM0QsT0FBTyxFQUFVLFdBQVcsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUU3QyxP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