UNPKG

ng-cw-v12

Version:

Angular UI Component Library

419 lines 66.4 kB
import { Directive, Input, Output, EventEmitter } from '@angular/core'; import * as i0 from "@angular/core"; export class ElectricBorderDirective { constructor(el, renderer, ngZone) { this.el = el; this.renderer = renderer; this.ngZone = ngZone; /** 边框圆角半径 单位px */ this.ncBorderRadius = 24; /** 边框线宽 单位px */ this.ncBorderWidth = 2; /** 电弧宽度 单位px */ this.ncElectricWidth = 1; /** 颜色 */ this.ncColor = '#5227FF'; /** 动画速度倍率 */ this.ncSpeed = 1; /** 扰动强度(振幅) */ this.ncChaos = 0.12; /** 停止动画时间,ms,0表示不停止 */ this.ncStopTime = 0; /** 是否启用动画 */ this._enabled = true; /** 双向绑定输出事件 */ this.ncEnabledChange = new EventEmitter(); // 动画状态 this.animationId = null; this.time = 0; this.lastFrameTime = 0; this.isInitialized = false; } set ncEnabled(val) { this._enabled = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncEnabled() { return this._enabled; } ngOnInit() { this.setupHost(); this.createDom(); this.injectStyles(); this.isInitialized = true; if (this.ncEnabled) { this.startAnimation(); } } ngOnChanges(changes) { if (!this.isInitialized) return; // ncColor / ncSpeed / ncChaos / ncElectricWidth / ncBorderRadius 在 drawFrame() 中每帧直接读取,变更自动生效,无需处理。 // ncColor 除 canvas strokeStyle 外还驱动三个 glow DOM 元素,需显式更新。 if (changes['ncColor']) { this.applyColorVar(); } // ncBorderRadius 除 canvas路径圆角 外还影响宿主元素 CSS border-radius(glow 层用 inherit 会跟随),需显式更新。 if (changes['ncBorderRadius']) { this.applyBorderRadius(); } // ncBorderWidth 影响 glow 层 border 宽度(需显式更新) if (changes['ncBorderWidth']) { this.applyBorderWidth(); } // ncEnabled 变化时启停动画 if (changes['ncEnabled']) { if (this.ncEnabled) { this.startAnimation(); } else { this.stopAnimation(); } } } ngOnDestroy() { this.stopAnimation(); if (this.resizeObserver) { this.resizeObserver.disconnect(); } if (this.stopTimer) { clearTimeout(this.stopTimer); } } // ─── 初始化 ───────────────────────────────────────────────────────────────── setupHost() { const host = this.el.nativeElement; const pos = getComputedStyle(host).position; if (!pos || pos === 'static') { this.renderer.setStyle(host, 'position', 'relative'); } this.renderer.setStyle(host, 'isolation', 'isolate'); this.renderer.setStyle(host, 'overflow', 'visible'); this.applyColorVar(); this.applyBorderRadius(); } applyBorderRadius() { this.renderer.setStyle(this.el.nativeElement, 'border-radius', `${this.ncBorderRadius}px`); } applyBorderWidth() { if (this.glow1El) { this.renderer.setStyle(this.glow1El, 'border-width', `${this.ncBorderWidth}px`); } if (this.glow2El) { this.renderer.setStyle(this.glow2El, 'border-width', `${this.ncBorderWidth}px`); } } applyColorVar() { this.renderer.setStyle(this.el.nativeElement, '--electric-border-color', this.ncColor); // 同步更新已存在的 glow 层颜色(ngOnChanges 时也能生效) if (this.glow1El) { this.renderer.setStyle(this.glow1El, 'border-color', `oklch(from ${this.ncColor} l c h / 0.6)`); } if (this.glow2El) { this.renderer.setStyle(this.glow2El, 'border-color', this.ncColor); } if (this.bgGlowEl) { this.renderer.setStyle(this.bgGlowEl, 'background', `linear-gradient(-30deg, ${this.ncColor}, transparent, ${this.ncColor})`); } } createDom() { const host = this.el.nativeElement; // ── canvas 容器 ── this.canvasContainerEl = this.renderer.createElement('div'); this.renderer.addClass(this.canvasContainerEl, 'nc-eb-canvas-container'); this.setStyles(this.canvasContainerEl, { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', 'pointer-events': 'none', 'z-index': '2' }); // ── canvas ── this.canvasEl = this.renderer.createElement('canvas'); this.renderer.addClass(this.canvasEl, 'nc-eb-canvas'); this.renderer.setStyle(this.canvasEl, 'display', 'block'); this.renderer.appendChild(this.canvasContainerEl, this.canvasEl); this.renderer.appendChild(host, this.canvasContainerEl); // ── glow 层容器 ── this.layersEl = this.renderer.createElement('div'); this.renderer.addClass(this.layersEl, 'nc-eb-layers'); this.setStyles(this.layersEl, { position: 'absolute', inset: '0', 'border-radius': 'inherit', 'pointer-events': 'none', 'z-index': '0' }); const glowBase = { position: 'absolute', inset: '0', 'border-radius': 'inherit', 'pointer-events': 'none', 'box-sizing': 'border-box' }; // nc-eb-glow-1 this.glow1El = this.renderer.createElement('div'); this.renderer.addClass(this.glow1El, 'nc-eb-glow-1'); this.setStyles(this.glow1El, Object.assign(Object.assign({}, glowBase), { border: `${this.ncBorderWidth}px solid ${this.ncColor}`, filter: 'blur(1px)' })); // nc-eb-glow-2 this.glow2El = this.renderer.createElement('div'); this.renderer.addClass(this.glow2El, 'nc-eb-glow-2'); this.setStyles(this.glow2El, Object.assign(Object.assign({}, glowBase), { border: `${this.ncBorderWidth}px solid ${this.ncColor}`, filter: 'blur(4px)' })); // nc-eb-background-glow this.bgGlowEl = this.renderer.createElement('div'); this.renderer.addClass(this.bgGlowEl, 'nc-eb-background-glow'); this.setStyles(this.bgGlowEl, Object.assign(Object.assign({}, glowBase), { 'z-index': '-1', transform: 'scale(1.1)', filter: 'blur(32px)', opacity: '0.3', background: `linear-gradient(-30deg, ${this.ncColor}, transparent, ${this.ncColor})` })); this.renderer.appendChild(this.layersEl, this.glow1El); this.renderer.appendChild(this.layersEl, this.glow2El); this.renderer.appendChild(this.layersEl, this.bgGlowEl); this.renderer.appendChild(host, this.layersEl); } injectStyles() { // oklch() CSS 函数需要现代浏览器,此处通过 <style> 注入 eb-glow 透明度变量 this.styleEl = this.renderer.createElement('style'); const css = ` [ncElectricBorder] { --electric-light-color: oklch(from var(--electric-border-color) l c h); } `; this.renderer.appendChild(this.styleEl, this.renderer.createText(css)); this.renderer.appendChild(document.head, this.styleEl); } // ─── 动画控制 ──────────────────────────────────────────────────────────────── startAnimation() { if (!this.canvasEl) return; // 显示 canvas 容器和 glow 层 this.renderer.setStyle(this.canvasContainerEl, 'display', 'block'); this.renderer.setStyle(this.layersEl, 'display', 'block'); // 重置时间(避免首帧大幅跳变) this.lastFrameTime = 0; this.ngZone.runOutsideAngular(() => { // 启动 ResizeObserver this.resizeObserver = new ResizeObserver(() => this.updateCanvasSize()); this.resizeObserver.observe(this.el.nativeElement); this.updateCanvasSize(); // 启动 rAF 循环 const loop = (currentTime) => { this.drawFrame(currentTime); this.animationId = requestAnimationFrame(loop); }; this.animationId = requestAnimationFrame(loop); }); // 如果设置了停止时间,则在指定时间后停止 if (this.ncStopTime > 0) { this.stopTimer = setTimeout(() => { this.stopAnimation(); this.ncEnabled = false; this.ncEnabledChange.emit(false); }, this.ncStopTime); } } stopAnimation() { if (this.animationId !== null) { cancelAnimationFrame(this.animationId); this.animationId = null; } if (this.resizeObserver) { this.resizeObserver.disconnect(); } if (this.stopTimer) { clearTimeout(this.stopTimer); this.stopTimer = null; } // 隐藏 canvas 容器和 glow 层 if (this.canvasContainerEl) { this.renderer.setStyle(this.canvasContainerEl, 'display', 'none'); } if (this.layersEl) { this.renderer.setStyle(this.layersEl, 'display', 'none'); } } // ─── Canvas 绘制 ───────────────────────────────────────────────────────────── updateCanvasSize() { const container = this.el.nativeElement; const rect = container.getBoundingClientRect(); const borderOffset = 60; const width = rect.width + borderOffset * 2; const height = rect.height + borderOffset * 2; const dpr = Math.min(window.devicePixelRatio || 1, 2); this.canvasEl.width = width * dpr; this.canvasEl.height = height * dpr; this.canvasEl.style.width = `${width}px`; this.canvasEl.style.height = `${height}px`; } drawFrame(currentTime) { const canvas = this.canvasEl; const ctx = canvas.getContext('2d'); if (!ctx) return; const deltaTime = this.lastFrameTime === 0 ? 0 : (currentTime - this.lastFrameTime) / 1000; this.time += deltaTime * this.ncSpeed; this.lastFrameTime = currentTime; const dpr = Math.min(window.devicePixelRatio || 1, 2); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.scale(dpr, dpr); ctx.strokeStyle = this.ncColor; ctx.lineWidth = this.ncElectricWidth; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; const borderOffset = 60; const displacement = 60; const canvasW = canvas.width / dpr; const canvasH = canvas.height / dpr; const left = borderOffset; const top = borderOffset; const borderWidth = canvasW - 2 * borderOffset; const borderHeight = canvasH - 2 * borderOffset; const maxRadius = Math.min(borderWidth, borderHeight) / 2; const radius = Math.min(this.ncBorderRadius, maxRadius); const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius; const sampleCount = Math.floor(approximatePerimeter / 2); // 噪声参数 const octaves = 10; const lacunarity = 1.6; const gain = 0.7; const amplitude = this.ncChaos; const frequency = 10; const baseFlatness = 0; ctx.beginPath(); for (let i = 0; i <= sampleCount; i++) { const progress = i / sampleCount; const point = this.getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius); const xNoise = this.octavedNoise(progress * 8, octaves, lacunarity, gain, amplitude, frequency, this.time, 0, baseFlatness); const yNoise = this.octavedNoise(progress * 8, octaves, lacunarity, gain, amplitude, frequency, this.time, 1, baseFlatness); const displacedX = point.x + xNoise * displacement; const displacedY = point.y + yNoise * displacement; if (i === 0) { ctx.moveTo(displacedX, displacedY); } else { ctx.lineTo(displacedX, displacedY); } } ctx.closePath(); ctx.stroke(); } // ─── 几何与噪声工具方法 ─────────────────────────────────────────────────────── random(x) { return (Math.sin(x * 12.9898) * 43758.5453) % 1; } noise2D(x, y) { const i = Math.floor(x); const j = Math.floor(y); const fx = x - i; const fy = y - j; const a = this.random(i + j * 57); const b = this.random(i + 1 + j * 57); const c = this.random(i + (j + 1) * 57); const d = this.random(i + 1 + (j + 1) * 57); const ux = fx * fx * (3.0 - 2.0 * fx); const uy = fy * fy * (3.0 - 2.0 * fy); return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy; } octavedNoise(x, octaves, lacunarity, gain, baseAmplitude, baseFrequency, time, seed, baseFlatness) { let y = 0; let amplitude = baseAmplitude; let frequency = baseFrequency; for (let i = 0; i < octaves; i++) { let octaveAmplitude = amplitude; if (i === 0) octaveAmplitude *= baseFlatness; y += octaveAmplitude * this.noise2D(frequency * x + seed * 100, time * frequency * 0.3); frequency *= lacunarity; amplitude *= gain; } return y; } getCornerPoint(centerX, centerY, radius, startAngle, arcLength, progress) { const angle = startAngle + progress * arcLength; return { x: centerX + radius * Math.cos(angle), y: centerY + radius * Math.sin(angle) }; } getRoundedRectPoint(t, left, top, width, height, radius) { const straightWidth = width - 2 * radius; const straightHeight = height - 2 * radius; const cornerArc = (Math.PI * radius) / 2; const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc; const distance = t * totalPerimeter; let accumulated = 0; // Top edge if (distance <= accumulated + straightWidth) { const progress = (distance - accumulated) / straightWidth; return { x: left + radius + progress * straightWidth, y: top }; } accumulated += straightWidth; // Top-right corner if (distance <= accumulated + cornerArc) { const progress = (distance - accumulated) / cornerArc; return this.getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress); } accumulated += cornerArc; // Right edge if (distance <= accumulated + straightHeight) { const progress = (distance - accumulated) / straightHeight; return { x: left + width, y: top + radius + progress * straightHeight }; } accumulated += straightHeight; // Bottom-right corner if (distance <= accumulated + cornerArc) { const progress = (distance - accumulated) / cornerArc; return this.getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress); } accumulated += cornerArc; // Bottom edge if (distance <= accumulated + straightWidth) { const progress = (distance - accumulated) / straightWidth; return { x: left + width - radius - progress * straightWidth, y: top + height }; } accumulated += straightWidth; // Bottom-left corner if (distance <= accumulated + cornerArc) { const progress = (distance - accumulated) / cornerArc; return this.getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress); } accumulated += cornerArc; // Left edge if (distance <= accumulated + straightHeight) { const progress = (distance - accumulated) / straightHeight; return { x: left, y: top + height - radius - progress * straightHeight }; } accumulated += straightHeight; // Top-left corner const progress = (distance - accumulated) / cornerArc; return this.getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress); } // ─── 工具 ──────────────────────────────────────────────────────────────────── setStyles(el, styles) { Object.entries(styles).forEach(([prop, value]) => { this.renderer.setStyle(el, prop, value); }); } } ElectricBorderDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ElectricBorderDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); ElectricBorderDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.1.5", type: ElectricBorderDirective, selector: "[ncElectricBorder]", inputs: { ncBorderRadius: "ncBorderRadius", ncBorderWidth: "ncBorderWidth", ncElectricWidth: "ncElectricWidth", ncColor: "ncColor", ncSpeed: "ncSpeed", ncChaos: "ncChaos", ncStopTime: "ncStopTime", ncEnabled: "ncEnabled" }, outputs: { ncEnabledChange: "ncEnabledChange" }, usesOnChanges: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ElectricBorderDirective, decorators: [{ type: Directive, args: [{ selector: '[ncElectricBorder]' }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { ncBorderRadius: [{ type: Input }], ncBorderWidth: [{ type: Input }], ncElectricWidth: [{ type: Input }], ncColor: [{ type: Input }], ncSpeed: [{ type: Input }], ncChaos: [{ type: Input }], ncStopTime: [{ type: Input }], ncEnabled: [{ type: Input }], ncEnabledChange: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlY3RyaWMtYm9yZGVyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvZWxlY3RyaWMtYm9yZGVyL2VsZWN0cmljLWJvcmRlci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFBeUIsS0FBSyxFQUFFLE1BQU0sRUFDL0MsWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDOztBQUt2QixNQUFNLE9BQU8sdUJBQXVCO0lBNENsQyxZQUFvQixFQUFjLEVBQVUsUUFBbUIsRUFBVSxNQUFjO1FBQW5FLE9BQUUsR0FBRixFQUFFLENBQVk7UUFBVSxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQTNDdkYsa0JBQWtCO1FBQ1QsbUJBQWMsR0FBVyxFQUFFLENBQUM7UUFDckMsZ0JBQWdCO1FBQ1Asa0JBQWEsR0FBVyxDQUFDLENBQUM7UUFDbkMsZ0JBQWdCO1FBQ1Asb0JBQWUsR0FBVyxDQUFDLENBQUM7UUFDckMsU0FBUztRQUNBLFlBQU8sR0FBVyxTQUFTLENBQUM7UUFDckMsYUFBYTtRQUNKLFlBQU8sR0FBVyxDQUFDLENBQUM7UUFDN0IsZUFBZTtRQUNOLFlBQU8sR0FBVyxJQUFJLENBQUM7UUFDaEMsdUJBQXVCO1FBQ2QsZUFBVSxHQUFXLENBQUMsQ0FBQztRQUNoQyxhQUFhO1FBQ0wsYUFBUSxHQUFZLElBQUksQ0FBQztRQVFqQyxlQUFlO1FBQ0wsb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBVyxDQUFDO1FBV3hELE9BQU87UUFDQyxnQkFBVyxHQUFrQixJQUFJLENBQUM7UUFFbEMsU0FBSSxHQUFXLENBQUMsQ0FBQztRQUNqQixrQkFBYSxHQUFXLENBQUMsQ0FBQztRQUMxQixrQkFBYSxHQUFHLEtBQUssQ0FBQztJQUc2RCxDQUFDO0lBM0I1RixJQUNJLFNBQVMsQ0FBQyxHQUFxQjtRQUNq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S0FBSztnQkFJRixTQUFTO3NCQURaLEtBQUs7Z0JBUUksZUFBZTtzQkFBeEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBSZW5kZXJlcjIsIElucHV0LCBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLCBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzLCBOZ1pvbmVcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW25jRWxlY3RyaWNCb3JkZXJdJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRWxlY3RyaWNCb3JkZXJEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcclxuICAvKiog6L655qGG5ZyG6KeS5Y2K5b6EIOWNleS9jXB4ICovXHJcbiAgQElucHV0KCkgbmNCb3JkZXJSYWRpdXM6IG51bWJlciA9IDI0O1xyXG4gIC8qKiDovrnmoYbnur/lrr0g5Y2V5L2NcHggKi9cclxuICBASW5wdXQoKSBuY0JvcmRlcldpZHRoOiBudW1iZXIgPSAyO1xyXG4gIC8qKiDnlLXlvKflrr3luqYg5Y2V5L2NcHggKi9cclxuICBASW5wdXQoKSBuY0VsZWN0cmljV2lkdGg6IG51bWJlciA9IDE7XHJcbiAgLyoqIOminOiJsiAqL1xyXG4gIEBJbnB1dCgpIG5jQ29sb3I6IHN0cmluZyA9ICcjNTIyN0ZGJztcclxuICAvKiog5Yqo55S76YCf5bqm5YCN546HICovXHJcbiAgQElucHV0KCkgbmNTcGVlZDogbnVtYmVyID0gMTtcclxuICAvKiog5omw5Yqo5by65bqm77yI5oyv5bmF77yJICovXHJcbiAgQElucHV0KCkgbmNDaGFvczogbnVtYmVyID0gMC4xMjtcclxuICAvKiog5YGc5q2i5Yqo55S75pe26Ze077yMbXPvvIww6KGo56S65LiN5YGc5q2iICovXHJcbiAgQElucHV0KCkgbmNTdG9wVGltZTogbnVtYmVyID0gMDtcclxuICAvKiog5piv5ZCm5ZCv55So5Yqo55S7ICovXHJcbiAgcHJpdmF0ZSBfZW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNFbmFibGVkKHZhbDogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5fZW5hYmxlZCA9IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IGZhbHNlICYmIHZhbCAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jRW5hYmxlZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9lbmFibGVkO1xyXG4gIH1cclxuICAvKiog5Y+M5ZCR57uR5a6a6L6T5Ye65LqL5Lu2ICovXHJcbiAgQE91dHB1dCgpIG5jRW5hYmxlZENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcclxuXHJcbiAgLy8gRE9NIOWFg+e0oFxyXG4gIHByaXZhdGUgY2FudmFzRWwhOiBIVE1MQ2FudmFzRWxlbWVudDtcclxuICBwcml2YXRlIGNhbnZhc0NvbnRhaW5lckVsITogSFRNTEVsZW1lbnQ7XHJcbiAgcHJpdmF0ZSBnbG93MUVsITogSFRNTEVsZW1lbnQ7XHJcbiAgcHJpdmF0ZSBnbG93MkVsITogSFRNTEVsZW1lbnQ7XHJcbiAgcHJpdmF0ZSBiZ0dsb3dFbCE6IEhUTUxFbGVtZW50O1xyXG4gIHByaXZhdGUgbGF5ZXJzRWwhOiBIVE1MRWxlbWVudDtcclxuICBwcml2YXRlIHN0eWxlRWwhOiBIVE1MRWxlbWVudDtcclxuXHJcbiAgLy8g5Yqo55S754q25oCBXHJcbiAgcHJpdmF0ZSBhbmltYXRpb25JZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSByZXNpemVPYnNlcnZlciE6IFJlc2l6ZU9ic2VydmVyO1xyXG4gIHByaXZhdGUgdGltZTogbnVtYmVyID0gMDtcclxuICBwcml2YXRlIGxhc3RGcmFtZVRpbWU6IG51bWJlciA9IDA7XHJcbiAgcHJpdmF0ZSBpc0luaXRpYWxpemVkID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBzdG9wVGltZXI6IGFueTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlbDogRWxlbWVudFJlZiwgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLCBwcml2YXRlIG5nWm9uZTogTmdab25lKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLnNldHVwSG9zdCgpO1xyXG4gICAgdGhpcy5jcmVhdGVEb20oKTtcclxuICAgIHRoaXMuaW5qZWN0U3R5bGVzKCk7XHJcbiAgICB0aGlzLmlzSW5pdGlhbGl6ZWQgPSB0cnVlO1xyXG4gICAgaWYgKHRoaXMubmNFbmFibGVkKSB7XHJcbiAgICAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcclxuICAgIGlmICghdGhpcy5pc0luaXRpYWxpemVkKSByZXR1cm47XHJcblxyXG4gICAgLy8gbmNDb2xvciAvIG5jU3BlZWQgLyBuY0NoYW9zIC8gbmNFbGVjdHJpY1dpZHRoIC8gbmNCb3JkZXJSYWRpdXMg5ZyoIGRyYXdGcmFtZSgpIOS4reavj+W4p+ebtOaOpeivu+WPlu+8jOWPmOabtOiHquWKqOeUn+aViO+8jOaXoOmcgOWkhOeQhuOAglxyXG5cclxuICAgIC8vIG5jQ29sb3Ig6ZmkIGNhbnZhcyBzdHJva2VTdHlsZSDlpJbov5jpqbHliqjkuInkuKogZ2xvdyBET00g5YWD57Sg77yM6ZyA5pi+5byP5pu05paw44CCXHJcbiAgICBpZiAoY2hhbmdlc1snbmNDb2xvciddKSB7XHJcbiAgICAgIHRoaXMuYXBwbHlDb2xvclZhcigpO1xyXG4gICAgfVxyXG4gICAgLy8gbmNCb3JkZXJSYWRpdXMg6ZmkIGNhbnZhc+i3r+W+hOWchuinkiDlpJbov5jlvbHlk43lrr/kuLvlhYPntKAgQ1NTIGJvcmRlci1yYWRpdXPvvIhnbG93IOWxgueUqCBpbmhlcml0IOS8mui3n+maj++8ie+8jOmcgOaYvuW8j+abtOaWsOOAglxyXG4gICAgaWYgKGNoYW5nZXNbJ25jQm9yZGVyUmFkaXVzJ10pIHtcclxuICAgICAgdGhpcy5hcHBseUJvcmRlclJhZGl1cygpO1xyXG4gICAgfVxyXG4gICAgLy8gbmNCb3JkZXJXaWR0aCDlvbHlk40gZ2xvdyDlsYIgYm9yZGVyIOWuveW6pu+8iOmcgOaYvuW8j+abtOaWsO+8iVxyXG4gICAgaWYgKGNoYW5nZXNbJ25jQm9yZGVyV2lkdGgnXSkge1xyXG4gICAgICB0aGlzLmFwcGx5Qm9yZGVyV2lkdGgoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBuY0VuYWJsZWQg5Y+Y5YyW5pe25ZCv5YGc5Yqo55S7XHJcbiAgICBpZiAoY2hhbmdlc1snbmNFbmFibGVkJ10pIHtcclxuICAgICAgaWYgKHRoaXMubmNFbmFibGVkKSB7XHJcbiAgICAgICAgdGhpcy5zdGFydEFuaW1hdGlvbigpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuc3RvcEFuaW1hdGlvbigpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIHRoaXMuc3RvcEFuaW1hdGlvbigpO1xyXG4gICAgaWYgKHRoaXMucmVzaXplT2JzZXJ2ZXIpIHtcclxuICAgICAgdGhpcy5yZXNpemVPYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zdG9wVGltZXIpIHtcclxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuc3RvcFRpbWVyKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCDliJ3lp4vljJYg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgc2V0dXBIb3N0KCkge1xyXG4gICAgY29uc3QgaG9zdDogSFRNTEVsZW1lbnQgPSB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCBwb3MgPSBnZXRDb21wdXRlZFN0eWxlKGhvc3QpLnBvc2l0aW9uO1xyXG4gICAgaWYgKCFwb3MgfHwgcG9zID09PSAnc3RhdGljJykge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKGhvc3QsICdwb3NpdGlvbicsICdyZWxhdGl2ZScpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShob3N0LCAnaXNvbGF0aW9uJywgJ2lzb2xhdGUnKTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoaG9zdCwgJ292ZXJmbG93JywgJ3Zpc2libGUnKTtcclxuICAgIHRoaXMuYXBwbHlDb2xvclZhcigpO1xyXG4gICAgdGhpcy5hcHBseUJvcmRlclJhZGl1cygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBseUJvcmRlclJhZGl1cygpIHtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbC5uYXRpdmVFbGVtZW50LCAnYm9yZGVyLXJhZGl1cycsIGAke3RoaXMubmNCb3JkZXJSYWRpdXN9cHhgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlCb3JkZXJXaWR0aCgpIHtcclxuICAgIGlmICh0aGlzLmdsb3cxRWwpIHtcclxuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmdsb3cxRWwsICdib3JkZXItd2lkdGgnLCBgJHt0aGlzLm5jQm9yZGVyV2lkdGh9cHhgKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmdsb3cyRWwpIHtcclxuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmdsb3cyRWwsICdib3JkZXItd2lkdGgnLCBgJHt0aGlzLm5jQm9yZGVyV2lkdGh9cHhgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlDb2xvclZhcigpIHtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbC5uYXRpdmVFbGVtZW50LCAnLS1lbGVjdHJpYy1ib3JkZXItY29sb3InLCB0aGlzLm5jQ29sb3IpO1xyXG4gICAgLy8g5ZCM5q2l5pu05paw5bey5a2Y5Zyo55qEIGdsb3cg5bGC6aKc6Imy77yIbmdPbkNoYW5nZXMg5pe25Lmf6IO955Sf5pWI77yJXHJcbiAgICBpZiAodGhpcy5nbG93MUVsKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5nbG93MUVsLCAnYm9yZGVyLWNvbG9yJywgYG9rbGNoKGZyb20gJHt0aGlzLm5jQ29sb3J9IGwgYyBoIC8gMC42KWApO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuZ2xvdzJFbCkge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZ2xvdzJFbCwgJ2JvcmRlci1jb2xvcicsIHRoaXMubmNDb2xvcik7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5iZ0dsb3dFbCkge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxyXG4gICAgICAgIHRoaXMuYmdHbG93RWwsICdiYWNrZ3JvdW5kJyxcclxuICAgICAgICBgbGluZWFyLWdyYWRpZW50KC0zMGRlZywgJHt0aGlzLm5jQ29sb3J9LCB0cmFuc3BhcmVudCwgJHt0aGlzLm5jQ29sb3J9KWBcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRG9tKCkge1xyXG4gICAgY29uc3QgaG9zdDogSFRNTEVsZW1lbnQgPSB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQ7XHJcblxyXG4gICAgLy8g4pSA4pSAIGNhbnZhcyDlrrnlmagg4pSA4pSAXHJcbiAgICB0aGlzLmNhbnZhc0NvbnRhaW5lckVsID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5jYW52YXNDb250YWluZXJFbCwgJ25jLWViLWNhbnZhcy1jb250YWluZXInKTtcclxuICAgIHRoaXMuc2V0U3R5bGVzKHRoaXMuY2FudmFzQ29udGFpbmVyRWwsIHtcclxuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXHJcbiAgICAgIHRvcDogJzUwJScsXHJcbiAgICAgIGxlZnQ6ICc1MCUnLFxyXG4gICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoLTUwJSwgLTUwJSknLFxyXG4gICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZScsXHJcbiAgICAgICd6LWluZGV4JzogJzInXHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyDilIDilIAgY2FudmFzIOKUgOKUgFxyXG4gICAgdGhpcy5jYW52YXNFbCA9IHRoaXMucmVuZGVyZXIuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XHJcbiAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuY2FudmFzRWwsICduYy1lYi1jYW52YXMnKTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jYW52YXNFbCwgJ2Rpc3BsYXknLCAnYmxvY2snKTtcclxuICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXNDb250YWluZXJFbCwgdGhpcy5jYW52YXNFbCk7XHJcbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKGhvc3QsIHRoaXMuY2FudmFzQ29udGFpbmVyRWwpO1xyXG5cclxuICAgIC8vIOKUgOKUgCBnbG93IOWxguWuueWZqCDilIDilIBcclxuICAgIHRoaXMubGF5ZXJzRWwgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmxheWVyc0VsLCAnbmMtZWItbGF5ZXJzJyk7XHJcbiAgICB0aGlzLnNldFN0eWxlcyh0aGlzLmxheWVyc0VsLCB7XHJcbiAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxyXG4gICAgICBpbnNldDogJzAnLFxyXG4gICAgICAnYm9yZGVyLXJhZGl1cyc6ICdpbmhlcml0JyxcclxuICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnLFxyXG4gICAgICAnei1pbmRleCc6ICcwJ1xyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgZ2xvd0Jhc2U6IHsgW2s6IHN0cmluZ106IHN0cmluZyB9ID0ge1xyXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcclxuICAgICAgaW5zZXQ6ICcwJyxcclxuICAgICAgJ2JvcmRlci1yYWRpdXMnOiAnaW5oZXJpdCcsXHJcbiAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJyxcclxuICAgICAgJ2JveC1zaXppbmcnOiAnYm9yZGVyLWJveCdcclxuICAgIH07XHJcblxyXG4gICAgLy8gbmMtZWItZ2xvdy0xXHJcbiAgICB0aGlzLmdsb3cxRWwgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmdsb3cxRWwsICduYy1lYi1nbG93LTEnKTtcclxuICAgIHRoaXMuc2V0U3R5bGVzKHRoaXMuZ2xvdzFFbCwge1xyXG4gICAgICAuLi5nbG93QmFzZSxcclxuICAgICAgYm9yZGVyOiBgJHt0aGlzLm5jQm9yZGVyV2lkdGh9cHggc29saWQgJHt0aGlzLm5jQ29sb3J9YCxcclxuICAgICAgZmlsdGVyOiAnYmx1cigxcHgpJ1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gbmMtZWItZ2xvdy0yXHJcbiAgICB0aGlzLmdsb3cyRWwgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmdsb3cyRWwsICduYy1lYi1nbG93LTInKTtcclxuICAgIHRoaXMuc2V0U3R5bGVzKHRoaXMuZ2xvdzJFbCwge1xyXG4gICAgICAuLi5nbG93QmFzZSxcclxuICAgICAgYm9yZGVyOiBgJHt0aGlzLm5jQm9yZGVyV2lkdGh9cHggc29saWQgJHt0aGlzLm5jQ29sb3J9YCxcclxuICAgICAgZmlsdGVyOiAnYmx1cig0cHgpJ1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gbmMtZWItYmFja2dyb3VuZC1nbG93XHJcbiAgICB0aGlzLmJnR2xvd0VsID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICAgIHRoaXMucmV