UNPKG

carbon-components-angular

Version:
321 lines 36.5 kB
import { Component, Input, EventEmitter, Output, HostBinding, HostListener, ViewChild } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/i18n"; import * as i2 from "@angular/common"; import * as i3 from "carbon-components-angular/icon"; /** * Get started with importing the module: * * ```typescript * import { SearchModule } from 'carbon-components-angular'; * ``` * * [See demo](../../?path=/story/components-search--basic) */ export class Search { /** * Creates an instance of `Search`. * @param i18n The i18n translations. */ constructor(elementRef, i18n) { this.elementRef = elementRef; this.i18n = i18n; /** * @deprecated since v5 - Use `cdsLayer` directive instead * `light` or `dark` search theme. */ this.theme = "dark"; /** * Size of the search field. */ this.size = "md"; /** * Set to `true` for a disabled search input. */ this.disabled = false; /** * Set to `true` for a toolbar search component. */ this.toolbar = false; /** * Set to `true` to make the search component expandable. * `expandable` would override `toolbar` property behaviours. */ this.expandable = false; /** * Set to `true` for a loading search component. */ this.skeleton = false; /** * Set to `true` to expand the toolbar search component. */ this.active = false; /** * Specifies whether the search component is used in the table toolbar. */ this.tableSearch = false; /** * The unique id for the search component. */ this.id = `search-${Search.searchCount}`; /** * Sets the value attribute on the `input` element. */ this.value = ""; /** * Sets the autocomplete attribute on the `input` element. * For reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#Values */ this.autocomplete = "on"; /** * Sets the text inside the `label` tag. */ this.label = this.i18n.get().SEARCH.LABEL; /** * Sets the placeholder attribute on the `input` element. */ this.placeholder = this.i18n.get().SEARCH.PLACEHOLDER; /** * Used to set the `title` attribute of the clear button. */ this.clearButtonTitle = this.i18n.get().SEARCH.CLEAR_BUTTON; /** * Title for the search trigger */ this.searchTitle = ""; /** * Experimental: enable fluid state */ this.fluid = false; /** * Emits an event when value is changed. */ this.valueChange = new EventEmitter(); this.open = new EventEmitter(); /** * Emits an event when the clear button is clicked. */ this.clear = new EventEmitter(); /** * Emits an event on enter. */ this.search = new EventEmitter(); /** * Sets `true` when composing text via IME. */ this.isComposing = false; /** * Called when search input is blurred. Needed to properly implement `ControlValueAccessor`. */ this.onTouched = () => { }; /** * Method set in `registerOnChange` to propagate changes back to the form. */ this.propagateChange = (_) => { }; Search.searchCount++; } get containerClass() { return !(this.toolbar || this.expandable); } get fluidSkeletonClass() { return this.skeleton && this.fluid; } /** * This is the initial value set to the component * @param value The input value. */ writeValue(value) { this.value = value; } /** * Sets a method in order to propagate changes back to the form. */ registerOnChange(fn) { this.propagateChange = fn; } /** * Registers a callback to be triggered when the control has been touched. * @param fn Callback to be triggered when the search input is touched. */ registerOnTouched(fn) { this.onTouched = fn; } /** * Called when text is written in the input. * @param search The input text. */ onSearch(search) { if (this.isComposing) { // check for IME use return; } this.value = search; this.doValueChange(); } /** * Called on enter. */ onEnter() { this.search.emit(this.value); } /** * Called when clear button is clicked. */ clearSearch() { this.value = ""; this.doValueChange(); this.clear.emit(); } doValueChange() { this.propagateChange(this.value); this.valueChange.emit(this.value); } openSearch() { this.active = true; this.open.emit(this.active); setTimeout(() => this.inputRef.nativeElement.focus()); } keyDown(event) { if (this.toolbar || this.expandable) { if (event.key === "Escape") { if (this.value === "") { this.active = false; this.open.emit(this.active); } } else if (event.key === "Enter") { this.openSearch(); } } if (event.key === "Escape") { if (this.value !== "") { this.clearSearch(); } } } focusOut(event) { this.onTouched(); if ((this.expandable || this.toolbar) && this.inputRef && this.inputRef.nativeElement.value === "" && !this.elementRef.nativeElement.contains(event.relatedTarget)) { this.active = false; this.open.emit(this.active); } } focusIn(event) { this.onTouched(); // set input focus if search icon get focus from tab key press event. if ((this.expandable || this.toolbar) && this.inputRef && !event.relatedTarget && !this.elementRef.nativeElement.contains(event.relatedTarget)) { this.openSearch(); } } /** * Called when using IME composition. */ compositionStart(event) { this.isComposing = true; } /** * Called when IME composition finishes. */ compositionEnd(event) { this.isComposing = false; this.onSearch(this.value + event.data); } } /** * Variable used for creating unique ids for search components. */ Search.searchCount = 0; Search.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Search, deps: [{ token: i0.ElementRef }, { token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component }); Search.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Search, selector: "cds-search, ibm-search", inputs: { theme: "theme", size: "size", disabled: "disabled", toolbar: "toolbar", expandable: "expandable", skeleton: "skeleton", active: "active", tableSearch: "tableSearch", name: "name", id: "id", required: "required", value: "value", autocomplete: "autocomplete", label: "label", placeholder: "placeholder", clearButtonTitle: "clearButtonTitle", searchTitle: "searchTitle", ariaLabel: "ariaLabel", fluid: "fluid" }, outputs: { valueChange: "valueChange", open: "open", clear: "clear", search: "search" }, host: { listeners: { "keydown": "keyDown($event)", "focusout": "focusOut($event)", "focusin": "focusIn($event)", "compositionstart": "compositionStart($event)", "compositionend": "compositionEnd($event)" }, properties: { "class.cds--form-item": "this.containerClass", "class.cds--text-input--fluid__skeleton": "this.fluidSkeletonClass" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Search, multi: true } ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: "<div\n\tclass=\"cds--search\"\n\t[ngClass]=\"{\n\t\t'cds--search--sm': size === 'sm',\n\t\t'cds--search--md': size === 'md',\n\t\t'cds--search--lg': size === 'lg',\n\t\t'cds--search--light': theme === 'light',\n\t\t'cds--skeleton': skeleton && !fluid,\n\t\t'cds--search--expandable': expandable && !tableSearch,\n\t\t'cds--search--expanded': expandable && !tableSearch && active,\n\t\t'cds--toolbar-search': toolbar && !expandable,\n\t\t'cds--toolbar-search--active': toolbar && !expandable && active,\n\t\t'cds--toolbar-search-container-persistent': tableSearch && !expandable,\n\t\t'cds--toolbar-search-container-expandable': tableSearch && expandable,\n\t\t'cds--toolbar-search-container-active': tableSearch && expandable && active,\n\t\t'cds--search--fluid': fluid,\n\t\t'cds--search--disabled': disabled\n\t}\"\n\trole=\"search\"\n\t[attr.aria-label]=\"ariaLabel\"\n\t(click)=\"openSearch()\">\n\t<label\n\t\tclass=\"cds--label\"\n\t\t[for]=\"id\"\n\t\t[ngClass]=\"{ 'cds--skeleton': skeleton && fluid }\">\n\t\t{{ !skeleton ? label : ''}}\n\t</label>\n\n\t<div *ngIf=\"skeleton; else enableInput\" class=\"cds--text-input cds--skeleton\"></div>\n\t<ng-template #enableInput>\n\t\t<input\n\t\t\t#input\n\t\t\tclass=\"cds--search-input\"\n\t\t\t[type]=\"tableSearch || !toolbar ? 'text' : 'search'\"\n\t\t\t[id]=\"id\"\n\t\t\t[value]=\"value\"\n\t\t\t[autocomplete]=\"autocomplete\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[required]=\"required\"\n\t\t\t(input)=\"onSearch($event.target.value)\"\n\t\t\t(keyup.enter)=\"onEnter()\"/>\n\t\t<button\n\t\t\t*ngIf=\"!tableSearch && toolbar\"\n\t\t\tclass=\"cds--toolbar-search__btn\"\n\t\t\t(click)=\"openSearch()\"\n\t\t\taria-label=\"Open search\">\n\t\t\t<svg cdsIcon=\"search\" size=\"16\" class=\"cds--search-magnifier-icon\"></svg>\n\t\t</button>\n\t\t<svg\n\t\t\tcdsIcon=\"search\"\n\t\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\t\tclass=\"cds--search-magnifier-icon\"\n\t\t\tsize=\"16\">\n\t\t</svg>\n\t</ng-template>\n\n\t<button\n\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\tclass=\"cds--search-close\"\n\t\t[ngClass]=\"{\n\t\t\t'cds--search-close--hidden': !value || value.length === 0\n\t\t}\"\n\t\t[title]=\"clearButtonTitle\"\n\t\t(click)=\"clearSearch()\">\n\t\t<span class=\"cds--visually-hidden\">{{ clearButtonTitle }}</span>\n\t\t<svg cdsIcon=\"close\" size=\"16\"></svg>\n\t</button>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Search, decorators: [{ type: Component, args: [{ selector: "cds-search, ibm-search", providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Search, multi: true } ], template: "<div\n\tclass=\"cds--search\"\n\t[ngClass]=\"{\n\t\t'cds--search--sm': size === 'sm',\n\t\t'cds--search--md': size === 'md',\n\t\t'cds--search--lg': size === 'lg',\n\t\t'cds--search--light': theme === 'light',\n\t\t'cds--skeleton': skeleton && !fluid,\n\t\t'cds--search--expandable': expandable && !tableSearch,\n\t\t'cds--search--expanded': expandable && !tableSearch && active,\n\t\t'cds--toolbar-search': toolbar && !expandable,\n\t\t'cds--toolbar-search--active': toolbar && !expandable && active,\n\t\t'cds--toolbar-search-container-persistent': tableSearch && !expandable,\n\t\t'cds--toolbar-search-container-expandable': tableSearch && expandable,\n\t\t'cds--toolbar-search-container-active': tableSearch && expandable && active,\n\t\t'cds--search--fluid': fluid,\n\t\t'cds--search--disabled': disabled\n\t}\"\n\trole=\"search\"\n\t[attr.aria-label]=\"ariaLabel\"\n\t(click)=\"openSearch()\">\n\t<label\n\t\tclass=\"cds--label\"\n\t\t[for]=\"id\"\n\t\t[ngClass]=\"{ 'cds--skeleton': skeleton && fluid }\">\n\t\t{{ !skeleton ? label : ''}}\n\t</label>\n\n\t<div *ngIf=\"skeleton; else enableInput\" class=\"cds--text-input cds--skeleton\"></div>\n\t<ng-template #enableInput>\n\t\t<input\n\t\t\t#input\n\t\t\tclass=\"cds--search-input\"\n\t\t\t[type]=\"tableSearch || !toolbar ? 'text' : 'search'\"\n\t\t\t[id]=\"id\"\n\t\t\t[value]=\"value\"\n\t\t\t[autocomplete]=\"autocomplete\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[required]=\"required\"\n\t\t\t(input)=\"onSearch($event.target.value)\"\n\t\t\t(keyup.enter)=\"onEnter()\"/>\n\t\t<button\n\t\t\t*ngIf=\"!tableSearch && toolbar\"\n\t\t\tclass=\"cds--toolbar-search__btn\"\n\t\t\t(click)=\"openSearch()\"\n\t\t\taria-label=\"Open search\">\n\t\t\t<svg cdsIcon=\"search\" size=\"16\" class=\"cds--search-magnifier-icon\"></svg>\n\t\t</button>\n\t\t<svg\n\t\t\tcdsIcon=\"search\"\n\t\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\t\tclass=\"cds--search-magnifier-icon\"\n\t\t\tsize=\"16\">\n\t\t</svg>\n\t</ng-template>\n\n\t<button\n\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\tclass=\"cds--search-close\"\n\t\t[ngClass]=\"{\n\t\t\t'cds--search-close--hidden': !value || value.length === 0\n\t\t}\"\n\t\t[title]=\"clearButtonTitle\"\n\t\t(click)=\"clearSearch()\">\n\t\t<span class=\"cds--visually-hidden\">{{ clearButtonTitle }}</span>\n\t\t<svg cdsIcon=\"close\" size=\"16\"></svg>\n\t</button>\n</div>\n" }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.I18n }]; }, propDecorators: { containerClass: [{ type: HostBinding, args: ["class.cds--form-item"] }], fluidSkeletonClass: [{ type: HostBinding, args: ["class.cds--text-input--fluid__skeleton"] }], theme: [{ type: Input }], size: [{ type: Input }], disabled: [{ type: Input }], toolbar: [{ type: Input }], expandable: [{ type: Input }], skeleton: [{ type: Input }], active: [{ type: Input }], tableSearch: [{ type: Input }], name: [{ type: Input }], id: [{ type: Input }], required: [{ type: Input }], value: [{ type: Input }], autocomplete: [{ type: Input }], label: [{ type: Input }], placeholder: [{ type: Input }], clearButtonTitle: [{ type: Input }], searchTitle: [{ type: Input }], ariaLabel: [{ type: Input }], fluid: [{ type: Input }], valueChange: [{ type: Output }], open: [{ type: Output }], clear: [{ type: Output }], search: [{ type: Output }], inputRef: [{ type: ViewChild, args: ["input"] }], keyDown: [{ type: HostListener, args: ["keydown", ["$event"]] }], focusOut: [{ type: HostListener, args: ["focusout", ["$event"]] }], focusIn: [{ type: HostListener, args: ["focusin", ["$event"]] }], compositionStart: [{ type: HostListener, args: ["compositionstart", ["$event"]] }], compositionEnd: [{ type: HostListener, args: ["compositionend", ["$event"]] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZWFyY2gvc2VhcmNoLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uL3NyYy9zZWFyY2gvc2VhcmNoLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTixTQUFTLEVBQ1QsS0FBSyxFQUNMLFlBQVksRUFDWixNQUFNLEVBQ04sV0FBVyxFQUVYLFlBQVksRUFDWixTQUFTLEVBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDOzs7OztBQUd6RTs7Ozs7Ozs7R0FRRztBQVlILE1BQU0sT0FBTyxNQUFNO0lBb0hsQjs7O09BR0c7SUFDSCxZQUFzQixVQUFzQixFQUFZLElBQVU7UUFBNUMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUFZLFNBQUksR0FBSixJQUFJLENBQU07UUExR2xFOzs7V0FHRztRQUNNLFVBQUssR0FBcUIsTUFBTSxDQUFDO1FBRTFDOztXQUVHO1FBQ00sU0FBSSxHQUF1QixJQUFJLENBQUM7UUFFekM7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sWUFBTyxHQUFHLEtBQUssQ0FBQztRQUN6Qjs7O1dBR0c7UUFDTSxlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzVCOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQUMxQjs7V0FFRztRQUNNLFdBQU0sR0FBRyxLQUFLLENBQUM7UUFDeEI7O1dBRUc7UUFDTSxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUs3Qjs7V0FFRztRQUNNLE9BQUUsR0FBRyxVQUFVLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUs3Qzs7V0FFRztRQUNNLFVBQUssR0FBRyxFQUFFLENBQUM7UUFDcEI7OztXQUdHO1FBQ00saUJBQVksR0FBRyxJQUFJLENBQUM7UUFDN0I7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O3NCQUFaLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFJRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csVUFBVTtzQkFBbEIsS0FBSztnQkFJRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLE1BQU07c0JBQWQsS0FBSztnQkFJRyxXQUFXO3NCQUFuQixLQUFLO2dCQUlHLElBQUk7c0JBQVosS0FBSztnQkFJRyxFQUFFO3NCQUFWLEtBQUs7Z0JBSUcsUUFBUTtzQkFBaEIsS0FBSztnQkFJRyxLQUFLO3NCQUFiLEtBQUs7Z0JBS0csWUFBWTtzQkFBcEIsS0FBSztnQkFJRyxLQUFLO3NCQUFiLEtBQUs7Z0JBSUcsV0FBVztzQkFBbkIsS0FBSztnQkFJRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBSUcsV0FBVztzQkFBbkIsS0FBSztnQkFJRyxTQUFTO3NCQUFqQixLQUFLO2dCQUlHLEtBQUs7c0JBQWIsS0FBSztnQkFJSSxXQUFXO3NCQUFwQixNQUFNO2dCQUNHLElBQUk7c0JBQWIsTUFBTTtnQkFJRyxLQUFLO3NCQUFkLE1BQU07Z0JBSUcsTUFBTTtzQkFBZixNQUFNO2dCQUVhLFFBQVE7c0JBQTNCLFNBQVM7dUJBQUMsT0FBTztnQkF3RmxCLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBcUJuQyxRQUFRO3NCQURQLFlBQVk7dUJBQUMsVUFBVSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWFwQyxPQUFPO3NCQUROLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWVuQyxnQkFBZ0I7c0JBRGYsWUFBWTt1QkFBQyxrQkFBa0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFTNUMsY0FBYztzQkFEYixZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0RXZlbnRFbWl0dGVyLFxuXHRPdXRwdXQsXG5cdEhvc3RCaW5kaW5nLFxuXHRFbGVtZW50UmVmLFxuXHRIb3N0TGlzdGVuZXIsXG5cdFZpZXdDaGlsZFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG5pbXBvcnQgeyBJMThuIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvaTE4blwiO1xuXG4vKipcbiAqIEdldCBzdGFydGVkIHdpdGggaW1wb3J0aW5nIHRoZSBtb2R1bGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgU2VhcmNoTW9kdWxlIH0gZnJvbSAnY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhcic7XG4gKiBgYGBcbiAqXG4gKiBbU2VlIGRlbW9dKC4uLy4uLz9wYXRoPS9zdG9yeS9jb21wb25lbnRzLXNlYXJjaC0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtc2VhcmNoLCBpYm0tc2VhcmNoXCIsXG5cdHRlbXBsYXRlVXJsOiBcInNlYXJjaC5jb21wb25lbnQuaHRtbFwiLFxuXHRwcm92aWRlcnM6IFtcblx0XHR7XG5cdFx0XHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHRcdHVzZUV4aXN0aW5nOiBTZWFyY2gsXG5cdFx0XHRtdWx0aTogdHJ1ZVxuXHRcdH1cblx0XVxufSlcbmV4cG9ydCBjbGFzcyBTZWFyY2ggaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cdC8qKlxuXHQgKiBWYXJpYWJsZSB1c2VkIGZvciBjcmVhdGluZyB1bmlxdWUgaWRzIGZvciBzZWFyY2ggY29tcG9uZW50cy5cblx0ICovXG5cdHN0YXRpYyBzZWFyY2hDb3VudCA9IDA7XG5cblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1mb3JtLWl0ZW1cIikgZ2V0IGNvbnRhaW5lckNsYXNzKCkge1xuXHRcdHJldHVybiAhKHRoaXMudG9vbGJhciB8fCB0aGlzLmV4cGFuZGFibGUpO1xuXHR9XG5cblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS10ZXh0LWlucHV0LS1mbHVpZF9fc2tlbGV0b25cIikgZ2V0IGZsdWlkU2tlbGV0b25DbGFzcygpIHtcblx0XHRyZXR1cm4gdGhpcy5za2VsZXRvbiAmJiB0aGlzLmZsdWlkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBkZXByZWNhdGVkIHNpbmNlIHY1IC0gVXNlIGBjZHNMYXllcmAgZGlyZWN0aXZlIGluc3RlYWRcblx0ICogYGxpZ2h0YCBvciBgZGFya2Agc2VhcmNoIHRoZW1lLlxuXHQgKi9cblx0QElucHV0KCkgdGhlbWU6IFwibGlnaHRcIiB8IFwiZGFya1wiID0gXCJkYXJrXCI7XG5cblx0LyoqXG5cdCAqIFNpemUgb2YgdGhlIHNlYXJjaCBmaWVsZC5cblx0ICovXG5cdEBJbnB1dCgpIHNpemU6IFwic21cIiB8IFwibWRcIiB8IFwibGdcIiA9IFwibWRcIjtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBkaXNhYmxlZCBzZWFyY2ggaW5wdXQuXG5cdCAqL1xuXHRASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSB0b29sYmFyIHNlYXJjaCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSB0b29sYmFyID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIG1ha2UgdGhlIHNlYXJjaCBjb21wb25lbnQgZXhwYW5kYWJsZS5cblx0ICogYGV4cGFuZGFibGVgIHdvdWxkIG92ZXJyaWRlIGB0b29sYmFyYCBwcm9wZXJ0eSBiZWhhdmlvdXJzLlxuXHQgKi9cblx0QElucHV0KCkgZXhwYW5kYWJsZSA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBsb2FkaW5nIHNlYXJjaCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBza2VsZXRvbiA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byBleHBhbmQgdGhlIHRvb2xiYXIgc2VhcmNoIGNvbXBvbmVudC5cblx0ICovXG5cdEBJbnB1dCgpIGFjdGl2ZSA9IGZhbHNlO1xuXHQvKipcblx0ICogU3BlY2lmaWVzIHdoZXRoZXIgdGhlIHNlYXJjaCBjb21wb25lbnQgaXMgdXNlZCBpbiB0aGUgdGFibGUgdG9vbGJhci5cblx0ICovXG5cdEBJbnB1dCgpIHRhYmxlU2VhcmNoID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBuYW1lIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgbmFtZTogc3RyaW5nO1xuXHQvKipcblx0ICogVGhlIHVuaXF1ZSBpZCBmb3IgdGhlIHNlYXJjaCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBpZCA9IGBzZWFyY2gtJHtTZWFyY2guc2VhcmNoQ291bnR9YDtcblx0LyoqXG5cdCAqIFJlZmxlY3RzIHRoZSByZXF1aXJlZCBhdHRyaWJ1dGUgb2YgdGhlIGBpbnB1dGAgZWxlbWVudC5cblx0ICovXG5cdEBJbnB1dCgpIHJlcXVpcmVkOiBib29sZWFuO1xuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWUgYXR0cmlidXRlIG9uIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSB2YWx1ZSA9IFwiXCI7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBhdXRvY29tcGxldGUgYXR0cmlidXRlIG9uIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqIEZvciByZWZlcmVuY2U6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQXR0cmlidXRlcy9hdXRvY29tcGxldGUjVmFsdWVzXG5cdCAqL1xuXHRASW5wdXQoKSBhdXRvY29tcGxldGUgPSBcIm9uXCI7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0ZXh0IGluc2lkZSB0aGUgYGxhYmVsYCB0YWcuXG5cdCAqL1xuXHRASW5wdXQoKSBsYWJlbCA9IHRoaXMuaTE4bi5nZXQoKS5TRUFSQ0guTEFCRUw7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwbGFjZWhvbGRlciBhdHRyaWJ1dGUgb24gdGhlIGBpbnB1dGAgZWxlbWVudC5cblx0ICovXG5cdEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gdGhpcy5pMThuLmdldCgpLlNFQVJDSC5QTEFDRUhPTERFUjtcblx0LyoqXG5cdCAqIFVzZWQgdG8gc2V0IHRoZSBgdGl0bGVgIGF0dHJpYnV0ZSBvZiB0aGUgY2xlYXIgYnV0dG9uLlxuXHQgKi9cblx0QElucHV0KCkgY2xlYXJCdXR0b25UaXRsZSA9IHRoaXMuaTE4bi5nZXQoKS5TRUFSQ0guQ0xFQVJfQlVUVE9OO1xuXHQvKipcblx0ICogVGl0bGUgZm9yIHRoZSBzZWFyY2ggdHJpZ2dlclxuXHQgKi9cblx0QElucHV0KCkgc2VhcmNoVGl0bGUgPSBcIlwiO1xuXHQvKipcblx0ICogU2V0cyB0aGUgYXJpYSBsYWJlbCBvbiB0aGUgYGRpdmAgZWxlbWVudCB3aXRoIHRoZSBgc2VhcmNoYCByb2xlLlxuXHQgKi9cblx0QElucHV0KCkgYXJpYUxhYmVsOiBzdHJpbmc7XG5cdC8qKlxuXHQgKiBFeHBlcmltZW50YWw6IGVuYWJsZSBmbHVpZCBzdGF0ZVxuXHQgKi9cblx0QElucHV0KCkgZmx1aWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdmFsdWUgaXMgY2hhbmdlZC5cblx0ICovXG5cdEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXHRAT3V0cHV0KCkgb3BlbiA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblx0LyoqXG5cdCAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIGNsZWFyIGJ1dHRvbiBpcyBjbGlja2VkLlxuXHQgKi9cblx0QE91dHB1dCgpIGNsZWFyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXHQvKipcblx0ICogRW1pdHMgYW4gZXZlbnQgb24gZW50ZXIuXG5cdCAqL1xuXHRAT3V0cHV0KCkgc2VhcmNoID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cblx0QFZpZXdDaGlsZChcImlucHV0XCIpIGlucHV0UmVmOiBFbGVtZW50UmVmO1xuXG5cdC8qKlxuXHQgKiBTZXRzIGB0cnVlYCB3aGVuIGNvbXBvc2luZyB0ZXh0IHZpYSBJTUUuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgaXNDb21wb3NpbmcgPSBmYWxzZTtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgU2VhcmNoYC5cblx0ICogQHBhcmFtIGkxOG4gVGhlIGkxOG4gdHJhbnNsYXRpb25zLlxuXHQgKi9cblx0Y29uc3RydWN0b3IocHJvdGVjdGVkIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIHByb3RlY3RlZCBpMThuOiBJMThuKSB7XG5cdFx0U2VhcmNoLnNlYXJjaENvdW50Kys7XG5cdH1cblxuXHQvKipcblx0ICogVGhpcyBpcyB0aGUgaW5pdGlhbCB2YWx1ZSBzZXQgdG8gdGhlIGNvbXBvbmVudFxuXHQgKiBAcGFyYW0gdmFsdWUgVGhlIGlucHV0IHZhbHVlLlxuXHQgKi9cblx0cHVibGljIHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuXHRcdHRoaXMudmFsdWUgPSB2YWx1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGEgbWV0aG9kIGluIG9yZGVyIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KSB7XG5cdFx0dGhpcy5wcm9wYWdhdGVDaGFuZ2UgPSBmbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBjYWxsYmFjayB0byBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgY29udHJvbCBoYXMgYmVlbiB0b3VjaGVkLlxuXHQgKiBAcGFyYW0gZm4gQ2FsbGJhY2sgdG8gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIHNlYXJjaCBpbnB1dCBpcyB0b3VjaGVkLlxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpIHtcblx0XHR0aGlzLm9uVG91Y2hlZCA9IGZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIHNlYXJjaCBpbnB1dCBpcyBibHVycmVkLiBOZWVkZWQgdG8gcHJvcGVybHkgaW1wbGVtZW50IGBDb250cm9sVmFsdWVBY2Nlc3NvcmAuXG5cdCAqL1xuXHRvblRvdWNoZWQ6ICgpID0+IGFueSA9ICgpID0+IHt9O1xuXG5cdC8qKlxuXHQgKiBNZXRob2Qgc2V0IGluIGByZWdpc3Rlck9uQ2hhbmdlYCB0byBwcm9wYWdhdGUgY2hhbmdlcyBiYWNrIHRvIHRoZSBmb3JtLlxuXHQgKi9cblx0cHJvcGFnYXRlQ2hhbmdlID0gKF86IGFueSkgPT4ge307XG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIHRleHQgaXMgd3JpdHRlbiBpbiB0aGUgaW5wdXQuXG5cdCAqIEBwYXJhbSBzZWFyY2ggVGhlIGlucHV0IHRleHQuXG5cdCAqL1xuXHRvblNlYXJjaChzZWFyY2g6IHN0cmluZykge1xuXHRcdGlmICh0aGlzLmlzQ29tcG9zaW5nKSB7IC8vIGNoZWNrIGZvciBJTUUgdXNlXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMudmFsdWUgPSBzZWFyY2g7XG5cdFx0dGhpcy5kb1ZhbHVlQ2hhbmdlKCk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIG9uIGVudGVyLlxuXHQgKi9cblx0b25FbnRlcigpIHtcblx0XHR0aGlzLnNlYXJjaC5lbWl0KHRoaXMudmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIGNsZWFyIGJ1dHRvbiBpcyBjbGlja2VkLlxuXHQgKi9cblx0Y2xlYXJTZWFyY2goKTogdm9pZCB7XG5cdFx0dGhpcy52YWx1ZSA9IFwiXCI7XG5cdFx0dGhpcy5kb1ZhbHVlQ2hhbmdlKCk7XG5cdFx0dGhpcy5jbGVhci5lbWl0KCk7XG5cdH1cblxuXHRkb1ZhbHVlQ2hhbmdlKCkge1xuXHRcdHRoaXMucHJvcGFnYXRlQ2hhbmdlKHRoaXMudmFsdWUpO1xuXHRcdHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh0aGlzLnZhbHVlKTtcblx0fVxuXG5cdG9wZW5TZWFyY2goKSB7XG5cdFx0dGhpcy5hY3RpdmUgPSB0cnVlO1xuXHRcdHRoaXMub3Blbi5lbWl0KHRoaXMuYWN0aXZlKTtcblx0XHRzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5wdXRSZWYubmF0aXZlRWxlbWVudC5mb2N1cygpKTtcblx0fVxuXG5cdEBIb3N0TGlzdGVuZXIoXCJrZXlkb3duXCIsIFtcIiRldmVudFwiXSlcblx0a2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuXHRcdGlmICh0aGlzLnRvb2xiYXIgfHwgdGhpcy5leHBhbmRhYmxlKSB7XG5cdFx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkVzY2FwZVwiKSB7XG5cdFx0XHRcdGlmICh0aGlzLnZhbHVlID09PSBcIlwiKSB7XG5cdFx0XHRcdFx0dGhpcy5hY3RpdmUgPSBmYWxzZTtcblx0XHRcdFx0XHR0aGlzLm9wZW4uZW1pdCh0aGlzLmFjdGl2ZSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBcIkVudGVyXCIpIHtcblx0XHRcdFx0dGhpcy5vcGVuU2VhcmNoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJFc2NhcGVcIikge1xuXHRcdFx0aWYgKHRoaXMudmFsdWUgIT09IFwiXCIpIHtcblx0XHRcdFx0dGhpcy5jbGVhclNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdEBIb3N0TGlzdGVuZXIoXCJmb2N1c291dFwiLCBbXCIkZXZlbnRcIl0pXG5cdGZvY3VzT3V0KGV2ZW50KSB7XG5cdFx0dGhpcy5vblRvdWNoZWQoKTtcblx0XHRpZiAoKHRoaXMuZXhwYW5kYWJsZSB8fCB0aGlzLnRvb2xiYXIpICYmXG5cdFx0XHR0aGlzLmlucHV0UmVmICYmXG5cdFx0XHR0aGlzLmlucHV0UmVmLm5hdGl2ZUVsZW1lbnQudmFsdWUgPT09IFwiXCIgJiZcblx0XHRcdCEodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQpLmNvbnRhaW5zKGV2ZW50LnJlbGF0ZWRUYXJnZXQpKSB7XG5cdFx0XHR0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuXHRcdFx0dGhpcy5vcGVuLmVtaXQodGhpcy5hY3RpdmUpO1xuXHRcdH1cblx0fVxuXG5cdEBIb3N0TGlzdGVuZXIoXCJmb2N1c2luXCIsIFtcIiRldmVudFwiXSlcblx0Zm9jdXNJbihldmVudCkge1xuXHRcdHRoaXMub25Ub3VjaGVkKCk7XG5cdFx0Ly8gc2V0IGlucHV0IGZvY3VzIGlmIHNlYXJjaCBpY29uIGdldCBmb2N1cyBmcm9tIHRhYiBrZXkgcHJlc3MgZXZlbnQuXG5cdFx0aWYgKCh0aGlzLmV4cGFuZGFibGUgfHwgdGhpcy50b29sYmFyKSAmJlxuXHRcdFx0dGhpcy5pbnB1dFJlZiAmJiAhZXZlbnQucmVsYXRlZFRhcmdldCAmJlxuXHRcdFx0ISh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudCkuY29udGFpbnMoZXZlbnQucmVsYXRlZFRhcmdldCkgKSB7XG5cdFx0XHR0aGlzLm9wZW5TZWFyY2goKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gdXNpbmcgSU1FIGNvbXBvc2l0aW9uLlxuXHQgKi9cblx0QEhvc3RMaXN0ZW5lcihcImNvbXBvc2l0aW9uc3RhcnRcIiwgW1wiJGV2ZW50XCJdKVxuXHRjb21wb3NpdGlvblN0YXJ0KGV2ZW50KSB7XG5cdFx0dGhpcy5pc0NvbXBvc2luZyA9IHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gSU1FIGNvbXBvc2l0aW9uIGZpbmlzaGVzLlxuXHQgKi9cblx0QEhvc3RMaXN0ZW5lcihcImNvbXBvc2l0aW9uZW5kXCIsIFtcIiRldmVudFwiXSlcblx0Y29tcG9zaXRpb25FbmQoZXZlbnQpIHtcblx0XHR0aGlzLmlzQ29tcG9zaW5nID0gZmFsc2U7XG5cdFx0dGhpcy5vblNlYXJjaCh0aGlzLnZhbHVlICsgZXZlbnQuZGF0YSk7XG5cdH1cbn1cbiIsIjxkaXZcblx0Y2xhc3M9XCJjZHMtLXNlYXJjaFwiXG5cdFtuZ0NsYXNzXT1cIntcblx0XHQnY2RzLS1zZWFyY2gtLXNtJzogc2l6ZSA9PT0gJ3NtJyxcblx0XHQnY2RzLS1zZWFyY2gtLW1kJzogc2l6ZSA9PT0gJ21kJyxcblx0XHQnY2RzLS1zZWFyY2gtLWxnJzogc2l6ZSA9PT0gJ2xnJyxcblx0XHQnY2RzLS1zZWFyY2gtLWxpZ2h0JzogdGhlbWUgPT09ICdsaWdodCcsXG5cdFx0J2Nkcy0tc2tlbGV0b24nOiBza2VsZXRvbiAmJiAhZmx1aWQsXG5cdFx0J2Nkcy0tc2VhcmNoLS1leHBhbmRhYmxlJzogZXhwYW5kYWJsZSAmJiAhdGFibGVTZWFyY2gsXG5cdFx0J2Nkcy0tc2VhcmNoLS1leHBhbmRlZCc6IGV4cGFuZGFibGUgJiYgIXRhYmxlU2VhcmNoICYmIGFjdGl2ZSxcblx0XHQnY2RzLS10b29sYmFyLXNlYXJjaCc6IHRvb2xiYXIgJiYgIWV4cGFuZGFibGUsXG5cdFx0J2Nkcy0tdG9vbGJhci1zZWFyY2gtLWFjdGl2ZSc6IHRvb2xiYXIgJiYgIWV4cGFuZGFibGUgJiYgYWN0aXZlLFxuXHRcdCdjZHMtLXRvb2xiYXItc2VhcmNoLWNvbnRhaW5lci1wZXJzaXN0ZW50JzogdGFibGVTZWFyY2ggJiYgIWV4cGFuZGFibGUsXG5cdFx0J2Nkcy0tdG9vbGJhci1zZWFyY2gtY29udGFpbmVyLWV4cGFuZGFibGUnOiB0YWJsZVNlYXJjaCAmJiBleHBhbmRhYmxlLFxuXHRcdCdjZHMtLXRvb2xiYXItc2VhcmNoLWNvbnRhaW5lci1hY3RpdmUnOiB0YWJsZVNlYXJjaCAmJiBleHBhbmRhYmxlICYmIGFjdGl2ZSxcblx0XHQnY2RzLS1zZWFyY2gtLWZsdWlkJzogZmx1aWQsXG5cdFx0J2Nkcy0tc2VhcmNoLS1kaXNhYmxlZCc6IGRpc2FibGVkXG5cdH1cIlxuXHRyb2xlPVwic2VhcmNoXCJcblx0W2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuXHQoY2xpY2spPVwib3BlblNlYXJjaCgpXCI+XG5cdDxsYWJlbFxuXHRcdGNsYXNzPVwiY2RzLS1sYWJlbFwiXG5cdFx0W2Zvcl09XCJpZFwiXG5cdFx0W25nQ2xhc3NdPVwieyAnY2RzLS1za2VsZXRvbic6IHNrZWxldG9uICYmIGZsdWlkIH1cIj5cblx0XHR7eyAhc2tlbGV0b24gPyBsYWJlbCA6ICcnfX1cblx0PC9sYWJlbD5cblxuXHQ8ZGl2ICpuZ0lmPVwic2tlbGV0b247IGVsc2UgZW5hYmxlSW5wdXRcIiBjbGFzcz1cImNkcy0tdGV4dC1pbnB1dCBjZHMtLXNrZWxldG9uXCI+PC9kaXY+XG5cdDxuZy10ZW1wbGF0ZSAjZW5hYmxlSW5wdXQ+XG5cdFx0PGlucHV0XG5cdFx0XHQjaW5wdXRcblx0XHRcdGNsYXNzPVwiY2RzLS1zZWFyY2gtaW5wdXRcIlxuXHRcdFx0W3R5cGVdPVwidGFibGVTZWFyY2ggfHwgIXRvb2xiYXIgPyAndGV4dCcgOiAnc2VhcmNoJ1wiXG5cdFx0XHRbaWRdPVwiaWRcIlxuXHRcdFx0W3ZhbHVlXT1cInZhbHVlXCJcblx0XHRcdFthdXRvY29tcGxldGVdPVwiYXV0b2NvbXBsZXRlXCJcblx0XHRcdFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXG5cdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0W3JlcXVpcmVkXT1cInJlcXVpcmVkXCJcblx0XHRcdChpbnB1dCk9XCJvblNlYXJjaCgkZXZlbnQudGFyZ2V0LnZhbHVlKVwiXG5cdFx0XHQoa2V5dXAuZW50ZXIpPVwib25FbnRlcigpXCIvPlxuXHRcdDxidXR0b25cblx0XHRcdCpuZ0lmPVwiIXRhYmxlU2VhcmNoICYmIHRvb2xiYXJcIlxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRvb2xiYXItc2VhcmNoX19idG5cIlxuXHRcdFx0KGNsaWNrKT1cIm9wZW5TZWFyY2goKVwiXG5cdFx0XHRhcmlhLWxhYmVsPVwiT3BlbiBzZWFyY2hcIj5cblx0XHRcdDxzdmcgY2RzSWNvbj1cInNlYXJjaFwiIHNpemU9XCIxNlwiIGNsYXNzPVwiY2RzLS1zZWFyY2gtbWFnbmlmaWVyLWljb25cIj48L3N2Zz5cblx0XHQ8L2J1dHRvbj5cblx0XHQ8c3ZnXG5cdFx0XHRjZHNJY29uPVwic2VhcmNoXCJcblx0XHRcdCpuZ0lmPVwidGFibGVTZWFyY2ggfHwgIXRvb2xiYXJcIlxuXHRcdFx0Y2xhc3M9XCJjZHMtLXNlYXJjaC1tYWduaWZpZXItaWNvblwiXG5cdFx0XHRzaXplPVwiMTZcIj5cblx0XHQ8L3N2Zz5cblx0PC9uZy10ZW1wbGF0ZT5cblxuXHQ8YnV0dG9uXG5cdFx0Km5nSWY9XCJ0YWJsZVNlYXJjaCB8fCAhdG9vbGJhclwiXG5cdFx0Y2xhc3M9XCJjZHMtLXNlYXJjaC1jbG9zZVwiXG5cdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0J2Nkcy0tc2VhcmNoLWNsb3NlLS1oaWRkZW4nOiAhdmFsdWUgfHwgdmFsdWUubGVuZ3RoID09PSAwXG5cdFx0fVwiXG5cdFx0W3RpdGxlXT1cImNsZWFyQnV0dG9uVGl0bGVcIlxuXHRcdChjbGljayk9XCJjbGVhclNlYXJjaCgpXCI+XG5cdFx0PHNwYW4gY2xhc3M9XCJjZHMtLXZpc3VhbGx5LWhpZGRlblwiPnt7IGNsZWFyQnV0dG9uVGl0bGUgfX08L3NwYW4+XG5cdFx0PHN2ZyBjZHNJY29uPVwiY2xvc2VcIiBzaXplPVwiMTZcIj48L3N2Zz5cblx0PC9idXR0b24+XG48L2Rpdj5cbiJdfQ==