UNPKG

carbon-components-angular

Version:
349 lines (345 loc) 32.4 kB
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, HostListener, Input, Output, ViewChild } from "@angular/core"; import { AILabelPopoverDirective } from "./ai-label-popover.directive"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "carbon-components-angular/button"; import * as i3 from "carbon-components-angular/icon"; import * as i4 from "./ai-label-popover.directive"; /** * AI-branded toggletip control (`cds-ai-label`). Renders an "AI" badge that opens a * popover; projected content and optional actions use `ng-content`. * * Get started with importing the module: * * ```typescript * import { AILabelModule } from 'carbon-components-angular'; * ``` * * ```html * <cds-ai-label size="md"> * <div> * <p>AI Explained</p> * <h2>84%</h2> * <p>Confidence score</p> * </div> * <div cdsAILabelActions> * <button cdsButton="ghost" size="sm">View details</button> * </div> * </cds-ai-label> * ``` * * `[cdsAILabelActions]` adds `cds--toggletip-actions` and `cds--ai-label-actions` * to its host. Place it as a **sibling** of the body content, both direct * children of `<cds-ai-label>`. `[cdsAILabelContent]` is an optional marker; the * `cds--ai-label-content` / `cds--toggletip-content` classes come from this * component’s template. * * [See demo](../../?path=/story/components-ai-label--default) */ export class AILabelComponent { constructor(elementRef) { this.elementRef = elementRef; this.aiLabelClass = true; /** * Show caret at the alignment position. */ this.caret = true; /** * Enable drop shadow around the popover container. */ this.dropShadow = false; /** * Enable high contrast for popover container. */ this.highContrast = true; /** * **Experimental**: Use floating-ui to position the tooltip. */ this.autoAlign = false; /** * Whether the callout is open. */ this.isOpen = false; /** * Emits when the callout is closed. */ this.onClose = new EventEmitter(); /** * Emits when the callout is opened. */ this.onOpen = new EventEmitter(); /** * Emits when `isOpen` changes (two-way binding). */ this.isOpenChange = new EventEmitter(); /** * Unique id used to associate the trigger button with the popover panel * via `aria-controls` / `id`. */ this.id = `ai-label-${AILabelComponent.labelCounter++}`; /** * Text inside the AI badge. */ this.aiText = "AI"; /** * Set badge shape: `"default"` (circular) or `"inline"` (pill, optional `textLabel`). */ this.kind = "default"; /** * Set badge size */ this.size = "xs"; /** * When `true`, shows the revert icon instead of the badge (AI-generated value * is active and can be reverted). */ this.revertActive = false; /** * Accessible label / tooltip for the revert icon button. */ this.revertLabel = "Revert to AI input"; /** * `aria-label` for the AI badge trigger (combined with `aiText` in `computedAriaLabel`). */ this.ariaLabel = "Show information"; /** * Emitted when the revert icon is clicked. */ this.revertClick = new EventEmitter(); this.documentClick = this.handleOutsideClick.bind(this); } get revertClass() { return this.revertActive; } /** * Horizontal shift along the alignment axis when `autoAlign` is on, matching * React `AILabel` (`alignmentAxisOffset={isSmallIcon ? -24 : 0}` on `Toggletip`). */ get alignmentAxisOffset() { return ["mini", "2xs", "xs"].includes(this.size) ? -24 : 0; } onPopoverIsOpenChange(open) { this.isOpen = open; this.isOpenChange.emit(open); } get triggerClasses() { return { "cds--toggletip-button": true, "cds--ai-label__button": true, [`cds--ai-label__button--${this.size}`]: true, [`cds--ai-label__button--${this.kind}`]: true, "cds--ai-label__button--inline-with-content": this.kind === "inline" && !!this.textLabel }; } /** * Trigger `aria-label`: `"${aiText} ${ariaLabel}"`, or * `"${aiText} ${textLabel}"` when `kind` is `"inline"` and `textLabel` is set. */ get computedAriaLabel() { const suffix = (this.kind === "inline" && this.textLabel) ? this.textLabel : this.ariaLabel; return `${this.aiText} ${suffix}`; } ngAfterViewInit() { if (this.isOpen) { document.addEventListener("click", this.documentClick); } } ngOnChanges(changes) { if (changes.revertActive && !changes.revertActive.firstChange && changes.revertActive.currentValue) { this.isOpen = false; document.removeEventListener("click", this.documentClick); } } ngOnDestroy() { document.removeEventListener("click", this.documentClick); } onTriggerClick(event) { const opening = !this.isOpen; if (opening) { document.addEventListener("click", this.documentClick); } else { document.removeEventListener("click", this.documentClick); } this.aiLabelPopover?.handleChange(opening, event); } onRevertButtonClick(event) { this.revertClick.emit(event); } hostkeys(event) { if (this.isOpen && event.key === "Escape") { event.stopPropagation(); document.removeEventListener("click", this.documentClick); this.aiLabelPopover?.handleChange(false, event); } } /** * Dismisses the popover when a click lands outside the host element. */ handleOutsideClick(event) { if (!this.elementRef.nativeElement.contains(event.target)) { this.aiLabelPopover?.handleChange(false, event); document.removeEventListener("click", this.documentClick); } } } AILabelComponent.labelCounter = 0; AILabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: AILabelComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); AILabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: AILabelComponent, selector: "cds-ai-label, ibm-ai-label", inputs: { align: "align", caret: "caret", dropShadow: "dropShadow", highContrast: "highContrast", autoAlign: "autoAlign", isOpen: "isOpen", id: "id", aiText: "aiText", textLabel: "textLabel", kind: "kind", size: "size", revertActive: "revertActive", revertLabel: "revertLabel", ariaLabel: "ariaLabel" }, outputs: { onClose: "onClose", onOpen: "onOpen", isOpenChange: "isOpenChange", revertClick: "revertClick" }, host: { listeners: { "keyup": "hostkeys($event)" }, properties: { "class.cds--ai-label": "this.aiLabelClass", "class.cds--ai-label--revert": "this.revertClass" } }, viewQueries: [{ propertyName: "aiLabelPopover", first: true, predicate: ["aiLabelPopoverHost"], descendants: true, read: AILabelPopoverDirective }], usesOnChanges: true, ngImport: i0, template: ` <ng-container *ngIf="!revertActive"> <span #aiLabelPopoverHost cdsAILabelPopover class="cds--toggletip" [isOpen]="isOpen" (isOpenChange)="onPopoverIsOpenChange($event)" (onOpen)="onOpen.emit($event)" (onClose)="onClose.emit($event)" [align]="align" [caret]="caret" [dropShadow]="dropShadow" [highContrast]="highContrast" [autoAlign]="autoAlign" [alignmentAxisOffset]="alignmentAxisOffset"> <button type="button" [attr.aria-label]="computedAriaLabel" [attr.aria-expanded]="isOpen" [attr.aria-controls]="id" [ngClass]="triggerClasses" (click)="onTriggerClick($event)"> <span class="cds--ai-label__text">{{aiText}}</span> <span *ngIf="kind === 'inline' && textLabel" class="cds--ai-label__additional-text">{{textLabel}}</span> </button> <span [id]="id" class="cds--popover" aria-live="polite"> <span class="cds--popover-content cds--ai-label-content"> <div class="cds--toggletip-content"> <ng-content></ng-content> </div> <span *ngIf="autoAlign" class="cds--popover-caret cds--popover--auto-align"></span> </span> <span *ngIf="!autoAlign" class="cds--popover-caret"></span> </span> </span> </ng-container> <cds-icon-button *ngIf="revertActive" kind="ghost" size="sm" [description]="revertLabel" [autoAlign]="autoAlign" [buttonAttributes]="{ 'aria-label': revertLabel }" (click)="onRevertButtonClick($event)"> <svg cdsIcon="undo" size="16"></svg> </cds-icon-button> `, 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: "component", type: i2.IconButton, selector: "cds-icon-button, ibm-icon-button", inputs: ["buttonNgClass", "buttonAttributes", "buttonId", "kind", "size", "type", "isExpressive", "disabled", "description", "showTooltipWhenDisabled"], outputs: ["click", "focus", "blur", "tooltipClick"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: i4.AILabelPopoverDirective, selector: "[cdsAILabelPopover]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: AILabelComponent, decorators: [{ type: Component, args: [{ selector: "cds-ai-label, ibm-ai-label", changeDetection: ChangeDetectionStrategy.OnPush, template: ` <ng-container *ngIf="!revertActive"> <span #aiLabelPopoverHost cdsAILabelPopover class="cds--toggletip" [isOpen]="isOpen" (isOpenChange)="onPopoverIsOpenChange($event)" (onOpen)="onOpen.emit($event)" (onClose)="onClose.emit($event)" [align]="align" [caret]="caret" [dropShadow]="dropShadow" [highContrast]="highContrast" [autoAlign]="autoAlign" [alignmentAxisOffset]="alignmentAxisOffset"> <button type="button" [attr.aria-label]="computedAriaLabel" [attr.aria-expanded]="isOpen" [attr.aria-controls]="id" [ngClass]="triggerClasses" (click)="onTriggerClick($event)"> <span class="cds--ai-label__text">{{aiText}}</span> <span *ngIf="kind === 'inline' && textLabel" class="cds--ai-label__additional-text">{{textLabel}}</span> </button> <span [id]="id" class="cds--popover" aria-live="polite"> <span class="cds--popover-content cds--ai-label-content"> <div class="cds--toggletip-content"> <ng-content></ng-content> </div> <span *ngIf="autoAlign" class="cds--popover-caret cds--popover--auto-align"></span> </span> <span *ngIf="!autoAlign" class="cds--popover-caret"></span> </span> </span> </ng-container> <cds-icon-button *ngIf="revertActive" kind="ghost" size="sm" [description]="revertLabel" [autoAlign]="autoAlign" [buttonAttributes]="{ 'aria-label': revertLabel }" (click)="onRevertButtonClick($event)"> <svg cdsIcon="undo" size="16"></svg> </cds-icon-button> ` }] }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { aiLabelClass: [{ type: HostBinding, args: ["class.cds--ai-label"] }], revertClass: [{ type: HostBinding, args: ["class.cds--ai-label--revert"] }], align: [{ type: Input }], caret: [{ type: Input }], dropShadow: [{ type: Input }], highContrast: [{ type: Input }], autoAlign: [{ type: Input }], isOpen: [{ type: Input }], onClose: [{ type: Output }], onOpen: [{ type: Output }], isOpenChange: [{ type: Output }], id: [{ type: Input }], aiText: [{ type: Input }], textLabel: [{ type: Input }], kind: [{ type: Input }], size: [{ type: Input }], revertActive: [{ type: Input }], revertLabel: [{ type: Input }], ariaLabel: [{ type: Input }], revertClick: [{ type: Output }], aiLabelPopover: [{ type: ViewChild, args: ["aiLabelPopoverHost", { read: AILabelPopoverDirective }] }], hostkeys: [{ type: HostListener, args: ["keyup", ["$event"]] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktbGFiZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FpLWxhYmVsL2FpLWxhYmVsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sdUJBQXVCLEVBQ3ZCLFNBQVMsRUFFVCxZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxFQUVOLFNBQVMsRUFDVCxNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQzs7Ozs7O0FBZXZFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7QUEwREgsTUFBTSxPQUFPLGdCQUFnQjtJQWtINUIsWUFBb0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQS9HTixpQkFBWSxHQUFHLElBQUksQ0FBQztRQVd4RDs7V0FFRztRQUNNLFVBQUssR0FBRyxJQUFJLENBQUM7UUFFdEI7O1dBRUc7UUFDTSxlQUFVLEdBQUcsS0FBSyxDQUFDO1FBRTVCOztXQUVHO1FBQ00saUJBQVksR0FBRyxJQUFJLENBQUM7UUFFN0I7O1dBRUc7UUFDTSxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRTNCOztXQUVHO1FBQ00sV0FBTSxHQUFHLEtBQUssQ0FBQztRQUV4Qjs7V0FFRztRQUNPLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBUyxDQUFDO1FBRTlDOztXQUVHO1FBQ08sV0FBTSxHQUFHLElBQUksWUFBWSxFQUFTLENBQUM7UUFFN0M7O1dBRUc7UUFDTyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFXLENBQUM7UUFFckQ7OztXQUdHO1FBQ00sT0FBRSxHQUFHLFlBQVksZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUU1RDs7V0FFRztRQUNNLFdBQU0sR0FBRyxJQUFJLENBQUM7UUFPdkI7O1dBRUc7UUFDTSxTQUFJLEdBQXlCLFNBQVMsQ0FBQztRQUVoRDs7V0FFRztRQUNNLFNBQUksR0FBc0QsSUFBSSxDQUFDO1FBVXhFOzs7V0FHRztRQUNNLGlCQUFZLEdBQUcsS0FBSyxDQUFDO1FBRTlCOztXQUVHO1FBQ00sZ0JBQVcsR0FBRyxvQkFBb0IsQ0FBQztRQUU1Qzs7V0FFRztRQUNNLGNBQVMsR0FBRyxrQkFBa0IsQ0FBQztRQUV4Qzs7V0FFRztRQUNPLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQWMsQ0FBQztRQUt0QyxrQkFBYSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFdkIsQ0FBQztJQTlHOUMsSUFBZ0QsV0FBVztRQUMxRCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDMUIsQ0FBQztJQTBFRDs7O09BR0c7SUFDSCxJQUFJLG1CQUFtQjtRQUN0QixPQUFPLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUE4QkQscUJBQXFCLENBQUMsSUFBYTtRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2pCLE9BQU87WUFDTix1QkFBdUIsRUFBRSxJQUFJO1lBQzdCLHVCQUF1QixFQUFFLElBQUk7WUFDN0IsQ0FBQywwQkFBMEIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSTtZQUM3QyxDQUFDLDBCQUEwQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJO1lBQzdDLDRDQUE0QyxFQUFFLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUztTQUN4RixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUksaUJBQWlCO1FBQ3BCLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQzVGLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO0lBQ25DLENBQUM7SUFFRCxlQUFlO1FBQ2QsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQ3ZEO0lBQ0YsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNqQyxJQUFJLE9BQU8sQ0FBQyxZQUFZLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRTtZQUNuRyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztZQUNwQixRQUFRLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUMxRDtJQUNGLENBQUM7SUFFRCxXQUFXO1FBQ1YsUUFBUSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELGNBQWMsQ0FBQyxLQUFpQjtRQUMvQixNQUFNLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDN0IsSUFBSSxPQUFPLEVBQUU7WUFDWixRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUN2RDthQUFNO1lBQ04sUUFBUSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDMUQ7UUFDRCxJQUFJLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELG1CQUFtQixDQUFDLEtBQWlCO1FBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFHRCxRQUFRLENBQUMsS0FBb0I7UUFDNUIsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFO1lBQzFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN4QixRQUFRLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMxRCxJQUFJLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDaEQ7SUFDRixDQUFDO0lBRUQ7O09BRUc7SUFDSyxrQkFBa0IsQ0FBQyxLQUFpQjtRQUMzQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFjLENBQUMsRUFBRTtZQUNsRSxJQUFJLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsUUFBUSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDMUQ7SUFDRixDQUFDOztBQTNMTSw2QkFBWSxHQUFHLENBQUMsQ0FBQzs2R0FEWixnQkFBZ0I7aUdBQWhCLGdCQUFnQixxdUJBNkdhLHVCQUF1QixrREFuS3REOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBb0RUOzJGQUVXLGdCQUFnQjtrQkF6RDVCLFNBQVM7bUJBQUM7b0JBQ1YsUUFBUSxFQUFFLDRCQUE0QjtvQkFDdEMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07b0JBQy9DLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQW9EVDtpQkFDRDtpR0FJb0MsWUFBWTtzQkFBL0MsV0FBVzt1QkFBQyxxQkFBcUI7Z0JBQ2MsV0FBVztzQkFBMUQsV0FBVzt1QkFBQyw2QkFBNkI7Z0JBUWpDLEtBQUs7c0JBQWIsS0FBSztnQkFLRyxLQUFLO3NCQUFiLEtBQUs7Z0JBS0csVUFBVTtzQkFBbEIsS0FBSztnQkFLRyxZQUFZO3NCQUFwQixLQUFLO2dCQUtHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBS0csTUFBTTtzQkFBZCxLQUFLO2dCQUtJLE9BQU87c0JBQWhCLE1BQU07Z0JBS0csTUFBTTtzQkFBZixNQUFNO2dCQUtHLFlBQVk7c0JBQXJCLE1BQU07Z0JBTUUsRUFBRTtzQkFBVixLQUFLO2dCQUtHLE1BQU07c0JBQWQsS0FBSztnQkFLRyxTQUFTO3NCQUFqQixLQUFLO2dCQUtHLElBQUk7c0JBQVosS0FBSztnQkFLRyxJQUFJO3NCQUFaLEtBQUs7Z0JBY0csWUFBWTtzQkFBcEIsS0FBSztnQkFLRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBS0ksV0FBVztzQkFBcEIsTUFBTTtnQkFHQyxjQUFjO3NCQURyQixTQUFTO3VCQUFDLG9CQUFvQixFQUFFLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixFQUFFO2dCQStEbEUsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcblx0QWZ0ZXJWaWV3SW5pdCxcclxuXHRDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuXHRDb21wb25lbnQsXHJcblx0RWxlbWVudFJlZixcclxuXHRFdmVudEVtaXR0ZXIsXHJcblx0SG9zdEJpbmRpbmcsXHJcblx0SG9zdExpc3RlbmVyLFxyXG5cdElucHV0LFxyXG5cdE9uQ2hhbmdlcyxcclxuXHRPbkRlc3Ryb3ksXHJcblx0T3V0cHV0LFxyXG5cdFNpbXBsZUNoYW5nZXMsXHJcblx0Vmlld0NoaWxkXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgUGxhY2VtZW50IH0gZnJvbSBcIkBmbG9hdGluZy11aS9kb21cIjtcclxuXHJcbmltcG9ydCB7IEFJTGFiZWxQb3BvdmVyRGlyZWN0aXZlIH0gZnJvbSBcIi4vYWktbGFiZWwtcG9wb3Zlci5kaXJlY3RpdmVcIjtcclxuXHJcbi8qKlxyXG4gKiBAZGVwcmVjYXRlZCBhbGlnbm1lbnRzIOKAlCB1c2UgYFBsYWNlbWVudGAgbmFtZXNcclxuICovXHJcbnR5cGUgRGVwcmVjYXRlZEFJTGFiZWxBbGlnbiA9XHJcblx0fCBcInRvcC1sZWZ0XCJcclxuXHR8IFwidG9wLXJpZ2h0XCJcclxuXHR8IFwiYm90dG9tLWxlZnRcIlxyXG5cdHwgXCJib3R0b20tcmlnaHRcIlxyXG5cdHwgXCJsZWZ0LWJvdHRvbVwiXHJcblx0fCBcImxlZnQtdG9wXCJcclxuXHR8IFwicmlnaHQtYm90dG9tXCJcclxuXHR8IFwicmlnaHQtdG9wXCI7XHJcblxyXG4vKipcclxuICogQUktYnJhbmRlZCB0b2dnbGV0aXAgY29udHJvbCAoYGNkcy1haS1sYWJlbGApLiBSZW5kZXJzIGFuIFwiQUlcIiBiYWRnZSB0aGF0IG9wZW5zIGFcclxuICogcG9wb3ZlcjsgcHJvamVjdGVkIGNvbnRlbnQgYW5kIG9wdGlvbmFsIGFjdGlvbnMgdXNlIGBuZy1jb250ZW50YC5cclxuICpcclxuICogR2V0IHN0YXJ0ZWQgd2l0aCBpbXBvcnRpbmcgdGhlIG1vZHVsZTpcclxuICpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBpbXBvcnQgeyBBSUxhYmVsTW9kdWxlIH0gZnJvbSAnY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhcic7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBgYGBodG1sXHJcbiAqIDxjZHMtYWktbGFiZWwgc2l6ZT1cIm1kXCI+XHJcbiAqICAgPGRpdj5cclxuICogICAgIDxwPkFJIEV4cGxhaW5lZDwvcD5cclxuICogICAgIDxoMj44NCU8L2gyPlxyXG4gKiAgICAgPHA+Q29uZmlkZW5jZSBzY29yZTwvcD5cclxuICogICA8L2Rpdj5cclxuICogICA8ZGl2IGNkc0FJTGFiZWxBY3Rpb25zPlxyXG4gKiAgICAgPGJ1dHRvbiBjZHNCdXR0b249XCJnaG9zdFwiIHNpemU9XCJzbVwiPlZpZXcgZGV0YWlsczwvYnV0dG9uPlxyXG4gKiAgIDwvZGl2PlxyXG4gKiA8L2Nkcy1haS1sYWJlbD5cclxuICogYGBgXHJcbiAqXHJcbiAqIGBbY2RzQUlMYWJlbEFjdGlvbnNdYCBhZGRzIGBjZHMtLXRvZ2dsZXRpcC1hY3Rpb25zYCBhbmQgYGNkcy0tYWktbGFiZWwtYWN0aW9uc2BcclxuICogdG8gaXRzIGhvc3QuIFBsYWNlIGl0IGFzIGEgKipzaWJsaW5nKiogb2YgdGhlIGJvZHkgY29udGVudCwgYm90aCBkaXJlY3RcclxuICogY2hpbGRyZW4gb2YgYDxjZHMtYWktbGFiZWw+YC4gYFtjZHNBSUxhYmVsQ29udGVudF1gIGlzIGFuIG9wdGlvbmFsIG1hcmtlcjsgdGhlXHJcbiAqIGBjZHMtLWFpLWxhYmVsLWNvbnRlbnRgIC8gYGNkcy0tdG9nZ2xldGlwLWNvbnRlbnRgIGNsYXNzZXMgY29tZSBmcm9tIHRoaXNcclxuICogY29tcG9uZW504oCZcyB0ZW1wbGF0ZS5cclxuICpcclxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy1haS1sYWJlbC0tZGVmYXVsdClcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG5cdHNlbGVjdG9yOiBcImNkcy1haS1sYWJlbCwgaWJtLWFpLWxhYmVsXCIsXHJcblx0Y2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcblx0dGVtcGxhdGU6IGBcclxuXHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhcmV2ZXJ0QWN0aXZlXCI+XHJcblx0XHRcdDxzcGFuXHJcblx0XHRcdFx0I2FpTGFiZWxQb3BvdmVySG9zdFxyXG5cdFx0XHRcdGNkc0FJTGFiZWxQb3BvdmVyXHJcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLXRvZ2dsZXRpcFwiXHJcblx0XHRcdFx0W2lzT3Blbl09XCJpc09wZW5cIlxyXG5cdFx0XHRcdChpc09wZW5DaGFuZ2UpPVwib25Qb3BvdmVySXNPcGVuQ2hhbmdlKCRldmVudClcIlxyXG5cdFx0XHRcdChvbk9wZW4pPVwib25PcGVuLmVtaXQoJGV2ZW50KVwiXHJcblx0XHRcdFx0KG9uQ2xvc2UpPVwib25DbG9zZS5lbWl0KCRldmVudClcIlxyXG5cdFx0XHRcdFthbGlnbl09XCJhbGlnblwiXHJcblx0XHRcdFx0W2NhcmV0XT1cImNhcmV0XCJcclxuXHRcdFx0XHRbZHJvcFNoYWRvd109XCJkcm9wU2hhZG93XCJcclxuXHRcdFx0XHRbaGlnaENvbnRyYXN0XT1cImhpZ2hDb250cmFzdFwiXHJcblx0XHRcdFx0W2F1dG9BbGlnbl09XCJhdXRvQWxpZ25cIlxyXG5cdFx0XHRcdFthbGlnbm1lbnRBeGlzT2Zmc2V0XT1cImFsaWdubWVudEF4aXNPZmZzZXRcIj5cclxuXHRcdFx0XHQ8YnV0dG9uXHJcblx0XHRcdFx0XHR0eXBlPVwiYnV0dG9uXCJcclxuXHRcdFx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwiY29tcHV0ZWRBcmlhTGFiZWxcIlxyXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1leHBhbmRlZF09XCJpc09wZW5cIlxyXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1jb250cm9sc109XCJpZFwiXHJcblx0XHRcdFx0XHRbbmdDbGFzc109XCJ0cmlnZ2VyQ2xhc3Nlc1wiXHJcblx0XHRcdFx0XHQoY2xpY2spPVwib25UcmlnZ2VyQ2xpY2soJGV2ZW50KVwiPlxyXG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJjZHMtLWFpLWxhYmVsX190ZXh0XCI+e3thaVRleHR9fTwvc3Bhbj5cclxuXHRcdFx0XHRcdDxzcGFuICpuZ0lmPVwia2luZCA9PT0gJ2lubGluZScgJiYgdGV4dExhYmVsXCIgY2xhc3M9XCJjZHMtLWFpLWxhYmVsX19hZGRpdGlvbmFsLXRleHRcIj57e3RleHRMYWJlbH19PC9zcGFuPlxyXG5cdFx0XHRcdDwvYnV0dG9uPlxyXG5cclxuXHRcdFx0XHQ8c3BhblxyXG5cdFx0XHRcdFx0W2lkXT1cImlkXCJcclxuXHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1wb3BvdmVyXCJcclxuXHRcdFx0XHRcdGFyaWEtbGl2ZT1cInBvbGl0ZVwiPlxyXG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJjZHMtLXBvcG92ZXItY29udGVudCBjZHMtLWFpLWxhYmVsLWNvbnRlbnRcIj5cclxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tdG9nZ2xldGlwLWNvbnRlbnRcIj5cclxuXHRcdFx0XHRcdFx0XHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcblx0XHRcdFx0XHRcdDwvZGl2PlxyXG5cdFx0XHRcdFx0XHQ8c3BhbiAqbmdJZj1cImF1dG9BbGlnblwiIGNsYXNzPVwiY2RzLS1wb3BvdmVyLWNhcmV0IGNkcy0tcG9wb3Zlci0tYXV0by1hbGlnblwiPjwvc3Bhbj5cclxuXHRcdFx0XHRcdDwvc3Bhbj5cclxuXHRcdFx0XHRcdDxzcGFuICpuZ0lmPVwiIWF1dG9BbGlnblwiIGNsYXNzPVwiY2RzLS1wb3BvdmVyLWNhcmV0XCI+PC9zcGFuPlxyXG5cdFx0XHRcdDwvc3Bhbj5cclxuXHRcdFx0PC9zcGFuPlxyXG5cdFx0PC9uZy1jb250YWluZXI+XHJcblxyXG5cdFx0PGNkcy1pY29uLWJ1dHRvblxyXG5cdFx0XHQqbmdJZj1cInJldmVydEFjdGl2ZVwiXHJcblx0XHRcdGtpbmQ9XCJnaG9zdFwiXHJcblx0XHRcdHNpemU9XCJzbVwiXHJcblx0XHRcdFtkZXNjcmlwdGlvbl09XCJyZXZlcnRMYWJlbFwiXHJcblx0XHRcdFthdXRvQWxpZ25dPVwiYXV0b0FsaWduXCJcclxuXHRcdFx0W2J1dHRvbkF0dHJpYnV0ZXNdPVwieyAnYXJpYS1sYWJlbCc6IHJldmVydExhYmVsIH1cIlxyXG5cdFx0XHQoY2xpY2spPVwib25SZXZlcnRCdXR0b25DbGljaygkZXZlbnQpXCI+XHJcblx0XHRcdDxzdmcgY2RzSWNvbj1cInVuZG9cIiBzaXplPVwiMTZcIj48L3N2Zz5cclxuXHRcdDwvY2RzLWljb24tYnV0dG9uPlxyXG5cdGBcclxufSlcclxuZXhwb3J0IGNsYXNzIEFJTGFiZWxDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XHJcblx0c3RhdGljIGxhYmVsQ291bnRlciA9IDA7XHJcblxyXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tYWktbGFiZWxcIikgYWlMYWJlbENsYXNzID0gdHJ1ZTtcclxuXHRASG9zdEJpbmRpbmcoXCJjbGFzcy5jZHMtLWFpLWxhYmVsLS1yZXZlcnRcIikgZ2V0IHJldmVydENsYXNzKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMucmV2ZXJ0QWN0aXZlO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2V0IGFsaWdubWVudCBvZiBwb3BvdmVyLiBEZXByZWNhdGVkIENhcmJvbiBhbGlnbm1lbnRzIGFyZSBtYXBwZWQgdG9cclxuXHQgKiBmbG9hdGluZy11aSBwbGFjZW1lbnRzLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIGFsaWduOiBEZXByZWNhdGVkQUlMYWJlbEFsaWduIHwgUGxhY2VtZW50O1xyXG5cclxuXHQvKipcclxuXHQgKiBTaG93IGNhcmV0IGF0IHRoZSBhbGlnbm1lbnQgcG9zaXRpb24uXHJcblx0ICovXHJcblx0QElucHV0KCkgY2FyZXQgPSB0cnVlO1xyXG5cclxuXHQvKipcclxuXHQgKiBFbmFibGUgZHJvcCBzaGFkb3cgYXJvdW5kIHRoZSBwb3BvdmVyIGNvbnRhaW5lci5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBkcm9wU2hhZG93ID0gZmFsc2U7XHJcblxyXG5cdC8qKlxyXG5cdCAqIEVuYWJsZSBoaWdoIGNvbnRyYXN0IGZvciBwb3BvdmVyIGNvbnRhaW5lci5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBoaWdoQ29udHJhc3QgPSB0cnVlO1xyXG5cclxuXHQvKipcclxuXHQgKiAqKkV4cGVyaW1lbnRhbCoqOiBVc2UgZmxvYXRpbmctdWkgdG8gcG9zaXRpb24gdGhlIHRvb2x0aXAuXHJcblx0ICovXHJcblx0QElucHV0KCkgYXV0b0FsaWduID0gZmFsc2U7XHJcblxyXG5cdC8qKlxyXG5cdCAqIFdoZXRoZXIgdGhlIGNhbGxvdXQgaXMgb3Blbi5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBpc09wZW4gPSBmYWxzZTtcclxuXHJcblx0LyoqXHJcblx0ICogRW1pdHMgd2hlbiB0aGUgY2FsbG91dCBpcyBjbG9zZWQuXHJcblx0ICovXHJcblx0QE91dHB1dCgpIG9uQ2xvc2UgPSBuZXcgRXZlbnRFbWl0dGVyPEV2ZW50PigpO1xyXG5cclxuXHQvKipcclxuXHQgKiBFbWl0cyB3aGVuIHRoZSBjYWxsb3V0IGlzIG9wZW5lZC5cclxuXHQgKi9cclxuXHRAT3V0cHV0KCkgb25PcGVuID0gbmV3IEV2ZW50RW1pdHRlcjxFdmVudD4oKTtcclxuXHJcblx0LyoqXHJcblx0ICogRW1pdHMgd2hlbiBgaXNPcGVuYCBjaGFuZ2VzICh0d28td2F5IGJpbmRpbmcpLlxyXG5cdCAqL1xyXG5cdEBPdXRwdXQoKSBpc09wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XHJcblxyXG5cdC8qKlxyXG5cdCAqIFVuaXF1ZSBpZCB1c2VkIHRvIGFzc29jaWF0ZSB0aGUgdHJpZ2dlciBidXR0b24gd2l0aCB0aGUgcG9wb3ZlciBwYW5lbFxyXG5cdCAqIHZpYSBgYXJpYS1jb250cm9sc2AgLyBgaWRgLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIGlkID0gYGFpLWxhYmVsLSR7QUlMYWJlbENvbXBvbmVudC5sYWJlbENvdW50ZXIrK31gO1xyXG5cclxuXHQvKipcclxuXHQgKiBUZXh0IGluc2lkZSB0aGUgQUkgYmFkZ2UuXHJcblx0ICovXHJcblx0QElucHV0KCkgYWlUZXh0ID0gXCJBSVwiO1xyXG5cclxuXHQvKipcclxuXHQgKiBFeHRyYSB0ZXh0IGJlc2lkZSB0aGUgYmFkZ2Ugd2hlbiBga2luZGAgaXMgYFwiaW5saW5lXCJgLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHRleHRMYWJlbDogc3RyaW5nO1xyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgYmFkZ2Ugc2hhcGU6IGBcImRlZmF1bHRcImAgKGNpcmN1bGFyKSBvciBgXCJpbmxpbmVcImAgKHBpbGwsIG9wdGlvbmFsIGB0ZXh0TGFiZWxgKS5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBraW5kOiBcImRlZmF1bHRcIiB8IFwiaW5saW5lXCIgPSBcImRlZmF1bHRcIjtcclxuXHJcblx0LyoqXHJcblx0ICogU2V0IGJhZGdlIHNpemVcclxuXHQgKi9cclxuXHRASW5wdXQoKSBzaXplOiBcIm1pbmlcIiB8IFwiMnhzXCIgfCBcInhzXCIgfCBcInNtXCIgfCBcIm1kXCIgfCBcImxnXCIgfCBcInhsXCIgPSBcInhzXCI7XHJcblxyXG5cdC8qKlxyXG5cdCAqIEhvcml6b250YWwgc2hpZnQgYWxvbmcgdGhlIGFsaWdubWVudCBheGlzIHdoZW4gYGF1dG9BbGlnbmAgaXMgb24sIG1hdGNoaW5nXHJcblx0ICogUmVhY3QgYEFJTGFiZWxgIChgYWxpZ25tZW50QXhpc09mZnNldD17aXNTbWFsbEljb24gPyAtMjQgOiAwfWAgb24gYFRvZ2dsZXRpcGApLlxyXG5cdCAqL1xyXG5cdGdldCBhbGlnbm1lbnRBeGlzT2Zmc2V0KCk6IG51bWJlciB7XHJcblx0XHRyZXR1cm4gW1wibWluaVwiLCBcIjJ4c1wiLCBcInhzXCJdLmluY2x1ZGVzKHRoaXMuc2l6ZSkgPyAtMjQgOiAwO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogV2hlbiBgdHJ1ZWAsIHNob3dzIHRoZSByZXZlcnQgaWNvbiBpbnN0ZWFkIG9mIHRoZSBiYWRnZSAoQUktZ2VuZXJhdGVkIHZhbHVlXHJcblx0ICogaXMgYWN0aXZlIGFuZCBjYW4gYmUgcmV2ZXJ0ZWQpLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIHJldmVydEFjdGl2ZSA9IGZhbHNlO1xyXG5cclxuXHQvKipcclxuXHQgKiBBY2Nlc3NpYmxlIGxhYmVsIC8gdG9vbHRpcCBmb3IgdGhlIHJldmVydCBpY29uIGJ1dHRvbi5cclxuXHQgKi9cclxuXHRASW5wdXQoKSByZXZlcnRMYWJlbCA9IFwiUmV2ZXJ0IHRvIEFJIGlucHV0XCI7XHJcblxyXG5cdC8qKlxyXG5cdCAqIGBhcmlhLWxhYmVsYCBmb3IgdGhlIEFJIGJhZGdlIHRyaWdnZXIgKGNvbWJpbmVkIHdpdGggYGFpVGV4dGAgaW4gYGNvbXB1dGVkQXJpYUxhYmVsYCkuXHJcblx0ICovXHJcblx0QElucHV0KCkgYXJpYUxhYmVsID0gXCJTaG93IGluZm9ybWF0aW9uXCI7XHJcblxyXG5cdC8qKlxyXG5cdCAqIEVtaXR0ZWQgd2hlbiB0aGUgcmV2ZXJ0IGljb24gaXMgY2xpY2tlZC5cclxuXHQgKi9cclxuXHRAT3V0cHV0KCkgcmV2ZXJ0Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPE1vdXNlRXZlbnQ+KCk7XHJcblxyXG5cdEBWaWV3Q2hpbGQoXCJhaUxhYmVsUG9wb3Zlckhvc3RcIiwgeyByZWFkOiBBSUxhYmVsUG9wb3ZlckRpcmVjdGl2ZSB9KVxyXG5cdHByaXZhdGUgYWlMYWJlbFBvcG92ZXI6IEFJTGFiZWxQb3BvdmVyRGlyZWN0aXZlO1xyXG5cclxuXHRwcml2YXRlIHJlYWRvbmx5IGRvY3VtZW50Q2xpY2sgPSB0aGlzLmhhbmRsZU91dHNpZGVDbGljay5iaW5kKHRoaXMpO1xyXG5cclxuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYpIHt9XHJcblxyXG5cdG9uUG9wb3ZlcklzT3BlbkNoYW5nZShvcGVuOiBib29sZWFuKTogdm9pZCB7XHJcblx0XHR0aGlzLmlzT3BlbiA9IG9wZW47XHJcblx0XHR0aGlzLmlzT3BlbkNoYW5nZS5lbWl0KG9wZW4pO1xyXG5cdH1cclxuXHJcblx0Z2V0IHRyaWdnZXJDbGFzc2VzKCk6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+IHtcclxuXHRcdHJldHVybiB7XHJcblx0XHRcdFwiY2RzLS10b2dnbGV0aXAtYnV0dG9uXCI6IHRydWUsXHJcblx0XHRcdFwiY2RzLS1haS1sYWJlbF9fYnV0dG9uXCI6IHRydWUsXHJcblx0XHRcdFtgY2RzLS1haS1sYWJlbF9fYnV0dG9uLS0ke3RoaXMuc2l6ZX1gXTogdHJ1ZSxcclxuXHRcdFx0W2BjZHMtLWFpLWxhYmVsX19idXR0b24tLSR7dGhpcy5raW5kfWBdOiB0cnVlLFxyXG5cdFx0XHRcImNkcy0tYWktbGFiZWxfX2J1dHRvbi0taW5saW5lLXdpdGgtY29udGVudFwiOiB0aGlzLmtpbmQgPT09IFwiaW5saW5lXCIgJiYgISF0aGlzLnRleHRMYWJlbFxyXG5cdFx0fTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFRyaWdnZXIgYGFyaWEtbGFiZWxgOiBgXCIke2FpVGV4dH0gJHthcmlhTGFiZWx9XCJgLCBvclxyXG5cdCAqIGBcIiR7YWlUZXh0fSAke3RleHRMYWJlbH1cImAgd2hlbiBga2luZGAgaXMgYFwiaW5saW5lXCJgIGFuZCBgdGV4dExhYmVsYCBpcyBzZXQuXHJcblx0ICovXHJcblx0Z2V0IGNvbXB1dGVkQXJpYUxhYmVsKCk6IHN0cmluZyB7XHJcblx0XHRjb25zdCBzdWZmaXggPSAodGhpcy5raW5kID09PSBcImlubGluZVwiICYmIHRoaXMudGV4dExhYmVsKSA/IHRoaXMudGV4dExhYmVsIDogdGhpcy5hcmlhTGFiZWw7XHJcblx0XHRyZXR1cm4gYCR7dGhpcy5haVRleHR9ICR7c3VmZml4fWA7XHJcblx0fVxyXG5cclxuXHRuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5pc09wZW4pIHtcclxuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMuZG9jdW1lbnRDbGljayk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcblx0XHRpZiAoY2hhbmdlcy5yZXZlcnRBY3RpdmUgJiYgIWNoYW5nZXMucmV2ZXJ0QWN0aXZlLmZpcnN0Q2hhbmdlICYmIGNoYW5nZXMucmV2ZXJ0QWN0aXZlLmN1cnJlbnRWYWx1ZSkge1xyXG5cdFx0XHR0aGlzLmlzT3BlbiA9IGZhbHNlO1xyXG5cdFx0XHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5kb2N1bWVudENsaWNrKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG5cdFx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMuZG9jdW1lbnRDbGljayk7XHJcblx0fVxyXG5cclxuXHRvblRyaWdnZXJDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3Qgb3BlbmluZyA9ICF0aGlzLmlzT3BlbjtcclxuXHRcdGlmIChvcGVuaW5nKSB7XHJcblx0XHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmRvY3VtZW50Q2xpY2spO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMuZG9jdW1lbnRDbGljayk7XHJcblx0XHR9XHJcblx0XHR0aGlzLmFpTGFiZWxQb3BvdmVyPy5oYW5kbGVDaGFuZ2Uob3BlbmluZywgZXZlbnQpO1xyXG5cdH1cclxuXHJcblx0b25SZXZlcnRCdXR0b25DbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG5cdFx0dGhpcy5yZXZlcnRDbGljay5lbWl0KGV2ZW50KTtcclxuXHR9XHJcblxyXG5cdEBIb3N0TGlzdGVuZXIoXCJrZXl1cFwiLCBbXCIkZXZlbnRcIl0pXHJcblx0aG9zdGtleXMoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLmlzT3BlbiAmJiBldmVudC5rZXkgPT09IFwiRXNjYXBlXCIpIHtcclxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCB0aGlzLmRvY3VtZW50Q2xpY2spO1xyXG5cdFx0XHR0aGlzLmFpTGFiZWxQb3BvdmVyPy5oYW5kbGVDaGFuZ2UoZmFsc2UsIGV2ZW50KTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIERpc21pc3NlcyB0aGUgcG9wb3ZlciB3aGVuIGEgY2xpY2sgbGFuZHMgb3V0c2lkZSB0aGUgaG9zdCBlbGVtZW50LlxyXG5cdCAqL1xyXG5cdHByaXZhdGUgaGFuZGxlT3V0c2lkZUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcblx0XHRpZiAoIXRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnRhcmdldCBhcyBOb2RlKSkge1xyXG5cdFx0XHR0aGlzLmFpTGFiZWxQb3BvdmVyPy5oYW5kbGVDaGFuZ2UoZmFsc2UsIGV2ZW50KTtcclxuXHRcdFx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMuZG9jdW1lbnRDbGljayk7XHJcblx0XHR9XHJcblx0fVxyXG59XHJcbiJdfQ==