carbon-components-angular
Version:
Next generation components
321 lines • 36.5 kB
JavaScript
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==