UNPKG

@angular/common

Version:

Angular - commonly needed directives and services

201 lines 26.5 kB
import * as tslib_1 from "tslib"; /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { ElementRef, Injectable, IterableDiffers, KeyValueDiffers, Renderer2, ɵisListLikeIterable as isListLikeIterable, ɵstringify as stringify } from '@angular/core'; import { StylingDiffer } from './styling_differ'; /** * 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. */ var NgClassImpl = /** @class */ (function () { function NgClassImpl() { } return NgClassImpl; }()); export { NgClassImpl }; var NgClassR2Impl = /** @class */ (function () { function NgClassR2Impl(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) { this._iterableDiffers = _iterableDiffers; this._keyValueDiffers = _keyValueDiffers; this._ngEl = _ngEl; this._renderer = _renderer; this._initialClasses = []; } NgClassR2Impl.prototype.getValue = function () { return null; }; NgClassR2Impl.prototype.setClass = function (value) { this._removeClasses(this._initialClasses); this._initialClasses = typeof value === 'string' ? value.split(/\s+/) : []; this._applyClasses(this._initialClasses); this._applyClasses(this._rawClass); }; NgClassR2Impl.prototype.setNgClass = function (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 (isListLikeIterable(this._rawClass)) { this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create(); } else { this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create(); } } }; NgClassR2Impl.prototype.applyChanges = function () { if (this._iterableDiffer) { var iterableChanges = this._iterableDiffer.diff(this._rawClass); if (iterableChanges) { this._applyIterableChanges(iterableChanges); } } else if (this._keyValueDiffer) { var keyValueChanges = this._keyValueDiffer.diff(this._rawClass); if (keyValueChanges) { this._applyKeyValueChanges(keyValueChanges); } } }; NgClassR2Impl.prototype._applyKeyValueChanges = function (changes) { var _this = this; changes.forEachAddedItem(function (record) { return _this._toggleClass(record.key, record.currentValue); }); changes.forEachChangedItem(function (record) { return _this._toggleClass(record.key, record.currentValue); }); changes.forEachRemovedItem(function (record) { if (record.previousValue) { _this._toggleClass(record.key, false); } }); }; NgClassR2Impl.prototype._applyIterableChanges = function (changes) { var _this = this; changes.forEachAddedItem(function (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 " + stringify(record.item)); } }); changes.forEachRemovedItem(function (record) { return _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). */ NgClassR2Impl.prototype._applyClasses = function (rawClassVal) { var _this = this; if (rawClassVal) { if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { rawClassVal.forEach(function (klass) { return _this._toggleClass(klass, true); }); } else { Object.keys(rawClassVal).forEach(function (klass) { return _this._toggleClass(klass, !!rawClassVal[klass]); }); } } }; /** * Removes a collection of CSS classes from the DOM element. This is mostly useful for cleanup * purposes. */ NgClassR2Impl.prototype._removeClasses = function (rawClassVal) { var _this = this; if (rawClassVal) { if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { rawClassVal.forEach(function (klass) { return _this._toggleClass(klass, false); }); } else { Object.keys(rawClassVal).forEach(function (klass) { return _this._toggleClass(klass, false); }); } } }; NgClassR2Impl.prototype._toggleClass = function (klass, enabled) { var _this = this; klass = klass.trim(); if (klass) { klass.split(/\s+/g).forEach(function (klass) { if (enabled) { _this._renderer.addClass(_this._ngEl.nativeElement, klass); } else { _this._renderer.removeClass(_this._ngEl.nativeElement, klass); } }); } }; NgClassR2Impl = tslib_1.__decorate([ Injectable(), tslib_1.__metadata("design:paramtypes", [IterableDiffers, KeyValueDiffers, ElementRef, Renderer2]) ], NgClassR2Impl); return NgClassR2Impl; }()); export { NgClassR2Impl }; var NgClassR3Impl = /** @class */ (function () { function NgClassR3Impl() { this._value = null; this._ngClassDiffer = new StylingDiffer('NgClass', 1 /* TrimProperties */ | 2 /* AllowSubKeys */ | 4 /* AllowStringValue */ | 16 /* ForceAsMap */); this._classStringDiffer = null; } NgClassR3Impl.prototype.getValue = function () { return this._value; }; NgClassR3Impl.prototype.setClass = function (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); }; NgClassR3Impl.prototype.setNgClass = function (value) { this._ngClassDiffer.setValue(value); }; NgClassR3Impl.prototype.applyChanges = function () { var classChanged = this._classStringDiffer ? this._classStringDiffer.hasValueChanged() : false; var ngClassChanged = this._ngClassDiffer.hasValueChanged(); if (classChanged || ngClassChanged) { var value = this._ngClassDiffer.value; if (this._classStringDiffer) { var classValue = this._classStringDiffer.value; if (classValue) { value = value ? tslib_1.__assign({}, classValue, value) : classValue; } } this._value = value; } }; NgClassR3Impl = tslib_1.__decorate([ Injectable() ], NgClassR3Impl); return NgClassR3Impl; }()); export { NgClassR3Impl }; // 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. export var NgClassImplProvider__PRE_R3__ = { provide: NgClassImpl, useClass: NgClassR2Impl }; export var NgClassImplProvider__POST_R3__ = { provide: NgClassImpl, useClass: NgClassR3Impl }; export var NgClassImplProvider = NgClassImplProvider__PRE_R3__; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdfY2xhc3NfaW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbW1vbi9zcmMvZGlyZWN0aXZlcy9uZ19jbGFzc19pbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7QUFDSCxPQUFPLEVBQUMsVUFBVSxFQUFFLFVBQVUsRUFBbUMsZUFBZSxFQUFtQyxlQUFlLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixJQUFJLGtCQUFrQixFQUFFLFVBQVUsSUFBSSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFeE8sT0FBTyxFQUFDLGFBQWEsRUFBdUIsTUFBTSxrQkFBa0IsQ0FBQztBQUVyRTs7Ozs7Ozs7R0FRRztBQUNIO0lBQUE7SUFLQSxDQUFDO0lBQUQsa0JBQUM7QUFBRCxDQUFDLEFBTEQsSUFLQzs7QUFHRDtJQVNFLHVCQUNZLGdCQUFpQyxFQUFVLGdCQUFpQyxFQUM1RSxLQUFpQixFQUFVLFNBQW9CO1FBRC9DLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBaUI7UUFBVSxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWlCO1FBQzVFLFVBQUssR0FBTCxLQUFLLENBQVk7UUFBVSxjQUFTLEdBQVQsU0FBUyxDQUFXO1FBTm5ELG9CQUFlLEdBQWEsRUFBRSxDQUFDO0lBTXVCLENBQUM7SUFFL0QsZ0NBQVEsR0FBUixjQUFhLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQztJQUUzQixnQ0FBUSxHQUFSLFVBQVMsS0FBYTtRQUNwQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsZUFBZSxHQUFHLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNFLElBQUksQ0FBQyxhQUFhLENB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QUU7T0FDQSxhQUFhLENBd0N6QjtJQUFELG9CQUFDO0NBQUEsQUF4Q0QsSUF3Q0M7U0F4Q1ksYUFBYTtBQTBDMUIsa0VBQWtFO0FBQ2xFLGtFQUFrRTtBQUNsRSxrREFBa0Q7QUFDbEQsTUFBTSxDQUFDLElBQU0sNkJBQTZCLEdBQUc7SUFDM0MsT0FBTyxFQUFFLFdBQVc7SUFDcEIsUUFBUSxFQUFFLGFBQWE7Q0FDeEIsQ0FBQztBQUVGLE1BQU0sQ0FBQyxJQUFNLDhCQUE4QixHQUFHO0lBQzVDLE9BQU8sRUFBRSxXQUFXO0lBQ3BCLFFBQVEsRUFBRSxhQUFhO0NBQ3hCLENBQUM7QUFFRixNQUFNLENBQUMsSUFBTSxtQkFBbUIsR0FBRyw2QkFBNkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7RWxlbWVudFJlZiwgSW5qZWN0YWJsZSwgSXRlcmFibGVDaGFuZ2VzLCBJdGVyYWJsZURpZmZlciwgSXRlcmFibGVEaWZmZXJzLCBLZXlWYWx1ZUNoYW5nZXMsIEtleVZhbHVlRGlmZmVyLCBLZXlWYWx1ZURpZmZlcnMsIFJlbmRlcmVyMiwgybVpc0xpc3RMaWtlSXRlcmFibGUgYXMgaXNMaXN0TGlrZUl0ZXJhYmxlLCDJtXN0cmluZ2lmeSBhcyBzdHJpbmdpZnl9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1N0eWxpbmdEaWZmZXIsIFN0eWxpbmdEaWZmZXJPcHRpb25zfSBmcm9tICcuL3N0eWxpbmdfZGlmZmVyJztcblxuLyoqXG4gKiBVc2VkIGFzIGEgdG9rZW4gZm9yIGFuIGluamVjdGVkIHNlcnZpY2Ugd2l0aGluIHRoZSBOZ0NsYXNzIGRpcmVjdGl2ZS5cbiAqXG4gKiBOZ0NsYXNzIGJlaGF2ZXMgZGlmZmVyZW5seSB3aGV0aGVyIG9yIG5vdCBWRSBpcyBiZWluZyB1c2VkIG9yIG5vdC4gSWZcbiAqIHByZXNlbnQgdGhlbiB0aGUgbGVnYWN5IG5nQ2xhc3MgZGlmZmluZyBhbGdvcml0aG0gd2lsbCBiZSB1c2VkIGFzIGFuXG4gKiBpbmplY3RlZCBzZXJ2aWNlLiBPdGhlcndpc2UgdGhlIG5ldyBkaWZmaW5nIGFsZ29yaXRobSAod2hpY2ggZGVsZWdhdGVzXG4gKiB0byB0aGUgYFtjbGFzc11gIGJpbmRpbmcpIHdpbGwgYmUgdXNlZC4gVGhpcyB0b2dnbGUgYmVoYXZpb3IgaXMgZG9uZSBzb1xuICogdmlhIHRoZSBpdnlfc3dpdGNoIG1lY2hhbmlzbS5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE5nQ2xhc3NJbXBsIHtcbiAgYWJzdHJhY3Qgc2V0Q2xhc3ModmFsdWU6IHN0cmluZyk6IHZvaWQ7XG4gIGFic3RyYWN0IHNldE5nQ2xhc3ModmFsdWU6IHN0cmluZ3xzdHJpbmdbXXxTZXQ8c3RyaW5nPnx7W2tsYXNzOiBzdHJpbmddOiBhbnl9KTogdm9pZDtcbiAgYWJzdHJhY3QgYXBwbHlDaGFuZ2VzKCk6IHZvaWQ7XG4gIGFic3RyYWN0IGdldFZhbHVlKCk6IHtba2V5OiBzdHJpbmddOiBhbnl9fG51bGw7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBOZ0NsYXNzUjJJbXBsIGltcGxlbWVudHMgTmdDbGFzc0ltcGwge1xuICAvLyBUT0RPKGlzc3VlLzI0NTcxKTogcmVtb3ZlICchJy5cbiAgcHJpdmF0ZSBfaXRlcmFibGVEaWZmZXIgITogSXRlcmFibGVEaWZmZXI8c3RyaW5nPnwgbnVsbDtcbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIHByaXZhdGUgX2tleVZhbHVlRGlmZmVyICE6IEtleVZhbHVlRGlmZmVyPHN0cmluZywgYW55PnwgbnVsbDtcbiAgcHJpdmF0ZSBfaW5pdGlhbENsYXNzZXM6IHN0cmluZ1tdID0gW107XG4gIC8vIFRPRE8oaXNzdWUvMjQ1NzEpOiByZW1vdmUgJyEnLlxuICBwcml2YXRlIF9yYXdDbGFzcyAhOiBzdHJpbmdbXSB8IFNldDxzdHJpbmc+fCB7W2tsYXNzOiBzdHJpbmddOiBhbnl9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBfaXRlcmFibGVEaWZmZXJzOiBJdGVyYWJsZURpZmZlcnMsIHByaXZhdGUgX2tleVZhbHVlRGlmZmVyczogS2V5VmFsdWVEaWZmZXJzLFxuICAgICAgcHJpdmF0ZSBfbmdFbDogRWxlbWVudFJlZiwgcHJpdmF0ZSBfcmVuZGVyZXI6IFJlbmRlcmVyMikge31cblxuICBnZXRWYWx1ZSgpIHsgcmV0dXJuIG51bGw7IH1cblxuICBzZXRDbGFzcyh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fcmVtb3ZlQ2xhc3Nlcyh0aGlzLl9pbml0aWFsQ2xhc3Nlcyk7XG4gICAgdGhpcy5faW5pdGlhbENsYXNzZXMgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUuc3BsaXQoL1xccysvKSA6IFtdO1xuICAgIHRoaXMuX2FwcGx5Q2xhc3Nlcyh0aGlzLl9pbml0aWFsQ2xhc3Nlcyk7XG4gICAgdGhpcy5fYXBwbHlDbGFzc2VzKHRoaXMuX3Jhd0NsYXNzKTtcbiAgfVxuXG4gIHNldE5nQ2xhc3ModmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuX3JlbW92ZUNsYXNzZXModGhpcy5fcmF3Q2xhc3MpO1xuICAgIHRoaXMuX2FwcGx5Q2xhc3Nlcyh0aGlzLl9pbml0aWFsQ2xhc3Nlcyk7XG5cbiAgICB0aGlzLl9pdGVyYWJsZURpZmZlciA9IG51bGw7XG4gICAgdGhpcy5fa2V5VmFsdWVEaWZmZXIgPSBudWxsO1xuXG4gICAgdGhpcy5fcmF3Q2xhc3MgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUuc3BsaXQoL1xccysvKSA6IHZhbHVlO1xuXG4gICAgaWYgKHRoaXMuX3Jhd0NsYXNzKSB7XG4gICAgICBpZiAoaXNMaXN0TGlrZUl0ZXJhYmxlKHRoaXMuX3Jhd0NsYXNzKSkge1xuICAgICAgICB0aGlzLl9pdGVyYWJsZURpZmZlciA9IHRoaXMuX2l0ZXJhYmxlRGlmZmVycy5maW5kKHRoaXMuX3Jhd0NsYXNzKS5jcmVhdGUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2tleVZhbHVlRGlmZmVyID0gdGhpcy5fa2V5VmFsdWVEaWZmZXJzLmZpbmQodGhpcy5fcmF3Q2xhc3MpLmNyZWF0ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFwcGx5Q2hhbmdlcygpIHtcbiAgICBpZiAodGhpcy5faXRlcmFibGVEaWZmZXIpIHtcbiAgICAgIGNvbnN0IGl0ZXJhYmxlQ2hhbmdlcyA9IHRoaXMuX2l0ZXJhYmxlRGlmZmVyLmRpZmYodGhpcy5fcmF3Q2xhc3MgYXMgc3RyaW5nW10pO1xuICAgICAgaWYgKGl0ZXJhYmxlQ2hhbmdlcykge1xuICAgICAgICB0aGlzLl9hcHBseUl0ZXJhYmxlQ2hhbmdlcyhpdGVyYWJsZUNoYW5nZXMpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy5fa2V5VmFsdWVEaWZmZXIpIHtcbiAgICAgIGNvbnN0IGtleVZhbHVlQ2hhbmdlcyA9IHRoaXMuX2tleVZhbHVlRGlmZmVyLmRpZmYodGhpcy5fcmF3Q2xhc3MgYXN7W2s6IHN0cmluZ106IGFueX0pO1xuICAgICAgaWYgKGtleVZhbHVlQ2hhbmdlcykge1xuICAgICAgICB0aGlzLl9hcHBseUtleVZhbHVlQ2hhbmdlcyhrZXlWYWx1ZUNoYW5nZXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2FwcGx5S2V5VmFsdWVDaGFuZ2VzKGNoYW5nZXM6IEtleVZhbHVlQ2hhbmdlczxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICBjaGFuZ2VzLmZvckVhY2hBZGRlZEl0ZW0oKHJlY29yZCkgPT4gdGhpcy5fdG9nZ2xlQ2xhc3MocmVjb3JkLmtleSwgcmVjb3JkLmN1cnJlbnRWYWx1ZSkpO1xuICAgIGNoYW5nZXMuZm9yRWFjaENoYW5nZWRJdGVtKChyZWNvcmQpID0+IHRoaXMuX3RvZ2dsZUNsYXNzKHJlY29yZC5rZXksIHJlY29yZC5jdXJyZW50VmFsdWUpKTtcbiAgICBjaGFuZ2VzLmZvckVhY2hSZW1vdmVkSXRlbSgocmVjb3JkKSA9PiB7XG4gICAgICBpZiAocmVjb3JkLnByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlQ2xhc3MocmVjb3JkLmtleSwgZmFsc2UpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfYXBwbHlJdGVyYWJsZUNoYW5nZXMoY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPHN0cmluZz4pOiB2b2lkIHtcbiAgICBjaGFuZ2VzLmZvckVhY2hBZGRlZEl0ZW0oKHJlY29yZCkgPT4ge1xuICAgICAgaWYgKHR5cGVvZiByZWNvcmQuaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5fdG9nZ2xlQ2xhc3MocmVjb3JkLml0ZW0sIHRydWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYE5nQ2xhc3MgY2FuIG9ubHkgdG9nZ2xlIENTUyBjbGFzc2VzIGV4cHJlc3NlZCBhcyBzdHJpbmdzLCBnb3QgJHtzdHJpbmdpZnkocmVjb3JkLml0ZW0pfWApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY2hhbmdlcy5mb3JFYWNoUmVtb3ZlZEl0ZW0oKHJlY29yZCkgPT4gdGhpcy5fdG9nZ2xlQ2xhc3MocmVjb3JkLml0ZW0sIGZhbHNlKSk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhIGNvbGxlY3Rpb24gb2YgQ1NTIGNsYXNzZXMgdG8gdGhlIERPTSBlbGVtZW50LlxuICAgKlxuICAgKiBGb3IgYXJndW1lbnQgb2YgdHlwZSBTZXQgYW5kIEFycmF5IENTUyBjbGFzcyBuYW1lcyBjb250YWluZWQgaW4gdGhvc2UgY29sbGVjdGlvbnMgYXJlIGFsd2F5c1xuICAgKiBhZGRlZC5cbiAgICogRm9yIGFyZ3VtZW50IG9mIHR5cGUgTWFwIENTUyBjbGFzcyBuYW1lIGluIHRoZSBtYXAncyBrZXkgaXMgdG9nZ2xlZCBiYXNlZCBvbiB0aGUgdmFsdWUgKGFkZGVkXG4gICAqIGZvciB0cnV0aHkgYW5kIHJlbW92ZWQgZm9yIGZhbHN5KS5cbiAgICovXG4gIHByaXZhdGUgX2FwcGx5Q2xhc3NlcyhyYXdDbGFzc1ZhbDogc3RyaW5nW118U2V0PHN0cmluZz58e1trbGFzczogc3RyaW5nXTogYW55fSkge1xuICAgIGlmIChyYXdDbGFzc1ZhbCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmF3Q2xhc3NWYWwpIHx8IHJhd0NsYXNzVmFsIGluc3RhbmNlb2YgU2V0KSB7XG4gICAgICAgICg8YW55PnJhd0NsYXNzVmFsKS5mb3JFYWNoKChrbGFzczogc3RyaW5nKSA9PiB0aGlzLl90b2dnbGVDbGFzcyhrbGFzcywgdHJ1ZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgT2JqZWN0LmtleXMocmF3Q2xhc3NWYWwpLmZvckVhY2goa2xhc3MgPT4gdGhpcy5fdG9nZ2xlQ2xhc3Moa2xhc3MsICEhcmF3Q2xhc3NWYWxba2xhc3NdKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSBjb2xsZWN0aW9uIG9mIENTUyBjbGFzc2VzIGZyb20gdGhlIERPTSBlbGVtZW50LiBUaGlzIGlzIG1vc3RseSB1c2VmdWwgZm9yIGNsZWFudXBcbiAgICogcHVycG9zZXMuXG4gICAqL1xuICBwcml2YXRlIF9yZW1vdmVDbGFzc2VzKHJhd0NsYXNzVmFsOiBzdHJpbmdbXXxTZXQ8c3RyaW5nPnx7W2tsYXNzOiBzdHJpbmddOiBhbnl9KSB7XG4gICAgaWYgKHJhd0NsYXNzVmFsKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShyYXdDbGFzc1ZhbCkgfHwgcmF3Q2xhc3NWYWwgaW5zdGFuY2VvZiBTZXQpIHtcbiAgICAgICAgKDxhbnk+cmF3Q2xhc3NWYWwpLmZvckVhY2goKGtsYXNzOiBzdHJpbmcpID0+IHRoaXMuX3RvZ2dsZUNsYXNzKGtsYXNzLCBmYWxzZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgT2JqZWN0LmtleXMocmF3Q2xhc3NWYWwpLmZvckVhY2goa2xhc3MgPT4gdGhpcy5fdG9nZ2xlQ2xhc3Moa2xhc3MsIGZhbHNlKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdG9nZ2xlQ2xhc3Moa2xhc3M6IHN0cmluZywgZW5hYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGtsYXNzID0ga2xhc3MudHJpbSgpO1xuICAgIGlmIChrbGFzcykge1xuICAgICAga2xhc3Muc3BsaXQoL1xccysvZykuZm9yRWFjaChrbGFzcyA9PiB7XG4gICAgICAgIGlmIChlbmFibGVkKSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5fbmdFbC5uYXRpdmVFbGVtZW50LCBrbGFzcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5fbmdFbC5uYXRpdmVFbGVtZW50LCBrbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmdDbGFzc1IzSW1wbCBpbXBsZW1lbnRzIE5nQ2xhc3NJbXBsIHtcbiAgcHJpdmF0ZSBfdmFsdWU6IHtba2V5OiBzdHJpbmddOiBib29sZWFufXxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfbmdDbGFzc0RpZmZlciA9IG5ldyBTdHlsaW5nRGlmZmVyPHtba2V5OiBzdHJpbmddOiBib29sZWFufXxudWxsPihcbiAgICAgICdOZ0NsYXNzJywgU3R5bGluZ0RpZmZlck9wdGlvbnMuVHJpbVByb3BlcnRpZXN8XG4gICAgICAgICAgICAgICAgIFN0eWxpbmdEaWZmZXJPcHRpb25zLkFsbG93U3ViS2V5c3xcbiAgICAgICAgICAgICAgICAgU3R5bGluZ0RpZmZlck9wdGlvbnMuQWxsb3dTdHJpbmdWYWx1ZXxTdHlsaW5nRGlmZmVyT3B0aW9ucy5Gb3JjZUFzTWFwKTtcbiAgcHJpdmF0ZSBfY2xhc3NTdHJpbmdEaWZmZXI6IFN0eWxpbmdEaWZmZXI8e1trZXk6IHN0cmluZ106IGJvb2xlYW59PnxudWxsID0gbnVsbDtcblxuICBnZXRWYWx1ZSgpIHsgcmV0dXJuIHRoaXMuX3ZhbHVlOyB9XG5cbiAgc2V0Q2xhc3ModmFsdWU6IHN0cmluZykge1xuICAgIC8vIGVhcmx5IGV4aXQgaW5jYXNlIHRoZSBiaW5kaW5nIGdldHMgZW1pdHRlZCBhcyBhbiBlbXB0eSB2YWx1ZSB3aGljaFxuICAgIC8vIG1lYW5zIHRoZXJlIGlzIG5vIHJlYXNvbiB0byBpbnN0YW50aWF0ZSBhbmQgZGlmZiB0aGUgdmFsdWVzLi4uXG4gICAgaWYgKCF2YWx1ZSAmJiAhdGhpcy5fY2xhc3NTdHJpbmdEaWZmZXIpIHJldHVybjtcblxuICAgIHRoaXMuX2NsYXNzU3RyaW5nRGlmZmVyID0gdGhpcy5fY2xhc3NTdHJpbmdEaWZmZXIgfHxcbiAgICAgICAgbmV3IFN0eWxpbmdEaWZmZXIoJ2NsYXNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgU3R5bGluZ0RpZmZlck9wdGlvbnMuQWxsb3dTdHJpbmdWYWx1ZSB8IFN0eWxpbmdEaWZmZXJPcHRpb25zLkZvcmNlQXNNYXApO1xuICAgIHRoaXMuX2NsYXNzU3RyaW5nRGlmZmVyLnNldFZhbHVlKHZhbHVlKTtcbiAgfVxuXG4gIHNldE5nQ2xhc3ModmFsdWU6IHN0cmluZ3xzdHJpbmdbXXxTZXQ8c3RyaW5nPnx7W2tsYXNzOiBzdHJpbmddOiBhbnl9KSB7XG4gICAgdGhpcy5fbmdDbGFzc0RpZmZlci5zZXRWYWx1ZSh2YWx1ZSk7XG4gIH1cblxuICBhcHBseUNoYW5nZXMoKSB7XG4gICAgY29uc3QgY2xhc3NDaGFuZ2VkID1cbiAgICAgICAgdGhpcy5fY2xhc3NTdHJpbmdEaWZmZXIgPyB0aGlzLl9jbGFzc1N0cmluZ0RpZmZlci5oYXNWYWx1ZUNoYW5nZWQoKSA6IGZhbHNlO1xuICAgIGNvbnN0IG5nQ2xhc3NDaGFuZ2VkID0gdGhpcy5fbmdDbGFzc0RpZmZlci5oYXNWYWx1ZUNoYW5nZWQoKTtcbiAgICBpZiAoY2xhc3NDaGFuZ2VkIHx8IG5nQ2xhc3NDaGFuZ2VkKSB7XG4gICAgICBsZXQgdmFsdWUgPSB0aGlzLl9uZ0NsYXNzRGlmZmVyLnZhbHVlO1xuICAgICAgaWYgKHRoaXMuX2NsYXNzU3RyaW5nRGlmZmVyKSB7XG4gICAgICAgIGxldCBjbGFzc1ZhbHVlID0gdGhpcy5fY2xhc3NTdHJpbmdEaWZmZXIudmFsdWU7XG4gICAgICAgIGlmIChjbGFzc1ZhbHVlKSB7XG4gICAgICAgICAgdmFsdWUgPSB2YWx1ZSA/IHsuLi5jbGFzc1ZhbHVlLCAuLi52YWx1ZX0gOiBjbGFzc1ZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgIH1cbiAgfVxufVxuXG4vLyB0aGUgaW1wbGVtZW50YXRpb24gZm9yIGJvdGggTmdTdHlsZVIySW1wbCBhbmQgTmdTdHlsZVIzSW1wbCBhcmVcbi8vIG5vdCBpdnlfc3dpdGNoJ2QgYXdheSwgaW5zdGVhZCB0aGV5IGFyZSBvbmx5IGhvb2tlZCB1cCBpbnRvIHRoZVxuLy8gREkgdmlhIE5nU3R5bGUncyBkaXJlY3RpdmUncyBwcm92aWRlciBwcm9wZXJ0eS5cbmV4cG9ydCBjb25zdCBOZ0NsYXNzSW1wbFByb3ZpZGVyX19QUkVfUjNfXyA9IHtcbiAgcHJvdmlkZTogTmdDbGFzc0ltcGwsXG4gIHVzZUNsYXNzOiBOZ0NsYXNzUjJJbXBsXG59O1xuXG5leHBvcnQgY29uc3QgTmdDbGFzc0ltcGxQcm92aWRlcl9fUE9TVF9SM19fID0ge1xuICBwcm92aWRlOiBOZ0NsYXNzSW1wbCxcbiAgdXNlQ2xhc3M6IE5nQ2xhc3NSM0ltcGxcbn07XG5cbmV4cG9ydCBjb25zdCBOZ0NsYXNzSW1wbFByb3ZpZGVyID0gTmdDbGFzc0ltcGxQcm92aWRlcl9fUFJFX1IzX187XG4iXX0=