UNPKG

carbon-components-angular

Version:
431 lines (425 loc) 34.2 kB
import { Component, Input, HostBinding, TemplateRef, ViewChild, ContentChild } from "@angular/core"; import { TextArea } from "./text-area.directive"; import { TextInput } from "./input.directive"; import { PasswordInput } from "./password.directive"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "carbon-components-angular/icon"; import * as i3 from "./textarea-label.component"; import * as i4 from "./text-input-label.component"; import * as i5 from "./password-input-label.component"; /** * Get started with importing the module: * * ```typescript * import { InputModule } from 'carbon-components-angular'; * ``` * * To prevent attribute drilling, use `ibm-text-label` or `ibm-textarea-label` components * * ```html * <cds-label> * Label * <input cdsText type="text" class="input-field"> * </cds-label> * ``` * * [See demo](../../?path=/story/components-input--basic) */ export class Label { /** * Creates an instance of Label. */ constructor(changeDetectorRef) { this.changeDetectorRef = changeDetectorRef; /** * The id of the input item associated with the `Label`. This value is also used to associate the `Label` with * its input counterpart through the 'for' attribute. */ this.labelInputID = `cds-label-${Label.labelCounter++}`; /** * Set to `true` for disabled state. */ this.disabled = false; /** * Set to `true` for a loading label. */ this.skeleton = false; /** * Set to `true` for an invalid label component. */ this.invalid = false; /** * Set to `true` to show a warning (contents set by warningText) */ this.warn = false; /** * Set to `true` to hide the label visually, but keep accessible to * screen readers. */ this.hideLabel = false; /** * Set to `true` to render the label and field side-by-side instead of stacked. * Applies to `TextInput` and `PasswordInput` label variants. */ this.inline = false; /** * The render size for the `TextInput`. Used to compute INLINE label size * variant classes. */ this.size = "md"; /** * Set to `true` (`maxCount` must be set) to displays a live character/word * counter alongside the label. */ this.enableCounter = false; /** * Determines whether the `TextArea` counter counts characters or words. */ this.counterMode = "character"; } get labelClass() { return this.type === undefined; } /** * Update wrapper class if a textarea is hosted. */ ngAfterContentInit() { if (this.textArea) { this.type = "TextArea"; } else if (this.textInput) { this.type = "TextInput"; } else if (this.passwordInput) { this.type = "PasswordInput"; } } /** * Sets the id on the input item associated with the `Label`. */ ngAfterViewInit() { // Will only be called when `default` template is being used if (this.wrapper) { // Prioritize setting id to `input` & `textarea` over div const inputElement = this.wrapper.nativeElement.querySelector("input,textarea"); if (inputElement) { // avoid overriding ids already set by the user reuse it instead if (inputElement.id) { this.labelInputID = inputElement.id; this.changeDetectorRef.detectChanges(); } inputElement.setAttribute("id", this.labelInputID); return; } const divElement = this.wrapper.nativeElement.querySelector("div"); if (divElement) { if (divElement.id) { this.labelInputID = divElement.id; this.changeDetectorRef.detectChanges(); } divElement.setAttribute("id", this.labelInputID); } } } isTemplate(value) { return value instanceof TemplateRef; } } /** * Used to build the id of the input item associated with the `Label`. */ Label.labelCounter = 0; Label.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Label, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); Label.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Label, selector: "cds-label, ibm-label", inputs: { labelInputID: "labelInputID", disabled: "disabled", skeleton: "skeleton", helperText: "helperText", invalidText: "invalidText", invalid: "invalid", warn: "warn", warnText: "warnText", ariaLabel: "ariaLabel", hideLabel: "hideLabel", inline: "inline", size: "size", enableCounter: "enableCounter", maxCount: "maxCount", counterMode: "counterMode", decorator: "decorator" }, host: { properties: { "class.cds--form-item": "this.labelClass" } }, queries: [{ propertyName: "textArea", first: true, predicate: TextArea, descendants: true }, { propertyName: "textInput", first: true, predicate: TextInput, descendants: true }, { propertyName: "passwordInput", first: true, predicate: PasswordInput, descendants: true }], viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true }], ngImport: i0, template: ` <ng-template #inputContentTemplate> <ng-content select="input,textarea,div"></ng-content> </ng-template> <ng-template #labelContentTemplate> <ng-content></ng-content> </ng-template> <ng-container [ngSwitch]="type"> <ng-container *ngSwitchCase="'TextArea'"> <cds-textarea-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [enableCounter]="enableCounter" [maxCount]="maxCount" [counterMode]="counterMode" [decorator]="decorator" [labelTemplate]="labelContentTemplate" [textAreaTemplate]="inputContentTemplate"> </cds-textarea-label> </ng-container> <ng-container *ngSwitchCase="'TextInput'"> <cds-text-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [inline]="inline" [size]="size" [enableCounter]="enableCounter" [maxCount]="maxCount" [decorator]="decorator" [labelTemplate]="labelContentTemplate" [textInputTemplate]="inputContentTemplate"> </cds-text-label> </ng-container> <ng-container *ngSwitchCase="'PasswordInput'"> <cds-password-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [inline]="inline" [labelTemplate]="labelContentTemplate" [passwordInputTemplate]="inputContentTemplate"> </cds-password-label> </ng-container> <ng-container *ngSwitchDefault> <ng-template [ngTemplateOutlet]="default"></ng-template> </ng-container> </ng-container> <ng-template #default> <label [for]="labelInputID" [attr.aria-label]="ariaLabel" class="cds--label" [ngClass]="{ 'cds--label--disabled': disabled, 'cds--skeleton': skeleton }"> <ng-template [ngTemplateOutlet]="labelContentTemplate"></ng-template> </label> <div class="cds--text-input__field-wrapper" [ngClass]="{ 'cds--text-input__field-wrapper--warning': warn }" [attr.data-invalid]="(invalid ? true : null)" #wrapper> <svg *ngIf="invalid" cdsIcon="warning--filled" size="16" class="cds--text-input__invalid-icon"> </svg> <svg *ngIf="!invalid && warn" cdsIcon="warning--alt--filled" size="16" class="cds--text-input__invalid-icon cds--text-input__invalid-icon--warning"> </svg> <ng-template [ngTemplateOutlet]="inputContentTemplate"></ng-template> </div> <div *ngIf="!skeleton && helperText && !invalid && !warn" 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 *ngIf="invalid" class="cds--form-requirement"> <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-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: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3.TextareaLabelComponent, selector: "cds-textarea-label, ibm-textarea-label", inputs: ["labelInputID", "disabled", "skeleton", "labelTemplate", "textAreaTemplate", "helperText", "invalidText", "invalid", "warn", "warnText", "ariaLabel", "fluid", "hideLabel", "enableCounter", "maxCount", "counterMode", "decorator"] }, { kind: "component", type: i4.TextInputLabelComponent, selector: "cds-text-label, ibm-text-label", inputs: ["labelInputID", "disabled", "skeleton", "labelTemplate", "textInputTemplate", "helperText", "invalidText", "invalid", "warn", "warnText", "ariaLabel", "fluid", "decorator", "hideLabel", "inline", "size", "enableCounter", "maxCount"] }, { kind: "component", type: i5.PasswordInputLabelComponent, selector: "cds-password-label, ibm-password-label", inputs: ["labelInputID", "disabled", "skeleton", "labelTemplate", "passwordInputTemplate", "helperText", "invalidText", "invalid", "warn", "warnText", "ariaLabel", "hidePasswordLabel", "showPasswordLabel", "fluid", "hideLabel", "inline"], outputs: ["togglePasswordVisibility"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Label, decorators: [{ type: Component, args: [{ selector: "cds-label, ibm-label", template: ` <ng-template #inputContentTemplate> <ng-content select="input,textarea,div"></ng-content> </ng-template> <ng-template #labelContentTemplate> <ng-content></ng-content> </ng-template> <ng-container [ngSwitch]="type"> <ng-container *ngSwitchCase="'TextArea'"> <cds-textarea-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [enableCounter]="enableCounter" [maxCount]="maxCount" [counterMode]="counterMode" [decorator]="decorator" [labelTemplate]="labelContentTemplate" [textAreaTemplate]="inputContentTemplate"> </cds-textarea-label> </ng-container> <ng-container *ngSwitchCase="'TextInput'"> <cds-text-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [inline]="inline" [size]="size" [enableCounter]="enableCounter" [maxCount]="maxCount" [decorator]="decorator" [labelTemplate]="labelContentTemplate" [textInputTemplate]="inputContentTemplate"> </cds-text-label> </ng-container> <ng-container *ngSwitchCase="'PasswordInput'"> <cds-password-label [labelInputID]="labelInputID" [disabled]="disabled" [skeleton]="skeleton" [helperText]="helperText" [invalid]="invalid" [invalidText]="invalidText" [warn]="warn" [warnText]="warnText" [ariaLabel]="ariaLabel" [hideLabel]="hideLabel" [inline]="inline" [labelTemplate]="labelContentTemplate" [passwordInputTemplate]="inputContentTemplate"> </cds-password-label> </ng-container> <ng-container *ngSwitchDefault> <ng-template [ngTemplateOutlet]="default"></ng-template> </ng-container> </ng-container> <ng-template #default> <label [for]="labelInputID" [attr.aria-label]="ariaLabel" class="cds--label" [ngClass]="{ 'cds--label--disabled': disabled, 'cds--skeleton': skeleton }"> <ng-template [ngTemplateOutlet]="labelContentTemplate"></ng-template> </label> <div class="cds--text-input__field-wrapper" [ngClass]="{ 'cds--text-input__field-wrapper--warning': warn }" [attr.data-invalid]="(invalid ? true : null)" #wrapper> <svg *ngIf="invalid" cdsIcon="warning--filled" size="16" class="cds--text-input__invalid-icon"> </svg> <svg *ngIf="!invalid && warn" cdsIcon="warning--alt--filled" size="16" class="cds--text-input__invalid-icon cds--text-input__invalid-icon--warning"> </svg> <ng-template [ngTemplateOutlet]="inputContentTemplate"></ng-template> </div> <div *ngIf="!skeleton && helperText && !invalid && !warn" 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 *ngIf="invalid" class="cds--form-requirement"> <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-template> ` }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { labelInputID: [{ type: Input }], disabled: [{ type: Input }], skeleton: [{ type: Input }], helperText: [{ type: Input }], invalidText: [{ type: Input }], invalid: [{ type: Input }], warn: [{ type: Input }], warnText: [{ type: Input }], ariaLabel: [{ type: Input }], hideLabel: [{ type: Input }], inline: [{ type: Input }], size: [{ type: Input }], enableCounter: [{ type: Input }], maxCount: [{ type: Input }], counterMode: [{ type: Input }], decorator: [{ type: Input }], wrapper: [{ type: ViewChild, args: ["wrapper"] }], textArea: [{ type: ContentChild, args: [TextArea] }], textInput: [{ type: ContentChild, args: [TextInput, { static: false }] }], passwordInput: [{ type: ContentChild, args: [PasswordInput, { static: false }] }], labelClass: [{ type: HostBinding, args: ["class.cds--form-item"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFiZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2lucHV0L2xhYmVsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFHTCxXQUFXLEVBQ1gsV0FBVyxFQUNYLFNBQVMsRUFDVCxZQUFZLEVBR1osTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7Ozs7QUFFckQ7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBOEhILE1BQU0sT0FBTyxLQUFLO0lBbUdqQjs7T0FFRztJQUNILFlBQXNCLGlCQUFvQztRQUFwQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBakcxRDs7O1dBR0c7UUFDTSxpQkFBWSxHQUFHLGFBQWEsS0FBSyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7UUFDNUQ7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQVMxQjs7V0FFRztRQUNNLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDekI7O1dBRUc7UUFDTSxTQUFJLEdBQUcsS0FBSyxDQUFDO1FBVXRCOzs7V0FHRztRQUNNLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFFM0I7OztXQUdHO1FBQ00sV0FBTSxHQUFHLEtBQUssQ0FBQztRQUV4Qjs7O1dBR0c7UUFDTSxTQUFJLEdBQXVCLElBQUksQ0FBQztRQUV6Qzs7O1dBR0c7UUFDTSxrQkFBYSxHQUFHLEtBQUssQ0FBQztRQVEvQjs7V0FFRztRQUNNLGdCQUFXLEdBQXlCLFdBQVcsQ0FBQztJQTBCSSxDQUFDO0lBVDlELElBQXlDLFVB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QkFNRyxRQUFRO3NCQUFoQixLQUFLO2dCQUtHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBS0csU0FBUztzQkFBakIsS0FBSztnQkFFZ0IsT0FBTztzQkFBNUIsU0FBUzt1QkFBQyxTQUFTO2dCQUVJLFFBQVE7c0JBQS9CLFlBQVk7dUJBQUMsUUFBUTtnQkFHc0IsU0FBUztzQkFBcEQsWUFBWTt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUcxQyxhQUFhO3NCQURaLFlBQVk7dUJBQUMsYUFBYSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFHTCxVQUFVO3NCQUFsRCxXQUFXO3VCQUFDLHNCQUFzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0SW5wdXQsXG5cdEFmdGVyVmlld0luaXQsXG5cdEVsZW1lbnRSZWYsXG5cdEhvc3RCaW5kaW5nLFxuXHRUZW1wbGF0ZVJlZixcblx0Vmlld0NoaWxkLFxuXHRDb250ZW50Q2hpbGQsXG5cdEFmdGVyQ29udGVudEluaXQsXG5cdENoYW5nZURldGVjdG9yUmVmXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5cbmltcG9ydCB7IFRleHRBcmVhIH0gZnJvbSBcIi4vdGV4dC1hcmVhLmRpcmVjdGl2ZVwiO1xuaW1wb3J0IHsgVGV4dElucHV0IH0gZnJvbSBcIi4vaW5wdXQuZGlyZWN0aXZlXCI7XG5pbXBvcnQgeyBQYXNzd29yZElucHV0IH0gZnJvbSBcIi4vcGFzc3dvcmQuZGlyZWN0aXZlXCI7XG5cbi8qKlxuICogR2V0IHN0YXJ0ZWQgd2l0aCBpbXBvcnRpbmcgdGhlIG1vZHVsZTpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBJbnB1dE1vZHVsZSB9IGZyb20gJ2NhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXInO1xuICogYGBgXG4gKlxuICogVG8gcHJldmVudCBhdHRyaWJ1dGUgZHJpbGxpbmcsIHVzZSBgaWJtLXRleHQtbGFiZWxgIG9yIGBpYm0tdGV4dGFyZWEtbGFiZWxgIGNvbXBvbmVudHNcbiAqXG4gKiBgYGBodG1sXG4gKiA8Y2RzLWxhYmVsPlxuICogXHRMYWJlbFxuICogXHQ8aW5wdXQgY2RzVGV4dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiaW5wdXQtZmllbGRcIj5cbiAqIDwvY2RzLWxhYmVsPlxuICogYGBgXG4gKlxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy1pbnB1dC0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtbGFiZWwsIGlibS1sYWJlbFwiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxuZy10ZW1wbGF0ZSAjaW5wdXRDb250ZW50VGVtcGxhdGU+XG5cdFx0XHQ8bmctY29udGVudCBzZWxlY3Q9XCJpbnB1dCx0ZXh0YXJlYSxkaXZcIj48L25nLWNvbnRlbnQ+XG5cdFx0PC9uZy10ZW1wbGF0ZT5cblxuXHRcdDxuZy10ZW1wbGF0ZSAjbGFiZWxDb250ZW50VGVtcGxhdGU+XG5cdFx0XHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG5cdFx0PC9uZy10ZW1wbGF0ZT5cblxuXHRcdDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cInR5cGVcIj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidUZXh0QXJlYSdcIj5cblx0XHRcdFx0PGNkcy10ZXh0YXJlYS1sYWJlbFxuXHRcdFx0XHRcdFtsYWJlbElucHV0SURdPVwibGFiZWxJbnB1dElEXCJcblx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0XHRcdFtza2VsZXRvbl09XCJza2VsZXRvblwiXG5cdFx0XHRcdFx0W2hlbHBlclRleHRdPVwiaGVscGVyVGV4dFwiXG5cdFx0XHRcdFx0W2ludmFsaWRdPVwiaW52YWxpZFwiXG5cdFx0XHRcdFx0W2ludmFsaWRUZXh0XT1cImludmFsaWRUZXh0XCJcblx0XHRcdFx0XHRbd2Fybl09XCJ3YXJuXCJcblx0XHRcdFx0XHRbd2FyblRleHRdPVwid2FyblRleHRcIlxuXHRcdFx0XHRcdFthcmlhTGFiZWxdPVwiYXJpYUxhYmVsXCJcblx0XHRcdFx0XHRbaGlkZUxhYmVsXT1cImhpZGVMYWJlbFwiXG5cdFx0XHRcdFx0W2VuYWJsZUNvdW50ZXJdPVwiZW5hYmxlQ291bnRlclwiXG5cdFx0XHRcdFx0W21heENvdW50XT1cIm1heENvdW50XCJcblx0XHRcdFx0XHRbY291bnRlck1vZGVdPVwiY291bnRlck1vZGVcIlxuXHRcdFx0XHRcdFtkZWNvcmF0b3JdPVwiZGVjb3JhdG9yXCJcblx0XHRcdFx0XHRbbGFiZWxUZW1wbGF0ZV09XCJsYWJlbENvbnRlbnRUZW1wbGF0ZVwiXG5cdFx0XHRcdFx0W3RleHRBcmVhVGVtcGxhdGVdPVwiaW5wdXRDb250ZW50VGVtcGxhdGVcIj5cblx0XHRcdFx0PC9jZHMtdGV4dGFyZWEtbGFiZWw+XG5cdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidUZXh0SW5wdXQnXCI+XG5cdFx0XHRcdDxjZHMtdGV4dC1sYWJlbFxuXHRcdFx0XHRcdFtsYWJlbElucHV0SURdPVwibGFiZWxJbnB1dElEXCJcblx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0XHRcdFtza2VsZXRvbl09XCJza2VsZXRvblwiXG5cdFx0XHRcdFx0W2hlbHBlclRleHRdPVwiaGVscGVyVGV4dFwiXG5cdFx0XHRcdFx0W2ludmFsaWRdPVwiaW52YWxpZFwiXG5cdFx0XHRcdFx0W2ludmFsaWRUZXh0XT1cImludmFsaWRUZXh0XCJcblx0XHRcdFx0XHRbd2Fybl09XCJ3YXJuXCJcblx0XHRcdFx0XHRbd2FyblRleHRdPVwid2FyblRleHRcIlxuXHRcdFx0XHRcdFthcmlhTGFiZWxdPVwiYXJpYUxhYmVsXCJcblx0XHRcdFx0XHRbaGlkZUxhYmVsXT1cImhpZGVMYWJlbFwiXG5cdFx0XHRcdFx0W2lubGluZV09XCJpbmxpbmVcIlxuXHRcdFx0XHRcdFtzaXplXT1cInNpemVcIlxuXHRcdFx0XHRcdFtlbmFibGVDb3VudGVyXT1cImVuYWJsZUNvdW50ZXJcIlxuXHRcdFx0XHRcdFttYXhDb3VudF09XCJtYXhDb3VudFwiXG5cdFx0XHRcdFx0W2RlY29yYXRvcl09XCJkZWNvcmF0b3JcIlxuXHRcdFx0XHRcdFtsYWJlbFRlbXBsYXRlXT1cImxhYmVsQ29udGVudFRlbXBsYXRlXCJcblx0XHRcdFx0XHRbdGV4dElucHV0VGVtcGxhdGVdPVwiaW5wdXRDb250ZW50VGVtcGxhdGVcIj5cblx0XHRcdFx0PC9jZHMtdGV4dC1sYWJlbD5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ1Bhc3N3b3JkSW5wdXQnXCI+XG5cdFx0XHRcdDxjZHMtcGFzc3dvcmQtbGFiZWxcblx0XHRcdFx0XHRbbGFiZWxJbnB1dElEXT1cImxhYmVsSW5wdXRJRFwiXG5cdFx0XHRcdFx0W2Rpc2FibGVkXT1cImRpc2FibGVkXCJcblx0XHRcdFx0XHRbc2tlbGV0b25dPVwic2tlbGV0b25cIlxuXHRcdFx0XHRcdFtoZWxwZXJUZXh0XT1cImhlbHBlclRleHRcIlxuXHRcdFx0XHRcdFtpbnZhbGlkXT1cImludmFsaWRcIlxuXHRcdFx0XHRcdFtpbnZhbGlkVGV4dF09XCJpbnZhbGlkVGV4dFwiXG5cdFx0XHRcdFx0W3dhcm5dPVwid2FyblwiXG5cdFx0XHRcdFx0W3dhcm5UZXh0XT1cIndhcm5UZXh0XCJcblx0XHRcdFx0XHRbYXJpYUxhYmVsXT1cImFyaWFMYWJlbFwiXG5cdFx0XHRcdFx0W2hpZGVMYWJlbF09XCJoaWRlTGFiZWxcIlxuXHRcdFx0XHRcdFtpbmxpbmVdPVwiaW5saW5lXCJcblx0XHRcdFx0XHRbbGFiZWxUZW1wbGF0ZV09XCJsYWJlbENvbnRlbnRUZW1wbGF0ZVwiXG5cdFx0XHRcdFx0W3Bhc3N3b3JkSW5wdXRUZW1wbGF0ZV09XCJpbnB1dENvbnRlbnRUZW1wbGF0ZVwiPlxuXHRcdFx0XHQ8L2Nkcy1wYXNzd29yZC1sYWJlbD5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hEZWZhdWx0PlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwiZGVmYXVsdFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHQ8L25nLWNvbnRhaW5lcj5cblxuXHRcdDxuZy10ZW1wbGF0ZSAjZGVmYXVsdD5cblx0XHRcdDxsYWJlbFxuXHRcdFx0XHRbZm9yXT1cImxhYmVsSW5wdXRJRFwiXG5cdFx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsXCJcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLWxhYmVsXCJcblx0XHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHRcdCdjZHMtLWxhYmVsLS1kaXNhYmxlZCc6IGRpc2FibGVkLFxuXHRcdFx0XHRcdCdjZHMtLXNrZWxldG9uJzogc2tlbGV0b25cblx0XHRcdFx0fVwiPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwibGFiZWxDb250ZW50VGVtcGxhdGVcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0PC9sYWJlbD5cblx0XHRcdDxkaXZcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLXRleHQtaW5wdXRfX2ZpZWxkLXdyYXBwZXJcIlxuXHRcdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdFx0J2Nkcy0tdGV4dC1pbnB1dF9fZmllbGQtd3JhcHBlci0td2FybmluZyc6IHdhcm5cblx0XHRcdFx0fVwiXG5cdFx0XHRcdFthdHRyLmRhdGEtaW52YWxpZF09XCIoaW52YWxpZCA/IHRydWUgOiBudWxsKVwiXG5cdFx0XHRcdCN3cmFwcGVyPlxuXHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0Km5nSWY9XCJpbnZhbGlkXCJcblx0XHRcdFx0XHRjZHNJY29uPVwid2FybmluZy0tZmlsbGVkXCJcblx0XHRcdFx0XHRzaXplPVwiMTZcIlxuXHRcdFx0XHRcdGNsYXNzPVwiY2RzLS10ZXh0LWlucHV0X19pbnZhbGlkLWljb25cIj5cblx0XHRcdFx0PC9zdmc+XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHQqbmdJZj1cIiFpbnZhbGlkICYmIHdhcm5cIlxuXHRcdFx0XHRcdGNkc0ljb249XCJ3YXJuaW5nLS1hbHQtLWZpbGxlZFwiXG5cdFx0XHRcdFx0c2l6ZT1cIjE2XCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tdGV4dC1pbnB1dF9faW52YWxpZC1pY29uIGNkcy0tdGV4dC1pbnB1dF9faW52YWxpZC1pY29uLS13YXJuaW5nXCI+XG5cdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwiaW5wdXRDb250ZW50VGVtcGxhdGVcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0PC9kaXY+XG5cdFx0XHQ8ZGl2XG5cdFx0XHRcdCpuZ0lmPVwiIXNrZWxldG9uICYmIGhlbHBlclRleHQgJiYgIWludmFsaWQgJiYgIXdhcm5cIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tZm9ybV9faGVscGVyLXRleHRcIlxuXHRcdFx0XHRbbmdDbGFzc109XCJ7J2Nkcy0tZm9ybV9faGVscGVyLXRleHQtLWRpc2FibGVkJzogZGlzYWJsZWR9XCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShoZWxwZXJUZXh0KVwiPnt7aGVscGVyVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaGVscGVyVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJoZWxwZXJUZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdDwvZGl2PlxuXHRcdFx0PGRpdiAqbmdJZj1cImludmFsaWRcIiBjbGFzcz1cImNkcy0tZm9ybS1yZXF1aXJlbWVudFwiPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUoaW52YWxpZFRleHQpXCI+e3tpbnZhbGlkVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaW52YWxpZFRleHQpXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaW52YWxpZFRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0PC9kaXY+XG5cdFx0XHQ8ZGl2ICpuZ0lmPVwiIWludmFsaWQgJiYgd2FyblwiIGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZSh3YXJuVGV4dClcIj57e3dhcm5UZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZSh3YXJuVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJ3YXJuVGV4dFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L2Rpdj5cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRgXG59KVxuZXhwb3J0IGNsYXNzIExhYmVsIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cdC8qKlxuXHQgKiBVc2VkIHRvIGJ1aWxkIHRoZSBpZCBvZiB0aGUgaW5wdXQgaXRlbSBhc3NvY2lhdGVkIHdpdGggdGhlIGBMYWJlbGAuXG5cdCAqL1xuXHRzdGF0aWMgbGFiZWxDb3VudGVyID0gMDtcblx0LyoqXG5cdCAqIFRoZSBpZCBvZiB0aGUgaW5wdXQgaXRlbSBhc3NvY2lhdGVkIHdpdGggdGhlIGBMYWJlbGAuIFRoaXMgdmFsdWUgaXMgYWxzbyB1c2VkIHRvIGFzc29jaWF0ZSB0aGUgYExhYmVsYCB3aXRoXG5cdCAqIGl0cyBpbnB1dCBjb3VudGVycGFydCB0aHJvdWdoIHRoZSAnZm9yJyBhdHRyaWJ1dGUuXG5cdCAqL1xuXHRASW5wdXQoKSBsYWJlbElucHV0SUQgPSBgY2RzLWxhYmVsLSR7TGFiZWwubGFiZWxDb3VudGVyKyt9YDtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgZm9yIGRpc2FibGVkIHN0YXRlLlxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgZm9yIGEgbG9hZGluZyBsYWJlbC5cblx0ICovXG5cdEBJbnB1dCgpIHNrZWxldG9uID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBPcHRpb25hbCBoZWxwZXIgdGV4dCB0aGF0IGFwcGVhcnMgdW5kZXIgdGhlIGxhYmVsLlxuXHQgKi9cblx0QElucHV0KCkgaGVscGVyVGV4dDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55Pjtcblx0LyoqXG5cdCAqIFNldHMgdGhlIGludmFsaWQgdGV4dC5cblx0ICovXG5cdEBJbnB1dCgpIGludmFsaWRUZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYW4gaW52YWxpZCBsYWJlbCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBpbnZhbGlkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIHNob3cgYSB3YXJuaW5nIChjb250ZW50cyBzZXQgYnkgd2FybmluZ1RleHQpXG5cdCAqL1xuXHRASW5wdXQoKSB3YXJuID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB3YXJuaW5nIHRleHRcblx0ICovXG5cdEBJbnB1dCgpIHdhcm5UZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0IHRoZSBhcmlhbGFiZWwgZm9yIGxhYmVsXG5cdCAqL1xuXHRASW5wdXQoKSBhcmlhTGFiZWw6IHN0cmluZztcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byBoaWRlIHRoZSBsYWJlbCB2aXN1YWxseSwgYnV0IGtlZXAgYWNjZXNzaWJsZSB0b1xuXHQgKiBzY3JlZW4gcmVhZGVycy5cblx0ICovXG5cdEBJbnB1dCgpIGhpZGVMYWJlbCA9IGZhbHNlO1xuXG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIHJlbmRlciB0aGUgbGFiZWwgYW5kIGZpZWxkIHNpZGUtYnktc2lkZSBpbnN0ZWFkIG9mIHN0YWNrZWQuXG5cdCAqIEFwcGxpZXMgdG8gYFRleHRJbnB1dGAgYW5kIGBQYXNzd29yZElucHV0YCBsYWJlbCB2YXJpYW50cy5cblx0ICovXG5cdEBJbnB1dCgpIGlubGluZSA9IGZhbHNlO1xuXG5cdC8qKlxuXHQgKiBUaGUgcmVuZGVyIHNpemUgZm9yIHRoZSBgVGV4dElucHV0YC4gVXNlZCB0byBjb21wdXRlIElOTElORSBsYWJlbCBzaXplXG5cdCAqIHZhcmlhbnQgY2xhc3Nlcy5cblx0ICovXG5cdEBJbnB1dCgpIHNpemU6IFwic21cIiB8IFwibWRcIiB8IFwibGdcIiA9IFwibWRcIjtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCAoYG1heENvdW50YCBtdXN0IGJlIHNldCkgdG8gZGlzcGxheXMgYSBsaXZlIGNoYXJhY3Rlci93b3JkXG5cdCAqIGNvdW50ZXIgYWxvbmdzaWRlIHRoZSBsYWJlbC5cblx0ICovXG5cdEBJbnB1dCgpIGVuYWJsZUNvdW50ZXIgPSBmYWxzZTtcblxuXHQvKipcblx0ICogTWF4aW11bSBudW1iZXIgb2YgY2hhcmFjdGVycyAob3Igd29yZHMpIGFsbG93ZWQuIFJlcXVpcmVkIGZvciB0aGVcblx0ICogY291bnRlciB0byBkaXNwbGF5LlxuXHQgKi9cblx0QElucHV0KCkgbWF4Q291bnQ6IG51bWJlcjtcblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBgVGV4dEFyZWFgIGNvdW50ZXIgY291bnRzIGNoYXJhY3RlcnMgb3Igd29yZHMuXG5cdCAqL1xuXHRASW5wdXQoKSBjb3VudGVyTW9kZTogXCJjaGFyYWN0ZXJcIiB8IFwid29yZFwiID0gXCJjaGFyYWN0ZXJcIjtcblxuXHQvKipcblx0ICogKipFeHBlcmltZW50YWwqKjogT3B0aW9uYWwgZGVjb3JhdG9yIChlLmcuIEFJIGxhYmVsKS5cblx0ICovXG5cdEBJbnB1dCgpIGRlY29yYXRvcjogVGVtcGxhdGVSZWY8YW55PjtcblxuXHRAVmlld0NoaWxkKFwid3JhcHBlclwiKSB3cmFwcGVyOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcblxuXHRAQ29udGVudENoaWxkKFRleHRBcmVhKSB0ZXh0QXJlYTogVGV4dEFyZWE7XG5cblx0Ly8gQHRzLWlnbm9yZVxuXHRAQ29udGVudENoaWxkKFRleHRJbnB1dCwgeyBzdGF0aWM6IGZhbHNlIH0pIHRleHRJbnB1dDogVGV4dElucHV0O1xuXG5cdEBDb250ZW50Q2hpbGQoUGFzc3dvcmRJbnB1dCwgeyBzdGF0aWM6IGZhbHNlIH0pXG5cdHBhc3N3b3JkSW5wdXQ6IFBhc3N3b3JkSW5wdXQ7XG5cblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1mb3JtLWl0ZW1cIikgZ2V0IGxhYmVsQ2xhc3MoKSB7XG5cdFx0cmV0dXJuIHRoaXMudHlwZSA9PT0gdW5kZWZpbmVkO1xuXHR9XG5cblx0dHlwZTogXCJUZXh0QXJlYVwiIHwgXCJUZXh0SW5wdXRcIiB8IFwiUGFzc3dvcmRJbnB1dFwiO1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIExhYmVsLlxuXHQgKi9cblx0Y29uc3RydWN0b3IocHJvdGVjdGVkIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuXHQvKipcblx0ICogVXBkYXRlIHdyYXBwZXIgY2xhc3MgaWYgYSB0ZXh0YXJlYSBpcyBob3N0ZWQuXG5cdCAqL1xuXHRuZ0FmdGVyQ29udGVudEluaXQoKSB7XG5cdFx0aWYgKHRoaXMudGV4dEFyZWEpIHtcblx0XHRcdHRoaXMudHlwZSA9IFwiVGV4dEFyZWFcIjtcblx0XHR9IGVsc2UgaWYgKHRoaXMudGV4dElucHV0KSB7XG5cdFx0XHR0aGlzLnR5cGUgPSBcIlRleHRJbnB1dFwiO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5wYXNzd29yZElucHV0KSB7XG5cdFx0XHR0aGlzLnR5cGUgPSBcIlBhc3N3b3JkSW5wdXRcIjtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgaWQgb24gdGhlIGlucHV0IGl0ZW0gYXNzb2NpYXRlZCB3aXRoIHRoZSBgTGFiZWxgLlxuXHQgKi9cblx0bmdBZnRlclZpZXdJbml0KCkge1xuXHRcdC8vIFdpbGwgb25seSBiZSBjYWxsZWQgd2hlbiBgZGVmYXVsdGAgdGVtcGxhdGUgaXMgYmVpbmcgdXNlZFxuXHRcdGlmICh0aGlzLndyYXBwZXIpIHtcblx0XHRcdC8vIFByaW9yaXRpemUgc2V0dGluZyBpZCB0byBgaW5wdXRgICYgYHRleHRhcmVhYCBvdmVyIGRpdlxuXHRcdFx0Y29uc3QgaW5wdXRFbGVtZW50ID0gdGhpcy53cmFwcGVyLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcImlucHV0LHRleHRhcmVhXCIpO1xuXHRcdFx0aWYgKGlucHV0RWxlbWVudCkge1xuXHRcdFx0XHQvLyBhdm9pZCBvdmVycmlkaW5nIGlkcyBhbHJlYWR5IHNldCBieSB0aGUgdXNlciByZXVzZSBpdCBpbnN0ZWFkXG5cdFx0XHRcdGlmIChpbnB1dEVsZW1lbnQuaWQpIHtcblx0XHRcdFx0XHR0aGlzLmxhYmVsSW5wdXRJRCA9IGlucHV0RWxlbWVudC5pZDtcblx0XHRcdFx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpbnB1dEVsZW1lbnQuc2V0QXR0cmlidXRlKFwiaWRcIiwgdGhpcy5sYWJlbElucHV0SUQpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGRpdkVsZW1lbnQgPSB0aGlzLndyYXBwZXIubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiZGl2XCIpO1xuXHRcdFx0aWYgKGRpdkVsZW1lbnQpIHtcblx0XHRcdFx0aWYgKGRpdkVsZW1lbnQuaWQpIHtcblx0XHRcdFx0XHR0aGlzLmxhYmVsSW5wdXRJRCA9IGRpdkVsZW1lbnQuaWQ7XG5cdFx0XHRcdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGl2RWxlbWVudC5zZXRBdHRyaWJ1dGUoXCJpZFwiLCB0aGlzLmxhYmVsSW5wdXRJRCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIGlzVGVtcGxhdGUodmFsdWUpIHtcblx0XHRyZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUZW1wbGF0ZVJlZjtcblx0fVxufVxuIl19