ng-devui
Version:
DevUI components based on Angular
190 lines • 41.2 kB
JavaScript
import { Component, ContentChildren, Input, QueryList } from '@angular/core';
import { merge } from 'lodash-es';
import { ProgressTemplateDirective } from './progress-template.directive';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class ProgressComponent {
static { this.ID_SEED = 0; }
/**
* @deprecated
* 统一用strokeWidth
*/
set height(value) {
this.strokeWidth = parseInt(value, 10);
}
/**
* @deprecated
* 用type类型替换
*/
set isCircle(value) {
this.type = value ? 'circle' : 'line';
}
get content() {
return this.percentageText ? this.percentageText : `${this.percentage}%`;
}
constructor() {
this.isDynamic = true;
this.percentage = 0;
this.strokeColor = '';
this.strokeWidth = 14; // 进度条的线条宽度
this.type = 'line';
this.multiProgressConfig = [];
this.progressData = [];
this.gradientColor = [];
this.isGradient = false;
this.showContentConfig = {
showInnerContent: false,
showOuterContent: false,
showCenterContent: true,
};
this.id = ProgressComponent.ID_SEED++;
}
ngOnChanges(changes) {
const { isCircle, multiProgressConfig, percentage, showContent, strokeColor, type } = changes;
const hasChanged = [percentage, strokeColor, type, isCircle].some((change) => change);
if (multiProgressConfig || (this.multiProgressConfig?.length && percentage) || (!this.multiProgressConfig?.length && hasChanged)) {
this.render();
}
if (showContent) {
this.showContentConfig =
typeof this.showContent === 'boolean'
? {
showInnerContent: this.showContent,
showOuterContent: this.showContent,
showCenterContent: false,
}
: { ...this.showContentConfig, ...this.showContent };
}
}
ngAfterViewInit() {
// 兼容之前line中自定义模板对应右侧模板,circle对应中间模板
if (this.templates?.length) {
const restItem = [];
this.templates.forEach((item) => {
const pos = item.position || item.dPosition;
const name = pos && `${pos}Template`;
if (name) {
this[name] = item.template;
}
else {
restItem.push(item);
}
});
if (restItem.length) {
this.outerTemplate = this.outerTemplate || restItem[0].template;
this.centerTemplate = this.centerTemplate || restItem[restItem.length - 1]?.template;
}
}
}
render() {
const data = this.multiProgressConfig?.length
? [...this.multiProgressConfig]
: [
{
color: (this.checkStrokeColor() || this.barbgcolor) ?? '',
percentage: this.percentage ?? 0,
percentageText: this.percentageText ?? '',
content: this.content ?? '',
},
];
if (this.type === 'line') {
this.checkSumOfPercentages(data, (sum, item) => {
item.width = sum;
});
}
if (this.type === 'circle') {
this.setCircleProgress(data);
}
// 展示数据倒序输出,短的后输出,显示层级高
data.reverse();
if (this.isDynamic) {
// merge方式覆盖数据,不改变数据源,避免重渲染dom导致动画失效
merge(this.progressData, data);
}
else {
this.progressData = [...data];
}
}
setCircleProgress(data) {
const radius = 50 - this.strokeWidth / 2;
const beginPositionY = -radius;
const endPositionY = radius * -2;
const len = Math.PI * 2 * radius;
this.pathString = `M 50,50 m 0,${beginPositionY}
a ${radius},${radius} 0 1 1 0,${-endPositionY}
a ${radius},${radius} 0 1 1 0,${endPositionY}`;
this.trailPath = {
strokeDasharray: `${len}px ${len}px`,
strokeDashoffset: `0`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s',
};
this.checkSumOfPercentages(data, (sum, item) => {
item.strokePath = {
stroke: item.color || this.checkStrokeColor() || this.barbgcolor || null,
strokeDasharray: `${(sum / 100) * len}px ${len}px`,
strokeDashoffset: `0`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s',
};
});
}
checkSumOfPercentages(data, func) {
const result = data.reduce((sum, item, index) => {
sum += Number(item.percentage);
sum = sum > 100 || (index > 0 && index === data.length - 1 && this.percentage === 100) ? 100 : sum;
func(sum, item);
return sum;
}, 0);
this.percentage = this.percentage >= 100 ? 100 : result;
}
checkStrokeColor() {
if (Array.isArray(this.strokeColor)) {
this.isGradient = true;
this.gradientColor = this.strokeColor;
if (this.type === 'line') {
const colors = this.strokeColor.map((item) => `${item.color} ${item.percentage}`).join(', ');
const result = `linear-gradient(to right, ${colors})`;
return this.strokeColor.length ? result : '';
}
if (this.type === 'circle') {
return `url(#devui-progress-gradient-${this.id}`;
}
}
else {
this.isGradient = false;
this.strokeColor = this.strokeColor || '';
return this.strokeColor;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProgressComponent, selector: "d-progress", inputs: { isDynamic: "isDynamic", percentage: "percentage", percentageText: "percentageText", barbgcolor: "barbgcolor", strokeColor: "strokeColor", height: "height", strokeWidth: "strokeWidth", isCircle: "isCircle", type: "type", showContent: "showContent", multiProgressConfig: "multiProgressConfig" }, queries: [{ propertyName: "templates", predicate: ProgressTemplateDirective }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"type === 'line'\">\n <div id=\"devui-progress-line-{{ id }}\" class=\"devui-progress devui-progress-line\" [style.height]=\"strokeWidth + 'px'\">\n <div\n *ngFor=\"let bar of progressData\"\n class=\"devui-progress-bar\"\n [class.devui-progress-bar-default-bg]=\"!bar.color\"\n [style.background]=\"bar.color\"\n [style.width]=\"bar.width + '%'\"\n >\n <ng-template\n *ngIf=\"showContentConfig.showInnerContent\"\n [ngTemplateOutlet]=\"bar.template || defaultInnerContent\"\n [ngTemplateOutletContext]=\"{ $implicit: this, bar: bar }\"\n ></ng-template>\n </div>\n <ng-template\n *ngIf=\"showContentConfig.showCenterContent\"\n [ngTemplateOutlet]=\"centerTemplate || defaultCenterContent\"\n [ngTemplateOutletContext]=\"{ $implicit: this }\"\n ></ng-template>\n </div>\n <ng-template\n *ngIf=\"showContentConfig.showOuterContent\"\n [ngTemplateOutlet]=\"outerTemplate || defaultPercentageText\"\n [ngTemplateOutletContext]=\"{ $implicit: this, percentage: percentage }\"\n ></ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"type === 'circle'\">\n <div id=\"devui-progress-circle-{{ id }}\" class=\"devui-progress devui-progress-circle\">\n <svg viewBox=\"0 0 100 100\">\n <defs *ngIf=\"isGradient\">\n <linearGradient id=\"devui-progress-gradient-{{ id }}\" x1=\"100%\" y1=\"0%\" x2=\"0%\" y2=\"0%\">\n <stop *ngFor=\"let color of gradientColor\" [attr.offset]=\"color.percentage\" [attr.stop-color]=\"color.color\"></stop>\n </linearGradient>\n </defs>\n <path\n class=\"devui-progress-circle-trail\"\n fill-opacity=\"0\"\n [attr.d]=\"pathString\"\n [attr.stroke-width]=\"strokeWidth\"\n [ngStyle]=\"trailPath\"\n ></path>\n <path\n *ngFor=\"let circle of progressData\"\n fill-opacity=\"0\"\n [attr.d]=\"pathString\"\n [attr.stroke]=\"circle.color\"\n [attr.stroke-linecap]=\"'round'\"\n [attr.stroke-width]=\"circle.percentage ? strokeWidth : 0\"\n [class.devui-progress-circle-path]=\"!isGradient\"\n [ngStyle]=\"circle.strokePath\"\n >\n <title>{{ circle.percentageText ? circle.percentageText : circle.percentage + '%' }}</title>\n </path>\n </svg>\n <ng-template\n *ngIf=\"showContentConfig.showCenterContent\"\n [ngTemplateOutlet]=\"centerTemplate || defaultPercentageText\"\n [ngTemplateOutletContext]=\"{ $implicit: this, percentage: percentage }\"\n ></ng-template>\n </div>\n</ng-container>\n\n<ng-template #defaultInnerContent let-bar=\"bar\">\n <span [style.line-height]=\"strokeWidth + 'px'\" [title]=\"bar.percentageText ? bar.percentageText : bar.percentage + '%'\">\n {{ bar.percentageText ? bar.percentageText : bar.percentage + '%' }}\n </span>\n</ng-template>\n\n<ng-template #defaultCenterContent>\n <span [style.line-height]=\"strokeWidth + 'px'\" [title]=\"content\">{{ content }}</span>\n</ng-template>\n\n<ng-template #defaultPercentageText>\n <div class=\"devui-progress-default-text\" [title]=\"content\">{{ content }}</div>\n</ng-template>\n", styles: [".devui-font-size-base{font-size:var(--devui-font-size, 12px)}.devui-font-base{font-size:var(--devui-font-size, 12px);font-weight:var(--devui-font-content-weight, normal);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-modal-title{font-size:var(--devui-font-size-modal-title, 18px)}.devui-font-modal-title{font-size:var(--devui-font-size-modal-title, 18px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-page-title{font-size:var(--devui-font-size-page-title, 16px)}.devui-font-page-title{font-size:var(--devui-font-size-page-title, 16px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-secondary-title{font-size:var(--devui-font-size-card-title, 14px)}.devui-font-secondary-title{font-size:var(--devui-font-size-card-title, 14px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}:host{display:flex;align-items:center;justify-content:flex-start;flex-wrap:nowrap}:host .devui-progress-default-text{width:fit-content;margin:0;padding:0 8px;color:var(--devui-text, #191919);font-size:var(--devui-font-size, 12px);line-height:1}:host .devui-progress-line,:host .devui-progress-circle{flex:1 1 auto;position:relative}:host .devui-progress-line{background:var(--devui-range-item-hover-bg, #cedefd);border-radius:var(--devui-border-radius-full, 100px)}:host .devui-progress-line .devui-progress-bar{position:absolute;left:0;top:0;width:0;height:100%;transition:width .6s ease;border-radius:var(--devui-border-radius-full, 100px)}:host .devui-progress-line .devui-progress-bar.devui-progress-bar-default-bg{background-color:var(--devui-brand, #0a59f7)}:host .devui-progress-line .devui-progress-bar>span{color:var(--devui-light-text, #ffffff);font-size:var(--devui-font-size, 12px);position:absolute;right:8px;height:100%;line-height:100%;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-line>span{color:var(--devui-light-text, #ffffff);font-size:var(--devui-font-size, 12px);position:absolute;left:50%;top:0;width:fit-content;transform:translate(-50%);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-circle{height:100%}:host .devui-progress-circle .devui-progress-default-text{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-circle .devui-progress-circle-trail{stroke:var(--devui-dividing-line, #f0f0f0)}:host .devui-progress-circle .devui-progress-circle-path{stroke:var(--devui-brand, #0a59f7)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProgressComponent, decorators: [{
type: Component,
args: [{ selector: 'd-progress', preserveWhitespaces: false, template: "<ng-container *ngIf=\"type === 'line'\">\n <div id=\"devui-progress-line-{{ id }}\" class=\"devui-progress devui-progress-line\" [style.height]=\"strokeWidth + 'px'\">\n <div\n *ngFor=\"let bar of progressData\"\n class=\"devui-progress-bar\"\n [class.devui-progress-bar-default-bg]=\"!bar.color\"\n [style.background]=\"bar.color\"\n [style.width]=\"bar.width + '%'\"\n >\n <ng-template\n *ngIf=\"showContentConfig.showInnerContent\"\n [ngTemplateOutlet]=\"bar.template || defaultInnerContent\"\n [ngTemplateOutletContext]=\"{ $implicit: this, bar: bar }\"\n ></ng-template>\n </div>\n <ng-template\n *ngIf=\"showContentConfig.showCenterContent\"\n [ngTemplateOutlet]=\"centerTemplate || defaultCenterContent\"\n [ngTemplateOutletContext]=\"{ $implicit: this }\"\n ></ng-template>\n </div>\n <ng-template\n *ngIf=\"showContentConfig.showOuterContent\"\n [ngTemplateOutlet]=\"outerTemplate || defaultPercentageText\"\n [ngTemplateOutletContext]=\"{ $implicit: this, percentage: percentage }\"\n ></ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"type === 'circle'\">\n <div id=\"devui-progress-circle-{{ id }}\" class=\"devui-progress devui-progress-circle\">\n <svg viewBox=\"0 0 100 100\">\n <defs *ngIf=\"isGradient\">\n <linearGradient id=\"devui-progress-gradient-{{ id }}\" x1=\"100%\" y1=\"0%\" x2=\"0%\" y2=\"0%\">\n <stop *ngFor=\"let color of gradientColor\" [attr.offset]=\"color.percentage\" [attr.stop-color]=\"color.color\"></stop>\n </linearGradient>\n </defs>\n <path\n class=\"devui-progress-circle-trail\"\n fill-opacity=\"0\"\n [attr.d]=\"pathString\"\n [attr.stroke-width]=\"strokeWidth\"\n [ngStyle]=\"trailPath\"\n ></path>\n <path\n *ngFor=\"let circle of progressData\"\n fill-opacity=\"0\"\n [attr.d]=\"pathString\"\n [attr.stroke]=\"circle.color\"\n [attr.stroke-linecap]=\"'round'\"\n [attr.stroke-width]=\"circle.percentage ? strokeWidth : 0\"\n [class.devui-progress-circle-path]=\"!isGradient\"\n [ngStyle]=\"circle.strokePath\"\n >\n <title>{{ circle.percentageText ? circle.percentageText : circle.percentage + '%' }}</title>\n </path>\n </svg>\n <ng-template\n *ngIf=\"showContentConfig.showCenterContent\"\n [ngTemplateOutlet]=\"centerTemplate || defaultPercentageText\"\n [ngTemplateOutletContext]=\"{ $implicit: this, percentage: percentage }\"\n ></ng-template>\n </div>\n</ng-container>\n\n<ng-template #defaultInnerContent let-bar=\"bar\">\n <span [style.line-height]=\"strokeWidth + 'px'\" [title]=\"bar.percentageText ? bar.percentageText : bar.percentage + '%'\">\n {{ bar.percentageText ? bar.percentageText : bar.percentage + '%' }}\n </span>\n</ng-template>\n\n<ng-template #defaultCenterContent>\n <span [style.line-height]=\"strokeWidth + 'px'\" [title]=\"content\">{{ content }}</span>\n</ng-template>\n\n<ng-template #defaultPercentageText>\n <div class=\"devui-progress-default-text\" [title]=\"content\">{{ content }}</div>\n</ng-template>\n", styles: [".devui-font-size-base{font-size:var(--devui-font-size, 12px)}.devui-font-base{font-size:var(--devui-font-size, 12px);font-weight:var(--devui-font-content-weight, normal);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-modal-title{font-size:var(--devui-font-size-modal-title, 18px)}.devui-font-modal-title{font-size:var(--devui-font-size-modal-title, 18px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-page-title{font-size:var(--devui-font-size-page-title, 16px)}.devui-font-page-title{font-size:var(--devui-font-size-page-title, 16px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}.devui-font-size-secondary-title{font-size:var(--devui-font-size-card-title, 14px)}.devui-font-secondary-title{font-size:var(--devui-font-size-card-title, 14px);font-weight:var(--devui-font-title-weight, bold);line-height:var(--devui-line-height-base, 1.5)}:host{display:flex;align-items:center;justify-content:flex-start;flex-wrap:nowrap}:host .devui-progress-default-text{width:fit-content;margin:0;padding:0 8px;color:var(--devui-text, #191919);font-size:var(--devui-font-size, 12px);line-height:1}:host .devui-progress-line,:host .devui-progress-circle{flex:1 1 auto;position:relative}:host .devui-progress-line{background:var(--devui-range-item-hover-bg, #cedefd);border-radius:var(--devui-border-radius-full, 100px)}:host .devui-progress-line .devui-progress-bar{position:absolute;left:0;top:0;width:0;height:100%;transition:width .6s ease;border-radius:var(--devui-border-radius-full, 100px)}:host .devui-progress-line .devui-progress-bar.devui-progress-bar-default-bg{background-color:var(--devui-brand, #0a59f7)}:host .devui-progress-line .devui-progress-bar>span{color:var(--devui-light-text, #ffffff);font-size:var(--devui-font-size, 12px);position:absolute;right:8px;height:100%;line-height:100%;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-line>span{color:var(--devui-light-text, #ffffff);font-size:var(--devui-font-size, 12px);position:absolute;left:50%;top:0;width:fit-content;transform:translate(-50%);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-circle{height:100%}:host .devui-progress-circle .devui-progress-default-text{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .devui-progress-circle .devui-progress-circle-trail{stroke:var(--devui-dividing-line, #f0f0f0)}:host .devui-progress-circle .devui-progress-circle-path{stroke:var(--devui-brand, #0a59f7)}\n"] }]
}], ctorParameters: () => [], propDecorators: { isDynamic: [{
type: Input
}], percentage: [{
type: Input
}], percentageText: [{
type: Input
}], barbgcolor: [{
type: Input
}], strokeColor: [{
type: Input
}], height: [{
type: Input
}], strokeWidth: [{
type: Input
}], isCircle: [{
type: Input
}], type: [{
type: Input
}], showContent: [{
type: Input
}], multiProgressConfig: [{
type: Input
}], templates: [{
type: ContentChildren,
args: [ProgressTemplateDirective]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3MuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vZGV2dWkvcHJvZ3Jlc3MvcHJvZ3Jlc3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vZGV2dWkvcHJvZ3Jlc3MvcHJvZ3Jlc3MuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBYSxTQUFTLEVBQThCLE1BQU0sZUFBZSxDQUFDO0FBQ25JLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sK0JBQStCLENBQUM7OztBQVMxRSxNQUFNLE9BQU8saUJBQWlCO2FBQ3JCLFlBQU8sR0FBRyxDQUFDLEFBQUosQ0FBSztJQVVuQjs7O09BR0c7SUFDSCxJQUFhLE1BQU0sQ0FBQyxLQUFLO1FBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBYSxRQUFRLENBQUMsS0FBYztRQUNsQyxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDeEMsQ0FBQztJQW9CRCxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDO0lBQzNFLENBQUM7SUFFRDtRQS9DUyxjQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLGVBQVUsR0FBRyxDQUFDLENBQUM7UUFPZixnQkFBVyxHQUE4QixFQUFFLENBQUM7UUFRNUMsZ0JBQVcsR0FBRyxFQUFFLENBQUMsQ0FBQyxXQUFXO1FBUTdCLFNBQUks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Q0gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztZQUN4QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDO1lBQzFDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQzsrR0FqTFUsaUJBQWlCO21HQUFqQixpQkFBaUIsNFhBNkJYLHlCQUF5QixrREN4QzVDLHduR0E2RUE7OzRGRGxFYSxpQkFBaUI7a0JBTjdCLFNBQVM7K0JBQ0UsWUFBWSx1QkFHRCxLQUFLO3dEQUlqQixTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFLRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBS08sTUFBTTtzQkFBbEIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtPLFFBQVE7c0JBQXBCLEtBQUs7Z0JBR0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUNzQyxTQUFTO3NCQUFwRCxlQUFlO3VCQUFDLHlCQUF5QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgQ29udGVudENoaWxkcmVuLCBJbnB1dCwgT25DaGFuZ2VzLCBRdWVyeUxpc3QsIFNpbXBsZUNoYW5nZXMsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBtZXJnZSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBQcm9ncmVzc1RlbXBsYXRlRGlyZWN0aXZlIH0gZnJvbSAnLi9wcm9ncmVzcy10ZW1wbGF0ZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSUdyYWRpZW50Q29sb3IsIElQcm9ncmVzc0l0ZW0sIFNob3dDb250ZW50Q29uZmlnIH0gZnJvbSAnLi9wcm9ncmVzcy50eXBlcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2QtcHJvZ3Jlc3MnLFxuICB0ZW1wbGF0ZVVybDogJy4vcHJvZ3Jlc3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9wcm9ncmVzcy5jb21wb25lbnQuc2NzcyddLFxuICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbn0pXG5leHBvcnQgY2xhc3MgUHJvZ3Jlc3NDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQge1xuICBzdGF0aWMgSURfU0VFRCA9IDA7XG4gIEBJbnB1dCgpIGlzRHluYW1pYyA9IHRydWU7XG4gIEBJbnB1dCgpIHBlcmNlbnRhZ2UgPSAwO1xuICBASW5wdXQoKSBwZXJjZW50YWdlVGV4dDogc3RyaW5nO1xuICAvKipcbiAgICogQGRlcHJlY2F0ZWRcbiAgICog55Soc3Ryb2tlQ29sb3Lmm7/mjaJcbiAgICovXG4gIEBJbnB1dCgpIGJhcmJnY29sb3I6IHN0cmluZztcbiAgQElucHV0KCkgc3Ryb2tlQ29sb3I6IHN0cmluZyB8IElHcmFkaWVudENvbG9yW10gPSAnJztcbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkXG4gICAqIOe7n+S4gOeUqHN0cm9rZVdpZHRoXG4gICAqL1xuICBASW5wdXQoKSBzZXQgaGVpZ2h0KHZhbHVlKSB7XG4gICAgdGhpcy5zdHJva2VXaWR0aCA9IHBhcnNlSW50KHZhbHVlLCAxMCk7XG4gIH1cbiAgQElucHV0KCkgc3Ryb2tlV2lkdGggPSAxNDsgLy8g6L+b5bqm5p2h55qE57q/5p2h5a695bqmXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZFxuICAgKiDnlKh0eXBl57G75Z6L5pu/5o2iXG4gICAqL1xuICBASW5wdXQoKSBzZXQgaXNDaXJjbGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnR5cGUgPSB2YWx1ZSA/ICdjaXJjbGUnIDogJ2xpbmUnO1xuICB9XG4gIEBJbnB1dCgpIHR5cGU6ICdsaW5lJyB8ICdjaXJjbGUnID0gJ2xpbmUnO1xuICBASW5wdXQoKSBzaG93Q29udGVudDogYm9vbGVhbiB8IFNob3dDb250ZW50Q29uZmlnO1xuICBASW5wdXQoKSBtdWx0aVByb2dyZXNzQ29uZmlnOiBJUHJvZ3Jlc3NJdGVtW10gPSBbXTtcbiAgQENvbnRlbnRDaGlsZHJlbihQcm9ncmVzc1RlbXBsYXRlRGlyZWN0aXZlKSB0ZW1wbGF0ZXM6IFF1ZXJ5TGlzdDxQcm9ncmVzc1RlbXBsYXRlRGlyZWN0aXZlPjtcblxuICBpZDogbnVtYmVyO1xuICBwYXRoU3RyaW5nOiBzdHJpbmc7XG4gIHRyYWlsUGF0aDogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgcHJvZ3Jlc3NEYXRhOiBJUHJvZ3Jlc3NJdGVtW10gPSBbXTtcbiAgZ3JhZGllbnRDb2xvcjogSUdyYWRpZW50Q29sb3JbXSA9IFtdO1xuICBpc0dyYWRpZW50ID0gZmFsc2U7XG4gIHNob3dDb250ZW50Q29uZmlnID0ge1xuICAgIHNob3dJbm5lckNvbnRlbnQ6IGZhbHNlLFxuICAgIHNob3dPdXRlckNvbnRlbnQ6IGZhbHNlLFxuICAgIHNob3dDZW50ZXJDb250ZW50OiB0cnVlLFxuICB9O1xuICBjZW50ZXJUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgb3V0ZXJUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICBnZXQgY29udGVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5wZXJjZW50YWdlVGV4dCA/IHRoaXMucGVyY2VudGFnZVRleHQgOiBgJHt0aGlzLnBlcmNlbnRhZ2V9JWA7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmlkID0gUHJvZ3Jlc3NDb21wb25lbnQuSURfU0VFRCsrO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGNvbnN0IHsgaXNDaXJjbGUsIG11bHRpUHJvZ3Jlc3NDb25maWcsIHBlcmNlbnRhZ2UsIHNob3dDb250ZW50LCBzdHJva2VDb2xvciwgdHlwZSB9ID0gY2hhbmdlcztcbiAgICBjb25zdCBoYXNDaGFuZ2VkID0gW3BlcmNlbnRhZ2UsIHN0cm9rZUNvbG9yLCB0eXBlLCBpc0NpcmNsZV0uc29tZSgoY2hhbmdlKSA9PiBjaGFuZ2UpO1xuXG4gICAgaWYgKG11bHRpUHJvZ3Jlc3NDb25maWcgfHwgKHRoaXMubXVsdGlQcm9ncmVzc0NvbmZpZz8ubGVuZ3RoICYmIHBlcmNlbnRhZ2UpIHx8ICghdGhpcy5tdWx0aVByb2dyZXNzQ29uZmlnPy5sZW5ndGggJiYgaGFzQ2hhbmdlZCkpIHtcbiAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgfVxuICAgIGlmIChzaG93Q29udGVudCkge1xuICAgICAgdGhpcy5zaG93Q29udGVudENvbmZpZyA9XG4gICAgICAgIHR5cGVvZiB0aGlzLnNob3dDb250ZW50ID09PSAnYm9vbGVhbidcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgIHNob3dJbm5lckNvbnRlbnQ6IHRoaXMuc2hvd0NvbnRlbnQsXG4gICAgICAgICAgICBzaG93T3V0ZXJDb250ZW50OiB0aGlzLnNob3dDb250ZW50LFxuICAgICAgICAgICAgc2hvd0NlbnRlckNvbnRlbnQ6IGZhbHNlLFxuICAgICAgICAgIH1cbiAgICAgICAgICA6IHsgLi4udGhpcy5zaG93Q29udGVudENvbmZpZywgLi4udGhpcy5zaG93Q29udGVudCB9O1xuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAvLyDlhbzlrrnkuYvliY1saW5l5Lit6Ieq5a6a5LmJ5qih5p2/5a+55bqU5Y+z5L6n5qih5p2/77yMY2lyY2xl5a+55bqU5Lit6Ze05qih5p2/XG4gICAgaWYgKHRoaXMudGVtcGxhdGVzPy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHJlc3RJdGVtID0gW107XG4gICAgICB0aGlzLnRlbXBsYXRlcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IHBvcyA9IGl0ZW0ucG9zaXRpb24gfHwgaXRlbS5kUG9zaXRpb247XG4gICAgICAgIGNvbnN0IG5hbWUgPSBwb3MgJiYgYCR7cG9zfVRlbXBsYXRlYDtcbiAgICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgICB0aGlzW25hbWVdID0gaXRlbS50ZW1wbGF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN0SXRlbS5wdXNoKGl0ZW0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmIChyZXN0SXRlbS5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5vdXRlclRlbXBsYXRlID0gdGhpcy5vdXRlclRlbXBsYXRlIHx8IHJlc3RJdGVtWzBdLnRlbXBsYXRlO1xuICAgICAgICB0aGlzLmNlbnRlclRlbXBsYXRlID0gdGhpcy5jZW50ZXJUZW1wbGF0ZSB8fCByZXN0SXRlbVtyZXN0SXRlbS5sZW5ndGggLSAxXT8udGVtcGxhdGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmVuZGVyKCk6IHZvaWQge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLm11bHRpUHJvZ3Jlc3NDb25maWc/Lmxlbmd0aFxuICAgICAgPyBbLi4udGhpcy5tdWx0aVByb2dyZXNzQ29uZmlnXVxuICAgICAgOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBjb2xvcjogKHRoaXMuY2hlY2tTdHJva2VDb2xvcigpIHx8IHRoaXMuYmFyYmdjb2xvcikgPz8gJycsXG4gICAgICAgICAgcGVyY2VudGFnZTogdGhpcy5wZXJjZW50YWdlID8/IDAsXG4gICAgICAgICAgcGVyY2VudGFnZVRleHQ6IHRoaXMucGVyY2VudGFnZVRleHQgPz8gJycsXG4gICAgICAgICAgY29udGVudDogdGhpcy5jb250ZW50ID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgIGlmICh0aGlzLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgdGhpcy5jaGVja1N1bU9mUGVyY2VudGFnZXMoZGF0YSwgKHN1bTogbnVtYmVyLCBpdGVtOiBJUHJvZ3Jlc3NJdGVtKSA9PiB7XG4gICAgICAgIGl0ZW0ud2lkdGggPSBzdW07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50eXBlID09PSAnY2lyY2xlJykge1xuICAgICAgdGhpcy5zZXRDaXJjbGVQcm9ncmVzcyhkYXRhKTtcbiAgICB9XG5cbiAgICAvLyDlsZXnpLrmlbDmja7lgJLluo/ovpPlh7rvvIznn63nmoTlkI7ovpPlh7rvvIzmmL7npLrlsYLnuqfpq5hcbiAgICBkYXRhLnJldmVyc2UoKTtcblxuICAgIGlmICh0aGlzLmlzRHluYW1pYykge1xuICAgICAgLy8gbWVyZ2XmlrnlvI/opobnm5bmlbDmja7vvIzkuI3mlLnlj5jmlbDmja7mupDvvIzpgb/lhY3ph43muLLmn5Nkb23lr7zoh7TliqjnlLvlpLHmlYhcbiAgICAgIG1lcmdlKHRoaXMucHJvZ3Jlc3NEYXRhLCBkYXRhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wcm9ncmVzc0RhdGEgPSBbLi4uZGF0YV07XG4gICAgfVxuICB9XG5cbiAgc2V0Q2lyY2xlUHJvZ3Jlc3MoZGF0YTogSVByb2dyZXNzSXRlbVtdKTogdm9pZCB7XG4gICAgY29uc3QgcmFkaXVzID0gNTAgLSB0aGlzLnN0cm9rZVdpZHRoIC8gMjtcbiAgICBjb25zdCBiZWdpblBvc2l0aW9uWSA9IC1yYWRpdXM7XG4gICAgY29uc3QgZW5kUG9zaXRpb25ZID0gcmFkaXVzICogLTI7XG4gICAgY29uc3QgbGVuID0gTWF0aC5QSSAqIDIgKiByYWRpdXM7XG5cbiAgICB0aGlzLnBhdGhTdHJpbmcgPSBgTSA1MCw1MCBtIDAsJHtiZWdpblBvc2l0aW9uWX1cbiAgICAgYSAke3JhZGl1c30sJHtyYWRpdXN9IDAgMSAxIDAsJHstZW5kUG9zaXRpb25ZfVxuICAgICBhICR7cmFkaXVzfSwke3JhZGl1c30gMCAxIDEgMCwke2VuZFBvc2l0aW9uWX1gO1xuXG4gICAgdGhpcy50cmFpbFBhdGggPSB7XG4gICAgICBzdHJva2VEYXNoYXJyYXk6IGAke2xlbn1weCAke2xlbn1weGAsXG4gICAgICBzdHJva2VEYXNob2Zmc2V0OiBgMGAsXG4gICAgICB0cmFuc2l0aW9uOiAnc3Ryb2tlLWRhc2hvZmZzZXQgLjNzIGVhc2UgMHMsIHN0cm9rZS1kYXNoYXJyYXkgLjNzIGVhc2UgMHMsIHN0cm9rZSAuM3MnLFxuICAgIH07XG4gICAgdGhpcy5jaGVja1N1bU9mUGVyY2VudGFnZXMoZGF0YSwgKHN1bTogbnVtYmVyLCBpdGVtOiBJUHJvZ3Jlc3NJdGVtKSA9PiB7XG4gICAgICBpdGVtLnN0cm9rZVBhdGggPSB7XG4gICAgICAgIHN0cm9rZTogaXRlbS5jb2xvciB8fCB0aGlzLmNoZWNrU3Ryb2tlQ29sb3IoKSB8fCB0aGlzLmJhcmJnY29sb3IgfHwgKG51bGwgYXMgYW55KSxcbiAgICAgICAgc3Ryb2tlRGFzaGFycmF5OiBgJHsoc3VtIC8gMTAwKSAqIGxlbn1weCAke2xlbn1weGAsXG4gICAgICAgIHN0cm9rZURhc2hvZmZzZXQ6IGAwYCxcbiAgICAgICAgdHJhbnNpdGlvbjogJ3N0cm9rZS1kYXNob2Zmc2V0IC4zcyBlYXNlIDBzLCBzdHJva2UtZGFzaGFycmF5IC4zcyBlYXNlIDBzLCBzdHJva2UgLjNzLCBzdHJva2Utd2lkdGggLjA2cyBlYXNlIC4zcycsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgY2hlY2tTdW1PZlBlcmNlbnRhZ2VzKGRhdGE6IElQcm9ncmVzc0l0ZW1bXSwgZnVuYzogRnVuY3Rpb24pIHtcbiAgICBjb25zdCByZXN1bHQgPSBkYXRhLnJlZHVjZSgoc3VtOiBudW1iZXIsIGl0ZW06IElQcm9ncmVzc0l0ZW0sIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHN1bSArPSBOdW1iZXIoaXRlbS5wZXJjZW50YWdlKTtcbiAgICAgIHN1bSA9IHN1bSA+IDEwMCB8fCAoaW5kZXggPiAwICYmIGluZGV4ID09PSBkYXRhLmxlbmd0aCAtIDEgJiYgdGhpcy5wZXJjZW50YWdlID09PSAxMDApID8gMTAwIDogc3VtO1xuICAgICAgZnVuYyhzdW0sIGl0ZW0pO1xuICAgICAgcmV0dXJuIHN1bTtcbiAgICB9LCAwKTtcbiAgICB0aGlzLnBlcmNlbnRhZ2UgPSB0aGlzLnBlcmNlbnRhZ2UgPj0gMTAwID8gMTAwIDogcmVzdWx0O1xuICB9XG5cbiAgY2hlY2tTdHJva2VDb2xvcigpOiBzdHJpbmcge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHRoaXMuc3Ryb2tlQ29sb3IpKSB7XG4gICAgICB0aGlzLmlzR3JhZGllbnQgPSB0cnVlO1xuICAgICAgdGhpcy5ncmFkaWVudENvbG9yID0gdGhpcy5zdHJva2VDb2xvcjtcbiAgICAgIGlmICh0aGlzLnR5cGUgPT09ICdsaW5lJykge1xuICAgICAgICBjb25zdCBjb2xvcnMgPSB0aGlzLnN0cm9rZUNvbG9yLm1hcCgoaXRlbSkgPT4gYCR7aXRlbS5jb2xvcn0gJHtpdGVtLnBlcmNlbnRhZ2V9YCkuam9pbignLCAnKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYGxpbmVhci1ncmFkaWVudCh0byByaWdodCwgJHtjb2xvcnN9KWA7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cm9rZUNvbG9yLmxlbmd0aCA/IHJlc3VsdCA6ICcnO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ2NpcmNsZScpIHtcbiAgICAgICAgcmV0dXJuIGB1cmwoI2RldnVpLXByb2dyZXNzLWdyYWRpZW50LSR7dGhpcy5pZH1gO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmlzR3JhZGllbnQgPSBmYWxzZTtcbiAgICAgIHRoaXMuc3Ryb2tlQ29sb3IgPSB0aGlzLnN0cm9rZUNvbG9yIHx8ICcnO1xuICAgICAgcmV0dXJuIHRoaXMuc3Ryb2tlQ29sb3I7XG4gICAgfVxuICB9XG59XG4iLCI8bmctY29udGFpbmVyICpuZ0lmPVwidHlwZSA9PT0gJ2xpbmUnXCI+XG4gIDxkaXYgaWQ9XCJkZXZ1aS1wcm9ncmVzcy1saW5lLXt7IGlkIH19XCIgY2xhc3M9XCJkZXZ1aS1wcm9ncmVzcyBkZXZ1aS1wcm9ncmVzcy1saW5lXCIgW3N0eWxlLmhlaWdodF09XCJzdHJva2VXaWR0aCArICdweCdcIj5cbiAgICA8ZGl2XG4gICAgICAqbmdGb3I9XCJsZXQgYmFyIG9mIHByb2dyZXNzRGF0YVwiXG4gICAgICBjbGFzcz1cImRldnVpLXByb2dyZXNzLWJhclwiXG4gICAgICBbY2xhc3MuZGV2dWktcHJvZ3Jlc3MtYmFyLWRlZmF1bHQtYmddPVwiIWJhci5jb2xvclwiXG4gICAgICBbc3R5bGUuYmFja2dyb3VuZF09XCJiYXIuY29sb3JcIlxuICAgICAgW3N0eWxlLndpZHRoXT1cImJhci53aWR0aCArICclJ1wiXG4gICAgPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICpuZ0lmPVwic2hvd0NvbnRlbnRDb25maWcuc2hvd0lubmVyQ29udGVudFwiXG4gICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImJhci50ZW1wbGF0ZSB8fCBkZWZhdWx0SW5uZXJDb250ZW50XCJcbiAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiB0aGlzLCBiYXI6IGJhciB9XCJcbiAgICAgID48L25nLXRlbXBsYXRlPlxuICAgIDwvZGl2PlxuICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgKm5nSWY9XCJzaG93Q29udGVudENvbmZpZy5zaG93Q2VudGVyQ29udGVudFwiXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjZW50ZXJUZW1wbGF0ZSB8fCBkZWZhdWx0Q2VudGVyQ29udGVudFwiXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHRoaXMgfVwiXG4gICAgPjwvbmctdGVtcGxhdGU+XG4gIDwvZGl2PlxuICA8bmctdGVtcGxhdGVcbiAgICAqbmdJZj1cInNob3dDb250ZW50Q29uZmlnLnNob3dPdXRlckNvbnRlbnRcIlxuICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm91dGVyVGVtcGxhdGUgfHwgZGVmYXVsdFBlcmNlbnRhZ2VUZXh0XCJcbiAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHRoaXMsIHBlcmNlbnRhZ2U6IHBlcmNlbnRhZ2UgfVwiXG4gID48L25nLXRlbXBsYXRlPlxuPC9uZy1jb250YWluZXI+XG5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJ0eXBlID09PSAnY2lyY2xlJ1wiPlxuICA8ZGl2IGlkPVwiZGV2dWktcHJvZ3Jlc3MtY2lyY2xlLXt7IGlkIH19XCIgY2xhc3M9XCJkZXZ1aS1wcm9ncmVzcyBkZXZ1aS1wcm9ncmVzcy1jaXJjbGVcIj5cbiAgICA8c3ZnIHZpZXdCb3g9XCIwIDAgMTAwIDEwMFwiPlxuICAgICAgPGRlZnMgKm5nSWY9XCJpc0dyYWRpZW50XCI+XG4gICAgICAgIDxsaW5lYXJHcmFkaWVudCBpZD1cImRldnVpLXByb2dyZXNzLWdyYWRpZW50LXt7IGlkIH19XCIgeDE9XCIxMDAlXCIgeTE9XCIwJVwiIHgyPVwiMCVcIiB5Mj1cIjAlXCI+XG4gICAgICAgICAgPHN0b3AgKm5nRm9yPVwibGV0IGNvbG9yIG9mIGdyYWRpZW50Q29sb3JcIiBbYXR0ci5vZmZzZXRdPVwiY29sb3IucGVyY2VudGFnZVwiIFthdHRyLnN0b3AtY29sb3JdPVwiY29sb3IuY29sb3JcIj48L3N0b3A+XG4gICAgICAgIDwvbGluZWFyR3JhZGllbnQ+XG4gICAgICA8L2RlZnM+XG4gICAgICA8cGF0aFxuICAgICAgICBjbGFzcz1cImRldnVpLXByb2dyZXNzLWNpcmNsZS10cmFpbFwiXG4gICAgICAgIGZpbGwtb3BhY2l0eT1cIjBcIlxuICAgICAgICBbYXR0ci5kXT1cInBhdGhTdHJpbmdcIlxuICAgICAgICBbYXR0ci5zdHJva2Utd2lkdGhdPVwic3Ryb2tlV2lkdGhcIlxuICAgICAgICBbbmdTdHlsZV09XCJ0cmFpbFBhdGhcIlxuICAgICAgPjwvcGF0aD5cbiAgICAgIDxwYXRoXG4gICAgICAgICpuZ0Zvcj1cImxldCBjaXJjbGUgb2YgcHJvZ3Jlc3NEYXRhXCJcbiAgICAgICAgZmlsbC1vcGFjaXR5PVwiMFwiXG4gICAgICAgIFthdHRyLmRdPVwicGF0aFN0cmluZ1wiXG4gICAgICAgIFthdHRyLnN0cm9rZV09XCJjaXJjbGUuY29sb3JcIlxuICAgICAgICBbYXR0ci5zdHJva2UtbGluZWNhcF09XCIncm91bmQnXCJcbiAgICAgICAgW2F0dHIuc3Ryb2tlLXdpZHRoXT1cImNpcmNsZS5wZXJjZW50YWdlID8gc3Ryb2tlV2lkdGggOiAwXCJcbiAgICAgICAgW2NsYXNzLmRldnVpLXByb2dyZXNzLWNpcmNsZS1wYXRoXT1cIiFpc0dyYWRpZW50XCJcbiAgICAgICAgW25nU3R5bGVdPVwiY2lyY2xlLnN0cm9rZVBhdGhcIlxuICAgICAgPlxuICAgICAgICA8dGl0bGU+e3sgY2lyY2xlLnBlcmNlbnRhZ2VUZXh0ID8gY2lyY2xlLnBlcmNlbnRhZ2VUZXh0IDogY2lyY2xlLnBlcmNlbnRhZ2UgKyAnJScgfX08L3RpdGxlPlxuICAgICAgPC9wYXRoPlxuICAgIDwvc3ZnPlxuICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgKm5nSWY9XCJzaG93Q29udGVudENvbmZpZy5zaG93Q2VudGVyQ29udGVudFwiXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjZW50ZXJUZW1wbGF0ZSB8fCBkZWZhdWx0UGVyY2VudGFnZVRleHRcIlxuICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiB0aGlzLCBwZXJjZW50YWdlOiBwZXJjZW50YWdlIH1cIlxuICAgID48L25nLXRlbXBsYXRlPlxuICA8L2Rpdj5cbjwvbmctY29udGFpbmVyPlxuXG48bmctdGVtcGxhdGUgI2RlZmF1bHRJbm5lckNvbnRlbnQgbGV0LWJhcj1cImJhclwiPlxuICA8c3BhbiBbc3R5bGUubGluZS1oZWlnaHRdPVwic3Ryb2tlV2lkdGggKyAncHgnXCIgW3RpdGxlXT1cImJhci5wZXJjZW50YWdlVGV4dCA/IGJhci5wZXJjZW50YWdlVGV4dCA6IGJhci5wZXJjZW50YWdlICsgJyUnXCI+XG4gICAge3sgYmFyLnBlcmNlbnRhZ2VUZXh0ID8gYmFyLnBlcmNlbnRhZ2VUZXh0IDogYmFyLnBlcmNlbnRhZ2UgKyAnJScgfX1cbiAgPC9zcGFuPlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0Q2VudGVyQ29udGVudD5cbiAgPHNwYW4gW3N0eWxlLmxpbmUtaGVpZ2h0XT1cInN0cm9rZVdpZHRoICsgJ3B4J1wiIFt0aXRsZV09XCJjb250ZW50XCI+e3sgY29udGVudCB9fTwvc3Bhbj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdFBlcmNlbnRhZ2VUZXh0PlxuICA8ZGl2IGNsYXNzPVwiZGV2dWktcHJvZ3Jlc3MtZGVmYXVsdC10ZXh0XCIgW3RpdGxlXT1cImNvbnRlbnRcIj57eyBjb250ZW50IH19PC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19