UNPKG

@ngx-formly/bootstrap

Version:

ngx-formly is an Angular 2 module which has a Components to help customize and render JavaScript/JSON configured forms. The formly-form Component and the FormlyConfig service are very powerful and bring unmatched maintainability to your application's form

422 lines (399 loc) 57.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@ngx-formly/core'), require('@angular/forms'), require('rxjs'), require('@angular/common'), require('@ngx-formly/core/select')) : typeof define === 'function' && define.amd ? define('@ngx-formly/bootstrap', ['exports', '@angular/core', '@ngx-formly/core', '@angular/forms', 'rxjs', '@angular/common', '@ngx-formly/core/select'], factory) : (factory((global['ngx-formly'] = global['ngx-formly'] || {}, global['ngx-formly'].bootstrap = {}),global.ng.core,global.core$1,global.ng.forms,global.rxjs,global.ng.common,global.select)); }(this, (function (exports,core,core$1,forms,rxjs,common,select) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldCheckbox = /** @class */ (function (_super) { __extends(FormlyFieldCheckbox, _super); function FormlyFieldCheckbox() { return _super !== null && _super.apply(this, arguments) || this; } FormlyFieldCheckbox.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-checkbox', template: "\n <div class=\"custom-control custom-checkbox\">\n <input class=\"custom-control-input\" type=\"checkbox\"\n [class.is-invalid]=\"showError\"\n [indeterminate]=\"to.indeterminate && field.formControl.value === null\"\n [formControl]=\"formControl\"\n [formlyAttributes]=\"field\">\n <label class=\"custom-control-label\" [for]=\"id\">\n {{ to.label }}\n <span *ngIf=\"to.required && to.hideRequiredMarker !== true\">*</span>\n </label>\n </div>\n " }] } ]; return FormlyFieldCheckbox; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldMultiCheckbox = /** @class */ (function (_super) { __extends(FormlyFieldMultiCheckbox, _super); function FormlyFieldMultiCheckbox() { return _super !== null && _super.apply(this, arguments) || this; } /** * @param {?} model * @param {?} field * @return {?} */ FormlyFieldMultiCheckbox.createControl = /** * @param {?} model * @param {?} field * @return {?} */ function (model, field) { if (field.templateOptions.options instanceof rxjs.Observable) { throw new Error("[Formly Error] You cannot pass an Observable to a multicheckbox yet."); } /** @type {?} */ var controls = field.templateOptions.options.reduce(function (obj, option) { obj[option.key] = new forms.FormControl(model ? model[option.key] : undefined); return obj; }, {}); return new forms.FormGroup(controls, field.validators ? field.validators.validation : undefined, field.asyncValidators ? field.asyncValidators.validation : undefined); }; FormlyFieldMultiCheckbox.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-multicheckbox', template: "\n <div class=\"custom-control custom-checkbox\" *ngFor=\"let option of to.options; let i = index;\">\n <input class=\"custom-control-input\" type=\"checkbox\"\n [id]=\"id + '_' + i\"\n [value]=\"option.value\"\n [formControl]=\"formControl.get(option.key)\"\n [formlyAttributes]=\"field\">\n <label class=\"custom-control-label\" [for]=\"id + '_' + i\">\n {{ option.value }}\n </label>\n </div>\n " }] } ]; return FormlyFieldMultiCheckbox; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldInput = /** @class */ (function (_super) { __extends(FormlyFieldInput, _super); function FormlyFieldInput() { return _super !== null && _super.apply(this, arguments) || this; } Object.defineProperty(FormlyFieldInput.prototype, "type", { get: /** * @return {?} */ function () { return this.to.type || 'text'; }, enumerable: true, configurable: true }); FormlyFieldInput.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-input', template: "\n <input *ngIf=\"type !== 'number' else numberTmp\" [type]=\"type\" [formControl]=\"formControl\" class=\"form-control\" [formlyAttributes]=\"field\" [class.is-invalid]=\"showError\">\n <ng-template #numberTmp>\n <input type=\"number\" [formControl]=\"formControl\" class=\"form-control\" [formlyAttributes]=\"field\" [class.is-invalid]=\"showError\">\n </ng-template>\n ", host: { '[class.d-inline-flex]': 'to.addonLeft || to.addonRight', '[class.custom-file]': 'to.addonLeft || to.addonRight', } }] } ]; return FormlyFieldInput; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldRadio = /** @class */ (function (_super) { __extends(FormlyFieldRadio, _super); function FormlyFieldRadio() { return _super !== null && _super.apply(this, arguments) || this; } FormlyFieldRadio.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-radio', template: "\n <div [formGroup]=\"form\">\n <div class=\"custom-control custom-radio\" *ngFor=\"let option of to.options | formlySelectOptions:field | async; let i = index;\">\n <input class=\"custom-control-input\" type=\"radio\"\n [id]=\"id + '_' + i\"\n [name]=\"id\"\n [class.is-invalid]=\"showError\"\n [value]=\"option.value\"\n [formControl]=\"formControl\"\n [formlyAttributes]=\"field\">\n <label class=\"custom-control-label\" [for]=\"id + '_' + i\">\n {{ option.label }}\n </label>\n </div>\n </div>\n " }] } ]; return FormlyFieldRadio; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldTextArea = /** @class */ (function (_super) { __extends(FormlyFieldTextArea, _super); function FormlyFieldTextArea() { return _super !== null && _super.apply(this, arguments) || this; } FormlyFieldTextArea.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-textarea', template: "\n <textarea [formControl]=\"formControl\" [cols]=\"to.cols\"\n [rows]=\"to.rows\" class=\"form-control\" [class.is-invalid]=\"showError\"\n [formlyAttributes]=\"field\">\n </textarea>\n " }] } ]; return FormlyFieldTextArea; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyFieldSelect = /** @class */ (function (_super) { __extends(FormlyFieldSelect, _super); function FormlyFieldSelect() { return _super !== null && _super.apply(this, arguments) || this; } FormlyFieldSelect.decorators = [ { type: core.Component, args: [{ selector: 'formly-field-select', template: "\n <select *ngIf=\"to.multiple; else singleSelect\" class=\"form-control\"\n multiple\n [class.custom-select]=\"to.customSelect\"\n [formControl]=\"formControl\"\n [class.is-invalid]=\"showError\"\n [formlyAttributes]=\"field\">\n <ng-container *ngFor=\"let item of to.options | formlySelectOptions:field | async\">\n <optgroup *ngIf=\"item.group\" label=\"{{item.label}}\">\n <option *ngFor=\"let child of item.group\" [value]=\"child.value\" [disabled]=\"child.disabled\">\n {{ child.label }}\n </option>\n </optgroup>\n <option *ngIf=\"!item.group\" [value]=\"item.value\" [disabled]=\"item.disabled\">{{ item.label }}</option>\n </ng-container>\n </select>\n\n <ng-template #singleSelect>\n <select class=\"form-control\"\n [formControl]=\"formControl\"\n [class.custom-select]=\"to.customSelect\"\n [class.is-invalid]=\"showError\"\n [formlyAttributes]=\"field\">\n <option *ngIf=\"to.placeholder\" value=\"\">{{ to.placeholder }}</option>\n <ng-container *ngFor=\"let item of to.options | formlySelectOptions:field | async\">\n <optgroup *ngIf=\"item.group\" label=\"{{item.label}}\">\n <option *ngFor=\"let child of item.group\" [value]=\"child.value\" [disabled]=\"child.disabled\">\n {{ child.label }}\n </option>\n </optgroup>\n <option *ngIf=\"!item.group\" [value]=\"item.value\" [disabled]=\"item.disabled\">{{ item.label }}</option>\n </ng-container>\n </select>\n </ng-template>\n " }] } ]; return FormlyFieldSelect; }(core$1.FieldType)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyWrapperFormField = /** @class */ (function (_super) { __extends(FormlyWrapperFormField, _super); function FormlyWrapperFormField() { return _super !== null && _super.apply(this, arguments) || this; } FormlyWrapperFormField.decorators = [ { type: core.Component, args: [{ selector: 'formly-wrapper-form-field', template: "\n <div class=\"form-group\" [class.has-error]=\"showError\">\n <label *ngIf=\"to.label && to.hideLabel !== true\" [attr.for]=\"id\">\n {{ to.label }} <ng-container *ngIf=\"to.required && to.hideRequiredMarker !== true\">*</ng-container>\n </label>\n\n <ng-template #fieldComponent></ng-template>\n\n <div *ngIf=\"showError\" class=\"invalid-feedback\" [style.display]=\"'block'\">\n <formly-validation-message [field]=\"field\"></formly-validation-message>\n </div>\n\n <small *ngIf=\"to.description\" class=\"form-text text-muted\">{{ to.description }}</small>\n </div>\n " }] } ]; FormlyWrapperFormField.propDecorators = { fieldComponent: [{ type: core.ViewChild, args: ['fieldComponent', { read: core.ViewContainerRef },] }] }; return FormlyWrapperFormField; }(core$1.FieldWrapper)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyWrapperAddons = /** @class */ (function (_super) { __extends(FormlyWrapperAddons, _super); function FormlyWrapperAddons() { return _super !== null && _super.apply(this, arguments) || this; } /** * @param {?} $event * @return {?} */ FormlyWrapperAddons.prototype.addonRightClick = /** * @param {?} $event * @return {?} */ function ($event) { if (this.to["addonRight"].onClick) { this.to["addonRight"].onClick(this.to, this, $event); } }; /** * @param {?} $event * @return {?} */ FormlyWrapperAddons.prototype.addonLeftClick = /** * @param {?} $event * @return {?} */ function ($event) { if (this.to["addonLeft"].onClick) { this.to["addonLeft"].onClick(this.to, this, $event); } }; FormlyWrapperAddons.decorators = [ { type: core.Component, args: [{ selector: 'formly-wrapper-addons', template: "\n <div class=\"input-group\">\n <div class=\"input-group-prepend\"\n *ngIf=\"to.addonLeft\"\n [ngStyle]=\"{cursor: to.addonLeft.onClick ? 'pointer' : 'inherit'}\"\n (click)=\"addonLeftClick($event)\">\n <i class=\"input-group-text\" [ngClass]=\"to.addonLeft.class\" *ngIf=\"to.addonLeft.class\"></i>\n <span *ngIf=\"to.addonLeft.text\" class=\"input-group-text\">{{ to.addonLeft.text }}</span>\n </div>\n <ng-template #fieldComponent></ng-template>\n <div class=\"input-group-append\"\n *ngIf=\"to.addonRight\"\n [ngStyle]=\"{cursor: to.addonRight.onClick ? 'pointer' : 'inherit'}\"\n (click)=\"addonRightClick($event)\">\n <i class=\"input-group-text\" [ngClass]=\"to.addonRight.class\" *ngIf=\"to.addonRight.class\"></i>\n <span *ngIf=\"to.addonRight.text\" class=\"input-group-text\">{{ to.addonRight.text }}</span>\n </div>\n </div>\n ", styles: ["\n :host ::ng-deep .input-group>:not(:first-child)> .form-control {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n :host ::ng-deep .input-group>:not(:last-child)> .form-control {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n "] }] } ]; FormlyWrapperAddons.propDecorators = { fieldComponent: [{ type: core.ViewChild, args: ['fieldComponent', { read: core.ViewContainerRef },] }] }; return FormlyWrapperAddons; }(core$1.FieldWrapper)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var TemplateAddons = /** @class */ (function () { function TemplateAddons() { } /** * @param {?} fc * @return {?} */ TemplateAddons.prototype.run = /** * @param {?} fc * @return {?} */ function (fc) { fc.templateManipulators.postWrapper.push(function (field) { if (field && field.templateOptions && (field.templateOptions["addonLeft"] || field.templateOptions["addonRight"])) { return 'addons'; } }); }; return TemplateAddons; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** @type {?} */ var FIELD_TYPE_COMPONENTS = [ FormlyFieldInput, FormlyFieldCheckbox, FormlyFieldRadio, FormlyFieldSelect, FormlyFieldTextArea, FormlyFieldMultiCheckbox, FormlyWrapperAddons, FormlyWrapperFormField, ]; /** @type {?} */ var BOOTSTRAP_FORMLY_CONFIG = { types: [ { name: 'input', component: FormlyFieldInput, wrappers: ['form-field'], }, { name: 'checkbox', component: FormlyFieldCheckbox, wrappers: ['form-field'], defaultOptions: { templateOptions: { indeterminate: true, hideLabel: true, }, }, }, { name: 'radio', component: FormlyFieldRadio, wrappers: ['form-field'], defaultOptions: { templateOptions: { options: [], }, }, }, { name: 'select', component: FormlyFieldSelect, wrappers: ['form-field'], defaultOptions: { templateOptions: { options: [], }, }, }, { name: 'textarea', component: FormlyFieldTextArea, wrappers: ['form-field'], defaultOptions: { templateOptions: { cols: 1, rows: 1, }, }, }, { name: 'multicheckbox', component: FormlyFieldMultiCheckbox, wrappers: ['form-field'], defaultOptions: { templateOptions: { options: [], }, }, }, ], wrappers: [ { name: 'addons', component: FormlyWrapperAddons }, { name: 'form-field', component: FormlyWrapperFormField }, ], manipulators: [ { class: TemplateAddons, method: 'run' }, ], }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var FormlyBootstrapModule = /** @class */ (function () { function FormlyBootstrapModule() { } FormlyBootstrapModule.decorators = [ { type: core.NgModule, args: [{ declarations: [ FIELD_TYPE_COMPONENTS, ], imports: [ common.CommonModule, forms.ReactiveFormsModule, select.FormlySelectModule, core$1.FormlyModule.forRoot(BOOTSTRAP_FORMLY_CONFIG), ], },] } ]; return FormlyBootstrapModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ exports.FormlyBootstrapModule = FormlyBootstrapModule; exports.FormlyFieldCheckbox = FormlyFieldCheckbox; exports.FormlyFieldMultiCheckbox = FormlyFieldMultiCheckbox; exports.FormlyFieldInput = FormlyFieldInput; exports.FormlyFieldRadio = FormlyFieldRadio; exports.FormlyFieldTextArea = FormlyFieldTextArea; exports.FormlyFieldSelect = FormlyFieldSelect; exports.FormlyWrapperFormField = FormlyWrapperFormField; exports.FormlyWrapperAddons = FormlyWrapperAddons; exports.ɵb = BOOTSTRAP_FORMLY_CONFIG; exports.ɵa = FIELD_TYPE_COMPONENTS; exports.ɵc = TemplateAddons; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWZvcm1seS1ib290c3RyYXAudW1kLmpzLm1hcCIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm5nOi8vQG5neC1mb3JtbHkvYm9vdHN0cmFwL2xpYi90eXBlcy9jaGVja2JveC50cyIsIm5nOi8vQG5neC1mb3JtbHkvYm9vdHN0cmFwL2xpYi90eXBlcy9tdWx0aWNoZWNrYm94LnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL3R5cGVzL2lucHV0LnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL3R5cGVzL3JhZGlvLnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL3R5cGVzL3RleHRhcmVhLnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL3R5cGVzL3NlbGVjdC50cyIsIm5nOi8vQG5neC1mb3JtbHkvYm9vdHN0cmFwL2xpYi93cmFwcGVycy9mb3JtLWZpZWxkLndyYXBwZXIudHMiLCJuZzovL0BuZ3gtZm9ybWx5L2Jvb3RzdHJhcC9saWIvd3JhcHBlcnMvYWRkb25zLnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL3J1bi9hZGRvbi50cyIsIm5nOi8vQG5neC1mb3JtbHkvYm9vdHN0cmFwL2xpYi9ib290c3RyYXAuY29uZmlnLnRzIiwibmc6Ly9Abmd4LWZvcm1seS9ib290c3RyYXAvbGliL2Jvb3RzdHJhcC5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2VcclxudGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGVcclxuTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcclxuXHJcblRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcclxuS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRFxyXG5XQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLFxyXG5NRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULlxyXG5cclxuU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXHJcbmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIGV4cG9ydHMpIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0U3Rhcihtb2QpIHtcclxuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XHJcbiAgICB2YXIgcmVzdWx0ID0ge307XHJcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgcmVzdWx0W2tdID0gbW9kW2tdO1xyXG4gICAgcmVzdWx0LmRlZmF1bHQgPSBtb2Q7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZpZWxkVHlwZSB9IGZyb20gJ0BuZ3gtZm9ybWx5L2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmb3JtbHktZmllbGQtY2hlY2tib3gnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJjdXN0b20tY29udHJvbCBjdXN0b20tY2hlY2tib3hcIj5cbiAgICAgIDxpbnB1dCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwic2hvd0Vycm9yXCJcbiAgICAgICAgW2luZGV0ZXJtaW5hdGVdPVwidG8uaW5kZXRlcm1pbmF0ZSAmJiBmaWVsZC5mb3JtQ29udHJvbC52YWx1ZSA9PT0gbnVsbFwiXG4gICAgICAgIFtmb3JtQ29udHJvbF09XCJmb3JtQ29udHJvbFwiXG4gICAgICAgIFtmb3JtbHlBdHRyaWJ1dGVzXT1cImZpZWxkXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJjdXN0b20tY29udHJvbC1sYWJlbFwiIFtmb3JdPVwiaWRcIj5cbiAgICAgICAge3sgdG8ubGFiZWwgfX1cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJ0by5yZXF1aXJlZCAmJiB0by5oaWRlUmVxdWlyZWRNYXJrZXIgIT09IHRydWVcIj4qPC9zcGFuPlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgRm9ybWx5RmllbGRDaGVja2JveCBleHRlbmRzIEZpZWxkVHlwZSB7IH1cbiIsImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgQWJzdHJhY3RDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgRmllbGRUeXBlLCBGb3JtbHlGaWVsZENvbmZpZyB9IGZyb20gJ0BuZ3gtZm9ybWx5L2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmb3JtbHktZmllbGQtbXVsdGljaGVja2JveCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImN1c3RvbS1jb250cm9sIGN1c3RvbS1jaGVja2JveFwiICpuZ0Zvcj1cImxldCBvcHRpb24gb2YgdG8ub3B0aW9uczsgbGV0IGkgPSBpbmRleDtcIj5cbiAgICAgIDxpbnB1dCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW2lkXT1cImlkICsgJ18nICsgaVwiXG4gICAgICAgIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIlxuICAgICAgICBbZm9ybUNvbnRyb2xdPVwiZm9ybUNvbnRyb2wuZ2V0KG9wdGlvbi5rZXkpXCJcbiAgICAgICAgW2Zvcm1seUF0dHJpYnV0ZXNdPVwiZmllbGRcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWxhYmVsXCIgW2Zvcl09XCJpZCArICdfJyArIGlcIj5cbiAgICAgICAge3sgb3B0aW9uLnZhbHVlIH19XG4gICAgICA8L2xhYmVsPlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBGb3JtbHlGaWVsZE11bHRpQ2hlY2tib3ggZXh0ZW5kcyBGaWVsZFR5cGUge1xuXG4gIHN0YXRpYyBjcmVhdGVDb250cm9sKG1vZGVsOiBhbnksIGZpZWxkOiBGb3JtbHlGaWVsZENvbmZpZyk6IEFic3RyYWN0Q29udHJvbCB7XG4gICAgaWYgKGZpZWxkLnRlbXBsYXRlT3B0aW9ucy5vcHRpb25zIGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBbRm9ybWx5IEVycm9yXSBZb3UgY2Fubm90IHBhc3MgYW4gT2JzZXJ2YWJsZSB0byBhIG11bHRpY2hlY2tib3ggeWV0LmApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRyb2xzID0gZmllbGQudGVtcGxhdGVPcHRpb25zLm9wdGlvbnMucmVkdWNlKChvYmosIG9wdGlvbikgPT4ge1xuICAgICAgb2JqW29wdGlvbi5rZXldID0gbmV3IEZvcm1Db250cm9sKG1vZGVsID8gbW9kZWxbb3B0aW9uLmtleV0gOiB1bmRlZmluZWQpO1xuICAgICAgcmV0dXJuIG9iajtcbiAgICB9LCB7fSk7XG5cbiAgICByZXR1cm4gbmV3IEZvcm1Hcm91cChcbiAgICAgIGNvbnRyb2xzLFxuICAgICAgZmllbGQudmFsaWRhdG9ycyA/IGZpZWxkLnZhbGlkYXRvcnMudmFsaWRhdGlvbiA6IHVuZGVmaW5lZCxcbiAgICAgIGZpZWxkLmFzeW5jVmFsaWRhdG9ycyA/IGZpZWxkLmFzeW5jVmFsaWRhdG9ycy52YWxpZGF0aW9uIDogdW5kZWZpbmVkLFxuICAgICk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGaWVsZFR5cGUgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZm9ybWx5LWZpZWxkLWlucHV0JyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8aW5wdXQgKm5nSWY9XCJ0eXBlICE9PSAnbnVtYmVyJyBlbHNlIG51bWJlclRtcFwiIFt0eXBlXT1cInR5cGVcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybUNvbnRyb2xcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFtmb3JtbHlBdHRyaWJ1dGVzXT1cImZpZWxkXCIgW2NsYXNzLmlzLWludmFsaWRdPVwic2hvd0Vycm9yXCI+XG4gICAgPG5nLXRlbXBsYXRlICNudW1iZXJUbXA+XG4gICAgICA8aW5wdXQgdHlwZT1cIm51bWJlclwiIFtmb3JtQ29udHJvbF09XCJmb3JtQ29udHJvbFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgW2Zvcm1seUF0dHJpYnV0ZXNdPVwiZmllbGRcIiBbY2xhc3MuaXMtaW52YWxpZF09XCJzaG93RXJyb3JcIj5cbiAgICA8L25nLXRlbXBsYXRlPlxuICBgLFxuICBob3N0OiB7XG4gICAgJ1tjbGFzcy5kLWlubGluZS1mbGV4XSc6ICd0by5hZGRvbkxlZnQgfHwgdG8uYWRkb25SaWdodCcsXG4gICAgJ1tjbGFzcy5jdXN0b20tZmlsZV0nOiAndG8uYWRkb25MZWZ0IHx8IHRvLmFkZG9uUmlnaHQnLFxuICB9LFxufSlcbmV4cG9ydCBjbGFzcyBGb3JtbHlGaWVsZElucHV0IGV4dGVuZHMgRmllbGRUeXBlIHtcbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8udHlwZSB8fCAndGV4dCc7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRmllbGRUeXBlIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Zvcm1seS1maWVsZC1yYWRpbycsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbZm9ybUdyb3VwXT1cImZvcm1cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjdXN0b20tY29udHJvbCBjdXN0b20tcmFkaW9cIiAqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIHRvLm9wdGlvbnMgfCBmb3JtbHlTZWxlY3RPcHRpb25zOmZpZWxkIHwgYXN5bmM7IGxldCBpID0gaW5kZXg7XCI+XG4gICAgICAgIDxpbnB1dCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWlucHV0XCIgdHlwZT1cInJhZGlvXCJcbiAgICAgICAgICBbaWRdPVwiaWQgKyAnXycgKyBpXCJcbiAgICAgICAgICBbbmFtZV09XCJpZFwiXG4gICAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwic2hvd0Vycm9yXCJcbiAgICAgICAgICBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCJcbiAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiZm9ybUNvbnRyb2xcIlxuICAgICAgICAgIFtmb3JtbHlBdHRyaWJ1dGVzXT1cImZpZWxkXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWxhYmVsXCIgW2Zvcl09XCJpZCArICdfJyArIGlcIj5cbiAgICAgICAgICB7eyBvcHRpb24ubGFiZWwgfX1cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBGb3JtbHlGaWVsZFJhZGlvIGV4dGVuZHMgRmllbGRUeXBlIHt9XG4iLCJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZpZWxkVHlwZSB9IGZyb20gJ0BuZ3gtZm9ybWx5L2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmb3JtbHktZmllbGQtdGV4dGFyZWEnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDx0ZXh0YXJlYSBbZm9ybUNvbnRyb2xdPVwiZm9ybUNvbnRyb2xcIiBbY29sc109XCJ0by5jb2xzXCJcbiAgICAgIFtyb3dzXT1cInRvLnJvd3NcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFtjbGFzcy5pcy1pbnZhbGlkXT1cInNob3dFcnJvclwiXG4gICAgICBbZm9ybWx5QXR0cmlidXRlc109XCJmaWVsZFwiPlxuICAgIDwvdGV4dGFyZWE+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEZvcm1seUZpZWxkVGV4dEFyZWEgZXh0ZW5kcyBGaWVsZFR5cGUge1xufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGaWVsZFR5cGUgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZm9ybWx5LWZpZWxkLXNlbGVjdCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPHNlbGVjdCAqbmdJZj1cInRvLm11bHRpcGxlOyBlbHNlIHNpbmdsZVNlbGVjdFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIG11bHRpcGxlXG4gICAgICBbY2xhc3MuY3VzdG9tLXNlbGVjdF09XCJ0by5jdXN0b21TZWxlY3RcIlxuICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm1Db250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInNob3dFcnJvclwiXG4gICAgICBbZm9ybWx5QXR0cmlidXRlc109XCJmaWVsZFwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtIG9mIHRvLm9wdGlvbnMgfCBmb3JtbHlTZWxlY3RPcHRpb25zOmZpZWxkIHwgYXN5bmNcIj5cbiAgICAgICAgIDxvcHRncm91cCAqbmdJZj1cIml0ZW0uZ3JvdXBcIiBsYWJlbD1cInt7aXRlbS5sYWJlbH19XCI+XG4gICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjaGlsZCBvZiBpdGVtLmdyb3VwXCIgW3ZhbHVlXT1cImNoaWxkLnZhbHVlXCIgW2Rpc2FibGVkXT1cImNoaWxkLmRpc2FibGVkXCI+XG4gICAgICAgICAgICAgIHt7IGNoaWxkLmxhYmVsIH19XG4gICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICA8L29wdGdyb3VwPlxuICAgICAgICAgIDxvcHRpb24gKm5nSWY9XCIhaXRlbS5ncm91cFwiIFt2YWx1ZV09XCJpdGVtLnZhbHVlXCIgW2Rpc2FibGVkXT1cIml0ZW0uZGlzYWJsZWRcIj57eyBpdGVtLmxhYmVsIH19PC9vcHRpb24+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvc2VsZWN0PlxuXG4gICAgPG5nLXRlbXBsYXRlICNzaW5nbGVTZWxlY3Q+XG4gICAgICA8c2VsZWN0IGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm1Db250cm9sXCJcbiAgICAgICAgW2NsYXNzLmN1c3RvbS1zZWxlY3RdPVwidG8uY3VzdG9tU2VsZWN0XCJcbiAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwic2hvd0Vycm9yXCJcbiAgICAgICAgW2Zvcm1seUF0dHJpYnV0ZXNdPVwiZmllbGRcIj5cbiAgICAgICAgPG9wdGlvbiAqbmdJZj1cInRvLnBsYWNlaG9sZGVyXCIgdmFsdWU9XCJcIj57eyB0by5wbGFjZWhvbGRlciB9fTwvb3B0aW9uPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtIG9mIHRvLm9wdGlvbnMgfCBmb3JtbHlTZWxlY3RPcHRpb25zOmZpZWxkIHwgYXN5bmNcIj5cbiAgICAgICAgICA8b3B0Z3JvdXAgKm5nSWY9XCJpdGVtLmdyb3VwXCIgbGFiZWw9XCJ7e2l0ZW0ubGFiZWx9fVwiPlxuICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgY2hpbGQgb2YgaXRlbS5ncm91cFwiIFt2YWx1ZV09XCJjaGlsZC52YWx1ZVwiIFtkaXNhYmxlZF09XCJjaGlsZC5kaXNhYmxlZFwiPlxuICAgICAgICAgICAgICB7eyBjaGlsZC5sYWJlbCB9fVxuICAgICAgICAgICAgPC9vcHRpb24+XG4gICAgICAgICAgPC9vcHRncm91cD5cbiAgICAgICAgICA8b3B0aW9uICpuZ0lmPVwiIWl0ZW0uZ3JvdXBcIiBbdmFsdWVdPVwiaXRlbS52YWx1ZVwiIFtkaXNhYmxlZF09XCJpdGVtLmRpc2FibGVkXCI+e3sgaXRlbS5sYWJlbCB9fTwvb3B0aW9uPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvc2VsZWN0PlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEZvcm1seUZpZWxkU2VsZWN0IGV4dGVuZHMgRmllbGRUeXBlIHt9XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRmllbGRXcmFwcGVyIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Zvcm1seS13cmFwcGVyLWZvcm0tZmllbGQnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCIgW2NsYXNzLmhhcy1lcnJvcl09XCJzaG93RXJyb3JcIj5cbiAgICAgIDxsYWJlbCAqbmdJZj1cInRvLmxhYmVsICYmIHRvLmhpZGVMYWJlbCAhPT0gdHJ1ZVwiIFthdHRyLmZvcl09XCJpZFwiPlxuICAgICAgICB7eyB0by5sYWJlbCB9fSA8bmctY29udGFpbmVyICpuZ0lmPVwidG8ucmVxdWlyZWQgJiYgdG8uaGlkZVJlcXVpcmVkTWFya2VyICE9PSB0cnVlXCI+KjwvbmctY29udGFpbmVyPlxuICAgICAgPC9sYWJlbD5cblxuICAgICAgPG5nLXRlbXBsYXRlICNmaWVsZENvbXBvbmVudD48L25nLXRlbXBsYXRlPlxuXG4gICAgICA8ZGl2ICpuZ0lmPVwic2hvd0Vycm9yXCIgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW3N0eWxlLmRpc3BsYXldPVwiJ2Jsb2NrJ1wiPlxuICAgICAgICA8Zm9ybWx5LXZhbGlkYXRpb24tbWVzc2FnZSBbZmllbGRdPVwiZmllbGRcIj48L2Zvcm1seS12YWxpZGF0aW9uLW1lc3NhZ2U+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHNtYWxsICpuZ0lmPVwidG8uZGVzY3JpcHRpb25cIiBjbGFzcz1cImZvcm0tdGV4dCB0ZXh0LW11dGVkXCI+e3sgdG8uZGVzY3JpcHRpb24gfX08L3NtYWxsPlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBGb3JtbHlXcmFwcGVyRm9ybUZpZWxkIGV4dGVuZHMgRmllbGRXcmFwcGVyIHtcbiAgQFZpZXdDaGlsZCgnZmllbGRDb21wb25lbnQnLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYgfSkgZmllbGRDb21wb25lbnQ6IFZpZXdDb250YWluZXJSZWY7XG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRmllbGRXcmFwcGVyIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Zvcm1seS13cmFwcGVyLWFkZG9ucycsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtcHJlcGVuZFwiXG4gICAgICAgICpuZ0lmPVwidG8uYWRkb25MZWZ0XCJcbiAgICAgICAgW25nU3R5bGVdPVwie2N1cnNvcjogdG8uYWRkb25MZWZ0Lm9uQ2xpY2sgPyAncG9pbnRlcicgOiAnaW5oZXJpdCd9XCJcbiAgICAgICAgKGNsaWNrKT1cImFkZG9uTGVmdENsaWNrKCRldmVudClcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJpbnB1dC1ncm91cC10ZXh0XCIgW25nQ2xhc3NdPVwidG8uYWRkb25MZWZ0LmNsYXNzXCIgKm5nSWY9XCJ0by5hZGRvbkxlZnQuY2xhc3NcIj48L2k+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwidG8uYWRkb25MZWZ0LnRleHRcIiBjbGFzcz1cImlucHV0LWdyb3VwLXRleHRcIj57eyB0by5hZGRvbkxlZnQudGV4dCB9fTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPG5nLXRlbXBsYXRlICNmaWVsZENvbXBvbmVudD48L25nLXRlbXBsYXRlPlxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwLWFwcGVuZFwiXG4gICAgICAgICpuZ0lmPVwidG8uYWRkb25SaWdodFwiXG4gICAgICAgIFtuZ1N0eWxlXT1cIntjdXJzb3I6IHRvLmFkZG9uUmlnaHQub25DbGljayA/ICdwb2ludGVyJyA6ICdpbmhlcml0J31cIlxuICAgICAgICAoY2xpY2spPVwiYWRkb25SaWdodENsaWNrKCRldmVudClcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJpbnB1dC1ncm91cC10ZXh0XCIgW25nQ2xhc3NdPVwidG8uYWRkb25SaWdodC5jbGFzc1wiICpuZ0lmPVwidG8uYWRkb25SaWdodC5jbGFzc1wiPjwvaT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJ0by5hZGRvblJpZ2h0LnRleHRcIiBjbGFzcz1cImlucHV0LWdyb3VwLXRleHRcIj57eyB0by5hZGRvblJpZ2h0LnRleHQgfX08L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IDo6bmctZGVlcCAuaW5wdXQtZ3JvdXA+Om5vdCg6Zmlyc3QtY2hpbGQpPiAuZm9ybS1jb250cm9sIHtcbiAgICAgIGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IDA7XG4gICAgICBib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOiAwO1xuICAgIH1cbiAgICA6aG9zdCA6Om5nLWRlZXAgLmlucHV0LWdyb3VwPjpub3QoOmxhc3QtY2hpbGQpPiAuZm9ybS1jb250cm9sIHtcbiAgICAgIGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiAwO1xuICAgICAgYm9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6IDA7XG4gICAgfVxuICBgXSxcbn0pXG5leHBvcnQgY2xhc3MgRm9ybWx5V3JhcHBlckFkZG9ucyBleHRlbmRzIEZpZWxkV3JhcHBlciB7XG4gIEBWaWV3Q2hpbGQoJ2ZpZWxkQ29tcG9uZW50Jywge3JlYWQ6IFZpZXdDb250YWluZXJSZWZ9KSBmaWVsZENvbXBvbmVudDogVmlld0NvbnRhaW5lclJlZjtcblxuICBhZGRvblJpZ2h0Q2xpY2soJGV2ZW50OiBhbnkpIHtcbiAgICBpZiAodGhpcy50by5hZGRvblJpZ2h0Lm9uQ2xpY2spIHtcbiAgICAgIHRoaXMudG8uYWRkb25SaWdodC5vbkNsaWNrKHRoaXMudG8sIHRoaXMsICRldmVudCk7XG4gICAgfVxuICB9XG5cbiAgYWRkb25MZWZ0Q2xpY2soJGV2ZW50OiBhbnkpIHtcbiAgICBpZiAodGhpcy50by5hZGRvbkxlZnQub25DbGljaykge1xuICAgICAgdGhpcy50by5hZGRvbkxlZnQub25DbGljayh0aGlzLnRvLCB0aGlzLCAkZXZlbnQpO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHsgRm9ybWx5Q29uZmlnIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5cbmV4cG9ydCBjbGFzcyBUZW1wbGF0ZUFkZG9ucyB7XG4gIHJ1bihmYzogRm9ybWx5Q29uZmlnKSB7XG4gICAgZmMudGVtcGxhdGVNYW5pcHVsYXRvcnMucG9zdFdyYXBwZXIucHVzaCgoZmllbGQpID0+IHtcbiAgICAgIGlmIChmaWVsZCAmJiBmaWVsZC50ZW1wbGF0ZU9wdGlvbnMgJiYgKGZpZWxkLnRlbXBsYXRlT3B0aW9ucy5hZGRvbkxlZnQgfHwgZmllbGQudGVtcGxhdGVPcHRpb25zLmFkZG9uUmlnaHQpKSB7XG4gICAgICAgIHJldHVybiAnYWRkb25zJztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29uZmlnT3B0aW9uIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5pbXBvcnQgeyBUZW1wbGF0ZUFkZG9ucyB9IGZyb20gJy4vcnVuL2FkZG9uJztcbmltcG9ydCB7XG4gIEZvcm1seUZpZWxkSW5wdXQsXG4gIEZvcm1seUZpZWxkQ2hlY2tib3gsXG4gIEZvcm1seUZpZWxkUmFkaW8sXG4gIEZvcm1seUZpZWxkU2VsZWN0LFxuICBGb3JtbHlGaWVsZFRleHRBcmVhLFxuICBGb3JtbHlGaWVsZE11bHRpQ2hlY2tib3gsXG59IGZyb20gJy4vdHlwZXMvdHlwZXMnO1xuaW1wb3J0IHtcbiAgRm9ybWx5V3JhcHBlckFkZG9ucyxcbiAgRm9ybWx5V3JhcHBlckZvcm1GaWVsZCxcbn0gZnJvbSAnLi93cmFwcGVycy93cmFwcGVycyc7XG5cbmV4cG9ydCBjb25zdCBGSUVMRF9UWVBFX0NPTVBPTkVOVFMgPSBbXG4gIC8vIHR5cGVzXG4gIEZvcm1seUZpZWxkSW5wdXQsXG4gIEZvcm1seUZpZWxkQ2hlY2tib3gsXG4gIEZvcm1seUZpZWxkUmFkaW8sXG4gIEZvcm1seUZpZWxkU2VsZWN0LFxuICBGb3JtbHlGaWVsZFRleHRBcmVhLFxuICBGb3JtbHlGaWVsZE11bHRpQ2hlY2tib3gsXG5cbiAgLy8gd3JhcHBlcnNcbiAgRm9ybWx5V3JhcHBlckFkZG9ucyxcbiAgRm9ybWx5V3JhcHBlckZvcm1GaWVsZCxcbl07XG5cbmV4cG9ydCBjb25zdCBCT09UU1RSQVBfRk9STUxZX0NPTkZJRzogQ29uZmlnT3B0aW9uID0ge1xuICB0eXBlczogW1xuICAgIHtcbiAgICAgIG5hbWU6ICdpbnB1dCcsXG4gICAgICBjb21wb25lbnQ6IEZvcm1seUZpZWxkSW5wdXQsXG4gICAgICB3cmFwcGVyczogWydmb3JtLWZpZWxkJ10sXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnY2hlY2tib3gnLFxuICAgICAgY29tcG9uZW50OiBGb3JtbHlGaWVsZENoZWNrYm94LFxuICAgICAgd3JhcHBlcnM6IFsnZm9ybS1maWVsZCddLFxuICAgICAgZGVmYXVsdE9wdGlvbnM6IHtcbiAgICAgICAgdGVtcGxhdGVPcHRpb25zOiB7XG4gICAgICAgICAgaW5kZXRlcm1pbmF0ZTogdHJ1ZSxcbiAgICAgICAgICBoaWRlTGFiZWw6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ3JhZGlvJyxcbiAgICAgIGNvbXBvbmVudDogRm9ybWx5RmllbGRSYWRpbyxcbiAgICAgIHdyYXBwZXJzOiBbJ2Zvcm0tZmllbGQnXSxcbiAgICAgIGRlZmF1bHRPcHRpb25zOiB7XG4gICAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICAgIG9wdGlvbnM6IFtdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdzZWxlY3QnLFxuICAgICAgY29tcG9uZW50OiBGb3JtbHlGaWVsZFNlbGVjdCxcbiAgICAgIHdyYXBwZXJzOiBbJ2Zvcm0tZmllbGQnXSxcbiAgICAgIGRlZmF1bHRPcHRpb25zOiB7XG4gICAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICAgIG9wdGlvbnM6IFtdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICd0ZXh0YXJlYScsXG4gICAgICBjb21wb25lbnQ6IEZvcm1seUZpZWxkVGV4dEFyZWEsXG4gICAgICB3cmFwcGVyczogWydmb3JtLWZpZWxkJ10sXG4gICAgICBkZWZhdWx0T3B0aW9uczoge1xuICAgICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgICBjb2xzOiAxLFxuICAgICAgICAgIHJvd3M6IDEsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ211bHRpY2hlY2tib3gnLFxuICAgICAgY29tcG9uZW50OiBGb3JtbHlGaWVsZE11bHRpQ2hlY2tib3gsXG4gICAgICB3cmFwcGVyczogWydmb3JtLWZpZWxkJ10sXG4gICAgICBkZWZhdWx0T3B0aW9uczoge1xuICAgICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgICBvcHRpb25zOiBbXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgXSxcbiAgd3JhcHBlcnM6IFtcbiAgICB7bmFtZTogJ2FkZG9ucycsIGNvbXBvbmVudDogRm9ybWx5V3JhcHBlckFkZG9uc30sXG4gICAge25hbWU6ICdmb3JtLWZpZWxkJywgY29tcG9uZW50OiBGb3JtbHlXcmFwcGVyRm9ybUZpZWxkfSxcbiAgXSxcbiA