UNPKG

@nova-ui/bits

Version:

SolarWinds Nova Framework

188 lines 33 kB
// © 2023 SolarWinds Worldwide, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { Component, ElementRef, Inject, Input, ViewChild, } from "@angular/core"; import { WindowToken } from "../helpers/window"; import * as i0 from "@angular/core"; export class TextHighlightOverlayComponent { get container() { return this.parentContainer.nativeElement; } get textHolder() { return this.textContainer.nativeElement; } get span() { return this.text.nativeElement; } constructor(window) { this.ONE_SIDE_STROKE_WIDTH = 1; this.BOTH_SIDES_STROKE_WIDTH = 2; this.BOX_SUM_PADDING = 8; this.window = window; } ngOnChanges(changes) { if (changes.model && changes.model.previousValue) { setTimeout(() => this.highlightTokens(this.model.tokens)); } } ngOnInit() { // @ts-ignore const resizeObserver = new ResizeObserver(() => { this.highlightTokens(this.model.tokens); }); resizeObserver.observe(this.textHolder); setTimeout(() => this.highlightTokens(this.model.tokens)); } getBorderWidths(element) { const getBorderWidth = (direction) => this.getPixelPropertyValue(element, "border-" + direction + "-width"); return { top: getBorderWidth("top"), bottom: getBorderWidth("bottom"), left: getBorderWidth("left"), right: getBorderWidth("right"), }; } getPaddings(element) { const getPaddingSize = (direction) => this.getPixelPropertyValue(element, "padding-" + direction); return { top: getPaddingSize("top"), bottom: getPaddingSize("bottom"), left: getPaddingSize("left"), right: getPaddingSize("right"), }; } getPixelPropertyValue(element, propName) { return Number(this.window .getComputedStyle(element, null) .getPropertyValue(propName) .split("px")[0]); } highlightTokens(tokens) { const canvas = this.highlightCanvas .nativeElement; if (!this.renderConfigurator || !canvas) { return; } const context = canvas.getContext("2d"); this.setupContext(context, canvas); if (!tokens || tokens.length === 0) { return; } const containerRect = this.container.getBoundingClientRect(); const textHolderPaddings = this.getPaddings(this.textHolder); const baseLeft = containerRect.left + textHolderPaddings.left; const baseTop = containerRect.top + textHolderPaddings.top; if (this.renderConfigurator.enhanceTokens) { tokens = this.renderConfigurator.enhanceTokens(tokens); } this.processTokens(tokens, context, baseLeft, baseTop); } processTokens(tokens, ctx, baseLeft, baseTop) { for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; const color = this.renderConfigurator.getHighlightColor(token); const notifColor = this.renderConfigurator.getNotifColor(token); if (!color && !notifColor) { continue; } if (!this.span.childNodes[0].textContent || this.span.childNodes[0].textContent.length <= token.start || this.span.childNodes[0].textContent.length <= token.end) { continue; } this.highlightToken(token, ctx, { notif: notifColor, highlight: color }, { left: baseLeft, top: baseTop }); } } setupContext(context, canvas) { context.lineWidth = 1; const childPaddingSizes = this.getPaddings(this.textHolder); const childBorderWidths = this.getBorderWidths(this.textHolder); const childHeight = this.getPixelPropertyValue(this.textHolder, "height"); const childWidth = this.getPixelPropertyValue(this.textHolder, "width"); const parentWidth = this.getPixelPropertyValue(this.container, "width"); context.canvas.width = childWidth - childPaddingSizes.left - childPaddingSizes.right - childBorderWidths.left - childBorderWidths.right; context.canvas.height = childHeight - childPaddingSizes.top - childPaddingSizes.bottom - childBorderWidths.top - childBorderWidths.bottom; context.canvas.style.width = parentWidth + "px"; context.canvas.style.height = childHeight + "px"; context.shadowOffsetX = 0; context.shadowOffsetY = 0; context.clearRect(0, 0, canvas.width, canvas.height); } highlightToken(token, context, colors, coordBase) { const range = document.createRange(); range.setStart(this.span.childNodes[0], token.start); range.setEnd(this.span.childNodes[0], token.end); const rects = range.getClientRects(); for (let rectIdx = 0; rectIdx < rects.length; rectIdx++) { const rect = rects[rectIdx]; context.beginPath(); if (colors.notif) { this.addNotificationRectangle(colors, context, rect, coordBase); } if (colors.highlight) { this.addHighlightRectangle(colors, context, rect, coordBase); } context.closePath(); } } addHighlightRectangle(colors, context, rect, coordBase) { context.fillStyle = colors.highlight; context.fillRect(rect.left - coordBase.left - this.ONE_SIDE_STROKE_WIDTH, rect.top - coordBase.top, rect.width + this.BOX_SUM_PADDING, rect.height - this.BOTH_SIDES_STROKE_WIDTH); } addNotificationRectangle(colors, context, rect, coordBase) { context.strokeStyle = colors.notif; context.strokeRect(rect.left - coordBase.left - this.BOTH_SIDES_STROKE_WIDTH, rect.top - coordBase.top - this.ONE_SIDE_STROKE_WIDTH, rect.width + this.BOX_SUM_PADDING + this.BOTH_SIDES_STROKE_WIDTH, rect.height); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextHighlightOverlayComponent, deps: [{ token: WindowToken }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextHighlightOverlayComponent, selector: "nui-text-highlight-overlay", inputs: { model: "model", renderConfigurator: "renderConfigurator" }, viewQueries: [{ propertyName: "parentContainer", first: true, predicate: ["parentContainer"], descendants: true, static: true }, { propertyName: "textContainer", first: true, predicate: ["textContainer"], descendants: true, static: true }, { propertyName: "text", first: true, predicate: ["text"], descendants: true, static: true }, { propertyName: "highlightCanvas", first: true, predicate: ["highlightCanvas"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #parentContainer class=\"parent\">\n <div #textContainer class=\"child\">\n <span #text class=\"text\">{{this.model.value}}</span>\n </div>\n <canvas #highlightCanvas id=\"highlightCanvas\" class=\"canvas\"></canvas>\n</div>\n", styles: [".child{word-break:break-word;background-color:transparent;line-height:1.66666667;font-size:13px;font-family:monospace;width:100%;border:1px solid transparent;min-height:34px;padding:5px 10px}.parent{position:relative}.parent .text{white-space:break-spaces}.parent .canvas{padding:5px 10px;border:1px solid transparent;position:absolute;pointer-events:none;top:0;left:0;height:100%;width:calc(100% + 1px)}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextHighlightOverlayComponent, decorators: [{ type: Component, args: [{ selector: "nui-text-highlight-overlay", template: "<div #parentContainer class=\"parent\">\n <div #textContainer class=\"child\">\n <span #text class=\"text\">{{this.model.value}}</span>\n </div>\n <canvas #highlightCanvas id=\"highlightCanvas\" class=\"canvas\"></canvas>\n</div>\n", styles: [".child{word-break:break-word;background-color:transparent;line-height:1.66666667;font-size:13px;font-family:monospace;width:100%;border:1px solid transparent;min-height:34px;padding:5px 10px}.parent{position:relative}.parent .text{white-space:break-spaces}.parent .canvas{padding:5px 10px;border:1px solid transparent;position:absolute;pointer-events:none;top:0;left:0;height:100%;width:calc(100% + 1px)}\n"] }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [WindowToken] }] }], propDecorators: { model: [{ type: Input }], renderConfigurator: [{ type: Input }], parentContainer: [{ type: ViewChild, args: ["parentContainer", { static: true }] }], textContainer: [{ type: ViewChild, args: ["textContainer", { static: true }] }], text: [{ type: ViewChild, args: ["text", { static: true }] }], highlightCanvas: [{ type: ViewChild, args: ["highlightCanvas", { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1oaWdobGlnaHQtb3ZlcmxheS1jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ZyZWV0eXBlLXF1ZXJ5LWJ1aWxkZXIvdGV4dC1oaWdobGlnaHQtb3ZlcmxheS90ZXh0LWhpZ2hsaWdodC1vdmVybGF5LWNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZnJlZXR5cGUtcXVlcnktYnVpbGRlci90ZXh0LWhpZ2hsaWdodC1vdmVybGF5L3RleHQtaGlnaGxpZ2h0LW92ZXJsYXktY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFDSCxTQUFTLEVBQ1QsVUFBVSxFQUNWLE1BQU0sRUFDTixLQUFLLEVBSUwsU0FBUyxHQUNaLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7QUFjaEQsTUFBTSxPQUFPLDZCQUE2QjtJQXFCdEMsSUFBWSxTQUFTO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUM7SUFDOUMsQ0FBQztJQUVELElBQVksVUFBVTtRQUNsQixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDO0lBQzVDLENBQUM7SUFFRCxJQUFZLElBQUk7UUFDWixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFD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cUJBQXFCLEVBQ3JELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLEVBQ2hFLElBQUksQ0FBQyxNQUFNLENBQ2QsQ0FBQztJQUNOLENBQUM7K0dBck9RLDZCQUE2QixrQkFrQ2xCLFdBQVc7bUdBbEN0Qiw2QkFBNkIsOGxCQzdDMUMseVBBTUE7OzRGRHVDYSw2QkFBNkI7a0JBTHpDLFNBQVM7K0JBQ0ksNEJBQTRCOzswQkFzQ3pCLE1BQU07MkJBQUMsV0FBVzt5Q0ExQi9CLEtBQUs7c0JBREosS0FBSztnQkFHTixrQkFBa0I7c0JBRGpCLEtBQUs7Z0JBSU4sZUFBZTtzQkFEZCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFHOUMsYUFBYTtzQkFEWixTQUFTO3VCQUFDLGVBQWUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRzVDLElBQUk7c0JBREgsU0FBUzt1QkFBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUduQyxlQUFlO3NCQURkLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMyBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgSW5qZWN0LFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkluaXQsXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBWaWV3Q2hpbGQsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5cbmltcG9ydCB7IFdpbmRvd1Rva2VuIH0gZnJvbSBcIi4uL2hlbHBlcnMvd2luZG93XCI7XG5pbXBvcnQge1xuICAgIEJhc2VDb29yZGluYXRlcyxcbiAgICBDb2xvcnNDb25mLFxuICAgIEVsZW1lbnRQYWRkaW5nLFxuICAgIFF1ZXJ5VG9rZW4sXG4gICAgUmVuZGVyQ29uZmlndXJhdG9yLFxufSBmcm9tIFwiLi4vbW9kZWxzXCI7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiBcIm51aS10ZXh0LWhpZ2hsaWdodC1vdmVybGF5XCIsXG4gICAgdGVtcGxhdGVVcmw6IFwiLi90ZXh0LWhpZ2hsaWdodC1vdmVybGF5LWNvbXBvbmVudC5odG1sXCIsXG4gICAgc3R5bGVVcmxzOiBbXCIuL3RleHQtaGlnaGxpZ2h0LW92ZXJsYXktY29tcG9uZW50Lmxlc3NcIl0sXG59KVxuZXhwb3J0IGNsYXNzIFRleHRIaWdobGlnaHRPdmVybGF5Q29tcG9uZW50PFQgZXh0ZW5kcyBRdWVyeVRva2VuPlxuICAgIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXNcbntcbiAgICByZWFkb25seSBPTkVfU0lERV9TVFJPS0VfV0lEVEggPSAxO1xuICAgIHJlYWRvbmx5IEJPVEhfU0lERVNfU1RST0tFX1dJRFRIID0gMjtcbiAgICByZWFkb25seSBCT1hfU1VNX1BBRERJTkcgPSA4O1xuXG4gICAgQElucHV0KClcbiAgICBtb2RlbDogeyB2YWx1ZTogc3RyaW5nOyB0b2tlbnM6IFRbXSB9O1xuICAgIEBJbnB1dCgpXG4gICAgcmVuZGVyQ29uZmlndXJhdG9yOiBSZW5kZXJDb25maWd1cmF0b3I8VD47XG5cbiAgICBAVmlld0NoaWxkKFwicGFyZW50Q29udGFpbmVyXCIsIHsgc3RhdGljOiB0cnVlIH0pXG4gICAgcGFyZW50Q29udGFpbmVyOiBFbGVtZW50UmVmO1xuICAgIEBWaWV3Q2hpbGQoXCJ0ZXh0Q29udGFpbmVyXCIsIHsgc3RhdGljOiB0cnVlIH0pXG4gICAgdGV4dENvbnRhaW5lcjogRWxlbWVudFJlZjtcbiAgICBAVmlld0NoaWxkKFwidGV4dFwiLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHRleHQ6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZChcImhpZ2hsaWdodENhbnZhc1wiLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIGhpZ2hsaWdodENhbnZhczogRWxlbWVudFJlZjtcblxuICAgIHByaXZhdGUgZ2V0IGNvbnRhaW5lcigpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudENvbnRhaW5lci5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IHRleHRIb2xkZXIoKTogSFRNTFRleHRBcmVhRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLnRleHRDb250YWluZXIubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBzcGFuKCk6IEhUTUxFbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGV4dC5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgd2luZG93OiBXaW5kb3c7XG4gICAgY29uc3RydWN0b3IoQEluamVjdChXaW5kb3dUb2tlbikgd2luZG93OiBhbnkpIHtcbiAgICAgICAgdGhpcy53aW5kb3cgPSB3aW5kb3cgYXMgV2luZG93O1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKGNoYW5nZXMubW9kZWwgJiYgY2hhbmdlcy5tb2RlbC5wcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaGlnaGxpZ2h0VG9rZW5zKHRoaXMubW9kZWwudG9rZW5zKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICBjb25zdCByZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmhpZ2hsaWdodFRva2Vucyh0aGlzLm1vZGVsLnRva2Vucyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMudGV4dEhvbGRlcik7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5oaWdobGlnaHRUb2tlbnModGhpcy5tb2RlbC50b2tlbnMpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEJvcmRlcldpZHRocyhlbGVtZW50OiBIVE1MVGV4dEFyZWFFbGVtZW50KTogRWxlbWVudFBhZGRpbmcge1xuICAgICAgICBjb25zdCBnZXRCb3JkZXJXaWR0aCA9IChkaXJlY3Rpb246IHN0cmluZyk6IG51bWJlciA9PlxuICAgICAgICAgICAgdGhpcy5nZXRQaXhlbFByb3BlcnR5VmFsdWUoXG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBcImJvcmRlci1cIiArIGRpcmVjdGlvbiArIFwiLXdpZHRoXCJcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRvcDogZ2V0Qm9yZGVyV2lkdGgoXCJ0b3BcIiksXG4gICAgICAgICAgICBib3R0b206IGdldEJvcmRlcldpZHRoKFwiYm90dG9tXCIpLFxuICAgICAgICAgICAgbGVmdDogZ2V0Qm9yZGVyV2lkdGgoXCJsZWZ0XCIpLFxuICAgICAgICAgICAgcmlnaHQ6IGdldEJvcmRlcldpZHRoKFwicmlnaHRcIiksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRQYWRkaW5ncyhlbGVtZW50OiBIVE1MVGV4dEFyZWFFbGVtZW50KTogRWxlbWVudFBhZGRpbmcge1xuICAgICAgICBjb25zdCBnZXRQYWRkaW5nU2l6ZSA9IChkaXJlY3Rpb246IHN0cmluZyk6IG51bWJlciA9PlxuICAgICAgICAgICAgdGhpcy5nZXRQaXhlbFByb3BlcnR5VmFsdWUoZWxlbWVudCwgXCJwYWRkaW5nLVwiICsgZGlyZWN0aW9uKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdG9wOiBnZXRQYWRkaW5nU2l6ZShcInRvcFwiKSxcbiAgICAgICAgICAgIGJvdHRvbTogZ2V0UGFkZGluZ1NpemUoXCJib3R0b21cIiksXG4gICAgICAgICAgICBsZWZ0OiBnZXRQYWRkaW5nU2l6ZShcImxlZnRcIiksXG4gICAgICAgICAgICByaWdodDogZ2V0UGFkZGluZ1NpemUoXCJyaWdodFwiKSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFBpeGVsUHJvcGVydHlWYWx1ZShcbiAgICAgICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgICAgIHByb3BOYW1lOiBzdHJpbmdcbiAgICApOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTnVtYmVyKFxuICAgICAgICAgICAgdGhpcy53aW5kb3dcbiAgICAgICAgICAgICAgICAuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50LCBudWxsKVxuICAgICAgICAgICAgICAgIC5nZXRQcm9wZXJ0eVZhbHVlKHByb3BOYW1lKVxuICAgICAgICAgICAgICAgIC5zcGxpdChcInB4XCIpWzBdXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoaWdobGlnaHRUb2tlbnModG9rZW5zOiBUW10pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IHRoaXMuaGlnaGxpZ2h0Q2FudmFzXG4gICAgICAgICAgICAubmF0aXZlRWxlbWVudCBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICAgICAgaWYgKCF0aGlzLnJlbmRlckNvbmZpZ3VyYXRvciB8fCAhY2FudmFzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIikgYXMgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICAgICAgICB0aGlzLnNldHVwQ29udGV4dChjb250ZXh0LCBjYW52YXMpO1xuICAgICAgICBpZiAoIXRva2VucyB8fCB0b2tlbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29udGFpbmVyUmVjdCA9IHRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCB0ZXh0SG9sZGVyUGFkZGluZ3MgPSB0aGlzLmdldFBhZGRpbmdzKHRoaXMudGV4dEhvbGRlcik7XG4gICAgICAgIGNvbnN0IGJhc2VMZWZ0OiBudW1iZXIgPSBjb250YWluZXJSZWN0LmxlZnQgKyB0ZXh0SG9sZGVyUGFkZGluZ3MubGVmdDtcbiAgICAgICAgY29uc3QgYmFzZVRvcDogbnVtYmVyID0gY29udGFpbmVyUmVjdC50b3AgKyB0ZXh0SG9sZGVyUGFkZGluZ3MudG9wO1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJDb25maWd1cmF0b3IuZW5oYW5jZVRva2Vucykge1xuICAgICAgICAgICAgdG9rZW5zID0gdGhpcy5yZW5kZXJDb25maWd1cmF0b3IuZW5oYW5jZVRva2Vucyh0b2tlbnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvY2Vzc1Rva2Vucyh0b2tlbnMsIGNvbnRleHQsIGJhc2VMZWZ0LCBiYXNlVG9wKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbnMoXG4gICAgICAgIHRva2VuczogVFtdLFxuICAgICAgICBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCxcbiAgICAgICAgYmFzZUxlZnQ6IGFueSxcbiAgICAgICAgYmFzZVRvcDogYW55XG4gICAgKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gdGhpcy5yZW5kZXJDb25maWd1cmF0b3IuZ2V0SGlnaGxpZ2h0Q29sb3IodG9rZW4pO1xuICAgICAgICAgICAgY29uc3Qgbm90aWZDb2xvciA9IHRoaXMucmVuZGVyQ29uZmlndXJhdG9yLmdldE5vdGlmQ29sb3IodG9rZW4pO1xuICAgICAgICAgICAgaWYgKCFjb2xvciAmJiAhbm90aWZDb2xvcikge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICF0aGlzLnNwYW4uY2hpbGROb2Rlc1swXS50ZXh0Q29udGVudCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuc3Bhbi5jaGlsZE5vZGVzWzBdLnRleHRDb250ZW50Lmxlbmd0aCA8PSB0b2tlbi5zdGFydCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuc3Bhbi5jaGlsZE5vZGVzWzBdLnRleHRDb250ZW50Lmxlbmd0aCA8PSB0b2tlbi5lbmRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRUb2tlbihcbiAgICAgICAgICAgICAgICB0b2tlbixcbiAgICAgICAgICAgICAgICBjdHgsXG4gICAgICAgICAgICAgICAgeyBub3RpZjogbm90aWZDb2xvciwgaGlnaGxpZ2h0OiBjb2xvciB9LFxuICAgICAgICAgICAgICAgIHsgbGVmdDogYmFzZUxlZnQsIHRvcDogYmFzZVRvcCB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXR1cENvbnRleHQoXG4gICAgICAgIGNvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCxcbiAgICAgICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudFxuICAgICk6IHZvaWQge1xuICAgICAgICBjb250ZXh0LmxpbmVXaWR0aCA9IDE7XG4gICAgICAgIGNvbnN0IGNoaWxkUGFkZGluZ1NpemVzID0gdGhpcy5nZXRQYWRkaW5ncyh0aGlzLnRleHRIb2xkZXIpO1xuICAgICAgICBjb25zdCBjaGlsZEJvcmRlcldpZHRocyA9IHRoaXMuZ2V0Qm9yZGVyV2lkdGhzKHRoaXMudGV4dEhvbGRlcik7XG5cbiAgICAgICAgY29uc3QgY2hpbGRIZWlnaHQgPSB0aGlzLmdldFBpeGVsUHJvcGVydHlWYWx1ZShcbiAgICAgICAgICAgIHRoaXMudGV4dEhvbGRlcixcbiAgICAgICAgICAgIFwiaGVpZ2h0XCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgY2hpbGRXaWR0aCA9IHRoaXMuZ2V0UGl4ZWxQcm9wZXJ0eVZhbHVlKHRoaXMudGV4dEhvbGRlciwgXCJ3aWR0aFwiKTtcbiAgICAgICAgY29uc3QgcGFyZW50V2lkdGggPSB0aGlzLmdldFBpeGVsUHJvcGVydHlWYWx1ZSh0aGlzLmNvbnRhaW5lciwgXCJ3aWR0aFwiKTtcblxuICAgICAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9XG4gICAgICAgICAgICBjaGlsZFdpZHRoIC1cbiAgICAgICAgICAgIGNoaWxkUGFkZGluZ1NpemVzLmxlZnQgLVxuICAgICAgICAgICAgY2hpbGRQYWRkaW5nU2l6ZXMucmlnaHQgLVxuICAgICAgICAgICAgY2hpbGRCb3JkZXJXaWR0aHMubGVmdCAtXG4gICAgICAgICAgICBjaGlsZEJvcmRlcldpZHRocy5yaWdodDtcbiAgICAgICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID1cbiAgICAgICAgICAgIGNoaWxkSGVpZ2h0IC1cbiAgICAgICAgICAgIGNoaWxkUGFkZGluZ1NpemVzLnRvcCAtXG4gICAgICAgICAgICBjaGlsZFBhZGRpbmdTaXplcy5ib3R0b20gLVxuICAgICAgICAgICAgY2hpbGRCb3JkZXJXaWR0aHMudG9wIC1cbiAgICAgICAgICAgIGNoaWxkQm9yZGVyV2lkdGhzLmJvdHRvbTtcbiAgICAgICAgY29udGV4dC5jYW52YXMuc3R5bGUud2lkdGggPSBwYXJlbnRXaWR0aCArIFwicHhcIjtcbiAgICAgICAgY29udGV4dC5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gY2hpbGRIZWlnaHQgKyBcInB4XCI7XG4gICAgICAgIGNvbnRleHQuc2hhZG93T2Zmc2V0WCA9IDA7XG4gICAgICAgIGNvbnRleHQuc2hhZG93T2Zmc2V0WSA9IDA7XG5cbiAgICAgICAgY29udGV4dC5jbGVhclJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhpZ2hsaWdodFRva2VuKFxuICAgICAgICB0b2tlbjogVCxcbiAgICAgICAgY29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELFxuICAgICAgICBjb2xvcnM6IENvbG9yc0NvbmYsXG4gICAgICAgIGNvb3JkQmFzZTogQmFzZUNvb3JkaW5hdGVzXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgcmFuZ2Uuc2V0U3RhcnQodGhpcy5zcGFuLmNoaWxkTm9kZXNbMF0sIHRva2VuLnN0YXJ0KTtcbiAgICAgICAgcmFuZ2Uuc2V0RW5kKHRoaXMuc3Bhbi5jaGlsZE5vZGVzWzBdLCB0b2tlbi5lbmQpO1xuICAgICAgICBjb25zdCByZWN0cyA9IHJhbmdlLmdldENsaWVudFJlY3RzKCk7XG5cbiAgICAgICAgZm9yIChsZXQgcmVjdElkeCA9IDA7IHJlY3RJZHggPCByZWN0cy5sZW5ndGg7IHJlY3RJZHgrKykge1xuICAgICAgICAgICAgY29uc3QgcmVjdCA9IHJlY3RzW3JlY3RJZHhdO1xuICAgICAgICAgICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIGlmIChjb2xvcnMubm90aWYpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZE5vdGlmaWNhdGlvblJlY3RhbmdsZShjb2xvcnMsIGNvbnRleHQsIHJlY3QsIGNvb3JkQmFzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29sb3JzLmhpZ2hsaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkSGlnaGxpZ2h0UmVjdGFuZ2xlKGNvbG9ycywgY29udGV4dCwgcmVjdCwgY29vcmRCYXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFkZEhpZ2hsaWdodFJlY3RhbmdsZShcbiAgICAgICAgY29sb3JzOiBDb2xvcnNDb25mLFxuICAgICAgICBjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsXG4gICAgICAgIHJlY3Q6IERPTVJlY3QsXG4gICAgICAgIGNvb3JkQmFzZTogQmFzZUNvb3JkaW5hdGVzXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gY29sb3JzLmhpZ2hsaWdodDtcbiAgICAgICAgY29udGV4dC5maWxsUmVjdChcbiAgICAgICAgICAgIHJlY3QubGVmdCAtIGNvb3JkQmFzZS5sZWZ0IC0gdGhpcy5PTkVfU0lERV9TVFJPS0VfV0lEVEgsXG4gICAgICAgICAgICByZWN0LnRvcCAtIGNvb3JkQmFzZS50b3AsXG4gICAgICAgICAgICByZWN0LndpZHRoICsgdGhpcy5CT1hfU1VNX1BBRERJTkcsXG4gICAgICAgICAgICByZWN0LmhlaWdodCAtIHRoaXMuQk9USF9TSURFU19TVFJPS0VfV0lEVEhcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFkZE5vdGlmaWNhdGlvblJlY3RhbmdsZShcbiAgICAgICAgY29sb3JzOiBDb2xvcnNDb25mLFxuICAgICAgICBjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsXG4gICAgICAgIHJlY3Q6IERPTVJlY3QsXG4gICAgICAgIGNvb3JkQmFzZTogQmFzZUNvb3JkaW5hdGVzXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSBjb2xvcnMubm90aWY7XG4gICAgICAgIGNvbnRleHQuc3Ryb2tlUmVjdChcbiAgICAgICAgICAgIHJlY3QubGVmdCAtIGNvb3JkQmFzZS5sZWZ0IC0gdGhpcy5CT1RIX1NJREVTX1NUUk9LRV9XSURUSCxcbiAgICAgICAgICAgIHJlY3QudG9wIC0gY29vcmRCYXNlLnRvcCAtIHRoaXMuT05FX1NJREVfU1RST0tFX1dJRFRILFxuICAgICAgICAgICAgcmVjdC53aWR0aCArIHRoaXMuQk9YX1NVTV9QQURESU5HICsgdGhpcy5CT1RIX1NJREVTX1NUUk9LRV9XSURUSCxcbiAgICAgICAgICAgIHJlY3QuaGVpZ2h0XG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiPGRpdiAjcGFyZW50Q29udGFpbmVyIGNsYXNzPVwicGFyZW50XCI+XG4gICAgPGRpdiAjdGV4dENvbnRhaW5lciBjbGFzcz1cImNoaWxkXCI+XG4gICAgICAgIDxzcGFuICN0ZXh0IGNsYXNzPVwidGV4dFwiPnt7dGhpcy5tb2RlbC52YWx1ZX19PC9zcGFuPlxuICAgIDwvZGl2PlxuICAgIDxjYW52YXMgI2hpZ2hsaWdodENhbnZhcyBpZD1cImhpZ2hsaWdodENhbnZhc1wiIGNsYXNzPVwiY2FudmFzXCI+PC9jYW52YXM+XG48L2Rpdj5cbiJdfQ==