UNPKG

@angular/compiler

Version:

Angular - the compiler library

1,380 lines (1,371 loc) • 978 kB
/** * @license Angular v6.1.10 * (c) 2010-2018 Google, Inc. https://angular.io/ * License: MIT */ /** * @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 */ var TagContentType; (function (TagContentType) { TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT"; TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT"; TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA"; })(TagContentType || (TagContentType = {})); function splitNsName(elementName) { if (elementName[0] != ':') { return [null, elementName]; } const colonIndex = elementName.indexOf(':', 1); if (colonIndex == -1) { throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`); } return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; } // `<ng-container>` tags work the same regardless the namespace function isNgContainer(tagName) { return splitNsName(tagName)[1] === 'ng-container'; } // `<ng-content>` tags work the same regardless the namespace function isNgContent(tagName) { return splitNsName(tagName)[1] === 'ng-content'; } // `<ng-template>` tags work the same regardless the namespace function isNgTemplate(tagName) { return splitNsName(tagName)[1] === 'ng-template'; } function getNsPrefix(fullName) { return fullName === null ? null : splitNsName(fullName)[0]; } function mergeNsAndName(prefix, localName) { return prefix ? `:${prefix}:${localName}` : localName; } // see http://www.w3.org/TR/html51/syntax.html#named-character-references // see https://html.spec.whatwg.org/multipage/entities.json // This list is not exhaustive to keep the compiler footprint low. // The `&#123;` / `&#x1ab;` syntax should be used when the named character reference does not // exist. const NAMED_ENTITIES = { 'Aacute': '\u00C1', 'aacute': '\u00E1', 'Acirc': '\u00C2', 'acirc': '\u00E2', 'acute': '\u00B4', 'AElig': '\u00C6', 'aelig': '\u00E6', 'Agrave': '\u00C0', 'agrave': '\u00E0', 'alefsym': '\u2135', 'Alpha': '\u0391', 'alpha': '\u03B1', 'amp': '&', 'and': '\u2227', 'ang': '\u2220', 'apos': '\u0027', 'Aring': '\u00C5', 'aring': '\u00E5', 'asymp': '\u2248', 'Atilde': '\u00C3', 'atilde': '\u00E3', 'Auml': '\u00C4', 'auml': '\u00E4', 'bdquo': '\u201E', 'Beta': '\u0392', 'beta': '\u03B2', 'brvbar': '\u00A6', 'bull': '\u2022', 'cap': '\u2229', 'Ccedil': '\u00C7', 'ccedil': '\u00E7', 'cedil': '\u00B8', 'cent': '\u00A2', 'Chi': '\u03A7', 'chi': '\u03C7', 'circ': '\u02C6', 'clubs': '\u2663', 'cong': '\u2245', 'copy': '\u00A9', 'crarr': '\u21B5', 'cup': '\u222A', 'curren': '\u00A4', 'dagger': '\u2020', 'Dagger': '\u2021', 'darr': '\u2193', 'dArr': '\u21D3', 'deg': '\u00B0', 'Delta': '\u0394', 'delta': '\u03B4', 'diams': '\u2666', 'divide': '\u00F7', 'Eacute': '\u00C9', 'eacute': '\u00E9', 'Ecirc': '\u00CA', 'ecirc': '\u00EA', 'Egrave': '\u00C8', 'egrave': '\u00E8', 'empty': '\u2205', 'emsp': '\u2003', 'ensp': '\u2002', 'Epsilon': '\u0395', 'epsilon': '\u03B5', 'equiv': '\u2261', 'Eta': '\u0397', 'eta': '\u03B7', 'ETH': '\u00D0', 'eth': '\u00F0', 'Euml': '\u00CB', 'euml': '\u00EB', 'euro': '\u20AC', 'exist': '\u2203', 'fnof': '\u0192', 'forall': '\u2200', 'frac12': '\u00BD', 'frac14': '\u00BC', 'frac34': '\u00BE', 'frasl': '\u2044', 'Gamma': '\u0393', 'gamma': '\u03B3', 'ge': '\u2265', 'gt': '>', 'harr': '\u2194', 'hArr': '\u21D4', 'hearts': '\u2665', 'hellip': '\u2026', 'Iacute': '\u00CD', 'iacute': '\u00ED', 'Icirc': '\u00CE', 'icirc': '\u00EE', 'iexcl': '\u00A1', 'Igrave': '\u00CC', 'igrave': '\u00EC', 'image': '\u2111', 'infin': '\u221E', 'int': '\u222B', 'Iota': '\u0399', 'iota': '\u03B9', 'iquest': '\u00BF', 'isin': '\u2208', 'Iuml': '\u00CF', 'iuml': '\u00EF', 'Kappa': '\u039A', 'kappa': '\u03BA', 'Lambda': '\u039B', 'lambda': '\u03BB', 'lang': '\u27E8', 'laquo': '\u00AB', 'larr': '\u2190', 'lArr': '\u21D0', 'lceil': '\u2308', 'ldquo': '\u201C', 'le': '\u2264', 'lfloor': '\u230A', 'lowast': '\u2217', 'loz': '\u25CA', 'lrm': '\u200E', 'lsaquo': '\u2039', 'lsquo': '\u2018', 'lt': '<', 'macr': '\u00AF', 'mdash': '\u2014', 'micro': '\u00B5', 'middot': '\u00B7', 'minus': '\u2212', 'Mu': '\u039C', 'mu': '\u03BC', 'nabla': '\u2207', 'nbsp': '\u00A0', 'ndash': '\u2013', 'ne': '\u2260', 'ni': '\u220B', 'not': '\u00AC', 'notin': '\u2209', 'nsub': '\u2284', 'Ntilde': '\u00D1', 'ntilde': '\u00F1', 'Nu': '\u039D', 'nu': '\u03BD', 'Oacute': '\u00D3', 'oacute': '\u00F3', 'Ocirc': '\u00D4', 'ocirc': '\u00F4', 'OElig': '\u0152', 'oelig': '\u0153', 'Ograve': '\u00D2', 'ograve': '\u00F2', 'oline': '\u203E', 'Omega': '\u03A9', 'omega': '\u03C9', 'Omicron': '\u039F', 'omicron': '\u03BF', 'oplus': '\u2295', 'or': '\u2228', 'ordf': '\u00AA', 'ordm': '\u00BA', 'Oslash': '\u00D8', 'oslash': '\u00F8', 'Otilde': '\u00D5', 'otilde': '\u00F5', 'otimes': '\u2297', 'Ouml': '\u00D6', 'ouml': '\u00F6', 'para': '\u00B6', 'permil': '\u2030', 'perp': '\u22A5', 'Phi': '\u03A6', 'phi': '\u03C6', 'Pi': '\u03A0', 'pi': '\u03C0', 'piv': '\u03D6', 'plusmn': '\u00B1', 'pound': '\u00A3', 'prime': '\u2032', 'Prime': '\u2033', 'prod': '\u220F', 'prop': '\u221D', 'Psi': '\u03A8', 'psi': '\u03C8', 'quot': '\u0022', 'radic': '\u221A', 'rang': '\u27E9', 'raquo': '\u00BB', 'rarr': '\u2192', 'rArr': '\u21D2', 'rceil': '\u2309', 'rdquo': '\u201D', 'real': '\u211C', 'reg': '\u00AE', 'rfloor': '\u230B', 'Rho': '\u03A1', 'rho': '\u03C1', 'rlm': '\u200F', 'rsaquo': '\u203A', 'rsquo': '\u2019', 'sbquo': '\u201A', 'Scaron': '\u0160', 'scaron': '\u0161', 'sdot': '\u22C5', 'sect': '\u00A7', 'shy': '\u00AD', 'Sigma': '\u03A3', 'sigma': '\u03C3', 'sigmaf': '\u03C2', 'sim': '\u223C', 'spades': '\u2660', 'sub': '\u2282', 'sube': '\u2286', 'sum': '\u2211', 'sup': '\u2283', 'sup1': '\u00B9', 'sup2': '\u00B2', 'sup3': '\u00B3', 'supe': '\u2287', 'szlig': '\u00DF', 'Tau': '\u03A4', 'tau': '\u03C4', 'there4': '\u2234', 'Theta': '\u0398', 'theta': '\u03B8', 'thetasym': '\u03D1', 'thinsp': '\u2009', 'THORN': '\u00DE', 'thorn': '\u00FE', 'tilde': '\u02DC', 'times': '\u00D7', 'trade': '\u2122', 'Uacute': '\u00DA', 'uacute': '\u00FA', 'uarr': '\u2191', 'uArr': '\u21D1', 'Ucirc': '\u00DB', 'ucirc': '\u00FB', 'Ugrave': '\u00D9', 'ugrave': '\u00F9', 'uml': '\u00A8', 'upsih': '\u03D2', 'Upsilon': '\u03A5', 'upsilon': '\u03C5', 'Uuml': '\u00DC', 'uuml': '\u00FC', 'weierp': '\u2118', 'Xi': '\u039E', 'xi': '\u03BE', 'Yacute': '\u00DD', 'yacute': '\u00FD', 'yen': '\u00A5', 'yuml': '\u00FF', 'Yuml': '\u0178', 'Zeta': '\u0396', 'zeta': '\u03B6', 'zwj': '\u200D', 'zwnj': '\u200C', }; // The &ngsp; pseudo-entity is denoting a space. see: // https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart const NGSP_UNICODE = '\uE500'; NAMED_ENTITIES['ngsp'] = NGSP_UNICODE; /** * @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 */ class HtmlTagDefinition { constructor({ closedByChildren, requiredParents, implicitNamespacePrefix, contentType = TagContentType.PARSABLE_DATA, closedByParent = false, isVoid = false, ignoreFirstLf = false } = {}) { this.closedByChildren = {}; this.closedByParent = false; this.canSelfClose = false; if (closedByChildren && closedByChildren.length > 0) { closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true); } this.isVoid = isVoid; this.closedByParent = closedByParent || isVoid; if (requiredParents && requiredParents.length > 0) { this.requiredParents = {}; // The first parent is the list is automatically when none of the listed parents are present this.parentToAdd = requiredParents[0]; requiredParents.forEach(tagName => this.requiredParents[tagName] = true); } this.implicitNamespacePrefix = implicitNamespacePrefix || null; this.contentType = contentType; this.ignoreFirstLf = ignoreFirstLf; } requireExtraParent(currentParent) { if (!this.requiredParents) { return false; } if (!currentParent) { return true; } const lcParent = currentParent.toLowerCase(); const isParentTemplate = lcParent === 'template' || currentParent === 'ng-template'; return !isParentTemplate && this.requiredParents[lcParent] != true; } isClosedByChild(name) { return this.isVoid || name.toLowerCase() in this.closedByChildren; } } let _DEFAULT_TAG_DEFINITION; // see http://www.w3.org/TR/html51/syntax.html#optional-tags // This implementation does not fully conform to the HTML5 spec. let TAG_DEFINITIONS; function getHtmlTagDefinition(tagName) { if (!TAG_DEFINITIONS) { _DEFAULT_TAG_DEFINITION = new HtmlTagDefinition(); TAG_DEFINITIONS = { 'base': new HtmlTagDefinition({ isVoid: true }), 'meta': new HtmlTagDefinition({ isVoid: true }), 'area': new HtmlTagDefinition({ isVoid: true }), 'embed': new HtmlTagDefinition({ isVoid: true }), 'link': new HtmlTagDefinition({ isVoid: true }), 'img': new HtmlTagDefinition({ isVoid: true }), 'input': new HtmlTagDefinition({ isVoid: true }), 'param': new HtmlTagDefinition({ isVoid: true }), 'hr': new HtmlTagDefinition({ isVoid: true }), 'br': new HtmlTagDefinition({ isVoid: true }), 'source': new HtmlTagDefinition({ isVoid: true }), 'track': new HtmlTagDefinition({ isVoid: true }), 'wbr': new HtmlTagDefinition({ isVoid: true }), 'p': new HtmlTagDefinition({ closedByChildren: [ 'address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul' ], closedByParent: true }), 'thead': new HtmlTagDefinition({ closedByChildren: ['tbody', 'tfoot'] }), 'tbody': new HtmlTagDefinition({ closedByChildren: ['tbody', 'tfoot'], closedByParent: true }), 'tfoot': new HtmlTagDefinition({ closedByChildren: ['tbody'], closedByParent: true }), 'tr': new HtmlTagDefinition({ closedByChildren: ['tr'], requiredParents: ['tbody', 'tfoot', 'thead'], closedByParent: true }), 'td': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }), 'th': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }), 'col': new HtmlTagDefinition({ requiredParents: ['colgroup'], isVoid: true }), 'svg': new HtmlTagDefinition({ implicitNamespacePrefix: 'svg' }), 'math': new HtmlTagDefinition({ implicitNamespacePrefix: 'math' }), 'li': new HtmlTagDefinition({ closedByChildren: ['li'], closedByParent: true }), 'dt': new HtmlTagDefinition({ closedByChildren: ['dt', 'dd'] }), 'dd': new HtmlTagDefinition({ closedByChildren: ['dt', 'dd'], closedByParent: true }), 'rb': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }), 'rt': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }), 'rtc': new HtmlTagDefinition({ closedByChildren: ['rb', 'rtc', 'rp'], closedByParent: true }), 'rp': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }), 'optgroup': new HtmlTagDefinition({ closedByChildren: ['optgroup'], closedByParent: true }), 'option': new HtmlTagDefinition({ closedByChildren: ['option', 'optgroup'], closedByParent: true }), 'pre': new HtmlTagDefinition({ ignoreFirstLf: true }), 'listing': new HtmlTagDefinition({ ignoreFirstLf: true }), 'style': new HtmlTagDefinition({ contentType: TagContentType.RAW_TEXT }), 'script': new HtmlTagDefinition({ contentType: TagContentType.RAW_TEXT }), 'title': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT }), 'textarea': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true }), }; } return TAG_DEFINITIONS[tagName.toLowerCase()] || _DEFAULT_TAG_DEFINITION; } /** * @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 */ const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + //":not(" '([-\\w]+)|' + // "tag" '(?:\\.([-\\w]+))|' + // ".class" // "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range '(?:\\[([-.\\w*]+)(?:=([\"\']?)([^\\]\"\']*)\\5)?\\])|' + // "[name]", "[name=value]", // "[name="value"]", // "[name='value']" '(\\))|' + // ")" '(\\s*,\\s*)', // "," 'g'); /** * A css selector contains an element name, * css classes and attribute/value pairs with the purpose * of selecting subsets out of them. */ class CssSelector { constructor() { this.element = null; this.classNames = []; /** * The selectors are encoded in pairs where: * - even locations are attribute names * - odd locations are attribute values. * * Example: * Selector: `[key1=value1][key2]` would parse to: * ``` * ['key1', 'value1', 'key2', ''] * ``` */ this.attrs = []; this.notSelectors = []; } static parse(selector) { const results = []; const _addResult = (res, cssSel) => { if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 && cssSel.attrs.length == 0) { cssSel.element = '*'; } res.push(cssSel); }; let cssSelector = new CssSelector(); let match; let current = cssSelector; let inNot = false; _SELECTOR_REGEXP.lastIndex = 0; while (match = _SELECTOR_REGEXP.exec(selector)) { if (match[1]) { if (inNot) { throw new Error('Nesting :not is not allowed in a selector'); } inNot = true; current = new CssSelector(); cssSelector.notSelectors.push(current); } if (match[2]) { current.setElement(match[2]); } if (match[3]) { current.addClassName(match[3]); } if (match[4]) { current.addAttribute(match[4], match[6]); } if (match[7]) { inNot = false; current = cssSelector; } if (match[8]) { if (inNot) { throw new Error('Multiple selectors in :not are not supported'); } _addResult(results, cssSelector); cssSelector = current = new CssSelector(); } } _addResult(results, cssSelector); return results; } isElementSelector() { return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 && this.notSelectors.length === 0; } hasElementSelector() { return !!this.element; } setElement(element = null) { this.element = element; } /** Gets a template string for an element that matches the selector. */ getMatchingElementTemplate() { const tagName = this.element || 'div'; const classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : ''; let attrs = ''; for (let i = 0; i < this.attrs.length; i += 2) { const attrName = this.attrs[i]; const attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : ''; attrs += ` ${attrName}${attrValue}`; } return getHtmlTagDefinition(tagName).isVoid ? `<${tagName}${classAttr}${attrs}/>` : `<${tagName}${classAttr}${attrs}></${tagName}>`; } getAttrs() { const result = []; if (this.classNames.length > 0) { result.push('class', this.classNames.join(' ')); } return result.concat(this.attrs); } addAttribute(name, value = '') { this.attrs.push(name, value && value.toLowerCase() || ''); } addClassName(name) { this.classNames.push(name.toLowerCase()); } toString() { let res = this.element || ''; if (this.classNames) { this.classNames.forEach(klass => res += `.${klass}`); } if (this.attrs) { for (let i = 0; i < this.attrs.length; i += 2) { const name = this.attrs[i]; const value = this.attrs[i + 1]; res += `[${name}${value ? '=' + value : ''}]`; } } this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`); return res; } } /** * Reads a list of CssSelectors and allows to calculate which ones * are contained in a given CssSelector. */ class SelectorMatcher { constructor() { this._elementMap = new Map(); this._elementPartialMap = new Map(); this._classMap = new Map(); this._classPartialMap = new Map(); this._attrValueMap = new Map(); this._attrValuePartialMap = new Map(); this._listContexts = []; } static createNotMatcher(notSelectors) { const notMatcher = new SelectorMatcher(); notMatcher.addSelectables(notSelectors, null); return notMatcher; } addSelectables(cssSelectors, callbackCtxt) { let listContext = null; if (cssSelectors.length > 1) { listContext = new SelectorListContext(cssSelectors); this._listContexts.push(listContext); } for (let i = 0; i < cssSelectors.length; i++) { this._addSelectable(cssSelectors[i], callbackCtxt, listContext); } } /** * Add an object that can be found later on by calling `match`. * @param cssSelector A css selector * @param callbackCtxt An opaque object that will be given to the callback of the `match` function */ _addSelectable(cssSelector, callbackCtxt, listContext) { let matcher = this; const element = cssSelector.element; const classNames = cssSelector.classNames; const attrs = cssSelector.attrs; const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext); if (element) { const isTerminal = attrs.length === 0 && classNames.length === 0; if (isTerminal) { this._addTerminal(matcher._elementMap, element, selectable); } else { matcher = this._addPartial(matcher._elementPartialMap, element); } } if (classNames) { for (let i = 0; i < classNames.length; i++) { const isTerminal = attrs.length === 0 && i === classNames.length - 1; const className = classNames[i]; if (isTerminal) { this._addTerminal(matcher._classMap, className, selectable); } else { matcher = this._addPartial(matcher._classPartialMap, className); } } } if (attrs) { for (let i = 0; i < attrs.length; i += 2) { const isTerminal = i === attrs.length - 2; const name = attrs[i]; const value = attrs[i + 1]; if (isTerminal) { const terminalMap = matcher._attrValueMap; let terminalValuesMap = terminalMap.get(name); if (!terminalValuesMap) { terminalValuesMap = new Map(); terminalMap.set(name, terminalValuesMap); } this._addTerminal(terminalValuesMap, value, selectable); } else { const partialMap = matcher._attrValuePartialMap; let partialValuesMap = partialMap.get(name); if (!partialValuesMap) { partialValuesMap = new Map(); partialMap.set(name, partialValuesMap); } matcher = this._addPartial(partialValuesMap, value); } } } } _addTerminal(map, name, selectable) { let terminalList = map.get(name); if (!terminalList) { terminalList = []; map.set(name, terminalList); } terminalList.push(selectable); } _addPartial(map, name) { let matcher = map.get(name); if (!matcher) { matcher = new SelectorMatcher(); map.set(name, matcher); } return matcher; } /** * Find the objects that have been added via `addSelectable` * whose css selector is contained in the given css selector. * @param cssSelector A css selector * @param matchedCallback This callback will be called with the object handed into `addSelectable` * @return boolean true if a match was found */ match(cssSelector, matchedCallback) { let result = false; const element = cssSelector.element; const classNames = cssSelector.classNames; const attrs = cssSelector.attrs; for (let i = 0; i < this._listContexts.length; i++) { this._listContexts[i].alreadyMatched = false; } result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result; result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) || result; if (classNames) { for (let i = 0; i < classNames.length; i++) { const className = classNames[i]; result = this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result; result = this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) || result; } } if (attrs) { for (let i = 0; i < attrs.length; i += 2) { const name = attrs[i]; const value = attrs[i + 1]; const terminalValuesMap = this._attrValueMap.get(name); if (value) { result = this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result; } result = this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result; const partialValuesMap = this._attrValuePartialMap.get(name); if (value) { result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result; } result = this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result; } } return result; } /** @internal */ _matchTerminal(map, name, cssSelector, matchedCallback) { if (!map || typeof name !== 'string') { return false; } let selectables = map.get(name) || []; const starSelectables = map.get('*'); if (starSelectables) { selectables = selectables.concat(starSelectables); } if (selectables.length === 0) { return false; } let selectable; let result = false; for (let i = 0; i < selectables.length; i++) { selectable = selectables[i]; result = selectable.finalize(cssSelector, matchedCallback) || result; } return result; } /** @internal */ _matchPartial(map, name, cssSelector, matchedCallback) { if (!map || typeof name !== 'string') { return false; } const nestedSelector = map.get(name); if (!nestedSelector) { return false; } // TODO(perf): get rid of recursion and measure again // TODO(perf): don't pass the whole selector into the recursion, // but only the not processed parts return nestedSelector.match(cssSelector, matchedCallback); } } class SelectorListContext { constructor(selectors) { this.selectors = selectors; this.alreadyMatched = false; } } // Store context to pass back selector and context when a selector is matched class SelectorContext { constructor(selector, cbContext, listContext) { this.selector = selector; this.cbContext = cbContext; this.listContext = listContext; this.notSelectors = selector.notSelectors; } finalize(cssSelector, callback) { let result = true; if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) { const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors); result = !notMatcher.match(cssSelector, null); } if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) { if (this.listContext) { this.listContext.alreadyMatched = true; } callback(this.selector, this.cbContext); } return result; } } /** * @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 */ const createInject = makeMetadataFactory('Inject', (token) => ({ token })); const createInjectionToken = makeMetadataFactory('InjectionToken', (desc) => ({ _desc: desc, ngInjectableDef: undefined })); const createAttribute = makeMetadataFactory('Attribute', (attributeName) => ({ attributeName })); const createContentChildren = makeMetadataFactory('ContentChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: false, descendants: false }, data))); const createContentChild = makeMetadataFactory('ContentChild', (selector, data = {}) => (Object.assign({ selector, first: true, isViewQuery: false, descendants: true }, data))); const createViewChildren = makeMetadataFactory('ViewChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: true, descendants: true }, data))); const createViewChild = makeMetadataFactory('ViewChild', (selector, data) => (Object.assign({ selector, first: true, isViewQuery: true, descendants: true }, data))); const createDirective = makeMetadataFactory('Directive', (dir = {}) => dir); var ViewEncapsulation; (function (ViewEncapsulation) { ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; ViewEncapsulation[ViewEncapsulation["Native"] = 1] = "Native"; ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None"; ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom"; })(ViewEncapsulation || (ViewEncapsulation = {})); var ChangeDetectionStrategy; (function (ChangeDetectionStrategy) { ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); const createComponent = makeMetadataFactory('Component', (c = {}) => (Object.assign({ changeDetection: ChangeDetectionStrategy.Default }, c))); const createPipe = makeMetadataFactory('Pipe', (p) => (Object.assign({ pure: true }, p))); const createInput = makeMetadataFactory('Input', (bindingPropertyName) => ({ bindingPropertyName })); const createOutput = makeMetadataFactory('Output', (bindingPropertyName) => ({ bindingPropertyName })); const createHostBinding = makeMetadataFactory('HostBinding', (hostPropertyName) => ({ hostPropertyName })); const createHostListener = makeMetadataFactory('HostListener', (eventName, args) => ({ eventName, args })); const createNgModule = makeMetadataFactory('NgModule', (ngModule) => ngModule); const createInjectable = makeMetadataFactory('Injectable', (injectable = {}) => injectable); const CUSTOM_ELEMENTS_SCHEMA = { name: 'custom-elements' }; const NO_ERRORS_SCHEMA = { name: 'no-errors-schema' }; const createOptional = makeMetadataFactory('Optional'); const createSelf = makeMetadataFactory('Self'); const createSkipSelf = makeMetadataFactory('SkipSelf'); const createHost = makeMetadataFactory('Host'); const Type = Function; var SecurityContext; (function (SecurityContext) { SecurityContext[SecurityContext["NONE"] = 0] = "NONE"; SecurityContext[SecurityContext["HTML"] = 1] = "HTML"; SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE"; SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT"; SecurityContext[SecurityContext["URL"] = 4] = "URL"; SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL"; })(SecurityContext || (SecurityContext = {})); var MissingTranslationStrategy; (function (MissingTranslationStrategy) { MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error"; MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning"; MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore"; })(MissingTranslationStrategy || (MissingTranslationStrategy = {})); function makeMetadataFactory(name, props) { const factory = (...args) => { const values = props ? props(...args) : {}; return Object.assign({ ngMetadataName: name }, values); }; factory.isTypeOf = (obj) => obj && obj.ngMetadataName === name; factory.ngMetadataName = name; return factory; } function parserSelectorToSimpleSelector(selector) { const classes = selector.classNames && selector.classNames.length ? [8 /* CLASS */, ...selector.classNames] : []; const elementName = selector.element && selector.element !== '*' ? selector.element : ''; return [elementName, ...selector.attrs, ...classes]; } function parserSelectorToNegativeSelector(selector) { const classes = selector.classNames && selector.classNames.length ? [8 /* CLASS */, ...selector.classNames] : []; if (selector.element) { return [ 1 /* NOT */ | 4 /* ELEMENT */, selector.element, ...selector.attrs, ...classes ]; } else if (selector.attrs.length) { return [1 /* NOT */ | 2 /* ATTRIBUTE */, ...selector.attrs, ...classes]; } else { return selector.classNames && selector.classNames.length ? [1 /* NOT */ | 8 /* CLASS */, ...selector.classNames] : []; } } function parserSelectorToR3Selector(selector) { const positive = parserSelectorToSimpleSelector(selector); const negative = selector.notSelectors && selector.notSelectors.length ? selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) : []; return positive.concat(...negative); } function parseSelectorToR3Selector(selector) { const selectors = CssSelector.parse(selector); return selectors.map(parserSelectorToR3Selector); } var core = /*#__PURE__*/Object.freeze({ createInject: createInject, createInjectionToken: createInjectionToken, createAttribute: createAttribute, createContentChildren: createContentChildren, createContentChild: createContentChild, createViewChildren: createViewChildren, createViewChild: createViewChild, createDirective: createDirective, get ViewEncapsulation () { return ViewEncapsulation; }, get ChangeDetectionStrategy () { return ChangeDetectionStrategy; }, createComponent: createComponent, createPipe: createPipe, createInput: createInput, createOutput: createOutput, createHostBinding: createHostBinding, createHostListener: createHostListener, createNgModule: createNgModule, createInjectable: createInjectable, CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA, createOptional: createOptional, createSelf: createSelf, createSkipSelf: createSkipSelf, createHost: createHost, Type: Type, get SecurityContext () { return SecurityContext; }, get MissingTranslationStrategy () { return MissingTranslationStrategy; }, parseSelectorToR3Selector: parseSelectorToR3Selector }); /** * @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 */ const DASH_CASE_REGEXP = /-+([a-z0-9])/g; function dashCaseToCamelCase(input) { return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase()); } function splitAtColon(input, defaultValues) { return _splitAt(input, ':', defaultValues); } function splitAtPeriod(input, defaultValues) { return _splitAt(input, '.', defaultValues); } function _splitAt(input, character, defaultValues) { const characterIndex = input.indexOf(character); if (characterIndex == -1) return defaultValues; return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()]; } function visitValue(value, visitor, context) { if (Array.isArray(value)) { return visitor.visitArray(value, context); } if (isStrictStringMap(value)) { return visitor.visitStringMap(value, context); } if (value == null || typeof value == 'string' || typeof value == 'number' || typeof value == 'boolean') { return visitor.visitPrimitive(value, context); } return visitor.visitOther(value, context); } function isDefined(val) { return val !== null && val !== undefined; } function noUndefined(val) { return val === undefined ? null : val; } class ValueTransformer { visitArray(arr, context) { return arr.map(value => visitValue(value, this, context)); } visitStringMap(map, context) { const result = {}; Object.keys(map).forEach(key => { result[key] = visitValue(map[key], this, context); }); return result; } visitPrimitive(value, context) { return value; } visitOther(value, context) { return value; } } const SyncAsync = { assertSync: (value) => { if (isPromise(value)) { throw new Error(`Illegal state: value cannot be a promise`); } return value; }, then: (value, cb) => { return isPromise(value) ? value.then(cb) : cb(value); }, all: (syncAsyncValues) => { return syncAsyncValues.some(isPromise) ? Promise.all(syncAsyncValues) : syncAsyncValues; } }; function error(msg) { throw new Error(`Internal Error: ${msg}`); } function syntaxError(msg, parseErrors) { const error = Error(msg); error[ERROR_SYNTAX_ERROR] = true; if (parseErrors) error[ERROR_PARSE_ERRORS] = parseErrors; return error; } const ERROR_SYNTAX_ERROR = 'ngSyntaxError'; const ERROR_PARSE_ERRORS = 'ngParseErrors'; function isSyntaxError(error) { return error[ERROR_SYNTAX_ERROR]; } function getParseErrors(error) { return error[ERROR_PARSE_ERRORS] || []; } // Escape characters that have a special meaning in Regular Expressions function escapeRegExp(s) { return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); } const STRING_MAP_PROTO = Object.getPrototypeOf({}); function isStrictStringMap(obj) { return typeof obj === 'object' && obj !== null && Object.getPrototypeOf(obj) === STRING_MAP_PROTO; } function utf8Encode(str) { let encoded = ''; for (let index = 0; index < str.length; index++) { let codePoint = str.charCodeAt(index); // decode surrogate // see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > (index + 1)) { const low = str.charCodeAt(index + 1); if (low >= 0xdc00 && low <= 0xdfff) { index++; codePoint = ((codePoint - 0xd800) << 10) + low - 0xdc00 + 0x10000; } } if (codePoint <= 0x7f) { encoded += String.fromCharCode(codePoint); } else if (codePoint <= 0x7ff) { encoded += String.fromCharCode(((codePoint >> 6) & 0x1F) | 0xc0, (codePoint & 0x3f) | 0x80); } else if (codePoint <= 0xffff) { encoded += String.fromCharCode((codePoint >> 12) | 0xe0, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80); } else if (codePoint <= 0x1fffff) { encoded += String.fromCharCode(((codePoint >> 18) & 0x07) | 0xf0, ((codePoint >> 12) & 0x3f) | 0x80, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80); } } return encoded; } function stringify(token) { if (typeof token === 'string') { return token; } if (token instanceof Array) { return '[' + token.map(stringify).join(', ') + ']'; } if (token == null) { return '' + token; } if (token.overriddenName) { return `${token.overriddenName}`; } if (token.name) { return `${token.name}`; } // WARNING: do not try to `JSON.stringify(token)` here // see https://github.com/angular/angular/issues/23440 const res = token.toString(); if (res == null) { return '' + res; } const newLineIndex = res.indexOf('\n'); return newLineIndex === -1 ? res : res.substring(0, newLineIndex); } /** * Lazily retrieves the reference value from a forwardRef. */ function resolveForwardRef(type) { if (typeof type === 'function' && type.hasOwnProperty('__forward_ref__')) { return type(); } else { return type; } } /** * Determine if the argument is shaped like a Promise */ function isPromise(obj) { // allow any Promise/A+ compliant thenable. // It's up to the caller to ensure that obj.then conforms to the spec return !!obj && typeof obj.then === 'function'; } class Version { constructor(full) { this.full = full; const splits = full.split('.'); this.major = splits[0]; this.minor = splits[1]; this.patch = splits.slice(2).join('.'); } } /** * @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 */ const VERSION = new Version('6.1.10'); /** * @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 */ /** * A segment of text within the template. */ class TextAst { constructor(value, ngContentIndex, sourceSpan) { this.value = value; this.ngContentIndex = ngContentIndex; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitText(this, context); } } /** * A bound expression within the text of a template. */ class BoundTextAst { constructor(value, ngContentIndex, sourceSpan) { this.value = value; this.ngContentIndex = ngContentIndex; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitBoundText(this, context); } } /** * A plain attribute on an element. */ class AttrAst { constructor(name, value, sourceSpan) { this.name = name; this.value = value; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitAttr(this, context); } } const BoundPropertyMapping = { [4 /* Animation */]: 4 /* Animation */, [1 /* Attribute */]: 1 /* Attribute */, [2 /* Class */]: 2 /* Class */, [0 /* Property */]: 0 /* Property */, [3 /* Style */]: 3 /* Style */, }; /** * A binding for an element property (e.g. `[property]="expression"`) or an animation trigger (e.g. * `[@trigger]="stateExp"`) */ class BoundElementPropertyAst { constructor(name, type, securityContext, value, unit, sourceSpan) { this.name = name; this.type = type; this.securityContext = securityContext; this.value = value; this.unit = unit; this.sourceSpan = sourceSpan; this.isAnimation = this.type === 4 /* Animation */; } static fromBoundProperty(prop) { const type = BoundPropertyMapping[prop.type]; return new BoundElementPropertyAst(prop.name, type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan); } visit(visitor, context) { return visitor.visitElementProperty(this, context); } } /** * A binding for an element event (e.g. `(event)="handler()"`) or an animation trigger event (e.g. * `(@trigger.phase)="callback($event)"`). */ class BoundEventAst { constructor(name, target, phase, handler, sourceSpan) { this.name = name; this.target = target; this.phase = phase; this.handler = handler; this.sourceSpan = sourceSpan; this.fullName = BoundEventAst.calcFullName(this.name, this.target, this.phase); this.isAnimation = !!this.phase; } static calcFullName(name, target, phase) { if (target) { return `${target}:${name}`; } if (phase) { return `@${name}.${phase}`; } return name; } static fromParsedEvent(event) { const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null; const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null; return new BoundEventAst(event.name, target, phase, event.handler, event.sourceSpan); } visit(visitor, context) { return visitor.visitEvent(this, context); } } /** * A reference declaration on an element (e.g. `let someName="expression"`). */ class ReferenceAst { constructor(name, value, originalValue, sourceSpan) { this.name = name; this.value = value; this.originalValue = originalValue; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitReference(this, context); } } /** * A variable declaration on a <ng-template> (e.g. `var-someName="someLocalName"`). */ class VariableAst { constructor(name, value, sourceSpan) { this.name = name; this.value = value; this.sourceSpan = sourceSpan; } static fromParsedVariable(v) { return new VariableAst(v.name, v.value, v.sourceSpan); } visit(visitor, context) { return visitor.visitVariable(this, context); } } /** * An element declaration in a template. */ class ElementAst { constructor(name, attrs, inputs, outputs, references, directives, providers, hasViewContainer, queryMatches, children, ngContentIndex, sourceSpan, endSourceSpan) { this.name = name; this.attrs = attrs; this.inputs = inputs; this.outputs = outputs; this.references = references; this.directives = directives; this.providers = providers; this.hasViewContainer = hasViewContainer; this.queryMatches = queryMatches; this.children = children; this.ngContentIndex = ngContentIndex; this.sourceSpan = sourceSpan; this.endSourceSpan = endSourceSpan; } visit(visitor, context) { return visitor.visitElement(this, context); } } /** * A `<ng-template>` element included in an Angular template. */ class EmbeddedTemplateAst { constructor(attrs, outputs, references, variables, directives, providers, hasViewContainer, queryMatches, children, ngContentIndex, sourceSpan) { this.attrs = attrs; this.outputs = outputs; this.references = references; this.variables = variables; this.directives = directives; this.providers = providers; this.hasViewContainer = hasViewContainer; this.queryMatches = queryMatches; this.children = children; this.ngContentIndex = ngContentIndex; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitEmbeddedTemplate(this, context); } } /** * A directive property with a bound value (e.g. `*ngIf="condition"). */ class BoundDirectivePropertyAst { constructor(directiveName, templateName, value, sourceSpan) { this.directiveName = directiveName; this.templateName = templateName; this.value = value; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitDirectiveProperty(this, context); } } /** * A directive declared on an element. */ class DirectiveAst { constructor(directive, inputs, hostProperties, hostEvents, contentQueryStartId, sourceSpan) { this.directive = directive; this.inputs = inputs; this.hostProperties = hostProperties; this.hostEvents = hostEvents; this.contentQueryStartId = contentQueryStartId; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitDirective(this, context); } } /** * A provider declared on an element */ class ProviderAst { constructor(token, multiProvider, eager, providers, providerType, lifecycleHooks, sourceSpan, isModule) { this.token = token; this.multiProvider = multiProvider; this.eager = eager; this.providers = providers; this.providerType = providerType; this.lifecycleHooks = lifecycleHooks; this.sourceSpan = sourceSpan; this.isModule = isModule; } visit(visitor, context) { // No visit method in the visitor for now... return null; } } var ProviderAstType; (function (ProviderAstType) { ProviderAstType[ProviderAstType["PublicService"] = 0] = "PublicService"; ProviderAstType[ProviderAstType["PrivateService"] = 1] = "PrivateService"; ProviderAstType[ProviderAstType["Component"] = 2] = "Component"; ProviderAstType[ProviderAstType["Directive"] = 3] = "Directive"; ProviderAstType[ProviderAstType["Builtin"] = 4] = "Builtin"; })(ProviderAstType || (ProviderAstType = {})); /** * Position where content is to be projected (instance of `<ng-content>` in a template). */ class NgContentAst { constructor(index, ngContentIndex, sourceSpan) { this.index = index; this.ngContentIndex = ngContentIndex; this.sourceSpan = sourceSpan; } visit(visitor, context) { return visitor.visitNgContent(this, context); } } /** * A visitor that accepts each node but doesn't do anything. It is intended to be used * as the base class for a visitor that is only interested in a subset of the node types. */ class NullTemplateVisitor { visitNgContent(ast, context) { } visitEmbeddedTemplate(ast, context) { } visitElement(ast, context) { } visitReference(ast, context) { } visitVariable(ast, context) { } visitEvent(ast, context) { } visitElementProperty(ast, context) { } visitAttr(ast, context) { } visitBoundText(ast, context) { } visitText(ast, context) { } visitDirective(ast, context) { } visitDirectiveProperty(ast, context) { } } /** * Base class that can be used to build a visitor that visits each node * in an template ast recursively. */ class RecursiveTemplateAstVisitor extends NullTemplateVisitor { constructor() { super(); } // Nodes with children visitEmbeddedTemplate(ast, context) { return this.visitChildren(context, visit => { visit(ast.attrs); visit(ast.references); visit(ast.variables); visit(ast.directives); visit(ast.providers); visit(ast.children); }); } visitElement(ast, context) { return this.visitChildren(context, visit => { visit(ast.attrs); visit(ast.inputs); visit(ast.outputs); visit(ast.references); visit(ast.directives); visit(ast.providers); visit(ast.children);