@taiga-ui/addon-doc
Version:
Taiga UI based library for developing documentation portals for Angular libraries.
118 lines • 33.7 kB
JavaScript
import { Location, NgForOf, NgIf, NgSwitch, NgSwitchCase } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, inject, Input, Output, } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, UrlSerializer } from '@angular/router';
import { TUI_DOC_ICONS, TUI_DOC_URL_STATE_HANDLER } from '@taiga-ui/addon-doc/tokens';
import { tuiCoerceValue, tuiInspectAny } from '@taiga-ui/addon-doc/utils';
import { tuiIsNumber } from '@taiga-ui/cdk/utils/miscellaneous';
import { TuiAlertService } from '@taiga-ui/core/components/alert';
import { TuiIcon } from '@taiga-ui/core/components/icon';
import { TuiTextfield } from '@taiga-ui/core/components/textfield';
import { TuiDataListWrapper } from '@taiga-ui/kit/components/data-list-wrapper';
import { TuiInputNumber } from '@taiga-ui/kit/components/input-number';
import { TuiSwitch } from '@taiga-ui/kit/components/switch';
import { TuiChevron } from '@taiga-ui/kit/directives/chevron';
import { TuiInspectPipe } from '../documentation/pipes/inspect.pipe';
import { TuiDocTypeReferencePipe } from '../documentation/pipes/type-reference.pipe';
import { TuiDocAPINumberItem } from './api-item-number.directive';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@taiga-ui/kit/components/data-list-wrapper";
import * as i3 from "@taiga-ui/kit/components/input-number";
import * as i4 from "@taiga-ui/core/components/textfield";
const SERIALIZED_SUFFIX = '$';
class TuiDocAPIItem {
constructor() {
this.locationRef = inject(Location);
this.activatedRoute = inject(ActivatedRoute);
this.urlSerializer = inject(UrlSerializer);
this.urlStateHandler = inject(TUI_DOC_URL_STATE_HANDLER);
this.alerts = inject(TuiAlertService);
this.icons = inject(TUI_DOC_ICONS);
this.numberItem = inject(TuiDocAPINumberItem, {
self: true,
optional: true,
});
this.name = '';
this.type = '';
this.items = [];
this.valueChange = new EventEmitter();
}
ngAfterViewInit() {
this.parseParams(this.activatedRoute.snapshot.queryParams);
}
onValueChange(value) {
this.value = value;
this.valueChange.emit(value);
this.setQueryParam(value);
}
emitEvent(event) {
console.info('emitEvent', event);
const alert = !event || event?.toString() === '[object Object]'
? tuiInspectAny(event, 2)
: event;
this.alerts.open(alert, { label: this.name }).subscribe();
}
clearBrackets(value) {
return value.replaceAll(/[()[\]]/g, '');
}
parseParams(params) {
const name = this.clearBrackets(this.name);
const propertyValue = params[name];
const propertyValueWithSuffix = params[`${name}${SERIALIZED_SUFFIX}`];
if (!propertyValue && !propertyValueWithSuffix) {
return;
}
let value = !!propertyValueWithSuffix && this.items
? this.items[propertyValueWithSuffix]
: tuiCoerceValue(propertyValue);
if (this.type === 'string' && tuiIsNumber(value)) {
value = value.toString();
}
this.onValueChange(value);
}
setQueryParam(value) {
const tree = this.urlSerializer.parse(this.locationRef.path());
const isValueAvailableByKey = value instanceof Object;
const computedValue = isValueAvailableByKey && this.items ? this.items.indexOf(value) : value;
const suffix = isValueAvailableByKey ? SERIALIZED_SUFFIX : '';
const propName = this.clearBrackets(this.name) + suffix;
tree.queryParams = {
...tree.queryParams,
[propName]: computedValue,
};
this.locationRef.go(this.urlStateHandler(tree));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiDocAPIItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TuiDocAPIItem, isStandalone: true, selector: "tr[tuiDocAPIItem]", inputs: { name: "name", type: "type", value: "value", items: "items" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<td class=\"t-td\">\n <code\n class=\"t-name\"\n [class.t-name_banana]=\"name.startsWith('[(')\"\n [class.t-name_input]=\"name.startsWith('[')\"\n [class.t-name_output]=\"name.startsWith('(')\"\n >\n {{ name }}\n </code>\n <ng-content />\n</td>\n<td class=\"t-td\">\n <code class=\"t-type\">\n <ng-container *ngFor=\"let item of type | tuiDocTypeReference; let last = last\">\n <a\n *ngIf=\"item.reference; else default\"\n target=\"_blank\"\n class=\"t-reference\"\n [attr.href]=\"item.reference\"\n >\n {{ item.type }}\n <tui-icon\n *ngIf=\"icons.externalLink\"\n [icon]=\"icons.externalLink\"\n [style.font-size.rem]=\"1\"\n />\n </a>\n <ng-template #default>\n {{ item.type }}\n </ng-template>\n <span *ngIf=\"!last\"> | </span>\n </ng-container>\n </code>\n</td>\n<td class=\"t-td\">\n <tui-textfield\n *ngIf=\"items.length; else noItems\"\n tuiChevron\n tuiTextfieldSize=\"m\"\n class=\"t-input\"\n [content]=\"content\"\n [tuiTextfieldCleaner]=\"type.includes('null') || type.includes('PolymorpheusContent')\"\n >\n <select\n placeholder=\"null\"\n tuiTextfield\n [ngModel]=\"value ?? null\"\n (ngModelChange)=\"onValueChange($event)\"\n ></select>\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n [itemContent]=\"content\"\n [items]=\"items\"\n />\n </tui-textfield>\n <ng-template\n #content\n let-data\n >\n <code [style.margin]=\"0\">{{ data | tuiInspectAny }}</code>\n </ng-template>\n <ng-template #noItems>\n <ng-container\n *ngIf=\"value !== undefined\"\n [ngSwitch]=\"type\"\n >\n <input\n *ngSwitchCase=\"'boolean'\"\n tuiSwitch\n type=\"checkbox\"\n [id]=\"name\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n />\n\n <tui-textfield\n *ngSwitchCase=\"'string'\"\n tuiTextfieldSize=\"m\"\n class=\"t-input\"\n >\n <input\n tuiTextfield\n [id]=\"name\"\n [ngModel]=\"value || ''\"\n (ngModelChange)=\"onValueChange($event)\"\n />\n </tui-textfield>\n\n <tui-textfield\n *ngSwitchCase=\"'number'\"\n tuiTextfieldSize=\"m\"\n >\n <input\n tuiInputNumber\n [id]=\"name\"\n [max]=\"numberItem?.max ?? null\"\n [min]=\"numberItem?.min ?? null\"\n [ngModel]=\"value\"\n [step]=\"1\"\n (ngModelChange)=\"onValueChange($event || 0)\"\n />\n </tui-textfield>\n </ng-container>\n </ng-template>\n</td>\n", styles: [":host{box-shadow:inset 0 -1px var(--tui-border-normal)}.t-td{padding:1.5rem 2rem 1.5rem 0;vertical-align:top}.t-td:last-child{padding-inline-end:0;text-align:end;min-inline-size:10rem}.t-name{display:flex!important;min-block-size:1.5rem;inline-size:-webkit-fit-content;inline-size:-moz-fit-content;inline-size:fit-content;margin:0 0 .5rem!important;-webkit-text-fill-color:var(--tui-background-accent-2-pressed)}.t-name_input{-webkit-text-fill-color:var(--tui-text-negative)}.t-name_banana{-webkit-text-fill-color:var(--tui-text-action)}.t-name_output{-webkit-text-fill-color:var(--tui-status-info)}.t-type{flex-wrap:wrap;align-items:center;justify-content:flex-start;min-block-size:1.5rem;margin:0!important}.t-reference{display:inline-flex;color:var(--tui-text-action);text-decoration:none;align-items:center;justify-content:center;gap:3px}.t-input{min-inline-size:10rem;margin-block-start:-.625rem}.t-input code{overflow:hidden;white-space:nowrap}@media screen and (max-width: 47.9625em){:host{gap:1rem;padding:1rem 0}.t-td{padding:0}.t-td:last-child{text-align:start}.t-input{margin:0}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "component", type: i2.TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "pipe", type: TuiDocTypeReferencePipe, name: "tuiDocTypeReference" }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "directive", type: i3.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "component", type: i3.TuiInputNumberStep, selector: "input[tuiInputNumber][step]", inputs: ["step"] }, { kind: "pipe", type: TuiInspectPipe, name: "tuiInspectAny" }, { kind: "component", type: TuiSwitch, selector: "input[type=\"checkbox\"][tuiSwitch]", inputs: ["size", "showIcons"] }, { kind: "component", type: i4.TuiSelect, selector: "select[tuiTextfield]", inputs: ["placeholder"] }, { kind: "component", type: i4.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i4.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i4.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i4.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
export { TuiDocAPIItem };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiDocAPIItem, decorators: [{
type: Component,
args: [{ standalone: true, selector: 'tr[tuiDocAPIItem]', imports: [
FormsModule,
NgForOf,
NgIf,
NgSwitch,
NgSwitchCase,
TuiChevron,
TuiDataListWrapper,
TuiDocTypeReferencePipe,
TuiIcon,
TuiInputNumber,
TuiInspectPipe,
TuiSwitch,
TuiTextfield,
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<td class=\"t-td\">\n <code\n class=\"t-name\"\n [class.t-name_banana]=\"name.startsWith('[(')\"\n [class.t-name_input]=\"name.startsWith('[')\"\n [class.t-name_output]=\"name.startsWith('(')\"\n >\n {{ name }}\n </code>\n <ng-content />\n</td>\n<td class=\"t-td\">\n <code class=\"t-type\">\n <ng-container *ngFor=\"let item of type | tuiDocTypeReference; let last = last\">\n <a\n *ngIf=\"item.reference; else default\"\n target=\"_blank\"\n class=\"t-reference\"\n [attr.href]=\"item.reference\"\n >\n {{ item.type }}\n <tui-icon\n *ngIf=\"icons.externalLink\"\n [icon]=\"icons.externalLink\"\n [style.font-size.rem]=\"1\"\n />\n </a>\n <ng-template #default>\n {{ item.type }}\n </ng-template>\n <span *ngIf=\"!last\"> | </span>\n </ng-container>\n </code>\n</td>\n<td class=\"t-td\">\n <tui-textfield\n *ngIf=\"items.length; else noItems\"\n tuiChevron\n tuiTextfieldSize=\"m\"\n class=\"t-input\"\n [content]=\"content\"\n [tuiTextfieldCleaner]=\"type.includes('null') || type.includes('PolymorpheusContent')\"\n >\n <select\n placeholder=\"null\"\n tuiTextfield\n [ngModel]=\"value ?? null\"\n (ngModelChange)=\"onValueChange($event)\"\n ></select>\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n [itemContent]=\"content\"\n [items]=\"items\"\n />\n </tui-textfield>\n <ng-template\n #content\n let-data\n >\n <code [style.margin]=\"0\">{{ data | tuiInspectAny }}</code>\n </ng-template>\n <ng-template #noItems>\n <ng-container\n *ngIf=\"value !== undefined\"\n [ngSwitch]=\"type\"\n >\n <input\n *ngSwitchCase=\"'boolean'\"\n tuiSwitch\n type=\"checkbox\"\n [id]=\"name\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n />\n\n <tui-textfield\n *ngSwitchCase=\"'string'\"\n tuiTextfieldSize=\"m\"\n class=\"t-input\"\n >\n <input\n tuiTextfield\n [id]=\"name\"\n [ngModel]=\"value || ''\"\n (ngModelChange)=\"onValueChange($event)\"\n />\n </tui-textfield>\n\n <tui-textfield\n *ngSwitchCase=\"'number'\"\n tuiTextfieldSize=\"m\"\n >\n <input\n tuiInputNumber\n [id]=\"name\"\n [max]=\"numberItem?.max ?? null\"\n [min]=\"numberItem?.min ?? null\"\n [ngModel]=\"value\"\n [step]=\"1\"\n (ngModelChange)=\"onValueChange($event || 0)\"\n />\n </tui-textfield>\n </ng-container>\n </ng-template>\n</td>\n", styles: [":host{box-shadow:inset 0 -1px var(--tui-border-normal)}.t-td{padding:1.5rem 2rem 1.5rem 0;vertical-align:top}.t-td:last-child{padding-inline-end:0;text-align:end;min-inline-size:10rem}.t-name{display:flex!important;min-block-size:1.5rem;inline-size:-webkit-fit-content;inline-size:-moz-fit-content;inline-size:fit-content;margin:0 0 .5rem!important;-webkit-text-fill-color:var(--tui-background-accent-2-pressed)}.t-name_input{-webkit-text-fill-color:var(--tui-text-negative)}.t-name_banana{-webkit-text-fill-color:var(--tui-text-action)}.t-name_output{-webkit-text-fill-color:var(--tui-status-info)}.t-type{flex-wrap:wrap;align-items:center;justify-content:flex-start;min-block-size:1.5rem;margin:0!important}.t-reference{display:inline-flex;color:var(--tui-text-action);text-decoration:none;align-items:center;justify-content:center;gap:3px}.t-input{min-inline-size:10rem;margin-block-start:-.625rem}.t-input code{overflow:hidden;white-space:nowrap}@media screen and (max-width: 47.9625em){:host{gap:1rem;padding:1rem 0}.t-td{padding:0}.t-td:last-child{text-align:start}.t-input{margin:0}}\n"] }]
}], propDecorators: { name: [{
type: Input
}], type: [{
type: Input
}], value: [{
type: Input
}], items: [{
type: Input
}], valueChange: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLWl0ZW0uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYWRkb24tZG9jL2NvbXBvbmVudHMvYXBpL2FwaS1pdGVtLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FkZG9uLWRvYy9jb21wb25lbnRzL2FwaS9hcGktaXRlbS50ZW1wbGF0ZS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFaEYsT0FBTyxFQUNILHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUMsY0FBYyxFQUFFLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzlELE9BQU8sRUFBQyxhQUFhLEVBQUUseUJBQXlCLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRixPQUFPLEVBQUMsY0FBYyxFQUFFLGFBQWEsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQ3hFLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUM5RCxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxxQ0FBcUMsQ0FBQztBQUNqRSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSw0Q0FBNEMsQ0FBQztBQUM5RSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sdUNBQXVDLENBQUM7QUFDckUsT0FBTyxFQUFDLFNB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QkFBdUIsNERBQ3ZCLE9BQU8sd1VBRVAsY0FBYyxzREFDZCxTQUFTOztTQU9KLGFBQWE7NEZBQWIsYUFBYTtrQkF0QnpCLFNBQVM7aUNBQ00sSUFBSSxZQUNOLG1CQUFtQixXQUNwQjt3QkFDTCxXQUFXO3dCQUNYLE9BQU87d0JBQ1AsSUFBSTt3QkFDSixRQUFRO3dCQUNSLFlBQVk7d0JBQ1osVUFBVTt3QkFDVixrQkFBa0I7d0JBQ2xCLHVCQUF1Qjt3QkFDdkIsT0FBTzt3QkFDUCxjQUFjO3dCQUNkLGNBQWM7d0JBQ2QsU0FBUzt3QkFDVCxZQUFZO3FCQUNmLG1CQUdnQix1QkFBdUIsQ0FBQyxNQUFNOzhCQWlCeEMsSUFBSTtzQkFEVixLQUFLO2dCQUlDLElBQUk7c0JBRFYsS0FBSztnQkFJQyxLQUFLO3NCQURYLEtBQUs7Z0JBSUMsS0FBSztzQkFEWCxLQUFLO2dCQUlVLFdBQVc7c0JBRDFCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0xvY2F0aW9uLCBOZ0Zvck9mLCBOZ0lmLCBOZ1N3aXRjaCwgTmdTd2l0Y2hDYXNlfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHR5cGUge0FmdGVyVmlld0luaXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDb21wb25lbnQsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGluamVjdCxcbiAgICBJbnB1dCxcbiAgICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtGb3Jtc01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHR5cGUge1BhcmFtc30gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7QWN0aXZhdGVkUm91dGUsIFVybFNlcmlhbGl6ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1RVSV9ET0NfSUNPTlMsIFRVSV9ET0NfVVJMX1NUQVRFX0hBTkRMRVJ9IGZyb20gJ0B0YWlnYS11aS9hZGRvbi1kb2MvdG9rZW5zJztcbmltcG9ydCB7dHVpQ29lcmNlVmFsdWUsIHR1aUluc3BlY3RBbnl9IGZyb20gJ0B0YWlnYS11aS9hZGRvbi1kb2MvdXRpbHMnO1xuaW1wb3J0IHt0dWlJc051bWJlcn0gZnJvbSAnQHRhaWdhLXVpL2Nkay91dGlscy9taXNjZWxsYW5lb3VzJztcbmltcG9ydCB7VHVpQWxlcnRTZXJ2aWNlfSBmcm9tICdAdGFpZ2EtdWkvY29yZS9jb21wb25lbnRzL2FsZXJ0JztcbmltcG9ydCB7VHVpSWNvbn0gZnJvbSAnQHRhaWdhLXVpL2NvcmUvY29tcG9uZW50cy9pY29uJztcbmltcG9ydCB7VHVpVGV4dGZpZWxkfSBmcm9tICdAdGFpZ2EtdWkvY29yZS9jb21wb25lbnRzL3RleHRmaWVsZCc7XG5pbXBvcnQge1R1aURhdGFMaXN0V3JhcHBlcn0gZnJvbSAnQHRhaWdhLXVpL2tpdC9jb21wb25lbnRzL2RhdGEtbGlzdC13cmFwcGVyJztcbmltcG9ydCB7VHVpSW5wdXROdW1iZXJ9IGZyb20gJ0B0YWlnYS11aS9raXQvY29tcG9uZW50cy9pbnB1dC1udW1iZXInO1xuaW1wb3J0IHtUdWlTd2l0Y2h9IGZyb20gJ0B0YWlnYS11aS9raXQvY29tcG9uZW50cy9zd2l0Y2gnO1xuaW1wb3J0IHtUdWlDaGV2cm9ufSBmcm9tICdAdGFpZ2EtdWkva2l0L2RpcmVjdGl2ZXMvY2hldnJvbic7XG5cbmltcG9ydCB7VHVpSW5zcGVjdFBpcGV9IGZyb20gJy4uL2RvY3VtZW50YXRpb24vcGlwZXMvaW5zcGVjdC5waXBlJztcbmltcG9ydCB7VHVpRG9jVHlwZVJlZmVyZW5jZVBpcGV9IGZyb20gJy4uL2RvY3VtZW50YXRpb24vcGlwZXMvdHlwZS1yZWZlcmVuY2UucGlwZSc7XG5pbXBvcnQge1R1aURvY0FQSU51bWJlckl0ZW19IGZyb20gJy4vYXBpLWl0ZW0tbnVtYmVyLmRpcmVjdGl2ZSc7XG5cbmNvbnN0IFNFUklBTElaRURfU1VGRklYID0gJyQnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIHNlbGVjdG9yOiAndHJbdHVpRG9jQVBJSXRlbV0nLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgRm9ybXNNb2R1bGUsXG4gICAgICAgIE5nRm9yT2YsXG4gICAgICAgIE5nSWYsXG4gICAgICAgIE5nU3dpdGNoLFxuICAgICAgICBOZ1N3aXRjaENhc2UsXG4gICAgICAgIFR1aUNoZXZyb24sXG4gICAgICAgIFR1aURhdGFMaXN0V3JhcHBlcixcbiAgICAgICAgVHVpRG9jVHlwZVJlZmVyZW5jZVBpcGUsXG4gICAgICAgIFR1aUljb24sXG4gICAgICAgIFR1aUlucHV0TnVtYmVyLFxuICAgICAgICBUdWlJbnNwZWN0UGlwZSxcbiAgICAgICAgVHVpU3dpdGNoLFxuICAgICAgICBUdWlUZXh0ZmllbGQsXG4gICAgXSxcbiAgICB0ZW1wbGF0ZVVybDogJy4vYXBpLWl0ZW0udGVtcGxhdGUuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vYXBpLWl0ZW0uc3R5bGUubGVzcyddLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBUdWlEb2NBUElJdGVtPFQ+IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBsb2NhdGlvblJlZiA9IGluamVjdChMb2NhdGlvbik7XG4gICAgcHJpdmF0ZSByZWFkb25seSBhY3RpdmF0ZWRSb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSk7XG4gICAgcHJpdmF0ZSByZWFkb25seSB1cmxTZXJpYWxpemVyID0gaW5qZWN0KFVybFNlcmlhbGl6ZXIpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgdXJsU3RhdGVIYW5kbGVyID0gaW5qZWN0KFRVSV9ET0NfVVJMX1NUQVRFX0hBTkRMRVIpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYWxlcnRzID0gaW5qZWN0KFR1aUFsZXJ0U2VydmljZSk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaWNvbnMgPSBpbmplY3QoVFVJX0RPQ19JQ09OUyk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgbnVtYmVySXRlbSA9IGluamVjdChUdWlEb2NBUElOdW1iZXJJdGVtLCB7XG4gICAgICAgIHNlbGY6IHRydWUsXG4gICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbmFtZSA9ICcnO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdHlwZSA9ICcnO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdmFsdWU/OiBUO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaXRlbXM6IHJlYWRvbmx5IFRbXSA9IFtdO1xuXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIHJlYWRvbmx5IHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxUPigpO1xuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXJzZVBhcmFtcyh0aGlzLmFjdGl2YXRlZFJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25WYWx1ZUNoYW5nZSh2YWx1ZTogVCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gICAgICAgIHRoaXMuc2V0UXVlcnlQYXJhbSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGVtaXRFdmVudChldmVudDogdW5rbm93bik6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmluZm8oJ2VtaXRFdmVudCcsIGV2ZW50KTtcblxuICAgICAgICBjb25zdCBhbGVydCA9XG4gICAgICAgICAgICAhZXZlbnQgfHwgZXZlbnQ/LnRvU3RyaW5nKCkgPT09ICdbb2JqZWN0IE9iamVjdF0nXG4gICAgICAgICAgICAgICAgPyB0dWlJbnNwZWN0QW55KGV2ZW50LCAyKVxuICAgICAgICAgICAgICAgIDogKGV2ZW50IGFzIHN0cmluZyk7XG5cbiAgICAgICAgdGhpcy5hbGVydHMub3BlbihhbGVydCwge2xhYmVsOiB0aGlzLm5hbWV9KS5zdWJzY3JpYmUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsZWFyQnJhY2tldHModmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB2YWx1ZS5yZXBsYWNlQWxsKC9bKClbXFxdXS9nLCAnJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwYXJzZVBhcmFtcyhwYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgICAgICBjb25zdCBuYW1lID0gdGhpcy5jbGVhckJyYWNrZXRzKHRoaXMubmFtZSk7XG4gICAgICAgIGNvbnN0IHByb3BlcnR5VmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHBhcmFtc1tuYW1lXTtcbiAgICAgICAgY29uc3QgcHJvcGVydHlWYWx1ZVdpdGhTdWZmaXg6IG51bWJlciB8IHN0cmluZyB8IHVuZGVmaW5lZCA9XG4gICAgICAgICAgICBwYXJhbXNbYCR7bmFtZX0ke1NFUklBTElaRURfU1VGRklYfWBdO1xuXG4gICAgICAgIGlmICghcHJvcGVydHlWYWx1ZSAmJiAhcHJvcGVydHlWYWx1ZVdpdGhTdWZmaXgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB2YWx1ZSA9XG4gICAgICAgICAgICAhIXByb3BlcnR5VmFsdWVXaXRoU3VmZml4ICYmIHRoaXMuaXRlbXNcbiAgICAgICAgICAgICAgICA/IHRoaXMuaXRlbXNbcHJvcGVydHlWYWx1ZVdpdGhTdWZmaXggYXMgbnVtYmVyXVxuICAgICAgICAgICAgICAgIDogdHVpQ29lcmNlVmFsdWUocHJvcGVydHlWYWx1ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmluZycgJiYgdHVpSXNOdW1iZXIodmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9uVmFsdWVDaGFuZ2UodmFsdWUgYXMgVCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXRRdWVyeVBhcmFtKHZhbHVlOiBUIHwgYm9vbGVhbiB8IG51bWJlciB8IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdHJlZSA9IHRoaXMudXJsU2VyaWFsaXplci5wYXJzZSh0aGlzLmxvY2F0aW9uUmVmLnBhdGgoKSk7XG5cbiAgICAgICAgY29uc3QgaXNWYWx1ZUF2YWlsYWJsZUJ5S2V5ID0gdmFsdWUgaW5zdGFuY2VvZiBPYmplY3Q7XG4gICAgICAgIGNvbnN0IGNvbXB1dGVkVmFsdWUgPVxuICAgICAgICAgICAgaXNWYWx1ZUF2YWlsYWJsZUJ5S2V5ICYmIHRoaXMuaXRlbXMgPyB0aGlzLml0ZW1zLmluZGV4T2YodmFsdWUgYXMgVCkgOiB2YWx1ZTtcblxuICAgICAgICBjb25zdCBzdWZmaXggPSBpc1ZhbHVlQXZhaWxhYmxlQnlLZXkgPyBTRVJJQUxJWkVEX1NVRkZJWCA6ICcnO1xuICAgICAgICBjb25zdCBwcm9wTmFtZSA9IHRoaXMuY2xlYXJCcmFja2V0cyh0aGlzLm5hbWUpICsgc3VmZml4O1xuXG4gICAgICAgIHRyZWUucXVlcnlQYXJhbXMgPSB7XG4gICAgICAgICAgICAuLi50cmVlLnF1ZXJ5UGFyYW1zLFxuICAgICAgICAgICAgW3Byb3BOYW1lXTogY29tcHV0ZWRWYWx1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmxvY2F0aW9uUmVmLmdvKHRoaXMudXJsU3RhdGVIYW5kbGVyKHRyZWUpKTtcbiAgICB9XG59XG4iLCI8dGQgY2xhc3M9XCJ0LXRkXCI+XG4gICAgPGNvZGVcbiAgICAgICAgY2xhc3M9XCJ0LW5hbWVcIlxuICAgICAgICBbY2xhc3MudC1uYW1lX2JhbmFuYV09XCJuYW1lLnN0YXJ0c1dpdGgoJ1soJylcIlxuICAgICAgICBbY2xhc3MudC1uYW1lX2lucHV0XT1cIm5hbWUuc3RhcnRzV2l0aCgnWycpXCJcbiAgICAgICAgW2NsYXNzLnQtbmFtZV9vdXRwdXRdPVwibmFtZS5zdGFydHNXaXRoKCcoJylcIlxuICAgID5cbiAgICAgICAge3sgbmFtZSB9fVxuICAgIDwvY29kZT5cbiAgICA8bmctY29udGVudCAvPlxuPC90ZD5cbjx0ZCBjbGFzcz1cInQtdGRcIj5cbiAgICA8Y29kZSBjbGFzcz1cInQtdHlwZVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtIG9mIHR5cGUgfCB0dWlEb2NUeXBlUmVmZXJlbmNlOyBsZXQgbGFzdCA9IGxhc3RcIj5cbiAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJpdGVtLnJlZmVyZW5jZTsgZWxzZSBkZWZhdWx0XCJcbiAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidC1yZWZlcmVuY2VcIlxuICAgICAgICAgICAgICAgIFthdHRyLmhyZWZdPVwiaXRlbS5yZWZlcmVuY2VcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHt7IGl0ZW0udHlwZSB9fVxuICAgICAgICAgICAgICAgIDx0dWktaWNvblxuICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImljb25zLmV4dGVybmFsTGlua1wiXG4gICAgICAgICAgICAgICAgICAgIFtpY29uXT1cImljb25zLmV4dGVybmFsTGlua1wiXG4gICAgICAgICAgICAgICAgICAgIFtzdHlsZS5mb250LXNpemUucmVtXT1cIjFcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHQ+XG4gICAgICAgICAgICAgICAge3sgaXRlbS50eXBlIH19XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIhbGFzdFwiPiZuYnNwO3wmbmJzcDs8L3NwYW4+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvY29kZT5cbjwvdGQ+XG48dGQgY2xhc3M9XCJ0LXRkXCI+XG4gICAgPHR1aS10ZXh0ZmllbGRcbiAgICAgICAgKm5nSWY9XCJpdGVtcy5sZW5ndGg7IGVsc2Ugbm9JdGVtc1wiXG4gICAgICAgIHR1aUNoZXZyb25cbiAgICAgICAgdHVpVGV4dGZpZWxkU2l6ZT1cIm1cIlxuICAgICAgICBjbGFzcz1cInQtaW5wdXRcIlxuICAgICAgICBbY29udGVudF09XCJjb250ZW50XCJcbiAgICAgICAgW3R1aVRleHRmaWVsZENsZWFuZXJdPVwidHlwZS5pbmNsdWRlcygnbnVsbCcpIHx8IHR5cGUuaW5jbHVkZXMoJ1BvbHltb3JwaGV1c0NvbnRlbnQnKVwiXG4gICAgPlxuICAgICAgICA8c2VsZWN0XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIm51bGxcIlxuICAgICAgICAgICAgdHVpVGV4dGZpZWxkXG4gICAgICAgICAgICBbbmdNb2RlbF09XCJ2YWx1ZSA/PyBudWxsXCJcbiAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uVmFsdWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgID48L3NlbGVjdD5cbiAgICAgICAgPHR1aS1kYXRhLWxpc3Qtd3JhcHBlclxuICAgICAgICAgICAgKnR1aVRleHRmaWVsZERyb3Bkb3duXG4gICAgICAgICAgICBbaXRlbUNvbnRlbnRdPVwiY29udGVudFwiXG4gICAgICAgICAgICBbaXRlbXNdPVwiaXRlbXNcIlxuICAgICAgICAvPlxuICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgI2NvbnRlbnRcbiAgICAgICAgbGV0LWRhdGFcbiAgICA+XG4gICAgICAgIDxjb2RlIFtzdHlsZS5tYXJnaW5dPVwiMFwiPnt7IGRhdGEgfCB0dWlJbnNwZWN0QW55IH19PC9jb2RlPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPG5nLXRlbXBsYXRlICNub0l0ZW1zPlxuICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdJZj1cInZhbHVlICE9PSB1bmRlZmluZWRcIlxuICAgICAgICAgICAgW25nU3dpdGNoXT1cInR5cGVcIlxuICAgICAgICA+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAqbmdTd2l0Y2hDYXNlPVwiJ2Jvb2xlYW4nXCJcbiAgICAgICAgICAgICAgICB0dWlTd2l0Y2hcbiAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgICAgICAgIFtpZF09XCJuYW1lXCJcbiAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ2YWx1ZVwiXG4gICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIC8+XG5cbiAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkXG4gICAgICAgICAgICAgICAgKm5nU3dpdGNoQ2FzZT1cIidzdHJpbmcnXCJcbiAgICAgICAgICAgICAgICB0dWlUZXh0ZmllbGRTaXplPVwibVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ0LWlucHV0XCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgdHVpVGV4dGZpZWxkXG4gICAgICAgICAgICAgICAgICAgIFtpZF09XCJuYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwidmFsdWUgfHwgJydcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvblZhbHVlQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L3R1aS10ZXh0ZmllbGQ+XG5cbiAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkXG4gICAgICAgICAgICAgICAgKm5nU3dpdGNoQ2FzZT1cIidudW1iZXInXCJcbiAgICAgICAgICAgICAgICB0dWlUZXh0ZmllbGRTaXplPVwibVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR1aUlucHV0TnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtpZF09XCJuYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgW21heF09XCJudW1iZXJJdGVtPy5tYXggPz8gbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgIFttaW5dPVwibnVtYmVySXRlbT8ubWluID8/IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ2YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtzdGVwXT1cIjFcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvblZhbHVlQ2hhbmdlKCRldmVudCB8fCAwKVwiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbjwvdGQ+XG4iXX0=