UNPKG

carbon-components-angular

Version:
474 lines (472 loc) 36.4 kB
import { Component, Input, Output, HostListener, EventEmitter, TemplateRef, ViewChild } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "carbon-components-angular/icon"; /** * `cds-select` provides a styled `select` component. Get started with importing the module: * * ```typescript * import { SelectModule } from 'carbon-components-angular'; * ``` * * ```html * <cds-select [(ngModel)]="model"> * <option value="default" disabled selected hidden>Choose an option</option> * <option value="option1">Option 1</option> * <option value="option2">Option 2</option> * <option value="option3">Option 3</option> * </cds-select> * ``` * * [See demo](../../?path=/story/components-select--basic) */ export class Select { constructor() { /** * `inline` or `default` select displays */ this.display = "default"; /** * Set to `true` to show a warning (contents set by warningText) */ this.warn = false; /** * Sets the unique ID. Defaults to `select-${total count of selects instantiated}` */ this.id = `select-${Select.selectCount++}`; /** * Number input field render size */ this.size = "md"; /** * Set to true to disable component. */ this.disabled = false; /** * Set to true for a loading select. */ this.skeleton = false; /** * Set to `true` for an invalid select component. */ this.invalid = false; /** * Set to `true` for readonly state. */ this.readonly = false; /** * @deprecated since v5 - Use `cdsLayer` directive instead * `light` or `dark` select theme */ this.theme = "dark"; /** * Experimental: enable fluid state */ this.fluid = false; this.valueChange = new EventEmitter(); this.focused = false; /** * placeholder declarations. Replaced by the functions provided to `registerOnChange` and `registerOnTouched` */ this.onChangeHandler = (_) => { }; this.onTouchedHandler = () => { }; } set value(v) { this._value = v; if (this.select) { this.select.nativeElement.value = this._value; } } get value() { return this._value; } ngAfterViewInit() { if (this.value !== undefined && this.value !== null && this.select && this.select.nativeElement.value !== this.value) { this.select.nativeElement.value = this.value; } } /** * Receives a value from the model. */ writeValue(obj) { this.value = obj; } /** * Registers a listener that notifies the model when the control updates */ registerOnChange(fn) { this.onChangeHandler = fn; } /** * Registers a listener that notifies the model when the control is blurred */ registerOnTouched(fn) { this.onTouchedHandler = fn; } /** * Sets the disabled state through the model */ setDisabledState(isDisabled) { this.disabled = isDisabled; } /** * Handles the change event from the `select`. * Sends events to the change handler and emits a `selected` event. */ onChange(event) { this.value = event.target.value; this.onChangeHandler(event.target.value); this.valueChange.emit(event.target.value); } /** * Listens for the host blurring, and notifies the model */ focusOut() { this.onTouchedHandler(); } isTemplate(value) { return value instanceof TemplateRef; } onMouseDown(event) { /** * This prevents the select from opening with mouse */ if (this.readonly) { event.preventDefault(); event.target.focus(); } } onKeyDown(event) { const selectAccessKeys = ["ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight", " "]; /** * This prevents the select from opening for the above keys */ if (this.readonly && selectAccessKeys.includes(event.key)) { event.preventDefault(); } } handleFocus(event) { this.focused = event.type === "focus"; } } /** * Tracks the total number of selects instantiated. Used to generate unique IDs */ Select.selectCount = 0; Select.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component }); Select.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Select, selector: "cds-select, ibm-select", inputs: { value: "value", display: "display", label: "label", helperText: "helperText", invalidText: "invalidText", warn: "warn", warnText: "warnText", id: "id", size: "size", disabled: "disabled", skeleton: "skeleton", invalid: "invalid", readonly: "readonly", theme: "theme", ariaLabel: "ariaLabel", fluid: "fluid" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "focusout": "focusOut()" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Select, multi: true } ], viewQueries: [{ propertyName: "select", first: true, predicate: ["select"], descendants: true }], ngImport: i0, template: ` <div [ngClass]="{ 'cds--form-item': !skeleton, 'cds--select--fluid': fluid && !skeleton }"> <ng-container *ngIf="skeleton && !fluid"> <div *ngIf="label" class="cds--label cds--skeleton"></div> <div class="cds--select cds--skeleton"></div> </ng-container> <ng-container *ngIf="skeleton && fluid"> <div class="cds--list-box__wrapper--fluid"> <div class="cds--list-box cds--skeleton"> <div class="cds--list-box__label"></div> <div class="cds--list-box__field"></div> </div> </div> </ng-container> <div *ngIf="!skeleton" class="cds--select" [ngClass]="{ 'cds--select--inline': display === 'inline', 'cds--select--light': theme === 'light', 'cds--select--invalid': invalid, 'cds--select--warning': warn, 'cds--select--disabled': disabled, 'cds--select--readonly': readonly, 'cds--select--fluid--invalid': fluid && invalid, 'cds--select--fluid--focus': fluid && focused }"> <label *ngIf="label" [for]="id" class="cds--label" [ngClass]="{'cds--label--disabled': disabled}"> <ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container> <ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template> </label> <div *ngIf="display === 'inline'; else noInline" class="cds--select-input--inline__wrapper"> <ng-container *ngTemplateOutlet="noInline"></ng-container> </div> <div *ngIf="helperText && !invalid && !warn && !skeleton && !fluid" class="cds--form__helper-text" [ngClass]="{ 'cds--form__helper-text--disabled': disabled }"> <ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container> <ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template> </div> </div> </div> <!-- select element: dynamically projected based on 'display' variant --> <ng-template #noInline> <div class="cds--select-input__wrapper" [attr.data-invalid]="(invalid ? true : null)"> <select #select [attr.id]="id" [attr.aria-label]="ariaLabel" [disabled]="disabled" (change)="onChange($event)" [attr.aria-invalid]="invalid ? 'true' : null" [attr.aria-readonly]="readonly ? 'true' : null" class="cds--select-input" [ngClass]="{ 'cds--select-input--sm': size === 'sm', 'cds--select-input--md': size === 'md', 'cds--select-input--lg': size === 'lg' }" (mousedown)="onMouseDown($event)" (keydown)="onKeyDown($event)" (focus)="fluid ? handleFocus($event) : null" (blur)="fluid ? handleFocus($event) : null"> <ng-content></ng-content> </select> <svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;" xmlns="http://www.w3.org/2000/svg" class="cds--select__arrow" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M8 11L3 6 3.7 5.3 8 9.6 12.3 5.3 13 6z"></path> </svg> <svg *ngIf="invalid" cdsIcon="warning--filled" size="16" class="cds--select__invalid-icon"> </svg> <svg *ngIf="!invalid && warn" cdsIcon="warning--alt--filled" size="16" class="cds--select__invalid-icon cds--select__invalid-icon--warning"> </svg> <ng-container *ngIf="fluid"> <hr class="cds--select__divider" /> <div *ngIf="invalid && invalidText" role="alert" class="cds--form-requirement" aria-live="polite"> <ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> <div *ngIf="!invalid && warn" class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </div> <ng-container *ngIf="!fluid"> <div *ngIf="invalid && invalidText" role="alert" class="cds--form-requirement" aria-live="polite"> <ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> <div *ngIf="!invalid && warn" class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </ng-template> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.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: Select, decorators: [{ type: Component, args: [{ selector: "cds-select, ibm-select", template: ` <div [ngClass]="{ 'cds--form-item': !skeleton, 'cds--select--fluid': fluid && !skeleton }"> <ng-container *ngIf="skeleton && !fluid"> <div *ngIf="label" class="cds--label cds--skeleton"></div> <div class="cds--select cds--skeleton"></div> </ng-container> <ng-container *ngIf="skeleton && fluid"> <div class="cds--list-box__wrapper--fluid"> <div class="cds--list-box cds--skeleton"> <div class="cds--list-box__label"></div> <div class="cds--list-box__field"></div> </div> </div> </ng-container> <div *ngIf="!skeleton" class="cds--select" [ngClass]="{ 'cds--select--inline': display === 'inline', 'cds--select--light': theme === 'light', 'cds--select--invalid': invalid, 'cds--select--warning': warn, 'cds--select--disabled': disabled, 'cds--select--readonly': readonly, 'cds--select--fluid--invalid': fluid && invalid, 'cds--select--fluid--focus': fluid && focused }"> <label *ngIf="label" [for]="id" class="cds--label" [ngClass]="{'cds--label--disabled': disabled}"> <ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container> <ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template> </label> <div *ngIf="display === 'inline'; else noInline" class="cds--select-input--inline__wrapper"> <ng-container *ngTemplateOutlet="noInline"></ng-container> </div> <div *ngIf="helperText && !invalid && !warn && !skeleton && !fluid" class="cds--form__helper-text" [ngClass]="{ 'cds--form__helper-text--disabled': disabled }"> <ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container> <ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template> </div> </div> </div> <!-- select element: dynamically projected based on 'display' variant --> <ng-template #noInline> <div class="cds--select-input__wrapper" [attr.data-invalid]="(invalid ? true : null)"> <select #select [attr.id]="id" [attr.aria-label]="ariaLabel" [disabled]="disabled" (change)="onChange($event)" [attr.aria-invalid]="invalid ? 'true' : null" [attr.aria-readonly]="readonly ? 'true' : null" class="cds--select-input" [ngClass]="{ 'cds--select-input--sm': size === 'sm', 'cds--select-input--md': size === 'md', 'cds--select-input--lg': size === 'lg' }" (mousedown)="onMouseDown($event)" (keydown)="onKeyDown($event)" (focus)="fluid ? handleFocus($event) : null" (blur)="fluid ? handleFocus($event) : null"> <ng-content></ng-content> </select> <svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform;" xmlns="http://www.w3.org/2000/svg" class="cds--select__arrow" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M8 11L3 6 3.7 5.3 8 9.6 12.3 5.3 13 6z"></path> </svg> <svg *ngIf="invalid" cdsIcon="warning--filled" size="16" class="cds--select__invalid-icon"> </svg> <svg *ngIf="!invalid && warn" cdsIcon="warning--alt--filled" size="16" class="cds--select__invalid-icon cds--select__invalid-icon--warning"> </svg> <ng-container *ngIf="fluid"> <hr class="cds--select__divider" /> <div *ngIf="invalid && invalidText" role="alert" class="cds--form-requirement" aria-live="polite"> <ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> <div *ngIf="!invalid && warn" class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </div> <ng-container *ngIf="!fluid"> <div *ngIf="invalid && invalidText" role="alert" class="cds--form-requirement" aria-live="polite"> <ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> <div *ngIf="!invalid && warn" class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </ng-template> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Select, multi: true } ] }] }], propDecorators: { value: [{ type: Input }], display: [{ type: Input }], label: [{ type: Input }], helperText: [{ type: Input }], invalidText: [{ type: Input }], warn: [{ type: Input }], warnText: [{ type: Input }], id: [{ type: Input }], size: [{ type: Input }], disabled: [{ type: Input }], skeleton: [{ type: Input }], invalid: [{ type: Input }], readonly: [{ type: Input }], theme: [{ type: Input }], ariaLabel: [{ type: Input }], fluid: [{ type: Input }], valueChange: [{ type: Output }], select: [{ type: ViewChild, args: ["select"] }], focusOut: [{ type: HostListener, args: ["focusout"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZWxlY3Qvc2VsZWN0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUNaLFlBQVksRUFDWixXQUFXLEVBQ1gsU0FBUyxFQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7OztBQUV6RTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUEwSUgsTUFBTSxPQUFPLE1BQU07SUF6SW5CO1FBMEpDOztXQUVHO1FBQ00sWUFBTyxHQUF5QixTQUFTLENBQUM7UUFhbkQ7O1lBRUk7UUFDSyxTQUFJLEdBQUcsS0FBSyxDQUFDO1FBS3RCOztXQUVHO1FBQ00sT0FBRSxHQUFHLFVBQVUsTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7UUFDL0M7O1dBRUc7UUFDTSxTQUFJLEdBQXVCLElBQUksQ0FBQztRQUN6Qzs7V0FFRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDMUI7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sWUFBTyxHQUFHLEtBQUssQ0FBQztRQUN6Qjs7V0FFRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFMUI7OztXQUdHO1FBQ00sVUFBSyxHQUFxQixNQUFNLENBQUM7UUFHMUM7O1dBRUc7UUFDTSxVQUFLLEdBQUcsS0FBSyxDQUFDO1FBRWIsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBSTNDLFlBQU8sR0FBRyxLQUFLLENBQUM7UUF5RmhCOztXQUVHO1FBQ08sb0JBQWUsR0FBRyxDQUFDLENBQU0sRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2xDLHFCQUFnQixHQUFHLEdBQUcsRUFBRSxHQUFHLENB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dCI6WyJpbXBvcnQge1xuXHRBZnRlclZpZXdJbml0LFxuXHRDb21wb25lbnQsXG5cdEVsZW1lbnRSZWYsXG5cdElucHV0LFxuXHRPdXRwdXQsXG5cdEhvc3RMaXN0ZW5lcixcblx0RXZlbnRFbWl0dGVyLFxuXHRUZW1wbGF0ZVJlZixcblx0Vmlld0NoaWxkXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcblxuLyoqXG4gKiBgY2RzLXNlbGVjdGAgcHJvdmlkZXMgYSBzdHlsZWQgYHNlbGVjdGAgY29tcG9uZW50LiBHZXQgc3RhcnRlZCB3aXRoIGltcG9ydGluZyB0aGUgbW9kdWxlOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFNlbGVjdE1vZHVsZSB9IGZyb20gJ2NhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXInO1xuICogYGBgXG4gKlxuICogYGBgaHRtbFxuICogPGNkcy1zZWxlY3QgWyhuZ01vZGVsKV09XCJtb2RlbFwiPlxuICogXHQ8b3B0aW9uIHZhbHVlPVwiZGVmYXVsdFwiIGRpc2FibGVkIHNlbGVjdGVkIGhpZGRlbj5DaG9vc2UgYW4gb3B0aW9uPC9vcHRpb24+XG4gKiBcdDxvcHRpb24gdmFsdWU9XCJvcHRpb24xXCI+T3B0aW9uIDE8L29wdGlvbj5cbiAqXHQ8b3B0aW9uIHZhbHVlPVwib3B0aW9uMlwiPk9wdGlvbiAyPC9vcHRpb24+XG4gKiBcdDxvcHRpb24gdmFsdWU9XCJvcHRpb24zXCI+T3B0aW9uIDM8L29wdGlvbj5cbiAqIDwvY2RzLXNlbGVjdD5cbiAqXHRgYGBcbiAqXG4gKiBbU2VlIGRlbW9dKC4uLy4uLz9wYXRoPS9zdG9yeS9jb21wb25lbnRzLXNlbGVjdC0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtc2VsZWN0LCBpYm0tc2VsZWN0XCIsXG5cdHRlbXBsYXRlOiBgXG5cdFx0PGRpdlxuXHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHQnY2RzLS1mb3JtLWl0ZW0nOiAhc2tlbGV0b24sXG5cdFx0XHRcdCdjZHMtLXNlbGVjdC0tZmx1aWQnOiBmbHVpZCAmJiAhc2tlbGV0b25cblx0XHRcdH1cIj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCJza2VsZXRvbiAmJiAhZmx1aWRcIj5cblx0XHRcdFx0PGRpdiAqbmdJZj1cImxhYmVsXCIgY2xhc3M9XCJjZHMtLWxhYmVsIGNkcy0tc2tlbGV0b25cIj48L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tc2VsZWN0IGNkcy0tc2tlbGV0b25cIj48L2Rpdj5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cInNrZWxldG9uICYmIGZsdWlkXCI+XG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWxpc3QtYm94X193cmFwcGVyLS1mbHVpZFwiPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWxpc3QtYm94IGNkcy0tc2tlbGV0b25cIj5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWxpc3QtYm94X19sYWJlbFwiPjwvZGl2PlxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tbGlzdC1ib3hfX2ZpZWxkXCI+PC9kaXY+XG5cdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8ZGl2XG5cdFx0XHRcdCpuZ0lmPVwiIXNrZWxldG9uXCJcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLXNlbGVjdFwiXG5cdFx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0XHQnY2RzLS1zZWxlY3QtLWlubGluZSc6IGRpc3BsYXkgPT09ICdpbmxpbmUnLFxuXHRcdFx0XHRcdCdjZHMtLXNlbGVjdC0tbGlnaHQnOiB0aGVtZSA9PT0gJ2xpZ2h0Jyxcblx0XHRcdFx0XHQnY2RzLS1zZWxlY3QtLWludmFsaWQnOiBpbnZhbGlkLFxuXHRcdFx0XHRcdCdjZHMtLXNlbGVjdC0td2FybmluZyc6IHdhcm4sXG5cdFx0XHRcdFx0J2Nkcy0tc2VsZWN0LS1kaXNhYmxlZCc6IGRpc2FibGVkLFxuXHRcdFx0XHRcdCdjZHMtLXNlbGVjdC0tcmVhZG9ubHknOiByZWFkb25seSxcblx0XHRcdFx0XHQnY2RzLS1zZWxlY3QtLWZsdWlkLS1pbnZhbGlkJzogZmx1aWQgJiYgaW52YWxpZCxcblx0XHRcdFx0XHQnY2RzLS1zZWxlY3QtLWZsdWlkLS1mb2N1cyc6IGZsdWlkICYmIGZvY3VzZWRcblx0XHRcdFx0fVwiPlxuXHRcdFx0XHQ8bGFiZWxcblx0XHRcdFx0XHQqbmdJZj1cImxhYmVsXCJcblx0XHRcdFx0XHRbZm9yXT1cImlkXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tbGFiZWxcIlxuXHRcdFx0XHRcdFtuZ0NsYXNzXT1cInsnY2RzLS1sYWJlbC0tZGlzYWJsZWQnOiBkaXNhYmxlZH1cIj5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUobGFiZWwpXCI+e3tsYWJlbH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShsYWJlbClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJsYWJlbFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdDwvbGFiZWw+XG5cdFx0XHRcdDxkaXYgKm5nSWY9XCJkaXNwbGF5ID09PSAnaW5saW5lJzsgZWxzZSBub0lubGluZVwiIGNsYXNzPVwiY2RzLS1zZWxlY3QtaW5wdXQtLWlubGluZV9fd3JhcHBlclwiPlxuXHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJub0lubGluZVwiPjwvbmctY29udGFpbmVyPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdCpuZ0lmPVwiaGVscGVyVGV4dCAmJiAhaW52YWxpZCAmJiAhd2FybiAmJiAhc2tlbGV0b24gJiYgIWZsdWlkXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tZm9ybV9faGVscGVyLXRleHRcIlxuXHRcdFx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0XHRcdCdjZHMtLWZvcm1fX2hlbHBlci10ZXh0LS1kaXNhYmxlZCc6IGRpc2FibGVkXG5cdFx0XHRcdFx0fVwiPlxuXHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShoZWxwZXJUZXh0KVwiPnt7aGVscGVyVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShoZWxwZXJUZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImhlbHBlclRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdDwvZGl2PlxuXG5cdFx0PCEtLSBzZWxlY3QgZWxlbWVudDogZHluYW1pY2FsbHkgcHJvamVjdGVkIGJhc2VkIG9uICdkaXNwbGF5JyB2YXJpYW50IC0tPlxuXHRcdDxuZy10ZW1wbGF0ZSAjbm9JbmxpbmU+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1zZWxlY3QtaW5wdXRfX3dyYXBwZXJcIiBbYXR0ci5kYXRhLWludmFsaWRdPVwiKGludmFsaWQgPyB0cnVlIDogbnVsbClcIj5cblx0XHRcdFx0PHNlbGVjdFxuXHRcdFx0XHRcdCNzZWxlY3Rcblx0XHRcdFx0XHRbYXR0ci5pZF09XCJpZFwiXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuXHRcdFx0XHRcdFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG5cdFx0XHRcdFx0KGNoYW5nZSk9XCJvbkNoYW5nZSgkZXZlbnQpXCJcblx0XHRcdFx0XHRbYXR0ci5hcmlhLWludmFsaWRdPVwiaW52YWxpZCA/ICd0cnVlJyA6IG51bGxcIlxuXHRcdFx0XHRcdFthdHRyLmFyaWEtcmVhZG9ubHldPVwicmVhZG9ubHkgPyAndHJ1ZScgOiBudWxsXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0LWlucHV0XCJcblx0XHRcdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdFx0XHQnY2RzLS1zZWxlY3QtaW5wdXQtLXNtJzogc2l6ZSA9PT0gJ3NtJyxcblx0XHRcdFx0XHRcdCdjZHMtLXNlbGVjdC1pbnB1dC0tbWQnOiBzaXplID09PSAnbWQnLFxuXHRcdFx0XHRcdFx0J2Nkcy0tc2VsZWN0LWlucHV0LS1sZyc6IHNpemUgPT09ICdsZydcblx0XHRcdFx0XHR9XCJcblx0XHRcdFx0XHQobW91c2Vkb3duKT1cIm9uTW91c2VEb3duKCRldmVudClcIlxuXHRcdFx0XHRcdChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcblx0XHRcdFx0XHQoZm9jdXMpPVwiZmx1aWQgPyBoYW5kbGVGb2N1cygkZXZlbnQpIDogbnVsbFwiXG5cdFx0XHRcdFx0KGJsdXIpPVwiZmx1aWQgPyBoYW5kbGVGb2N1cygkZXZlbnQpIDogbnVsbFwiPlxuXHRcdFx0XHRcdDxuZy1jb250ZW50PjwvbmctY29udGVudD5cblx0XHRcdFx0PC9zZWxlY3Q+XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRmb2N1c2FibGU9XCJmYWxzZVwiXG5cdFx0XHRcdFx0cHJlc2VydmVBc3BlY3RSYXRpbz1cInhNaWRZTWlkIG1lZXRcIlxuXHRcdFx0XHRcdHN0eWxlPVwid2lsbC1jaGFuZ2U6IHRyYW5zZm9ybTtcIlxuXHRcdFx0XHRcdHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuXHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1zZWxlY3RfX2Fycm93XCJcblx0XHRcdFx0XHR3aWR0aD1cIjE2XCJcblx0XHRcdFx0XHRoZWlnaHQ9XCIxNlwiXG5cdFx0XHRcdFx0dmlld0JveD1cIjAgMCAxNiAxNlwiXG5cdFx0XHRcdFx0YXJpYS1oaWRkZW49XCJ0cnVlXCI+XG5cdFx0XHRcdFx0PHBhdGggZD1cIk04IDExTDMgNiAzLjcgNS4zIDggOS42IDEyLjMgNS4zIDEzIDZ6XCI+PC9wYXRoPlxuXHRcdFx0XHQ8L3N2Zz5cblx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdCpuZ0lmPVwiaW52YWxpZFwiXG5cdFx0XHRcdFx0Y2RzSWNvbj1cIndhcm5pbmctLWZpbGxlZFwiXG5cdFx0XHRcdFx0c2l6ZT1cIjE2XCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0X19pbnZhbGlkLWljb25cIj5cblx0XHRcdFx0PC9zdmc+XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHQqbmdJZj1cIiFpbnZhbGlkICYmIHdhcm5cIlxuXHRcdFx0XHRcdGNkc0ljb249XCJ3YXJuaW5nLS1hbHQtLWZpbGxlZFwiXG5cdFx0XHRcdFx0c2l6ZT1cIjE2XCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tc2VsZWN0X19pbnZhbGlkLWljb24gY2RzLS1zZWxlY3RfX2ludmFsaWQtaWNvbi0td2FybmluZ1wiPlxuXHRcdFx0XHQ8L3N2Zz5cblx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cImZsdWlkXCI+XG5cdFx0XHRcdFx0PGhyIGNsYXNzPVwiY2RzLS1zZWxlY3RfX2RpdmlkZXJcIiAvPlxuXHRcdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRcdCpuZ0lmPVwiaW52YWxpZCAmJiBpbnZhbGlkVGV4dFwiIHJvbGU9XCJhbGVydFwiIGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG5cdFx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUoaW52YWxpZFRleHQpXCI+e3tpbnZhbGlkVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKGludmFsaWRUZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImludmFsaWRUZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHQ8ZGl2ICpuZ0lmPVwiIWludmFsaWQgJiYgd2FyblwiIGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUod2FyblRleHQpXCI+e3t3YXJuVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKHdhcm5UZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIndhcm5UZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhZmx1aWRcIj5cblx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdCpuZ0lmPVwiaW52YWxpZCAmJiBpbnZhbGlkVGV4dFwiIHJvbGU9XCJhbGVydFwiIGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG5cdFx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKGludmFsaWRUZXh0KVwiPnt7aW52YWxpZFRleHR9fTwvbmctY29udGFpbmVyPlxuXHRcdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaW52YWxpZFRleHQpXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaW52YWxpZFRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PGRpdiAqbmdJZj1cIiFpbnZhbGlkICYmIHdhcm5cIiBjbGFzcz1cImNkcy0tZm9ybS1yZXF1aXJlbWVudFwiPlxuXHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZSh3YXJuVGV4dClcIj57e3dhcm5UZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKHdhcm5UZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIndhcm5UZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRgLFxuXHRwcm92aWRlcnM6IFtcblx0XHR7XG5cdFx0XHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHRcdHVzZUV4aXN0aW5nOiBTZWxlY3QsXG5cdFx0XHRtdWx0aTogdHJ1ZVxuXHRcdH1cblx0XVxufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3QgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgQWZ0ZXJWaWV3SW5pdCB7XG5cdEBJbnB1dCgpIHNldCB2YWx1ZSh2KSB7XG5cdFx0dGhpcy5fdmFsdWUgPSB2O1xuXHRcdGlmICh0aGlzLnNlbGVjdCkge1xuXHRcdFx0dGhpcy5zZWxlY3QubmF0aXZlRWxlbWVudC52YWx1ZSA9IHRoaXMuX3ZhbHVlO1xuXHRcdH1cblx0fVxuXG5cdGdldCB2YWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdmFsdWU7XG5cdH1cblxuXHQvKipcblx0ICogVHJhY2tzIHRoZSB0b3RhbCBudW1iZXIgb2Ygc2VsZWN0cyBpbnN0YW50aWF0ZWQuIFVzZWQgdG8gZ2VuZXJhdGUgdW5pcXVlIElEc1xuXHQgKi9cblx0c3RhdGljIHNlbGVjdENvdW50ID0gMDtcblxuXHQvKipcblx0ICogYGlubGluZWAgb3IgYGRlZmF1bHRgIHNlbGVjdCBkaXNwbGF5c1xuXHQgKi9cblx0QElucHV0KCkgZGlzcGxheTogXCJpbmxpbmVcIiB8IFwiZGVmYXVsdFwiID0gXCJkZWZhdWx0XCI7XG5cdC8qKlxuXHQgKiBMYWJlbCBmb3IgdGhlIHNlbGVjdC4gQXBwZWFycyBhYm92ZSB0aGUgaW5wdXQuXG5cdCAqL1xuXHRASW5wdXQoKSBsYWJlbDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55Pjtcblx0LyoqXG5cdCAqIE9wdGlvbmFsIGhlbHBlciB0ZXh0IHRoYXQgYXBwZWFycyB1bmRlciB0aGUgbGFiZWwuXG5cdCAqL1xuXHRASW5wdXQoKSBoZWxwZXJUZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0cyB0aGUgaW52YWxpZCB0ZXh0LlxuXHQgKi9cblx0QElucHV0KCkgaW52YWxpZFRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cdC8qKlxuXHQgICogU2V0IHRvIGB0cnVlYCB0byBzaG93IGEgd2FybmluZyAoY29udGVudHMgc2V0IGJ5IHdhcm5pbmdUZXh0KVxuXHQgICovXG5cdEBJbnB1dCgpIHdhcm4gPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHdhcm5pbmcgdGV4dFxuXHQgKi9cblx0QElucHV0KCkgd2FyblRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB1bmlxdWUgSUQuIERlZmF1bHRzIHRvIGBzZWxlY3QtJHt0b3RhbCBjb3VudCBvZiBzZWxlY3RzIGluc3RhbnRpYXRlZH1gXG5cdCAqL1xuXHRASW5wdXQoKSBpZCA9IGBzZWxlY3QtJHtTZWxlY3Quc2VsZWN0Q291bnQrK31gO1xuXHQvKipcblx0ICogTnVtYmVyIGlucHV0IGZpZWxkIHJlbmRlciBzaXplXG5cdCAqL1xuXHRASW5wdXQoKSBzaXplOiBcInNtXCIgfCBcIm1kXCIgfCBcImxnXCIgPSBcIm1kXCI7XG5cdC8qKlxuXHQgKiBTZXQgdG8gdHJ1ZSB0byBkaXNhYmxlIGNvbXBvbmVudC5cblx0ICovXG5cdEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gdHJ1ZSBmb3IgYSBsb2FkaW5nIHNlbGVjdC5cblx0ICovXG5cdEBJbnB1dCgpIHNrZWxldG9uID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIGZvciBhbiBpbnZhbGlkIHNlbGVjdCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBpbnZhbGlkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIGZvciByZWFkb25seSBzdGF0ZS5cblx0ICovXG5cdEBJbnB1dCgpIHJlYWRvbmx5ID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqIEBkZXByZWNhdGVkIHNpbmNlIHY1IC0gVXNlIGBjZHNMYXllcmAgZGlyZWN0aXZlIGluc3RlYWRcblx0ICogYGxpZ2h0YCBvciBgZGFya2Agc2VsZWN0IHRoZW1lXG5cdCAqL1xuXHRASW5wdXQoKSB0aGVtZTogXCJsaWdodFwiIHwgXCJkYXJrXCIgPSBcImRhcmtcIjtcblx0QElucHV0KCkgYXJpYUxhYmVsOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIEV4cGVyaW1lbnRhbDogZW5hYmxlIGZsdWlkIHN0YXRlXG5cdCAqL1xuXHRASW5wdXQoKSBmbHVpZCA9IGZhbHNlO1xuXG5cdEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHRAVmlld0NoaWxkKFwic2VsZWN0XCIpIHNlbGVjdDogRWxlbWVudFJlZjtcblxuXHRmb2N1c2VkID0gZmFsc2U7XG5cblx0cHJvdGVjdGVkIF92YWx1ZTtcblxuXHRuZ0FmdGVyVmlld0luaXQoKSB7XG5cdFx0aWYgKFxuXHRcdFx0dGhpcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmXG5cdFx0XHR0aGlzLnZhbHVlICE9PSBudWxsICYmXG5cdFx0XHR0aGlzLnNlbGVjdCAmJlxuXHRcdFx0dGhpcy5zZWxlY3QubmF0aXZlRWxlbWVudC52YWx1ZSAhPT0gdGhpcy52YWx1ZVxuXHRcdCkge1xuXHRcdFx0dGhpcy5zZWxlY3QubmF0aXZlRWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlY2VpdmVzIGEgdmFsdWUgZnJvbSB0aGUgbW9kZWwuXG5cdCAqL1xuXHR3cml0ZVZhbHVlKG9iajogYW55KSB7XG5cdFx0dGhpcy52YWx1ZSA9IG9iajtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBsaXN0ZW5lciB0aGF0IG5vdGlmaWVzIHRoZSBtb2RlbCB3aGVuIHRoZSBjb250cm9sIHVwZGF0ZXNcblx0ICovXG5cdHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSkge1xuXHRcdHRoaXMub25DaGFuZ2VIYW5kbGVyID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgbGlzdGVuZXIgdGhhdCBub3RpZmllcyB0aGUgbW9kZWwgd2hlbiB0aGUgY29udHJvbCBpcyBibHVycmVkXG5cdCAqL1xuXHRyZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KSB7XG5cdFx0dGhpcy5vblRvdWNoZWRIYW5kbGVyID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZGlzYWJsZWQgc3RhdGUgdGhyb3VnaCB0aGUgbW9kZWxcblx0ICovXG5cdHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbikge1xuXHRcdHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZXMgdGhlIGNoYW5nZSBldmVudCBmcm9tIHRoZSBgc2VsZWN0YC5cblx0ICogU2VuZHMgZXZlbnRzIHRvIHRoZSBjaGFuZ2UgaGFuZGxlciBhbmQgZW1pdHMgYSBgc2VsZWN0ZWRgIGV2ZW50LlxuXHQgKi9cblx0b25DaGFuZ2UoZXZlbnQpIHtcblx0XHR0aGlzLnZhbHVlID0gZXZlbnQudGFyZ2V0LnZhbHVlO1xuXHRcdHRoaXMub25DaGFuZ2VIYW5kbGVyKGV2ZW50LnRhcmdldC52YWx1ZSk7XG5cdFx0dGhpcy52YWx1ZUNoYW5nZS5lbWl0KGV2ZW50LnRhcmdldC52YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogTGlzdGVucyBmb3IgdGhlIGhvc3QgYmx1cnJpbmcsIGFuZCBub3RpZmllcyB0aGUgbW9kZWxcblx0ICovXG5cdEBIb3N0TGlzdGVuZXIoXCJmb2N1c291dFwiKVxuXHRmb2N1c091dCgpIHtcblx0XHR0aGlzLm9uVG91Y2hlZEhhbmRsZXIoKTtcblx0fVxuXG5cdHB1YmxpYyBpc1RlbXBsYXRlKHZhbHVlKSB7XG5cdFx0cmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVGVtcGxhdGVSZWY7XG5cdH1cblxuXHRvbk1vdXNlRG93bihldmVudDogTW91c2VFdmVudCkge1xuXHRcdC8qKlxuXHRcdCAqIFRoaXMgcHJldmVudHMgdGhlIHNlbGVjdCBmcm9tIG9wZW5pbmcgd2l0aCBtb3VzZVxuXHRcdCAqL1xuXHRcdGlmICh0aGlzLnJlYWRvbmx5KSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0KDxIVE1MRWxlbWVudD5ldmVudC50YXJnZXQpLmZvY3VzKCk7XG5cdFx0fVxuXHR9XG5cblx0b25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG5cdFx0Y29uc3Qgc2VsZWN0QWNjZXNzS2V5cyA9IFtcIkFycm93RG93blwiLCBcIkFycm93VXBcIiwgXCJBcnJvd0xlZnRcIiwgXCJBcnJvd1JpZ2h0XCIsIFwiIFwiXTtcblx0XHQvKipcblx0XHQgKiBUaGlzIHByZXZlbnRzIHRoZSBzZWxlY3QgZnJvbSBvcGVuaW5nIGZvciB0aGUgYWJvdmUga2V5c1xuXHRcdCAqL1xuXHRcdGlmICh0aGlzLnJlYWRvbmx5ICYmIHNlbGVjdEFjY2Vzc0tleXMuaW5jbHVkZXMoZXZlbnQua2V5KSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH1cblxuXHRoYW5kbGVGb2N1cyhldmVudDogRm9jdXNFdmVudCkge1xuXHRcdHRoaXMuZm9jdXNlZCA9IGV2ZW50LnR5cGUgPT09IFwiZm9jdXNcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBwbGFjZWhvbGRlciBkZWNsYXJhdGlvbnMuIFJlcGxhY2VkIGJ5IHRoZSBmdW5jdGlvbnMgcHJvdmlkZWQgdG8gYHJlZ2lzdGVyT25DaGFuZ2VgIGFuZCBgcmVnaXN0ZXJPblRvdWNoZWRgXG5cdCAqL1xuXHRwcm90ZWN0ZWQgb25DaGFuZ2VIYW5kbGVyID0gKF86IGFueSkgPT4geyB9O1xuXHRwcm90ZWN0ZWQgb25Ub3VjaGVkSGFuZGxlciA9ICgpID0+IHsgfTtcblxufVxuIl19