ng-cw-v12
Version:
Angular UI Component Library
419 lines • 66.4 kB
JavaScript
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