(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["vendor"],{
/***/ "./node_modules/@angular/common/fesm2015/common.js":
/*!*********************************************************!*\
!*** ./node_modules/@angular/common/fesm2015/common.js ***!
\*********************************************************/
/*! exports provided: ɵangular_packages_common_common_c, ɵangular_packages_common_common_h, ɵangular_packages_common_common_g, ɵangular_packages_common_common_f, ɵangular_packages_common_common_k, ɵangular_packages_common_common_j, ɵangular_packages_common_common_i, ɵangular_packages_common_common_a, ɵangular_packages_common_common_b, ɵangular_packages_common_common_e, ɵangular_packages_common_common_d, ɵregisterLocaleData, registerLocaleData, formatDate, formatCurrency, formatNumber, formatPercent, NgLocaleLocalization, NgLocalization, Plural, NumberFormatStyle, FormStyle, TranslationWidth, FormatWidth, NumberSymbol, WeekDay, getNumberOfCurrencyDigits, getCurrencySymbol, getLocaleDayPeriods, getLocaleDayNames, getLocaleMonthNames, getLocaleId, getLocaleEraNames, getLocaleWeekEndRange, getLocaleFirstDayOfWeek, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocalePluralCase, getLocaleTimeFormat, getLocaleNumberSymbol, getLocaleNumberFormat, getLocaleCurrencyName, getLocaleCurrencySymbol, ɵparseCookieValue, CommonModule, DeprecatedI18NPipesModule, NgClass, NgClassBase, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgStyleBase, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe, KeyValuePipe, DeprecatedDatePipe, DeprecatedCurrencyPipe, DeprecatedDecimalPipe, DeprecatedPercentPipe, ɵPLATFORM_BROWSER_ID, ɵPLATFORM_SERVER_ID, ɵPLATFORM_WORKER_APP_ID, ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi, VERSION, ViewportScroller, ɵNullViewportScroller, ɵNgClassImplProvider__POST_R3__, ɵNgClassR2Impl, ɵNgClassImpl, ɵNgStyleImplProvider__POST_R3__, ɵNgStyleR2Impl, ɵNgStyleImpl, ɵngStyleDirectiveDef__POST_R3__, ɵngClassDirectiveDef__POST_R3__, PlatformLocation, LOCATION_INITIALIZED, LocationStrategy, APP_BASE_HREF, HashLocationStrategy, PathLocationStrategy, Location */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_c", function() { return COMMON_DIRECTIVES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_h", function() { return NgClassImplProvider; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_g", function() { return NgClassImplProvider__PRE_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_f", function() { return NgClassR3Impl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_k", function() { return NgStyleImplProvider; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_j", function() { return NgStyleImplProvider__PRE_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_i", function() { return NgStyleR3Impl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_a", function() { return DEPRECATED_PLURAL_FN; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_b", function() { return getPluralCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_e", function() { return COMMON_DEPRECATED_I18N_PIPES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_d", function() { return COMMON_PIPES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵregisterLocaleData", function() { return registerLocaleData; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "registerLocaleData", function() { return registerLocaleData; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatDate", function() { return formatDate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatCurrency", function() { return formatCurrency; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatNumber", function() { return formatNumber; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatPercent", function() { return formatPercent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocaleLocalization", function() { return NgLocaleLocalization; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocalization", function() { return NgLocalization; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Plural", function() { return Plural; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberFormatStyle", function() { return NumberFormatStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormStyle", function() { return FormStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TranslationWidth", function() { return TranslationWidth; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormatWidth", function() { return FormatWidth; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberSymbol", function() { return NumberSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WeekDay", function() { return WeekDay; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNumberOfCurrencyDigits", function() { return getNumberOfCurrencyDigits; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getCurrencySymbol", function() { return getCurrencySymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayPeriods", function() { return getLocaleDayPeriods; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayNames", function() { return getLocaleDayNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleMonthNames", function() { return getLocaleMonthNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleId", function() { return getLocaleId; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleEraNames", function() { return getLocaleEraNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleWeekEndRange", function() { return getLocaleWeekEndRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleFirstDayOfWeek", function() { return getLocaleFirstDayOfWeek; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateFormat", function() { return getLocaleDateFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateTimeFormat", function() { return getLocaleDateTimeFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriodRules", function() { return getLocaleExtraDayPeriodRules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriods", function() { return getLocaleExtraDayPeriods; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocalePluralCase", function() { return getLocalePluralCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleTimeFormat", function() { return getLocaleTimeFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberSymbol", function() { return getLocaleNumberSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberFormat", function() { return getLocaleNumberFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencyName", function() { return getLocaleCurrencyName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencySymbol", function() { return getLocaleCurrencySymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵparseCookieValue", function() { return parseCookieValue; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommonModule", function() { return CommonModule; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedI18NPipesModule", function() { return DeprecatedI18NPipesModule; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgClass", function() { return NgClass; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgClassBase", function() { return NgClassBase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOf", function() { return NgForOf; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOfContext", function() { return NgForOfContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIf", function() { return NgIf; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIfContext", function() { return NgIfContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPlural", function() { return NgPlural; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPluralCase", function() { return NgPluralCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgStyle", function() { return NgStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgStyleBase", function() { return NgStyleBase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitch", function() { return NgSwitch; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchCase", function() { return NgSwitchCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchDefault", function() { return NgSwitchDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgTemplateOutlet", function() { return NgTemplateOutlet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgComponentOutlet", function() { return NgComponentOutlet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DOCUMENT", function() { return DOCUMENT; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncPipe", function() { return AsyncPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DatePipe", function() { return DatePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nPluralPipe", function() { return I18nPluralPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nSelectPipe", function() { return I18nSelectPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JsonPipe", function() { return JsonPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LowerCasePipe", function() { return LowerCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CurrencyPipe", function() { return CurrencyPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DecimalPipe", function() { return DecimalPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PercentPipe", function() { return PercentPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SlicePipe", function() { return SlicePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UpperCasePipe", function() { return UpperCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TitleCasePipe", function() { return TitleCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyValuePipe", function() { return KeyValuePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedDatePipe", function() { return DeprecatedDatePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedCurrencyPipe", function() { return DeprecatedCurrencyPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedDecimalPipe", function() { return DeprecatedDecimalPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedPercentPipe", function() { return DeprecatedPercentPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_BROWSER_ID", function() { return PLATFORM_BROWSER_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_SERVER_ID", function() { return PLATFORM_SERVER_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_APP_ID", function() { return PLATFORM_WORKER_APP_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_UI_ID", function() { return PLATFORM_WORKER_UI_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformBrowser", function() { return isPlatformBrowser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformServer", function() { return isPlatformServer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerApp", function() { return isPlatformWorkerApp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerUi", function() { return isPlatformWorkerUi; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewportScroller", function() { return ViewportScroller; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNullViewportScroller", function() { return NullViewportScroller; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassImplProvider__POST_R3__", function() { return NgClassImplProvider__POST_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassR2Impl", function() { return NgClassR2Impl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassImpl", function() { return NgClassImpl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleImplProvider__POST_R3__", function() { return NgStyleImplProvider__POST_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleR2Impl", function() { return NgStyleR2Impl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleImpl", function() { return NgStyleImpl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵngStyleDirectiveDef__POST_R3__", function() { return ngStyleDirectiveDef__POST_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵngClassDirectiveDef__POST_R3__", function() { return ngClassDirectiveDef__POST_R3__; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlatformLocation", function() { return PlatformLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LOCATION_INITIALIZED", function() { return LOCATION_INITIALIZED; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LocationStrategy", function() { return LocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "APP_BASE_HREF", function() { return APP_BASE_HREF; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HashLocationStrategy", function() { return HashLocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PathLocationStrategy", function() { return PathLocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Location", function() { return Location; });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js");
/**
* @license Angular v8.2.14
* (c) 2010-2019 Google LLC. https://angular.io/
* License: MIT
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* This class should not be used directly by an application developer. Instead, use
* {\@link Location}.
*
* `PlatformLocation` encapsulates all calls to DOM apis, which allows the Router to be platform
* agnostic.
* This means that we can have different implementation of `PlatformLocation` for the different
* platforms that angular supports. For example, `\@angular/platform-browser` provides an
* implementation specific to the browser environment, while `\@angular/platform-webworker` provides
* one suitable for use with web workers.
*
* The `PlatformLocation` class is used directly by all implementations of {\@link LocationStrategy}
* when they need to interact with the DOM apis like pushState, popState, etc...
*
* {\@link LocationStrategy} in turn is used by the {\@link Location} service which is used directly
* by the {\@link Router} in order to navigate between routes. Since all interactions between {\@link
* Router} /
* {\@link Location} / {\@link LocationStrategy} and DOM apis flow through the `PlatformLocation`
* class they are all platform independent.
*
* \@publicApi
* @abstract
*/
class PlatformLocation {
}
if (false) {}
/**
* \@description
* Indicates when a location is initialized.
*
* \@publicApi
* @type {?}
*/
const LOCATION_INITIALIZED = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('Location Initialized');
/**
* \@description
* A serializable version of the event from `onPopState` or `onHashChange`
*
* \@publicApi
* @record
*/
function LocationChangeEvent() { }
if (false) {}
/**
* \@publicApi
* @record
*/
function LocationChangeListener() { }
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Enables the `Location` service to read route state from the browser's URL.
* Angular provides two strategies:
* `HashLocationStrategy` and `PathLocationStrategy`.
*
* Applications should use the `Router` or `Location` services to
* interact with application route state.
*
* For instance, `HashLocationStrategy` produces URLs like
* http://example.com#/foo,
* and `PathLocationStrategy` produces
* http://example.com/foo as an equivalent URL.
*
* See these two classes for more.
*
* \@publicApi
* @abstract
*/
class LocationStrategy {
}
if (false) {}
/**
* A predefined [DI token](guide/glossary#di-token) for the base href
* to be used with the `PathLocationStrategy`.
* The base href is the URL prefix that should be preserved when generating
* and recognizing URLs.
*
* \@usageNotes
*
* The following example shows how to use this token to configure the root app injector
* with a base href value, so that the DI framework can supply the dependency anywhere in the app.
*
* ```typescript
* import {Component, NgModule} from '\@angular/core';
* import {APP_BASE_HREF} from '\@angular/common';
*
* \@NgModule({
* providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
* })
* class AppModule {}
* ```
*
* \@publicApi
* @type {?}
*/
const APP_BASE_HREF = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('appBaseHref');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@publicApi
* @record
*/
function PopStateEvent() { }
if (false) {}
/**
* \@description
*
* A service that applications can use to interact with a browser's URL.
*
* Depending on the `LocationStrategy` used, `Location` persists
* to the URL's path or the URL's hash segment.
*
* \@usageNotes
*
* It's better to use the `Router#navigate` service to trigger route changes. Use
* `Location` only if you need to interact with or create normalized URLs outside of
* routing.
*
* `Location` is responsible for normalizing the URL against the application's base href.
* A normalized URL is absolute from the URL host, includes the application's base href, and has no
* trailing slash:
* - `/my/app/user/123` is normalized
* - `my/app/user/123` **is not** normalized
* - `/my/app/user/123/` **is not** normalized
*
* ### Example
*
*
*
* \@publicApi
*/
class Location {
/**
* @param {?} platformStrategy
* @param {?} platformLocation
*/
constructor(platformStrategy, platformLocation) {
/**
* \@internal
*/
this._subject = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["EventEmitter"]();
/**
* \@internal
*/
this._urlChangeListeners = [];
this._platformStrategy = platformStrategy;
/** @type {?} */
const browserBaseHref = this._platformStrategy.getBaseHref();
this._platformLocation = platformLocation;
this._baseHref = Location.stripTrailingSlash(_stripIndexHtml(browserBaseHref));
this._platformStrategy.onPopState((/**
* @param {?} ev
* @return {?}
*/
(ev) => {
this._subject.emit({
'url': this.path(true),
'pop': true,
'state': ev.state,
'type': ev.type,
});
}));
}
/**
* Normalizes the URL path for this location.
*
* @param {?=} includeHash True to include an anchor fragment in the path.
*
* @return {?} The normalized URL path.
*/
// TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is
// removed.
path(includeHash = false) {
return this.normalize(this._platformStrategy.path(includeHash));
}
/**
* Reports the current state of the location history.
* @return {?} The current value of the `history.state` object.
*/
getState() { return this._platformLocation.getState(); }
/**
* Normalizes the given path and compares to the current normalized path.
*
* @param {?} path The given URL path.
* @param {?=} query Query parameters.
*
* @return {?} True if the given URL path is equal to the current normalized path, false
* otherwise.
*/
isCurrentPathEqualTo(path, query = '') {
return this.path() == this.normalize(path + Location.normalizeQueryParams(query));
}
/**
* Normalizes a URL path by stripping any trailing slashes.
*
* @param {?} url String representing a URL.
*
* @return {?} The normalized URL string.
*/
normalize(url) {
return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url)));
}
/**
* Normalizes an external URL path.
* If the given URL doesn't begin with a leading slash (`'/'`), adds one
* before normalizing. Adds a hash if `HashLocationStrategy` is
* in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
*
* @param {?} url String representing a URL.
*
* @return {?} A normalized platform-specific URL.
*/
prepareExternalUrl(url) {
if (url && url[0] !== '/') {
url = '/' + url;
}
return this._platformStrategy.prepareExternalUrl(url);
}
// TODO: rename this method to pushState
/**
* Changes the browser's URL to a normalized version of a given URL, and pushes a
* new item onto the platform's history.
*
* @param {?} path URL path to normalize.
* @param {?=} query Query parameters.
* @param {?=} state Location history state.
*
* @return {?}
*/
go(path, query = '', state = null) {
this._platformStrategy.pushState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + Location.normalizeQueryParams(query)), state);
}
/**
* Changes the browser's URL to a normalized version of the given URL, and replaces
* the top item on the platform's history stack.
*
* @param {?} path URL path to normalize.
* @param {?=} query Query parameters.
* @param {?=} state Location history state.
* @return {?}
*/
replaceState(path, query = '', state = null) {
this._platformStrategy.replaceState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + Location.normalizeQueryParams(query)), state);
}
/**
* Navigates forward in the platform's history.
* @return {?}
*/
forward() { this._platformStrategy.forward(); }
/**
* Navigates back in the platform's history.
* @return {?}
*/
back() { this._platformStrategy.back(); }
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param {?} fn The change handler function, which take a URL and a location history state.
* @return {?}
*/
onUrlChange(fn) {
this._urlChangeListeners.push(fn);
this.subscribe((/**
* @param {?} v
* @return {?}
*/
v => { this._notifyUrlChangeListeners(v.url, v.state); }));
}
/**
* \@internal
* @param {?=} url
* @param {?=} state
* @return {?}
*/
_notifyUrlChangeListeners(url = '', state) {
this._urlChangeListeners.forEach((/**
* @param {?} fn
* @return {?}
*/
fn => fn(url, state)));
}
/**
* Subscribes to the platform's `popState` events.
*
* @param {?} onNext
* @param {?=} onThrow
* @param {?=} onReturn
* @return {?} Subscribed events.
*/
subscribe(onNext, onThrow, onReturn) {
return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
}
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param {?} params String of URL parameters.
*
* @return {?} The normalized URL parameters string.
*/
static normalizeQueryParams(params) {
return params && params[0] !== '?' ? '?' + params : params;
}
/**
* Joins two parts of a URL with a slash if needed.
*
* @param {?} start URL string
* @param {?} end URL string
*
*
* @return {?} The joined URL string.
*/
static joinWithSlash(start, end) {
if (start.length == 0) {
return end;
}
if (end.length == 0) {
return start;
}
/** @type {?} */
let slashes = 0;
if (start.endsWith('/')) {
slashes++;
}
if (end.startsWith('/')) {
slashes++;
}
if (slashes == 2) {
return start + end.substring(1);
}
if (slashes == 1) {
return start + end;
}
return start + '/' + end;
}
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param {?} url URL string.
*
* @return {?} The URL string, modified if needed.
*/
static stripTrailingSlash(url) {
/** @type {?} */
const match = url.match(/#|\?|$/);
/** @type {?} */
const pathEndIdx = match && match.index || url.length;
/** @type {?} */
const droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0);
return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx);
}
}
Location.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
Location.ctorParameters = () => [
{ type: LocationStrategy },
{ type: PlatformLocation }
];
if (false) {}
/**
* @param {?} baseHref
* @param {?} url
* @return {?}
*/
function _stripBaseHref(baseHref, url) {
return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url;
}
/**
* @param {?} url
* @return {?}
*/
function _stripIndexHtml(url) {
return url.replace(/\/index.html$/, '');
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@description
* A {\@link LocationStrategy} used to configure the {\@link Location} service to
* represent its state in the
* [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax)
* of the browser's URL.
*
* For instance, if you call `location.go('/foo')`, the browser's URL will become
* `example.com#/foo`.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/location/ts/hash_location_component.ts region='LocationComponent'}
*
* \@publicApi
*/
class HashLocationStrategy extends LocationStrategy {
/**
* @param {?} _platformLocation
* @param {?=} _baseHref
*/
constructor(_platformLocation, _baseHref) {
super();
this._platformLocation = _platformLocation;
this._baseHref = '';
if (_baseHref != null) {
this._baseHref = _baseHref;
}
}
/**
* @param {?} fn
* @return {?}
*/
onPopState(fn) {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}
/**
* @return {?}
*/
getBaseHref() { return this._baseHref; }
/**
* @param {?=} includeHash
* @return {?}
*/
path(includeHash = false) {
// the hash value is always prefixed with a `#`
// and if it is empty then it will stay empty
/** @type {?} */
let path = this._platformLocation.hash;
if (path == null)
path = '#';
return path.length > 0 ? path.substring(1) : path;
}
/**
* @param {?} internal
* @return {?}
*/
prepareExternalUrl(internal) {
/** @type {?} */
const url = Location.joinWithSlash(this._baseHref, internal);
return url.length > 0 ? ('#' + url) : url;
}
/**
* @param {?} state
* @param {?} title
* @param {?} path
* @param {?} queryParams
* @return {?}
*/
pushState(state, title, path, queryParams) {
/** @type {?} */
let url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
if (url.length == 0) {
url = this._platformLocation.pathname;
}
this._platformLocation.pushState(state, title, url);
}
/**
* @param {?} state
* @param {?} title
* @param {?} path
* @param {?} queryParams
* @return {?}
*/
replaceState(state, title, path, queryParams) {
/** @type {?} */
let url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
if (url.length == 0) {
url = this._platformLocation.pathname;
}
this._platformLocation.replaceState(state, title, url);
}
/**
* @return {?}
*/
forward() { this._platformLocation.forward(); }
/**
* @return {?}
*/
back() { this._platformLocation.back(); }
}
HashLocationStrategy.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
HashLocationStrategy.ctorParameters = () => [
{ type: PlatformLocation },
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@description
* A {\@link LocationStrategy} used to configure the {\@link Location} service to
* represent its state in the
* [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the
* browser's URL.
*
* If you're using `PathLocationStrategy`, you must provide a {\@link APP_BASE_HREF}
* or add a base element to the document. This URL prefix that will be preserved
* when generating and recognizing URLs.
*
* For instance, if you provide an `APP_BASE_HREF` of `'/my/app'` and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`.
*
* Similarly, if you add `` to the document and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/location/ts/path_location_component.ts region='LocationComponent'}
*
* \@publicApi
*/
class PathLocationStrategy extends LocationStrategy {
/**
* @param {?} _platformLocation
* @param {?=} href
*/
constructor(_platformLocation, href) {
super();
this._platformLocation = _platformLocation;
if (href == null) {
href = this._platformLocation.getBaseHrefFromDOM();
}
if (href == null) {
throw new Error(`No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.`);
}
this._baseHref = href;
}
/**
* @param {?} fn
* @return {?}
*/
onPopState(fn) {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}
/**
* @return {?}
*/
getBaseHref() { return this._baseHref; }
/**
* @param {?} internal
* @return {?}
*/
prepareExternalUrl(internal) {
return Location.joinWithSlash(this._baseHref, internal);
}
/**
* @param {?=} includeHash
* @return {?}
*/
path(includeHash = false) {
/** @type {?} */
const pathname = this._platformLocation.pathname +
Location.normalizeQueryParams(this._platformLocation.search);
/** @type {?} */
const hash = this._platformLocation.hash;
return hash && includeHash ? `${pathname}${hash}` : pathname;
}
/**
* @param {?} state
* @param {?} title
* @param {?} url
* @param {?} queryParams
* @return {?}
*/
pushState(state, title, url, queryParams) {
/** @type {?} */
const externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams));
this._platformLocation.pushState(state, title, externalUrl);
}
/**
* @param {?} state
* @param {?} title
* @param {?} url
* @param {?} queryParams
* @return {?}
*/
replaceState(state, title, url, queryParams) {
/** @type {?} */
const externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams));
this._platformLocation.replaceState(state, title, externalUrl);
}
/**
* @return {?}
*/
forward() { this._platformLocation.forward(); }
/**
* @return {?}
*/
back() { this._platformLocation.back(); }
}
PathLocationStrategy.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
PathLocationStrategy.ctorParameters = () => [
{ type: PlatformLocation },
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @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
*/
// THIS CODE IS GENERATED - DO NOT MODIFY
// See angular/tools/gulp-tasks/cldr/extract.js
/**
* \@internal
* @type {?}
*/
const CURRENCIES_EN = {
'ADP': [undefined, undefined, 0],
'AFN': [undefined, undefined, 0],
'ALL': [undefined, undefined, 0],
'AMD': [undefined, undefined, 0],
'AOA': [undefined, 'Kz'],
'ARS': [undefined, '$'],
'AUD': ['A$', '$'],
'BAM': [undefined, 'KM'],
'BBD': [undefined, '$'],
'BDT': [undefined, '৳'],
'BHD': [undefined, undefined, 3],
'BIF': [undefined, undefined, 0],
'BMD': [undefined, '$'],
'BND': [undefined, '$'],
'BOB': [undefined, 'Bs'],
'BRL': ['R$'],
'BSD': [undefined, '$'],
'BWP': [undefined, 'P'],
'BYN': [undefined, 'р.', 2],
'BYR': [undefined, undefined, 0],
'BZD': [undefined, '$'],
'CAD': ['CA$', '$', 2],
'CHF': [undefined, undefined, 2],
'CLF': [undefined, undefined, 4],
'CLP': [undefined, '$', 0],
'CNY': ['CN¥', '¥'],
'COP': [undefined, '$', 0],
'CRC': [undefined, '₡', 2],
'CUC': [undefined, '$'],
'CUP': [undefined, '$'],
'CZK': [undefined, 'Kč', 2],
'DJF': [undefined, undefined, 0],
'DKK': [undefined, 'kr', 2],
'DOP': [undefined, '$'],
'EGP': [undefined, 'E£'],
'ESP': [undefined, '₧', 0],
'EUR': ['€'],
'FJD': [undefined, '$'],
'FKP': [undefined, '£'],
'GBP': ['£'],
'GEL': [undefined, '₾'],
'GIP': [undefined, '£'],
'GNF': [undefined, 'FG', 0],
'GTQ': [undefined, 'Q'],
'GYD': [undefined, '$', 0],
'HKD': ['HK$', '$'],
'HNL': [undefined, 'L'],
'HRK': [undefined, 'kn'],
'HUF': [undefined, 'Ft', 2],
'IDR': [undefined, 'Rp', 0],
'ILS': ['₪'],
'INR': ['₹'],
'IQD': [undefined, undefined, 0],
'IRR': [undefined, undefined, 0],
'ISK': [undefined, 'kr', 0],
'ITL': [undefined, undefined, 0],
'JMD': [undefined, '$'],
'JOD': [undefined, undefined, 3],
'JPY': ['¥', undefined, 0],
'KHR': [undefined, '៛'],
'KMF': [undefined, 'CF', 0],
'KPW': [undefined, '₩', 0],
'KRW': ['₩', undefined, 0],
'KWD': [undefined, undefined, 3],
'KYD': [undefined, '$'],
'KZT': [undefined, '₸'],
'LAK': [undefined, '₭', 0],
'LBP': [undefined, 'L£', 0],
'LKR': [undefined, 'Rs'],
'LRD': [undefined, '$'],
'LTL': [undefined, 'Lt'],
'LUF': [undefined, undefined, 0],
'LVL': [undefined, 'Ls'],
'LYD': [undefined, undefined, 3],
'MGA': [undefined, 'Ar', 0],
'MGF': [undefined, undefined, 0],
'MMK': [undefined, 'K', 0],
'MNT': [undefined, '₮', 0],
'MRO': [undefined, undefined, 0],
'MUR': [undefined, 'Rs', 0],
'MXN': ['MX$', '$'],
'MYR': [undefined, 'RM'],
'NAD': [undefined, '$'],
'NGN': [undefined, '₦'],
'NIO': [undefined, 'C$'],
'NOK': [undefined, 'kr', 2],
'NPR': [undefined, 'Rs'],
'NZD': ['NZ$', '$'],
'OMR': [undefined, undefined, 3],
'PHP': [undefined, '₱'],
'PKR': [undefined, 'Rs', 0],
'PLN': [undefined, 'zł'],
'PYG': [undefined, '₲', 0],
'RON': [undefined, 'lei'],
'RSD': [undefined, undefined, 0],
'RUB': [undefined, '₽'],
'RUR': [undefined, 'р.'],
'RWF': [undefined, 'RF', 0],
'SBD': [undefined, '$'],
'SEK': [undefined, 'kr', 2],
'SGD': [undefined, '$'],
'SHP': [undefined, '£'],
'SLL': [undefined, undefined, 0],
'SOS': [undefined, undefined, 0],
'SRD': [undefined, '$'],
'SSP': [undefined, '£'],
'STD': [undefined, undefined, 0],
'STN': [undefined, 'Db'],
'SYP': [undefined, '£', 0],
'THB': [undefined, '฿'],
'TMM': [undefined, undefined, 0],
'TND': [undefined, undefined, 3],
'TOP': [undefined, 'T$'],
'TRL': [undefined, undefined, 0],
'TRY': [undefined, '₺'],
'TTD': [undefined, '$'],
'TWD': ['NT$', '$', 2],
'TZS': [undefined, undefined, 0],
'UAH': [undefined, '₴'],
'UGX': [undefined, undefined, 0],
'USD': ['$'],
'UYI': [undefined, undefined, 0],
'UYU': [undefined, '$'],
'UZS': [undefined, undefined, 0],
'VEF': [undefined, 'Bs'],
'VND': ['₫', undefined, 0],
'VUV': [undefined, undefined, 0],
'XAF': ['FCFA', undefined, 0],
'XCD': ['EC$', '$'],
'XOF': ['CFA', undefined, 0],
'XPF': ['CFPF', undefined, 0],
'YER': [undefined, undefined, 0],
'ZAR': [undefined, 'R'],
'ZMK': [undefined, undefined, 0],
'ZMW': [undefined, 'ZK'],
'ZWD': [undefined, undefined, 0]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @enum {number} */
const NumberFormatStyle = {
Decimal: 0,
Percent: 1,
Currency: 2,
Scientific: 3,
};
NumberFormatStyle[NumberFormatStyle.Decimal] = 'Decimal';
NumberFormatStyle[NumberFormatStyle.Percent] = 'Percent';
NumberFormatStyle[NumberFormatStyle.Currency] = 'Currency';
NumberFormatStyle[NumberFormatStyle.Scientific] = 'Scientific';
/** @enum {number} */
const Plural = {
Zero: 0,
One: 1,
Two: 2,
Few: 3,
Many: 4,
Other: 5,
};
Plural[Plural.Zero] = 'Zero';
Plural[Plural.One] = 'One';
Plural[Plural.Two] = 'Two';
Plural[Plural.Few] = 'Few';
Plural[Plural.Many] = 'Many';
Plural[Plural.Other] = 'Other';
/** @enum {number} */
const FormStyle = {
Format: 0,
Standalone: 1,
};
FormStyle[FormStyle.Format] = 'Format';
FormStyle[FormStyle.Standalone] = 'Standalone';
/** @enum {number} */
const TranslationWidth = {
/** 1 character for `en-US`. For example: 'S' */
Narrow: 0,
/** 3 characters for `en-US`. For example: 'Sun' */
Abbreviated: 1,
/** Full length for `en-US`. For example: "Sunday" */
Wide: 2,
/** 2 characters for `en-US`, For example: "Su" */
Short: 3,
};
TranslationWidth[TranslationWidth.Narrow] = 'Narrow';
TranslationWidth[TranslationWidth.Abbreviated] = 'Abbreviated';
TranslationWidth[TranslationWidth.Wide] = 'Wide';
TranslationWidth[TranslationWidth.Short] = 'Short';
/** @enum {number} */
const FormatWidth = {
/**
* For `en-US`, 'M/d/yy, h:mm a'`
* (Example: `6/15/15, 9:03 AM`)
*/
Short: 0,
/**
* For `en-US`, `'MMM d, y, h:mm:ss a'`
* (Example: `Jun 15, 2015, 9:03:01 AM`)
*/
Medium: 1,
/**
* For `en-US`, `'MMMM d, y, h:mm:ss a z'`
* (Example: `June 15, 2015 at 9:03:01 AM GMT+1`)
*/
Long: 2,
/**
* For `en-US`, `'EEEE, MMMM d, y, h:mm:ss a zzzz'`
* (Example: `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00`)
*/
Full: 3,
};
FormatWidth[FormatWidth.Short] = 'Short';
FormatWidth[FormatWidth.Medium] = 'Medium';
FormatWidth[FormatWidth.Long] = 'Long';
FormatWidth[FormatWidth.Full] = 'Full';
/** @enum {number} */
const NumberSymbol = {
/**
* Decimal separator.
* For `en-US`, the dot character.
* Example : 2,345`.`67
*/
Decimal: 0,
/**
* Grouping separator, typically for thousands.
* For `en-US`, the comma character.
* Example: 2`,`345.67
*/
Group: 1,
/**
* List-item separator.
* Example: "one, two, and three"
*/
List: 2,
/**
* Sign for percentage (out of 100).
* Example: 23.4%
*/
PercentSign: 3,
/**
* Sign for positive numbers.
* Example: +23
*/
PlusSign: 4,
/**
* Sign for negative numbers.
* Example: -23
*/
MinusSign: 5,
/**
* Computer notation for exponential value (n times a power of 10).
* Example: 1.2E3
*/
Exponential: 6,
/**
* Human-readable format of exponential.
* Example: 1.2x103
*/
SuperscriptingExponent: 7,
/**
* Sign for permille (out of 1000).
* Example: 23.4‰
*/
PerMille: 8,
/**
* Infinity, can be used with plus and minus.
* Example: ∞, +∞, -∞
*/
Infinity: 9,
/**
* Not a number.
* Example: NaN
*/
NaN: 10,
/**
* Symbol used between time units.
* Example: 10:52
*/
TimeSeparator: 11,
/**
* Decimal separator for currency values (fallback to `Decimal`).
* Example: $2,345.67
*/
CurrencyDecimal: 12,
/**
* Group separator for currency values (fallback to `Group`).
* Example: $2,345.67
*/
CurrencyGroup: 13,
};
NumberSymbol[NumberSymbol.Decimal] = 'Decimal';
NumberSymbol[NumberSymbol.Group] = 'Group';
NumberSymbol[NumberSymbol.List] = 'List';
NumberSymbol[NumberSymbol.PercentSign] = 'PercentSign';
NumberSymbol[NumberSymbol.PlusSign] = 'PlusSign';
NumberSymbol[NumberSymbol.MinusSign] = 'MinusSign';
NumberSymbol[NumberSymbol.Exponential] = 'Exponential';
NumberSymbol[NumberSymbol.SuperscriptingExponent] = 'SuperscriptingExponent';
NumberSymbol[NumberSymbol.PerMille] = 'PerMille';
NumberSymbol[NumberSymbol.Infinity] = 'Infinity';
NumberSymbol[NumberSymbol.NaN] = 'NaN';
NumberSymbol[NumberSymbol.TimeSeparator] = 'TimeSeparator';
NumberSymbol[NumberSymbol.CurrencyDecimal] = 'CurrencyDecimal';
NumberSymbol[NumberSymbol.CurrencyGroup] = 'CurrencyGroup';
/** @enum {number} */
const WeekDay = {
Sunday: 0,
Monday: 1,
Tuesday: 2,
Wednesday: 3,
Thursday: 4,
Friday: 5,
Saturday: 6,
};
WeekDay[WeekDay.Sunday] = 'Sunday';
WeekDay[WeekDay.Monday] = 'Monday';
WeekDay[WeekDay.Tuesday] = 'Tuesday';
WeekDay[WeekDay.Wednesday] = 'Wednesday';
WeekDay[WeekDay.Thursday] = 'Thursday';
WeekDay[WeekDay.Friday] = 'Friday';
WeekDay[WeekDay.Saturday] = 'Saturday';
/**
* Retrieves the locale ID from the currently loaded locale.
* The loaded locale could be, for example, a global one rather than a regional one.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code, such as `fr-FR`.
* @return {?} The locale code. For example, `fr`.
*/
function getLocaleId(locale) {
return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale)[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId];
}
/**
* Retrieves day period strings for the given locale.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} formStyle The required grammatical form.
* @param {?} width The required character width.
* @return {?} An array of localized period strings. For example, `[AM, PM]` for `en-US`.
*/
function getLocaleDayPeriods(locale, formStyle, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const amPmData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsStandalone]]));
/** @type {?} */
const amPm = getLastDefinedValue(amPmData, formStyle);
return getLastDefinedValue(amPm, width);
}
/**
* Retrieves days of the week for the given locale, using the Gregorian calendar.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} formStyle The required grammatical form.
* @param {?} width The required character width.
* @return {?} An array of localized name strings.
* For example,`[Sunday, Monday, ... Saturday]` for `en-US`.
*/
function getLocaleDayNames(locale, formStyle, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const daysData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysStandalone]]));
/** @type {?} */
const days = getLastDefinedValue(daysData, formStyle);
return getLastDefinedValue(days, width);
}
/**
* Retrieves months of the year for the given locale, using the Gregorian calendar.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} formStyle The required grammatical form.
* @param {?} width The required character width.
* @return {?} An array of localized name strings.
* For example, `[January, February, ...]` for `en-US`.
*/
function getLocaleMonthNames(locale, formStyle, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const monthsData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsStandalone]]));
/** @type {?} */
const months = getLastDefinedValue(monthsData, formStyle);
return getLastDefinedValue(months, width);
}
/**
* Retrieves Gregorian-calendar eras for the given locale.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} width The required character width.
* @return {?} An array of localized era strings.
* For example, `[AD, BC]` for `en-US`.
*/
function getLocaleEraNames(locale, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const erasData = (/** @type {?} */ (data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Eras]));
return getLastDefinedValue(erasData, width);
}
/**
* Retrieves the first day of the week for the given locale.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} A day index number, using the 0-based week-day index for `en-US`
* (Sunday = 0, Monday = 1, ...).
* For example, for `fr-FR`, returns 1 to indicate that the first day is Monday.
*/
function getLocaleFirstDayOfWeek(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].FirstDayOfWeek];
}
/**
* Range of week days that are considered the week-end for the given locale.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} The range of day values, `[startDay, endDay]`.
*/
function getLocaleWeekEndRange(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].WeekendRange];
}
/**
* Retrieves a localized date-value formating string.
*
* @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} width The format type.
* @return {?} The localized formating string.
*/
function getLocaleDateFormat(locale, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateFormat], width);
}
/**
* Retrieves a localized time-value formatting string.
*
* @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} width The format type.
* @return {?} The localized formatting string.
*/
function getLocaleTimeFormat(locale, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].TimeFormat], width);
}
/**
* Retrieves a localized date-time formatting string.
*
* @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} width The format type.
* @return {?} The localized formatting string.
*/
function getLocaleDateTimeFormat(locale, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const dateTimeFormatData = (/** @type {?} */ (data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateTimeFormat]));
return getLastDefinedValue(dateTimeFormatData, width);
}
/**
* Retrieves a localized number symbol that can be used to replace placeholders in number formats.
* @see `NumberSymbol` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale The locale code.
* @param {?} symbol The symbol to localize.
* @return {?} The character for the localized symbol.
*/
function getLocaleNumberSymbol(locale, symbol) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
/** @type {?} */
const res = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][symbol];
if (typeof res === 'undefined') {
if (symbol === NumberSymbol.CurrencyDecimal) {
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Decimal];
}
else if (symbol === NumberSymbol.CurrencyGroup) {
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Group];
}
}
return res;
}
/**
* Retrieves a number format for a given locale.
*
* Numbers are formatted using patterns, like `#,###.00`. For example, the pattern `#,###.00`
* when used to format the number 12345.678 could result in "12'345,678". That would happen if the
* grouping separator for your language is an apostrophe, and the decimal separator is a comma.
*
* Important: The characters `.` `,` `0` `#` (and others below) are special placeholders
* that stand for the decimal separator, and so on, and are NOT real characters.
* You must NOT "translate" the placeholders. For example, don't change `.` to `,` even though in
* your language the decimal point is written with a comma. The symbols should be replaced by the
* local equivalents, using the appropriate `NumberSymbol` for your language.
*
* Here are the special characters used in number patterns:
*
* | Symbol | Meaning |
* |--------|---------|
* | . | Replaced automatically by the character used for the decimal point. |
* | , | Replaced by the "grouping" (thousands) separator. |
* | 0 | Replaced by a digit (or zero if there aren't enough digits). |
* | # | Replaced by a digit (or nothing if there aren't enough). |
* | ¤ | Replaced by a currency symbol, such as $ or USD. |
* | % | Marks a percent format. The % symbol may change position, but must be retained. |
* | E | Marks a scientific format. The E symbol may change position, but must be retained. |
* | ' | Special characters used as literal characters are quoted with ASCII single quotes. |
*
* @see `NumberFormatStyle` / [CLDR website](http://cldr.unicode.org/translation/number-patterns) / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} type The type of numeric value to be formatted (such as `Decimal` or `Currency`.)
* @return {?} The localized format string.
*/
function getLocaleNumberFormat(locale, type) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberFormats][type];
}
/**
* Retrieves the symbol used to represent the currency for the main country
* corresponding to a given locale. For example, '$' for `en-US`.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} The localized symbol character,
* or `null` if the main country cannot be determined.
*/
function getLocaleCurrencySymbol(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencySymbol] || null;
}
/**
* Retrieves the name of the currency for the main country corresponding
* to a given locale. For example, 'US Dollar' for `en-US`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} The currency name,
* or `null` if the main country cannot be determined.
*/
function getLocaleCurrencyName(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencyName] || null;
}
/**
* Retrieves the currency values for a given locale.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} The currency values.
*/
function getLocaleCurrencies(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Currencies];
}
/**
* \@alias core/ɵgetLocalePluralCase
* \@publicApi
* @type {?}
*/
const getLocalePluralCase = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocalePluralCase"];
/**
* @param {?} data
* @return {?}
*/
function checkFullData(data) {
if (!data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData]) {
throw new Error(`Missing extra locale data for the locale "${data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`);
}
}
/**
* Retrieves locale-specific rules used to determine which day period to use
* when more than one period is defined for a locale.
*
* There is a rule for each defined day period. The
* first rule is applied to the first day period and so on.
* Fall back to AM/PM when no rules are available.
*
* A rule can specify a period as time range, or as a single time value.
*
* This functionality is only available when you have loaded the full locale data.
* See the ["I18n guide"](guide/i18n#i18n-pipes).
*
* @see `getLocaleExtraDayPeriods()` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @return {?} The rules for the locale, a single time value or array of *from-time, to-time*,
* or null if no periods are available.
*
*/
function getLocaleExtraDayPeriodRules(locale) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
checkFullData(data);
/** @type {?} */
const rules = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][2 /* ExtraDayPeriodsRules */] || [];
return rules.map((/**
* @param {?} rule
* @return {?}
*/
(rule) => {
if (typeof rule === 'string') {
return extractTime(rule);
}
return [extractTime(rule[0]), extractTime(rule[1])];
}));
}
/**
* Retrieves locale-specific day periods, which indicate roughly how a day is broken up
* in different languages.
* For example, for `en-US`, periods are morning, noon, afternoon, evening, and midnight.
*
* This functionality is only available when you have loaded the full locale data.
* See the ["I18n guide"](guide/i18n#i18n-pipes).
*
* @see `getLocaleExtraDayPeriodRules()` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} formStyle The required grammatical form.
* @param {?} width The required character width.
* @return {?} The translated day-period strings.
*/
function getLocaleExtraDayPeriods(locale, formStyle, width) {
/** @type {?} */
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
checkFullData(data);
/** @type {?} */
const dayPeriodsData = (/** @type {?} */ ([
data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][0 /* ExtraDayPeriodFormats */],
data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][1 /* ExtraDayPeriodStandalone */]
]));
/** @type {?} */
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
return getLastDefinedValue(dayPeriods, width) || [];
}
/**
* Retrieves the first value that is defined in an array, going backwards from an index position.
*
* To avoid repeating the same data (as when the "format" and "standalone" forms are the same)
* add the first value to the locale data arrays, and add other values only if they are different.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @template T
* @param {?} data The data array to retrieve from.
* @param {?} index A 0-based index into the array to start from.
* @return {?} The value immediately before the given index position.
*/
function getLastDefinedValue(data, index) {
for (let i = index; i > -1; i--) {
if (typeof data[i] !== 'undefined') {
return data[i];
}
}
throw new Error('Locale data API: locale data undefined');
}
/**
* Extracts the hours and minutes from a string like "15:45"
* @param {?} time
* @return {?}
*/
function extractTime(time) {
const [h, m] = time.split(':');
return { hours: +h, minutes: +m };
}
/**
* Retrieves the currency symbol for a given currency code.
*
* For example, for the default `en-US` locale, the code `USD` can
* be represented by the narrow symbol `$` or the wide symbol `US$`.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} code The currency code.
* @param {?} format The format, `wide` or `narrow`.
* @param {?=} locale A locale code for the locale format rules to use.
*
* @return {?} The symbol, or the currency code if no symbol is available.0
*/
function getCurrencySymbol(code, format, locale = 'en') {
/** @type {?} */
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
/** @type {?} */
const symbolNarrow = currency[1 /* SymbolNarrow */];
if (format === 'narrow' && typeof symbolNarrow === 'string') {
return symbolNarrow;
}
return currency[0 /* Symbol */] || code;
}
// Most currencies have cents, that's why the default is 2
/** @type {?} */
const DEFAULT_NB_OF_CURRENCY_DIGITS = 2;
/**
* Reports the number of decimal digits for a given currency.
* The value depends upon the presence of cents in that particular currency.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} code The currency code.
* @return {?} The number of decimal digits, typically 0 or 2.
*/
function getNumberOfCurrencyDigits(code) {
/** @type {?} */
let digits;
/** @type {?} */
const currency = CURRENCIES_EN[code];
if (currency) {
digits = currency[2 /* NbOfDigits */];
}
return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
// 1 2 3 4 5 6 7 8 9 10 11
/** @type {?} */
const NAMED_FORMATS = {};
/** @type {?} */
const DATE_FORMATS_SPLIT = /((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
/** @enum {number} */
const ZoneWidth = {
Short: 0,
ShortGMT: 1,
Long: 2,
Extended: 3,
};
ZoneWidth[ZoneWidth.Short] = 'Short';
ZoneWidth[ZoneWidth.ShortGMT] = 'ShortGMT';
ZoneWidth[ZoneWidth.Long] = 'Long';
ZoneWidth[ZoneWidth.Extended] = 'Extended';
/** @enum {number} */
const DateType = {
FullYear: 0,
Month: 1,
Date: 2,
Hours: 3,
Minutes: 4,
Seconds: 5,
FractionalSeconds: 6,
Day: 7,
};
DateType[DateType.FullYear] = 'FullYear';
DateType[DateType.Month] = 'Month';
DateType[DateType.Date] = 'Date';
DateType[DateType.Hours] = 'Hours';
DateType[DateType.Minutes] = 'Minutes';
DateType[DateType.Seconds] = 'Seconds';
DateType[DateType.FractionalSeconds] = 'FractionalSeconds';
DateType[DateType.Day] = 'Day';
/** @enum {number} */
const TranslationType = {
DayPeriods: 0,
Days: 1,
Months: 2,
Eras: 3,
};
TranslationType[TranslationType.DayPeriods] = 'DayPeriods';
TranslationType[TranslationType.Days] = 'Days';
TranslationType[TranslationType.Months] = 'Months';
TranslationType[TranslationType.Eras] = 'Eras';
/**
* \@ngModule CommonModule
* \@description
*
* Formats a date according to locale rules.
*
* @see `DatePipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} value The date to format, as a Date, or a number (milliseconds since UTC epoch)
* or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime).
* @param {?} format The date-time components to include. See `DatePipe` for details.
* @param {?} locale A locale code for the locale format rules to use.
* @param {?=} timezone The time zone. A time zone offset from GMT (such as `'+0430'`),
* or a standard UTC/GMT or continental US time zone abbreviation.
* If not specified, uses host system settings.
*
* @return {?} The formatted date string.
*
*/
function formatDate(value, format, locale, timezone) {
/** @type {?} */
let date = toDate(value);
/** @type {?} */
const namedFormat = getNamedFormat(locale, format);
format = namedFormat || format;
/** @type {?} */
let parts = [];
/** @type {?} */
let match;
while (format) {
match = DATE_FORMATS_SPLIT.exec(format);
if (match) {
parts = parts.concat(match.slice(1));
/** @type {?} */
const part = parts.pop();
if (!part) {
break;
}
format = part;
}
else {
parts.push(format);
break;
}
}
/** @type {?} */
let dateTimezoneOffset = date.getTimezoneOffset();
if (timezone) {
dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
date = convertTimezoneToLocal(date, timezone, true);
}
/** @type {?} */
let text = '';
parts.forEach((/**
* @param {?} value
* @return {?}
*/
value => {
/** @type {?} */
const dateFormatter = getDateFormatter(value);
text += dateFormatter ?
dateFormatter(date, locale, dateTimezoneOffset) :
value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
}));
return text;
}
/**
* @param {?} locale
* @param {?} format
* @return {?}
*/
function getNamedFormat(locale, format) {
/** @type {?} */
const localeId = getLocaleId(locale);
NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {};
if (NAMED_FORMATS[localeId][format]) {
return NAMED_FORMATS[localeId][format];
}
/** @type {?} */
let formatValue = '';
switch (format) {
case 'shortDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Short);
break;
case 'mediumDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Medium);
break;
case 'longDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Long);
break;
case 'fullDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Full);
break;
case 'shortTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Short);
break;
case 'mediumTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium);
break;
case 'longTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Long);
break;
case 'fullTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Full);
break;
case 'short':
/** @type {?} */
const shortTime = getNamedFormat(locale, 'shortTime');
/** @type {?} */
const shortDate = getNamedFormat(locale, 'shortDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]);
break;
case 'medium':
/** @type {?} */
const mediumTime = getNamedFormat(locale, 'mediumTime');
/** @type {?} */
const mediumDate = getNamedFormat(locale, 'mediumDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]);
break;
case 'long':
/** @type {?} */
const longTime = getNamedFormat(locale, 'longTime');
/** @type {?} */
const longDate = getNamedFormat(locale, 'longDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]);
break;
case 'full':
/** @type {?} */
const fullTime = getNamedFormat(locale, 'fullTime');
/** @type {?} */
const fullDate = getNamedFormat(locale, 'fullDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]);
break;
}
if (formatValue) {
NAMED_FORMATS[localeId][format] = formatValue;
}
return formatValue;
}
/**
* @param {?} str
* @param {?} opt_values
* @return {?}
*/
function formatDateTime(str, opt_values) {
if (opt_values) {
str = str.replace(/\{([^}]+)}/g, (/**
* @param {?} match
* @param {?} key
* @return {?}
*/
function (match, key) {
return (opt_values != null && key in opt_values) ? opt_values[key] : match;
}));
}
return str;
}
/**
* @param {?} num
* @param {?} digits
* @param {?=} minusSign
* @param {?=} trim
* @param {?=} negWrap
* @return {?}
*/
function padNumber(num, digits, minusSign = '-', trim, negWrap) {
/** @type {?} */
let neg = '';
if (num < 0 || (negWrap && num <= 0)) {
if (negWrap) {
num = -num + 1;
}
else {
num = -num;
neg = minusSign;
}
}
/** @type {?} */
let strNum = String(num);
while (strNum.length < digits) {
strNum = '0' + strNum;
}
if (trim) {
strNum = strNum.substr(strNum.length - digits);
}
return neg + strNum;
}
/**
* @param {?} milliseconds
* @param {?} digits
* @return {?}
*/
function formatFractionalSeconds(milliseconds, digits) {
/** @type {?} */
const strMs = padNumber(milliseconds, 3);
return strMs.substr(0, digits);
}
/**
* Returns a date formatter that transforms a date into its locale digit representation
* @param {?} name
* @param {?} size
* @param {?=} offset
* @param {?=} trim
* @param {?=} negWrap
* @return {?}
*/
function dateGetter(name, size, offset = 0, trim = false, negWrap = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
let part = getDatePart(name, date);
if (offset > 0 || part > -offset) {
part += offset;
}
if (name === DateType.Hours) {
if (part === 0 && offset === -12) {
part = 12;
}
}
else if (name === DateType.FractionalSeconds) {
return formatFractionalSeconds(part, size);
}
/** @type {?} */
const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
return padNumber(part, size, localeMinus, trim, negWrap);
});
}
/**
* @param {?} part
* @param {?} date
* @return {?}
*/
function getDatePart(part, date) {
switch (part) {
case DateType.FullYear:
return date.getFullYear();
case DateType.Month:
return date.getMonth();
case DateType.Date:
return date.getDate();
case DateType.Hours:
return date.getHours();
case DateType.Minutes:
return date.getMinutes();
case DateType.Seconds:
return date.getSeconds();
case DateType.FractionalSeconds:
return date.getMilliseconds();
case DateType.Day:
return date.getDay();
default:
throw new Error(`Unknown DateType value "${part}".`);
}
}
/**
* Returns a date formatter that transforms a date into its locale string representation
* @param {?} name
* @param {?} width
* @param {?=} form
* @param {?=} extended
* @return {?}
*/
function dateStrGetter(name, width, form = FormStyle.Format, extended = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
return getDateTranslation(date, locale, name, width, form, extended);
});
}
/**
* Returns the locale translation of a date for a given form, type and width
* @param {?} date
* @param {?} locale
* @param {?} name
* @param {?} width
* @param {?} form
* @param {?} extended
* @return {?}
*/
function getDateTranslation(date, locale, name, width, form, extended) {
switch (name) {
case TranslationType.Months:
return getLocaleMonthNames(locale, form, width)[date.getMonth()];
case TranslationType.Days:
return getLocaleDayNames(locale, form, width)[date.getDay()];
case TranslationType.DayPeriods:
/** @type {?} */
const currentHours = date.getHours();
/** @type {?} */
const currentMinutes = date.getMinutes();
if (extended) {
/** @type {?} */
const rules = getLocaleExtraDayPeriodRules(locale);
/** @type {?} */
const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);
/** @type {?} */
let result;
rules.forEach((/**
* @param {?} rule
* @param {?} index
* @return {?}
*/
(rule, index) => {
if (Array.isArray(rule)) {
// morning, afternoon, evening, night
const { hours: hoursFrom, minutes: minutesFrom } = rule[0];
const { hours: hoursTo, minutes: minutesTo } = rule[1];
if (currentHours >= hoursFrom && currentMinutes >= minutesFrom &&
(currentHours < hoursTo ||
(currentHours === hoursTo && currentMinutes < minutesTo))) {
result = dayPeriods[index];
}
}
else { // noon or midnight
// noon or midnight
const { hours, minutes } = rule;
if (hours === currentHours && minutes === currentMinutes) {
result = dayPeriods[index];
}
}
}));
if (result) {
return result;
}
}
// if no rules for the day periods, we use am/pm by default
return getLocaleDayPeriods(locale, form, (/** @type {?} */ (width)))[currentHours < 12 ? 0 : 1];
case TranslationType.Eras:
return getLocaleEraNames(locale, (/** @type {?} */ (width)))[date.getFullYear() <= 0 ? 0 : 1];
default:
// This default case is not needed by TypeScript compiler, as the switch is exhaustive.
// However Closure Compiler does not understand that and reports an error in typed mode.
// The `throw new Error` below works around the problem, and the unexpected: never variable
// makes sure tsc still checks this code is unreachable.
/** @type {?} */
const unexpected = name;
throw new Error(`unexpected translation type ${unexpected}`);
}
}
/**
* Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or
* GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30,
* extended = +04:30)
* @param {?} width
* @return {?}
*/
function timeZoneGetter(width) {
return (/**
* @param {?} date
* @param {?} locale
* @param {?} offset
* @return {?}
*/
function (date, locale, offset) {
/** @type {?} */
const zone = -1 * offset;
/** @type {?} */
const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
/** @type {?} */
const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60);
switch (width) {
case ZoneWidth.Short:
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.ShortGMT:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 1, minusSign);
case ZoneWidth.Long:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.Extended:
if (offset === 0) {
return 'Z';
}
else {
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
}
default:
throw new Error(`Unknown zone width "${width}"`);
}
});
}
/** @type {?} */
const JANUARY = 0;
/** @type {?} */
const THURSDAY = 4;
/**
* @param {?} year
* @return {?}
*/
function getFirstThursdayOfYear(year) {
/** @type {?} */
const firstDayOfYear = (new Date(year, JANUARY, 1)).getDay();
return new Date(year, 0, 1 + ((firstDayOfYear <= THURSDAY) ? THURSDAY : THURSDAY + 7) - firstDayOfYear);
}
/**
* @param {?} datetime
* @return {?}
*/
function getThursdayThisWeek(datetime) {
return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (THURSDAY - datetime.getDay()));
}
/**
* @param {?} size
* @param {?=} monthBased
* @return {?}
*/
function weekGetter(size, monthBased = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
let result;
if (monthBased) {
/** @type {?} */
const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1;
/** @type {?} */
const today = date.getDate();
result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7);
}
else {
/** @type {?} */
const firstThurs = getFirstThursdayOfYear(date.getFullYear());
/** @type {?} */
const thisThurs = getThursdayThisWeek(date);
/** @type {?} */
const diff = thisThurs.getTime() - firstThurs.getTime();
result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
}
return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
});
}
/** @type {?} */
const DATE_FORMATS = {};
// Based on CLDR formats:
// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
// See also explanations: http://cldr.unicode.org/translation/date-time
// TODO(ocombe): support all missing cldr formats: Y, U, Q, D, F, e, c, j, J, C, A, v, V, X, x
/**
* @param {?} format
* @return {?}
*/
function getDateFormatter(format) {
if (DATE_FORMATS[format]) {
return DATE_FORMATS[format];
}
/** @type {?} */
let formatter;
switch (format) {
// Era name (AD/BC)
case 'G':
case 'GG':
case 'GGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated);
break;
case 'GGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide);
break;
case 'GGGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow);
break;
// 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199)
case 'y':
formatter = dateGetter(DateType.FullYear, 1, 0, false, true);
break;
// 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yy':
formatter = dateGetter(DateType.FullYear, 2, 0, true, true);
break;
// 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yyy':
formatter = dateGetter(DateType.FullYear, 3, 0, false, true);
break;
// 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010)
case 'yyyy':
formatter = dateGetter(DateType.FullYear, 4, 0, false, true);
break;
// Month of the year (1-12), numeric
case 'M':
case 'L':
formatter = dateGetter(DateType.Month, 1, 1);
break;
case 'MM':
case 'LL':
formatter = dateGetter(DateType.Month, 2, 1);
break;
// Month of the year (January, ...), string, format
case 'MMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated);
break;
case 'MMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide);
break;
case 'MMMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow);
break;
// Month of the year (January, ...), string, standalone
case 'LLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone);
break;
case 'LLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone);
break;
case 'LLLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone);
break;
// Week of the year (1, ... 52)
case 'w':
formatter = weekGetter(1);
break;
case 'ww':
formatter = weekGetter(2);
break;
// Week of the month (1, ...)
case 'W':
formatter = weekGetter(1, true);
break;
// Day of the month (1-31)
case 'd':
formatter = dateGetter(DateType.Date, 1);
break;
case 'dd':
formatter = dateGetter(DateType.Date, 2);
break;
// Day of the Week
case 'E':
case 'EE':
case 'EEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated);
break;
case 'EEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide);
break;
case 'EEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow);
break;
case 'EEEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short);
break;
// Generic period of the day (am-pm)
case 'a':
case 'aa':
case 'aaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated);
break;
case 'aaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide);
break;
case 'aaaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow);
break;
// Extended period of the day (midnight, at night, ...), standalone
case 'b':
case 'bb':
case 'bbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true);
break;
case 'bbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true);
break;
case 'bbbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true);
break;
// Extended period of the day (midnight, night, ...), standalone
case 'B':
case 'BB':
case 'BBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true);
break;
case 'BBBB':
formatter =
dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true);
break;
case 'BBBBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true);
break;
// Hour in AM/PM, (1-12)
case 'h':
formatter = dateGetter(DateType.Hours, 1, -12);
break;
case 'hh':
formatter = dateGetter(DateType.Hours, 2, -12);
break;
// Hour of the day (0-23)
case 'H':
formatter = dateGetter(DateType.Hours, 1);
break;
// Hour in day, padded (00-23)
case 'HH':
formatter = dateGetter(DateType.Hours, 2);
break;
// Minute of the hour (0-59)
case 'm':
formatter = dateGetter(DateType.Minutes, 1);
break;
case 'mm':
formatter = dateGetter(DateType.Minutes, 2);
break;
// Second of the minute (0-59)
case 's':
formatter = dateGetter(DateType.Seconds, 1);
break;
case 'ss':
formatter = dateGetter(DateType.Seconds, 2);
break;
// Fractional second
case 'S':
formatter = dateGetter(DateType.FractionalSeconds, 1);
break;
case 'SS':
formatter = dateGetter(DateType.FractionalSeconds, 2);
break;
case 'SSS':
formatter = dateGetter(DateType.FractionalSeconds, 3);
break;
// Timezone ISO8601 short format (-0430)
case 'Z':
case 'ZZ':
case 'ZZZ':
formatter = timeZoneGetter(ZoneWidth.Short);
break;
// Timezone ISO8601 extended format (-04:30)
case 'ZZZZZ':
formatter = timeZoneGetter(ZoneWidth.Extended);
break;
// Timezone GMT short format (GMT+4)
case 'O':
case 'OO':
case 'OOO':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'z':
case 'zz':
case 'zzz':
formatter = timeZoneGetter(ZoneWidth.ShortGMT);
break;
// Timezone GMT long format (GMT+0430)
case 'OOOO':
case 'ZZZZ':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'zzzz':
formatter = timeZoneGetter(ZoneWidth.Long);
break;
default:
return null;
}
DATE_FORMATS[format] = formatter;
return formatter;
}
/**
* @param {?} timezone
* @param {?} fallback
* @return {?}
*/
function timezoneToOffset(timezone, fallback) {
// Support: IE 9-11 only, Edge 13-15+
// IE/Edge do not "understand" colon (`:`) in timezone
timezone = timezone.replace(/:/g, '');
/** @type {?} */
const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
/**
* @param {?} date
* @param {?} minutes
* @return {?}
*/
function addDateMinutes(date, minutes) {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + minutes);
return date;
}
/**
* @param {?} date
* @param {?} timezone
* @param {?} reverse
* @return {?}
*/
function convertTimezoneToLocal(date, timezone, reverse) {
/** @type {?} */
const reverseValue = reverse ? -1 : 1;
/** @type {?} */
const dateTimezoneOffset = date.getTimezoneOffset();
/** @type {?} */
const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset));
}
/**
* Converts a value to date.
*
* Supported input formats:
* - `Date`
* - number: timestamp
* - string: numeric (e.g. "1234"), ISO and date strings in a format supported by
* [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
* Note: ISO strings without time return a date without timeoffset.
*
* Throws if unable to convert to a date.
* @param {?} value
* @return {?}
*/
function toDate(value) {
if (isDate(value)) {
return value;
}
if (typeof value === 'number' && !isNaN(value)) {
return new Date(value);
}
if (typeof value === 'string') {
value = value.trim();
/** @type {?} */
const parsedNb = parseFloat(value);
// any string that only contains numbers, like "1234" but not like "1234hello"
if (!isNaN((/** @type {?} */ (value)) - parsedNb)) {
return new Date(parsedNb);
}
if (/^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
/* For ISO Strings without time the day, month and year must be extracted from the ISO String
before Date creation to avoid time offset and errors in the new Date.
If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new
date, some browsers (e.g. IE 9) will throw an invalid Date error.
If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset
is applied.
Note: ISO months are 0 for January, 1 for February, ... */
const [y, m, d] = value.split('-').map((/**
* @param {?} val
* @return {?}
*/
(val) => +val));
return new Date(y, m - 1, d);
}
/** @type {?} */
let match;
if (match = value.match(ISO8601_DATE_REGEX)) {
return isoStringToDate(match);
}
}
/** @type {?} */
const date = new Date((/** @type {?} */ (value)));
if (!isDate(date)) {
throw new Error(`Unable to convert "${value}" into a date`);
}
return date;
}
/**
* Converts a date in ISO8601 to a Date.
* Used instead of `Date.parse` because of browser discrepancies.
* @param {?} match
* @return {?}
*/
function isoStringToDate(match) {
/** @type {?} */
const date = new Date(0);
/** @type {?} */
let tzHour = 0;
/** @type {?} */
let tzMin = 0;
// match[8] means that the string contains "Z" (UTC) or a timezone like "+01:00" or "+0100"
/** @type {?} */
const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
/** @type {?} */
const timeSetter = match[8] ? date.setUTCHours : date.setHours;
// if there is a timezone defined like "+01:00" or "+0100"
if (match[9]) {
tzHour = Number(match[9] + match[10]);
tzMin = Number(match[9] + match[11]);
}
dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3]));
/** @type {?} */
const h = Number(match[4] || 0) - tzHour;
/** @type {?} */
const m = Number(match[5] || 0) - tzMin;
/** @type {?} */
const s = Number(match[6] || 0);
/** @type {?} */
const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
timeSetter.call(date, h, m, s, ms);
return date;
}
/**
* @param {?} value
* @return {?}
*/
function isDate(value) {
return value instanceof Date && !isNaN(value.valueOf());
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
/** @type {?} */
const MAX_DIGITS = 22;
/** @type {?} */
const DECIMAL_SEP = '.';
/** @type {?} */
const ZERO_CHAR = '0';
/** @type {?} */
const PATTERN_SEP = ';';
/** @type {?} */
const GROUP_SEP = ',';
/** @type {?} */
const DIGIT_CHAR = '#';
/** @type {?} */
const CURRENCY_CHAR = '¤';
/** @type {?} */
const PERCENT_CHAR = '%';
/**
* Transforms a number to a locale string based on a style and a format.
* @param {?} value
* @param {?} pattern
* @param {?} locale
* @param {?} groupSymbol
* @param {?} decimalSymbol
* @param {?=} digitsInfo
* @param {?=} isPercent
* @return {?}
*/
function formatNumberToLocaleString(value, pattern, locale, groupSymbol, decimalSymbol, digitsInfo, isPercent = false) {
/** @type {?} */
let formattedText = '';
/** @type {?} */
let isZero = false;
if (!isFinite(value)) {
formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity);
}
else {
/** @type {?} */
let parsedNumber = parseNumber(value);
if (isPercent) {
parsedNumber = toPercent(parsedNumber);
}
/** @type {?} */
let minInt = pattern.minInt;
/** @type {?} */
let minFraction = pattern.minFrac;
/** @type {?} */
let maxFraction = pattern.maxFrac;
if (digitsInfo) {
/** @type {?} */
const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);
if (parts === null) {
throw new Error(`${digitsInfo} is not a valid digit info`);
}
/** @type {?} */
const minIntPart = parts[1];
/** @type {?} */
const minFractionPart = parts[3];
/** @type {?} */
const maxFractionPart = parts[5];
if (minIntPart != null) {
minInt = parseIntAutoRadix(minIntPart);
}
if (minFractionPart != null) {
minFraction = parseIntAutoRadix(minFractionPart);
}
if (maxFractionPart != null) {
maxFraction = parseIntAutoRadix(maxFractionPart);
}
else if (minFractionPart != null && minFraction > maxFraction) {
maxFraction = minFraction;
}
}
roundNumber(parsedNumber, minFraction, maxFraction);
/** @type {?} */
let digits = parsedNumber.digits;
/** @type {?} */
let integerLen = parsedNumber.integerLen;
/** @type {?} */
const exponent = parsedNumber.exponent;
/** @type {?} */
let decimals = [];
isZero = digits.every((/**
* @param {?} d
* @return {?}
*/
d => !d));
// pad zeros for small numbers
for (; integerLen < minInt; integerLen++) {
digits.unshift(0);
}
// pad zeros for small numbers
for (; integerLen < 0; integerLen++) {
digits.unshift(0);
}
// extract decimals digits
if (integerLen > 0) {
decimals = digits.splice(integerLen, digits.length);
}
else {
decimals = digits;
digits = [0];
}
// format the integer digits with grouping separators
/** @type {?} */
const groups = [];
if (digits.length >= pattern.lgSize) {
groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
}
while (digits.length > pattern.gSize) {
groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
}
if (digits.length) {
groups.unshift(digits.join(''));
}
formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));
// append the decimal digits
if (decimals.length) {
formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join('');
}
if (exponent) {
formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + '+' + exponent;
}
}
if (value < 0 && !isZero) {
formattedText = pattern.negPre + formattedText + pattern.negSuf;
}
else {
formattedText = pattern.posPre + formattedText + pattern.posSuf;
}
return formattedText;
}
/**
* \@ngModule CommonModule
* \@description
*
* Formats a number as currency using locale rules.
*
* @see `formatNumber()` / `DecimalPipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} value The number to format.
* @param {?} locale A locale code for the locale format rules to use.
* @param {?} currency A string containing the currency symbol or its name,
* such as "$" or "Canadian Dollar". Used in output string, but does not affect the operation
* of the function.
* @param {?=} currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)
* currency code, such as `USD` for the US dollar and `EUR` for the euro.
* Used to determine the number of digits in the decimal part.
* @param {?=} digitsInfo
* @return {?} The formatted currency value.
*
*/
function formatCurrency(value, locale, currency, currencyCode, digitsInfo) {
/** @type {?} */
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency);
/** @type {?} */
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
pattern.minFrac = getNumberOfCurrencyDigits((/** @type {?} */ (currencyCode)));
pattern.maxFrac = pattern.minFrac;
/** @type {?} */
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo);
return res
.replace(CURRENCY_CHAR, currency)
// if we have 2 time the currency character, the second one is ignored
.replace(CURRENCY_CHAR, '');
}
/**
* \@ngModule CommonModule
* \@description
*
* Formats a number as a percentage according to locale rules.
*
* @see `formatNumber()` / `DecimalPipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* \@publicApi
*
* @param {?} value The number to format.
* @param {?} locale A locale code for the locale format rules to use.
* @param {?=} digitsInfo
* @return {?} The formatted percentage value.
*
*/
function formatPercent(value, locale, digitsInfo) {
/** @type {?} */
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent);
/** @type {?} */
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
/** @type {?} */
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true);
return res.replace(new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));
}
/**
* \@ngModule CommonModule
* \@description
*
* Formats a number as text, with group sizing, separator, and other
* parameters based on the locale.
*
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} value The number to format.
* @param {?} locale A locale code for the locale format rules to use.
* @param {?=} digitsInfo
* @return {?} The formatted text string.
*/
function formatNumber(value, locale, digitsInfo) {
/** @type {?} */
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal);
/** @type {?} */
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
return formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo);
}
/**
* @record
*/
function ParsedNumberFormat() { }
if (false) {}
/**
* @param {?} format
* @param {?=} minusSign
* @return {?}
*/
function parseNumberFormat(format, minusSign = '-') {
/** @type {?} */
const p = {
minInt: 1,
minFrac: 0,
maxFrac: 0,
posPre: '',
posSuf: '',
negPre: '',
negSuf: '',
gSize: 0,
lgSize: 0
};
/** @type {?} */
const patternParts = format.split(PATTERN_SEP);
/** @type {?} */
const positive = patternParts[0];
/** @type {?} */
const negative = patternParts[1];
/** @type {?} */
const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ?
positive.split(DECIMAL_SEP) :
[
positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1),
positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1)
];
/** @type {?} */
const integer = positiveParts[0];
/** @type {?} */
const fraction = positiveParts[1] || '';
p.posPre = integer.substr(0, integer.indexOf(DIGIT_CHAR));
for (let i = 0; i < fraction.length; i++) {
/** @type {?} */
const ch = fraction.charAt(i);
if (ch === ZERO_CHAR) {
p.minFrac = p.maxFrac = i + 1;
}
else if (ch === DIGIT_CHAR) {
p.maxFrac = i + 1;
}
else {
p.posSuf += ch;
}
}
/** @type {?} */
const groups = integer.split(GROUP_SEP);
p.gSize = groups[1] ? groups[1].length : 0;
p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;
if (negative) {
/** @type {?} */
const trunkLen = positive.length - p.posPre.length - p.posSuf.length;
/** @type {?} */
const pos = negative.indexOf(DIGIT_CHAR);
p.negPre = negative.substr(0, pos).replace(/'/g, '');
p.negSuf = negative.substr(pos + trunkLen).replace(/'/g, '');
}
else {
p.negPre = minusSign + p.posPre;
p.negSuf = p.posSuf;
}
return p;
}
/**
* @record
*/
function ParsedNumber() { }
if (false) {}
// Transforms a parsed number into a percentage by multiplying it by 100
/**
* @param {?} parsedNumber
* @return {?}
*/
function toPercent(parsedNumber) {
// if the number is 0, don't do anything
if (parsedNumber.digits[0] === 0) {
return parsedNumber;
}
// Getting the current number of decimals
/** @type {?} */
const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen;
if (parsedNumber.exponent) {
parsedNumber.exponent += 2;
}
else {
if (fractionLen === 0) {
parsedNumber.digits.push(0, 0);
}
else if (fractionLen === 1) {
parsedNumber.digits.push(0);
}
parsedNumber.integerLen += 2;
}
return parsedNumber;
}
/**
* Parses a number.
* Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/
* @param {?} num
* @return {?}
*/
function parseNumber(num) {
/** @type {?} */
let numStr = Math.abs(num) + '';
/** @type {?} */
let exponent = 0;
/** @type {?} */
let digits;
/** @type {?} */
let integerLen;
/** @type {?} */
let i;
/** @type {?} */
let j;
/** @type {?} */
let zeros;
// Decimal point?
if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) {
numStr = numStr.replace(DECIMAL_SEP, '');
}
// Exponential form?
if ((i = numStr.search(/e/i)) > 0) {
// Work out the exponent.
if (integerLen < 0)
integerLen = i;
integerLen += +numStr.slice(i + 1);
numStr = numStr.substring(0, i);
}
else if (integerLen < 0) {
// There was no decimal point or exponent so it is an integer.
integerLen = numStr.length;
}
// Count the number of leading zeros.
for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */
}
if (i === (zeros = numStr.length)) {
// The digits are all zero.
digits = [0];
integerLen = 1;
}
else {
// Count the number of trailing zeros
zeros--;
while (numStr.charAt(zeros) === ZERO_CHAR)
zeros--;
// Trailing zeros are insignificant so ignore them
integerLen -= i;
digits = [];
// Convert string to array of digits without leading/trailing zeros.
for (j = 0; i <= zeros; i++, j++) {
digits[j] = Number(numStr.charAt(i));
}
}
// If the number overflows the maximum allowed digits then use an exponent.
if (integerLen > MAX_DIGITS) {
digits = digits.splice(0, MAX_DIGITS - 1);
exponent = integerLen - 1;
integerLen = 1;
}
return { digits, exponent, integerLen };
}
/**
* Round the parsed number to the specified number of decimal places
* This function changes the parsedNumber in-place
* @param {?} parsedNumber
* @param {?} minFrac
* @param {?} maxFrac
* @return {?}
*/
function roundNumber(parsedNumber, minFrac, maxFrac) {
if (minFrac > maxFrac) {
throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`);
}
/** @type {?} */
let digits = parsedNumber.digits;
/** @type {?} */
let fractionLen = digits.length - parsedNumber.integerLen;
/** @type {?} */
const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac);
// The index of the digit to where rounding is to occur
/** @type {?} */
let roundAt = fractionSize + parsedNumber.integerLen;
/** @type {?} */
let digit = digits[roundAt];
if (roundAt > 0) {
// Drop fractional digits beyond `roundAt`
digits.splice(Math.max(parsedNumber.integerLen, roundAt));
// Set non-fractional digits beyond `roundAt` to 0
for (let j = roundAt; j < digits.length; j++) {
digits[j] = 0;
}
}
else {
// We rounded to zero so reset the parsedNumber
fractionLen = Math.max(0, fractionLen);
parsedNumber.integerLen = 1;
digits.length = Math.max(1, roundAt = fractionSize + 1);
digits[0] = 0;
for (let i = 1; i < roundAt; i++)
digits[i] = 0;
}
if (digit >= 5) {
if (roundAt - 1 < 0) {
for (let k = 0; k > roundAt; k--) {
digits.unshift(0);
parsedNumber.integerLen++;
}
digits.unshift(1);
parsedNumber.integerLen++;
}
else {
digits[roundAt - 1]++;
}
}
// Pad out with zeros to get the required fraction length
for (; fractionLen < Math.max(0, fractionSize); fractionLen++)
digits.push(0);
/** @type {?} */
let dropTrailingZeros = fractionSize !== 0;
// Minimal length = nb of decimals required + current nb of integers
// Any number besides that is optional and can be removed if it's a trailing 0
/** @type {?} */
const minLen = minFrac + parsedNumber.integerLen;
// Do any carrying, e.g. a digit was rounded up to 10
/** @type {?} */
const carry = digits.reduceRight((/**
* @param {?} carry
* @param {?} d
* @param {?} i
* @param {?} digits
* @return {?}
*/
function (carry, d, i, digits) {
d = d + carry;
digits[i] = d < 10 ? d : d - 10; // d % 10
if (dropTrailingZeros) {
// Do not keep meaningless fractional trailing zeros (e.g. 15.52000 --> 15.52)
if (digits[i] === 0 && i >= minLen) {
digits.pop();
}
else {
dropTrailingZeros = false;
}
}
return d >= 10 ? 1 : 0; // Math.floor(d / 10);
}), 0);
if (carry) {
digits.unshift(carry);
parsedNumber.integerLen++;
}
}
/**
* @param {?} text
* @return {?}
*/
function parseIntAutoRadix(text) {
/** @type {?} */
const result = parseInt(text);
if (isNaN(result)) {
throw new Error('Invalid integer literal when parsing ' + text);
}
return result;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @deprecated from v5
* @type {?}
*/
const DEPRECATED_PLURAL_FN = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('UseV4Plurals');
/**
* \@publicApi
* @abstract
*/
class NgLocalization {
}
if (false) {}
/**
* Returns the plural category for a given value.
* - "=value" when the case exists,
* - the plural category otherwise
* @param {?} value
* @param {?} cases
* @param {?} ngLocalization
* @param {?=} locale
* @return {?}
*/
function getPluralCategory(value, cases, ngLocalization, locale) {
/** @type {?} */
let key = `=${value}`;
if (cases.indexOf(key) > -1) {
return key;
}
key = ngLocalization.getPluralCategory(value, locale);
if (cases.indexOf(key) > -1) {
return key;
}
if (cases.indexOf('other') > -1) {
return 'other';
}
throw new Error(`No plural message found for value "${value}"`);
}
/**
* Returns the plural case based on the locale
*
* \@publicApi
*/
class NgLocaleLocalization extends NgLocalization {
/**
* @param {?} locale
* @param {?=} deprecatedPluralFn
*/
constructor(locale, deprecatedPluralFn) {
super();
this.locale = locale;
this.deprecatedPluralFn = deprecatedPluralFn;
}
/**
* @param {?} value
* @param {?=} locale
* @return {?}
*/
getPluralCategory(value, locale) {
/** @type {?} */
const plural = this.deprecatedPluralFn ? this.deprecatedPluralFn(locale || this.locale, value) :
getLocalePluralCase(locale || this.locale)(value);
switch (plural) {
case Plural.Zero:
return 'zero';
case Plural.One:
return 'one';
case Plural.Two:
return 'two';
case Plural.Few:
return 'few';
case Plural.Many:
return 'many';
default:
return 'other';
}
}
}
NgLocaleLocalization.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
NgLocaleLocalization.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] },
{ type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [DEPRECATED_PLURAL_FN,] }] }
];
if (false) {}
/**
* Returns the plural case based on the locale
*
* @deprecated from v5 the plural case function is in locale data files common/locales/*.ts
* \@publicApi
* @param {?} locale
* @param {?} nLike
* @return {?}
*/
function getPluralCase(locale, nLike) {
// TODO(vicb): lazy compute
if (typeof nLike === 'string') {
nLike = parseInt((/** @type {?} */ (nLike)), 10);
}
/** @type {?} */
const n = (/** @type {?} */ (nLike));
/** @type {?} */
const nDecimal = n.toString().replace(/^[^.]*\.?/, '');
/** @type {?} */
const i = Math.floor(Math.abs(n));
/** @type {?} */
const v = nDecimal.length;
/** @type {?} */
const f = parseInt(nDecimal, 10);
/** @type {?} */
const t = parseInt(n.toString().replace(/^[^.]*\.?|0+$/g, ''), 10) || 0;
/** @type {?} */
const lang = locale.split('-')[0].toLowerCase();
switch (lang) {
case 'af':
case 'asa':
case 'az':
case 'bem':
case 'bez':
case 'bg':
case 'brx':
case 'ce':
case 'cgg':
case 'chr':
case 'ckb':
case 'ee':
case 'el':
case 'eo':
case 'es':
case 'eu':
case 'fo':
case 'fur':
case 'gsw':
case 'ha':
case 'haw':
case 'hu':
case 'jgo':
case 'jmc':
case 'ka':
case 'kk':
case 'kkj':
case 'kl':
case 'ks':
case 'ksb':
case 'ky':
case 'lb':
case 'lg':
case 'mas':
case 'mgo':
case 'ml':
case 'mn':
case 'nb':
case 'nd':
case 'ne':
case 'nn':
case 'nnh':
case 'nyn':
case 'om':
case 'or':
case 'os':
case 'ps':
case 'rm':
case 'rof':
case 'rwk':
case 'saq':
case 'seh':
case 'sn':
case 'so':
case 'sq':
case 'ta':
case 'te':
case 'teo':
case 'tk':
case 'tr':
case 'ug':
case 'uz':
case 'vo':
case 'vun':
case 'wae':
case 'xog':
if (n === 1)
return Plural.One;
return Plural.Other;
case 'ak':
case 'ln':
case 'mg':
case 'pa':
case 'ti':
if (n === Math.floor(n) && n >= 0 && n <= 1)
return Plural.One;
return Plural.Other;
case 'am':
case 'as':
case 'bn':
case 'fa':
case 'gu':
case 'hi':
case 'kn':
case 'mr':
case 'zu':
if (i === 0 || n === 1)
return Plural.One;
return Plural.Other;
case 'ar':
if (n === 0)
return Plural.Zero;
if (n === 1)
return Plural.One;
if (n === 2)
return Plural.Two;
if (n % 100 === Math.floor(n % 100) && n % 100 >= 3 && n % 100 <= 10)
return Plural.Few;
if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 99)
return Plural.Many;
return Plural.Other;
case 'ast':
case 'ca':
case 'de':
case 'en':
case 'et':
case 'fi':
case 'fy':
case 'gl':
case 'it':
case 'nl':
case 'sv':
case 'sw':
case 'ur':
case 'yi':
if (i === 1 && v === 0)
return Plural.One;
return Plural.Other;
case 'be':
if (n % 10 === 1 && !(n % 100 === 11))
return Plural.One;
if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 4 &&
!(n % 100 >= 12 && n % 100 <= 14))
return Plural.Few;
if (n % 10 === 0 || n % 10 === Math.floor(n % 10) && n % 10 >= 5 && n % 10 <= 9 ||
n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 14)
return Plural.Many;
return Plural.Other;
case 'br':
if (n % 10 === 1 && !(n % 100 === 11 || n % 100 === 71 || n % 100 === 91))
return Plural.One;
if (n % 10 === 2 && !(n % 100 === 12 || n % 100 === 72 || n % 100 === 92))
return Plural.Two;
if (n % 10 === Math.floor(n % 10) && (n % 10 >= 3 && n % 10 <= 4 || n % 10 === 9) &&
!(n % 100 >= 10 && n % 100 <= 19 || n % 100 >= 70 && n % 100 <= 79 ||
n % 100 >= 90 && n % 100 <= 99))
return Plural.Few;
if (!(n === 0) && n % 1e6 === 0)
return Plural.Many;
return Plural.Other;
case 'bs':
case 'hr':
case 'sr':
if (v === 0 && i % 10 === 1 && !(i % 100 === 11) || f % 10 === 1 && !(f % 100 === 11))
return Plural.One;
if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
!(i % 100 >= 12 && i % 100 <= 14) ||
f % 10 === Math.floor(f % 10) && f % 10 >= 2 && f % 10 <= 4 &&
!(f % 100 >= 12 && f % 100 <= 14))
return Plural.Few;
return Plural.Other;
case 'cs':
case 'sk':
if (i === 1 && v === 0)
return Plural.One;
if (i === Math.floor(i) && i >= 2 && i <= 4 && v === 0)
return Plural.Few;
if (!(v === 0))
return Plural.Many;
return Plural.Other;
case 'cy':
if (n === 0)
return Plural.Zero;
if (n === 1)
return Plural.One;
if (n === 2)
return Plural.Two;
if (n === 3)
return Plural.Few;
if (n === 6)
return Plural.Many;
return Plural.Other;
case 'da':
if (n === 1 || !(t === 0) && (i === 0 || i === 1))
return Plural.One;
return Plural.Other;
case 'dsb':
case 'hsb':
if (v === 0 && i % 100 === 1 || f % 100 === 1)
return Plural.One;
if (v === 0 && i % 100 === 2 || f % 100 === 2)
return Plural.Two;
if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 ||
f % 100 === Math.floor(f % 100) && f % 100 >= 3 && f % 100 <= 4)
return Plural.Few;
return Plural.Other;
case 'ff':
case 'fr':
case 'hy':
case 'kab':
if (i === 0 || i === 1)
return Plural.One;
return Plural.Other;
case 'fil':
if (v === 0 && (i === 1 || i === 2 || i === 3) ||
v === 0 && !(i % 10 === 4 || i % 10 === 6 || i % 10 === 9) ||
!(v === 0) && !(f % 10 === 4 || f % 10 === 6 || f % 10 === 9))
return Plural.One;
return Plural.Other;
case 'ga':
if (n === 1)
return Plural.One;
if (n === 2)
return Plural.Two;
if (n === Math.floor(n) && n >= 3 && n <= 6)
return Plural.Few;
if (n === Math.floor(n) && n >= 7 && n <= 10)
return Plural.Many;
return Plural.Other;
case 'gd':
if (n === 1 || n === 11)
return Plural.One;
if (n === 2 || n === 12)
return Plural.Two;
if (n === Math.floor(n) && (n >= 3 && n <= 10 || n >= 13 && n <= 19))
return Plural.Few;
return Plural.Other;
case 'gv':
if (v === 0 && i % 10 === 1)
return Plural.One;
if (v === 0 && i % 10 === 2)
return Plural.Two;
if (v === 0 &&
(i % 100 === 0 || i % 100 === 20 || i % 100 === 40 || i % 100 === 60 || i % 100 === 80))
return Plural.Few;
if (!(v === 0))
return Plural.Many;
return Plural.Other;
case 'he':
if (i === 1 && v === 0)
return Plural.One;
if (i === 2 && v === 0)
return Plural.Two;
if (v === 0 && !(n >= 0 && n <= 10) && n % 10 === 0)
return Plural.Many;
return Plural.Other;
case 'is':
if (t === 0 && i % 10 === 1 && !(i % 100 === 11) || !(t === 0))
return Plural.One;
return Plural.Other;
case 'ksh':
if (n === 0)
return Plural.Zero;
if (n === 1)
return Plural.One;
return Plural.Other;
case 'kw':
case 'naq':
case 'se':
case 'smn':
if (n === 1)
return Plural.One;
if (n === 2)
return Plural.Two;
return Plural.Other;
case 'lag':
if (n === 0)
return Plural.Zero;
if ((i === 0 || i === 1) && !(n === 0))
return Plural.One;
return Plural.Other;
case 'lt':
if (n % 10 === 1 && !(n % 100 >= 11 && n % 100 <= 19))
return Plural.One;
if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 9 &&
!(n % 100 >= 11 && n % 100 <= 19))
return Plural.Few;
if (!(f === 0))
return Plural.Many;
return Plural.Other;
case 'lv':
case 'prg':
if (n % 10 === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19 ||
v === 2 && f % 100 === Math.floor(f % 100) && f % 100 >= 11 && f % 100 <= 19)
return Plural.Zero;
if (n % 10 === 1 && !(n % 100 === 11) || v === 2 && f % 10 === 1 && !(f % 100 === 11) ||
!(v === 2) && f % 10 === 1)
return Plural.One;
return Plural.Other;
case 'mk':
if (v === 0 && i % 10 === 1 || f % 10 === 1)
return Plural.One;
return Plural.Other;
case 'mt':
if (n === 1)
return Plural.One;
if (n === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 2 && n % 100 <= 10)
return Plural.Few;
if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19)
return Plural.Many;
return Plural.Other;
case 'pl':
if (i === 1 && v === 0)
return Plural.One;
if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
!(i % 100 >= 12 && i % 100 <= 14))
return Plural.Few;
if (v === 0 && !(i === 1) && i % 10 === Math.floor(i % 10) && i % 10 >= 0 && i % 10 <= 1 ||
v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 ||
v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 12 && i % 100 <= 14)
return Plural.Many;
return Plural.Other;
case 'pt':
if (n === Math.floor(n) && n >= 0 && n <= 2 && !(n === 2))
return Plural.One;
return Plural.Other;
case 'ro':
if (i === 1 && v === 0)
return Plural.One;
if (!(v === 0) || n === 0 ||
!(n === 1) && n % 100 === Math.floor(n % 100) && n % 100 >= 1 && n % 100 <= 19)
return Plural.Few;
return Plural.Other;
case 'ru':
case 'uk':
if (v === 0 && i % 10 === 1 && !(i % 100 === 11))
return Plural.One;
if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 &&
!(i % 100 >= 12 && i % 100 <= 14))
return Plural.Few;
if (v === 0 && i % 10 === 0 ||
v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 ||
v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 11 && i % 100 <= 14)
return Plural.Many;
return Plural.Other;
case 'shi':
if (i === 0 || n === 1)
return Plural.One;
if (n === Math.floor(n) && n >= 2 && n <= 10)
return Plural.Few;
return Plural.Other;
case 'si':
if (n === 0 || n === 1 || i === 0 && f === 1)
return Plural.One;
return Plural.Other;
case 'sl':
if (v === 0 && i % 100 === 1)
return Plural.One;
if (v === 0 && i % 100 === 2)
return Plural.Two;
if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 || !(v === 0))
return Plural.Few;
return Plural.Other;
case 'tzm':
if (n === Math.floor(n) && n >= 0 && n <= 1 || n === Math.floor(n) && n >= 11 && n <= 99)
return Plural.One;
return Plural.Other;
// When there is no specification, the default is always "other"
// Spec: http://cldr.unicode.org/index/cldr-spec/plural-rules
// > other (required—general plural form — also used if the language only has a single form)
default:
return Plural.Other;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Register global data to be used internally by Angular. See the
* ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data.
*
* \@publicApi
* @param {?} data
* @param {?=} localeId
* @param {?=} extraData
* @return {?}
*/
// The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1
function registerLocaleData(data, localeId, extraData) {
if (typeof localeId !== 'string') {
extraData = localeId;
localeId = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId];
}
localeId = localeId.toLowerCase().replace(/_/g, '-');
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLOCALE_DATA"][localeId] = data;
if (extraData) {
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLOCALE_DATA"][localeId][_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData] = extraData;
}
}
/** @enum {number} */
const ExtraLocaleDataIndex = {
ExtraDayPeriodFormats: 0,
ExtraDayPeriodStandalone: 1,
ExtraDayPeriodsRules: 2,
};
/** @enum {number} */
const CurrencyIndex = {
Symbol: 0, SymbolNarrow: 1, NbOfDigits: 2,
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @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
*/
/**
* @param {?} cookieStr
* @param {?} name
* @return {?}
*/
function parseCookieValue(cookieStr, name) {
name = encodeURIComponent(name);
for (const cookie of cookieStr.split(';')) {
/** @type {?} */
const eqIndex = cookie.indexOf('=');
const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];
if (cookieName.trim() === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @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
*/
/**
* Used to diff and convert ngStyle/ngClass instructions into [style] and [class] bindings.
*
* ngStyle and ngClass both accept various forms of input and behave differently than that
* of how [style] and [class] behave in Angular.
*
* The differences are:
* - ngStyle and ngClass both **watch** their binding values for changes each time CD runs
* while [style] and [class] bindings do not (they check for identity changes)
* - ngStyle allows for unit-based keys (e.g. `{'max-width.px':value}`) and [style] does not
* - ngClass supports arrays of class values and [class] only accepts map and string values
* - ngClass allows for multiple className keys (space-separated) within an array or map
* (as the * key) while [class] only accepts a simple key/value map object
*
* Having Angular understand and adapt to all the different forms of behavior is complicated
* and unnecessary. Instead, ngClass and ngStyle should have their input values be converted
* into something that the core-level [style] and [class] bindings understand.
*
* This [StylingDiffer] class handles this conversion by creating a new input value each time
* the inner representation of the binding value have changed.
*
* ## Why do we care about ngStyle/ngClass?
* The styling algorithm code (documented inside of `render3/interfaces/styling.ts`) needs to
* respect and understand the styling values emitted through ngStyle and ngClass (when they
* are present and used in a template).
*
* Instead of having these directives manage styling on their own, they should be included
* into the Angular styling algorithm that exists for [style] and [class] bindings.
*
* Here's why:
*
* - If ngStyle/ngClass is used in combination with [style]/[class] bindings then the
* styles and classes would fall out of sync and be applied and updated at
* inconsistent times
* - Both ngClass/ngStyle do not respect [class.name] and [style.prop] bindings
* (they will write over them given the right combination of events)
*
* ```
*
*
...
*
*
*
...
* ```
* - ngClass/ngStyle were written as a directives and made use of maps, closures and other
* expensive data structures which were evaluated each time CD runs
* @template T
*/
class StylingDiffer {
/**
* @param {?} _name
* @param {?} _options
*/
constructor(_name, _options) {
this._name = _name;
this._options = _options;
this.value = null;
this._lastSetValue = null;
this._lastSetValueType = 0 /* Null */;
this._lastSetValueIdentityChange = false;
}
/**
* Sets (updates) the styling value within the differ.
*
* Only when `hasValueChanged` is called then this new value will be evaluted
* and checked against the previous value.
*
* @param {?} value the new styling value provided from the ngClass/ngStyle binding
* @return {?}
*/
setValue(value) {
if (Array.isArray(value)) {
this._lastSetValueType = 4 /* Array */;
}
else if (value instanceof Set) {
this._lastSetValueType = 8 /* Set */;
}
else if (value && typeof value === 'string') {
if (!(this._options & 4 /* AllowStringValue */)) {
throw new Error(this._name + ' string values are not allowed');
}
this._lastSetValueType = 1 /* String */;
}
else {
this._lastSetValueType = value ? 2 /* Map */ : 0 /* Null */;
}
this._lastSetValueIdentityChange = true;
this._lastSetValue = value || null;
}
/**
* Determines whether or not the value has changed.
*
* This function can be called right after `setValue()` is called, but it can also be
* called incase the existing value (if it's a collection) changes internally. If the
* value is indeed a collection it will do the necessary diffing work and produce a
* new object value as assign that to `value`.
*
* @return {?} whether or not the value has changed in some way.
*/
hasValueChanged() {
/** @type {?} */
let valueHasChanged = this._lastSetValueIdentityChange;
if (!valueHasChanged && !(this._lastSetValueType & 14 /* Collection */))
return false;
/** @type {?} */
let finalValue = null;
/** @type {?} */
const trimValues = (this._options & 1 /* TrimProperties */) ? true : false;
/** @type {?} */
const parseOutUnits = (this._options & 8 /* AllowUnits */) ? true : false;
/** @type {?} */
const allowSubKeys = (this._options & 2 /* AllowSubKeys */) ? true : false;
switch (this._lastSetValueType) {
// case 1: [input]="string"
case 1 /* String */:
/** @type {?} */
const tokens = ((/** @type {?} */ (this._lastSetValue))).split(/\s+/g);
if (this._options & 16 /* ForceAsMap */) {
finalValue = {};
tokens.forEach((/**
* @param {?} token
* @param {?} i
* @return {?}
*/
(token, i) => ((/** @type {?} */ (finalValue)))[token] = true));
}
else {
finalValue = tokens.reduce((/**
* @param {?} str
* @param {?} token
* @param {?} i
* @return {?}
*/
(str, token, i) => str + (i ? ' ' : '') + token));
}
break;
// case 2: [input]="{key:value}"
case 2 /* Map */:
/** @type {?} */
const map = (/** @type {?} */ (this._lastSetValue));
/** @type {?} */
const keys = Object.keys(map);
if (!valueHasChanged) {
if (this.value) {
// we know that the classExp value exists and that it is
// a map (otherwise an identity change would have occurred)
valueHasChanged = mapHasChanged(keys, (/** @type {?} */ (this.value)), map);
}
else {
valueHasChanged = true;
}
}
if (valueHasChanged) {
finalValue =
bulidMapFromValues(this._name, trimValues, parseOutUnits, allowSubKeys, map, keys);
}
break;
// case 3a: [input]="[str1, str2, ...]"
// case 3b: [input]="Set"
case 4 /* Array */:
case 8 /* Set */:
/** @type {?} */
const values = Array.from((/** @type {?} */ (this._lastSetValue)));
if (!valueHasChanged) {
/** @type {?} */
const keys = Object.keys((/** @type {?} */ (this.value)));
valueHasChanged = !arrayEqualsArray(keys, values);
}
if (valueHasChanged) {
finalValue =
bulidMapFromValues(this._name, trimValues, parseOutUnits, allowSubKeys, values);
}
break;
// case 4: [input]="null|undefined"
default:
finalValue = null;
break;
}
if (valueHasChanged) {
((/** @type {?} */ (this))).value = (/** @type {?} */ (finalValue));
}
return valueHasChanged;
}
}
if (false) {}
/** @enum {number} */
const StylingDifferOptions = {
None: 0,
TrimProperties: 1,
AllowSubKeys: 2,
AllowStringValue: 4,
AllowUnits: 8,
ForceAsMap: 16,
};
/** @enum {number} */
const StylingDifferValueTypes = {
Null: 0,
String: 1,
Map: 2,
Array: 4,
Set: 8,
Collection: 14,
};
/**
* builds and returns a map based on the values input value
*
* If the `keys` param is provided then the `values` param is treated as a
* string map. Otherwise `values` is treated as a string array.
* @param {?} errorPrefix
* @param {?} trim
* @param {?} parseOutUnits
* @param {?} allowSubKeys
* @param {?} values
* @param {?=} keys
* @return {?}
*/
function bulidMapFromValues(errorPrefix, trim, parseOutUnits, allowSubKeys, values, keys) {
/** @type {?} */
const map = {};
if (keys) {
// case 1: map
for (let i = 0; i < keys.length; i++) {
/** @type {?} */
let key = keys[i];
key = trim ? key.trim() : key;
/** @type {?} */
const value = ((/** @type {?} */ (values)))[key];
setMapValues(map, key, value, parseOutUnits, allowSubKeys);
}
}
else {
// case 2: array
for (let i = 0; i < values.length; i++) {
/** @type {?} */
let value = ((/** @type {?} */ (values)))[i];
assertValidValue(errorPrefix, value);
value = trim ? value.trim() : value;
setMapValues(map, value, true, false, allowSubKeys);
}
}
return map;
}
/**
* @param {?} errorPrefix
* @param {?} value
* @return {?}
*/
function assertValidValue(errorPrefix, value) {
if (typeof value !== 'string') {
throw new Error(`${errorPrefix} can only toggle CSS classes expressed as strings, got ${value}`);
}
}
/**
* @param {?} map
* @param {?} key
* @param {?} value
* @param {?} parseOutUnits
* @param {?} allowSubKeys
* @return {?}
*/
function setMapValues(map, key, value, parseOutUnits, allowSubKeys) {
if (allowSubKeys && key.indexOf(' ') > 0) {
/** @type {?} */
const innerKeys = key.split(/\s+/g);
for (let j = 0; j < innerKeys.length; j++) {
setIndividualMapValue(map, innerKeys[j], value, parseOutUnits);
}
}
else {
setIndividualMapValue(map, key, value, parseOutUnits);
}
}
/**
* @param {?} map
* @param {?} key
* @param {?} value
* @param {?} parseOutUnits
* @return {?}
*/
function setIndividualMapValue(map, key, value, parseOutUnits) {
if (parseOutUnits) {
/** @type {?} */
const values = normalizeStyleKeyAndValue(key, value);
value = values.value;
key = values.key;
}
map[key] = value;
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
function normalizeStyleKeyAndValue(key, value) {
/** @type {?} */
const index = key.indexOf('.');
if (index > 0) {
/** @type {?} */
const unit = key.substr(index + 1);
key = key.substring(0, index);
if (value != null) { // we should not convert null values to string
value += unit;
}
}
return { key, value };
}
/**
* @param {?} keys
* @param {?} a
* @param {?} b
* @return {?}
*/
function mapHasChanged(keys, a, b) {
/** @type {?} */
const oldKeys = Object.keys(a);
/** @type {?} */
const newKeys = keys;
// the keys are different which means the map changed
if (!arrayEqualsArray(oldKeys, newKeys)) {
return true;
}
for (let i = 0; i < newKeys.length; i++) {
/** @type {?} */
const key = newKeys[i];
if (a[key] !== b[key]) {
return true;
}
}
return false;
}
/**
* @param {?} a
* @param {?} b
* @return {?}
*/
function arrayEqualsArray(a, b) {
if (a && b) {
if (a.length !== b.length)
return false;
for (let i = 0; i < a.length; i++) {
if (b.indexOf(a[i]) === -1)
return false;
}
return true;
}
return false;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Used as a token for an injected service within the NgClass directive.
*
* NgClass behaves differenly whether or not VE is being used or not. If
* present then the legacy ngClass diffing algorithm will be used as an
* injected service. Otherwise the new diffing algorithm (which delegates
* to the `[class]` binding) will be used. This toggle behavior is done so
* via the ivy_switch mechanism.
* @abstract
*/
class NgClassImpl {
}
if (false) {}
class NgClassR2Impl {
/**
* @param {?} _iterableDiffers
* @param {?} _keyValueDiffers
* @param {?} _ngEl
* @param {?} _renderer
*/
constructor(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) {
this._iterableDiffers = _iterableDiffers;
this._keyValueDiffers = _keyValueDiffers;
this._ngEl = _ngEl;
this._renderer = _renderer;
this._initialClasses = [];
}
/**
* @return {?}
*/
getValue() { return null; }
/**
* @param {?} value
* @return {?}
*/
setClass(value) {
this._removeClasses(this._initialClasses);
this._initialClasses = typeof value === 'string' ? value.split(/\s+/) : [];
this._applyClasses(this._initialClasses);
this._applyClasses(this._rawClass);
}
/**
* @param {?} value
* @return {?}
*/
setNgClass(value) {
this._removeClasses(this._rawClass);
this._applyClasses(this._initialClasses);
this._iterableDiffer = null;
this._keyValueDiffer = null;
this._rawClass = typeof value === 'string' ? value.split(/\s+/) : value;
if (this._rawClass) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisListLikeIterable"])(this._rawClass)) {
this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create();
}
else {
this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create();
}
}
}
/**
* @return {?}
*/
applyChanges() {
if (this._iterableDiffer) {
/** @type {?} */
const iterableChanges = this._iterableDiffer.diff((/** @type {?} */ (this._rawClass)));
if (iterableChanges) {
this._applyIterableChanges(iterableChanges);
}
}
else if (this._keyValueDiffer) {
/** @type {?} */
const keyValueChanges = this._keyValueDiffer.diff((/** @type {?} */ (this._rawClass)));
if (keyValueChanges) {
this._applyKeyValueChanges(keyValueChanges);
}
}
}
/**
* @private
* @param {?} changes
* @return {?}
*/
_applyKeyValueChanges(changes) {
changes.forEachAddedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._toggleClass(record.key, record.currentValue)));
changes.forEachChangedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._toggleClass(record.key, record.currentValue)));
changes.forEachRemovedItem((/**
* @param {?} record
* @return {?}
*/
(record) => {
if (record.previousValue) {
this._toggleClass(record.key, false);
}
}));
}
/**
* @private
* @param {?} changes
* @return {?}
*/
_applyIterableChanges(changes) {
changes.forEachAddedItem((/**
* @param {?} record
* @return {?}
*/
(record) => {
if (typeof record.item === 'string') {
this._toggleClass(record.item, true);
}
else {
throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(record.item)}`);
}
}));
changes.forEachRemovedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._toggleClass(record.item, false)));
}
/**
* Applies a collection of CSS classes to the DOM element.
*
* For argument of type Set and Array CSS class names contained in those collections are always
* added.
* For argument of type Map CSS class name in the map's key is toggled based on the value (added
* for truthy and removed for falsy).
* @private
* @param {?} rawClassVal
* @return {?}
*/
_applyClasses(rawClassVal) {
if (rawClassVal) {
if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
((/** @type {?} */ (rawClassVal))).forEach((/**
* @param {?} klass
* @return {?}
*/
(klass) => this._toggleClass(klass, true)));
}
else {
Object.keys(rawClassVal).forEach((/**
* @param {?} klass
* @return {?}
*/
klass => this._toggleClass(klass, !!rawClassVal[klass])));
}
}
}
/**
* Removes a collection of CSS classes from the DOM element. This is mostly useful for cleanup
* purposes.
* @private
* @param {?} rawClassVal
* @return {?}
*/
_removeClasses(rawClassVal) {
if (rawClassVal) {
if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
((/** @type {?} */ (rawClassVal))).forEach((/**
* @param {?} klass
* @return {?}
*/
(klass) => this._toggleClass(klass, false)));
}
else {
Object.keys(rawClassVal).forEach((/**
* @param {?} klass
* @return {?}
*/
klass => this._toggleClass(klass, false)));
}
}
}
/**
* @private
* @param {?} klass
* @param {?} enabled
* @return {?}
*/
_toggleClass(klass, enabled) {
klass = klass.trim();
if (klass) {
klass.split(/\s+/g).forEach((/**
* @param {?} klass
* @return {?}
*/
klass => {
if (enabled) {
this._renderer.addClass(this._ngEl.nativeElement, klass);
}
else {
this._renderer.removeClass(this._ngEl.nativeElement, klass);
}
}));
}
}
}
NgClassR2Impl.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
NgClassR2Impl.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }
];
if (false) {}
class NgClassR3Impl {
constructor() {
this._value = null;
this._ngClassDiffer = new StylingDiffer('NgClass', 1 /* TrimProperties */ |
2 /* AllowSubKeys */ |
4 /* AllowStringValue */ | 16 /* ForceAsMap */);
this._classStringDiffer = null;
}
/**
* @return {?}
*/
getValue() { return this._value; }
/**
* @param {?} value
* @return {?}
*/
setClass(value) {
// early exit incase the binding gets emitted as an empty value which
// means there is no reason to instantiate and diff the values...
if (!value && !this._classStringDiffer)
return;
this._classStringDiffer = this._classStringDiffer ||
new StylingDiffer('class', 4 /* AllowStringValue */ | 16 /* ForceAsMap */);
this._classStringDiffer.setValue(value);
}
/**
* @param {?} value
* @return {?}
*/
setNgClass(value) {
this._ngClassDiffer.setValue(value);
}
/**
* @return {?}
*/
applyChanges() {
/** @type {?} */
const classChanged = this._classStringDiffer ? this._classStringDiffer.hasValueChanged() : false;
/** @type {?} */
const ngClassChanged = this._ngClassDiffer.hasValueChanged();
if (classChanged || ngClassChanged) {
/** @type {?} */
let value = this._ngClassDiffer.value;
if (this._classStringDiffer) {
/** @type {?} */
let classValue = this._classStringDiffer.value;
if (classValue) {
value = value ? Object.assign({}, classValue, value) : classValue;
}
}
this._value = value;
}
}
}
NgClassR3Impl.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
if (false) {}
// the implementation for both NgStyleR2Impl and NgStyleR3Impl are
// not ivy_switch'd away, instead they are only hooked up into the
// DI via NgStyle's directive's provider property.
/** @type {?} */
const NgClassImplProvider__PRE_R3__ = {
provide: NgClassImpl,
useClass: NgClassR2Impl
};
/** @type {?} */
const NgClassImplProvider__POST_R3__ = {
provide: NgClassImpl,
useClass: NgClassR3Impl
};
/** @type {?} */
const NgClassImplProvider = NgClassImplProvider__PRE_R3__;
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/*
* NgClass (as well as NgStyle) behaves differently when loaded in the VE and when not.
*
* If the VE is present (which is for older versions of Angular) then NgClass will inject
* the legacy diffing algorithm as a service and delegate all styling changes to that.
*
* If the VE is not present then NgStyle will normalize (through the injected service) and
* then write all styling changes to the `[style]` binding directly (through a host binding).
* Then Angular will notice the host binding change and treat the changes as styling
* changes and apply them via the core styling instructions that exist within Angular.
*/
// used when the VE is present
/** @type {?} */
const ngClassDirectiveDef__PRE_R3__ = undefined;
// used when the VE is not present (note the directive will
// never be instantiated normally because it is apart of a
// base class)
const ɵ0 = /**
* @return {?}
*/
function () { }, ɵ1 = /**
* @return {?}
*/
() => { }, ɵ2 = /**
* @param {?} rf
* @param {?} ctx
* @param {?} elIndex
* @return {?}
*/
function (rf, ctx, elIndex) {
if (rf & 1 /* Create */) {
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵallocHostVars"])(1);
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyling"])();
}
if (rf & 2 /* Update */) {
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassMap"])(ctx.getValue());
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstylingApply"])();
}
};
/** @type {?} */
const ngClassDirectiveDef__POST_R3__ = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"])({
type: (/** @type {?} */ ((ɵ0))),
selectors: (/** @type {?} */ (null)),
factory: (ɵ1),
hostBindings: (ɵ2)
});
/** @type {?} */
const ngClassDirectiveDef = ngClassDirectiveDef__PRE_R3__;
/**
* Serves as the base non-VE container for NgClass.
*
* While this is a base class that NgClass extends from, the
* class itself acts as a container for non-VE code to setup
* a link to the `[class]` host binding (via the static
* `ngDirectiveDef` property on the class).
*
* Note that the `ngDirectiveDef` property's code is switched
* depending if VE is present or not (this allows for the
* binding code to be set only for newer versions of Angular).
*
* \@publicApi
*/
class NgClassBase {
/**
* @param {?} _delegate
*/
constructor(_delegate) {
this._delegate = _delegate;
}
/**
* @return {?}
*/
getValue() { return this._delegate.getValue(); }
}
/** @nocollapse */ NgClassBase.ngDirectiveDef = ngClassDirectiveDef;
if (false) {}
/**
* \@ngModule CommonModule
*
* \@usageNotes
* ```
* ...
*
* ...
*
* ...
*
* ...
*
* ...
* ```
*
* \@description
*
* Adds and removes CSS classes on an HTML element.
*
* The CSS classes are updated as follows, depending on the type of the expression evaluation:
* - `string` - the CSS classes listed in the string (space delimited) are added,
* - `Array` - the CSS classes declared as Array elements are added,
* - `Object` - keys are CSS classes that get added when the expression given in the value
* evaluates to a truthy value, otherwise they are removed.
*
* \@publicApi
*/
class NgClass extends NgClassBase {
/**
* @param {?} delegate
*/
constructor(delegate) { super(delegate); }
/**
* @param {?} value
* @return {?}
*/
set klass(value) { this._delegate.setClass(value); }
/**
* @param {?} value
* @return {?}
*/
set ngClass(value) {
this._delegate.setNgClass(value);
}
/**
* @return {?}
*/
ngDoCheck() { this._delegate.applyChanges(); }
}
NgClass.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngClass]', providers: [NgClassImplProvider] },] }
];
/** @nocollapse */
NgClass.ctorParameters = () => [
{ type: NgClassImpl }
];
NgClass.propDecorators = {
klass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['class',] }],
ngClass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngClass',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Instantiates a single {\@link Component} type and inserts its Host View into current View.
* `NgComponentOutlet` provides a declarative approach for dynamic component creation.
*
* `NgComponentOutlet` requires a component type, if a falsy value is set the view will clear and
* any existing component will get destroyed.
*
* \@usageNotes
*
* ### Fine tune control
*
* You can control the component creation process by using the following optional attributes:
*
* * `ngComponentOutletInjector`: Optional custom {\@link Injector} that will be used as parent for
* the Component. Defaults to the injector of the current view container.
*
* * `ngComponentOutletContent`: Optional list of projectable nodes to insert into the content
* section of the component, if exists.
*
* * `ngComponentOutletNgModuleFactory`: Optional module factory to allow dynamically loading other
* module, then load a component from that module.
*
* ### Syntax
*
* Simple
* ```
*
* ```
*
* Customized injector/content
* ```
*
*
* ```
*
* Customized ngModuleFactory
* ```
*
*
* ```
*
* ### A simple example
*
* {\@example common/ngComponentOutlet/ts/module.ts region='SimpleExample'}
*
* A more complete example with additional options:
*
* {\@example common/ngComponentOutlet/ts/module.ts region='CompleteExample'}
*
* \@publicApi
* \@ngModule CommonModule
*/
class NgComponentOutlet {
/**
* @param {?} _viewContainerRef
*/
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
this._componentRef = null;
this._moduleRef = null;
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
this._viewContainerRef.clear();
this._componentRef = null;
if (this.ngComponentOutlet) {
/** @type {?} */
const elInjector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
if (changes['ngComponentOutletNgModuleFactory']) {
if (this._moduleRef)
this._moduleRef.destroy();
if (this.ngComponentOutletNgModuleFactory) {
/** @type {?} */
const parentModule = elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModuleRef"]);
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(parentModule.injector);
}
else {
this._moduleRef = null;
}
}
/** @type {?} */
const componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver :
elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ComponentFactoryResolver"]);
/** @type {?} */
const componentFactory = componentFactoryResolver.resolveComponentFactory(this.ngComponentOutlet);
this._componentRef = this._viewContainerRef.createComponent(componentFactory, this._viewContainerRef.length, elInjector, this.ngComponentOutletContent);
}
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this._moduleRef)
this._moduleRef.destroy();
}
}
NgComponentOutlet.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngComponentOutlet]' },] }
];
/** @nocollapse */
NgComponentOutlet.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }
];
NgComponentOutlet.propDecorators = {
ngComponentOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletInjector: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletContent: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletNgModuleFactory: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@publicApi
* @template T
*/
class NgForOfContext {
/**
* @param {?} $implicit
* @param {?} ngForOf
* @param {?} index
* @param {?} count
*/
constructor($implicit, ngForOf, index, count) {
this.$implicit = $implicit;
this.ngForOf = ngForOf;
this.index = index;
this.count = count;
}
/**
* @return {?}
*/
get first() { return this.index === 0; }
/**
* @return {?}
*/
get last() { return this.index === this.count - 1; }
/**
* @return {?}
*/
get even() { return this.index % 2 === 0; }
/**
* @return {?}
*/
get odd() { return !this.even; }
}
if (false) {}
/**
* A [structural directive](guide/structural-directives) that renders
* a template for each item in a collection.
* The directive is placed on an element, which becomes the parent
* of the cloned templates.
*
* The `ngForOf` directive is generally used in the
* [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`.
* In this form, the template to be rendered for each iteration is the content
* of an anchor element containing the directive.
*
* The following example shows the shorthand syntax with some options,
* contained in an `
` element.
*
* ```
*
...
* ```
*
* The shorthand form expands into a long form that uses the `ngForOf` selector
* on an `` element.
* The content of the `` element is the `
` element that held the
* short-form directive.
*
* Here is the expanded version of the short-form example.
*
* ```
*
*
...
*
* ```
*
* Angular automatically expands the shorthand syntax as it compiles the template.
* The context for each embedded view is logically merged to the current component
* context according to its lexical position.
*
* When using the shorthand syntax, Angular allows only [one structural directive
* on an element](guide/structural-directives#one-structural-directive-per-host-element).
* If you want to iterate conditionally, for example,
* put the `*ngIf` on a container element that wraps the `*ngFor` element.
* For futher discussion, see
* [Structural Directives](guide/structural-directives#one-per-element).
*
* \@usageNotes
*
* ### Local variables
*
* `NgForOf` provides exported values that can be aliased to local variables.
* For example:
*
* ```
*
* {{i}}/{{users.length}}. {{user}} default
*
* ```
*
* The following exported values can be aliased to local variables:
*
* - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
* - `ngForOf: NgIterable`: The value of the iterable expression. Useful when the expression is
* more complex then a property access, for example when using the async pipe (`userStreams |
* async`).
* - `index: number`: The index of the current item in the iterable.
* - `first: boolean`: True when the item is the first item in the iterable.
* - `last: boolean`: True when the item is the last item in the iterable.
* - `even: boolean`: True when the item has an even index in the iterable.
* - `odd: boolean`: True when the item has an odd index in the iterable.
*
* ### Change propagation
*
* When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
*
* * When an item is added, a new instance of the template is added to the DOM.
* * When an item is removed, its template instance is removed from the DOM.
* * When items are reordered, their respective templates are reordered in the DOM.
*
* Angular uses object identity to track insertions and deletions within the iterator and reproduce
* those changes in the DOM. This has important implications for animations and any stateful
* controls that are present, such as `` elements that accept user input. Inserted rows can
* be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
* such as user input.
* For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).
*
* The identities of elements in the iterator can change while the data does not.
* This can happen, for example, if the iterator is produced from an RPC to the server, and that
* RPC is re-run. Even if the data hasn't changed, the second response produces objects with
* different identities, and Angular must tear down the entire DOM and rebuild it (as if all old
* elements were deleted and all new elements inserted).
*
* To avoid this expensive operation, you can customize the default tracking algorithm.
* by supplying the `trackBy` option to `NgForOf`.
* `trackBy` takes a function that has two arguments: `index` and `item`.
* If `trackBy` is given, Angular tracks changes by the return value of the function.
*
* @see [Structural Directives](guide/structural-directives)
* \@ngModule CommonModule
* \@publicApi
* @template T
*/
class NgForOf {
/**
* @param {?} _viewContainer
* @param {?} _template
* @param {?} _differs
*/
constructor(_viewContainer, _template, _differs) {
this._viewContainer = _viewContainer;
this._template = _template;
this._differs = _differs;
this._ngForOfDirty = true;
this._differ = null;
}
/**
* The value of the iterable expression, which can be used as a
* [template input variable](guide/structural-directives#template-input-variable).
* @param {?} ngForOf
* @return {?}
*/
set ngForOf(ngForOf) {
this._ngForOf = ngForOf;
this._ngForOfDirty = true;
}
/**
* A function that defines how to track changes for items in the iterable.
*
* When items are added, moved, or removed in the iterable,
* the directive must re-render the appropriate DOM nodes.
* To minimize churn in the DOM, only nodes that have changed
* are re-rendered.
*
* By default, the change detector assumes that
* the object instance identifies the node in the iterable.
* When this function is supplied, the directive uses
* the result of calling this function to identify the item node,
* rather than the identity of the object itself.
*
* The function receives two inputs,
* the iteration index and the node object ID.
* @param {?} fn
* @return {?}
*/
set ngForTrackBy(fn) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["isDevMode"])() && fn != null && typeof fn !== 'function') {
// TODO(vicb): use a log service once there is a public one available
if ((/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) {
console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
`See https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#change-propagation for more information.`);
}
}
this._trackByFn = fn;
}
/**
* @return {?}
*/
get ngForTrackBy() { return this._trackByFn; }
/**
* A reference to the template that is stamped out for each item in the iterable.
* @see [template reference variable](guide/template-syntax#template-reference-variables--var-)
* @param {?} value
* @return {?}
*/
set ngForTemplate(value) {
// TODO(TS2.1): make TemplateRef>> once we move to TS v2.1
// The current type is too restrictive; a template that just uses index, for example,
// should be acceptable.
if (value) {
this._template = value;
}
}
/**
* Applies the changes when needed.
* @return {?}
*/
ngDoCheck() {
if (this._ngForOfDirty) {
this._ngForOfDirty = false;
// React on ngForOf changes only once all inputs have been initialized
/** @type {?} */
const value = this._ngForOf;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
}
catch (_a) {
throw new Error(`Cannot find a differ supporting object '${value}' of type '${getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
if (this._differ) {
/** @type {?} */
const changes = this._differ.diff(this._ngForOf);
if (changes)
this._applyChanges(changes);
}
}
/**
* @private
* @param {?} changes
* @return {?}
*/
_applyChanges(changes) {
/** @type {?} */
const insertTuples = [];
changes.forEachOperation((/**
* @param {?} item
* @param {?} adjustedPreviousIndex
* @param {?} currentIndex
* @return {?}
*/
(item, adjustedPreviousIndex, currentIndex) => {
if (item.previousIndex == null) {
/** @type {?} */
const view = this._viewContainer.createEmbeddedView(this._template, new NgForOfContext((/** @type {?} */ (null)), this._ngForOf, -1, -1), currentIndex === null ? undefined : currentIndex);
/** @type {?} */
const tuple = new RecordViewTuple(item, view);
insertTuples.push(tuple);
}
else if (currentIndex == null) {
this._viewContainer.remove(adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex);
}
else if (adjustedPreviousIndex !== null) {
/** @type {?} */
const view = (/** @type {?} */ (this._viewContainer.get(adjustedPreviousIndex)));
this._viewContainer.move(view, currentIndex);
/** @type {?} */
const tuple = new RecordViewTuple(item, (/** @type {?} */ (view)));
insertTuples.push(tuple);
}
}));
for (let i = 0; i < insertTuples.length; i++) {
this._perViewChange(insertTuples[i].view, insertTuples[i].record);
}
for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
/** @type {?} */
const viewRef = (/** @type {?} */ (this._viewContainer.get(i)));
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.ngForOf = this._ngForOf;
}
changes.forEachIdentityChange((/**
* @param {?} record
* @return {?}
*/
(record) => {
/** @type {?} */
const viewRef = (/** @type {?} */ (this._viewContainer.get(record.currentIndex)));
viewRef.context.$implicit = record.item;
}));
}
/**
* @private
* @param {?} view
* @param {?} record
* @return {?}
*/
_perViewChange(view, record) {
view.context.$implicit = record.item;
}
/**
* Asserts the correct type of the context for the template that `NgForOf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgForOf` structural directive renders its template with a specific context type.
* @template T
* @param {?} dir
* @param {?} ctx
* @return {?}
*/
static ngTemplateContextGuard(dir, ctx) {
return true;
}
}
NgForOf.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngFor][ngForOf]' },] }
];
/** @nocollapse */
NgForOf.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }
];
NgForOf.propDecorators = {
ngForOf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngForTrackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngForTemplate: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* @template T
*/
class RecordViewTuple {
/**
* @param {?} record
* @param {?} view
*/
constructor(record, view) {
this.record = record;
this.view = view;
}
}
if (false) {}
/**
* @param {?} type
* @return {?}
*/
function getTypeName(type) {
return type['name'] || typeof type;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A structural directive that conditionally includes a template based on the value of
* an expression coerced to Boolean.
* When the expression evaluates to true, Angular renders the template
* provided in a `then` clause, and when false or null,
* Angular renders the template provided in an optional `else` clause. The default
* template for the `else` clause is blank.
*
* A [shorthand form](guide/structural-directives#the-asterisk--prefix) of the directive,
* `*ngIf="condition"`, is generally used, provided
* as an attribute of the anchor element for the inserted template.
* Angular expands this into a more explicit version, in which the anchor element
* is contained in an `` element.
*
* Simple form with shorthand syntax:
*
* ```
*
Content to render when condition is true.
* ```
*
* Simple form with expanded syntax:
*
* ```
*
Content to render when condition is
* true.
* ```
*
* Form with an "else" block:
*
* ```
*
Content to render when condition is true.
* Content to render when condition is false.
* ```
*
* Shorthand form with "then" and "else" blocks:
*
* ```
*
* Content to render when condition is true.
* Content to render when condition is false.
* ```
*
* Form with storing the value locally:
*
* ```
*
{{value}}
* Content to render when value is null.
* ```
*
* \@usageNotes
*
* The `*ngIf` directive is most commonly used to conditionally show an inline template,
* as seen in the following example.
* The default `else` template is blank.
*
* {\@example common/ngIf/ts/module.ts region='NgIfSimple'}
*
* ### Showing an alternative template using `else`
*
* To display a template when `expression` evaluates to false, use an `else` template
* binding as shown in the following example.
* The `else` binding points to an `` element labeled `#elseBlock`.
* The template can be defined anywhere in the component view, but is typically placed right after
* `ngIf` for readability.
*
* {\@example common/ngIf/ts/module.ts region='NgIfElse'}
*
* ### Using an external `then` template
*
* In the previous example, the then-clause template is specified inline, as the content of the
* tag that contains the `ngIf` directive. You can also specify a template that is defined
* externally, by referencing a labeled `` element. When you do this, you can
* change which template to use at runtime, as shown in the following example.
*
* {\@example common/ngIf/ts/module.ts region='NgIfThenElse'}
*
* ### Storing a conditional result in a variable
*
* You might want to show a set of properties from the same object. If you are waiting
* for asynchronous data, the object can be undefined.
* In this case, you can use `ngIf` and store the result of the condition in a local
* variable as shown in the the following example.
*
* {\@example common/ngIf/ts/module.ts region='NgIfAs'}
*
* This code uses only one `AsyncPipe`, so only one subscription is created.
* The conditional statement stores the result of `userStream|async` in the local variable `user`.
* You can then bind the local `user` repeatedly.
*
* The conditional displays the data only if `userStream` returns a value,
* so you don't need to use the
* [safe-navigation-operator](guide/template-syntax#safe-navigation-operator) (`?.`)
* to guard against null values when accessing properties.
* You can display an alternative template while waiting for the data.
*
* ### Shorthand syntax
*
* The shorthand syntax `*ngIf` expands into two separate template specifications
* for the "then" and "else" clauses. For example, consider the following shorthand statement,
* that is meant to show a loading page while waiting for data to be loaded.
*
* ```
*
* ...
*
*
*
*
Loading...
*
* ```
*
* You can see that the "else" clause references the ``
* with the `#loading` label, and the template for the "then" clause
* is provided as the content of the anchor element.
*
* However, when Angular expands the shorthand syntax, it creates
* another `` tag, with `ngIf` and `ngIfElse` directives.
* The anchor element containing the template for the "then" clause becomes
* the content of this unlabeled `` tag.
*
* ```
*
*
* ...
*
*
*
*
*
Loading...
*
* ```
*
* The presence of the implicit template object has implications for the nesting of
* structural directives. For more on this subject, see
* [Structural Directives](https://angular.io/guide/structural-directives#one-per-element).
*
* \@ngModule CommonModule
* \@publicApi
*/
class NgIf {
/**
* @param {?} _viewContainer
* @param {?} templateRef
*/
constructor(_viewContainer, templateRef) {
this._viewContainer = _viewContainer;
this._context = new NgIfContext();
this._thenTemplateRef = null;
this._elseTemplateRef = null;
this._thenViewRef = null;
this._elseViewRef = null;
this._thenTemplateRef = templateRef;
}
/**
* The Boolean expression to evaluate as the condition for showing a template.
* @param {?} condition
* @return {?}
*/
set ngIf(condition) {
this._context.$implicit = this._context.ngIf = condition;
this._updateView();
}
/**
* A template to show if the condition expression evaluates to true.
* @param {?} templateRef
* @return {?}
*/
set ngIfThen(templateRef) {
assertTemplate('ngIfThen', templateRef);
this._thenTemplateRef = templateRef;
this._thenViewRef = null; // clear previous view if any.
this._updateView();
}
/**
* A template to show if the condition expression evaluates to false.
* @param {?} templateRef
* @return {?}
*/
set ngIfElse(templateRef) {
assertTemplate('ngIfElse', templateRef);
this._elseTemplateRef = templateRef;
this._elseViewRef = null; // clear previous view if any.
this._updateView();
}
/**
* @private
* @return {?}
*/
_updateView() {
if (this._context.$implicit) {
if (!this._thenViewRef) {
this._viewContainer.clear();
this._elseViewRef = null;
if (this._thenTemplateRef) {
this._thenViewRef =
this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
}
}
}
else {
if (!this._elseViewRef) {
this._viewContainer.clear();
this._thenViewRef = null;
if (this._elseTemplateRef) {
this._elseViewRef =
this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
}
}
}
}
}
NgIf.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngIf]' },] }
];
/** @nocollapse */
NgIf.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }
];
NgIf.propDecorators = {
ngIf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngIfThen: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngIfElse: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* \@publicApi
*/
class NgIfContext {
constructor() {
this.$implicit = null;
this.ngIf = null;
}
}
if (false) {}
/**
* @param {?} property
* @param {?} templateRef
* @return {?}
*/
function assertTemplate(property, templateRef) {
/** @type {?} */
const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView);
if (!isTemplateRefOrNull) {
throw new Error(`${property} must be a TemplateRef, but received '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(templateRef)}'.`);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class SwitchView {
/**
* @param {?} _viewContainerRef
* @param {?} _templateRef
*/
constructor(_viewContainerRef, _templateRef) {
this._viewContainerRef = _viewContainerRef;
this._templateRef = _templateRef;
this._created = false;
}
/**
* @return {?}
*/
create() {
this._created = true;
this._viewContainerRef.createEmbeddedView(this._templateRef);
}
/**
* @return {?}
*/
destroy() {
this._created = false;
this._viewContainerRef.clear();
}
/**
* @param {?} created
* @return {?}
*/
enforceState(created) {
if (created && !this._created) {
this.create();
}
else if (!created && this._created) {
this.destroy();
}
}
}
if (false) {}
/**
* \@ngModule CommonModule
*
* \@description A structural directive that adds or removes templates (displaying or hiding views)
* when the next match expression matches the switch expression.
*
* The `[ngSwitch]` directive on a container specifies an expression to match against.
* The expressions to match are provided by `ngSwitchCase` directives on views within the container.
* - Every view that matches is rendered.
* - If there are no matches, a view with the `ngSwitchDefault` directive is rendered.
* - Elements within the `[NgSwitch]` statement but outside of any `NgSwitchCase`
* or `ngSwitchDefault` directive are preserved at the location.
*
* \@usageNotes
* Define a container element for the directive, and specify the switch expression
* to match against as an attribute:
*
* ```
*
* ```
*
* Within the container, `*ngSwitchCase` statements specify the match expressions
* as attributes. Include `*ngSwitchDefault` as the final case.
*
* ```
*
* ...
* ...
* ...
*
* ```
*
* ### Usage Examples
*
* The following example shows how to use more than one case to display the same view:
*
* ```
*
*
* ...
* ...
* ...
*
* ...
*
* ```
*
* The following example shows how cases can be nested:
* ```
*
* ...
* ...
* ...
*
*
*
*
*
* ...
*
* ```
*
* \@publicApi
* @see `NgSwitchCase`
* @see `NgSwitchDefault`
* @see [Structural Directives](guide/structural-directives)
*
*/
class NgSwitch {
constructor() {
this._defaultUsed = false;
this._caseCount = 0;
this._lastCaseCheckIndex = 0;
this._lastCasesMatched = false;
}
/**
* @param {?} newValue
* @return {?}
*/
set ngSwitch(newValue) {
this._ngSwitch = newValue;
if (this._caseCount === 0) {
this._updateDefaultCases(true);
}
}
/**
* \@internal
* @return {?}
*/
_addCase() { return this._caseCount++; }
/**
* \@internal
* @param {?} view
* @return {?}
*/
_addDefault(view) {
if (!this._defaultViews) {
this._defaultViews = [];
}
this._defaultViews.push(view);
}
/**
* \@internal
* @param {?} value
* @return {?}
*/
_matchCase(value) {
/** @type {?} */
const matched = value == this._ngSwitch;
this._lastCasesMatched = this._lastCasesMatched || matched;
this._lastCaseCheckIndex++;
if (this._lastCaseCheckIndex === this._caseCount) {
this._updateDefaultCases(!this._lastCasesMatched);
this._lastCaseCheckIndex = 0;
this._lastCasesMatched = false;
}
return matched;
}
/**
* @private
* @param {?} useDefault
* @return {?}
*/
_updateDefaultCases(useDefault) {
if (this._defaultViews && useDefault !== this._defaultUsed) {
this._defaultUsed = useDefault;
for (let i = 0; i < this._defaultViews.length; i++) {
/** @type {?} */
const defaultView = this._defaultViews[i];
defaultView.enforceState(useDefault);
}
}
}
}
NgSwitch.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitch]' },] }
];
NgSwitch.propDecorators = {
ngSwitch: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* \@ngModule CommonModule
*
* \@description
* Provides a switch case expression to match against an enclosing `ngSwitch` expression.
* When the expressions match, the given `NgSwitchCase` template is rendered.
* If multiple match expressions match the switch expression value, all of them are displayed.
*
* \@usageNotes
*
* Within a switch container, `*ngSwitchCase` statements specify the match expressions
* as attributes. Include `*ngSwitchDefault` as the final case.
*
* ```
*
* ...
* ...
* ...
*
* ```
*
* Each switch-case statement contains an in-line HTML template or template reference
* that defines the subtree to be selected if the value of the match expression
* matches the value of the switch expression.
*
* Unlike JavaScript, which uses strict equality, Angular uses loose equality.
* This means that the empty string, `""` matches 0.
*
* \@publicApi
* @see `NgSwitch`
* @see `NgSwitchDefault`
*
*/
class NgSwitchCase {
/**
* @param {?} viewContainer
* @param {?} templateRef
* @param {?} ngSwitch
*/
constructor(viewContainer, templateRef, ngSwitch) {
this.ngSwitch = ngSwitch;
ngSwitch._addCase();
this._view = new SwitchView(viewContainer, templateRef);
}
/**
* Performs case matching. For internal use only.
* @return {?}
*/
ngDoCheck() { this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase)); }
}
NgSwitchCase.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitchCase]' },] }
];
/** @nocollapse */
NgSwitchCase.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
NgSwitchCase.propDecorators = {
ngSwitchCase: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* \@ngModule CommonModule
*
* \@description
*
* Creates a view that is rendered when no `NgSwitchCase` expressions
* match the `NgSwitch` expression.
* This statement should be the final case in an `NgSwitch`.
*
* \@publicApi
* @see `NgSwitch`
* @see `NgSwitchCase`
*
*/
class NgSwitchDefault {
/**
* @param {?} viewContainer
* @param {?} templateRef
* @param {?} ngSwitch
*/
constructor(viewContainer, templateRef, ngSwitch) {
ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
}
}
NgSwitchDefault.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitchDefault]' },] }
];
/** @nocollapse */
NgSwitchDefault.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
*
* \@usageNotes
* ```
*
* there is nothing
* there is one
* there are a few
*
* ```
*
* \@description
*
* Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization.
*
* Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees
* that match the switch expression's pluralization category.
*
* To use this directive you must provide a container element that sets the `[ngPlural]` attribute
* to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their
* expression:
* - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value
* matches the switch expression exactly,
* - otherwise, the view will be treated as a "category match", and will only display if exact
* value matches aren't found and the value maps to its category for the defined locale.
*
* See http://cldr.unicode.org/index/cldr-spec/plural-rules
*
* \@publicApi
*/
class NgPlural {
/**
* @param {?} _localization
*/
constructor(_localization) {
this._localization = _localization;
this._caseViews = {};
}
/**
* @param {?} value
* @return {?}
*/
set ngPlural(value) {
this._switchValue = value;
this._updateView();
}
/**
* @param {?} value
* @param {?} switchView
* @return {?}
*/
addCase(value, switchView) { this._caseViews[value] = switchView; }
/**
* @private
* @return {?}
*/
_updateView() {
this._clearViews();
/** @type {?} */
const cases = Object.keys(this._caseViews);
/** @type {?} */
const key = getPluralCategory(this._switchValue, cases, this._localization);
this._activateView(this._caseViews[key]);
}
/**
* @private
* @return {?}
*/
_clearViews() {
if (this._activeView)
this._activeView.destroy();
}
/**
* @private
* @param {?} view
* @return {?}
*/
_activateView(view) {
if (view) {
this._activeView = view;
this._activeView.create();
}
}
}
NgPlural.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngPlural]' },] }
];
/** @nocollapse */
NgPlural.ctorParameters = () => [
{ type: NgLocalization }
];
NgPlural.propDecorators = {
ngPlural: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* \@ngModule CommonModule
*
* \@description
*
* Creates a view that will be added/removed from the parent {\@link NgPlural} when the
* given expression matches the plural expression according to CLDR rules.
*
* \@usageNotes
* ```
*
* ...
* ...
*
* ```
*
* See {\@link NgPlural} for more details and example.
*
* \@publicApi
*/
class NgPluralCase {
/**
* @param {?} value
* @param {?} template
* @param {?} viewContainer
* @param {?} ngPlural
*/
constructor(value, template, viewContainer, ngPlural) {
this.value = value;
/** @type {?} */
const isANumber = !isNaN(Number(value));
ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));
}
}
NgPluralCase.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngPluralCase]' },] }
];
/** @nocollapse */
NgPluralCase.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Attribute"], args: ['ngPluralCase',] }] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: NgPlural, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Used as a token for an injected service within the NgStyle directive.
*
* NgStyle behaves differenly whether or not VE is being used or not. If
* present then the legacy ngClass diffing algorithm will be used as an
* injected service. Otherwise the new diffing algorithm (which delegates
* to the `[style]` binding) will be used. This toggle behavior is done so
* via the ivy_switch mechanism.
* @abstract
*/
class NgStyleImpl {
}
if (false) {}
class NgStyleR2Impl {
/**
* @param {?} _ngEl
* @param {?} _differs
* @param {?} _renderer
*/
constructor(_ngEl, _differs, _renderer) {
this._ngEl = _ngEl;
this._differs = _differs;
this._renderer = _renderer;
}
/**
* @return {?}
*/
getValue() { return null; }
/**
* A map of style properties, specified as colon-separated
* key-value pairs.
* * The key is a style name, with an optional `.` suffix
* (such as 'top.px', 'font-style.em').
* * The value is an expression to be evaluated.
* @param {?} values
* @return {?}
*/
setNgStyle(values) {
this._ngStyle = values;
if (!this._differ && values) {
this._differ = this._differs.find(values).create();
}
}
/**
* Applies the new styles if needed.
* @return {?}
*/
applyChanges() {
if (this._differ) {
/** @type {?} */
const changes = this._differ.diff(this._ngStyle);
if (changes) {
this._applyChanges(changes);
}
}
}
/**
* @private
* @param {?} changes
* @return {?}
*/
_applyChanges(changes) {
changes.forEachRemovedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._setStyle(record.key, null)));
changes.forEachAddedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._setStyle(record.key, record.currentValue)));
changes.forEachChangedItem((/**
* @param {?} record
* @return {?}
*/
(record) => this._setStyle(record.key, record.currentValue)));
}
/**
* @private
* @param {?} nameAndUnit
* @param {?} value
* @return {?}
*/
_setStyle(nameAndUnit, value) {
const [name, unit] = nameAndUnit.split('.');
value = value != null && unit ? `${value}${unit}` : value;
if (value != null) {
this._renderer.setStyle(this._ngEl.nativeElement, name, (/** @type {?} */ (value)));
}
else {
this._renderer.removeStyle(this._ngEl.nativeElement, name);
}
}
}
NgStyleR2Impl.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
/** @nocollapse */
NgStyleR2Impl.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }
];
if (false) {}
class NgStyleR3Impl {
constructor() {
this._differ = new StylingDiffer('NgStyle', 8 /* AllowUnits */);
this._value = null;
}
/**
* @return {?}
*/
getValue() { return this._value; }
/**
* @param {?} value
* @return {?}
*/
setNgStyle(value) { this._differ.setValue(value); }
/**
* @return {?}
*/
applyChanges() {
if (this._differ.hasValueChanged()) {
this._value = this._differ.value;
}
}
}
NgStyleR3Impl.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }
];
if (false) {}
// the implementation for both NgClassR2Impl and NgClassR3Impl are
// not ivy_switch'd away, instead they are only hooked up into the
// DI via NgStyle's directive's provider property.
/** @type {?} */
const NgStyleImplProvider__PRE_R3__ = {
provide: NgStyleImpl,
useClass: NgStyleR2Impl
};
/** @type {?} */
const NgStyleImplProvider__POST_R3__ = {
provide: NgStyleImpl,
useClass: NgStyleR3Impl
};
/** @type {?} */
const NgStyleImplProvider = NgStyleImplProvider__PRE_R3__;
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/*
* NgStyle (as well as NgClass) behaves differently when loaded in the VE and when not.
*
* If the VE is present (which is for older versions of Angular) then NgStyle will inject
* the legacy diffing algorithm as a service and delegate all styling changes to that.
*
* If the VE is not present then NgStyle will normalize (through the injected service) and
* then write all styling changes to the `[style]` binding directly (through a host binding).
* Then Angular will notice the host binding change and treat the changes as styling
* changes and apply them via the core styling instructions that exist within Angular.
*/
// used when the VE is present
/** @type {?} */
const ngStyleDirectiveDef__PRE_R3__ = undefined;
// used when the VE is not present (note the directive will
// never be instantiated normally because it is apart of a
// base class)
const ɵ0$1 = /**
* @return {?}
*/
function () { }, ɵ1$1 = /**
* @return {?}
*/
() => { }, ɵ2$1 = /**
* @param {?} rf
* @param {?} ctx
* @param {?} elIndex
* @return {?}
*/
function (rf, ctx, elIndex) {
if (rf & 1 /* Create */) {
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyling"])();
}
if (rf & 2 /* Update */) {
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyleMap"])(ctx.getValue());
Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstylingApply"])();
}
};
/** @type {?} */
const ngStyleDirectiveDef__POST_R3__ = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"])({
type: (/** @type {?} */ ((ɵ0$1))),
selectors: (/** @type {?} */ (null)),
factory: (ɵ1$1),
hostBindings: (ɵ2$1)
});
/** @type {?} */
const ngStyleDirectiveDef = ngStyleDirectiveDef__PRE_R3__;
/**
* Serves as the base non-VE container for NgStyle.
*
* While this is a base class that NgStyle extends from, the
* class itself acts as a container for non-VE code to setup
* a link to the `[style]` host binding (via the static
* `ngDirectiveDef` property on the class).
*
* Note that the `ngDirectiveDef` property's code is switched
* depending if VE is present or not (this allows for the
* binding code to be set only for newer versions of Angular).
*
* \@publicApi
*/
class NgStyleBase {
/**
* @param {?} _delegate
*/
constructor(_delegate) {
this._delegate = _delegate;
}
/**
* @return {?}
*/
getValue() { return this._delegate.getValue(); }
}
/** @nocollapse */ NgStyleBase.ngDirectiveDef = ngStyleDirectiveDef;
if (false) {}
/**
* \@ngModule CommonModule
*
* \@usageNotes
*
* Set the font of the containing element to the result of an expression.
*
* ```
* ...
* ```
*
* Set the width of the containing element to a pixel value returned by an expression.
*
* ```
* ...
* ```
*
* Set a collection of style values using an expression that returns key-value pairs.
*
* ```
* ...
* ```
*
* \@description
*
* An attribute directive that updates styles for the containing HTML element.
* Sets one or more style properties, specified as colon-separated key-value pairs.
* The key is a style name, with an optional `.` suffix
* (such as 'top.px', 'font-style.em').
* The value is an expression to be evaluated.
* The resulting non-null value, expressed in the given unit,
* is assigned to the given style property.
* If the result of evaluation is null, the corresponding style is removed.
*
* \@publicApi
*/
class NgStyle extends NgStyleBase {
/**
* @param {?} delegate
*/
constructor(delegate) { super(delegate); }
/**
* @param {?} value
* @return {?}
*/
set ngStyle(value) { this._delegate.setNgStyle(value); }
/**
* @return {?}
*/
ngDoCheck() { this._delegate.applyChanges(); }
}
NgStyle.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngStyle]', providers: [NgStyleImplProvider] },] }
];
/** @nocollapse */
NgStyle.ctorParameters = () => [
{ type: NgStyleImpl }
];
NgStyle.propDecorators = {
ngStyle: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngStyle',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
*
* \@description
*
* Inserts an embedded view from a prepared `TemplateRef`.
*
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.
* `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding
* by the local template `let` declarations.
*
* \@usageNotes
* ```
*
* ```
*
* Using the key `$implicit` in the context object will set its value as default.
*
* ### Example
*
* {\@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'}
*
* \@publicApi
*/
class NgTemplateOutlet {
/**
* @param {?} _viewContainerRef
*/
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
this._viewRef = null;
/**
* A context object to attach to the {\@link EmbeddedViewRef}. This should be an
* object, the object's keys will be available for binding by the local template `let`
* declarations.
* Using the key `$implicit` in the context object will set its value as default.
*/
this.ngTemplateOutletContext = null;
/**
* A string defining the template reference and optionally the context object for the template.
*/
this.ngTemplateOutlet = null;
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
/** @type {?} */
const recreateView = this._shouldRecreateView(changes);
if (recreateView) {
if (this._viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
}
if (this.ngTemplateOutlet) {
this._viewRef = this._viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, this.ngTemplateOutletContext);
}
}
else {
if (this._viewRef && this.ngTemplateOutletContext) {
this._updateExistingContext(this.ngTemplateOutletContext);
}
}
}
/**
* We need to re-create existing embedded view if:
* - templateRef has changed
* - context has changes
*
* We mark context object as changed when the corresponding object
* shape changes (new properties are added or existing properties are removed).
* In other words we consider context with the same properties as "the same" even
* if object reference changes (see https://github.com/angular/angular/issues/13407).
* @private
* @param {?} changes
* @return {?}
*/
_shouldRecreateView(changes) {
/** @type {?} */
const ctxChange = changes['ngTemplateOutletContext'];
return !!changes['ngTemplateOutlet'] || (ctxChange && this._hasContextShapeChanged(ctxChange));
}
/**
* @private
* @param {?} ctxChange
* @return {?}
*/
_hasContextShapeChanged(ctxChange) {
/** @type {?} */
const prevCtxKeys = Object.keys(ctxChange.previousValue || {});
/** @type {?} */
const currCtxKeys = Object.keys(ctxChange.currentValue || {});
if (prevCtxKeys.length === currCtxKeys.length) {
for (let propName of currCtxKeys) {
if (prevCtxKeys.indexOf(propName) === -1) {
return true;
}
}
return false;
}
else {
return true;
}
}
/**
* @private
* @param {?} ctx
* @return {?}
*/
_updateExistingContext(ctx) {
for (let propName of Object.keys(ctx)) {
((/** @type {?} */ ((/** @type {?} */ (this._viewRef)).context)))[propName] = ((/** @type {?} */ (this.ngTemplateOutletContext)))[propName];
}
}
}
NgTemplateOutlet.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngTemplateOutlet]' },] }
];
/** @nocollapse */
NgTemplateOutlet.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }
];
NgTemplateOutlet.propDecorators = {
ngTemplateOutletContext: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngTemplateOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A collection of Angular directives that are likely to be used in each and every Angular
* application.
* @type {?}
*/
const COMMON_DIRECTIVES = [
NgClass,
NgComponentOutlet,
NgForOf,
NgIf,
NgTemplateOutlet,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgPlural,
NgPluralCase,
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} type
* @param {?} value
* @return {?}
*/
function invalidPipeArgumentError(type, value) {
return Error(`InvalidPipeArgument: '${value}' for pipe '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(type)}'`);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NumberFormatter {
/**
* @param {?} num
* @param {?} locale
* @param {?} style
* @param {?=} opts
* @return {?}
*/
static format(num, locale, style, opts = {}) {
const { minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, currency, currencyAsSymbol = false } = opts;
/** @type {?} */
const options = {
minimumIntegerDigits,
minimumFractionDigits,
maximumFractionDigits,
style: NumberFormatStyle[style].toLowerCase()
};
if (style == NumberFormatStyle.Currency) {
options.currency = typeof currency == 'string' ? currency : undefined;
options.currencyDisplay = currencyAsSymbol ? 'symbol' : 'code';
}
return new Intl.NumberFormat(locale, options).format(num);
}
}
/** @type {?} */
const DATE_FORMATS_SPLIT$1 = /((?:[^yMLdHhmsazZEwGjJ']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|J+|j+|m+|s+|a|z|Z|G+|w+))(.*)/;
/** @type {?} */
const PATTERN_ALIASES = {
// Keys are quoted so they do not get renamed during closure compilation.
'yMMMdjms': datePartGetterFactory(combine([
digitCondition('year', 1),
nameCondition('month', 3),
digitCondition('day', 1),
digitCondition('hour', 1),
digitCondition('minute', 1),
digitCondition('second', 1),
])),
'yMdjm': datePartGetterFactory(combine([
digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1),
digitCondition('hour', 1), digitCondition('minute', 1)
])),
'yMMMMEEEEd': datePartGetterFactory(combine([
digitCondition('year', 1), nameCondition('month', 4), nameCondition('weekday', 4),
digitCondition('day', 1)
])),
'yMMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 4), digitCondition('day', 1)])),
'yMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 3), digitCondition('day', 1)])),
'yMd': datePartGetterFactory(combine([digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1)])),
'jms': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('second', 1), digitCondition('minute', 1)])),
'jm': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('minute', 1)]))
};
/** @type {?} */
const DATE_FORMATS$1 = {
// Keys are quoted so they do not get renamed.
'yyyy': datePartGetterFactory(digitCondition('year', 4)),
'yy': datePartGetterFactory(digitCondition('year', 2)),
'y': datePartGetterFactory(digitCondition('year', 1)),
'MMMM': datePartGetterFactory(nameCondition('month', 4)),
'MMM': datePartGetterFactory(nameCondition('month', 3)),
'MM': datePartGetterFactory(digitCondition('month', 2)),
'M': datePartGetterFactory(digitCondition('month', 1)),
'LLLL': datePartGetterFactory(nameCondition('month', 4)),
'L': datePartGetterFactory(nameCondition('month', 1)),
'dd': datePartGetterFactory(digitCondition('day', 2)),
'd': datePartGetterFactory(digitCondition('day', 1)),
'HH': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), false)))),
'H': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), false))),
'hh': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), true)))),
'h': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
'jj': datePartGetterFactory(digitCondition('hour', 2)),
'j': datePartGetterFactory(digitCondition('hour', 1)),
'mm': digitModifier(datePartGetterFactory(digitCondition('minute', 2))),
'm': datePartGetterFactory(digitCondition('minute', 1)),
'ss': digitModifier(datePartGetterFactory(digitCondition('second', 2))),
's': datePartGetterFactory(digitCondition('second', 1)),
// while ISO 8601 requires fractions to be prefixed with `.` or `,`
// we can be just safely rely on using `sss` since we currently don't support single or two digit
// fractions
'sss': datePartGetterFactory(digitCondition('second', 3)),
'EEEE': datePartGetterFactory(nameCondition('weekday', 4)),
'EEE': datePartGetterFactory(nameCondition('weekday', 3)),
'EE': datePartGetterFactory(nameCondition('weekday', 2)),
'E': datePartGetterFactory(nameCondition('weekday', 1)),
'a': hourClockExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))),
'Z': timeZoneGetter$1('short'),
'z': timeZoneGetter$1('long'),
'ww': datePartGetterFactory({}),
// Week of year, padded (00-53). Week 01 is the week with the
// first Thursday of the year. not support ?
'w': datePartGetterFactory({}),
// Week of year (0-53). Week 1 is the week with the first Thursday
// of the year not support ?
'G': datePartGetterFactory(nameCondition('era', 1)),
'GG': datePartGetterFactory(nameCondition('era', 2)),
'GGG': datePartGetterFactory(nameCondition('era', 3)),
'GGGG': datePartGetterFactory(nameCondition('era', 4))
};
/**
* @param {?} inner
* @return {?}
*/
function digitModifier(inner) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
const result = inner(date, locale);
return result.length == 1 ? '0' + result : result;
});
}
/**
* @param {?} inner
* @return {?}
*/
function hourClockExtractor(inner) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) { return inner(date, locale).split(' ')[1]; });
}
/**
* @param {?} inner
* @return {?}
*/
function hourExtractor(inner) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) { return inner(date, locale).split(' ')[0]; });
}
/**
* @param {?} date
* @param {?} locale
* @param {?} options
* @return {?}
*/
function intlDateFormat(date, locale, options) {
return new Intl.DateTimeFormat(locale, options).format(date).replace(/[\u200e\u200f]/g, '');
}
/**
* @param {?} timezone
* @return {?}
*/
function timeZoneGetter$1(timezone) {
// To workaround `Intl` API restriction for single timezone let format with 24 hours
/** @type {?} */
const options = { hour: '2-digit', hour12: false, timeZoneName: timezone };
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
const result = intlDateFormat(date, locale, options);
// Then extract first 3 letters that related to hours
return result ? result.substring(3) : '';
});
}
/**
* @param {?} options
* @param {?} value
* @return {?}
*/
function hour12Modify(options, value) {
options.hour12 = value;
return options;
}
/**
* @param {?} prop
* @param {?} len
* @return {?}
*/
function digitCondition(prop, len) {
/** @type {?} */
const result = {};
result[prop] = len === 2 ? '2-digit' : 'numeric';
return result;
}
/**
* @param {?} prop
* @param {?} len
* @return {?}
*/
function nameCondition(prop, len) {
/** @type {?} */
const result = {};
if (len < 4) {
result[prop] = len > 1 ? 'short' : 'narrow';
}
else {
result[prop] = 'long';
}
return result;
}
/**
* @param {?} options
* @return {?}
*/
function combine(options) {
return options.reduce((/**
* @param {?} merged
* @param {?} opt
* @return {?}
*/
(merged, opt) => (Object.assign({}, merged, opt))), {});
}
/**
* @param {?} ret
* @return {?}
*/
function datePartGetterFactory(ret) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
(date, locale) => intlDateFormat(date, locale, ret));
}
/** @type {?} */
const DATE_FORMATTER_CACHE = new Map();
/**
* @param {?} format
* @param {?} date
* @param {?} locale
* @return {?}
*/
function dateFormatter(format, date, locale) {
/** @type {?} */
const fn = PATTERN_ALIASES[format];
if (fn)
return fn(date, locale);
/** @type {?} */
const cacheKey = format;
/** @type {?} */
let parts = DATE_FORMATTER_CACHE.get(cacheKey);
if (!parts) {
parts = [];
/** @type {?} */
let match;
DATE_FORMATS_SPLIT$1.exec(format);
/** @type {?} */
let _format = format;
while (_format) {
match = DATE_FORMATS_SPLIT$1.exec(_format);
if (match) {
parts = parts.concat(match.slice(1));
_format = (/** @type {?} */ (parts.pop()));
}
else {
parts.push(_format);
_format = null;
}
}
DATE_FORMATTER_CACHE.set(cacheKey, parts);
}
return parts.reduce((/**
* @param {?} text
* @param {?} part
* @return {?}
*/
(text, part) => {
/** @type {?} */
const fn = DATE_FORMATS$1[part];
return text + (fn ? fn(date, locale) : partToTime(part));
}), '');
}
/**
* @param {?} part
* @return {?}
*/
function partToTime(part) {
return part === '\'\'' ? '\'' : part.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
}
class DateFormatter {
/**
* @param {?} date
* @param {?} locale
* @param {?} pattern
* @return {?}
*/
static format(date, locale, pattern) {
return dateFormatter(pattern, date, locale);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
* \@description
*
* Formats a date according to locale rules.
*
* Where:
* - `expression` is a date object or a number (milliseconds since UTC epoch) or an ISO string
* (https://www.w3.org/TR/NOTE-datetime).
* - `format` indicates which date/time components to include. The format can be predefined as
* shown below or custom as shown in the table.
* - `'medium'`: equivalent to `'yMMMdjms'` (e.g. `Sep 3, 2010, 12:05:08 PM` for `en-US`)
* - `'short'`: equivalent to `'yMdjm'` (e.g. `9/3/2010, 12:05 PM` for `en-US`)
* - `'fullDate'`: equivalent to `'yMMMMEEEEd'` (e.g. `Friday, September 3, 2010` for `en-US`)
* - `'longDate'`: equivalent to `'yMMMMd'` (e.g. `September 3, 2010` for `en-US`)
* - `'mediumDate'`: equivalent to `'yMMMd'` (e.g. `Sep 3, 2010` for `en-US`)
* - `'shortDate'`: equivalent to `'yMd'` (e.g. `9/3/2010` for `en-US`)
* - `'mediumTime'`: equivalent to `'jms'` (e.g. `12:05:08 PM` for `en-US`)
* - `'shortTime'`: equivalent to `'jm'` (e.g. `12:05 PM` for `en-US`)
*
*
* | Component | Symbol | Narrow | Short Form | Long Form | Numeric | 2-digit |
* |-----------|:------:|--------|--------------|-------------------|-----------|-----------|
* | era | G | G (A) | GGG (AD) | GGGG (Anno Domini)| - | - |
* | year | y | - | - | - | y (2015) | yy (15) |
* | month | M | L (S) | MMM (Sep) | MMMM (September) | M (9) | MM (09) |
* | day | d | - | - | - | d (3) | dd (03) |
* | weekday | E | E (S) | EEE (Sun) | EEEE (Sunday) | - | - |
* | hour | j | - | - | - | j (13) | jj (13) |
* | hour12 | h | - | - | - | h (1 PM) | hh (01 PM)|
* | hour24 | H | - | - | - | H (13) | HH (13) |
* | minute | m | - | - | - | m (5) | mm (05) |
* | second | s | - | - | - | s (9) | ss (09) |
* | timezone | z | - | - | z (Pacific Standard Time)| - | - |
* | timezone | Z | - | Z (GMT-8:00) | - | - | - |
* | timezone | a | - | a (PM) | - | - | - |
*
* In javascript, only the components specified will be respected (not the ordering,
* punctuations, ...) and details of the formatting will be dependent on the locale.
*
* Timezone of the formatted text will be the local system timezone of the end-user's machine.
*
* When the expression is a ISO string without time (e.g. 2016-09-19) the time zone offset is not
* applied and the formatted text will have the same day, month and year of the expression.
*
* WARNINGS:
* - this pipe is marked as pure hence it will not be re-evaluated when the input is mutated.
* Instead users should treat the date as an immutable object and change the reference when the
* pipe needs to re-run (this is to avoid reformatting the date on every change detection run
* which would be an expensive operation).
* - this pipe uses the Internationalization API. Therefore it is only reliable in Chrome and Opera
* browsers.
*
* \@usageNotes
*
* ### Examples
*
* Assuming `dateObj` is (year: 2010, month: 9, day: 3, hour: 12 PM, minute: 05, second: 08)
* in the _local_ time and locale is 'en-US':
*
* {\@example common/pipes/ts/date_pipe.ts region='DeprecatedDatePipe'}
*
* \@publicApi
*/
class DeprecatedDatePipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
* @param {?} value
* @param {?=} pattern
* @return {?}
*/
transform(value, pattern = 'mediumDate') {
if (value == null || value === '' || value !== value)
return null;
/** @type {?} */
let date;
if (typeof value === 'string') {
value = value.trim();
}
if (isDate$1(value)) {
date = value;
}
else if (!isNaN(value - parseFloat(value))) {
date = new Date(parseFloat(value));
}
else if (typeof value === 'string' && /^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
/**
* For ISO Strings without time the day, month and year must be extracted from the ISO String
* before Date creation to avoid time offset and errors in the new Date.
* If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new
* date, some browsers (e.g. IE 9) will throw an invalid Date error
* If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the
* timeoffset
* is applied
* Note: ISO months are 0 for January, 1 for February, ...
*/
const [y, m, d] = value.split('-').map((/**
* @param {?} val
* @return {?}
*/
(val) => parseInt(val, 10)));
date = new Date(y, m - 1, d);
}
else {
date = new Date(value);
}
if (!isDate$1(date)) {
/** @type {?} */
let match;
if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
date = isoStringToDate(match);
}
else {
throw invalidPipeArgumentError(DeprecatedDatePipe, value);
}
}
return DateFormatter.format(date, this._locale, DeprecatedDatePipe._ALIASES[pattern] || pattern);
}
}
/**
* \@internal
*/
DeprecatedDatePipe._ALIASES = {
'medium': 'yMMMdjms',
'short': 'yMdjm',
'fullDate': 'yMMMMEEEEd',
'longDate': 'yMMMMd',
'mediumDate': 'yMMMd',
'shortDate': 'yMd',
'mediumTime': 'jms',
'shortTime': 'jm'
};
DeprecatedDatePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'date', pure: true },] }
];
/** @nocollapse */
DeprecatedDatePipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* @param {?} value
* @return {?}
*/
function isDate$1(value) {
return value instanceof Date && !isNaN(value.valueOf());
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} pipe
* @param {?} locale
* @param {?} value
* @param {?} style
* @param {?=} digits
* @param {?=} currency
* @param {?=} currencyAsSymbol
* @return {?}
*/
function formatNumber$1(pipe, locale, value, style, digits, currency = null, currencyAsSymbol = false) {
if (value == null)
return null;
// Convert strings to numbers
value = typeof value === 'string' && !isNaN(+value - parseFloat(value)) ? +value : value;
if (typeof value !== 'number') {
throw invalidPipeArgumentError(pipe, value);
}
/** @type {?} */
let minInt;
/** @type {?} */
let minFraction;
/** @type {?} */
let maxFraction;
if (style !== NumberFormatStyle.Currency) {
// rely on Intl default for currency
minInt = 1;
minFraction = 0;
maxFraction = 3;
}
if (digits) {
/** @type {?} */
const parts = digits.match(NUMBER_FORMAT_REGEXP);
if (parts === null) {
throw new Error(`${digits} is not a valid digit info for number pipes`);
}
if (parts[1] != null) { // min integer digits
minInt = parseIntAutoRadix(parts[1]);
}
if (parts[3] != null) { // min fraction digits
minFraction = parseIntAutoRadix(parts[3]);
}
if (parts[5] != null) { // max fraction digits
maxFraction = parseIntAutoRadix(parts[5]);
}
}
return NumberFormatter.format((/** @type {?} */ (value)), locale, style, {
minimumIntegerDigits: minInt,
minimumFractionDigits: minFraction,
maximumFractionDigits: maxFraction,
currency: currency,
currencyAsSymbol: currencyAsSymbol,
});
}
/**
* Formats a number as text. Group sizing and separator and other locale-specific
* configurations are based on the active locale.
*
* where `expression` is a number:
* - `digitInfo` is a `string` which has a following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}
* - `minIntegerDigits` is the minimum number of integer digits to use. Defaults to `1`.
* - `minFractionDigits` is the minimum number of digits after fraction. Defaults to `0`.
* - `maxFractionDigits` is the maximum number of digits after fraction. Defaults to `3`.
*
* For more information on the acceptable range for each of these numbers and other
* details see your native internationalization library.
*
* WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
* and may require a polyfill. See [Browser Support](guide/browser-support) for details.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/pipes/ts/number_pipe.ts region='DeprecatedNumberPipe'}
*
* \@ngModule CommonModule
* \@publicApi
*/
class DeprecatedDecimalPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
* @param {?} value
* @param {?=} digits
* @return {?}
*/
transform(value, digits) {
return formatNumber$1(DeprecatedDecimalPipe, this._locale, value, NumberFormatStyle.Decimal, digits);
}
}
DeprecatedDecimalPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'number' },] }
];
/** @nocollapse */
DeprecatedDecimalPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* \@ngModule CommonModule
*
* \@description
*
* Formats a number as percentage according to locale rules.
*
* - `digitInfo` See {\@link DecimalPipe} for detailed description.
*
* WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
* and may require a polyfill. See [Browser Support](guide/browser-support) for details.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/pipes/ts/percent_pipe.ts region='DeprecatedPercentPipe'}
*
* \@publicApi
*/
class DeprecatedPercentPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
* @param {?} value
* @param {?=} digits
* @return {?}
*/
transform(value, digits) {
return formatNumber$1(DeprecatedPercentPipe, this._locale, value, NumberFormatStyle.Percent, digits);
}
}
DeprecatedPercentPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'percent' },] }
];
/** @nocollapse */
DeprecatedPercentPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* \@ngModule CommonModule
* \@description
*
* Formats a number as currency using locale rules.
*
* Use `currency` to format a number as currency.
*
* - `currencyCode` is the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, such
* as `USD` for the US dollar and `EUR` for the euro.
* - `symbolDisplay` is a boolean indicating whether to use the currency symbol or code.
* - `true`: use symbol (e.g. `$`).
* - `false`(default): use code (e.g. `USD`).
* - `digitInfo` See {\@link DecimalPipe} for detailed description.
*
* WARNING: this pipe uses the Internationalization API which is not yet available in all browsers
* and may require a polyfill. See [Browser Support](guide/browser-support) for details.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/pipes/ts/currency_pipe.ts region='DeprecatedCurrencyPipe'}
*
* \@publicApi
*/
class DeprecatedCurrencyPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
* @param {?} value
* @param {?=} currencyCode
* @param {?=} symbolDisplay
* @param {?=} digits
* @return {?}
*/
transform(value, currencyCode = 'USD', symbolDisplay = false, digits) {
return formatNumber$1(DeprecatedCurrencyPipe, this._locale, value, NumberFormatStyle.Currency, digits, currencyCode, symbolDisplay);
}
}
DeprecatedCurrencyPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'currency' },] }
];
/** @nocollapse */
DeprecatedCurrencyPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A collection of deprecated i18n pipes that require intl api
*
* @deprecated from v5
* @type {?}
*/
const COMMON_DEPRECATED_I18N_PIPES = [DeprecatedDecimalPipe, DeprecatedPercentPipe, DeprecatedCurrencyPipe, DeprecatedDatePipe];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @record
*/
function SubscriptionStrategy() { }
if (false) {}
class ObservableStrategy {
/**
* @param {?} async
* @param {?} updateLatestValue
* @return {?}
*/
createSubscription(async, updateLatestValue) {
return async.subscribe({ next: updateLatestValue, error: (/**
* @param {?} e
* @return {?}
*/
(e) => { throw e; }) });
}
/**
* @param {?} subscription
* @return {?}
*/
dispose(subscription) { subscription.unsubscribe(); }
/**
* @param {?} subscription
* @return {?}
*/
onDestroy(subscription) { subscription.unsubscribe(); }
}
class PromiseStrategy {
/**
* @param {?} async
* @param {?} updateLatestValue
* @return {?}
*/
createSubscription(async, updateLatestValue) {
return async.then(updateLatestValue, (/**
* @param {?} e
* @return {?}
*/
e => { throw e; }));
}
/**
* @param {?} subscription
* @return {?}
*/
dispose(subscription) { }
/**
* @param {?} subscription
* @return {?}
*/
onDestroy(subscription) { }
}
/** @type {?} */
const _promiseStrategy = new PromiseStrategy();
/** @type {?} */
const _observableStrategy = new ObservableStrategy();
/**
* \@ngModule CommonModule
* \@description
*
* Unwraps a value from an asynchronous primitive.
*
* The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has
* emitted. When a new value is emitted, the `async` pipe marks the component to be checked for
* changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid
* potential memory leaks.
*
* \@usageNotes
*
* ### Examples
*
* This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the
* promise.
*
* {\@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'}
*
* It's also possible to use `async` with Observables. The example below binds the `time` Observable
* to the view. The Observable continuously updates the view with the current time.
*
* {\@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'}
*
* \@publicApi
*/
class AsyncPipe {
/**
* @param {?} _ref
*/
constructor(_ref) {
this._ref = _ref;
this._latestValue = null;
this._latestReturnedValue = null;
this._subscription = null;
this._obj = null;
this._strategy = (/** @type {?} */ (null));
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this._subscription) {
this._dispose();
}
}
/**
* @param {?} obj
* @return {?}
*/
transform(obj) {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
}
this._latestReturnedValue = this._latestValue;
return this._latestValue;
}
if (obj !== this._obj) {
this._dispose();
return this.transform((/** @type {?} */ (obj)));
}
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵlooseIdentical"])(this._latestValue, this._latestReturnedValue)) {
return this._latestReturnedValue;
}
this._latestReturnedValue = this._latestValue;
return _angular_core__WEBPACK_IMPORTED_MODULE_0__["WrappedValue"].wrap(this._latestValue);
}
/**
* @private
* @param {?} obj
* @return {?}
*/
_subscribe(obj) {
this._obj = obj;
this._strategy = this._selectStrategy(obj);
this._subscription = this._strategy.createSubscription(obj, (/**
* @param {?} value
* @return {?}
*/
(value) => this._updateLatestValue(obj, value)));
}
/**
* @private
* @param {?} obj
* @return {?}
*/
_selectStrategy(obj) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(obj)) {
return _promiseStrategy;
}
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(obj)) {
return _observableStrategy;
}
throw invalidPipeArgumentError(AsyncPipe, obj);
}
/**
* @private
* @return {?}
*/
_dispose() {
this._strategy.dispose((/** @type {?} */ (this._subscription)));
this._latestValue = null;
this._latestReturnedValue = null;
this._subscription = null;
this._obj = null;
}
/**
* @private
* @param {?} async
* @param {?} value
* @return {?}
*/
_updateLatestValue(async, value) {
if (async === this._obj) {
this._latestValue = value;
this._ref.markForCheck();
}
}
}
AsyncPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'async', pure: false },] }
];
/** @nocollapse */
AsyncPipe.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Transforms text to all lower case.
*
* @see `UpperCasePipe`
* @see `TitleCasePipe`
* \@usageNotes
*
* The following example defines a view that allows the user to enter
* text, and then uses the pipe to convert the input text to all lower case.
*
*
*
* \@ngModule CommonModule
* \@publicApi
*/
class LowerCasePipe {
/**
* @param {?} value The string to transform to lower case.
* @return {?}
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(LowerCasePipe, value);
}
return value.toLowerCase();
}
}
LowerCasePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'lowercase' },] }
];
//
// Regex below matches any Unicode word and compatible with ES5. In ES2018 the same result
// can be achieved by using /\p{L}\S*/gu and also known as Unicode Property Escapes
// (http://2ality.com/2017/07/regexp-unicode-property-escapes.html). Since there is no
// transpilation of this functionality down to ES5 without external tool, the only solution is
// to use already transpiled form. Example can be found here -
// https://mothereff.in/regexpu#input=var+regex+%3D+/%5Cp%7BL%7D/u%3B&unicodePropertyEscape=1
//
/** @type {?} */
const unicodeWordMatch = /(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])\S*/g;
/**
* Transforms text to title case.
* Capitalizes the first letter of each word, and transforms the
* rest of the word to lower case.
* Words are delimited by any whitespace character, such as a space, tab, or line-feed character.
*
* @see `LowerCasePipe`
* @see `UpperCasePipe`
*
* \@usageNotes
* The following example shows the result of transforming various strings into title case.
*
*
*
* \@ngModule CommonModule
* \@publicApi
*/
class TitleCasePipe {
/**
* @param {?} value The string to transform to title case.
* @return {?}
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(TitleCasePipe, value);
}
return value.replace(unicodeWordMatch, ((/**
* @param {?} txt
* @return {?}
*/
txt => txt[0].toUpperCase() + txt.substr(1).toLowerCase())));
}
}
TitleCasePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'titlecase' },] }
];
/**
* Transforms text to all upper case.
* @see `LowerCasePipe`
* @see `TitleCasePipe`
*
* \@ngModule CommonModule
* \@publicApi
*/
class UpperCasePipe {
/**
* @param {?} value The string to transform to upper case.
* @return {?}
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(UpperCasePipe, value);
}
return value.toUpperCase();
}
}
UpperCasePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'uppercase' },] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// clang-format off
/**
* \@ngModule CommonModule
* \@description
*
* Formats a date value according to locale rules.
*
* Only the `en-US` locale data comes with Angular. To localize dates
* in another language, you must import the corresponding locale data.
* See the [I18n guide](guide/i18n#i18n-pipes) for more information.
*
* @see `formatDate()`
*
*
* \@usageNotes
*
* The result of this pipe is not reevaluated when the input is mutated. To avoid the need to
* reformat the date on every change-detection cycle, treat the date as an immutable object
* and change the reference when the pipe needs to run again.
*
* ### Pre-defined format options
*
* Examples are given in `en-US` locale.
*
* - `'short'`: equivalent to `'M/d/yy, h:mm a'` (`6/15/15, 9:03 AM`).
* - `'medium'`: equivalent to `'MMM d, y, h:mm:ss a'` (`Jun 15, 2015, 9:03:01 AM`).
* - `'long'`: equivalent to `'MMMM d, y, h:mm:ss a z'` (`June 15, 2015 at 9:03:01 AM
* GMT+1`).
* - `'full'`: equivalent to `'EEEE, MMMM d, y, h:mm:ss a zzzz'` (`Monday, June 15, 2015 at
* 9:03:01 AM GMT+01:00`).
* - `'shortDate'`: equivalent to `'M/d/yy'` (`6/15/15`).
* - `'mediumDate'`: equivalent to `'MMM d, y'` (`Jun 15, 2015`).
* - `'longDate'`: equivalent to `'MMMM d, y'` (`June 15, 2015`).
* - `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` (`Monday, June 15, 2015`).
* - `'shortTime'`: equivalent to `'h:mm a'` (`9:03 AM`).
* - `'mediumTime'`: equivalent to `'h:mm:ss a'` (`9:03:01 AM`).
* - `'longTime'`: equivalent to `'h:mm:ss a z'` (`9:03:01 AM GMT+1`).
* - `'fullTime'`: equivalent to `'h:mm:ss a zzzz'` (`9:03:01 AM GMT+01:00`).
*
* ### Custom format options
*
* You can construct a format string using symbols to specify the components
* of a date-time value, as described in the following table.
* Format details depend on the locale.
* Fields marked with (*) are only available in the extra data set for the given locale.
*
* | Field type | Format | Description | Example Value |
* |--------------------|-------------|---------------------------------------------------------------|------------------------------------------------------------|
* | Era | G, GG & GGG | Abbreviated | AD |
* | | GGGG | Wide | Anno Domini |
* | | GGGGG | Narrow | A |
* | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 |
* | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |
* | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |
* | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |
* | Month | M | Numeric: 1 digit | 9, 12 |
* | | MM | Numeric: 2 digits + zero padded | 09, 12 |
* | | MMM | Abbreviated | Sep |
* | | MMMM | Wide | September |
* | | MMMMM | Narrow | S |
* | Month standalone | L | Numeric: 1 digit | 9, 12 |
* | | LL | Numeric: 2 digits + zero padded | 09, 12 |
* | | LLL | Abbreviated | Sep |
* | | LLLL | Wide | September |
* | | LLLLL | Narrow | S |
* | Week of year | w | Numeric: minimum digits | 1... 53 |
* | | ww | Numeric: 2 digits + zero padded | 01... 53 |
* | Week of month | W | Numeric: 1 digit | 1... 5 |
* | Day of month | d | Numeric: minimum digits | 1 |
* | | dd | Numeric: 2 digits + zero padded | 01 |
* | Week day | E, EE & EEE | Abbreviated | Tue |
* | | EEEE | Wide | Tuesday |
* | | EEEEE | Narrow | T |
* | | EEEEEE | Short | Tu |
* | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM |
* | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem |
* | | aaaaa | Narrow | a/p |
* | Period* | B, BB & BBB | Abbreviated | mid. |
* | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |
* | | BBBBB | Narrow | md |
* | Period standalone* | b, bb & bbb | Abbreviated | mid. |
* | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |
* | | bbbbb | Narrow | md |
* | Hour 1-12 | h | Numeric: minimum digits | 1, 12 |
* | | hh | Numeric: 2 digits + zero padded | 01, 12 |
* | Hour 0-23 | H | Numeric: minimum digits | 0, 23 |
* | | HH | Numeric: 2 digits + zero padded | 00, 23 |
* | Minute | m | Numeric: minimum digits | 8, 59 |
* | | mm | Numeric: 2 digits + zero padded | 08, 59 |
* | Second | s | Numeric: minimum digits | 0... 59 |
* | | ss | Numeric: 2 digits + zero padded | 00... 59 |
* | Fractional seconds | S | Numeric: 1 digit | 0... 9 |
* | | SS | Numeric: 2 digits + zero padded | 00... 99 |
* | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 |
* | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 |
* | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 |
* | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 |
* | | ZZZZ | Long localized GMT format | GMT-8:00 |
* | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 |
* | | O, OO & OOO | Short localized GMT format | GMT-8 |
* | | OOOO | Long localized GMT format | GMT-08:00 |
*
* Note that timezone correction is not applied to an ISO string that has no time component, such as "2016-09-19"
*
* ### Format examples
*
* These examples transform a date into various formats,
* assuming that `dateObj` is a JavaScript `Date` object for
* year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11,
* given in the local time for the `en-US` locale.
*
* ```
* {{ dateObj | date }} // output is 'Jun 15, 2015'
* {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM'
* {{ dateObj | date:'shortTime' }} // output is '9:43 PM'
* {{ dateObj | date:'mm:ss' }} // output is '43:11'
* ```
*
* ### Usage example
*
* The following component uses a date pipe to display the current date in different formats.
*
* ```
* \@Component({
* selector: 'date-pipe',
* template: `
*
Today is {{today | date}}
*
Or if you prefer, {{today | date:'fullDate'}}
*
The time is {{today | date:'h:mm a z'}}
*
`
* })
* // Get the current date and time as a date-time value.
* export class DatePipeComponent {
* today: number = Date.now();
* }
* ```
*
* \@publicApi
*/
// clang-format on
class DatePipe {
/**
* @param {?} locale
*/
constructor(locale) {
this.locale = locale;
}
/**
* @param {?} value The date expression: a `Date` object, a number
* (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).
* @param {?=} format The date/time components to include, using predefined options or a
* custom format string.
* @param {?=} timezone A timezone offset (such as `'+0430'`), or a standard
* UTC/GMT or continental US timezone abbreviation.
* When not supplied, uses the end-user's local system timezone.
* @param {?=} locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
* @return {?} A date string in the desired format.
*/
transform(value, format = 'mediumDate', timezone, locale) {
if (value == null || value === '' || value !== value)
return null;
try {
return formatDate(value, format, locale || this.locale, timezone);
}
catch (error) {
throw invalidPipeArgumentError(DatePipe, error.message);
}
}
}
DatePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'date', pure: true },] }
];
/** @nocollapse */
DatePipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const _INTERPOLATION_REGEXP = /#/g;
/**
* \@ngModule CommonModule
* \@description
*
* Maps a value to a string that pluralizes the value according to locale rules.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/pipes/ts/i18n_pipe.ts region='I18nPluralPipeComponent'}
*
* \@publicApi
*/
class I18nPluralPipe {
/**
* @param {?} _localization
*/
constructor(_localization) {
this._localization = _localization;
}
/**
* @param {?} value the number to be formatted
* @param {?} pluralMap an object that mimics the ICU format, see
* http://userguide.icu-project.org/formatparse/messages.
* @param {?=} locale a `string` defining the locale to use (uses the current {\@link LOCALE_ID} by
* default).
* @return {?}
*/
transform(value, pluralMap, locale) {
if (value == null)
return '';
if (typeof pluralMap !== 'object' || pluralMap === null) {
throw invalidPipeArgumentError(I18nPluralPipe, pluralMap);
}
/** @type {?} */
const key = getPluralCategory(value, Object.keys(pluralMap), this._localization, locale);
return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString());
}
}
I18nPluralPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'i18nPlural', pure: true },] }
];
/** @nocollapse */
I18nPluralPipe.ctorParameters = () => [
{ type: NgLocalization }
];
if (false) {}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
* \@description
*
* Generic selector that displays the string that matches the current value.
*
* If none of the keys of the `mapping` match the `value`, then the content
* of the `other` key is returned when present, otherwise an empty string is returned.
*
* \@usageNotes
*
* ### Example
*
* {\@example common/pipes/ts/i18n_pipe.ts region='I18nSelectPipeComponent'}
*
* \@publicApi
*/
class I18nSelectPipe {
/**
* @param {?} value a string to be internationalized.
* @param {?} mapping an object that indicates the text that should be displayed
* for different values of the provided `value`.
* @return {?}
*/
transform(value, mapping) {
if (value == null)
return '';
if (typeof mapping !== 'object' || typeof value !== 'string') {
throw invalidPipeArgumentError(I18nSelectPipe, mapping);
}
if (mapping.hasOwnProperty(value)) {
return mapping[value];
}
if (mapping.hasOwnProperty('other')) {
return mapping['other'];
}
return '';
}
}
I18nSelectPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'i18nSelect', pure: true },] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
* \@description
*
* Converts a value into its JSON-format representation. Useful for debugging.
*
* \@usageNotes
*
* The following component uses a JSON pipe to convert an object
* to JSON format, and displays the string in both formats for comparison.
*
* {\@example common/pipes/ts/json_pipe.ts region='JsonPipe'}
*
* \@publicApi
*/
class JsonPipe {
/**
* @param {?} value A value of any type to convert into a JSON-format string.
* @return {?}
*/
transform(value) { return JSON.stringify(value, null, 2); }
}
JsonPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'json', pure: false },] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @template K, V
* @param {?} key
* @param {?} value
* @return {?}
*/
function makeKeyValuePair(key, value) {
return { key: key, value: value };
}
/**
* A key value pair.
* Usually used to represent the key value pairs from a Map or Object.
*
* \@publicApi
* @record
* @template K, V
*/
function KeyValue() { }
if (false) {}
/**
* \@ngModule CommonModule
* \@description
*
* Transforms Object or Map into an array of key value pairs.
*
* The output array will be ordered by keys.
* By default the comparator will be by Unicode point value.
* You can optionally pass a compareFn if your keys are complex types.
*
* \@usageNotes
* ### Examples
*
* This examples show how an Object or a Map can be iterated by ngFor with the use of this keyvalue
* pipe.
*
* {\@example common/pipes/ts/keyvalue_pipe.ts region='KeyValuePipe'}
*
* \@publicApi
*/
class KeyValuePipe {
/**
* @param {?} differs
*/
constructor(differs) {
this.differs = differs;
this.keyValues = [];
}
/**
* @template K, V
* @param {?} input
* @param {?=} compareFn
* @return {?}
*/
transform(input, compareFn = defaultComparator) {
if (!input || (!(input instanceof Map) && typeof input !== 'object')) {
return null;
}
if (!this.differ) {
// make a differ for whatever type we've been passed in
this.differ = this.differs.find(input).create();
}
/** @type {?} */
const differChanges = this.differ.diff((/** @type {?} */ (input)));
if (differChanges) {
this.keyValues = [];
differChanges.forEachItem((/**
* @param {?} r
* @return {?}
*/
(r) => {
this.keyValues.push(makeKeyValuePair(r.key, (/** @type {?} */ (r.currentValue))));
}));
this.keyValues.sort(compareFn);
}
return this.keyValues;
}
}
KeyValuePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'keyvalue', pure: false },] }
];
/** @nocollapse */
KeyValuePipe.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }
];
if (false) {}
/**
* @template K, V
* @param {?} keyValueA
* @param {?} keyValueB
* @return {?}
*/
function defaultComparator(keyValueA, keyValueB) {
/** @type {?} */
const a = keyValueA.key;
/** @type {?} */
const b = keyValueB.key;
// if same exit with 0;
if (a === b)
return 0;
// make sure that undefined are at the end of the sort.
if (a === undefined)
return 1;
if (b === undefined)
return -1;
// make sure that nulls are at the end of the sort.
if (a === null)
return 1;
if (b === null)
return -1;
if (typeof a == 'string' && typeof b == 'string') {
return a < b ? -1 : 1;
}
if (typeof a == 'number' && typeof b == 'number') {
return a - b;
}
if (typeof a == 'boolean' && typeof b == 'boolean') {
return a < b ? -1 : 1;
}
// `a` and `b` are of different types. Compare their string values.
/** @type {?} */
const aString = String(a);
/** @type {?} */
const bString = String(b);
return aString == bString ? 0 : aString < bString ? -1 : 1;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
* \@description
*
* Transforms a number into a string,
* formatted according to locale rules that determine group sizing and
* separator, decimal-point character, and other locale-specific
* configurations.
*
* If no parameters are specified, the function rounds off to the nearest value using this
* [rounding method](https://en.wikibooks.org/wiki/Arithmetic/Rounding).
* The behavior differs from that of the JavaScript ```Math.round()``` function.
* In the following case for example, the pipe rounds down where
* ```Math.round()``` rounds up:
*
* ```html
* -2.5 | number:'1.0-0'
* > -3
* Math.round(-2.5)
* > -2
* ```
*
* @see `formatNumber()`
*
* \@usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
* ### Example
*
*
*
* \@publicApi
*/
class DecimalPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
* @param {?} value The number to be formatted.
* @param {?=} digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `3`.
* @param {?=} locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
* @return {?}
*/
transform(value, digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
try {
/** @type {?} */
const num = strToNumber(value);
return formatNumber(num, locale, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(DecimalPipe, error.message);
}
}
}
DecimalPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'number' },] }
];
/** @nocollapse */
DecimalPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* \@ngModule CommonModule
* \@description
*
* Transforms a number to a percentage
* string, formatted according to locale rules that determine group sizing and
* separator, decimal-point character, and other locale-specific
* configurations.
*
* @see `formatPercent()`
*
* \@usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
*
*
* \@publicApi
*/
class PercentPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
*
* @param {?} value The number to be formatted as a percentage.
* @param {?=} digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `0`.
* @param {?=} locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
* @return {?}
*/
transform(value, digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
try {
/** @type {?} */
const num = strToNumber(value);
return formatPercent(num, locale, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(PercentPipe, error.message);
}
}
}
PercentPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'percent' },] }
];
/** @nocollapse */
PercentPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* \@ngModule CommonModule
* \@description
*
* Transforms a number to a currency string, formatted according to locale rules
* that determine group sizing and separator, decimal-point character,
* and other locale-specific configurations.
*
* @see `getCurrencySymbol()`
* @see `formatCurrency()`
*
* \@usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
*
*
* \@publicApi
*/
class CurrencyPipe {
/**
* @param {?} _locale
*/
constructor(_locale) {
this._locale = _locale;
}
/**
*
* @param {?} value The number to be formatted as currency.
* @param {?=} currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code,
* such as `USD` for the US dollar and `EUR` for the euro.
* @param {?=} display The format for the currency indicator. One of the following:
* - `code`: Show the code (such as `USD`).
* - `symbol`(default): Show the symbol (such as `$`).
* - `symbol-narrow`: Use the narrow symbol for locales that have two symbols for their
* currency.
* For example, the Canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`. If the
* locale has no narrow symbol, uses the standard symbol for the locale.
* - String: Use the given string value instead of a code or a symbol.
* For example, an empty string will suppress the currency & symbol.
* - Boolean (marked deprecated in v5): `true` for symbol and false for `code`.
*
* @param {?=} digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `2`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `2`.
* If not provided, the number will be formatted with the proper amount of digits,
* depending on what the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) specifies.
* For example, the Canadian dollar has 2 digits, whereas the Chilean peso has none.
* @param {?=} locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
* @return {?}
*/
transform(value, currencyCode, display = 'symbol', digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
if (typeof display === 'boolean') {
if ((/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) {
console.warn(`Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".`);
}
display = display ? 'symbol' : 'code';
}
/** @type {?} */
let currency = currencyCode || 'USD';
if (display !== 'code') {
if (display === 'symbol' || display === 'symbol-narrow') {
currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale);
}
else {
currency = display;
}
}
try {
/** @type {?} */
const num = strToNumber(value);
return formatCurrency(num, locale, currency, currencyCode, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(CurrencyPipe, error.message);
}
}
}
CurrencyPipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'currency' },] }
];
/** @nocollapse */
CurrencyPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
if (false) {}
/**
* @param {?} value
* @return {?}
*/
function isEmpty(value) {
return value == null || value === '' || value !== value;
}
/**
* Transforms a string into a number (if needed).
* @param {?} value
* @return {?}
*/
function strToNumber(value) {
// Convert strings to numbers
if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) {
return Number(value);
}
if (typeof value !== 'number') {
throw new Error(`${value} is not a number`);
}
return value;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@ngModule CommonModule
* \@description
*
* Creates a new `Array` or `String` containing a subset (slice) of the elements.
*
* \@usageNotes
*
* All behavior is based on the expected behavior of the JavaScript API `Array.prototype.slice()`
* and `String.prototype.slice()`.
*
* When operating on an `Array`, the returned `Array` is always a copy even when all
* the elements are being returned.
*
* When operating on a blank value, the pipe returns the blank value.
*
* ### List Example
*
* This `ngFor` example:
*
* {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_list'}
*
* produces the following:
*
* ```html
*
b
*
c
* ```
*
* ### String Examples
*
* {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'}
*
* \@publicApi
*/
class SlicePipe {
/**
* @param {?} value
* @param {?} start
* @param {?=} end
* @return {?}
*/
transform(value, start, end) {
if (value == null)
return value;
if (!this.supports(value)) {
throw invalidPipeArgumentError(SlicePipe, value);
}
return value.slice(start, end);
}
/**
* @private
* @param {?} obj
* @return {?}
*/
supports(obj) { return typeof obj === 'string' || Array.isArray(obj); }
}
SlicePipe.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'slice', pure: false },] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A collection of Angular pipes that are likely to be used in each and every application.
* @type {?}
*/
const COMMON_PIPES = [
AsyncPipe,
UpperCasePipe,
LowerCasePipe,
JsonPipe,
SlicePipe,
DecimalPipe,
PercentPipe,
TitleCasePipe,
CurrencyPipe,
DatePipe,
I18nPluralPipe,
I18nSelectPipe,
KeyValuePipe,
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// Note: This does not contain the location providers,
// as they need some platform specific implementations to work.
/**
* Exports all the basic Angular directives and pipes,
* such as `NgIf`, `NgForOf`, `DecimalPipe`, and so on.
* Re-exported by `BrowserModule`, which is included automatically in the root
* `AppModule` when you create a new app with the CLI `new` command.
*
* * The `providers` options configure the NgModule's injector to provide
* localization dependencies to members.
* * The `exports` options make the declared directives and pipes available for import
* by other NgModules.
*
* \@publicApi
*/
class CommonModule {
}
CommonModule.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{
declarations: [COMMON_DIRECTIVES, COMMON_PIPES],
exports: [COMMON_DIRECTIVES, COMMON_PIPES],
providers: [
{ provide: NgLocalization, useClass: NgLocaleLocalization },
],
},] }
];
const ɵ0$2 = getPluralCase;
/**
* A module that contains the deprecated i18n pipes.
*
* @deprecated from v5
* \@publicApi
*/
class DeprecatedI18NPipesModule {
}
DeprecatedI18NPipesModule.decorators = [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{
declarations: [COMMON_DEPRECATED_I18N_PIPES],
exports: [COMMON_DEPRECATED_I18N_PIPES],
providers: [{ provide: DEPRECATED_PLURAL_FN, useValue: ɵ0$2 }],
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A DI Token representing the main rendering context. In a browser this is the DOM Document.
*
* Note: Document might not be available in the Application Context when Application and Rendering
* Contexts are not the same (e.g. when running the application in a Web Worker).
*
* \@publicApi
* @type {?}
*/
const DOCUMENT = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('DocumentToken');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @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
*/
/** @type {?} */
const PLATFORM_BROWSER_ID = 'browser';
/** @type {?} */
const PLATFORM_SERVER_ID = 'server';
/** @type {?} */
const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
/** @type {?} */
const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
/**
* Returns whether a platform id represents a browser platform.
* \@publicApi
* @param {?} platformId
* @return {?}
*/
function isPlatformBrowser(platformId) {
return platformId === PLATFORM_BROWSER_ID;
}
/**
* Returns whether a platform id represents a server platform.
* \@publicApi
* @param {?} platformId
* @return {?}
*/
function isPlatformServer(platformId) {
return platformId === PLATFORM_SERVER_ID;
}
/**
* Returns whether a platform id represents a web worker app platform.
* \@publicApi
* @param {?} platformId
* @return {?}
*/
function isPlatformWorkerApp(platformId) {
return platformId === PLATFORM_WORKER_APP_ID;
}
/**
* Returns whether a platform id represents a web worker UI platform.
* \@publicApi
* @param {?} platformId
* @return {?}
*/
function isPlatformWorkerUi(platformId) {
return platformId === PLATFORM_WORKER_UI_ID;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* \@publicApi
* @type {?}
*/
const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Version"]('8.2.14');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Defines a scroll position manager. Implemented by `BrowserViewportScroller`.
*
* \@publicApi
* @abstract
*/
class ViewportScroller {
}
// De-sugared tree-shakable injection
// See #23917
/** @nocollapse */
/** @nocollapse */ ViewportScroller.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({
token: ViewportScroller,
providedIn: 'root',
factory: (/**
* @nocollapse @return {?}
*/
() => new BrowserViewportScroller(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT), window, Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ErrorHandler"])))
});
if (false) {}
/**
* Manages the scroll position for a browser window.
*/
class BrowserViewportScroller {
/**
* @param {?} document
* @param {?} window
* @param {?} errorHandler
*/
constructor(document, window, errorHandler) {
this.document = document;
this.window = window;
this.errorHandler = errorHandler;
this.offset = (/**
* @return {?}
*/
() => [0, 0]);
}
/**
* Configures the top offset used when scrolling to an anchor.
* @param {?} offset A position in screen coordinates (a tuple with x and y values)
* or a function that returns the top offset position.
*
* @return {?}
*/
setOffset(offset) {
if (Array.isArray(offset)) {
this.offset = (/**
* @return {?}
*/
() => offset);
}
else {
this.offset = offset;
}
}
/**
* Retrieves the current scroll position.
* @return {?} The position in screen coordinates.
*/
getScrollPosition() {
if (this.supportScrollRestoration()) {
return [this.window.scrollX, this.window.scrollY];
}
else {
return [0, 0];
}
}
/**
* Sets the scroll position.
* @param {?} position The new position in screen coordinates.
* @return {?}
*/
scrollToPosition(position) {
if (this.supportScrollRestoration()) {
this.window.scrollTo(position[0], position[1]);
}
}
/**
* Scrolls to an anchor element.
* @param {?} anchor The ID of the anchor element.
* @return {?}
*/
scrollToAnchor(anchor) {
if (this.supportScrollRestoration()) {
// Escape anything passed to `querySelector` as it can throw errors and stop the application
// from working if invalid values are passed.
if (this.window.CSS && this.window.CSS.escape) {
anchor = this.window.CSS.escape(anchor);
}
else {
anchor = anchor.replace(/(\"|\'\ |:|\.|\[|\]|,|=)/g, '\\$1');
}
try {
/** @type {?} */
const elSelectedById = this.document.querySelector(`#${anchor}`);
if (elSelectedById) {
this.scrollToElement(elSelectedById);
return;
}
/** @type {?} */
const elSelectedByName = this.document.querySelector(`[name='${anchor}']`);
if (elSelectedByName) {
this.scrollToElement(elSelectedByName);
return;
}
}
catch (e) {
this.errorHandler.handleError(e);
}
}
}
/**
* Disables automatic scroll restoration provided by the browser.
* @param {?} scrollRestoration
* @return {?}
*/
setHistoryScrollRestoration(scrollRestoration) {
if (this.supportScrollRestoration()) {
/** @type {?} */
const history = this.window.history;
if (history && history.scrollRestoration) {
history.scrollRestoration = scrollRestoration;
}
}
}
/**
* @private
* @param {?} el
* @return {?}
*/
scrollToElement(el) {
/** @type {?} */
const rect = el.getBoundingClientRect();
/** @type {?} */
const left = rect.left + this.window.pageXOffset;
/** @type {?} */
const top = rect.top + this.window.pageYOffset;
/** @type {?} */
const offset = this.offset();
this.window.scrollTo(left - offset[0], top - offset[1]);
}
/**
* We only support scroll restoration when we can get a hold of window.
* This means that we do not support this behavior when running in a web worker.
*
* Lifting this restriction right now would require more changes in the dom adapter.
* Since webworkers aren't widely used, we will lift it once RouterScroller is
* battle-tested.
* @private
* @return {?}
*/
supportScrollRestoration() {
try {
return !!this.window && !!this.window.scrollTo;
}
catch (_a) {
return false;
}
}
}
if (false) {}
/**
* Provides an empty implementation of the viewport scroller. This will
* live in \@angular/common as it will be used by both platform-server and platform-webworker.
*/
class NullViewportScroller {
/**
* Empty implementation
* @param {?} offset
* @return {?}
*/
setOffset(offset) { }
/**
* Empty implementation
* @return {?}
*/
getScrollPosition() { return [0, 0]; }
/**
* Empty implementation
* @param {?} position
* @return {?}
*/
scrollToPosition(position) { }
/**
* Empty implementation
* @param {?} anchor
* @return {?}
*/
scrollToAnchor(anchor) { }
/**
* Empty implementation
* @param {?} scrollRestoration
* @return {?}
*/
setHistoryScrollRestoration(scrollRestoration) { }
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
//# sourceMappingURL=common.js.map
/***/ }),
/***/ "./node_modules/@angular/compiler/fesm2015/compiler.js":
/*!*************************************************************!*\
!*** ./node_modules/@angular/compiler/fesm2015/compiler.js ***!
\*************************************************************/
/*! exports provided: core, CompilerConfig, preserveWhitespacesDefault, isLoweredSymbol, createLoweredSymbol, Identifiers, JitCompiler, ConstantPool, DirectiveResolver, PipeResolver, NgModuleResolver, DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig, NgModuleCompiler, ArrayType, AssertNotNull, DYNAMIC_TYPE, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinType, BuiltinTypeName, BuiltinVar, CastExpr, ClassField, ClassMethod, ClassStmt, CommaExpr, CommentStmt, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, Expression, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, literalMap, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, JSDocCommentStmt, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, MapType, NotExpr, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, ThrowStmt, TryCatchStmt, Type, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, StmtModifier, Statement, STRING_TYPE, TypeofExpr, collectExternalReferences, EmitterVisitorContext, JitEvaluator, ViewCompiler, findStaticQueryIds, staticViewQueryIds, getParseErrors, isSyntaxError, syntaxError, Version, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstContent, TmplAstElement, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstText, TmplAstTextAttribute, TmplAstVariable, R3Identifiers, R3ResolvedDependencyType, compileInjector, compileNgModule, compilePipeFromMetadata, makeBindingParser, parseTemplate, compileBaseDefFromMetadata, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, verifyHostBindings, publishFacade, VERSION, TextAst, BoundTextAst, AttrAst, BoundElementPropertyAst, BoundEventAst, ReferenceAst, VariableAst, ElementAst, EmbeddedTemplateAst, BoundDirectivePropertyAst, DirectiveAst, ProviderAst, ProviderAstType, NgContentAst, NullTemplateVisitor, RecursiveTemplateAstVisitor, templateVisitAll, sanitizeIdentifier, identifierName, identifierModuleUrl, viewClassName, rendererTypeName, hostViewClassName, componentFactoryName, CompileSummaryKind, tokenName, tokenReference, CompileStylesheetMetadata, CompileTemplateMetadata, CompileDirectiveMetadata, CompilePipeMetadata, CompileShallowModuleMetadata, CompileNgModuleMetadata, TransitiveCompileNgModuleMetadata, ProviderMeta, flatten, templateSourceUrl, sharedStylesheetJitUrl, ngModuleJitUrl, templateJitUrl, createAotUrlResolver, createAotCompiler, AotCompiler, analyzeNgModules, analyzeAndValidateNgModules, analyzeFile, analyzeFileForInjectables, mergeAnalyzedFiles, GeneratedFile, toTypeScript, formattedError, isFormattedError, StaticReflector, StaticSymbol, StaticSymbolCache, ResolvedStaticSymbol, StaticSymbolResolver, unescapeIdentifier, unwrapResolvedMetadata, AotSummaryResolver, AstPath, SummaryResolver, JitSummaryResolver, CompileReflector, createUrlResolverWithoutPackagePrefix, createOfflineCompileUrlResolver, UrlResolver, getUrlScheme, ResourceLoader, ElementSchemaRegistry, Extractor, I18NHtmlParser, MessageBundle, Serializer, Xliff, Xliff2, Xmb, Xtb, DirectiveNormalizer, ParserError, ParseSpan, AST, Quote, EmptyExpr, ImplicitReceiver, Chain, Conditional, PropertyRead, PropertyWrite, SafePropertyRead, KeyedRead, KeyedWrite, BindingPipe, LiteralPrimitive, LiteralArray, LiteralMap, Interpolation, Binary, PrefixNot, NonNullAssert, MethodCall, SafeMethodCall, FunctionCall, AbsoluteSourceSpan, ASTWithSource, TemplateBinding, NullAstVisitor, RecursiveAstVisitor, AstTransformer, AstMemoryEfficientTransformer, visitAstChildren, ParsedProperty, ParsedPropertyType, ParsedEvent, ParsedVariable, BoundElementProperty, TokenType, Lexer, Token, EOF, isIdentifier, isQuote, SplitInterpolation, TemplateBindingParseResult, Parser, _ParseAST, ERROR_COMPONENT_TYPE, CompileMetadataResolver, Text, Expansion, ExpansionCase, Attribute, Element, Comment, visitAll, RecursiveVisitor, findNode, HtmlParser, ParseTreeResult, TreeError, HtmlTagDefinition, getHtmlTagDefinition, TagContentType, splitNsName, isNgContainer, isNgContent, isNgTemplate, getNsPrefix, mergeNsAndName, NAMED_ENTITIES, NGSP_UNICODE, debugOutputAstAsTypeScript, TypeScriptEmitter, ParseLocation, ParseSourceFile, ParseSourceSpan, EMPTY_PARSE_LOCATION, EMPTY_SOURCE_SPAN, ParseErrorLevel, ParseError, typeSourceSpan, r3JitTypeSourceSpan, DomElementSchemaRegistry, CssSelector, SelectorMatcher, SelectorListContext, SelectorContext, HOST_ATTR, CONTENT_ATTR, StylesCompileDependency, CompiledStylesheet, StyleCompiler, TemplateParseError, TemplateParseResult, TemplateParser, splitClasses, createElementCssSelector, removeSummaryDuplicates, isEmptyExpression, compileInjectable, R3TargetBinder, R3BoundTarget */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "core", function() { return core; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompilerConfig", function() { return CompilerConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preserveWhitespacesDefault", function() { return preserveWhitespacesDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLoweredSymbol", function() { return isLoweredSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLoweredSymbol", function() { return createLoweredSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Identifiers", function() { return Identifiers; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitCompiler", function() { return JitCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConstantPool", function() { return ConstantPool; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveResolver", function() { return DirectiveResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PipeResolver", function() { return PipeResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgModuleResolver", function() { return NgModuleResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_INTERPOLATION_CONFIG", function() { return DEFAULT_INTERPOLATION_CONFIG; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InterpolationConfig", function() { return InterpolationConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgModuleCompiler", function() { return NgModuleCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayType", function() { return ArrayType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AssertNotNull", function() { return AssertNotNull; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DYNAMIC_TYPE", function() { return DYNAMIC_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BinaryOperator", function() { return BinaryOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BinaryOperatorExpr", function() { return BinaryOperatorExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinMethod", function() { return BuiltinMethod; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinType", function() { return BuiltinType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinTypeName", function() { return BuiltinTypeName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinVar", function() { return BuiltinVar; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CastExpr", function() { return CastExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassField", function() { return ClassField; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassMethod", function() { return ClassMethod; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassStmt", function() { return ClassStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommaExpr", function() { return CommaExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommentStmt", function() { return CommentStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConditionalExpr", function() { return ConditionalExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeclareFunctionStmt", function() { return DeclareFunctionStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeclareVarStmt", function() { return DeclareVarStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Expression", function() { return Expression; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpressionStatement", function() { return ExpressionStatement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpressionType", function() { return ExpressionType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExternalExpr", function() { return ExternalExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExternalReference", function() { return ExternalReference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "literalMap", function() { return literalMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FunctionExpr", function() { return FunctionExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IfStmt", function() { return IfStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InstantiateExpr", function() { return InstantiateExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InvokeFunctionExpr", function() { return InvokeFunctionExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InvokeMethodExpr", function() { return InvokeMethodExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JSDocCommentStmt", function() { return JSDocCommentStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralArrayExpr", function() { return LiteralArrayExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralExpr", function() { return LiteralExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralMapExpr", function() { return LiteralMapExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapType", function() { return MapType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NotExpr", function() { return NotExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadKeyExpr", function() { return ReadKeyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadPropExpr", function() { return ReadPropExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadVarExpr", function() { return ReadVarExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReturnStatement", function() { return ReturnStatement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ThrowStmt", function() { return ThrowStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TryCatchStmt", function() { return TryCatchStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WrappedNodeExpr", function() { return WrappedNodeExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WriteKeyExpr", function() { return WriteKeyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WritePropExpr", function() { return WritePropExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WriteVarExpr", function() { return WriteVarExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StmtModifier", function() { return StmtModifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Statement", function() { return Statement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "STRING_TYPE", function() { return STRING_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TypeofExpr", function() { return TypeofExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "collectExternalReferences", function() { return collectExternalReferences; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmitterVisitorContext", function() { return EmitterVisitorContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitEvaluator", function() { return JitEvaluator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewCompiler", function() { return ViewCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findStaticQueryIds", function() { return findStaticQueryIds; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "staticViewQueryIds", function() { return staticViewQueryIds; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getParseErrors", function() { return getParseErrors; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isSyntaxError", function() { return isSyntaxError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Version", function() { return Version; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundAttribute", function() { return BoundAttribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundEvent", function() { return BoundEvent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundText", function() { return BoundText; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstContent", function() { return Content; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstElement", function() { return Element; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstRecursiveVisitor", function() { return RecursiveVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstReference", function() { return Reference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstTemplate", function() { return Template; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstText", function() { return Text; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstTextAttribute", function() { return TextAttribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstVariable", function() { return Variable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3Identifiers", function() { return Identifiers$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3ResolvedDependencyType", function() { return R3ResolvedDependencyType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileInjector", function() { return compileInjector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileNgModule", function() { return compileNgModule; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compilePipeFromMetadata", function() { return compilePipeFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "makeBindingParser", function() { return makeBindingParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseTemplate", function() { return parseTemplate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileBaseDefFromMetadata", function() { return compileBaseDefFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileComponentFromMetadata", function() { return compileComponentFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileDirectiveFromMetadata", function() { return compileDirectiveFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseHostBindings", function() { return parseHostBindings; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "verifyHostBindings", function() { return verifyHostBindings; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishFacade", function() { return publishFacade; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextAst", function() { return TextAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundTextAst", function() { return BoundTextAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AttrAst", function() { return AttrAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundElementPropertyAst", function() { return BoundElementPropertyAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundEventAst", function() { return BoundEventAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReferenceAst", function() { return ReferenceAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VariableAst", function() { return VariableAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementAst", function() { return ElementAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmbeddedTemplateAst", function() { return EmbeddedTemplateAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundDirectivePropertyAst", function() { return BoundDirectivePropertyAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveAst", function() { return DirectiveAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderAst", function() { return ProviderAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderAstType", function() { return ProviderAstType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgContentAst", function() { return NgContentAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NullTemplateVisitor", function() { return NullTemplateVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveTemplateAstVisitor", function() { return RecursiveTemplateAstVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateVisitAll", function() { return templateVisitAll; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sanitizeIdentifier", function() { return sanitizeIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifierName", function() { return identifierName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifierModuleUrl", function() { return identifierModuleUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "viewClassName", function() { return viewClassName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rendererTypeName", function() { return rendererTypeName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hostViewClassName", function() { return hostViewClassName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "componentFactoryName", function() { return componentFactoryName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileSummaryKind", function() { return CompileSummaryKind; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tokenName", function() { return tokenName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tokenReference", function() { return tokenReference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileStylesheetMetadata", function() { return CompileStylesheetMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileTemplateMetadata", function() { return CompileTemplateMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileDirectiveMetadata", function() { return CompileDirectiveMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompilePipeMetadata", function() { return CompilePipeMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileShallowModuleMetadata", function() { return CompileShallowModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileNgModuleMetadata", function() { return CompileNgModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TransitiveCompileNgModuleMetadata", function() { return TransitiveCompileNgModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderMeta", function() { return ProviderMeta; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "flatten", function() { return flatten; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateSourceUrl", function() { return templateSourceUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sharedStylesheetJitUrl", function() { return sharedStylesheetJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ngModuleJitUrl", function() { return ngModuleJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateJitUrl", function() { return templateJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createAotUrlResolver", function() { return createAotUrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createAotCompiler", function() { return createAotCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AotCompiler", function() { return AotCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeNgModules", function() { return analyzeNgModules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeAndValidateNgModules", function() { return analyzeAndValidateNgModules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeFile", function() { return analyzeFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeFileForInjectables", function() { return analyzeFileForInjectables; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAnalyzedFiles", function() { return mergeAnalyzedFiles; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GeneratedFile", function() { return GeneratedFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toTypeScript", function() { return toTypeScript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formattedError", function() { return formattedError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFormattedError", function() { return isFormattedError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticReflector", function() { return StaticReflector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbol", function() { return StaticSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbolCache", function() { return StaticSymbolCache; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ResolvedStaticSymbol", function() { return ResolvedStaticSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbolResolver", function() { return StaticSymbolResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unescapeIdentifier", function() { return unescapeIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unwrapResolvedMetadata", function() { return unwrapResolvedMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AotSummaryResolver", function() { return AotSummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstPath", function() { return AstPath; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SummaryResolver", function() { return SummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitSummaryResolver", function() { return JitSummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileReflector", function() { return CompileReflector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createUrlResolverWithoutPackagePrefix", function() { return createUrlResolverWithoutPackagePrefix; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createOfflineCompileUrlResolver", function() { return createOfflineCompileUrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UrlResolver", function() { return UrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getUrlScheme", function() { return getUrlScheme; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ResourceLoader", function() { return ResourceLoader; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementSchemaRegistry", function() { return ElementSchemaRegistry; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Extractor", function() { return Extractor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18NHtmlParser", function() { return I18NHtmlParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MessageBundle", function() { return MessageBundle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Serializer", function() { return Serializer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xliff", function() { return Xliff; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xliff2", function() { return Xliff2; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xmb", function() { return Xmb; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xtb", function() { return Xtb; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveNormalizer", function() { return DirectiveNormalizer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParserError", function() { return ParserError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSpan", function() { return ParseSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AST", function() { return AST; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Quote", function() { return Quote; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyExpr", function() { return EmptyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ImplicitReceiver", function() { return ImplicitReceiver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Chain", function() { return Chain; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Conditional", function() { return Conditional; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PropertyRead", function() { return PropertyRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PropertyWrite", function() { return PropertyWrite; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafePropertyRead", function() { return SafePropertyRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyedRead", function() { return KeyedRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyedWrite", function() { return KeyedWrite; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BindingPipe", function() { return BindingPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralPrimitive", function() { return LiteralPrimitive; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralArray", function() { return LiteralArray; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralMap", function() { return LiteralMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interpolation", function() { return Interpolation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Binary", function() { return Binary; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PrefixNot", function() { return PrefixNot; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NonNullAssert", function() { return NonNullAssert; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MethodCall", function() { return MethodCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafeMethodCall", function() { return SafeMethodCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FunctionCall", function() { return FunctionCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbsoluteSourceSpan", function() { return AbsoluteSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ASTWithSource", function() { return ASTWithSource; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateBinding", function() { return TemplateBinding; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NullAstVisitor", function() { return NullAstVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveAstVisitor", function() { return RecursiveAstVisitor$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstTransformer", function() { return AstTransformer$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstMemoryEfficientTransformer", function() { return AstMemoryEfficientTransformer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visitAstChildren", function() { return visitAstChildren; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedProperty", function() { return ParsedProperty; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedPropertyType", function() { return ParsedPropertyType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedEvent", function() { return ParsedEvent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedVariable", function() { return ParsedVariable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundElementProperty", function() { return BoundElementProperty; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TokenType", function() { return TokenType$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Lexer", function() { return Lexer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EOF", function() { return EOF; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIdentifier", function() { return isIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isQuote", function() { return isQuote; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SplitInterpolation", function() { return SplitInterpolation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateBindingParseResult", function() { return TemplateBindingParseResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Parser", function() { return Parser$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_ParseAST", function() { return _ParseAST; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ERROR_COMPONENT_TYPE", function() { return ERROR_COMPONENT_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileMetadataResolver", function() { return CompileMetadataResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Text", function() { return Text$3; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Expansion", function() { return Expansion; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpansionCase", function() { return ExpansionCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Attribute", function() { return Attribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Element", function() { return Element$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Comment", function() { return Comment; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visitAll", function() { return visitAll$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveVisitor", function() { return RecursiveVisitor$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNode", function() { return findNode; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HtmlParser", function() { return HtmlParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseTreeResult", function() { return ParseTreeResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TreeError", function() { return TreeError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HtmlTagDefinition", function() { return HtmlTagDefinition; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHtmlTagDefinition", function() { return getHtmlTagDefinition; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TagContentType", function() { return TagContentType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "splitNsName", function() { return splitNsName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgContainer", function() { return isNgContainer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgContent", function() { return isNgContent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgTemplate", function() { return isNgTemplate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNsPrefix", function() { return getNsPrefix; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeNsAndName", function() { return mergeNsAndName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NAMED_ENTITIES", function() { return NAMED_ENTITIES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NGSP_UNICODE", function() { return NGSP_UNICODE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debugOutputAstAsTypeScript", function() { return debugOutputAstAsTypeScript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TypeScriptEmitter", function() { return TypeScriptEmitter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseLocation", function() { return ParseLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSourceFile", function() { return ParseSourceFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSourceSpan", function() { return ParseSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY_PARSE_LOCATION", function() { return EMPTY_PARSE_LOCATION; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY_SOURCE_SPAN", function() { return EMPTY_SOURCE_SPAN; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseErrorLevel", function() { return ParseErrorLevel; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseError", function() { return ParseError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "typeSourceSpan", function() { return typeSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "r3JitTypeSourceSpan", function() { return r3JitTypeSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DomElementSchemaRegistry", function() { return DomElementSchemaRegistry; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CssSelector", function() { return CssSelector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorMatcher", function() { return SelectorMatcher; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorListContext", function() { return SelectorListContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorContext", function() { return SelectorContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HOST_ATTR", function() { return HOST_ATTR; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CONTENT_ATTR", function() { return CONTENT_ATTR; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StylesCompileDependency", function() { return StylesCompileDependency; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompiledStylesheet", function() { return CompiledStylesheet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StyleCompiler", function() { return StyleCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParseError", function() { return TemplateParseError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParseResult", function() { return TemplateParseResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParser", function() { return TemplateParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "splitClasses", function() { return splitClasses; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createElementCssSelector", function() { return createElementCssSelector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeSummaryDuplicates", function() { return removeSummaryDuplicates; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmptyExpression", function() { return isEmptyExpression; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileInjectable", function() { return compileInjectable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3TargetBinder", function() { return R3TargetBinder; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3BoundTarget", function() { return R3BoundTarget; });
/**
* @license Angular v8.2.14
* (c) 2010-2019 Google LLC. 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)];
}
// `` tags work the same regardless the namespace
function isNgContainer(tagName) {
return splitNsName(tagName)[1] === 'ng-container';
}
// `` tags work the same regardless the namespace
function isNgContent(tagName) {
return splitNsName(tagName)[1] === 'ng-content';
}
// `` 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 `{` / `ƫ` 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, 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;
this.implicitNamespacePrefix = implicitNamespacePrefix || null;
this.contentType = contentType;
this.ignoreFirstLf = ignoreFirstLf;
}
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'], closedByParent: true }),
'td': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }),
'th': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }),
'col': new HtmlTagDefinition({ 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) {
// This must be declared as a function, not a fat arrow, so that ES2015 devmode produces code
// that works with the static_reflector.ts in the ViewEngine compiler.
// In particular, `_registerDecoratorOrConstructor` assumes that the value returned here can be
// new'ed.
function 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) {
return selector ? CssSelector.parse(selector).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
*/
//// Types
var TypeModifier;
(function (TypeModifier) {
TypeModifier[TypeModifier["Const"] = 0] = "Const";
})(TypeModifier || (TypeModifier = {}));
class Type$1 {
constructor(modifiers = null) {
this.modifiers = modifiers;
if (!modifiers) {
this.modifiers = [];
}
}
hasModifier(modifier) { return this.modifiers.indexOf(modifier) !== -1; }
}
var BuiltinTypeName;
(function (BuiltinTypeName) {
BuiltinTypeName[BuiltinTypeName["Dynamic"] = 0] = "Dynamic";
BuiltinTypeName[BuiltinTypeName["Bool"] = 1] = "Bool";
BuiltinTypeName[BuiltinTypeName["String"] = 2] = "String";
BuiltinTypeName[BuiltinTypeName["Int"] = 3] = "Int";
BuiltinTypeName[BuiltinTypeName["Number"] = 4] = "Number";
BuiltinTypeName[BuiltinTypeName["Function"] = 5] = "Function";
BuiltinTypeName[BuiltinTypeName["Inferred"] = 6] = "Inferred";
BuiltinTypeName[BuiltinTypeName["None"] = 7] = "None";
})(BuiltinTypeName || (BuiltinTypeName = {}));
class BuiltinType extends Type$1 {
constructor(name, modifiers = null) {
super(modifiers);
this.name = name;
}
visitType(visitor, context) {
return visitor.visitBuiltinType(this, context);
}
}
class ExpressionType extends Type$1 {
constructor(value, modifiers = null, typeParams = null) {
super(modifiers);
this.value = value;
this.typeParams = typeParams;
}
visitType(visitor, context) {
return visitor.visitExpressionType(this, context);
}
}
class ArrayType extends Type$1 {
constructor(of, modifiers = null) {
super(modifiers);
this.of = of;
}
visitType(visitor, context) {
return visitor.visitArrayType(this, context);
}
}
class MapType extends Type$1 {
constructor(valueType, modifiers = null) {
super(modifiers);
this.valueType = valueType || null;
}
visitType(visitor, context) { return visitor.visitMapType(this, context); }
}
const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);
const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
const NONE_TYPE = new BuiltinType(BuiltinTypeName.None);
///// Expressions
var BinaryOperator;
(function (BinaryOperator) {
BinaryOperator[BinaryOperator["Equals"] = 0] = "Equals";
BinaryOperator[BinaryOperator["NotEquals"] = 1] = "NotEquals";
BinaryOperator[BinaryOperator["Identical"] = 2] = "Identical";
BinaryOperator[BinaryOperator["NotIdentical"] = 3] = "NotIdentical";
BinaryOperator[BinaryOperator["Minus"] = 4] = "Minus";
BinaryOperator[BinaryOperator["Plus"] = 5] = "Plus";
BinaryOperator[BinaryOperator["Divide"] = 6] = "Divide";
BinaryOperator[BinaryOperator["Multiply"] = 7] = "Multiply";
BinaryOperator[BinaryOperator["Modulo"] = 8] = "Modulo";
BinaryOperator[BinaryOperator["And"] = 9] = "And";
BinaryOperator[BinaryOperator["Or"] = 10] = "Or";
BinaryOperator[BinaryOperator["BitwiseAnd"] = 11] = "BitwiseAnd";
BinaryOperator[BinaryOperator["Lower"] = 12] = "Lower";
BinaryOperator[BinaryOperator["LowerEquals"] = 13] = "LowerEquals";
BinaryOperator[BinaryOperator["Bigger"] = 14] = "Bigger";
BinaryOperator[BinaryOperator["BiggerEquals"] = 15] = "BiggerEquals";
})(BinaryOperator || (BinaryOperator = {}));
function nullSafeIsEquivalent(base, other) {
if (base == null || other == null) {
return base == other;
}
return base.isEquivalent(other);
}
function areAllEquivalent(base, other) {
const len = base.length;
if (len !== other.length) {
return false;
}
for (let i = 0; i < len; i++) {
if (!base[i].isEquivalent(other[i])) {
return false;
}
}
return true;
}
class Expression {
constructor(type, sourceSpan) {
this.type = type || null;
this.sourceSpan = sourceSpan || null;
}
prop(name, sourceSpan) {
return new ReadPropExpr(this, name, null, sourceSpan);
}
key(index, type, sourceSpan) {
return new ReadKeyExpr(this, index, type, sourceSpan);
}
callMethod(name, params, sourceSpan) {
return new InvokeMethodExpr(this, name, params, null, sourceSpan);
}
callFn(params, sourceSpan) {
return new InvokeFunctionExpr(this, params, null, sourceSpan);
}
instantiate(params, type, sourceSpan) {
return new InstantiateExpr(this, params, type, sourceSpan);
}
conditional(trueCase, falseCase = null, sourceSpan) {
return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);
}
equals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);
}
notEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);
}
identical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);
}
notIdentical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);
}
minus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);
}
plus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);
}
divide(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);
}
multiply(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);
}
modulo(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);
}
and(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
}
bitwiseAnd(rhs, sourceSpan, parens = true) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens);
}
or(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);
}
lower(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);
}
lowerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);
}
bigger(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);
}
biggerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);
}
isBlank(sourceSpan) {
// Note: We use equals by purpose here to compare to null and undefined in JS.
// We use the typed null to allow strictNullChecks to narrow types.
return this.equals(TYPED_NULL_EXPR, sourceSpan);
}
cast(type, sourceSpan) {
return new CastExpr(this, type, sourceSpan);
}
toStmt() { return new ExpressionStatement(this, null); }
}
var BuiltinVar;
(function (BuiltinVar) {
BuiltinVar[BuiltinVar["This"] = 0] = "This";
BuiltinVar[BuiltinVar["Super"] = 1] = "Super";
BuiltinVar[BuiltinVar["CatchError"] = 2] = "CatchError";
BuiltinVar[BuiltinVar["CatchStack"] = 3] = "CatchStack";
})(BuiltinVar || (BuiltinVar = {}));
class ReadVarExpr extends Expression {
constructor(name, type, sourceSpan) {
super(type, sourceSpan);
if (typeof name === 'string') {
this.name = name;
this.builtin = null;
}
else {
this.name = null;
this.builtin = name;
}
}
isEquivalent(e) {
return e instanceof ReadVarExpr && this.name === e.name && this.builtin === e.builtin;
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitReadVarExpr(this, context);
}
set(value) {
if (!this.name) {
throw new Error(`Built in variable ${this.builtin} can not be assigned to.`);
}
return new WriteVarExpr(this.name, value, null, this.sourceSpan);
}
}
class TypeofExpr extends Expression {
constructor(expr, type, sourceSpan) {
super(type, sourceSpan);
this.expr = expr;
}
visitExpression(visitor, context) {
return visitor.visitTypeofExpr(this, context);
}
isEquivalent(e) {
return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);
}
isConstant() { return this.expr.isConstant(); }
}
class WrappedNodeExpr extends Expression {
constructor(node, type, sourceSpan) {
super(type, sourceSpan);
this.node = node;
}
isEquivalent(e) {
return e instanceof WrappedNodeExpr && this.node === e.node;
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitWrappedNodeExpr(this, context);
}
}
class WriteVarExpr extends Expression {
constructor(name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.name = name;
this.value = value;
}
isEquivalent(e) {
return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitWriteVarExpr(this, context);
}
toDeclStmt(type, modifiers) {
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
}
toConstDecl() { return this.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]); }
}
class WriteKeyExpr extends Expression {
constructor(receiver, index, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.index = index;
this.value = value;
}
isEquivalent(e) {
return e instanceof WriteKeyExpr && this.receiver.isEquivalent(e.receiver) &&
this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitWriteKeyExpr(this, context);
}
}
class WritePropExpr extends Expression {
constructor(receiver, name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.name = name;
this.value = value;
}
isEquivalent(e) {
return e instanceof WritePropExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name && this.value.isEquivalent(e.value);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitWritePropExpr(this, context);
}
}
var BuiltinMethod;
(function (BuiltinMethod) {
BuiltinMethod[BuiltinMethod["ConcatArray"] = 0] = "ConcatArray";
BuiltinMethod[BuiltinMethod["SubscribeObservable"] = 1] = "SubscribeObservable";
BuiltinMethod[BuiltinMethod["Bind"] = 2] = "Bind";
})(BuiltinMethod || (BuiltinMethod = {}));
class InvokeMethodExpr extends Expression {
constructor(receiver, method, args, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.args = args;
if (typeof method === 'string') {
this.name = method;
this.builtin = null;
}
else {
this.name = null;
this.builtin = method;
}
}
isEquivalent(e) {
return e instanceof InvokeMethodExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name && this.builtin === e.builtin && areAllEquivalent(this.args, e.args);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitInvokeMethodExpr(this, context);
}
}
class InvokeFunctionExpr extends Expression {
constructor(fn, args, type, sourceSpan, pure = false) {
super(type, sourceSpan);
this.fn = fn;
this.args = args;
this.pure = pure;
}
isEquivalent(e) {
return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) &&
areAllEquivalent(this.args, e.args) && this.pure === e.pure;
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitInvokeFunctionExpr(this, context);
}
}
class InstantiateExpr extends Expression {
constructor(classExpr, args, type, sourceSpan) {
super(type, sourceSpan);
this.classExpr = classExpr;
this.args = args;
}
isEquivalent(e) {
return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) &&
areAllEquivalent(this.args, e.args);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitInstantiateExpr(this, context);
}
}
class LiteralExpr extends Expression {
constructor(value, type, sourceSpan) {
super(type, sourceSpan);
this.value = value;
}
isEquivalent(e) {
return e instanceof LiteralExpr && this.value === e.value;
}
isConstant() { return true; }
visitExpression(visitor, context) {
return visitor.visitLiteralExpr(this, context);
}
}
class ExternalExpr extends Expression {
constructor(value, type, typeParams = null, sourceSpan) {
super(type, sourceSpan);
this.value = value;
this.typeParams = typeParams;
}
isEquivalent(e) {
return e instanceof ExternalExpr && this.value.name === e.value.name &&
this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime;
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitExternalExpr(this, context);
}
}
class ExternalReference {
constructor(moduleName, name, runtime) {
this.moduleName = moduleName;
this.name = name;
this.runtime = runtime;
}
}
class ConditionalExpr extends Expression {
constructor(condition, trueCase, falseCase = null, type, sourceSpan) {
super(type || trueCase.type, sourceSpan);
this.condition = condition;
this.falseCase = falseCase;
this.trueCase = trueCase;
}
isEquivalent(e) {
return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) &&
this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitConditionalExpr(this, context);
}
}
class NotExpr extends Expression {
constructor(condition, sourceSpan) {
super(BOOL_TYPE, sourceSpan);
this.condition = condition;
}
isEquivalent(e) {
return e instanceof NotExpr && this.condition.isEquivalent(e.condition);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitNotExpr(this, context);
}
}
class AssertNotNull extends Expression {
constructor(condition, sourceSpan) {
super(condition.type, sourceSpan);
this.condition = condition;
}
isEquivalent(e) {
return e instanceof AssertNotNull && this.condition.isEquivalent(e.condition);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitAssertNotNullExpr(this, context);
}
}
class CastExpr extends Expression {
constructor(value, type, sourceSpan) {
super(type, sourceSpan);
this.value = value;
}
isEquivalent(e) {
return e instanceof CastExpr && this.value.isEquivalent(e.value);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitCastExpr(this, context);
}
}
class FnParam {
constructor(name, type = null) {
this.name = name;
this.type = type;
}
isEquivalent(param) { return this.name === param.name; }
}
class FunctionExpr extends Expression {
constructor(params, statements, type, sourceSpan, name) {
super(type, sourceSpan);
this.params = params;
this.statements = statements;
this.name = name;
}
isEquivalent(e) {
return e instanceof FunctionExpr && areAllEquivalent(this.params, e.params) &&
areAllEquivalent(this.statements, e.statements);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitFunctionExpr(this, context);
}
toDeclStmt(name, modifiers = null) {
return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
}
}
class BinaryOperatorExpr extends Expression {
constructor(operator, lhs, rhs, type, sourceSpan, parens = true) {
super(type || lhs.type, sourceSpan);
this.operator = operator;
this.rhs = rhs;
this.parens = parens;
this.lhs = lhs;
}
isEquivalent(e) {
return e instanceof BinaryOperatorExpr && this.operator === e.operator &&
this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitBinaryOperatorExpr(this, context);
}
}
class ReadPropExpr extends Expression {
constructor(receiver, name, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.name = name;
}
isEquivalent(e) {
return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name;
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitReadPropExpr(this, context);
}
set(value) {
return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan);
}
}
class ReadKeyExpr extends Expression {
constructor(receiver, index, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.index = index;
}
isEquivalent(e) {
return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) &&
this.index.isEquivalent(e.index);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitReadKeyExpr(this, context);
}
set(value) {
return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);
}
}
class LiteralArrayExpr extends Expression {
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
}
isConstant() { return this.entries.every(e => e.isConstant()); }
isEquivalent(e) {
return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);
}
visitExpression(visitor, context) {
return visitor.visitLiteralArrayExpr(this, context);
}
}
class LiteralMapEntry {
constructor(key, value, quoted) {
this.key = key;
this.value = value;
this.quoted = quoted;
}
isEquivalent(e) {
return this.key === e.key && this.value.isEquivalent(e.value);
}
}
class LiteralMapExpr extends Expression {
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
this.valueType = null;
if (type) {
this.valueType = type.valueType;
}
}
isEquivalent(e) {
return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);
}
isConstant() { return this.entries.every(e => e.value.isConstant()); }
visitExpression(visitor, context) {
return visitor.visitLiteralMapExpr(this, context);
}
}
class CommaExpr extends Expression {
constructor(parts, sourceSpan) {
super(parts[parts.length - 1].type, sourceSpan);
this.parts = parts;
}
isEquivalent(e) {
return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);
}
isConstant() { return false; }
visitExpression(visitor, context) {
return visitor.visitCommaExpr(this, context);
}
}
const THIS_EXPR = new ReadVarExpr(BuiltinVar.This, null, null);
const SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super, null, null);
const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError, null, null);
const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack, null, null);
const NULL_EXPR = new LiteralExpr(null, null, null);
const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
//// Statements
var StmtModifier;
(function (StmtModifier) {
StmtModifier[StmtModifier["Final"] = 0] = "Final";
StmtModifier[StmtModifier["Private"] = 1] = "Private";
StmtModifier[StmtModifier["Exported"] = 2] = "Exported";
StmtModifier[StmtModifier["Static"] = 3] = "Static";
})(StmtModifier || (StmtModifier = {}));
class Statement {
constructor(modifiers, sourceSpan) {
this.modifiers = modifiers || [];
this.sourceSpan = sourceSpan || null;
}
hasModifier(modifier) { return this.modifiers.indexOf(modifier) !== -1; }
}
class DeclareVarStmt extends Statement {
constructor(name, value, type, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.value = value;
this.type = type || (value && value.type) || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareVarStmt && this.name === stmt.name &&
(this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitDeclareVarStmt(this, context);
}
}
class DeclareFunctionStmt extends Statement {
constructor(name, params, statements, type, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.params = params;
this.statements = statements;
this.type = type || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) &&
areAllEquivalent(this.statements, stmt.statements);
}
visitStatement(visitor, context) {
return visitor.visitDeclareFunctionStmt(this, context);
}
}
class ExpressionStatement extends Statement {
constructor(expr, sourceSpan) {
super(null, sourceSpan);
this.expr = expr;
}
isEquivalent(stmt) {
return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr);
}
visitStatement(visitor, context) {
return visitor.visitExpressionStmt(this, context);
}
}
class ReturnStatement extends Statement {
constructor(value, sourceSpan) {
super(null, sourceSpan);
this.value = value;
}
isEquivalent(stmt) {
return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitReturnStmt(this, context);
}
}
class AbstractClassPart {
constructor(type, modifiers) {
this.modifiers = modifiers;
if (!modifiers) {
this.modifiers = [];
}
this.type = type || null;
}
hasModifier(modifier) { return this.modifiers.indexOf(modifier) !== -1; }
}
class ClassField extends AbstractClassPart {
constructor(name, type, modifiers = null, initializer) {
super(type, modifiers);
this.name = name;
this.initializer = initializer;
}
isEquivalent(f) { return this.name === f.name; }
}
class ClassMethod extends AbstractClassPart {
constructor(name, params, body, type, modifiers = null) {
super(type, modifiers);
this.name = name;
this.params = params;
this.body = body;
}
isEquivalent(m) {
return this.name === m.name && areAllEquivalent(this.body, m.body);
}
}
class ClassGetter extends AbstractClassPart {
constructor(name, body, type, modifiers = null) {
super(type, modifiers);
this.name = name;
this.body = body;
}
isEquivalent(m) {
return this.name === m.name && areAllEquivalent(this.body, m.body);
}
}
class ClassStmt extends Statement {
constructor(name, parent, fields, getters, constructorMethod, methods, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.parent = parent;
this.fields = fields;
this.getters = getters;
this.constructorMethod = constructorMethod;
this.methods = methods;
}
isEquivalent(stmt) {
return stmt instanceof ClassStmt && this.name === stmt.name &&
nullSafeIsEquivalent(this.parent, stmt.parent) &&
areAllEquivalent(this.fields, stmt.fields) &&
areAllEquivalent(this.getters, stmt.getters) &&
this.constructorMethod.isEquivalent(stmt.constructorMethod) &&
areAllEquivalent(this.methods, stmt.methods);
}
visitStatement(visitor, context) {
return visitor.visitDeclareClassStmt(this, context);
}
}
class IfStmt extends Statement {
constructor(condition, trueCase, falseCase = [], sourceSpan) {
super(null, sourceSpan);
this.condition = condition;
this.trueCase = trueCase;
this.falseCase = falseCase;
}
isEquivalent(stmt) {
return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) &&
areAllEquivalent(this.trueCase, stmt.trueCase) &&
areAllEquivalent(this.falseCase, stmt.falseCase);
}
visitStatement(visitor, context) {
return visitor.visitIfStmt(this, context);
}
}
class CommentStmt extends Statement {
constructor(comment, multiline = false, sourceSpan) {
super(null, sourceSpan);
this.comment = comment;
this.multiline = multiline;
}
isEquivalent(stmt) { return stmt instanceof CommentStmt; }
visitStatement(visitor, context) {
return visitor.visitCommentStmt(this, context);
}
}
class JSDocCommentStmt extends Statement {
constructor(tags = [], sourceSpan) {
super(null, sourceSpan);
this.tags = tags;
}
isEquivalent(stmt) {
return stmt instanceof JSDocCommentStmt && this.toString() === stmt.toString();
}
visitStatement(visitor, context) {
return visitor.visitJSDocCommentStmt(this, context);
}
toString() { return serializeTags(this.tags); }
}
class TryCatchStmt extends Statement {
constructor(bodyStmts, catchStmts, sourceSpan) {
super(null, sourceSpan);
this.bodyStmts = bodyStmts;
this.catchStmts = catchStmts;
}
isEquivalent(stmt) {
return stmt instanceof TryCatchStmt && areAllEquivalent(this.bodyStmts, stmt.bodyStmts) &&
areAllEquivalent(this.catchStmts, stmt.catchStmts);
}
visitStatement(visitor, context) {
return visitor.visitTryCatchStmt(this, context);
}
}
class ThrowStmt extends Statement {
constructor(error, sourceSpan) {
super(null, sourceSpan);
this.error = error;
}
isEquivalent(stmt) {
return stmt instanceof TryCatchStmt && this.error.isEquivalent(stmt.error);
}
visitStatement(visitor, context) {
return visitor.visitThrowStmt(this, context);
}
}
class AstTransformer {
transformExpr(expr, context) { return expr; }
transformStmt(stmt, context) { return stmt; }
visitReadVarExpr(ast, context) { return this.transformExpr(ast, context); }
visitWrappedNodeExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitTypeofExpr(expr, context) {
return this.transformExpr(new TypeofExpr(expr.expr.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWriteVarExpr(expr, context) {
return this.transformExpr(new WriteVarExpr(expr.name, expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWriteKeyExpr(expr, context) {
return this.transformExpr(new WriteKeyExpr(expr.receiver.visitExpression(this, context), expr.index.visitExpression(this, context), expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWritePropExpr(expr, context) {
return this.transformExpr(new WritePropExpr(expr.receiver.visitExpression(this, context), expr.name, expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitInvokeMethodExpr(ast, context) {
const method = ast.builtin || ast.name;
return this.transformExpr(new InvokeMethodExpr(ast.receiver.visitExpression(this, context), method, this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitInvokeFunctionExpr(ast, context) {
return this.transformExpr(new InvokeFunctionExpr(ast.fn.visitExpression(this, context), this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitInstantiateExpr(ast, context) {
return this.transformExpr(new InstantiateExpr(ast.classExpr.visitExpression(this, context), this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitLiteralExpr(ast, context) { return this.transformExpr(ast, context); }
visitExternalExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitConditionalExpr(ast, context) {
return this.transformExpr(new ConditionalExpr(ast.condition.visitExpression(this, context), ast.trueCase.visitExpression(this, context), ast.falseCase.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitNotExpr(ast, context) {
return this.transformExpr(new NotExpr(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
}
visitAssertNotNullExpr(ast, context) {
return this.transformExpr(new AssertNotNull(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
}
visitCastExpr(ast, context) {
return this.transformExpr(new CastExpr(ast.value.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitFunctionExpr(ast, context) {
return this.transformExpr(new FunctionExpr(ast.params, this.visitAllStatements(ast.statements, context), ast.type, ast.sourceSpan), context);
}
visitBinaryOperatorExpr(ast, context) {
return this.transformExpr(new BinaryOperatorExpr(ast.operator, ast.lhs.visitExpression(this, context), ast.rhs.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitReadPropExpr(ast, context) {
return this.transformExpr(new ReadPropExpr(ast.receiver.visitExpression(this, context), ast.name, ast.type, ast.sourceSpan), context);
}
visitReadKeyExpr(ast, context) {
return this.transformExpr(new ReadKeyExpr(ast.receiver.visitExpression(this, context), ast.index.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitLiteralArrayExpr(ast, context) {
return this.transformExpr(new LiteralArrayExpr(this.visitAllExpressions(ast.entries, context), ast.type, ast.sourceSpan), context);
}
visitLiteralMapExpr(ast, context) {
const entries = ast.entries.map((entry) => new LiteralMapEntry(entry.key, entry.value.visitExpression(this, context), entry.quoted));
const mapType = new MapType(ast.valueType, null);
return this.transformExpr(new LiteralMapExpr(entries, mapType, ast.sourceSpan), context);
}
visitCommaExpr(ast, context) {
return this.transformExpr(new CommaExpr(this.visitAllExpressions(ast.parts, context), ast.sourceSpan), context);
}
visitAllExpressions(exprs, context) {
return exprs.map(expr => expr.visitExpression(this, context));
}
visitDeclareVarStmt(stmt, context) {
const value = stmt.value && stmt.value.visitExpression(this, context);
return this.transformStmt(new DeclareVarStmt(stmt.name, value, stmt.type, stmt.modifiers, stmt.sourceSpan), context);
}
visitDeclareFunctionStmt(stmt, context) {
return this.transformStmt(new DeclareFunctionStmt(stmt.name, stmt.params, this.visitAllStatements(stmt.statements, context), stmt.type, stmt.modifiers, stmt.sourceSpan), context);
}
visitExpressionStmt(stmt, context) {
return this.transformStmt(new ExpressionStatement(stmt.expr.visitExpression(this, context), stmt.sourceSpan), context);
}
visitReturnStmt(stmt, context) {
return this.transformStmt(new ReturnStatement(stmt.value.visitExpression(this, context), stmt.sourceSpan), context);
}
visitDeclareClassStmt(stmt, context) {
const parent = stmt.parent.visitExpression(this, context);
const getters = stmt.getters.map(getter => new ClassGetter(getter.name, this.visitAllStatements(getter.body, context), getter.type, getter.modifiers));
const ctorMethod = stmt.constructorMethod &&
new ClassMethod(stmt.constructorMethod.name, stmt.constructorMethod.params, this.visitAllStatements(stmt.constructorMethod.body, context), stmt.constructorMethod.type, stmt.constructorMethod.modifiers);
const methods = stmt.methods.map(method => new ClassMethod(method.name, method.params, this.visitAllStatements(method.body, context), method.type, method.modifiers));
return this.transformStmt(new ClassStmt(stmt.name, parent, stmt.fields, getters, ctorMethod, methods, stmt.modifiers, stmt.sourceSpan), context);
}
visitIfStmt(stmt, context) {
return this.transformStmt(new IfStmt(stmt.condition.visitExpression(this, context), this.visitAllStatements(stmt.trueCase, context), this.visitAllStatements(stmt.falseCase, context), stmt.sourceSpan), context);
}
visitTryCatchStmt(stmt, context) {
return this.transformStmt(new TryCatchStmt(this.visitAllStatements(stmt.bodyStmts, context), this.visitAllStatements(stmt.catchStmts, context), stmt.sourceSpan), context);
}
visitThrowStmt(stmt, context) {
return this.transformStmt(new ThrowStmt(stmt.error.visitExpression(this, context), stmt.sourceSpan), context);
}
visitCommentStmt(stmt, context) {
return this.transformStmt(stmt, context);
}
visitJSDocCommentStmt(stmt, context) {
return this.transformStmt(stmt, context);
}
visitAllStatements(stmts, context) {
return stmts.map(stmt => stmt.visitStatement(this, context));
}
}
class RecursiveAstVisitor {
visitType(ast, context) { return ast; }
visitExpression(ast, context) {
if (ast.type) {
ast.type.visitType(this, context);
}
return ast;
}
visitBuiltinType(type, context) { return this.visitType(type, context); }
visitExpressionType(type, context) {
type.value.visitExpression(this, context);
if (type.typeParams !== null) {
type.typeParams.forEach(param => this.visitType(param, context));
}
return this.visitType(type, context);
}
visitArrayType(type, context) { return this.visitType(type, context); }
visitMapType(type, context) { return this.visitType(type, context); }
visitWrappedNodeExpr(ast, context) { return ast; }
visitTypeofExpr(ast, context) { return this.visitExpression(ast, context); }
visitReadVarExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitWriteVarExpr(ast, context) {
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitWriteKeyExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.index.visitExpression(this, context);
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitWritePropExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitInvokeMethodExpr(ast, context) {
ast.receiver.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitInvokeFunctionExpr(ast, context) {
ast.fn.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitInstantiateExpr(ast, context) {
ast.classExpr.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitLiteralExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitExternalExpr(ast, context) {
if (ast.typeParams) {
ast.typeParams.forEach(type => type.visitType(this, context));
}
return this.visitExpression(ast, context);
}
visitConditionalExpr(ast, context) {
ast.condition.visitExpression(this, context);
ast.trueCase.visitExpression(this, context);
ast.falseCase.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitNotExpr(ast, context) {
ast.condition.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitAssertNotNullExpr(ast, context) {
ast.condition.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitCastExpr(ast, context) {
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitFunctionExpr(ast, context) {
this.visitAllStatements(ast.statements, context);
return this.visitExpression(ast, context);
}
visitBinaryOperatorExpr(ast, context) {
ast.lhs.visitExpression(this, context);
ast.rhs.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadPropExpr(ast, context) {
ast.receiver.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadKeyExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.index.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitLiteralArrayExpr(ast, context) {
this.visitAllExpressions(ast.entries, context);
return this.visitExpression(ast, context);
}
visitLiteralMapExpr(ast, context) {
ast.entries.forEach((entry) => entry.value.visitExpression(this, context));
return this.visitExpression(ast, context);
}
visitCommaExpr(ast, context) {
this.visitAllExpressions(ast.parts, context);
return this.visitExpression(ast, context);
}
visitAllExpressions(exprs, context) {
exprs.forEach(expr => expr.visitExpression(this, context));
}
visitDeclareVarStmt(stmt, context) {
if (stmt.value) {
stmt.value.visitExpression(this, context);
}
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitDeclareFunctionStmt(stmt, context) {
this.visitAllStatements(stmt.statements, context);
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitExpressionStmt(stmt, context) {
stmt.expr.visitExpression(this, context);
return stmt;
}
visitReturnStmt(stmt, context) {
stmt.value.visitExpression(this, context);
return stmt;
}
visitDeclareClassStmt(stmt, context) {
stmt.parent.visitExpression(this, context);
stmt.getters.forEach(getter => this.visitAllStatements(getter.body, context));
if (stmt.constructorMethod) {
this.visitAllStatements(stmt.constructorMethod.body, context);
}
stmt.methods.forEach(method => this.visitAllStatements(method.body, context));
return stmt;
}
visitIfStmt(stmt, context) {
stmt.condition.visitExpression(this, context);
this.visitAllStatements(stmt.trueCase, context);
this.visitAllStatements(stmt.falseCase, context);
return stmt;
}
visitTryCatchStmt(stmt, context) {
this.visitAllStatements(stmt.bodyStmts, context);
this.visitAllStatements(stmt.catchStmts, context);
return stmt;
}
visitThrowStmt(stmt, context) {
stmt.error.visitExpression(this, context);
return stmt;
}
visitCommentStmt(stmt, context) { return stmt; }
visitJSDocCommentStmt(stmt, context) { return stmt; }
visitAllStatements(stmts, context) {
stmts.forEach(stmt => stmt.visitStatement(this, context));
}
}
function findReadVarNames(stmts) {
const visitor = new _ReadVarVisitor();
visitor.visitAllStatements(stmts, null);
return visitor.varNames;
}
class _ReadVarVisitor extends RecursiveAstVisitor {
constructor() {
super(...arguments);
this.varNames = new Set();
}
visitDeclareFunctionStmt(stmt, context) {
// Don't descend into nested functions
return stmt;
}
visitDeclareClassStmt(stmt, context) {
// Don't descend into nested classes
return stmt;
}
visitReadVarExpr(ast, context) {
if (ast.name) {
this.varNames.add(ast.name);
}
return null;
}
}
function collectExternalReferences(stmts) {
const visitor = new _FindExternalReferencesVisitor();
visitor.visitAllStatements(stmts, null);
return visitor.externalReferences;
}
class _FindExternalReferencesVisitor extends RecursiveAstVisitor {
constructor() {
super(...arguments);
this.externalReferences = [];
}
visitExternalExpr(e, context) {
this.externalReferences.push(e.value);
return super.visitExternalExpr(e, context);
}
}
function applySourceSpanToStatementIfNeeded(stmt, sourceSpan) {
if (!sourceSpan) {
return stmt;
}
const transformer = new _ApplySourceSpanTransformer(sourceSpan);
return stmt.visitStatement(transformer, null);
}
function applySourceSpanToExpressionIfNeeded(expr, sourceSpan) {
if (!sourceSpan) {
return expr;
}
const transformer = new _ApplySourceSpanTransformer(sourceSpan);
return expr.visitExpression(transformer, null);
}
class _ApplySourceSpanTransformer extends AstTransformer {
constructor(sourceSpan) {
super();
this.sourceSpan = sourceSpan;
}
_clone(obj) {
const clone = Object.create(obj.constructor.prototype);
for (let prop of Object.keys(obj)) {
clone[prop] = obj[prop];
}
return clone;
}
transformExpr(expr, context) {
if (!expr.sourceSpan) {
expr = this._clone(expr);
expr.sourceSpan = this.sourceSpan;
}
return expr;
}
transformStmt(stmt, context) {
if (!stmt.sourceSpan) {
stmt = this._clone(stmt);
stmt.sourceSpan = this.sourceSpan;
}
return stmt;
}
}
function variable(name, type, sourceSpan) {
return new ReadVarExpr(name, type, sourceSpan);
}
function importExpr(id, typeParams = null, sourceSpan) {
return new ExternalExpr(id, null, typeParams, sourceSpan);
}
function importType(id, typeParams = null, typeModifiers = null) {
return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
}
function expressionType(expr, typeModifiers = null, typeParams = null) {
return new ExpressionType(expr, typeModifiers, typeParams);
}
function typeofExpr(expr) {
return new TypeofExpr(expr);
}
function literalArr(values, type, sourceSpan) {
return new LiteralArrayExpr(values, type, sourceSpan);
}
function literalMap(values, type = null) {
return new LiteralMapExpr(values.map(e => new LiteralMapEntry(e.key, e.value, e.quoted)), type, null);
}
function not(expr, sourceSpan) {
return new NotExpr(expr, sourceSpan);
}
function assertNotNull(expr, sourceSpan) {
return new AssertNotNull(expr, sourceSpan);
}
function fn(params, body, type, sourceSpan, name) {
return new FunctionExpr(params, body, type, sourceSpan, name);
}
function ifStmt(condition, thenClause, elseClause) {
return new IfStmt(condition, thenClause, elseClause);
}
function literal(value, type, sourceSpan) {
return new LiteralExpr(value, type, sourceSpan);
}
function isNull(exp) {
return exp instanceof LiteralExpr && exp.value === null;
}
/*
* Serializes a `Tag` into a string.
* Returns a string like " @foo {bar} baz" (note the leading whitespace before `@foo`).
*/
function tagToString(tag) {
let out = '';
if (tag.tagName) {
out += ` @${tag.tagName}`;
}
if (tag.text) {
if (tag.text.match(/\/\*|\*\//)) {
throw new Error('JSDoc text cannot contain "/*" and "*/"');
}
out += ' ' + tag.text.replace(/@/g, '\\@');
}
return out;
}
function serializeTags(tags) {
if (tags.length === 0)
return '';
let out = '*\n';
for (const tag of tags) {
out += ' *';
// If the tagToString is multi-line, insert " * " prefixes on subsequent lines.
out += tagToString(tag).replace(/\n/g, '\n * ');
out += '\n';
}
out += ' ';
return out;
}
/**
* @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}`;
}
if (!token.toString) {
return 'object';
}
// 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('.');
}
}
const __window = typeof window !== 'undefined' && window;
const __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
self instanceof WorkerGlobalScope && self;
const __global = typeof global !== 'undefined' && global;
// Check __global first, because in Node tests both __global and __window may be defined and _global
// should be __global in that case.
const _global = __global || __window || __self;
/**
* @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 CONSTANT_PREFIX = '_c';
/**
* Context to use when producing a key.
*
* This ensures we see the constant not the reference variable when producing
* a key.
*/
const KEY_CONTEXT = {};
/**
* A node that is a place-holder that allows the node to be replaced when the actual
* node is known.
*
* This allows the constant pool to change an expression from a direct reference to
* a constant to a shared constant. It returns a fix-up node that is later allowed to
* change the referenced expression.
*/
class FixupExpression extends Expression {
constructor(resolved) {
super(resolved.type);
this.resolved = resolved;
this.original = resolved;
}
visitExpression(visitor, context) {
if (context === KEY_CONTEXT) {
// When producing a key we want to traverse the constant not the
// variable used to refer to it.
return this.original.visitExpression(visitor, context);
}
else {
return this.resolved.visitExpression(visitor, context);
}
}
isEquivalent(e) {
return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
}
isConstant() { return true; }
fixup(expression) {
this.resolved = expression;
this.shared = true;
}
}
/**
* A constant pool allows a code emitter to share constant in an output context.
*
* The constant pool also supports sharing access to ivy definitions references.
*/
class ConstantPool {
constructor() {
this.statements = [];
this.literals = new Map();
this.literalFactories = new Map();
this.injectorDefinitions = new Map();
this.directiveDefinitions = new Map();
this.componentDefinitions = new Map();
this.pipeDefinitions = new Map();
this.nextNameIndex = 0;
}
getConstLiteral(literal, forceShared) {
if (literal instanceof LiteralExpr || literal instanceof FixupExpression) {
// Do no put simple literals into the constant pool or try to produce a constant for a
// reference to a constant.
return literal;
}
const key = this.keyOf(literal);
let fixup = this.literals.get(key);
let newValue = false;
if (!fixup) {
fixup = new FixupExpression(literal);
this.literals.set(key, fixup);
newValue = true;
}
if ((!newValue && !fixup.shared) || (newValue && forceShared)) {
// Replace the expression with a variable
const name = this.freshName();
this.statements.push(variable(name).set(literal).toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]));
fixup.fixup(variable(name));
}
return fixup;
}
getDefinition(type, kind, ctx, forceShared = false) {
const definitions = this.definitionsOf(kind);
let fixup = definitions.get(type);
let newValue = false;
if (!fixup) {
const property = this.propertyNameOf(kind);
fixup = new FixupExpression(ctx.importExpr(type).prop(property));
definitions.set(type, fixup);
newValue = true;
}
if ((!newValue && !fixup.shared) || (newValue && forceShared)) {
const name = this.freshName();
this.statements.push(variable(name).set(fixup.resolved).toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]));
fixup.fixup(variable(name));
}
return fixup;
}
getLiteralFactory(literal$1) {
// Create a pure function that builds an array of a mix of constant and variable expressions
if (literal$1 instanceof LiteralArrayExpr) {
const argumentsForKey = literal$1.entries.map(e => e.isConstant() ? e : literal(null));
const key = this.keyOf(literalArr(argumentsForKey));
return this._getLiteralFactory(key, literal$1.entries, entries => literalArr(entries));
}
else {
const expressionForKey = literalMap(literal$1.entries.map(e => ({
key: e.key,
value: e.value.isConstant() ? e.value : literal(null),
quoted: e.quoted
})));
const key = this.keyOf(expressionForKey);
return this._getLiteralFactory(key, literal$1.entries.map(e => e.value), entries => literalMap(entries.map((value, index) => ({
key: literal$1.entries[index].key,
value,
quoted: literal$1.entries[index].quoted
}))));
}
}
_getLiteralFactory(key, values, resultMap) {
let literalFactory = this.literalFactories.get(key);
const literalFactoryArguments = values.filter((e => !e.isConstant()));
if (!literalFactory) {
const resultExpressions = values.map((e, index) => e.isConstant() ? this.getConstLiteral(e, true) : variable(`a${index}`));
const parameters = resultExpressions.filter(isVariable).map(e => new FnParam(e.name, DYNAMIC_TYPE));
const pureFunctionDeclaration = fn(parameters, [new ReturnStatement(resultMap(resultExpressions))], INFERRED_TYPE);
const name = this.freshName();
this.statements.push(variable(name).set(pureFunctionDeclaration).toDeclStmt(INFERRED_TYPE, [
StmtModifier.Final
]));
literalFactory = variable(name);
this.literalFactories.set(key, literalFactory);
}
return { literalFactory, literalFactoryArguments };
}
/**
* Produce a unique name.
*
* The name might be unique among different prefixes if any of the prefixes end in
* a digit so the prefix should be a constant string (not based on user input) and
* must not end in a digit.
*/
uniqueName(prefix) { return `${prefix}${this.nextNameIndex++}`; }
definitionsOf(kind) {
switch (kind) {
case 2 /* Component */:
return this.componentDefinitions;
case 1 /* Directive */:
return this.directiveDefinitions;
case 0 /* Injector */:
return this.injectorDefinitions;
case 3 /* Pipe */:
return this.pipeDefinitions;
}
error(`Unknown definition kind ${kind}`);
return this.componentDefinitions;
}
propertyNameOf(kind) {
switch (kind) {
case 2 /* Component */:
return 'ngComponentDef';
case 1 /* Directive */:
return 'ngDirectiveDef';
case 0 /* Injector */:
return 'ngInjectorDef';
case 3 /* Pipe */:
return 'ngPipeDef';
}
error(`Unknown definition kind ${kind}`);
return '';
}
freshName() { return this.uniqueName(CONSTANT_PREFIX); }
keyOf(expression) {
return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
}
}
/**
* Visitor used to determine if 2 expressions are equivalent and can be shared in the
* `ConstantPool`.
*
* When the id (string) generated by the visitor is equal, expressions are considered equivalent.
*/
class KeyVisitor {
constructor() {
this.visitWrappedNodeExpr = invalid;
this.visitWriteVarExpr = invalid;
this.visitWriteKeyExpr = invalid;
this.visitWritePropExpr = invalid;
this.visitInvokeMethodExpr = invalid;
this.visitInvokeFunctionExpr = invalid;
this.visitInstantiateExpr = invalid;
this.visitConditionalExpr = invalid;
this.visitNotExpr = invalid;
this.visitAssertNotNullExpr = invalid;
this.visitCastExpr = invalid;
this.visitFunctionExpr = invalid;
this.visitBinaryOperatorExpr = invalid;
this.visitReadPropExpr = invalid;
this.visitReadKeyExpr = invalid;
this.visitCommaExpr = invalid;
}
visitLiteralExpr(ast) {
return `${typeof ast.value === 'string' ? '"' + ast.value + '"' : ast.value}`;
}
visitLiteralArrayExpr(ast, context) {
return `[${ast.entries.map(entry => entry.visitExpression(this, context)).join(',')}]`;
}
visitLiteralMapExpr(ast, context) {
const mapKey = (entry) => {
const quote = entry.quoted ? '"' : '';
return `${quote}${entry.key}${quote}`;
};
const mapEntry = (entry) => `${mapKey(entry)}:${entry.value.visitExpression(this, context)}`;
return `{${ast.entries.map(mapEntry).join(',')}`;
}
visitExternalExpr(ast) {
return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` :
`EX:${ast.value.runtime.name}`;
}
visitReadVarExpr(node) { return `VAR:${node.name}`; }
visitTypeofExpr(node, context) {
return `TYPEOF:${node.expr.visitExpression(this, context)}`;
}
}
function invalid(arg) {
throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
}
function isVariable(e) {
return e instanceof ReadVarExpr;
}
/**
* @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 CORE = '@angular/core';
class Identifiers {
}
Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS = {
name: 'ANALYZE_FOR_ENTRY_COMPONENTS',
moduleName: CORE,
};
Identifiers.ElementRef = { name: 'ElementRef', moduleName: CORE };
Identifiers.NgModuleRef = { name: 'NgModuleRef', moduleName: CORE };
Identifiers.ViewContainerRef = { name: 'ViewContainerRef', moduleName: CORE };
Identifiers.ChangeDetectorRef = {
name: 'ChangeDetectorRef',
moduleName: CORE,
};
Identifiers.QueryList = { name: 'QueryList', moduleName: CORE };
Identifiers.TemplateRef = { name: 'TemplateRef', moduleName: CORE };
Identifiers.Renderer2 = { name: 'Renderer2', moduleName: CORE };
Identifiers.CodegenComponentFactoryResolver = {
name: 'ɵCodegenComponentFactoryResolver',
moduleName: CORE,
};
Identifiers.ComponentFactoryResolver = {
name: 'ComponentFactoryResolver',
moduleName: CORE,
};
Identifiers.ComponentFactory = { name: 'ComponentFactory', moduleName: CORE };
Identifiers.ComponentRef = { name: 'ComponentRef', moduleName: CORE };
Identifiers.NgModuleFactory = { name: 'NgModuleFactory', moduleName: CORE };
Identifiers.createModuleFactory = {
name: 'ɵcmf',
moduleName: CORE,
};
Identifiers.moduleDef = {
name: 'ɵmod',
moduleName: CORE,
};
Identifiers.moduleProviderDef = {
name: 'ɵmpd',
moduleName: CORE,
};
Identifiers.RegisterModuleFactoryFn = {
name: 'ɵregisterModuleFactory',
moduleName: CORE,
};
Identifiers.inject = { name: 'ɵɵinject', moduleName: CORE };
Identifiers.INJECTOR = { name: 'INJECTOR', moduleName: CORE };
Identifiers.Injector = { name: 'Injector', moduleName: CORE };
Identifiers.ɵɵdefineInjectable = { name: 'ɵɵdefineInjectable', moduleName: CORE };
Identifiers.InjectableDef = { name: 'ɵɵInjectableDef', moduleName: CORE };
Identifiers.ViewEncapsulation = {
name: 'ViewEncapsulation',
moduleName: CORE,
};
Identifiers.ChangeDetectionStrategy = {
name: 'ChangeDetectionStrategy',
moduleName: CORE,
};
Identifiers.SecurityContext = {
name: 'SecurityContext',
moduleName: CORE,
};
Identifiers.LOCALE_ID = { name: 'LOCALE_ID', moduleName: CORE };
Identifiers.TRANSLATIONS_FORMAT = {
name: 'TRANSLATIONS_FORMAT',
moduleName: CORE,
};
Identifiers.inlineInterpolate = {
name: 'ɵinlineInterpolate',
moduleName: CORE,
};
Identifiers.interpolate = { name: 'ɵinterpolate', moduleName: CORE };
Identifiers.EMPTY_ARRAY = { name: 'ɵEMPTY_ARRAY', moduleName: CORE };
Identifiers.EMPTY_MAP = { name: 'ɵEMPTY_MAP', moduleName: CORE };
Identifiers.Renderer = { name: 'Renderer', moduleName: CORE };
Identifiers.viewDef = { name: 'ɵvid', moduleName: CORE };
Identifiers.elementDef = { name: 'ɵeld', moduleName: CORE };
Identifiers.anchorDef = { name: 'ɵand', moduleName: CORE };
Identifiers.textDef = { name: 'ɵted', moduleName: CORE };
Identifiers.directiveDef = { name: 'ɵdid', moduleName: CORE };
Identifiers.providerDef = { name: 'ɵprd', moduleName: CORE };
Identifiers.queryDef = { name: 'ɵqud', moduleName: CORE };
Identifiers.pureArrayDef = { name: 'ɵpad', moduleName: CORE };
Identifiers.pureObjectDef = { name: 'ɵpod', moduleName: CORE };
Identifiers.purePipeDef = { name: 'ɵppd', moduleName: CORE };
Identifiers.pipeDef = { name: 'ɵpid', moduleName: CORE };
Identifiers.nodeValue = { name: 'ɵnov', moduleName: CORE };
Identifiers.ngContentDef = { name: 'ɵncd', moduleName: CORE };
Identifiers.unwrapValue = { name: 'ɵunv', moduleName: CORE };
Identifiers.createRendererType2 = { name: 'ɵcrt', moduleName: CORE };
// type only
Identifiers.RendererType2 = {
name: 'RendererType2',
moduleName: CORE,
};
// type only
Identifiers.ViewDefinition = {
name: 'ɵViewDefinition',
moduleName: CORE,
};
Identifiers.createComponentFactory = { name: 'ɵccf', moduleName: CORE };
Identifiers.setClassMetadata = { name: 'ɵsetClassMetadata', moduleName: CORE };
function createTokenForReference(reference) {
return { identifier: { reference: reference } };
}
function createTokenForExternalReference(reflector, reference) {
return createTokenForReference(reflector.resolveExternalReference(reference));
}
/**
* @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 token representing the a reference to a static type.
*
* This token is unique for a filePath and name and can be used as a hash table key.
*/
class StaticSymbol {
constructor(filePath, name, members) {
this.filePath = filePath;
this.name = name;
this.members = members;
}
assertNoMembers() {
if (this.members.length) {
throw new Error(`Illegal state: symbol without members expected, but got ${JSON.stringify(this)}.`);
}
}
}
/**
* A cache of static symbol used by the StaticReflector to return the same symbol for the
* same symbol values.
*/
class StaticSymbolCache {
constructor() {
this.cache = new Map();
}
get(declarationFile, name, members) {
members = members || [];
const memberSuffix = members.length ? `.${members.join('.')}` : '';
const key = `"${declarationFile}".${name}${memberSuffix}`;
let result = this.cache.get(key);
if (!result) {
result = new StaticSymbol(declarationFile, name, members);
this.cache.set(key, result);
}
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
*/
// group 0: "[prop] or (event) or @trigger"
// group 1: "prop" from "[prop]"
// group 2: "event" from "(event)"
// group 3: "@trigger" from "@trigger"
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
function sanitizeIdentifier(name) {
return name.replace(/\W/g, '_');
}
let _anonymousTypeIndex = 0;
function identifierName(compileIdentifier) {
if (!compileIdentifier || !compileIdentifier.reference) {
return null;
}
const ref = compileIdentifier.reference;
if (ref instanceof StaticSymbol) {
return ref.name;
}
if (ref['__anonymousType']) {
return ref['__anonymousType'];
}
let identifier = stringify(ref);
if (identifier.indexOf('(') >= 0) {
// case: anonymous functions!
identifier = `anonymous_${_anonymousTypeIndex++}`;
ref['__anonymousType'] = identifier;
}
else {
identifier = sanitizeIdentifier(identifier);
}
return identifier;
}
function identifierModuleUrl(compileIdentifier) {
const ref = compileIdentifier.reference;
if (ref instanceof StaticSymbol) {
return ref.filePath;
}
// Runtime type
return `./${stringify(ref)}`;
}
function viewClassName(compType, embeddedTemplateIndex) {
return `View_${identifierName({ reference: compType })}_${embeddedTemplateIndex}`;
}
function rendererTypeName(compType) {
return `RenderType_${identifierName({ reference: compType })}`;
}
function hostViewClassName(compType) {
return `HostView_${identifierName({ reference: compType })}`;
}
function componentFactoryName(compType) {
return `${identifierName({ reference: compType })}NgFactory`;
}
var CompileSummaryKind;
(function (CompileSummaryKind) {
CompileSummaryKind[CompileSummaryKind["Pipe"] = 0] = "Pipe";
CompileSummaryKind[CompileSummaryKind["Directive"] = 1] = "Directive";
CompileSummaryKind[CompileSummaryKind["NgModule"] = 2] = "NgModule";
CompileSummaryKind[CompileSummaryKind["Injectable"] = 3] = "Injectable";
})(CompileSummaryKind || (CompileSummaryKind = {}));
function tokenName(token) {
return token.value != null ? sanitizeIdentifier(token.value) : identifierName(token.identifier);
}
function tokenReference(token) {
if (token.identifier != null) {
return token.identifier.reference;
}
else {
return token.value;
}
}
/**
* Metadata about a stylesheet
*/
class CompileStylesheetMetadata {
constructor({ moduleUrl, styles, styleUrls } = {}) {
this.moduleUrl = moduleUrl || null;
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
}
}
/**
* Metadata regarding compilation of a template.
*/
class CompileTemplateMetadata {
constructor({ encapsulation, template, templateUrl, htmlAst, styles, styleUrls, externalStylesheets, animations, ngContentSelectors, interpolation, isInline, preserveWhitespaces }) {
this.encapsulation = encapsulation;
this.template = template;
this.templateUrl = templateUrl;
this.htmlAst = htmlAst;
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
this.externalStylesheets = _normalizeArray(externalStylesheets);
this.animations = animations ? flatten(animations) : [];
this.ngContentSelectors = ngContentSelectors || [];
if (interpolation && interpolation.length != 2) {
throw new Error(`'interpolation' should have a start and an end symbol.`);
}
this.interpolation = interpolation;
this.isInline = isInline;
this.preserveWhitespaces = preserveWhitespaces;
}
toSummary() {
return {
ngContentSelectors: this.ngContentSelectors,
encapsulation: this.encapsulation,
styles: this.styles,
animations: this.animations
};
}
}
/**
* Metadata regarding compilation of a directive.
*/
class CompileDirectiveMetadata {
static create({ isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host, providers, viewProviders, queries, guards, viewQueries, entryComponents, template, componentViewType, rendererType, componentFactory }) {
const hostListeners = {};
const hostProperties = {};
const hostAttributes = {};
if (host != null) {
Object.keys(host).forEach(key => {
const value = host[key];
const matches = key.match(HOST_REG_EXP);
if (matches === null) {
hostAttributes[key] = value;
}
else if (matches[1] != null) {
hostProperties[matches[1]] = value;
}
else if (matches[2] != null) {
hostListeners[matches[2]] = value;
}
});
}
const inputsMap = {};
if (inputs != null) {
inputs.forEach((bindConfig) => {
// canonical syntax: `dirProp: elProp`
// if there is no `:`, use dirProp = elProp
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
inputsMap[parts[0]] = parts[1];
});
}
const outputsMap = {};
if (outputs != null) {
outputs.forEach((bindConfig) => {
// canonical syntax: `dirProp: elProp`
// if there is no `:`, use dirProp = elProp
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
outputsMap[parts[0]] = parts[1];
});
}
return new CompileDirectiveMetadata({
isHost,
type,
isComponent: !!isComponent, selector, exportAs, changeDetection,
inputs: inputsMap,
outputs: outputsMap,
hostListeners,
hostProperties,
hostAttributes,
providers,
viewProviders,
queries,
guards,
viewQueries,
entryComponents,
template,
componentViewType,
rendererType,
componentFactory,
});
}
constructor({ isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners, hostProperties, hostAttributes, providers, viewProviders, queries, guards, viewQueries, entryComponents, template, componentViewType, rendererType, componentFactory }) {
this.isHost = !!isHost;
this.type = type;
this.isComponent = isComponent;
this.selector = selector;
this.exportAs = exportAs;
this.changeDetection = changeDetection;
this.inputs = inputs;
this.outputs = outputs;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.providers = _normalizeArray(providers);
this.viewProviders = _normalizeArray(viewProviders);
this.queries = _normalizeArray(queries);
this.guards = guards;
this.viewQueries = _normalizeArray(viewQueries);
this.entryComponents = _normalizeArray(entryComponents);
this.template = template;
this.componentViewType = componentViewType;
this.rendererType = rendererType;
this.componentFactory = componentFactory;
}
toSummary() {
return {
summaryKind: CompileSummaryKind.Directive,
type: this.type,
isComponent: this.isComponent,
selector: this.selector,
exportAs: this.exportAs,
inputs: this.inputs,
outputs: this.outputs,
hostListeners: this.hostListeners,
hostProperties: this.hostProperties,
hostAttributes: this.hostAttributes,
providers: this.providers,
viewProviders: this.viewProviders,
queries: this.queries,
guards: this.guards,
viewQueries: this.viewQueries,
entryComponents: this.entryComponents,
changeDetection: this.changeDetection,
template: this.template && this.template.toSummary(),
componentViewType: this.componentViewType,
rendererType: this.rendererType,
componentFactory: this.componentFactory
};
}
}
class CompilePipeMetadata {
constructor({ type, name, pure }) {
this.type = type;
this.name = name;
this.pure = !!pure;
}
toSummary() {
return {
summaryKind: CompileSummaryKind.Pipe,
type: this.type,
name: this.name,
pure: this.pure
};
}
}
class CompileShallowModuleMetadata {
}
/**
* Metadata regarding compilation of a module.
*/
class CompileNgModuleMetadata {
constructor({ type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes, entryComponents, bootstrapComponents, importedModules, exportedModules, schemas, transitiveModule, id }) {
this.type = type || null;
this.declaredDirectives = _normalizeArray(declaredDirectives);
this.exportedDirectives = _normalizeArray(exportedDirectives);
this.declaredPipes = _normalizeArray(declaredPipes);
this.exportedPipes = _normalizeArray(exportedPipes);
this.providers = _normalizeArray(providers);
this.entryComponents = _normalizeArray(entryComponents);
this.bootstrapComponents = _normalizeArray(bootstrapComponents);
this.importedModules = _normalizeArray(importedModules);
this.exportedModules = _normalizeArray(exportedModules);
this.schemas = _normalizeArray(schemas);
this.id = id || null;
this.transitiveModule = transitiveModule || null;
}
toSummary() {
const module = this.transitiveModule;
return {
summaryKind: CompileSummaryKind.NgModule,
type: this.type,
entryComponents: module.entryComponents,
providers: module.providers,
modules: module.modules,
exportedDirectives: module.exportedDirectives,
exportedPipes: module.exportedPipes
};
}
}
class TransitiveCompileNgModuleMetadata {
constructor() {
this.directivesSet = new Set();
this.directives = [];
this.exportedDirectivesSet = new Set();
this.exportedDirectives = [];
this.pipesSet = new Set();
this.pipes = [];
this.exportedPipesSet = new Set();
this.exportedPipes = [];
this.modulesSet = new Set();
this.modules = [];
this.entryComponentsSet = new Set();
this.entryComponents = [];
this.providers = [];
}
addProvider(provider, module) {
this.providers.push({ provider: provider, module: module });
}
addDirective(id) {
if (!this.directivesSet.has(id.reference)) {
this.directivesSet.add(id.reference);
this.directives.push(id);
}
}
addExportedDirective(id) {
if (!this.exportedDirectivesSet.has(id.reference)) {
this.exportedDirectivesSet.add(id.reference);
this.exportedDirectives.push(id);
}
}
addPipe(id) {
if (!this.pipesSet.has(id.reference)) {
this.pipesSet.add(id.reference);
this.pipes.push(id);
}
}
addExportedPipe(id) {
if (!this.exportedPipesSet.has(id.reference)) {
this.exportedPipesSet.add(id.reference);
this.exportedPipes.push(id);
}
}
addModule(id) {
if (!this.modulesSet.has(id.reference)) {
this.modulesSet.add(id.reference);
this.modules.push(id);
}
}
addEntryComponent(ec) {
if (!this.entryComponentsSet.has(ec.componentType)) {
this.entryComponentsSet.add(ec.componentType);
this.entryComponents.push(ec);
}
}
}
function _normalizeArray(obj) {
return obj || [];
}
class ProviderMeta {
constructor(token, { useClass, useValue, useExisting, useFactory, deps, multi }) {
this.token = token;
this.useClass = useClass || null;
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory || null;
this.dependencies = deps || null;
this.multi = !!multi;
}
}
function flatten(list) {
return list.reduce((flat, item) => {
const flatItem = Array.isArray(item) ? flatten(item) : item;
return flat.concat(flatItem);
}, []);
}
function jitSourceUrl(url) {
// Note: We need 3 "/" so that ng shows up as a separate domain
// in the chrome dev tools.
return url.replace(/(\w+:\/\/[\w:-]+)?(\/+)?/, 'ng:///');
}
function templateSourceUrl(ngModuleType, compMeta, templateMeta) {
let url;
if (templateMeta.isInline) {
if (compMeta.type.reference instanceof StaticSymbol) {
// Note: a .ts file might contain multiple components with inline templates,
// so we need to give them unique urls, as these will be used for sourcemaps.
url = `${compMeta.type.reference.filePath}.${compMeta.type.reference.name}.html`;
}
else {
url = `${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.html`;
}
}
else {
url = templateMeta.templateUrl;
}
return compMeta.type.reference instanceof StaticSymbol ? url : jitSourceUrl(url);
}
function sharedStylesheetJitUrl(meta, id) {
const pathParts = meta.moduleUrl.split(/\/\\/g);
const baseName = pathParts[pathParts.length - 1];
return jitSourceUrl(`css/${id}${baseName}.ngstyle.js`);
}
function ngModuleJitUrl(moduleMeta) {
return jitSourceUrl(`${identifierName(moduleMeta.type)}/module.ngfactory.js`);
}
function templateJitUrl(ngModuleType, compMeta) {
return jitSourceUrl(`${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.ngfactory.js`);
}
/**
* @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 CORE$1 = '@angular/core';
class Identifiers$1 {
}
/* Methods */
Identifiers$1.NEW_METHOD = 'factory';
Identifiers$1.TRANSFORM_METHOD = 'transform';
Identifiers$1.PATCH_DEPS = 'patchedDeps';
/* Instructions */
Identifiers$1.namespaceHTML = { name: 'ɵɵnamespaceHTML', moduleName: CORE$1 };
Identifiers$1.namespaceMathML = { name: 'ɵɵnamespaceMathML', moduleName: CORE$1 };
Identifiers$1.namespaceSVG = { name: 'ɵɵnamespaceSVG', moduleName: CORE$1 };
Identifiers$1.element = { name: 'ɵɵelement', moduleName: CORE$1 };
Identifiers$1.elementStart = { name: 'ɵɵelementStart', moduleName: CORE$1 };
Identifiers$1.elementEnd = { name: 'ɵɵelementEnd', moduleName: CORE$1 };
Identifiers$1.select = { name: 'ɵɵselect', moduleName: CORE$1 };
Identifiers$1.updateSyntheticHostBinding = { name: 'ɵɵupdateSyntheticHostBinding', moduleName: CORE$1 };
Identifiers$1.componentHostSyntheticListener = { name: 'ɵɵcomponentHostSyntheticListener', moduleName: CORE$1 };
Identifiers$1.attribute = { name: 'ɵɵattribute', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate1 = { name: 'ɵɵattributeInterpolate1', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate2 = { name: 'ɵɵattributeInterpolate2', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate3 = { name: 'ɵɵattributeInterpolate3', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate4 = { name: 'ɵɵattributeInterpolate4', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate5 = { name: 'ɵɵattributeInterpolate5', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate6 = { name: 'ɵɵattributeInterpolate6', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate7 = { name: 'ɵɵattributeInterpolate7', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate8 = { name: 'ɵɵattributeInterpolate8', moduleName: CORE$1 };
Identifiers$1.attributeInterpolateV = { name: 'ɵɵattributeInterpolateV', moduleName: CORE$1 };
Identifiers$1.classProp = { name: 'ɵɵclassProp', moduleName: CORE$1 };
Identifiers$1.elementContainerStart = { name: 'ɵɵelementContainerStart', moduleName: CORE$1 };
Identifiers$1.elementContainerEnd = { name: 'ɵɵelementContainerEnd', moduleName: CORE$1 };
Identifiers$1.elementContainer = { name: 'ɵɵelementContainer', moduleName: CORE$1 };
Identifiers$1.styling = { name: 'ɵɵstyling', moduleName: CORE$1 };
Identifiers$1.styleMap = { name: 'ɵɵstyleMap', moduleName: CORE$1 };
Identifiers$1.classMap = { name: 'ɵɵclassMap', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate1 = { name: 'ɵɵclassMapInterpolate1', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate2 = { name: 'ɵɵclassMapInterpolate2', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate3 = { name: 'ɵɵclassMapInterpolate3', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate4 = { name: 'ɵɵclassMapInterpolate4', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate5 = { name: 'ɵɵclassMapInterpolate5', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate6 = { name: 'ɵɵclassMapInterpolate6', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate7 = { name: 'ɵɵclassMapInterpolate7', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate8 = { name: 'ɵɵclassMapInterpolate8', moduleName: CORE$1 };
Identifiers$1.classMapInterpolateV = { name: 'ɵɵclassMapInterpolateV', moduleName: CORE$1 };
Identifiers$1.styleProp = { name: 'ɵɵstyleProp', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate1 = { name: 'ɵɵstylePropInterpolate1', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate2 = { name: 'ɵɵstylePropInterpolate2', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate3 = { name: 'ɵɵstylePropInterpolate3', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate4 = { name: 'ɵɵstylePropInterpolate4', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate5 = { name: 'ɵɵstylePropInterpolate5', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate6 = { name: 'ɵɵstylePropInterpolate6', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate7 = { name: 'ɵɵstylePropInterpolate7', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate8 = { name: 'ɵɵstylePropInterpolate8', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolateV = { name: 'ɵɵstylePropInterpolateV', moduleName: CORE$1 };
Identifiers$1.stylingApply = { name: 'ɵɵstylingApply', moduleName: CORE$1 };
Identifiers$1.styleSanitizer = { name: 'ɵɵstyleSanitizer', moduleName: CORE$1 };
Identifiers$1.elementHostAttrs = { name: 'ɵɵelementHostAttrs', moduleName: CORE$1 };
Identifiers$1.containerCreate = { name: 'ɵɵcontainer', moduleName: CORE$1 };
Identifiers$1.nextContext = { name: 'ɵɵnextContext', moduleName: CORE$1 };
Identifiers$1.templateCreate = { name: 'ɵɵtemplate', moduleName: CORE$1 };
Identifiers$1.text = { name: 'ɵɵtext', moduleName: CORE$1 };
Identifiers$1.textBinding = { name: 'ɵɵtextBinding', moduleName: CORE$1 };
Identifiers$1.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE$1 };
Identifiers$1.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE$1 };
Identifiers$1.allocHostVars = { name: 'ɵɵallocHostVars', moduleName: CORE$1 };
Identifiers$1.getCurrentView = { name: 'ɵɵgetCurrentView', moduleName: CORE$1 };
Identifiers$1.textInterpolate = { name: 'ɵɵtextInterpolate', moduleName: CORE$1 };
Identifiers$1.textInterpolate1 = { name: 'ɵɵtextInterpolate1', moduleName: CORE$1 };
Identifiers$1.textInterpolate2 = { name: 'ɵɵtextInterpolate2', moduleName: CORE$1 };
Identifiers$1.textInterpolate3 = { name: 'ɵɵtextInterpolate3', moduleName: CORE$1 };
Identifiers$1.textInterpolate4 = { name: 'ɵɵtextInterpolate4', moduleName: CORE$1 };
Identifiers$1.textInterpolate5 = { name: 'ɵɵtextInterpolate5', moduleName: CORE$1 };
Identifiers$1.textInterpolate6 = { name: 'ɵɵtextInterpolate6', moduleName: CORE$1 };
Identifiers$1.textInterpolate7 = { name: 'ɵɵtextInterpolate7', moduleName: CORE$1 };
Identifiers$1.textInterpolate8 = { name: 'ɵɵtextInterpolate8', moduleName: CORE$1 };
Identifiers$1.textInterpolateV = { name: 'ɵɵtextInterpolateV', moduleName: CORE$1 };
Identifiers$1.restoreView = { name: 'ɵɵrestoreView', moduleName: CORE$1 };
Identifiers$1.pureFunction0 = { name: 'ɵɵpureFunction0', moduleName: CORE$1 };
Identifiers$1.pureFunction1 = { name: 'ɵɵpureFunction1', moduleName: CORE$1 };
Identifiers$1.pureFunction2 = { name: 'ɵɵpureFunction2', moduleName: CORE$1 };
Identifiers$1.pureFunction3 = { name: 'ɵɵpureFunction3', moduleName: CORE$1 };
Identifiers$1.pureFunction4 = { name: 'ɵɵpureFunction4', moduleName: CORE$1 };
Identifiers$1.pureFunction5 = { name: 'ɵɵpureFunction5', moduleName: CORE$1 };
Identifiers$1.pureFunction6 = { name: 'ɵɵpureFunction6', moduleName: CORE$1 };
Identifiers$1.pureFunction7 = { name: 'ɵɵpureFunction7', moduleName: CORE$1 };
Identifiers$1.pureFunction8 = { name: 'ɵɵpureFunction8', moduleName: CORE$1 };
Identifiers$1.pureFunctionV = { name: 'ɵɵpureFunctionV', moduleName: CORE$1 };
Identifiers$1.pipeBind1 = { name: 'ɵɵpipeBind1', moduleName: CORE$1 };
Identifiers$1.pipeBind2 = { name: 'ɵɵpipeBind2', moduleName: CORE$1 };
Identifiers$1.pipeBind3 = { name: 'ɵɵpipeBind3', moduleName: CORE$1 };
Identifiers$1.pipeBind4 = { name: 'ɵɵpipeBind4', moduleName: CORE$1 };
Identifiers$1.pipeBindV = { name: 'ɵɵpipeBindV', moduleName: CORE$1 };
Identifiers$1.hostProperty = { name: 'ɵɵhostProperty', moduleName: CORE$1 };
Identifiers$1.property = { name: 'ɵɵproperty', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate = { name: 'ɵɵpropertyInterpolate', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate1 = { name: 'ɵɵpropertyInterpolate1', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate2 = { name: 'ɵɵpropertyInterpolate2', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate3 = { name: 'ɵɵpropertyInterpolate3', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate4 = { name: 'ɵɵpropertyInterpolate4', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate5 = { name: 'ɵɵpropertyInterpolate5', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate6 = { name: 'ɵɵpropertyInterpolate6', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate7 = { name: 'ɵɵpropertyInterpolate7', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate8 = { name: 'ɵɵpropertyInterpolate8', moduleName: CORE$1 };
Identifiers$1.propertyInterpolateV = { name: 'ɵɵpropertyInterpolateV', moduleName: CORE$1 };
Identifiers$1.i18n = { name: 'ɵɵi18n', moduleName: CORE$1 };
Identifiers$1.i18nAttributes = { name: 'ɵɵi18nAttributes', moduleName: CORE$1 };
Identifiers$1.i18nExp = { name: 'ɵɵi18nExp', moduleName: CORE$1 };
Identifiers$1.i18nStart = { name: 'ɵɵi18nStart', moduleName: CORE$1 };
Identifiers$1.i18nEnd = { name: 'ɵɵi18nEnd', moduleName: CORE$1 };
Identifiers$1.i18nApply = { name: 'ɵɵi18nApply', moduleName: CORE$1 };
Identifiers$1.i18nPostprocess = { name: 'ɵɵi18nPostprocess', moduleName: CORE$1 };
Identifiers$1.i18nLocalize = { name: 'ɵɵi18nLocalize', moduleName: CORE$1 };
Identifiers$1.load = { name: 'ɵɵload', moduleName: CORE$1 };
Identifiers$1.pipe = { name: 'ɵɵpipe', moduleName: CORE$1 };
Identifiers$1.projection = { name: 'ɵɵprojection', moduleName: CORE$1 };
Identifiers$1.projectionDef = { name: 'ɵɵprojectionDef', moduleName: CORE$1 };
Identifiers$1.reference = { name: 'ɵɵreference', moduleName: CORE$1 };
Identifiers$1.inject = { name: 'ɵɵinject', moduleName: CORE$1 };
Identifiers$1.injectAttribute = { name: 'ɵɵinjectAttribute', moduleName: CORE$1 };
Identifiers$1.injectPipeChangeDetectorRef = { name: 'ɵɵinjectPipeChangeDetectorRef', moduleName: CORE$1 };
Identifiers$1.directiveInject = { name: 'ɵɵdirectiveInject', moduleName: CORE$1 };
Identifiers$1.templateRefExtractor = { name: 'ɵɵtemplateRefExtractor', moduleName: CORE$1 };
Identifiers$1.resolveWindow = { name: 'ɵɵresolveWindow', moduleName: CORE$1 };
Identifiers$1.resolveDocument = { name: 'ɵɵresolveDocument', moduleName: CORE$1 };
Identifiers$1.resolveBody = { name: 'ɵɵresolveBody', moduleName: CORE$1 };
Identifiers$1.defineBase = { name: 'ɵɵdefineBase', moduleName: CORE$1 };
Identifiers$1.BaseDef = {
name: 'ɵɵBaseDef',
moduleName: CORE$1,
};
Identifiers$1.defineComponent = { name: 'ɵɵdefineComponent', moduleName: CORE$1 };
Identifiers$1.setComponentScope = { name: 'ɵɵsetComponentScope', moduleName: CORE$1 };
Identifiers$1.ComponentDefWithMeta = {
name: 'ɵɵComponentDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.defineDirective = {
name: 'ɵɵdefineDirective',
moduleName: CORE$1,
};
Identifiers$1.DirectiveDefWithMeta = {
name: 'ɵɵDirectiveDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.InjectorDef = {
name: 'ɵɵInjectorDef',
moduleName: CORE$1,
};
Identifiers$1.defineInjector = {
name: 'ɵɵdefineInjector',
moduleName: CORE$1,
};
Identifiers$1.NgModuleDefWithMeta = {
name: 'ɵɵNgModuleDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.defineNgModule = { name: 'ɵɵdefineNgModule', moduleName: CORE$1 };
Identifiers$1.setNgModuleScope = { name: 'ɵɵsetNgModuleScope', moduleName: CORE$1 };
Identifiers$1.PipeDefWithMeta = { name: 'ɵɵPipeDefWithMeta', moduleName: CORE$1 };
Identifiers$1.definePipe = { name: 'ɵɵdefinePipe', moduleName: CORE$1 };
Identifiers$1.queryRefresh = { name: 'ɵɵqueryRefresh', moduleName: CORE$1 };
Identifiers$1.viewQuery = { name: 'ɵɵviewQuery', moduleName: CORE$1 };
Identifiers$1.staticViewQuery = { name: 'ɵɵstaticViewQuery', moduleName: CORE$1 };
Identifiers$1.staticContentQuery = { name: 'ɵɵstaticContentQuery', moduleName: CORE$1 };
Identifiers$1.loadViewQuery = { name: 'ɵɵloadViewQuery', moduleName: CORE$1 };
Identifiers$1.contentQuery = { name: 'ɵɵcontentQuery', moduleName: CORE$1 };
Identifiers$1.loadContentQuery = { name: 'ɵɵloadContentQuery', moduleName: CORE$1 };
Identifiers$1.NgOnChangesFeature = { name: 'ɵɵNgOnChangesFeature', moduleName: CORE$1 };
Identifiers$1.InheritDefinitionFeature = { name: 'ɵɵInheritDefinitionFeature', moduleName: CORE$1 };
Identifiers$1.ProvidersFeature = { name: 'ɵɵProvidersFeature', moduleName: CORE$1 };
Identifiers$1.listener = { name: 'ɵɵlistener', moduleName: CORE$1 };
Identifiers$1.getFactoryOf = {
name: 'ɵɵgetFactoryOf',
moduleName: CORE$1,
};
Identifiers$1.getInheritedFactory = {
name: 'ɵɵgetInheritedFactory',
moduleName: CORE$1,
};
// sanitization-related functions
Identifiers$1.sanitizeHtml = { name: 'ɵɵsanitizeHtml', moduleName: CORE$1 };
Identifiers$1.sanitizeStyle = { name: 'ɵɵsanitizeStyle', moduleName: CORE$1 };
Identifiers$1.defaultStyleSanitizer = { name: 'ɵɵdefaultStyleSanitizer', moduleName: CORE$1 };
Identifiers$1.sanitizeResourceUrl = { name: 'ɵɵsanitizeResourceUrl', moduleName: CORE$1 };
Identifiers$1.sanitizeScript = { name: 'ɵɵsanitizeScript', moduleName: CORE$1 };
Identifiers$1.sanitizeUrl = { name: 'ɵɵsanitizeUrl', moduleName: CORE$1 };
Identifiers$1.sanitizeUrlOrResourceUrl = { name: 'ɵɵsanitizeUrlOrResourceUrl', moduleName: CORE$1 };
/**
* @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 $EOF = 0;
const $BSPACE = 8;
const $TAB = 9;
const $LF = 10;
const $VTAB = 11;
const $FF = 12;
const $CR = 13;
const $SPACE = 32;
const $BANG = 33;
const $DQ = 34;
const $HASH = 35;
const $$ = 36;
const $PERCENT = 37;
const $AMPERSAND = 38;
const $SQ = 39;
const $LPAREN = 40;
const $RPAREN = 41;
const $STAR = 42;
const $PLUS = 43;
const $COMMA = 44;
const $MINUS = 45;
const $PERIOD = 46;
const $SLASH = 47;
const $COLON = 58;
const $SEMICOLON = 59;
const $LT = 60;
const $EQ = 61;
const $GT = 62;
const $QUESTION = 63;
const $0 = 48;
const $7 = 55;
const $9 = 57;
const $A = 65;
const $E = 69;
const $F = 70;
const $X = 88;
const $Z = 90;
const $LBRACKET = 91;
const $BACKSLASH = 92;
const $RBRACKET = 93;
const $CARET = 94;
const $_ = 95;
const $a = 97;
const $b = 98;
const $e = 101;
const $f = 102;
const $n = 110;
const $r = 114;
const $t = 116;
const $u = 117;
const $v = 118;
const $x = 120;
const $z = 122;
const $LBRACE = 123;
const $BAR = 124;
const $RBRACE = 125;
const $NBSP = 160;
const $PIPE = 124;
const $TILDA = 126;
const $AT = 64;
const $BT = 96;
function isWhitespace(code) {
return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
}
function isDigit(code) {
return $0 <= code && code <= $9;
}
function isAsciiLetter(code) {
return code >= $a && code <= $z || code >= $A && code <= $Z;
}
function isAsciiHexDigit(code) {
return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
}
function isNewLine(code) {
return code === $LF || code === $CR;
}
function isOctalDigit(code) {
return $0 <= code && code <= $7;
}
/**
* @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 ParseLocation {
constructor(file, offset, line, col) {
this.file = file;
this.offset = offset;
this.line = line;
this.col = col;
}
toString() {
return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
}
moveBy(delta) {
const source = this.file.content;
const len = source.length;
let offset = this.offset;
let line = this.line;
let col = this.col;
while (offset > 0 && delta < 0) {
offset--;
delta++;
const ch = source.charCodeAt(offset);
if (ch == $LF) {
line--;
const priorLine = source.substr(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
col = priorLine > 0 ? offset - priorLine : offset;
}
else {
col--;
}
}
while (offset < len && delta > 0) {
const ch = source.charCodeAt(offset);
offset++;
delta--;
if (ch == $LF) {
line++;
col = 0;
}
else {
col++;
}
}
return new ParseLocation(this.file, offset, line, col);
}
// Return the source around the location
// Up to `maxChars` or `maxLines` on each side of the location
getContext(maxChars, maxLines) {
const content = this.file.content;
let startOffset = this.offset;
if (startOffset != null) {
if (startOffset > content.length - 1) {
startOffset = content.length - 1;
}
let endOffset = startOffset;
let ctxChars = 0;
let ctxLines = 0;
while (ctxChars < maxChars && startOffset > 0) {
startOffset--;
ctxChars++;
if (content[startOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
ctxChars = 0;
ctxLines = 0;
while (ctxChars < maxChars && endOffset < content.length - 1) {
endOffset++;
ctxChars++;
if (content[endOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
return {
before: content.substring(startOffset, this.offset),
after: content.substring(this.offset, endOffset + 1),
};
}
return null;
}
}
class ParseSourceFile {
constructor(content, url) {
this.content = content;
this.url = url;
}
}
class ParseSourceSpan {
constructor(start, end, details = null) {
this.start = start;
this.end = end;
this.details = details;
}
toString() {
return this.start.file.content.substring(this.start.offset, this.end.offset);
}
}
const EMPTY_PARSE_LOCATION = new ParseLocation(new ParseSourceFile('', ''), 0, 0, 0);
const EMPTY_SOURCE_SPAN = new ParseSourceSpan(EMPTY_PARSE_LOCATION, EMPTY_PARSE_LOCATION);
var ParseErrorLevel;
(function (ParseErrorLevel) {
ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
})(ParseErrorLevel || (ParseErrorLevel = {}));
class ParseError {
constructor(span, msg, level = ParseErrorLevel.ERROR) {
this.span = span;
this.msg = msg;
this.level = level;
}
contextualMessage() {
const ctx = this.span.start.getContext(100, 3);
return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` :
this.msg;
}
toString() {
const details = this.span.details ? `, ${this.span.details}` : '';
return `${this.contextualMessage()}: ${this.span.start}${details}`;
}
}
function typeSourceSpan(kind, type) {
const moduleUrl = identifierModuleUrl(type);
const sourceFileName = moduleUrl != null ? `in ${kind} ${identifierName(type)} in ${moduleUrl}` :
`in ${kind} ${identifierName(type)}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
}
/**
* Generates Source Span object for a given R3 Type for JIT mode.
*
* @param kind Component or Directive.
* @param typeName name of the Component or Directive.
* @param sourceUrl reference to Component or Directive source.
* @returns instance of ParseSourceSpan that represent a given Component or Directive.
*/
function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
}
/**
* @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 Text {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor) { return visitor.visitText(this); }
}
class BoundText {
constructor(value, sourceSpan, i18n) {
this.value = value;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) { return visitor.visitBoundText(this); }
}
class TextAttribute {
constructor(name, value, sourceSpan, valueSpan, i18n) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
visit(visitor) { return visitor.visitTextAttribute(this); }
}
class BoundAttribute {
constructor(name, type, securityContext, value, unit, sourceSpan, valueSpan, i18n) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
static fromBoundElementProperty(prop, i18n) {
return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.valueSpan, i18n);
}
visit(visitor) { return visitor.visitBoundAttribute(this); }
}
class BoundEvent {
constructor(name, type, handler, target, phase, sourceSpan, handlerSpan) {
this.name = name;
this.type = type;
this.handler = handler;
this.target = target;
this.phase = phase;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
}
static fromParsedEvent(event) {
const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null;
const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null;
return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan);
}
visit(visitor) { return visitor.visitBoundEvent(this); }
}
class Element {
constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.name = name;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.children = children;
this.references = references;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
// If the element is empty then the source span should include any closing tag
if (children.length === 0 && startSourceSpan && endSourceSpan) {
this.sourceSpan = new ParseSourceSpan(sourceSpan.start, endSourceSpan.end);
}
}
visit(visitor) { return visitor.visitElement(this); }
}
class Template {
constructor(tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.tagName = tagName;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.templateAttrs = templateAttrs;
this.children = children;
this.references = references;
this.variables = variables;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) { return visitor.visitTemplate(this); }
}
class Content {
constructor(selector, attributes, sourceSpan, i18n) {
this.selector = selector;
this.attributes = attributes;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) { return visitor.visitContent(this); }
}
class Variable {
constructor(name, value, sourceSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
visit(visitor) { return visitor.visitVariable(this); }
}
class Reference {
constructor(name, value, sourceSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
visit(visitor) { return visitor.visitReference(this); }
}
class Icu {
constructor(vars, placeholders, sourceSpan, i18n) {
this.vars = vars;
this.placeholders = placeholders;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) { return visitor.visitIcu(this); }
}
class NullVisitor {
visitElement(element) { }
visitTemplate(template) { }
visitContent(content) { }
visitVariable(variable) { }
visitReference(reference) { }
visitTextAttribute(attribute) { }
visitBoundAttribute(attribute) { }
visitBoundEvent(attribute) { }
visitText(text) { }
visitBoundText(text) { }
visitIcu(icu) { }
}
class RecursiveVisitor {
visitElement(element) {
visitAll(this, element.attributes);
visitAll(this, element.children);
visitAll(this, element.references);
}
visitTemplate(template) {
visitAll(this, template.attributes);
visitAll(this, template.children);
visitAll(this, template.references);
visitAll(this, template.variables);
}
visitContent(content) { }
visitVariable(variable) { }
visitReference(reference) { }
visitTextAttribute(attribute) { }
visitBoundAttribute(attribute) { }
visitBoundEvent(attribute) { }
visitText(text) { }
visitBoundText(text) { }
visitIcu(icu) { }
}
class TransformVisitor {
visitElement(element) {
const newAttributes = transformAll(this, element.attributes);
const newInputs = transformAll(this, element.inputs);
const newOutputs = transformAll(this, element.outputs);
const newChildren = transformAll(this, element.children);
const newReferences = transformAll(this, element.references);
if (newAttributes != element.attributes || newInputs != element.inputs ||
newOutputs != element.outputs || newChildren != element.children ||
newReferences != element.references) {
return new Element(element.name, newAttributes, newInputs, newOutputs, newChildren, newReferences, element.sourceSpan, element.startSourceSpan, element.endSourceSpan);
}
return element;
}
visitTemplate(template) {
const newAttributes = transformAll(this, template.attributes);
const newInputs = transformAll(this, template.inputs);
const newOutputs = transformAll(this, template.outputs);
const newTemplateAttrs = transformAll(this, template.templateAttrs);
const newChildren = transformAll(this, template.children);
const newReferences = transformAll(this, template.references);
const newVariables = transformAll(this, template.variables);
if (newAttributes != template.attributes || newInputs != template.inputs ||
newOutputs != template.outputs || newTemplateAttrs != template.templateAttrs ||
newChildren != template.children || newReferences != template.references ||
newVariables != template.variables) {
return new Template(template.tagName, newAttributes, newInputs, newOutputs, newTemplateAttrs, newChildren, newReferences, newVariables, template.sourceSpan, template.startSourceSpan, template.endSourceSpan);
}
return template;
}
visitContent(content) { return content; }
visitVariable(variable) { return variable; }
visitReference(reference) { return reference; }
visitTextAttribute(attribute) { return attribute; }
visitBoundAttribute(attribute) { return attribute; }
visitBoundEvent(attribute) { return attribute; }
visitText(text) { return text; }
visitBoundText(text) { return text; }
visitIcu(icu) { return icu; }
}
function visitAll(visitor, nodes) {
const result = [];
if (visitor.visit) {
for (const node of nodes) {
const newNode = visitor.visit(node) || node.visit(visitor);
}
}
else {
for (const node of nodes) {
const newNode = node.visit(visitor);
if (newNode) {
result.push(newNode);
}
}
}
return result;
}
function transformAll(visitor, nodes) {
const result = [];
let changed = false;
for (const node of nodes) {
const newNode = node.visit(visitor);
if (newNode) {
result.push(newNode);
}
changed = changed || newNode != node;
}
return changed ? result : nodes;
}
/**
* @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 Message {
/**
* @param nodes message AST
* @param placeholders maps placeholder names to static content
* @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)
* @param meaning
* @param description
* @param id
*/
constructor(nodes, placeholders, placeholderToMessage, meaning, description, id) {
this.nodes = nodes;
this.placeholders = placeholders;
this.placeholderToMessage = placeholderToMessage;
this.meaning = meaning;
this.description = description;
this.id = id;
if (nodes.length) {
this.sources = [{
filePath: nodes[0].sourceSpan.start.file.url,
startLine: nodes[0].sourceSpan.start.line + 1,
startCol: nodes[0].sourceSpan.start.col + 1,
endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
endCol: nodes[0].sourceSpan.start.col + 1
}];
}
else {
this.sources = [];
}
}
}
class Text$1 {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitText(this, context); }
}
// TODO(vicb): do we really need this node (vs an array) ?
class Container {
constructor(children, sourceSpan) {
this.children = children;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitContainer(this, context); }
}
class Icu$1 {
constructor(expression, type, cases, sourceSpan) {
this.expression = expression;
this.type = type;
this.cases = cases;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitIcu(this, context); }
}
class TagPlaceholder {
constructor(tag, attrs, startName, closeName, children, isVoid, sourceSpan) {
this.tag = tag;
this.attrs = attrs;
this.startName = startName;
this.closeName = closeName;
this.children = children;
this.isVoid = isVoid;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitTagPlaceholder(this, context); }
}
class Placeholder {
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitPlaceholder(this, context); }
}
class IcuPlaceholder {
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitIcuPlaceholder(this, context); }
}
// Clone the AST
class CloneVisitor {
visitText(text, context) { return new Text$1(text.value, text.sourceSpan); }
visitContainer(container, context) {
const children = container.children.map(n => n.visit(this, context));
return new Container(children, container.sourceSpan);
}
visitIcu(icu, context) {
const cases = {};
Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context));
const msg = new Icu$1(icu.expression, icu.type, cases, icu.sourceSpan);
msg.expressionPlaceholder = icu.expressionPlaceholder;
return msg;
}
visitTagPlaceholder(ph, context) {
const children = ph.children.map(n => n.visit(this, context));
return new TagPlaceholder(ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan);
}
visitPlaceholder(ph, context) {
return new Placeholder(ph.value, ph.name, ph.sourceSpan);
}
visitIcuPlaceholder(ph, context) {
return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
}
}
// Visit all the nodes recursively
class RecurseVisitor {
visitText(text, context) { }
visitContainer(container, context) {
container.children.forEach(child => child.visit(this));
}
visitIcu(icu, context) {
Object.keys(icu.cases).forEach(k => { icu.cases[k].visit(this); });
}
visitTagPlaceholder(ph, context) {
ph.children.forEach(child => child.visit(this));
}
visitPlaceholder(ph, context) { }
visitIcuPlaceholder(ph, context) { }
}
/**
* @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
*/
function digest(message) {
return message.id || sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
}
function decimalDigest(message) {
if (message.id) {
return message.id;
}
const visitor = new _SerializerIgnoreIcuExpVisitor();
const parts = message.nodes.map(a => a.visit(visitor, null));
return computeMsgId(parts.join(''), message.meaning);
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* The visitor is also used in the i18n parser tests
*
* @internal
*/
class _SerializerVisitor {
visitText(text, context) { return text.value; }
visitContainer(container, context) {
return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
}
visitIcu(icu, context) {
const strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
}
visitTagPlaceholder(ph, context) {
return ph.isVoid ?
`` :
`${ph.children.map(child => child.visit(this)).join(', ')}`;
}
visitPlaceholder(ph, context) {
return ph.value ? `${ph.value}` : ``;
}
visitIcuPlaceholder(ph, context) {
return `${ph.value.visit(this)}`;
}
}
const serializerVisitor = new _SerializerVisitor();
function serializeNodes(nodes) {
return nodes.map(a => a.visit(serializerVisitor, null));
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
*
* @internal
*/
class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
visitIcu(icu, context) {
let strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
// Do not take the expression into account
return `{${icu.type}, ${strCases.join(', ')}}`;
}
}
/**
* Compute the SHA1 of the given string
*
* see http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
*
* WARNING: this function has not been designed not tested with security in mind.
* DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
*/
function sha1(str) {
const utf8 = utf8Encode(str);
const words32 = stringToWords32(utf8, Endian.Big);
const len = utf8.length * 8;
const w = new Array(80);
let [a, b, c, d, e] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
words32[len >> 5] |= 0x80 << (24 - len % 32);
words32[((len + 64 >> 9) << 4) + 15] = len;
for (let i = 0; i < words32.length; i += 16) {
const [h0, h1, h2, h3, h4] = [a, b, c, d, e];
for (let j = 0; j < 80; j++) {
if (j < 16) {
w[j] = words32[i + j];
}
else {
w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
const [f, k] = fk(j, b, c, d);
const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
[e, d, c, b, a] = [d, c, rol32(b, 30), a, temp];
}
[a, b, c, d, e] = [add32(a, h0), add32(b, h1), add32(c, h2), add32(d, h3), add32(e, h4)];
}
return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
}
function fk(index, b, c, d) {
if (index < 20) {
return [(b & c) | (~b & d), 0x5a827999];
}
if (index < 40) {
return [b ^ c ^ d, 0x6ed9eba1];
}
if (index < 60) {
return [(b & c) | (b & d) | (c & d), 0x8f1bbcdc];
}
return [b ^ c ^ d, 0xca62c1d6];
}
/**
* Compute the fingerprint of the given string
*
* The output is 64 bit number encoded as a decimal string
*
* based on:
* https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
*/
function fingerprint(str) {
const utf8 = utf8Encode(str);
let [hi, lo] = [hash32(utf8, 0), hash32(utf8, 102072)];
if (hi == 0 && (lo == 0 || lo == 1)) {
hi = hi ^ 0x130f9bef;
lo = lo ^ -0x6b5f56d8;
}
return [hi, lo];
}
function computeMsgId(msg, meaning) {
let [hi, lo] = fingerprint(msg);
if (meaning) {
const [him, lom] = fingerprint(meaning);
[hi, lo] = add64(rol64([hi, lo], 1), [him, lom]);
}
return byteStringToDecString(words32ToByteString([hi & 0x7fffffff, lo]));
}
function hash32(str, c) {
let [a, b] = [0x9e3779b9, 0x9e3779b9];
let i;
const len = str.length;
for (i = 0; i + 12 <= len; i += 12) {
a = add32(a, wordAt(str, i, Endian.Little));
b = add32(b, wordAt(str, i + 4, Endian.Little));
c = add32(c, wordAt(str, i + 8, Endian.Little));
[a, b, c] = mix([a, b, c]);
}
a = add32(a, wordAt(str, i, Endian.Little));
b = add32(b, wordAt(str, i + 4, Endian.Little));
// the first byte of c is reserved for the length
c = add32(c, len);
c = add32(c, wordAt(str, i + 8, Endian.Little) << 8);
return mix([a, b, c])[2];
}
// clang-format off
function mix([a, b, c]) {
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 13;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 8;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 13;
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 12;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 16;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 5;
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 3;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 10;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 15;
return [a, b, c];
}
// clang-format on
// Utils
var Endian;
(function (Endian) {
Endian[Endian["Little"] = 0] = "Little";
Endian[Endian["Big"] = 1] = "Big";
})(Endian || (Endian = {}));
function add32(a, b) {
return add32to64(a, b)[1];
}
function add32to64(a, b) {
const low = (a & 0xffff) + (b & 0xffff);
const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
return [high >>> 16, (high << 16) | (low & 0xffff)];
}
function add64([ah, al], [bh, bl]) {
const [carry, l] = add32to64(al, bl);
const h = add32(add32(ah, bh), carry);
return [h, l];
}
function sub32(a, b) {
const low = (a & 0xffff) - (b & 0xffff);
const high = (a >> 16) - (b >> 16) + (low >> 16);
return (high << 16) | (low & 0xffff);
}
// Rotate a 32b number left `count` position
function rol32(a, count) {
return (a << count) | (a >>> (32 - count));
}
// Rotate a 64b number left `count` position
function rol64([hi, lo], count) {
const h = (hi << count) | (lo >>> (32 - count));
const l = (lo << count) | (hi >>> (32 - count));
return [h, l];
}
function stringToWords32(str, endian) {
const words32 = Array((str.length + 3) >>> 2);
for (let i = 0; i < words32.length; i++) {
words32[i] = wordAt(str, i * 4, endian);
}
return words32;
}
function byteAt(str, index) {
return index >= str.length ? 0 : str.charCodeAt(index) & 0xff;
}
function wordAt(str, index, endian) {
let word = 0;
if (endian === Endian.Big) {
for (let i = 0; i < 4; i++) {
word += byteAt(str, index + i) << (24 - 8 * i);
}
}
else {
for (let i = 0; i < 4; i++) {
word += byteAt(str, index + i) << 8 * i;
}
}
return word;
}
function words32ToByteString(words32) {
return words32.reduce((str, word) => str + word32ToByteString(word), '');
}
function word32ToByteString(word) {
let str = '';
for (let i = 0; i < 4; i++) {
str += String.fromCharCode((word >>> 8 * (3 - i)) & 0xff);
}
return str;
}
function byteStringToHexString(str) {
let hex = '';
for (let i = 0; i < str.length; i++) {
const b = byteAt(str, i);
hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16);
}
return hex.toLowerCase();
}
// based on http://www.danvk.org/hex2dec.html (JS can not handle more than 56b)
function byteStringToDecString(str) {
let decimal = '';
let toThePower = '1';
for (let i = str.length - 1; i >= 0; i--) {
decimal = addBigInt(decimal, numberTimesBigInt(byteAt(str, i), toThePower));
toThePower = numberTimesBigInt(256, toThePower);
}
return decimal.split('').reverse().join('');
}
// x and y decimal, lowest significant digit first
function addBigInt(x, y) {
let sum = '';
const len = Math.max(x.length, y.length);
for (let i = 0, carry = 0; i < len || carry; i++) {
const tmpSum = carry + +(x[i] || 0) + +(y[i] || 0);
if (tmpSum >= 10) {
carry = 1;
sum += tmpSum - 10;
}
else {
carry = 0;
sum += tmpSum;
}
}
return sum;
}
function numberTimesBigInt(num, b) {
let product = '';
let bToThePower = b;
for (; num !== 0; num = num >>> 1) {
if (num & 1)
product = addBigInt(product, bToThePower);
bToThePower = addBigInt(bToThePower, bToThePower);
}
return product;
}
/**
* @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 Serializer {
// Creates a name mapper, see `PlaceholderMapper`
// Returning `null` means that no name mapping is used.
createNameMapper(message) { return null; }
}
/**
* A simple mapper that take a function to transform an internal name to a public name
*/
class SimplePlaceholderMapper extends RecurseVisitor {
// create a mapping from the message
constructor(message, mapName) {
super();
this.mapName = mapName;
this.internalToPublic = {};
this.publicToNextId = {};
this.publicToInternal = {};
message.nodes.forEach(node => node.visit(this));
}
toPublicName(internalName) {
return this.internalToPublic.hasOwnProperty(internalName) ?
this.internalToPublic[internalName] :
null;
}
toInternalName(publicName) {
return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] :
null;
}
visitText(text, context) { return null; }
visitTagPlaceholder(ph, context) {
this.visitPlaceholderName(ph.startName);
super.visitTagPlaceholder(ph, context);
this.visitPlaceholderName(ph.closeName);
}
visitPlaceholder(ph, context) { this.visitPlaceholderName(ph.name); }
visitIcuPlaceholder(ph, context) {
this.visitPlaceholderName(ph.name);
}
// XMB placeholders could only contains A-Z, 0-9 and _
visitPlaceholderName(internalName) {
if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) {
return;
}
let publicName = this.mapName(internalName);
if (this.publicToInternal.hasOwnProperty(publicName)) {
// Create a new XMB when it has already been used
const nextId = this.publicToNextId[publicName];
this.publicToNextId[publicName] = nextId + 1;
publicName = `${publicName}_${nextId}`;
}
else {
this.publicToNextId[publicName] = 1;
}
this.internalToPublic[internalName] = publicName;
this.publicToInternal[publicName] = internalName;
}
}
/**
* @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 _Visitor {
visitTag(tag) {
const strAttrs = this._serializeAttributes(tag.attrs);
if (tag.children.length == 0) {
return `<${tag.name}${strAttrs}/>`;
}
const strChildren = tag.children.map(node => node.visit(this));
return `<${tag.name}${strAttrs}>${strChildren.join('')}${tag.name}>`;
}
visitText(text) { return text.value; }
visitDeclaration(decl) {
return ``;
}
_serializeAttributes(attrs) {
const strAttrs = Object.keys(attrs).map((name) => `${name}="${attrs[name]}"`).join(' ');
return strAttrs.length > 0 ? ' ' + strAttrs : '';
}
visitDoctype(doctype) {
return ``;
}
}
const _visitor = new _Visitor();
function serialize(nodes) {
return nodes.map((node) => node.visit(_visitor)).join('');
}
class Declaration {
constructor(unescapedAttrs) {
this.attrs = {};
Object.keys(unescapedAttrs).forEach((k) => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) { return visitor.visitDeclaration(this); }
}
class Doctype {
constructor(rootTag, dtd) {
this.rootTag = rootTag;
this.dtd = dtd;
}
visit(visitor) { return visitor.visitDoctype(this); }
}
class Tag {
constructor(name, unescapedAttrs = {}, children = []) {
this.name = name;
this.children = children;
this.attrs = {};
Object.keys(unescapedAttrs).forEach((k) => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) { return visitor.visitTag(this); }
}
class Text$2 {
constructor(unescapedValue) { this.value = escapeXml(unescapedValue); }
visit(visitor) { return visitor.visitText(this); }
}
class CR extends Text$2 {
constructor(ws = 0) { super(`\n${new Array(ws + 1).join(' ')}`); }
}
const _ESCAPED_CHARS = [
[/&/g, '&'],
[/"/g, '"'],
[/'/g, '''],
[//g, '>'],
];
// Escape `_ESCAPED_CHARS` characters in the given text with encoded entities
function escapeXml(text) {
return _ESCAPED_CHARS.reduce((text, entry) => text.replace(entry[0], entry[1]), text);
}
/**
* @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 _MESSAGES_TAG = 'messagebundle';
const _MESSAGE_TAG = 'msg';
const _PLACEHOLDER_TAG = 'ph';
const _EXAMPLE_TAG = 'ex';
const _SOURCE_TAG = 'source';
const _DOCTYPE = `
`;
class Xmb extends Serializer {
write(messages, locale) {
const exampleVisitor = new ExampleVisitor();
const visitor = new _Visitor$1();
let rootNode = new Tag(_MESSAGES_TAG);
messages.forEach(message => {
const attrs = { id: message.id };
if (message.description) {
attrs['desc'] = message.description;
}
if (message.meaning) {
attrs['meaning'] = message.meaning;
}
let sourceTags = [];
message.sources.forEach((source) => {
sourceTags.push(new Tag(_SOURCE_TAG, {}, [
new Text$2(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)
]));
});
rootNode.children.push(new CR(2), new Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));
});
rootNode.children.push(new CR());
return serialize([
new Declaration({ version: '1.0', encoding: 'UTF-8' }),
new CR(),
new Doctype(_MESSAGES_TAG, _DOCTYPE),
new CR(),
exampleVisitor.addDefaultExamples(rootNode),
new CR(),
]);
}
load(content, url) {
throw new Error('Unsupported');
}
digest(message) { return digest$1(message); }
createNameMapper(message) {
return new SimplePlaceholderMapper(message, toPublicName);
}
}
class _Visitor$1 {
visitText(text, context) { return [new Text$2(text.value)]; }
visitContainer(container, context) {
const nodes = [];
container.children.forEach((node) => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu, context) {
const nodes = [new Text$2(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
Object.keys(icu.cases).forEach((c) => {
nodes.push(new Text$2(`${c} {`), ...icu.cases[c].visit(this), new Text$2(`} `));
});
nodes.push(new Text$2(`}`));
return nodes;
}
visitTagPlaceholder(ph, context) {
const startTagAsText = new Text$2(`<${ph.tag}>`);
const startEx = new Tag(_EXAMPLE_TAG, {}, [startTagAsText]);
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
const startTagPh = new Tag(_PLACEHOLDER_TAG, { name: ph.startName }, [startEx, startTagAsText]);
if (ph.isVoid) {
// void tags have no children nor closing tags
return [startTagPh];
}
const closeTagAsText = new Text$2(`${ph.tag}>`);
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeTagAsText]);
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
const closeTagPh = new Tag(_PLACEHOLDER_TAG, { name: ph.closeName }, [closeEx, closeTagAsText]);
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitPlaceholder(ph, context) {
const interpolationAsText = new Text$2(`{{${ph.value}}}`);
// Example tag needs to be not-empty for TC.
const exTag = new Tag(_EXAMPLE_TAG, {}, [interpolationAsText]);
return [
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
new Tag(_PLACEHOLDER_TAG, { name: ph.name }, [exTag, interpolationAsText])
];
}
visitIcuPlaceholder(ph, context) {
const icuExpression = ph.value.expression;
const icuType = ph.value.type;
const icuCases = Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ');
const icuAsText = new Text$2(`{${icuExpression}, ${icuType}, ${icuCases}}`);
const exTag = new Tag(_EXAMPLE_TAG, {}, [icuAsText]);
return [
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
new Tag(_PLACEHOLDER_TAG, { name: ph.name }, [exTag, icuAsText])
];
}
serialize(nodes) {
return [].concat(...nodes.map(node => node.visit(this)));
}
}
function digest$1(message) {
return decimalDigest(message);
}
// TC requires at least one non-empty example on placeholders
class ExampleVisitor {
addDefaultExamples(node) {
node.visit(this);
return node;
}
visitTag(tag) {
if (tag.name === _PLACEHOLDER_TAG) {
if (!tag.children || tag.children.length == 0) {
const exText = new Text$2(tag.attrs['name'] || '...');
tag.children = [new Tag(_EXAMPLE_TAG, {}, [exText])];
}
}
else if (tag.children) {
tag.children.forEach(node => node.visit(this));
}
}
visitText(text) { }
visitDeclaration(decl) { }
visitDoctype(doctype) { }
}
// XMB/XTB placeholders can only contain A-Z, 0-9 and _
function toPublicName(internalName) {
return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
}
/**
* @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
*/
function mapEntry(key, value) {
return { key, value, quoted: false };
}
function mapLiteral(obj, quoted = false) {
return literalMap(Object.keys(obj).map(key => ({
key,
quoted,
value: obj[key],
})));
}
/**
* @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
*/
/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
const CLOSURE_TRANSLATION_PREFIX = 'MSG_';
/* Prefix for non-`goog.getMsg` i18n-related vars */
const TRANSLATION_PREFIX = 'I18N_';
/** Closure uses `goog.getMsg(message)` to lookup translations */
const GOOG_GET_MSG = 'goog.getMsg';
/** Name of the global variable that is used to determine if we use Closure translations or not */
const NG_I18N_CLOSURE_MODE = 'ngI18nClosureMode';
/** I18n separators for metadata **/
const I18N_MEANING_SEPARATOR = '|';
const I18N_ID_SEPARATOR = '@@';
/** Name of the i18n attributes **/
const I18N_ATTR = 'i18n';
const I18N_ATTR_PREFIX = 'i18n-';
/** Prefix of var expressions used in ICUs */
const I18N_ICU_VAR_PREFIX = 'VAR_';
/** Prefix of ICU expressions for post processing */
const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
/** Placeholder wrapper for i18n expressions **/
const I18N_PLACEHOLDER_SYMBOL = '�';
function i18nTranslationToDeclStmt(variable$1, closureVar, message, meta, params) {
const statements = [];
// var I18N_X;
statements.push(new DeclareVarStmt(variable$1.name, undefined, INFERRED_TYPE, null, variable$1.sourceSpan));
const args = [literal(message)];
if (params && Object.keys(params).length) {
args.push(mapLiteral(params, true));
}
// Closure JSDoc comments
const docStatements = i18nMetaToDocStmt(meta);
const thenStatements = docStatements ? [docStatements] : [];
const googFnCall = variable(GOOG_GET_MSG).callFn(args);
// const MSG_... = goog.getMsg(..);
thenStatements.push(closureVar.set(googFnCall).toConstDecl());
// I18N_X = MSG_...;
thenStatements.push(new ExpressionStatement(variable$1.set(closureVar)));
const localizeFnCall = importExpr(Identifiers$1.i18nLocalize).callFn(args);
// I18N_X = i18nLocalize(...);
const elseStatements = [new ExpressionStatement(variable$1.set(localizeFnCall))];
// if(ngI18nClosureMode) { ... } else { ... }
statements.push(ifStmt(variable(NG_I18N_CLOSURE_MODE), thenStatements, elseStatements));
return statements;
}
// Converts i18n meta information for a message (id, description, meaning)
// to a JsDoc statement formatted as expected by the Closure compiler.
function i18nMetaToDocStmt(meta) {
const tags = [];
if (meta.description) {
tags.push({ tagName: "desc" /* Desc */, text: meta.description });
}
if (meta.meaning) {
tags.push({ tagName: "meaning" /* Meaning */, text: meta.meaning });
}
return tags.length == 0 ? null : new JSDocCommentStmt(tags);
}
function isI18nAttribute(name) {
return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
}
function isI18nRootNode(meta) {
return meta instanceof Message;
}
function isSingleI18nIcu(meta) {
return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu$1;
}
function hasI18nAttrs(element) {
return element.attrs.some((attr) => isI18nAttribute(attr.name));
}
function metaFromI18nMessage(message, id = null) {
return {
id: typeof id === 'string' ? id : message.id || '',
meaning: message.meaning || '',
description: message.description || ''
};
}
function icuFromI18nMessage(message) {
return message.nodes[0];
}
function wrapI18nPlaceholder(content, contextId = 0) {
const blockId = contextId > 0 ? `:${contextId}` : '';
return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;
}
function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) {
if (!strings.length)
return '';
let acc = '';
const lastIdx = strings.length - 1;
for (let i = 0; i < lastIdx; i++) {
acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;
}
acc += strings[lastIdx];
return acc;
}
function getSeqNumberGenerator(startsAt = 0) {
let current = startsAt;
return () => current++;
}
function placeholdersToParams(placeholders) {
const params = {};
placeholders.forEach((values, key) => {
params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);
});
return params;
}
function updatePlaceholderMap(map, name, ...values) {
const current = map.get(name) || [];
current.push(...values);
map.set(name, current);
}
function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) {
const startIdx = bindingStartIndex;
const placeholders = new Map();
const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta;
if (node) {
node
.children
.filter((child) => child instanceof Placeholder)
.forEach((child, idx) => {
const content = wrapI18nPlaceholder(startIdx + idx, contextId);
updatePlaceholderMap(placeholders, child.name, content);
});
}
return placeholders;
}
function findIndex(items, callback) {
for (let i = 0; i < items.length; i++) {
if (callback(items[i])) {
return i;
}
}
return -1;
}
/**
* Parses i18n metas like:
* - "@@id",
* - "description[@@id]",
* - "meaning|description[@@id]"
* and returns an object with parsed output.
*
* @param meta String that represents i18n meta
* @returns Object with id, meaning and description fields
*/
function parseI18nMeta(meta) {
let id;
let meaning;
let description;
if (meta) {
const idIndex = meta.indexOf(I18N_ID_SEPARATOR);
const descIndex = meta.indexOf(I18N_MEANING_SEPARATOR);
let meaningAndDesc;
[meaningAndDesc, id] =
(idIndex > -1) ? [meta.slice(0, idIndex), meta.slice(idIndex + 2)] : [meta, ''];
[meaning, description] = (descIndex > -1) ?
[meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] :
['', meaningAndDesc];
}
return { id, meaning, description };
}
/**
* Converts internal placeholder names to public-facing format
* (for example to use in goog.getMsg call).
* Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.
*
* @param name The placeholder name that should be formatted
* @returns Formatted placeholder name
*/
function formatI18nPlaceholderName(name, useCamelCase = true) {
const publicName = toPublicName(name);
if (!useCamelCase) {
return publicName;
}
const chunks = publicName.split('_');
if (chunks.length === 1) {
// if no "_" found - just lowercase the value
return name.toLowerCase();
}
let postfix;
// eject last element if it's a number
if (/^\d+$/.test(chunks[chunks.length - 1])) {
postfix = chunks.pop();
}
let raw = chunks.shift().toLowerCase();
if (chunks.length) {
raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
}
return postfix ? `${raw}_${postfix}` : raw;
}
/**
* Generates a prefix for translation const name.
*
* @param extra Additional local prefix that should be injected into translation var name
* @returns Complete translation const prefix
*/
function getTranslationConstPrefix(extra) {
return `${CLOSURE_TRANSLATION_PREFIX}${extra}`.toUpperCase();
}
/**
* Generates translation declaration statements.
*
* @param variable Translation value reference
* @param closureVar Variable for Closure `goog.getMsg` calls
* @param message Text message to be translated
* @param meta Object that contains meta information (id, meaning and description)
* @param params Object with placeholders key-value pairs
* @param transformFn Optional transformation (post processing) function reference
* @returns Array of Statements that represent a given translation
*/
function getTranslationDeclStmts(variable, closureVar, message, meta, params = {}, transformFn) {
const statements = [];
statements.push(...i18nTranslationToDeclStmt(variable, closureVar, message, meta, params));
if (transformFn) {
statements.push(new ExpressionStatement(variable.set(transformFn(variable))));
}
return statements;
}
/**
* @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
*/
/**
* Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
* quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
* bot work in some cases when object keys are mangled by minifier.
*
* TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
* inputs that contain potentially unsafe chars.
*/
const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
/** Name of the temporary to use during data binding */
const TEMPORARY_NAME = '_t';
/** Name of the context parameter passed into a template function */
const CONTEXT_NAME = 'ctx';
/** Name of the RenderFlag passed into a template function */
const RENDER_FLAGS = 'rf';
/** The prefix reference variables */
const REFERENCE_PREFIX = '_r';
/** The name of the implicit context reference */
const IMPLICIT_REFERENCE = '$implicit';
/** Non bindable attribute name **/
const NON_BINDABLE_ATTR = 'ngNonBindable';
/**
* Creates an allocator for a temporary variable.
*
* A variable declaration is added to the statements the first time the allocator is invoked.
*/
function temporaryAllocator(statements, name) {
let temp = null;
return () => {
if (!temp) {
statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
temp = variable(name);
}
return temp;
};
}
function unsupported(feature) {
if (this) {
throw new Error(`Builder ${this.constructor.name} doesn't support ${feature} yet`);
}
throw new Error(`Feature ${feature} is not supported yet`);
}
function invalid$1(arg) {
throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
}
function asLiteral(value) {
if (Array.isArray(value)) {
return literalArr(value.map(asLiteral));
}
return literal(value, INFERRED_TYPE);
}
function conditionallyCreateMapObjectLiteral(keys, keepDeclared) {
if (Object.getOwnPropertyNames(keys).length > 0) {
return mapToExpression(keys, keepDeclared);
}
return null;
}
function mapToExpression(map, keepDeclared) {
return literalMap(Object.getOwnPropertyNames(map).map(key => {
// canonical syntax: `dirProp: publicProp`
// if there is no `:`, use dirProp = elProp
const value = map[key];
let declaredName;
let publicName;
let minifiedName;
if (Array.isArray(value)) {
[publicName, declaredName] = value;
}
else {
[declaredName, publicName] = splitAtColon(key, [key, value]);
}
minifiedName = declaredName;
return {
key: minifiedName,
// put quotes around keys that contain potentially unsafe characters
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
value: (keepDeclared && publicName !== declaredName) ?
literalArr([asLiteral(publicName), asLiteral(declaredName)]) :
asLiteral(publicName)
};
}));
}
/**
* Remove trailing null nodes as they are implied.
*/
function trimTrailingNulls(parameters) {
while (isNull(parameters[parameters.length - 1])) {
parameters.pop();
}
return parameters;
}
function getQueryPredicate(query, constantPool) {
if (Array.isArray(query.predicate)) {
let predicate = [];
query.predicate.forEach((selector) => {
// Each item in predicates array may contain strings with comma-separated refs
// (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them
// as separate array entities
const selectors = selector.split(',').map(token => literal(token.trim()));
predicate.push(...selectors);
});
return constantPool.getConstLiteral(literalArr(predicate), true);
}
else {
return query.predicate;
}
}
function noop() { }
class DefinitionMap {
constructor() {
this.values = [];
}
set(key, value) {
if (value) {
this.values.push({ key, value, quoted: false });
}
}
toLiteralMap() { return literalMap(this.values); }
}
/**
* Extract a map of properties to values for a given element or template node, which can be used
* by the directive matching machinery.
*
* @param elOrTpl the element or template in question
* @return an object set up for directive matching. For attributes on the element/template, this
* object maps a property name to its (static) value. For any bindings, this map simply maps the
* property name to an empty string.
*/
function getAttrsForDirectiveMatching(elOrTpl) {
const attributesMap = {};
if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
}
else {
elOrTpl.attributes.forEach(a => {
if (!isI18nAttribute(a.name)) {
attributesMap[a.name] = a.value;
}
});
elOrTpl.inputs.forEach(i => { attributesMap[i.name] = ''; });
elOrTpl.outputs.forEach(o => { attributesMap[o.name] = ''; });
}
return attributesMap;
}
/** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
function chainedInstruction(reference, calls, span) {
let expression = importExpr(reference, null, span);
if (calls.length > 0) {
for (let i = 0; i < calls.length; i++) {
expression = expression.callFn(calls[i], span);
}
}
else {
// Add a blank invocation, in case the `calls` array is empty.
expression = expression.callFn([], span);
}
return expression;
}
/**
* Gets the number of arguments expected to be passed to a generated instruction in the case of
* interpolation instructions.
* @param interpolation An interpolation ast
*/
function getInterpolationArgsLength(interpolation) {
const { expressions, strings } = interpolation;
if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
// If the interpolation has one interpolated value, but the prefix and suffix are both empty
// strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
// `textInterpolate`.
return 1;
}
else {
return expressions.length + strings.length;
}
}
/**
* @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 R3FactoryDelegateType;
(function (R3FactoryDelegateType) {
R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
R3FactoryDelegateType[R3FactoryDelegateType["Factory"] = 2] = "Factory";
})(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
/**
* Resolved type of a dependency.
*
* Occasionally, dependencies will have special significance which is known statically. In that
* case the `R3ResolvedDependencyType` informs the factory generator that a particular dependency
* should be generated specially (usually by calling a special injection function instead of the
* standard one).
*/
var R3ResolvedDependencyType;
(function (R3ResolvedDependencyType) {
/**
* A normal token dependency.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["Token"] = 0] = "Token";
/**
* The dependency is for an attribute.
*
* The token expression is a string representing the attribute name.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["Attribute"] = 1] = "Attribute";
/**
* Injecting the `ChangeDetectorRef` token. Needs special handling when injected into a pipe.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["ChangeDetectorRef"] = 2] = "ChangeDetectorRef";
})(R3ResolvedDependencyType || (R3ResolvedDependencyType = {}));
/**
* Construct a factory function expression for the given `R3FactoryMetadata`.
*/
function compileFactoryFunction(meta, isPipe = false) {
const t = variable('t');
const statements = [];
// The type to instantiate via constructor invocation. If there is no delegated factory, meaning
// this type is always created by constructor invocation, then this is the type-to-create
// parameter provided by the user (t) if specified, or the current type if not. If there is a
// delegated factory (which is used to create the current type) then this is only the type-to-
// create parameter (t).
const typeForCtor = !isDelegatedMetadata(meta) ? new BinaryOperatorExpr(BinaryOperator.Or, t, meta.type) : t;
let ctorExpr = null;
if (meta.deps !== null) {
// There is a constructor (either explicitly or implicitly defined).
if (meta.deps !== 'invalid') {
ctorExpr =
new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.injectFn, isPipe));
}
}
else {
const baseFactory = variable(`ɵ${meta.name}_BaseFactory`);
const getInheritedFactory = importExpr(Identifiers$1.getInheritedFactory);
const baseFactoryStmt = baseFactory.set(getInheritedFactory.callFn([meta.type])).toDeclStmt(INFERRED_TYPE, [
StmtModifier.Exported, StmtModifier.Final
]);
statements.push(baseFactoryStmt);
// There is no constructor, use the base class' factory to construct typeForCtor.
ctorExpr = baseFactory.callFn([typeForCtor]);
}
const ctorExprFinal = ctorExpr;
const body = [];
let retExpr = null;
function makeConditionalFactory(nonCtorExpr) {
const r = variable('r');
body.push(r.set(NULL_EXPR).toDeclStmt());
let ctorStmt = null;
if (ctorExprFinal !== null) {
ctorStmt = r.set(ctorExprFinal).toStmt();
}
else {
ctorStmt = makeErrorStmt(meta.name);
}
body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
return r;
}
if (isDelegatedMetadata(meta) && meta.delegateType === R3FactoryDelegateType.Factory) {
const delegateFactory = variable(`ɵ${meta.name}_BaseFactory`);
const getFactoryOf = importExpr(Identifiers$1.getFactoryOf);
if (meta.delegate.isEquivalent(meta.type)) {
throw new Error(`Illegal state: compiling factory that delegates to itself`);
}
const delegateFactoryStmt = delegateFactory.set(getFactoryOf.callFn([meta.delegate])).toDeclStmt(INFERRED_TYPE, [
StmtModifier.Exported, StmtModifier.Final
]);
statements.push(delegateFactoryStmt);
retExpr = makeConditionalFactory(delegateFactory.callFn([]));
}
else if (isDelegatedMetadata(meta)) {
// This type is created with a delegated factory. If a type parameter is not specified, call
// the factory instead.
const delegateArgs = injectDependencies(meta.delegateDeps, meta.injectFn, isPipe);
// Either call `new delegate(...)` or `delegate(...)` depending on meta.useNewForDelegate.
const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ?
InstantiateExpr :
InvokeFunctionExpr)(meta.delegate, delegateArgs);
retExpr = makeConditionalFactory(factoryExpr);
}
else if (isExpressionFactoryMetadata(meta)) {
// TODO(alxhub): decide whether to lower the value here or in the caller
retExpr = makeConditionalFactory(meta.expression);
}
else {
retExpr = ctorExpr;
}
if (retExpr !== null) {
body.push(new ReturnStatement(retExpr));
}
else {
body.push(makeErrorStmt(meta.name));
}
return {
factory: fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`),
statements,
};
}
function injectDependencies(deps, injectFn, isPipe) {
return deps.map(dep => compileInjectDependency(dep, injectFn, isPipe));
}
function compileInjectDependency(dep, injectFn, isPipe) {
// Interpret the dependency according to its resolved type.
switch (dep.resolved) {
case R3ResolvedDependencyType.Token:
case R3ResolvedDependencyType.ChangeDetectorRef:
// Build up the injection flags according to the metadata.
const flags = 0 /* Default */ | (dep.self ? 2 /* Self */ : 0) |
(dep.skipSelf ? 4 /* SkipSelf */ : 0) | (dep.host ? 1 /* Host */ : 0) |
(dep.optional ? 8 /* Optional */ : 0);
// If this dependency is optional or otherwise has non-default flags, then additional
// parameters describing how to inject the dependency must be passed to the inject function
// that's being used.
let flagsParam = (flags !== 0 /* Default */ || dep.optional) ? literal(flags) : null;
// We have a separate instruction for injecting ChangeDetectorRef into a pipe.
if (isPipe && dep.resolved === R3ResolvedDependencyType.ChangeDetectorRef) {
return importExpr(Identifiers$1.injectPipeChangeDetectorRef).callFn(flagsParam ? [flagsParam] : []);
}
// Build up the arguments to the injectFn call.
const injectArgs = [dep.token];
if (flagsParam) {
injectArgs.push(flagsParam);
}
return importExpr(injectFn).callFn(injectArgs);
case R3ResolvedDependencyType.Attribute:
// In the case of attributes, the attribute name in question is given as the token.
return importExpr(Identifiers$1.injectAttribute).callFn([dep.token]);
default:
return unsupported(`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
}
}
/**
* A helper function useful for extracting `R3DependencyMetadata` from a Render2
* `CompileTypeMetadata` instance.
*/
function dependenciesFromGlobalMetadata(type, outputCtx, reflector) {
// Use the `CompileReflector` to look up references to some well-known Angular types. These will
// be compared with the token to statically determine whether the token has significance to
// Angular, and set the correct `R3ResolvedDependencyType` as a result.
const injectorRef = reflector.resolveExternalReference(Identifiers.Injector);
// Iterate through the type's DI dependencies and produce `R3DependencyMetadata` for each of them.
const deps = [];
for (let dependency of type.diDeps) {
if (dependency.token) {
const tokenRef = tokenReference(dependency.token);
let resolved = dependency.isAttribute ?
R3ResolvedDependencyType.Attribute :
R3ResolvedDependencyType.Token;
// In the case of most dependencies, the token will be a reference to a type. Sometimes,
// however, it can be a string, in the case of older Angular code or @Attribute injection.
const token = tokenRef instanceof StaticSymbol ? outputCtx.importExpr(tokenRef) : literal(tokenRef);
// Construct the dependency.
deps.push({
token,
resolved,
host: !!dependency.isHost,
optional: !!dependency.isOptional,
self: !!dependency.isSelf,
skipSelf: !!dependency.isSkipSelf,
});
}
else {
unsupported('dependency without a token');
}
}
return deps;
}
function makeErrorStmt(name) {
return new ThrowStmt(new InstantiateExpr(new ReadVarExpr('Error'), [
literal(`${name} has a constructor which is not compatible with Dependency Injection. It should probably not be @Injectable().`)
]));
}
function isDelegatedMetadata(meta) {
return meta.delegateType !== undefined;
}
function isExpressionFactoryMetadata(meta) {
return meta.expression !== undefined;
}
/**
* @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
*/
/**
* Convert an object map with `Expression` values into a `LiteralMapExpr`.
*/
function mapToMapExpression(map) {
const result = Object.keys(map).map(key => ({ key, value: map[key], quoted: false }));
return literalMap(result);
}
/**
* Convert metadata into an `Expression` in the given `OutputContext`.
*
* This operation will handle arrays, references to symbols, or literal `null` or `undefined`.
*/
function convertMetaToOutput(meta, ctx) {
if (Array.isArray(meta)) {
return literalArr(meta.map(entry => convertMetaToOutput(entry, ctx)));
}
if (meta instanceof StaticSymbol) {
return ctx.importExpr(meta);
}
if (meta == null) {
return literal(meta);
}
throw new Error(`Internal error: Unsupported or unknown metadata: ${meta}`);
}
function typeWithParameters(type, numParams) {
let params = null;
if (numParams > 0) {
params = [];
for (let i = 0; i < numParams; i++) {
params.push(DYNAMIC_TYPE);
}
}
return expressionType(type, null, params);
}
const ANIMATE_SYMBOL_PREFIX = '@';
function prepareSyntheticPropertyName(name) {
return `${ANIMATE_SYMBOL_PREFIX}${name}`;
}
function prepareSyntheticListenerName(name, phase) {
return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
}
function isSyntheticPropertyOrListener(name) {
return name.charAt(0) == ANIMATE_SYMBOL_PREFIX;
}
function getSyntheticPropertyName(name) {
// this will strip out listener phase values...
// @foo.start => @foo
const i = name.indexOf('.');
name = i > 0 ? name.substring(0, i) : name;
if (name.charAt(0) !== ANIMATE_SYMBOL_PREFIX) {
name = ANIMATE_SYMBOL_PREFIX + name;
}
return name;
}
function prepareSyntheticListenerFunctionName(name, phase) {
return `animation_${name}_${phase}`;
}
/**
* @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
*/
function compileInjectable(meta) {
let result = null;
const factoryMeta = {
name: meta.name,
type: meta.type,
deps: meta.ctorDeps,
injectFn: Identifiers.inject,
};
if (meta.useClass !== undefined) {
// meta.useClass has two modes of operation. Either deps are specified, in which case `new` is
// used to instantiate the class with dependencies injected, or deps are not specified and
// the factory of the class is used to instantiate it.
//
// A special case exists for useClass: Type where Type is the injectable type itself and no
// deps are specified, in which case 'useClass' is effectively ignored.
const useClassOnSelf = meta.useClass.isEquivalent(meta.type);
let deps = undefined;
if (meta.userDeps !== undefined) {
deps = meta.userDeps;
}
if (deps !== undefined) {
// factory: () => new meta.useClass(...deps)
result = compileFactoryFunction(Object.assign({}, factoryMeta, { delegate: meta.useClass, delegateDeps: deps, delegateType: R3FactoryDelegateType.Class }));
}
else if (useClassOnSelf) {
result = compileFactoryFunction(factoryMeta);
}
else {
result = compileFactoryFunction(Object.assign({}, factoryMeta, { delegate: meta.useClass, delegateType: R3FactoryDelegateType.Factory }));
}
}
else if (meta.useFactory !== undefined) {
result = compileFactoryFunction(Object.assign({}, factoryMeta, { delegate: meta.useFactory, delegateDeps: meta.userDeps || [], delegateType: R3FactoryDelegateType.Function }));
}
else if (meta.useValue !== undefined) {
// Note: it's safe to use `meta.useValue` instead of the `USE_VALUE in meta` check used for
// client code because meta.useValue is an Expression which will be defined even if the actual
// value is undefined.
result = compileFactoryFunction(Object.assign({}, factoryMeta, { expression: meta.useValue }));
}
else if (meta.useExisting !== undefined) {
// useExisting is an `inject` call on the existing token.
result = compileFactoryFunction(Object.assign({}, factoryMeta, { expression: importExpr(Identifiers.inject).callFn([meta.useExisting]) }));
}
else {
result = compileFactoryFunction(factoryMeta);
}
const token = meta.type;
const providedIn = meta.providedIn;
const expression = importExpr(Identifiers.ɵɵdefineInjectable).callFn([mapToMapExpression({ token, factory: result.factory, providedIn })]);
const type = new ExpressionType(importExpr(Identifiers.InjectableDef, [typeWithParameters(meta.type, meta.typeArgumentCount)]));
return {
expression,
type,
statements: result.statements,
};
}
/**
* @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
*/
function assertArrayOfStrings(identifier, value) {
if (value == null) {
return;
}
if (!Array.isArray(value)) {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
for (let i = 0; i < value.length; i += 1) {
if (typeof value[i] !== 'string') {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
}
}
const UNUSABLE_INTERPOLATION_REGEXPS = [
/^\s*$/,
/[<>]/,
/^[{}]$/,
/&(#|[a-z])/i,
/^\/\//,
];
function assertInterpolationSymbols(identifier, value) {
if (value != null && !(Array.isArray(value) && value.length == 2)) {
throw new Error(`Expected '${identifier}' to be an array, [start, end].`);
}
else if (value != null) {
const start = value[0];
const end = value[1];
// Check for unusable interpolation symbols
UNUSABLE_INTERPOLATION_REGEXPS.forEach(regexp => {
if (regexp.test(start) || regexp.test(end)) {
throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`);
}
});
}
}
/**
* @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 InterpolationConfig {
constructor(start, end) {
this.start = start;
this.end = end;
}
static fromArray(markers) {
if (!markers) {
return DEFAULT_INTERPOLATION_CONFIG;
}
assertInterpolationSymbols('interpolation', markers);
return new InterpolationConfig(markers[0], markers[1]);
}
}
const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}');
/**
* @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
*/
// https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
const VERSION = 3;
const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
class SourceMapGenerator {
constructor(file = null) {
this.file = file;
this.sourcesContent = new Map();
this.lines = [];
this.lastCol0 = 0;
this.hasMappings = false;
}
// The content is `null` when the content is expected to be loaded using the URL
addSource(url, content = null) {
if (!this.sourcesContent.has(url)) {
this.sourcesContent.set(url, content);
}
return this;
}
addLine() {
this.lines.push([]);
this.lastCol0 = 0;
return this;
}
addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
if (!this.currentLine) {
throw new Error(`A line must be added before mappings can be added`);
}
if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
throw new Error(`Unknown source file "${sourceUrl}"`);
}
if (col0 == null) {
throw new Error(`The column in the generated code must be provided`);
}
if (col0 < this.lastCol0) {
throw new Error(`Mapping should be added in output order`);
}
if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
throw new Error(`The source location must be provided when a source url is provided`);
}
this.hasMappings = true;
this.lastCol0 = col0;
this.currentLine.push({ col0, sourceUrl, sourceLine0, sourceCol0 });
return this;
}
get currentLine() { return this.lines.slice(-1)[0]; }
toJSON() {
if (!this.hasMappings) {
return null;
}
const sourcesIndex = new Map();
const sources = [];
const sourcesContent = [];
Array.from(this.sourcesContent.keys()).forEach((url, i) => {
sourcesIndex.set(url, i);
sources.push(url);
sourcesContent.push(this.sourcesContent.get(url) || null);
});
let mappings = '';
let lastCol0 = 0;
let lastSourceIndex = 0;
let lastSourceLine0 = 0;
let lastSourceCol0 = 0;
this.lines.forEach(segments => {
lastCol0 = 0;
mappings += segments
.map(segment => {
// zero-based starting column of the line in the generated code
let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
lastCol0 = segment.col0;
if (segment.sourceUrl != null) {
// zero-based index into the “sources” list
segAsStr +=
toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
lastSourceIndex = sourcesIndex.get(segment.sourceUrl);
// the zero-based starting line in the original source
segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
lastSourceLine0 = segment.sourceLine0;
// the zero-based starting column in the original source
segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
lastSourceCol0 = segment.sourceCol0;
}
return segAsStr;
})
.join(',');
mappings += ';';
});
mappings = mappings.slice(0, -1);
return {
'file': this.file || '',
'version': VERSION,
'sourceRoot': '',
'sources': sources,
'sourcesContent': sourcesContent,
'mappings': mappings,
};
}
toJsComment() {
return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) :
'';
}
}
function toBase64String(value) {
let b64 = '';
value = utf8Encode(value);
for (let i = 0; i < value.length;) {
const i1 = value.charCodeAt(i++);
const i2 = value.charCodeAt(i++);
const i3 = value.charCodeAt(i++);
b64 += toBase64Digit(i1 >> 2);
b64 += toBase64Digit(((i1 & 3) << 4) | (isNaN(i2) ? 0 : i2 >> 4));
b64 += isNaN(i2) ? '=' : toBase64Digit(((i2 & 15) << 2) | (i3 >> 6));
b64 += isNaN(i2) || isNaN(i3) ? '=' : toBase64Digit(i3 & 63);
}
return b64;
}
function toBase64VLQ(value) {
value = value < 0 ? ((-value) << 1) + 1 : value << 1;
let out = '';
do {
let digit = value & 31;
value = value >> 5;
if (value > 0) {
digit = digit | 32;
}
out += toBase64Digit(digit);
} while (value > 0);
return out;
}
const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function toBase64Digit(value) {
if (value < 0 || value >= 64) {
throw new Error(`Can only encode value in the range [0, 63]`);
}
return B64_DIGITS[value];
}
/**
* @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 _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
const _INDENT_WITH = ' ';
const CATCH_ERROR_VAR$1 = variable('error', null, null);
const CATCH_STACK_VAR$1 = variable('stack', null, null);
class _EmittedLine {
constructor(indent) {
this.indent = indent;
this.partsLength = 0;
this.parts = [];
this.srcSpans = [];
}
}
class EmitterVisitorContext {
constructor(_indent) {
this._indent = _indent;
this._classes = [];
this._preambleLineCount = 0;
this._lines = [new _EmittedLine(_indent)];
}
static createRoot() { return new EmitterVisitorContext(0); }
get _currentLine() { return this._lines[this._lines.length - 1]; }
println(from, lastPart = '') {
this.print(from || null, lastPart, true);
}
lineIsEmpty() { return this._currentLine.parts.length === 0; }
lineLength() {
return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
}
print(from, part, newLine = false) {
if (part.length > 0) {
this._currentLine.parts.push(part);
this._currentLine.partsLength += part.length;
this._currentLine.srcSpans.push(from && from.sourceSpan || null);
}
if (newLine) {
this._lines.push(new _EmittedLine(this._indent));
}
}
removeEmptyLastLine() {
if (this.lineIsEmpty()) {
this._lines.pop();
}
}
incIndent() {
this._indent++;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
decIndent() {
this._indent--;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
pushClass(clazz) { this._classes.push(clazz); }
popClass() { return this._classes.pop(); }
get currentClass() {
return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
}
toSource() {
return this.sourceLines
.map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '')
.join('\n');
}
toSourceMapGenerator(genFilePath, startsAtLine = 0) {
const map = new SourceMapGenerator(genFilePath);
let firstOffsetMapped = false;
const mapFirstOffsetIfNeeded = () => {
if (!firstOffsetMapped) {
// Add a single space so that tools won't try to load the file from disk.
// Note: We are using virtual urls like `ng:///`, so we have to
// provide a content here.
map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
firstOffsetMapped = true;
}
};
for (let i = 0; i < startsAtLine; i++) {
map.addLine();
mapFirstOffsetIfNeeded();
}
this.sourceLines.forEach((line, lineIdx) => {
map.addLine();
const spans = line.srcSpans;
const parts = line.parts;
let col0 = line.indent * _INDENT_WITH.length;
let spanIdx = 0;
// skip leading parts without source spans
while (spanIdx < spans.length && !spans[spanIdx]) {
col0 += parts[spanIdx].length;
spanIdx++;
}
if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
firstOffsetMapped = true;
}
else {
mapFirstOffsetIfNeeded();
}
while (spanIdx < spans.length) {
const span = spans[spanIdx];
const source = span.start.file;
const sourceLine = span.start.line;
const sourceCol = span.start.col;
map.addSource(source.url, source.content)
.addMapping(col0, source.url, sourceLine, sourceCol);
col0 += parts[spanIdx].length;
spanIdx++;
// assign parts without span or the same span to the previous segment
while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
col0 += parts[spanIdx].length;
spanIdx++;
}
}
});
return map;
}
setPreambleLineCount(count) { return this._preambleLineCount = count; }
spanOf(line, column) {
const emittedLine = this._lines[line - this._preambleLineCount];
if (emittedLine) {
let columnsLeft = column - _createIndent(emittedLine.indent).length;
for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
const part = emittedLine.parts[partIndex];
if (part.length > columnsLeft) {
return emittedLine.srcSpans[partIndex];
}
columnsLeft -= part.length;
}
}
return null;
}
get sourceLines() {
if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
return this._lines.slice(0, -1);
}
return this._lines;
}
}
class AbstractEmitterVisitor {
constructor(_escapeDollarInStrings) {
this._escapeDollarInStrings = _escapeDollarInStrings;
}
visitExpressionStmt(stmt, ctx) {
stmt.expr.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitReturnStmt(stmt, ctx) {
ctx.print(stmt, `return `);
stmt.value.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitIfStmt(stmt, ctx) {
ctx.print(stmt, `if (`);
stmt.condition.visitExpression(this, ctx);
ctx.print(stmt, `) {`);
const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
if (stmt.trueCase.length <= 1 && !hasElseCase) {
ctx.print(stmt, ` `);
this.visitAllStatements(stmt.trueCase, ctx);
ctx.removeEmptyLastLine();
ctx.print(stmt, ` `);
}
else {
ctx.println();
ctx.incIndent();
this.visitAllStatements(stmt.trueCase, ctx);
ctx.decIndent();
if (hasElseCase) {
ctx.println(stmt, `} else {`);
ctx.incIndent();
this.visitAllStatements(stmt.falseCase, ctx);
ctx.decIndent();
}
}
ctx.println(stmt, `}`);
return null;
}
visitThrowStmt(stmt, ctx) {
ctx.print(stmt, `throw `);
stmt.error.visitExpression(this, ctx);
ctx.println(stmt, `;`);
return null;
}
visitCommentStmt(stmt, ctx) {
if (stmt.multiline) {
ctx.println(stmt, `/* ${stmt.comment} */`);
}
else {
stmt.comment.split('\n').forEach((line) => { ctx.println(stmt, `// ${line}`); });
}
return null;
}
visitJSDocCommentStmt(stmt, ctx) {
ctx.println(stmt, `/*${stmt.toString()}*/`);
return null;
}
visitWriteVarExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
ctx.print(expr, `${expr.name} = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitWriteKeyExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
expr.receiver.visitExpression(this, ctx);
ctx.print(expr, `[`);
expr.index.visitExpression(this, ctx);
ctx.print(expr, `] = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitWritePropExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
expr.receiver.visitExpression(this, ctx);
ctx.print(expr, `.${expr.name} = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitInvokeMethodExpr(expr, ctx) {
expr.receiver.visitExpression(this, ctx);
let name = expr.name;
if (expr.builtin != null) {
name = this.getBuiltinMethodName(expr.builtin);
if (name == null) {
// some builtins just mean to skip the call.
return null;
}
}
ctx.print(expr, `.${name}(`);
this.visitAllExpressions(expr.args, ctx, `,`);
ctx.print(expr, `)`);
return null;
}
visitInvokeFunctionExpr(expr, ctx) {
expr.fn.visitExpression(this, ctx);
ctx.print(expr, `(`);
this.visitAllExpressions(expr.args, ctx, ',');
ctx.print(expr, `)`);
return null;
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
}
visitTypeofExpr(expr, ctx) {
ctx.print(expr, 'typeof ');
expr.expr.visitExpression(this, ctx);
}
visitReadVarExpr(ast, ctx) {
let varName = ast.name;
if (ast.builtin != null) {
switch (ast.builtin) {
case BuiltinVar.Super:
varName = 'super';
break;
case BuiltinVar.This:
varName = 'this';
break;
case BuiltinVar.CatchError:
varName = CATCH_ERROR_VAR$1.name;
break;
case BuiltinVar.CatchStack:
varName = CATCH_STACK_VAR$1.name;
break;
default:
throw new Error(`Unknown builtin variable ${ast.builtin}`);
}
}
ctx.print(ast, varName);
return null;
}
visitInstantiateExpr(ast, ctx) {
ctx.print(ast, `new `);
ast.classExpr.visitExpression(this, ctx);
ctx.print(ast, `(`);
this.visitAllExpressions(ast.args, ctx, ',');
ctx.print(ast, `)`);
return null;
}
visitLiteralExpr(ast, ctx) {
const value = ast.value;
if (typeof value === 'string') {
ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
}
else {
ctx.print(ast, `${value}`);
}
return null;
}
visitConditionalExpr(ast, ctx) {
ctx.print(ast, `(`);
ast.condition.visitExpression(this, ctx);
ctx.print(ast, '? ');
ast.trueCase.visitExpression(this, ctx);
ctx.print(ast, ': ');
ast.falseCase.visitExpression(this, ctx);
ctx.print(ast, `)`);
return null;
}
visitNotExpr(ast, ctx) {
ctx.print(ast, '!');
ast.condition.visitExpression(this, ctx);
return null;
}
visitAssertNotNullExpr(ast, ctx) {
ast.condition.visitExpression(this, ctx);
return null;
}
visitBinaryOperatorExpr(ast, ctx) {
let opStr;
switch (ast.operator) {
case BinaryOperator.Equals:
opStr = '==';
break;
case BinaryOperator.Identical:
opStr = '===';
break;
case BinaryOperator.NotEquals:
opStr = '!=';
break;
case BinaryOperator.NotIdentical:
opStr = '!==';
break;
case BinaryOperator.And:
opStr = '&&';
break;
case BinaryOperator.BitwiseAnd:
opStr = '&';
break;
case BinaryOperator.Or:
opStr = '||';
break;
case BinaryOperator.Plus:
opStr = '+';
break;
case BinaryOperator.Minus:
opStr = '-';
break;
case BinaryOperator.Divide:
opStr = '/';
break;
case BinaryOperator.Multiply:
opStr = '*';
break;
case BinaryOperator.Modulo:
opStr = '%';
break;
case BinaryOperator.Lower:
opStr = '<';
break;
case BinaryOperator.LowerEquals:
opStr = '<=';
break;
case BinaryOperator.Bigger:
opStr = '>';
break;
case BinaryOperator.BiggerEquals:
opStr = '>=';
break;
default:
throw new Error(`Unknown operator ${ast.operator}`);
}
if (ast.parens)
ctx.print(ast, `(`);
ast.lhs.visitExpression(this, ctx);
ctx.print(ast, ` ${opStr} `);
ast.rhs.visitExpression(this, ctx);
if (ast.parens)
ctx.print(ast, `)`);
return null;
}
visitReadPropExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `.`);
ctx.print(ast, ast.name);
return null;
}
visitReadKeyExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `[`);
ast.index.visitExpression(this, ctx);
ctx.print(ast, `]`);
return null;
}
visitLiteralArrayExpr(ast, ctx) {
ctx.print(ast, `[`);
this.visitAllExpressions(ast.entries, ctx, ',');
ctx.print(ast, `]`);
return null;
}
visitLiteralMapExpr(ast, ctx) {
ctx.print(ast, `{`);
this.visitAllObjects(entry => {
ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
entry.value.visitExpression(this, ctx);
}, ast.entries, ctx, ',');
ctx.print(ast, `}`);
return null;
}
visitCommaExpr(ast, ctx) {
ctx.print(ast, '(');
this.visitAllExpressions(ast.parts, ctx, ',');
ctx.print(ast, ')');
return null;
}
visitAllExpressions(expressions, ctx, separator) {
this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
}
visitAllObjects(handler, expressions, ctx, separator) {
let incrementedIndent = false;
for (let i = 0; i < expressions.length; i++) {
if (i > 0) {
if (ctx.lineLength() > 80) {
ctx.print(null, separator, true);
if (!incrementedIndent) {
// continuation are marked with double indent.
ctx.incIndent();
ctx.incIndent();
incrementedIndent = true;
}
}
else {
ctx.print(null, separator, false);
}
}
handler(expressions[i]);
}
if (incrementedIndent) {
// continuation are marked with double indent.
ctx.decIndent();
ctx.decIndent();
}
}
visitAllStatements(statements, ctx) {
statements.forEach((stmt) => stmt.visitStatement(this, ctx));
}
}
function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
if (input == null) {
return null;
}
const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
}
else if (match[0] == '\n') {
return '\\n';
}
else if (match[0] == '\r') {
return '\\r';
}
else {
return `\\${match[0]}`;
}
});
const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
return requiresQuotes ? `'${body}'` : body;
}
function _createIndent(count) {
let res = '';
for (let i = 0; i < count; i++) {
res += _INDENT_WITH;
}
return res;
}
/**
* @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 AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
constructor() { super(false); }
visitDeclareClassStmt(stmt, ctx) {
ctx.pushClass(stmt);
this._visitClassConstructor(stmt, ctx);
if (stmt.parent != null) {
ctx.print(stmt, `${stmt.name}.prototype = Object.create(`);
stmt.parent.visitExpression(this, ctx);
ctx.println(stmt, `.prototype);`);
}
stmt.getters.forEach((getter) => this._visitClassGetter(stmt, getter, ctx));
stmt.methods.forEach((method) => this._visitClassMethod(stmt, method, ctx));
ctx.popClass();
return null;
}
_visitClassConstructor(stmt, ctx) {
ctx.print(stmt, `function ${stmt.name}(`);
if (stmt.constructorMethod != null) {
this._visitParams(stmt.constructorMethod.params, ctx);
}
ctx.println(stmt, `) {`);
ctx.incIndent();
if (stmt.constructorMethod != null) {
if (stmt.constructorMethod.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(stmt.constructorMethod.body, ctx);
}
}
ctx.decIndent();
ctx.println(stmt, `}`);
}
_visitClassGetter(stmt, getter, ctx) {
ctx.println(stmt, `Object.defineProperty(${stmt.name}.prototype, '${getter.name}', { get: function() {`);
ctx.incIndent();
if (getter.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(getter.body, ctx);
}
ctx.decIndent();
ctx.println(stmt, `}});`);
}
_visitClassMethod(stmt, method, ctx) {
ctx.print(stmt, `${stmt.name}.prototype.${method.name} = function(`);
this._visitParams(method.params, ctx);
ctx.println(stmt, `) {`);
ctx.incIndent();
if (method.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(method.body, ctx);
}
ctx.decIndent();
ctx.println(stmt, `};`);
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Cannot emit a WrappedNodeExpr in Javascript.');
}
visitReadVarExpr(ast, ctx) {
if (ast.builtin === BuiltinVar.This) {
ctx.print(ast, 'self');
}
else if (ast.builtin === BuiltinVar.Super) {
throw new Error(`'super' needs to be handled at a parent ast node, not at the variable level!`);
}
else {
super.visitReadVarExpr(ast, ctx);
}
return null;
}
visitDeclareVarStmt(stmt, ctx) {
ctx.print(stmt, `var ${stmt.name}`);
if (stmt.value) {
ctx.print(stmt, ' = ');
stmt.value.visitExpression(this, ctx);
}
ctx.println(stmt, `;`);
return null;
}
visitCastExpr(ast, ctx) {
ast.value.visitExpression(this, ctx);
return null;
}
visitInvokeFunctionExpr(expr, ctx) {
const fnExpr = expr.fn;
if (fnExpr instanceof ReadVarExpr && fnExpr.builtin === BuiltinVar.Super) {
ctx.currentClass.parent.visitExpression(this, ctx);
ctx.print(expr, `.call(this`);
if (expr.args.length > 0) {
ctx.print(expr, `, `);
this.visitAllExpressions(expr.args, ctx, ',');
}
ctx.print(expr, `)`);
}
else {
super.visitInvokeFunctionExpr(expr, ctx);
}
return null;
}
visitFunctionExpr(ast, ctx) {
ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);
this._visitParams(ast.params, ctx);
ctx.println(ast, `) {`);
ctx.incIndent();
this.visitAllStatements(ast.statements, ctx);
ctx.decIndent();
ctx.print(ast, `}`);
return null;
}
visitDeclareFunctionStmt(stmt, ctx) {
ctx.print(stmt, `function ${stmt.name}(`);
this._visitParams(stmt.params, ctx);
ctx.println(stmt, `) {`);
ctx.incIndent();
this.visitAllStatements(stmt.statements, ctx);
ctx.decIndent();
ctx.println(stmt, `}`);
return null;
}
visitTryCatchStmt(stmt, ctx) {
ctx.println(stmt, `try {`);
ctx.incIndent();
this.visitAllStatements(stmt.bodyStmts, ctx);
ctx.decIndent();
ctx.println(stmt, `} catch (${CATCH_ERROR_VAR$1.name}) {`);
ctx.incIndent();
const catchStmts = [CATCH_STACK_VAR$1.set(CATCH_ERROR_VAR$1.prop('stack')).toDeclStmt(null, [
StmtModifier.Final
])].concat(stmt.catchStmts);
this.visitAllStatements(catchStmts, ctx);
ctx.decIndent();
ctx.println(stmt, `}`);
return null;
}
_visitParams(params, ctx) {
this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ',');
}
getBuiltinMethodName(method) {
let name;
switch (method) {
case BuiltinMethod.ConcatArray:
name = 'concat';
break;
case BuiltinMethod.SubscribeObservable:
name = 'subscribe';
break;
case BuiltinMethod.Bind:
name = 'bind';
break;
default:
throw new Error(`Unknown builtin method: ${method}`);
}
return name;
}
}
/**
* @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 helper class to manage the evaluation of JIT generated code.
*/
class JitEvaluator {
/**
*
* @param sourceUrl The URL of the generated code.
* @param statements An array of Angular statement AST nodes to be evaluated.
* @param reflector A helper used when converting the statements to executable code.
* @param createSourceMaps If true then create a source-map for the generated code and include it
* inline as a source-map comment.
* @returns A map of all the variables in the generated code.
*/
evaluateStatements(sourceUrl, statements, reflector, createSourceMaps) {
const converter = new JitEmitterVisitor(reflector);
const ctx = EmitterVisitorContext.createRoot();
// Ensure generated code is in strict mode
if (statements.length > 0 && !isUseStrictStatement(statements[0])) {
statements = [
literal('use strict').toStmt(),
...statements,
];
}
converter.visitAllStatements(statements, ctx);
converter.createReturnStmt(ctx);
return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
}
/**
* Evaluate a piece of JIT generated code.
* @param sourceUrl The URL of this generated code.
* @param ctx A context object that contains an AST of the code to be evaluated.
* @param vars A map containing the names and values of variables that the evaluated code might
* reference.
* @param createSourceMap If true then create a source-map for the generated code and include it
* inline as a source-map comment.
* @returns The result of evaluating the code.
*/
evaluateCode(sourceUrl, ctx, vars, createSourceMap) {
let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
const fnArgNames = [];
const fnArgValues = [];
for (const argName in vars) {
fnArgValues.push(vars[argName]);
fnArgNames.push(argName);
}
if (createSourceMap) {
// using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
// E.g. ```
// function anonymous(a,b,c
// /**/) { ... }```
// We don't want to hard code this fact, so we auto detect it via an empty function first.
const emptyFn = new Function(...fnArgNames.concat('return null;')).toString();
const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
}
const fn = new Function(...fnArgNames.concat(fnBody));
return this.executeFunction(fn, fnArgValues);
}
/**
* Execute a JIT generated function by calling it.
*
* This method can be overridden in tests to capture the functions that are generated
* by this `JitEvaluator` class.
*
* @param fn A function to execute.
* @param args The arguments to pass to the function being executed.
* @returns The return value of the executed function.
*/
executeFunction(fn, args) { return fn(...args); }
}
/**
* An Angular AST visitor that converts AST nodes into executable JavaScript code.
*/
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
constructor(reflector) {
super();
this.reflector = reflector;
this._evalArgNames = [];
this._evalArgValues = [];
this._evalExportedVars = [];
}
createReturnStmt(ctx) {
const stmt = new ReturnStatement(new LiteralMapExpr(this._evalExportedVars.map(resultVar => new LiteralMapEntry(resultVar, variable(resultVar), false))));
stmt.visitStatement(this, ctx);
}
getArgs() {
const result = {};
for (let i = 0; i < this._evalArgNames.length; i++) {
result[this._evalArgNames[i]] = this._evalArgValues[i];
}
return result;
}
visitExternalExpr(ast, ctx) {
this._emitReferenceToExternal(ast, this.reflector.resolveExternalReference(ast.value), ctx);
return null;
}
visitWrappedNodeExpr(ast, ctx) {
this._emitReferenceToExternal(ast, ast.node, ctx);
return null;
}
visitDeclareVarStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareVarStmt(stmt, ctx);
}
visitDeclareFunctionStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareFunctionStmt(stmt, ctx);
}
visitDeclareClassStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareClassStmt(stmt, ctx);
}
_emitReferenceToExternal(ast, value, ctx) {
let id = this._evalArgValues.indexOf(value);
if (id === -1) {
id = this._evalArgValues.length;
this._evalArgValues.push(value);
const name = identifierName({ reference: value }) || 'val';
this._evalArgNames.push(`jit_${name}_${id}`);
}
ctx.print(ast, this._evalArgNames[id]);
}
}
function isUseStrictStatement(statement) {
return statement.isEquivalent(literal('use strict').toStmt());
}
/**
* @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
*/
/**
* Implementation of `CompileReflector` which resolves references to @angular/core
* symbols at runtime, according to a consumer-provided mapping.
*
* Only supports `resolveExternalReference`, all other methods throw.
*/
class R3JitReflector {
constructor(context) {
this.context = context;
}
resolveExternalReference(ref) {
// This reflector only handles @angular/core imports.
if (ref.moduleName !== '@angular/core') {
throw new Error(`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`);
}
if (!this.context.hasOwnProperty(ref.name)) {
throw new Error(`No value provided for @angular/core symbol '${ref.name}'.`);
}
return this.context[ref.name];
}
parameters(typeOrFunc) { throw new Error('Not implemented.'); }
annotations(typeOrFunc) { throw new Error('Not implemented.'); }
shallowAnnotations(typeOrFunc) { throw new Error('Not implemented.'); }
tryAnnotations(typeOrFunc) { throw new Error('Not implemented.'); }
propMetadata(typeOrFunc) { throw new Error('Not implemented.'); }
hasLifecycleHook(type, lcProperty) { throw new Error('Not implemented.'); }
guards(typeOrFunc) { throw new Error('Not implemented.'); }
componentModuleUrl(type, cmpMetadata) { throw new Error('Not implemented.'); }
}
/**
* @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
*/
/**
* Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
*/
function compileNgModule(meta) {
const { type: moduleType, bootstrap, declarations, imports, exports, schemas, containsForwardDecls, emitInline, id } = meta;
const additionalStatements = [];
const definitionMap = {
type: moduleType
};
// Only generate the keys in the metadata if the arrays have values.
if (bootstrap.length) {
definitionMap.bootstrap = refsToArray(bootstrap, containsForwardDecls);
}
// If requested to emit scope information inline, pass the declarations, imports and exports to
// the `ɵɵdefineNgModule` call. The JIT compilation uses this.
if (emitInline) {
if (declarations.length) {
definitionMap.declarations = refsToArray(declarations, containsForwardDecls);
}
if (imports.length) {
definitionMap.imports = refsToArray(imports, containsForwardDecls);
}
if (exports.length) {
definitionMap.exports = refsToArray(exports, containsForwardDecls);
}
}
// If not emitting inline, the scope information is not passed into `ɵɵdefineNgModule` as it would
// prevent tree-shaking of the declarations, imports and exports references.
else {
const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);
if (setNgModuleScopeCall !== null) {
additionalStatements.push(setNgModuleScopeCall);
}
}
if (schemas && schemas.length) {
definitionMap.schemas = literalArr(schemas.map(ref => ref.value));
}
if (id) {
definitionMap.id = id;
}
const expression = importExpr(Identifiers$1.defineNgModule).callFn([mapToMapExpression(definitionMap)]);
const type = new ExpressionType(importExpr(Identifiers$1.NgModuleDefWithMeta, [
new ExpressionType(moduleType), tupleTypeOf(declarations), tupleTypeOf(imports),
tupleTypeOf(exports)
]));
return { expression, type, additionalStatements };
}
/**
* Generates a function call to `ɵɵsetNgModuleScope` with all necessary information so that the
* transitive module scope can be computed during runtime in JIT mode. This call is marked pure
* such that the references to declarations, imports and exports may be elided causing these
* symbols to become tree-shakeable.
*/
function generateSetNgModuleScopeCall(meta) {
const { type: moduleType, declarations, imports, exports, containsForwardDecls } = meta;
const scopeMap = {};
if (declarations.length) {
scopeMap.declarations = refsToArray(declarations, containsForwardDecls);
}
if (imports.length) {
scopeMap.imports = refsToArray(imports, containsForwardDecls);
}
if (exports.length) {
scopeMap.exports = refsToArray(exports, containsForwardDecls);
}
if (Object.keys(scopeMap).length === 0) {
return null;
}
const fnCall = new InvokeFunctionExpr(
/* fn */ importExpr(Identifiers$1.setNgModuleScope),
/* args */ [moduleType, mapToMapExpression(scopeMap)],
/* type */ undefined,
/* sourceSpan */ undefined,
/* pure */ true);
return fnCall.toStmt();
}
function compileInjector(meta) {
const result = compileFactoryFunction({
name: meta.name,
type: meta.type,
deps: meta.deps,
injectFn: Identifiers$1.inject,
});
const definitionMap = {
factory: result.factory,
};
if (meta.providers !== null) {
definitionMap.providers = meta.providers;
}
if (meta.imports.length > 0) {
definitionMap.imports = literalArr(meta.imports);
}
const expression = importExpr(Identifiers$1.defineInjector).callFn([mapToMapExpression(definitionMap)]);
const type = new ExpressionType(importExpr(Identifiers$1.InjectorDef, [new ExpressionType(meta.type)]));
return { expression, type, statements: result.statements };
}
// TODO(alxhub): integrate this with `compileNgModule`. Currently the two are separate operations.
function compileNgModuleFromRender2(ctx, ngModule, injectableCompiler) {
const className = identifierName(ngModule.type);
const rawImports = ngModule.rawImports ? [ngModule.rawImports] : [];
const rawExports = ngModule.rawExports ? [ngModule.rawExports] : [];
const injectorDefArg = mapLiteral({
'factory': injectableCompiler.factoryFor({ type: ngModule.type, symbol: ngModule.type.reference }, ctx),
'providers': convertMetaToOutput(ngModule.rawProviders, ctx),
'imports': convertMetaToOutput([...rawImports, ...rawExports], ctx),
});
const injectorDef = importExpr(Identifiers$1.defineInjector).callFn([injectorDefArg]);
ctx.statements.push(new ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */ [new ClassField(
/* name */ 'ngInjectorDef',
/* type */ INFERRED_TYPE,
/* modifiers */ [StmtModifier.Static],
/* initializer */ injectorDef)],
/* getters */ [],
/* constructorMethod */ new ClassMethod(null, [], []),
/* methods */ []));
}
function accessExportScope(module) {
const selectorScope = new ReadPropExpr(module, 'ngModuleDef');
return new ReadPropExpr(selectorScope, 'exported');
}
function tupleTypeOf(exp) {
const types = exp.map(ref => typeofExpr(ref.type));
return exp.length > 0 ? expressionType(literalArr(types)) : NONE_TYPE;
}
function refsToArray(refs, shouldForwardDeclare) {
const values = literalArr(refs.map(ref => ref.value));
return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
}
/**
* @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
*/
function compilePipeFromMetadata(metadata) {
const definitionMapValues = [];
// e.g. `name: 'myPipe'`
definitionMapValues.push({ key: 'name', value: literal(metadata.pipeName), quoted: false });
// e.g. `type: MyPipe`
definitionMapValues.push({ key: 'type', value: metadata.type, quoted: false });
const templateFactory = compileFactoryFunction({
name: metadata.name,
type: metadata.type,
deps: metadata.deps,
injectFn: Identifiers$1.directiveInject,
}, true);
definitionMapValues.push({ key: 'factory', value: templateFactory.factory, quoted: false });
// e.g. `pure: true`
definitionMapValues.push({ key: 'pure', value: literal(metadata.pure), quoted: false });
const expression = importExpr(Identifiers$1.definePipe).callFn([literalMap(definitionMapValues)]);
const type = new ExpressionType(importExpr(Identifiers$1.PipeDefWithMeta, [
typeWithParameters(metadata.type, metadata.typeArgumentCount),
new ExpressionType(new LiteralExpr(metadata.pipeName)),
]));
return { expression, type, statements: templateFactory.statements };
}
/**
* Write a pipe definition to the output context.
*/
function compilePipeFromRender2(outputCtx, pipe, reflector) {
const definitionMapValues = [];
const name = identifierName(pipe.type);
if (!name) {
return error(`Cannot resolve the name of ${pipe.type}`);
}
const metadata = {
name,
pipeName: pipe.name,
type: outputCtx.importExpr(pipe.type.reference),
typeArgumentCount: 0,
deps: dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector),
pure: pipe.pure,
};
const res = compilePipeFromMetadata(metadata);
const definitionField = outputCtx.constantPool.propertyNameOf(3 /* Pipe */);
outputCtx.statements.push(new ClassStmt(
/* name */ name,
/* parent */ null,
/* fields */ [new ClassField(
/* name */ definitionField,
/* type */ INFERRED_TYPE,
/* modifiers */ [StmtModifier.Static],
/* initializer */ res.expression)],
/* getters */ [],
/* constructorMethod */ new ClassMethod(null, [], []),
/* methods */ []));
}
/**
* @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 ParserError {
constructor(message, input, errLocation, ctxLocation) {
this.input = input;
this.errLocation = errLocation;
this.ctxLocation = ctxLocation;
this.message = `Parser Error: ${message} ${errLocation} [${input}] in ${ctxLocation}`;
}
}
class ParseSpan {
constructor(start, end) {
this.start = start;
this.end = end;
}
}
class AST {
constructor(span) {
this.span = span;
}
visit(visitor, context = null) { return null; }
toString() { return 'AST'; }
}
/**
* Represents a quoted expression of the form:
*
* quote = prefix `:` uninterpretedExpression
* prefix = identifier
* uninterpretedExpression = arbitrary string
*
* A quoted expression is meant to be pre-processed by an AST transformer that
* converts it into another AST that no longer contains quoted expressions.
* It is meant to allow third-party developers to extend Angular template
* expression language. The `uninterpretedExpression` part of the quote is
* therefore not interpreted by the Angular's own expression parser.
*/
class Quote extends AST {
constructor(span, prefix, uninterpretedExpression, location) {
super(span);
this.prefix = prefix;
this.uninterpretedExpression = uninterpretedExpression;
this.location = location;
}
visit(visitor, context = null) { return visitor.visitQuote(this, context); }
toString() { return 'Quote'; }
}
class EmptyExpr extends AST {
visit(visitor, context = null) {
// do nothing
}
}
class ImplicitReceiver extends AST {
visit(visitor, context = null) {
return visitor.visitImplicitReceiver(this, context);
}
}
/**
* Multiple expressions separated by a semicolon.
*/
class Chain extends AST {
constructor(span, expressions) {
super(span);
this.expressions = expressions;
}
visit(visitor, context = null) { return visitor.visitChain(this, context); }
}
class Conditional extends AST {
constructor(span, condition, trueExp, falseExp) {
super(span);
this.condition = condition;
this.trueExp = trueExp;
this.falseExp = falseExp;
}
visit(visitor, context = null) {
return visitor.visitConditional(this, context);
}
}
class PropertyRead extends AST {
constructor(span, receiver, name) {
super(span);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitPropertyRead(this, context);
}
}
class PropertyWrite extends AST {
constructor(span, receiver, name, value) {
super(span);
this.receiver = receiver;
this.name = name;
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitPropertyWrite(this, context);
}
}
class SafePropertyRead extends AST {
constructor(span, receiver, name) {
super(span);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitSafePropertyRead(this, context);
}
}
class KeyedRead extends AST {
constructor(span, obj, key) {
super(span);
this.obj = obj;
this.key = key;
}
visit(visitor, context = null) {
return visitor.visitKeyedRead(this, context);
}
}
class KeyedWrite extends AST {
constructor(span, obj, key, value) {
super(span);
this.obj = obj;
this.key = key;
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitKeyedWrite(this, context);
}
}
class BindingPipe extends AST {
constructor(span, exp, name, args) {
super(span);
this.exp = exp;
this.name = name;
this.args = args;
}
visit(visitor, context = null) { return visitor.visitPipe(this, context); }
}
class LiteralPrimitive extends AST {
constructor(span, value) {
super(span);
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitLiteralPrimitive(this, context);
}
}
class LiteralArray extends AST {
constructor(span, expressions) {
super(span);
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitLiteralArray(this, context);
}
}
class LiteralMap extends AST {
constructor(span, keys, values) {
super(span);
this.keys = keys;
this.values = values;
}
visit(visitor, context = null) {
return visitor.visitLiteralMap(this, context);
}
}
class Interpolation extends AST {
constructor(span, strings, expressions) {
super(span);
this.strings = strings;
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitInterpolation(this, context);
}
}
class Binary extends AST {
constructor(span, operation, left, right) {
super(span);
this.operation = operation;
this.left = left;
this.right = right;
}
visit(visitor, context = null) {
return visitor.visitBinary(this, context);
}
}
class PrefixNot extends AST {
constructor(span, expression) {
super(span);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitPrefixNot(this, context);
}
}
class NonNullAssert extends AST {
constructor(span, expression) {
super(span);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitNonNullAssert(this, context);
}
}
class MethodCall extends AST {
constructor(span, receiver, name, args) {
super(span);
this.receiver = receiver;
this.name = name;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitMethodCall(this, context);
}
}
class SafeMethodCall extends AST {
constructor(span, receiver, name, args) {
super(span);
this.receiver = receiver;
this.name = name;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitSafeMethodCall(this, context);
}
}
class FunctionCall extends AST {
constructor(span, target, args) {
super(span);
this.target = target;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitFunctionCall(this, context);
}
}
/**
* Records the absolute position of a text span in a source file, where `start` and `end` are the
* starting and ending byte offsets, respectively, of the text span in a source file.
*/
class AbsoluteSourceSpan {
constructor(start, end) {
this.start = start;
this.end = end;
}
}
class ASTWithSource extends AST {
constructor(ast, source, location, absoluteOffset, errors) {
super(new ParseSpan(0, source == null ? 0 : source.length));
this.ast = ast;
this.source = source;
this.location = location;
this.errors = errors;
this.sourceSpan = new AbsoluteSourceSpan(absoluteOffset, absoluteOffset + this.span.end);
}
visit(visitor, context = null) {
if (visitor.visitASTWithSource) {
return visitor.visitASTWithSource(this, context);
}
return this.ast.visit(visitor, context);
}
toString() { return `${this.source} in ${this.location}`; }
}
class TemplateBinding {
constructor(span, key, keyIsVar, name, expression) {
this.span = span;
this.key = key;
this.keyIsVar = keyIsVar;
this.name = name;
this.expression = expression;
}
}
class NullAstVisitor {
visitBinary(ast, context) { }
visitChain(ast, context) { }
visitConditional(ast, context) { }
visitFunctionCall(ast, context) { }
visitImplicitReceiver(ast, context) { }
visitInterpolation(ast, context) { }
visitKeyedRead(ast, context) { }
visitKeyedWrite(ast, context) { }
visitLiteralArray(ast, context) { }
visitLiteralMap(ast, context) { }
visitLiteralPrimitive(ast, context) { }
visitMethodCall(ast, context) { }
visitPipe(ast, context) { }
visitPrefixNot(ast, context) { }
visitNonNullAssert(ast, context) { }
visitPropertyRead(ast, context) { }
visitPropertyWrite(ast, context) { }
visitQuote(ast, context) { }
visitSafeMethodCall(ast, context) { }
visitSafePropertyRead(ast, context) { }
}
class RecursiveAstVisitor$1 {
visitBinary(ast, context) {
ast.left.visit(this, context);
ast.right.visit(this, context);
return null;
}
visitChain(ast, context) { return this.visitAll(ast.expressions, context); }
visitConditional(ast, context) {
ast.condition.visit(this, context);
ast.trueExp.visit(this, context);
ast.falseExp.visit(this, context);
return null;
}
visitPipe(ast, context) {
ast.exp.visit(this, context);
this.visitAll(ast.args, context);
return null;
}
visitFunctionCall(ast, context) {
ast.target.visit(this, context);
this.visitAll(ast.args, context);
return null;
}
visitImplicitReceiver(ast, context) { return null; }
visitInterpolation(ast, context) {
return this.visitAll(ast.expressions, context);
}
visitKeyedRead(ast, context) {
ast.obj.visit(this, context);
ast.key.visit(this, context);
return null;
}
visitKeyedWrite(ast, context) {
ast.obj.visit(this, context);
ast.key.visit(this, context);
ast.value.visit(this, context);
return null;
}
visitLiteralArray(ast, context) {
return this.visitAll(ast.expressions, context);
}
visitLiteralMap(ast, context) { return this.visitAll(ast.values, context); }
visitLiteralPrimitive(ast, context) { return null; }
visitMethodCall(ast, context) {
ast.receiver.visit(this, context);
return this.visitAll(ast.args, context);
}
visitPrefixNot(ast, context) {
ast.expression.visit(this, context);
return null;
}
visitNonNullAssert(ast, context) {
ast.expression.visit(this, context);
return null;
}
visitPropertyRead(ast, context) {
ast.receiver.visit(this, context);
return null;
}
visitPropertyWrite(ast, context) {
ast.receiver.visit(this, context);
ast.value.visit(this, context);
return null;
}
visitSafePropertyRead(ast, context) {
ast.receiver.visit(this, context);
return null;
}
visitSafeMethodCall(ast, context) {
ast.receiver.visit(this, context);
return this.visitAll(ast.args, context);
}
visitAll(asts, context) {
asts.forEach(ast => ast.visit(this, context));
return null;
}
visitQuote(ast, context) { return null; }
}
class AstTransformer$1 {
visitImplicitReceiver(ast, context) { return ast; }
visitInterpolation(ast, context) {
return new Interpolation(ast.span, ast.strings, this.visitAll(ast.expressions));
}
visitLiteralPrimitive(ast, context) {
return new LiteralPrimitive(ast.span, ast.value);
}
visitPropertyRead(ast, context) {
return new PropertyRead(ast.span, ast.receiver.visit(this), ast.name);
}
visitPropertyWrite(ast, context) {
return new PropertyWrite(ast.span, ast.receiver.visit(this), ast.name, ast.value.visit(this));
}
visitSafePropertyRead(ast, context) {
return new SafePropertyRead(ast.span, ast.receiver.visit(this), ast.name);
}
visitMethodCall(ast, context) {
return new MethodCall(ast.span, ast.receiver.visit(this), ast.name, this.visitAll(ast.args));
}
visitSafeMethodCall(ast, context) {
return new SafeMethodCall(ast.span, ast.receiver.visit(this), ast.name, this.visitAll(ast.args));
}
visitFunctionCall(ast, context) {
return new FunctionCall(ast.span, ast.target.visit(this), this.visitAll(ast.args));
}
visitLiteralArray(ast, context) {
return new LiteralArray(ast.span, this.visitAll(ast.expressions));
}
visitLiteralMap(ast, context) {
return new LiteralMap(ast.span, ast.keys, this.visitAll(ast.values));
}
visitBinary(ast, context) {
return new Binary(ast.span, ast.operation, ast.left.visit(this), ast.right.visit(this));
}
visitPrefixNot(ast, context) {
return new PrefixNot(ast.span, ast.expression.visit(this));
}
visitNonNullAssert(ast, context) {
return new NonNullAssert(ast.span, ast.expression.visit(this));
}
visitConditional(ast, context) {
return new Conditional(ast.span, ast.condition.visit(this), ast.trueExp.visit(this), ast.falseExp.visit(this));
}
visitPipe(ast, context) {
return new BindingPipe(ast.span, ast.exp.visit(this), ast.name, this.visitAll(ast.args));
}
visitKeyedRead(ast, context) {
return new KeyedRead(ast.span, ast.obj.visit(this), ast.key.visit(this));
}
visitKeyedWrite(ast, context) {
return new KeyedWrite(ast.span, ast.obj.visit(this), ast.key.visit(this), ast.value.visit(this));
}
visitAll(asts) {
const res = new Array(asts.length);
for (let i = 0; i < asts.length; ++i) {
res[i] = asts[i].visit(this);
}
return res;
}
visitChain(ast, context) {
return new Chain(ast.span, this.visitAll(ast.expressions));
}
visitQuote(ast, context) {
return new Quote(ast.span, ast.prefix, ast.uninterpretedExpression, ast.location);
}
}
// A transformer that only creates new nodes if the transformer makes a change or
// a change is made a child node.
class AstMemoryEfficientTransformer {
visitImplicitReceiver(ast, context) { return ast; }
visitInterpolation(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions)
return new Interpolation(ast.span, ast.strings, expressions);
return ast;
}
visitLiteralPrimitive(ast, context) { return ast; }
visitPropertyRead(ast, context) {
const receiver = ast.receiver.visit(this);
if (receiver !== ast.receiver) {
return new PropertyRead(ast.span, receiver, ast.name);
}
return ast;
}
visitPropertyWrite(ast, context) {
const receiver = ast.receiver.visit(this);
const value = ast.value.visit(this);
if (receiver !== ast.receiver || value !== ast.value) {
return new PropertyWrite(ast.span, receiver, ast.name, value);
}
return ast;
}
visitSafePropertyRead(ast, context) {
const receiver = ast.receiver.visit(this);
if (receiver !== ast.receiver) {
return new SafePropertyRead(ast.span, receiver, ast.name);
}
return ast;
}
visitMethodCall(ast, context) {
const receiver = ast.receiver.visit(this);
const args = this.visitAll(ast.args);
if (receiver !== ast.receiver || args !== ast.args) {
return new MethodCall(ast.span, receiver, ast.name, args);
}
return ast;
}
visitSafeMethodCall(ast, context) {
const receiver = ast.receiver.visit(this);
const args = this.visitAll(ast.args);
if (receiver !== ast.receiver || args !== ast.args) {
return new SafeMethodCall(ast.span, receiver, ast.name, args);
}
return ast;
}
visitFunctionCall(ast, context) {
const target = ast.target && ast.target.visit(this);
const args = this.visitAll(ast.args);
if (target !== ast.target || args !== ast.args) {
return new FunctionCall(ast.span, target, args);
}
return ast;
}
visitLiteralArray(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions) {
return new LiteralArray(ast.span, expressions);
}
return ast;
}
visitLiteralMap(ast, context) {
const values = this.visitAll(ast.values);
if (values !== ast.values) {
return new LiteralMap(ast.span, ast.keys, values);
}
return ast;
}
visitBinary(ast, context) {
const left = ast.left.visit(this);
const right = ast.right.visit(this);
if (left !== ast.left || right !== ast.right) {
return new Binary(ast.span, ast.operation, left, right);
}
return ast;
}
visitPrefixNot(ast, context) {
const expression = ast.expression.visit(this);
if (expression !== ast.expression) {
return new PrefixNot(ast.span, expression);
}
return ast;
}
visitNonNullAssert(ast, context) {
const expression = ast.expression.visit(this);
if (expression !== ast.expression) {
return new NonNullAssert(ast.span, expression);
}
return ast;
}
visitConditional(ast, context) {
const condition = ast.condition.visit(this);
const trueExp = ast.trueExp.visit(this);
const falseExp = ast.falseExp.visit(this);
if (condition !== ast.condition || trueExp !== ast.trueExp || falseExp !== ast.falseExp) {
return new Conditional(ast.span, condition, trueExp, falseExp);
}
return ast;
}
visitPipe(ast, context) {
const exp = ast.exp.visit(this);
const args = this.visitAll(ast.args);
if (exp !== ast.exp || args !== ast.args) {
return new BindingPipe(ast.span, exp, ast.name, args);
}
return ast;
}
visitKeyedRead(ast, context) {
const obj = ast.obj.visit(this);
const key = ast.key.visit(this);
if (obj !== ast.obj || key !== ast.key) {
return new KeyedRead(ast.span, obj, key);
}
return ast;
}
visitKeyedWrite(ast, context) {
const obj = ast.obj.visit(this);
const key = ast.key.visit(this);
const value = ast.value.visit(this);
if (obj !== ast.obj || key !== ast.key || value !== ast.value) {
return new KeyedWrite(ast.span, obj, key, value);
}
return ast;
}
visitAll(asts) {
const res = new Array(asts.length);
let modified = false;
for (let i = 0; i < asts.length; ++i) {
const original = asts[i];
const value = original.visit(this);
res[i] = value;
modified = modified || value !== original;
}
return modified ? res : asts;
}
visitChain(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions) {
return new Chain(ast.span, expressions);
}
return ast;
}
visitQuote(ast, context) { return ast; }
}
function visitAstChildren(ast, visitor, context) {
function visit(ast) {
visitor.visit && visitor.visit(ast, context) || ast.visit(visitor, context);
}
function visitAll(asts) { asts.forEach(visit); }
ast.visit({
visitBinary(ast) {
visit(ast.left);
visit(ast.right);
},
visitChain(ast) { visitAll(ast.expressions); },
visitConditional(ast) {
visit(ast.condition);
visit(ast.trueExp);
visit(ast.falseExp);
},
visitFunctionCall(ast) {
if (ast.target) {
visit(ast.target);
}
visitAll(ast.args);
},
visitImplicitReceiver(ast) { },
visitInterpolation(ast) { visitAll(ast.expressions); },
visitKeyedRead(ast) {
visit(ast.obj);
visit(ast.key);
},
visitKeyedWrite(ast) {
visit(ast.obj);
visit(ast.key);
visit(ast.obj);
},
visitLiteralArray(ast) { visitAll(ast.expressions); },
visitLiteralMap(ast) { },
visitLiteralPrimitive(ast) { },
visitMethodCall(ast) {
visit(ast.receiver);
visitAll(ast.args);
},
visitPipe(ast) {
visit(ast.exp);
visitAll(ast.args);
},
visitPrefixNot(ast) { visit(ast.expression); },
visitNonNullAssert(ast) { visit(ast.expression); },
visitPropertyRead(ast) { visit(ast.receiver); },
visitPropertyWrite(ast) {
visit(ast.receiver);
visit(ast.value);
},
visitQuote(ast) { },
visitSafeMethodCall(ast) {
visit(ast.receiver);
visitAll(ast.args);
},
visitSafePropertyRead(ast) { visit(ast.receiver); },
});
}
// Bindings
class ParsedProperty {
constructor(name, expression, type, sourceSpan, valueSpan) {
this.name = name;
this.expression = expression;
this.type = type;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;
this.isAnimation = this.type === ParsedPropertyType.ANIMATION;
}
}
var ParsedPropertyType;
(function (ParsedPropertyType) {
ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT";
ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 2] = "ANIMATION";
})(ParsedPropertyType || (ParsedPropertyType = {}));
class ParsedEvent {
// Regular events have a target
// Animation events have a phase
constructor(name, targetOrPhase, type, handler, sourceSpan, handlerSpan) {
this.name = name;
this.targetOrPhase = targetOrPhase;
this.type = type;
this.handler = handler;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
}
}
class ParsedVariable {
constructor(name, value, sourceSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
}
}
class BoundElementProperty {
constructor(name, type, securityContext, value, unit, sourceSpan, valueSpan) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
}
/**
* @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 EventHandlerVars {
}
EventHandlerVars.event = variable('$event');
class ConvertActionBindingResult {
constructor(
/**
* Render2 compatible statements,
*/
stmts,
/**
* Variable name used with render2 compatible statements.
*/
allowDefault) {
this.stmts = stmts;
this.allowDefault = allowDefault;
/**
* This is bit of a hack. It converts statements which render2 expects to statements which are
* expected by render3.
*
* Example: `
` will generate:
*
* Render3:
* ```
* const pd_b:any = ((ctx.doSomething($event)) !== false);
* return pd_b;
* ```
*
* but render2 expects:
* ```
* return ctx.doSomething($event);
* ```
*/
// TODO(misko): remove this hack once we no longer support ViewEngine.
this.render3Stmts = stmts.map((statement) => {
if (statement instanceof DeclareVarStmt && statement.name == allowDefault.name &&
statement.value instanceof BinaryOperatorExpr) {
const lhs = statement.value.lhs;
return new ReturnStatement(lhs.value);
}
return statement;
});
}
}
/**
* Converts the given expression AST into an executable output AST, assuming the expression is
* used in an action binding (e.g. an event handler).
*/
function convertActionBinding(localResolver, implicitReceiver, action, bindingId, interpolationFunction, baseSourceSpan) {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const actionWithoutBuiltins = convertPropertyBindingBuiltins({
createLiteralArrayConverter: (argCount) => {
// Note: no caching for literal arrays in actions.
return (args) => literalArr(args);
},
createLiteralMapConverter: (keys) => {
// Note: no caching for literal maps in actions.
return (values) => {
const entries = keys.map((k, i) => ({
key: k.key,
value: values[i],
quoted: k.quoted,
}));
return literalMap(entries);
};
},
createPipeConverter: (name) => {
throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`);
}
}, action);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction, baseSourceSpan);
const actionStmts = [];
flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const lastIndex = actionStmts.length - 1;
let preventDefaultVar = null;
if (lastIndex >= 0) {
const lastStatement = actionStmts[lastIndex];
const returnExpr = convertStmtIntoExpression(lastStatement);
if (returnExpr) {
// Note: We need to cast the result of the method call to dynamic,
// as it might be a void method!
preventDefaultVar = createPreventDefaultVar(bindingId);
actionStmts[lastIndex] =
preventDefaultVar.set(returnExpr.cast(DYNAMIC_TYPE).notIdentical(literal(false)))
.toDeclStmt(null, [StmtModifier.Final]);
}
}
return new ConvertActionBindingResult(actionStmts, preventDefaultVar);
}
function convertPropertyBindingBuiltins(converterFactory, ast) {
return convertBuiltins(converterFactory, ast);
}
class ConvertPropertyBindingResult {
constructor(stmts, currValExpr) {
this.stmts = stmts;
this.currValExpr = currValExpr;
}
}
var BindingForm;
(function (BindingForm) {
// The general form of binding expression, supports all expressions.
BindingForm[BindingForm["General"] = 0] = "General";
// Try to generate a simple binding (no temporaries or statements)
// otherwise generate a general binding
BindingForm[BindingForm["TrySimple"] = 1] = "TrySimple";
})(BindingForm || (BindingForm = {}));
/**
* Converts the given expression AST into an executable output AST, assuming the expression
* is used in property binding. The expression has to be preprocessed via
* `convertPropertyBindingBuiltins`.
*/
function convertPropertyBinding(localResolver, implicitReceiver, expressionWithoutBuiltins, bindingId, form, interpolationFunction) {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const currValExpr = createCurrValueExpr(bindingId);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
const outputExpr = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
const stmts = getStatementsFromVisitor(visitor, bindingId);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
if (visitor.temporaryCount === 0 && form == BindingForm.TrySimple) {
return new ConvertPropertyBindingResult([], outputExpr);
}
stmts.push(currValExpr.set(outputExpr).toDeclStmt(DYNAMIC_TYPE, [StmtModifier.Final]));
return new ConvertPropertyBindingResult(stmts, currValExpr);
}
/**
* Given some expression, such as a binding or interpolation expression, and a context expression to
* look values up on, visit each facet of the given expression resolving values from the context
* expression such that a list of arguments can be derived from the found values that can be used as
* arguments to an external update instruction.
*
* @param localResolver The resolver to use to look up expressions by name appropriately
* @param contextVariableExpression The expression representing the context variable used to create
* the final argument expressions
* @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to
* be resolved and what arguments list to build.
* @param bindingId A name prefix used to create temporary variable names if they're needed for the
* arguments generated
* @returns An array of expressions that can be passed as arguments to instruction expressions like
* `o.importExpr(R3.propertyInterpolate).callFn(result)`
*/
function convertUpdateArguments(localResolver, contextVariableExpression, expressionWithArgumentsToExtract, bindingId) {
const visitor = new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId, undefined);
const outputExpr = expressionWithArgumentsToExtract.visit(visitor, _Mode.Expression);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const stmts = getStatementsFromVisitor(visitor, bindingId);
// Removing the first argument, because it was a length for ViewEngine, not Ivy.
let args = outputExpr.args.slice(1);
if (expressionWithArgumentsToExtract instanceof Interpolation) {
// If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the
// args returned to just the value, because we're going to pass it to a special instruction.
const strings = expressionWithArgumentsToExtract.strings;
if (args.length === 3 && strings[0] === '' && strings[1] === '') {
// Single argument interpolate instructions.
args = [args[1]];
}
else if (args.length >= 19) {
// 19 or more arguments must be passed to the `interpolateV`-style instructions, which accept
// an array of arguments
args = [literalArr(args)];
}
}
return { stmts, args };
}
function getStatementsFromVisitor(visitor, bindingId) {
const stmts = [];
for (let i = 0; i < visitor.temporaryCount; i++) {
stmts.push(temporaryDeclaration(bindingId, i));
}
return stmts;
}
function convertBuiltins(converterFactory, ast) {
const visitor = new _BuiltinAstConverter(converterFactory);
return ast.visit(visitor);
}
function temporaryName(bindingId, temporaryNumber) {
return `tmp_${bindingId}_${temporaryNumber}`;
}
function temporaryDeclaration(bindingId, temporaryNumber) {
return new DeclareVarStmt(temporaryName(bindingId, temporaryNumber), NULL_EXPR);
}
function prependTemporaryDecls(temporaryCount, bindingId, statements) {
for (let i = temporaryCount - 1; i >= 0; i--) {
statements.unshift(temporaryDeclaration(bindingId, i));
}
}
var _Mode;
(function (_Mode) {
_Mode[_Mode["Statement"] = 0] = "Statement";
_Mode[_Mode["Expression"] = 1] = "Expression";
})(_Mode || (_Mode = {}));
function ensureStatementMode(mode, ast) {
if (mode !== _Mode.Statement) {
throw new Error(`Expected a statement, but saw ${ast}`);
}
}
function ensureExpressionMode(mode, ast) {
if (mode !== _Mode.Expression) {
throw new Error(`Expected an expression, but saw ${ast}`);
}
}
function convertToStatementIfNeeded(mode, expr) {
if (mode === _Mode.Statement) {
return expr.toStmt();
}
else {
return expr;
}
}
class _BuiltinAstConverter extends AstTransformer$1 {
constructor(_converterFactory) {
super();
this._converterFactory = _converterFactory;
}
visitPipe(ast, context) {
const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, args, this._converterFactory.createPipeConverter(ast.name, args.length));
}
visitLiteralArray(ast, context) {
const args = ast.expressions.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, args, this._converterFactory.createLiteralArrayConverter(ast.expressions.length));
}
visitLiteralMap(ast, context) {
const args = ast.values.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, args, this._converterFactory.createLiteralMapConverter(ast.keys));
}
}
class _AstToIrVisitor {
constructor(_localResolver, _implicitReceiver, bindingId, interpolationFunction, baseSourceSpan) {
this._localResolver = _localResolver;
this._implicitReceiver = _implicitReceiver;
this.bindingId = bindingId;
this.interpolationFunction = interpolationFunction;
this.baseSourceSpan = baseSourceSpan;
this._nodeMap = new Map();
this._resultMap = new Map();
this._currentTemporary = 0;
this.temporaryCount = 0;
this.usesImplicitReceiver = false;
}
visitBinary(ast, mode) {
let op;
switch (ast.operation) {
case '+':
op = BinaryOperator.Plus;
break;
case '-':
op = BinaryOperator.Minus;
break;
case '*':
op = BinaryOperator.Multiply;
break;
case '/':
op = BinaryOperator.Divide;
break;
case '%':
op = BinaryOperator.Modulo;
break;
case '&&':
op = BinaryOperator.And;
break;
case '||':
op = BinaryOperator.Or;
break;
case '==':
op = BinaryOperator.Equals;
break;
case '!=':
op = BinaryOperator.NotEquals;
break;
case '===':
op = BinaryOperator.Identical;
break;
case '!==':
op = BinaryOperator.NotIdentical;
break;
case '<':
op = BinaryOperator.Lower;
break;
case '>':
op = BinaryOperator.Bigger;
break;
case '<=':
op = BinaryOperator.LowerEquals;
break;
case '>=':
op = BinaryOperator.BiggerEquals;
break;
default:
throw new Error(`Unsupported operation ${ast.operation}`);
}
return convertToStatementIfNeeded(mode, new BinaryOperatorExpr(op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
}
visitChain(ast, mode) {
ensureStatementMode(mode, ast);
return this.visitAll(ast.expressions, mode);
}
visitConditional(ast, mode) {
const value = this._visit(ast.condition, _Mode.Expression);
return convertToStatementIfNeeded(mode, value.conditional(this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span)));
}
visitPipe(ast, mode) {
throw new Error(`Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`);
}
visitFunctionCall(ast, mode) {
const convertedArgs = this.visitAll(ast.args, _Mode.Expression);
let fnResult;
if (ast instanceof BuiltinFunctionCall) {
fnResult = ast.converter(convertedArgs);
}
else {
fnResult = this._visit(ast.target, _Mode.Expression)
.callFn(convertedArgs, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, fnResult);
}
visitImplicitReceiver(ast, mode) {
ensureExpressionMode(mode, ast);
this.usesImplicitReceiver = true;
return this._implicitReceiver;
}
visitInterpolation(ast, mode) {
ensureExpressionMode(mode, ast);
const args = [literal(ast.expressions.length)];
for (let i = 0; i < ast.strings.length - 1; i++) {
args.push(literal(ast.strings[i]));
args.push(this._visit(ast.expressions[i], _Mode.Expression));
}
args.push(literal(ast.strings[ast.strings.length - 1]));
if (this.interpolationFunction) {
return this.interpolationFunction(args);
}
return ast.expressions.length <= 9 ?
importExpr(Identifiers.inlineInterpolate).callFn(args) :
importExpr(Identifiers.interpolate).callFn([
args[0], literalArr(args.slice(1), undefined, this.convertSourceSpan(ast.span))
]);
}
visitKeyedRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
return convertToStatementIfNeeded(mode, this._visit(ast.obj, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
}
}
visitKeyedWrite(ast, mode) {
const obj = this._visit(ast.obj, _Mode.Expression);
const key = this._visit(ast.key, _Mode.Expression);
const value = this._visit(ast.value, _Mode.Expression);
return convertToStatementIfNeeded(mode, obj.key(key).set(value));
}
visitLiteralArray(ast, mode) {
throw new Error(`Illegal State: literal arrays should have been converted into functions`);
}
visitLiteralMap(ast, mode) {
throw new Error(`Illegal State: literal maps should have been converted into functions`);
}
visitLiteralPrimitive(ast, mode) {
// For literal values of null, undefined, true, or false allow type interference
// to infer the type.
const type = ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ?
INFERRED_TYPE :
undefined;
return convertToStatementIfNeeded(mode, literal(ast.value, type, this.convertSourceSpan(ast.span)));
}
_getLocal(name) { return this._localResolver.getLocal(name); }
visitMethodCall(ast, mode) {
if (ast.receiver instanceof ImplicitReceiver && ast.name == '$any') {
const args = this.visitAll(ast.args, _Mode.Expression);
if (args.length != 1) {
throw new Error(`Invalid call to $any, expected 1 argument but received ${args.length || 'none'}`);
}
return args[0].cast(DYNAMIC_TYPE, this.convertSourceSpan(ast.span));
}
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
const args = this.visitAll(ast.args, _Mode.Expression);
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
let result = null;
const receiver = this._visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
const varExpr = this._getLocal(ast.name);
if (varExpr) {
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
result = varExpr.callFn(args);
}
}
if (result == null) {
result = receiver.callMethod(ast.name, args, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, result);
}
}
visitPrefixNot(ast, mode) {
return convertToStatementIfNeeded(mode, not(this._visit(ast.expression, _Mode.Expression)));
}
visitNonNullAssert(ast, mode) {
return convertToStatementIfNeeded(mode, assertNotNull(this._visit(ast.expression, _Mode.Expression)));
}
visitPropertyRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
let result = null;
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
const receiver = this._visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
result = this._getLocal(ast.name);
if (result) {
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
}
}
if (result == null) {
result = receiver.prop(ast.name);
}
return convertToStatementIfNeeded(mode, result);
}
}
visitPropertyWrite(ast, mode) {
const receiver = this._visit(ast.receiver, _Mode.Expression);
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
let varExpr = null;
if (receiver === this._implicitReceiver) {
const localExpr = this._getLocal(ast.name);
if (localExpr) {
if (localExpr instanceof ReadPropExpr) {
// If the local variable is a property read expression, it's a reference
// to a 'context.property' value and will be used as the target of the
// write expression.
varExpr = localExpr;
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
}
else {
// Otherwise it's an error.
throw new Error('Cannot assign to a reference or variable!');
}
}
}
// If no local expression could be produced, use the original receiver's
// property as the target.
if (varExpr === null) {
varExpr = receiver.prop(ast.name);
}
return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression)));
}
visitSafePropertyRead(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitSafeMethodCall(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitAll(asts, mode) { return asts.map(ast => this._visit(ast, mode)); }
visitQuote(ast, mode) {
throw new Error(`Quotes are not supported for evaluation!
Statement: ${ast.uninterpretedExpression} located at ${ast.location}`);
}
_visit(ast, mode) {
const result = this._resultMap.get(ast);
if (result)
return result;
return (this._nodeMap.get(ast) || ast).visit(this, mode);
}
convertSafeAccess(ast, leftMostSafe, mode) {
// If the expression contains a safe access node on the left it needs to be converted to
// an expression that guards the access to the member by checking the receiver for blank. As
// execution proceeds from left to right, the left most part of the expression must be guarded
// first but, because member access is left associative, the right side of the expression is at
// the top of the AST. The desired result requires lifting a copy of the the left part of the
// expression up to test it for blank before generating the unguarded version.
// Consider, for example the following expression: a?.b.c?.d.e
// This results in the ast:
// .
// / \
// ?. e
// / \
// . d
// / \
// ?. c
// / \
// a b
// The following tree should be generated:
//
// /---- ? ----\
// / | \
// a /--- ? ---\ null
// / | \
// . . null
// / \ / \
// . c . e
// / \ / \
// a b . d
// / \
// . c
// / \
// a b
//
// Notice that the first guard condition is the left hand of the left most safe access node
// which comes in as leftMostSafe to this routine.
let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression);
let temporary = undefined;
if (this.needsTemporary(leftMostSafe.receiver)) {
// If the expression has method calls or pipes then we need to save the result into a
// temporary variable to avoid calling stateful or impure code more than once.
temporary = this.allocateTemporary();
// Preserve the result in the temporary variable
guardedExpression = temporary.set(guardedExpression);
// Ensure all further references to the guarded expression refer to the temporary instead.
this._resultMap.set(leftMostSafe.receiver, temporary);
}
const condition = guardedExpression.isBlank();
// Convert the ast to an unguarded access to the receiver's member. The map will substitute
// leftMostNode with its unguarded version in the call to `this.visit()`.
if (leftMostSafe instanceof SafeMethodCall) {
this._nodeMap.set(leftMostSafe, new MethodCall(leftMostSafe.span, leftMostSafe.receiver, leftMostSafe.name, leftMostSafe.args));
}
else {
this._nodeMap.set(leftMostSafe, new PropertyRead(leftMostSafe.span, leftMostSafe.receiver, leftMostSafe.name));
}
// Recursively convert the node now without the guarded member access.
const access = this._visit(ast, _Mode.Expression);
// Remove the mapping. This is not strictly required as the converter only traverses each node
// once but is safer if the conversion is changed to traverse the nodes more than once.
this._nodeMap.delete(leftMostSafe);
// If we allocated a temporary, release it.
if (temporary) {
this.releaseTemporary(temporary);
}
// Produce the conditional
return convertToStatementIfNeeded(mode, condition.conditional(literal(null), access));
}
// Given a expression of the form a?.b.c?.d.e the the left most safe node is
// the (a?.b). The . and ?. are left associative thus can be rewritten as:
// ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or
// safe method call as this needs be transform initially to:
// a == null ? null : a.c.b.c?.d.e
// then to:
// a == null ? null : a.b.c == null ? null : a.b.c.d.e
leftMostSafeNode(ast) {
const visit = (visitor, ast) => {
return (this._nodeMap.get(ast) || ast).visit(visitor);
};
return ast.visit({
visitBinary(ast) { return null; },
visitChain(ast) { return null; },
visitConditional(ast) { return null; },
visitFunctionCall(ast) { return null; },
visitImplicitReceiver(ast) { return null; },
visitInterpolation(ast) { return null; },
visitKeyedRead(ast) { return visit(this, ast.obj); },
visitKeyedWrite(ast) { return null; },
visitLiteralArray(ast) { return null; },
visitLiteralMap(ast) { return null; },
visitLiteralPrimitive(ast) { return null; },
visitMethodCall(ast) { return visit(this, ast.receiver); },
visitPipe(ast) { return null; },
visitPrefixNot(ast) { return null; },
visitNonNullAssert(ast) { return null; },
visitPropertyRead(ast) { return visit(this, ast.receiver); },
visitPropertyWrite(ast) { return null; },
visitQuote(ast) { return null; },
visitSafeMethodCall(ast) { return visit(this, ast.receiver) || ast; },
visitSafePropertyRead(ast) {
return visit(this, ast.receiver) || ast;
}
});
}
// Returns true of the AST includes a method or a pipe indicating that, if the
// expression is used as the target of a safe property or method access then
// the expression should be stored into a temporary variable.
needsTemporary(ast) {
const visit = (visitor, ast) => {
return ast && (this._nodeMap.get(ast) || ast).visit(visitor);
};
const visitSome = (visitor, ast) => {
return ast.some(ast => visit(visitor, ast));
};
return ast.visit({
visitBinary(ast) { return visit(this, ast.left) || visit(this, ast.right); },
visitChain(ast) { return false; },
visitConditional(ast) {
return visit(this, ast.condition) || visit(this, ast.trueExp) ||
visit(this, ast.falseExp);
},
visitFunctionCall(ast) { return true; },
visitImplicitReceiver(ast) { return false; },
visitInterpolation(ast) { return visitSome(this, ast.expressions); },
visitKeyedRead(ast) { return false; },
visitKeyedWrite(ast) { return false; },
visitLiteralArray(ast) { return true; },
visitLiteralMap(ast) { return true; },
visitLiteralPrimitive(ast) { return false; },
visitMethodCall(ast) { return true; },
visitPipe(ast) { return true; },
visitPrefixNot(ast) { return visit(this, ast.expression); },
visitNonNullAssert(ast) { return visit(this, ast.expression); },
visitPropertyRead(ast) { return false; },
visitPropertyWrite(ast) { return false; },
visitQuote(ast) { return false; },
visitSafeMethodCall(ast) { return true; },
visitSafePropertyRead(ast) { return false; }
});
}
allocateTemporary() {
const tempNumber = this._currentTemporary++;
this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount);
return new ReadVarExpr(temporaryName(this.bindingId, tempNumber));
}
releaseTemporary(temporary) {
this._currentTemporary--;
if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) {
throw new Error(`Temporary ${temporary.name} released out of order`);
}
}
/**
* Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`.
*
* `ParseSpan` objects are relative to the start of the expression.
* This method converts these to full `ParseSourceSpan` objects that
* show where the span is within the overall source file.
*
* @param span the relative span to convert.
* @returns a `ParseSourceSpan` for the the given span or null if no
* `baseSourceSpan` was provided to this class.
*/
convertSourceSpan(span) {
if (this.baseSourceSpan) {
const start = this.baseSourceSpan.start.moveBy(span.start);
const end = this.baseSourceSpan.start.moveBy(span.end);
return new ParseSourceSpan(start, end);
}
else {
return null;
}
}
}
function flattenStatements(arg, output) {
if (Array.isArray(arg)) {
arg.forEach((entry) => flattenStatements(entry, output));
}
else {
output.push(arg);
}
}
class DefaultLocalResolver {
notifyImplicitReceiverUse() { }
getLocal(name) {
if (name === EventHandlerVars.event.name) {
return EventHandlerVars.event;
}
return null;
}
}
function createCurrValueExpr(bindingId) {
return variable(`currVal_${bindingId}`); // fix syntax highlighting: `
}
function createPreventDefaultVar(bindingId) {
return variable(`pd_${bindingId}`);
}
function convertStmtIntoExpression(stmt) {
if (stmt instanceof ExpressionStatement) {
return stmt.expr;
}
else if (stmt instanceof ReturnStatement) {
return stmt.value;
}
return null;
}
class BuiltinFunctionCall extends FunctionCall {
constructor(span, args, converter) {
super(span, null, args);
this.args = args;
this.converter = converter;
}
}
/**
* @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
*/
/**
* This file is a port of shadowCSS from webcomponents.js to TypeScript.
*
* Please make sure to keep to edits in sync with the source file.
*
* Source:
* https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
*
* The original file level comment is reproduced below
*/
/*
This is a limited shim for ShadowDOM css styling.
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
The intention here is to support only the styling features which can be
relatively simply implemented. The goal is to allow users to avoid the
most obvious pitfalls and do so without compromising performance significantly.
For ShadowDOM styling that's not covered here, a set of best practices
can be provided that should allow users to accomplish more complex styling.
The following is a list of specific ShadowDOM styling features and a brief
discussion of the approach used to shim.
Shimmed features:
* :host, :host-context: ShadowDOM allows styling of the shadowRoot's host
element using the :host rule. To shim this feature, the :host styles are
reformatted and prefixed with a given scope name and promoted to a
document level stylesheet.
For example, given a scope name of .foo, a rule like this:
:host {
background: red;
}
}
becomes:
.foo {
background: red;
}
* encapsulation: Styles defined within ShadowDOM, apply only to
dom inside the ShadowDOM. Polymer uses one of two techniques to implement
this feature.
By default, rules are prefixed with the host element tag name
as a descendant selector. This ensures styling does not leak out of the 'top'
of the element's ShadowDOM. For example,
div {
font-weight: bold;
}
becomes:
x-foo div {
font-weight: bold;
}
becomes:
Alternatively, if WebComponents.ShadowCSS.strictStyling is set to true then
selectors are scoped by adding an attribute selector suffix to each
simple selector that contains the host element tag name. Each element
in the element's ShadowDOM template is also given the scope attribute.
Thus, these rules match only elements that have the scope attribute.
For example, given a scope name of x-foo, a rule like this:
div {
font-weight: bold;
}
becomes:
div[x-foo] {
font-weight: bold;
}
Note that elements that are dynamically added to a scope must have the scope
selector added to them manually.
* upper/lower bound encapsulation: Styles which are defined outside a
shadowRoot should not cross the ShadowDOM boundary and should not apply
inside a shadowRoot.
This styling behavior is not emulated. Some possible ways to do this that
were rejected due to complexity and/or performance concerns include: (1) reset
every possible property for every possible selector for a given scope name;
(2) re-implement css in javascript.
As an alternative, users should make sure to use selectors
specific to the scope in which they are working.
* ::distributed: This behavior is not emulated. It's often not necessary
to style the contents of a specific insertion point and instead, descendants
of the host element can be styled selectively. Users can also create an
extra node around an insertion point and style that node's contents
via descendent selectors. For example, with a shadowRoot like this:
could become:
Note the use of @polyfill in the comment above a ShadowDOM specific style
declaration. This is a directive to the styling shim to use the selector
in comments in lieu of the next selector when running under polyfill.
*/
class ShadowCss {
constructor() {
this.strictStyling = true;
}
/*
* Shim some cssText with the given selector. Returns cssText that can
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
*
* When strictStyling is true:
* - selector is the attribute added to all elements inside the host,
* - hostSelector is the attribute added to the host itself.
*/
shimCssText(cssText, selector, hostSelector = '') {
const commentsWithHash = extractCommentsWithHash(cssText);
cssText = stripComments(cssText);
cssText = this._insertDirectives(cssText);
const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
return [scopedCssText, ...commentsWithHash].join('\n');
}
_insertDirectives(cssText) {
cssText = this._insertPolyfillDirectivesInCssText(cssText);
return this._insertPolyfillRulesInCssText(cssText);
}
/*
* Process styles to convert native ShadowDOM rules that will trip
* up the css parser; we rely on decorating the stylesheet with inert rules.
*
* For example, we convert this rule:
*
* polyfill-next-selector { content: ':host menu-item'; }
* ::content menu-item {
*
* to this:
*
* scopeName menu-item {
*
**/
_insertPolyfillDirectivesInCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
return cssText.replace(_cssContentNextSelectorRe, function (...m) { return m[2] + '{'; });
}
/*
* Process styles to add rules which will only apply under the polyfill
*
* For example, we convert this rule:
*
* polyfill-rule {
* content: ':host menu-item';
* ...
* }
*
* to this:
*
* scopeName menu-item {...}
*
**/
_insertPolyfillRulesInCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
return cssText.replace(_cssContentRuleRe, (...m) => {
const rule = m[0].replace(m[1], '').replace(m[2], '');
return m[4] + rule;
});
}
/* Ensure styles are scoped. Pseudo-scoping takes a rule like:
*
* .foo {... }
*
* and converts this to
*
* scopeName .foo { ... }
*/
_scopeCssText(cssText, scopeSelector, hostSelector) {
const unscopedRules = this._extractUnscopedRulesFromCssText(cssText);
// replace :host and :host-context -shadowcsshost and -shadowcsshost respectively
cssText = this._insertPolyfillHostInCssText(cssText);
cssText = this._convertColonHost(cssText);
cssText = this._convertColonHostContext(cssText);
cssText = this._convertShadowDOMSelectors(cssText);
if (scopeSelector) {
cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector);
}
cssText = cssText + '\n' + unscopedRules;
return cssText.trim();
}
/*
* Process styles to add rules which will only apply under the polyfill
* and do not process via CSSOM. (CSSOM is destructive to rules on rare
* occasions, e.g. -webkit-calc on Safari.)
* For example, we convert this rule:
*
* @polyfill-unscoped-rule {
* content: 'menu-item';
* ... }
*
* to this:
*
* menu-item {...}
*
**/
_extractUnscopedRulesFromCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
let r = '';
let m;
_cssContentUnscopedRuleRe.lastIndex = 0;
while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
r += rule + '\n\n';
}
return r;
}
/*
* convert a rule like :host(.foo) > .bar { }
*
* to
*
* .foo > .bar
*/
_convertColonHost(cssText) {
return this._convertColonRule(cssText, _cssColonHostRe, this._colonHostPartReplacer);
}
/*
* convert a rule like :host-context(.foo) > .bar { }
*
* to
*
* .foo > .bar, .foo scopeName > .bar { }
*
* and
*
* :host-context(.foo:host) .bar { ... }
*
* to
*
* .foo .bar { ... }
*/
_convertColonHostContext(cssText) {
return this._convertColonRule(cssText, _cssColonHostContextRe, this._colonHostContextPartReplacer);
}
_convertColonRule(cssText, regExp, partReplacer) {
// m[1] = :host(-context), m[2] = contents of (), m[3] rest of rule
return cssText.replace(regExp, function (...m) {
if (m[2]) {
const parts = m[2].split(',');
const r = [];
for (let i = 0; i < parts.length; i++) {
const p = parts[i].trim();
if (!p)
break;
r.push(partReplacer(_polyfillHostNoCombinator, p, m[3]));
}
return r.join(',');
}
else {
return _polyfillHostNoCombinator + m[3];
}
});
}
_colonHostContextPartReplacer(host, part, suffix) {
if (part.indexOf(_polyfillHost) > -1) {
return this._colonHostPartReplacer(host, part, suffix);
}
else {
return host + part + suffix + ', ' + part + ' ' + host + suffix;
}
}
_colonHostPartReplacer(host, part, suffix) {
return host + part.replace(_polyfillHost, '') + suffix;
}
/*
* Convert combinators like ::shadow and pseudo-elements like ::content
* by replacing with space.
*/
_convertShadowDOMSelectors(cssText) {
return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText);
}
// change a selector like 'div' to 'name div'
_scopeSelectors(cssText, scopeSelector, hostSelector) {
return processRules(cssText, (rule) => {
let selector = rule.selector;
let content = rule.content;
if (rule.selector[0] != '@') {
selector =
this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling);
}
else if (rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') ||
rule.selector.startsWith('@page') || rule.selector.startsWith('@document')) {
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
}
return new CssRule(selector, content);
});
}
_scopeSelector(selector, scopeSelector, hostSelector, strict) {
return selector.split(',')
.map(part => part.trim().split(_shadowDeepSelectors))
.map((deepParts) => {
const [shallowPart, ...otherParts] = deepParts;
const applyScope = (shallowPart) => {
if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
return strict ?
this._applyStrictSelectorScope(shallowPart, scopeSelector, hostSelector) :
this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
}
else {
return shallowPart;
}
};
return [applyScope(shallowPart), ...otherParts].join(' ');
})
.join(', ');
}
_selectorNeedsScoping(selector, scopeSelector) {
const re = this._makeScopeMatcher(scopeSelector);
return !re.test(selector);
}
_makeScopeMatcher(scopeSelector) {
const lre = /\[/g;
const rre = /\]/g;
scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]');
return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
}
_applySelectorScope(selector, scopeSelector, hostSelector) {
// Difference from webcomponents.js: scopeSelector could not be an array
return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector);
}
// scope via name and [is=name]
_applySimpleSelectorScope(selector, scopeSelector, hostSelector) {
// In Android browser, the lastIndex is not reset when the regex is used in String.replace()
_polyfillHostRe.lastIndex = 0;
if (_polyfillHostRe.test(selector)) {
const replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector;
return selector
.replace(_polyfillHostNoCombinatorRe, (hnc, selector) => {
return selector.replace(/([^:]*)(:*)(.*)/, (_, before, colon, after) => {
return before + replaceBy + colon + after;
});
})
.replace(_polyfillHostRe, replaceBy + ' ');
}
return scopeSelector + ' ' + selector;
}
// return a selector with [name] suffix on each simple selector
// e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */
_applyStrictSelectorScope(selector, scopeSelector, hostSelector) {
const isRe = /\[is=([^\]]*)\]/g;
scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]);
const attrName = '[' + scopeSelector + ']';
const _scopeSelectorPart = (p) => {
let scopedP = p.trim();
if (!scopedP) {
return '';
}
if (p.indexOf(_polyfillHostNoCombinator) > -1) {
scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
}
else {
// remove :host since it should be unnecessary
const t = p.replace(_polyfillHostRe, '');
if (t.length > 0) {
const matches = t.match(/([^:]*)(:*)(.*)/);
if (matches) {
scopedP = matches[1] + attrName + matches[2] + matches[3];
}
}
}
return scopedP;
};
const safeContent = new SafeSelector(selector);
selector = safeContent.content();
let scopedSelector = '';
let startIndex = 0;
let res;
const sep = /( |>|\+|~(?!=))\s*/g;
// If a selector appears before :host it should not be shimmed as it
// matches on ancestor elements and not on elements in the host's shadow
// `:host-context(div)` is transformed to
// `-shadowcsshost-no-combinatordiv, div -shadowcsshost-no-combinator`
// the `div` is not part of the component in the 2nd selectors and should not be scoped.
// Historically `component-tag:host` was matching the component so we also want to preserve
// this behavior to avoid breaking legacy apps (it should not match).
// The behavior should be:
// - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything)
// - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a
// `:host-context(tag)`)
const hasHost = selector.indexOf(_polyfillHostNoCombinator) > -1;
// Only scope parts after the first `-shadowcsshost-no-combinator` when it is present
let shouldScope = !hasHost;
while ((res = sep.exec(selector)) !== null) {
const separator = res[1];
const part = selector.slice(startIndex, res.index).trim();
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
scopedSelector += `${scopedPart} ${separator} `;
startIndex = sep.lastIndex;
}
const part = selector.substring(startIndex);
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
scopedSelector += shouldScope ? _scopeSelectorPart(part) : part;
// replace the placeholders with their original values
return safeContent.restore(scopedSelector);
}
_insertPolyfillHostInCssText(selector) {
return selector.replace(_colonHostContextRe, _polyfillHostContext)
.replace(_colonHostRe, _polyfillHost);
}
}
class SafeSelector {
constructor(selector) {
this.placeholders = [];
this.index = 0;
// Replaces attribute selectors with placeholders.
// The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
selector = selector.replace(/(\[[^\]]*\])/g, (_, keep) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(keep);
this.index++;
return replaceBy;
});
// Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
// WS and "+" would otherwise be interpreted as selector separators.
this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(exp);
this.index++;
return pseudo + replaceBy;
});
}
restore(content) {
return content.replace(/__ph-(\d+)__/g, (ph, index) => this.placeholders[+index]);
}
content() { return this._content; }
}
const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim;
const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _polyfillHost = '-shadowcsshost';
// note: :host-context pre-processed to -shadowcsshostcontext.
const _polyfillHostContext = '-shadowcsscontext';
const _parenSuffix = ')(?:\\((' +
'(?:\\([^)(]*\\)|[^)(]*)+?' +
')\\))?([^,{]*)';
const _cssColonHostRe = new RegExp('(' + _polyfillHost + _parenSuffix, 'gim');
const _cssColonHostContextRe = new RegExp('(' + _polyfillHostContext + _parenSuffix, 'gim');
const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
const _shadowDOMSelectorsRe = [
/::shadow/g,
/::content/g,
// Deprecated selectors
/\/shadow-deep\//g,
/\/shadow\//g,
];
// The deep combinator is deprecated in the CSS spec
// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
// see https://github.com/angular/angular/pull/17677
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
const _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
const _polyfillHostRe = /-shadowcsshost/gim;
const _colonHostRe = /:host/gim;
const _colonHostContextRe = /:host-context/gim;
const _commentRe = /\/\*\s*[\s\S]*?\*\//g;
function stripComments(input) {
return input.replace(_commentRe, '');
}
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
function extractCommentsWithHash(input) {
return input.match(_commentWithHashRe) || [];
}
const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
const _curlyRe = /([{}])/g;
const OPEN_CURLY = '{';
const CLOSE_CURLY = '}';
const BLOCK_PLACEHOLDER = '%BLOCK%';
class CssRule {
constructor(selector, content) {
this.selector = selector;
this.content = content;
}
}
function processRules(input, ruleCallback) {
const inputWithEscapedBlocks = escapeBlocks(input);
let nextBlockIndex = 0;
return inputWithEscapedBlocks.escapedString.replace(_ruleRe, function (...m) {
const selector = m[2];
let content = '';
let suffix = m[4];
let contentPrefix = '';
if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) {
content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1);
contentPrefix = '{';
}
const rule = ruleCallback(new CssRule(selector, content));
return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
});
}
class StringWithEscapedBlocks {
constructor(escapedString, blocks) {
this.escapedString = escapedString;
this.blocks = blocks;
}
}
function escapeBlocks(input) {
const inputParts = input.split(_curlyRe);
const resultParts = [];
const escapedBlocks = [];
let bracketCount = 0;
let currentBlockParts = [];
for (let partIndex = 0; partIndex < inputParts.length; partIndex++) {
const part = inputParts[partIndex];
if (part == CLOSE_CURLY) {
bracketCount--;
}
if (bracketCount > 0) {
currentBlockParts.push(part);
}
else {
if (currentBlockParts.length > 0) {
escapedBlocks.push(currentBlockParts.join(''));
resultParts.push(BLOCK_PLACEHOLDER);
currentBlockParts = [];
}
resultParts.push(part);
}
if (part == OPEN_CURLY) {
bracketCount++;
}
}
if (currentBlockParts.length > 0) {
escapedBlocks.push(currentBlockParts.join(''));
resultParts.push(BLOCK_PLACEHOLDER);
}
return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
}
/**
* @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 COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
class StylesCompileDependency {
constructor(name, moduleUrl, setValue) {
this.name = name;
this.moduleUrl = moduleUrl;
this.setValue = setValue;
}
}
class CompiledStylesheet {
constructor(outputCtx, stylesVar, dependencies, isShimmed, meta) {
this.outputCtx = outputCtx;
this.stylesVar = stylesVar;
this.dependencies = dependencies;
this.isShimmed = isShimmed;
this.meta = meta;
}
}
class StyleCompiler {
constructor(_urlResolver) {
this._urlResolver = _urlResolver;
this._shadowCss = new ShadowCss();
}
compileComponent(outputCtx, comp) {
const template = comp.template;
return this._compileStyles(outputCtx, comp, new CompileStylesheetMetadata({
styles: template.styles,
styleUrls: template.styleUrls,
moduleUrl: identifierModuleUrl(comp.type)
}), this.needsStyleShim(comp), true);
}
compileStyles(outputCtx, comp, stylesheet, shim = this.needsStyleShim(comp)) {
return this._compileStyles(outputCtx, comp, stylesheet, shim, false);
}
needsStyleShim(comp) {
return comp.template.encapsulation === ViewEncapsulation.Emulated;
}
_compileStyles(outputCtx, comp, stylesheet, shim, isComponentStylesheet) {
const styleExpressions = stylesheet.styles.map(plainStyle => literal(this._shimIfNeeded(plainStyle, shim)));
const dependencies = [];
stylesheet.styleUrls.forEach((styleUrl) => {
const exprIndex = styleExpressions.length;
// Note: This placeholder will be filled later.
styleExpressions.push(null);
dependencies.push(new StylesCompileDependency(getStylesVarName(null), styleUrl, (value) => styleExpressions[exprIndex] = outputCtx.importExpr(value)));
});
// styles variable contains plain strings and arrays of other styles arrays (recursive),
// so we set its type to dynamic.
const stylesVar = getStylesVarName(isComponentStylesheet ? comp : null);
const stmt = variable(stylesVar)
.set(literalArr(styleExpressions, new ArrayType(DYNAMIC_TYPE, [TypeModifier.Const])))
.toDeclStmt(null, isComponentStylesheet ? [StmtModifier.Final] : [
StmtModifier.Final, StmtModifier.Exported
]);
outputCtx.statements.push(stmt);
return new CompiledStylesheet(outputCtx, stylesVar, dependencies, shim, stylesheet);
}
_shimIfNeeded(style, shim) {
return shim ? this._shadowCss.shimCssText(style, CONTENT_ATTR, HOST_ATTR) : style;
}
}
function getStylesVarName(component) {
let result = `styles`;
if (component) {
result += `_${identifierName(component.type)}`;
}
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
*/
/**
* A path is an ordered set of elements. Typically a path is to a
* particular offset in a source file. The head of the list is the top
* most node. The tail is the node that contains the offset directly.
*
* For example, the expression `a + b + c` might have an ast that looks
* like:
* +
* / \
* a +
* / \
* b c
*
* The path to the node at offset 9 would be `['+' at 1-10, '+' at 7-10,
* 'c' at 9-10]` and the path the node at offset 1 would be
* `['+' at 1-10, 'a' at 1-2]`.
*/
class AstPath {
constructor(path, position = -1) {
this.path = path;
this.position = position;
}
get empty() { return !this.path || !this.path.length; }
get head() { return this.path[0]; }
get tail() { return this.path[this.path.length - 1]; }
parentOf(node) {
return node && this.path[this.path.indexOf(node) - 1];
}
childOf(node) { return this.path[this.path.indexOf(node) + 1]; }
first(ctor) {
for (let i = this.path.length - 1; i >= 0; i--) {
let item = this.path[i];
if (item instanceof ctor)
return item;
}
}
push(node) { this.path.push(node); }
pop() { return this.path.pop(); }
}
/**
* @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 Text$3 {
constructor(value, sourceSpan, i18n) {
this.value = value;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor, context) { return visitor.visitText(this, context); }
}
class Expansion {
constructor(switchValue, type, cases, sourceSpan, switchValueSourceSpan, i18n) {
this.switchValue = switchValue;
this.type = type;
this.cases = cases;
this.sourceSpan = sourceSpan;
this.switchValueSourceSpan = switchValueSourceSpan;
this.i18n = i18n;
}
visit(visitor, context) { return visitor.visitExpansion(this, context); }
}
class ExpansionCase {
constructor(value, expression, sourceSpan, valueSourceSpan, expSourceSpan) {
this.value = value;
this.expression = expression;
this.sourceSpan = sourceSpan;
this.valueSourceSpan = valueSourceSpan;
this.expSourceSpan = expSourceSpan;
}
visit(visitor, context) { return visitor.visitExpansionCase(this, context); }
}
class Attribute {
constructor(name, value, sourceSpan, valueSpan, i18n) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
visit(visitor, context) { return visitor.visitAttribute(this, context); }
}
class Element$1 {
constructor(name, attrs, children, sourceSpan, startSourceSpan = null, endSourceSpan = null, i18n) {
this.name = name;
this.attrs = attrs;
this.children = children;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor, context) { return visitor.visitElement(this, context); }
}
class Comment {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) { return visitor.visitComment(this, context); }
}
function visitAll$1(visitor, nodes, context = null) {
const result = [];
const visit = visitor.visit ?
(ast) => visitor.visit(ast, context) || ast.visit(visitor, context) :
(ast) => ast.visit(visitor, context);
nodes.forEach(ast => {
const astResult = visit(ast);
if (astResult) {
result.push(astResult);
}
});
return result;
}
class RecursiveVisitor$1 {
constructor() { }
visitElement(ast, context) {
this.visitChildren(context, visit => {
visit(ast.attrs);
visit(ast.children);
});
}
visitAttribute(ast, context) { }
visitText(ast, context) { }
visitComment(ast, context) { }
visitExpansion(ast, context) {
return this.visitChildren(context, visit => { visit(ast.cases); });
}
visitExpansionCase(ast, context) { }
visitChildren(context, cb) {
let results = [];
let t = this;
function visit(children) {
if (children)
results.push(visitAll$1(t, children, context));
}
cb(visit);
return Array.prototype.concat.apply([], results);
}
}
function spanOf(ast) {
const start = ast.sourceSpan.start.offset;
let end = ast.sourceSpan.end.offset;
if (ast instanceof Element$1) {
if (ast.endSourceSpan) {
end = ast.endSourceSpan.end.offset;
}
else if (ast.children && ast.children.length) {
end = spanOf(ast.children[ast.children.length - 1]).end;
}
}
return { start, end };
}
function findNode(nodes, position) {
const path = [];
const visitor = new class extends RecursiveVisitor$1 {
visit(ast, context) {
const span = spanOf(ast);
if (span.start <= position && position < span.end) {
path.push(ast);
}
else {
// Returning a value here will result in the children being skipped.
return true;
}
}
};
visitAll$1(visitor, nodes);
return new AstPath(path, position);
}
/**
* @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 TokenType;
(function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_QUOTE"] = 12] = "ATTR_QUOTE";
TokenType[TokenType["ATTR_VALUE"] = 13] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 14] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 15] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 16] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 17] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 18] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 19] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 20] = "EOF";
})(TokenType || (TokenType = {}));
class Token {
constructor(type, parts, sourceSpan) {
this.type = type;
this.parts = parts;
this.sourceSpan = sourceSpan;
}
}
class TokenError extends ParseError {
constructor(errorMsg, tokenType, span) {
super(span, errorMsg);
this.tokenType = tokenType;
}
}
class TokenizeResult {
constructor(tokens, errors) {
this.tokens = tokens;
this.errors = errors;
}
}
function tokenize(source, url, getTagDefinition, options = {}) {
return new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options).tokenize();
}
const _CR_OR_CRLF_REGEXP = /\r\n?/g;
function _unexpectedCharacterErrorMsg(charCode) {
const char = charCode === $EOF ? 'EOF' : String.fromCharCode(charCode);
return `Unexpected character "${char}"`;
}
function _unknownEntityErrorMsg(entitySrc) {
return `Unknown entity "${entitySrc}" - use the ";" or ";" syntax`;
}
class _ControlFlowError {
constructor(error) {
this.error = error;
}
}
// See http://www.w3.org/TR/html51/syntax.html#writing
class _Tokenizer {
/**
* @param _file The html source file being tokenized.
* @param _getTagDefinition A function that will retrieve a tag definition for a given tag name.
* @param options Configuration of the tokenization.
*/
constructor(_file, _getTagDefinition, options) {
this._getTagDefinition = _getTagDefinition;
this._currentTokenStart = null;
this._currentTokenType = null;
this._expansionCaseStack = [];
this._inInterpolation = false;
this.tokens = [];
this.errors = [];
this._tokenizeIcu = options.tokenizeExpansionForms || false;
this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
this._leadingTriviaCodePoints =
options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0);
const range = options.range || { endPos: _file.content.length, startPos: 0, startLine: 0, startCol: 0 };
this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) :
new PlainCharacterCursor(_file, range);
try {
this._cursor.init();
}
catch (e) {
this.handleError(e);
}
}
_processCarriageReturns(content) {
// http://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream
// In order to keep the original position in the source, we can not
// pre-process it.
// Instead CRs are processed right before instantiating the tokens.
return content.replace(_CR_OR_CRLF_REGEXP, '\n');
}
tokenize() {
while (this._cursor.peek() !== $EOF) {
const start = this._cursor.clone();
try {
if (this._attemptCharCode($LT)) {
if (this._attemptCharCode($BANG)) {
if (this._attemptCharCode($LBRACKET)) {
this._consumeCdata(start);
}
else if (this._attemptCharCode($MINUS)) {
this._consumeComment(start);
}
else {
this._consumeDocType(start);
}
}
else if (this._attemptCharCode($SLASH)) {
this._consumeTagClose(start);
}
else {
this._consumeTagOpen(start);
}
}
else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
this._consumeText();
}
}
catch (e) {
this.handleError(e);
}
}
this._beginToken(TokenType.EOF);
this._endToken([]);
return new TokenizeResult(mergeTextTokens(this.tokens), this.errors);
}
/**
* @returns whether an ICU token has been created
* @internal
*/
_tokenizeExpansionForm() {
if (this.isExpansionFormStart()) {
this._consumeExpansionFormStart();
return true;
}
if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) {
this._consumeExpansionCaseStart();
return true;
}
if (this._cursor.peek() === $RBRACE) {
if (this._isInExpansionCase()) {
this._consumeExpansionCaseEnd();
return true;
}
if (this._isInExpansionForm()) {
this._consumeExpansionFormEnd();
return true;
}
}
return false;
}
_beginToken(type, start = this._cursor.clone()) {
this._currentTokenStart = start;
this._currentTokenType = type;
}
_endToken(parts, end = this._cursor.clone()) {
if (this._currentTokenStart === null) {
throw new TokenError('Programming error - attempted to end a token when there was no start to the token', this._currentTokenType, this._cursor.getSpan(end));
}
if (this._currentTokenType === null) {
throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart));
}
const token = new Token(this._currentTokenType, parts, this._cursor.getSpan(this._currentTokenStart, this._leadingTriviaCodePoints));
this.tokens.push(token);
this._currentTokenStart = null;
this._currentTokenType = null;
return token;
}
_createError(msg, span) {
if (this._isInExpansionForm()) {
msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
}
const error = new TokenError(msg, this._currentTokenType, span);
this._currentTokenStart = null;
this._currentTokenType = null;
return new _ControlFlowError(error);
}
handleError(e) {
if (e instanceof CursorError) {
e = this._createError(e.msg, this._cursor.getSpan(e.cursor));
}
if (e instanceof _ControlFlowError) {
this.errors.push(e.error);
}
else {
throw e;
}
}
_attemptCharCode(charCode) {
if (this._cursor.peek() === charCode) {
this._cursor.advance();
return true;
}
return false;
}
_attemptCharCodeCaseInsensitive(charCode) {
if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) {
this._cursor.advance();
return true;
}
return false;
}
_requireCharCode(charCode) {
const location = this._cursor.clone();
if (!this._attemptCharCode(charCode)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptStr(chars) {
const len = chars.length;
if (this._cursor.charsLeft() < len) {
return false;
}
const initialPosition = this._cursor.clone();
for (let i = 0; i < len; i++) {
if (!this._attemptCharCode(chars.charCodeAt(i))) {
// If attempting to parse the string fails, we want to reset the parser
// to where it was before the attempt
this._cursor = initialPosition;
return false;
}
}
return true;
}
_attemptStrCaseInsensitive(chars) {
for (let i = 0; i < chars.length; i++) {
if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) {
return false;
}
}
return true;
}
_requireStr(chars) {
const location = this._cursor.clone();
if (!this._attemptStr(chars)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptCharCodeUntilFn(predicate) {
while (!predicate(this._cursor.peek())) {
this._cursor.advance();
}
}
_requireCharCodeUntilFn(predicate, len) {
const start = this._cursor.clone();
this._attemptCharCodeUntilFn(predicate);
const end = this._cursor.clone();
if (end.diff(start) < len) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
}
_attemptUntilChar(char) {
while (this._cursor.peek() !== char) {
this._cursor.advance();
}
}
_readChar(decodeEntities) {
if (decodeEntities && this._cursor.peek() === $AMPERSAND) {
return this._decodeEntity();
}
else {
// Don't rely upon reading directly from `_input` as the actual char value
// may have been generated from an escape sequence.
const char = String.fromCodePoint(this._cursor.peek());
this._cursor.advance();
return char;
}
}
_decodeEntity() {
const start = this._cursor.clone();
this._cursor.advance();
if (this._attemptCharCode($HASH)) {
const isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
const codeStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isDigitEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan());
}
const strNum = this._cursor.getChars(codeStart);
this._cursor.advance();
try {
const charCode = parseInt(strNum, isHex ? 16 : 10);
return String.fromCharCode(charCode);
}
catch (_a) {
throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
}
}
else {
const nameStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isNamedEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
this._cursor = nameStart;
return '&';
}
const name = this._cursor.getChars(nameStart);
this._cursor.advance();
const char = NAMED_ENTITIES[name];
if (!char) {
throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
}
return char;
}
}
_consumeRawText(decodeEntities, endMarkerPredicate) {
this._beginToken(decodeEntities ? TokenType.ESCAPABLE_RAW_TEXT : TokenType.RAW_TEXT);
const parts = [];
while (true) {
const tagCloseStart = this._cursor.clone();
const foundEndMarker = endMarkerPredicate();
this._cursor = tagCloseStart;
if (foundEndMarker) {
break;
}
parts.push(this._readChar(decodeEntities));
}
return this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_consumeComment(start) {
this._beginToken(TokenType.COMMENT_START, start);
this._requireCharCode($MINUS);
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr('-->'));
this._beginToken(TokenType.COMMENT_END);
this._requireStr('-->');
this._endToken([]);
}
_consumeCdata(start) {
this._beginToken(TokenType.CDATA_START, start);
this._requireStr('CDATA[');
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr(']]>'));
this._beginToken(TokenType.CDATA_END);
this._requireStr(']]>');
this._endToken([]);
}
_consumeDocType(start) {
this._beginToken(TokenType.DOC_TYPE, start);
const contentStart = this._cursor.clone();
this._attemptUntilChar($GT);
const content = this._cursor.getChars(contentStart);
this._cursor.advance();
this._endToken([content]);
}
_consumePrefixAndName() {
const nameOrPrefixStart = this._cursor.clone();
let prefix = '';
while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
this._cursor.advance();
}
let nameStart;
if (this._cursor.peek() === $COLON) {
prefix = this._cursor.getChars(nameOrPrefixStart);
this._cursor.advance();
nameStart = this._cursor.clone();
}
else {
nameStart = nameOrPrefixStart;
}
this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
const name = this._cursor.getChars(nameStart);
return [prefix, name];
}
_consumeTagOpen(start) {
let tagName;
let prefix;
let openTagToken;
let tokensBeforeTagOpen = this.tokens.length;
const innerStart = this._cursor.clone();
try {
if (!isAsciiLetter(this._cursor.peek())) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
openTagToken = this._consumeTagOpenStart(start);
prefix = openTagToken.parts[0];
tagName = openTagToken.parts[1];
this._attemptCharCodeUntilFn(isNotWhitespace);
while (this._cursor.peek() !== $SLASH && this._cursor.peek() !== $GT) {
this._consumeAttributeName();
this._attemptCharCodeUntilFn(isNotWhitespace);
if (this._attemptCharCode($EQ)) {
this._attemptCharCodeUntilFn(isNotWhitespace);
this._consumeAttributeValue();
}
this._attemptCharCodeUntilFn(isNotWhitespace);
}
this._consumeTagOpenEnd();
}
catch (e) {
if (e instanceof _ControlFlowError) {
// When the start tag is invalid (including invalid "attributes"), assume we want a "<"
this._cursor = innerStart;
if (openTagToken) {
this.tokens.length = tokensBeforeTagOpen;
}
// Back to back text tokens are merged at the end
this._beginToken(TokenType.TEXT, start);
this._endToken(['<']);
return;
}
throw e;
}
const contentTokenType = this._getTagDefinition(tagName).contentType;
if (contentTokenType === TagContentType.RAW_TEXT) {
this._consumeRawTextWithTagClose(prefix, tagName, false);
}
else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
this._consumeRawTextWithTagClose(prefix, tagName, true);
}
}
_consumeRawTextWithTagClose(prefix, tagName, decodeEntities) {
const textToken = this._consumeRawText(decodeEntities, () => {
if (!this._attemptCharCode($LT))
return false;
if (!this._attemptCharCode($SLASH))
return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
if (!this._attemptStrCaseInsensitive(tagName))
return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
return this._attemptCharCode($GT);
});
this._beginToken(TokenType.TAG_CLOSE);
this._requireCharCodeUntilFn(code => code === $GT, 3);
this._cursor.advance(); // Consume the `>`
this._endToken([prefix, tagName]);
}
_consumeTagOpenStart(start) {
this._beginToken(TokenType.TAG_OPEN_START, start);
const parts = this._consumePrefixAndName();
return this._endToken(parts);
}
_consumeAttributeName() {
const attrNameStart = this._cursor.peek();
if (attrNameStart === $SQ || attrNameStart === $DQ) {
throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
}
this._beginToken(TokenType.ATTR_NAME);
const prefixAndName = this._consumePrefixAndName();
this._endToken(prefixAndName);
}
_consumeAttributeValue() {
let value;
if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) {
this._beginToken(TokenType.ATTR_QUOTE);
const quoteChar = this._cursor.peek();
this._cursor.advance();
this._endToken([String.fromCodePoint(quoteChar)]);
this._beginToken(TokenType.ATTR_VALUE);
const parts = [];
while (this._cursor.peek() !== quoteChar) {
parts.push(this._readChar(true));
}
value = parts.join('');
this._endToken([this._processCarriageReturns(value)]);
this._beginToken(TokenType.ATTR_QUOTE);
this._cursor.advance();
this._endToken([String.fromCodePoint(quoteChar)]);
}
else {
this._beginToken(TokenType.ATTR_VALUE);
const valueStart = this._cursor.clone();
this._requireCharCodeUntilFn(isNameEnd, 1);
value = this._cursor.getChars(valueStart);
this._endToken([this._processCarriageReturns(value)]);
}
}
_consumeTagOpenEnd() {
const tokenType = this._attemptCharCode($SLASH) ? TokenType.TAG_OPEN_END_VOID : TokenType.TAG_OPEN_END;
this._beginToken(tokenType);
this._requireCharCode($GT);
this._endToken([]);
}
_consumeTagClose(start) {
this._beginToken(TokenType.TAG_CLOSE, start);
this._attemptCharCodeUntilFn(isNotWhitespace);
const prefixAndName = this._consumePrefixAndName();
this._attemptCharCodeUntilFn(isNotWhitespace);
this._requireCharCode($GT);
this._endToken(prefixAndName);
}
_consumeExpansionFormStart() {
this._beginToken(TokenType.EXPANSION_FORM_START);
this._requireCharCode($LBRACE);
this._endToken([]);
this._expansionCaseStack.push(TokenType.EXPANSION_FORM_START);
this._beginToken(TokenType.RAW_TEXT);
const condition = this._readUntil($COMMA);
this._endToken([condition]);
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(TokenType.RAW_TEXT);
const type = this._readUntil($COMMA);
this._endToken([type]);
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
}
_consumeExpansionCaseStart() {
this._beginToken(TokenType.EXPANSION_CASE_VALUE);
const value = this._readUntil($LBRACE).trim();
this._endToken([value]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(TokenType.EXPANSION_CASE_EXP_START);
this._requireCharCode($LBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.push(TokenType.EXPANSION_CASE_EXP_START);
}
_consumeExpansionCaseEnd() {
this._beginToken(TokenType.EXPANSION_CASE_EXP_END);
this._requireCharCode($RBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.pop();
}
_consumeExpansionFormEnd() {
this._beginToken(TokenType.EXPANSION_FORM_END);
this._requireCharCode($RBRACE);
this._endToken([]);
this._expansionCaseStack.pop();
}
_consumeText() {
const start = this._cursor.clone();
this._beginToken(TokenType.TEXT, start);
const parts = [];
do {
if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
parts.push(this._interpolationConfig.start);
this._inInterpolation = true;
}
else if (this._interpolationConfig && this._inInterpolation &&
this._attemptStr(this._interpolationConfig.end)) {
parts.push(this._interpolationConfig.end);
this._inInterpolation = false;
}
else {
parts.push(this._readChar(true));
}
} while (!this._isTextEnd());
this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_isTextEnd() {
if (this._cursor.peek() === $LT || this._cursor.peek() === $EOF) {
return true;
}
if (this._tokenizeIcu && !this._inInterpolation) {
if (this.isExpansionFormStart()) {
// start of an expansion form
return true;
}
if (this._cursor.peek() === $RBRACE && this._isInExpansionCase()) {
// end of and expansion case
return true;
}
}
return false;
}
_readUntil(char) {
const start = this._cursor.clone();
this._attemptUntilChar(char);
return this._cursor.getChars(start);
}
_isInExpansionCase() {
return this._expansionCaseStack.length > 0 &&
this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
TokenType.EXPANSION_CASE_EXP_START;
}
_isInExpansionForm() {
return this._expansionCaseStack.length > 0 &&
this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
TokenType.EXPANSION_FORM_START;
}
isExpansionFormStart() {
if (this._cursor.peek() !== $LBRACE) {
return false;
}
if (this._interpolationConfig) {
const start = this._cursor.clone();
const isInterpolation = this._attemptStr(this._interpolationConfig.start);
this._cursor = start;
return !isInterpolation;
}
return true;
}
}
function isNotWhitespace(code) {
return !isWhitespace(code) || code === $EOF;
}
function isNameEnd(code) {
return isWhitespace(code) || code === $GT || code === $SLASH ||
code === $SQ || code === $DQ || code === $EQ;
}
function isPrefixEnd(code) {
return (code < $a || $z < code) && (code < $A || $Z < code) &&
(code < $0 || code > $9);
}
function isDigitEntityEnd(code) {
return code == $SEMICOLON || code == $EOF || !isAsciiHexDigit(code);
}
function isNamedEntityEnd(code) {
return code == $SEMICOLON || code == $EOF || !isAsciiLetter(code);
}
function isExpansionCaseStart(peek) {
return peek === $EQ || isAsciiLetter(peek) || isDigit(peek);
}
function compareCharCodeCaseInsensitive(code1, code2) {
return toUpperCaseCharCode(code1) == toUpperCaseCharCode(code2);
}
function toUpperCaseCharCode(code) {
return code >= $a && code <= $z ? code - $a + $A : code;
}
function mergeTextTokens(srcTokens) {
const dstTokens = [];
let lastDstToken = undefined;
for (let i = 0; i < srcTokens.length; i++) {
const token = srcTokens[i];
if (lastDstToken && lastDstToken.type == TokenType.TEXT && token.type == TokenType.TEXT) {
lastDstToken.parts[0] += token.parts[0];
lastDstToken.sourceSpan.end = token.sourceSpan.end;
}
else {
lastDstToken = token;
dstTokens.push(lastDstToken);
}
}
return dstTokens;
}
class PlainCharacterCursor {
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof PlainCharacterCursor) {
this.file = fileOrCursor.file;
this.input = fileOrCursor.input;
this.end = fileOrCursor.end;
this.state = Object.assign({}, fileOrCursor.state);
}
else {
if (!range) {
throw new Error('Programming error: the range argument must be provided with a file argument.');
}
this.file = fileOrCursor;
this.input = fileOrCursor.content;
this.end = range.endPos;
this.state = {
peek: -1,
offset: range.startPos,
line: range.startLine,
column: range.startCol,
};
}
}
clone() { return new PlainCharacterCursor(this); }
peek() { return this.state.peek; }
charsLeft() { return this.end - this.state.offset; }
diff(other) { return this.state.offset - other.state.offset; }
advance() { this.advanceState(this.state); }
init() { this.updatePeek(this.state); }
getSpan(start, leadingTriviaCodePoints) {
start = start || this;
if (leadingTriviaCodePoints) {
start = start.clone();
while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) {
start.advance();
}
}
return new ParseSourceSpan(new ParseLocation(start.file, start.state.offset, start.state.line, start.state.column), new ParseLocation(this.file, this.state.offset, this.state.line, this.state.column));
}
getChars(start) {
return this.input.substring(start.state.offset, this.state.offset);
}
charAt(pos) { return this.input.charCodeAt(pos); }
advanceState(state) {
if (state.offset >= this.end) {
this.state = state;
throw new CursorError('Unexpected character "EOF"', this);
}
const currentChar = this.charAt(state.offset);
if (currentChar === $LF) {
state.line++;
state.column = 0;
}
else if (!isNewLine(currentChar)) {
state.column++;
}
state.offset++;
this.updatePeek(state);
}
updatePeek(state) {
state.peek = state.offset >= this.end ? $EOF : this.charAt(state.offset);
}
}
class EscapedCharacterCursor extends PlainCharacterCursor {
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof EscapedCharacterCursor) {
super(fileOrCursor);
this.internalState = Object.assign({}, fileOrCursor.internalState);
}
else {
super(fileOrCursor, range);
this.internalState = this.state;
}
}
advance() {
this.state = this.internalState;
super.advance();
this.processEscapeSequence();
}
init() {
super.init();
this.processEscapeSequence();
}
clone() { return new EscapedCharacterCursor(this); }
getChars(start) {
const cursor = start.clone();
let chars = '';
while (cursor.internalState.offset < this.internalState.offset) {
chars += String.fromCodePoint(cursor.peek());
cursor.advance();
}
return chars;
}
/**
* Process the escape sequence that starts at the current position in the text.
*
* This method is called to ensure that `peek` has the unescaped value of escape sequences.
*/
processEscapeSequence() {
const peek = () => this.internalState.peek;
if (peek() === $BACKSLASH) {
// We have hit an escape sequence so we need the internal state to become independent
// of the external state.
this.internalState = Object.assign({}, this.state);
// Move past the backslash
this.advanceState(this.internalState);
// First check for standard control char sequences
if (peek() === $n) {
this.state.peek = $LF;
}
else if (peek() === $r) {
this.state.peek = $CR;
}
else if (peek() === $v) {
this.state.peek = $VTAB;
}
else if (peek() === $t) {
this.state.peek = $TAB;
}
else if (peek() === $b) {
this.state.peek = $BSPACE;
}
else if (peek() === $f) {
this.state.peek = $FF;
}
// Now consider more complex sequences
else if (peek() === $u) {
// Unicode code-point sequence
this.advanceState(this.internalState); // advance past the `u` char
if (peek() === $LBRACE) {
// Variable length Unicode, e.g. `\x{123}`
this.advanceState(this.internalState); // advance past the `{` char
// Advance past the variable number of hex digits until we hit a `}` char
const digitStart = this.clone();
let length = 0;
while (peek() !== $RBRACE) {
this.advanceState(this.internalState);
length++;
}
this.state.peek = this.decodeHexDigits(digitStart, length);
}
else {
// Fixed length Unicode, e.g. `\u1234`
const digitStart = this.clone();
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 4);
}
}
else if (peek() === $x) {
// Hex char code, e.g. `\x2F`
this.advanceState(this.internalState); // advance past the `x` char
const digitStart = this.clone();
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 2);
}
else if (isOctalDigit(peek())) {
// Octal char code, e.g. `\012`,
let octal = '';
let length = 0;
let previous = this.clone();
while (isOctalDigit(peek()) && length < 3) {
previous = this.clone();
octal += String.fromCodePoint(peek());
this.advanceState(this.internalState);
length++;
}
this.state.peek = parseInt(octal, 8);
// Backup one char
this.internalState = previous.internalState;
}
else if (isNewLine(this.internalState.peek)) {
// Line continuation `\` followed by a new line
this.advanceState(this.internalState); // advance over the newline
this.state = this.internalState;
}
else {
// If none of the `if` blocks were executed then we just have an escaped normal character.
// In that case we just, effectively, skip the backslash from the character.
this.state.peek = this.internalState.peek;
}
}
}
decodeHexDigits(start, length) {
const hex = this.input.substr(start.internalState.offset, length);
const charCode = parseInt(hex, 16);
if (!isNaN(charCode)) {
return charCode;
}
else {
start.state = start.internalState;
throw new CursorError('Invalid hexadecimal escape sequence', start);
}
}
}
class CursorError {
constructor(msg, cursor) {
this.msg = msg;
this.cursor = cursor;
}
}
/**
* @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 TreeError extends ParseError {
constructor(elementName, span, msg) {
super(span, msg);
this.elementName = elementName;
}
static create(elementName, span, msg) {
return new TreeError(elementName, span, msg);
}
}
class ParseTreeResult {
constructor(rootNodes, errors) {
this.rootNodes = rootNodes;
this.errors = errors;
}
}
class Parser {
constructor(getTagDefinition) {
this.getTagDefinition = getTagDefinition;
}
parse(source, url, options) {
const tokensAndErrors = tokenize(source, url, this.getTagDefinition, options);
const treeAndErrors = new _TreeBuilder(tokensAndErrors.tokens, this.getTagDefinition).build();
return new ParseTreeResult(treeAndErrors.rootNodes, tokensAndErrors.errors.concat(treeAndErrors.errors));
}
}
class _TreeBuilder {
constructor(tokens, getTagDefinition) {
this.tokens = tokens;
this.getTagDefinition = getTagDefinition;
this._index = -1;
this._rootNodes = [];
this._errors = [];
this._elementStack = [];
this._advance();
}
build() {
while (this._peek.type !== TokenType.EOF) {
if (this._peek.type === TokenType.TAG_OPEN_START) {
this._consumeStartTag(this._advance());
}
else if (this._peek.type === TokenType.TAG_CLOSE) {
this._consumeEndTag(this._advance());
}
else if (this._peek.type === TokenType.CDATA_START) {
this._closeVoidElement();
this._consumeCdata(this._advance());
}
else if (this._peek.type === TokenType.COMMENT_START) {
this._closeVoidElement();
this._consumeComment(this._advance());
}
else if (this._peek.type === TokenType.TEXT || this._peek.type === TokenType.RAW_TEXT ||
this._peek.type === TokenType.ESCAPABLE_RAW_TEXT) {
this._closeVoidElement();
this._consumeText(this._advance());
}
else if (this._peek.type === TokenType.EXPANSION_FORM_START) {
this._consumeExpansion(this._advance());
}
else {
// Skip all other tokens...
this._advance();
}
}
return new ParseTreeResult(this._rootNodes, this._errors);
}
_advance() {
const prev = this._peek;
if (this._index < this.tokens.length - 1) {
// Note: there is always an EOF token at the end
this._index++;
}
this._peek = this.tokens[this._index];
return prev;
}
_advanceIf(type) {
if (this._peek.type === type) {
return this._advance();
}
return null;
}
_consumeCdata(startToken) {
this._consumeText(this._advance());
this._advanceIf(TokenType.CDATA_END);
}
_consumeComment(token) {
const text = this._advanceIf(TokenType.RAW_TEXT);
this._advanceIf(TokenType.COMMENT_END);
const value = text != null ? text.parts[0].trim() : null;
this._addToParent(new Comment(value, token.sourceSpan));
}
_consumeExpansion(token) {
const switchValue = this._advance();
const type = this._advance();
const cases = [];
// read =
while (this._peek.type === TokenType.EXPANSION_CASE_VALUE) {
const expCase = this._parseExpansionCase();
if (!expCase)
return; // error
cases.push(expCase);
}
// read the final }
if (this._peek.type !== TokenType.EXPANSION_FORM_END) {
this._errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`));
return;
}
const sourceSpan = new ParseSourceSpan(token.sourceSpan.start, this._peek.sourceSpan.end);
this._addToParent(new Expansion(switchValue.parts[0], type.parts[0], cases, sourceSpan, switchValue.sourceSpan));
this._advance();
}
_parseExpansionCase() {
const value = this._advance();
// read {
if (this._peek.type !== TokenType.EXPANSION_CASE_EXP_START) {
this._errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`));
return null;
}
// read until }
const start = this._advance();
const exp = this._collectExpansionExpTokens(start);
if (!exp)
return null;
const end = this._advance();
exp.push(new Token(TokenType.EOF, [], end.sourceSpan));
// parse everything in between { and }
const parsedExp = new _TreeBuilder(exp, this.getTagDefinition).build();
if (parsedExp.errors.length > 0) {
this._errors = this._errors.concat(parsedExp.errors);
return null;
}
const sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end);
const expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end);
return new ExpansionCase(value.parts[0], parsedExp.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
}
_collectExpansionExpTokens(start) {
const exp = [];
const expansionFormStack = [TokenType.EXPANSION_CASE_EXP_START];
while (true) {
if (this._peek.type === TokenType.EXPANSION_FORM_START ||
this._peek.type === TokenType.EXPANSION_CASE_EXP_START) {
expansionFormStack.push(this._peek.type);
}
if (this._peek.type === TokenType.EXPANSION_CASE_EXP_END) {
if (lastOnStack(expansionFormStack, TokenType.EXPANSION_CASE_EXP_START)) {
expansionFormStack.pop();
if (expansionFormStack.length == 0)
return exp;
}
else {
this._errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === TokenType.EXPANSION_FORM_END) {
if (lastOnStack(expansionFormStack, TokenType.EXPANSION_FORM_START)) {
expansionFormStack.pop();
}
else {
this._errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === TokenType.EOF) {
this._errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
exp.push(this._advance());
}
}
_consumeText(token) {
let text = token.parts[0];
if (text.length > 0 && text[0] == '\n') {
const parent = this._getParentElement();
if (parent != null && parent.children.length == 0 &&
this.getTagDefinition(parent.name).ignoreFirstLf) {
text = text.substring(1);
}
}
if (text.length > 0) {
this._addToParent(new Text$3(text, token.sourceSpan));
}
}
_closeVoidElement() {
const el = this._getParentElement();
if (el && this.getTagDefinition(el.name).isVoid) {
this._elementStack.pop();
}
}
_consumeStartTag(startTagToken) {
const prefix = startTagToken.parts[0];
const name = startTagToken.parts[1];
const attrs = [];
while (this._peek.type === TokenType.ATTR_NAME) {
attrs.push(this._consumeAttr(this._advance()));
}
const fullName = this._getElementFullName(prefix, name, this._getParentElement());
let selfClosing = false;
// Note: There could have been a tokenizer error
// so that we don't get a token for the end tag...
if (this._peek.type === TokenType.TAG_OPEN_END_VOID) {
this._advance();
selfClosing = true;
const tagDef = this.getTagDefinition(fullName);
if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) {
this._errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
}
}
else if (this._peek.type === TokenType.TAG_OPEN_END) {
this._advance();
selfClosing = false;
}
const end = this._peek.sourceSpan.start;
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end);
const el = new Element$1(fullName, attrs, [], span, span, undefined);
this._pushElement(el);
if (selfClosing) {
this._popElement(fullName);
el.endSourceSpan = span;
}
}
_pushElement(el) {
const parentEl = this._getParentElement();
if (parentEl && this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
this._elementStack.pop();
}
this._addToParent(el);
this._elementStack.push(el);
}
_consumeEndTag(endTagToken) {
const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
if (this._getParentElement()) {
this._getParentElement().endSourceSpan = endTagToken.sourceSpan;
}
if (this.getTagDefinition(fullName).isVoid) {
this._errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
}
else if (!this._popElement(fullName)) {
const errMsg = `Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
this._errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
}
}
_popElement(fullName) {
for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
const el = this._elementStack[stackIndex];
if (el.name == fullName) {
this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex);
return true;
}
if (!this.getTagDefinition(el.name).closedByParent) {
return false;
}
}
return false;
}
_consumeAttr(attrName) {
const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
let end = attrName.sourceSpan.end;
let value = '';
let valueSpan = undefined;
if (this._peek.type === TokenType.ATTR_QUOTE) {
this._advance();
}
if (this._peek.type === TokenType.ATTR_VALUE) {
const valueToken = this._advance();
value = valueToken.parts[0];
end = valueToken.sourceSpan.end;
valueSpan = valueToken.sourceSpan;
}
if (this._peek.type === TokenType.ATTR_QUOTE) {
const quoteToken = this._advance();
end = quoteToken.sourceSpan.end;
}
return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end), valueSpan);
}
_getParentElement() {
return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
}
/**
* Returns the parent in the DOM and the container.
*
* `` elements are skipped as they are not rendered as DOM element.
*/
_getParentElementSkippingContainers() {
let container = null;
for (let i = this._elementStack.length - 1; i >= 0; i--) {
if (!isNgContainer(this._elementStack[i].name)) {
return { parent: this._elementStack[i], container };
}
container = this._elementStack[i];
}
return { parent: null, container };
}
_addToParent(node) {
const parent = this._getParentElement();
if (parent != null) {
parent.children.push(node);
}
else {
this._rootNodes.push(node);
}
}
/**
* Insert a node between the parent and the container.
* When no container is given, the node is appended as a child of the parent.
* Also updates the element stack accordingly.
*
* @internal
*/
_insertBeforeContainer(parent, container, node) {
if (!container) {
this._addToParent(node);
this._elementStack.push(node);
}
else {
if (parent) {
// replace the container with the new node in the children
const index = parent.children.indexOf(container);
parent.children[index] = node;
}
else {
this._rootNodes.push(node);
}
node.children.push(container);
this._elementStack.splice(this._elementStack.indexOf(container), 0, node);
}
}
_getElementFullName(prefix, localName, parentElement) {
if (prefix === '') {
prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
if (prefix === '' && parentElement != null) {
prefix = getNsPrefix(parentElement.name);
}
}
return mergeNsAndName(prefix, localName);
}
}
function lastOnStack(stack, element) {
return stack.length > 0 && stack[stack.length - 1] === element;
}
/**
* @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 HtmlParser extends Parser {
constructor() { super(getHtmlTagDefinition); }
parse(source, url, options) {
return super.parse(source, url, options);
}
}
/**
* @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 PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']);
// Equivalent to \s with \u00a0 (non-breaking space) excluded.
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff';
const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`);
const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g');
function hasPreserveWhitespacesAttr(attrs) {
return attrs.some((attr) => attr.name === PRESERVE_WS_ATTR_NAME);
}
/**
* Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
* https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
* In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
* and later on replaced by a space. We are re-implementing the same idea here.
*/
function replaceNgsp(value) {
// lexer is replacing the &ngsp; pseudo-entity with NGSP_UNICODE
return value.replace(new RegExp(NGSP_UNICODE, 'g'), ' ');
}
/**
* This visitor can walk HTML parse tree and remove / trim text nodes using the following rules:
* - consider spaces, tabs and new lines as whitespace characters;
* - drop text nodes consisting of whitespace characters only;
* - for all other text nodes replace consecutive whitespace characters with one space;
* - convert &ngsp; pseudo-entity to a single space;
*
* Removal and trimming of whitespaces have positive performance impact (less code to generate
* while compiling templates, faster view creation). At the same time it can be "destructive"
* in some cases (whitespaces can influence layout). Because of the potential of breaking layout
* this visitor is not activated by default in Angular 5 and people need to explicitly opt-in for
* whitespace removal. The default option for whitespace removal will be revisited in Angular 6
* and might be changed to "on" by default.
*/
class WhitespaceVisitor {
visitElement(element, context) {
if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
// don't descent into elements where we need to preserve whitespaces
// but still visit all attributes to eliminate one used as a market to preserve WS
return new Element$1(element.name, visitAll$1(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
}
return new Element$1(element.name, element.attrs, visitAll$1(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
}
visitAttribute(attribute, context) {
return attribute.name !== PRESERVE_WS_ATTR_NAME ? attribute : null;
}
visitText(text, context) {
const isNotBlank = text.value.match(NO_WS_REGEXP);
if (isNotBlank) {
return new Text$3(replaceNgsp(text.value).replace(WS_REPLACE_REGEXP, ' '), text.sourceSpan, text.i18n);
}
return null;
}
visitComment(comment, context) { return comment; }
visitExpansion(expansion, context) { return expansion; }
visitExpansionCase(expansionCase, context) { return expansionCase; }
}
function removeWhitespaces(htmlAstWithErrors) {
return new ParseTreeResult(visitAll$1(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes), htmlAstWithErrors.errors);
}
/**
* @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
*/
// http://cldr.unicode.org/index/cldr-spec/plural-rules
const PLURAL_CASES = ['zero', 'one', 'two', 'few', 'many', 'other'];
/**
* Expands special forms into elements.
*
* For example,
*
* ```
* { messages.length, plural,
* =0 {zero}
* =1 {one}
* other {more than one}
* }
* ```
*
* will be expanded into
*
* ```
*
* zero
* one
* more than one
*
* ```
*/
function expandNodes(nodes) {
const expander = new _Expander();
return new ExpansionResult(visitAll$1(expander, nodes), expander.isExpanded, expander.errors);
}
class ExpansionResult {
constructor(nodes, expanded, errors) {
this.nodes = nodes;
this.expanded = expanded;
this.errors = errors;
}
}
class ExpansionError extends ParseError {
constructor(span, errorMsg) { super(span, errorMsg); }
}
/**
* Expand expansion forms (plural, select) to directives
*
* @internal
*/
class _Expander {
constructor() {
this.isExpanded = false;
this.errors = [];
}
visitElement(element, context) {
return new Element$1(element.name, element.attrs, visitAll$1(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan);
}
visitAttribute(attribute, context) { return attribute; }
visitText(text, context) { return text; }
visitComment(comment, context) { return comment; }
visitExpansion(icu, context) {
this.isExpanded = true;
return icu.type == 'plural' ? _expandPluralForm(icu, this.errors) :
_expandDefaultForm(icu, this.errors);
}
visitExpansionCase(icuCase, context) {
throw new Error('Should not be reached');
}
}
// Plural forms are expanded to `NgPlural` and `NgPluralCase`s
function _expandPluralForm(ast, errors) {
const children = ast.cases.map(c => {
if (PLURAL_CASES.indexOf(c.value) == -1 && !c.value.match(/^=\d+$/)) {
errors.push(new ExpansionError(c.valueSourceSpan, `Plural cases should be "=" or one of ${PLURAL_CASES.join(", ")}`));
}
const expansionResult = expandNodes(c.expression);
errors.push(...expansionResult.errors);
return new Element$1(`ng-template`, [new Attribute('ngPluralCase', `${c.value}`, c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
const switchAttr = new Attribute('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan);
return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}
// ICU messages (excluding plural form) are expanded to `NgSwitch` and `NgSwitchCase`s
function _expandDefaultForm(ast, errors) {
const children = ast.cases.map(c => {
const expansionResult = expandNodes(c.expression);
errors.push(...expansionResult.errors);
if (c.value === 'other') {
// other is the default case when no values match
return new Element$1(`ng-template`, [new Attribute('ngSwitchDefault', '', c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
}
return new Element$1(`ng-template`, [new Attribute('ngSwitchCase', `${c.value}`, c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
const switchAttr = new Attribute('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan);
return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}
/**
* @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, handlerSpan) {
this.name = name;
this.target = target;
this.phase = phase;
this.handler = handler;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
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, event.handlerSpan);
}
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 (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 `` 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 `` 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);
});
}
visitDirective(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.inputs);
visit(ast.hostProperties);
visit(ast.hostEvents);
});
}
visitChildren(context, cb) {
let results = [];
let t = this;
function visit(children) {
if (children && children.length)
results.push(templateVisitAll(t, children, context));
}
cb(visit);
return Array.prototype.concat.apply([], results);
}
}
/**
* Visit every node in a list of {@link TemplateAst}s with the given {@link TemplateAstVisitor}.
*/
function templateVisitAll(visitor, asts, context = null) {
const result = [];
const visit = visitor.visit ?
(ast) => visitor.visit(ast, context) || ast.visit(visitor, context) :
(ast) => ast.visit(visitor, context);
asts.forEach(ast => {
const astResult = visit(ast);
if (astResult) {
result.push(astResult);
}
});
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
*/
class ProviderError extends ParseError {
constructor(message, span) { super(span, message); }
}
class ProviderViewContext {
constructor(reflector, component) {
this.reflector = reflector;
this.component = component;
this.errors = [];
this.viewQueries = _getViewQueries(component);
this.viewProviders = new Map();
component.viewProviders.forEach((provider) => {
if (this.viewProviders.get(tokenReference(provider.token)) == null) {
this.viewProviders.set(tokenReference(provider.token), true);
}
});
}
}
class ProviderElementContext {
constructor(viewContext, _parent, _isViewRoot, _directiveAsts, attrs, refs, isTemplate, contentQueryStartId, _sourceSpan) {
this.viewContext = viewContext;
this._parent = _parent;
this._isViewRoot = _isViewRoot;
this._directiveAsts = _directiveAsts;
this._sourceSpan = _sourceSpan;
this._transformedProviders = new Map();
this._seenProviders = new Map();
this._queriedTokens = new Map();
this.transformedHasViewContainer = false;
this._attrs = {};
attrs.forEach((attrAst) => this._attrs[attrAst.name] = attrAst.value);
const directivesMeta = _directiveAsts.map(directiveAst => directiveAst.directive);
this._allProviders =
_resolveProvidersFromDirectives(directivesMeta, _sourceSpan, viewContext.errors);
this._contentQueries = _getContentQueries(contentQueryStartId, directivesMeta);
Array.from(this._allProviders.values()).forEach((provider) => {
this._addQueryReadsTo(provider.token, provider.token, this._queriedTokens);
});
if (isTemplate) {
const templateRefId = createTokenForExternalReference(this.viewContext.reflector, Identifiers.TemplateRef);
this._addQueryReadsTo(templateRefId, templateRefId, this._queriedTokens);
}
refs.forEach((refAst) => {
let defaultQueryValue = refAst.value ||
createTokenForExternalReference(this.viewContext.reflector, Identifiers.ElementRef);
this._addQueryReadsTo({ value: refAst.name }, defaultQueryValue, this._queriedTokens);
});
if (this._queriedTokens.get(this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef))) {
this.transformedHasViewContainer = true;
}
// create the providers that we know are eager first
Array.from(this._allProviders.values()).forEach((provider) => {
const eager = provider.eager || this._queriedTokens.get(tokenReference(provider.token));
if (eager) {
this._getOrCreateLocalProvider(provider.providerType, provider.token, true);
}
});
}
afterElement() {
// collect lazy providers
Array.from(this._allProviders.values()).forEach((provider) => {
this._getOrCreateLocalProvider(provider.providerType, provider.token, false);
});
}
get transformProviders() {
// Note: Maps keep their insertion order.
const lazyProviders = [];
const eagerProviders = [];
this._transformedProviders.forEach(provider => {
if (provider.eager) {
eagerProviders.push(provider);
}
else {
lazyProviders.push(provider);
}
});
return lazyProviders.concat(eagerProviders);
}
get transformedDirectiveAsts() {
const sortedProviderTypes = this.transformProviders.map(provider => provider.token.identifier);
const sortedDirectives = this._directiveAsts.slice();
sortedDirectives.sort((dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
sortedProviderTypes.indexOf(dir2.directive.type));
return sortedDirectives;
}
get queryMatches() {
const allMatches = [];
this._queriedTokens.forEach((matches) => { allMatches.push(...matches); });
return allMatches;
}
_addQueryReadsTo(token, defaultValue, queryReadTokens) {
this._getQueriesFor(token).forEach((query) => {
const queryValue = query.meta.read || defaultValue;
const tokenRef = tokenReference(queryValue);
let queryMatches = queryReadTokens.get(tokenRef);
if (!queryMatches) {
queryMatches = [];
queryReadTokens.set(tokenRef, queryMatches);
}
queryMatches.push({ queryId: query.queryId, value: queryValue });
});
}
_getQueriesFor(token) {
const result = [];
let currentEl = this;
let distance = 0;
let queries;
while (currentEl !== null) {
queries = currentEl._contentQueries.get(tokenReference(token));
if (queries) {
result.push(...queries.filter((query) => query.meta.descendants || distance <= 1));
}
if (currentEl._directiveAsts.length > 0) {
distance++;
}
currentEl = currentEl._parent;
}
queries = this.viewContext.viewQueries.get(tokenReference(token));
if (queries) {
result.push(...queries);
}
return result;
}
_getOrCreateLocalProvider(requestingProviderType, token, eager) {
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.PrivateService) ||
((requestingProviderType === ProviderAstType.PrivateService ||
requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.Builtin)) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (transformedProviderAst) {
return transformedProviderAst;
}
if (this._seenProviders.get(tokenReference(token)) != null) {
this.viewContext.errors.push(new ProviderError(`Cannot instantiate cyclic dependency! ${tokenName(token)}`, this._sourceSpan));
return null;
}
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps = undefined;
if (provider.useExisting != null) {
const existingDiDep = this._getDependency(resolvedProvider.providerType, { token: provider.useExisting }, eager);
if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token;
}
else {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
}
else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
}
else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
}
return _transformProvider(provider, {
useExisting: transformedUseExisting,
useValue: transformedUseValue,
deps: transformedDeps
});
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, { eager: eager, providers: transformedProviders });
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
_getLocalDependency(requestingProviderType, dep, eager = false) {
if (dep.isAttribute) {
const attrValue = this._attrs[dep.token.value];
return { isValue: true, value: attrValue == null ? null : attrValue };
}
if (dep.token != null) {
// access builtints
if ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.Component)) {
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.Renderer) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ElementRef) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ChangeDetectorRef) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.TemplateRef)) {
return dep;
}
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef)) {
this.transformedHasViewContainer = true;
}
}
// access the injector
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.Injector)) {
return dep;
}
// access providers
if (this._getOrCreateLocalProvider(requestingProviderType, dep.token, eager) != null) {
return dep;
}
}
return null;
}
_getDependency(requestingProviderType, dep, eager = false) {
let currElement = this;
let currEager = eager;
let result = null;
if (!dep.isSkipSelf) {
result = this._getLocalDependency(requestingProviderType, dep, eager);
}
if (dep.isSelf) {
if (!result && dep.isOptional) {
result = { isValue: true, value: null };
}
}
else {
// check parent elements
while (!result && currElement._parent) {
const prevElement = currElement;
currElement = currElement._parent;
if (prevElement._isViewRoot) {
currEager = false;
}
result = currElement._getLocalDependency(ProviderAstType.PublicService, dep, currEager);
}
// check @Host restriction
if (!result) {
if (!dep.isHost || this.viewContext.component.isHost ||
this.viewContext.component.type.reference === tokenReference(dep.token) ||
this.viewContext.viewProviders.get(tokenReference(dep.token)) != null) {
result = dep;
}
else {
result = dep.isOptional ? { isValue: true, value: null } : null;
}
}
}
if (!result) {
this.viewContext.errors.push(new ProviderError(`No provider for ${tokenName(dep.token)}`, this._sourceSpan));
}
return result;
}
}
class NgModuleProviderAnalyzer {
constructor(reflector, ngModule, extraProviders, sourceSpan) {
this.reflector = reflector;
this._transformedProviders = new Map();
this._seenProviders = new Map();
this._errors = [];
this._allProviders = new Map();
ngModule.transitiveModule.modules.forEach((ngModuleType) => {
const ngModuleProvider = { token: { identifier: ngModuleType }, useClass: ngModuleType };
_resolveProviders([ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors, this._allProviders, /* isModule */ true);
});
_resolveProviders(ngModule.transitiveModule.providers.map(entry => entry.provider).concat(extraProviders), ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders,
/* isModule */ false);
}
parse() {
Array.from(this._allProviders.values()).forEach((provider) => {
this._getOrCreateLocalProvider(provider.token, provider.eager);
});
if (this._errors.length > 0) {
const errorString = this._errors.join('\n');
throw new Error(`Provider parse errors:\n${errorString}`);
}
// Note: Maps keep their insertion order.
const lazyProviders = [];
const eagerProviders = [];
this._transformedProviders.forEach(provider => {
if (provider.eager) {
eagerProviders.push(provider);
}
else {
lazyProviders.push(provider);
}
});
return lazyProviders.concat(eagerProviders);
}
_getOrCreateLocalProvider(token, eager) {
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (transformedProviderAst) {
return transformedProviderAst;
}
if (this._seenProviders.get(tokenReference(token)) != null) {
this._errors.push(new ProviderError(`Cannot instantiate cyclic dependency! ${tokenName(token)}`, resolvedProvider.sourceSpan));
return null;
}
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps = undefined;
if (provider.useExisting != null) {
const existingDiDep = this._getDependency({ token: provider.useExisting }, eager, resolvedProvider.sourceSpan);
if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token;
}
else {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
}
else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
}
else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
}
return _transformProvider(provider, {
useExisting: transformedUseExisting,
useValue: transformedUseValue,
deps: transformedDeps
});
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, { eager: eager, providers: transformedProviders });
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
_getDependency(dep, eager = false, requestorSourceSpan) {
let foundLocal = false;
if (!dep.isSkipSelf && dep.token != null) {
// access the injector
if (tokenReference(dep.token) ===
this.reflector.resolveExternalReference(Identifiers.Injector) ||
tokenReference(dep.token) ===
this.reflector.resolveExternalReference(Identifiers.ComponentFactoryResolver)) {
foundLocal = true;
// access providers
}
else if (this._getOrCreateLocalProvider(dep.token, eager) != null) {
foundLocal = true;
}
}
return dep;
}
}
function _transformProvider(provider, { useExisting, useValue, deps }) {
return {
token: provider.token,
useClass: provider.useClass,
useExisting: useExisting,
useFactory: provider.useFactory,
useValue: useValue,
deps: deps,
multi: provider.multi
};
}
function _transformProviderAst(provider, { eager, providers }) {
return new ProviderAst(provider.token, provider.multiProvider, provider.eager || eager, providers, provider.providerType, provider.lifecycleHooks, provider.sourceSpan, provider.isModule);
}
function _resolveProvidersFromDirectives(directives, sourceSpan, targetErrors) {
const providersByToken = new Map();
directives.forEach((directive) => {
const dirProvider = { token: { identifier: directive.type }, useClass: directive.type };
_resolveProviders([dirProvider], directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
});
// Note: directives need to be able to overwrite providers of a component!
const directivesWithComponentFirst = directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent));
directivesWithComponentFirst.forEach((directive) => {
_resolveProviders(directive.providers, ProviderAstType.PublicService, false, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
_resolveProviders(directive.viewProviders, ProviderAstType.PrivateService, false, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
});
return providersByToken;
}
function _resolveProviders(providers, providerType, eager, sourceSpan, targetErrors, targetProvidersByToken, isModule) {
providers.forEach((provider) => {
let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token));
if (resolvedProvider != null && !!resolvedProvider.multiProvider !== !!provider.multi) {
targetErrors.push(new ProviderError(`Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`, sourceSpan));
}
if (!resolvedProvider) {
const lifecycleHooks = provider.token.identifier &&
provider.token.identifier.lifecycleHooks ?
provider.token.identifier.lifecycleHooks :
[];
const isUseValue = !(provider.useClass || provider.useExisting || provider.useFactory);
resolvedProvider = new ProviderAst(provider.token, !!provider.multi, eager || isUseValue, [provider], providerType, lifecycleHooks, sourceSpan, isModule);
targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider);
}
else {
if (!provider.multi) {
resolvedProvider.providers.length = 0;
}
resolvedProvider.providers.push(provider);
}
});
}
function _getViewQueries(component) {
// Note: queries start with id 1 so we can use the number in a Bloom filter!
let viewQueryId = 1;
const viewQueries = new Map();
if (component.viewQueries) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, { meta: query, queryId: viewQueryId++ }));
}
return viewQueries;
}
function _getContentQueries(contentQueryStartId, directives) {
let contentQueryId = contentQueryStartId;
const contentQueries = new Map();
directives.forEach((directive, directiveIndex) => {
if (directive.queries) {
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, { meta: query, queryId: contentQueryId++ }));
}
});
return contentQueries;
}
function _addQueryToTokenMap(map, query) {
query.meta.selectors.forEach((token) => {
let entry = map.get(tokenReference(token));
if (!entry) {
entry = [];
map.set(tokenReference(token), entry);
}
entry.push(query);
});
}
/**
* @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 StyleWithImports {
constructor(style, styleUrls) {
this.style = style;
this.styleUrls = styleUrls;
}
}
function isStyleUrlResolvable(url) {
if (url == null || url.length === 0 || url[0] == '/')
return false;
const schemeMatch = url.match(URL_WITH_SCHEMA_REGEXP);
return schemeMatch === null || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset';
}
/**
* Rewrites stylesheets by resolving and removing the @import urls that
* are either relative or don't have a `package:` scheme
*/
function extractStyleUrls(resolver, baseUrl, cssText) {
const foundUrls = [];
const modifiedCssText = cssText.replace(CSS_STRIPPABLE_COMMENT_REGEXP, '')
.replace(CSS_IMPORT_REGEXP, (...m) => {
const url = m[1] || m[2];
if (!isStyleUrlResolvable(url)) {
// Do not attempt to resolve non-package absolute URLs with URI
// scheme
return m[0];
}
foundUrls.push(resolver.resolve(baseUrl, url));
return '';
});
return new StyleWithImports(modifiedCssText, foundUrls);
}
const CSS_IMPORT_REGEXP = /@import\s+(?:url\()?\s*(?:(?:['"]([^'"]*))|([^;\)\s]*))[^;]*;?/g;
const CSS_STRIPPABLE_COMMENT_REGEXP = /\/\*(?!#\s*(?:sourceURL|sourceMappingURL)=)[\s\S]+?\*\//g;
const URL_WITH_SCHEMA_REGEXP = /^([^:/?#]+):/;
/**
* @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 PROPERTY_PARTS_SEPARATOR = '.';
const ATTRIBUTE_PREFIX = 'attr';
const CLASS_PREFIX = 'class';
const STYLE_PREFIX = 'style';
const ANIMATE_PROP_PREFIX = 'animate-';
/**
* Parses bindings in templates and in the directive host area.
*/
class BindingParser {
constructor(_exprParser, _interpolationConfig, _schemaRegistry, pipes, errors) {
this._exprParser = _exprParser;
this._interpolationConfig = _interpolationConfig;
this._schemaRegistry = _schemaRegistry;
this.errors = errors;
this.pipesByName = null;
this._usedPipes = new Map();
// When the `pipes` parameter is `null`, do not check for used pipes
// This is used in IVY when we might not know the available pipes at compile time
if (pipes) {
const pipesByName = new Map();
pipes.forEach(pipe => pipesByName.set(pipe.name, pipe));
this.pipesByName = pipesByName;
}
}
get interpolationConfig() { return this._interpolationConfig; }
getUsedPipes() { return Array.from(this._usedPipes.values()); }
createBoundHostProperties(dirMeta, sourceSpan) {
if (dirMeta.hostProperties) {
const boundProps = [];
Object.keys(dirMeta.hostProperties).forEach(propName => {
const expression = dirMeta.hostProperties[propName];
if (typeof expression === 'string') {
this.parsePropertyBinding(propName, expression, true, sourceSpan, sourceSpan.start.offset, undefined, [], boundProps);
}
else {
this._reportError(`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
});
return boundProps;
}
return null;
}
createDirectiveHostPropertyAsts(dirMeta, elementSelector, sourceSpan) {
const boundProps = this.createBoundHostProperties(dirMeta, sourceSpan);
return boundProps &&
boundProps.map((prop) => this.createBoundElementProperty(elementSelector, prop));
}
createDirectiveHostEventAsts(dirMeta, sourceSpan) {
if (dirMeta.hostListeners) {
const targetEvents = [];
Object.keys(dirMeta.hostListeners).forEach(propName => {
const expression = dirMeta.hostListeners[propName];
if (typeof expression === 'string') {
// TODO: pass a more accurate handlerSpan for this event.
this.parseEvent(propName, expression, sourceSpan, sourceSpan, [], targetEvents);
}
else {
this._reportError(`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
});
return targetEvents;
}
return null;
}
parseInterpolation(value, sourceSpan) {
const sourceInfo = sourceSpan.start.toString();
try {
const ast = this._exprParser.parseInterpolation(value, sourceInfo, sourceSpan.start.offset, this._interpolationConfig);
if (ast)
this._reportExpressionParserErrors(ast.errors, sourceSpan);
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, sourceSpan.start.offset);
}
}
// Parse an inline template binding. ie `">`
parseInlineTemplateBinding(tplKey, tplValue, sourceSpan, absoluteOffset, targetMatchableAttrs, targetProps, targetVars) {
const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan);
for (let i = 0; i < bindings.length; i++) {
const binding = bindings[i];
if (binding.keyIsVar) {
targetVars.push(new ParsedVariable(binding.key, binding.name, sourceSpan));
}
else if (binding.expression) {
this._parsePropertyAst(binding.key, binding.expression, sourceSpan, undefined, targetMatchableAttrs, targetProps);
}
else {
targetMatchableAttrs.push([binding.key, '']);
this.parseLiteralAttr(binding.key, null, sourceSpan, absoluteOffset, undefined, targetMatchableAttrs, targetProps);
}
}
}
_parseTemplateBindings(tplKey, tplValue, sourceSpan) {
const sourceInfo = sourceSpan.start.toString();
try {
const bindingsResult = this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceInfo, sourceSpan.start.offset);
this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
bindingsResult.templateBindings.forEach((binding) => {
if (binding.expression) {
this._checkPipes(binding.expression, sourceSpan);
}
});
bindingsResult.warnings.forEach((warning) => { this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING); });
return bindingsResult.templateBindings;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return [];
}
}
parseLiteralAttr(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
if (isAnimationLabel(name)) {
name = name.substring(1);
if (value) {
this._reportError(`Assigning animation triggers via @prop="exp" attributes with an expression is invalid.` +
` Use property bindings (e.g. [@prop]="exp") or use an attribute without a value (e.g. @prop) instead.`, sourceSpan, ParseErrorLevel.ERROR);
}
this._parseAnimation(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps);
}
else {
targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, valueSpan));
}
}
parsePropertyBinding(name, expression, isHost, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
let isAnimationProp = false;
if (name.startsWith(ANIMATE_PROP_PREFIX)) {
isAnimationProp = true;
name = name.substring(ANIMATE_PROP_PREFIX.length);
}
else if (isAnimationLabel(name)) {
isAnimationProp = true;
name = name.substring(1);
}
if (isAnimationProp) {
this._parseAnimation(name, expression, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps);
}
else {
this._parsePropertyAst(name, this._parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, valueSpan, targetMatchableAttrs, targetProps);
}
}
parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps) {
const expr = this.parseInterpolation(value, valueSpan || sourceSpan);
if (expr) {
this._parsePropertyAst(name, expr, sourceSpan, valueSpan, targetMatchableAttrs, targetProps);
return true;
}
return false;
}
_parsePropertyAst(name, ast, sourceSpan, valueSpan, targetMatchableAttrs, targetProps) {
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.DEFAULT, sourceSpan, valueSpan));
}
_parseAnimation(name, expression, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
// This will occur when a @trigger is not paired with an expression.
// For animations it is valid to not have an expression since */void
// states will be applied by angular when the element is attached/detached
const ast = this._parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset);
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, valueSpan));
}
_parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) {
const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown)').toString();
try {
const ast = isHostBinding ?
this._exprParser.parseSimpleBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig) :
this._exprParser.parseBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig);
if (ast)
this._reportExpressionParserErrors(ast.errors, sourceSpan);
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
}
createBoundElementProperty(elementSelector, boundProp, skipValidation = false, mapPropertyName = true) {
if (boundProp.isAnimation) {
return new BoundElementProperty(boundProp.name, 4 /* Animation */, SecurityContext.NONE, boundProp.expression, null, boundProp.sourceSpan, boundProp.valueSpan);
}
let unit = null;
let bindingType = undefined;
let boundPropertyName = null;
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
let securityContexts = undefined;
// Check for special cases (prefix style, attr, class)
if (parts.length > 1) {
if (parts[0] == ATTRIBUTE_PREFIX) {
boundPropertyName = parts[1];
if (!skipValidation) {
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
}
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, boundPropertyName, true);
const nsSeparatorIdx = boundPropertyName.indexOf(':');
if (nsSeparatorIdx > -1) {
const ns = boundPropertyName.substring(0, nsSeparatorIdx);
const name = boundPropertyName.substring(nsSeparatorIdx + 1);
boundPropertyName = mergeNsAndName(ns, name);
}
bindingType = 1 /* Attribute */;
}
else if (parts[0] == CLASS_PREFIX) {
boundPropertyName = parts[1];
bindingType = 2 /* Class */;
securityContexts = [SecurityContext.NONE];
}
else if (parts[0] == STYLE_PREFIX) {
unit = parts.length > 2 ? parts[2] : null;
boundPropertyName = parts[1];
bindingType = 3 /* Style */;
securityContexts = [SecurityContext.STYLE];
}
}
// If not a special case, use the full property name
if (boundPropertyName === null) {
const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name);
boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name;
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false);
bindingType = 0 /* Property */;
if (!skipValidation) {
this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false);
}
}
return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.valueSpan);
}
parseEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents) {
if (isAnimationLabel(name)) {
name = name.substr(1);
this._parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents);
}
else {
this._parseRegularEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents);
}
}
calcPossibleSecurityContexts(selector, propName, isAttribute) {
const prop = this._schemaRegistry.getMappedPropName(propName);
return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
}
_parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents) {
const matches = splitAtPeriod(name, [name, '']);
const eventName = matches[0];
const phase = matches[1].toLowerCase();
if (phase) {
switch (phase) {
case 'start':
case 'done':
const ast = this._parseAction(expression, handlerSpan);
targetEvents.push(new ParsedEvent(eventName, phase, 1 /* Animation */, ast, sourceSpan, handlerSpan));
break;
default:
this._reportError(`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, sourceSpan);
break;
}
}
else {
this._reportError(`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, sourceSpan);
}
}
_parseRegularEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents) {
// long format: 'target: eventName'
const [target, eventName] = splitAtColon(name, [null, name]);
const ast = this._parseAction(expression, handlerSpan);
targetMatchableAttrs.push([name, ast.source]);
targetEvents.push(new ParsedEvent(eventName, target, 0 /* Regular */, ast, sourceSpan, handlerSpan));
// Don't detect directives for event names for now,
// so don't add the event name to the matchableAttrs
}
_parseAction(value, sourceSpan) {
const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown').toString();
const absoluteOffset = (sourceSpan && sourceSpan.start) ? sourceSpan.start.offset : 0;
try {
const ast = this._exprParser.parseAction(value, sourceInfo, absoluteOffset, this._interpolationConfig);
if (ast) {
this._reportExpressionParserErrors(ast.errors, sourceSpan);
}
if (!ast || ast.ast instanceof EmptyExpr) {
this._reportError(`Empty expressions are not allowed`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
}
_reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
this.errors.push(new ParseError(sourceSpan, message, level));
}
_reportExpressionParserErrors(errors, sourceSpan) {
for (const error of errors) {
this._reportError(error.message, sourceSpan);
}
}
// Make sure all the used pipes are known in `this.pipesByName`
_checkPipes(ast, sourceSpan) {
if (ast && this.pipesByName) {
const collector = new PipeCollector();
ast.visit(collector);
collector.pipes.forEach((ast, pipeName) => {
const pipeMeta = this.pipesByName.get(pipeName);
if (!pipeMeta) {
this._reportError(`The pipe '${pipeName}' could not be found`, new ParseSourceSpan(sourceSpan.start.moveBy(ast.span.start), sourceSpan.start.moveBy(ast.span.end)));
}
else {
this._usedPipes.set(pipeName, pipeMeta);
}
});
}
}
/**
* @param propName the name of the property / attribute
* @param sourceSpan
* @param isAttr true when binding to an attribute
*/
_validatePropertyOrAttributeName(propName, sourceSpan, isAttr) {
const report = isAttr ? this._schemaRegistry.validateAttribute(propName) :
this._schemaRegistry.validateProperty(propName);
if (report.error) {
this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR);
}
}
}
class PipeCollector extends RecursiveAstVisitor$1 {
constructor() {
super(...arguments);
this.pipes = new Map();
}
visitPipe(ast, context) {
this.pipes.set(ast.name, ast);
ast.exp.visit(this);
this.visitAll(ast.args, context);
return null;
}
}
function isAnimationLabel(name) {
return name[0] == '@';
}
function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
const ctxs = [];
CssSelector.parse(selector).forEach((selector) => {
const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
const notElementNames = new Set(selector.notSelectors.filter(selector => selector.isElementSelector())
.map((selector) => selector.element));
const possibleElementNames = elementNames.filter(elementName => !notElementNames.has(elementName));
ctxs.push(...possibleElementNames.map(elementName => registry.securityContext(elementName, propName, isAttribute)));
});
return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
}
/**
* @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 NG_CONTENT_SELECT_ATTR = 'select';
const LINK_ELEMENT = 'link';
const LINK_STYLE_REL_ATTR = 'rel';
const LINK_STYLE_HREF_ATTR = 'href';
const LINK_STYLE_REL_VALUE = 'stylesheet';
const STYLE_ELEMENT = 'style';
const SCRIPT_ELEMENT = 'script';
const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
const NG_PROJECT_AS = 'ngProjectAs';
function preparseElement(ast) {
let selectAttr = null;
let hrefAttr = null;
let relAttr = null;
let nonBindable = false;
let projectAs = '';
ast.attrs.forEach(attr => {
const lcAttrName = attr.name.toLowerCase();
if (lcAttrName == NG_CONTENT_SELECT_ATTR) {
selectAttr = attr.value;
}
else if (lcAttrName == LINK_STYLE_HREF_ATTR) {
hrefAttr = attr.value;
}
else if (lcAttrName == LINK_STYLE_REL_ATTR) {
relAttr = attr.value;
}
else if (attr.name == NG_NON_BINDABLE_ATTR) {
nonBindable = true;
}
else if (attr.name == NG_PROJECT_AS) {
if (attr.value.length > 0) {
projectAs = attr.value;
}
}
});
selectAttr = normalizeNgContentSelect(selectAttr);
const nodeName = ast.name.toLowerCase();
let type = PreparsedElementType.OTHER;
if (isNgContent(nodeName)) {
type = PreparsedElementType.NG_CONTENT;
}
else if (nodeName == STYLE_ELEMENT) {
type = PreparsedElementType.STYLE;
}
else if (nodeName == SCRIPT_ELEMENT) {
type = PreparsedElementType.SCRIPT;
}
else if (nodeName == LINK_ELEMENT && relAttr == LINK_STYLE_REL_VALUE) {
type = PreparsedElementType.STYLESHEET;
}
return new PreparsedElement(type, selectAttr, hrefAttr, nonBindable, projectAs);
}
var PreparsedElementType;
(function (PreparsedElementType) {
PreparsedElementType[PreparsedElementType["NG_CONTENT"] = 0] = "NG_CONTENT";
PreparsedElementType[PreparsedElementType["STYLE"] = 1] = "STYLE";
PreparsedElementType[PreparsedElementType["STYLESHEET"] = 2] = "STYLESHEET";
PreparsedElementType[PreparsedElementType["SCRIPT"] = 3] = "SCRIPT";
PreparsedElementType[PreparsedElementType["OTHER"] = 4] = "OTHER";
})(PreparsedElementType || (PreparsedElementType = {}));
class PreparsedElement {
constructor(type, selectAttr, hrefAttr, nonBindable, projectAs) {
this.type = type;
this.selectAttr = selectAttr;
this.hrefAttr = hrefAttr;
this.nonBindable = nonBindable;
this.projectAs = projectAs;
}
}
function normalizeNgContentSelect(selectAttr) {
if (selectAttr === null || selectAttr.length === 0) {
return '*';
}
return selectAttr;
}
/**
* @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 BIND_NAME_REGEXP = /^(?:(?:(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/;
// Group 1 = "bind-"
const KW_BIND_IDX = 1;
// Group 2 = "let-"
const KW_LET_IDX = 2;
// Group 3 = "ref-/#"
const KW_REF_IDX = 3;
// Group 4 = "on-"
const KW_ON_IDX = 4;
// Group 5 = "bindon-"
const KW_BINDON_IDX = 5;
// Group 6 = "@"
const KW_AT_IDX = 6;
// Group 7 = the identifier after "bind-", "let-", "ref-/#", "on-", "bindon-" or "@"
const IDENT_KW_IDX = 7;
// Group 8 = identifier inside [()]
const IDENT_BANANA_BOX_IDX = 8;
// Group 9 = identifier inside []
const IDENT_PROPERTY_IDX = 9;
// Group 10 = identifier inside ()
const IDENT_EVENT_IDX = 10;
const TEMPLATE_ATTR_PREFIX = '*';
const CLASS_ATTR = 'class';
let _TEXT_CSS_SELECTOR;
function TEXT_CSS_SELECTOR() {
if (!_TEXT_CSS_SELECTOR) {
_TEXT_CSS_SELECTOR = CssSelector.parse('*')[0];
}
return _TEXT_CSS_SELECTOR;
}
class TemplateParseError extends ParseError {
constructor(message, span, level) {
super(span, message, level);
}
}
class TemplateParseResult {
constructor(templateAst, usedPipes, errors) {
this.templateAst = templateAst;
this.usedPipes = usedPipes;
this.errors = errors;
}
}
class TemplateParser {
constructor(_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;
}
get expressionParser() { return this._exprParser; }
parse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) {
const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces);
const warnings = result.errors.filter(error => error.level === ParseErrorLevel.WARNING);
const errors = result.errors.filter(error => error.level === ParseErrorLevel.ERROR);
if (warnings.length > 0) {
this._console.warn(`Template parse warnings:\n${warnings.join('\n')}`);
}
if (errors.length > 0) {
const errorString = errors.join('\n');
throw syntaxError(`Template parse errors:\n${errorString}`, errors);
}
return { template: result.templateAst, pipes: result.usedPipes };
}
tryParse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) {
let htmlParseResult = typeof template === 'string' ?
this._htmlParser.parse(template, templateUrl, {
tokenizeExpansionForms: true,
interpolationConfig: this.getInterpolationConfig(component)
}) :
template;
if (!preserveWhitespaces) {
htmlParseResult = removeWhitespaces(htmlParseResult);
}
return this.tryParseHtml(this.expandHtml(htmlParseResult), component, directives, pipes, schemas);
}
tryParseHtml(htmlAstWithErrors, component, directives, pipes, schemas) {
let result;
const errors = htmlAstWithErrors.errors;
const usedPipes = [];
if (htmlAstWithErrors.rootNodes.length > 0) {
const uniqDirectives = removeSummaryDuplicates(directives);
const uniqPipes = removeSummaryDuplicates(pipes);
const providerViewContext = new ProviderViewContext(this._reflector, component);
let interpolationConfig = undefined;
if (component.template && component.template.interpolation) {
interpolationConfig = {
start: component.template.interpolation[0],
end: component.template.interpolation[1]
};
}
const bindingParser = new BindingParser(this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors);
const parseVisitor = new TemplateParseVisitor(this._reflector, this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry, schemas, errors);
result = visitAll$1(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_ELEMENT_CONTEXT);
errors.push(...providerViewContext.errors);
usedPipes.push(...bindingParser.getUsedPipes());
}
else {
result = [];
}
this._assertNoReferenceDuplicationOnTemplate(result, errors);
if (errors.length > 0) {
return new TemplateParseResult(result, usedPipes, errors);
}
if (this.transforms) {
this.transforms.forEach((transform) => { result = templateVisitAll(transform, result); });
}
return new TemplateParseResult(result, usedPipes, errors);
}
expandHtml(htmlAstWithErrors, forced = false) {
const errors = htmlAstWithErrors.errors;
if (errors.length == 0 || forced) {
// Transform ICU messages to angular directives
const expandedHtmlAst = expandNodes(htmlAstWithErrors.rootNodes);
errors.push(...expandedHtmlAst.errors);
htmlAstWithErrors = new ParseTreeResult(expandedHtmlAst.nodes, errors);
}
return htmlAstWithErrors;
}
getInterpolationConfig(component) {
if (component.template) {
return InterpolationConfig.fromArray(component.template.interpolation);
}
return undefined;
}
/** @internal */
_assertNoReferenceDuplicationOnTemplate(result, errors) {
const existingReferences = [];
result.filter(element => !!element.references)
.forEach(element => element.references.forEach((reference) => {
const name = reference.name;
if (existingReferences.indexOf(name) < 0) {
existingReferences.push(name);
}
else {
const error = new TemplateParseError(`Reference "#${name}" is defined several times`, reference.sourceSpan, ParseErrorLevel.ERROR);
errors.push(error);
}
}));
}
}
class TemplateParseVisitor {
constructor(reflector, config, providerViewContext, directives, _bindingParser, _schemaRegistry, _schemas, _targetErrors) {
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((directive, index) => {
const selector = CssSelector.parse(directive.selector);
this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index);
});
}
visitExpansion(expansion, context) { return null; }
visitExpansionCase(expansionCase, context) { return null; }
visitText(text, parent) {
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR());
const valueNoNgsp = replaceNgsp(text.value);
const expr = this._bindingParser.parseInterpolation(valueNoNgsp, text.sourceSpan);
return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan) :
new TextAst(valueNoNgsp, ngContentIndex, text.sourceSpan);
}
visitAttribute(attribute, context) {
return new AttrAst(attribute.name, attribute.value, attribute.sourceSpan);
}
visitComment(comment, context) { return null; }
visitElement(element, parent) {
const queryStartIndex = this.contentQueryStartId;
const elName = element.name;
const preparsedElement = preparseElement(element);
if (preparsedElement.type === PreparsedElementType.SCRIPT ||
preparsedElement.type === PreparsedElementType.STYLE) {
// Skipping