@kepler.gl/utils 3.1.0-alpha.1 → 3.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregation.d.ts +13 -0
- package/dist/aggregation.js +84 -0
- package/dist/application-config.d.ts +25 -0
- package/dist/application-config.js +52 -0
- package/dist/arrow-data-container.d.ts +62 -0
- package/dist/arrow-data-container.js +331 -0
- package/dist/color-utils.d.ts +108 -0
- package/dist/color-utils.js +443 -0
- package/dist/data-container-interface.d.ts +138 -0
- package/dist/data-container-interface.js +6 -0
- package/dist/data-container-utils.d.ts +30 -0
- package/dist/data-container-utils.js +74 -0
- package/dist/data-row.d.ts +59 -0
- package/dist/data-row.js +110 -0
- package/dist/data-scale-utils.d.ts +119 -0
- package/dist/data-scale-utils.js +340 -0
- package/dist/data-utils.d.ts +98 -0
- package/dist/data-utils.js +436 -0
- package/dist/dataset-utils.d.ts +45 -0
- package/dist/dataset-utils.js +313 -0
- package/dist/dom-to-image.d.ts +73 -0
- package/dist/dom-to-image.js +421 -0
- package/dist/dom-utils.d.ts +23 -0
- package/dist/dom-utils.js +349 -0
- package/dist/effect-utils.d.ts +24 -0
- package/dist/effect-utils.js +166 -0
- package/dist/export-map-html.d.ts +9 -0
- package/dist/export-map-html.js +25 -0
- package/dist/export-utils.d.ts +40 -0
- package/dist/export-utils.js +201 -0
- package/dist/filter-utils.d.ts +331 -0
- package/dist/filter-utils.js +1214 -0
- package/dist/format.d.ts +3 -0
- package/dist/format.js +38 -0
- package/dist/gl-utils.d.ts +1 -0
- package/dist/gl-utils.js +27 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +941 -0
- package/dist/indexed-data-container.d.ts +34 -0
- package/dist/indexed-data-container.js +214 -0
- package/dist/locale-utils.d.ts +2 -0
- package/dist/locale-utils.js +39 -0
- package/dist/map-info-utils.d.ts +1 -0
- package/dist/map-info-utils.js +14 -0
- package/dist/map-style-utils/mapbox-gl-style-editor.d.ts +57 -0
- package/dist/map-style-utils/mapbox-gl-style-editor.js +188 -0
- package/dist/map-style-utils/mapbox-utils.d.ts +14 -0
- package/dist/map-style-utils/mapbox-utils.js +51 -0
- package/dist/map-utils.d.ts +9 -0
- package/dist/map-utils.js +48 -0
- package/dist/mapbox-utils.d.ts +7 -0
- package/dist/mapbox-utils.js +19 -0
- package/dist/noop.d.ts +1 -0
- package/dist/noop.js +13 -0
- package/dist/notifications-utils.d.ts +42 -0
- package/dist/notifications-utils.js +69 -0
- package/dist/observe-dimensions.d.ts +15 -0
- package/dist/observe-dimensions.js +130 -0
- package/dist/plot.d.ts +131 -0
- package/dist/plot.js +615 -0
- package/dist/position-utils.d.ts +6 -0
- package/dist/position-utils.js +26 -0
- package/dist/projection-utils.d.ts +22 -0
- package/dist/projection-utils.js +83 -0
- package/dist/quick-insertion-sort.d.ts +12 -0
- package/dist/quick-insertion-sort.js +132 -0
- package/dist/row-data-container.d.ts +31 -0
- package/dist/row-data-container.js +206 -0
- package/dist/searcher-utils.d.ts +1 -0
- package/dist/searcher-utils.js +25 -0
- package/dist/split-map-utils.d.ts +32 -0
- package/dist/split-map-utils.js +99 -0
- package/dist/strings.d.ts +4 -0
- package/dist/strings.js +16 -0
- package/dist/time.d.ts +54 -0
- package/dist/time.js +325 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +6 -0
- package/dist/utils.d.ts +104 -0
- package/dist/utils.js +241 -0
- package/package.json +14 -6
@@ -0,0 +1,108 @@
|
|
1
|
+
import { CategoricalPalette, ColorPalette } from '@kepler.gl/constants';
|
2
|
+
import { ColorMap, ColorRange, ColorRangeConfig, HexColor, RGBColor } from '@kepler.gl/types';
|
3
|
+
/**
|
4
|
+
* get r g b from hex code
|
5
|
+
*
|
6
|
+
* @param hex
|
7
|
+
* @returns array of r g bs
|
8
|
+
*/
|
9
|
+
export declare function hexToRgb(hex: string): RGBColor;
|
10
|
+
export declare function isHexColor(hex: string): RegExpExecArray | null;
|
11
|
+
/**
|
12
|
+
* get hex from r g b
|
13
|
+
*
|
14
|
+
* @param rgb
|
15
|
+
* @returns hex string
|
16
|
+
*/
|
17
|
+
export declare function rgbToHex([r, g, b]: RGBColor): HexColor;
|
18
|
+
/**
|
19
|
+
* Whether color range has custom color map
|
20
|
+
*/
|
21
|
+
export declare function hasColorMap(colorRange: ColorRange): boolean;
|
22
|
+
/**
|
23
|
+
* given a list of rgb arrays it will generate a linear gradient css rule
|
24
|
+
* @param direction
|
25
|
+
* @param colors
|
26
|
+
* @return
|
27
|
+
*/
|
28
|
+
export declare function createLinearGradient(direction: string, colors: RGBColor[]): string;
|
29
|
+
/**
|
30
|
+
* Convert color to RGB
|
31
|
+
*/
|
32
|
+
export declare function colorMaybeToRGB(color: unknown): RGBColor | null;
|
33
|
+
/**
|
34
|
+
* Whether color is rgb
|
35
|
+
* @returns
|
36
|
+
*/
|
37
|
+
export declare function isRgbColor(color: unknown): boolean;
|
38
|
+
/**
|
39
|
+
* Take color values in 0-255 range and map to [0, 1]
|
40
|
+
*/
|
41
|
+
export declare function normalizeColor(color: number[]): number[];
|
42
|
+
/**
|
43
|
+
* Convert color to Hex
|
44
|
+
*/
|
45
|
+
export declare function colorMaybeToHex(color: unknown): HexColor;
|
46
|
+
/**
|
47
|
+
* Convert color to Hex
|
48
|
+
*/
|
49
|
+
export declare function interpolateHex(hex1: HexColor, hex2: HexColor): HexColor;
|
50
|
+
export declare function addNewQuantativeColorBreakAtIndex(colorMap: any, index: any, newColors: any): any;
|
51
|
+
/**
|
52
|
+
* Add a new color to custom palette
|
53
|
+
*/
|
54
|
+
export declare function addCustomPaletteColor(customPalette: ColorRange, index: number): ColorRange;
|
55
|
+
/**
|
56
|
+
* Sort custom palette
|
57
|
+
*/
|
58
|
+
export declare function sortCustomPaletteColor(customPalette: ColorRange, oldIndex: number, newIndex: number): ColorRange;
|
59
|
+
/**
|
60
|
+
* remove a color in custom palette at index
|
61
|
+
*/
|
62
|
+
export declare function removeCustomPaletteColor(customPalette: ColorRange, index: number): ColorRange;
|
63
|
+
/**
|
64
|
+
* Update a color in custom palette at index
|
65
|
+
*/
|
66
|
+
export declare function updateCustomPaletteColor(customPalette: ColorRange, index: number, newValue: HexColor): ColorRange;
|
67
|
+
/**
|
68
|
+
* Get a reversed colorRange
|
69
|
+
*/
|
70
|
+
export declare function reverseColorRange(reversed: boolean, colorRange: ColorRange): ColorRange;
|
71
|
+
/**
|
72
|
+
* Whether palette matches current ColorBlindSafe config
|
73
|
+
*/
|
74
|
+
export declare function paletteIsColorBlindSafe(palette: ColorPalette, colorBlindSafe: boolean): boolean;
|
75
|
+
/**
|
76
|
+
* Whether palette matches current steps config
|
77
|
+
*/
|
78
|
+
export declare function isQuaPalette(palette: ColorPalette): palette is CategoricalPalette;
|
79
|
+
/**
|
80
|
+
* Whether palette matches current steps config
|
81
|
+
*/
|
82
|
+
export declare function paletteIsSteps(palette: ColorPalette, steps: number): boolean;
|
83
|
+
/**
|
84
|
+
* Whether palette matches current type config
|
85
|
+
*/
|
86
|
+
export declare function paletteIsType(palette: ColorPalette, type: string): boolean;
|
87
|
+
/**
|
88
|
+
* Find best match palette based on config, update color range by it
|
89
|
+
*/
|
90
|
+
export declare function updateColorRangeByMatchingPalette(currentColorRange: ColorRange, config: ColorRangeConfig): ColorRange;
|
91
|
+
/**
|
92
|
+
* Update custom palette when reverse the colors in custom palette, since changing 'steps',
|
93
|
+
* 'colorBindSafe', 'type' should fall back to predefined palette.
|
94
|
+
*/
|
95
|
+
export declare function updateCustomColorRangeByColorUI(oldColorRange: ColorRange, colorConfig: ColorRangeConfig): ColorRange;
|
96
|
+
/**
|
97
|
+
* Update color range after selecting a palette from color range selectoer
|
98
|
+
* Copy over colorMap and colorLegends
|
99
|
+
*/
|
100
|
+
export declare function updateColorRangeBySelectedPalette(oldColorRange: any, colorPalette: any, colorConfig: any): any;
|
101
|
+
/**
|
102
|
+
* convert saved colorRange to colorPalette objevt type/name/category/isColorBlind
|
103
|
+
*/
|
104
|
+
export declare function colorRangeBackwardCompatibility(colorRange: ColorRange): ColorRange;
|
105
|
+
/**
|
106
|
+
* Initialize custom palette from current standard color range object
|
107
|
+
*/
|
108
|
+
export declare function initializeCustomPalette(colorRange: ColorRange, colorMap?: ColorMap): ColorRange;
|
@@ -0,0 +1,443 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
5
|
+
value: true
|
6
|
+
});
|
7
|
+
exports.addCustomPaletteColor = addCustomPaletteColor;
|
8
|
+
exports.addNewQuantativeColorBreakAtIndex = addNewQuantativeColorBreakAtIndex;
|
9
|
+
exports.colorMaybeToHex = colorMaybeToHex;
|
10
|
+
exports.colorMaybeToRGB = colorMaybeToRGB;
|
11
|
+
exports.colorRangeBackwardCompatibility = colorRangeBackwardCompatibility;
|
12
|
+
exports.createLinearGradient = createLinearGradient;
|
13
|
+
exports.hasColorMap = hasColorMap;
|
14
|
+
exports.hexToRgb = hexToRgb;
|
15
|
+
exports.initializeCustomPalette = initializeCustomPalette;
|
16
|
+
exports.interpolateHex = interpolateHex;
|
17
|
+
exports.isHexColor = isHexColor;
|
18
|
+
exports.isQuaPalette = isQuaPalette;
|
19
|
+
exports.isRgbColor = isRgbColor;
|
20
|
+
exports.normalizeColor = normalizeColor;
|
21
|
+
exports.paletteIsColorBlindSafe = paletteIsColorBlindSafe;
|
22
|
+
exports.paletteIsSteps = paletteIsSteps;
|
23
|
+
exports.paletteIsType = paletteIsType;
|
24
|
+
exports.removeCustomPaletteColor = removeCustomPaletteColor;
|
25
|
+
exports.reverseColorRange = reverseColorRange;
|
26
|
+
exports.rgbToHex = rgbToHex;
|
27
|
+
exports.sortCustomPaletteColor = sortCustomPaletteColor;
|
28
|
+
exports.updateColorRangeByMatchingPalette = updateColorRangeByMatchingPalette;
|
29
|
+
exports.updateColorRangeBySelectedPalette = updateColorRangeBySelectedPalette;
|
30
|
+
exports.updateCustomColorRangeByColorUI = updateCustomColorRangeByColorUI;
|
31
|
+
exports.updateCustomPaletteColor = updateCustomPaletteColor;
|
32
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
33
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
34
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
35
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
36
|
+
var _constants = require("@kepler.gl/constants");
|
37
|
+
var _d3Color = require("d3-color");
|
38
|
+
var _d3Interpolate = require("d3-interpolate");
|
39
|
+
var _utils = require("./utils");
|
40
|
+
var _console = _interopRequireDefault(require("global/console"));
|
41
|
+
var _excluded = ["colors"];
|
42
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
43
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT
|
44
|
+
// Copyright contributors to the kepler.gl project
|
45
|
+
/**
|
46
|
+
* get r g b from hex code
|
47
|
+
*
|
48
|
+
* @param hex
|
49
|
+
* @returns array of r g bs
|
50
|
+
*/
|
51
|
+
function hexToRgb(hex) {
|
52
|
+
var result = isHexColor(hex);
|
53
|
+
if (!result) {
|
54
|
+
return [0, 0, 0];
|
55
|
+
}
|
56
|
+
var r = parseInt(result[1], 16);
|
57
|
+
var g = parseInt(result[2], 16);
|
58
|
+
var b = parseInt(result[3], 16);
|
59
|
+
return [r, g, b];
|
60
|
+
}
|
61
|
+
function isHexColor(hex) {
|
62
|
+
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
63
|
+
return result;
|
64
|
+
}
|
65
|
+
function PadNum(c) {
|
66
|
+
var hex = c.toString(16);
|
67
|
+
return hex.length === 1 ? "0".concat(hex) : hex;
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* get hex from r g b
|
72
|
+
*
|
73
|
+
* @param rgb
|
74
|
+
* @returns hex string
|
75
|
+
*/
|
76
|
+
function rgbToHex(_ref) {
|
77
|
+
var _ref2 = (0, _slicedToArray2["default"])(_ref, 3),
|
78
|
+
r = _ref2[0],
|
79
|
+
g = _ref2[1],
|
80
|
+
b = _ref2[2];
|
81
|
+
return "#".concat([r, g, b].map(function (n) {
|
82
|
+
return PadNum(n);
|
83
|
+
}).join('')).toUpperCase();
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Whether color range has custom color map
|
88
|
+
*/
|
89
|
+
function hasColorMap(colorRange) {
|
90
|
+
return Array.isArray(colorRange.colorMap) && Boolean(colorRange.colorMap.length);
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* given a list of rgb arrays it will generate a linear gradient css rule
|
95
|
+
* @param direction
|
96
|
+
* @param colors
|
97
|
+
* @return
|
98
|
+
*/
|
99
|
+
function createLinearGradient(direction, colors) {
|
100
|
+
var step = parseFloat((100.0 / colors.length).toFixed(2));
|
101
|
+
var bands = colors.map(function (rgb, index) {
|
102
|
+
return "rgba(".concat(rgb.join(','), ", 1) ").concat(step * index, "%, rgba(").concat(rgb.join(','), ", 1) ").concat(step * (index + 1), "%");
|
103
|
+
});
|
104
|
+
return "linear-gradient(to ".concat(direction, ", ").concat(bands.join(','), ")");
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
* Convert color to RGB
|
109
|
+
*/
|
110
|
+
function colorMaybeToRGB(color) {
|
111
|
+
if (isRgbColor(color)) {
|
112
|
+
return color;
|
113
|
+
}
|
114
|
+
if (typeof color === 'string') {
|
115
|
+
var rgbObj = (0, _d3Color.rgb)(color);
|
116
|
+
if (Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.r) && Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.g) && Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.b)) {
|
117
|
+
return [rgbObj.r, rgbObj.g, rgbObj.b];
|
118
|
+
}
|
119
|
+
}
|
120
|
+
return null;
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Whether color is rgb
|
125
|
+
* @returns
|
126
|
+
*/
|
127
|
+
function isRgbColor(color) {
|
128
|
+
return Boolean(color && Array.isArray(color) && color.length === 3 && color.every(function (n) {
|
129
|
+
return Number.isFinite(n) && n <= 255 && n >= 0;
|
130
|
+
}));
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Take color values in 0-255 range and map to [0, 1]
|
135
|
+
*/
|
136
|
+
function normalizeColor(color) {
|
137
|
+
return color.map(function (component) {
|
138
|
+
return component / 255.0;
|
139
|
+
});
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Convert color to Hex
|
144
|
+
*/
|
145
|
+
function colorMaybeToHex(color) {
|
146
|
+
var rgbColor = colorMaybeToRGB(color);
|
147
|
+
if (rgbColor) return rgbToHex(rgbColor);
|
148
|
+
return '#000000';
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Convert color to Hex
|
153
|
+
*/
|
154
|
+
|
155
|
+
function interpolateHex(hex1, hex2) {
|
156
|
+
return (0, _d3Color.rgb)((0, _d3Interpolate.interpolate)(hex1, hex2)(0.5)).hex().toUpperCase();
|
157
|
+
}
|
158
|
+
function addNewQuantativeColorBreakAtIndex(colorMap, index, newColors) {
|
159
|
+
if (!Array.isArray(colorMap) || !colorMap.length) {
|
160
|
+
return colorMap;
|
161
|
+
}
|
162
|
+
if (colorMap.length < 2) {
|
163
|
+
// less then 2, add 1 at end
|
164
|
+
// however shouldn't allow delete when there are 2
|
165
|
+
return newColors.map(function (c, i) {
|
166
|
+
return i === 0 ? colorMap[i] : [null, c];
|
167
|
+
});
|
168
|
+
}
|
169
|
+
|
170
|
+
// breaks should be 1 less than colors
|
171
|
+
var breaks = colorMap.map(function (cm) {
|
172
|
+
return cm[0];
|
173
|
+
}).slice(0, colorMap.length - 1);
|
174
|
+
|
175
|
+
// insert new break
|
176
|
+
var newValue = index >= breaks.length - 1 ? breaks[breaks.length - 1] + (breaks.length > 1 ? breaks[breaks.length - 1] - breaks[breaks.length - 2] : 0) : (breaks[index] + breaks[index + 1]) / 2;
|
177
|
+
var newBreaks = (0, _utils.arrayInsert)(breaks, index + 1, newValue);
|
178
|
+
|
179
|
+
// asign breaks to color
|
180
|
+
return newColors.map(function (c, i) {
|
181
|
+
return i === newColors.length - 1 ? [null, c] : [newBreaks[i] === undefined ? null : newBreaks[i], c];
|
182
|
+
});
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Add a new color to custom palette
|
187
|
+
*/
|
188
|
+
function addCustomPaletteColor(customPalette, index) {
|
189
|
+
var colors = customPalette.colors,
|
190
|
+
colorMap = customPalette.colorMap;
|
191
|
+
var update = {};
|
192
|
+
var newColor = index === colors.length - 1 ? colors[index] : interpolateHex(colors[index], colors[index + 1]);
|
193
|
+
update.colors = (0, _utils.arrayInsert)(colors, index + 1, newColor);
|
194
|
+
|
195
|
+
// add color to colorMap
|
196
|
+
if (colorMap) {
|
197
|
+
update.colorMap = addNewQuantativeColorBreakAtIndex(colorMap, index, update.colors);
|
198
|
+
}
|
199
|
+
return _objectSpread(_objectSpread({}, customPalette), update);
|
200
|
+
}
|
201
|
+
function replaceColorsInColorRange(colorRange, newColors) {
|
202
|
+
var oldColors = colorRange.colors;
|
203
|
+
var updated = _objectSpread(_objectSpread({}, colorRange), {}, {
|
204
|
+
colors: newColors
|
205
|
+
});
|
206
|
+
|
207
|
+
// update color map
|
208
|
+
// keep value, replace color
|
209
|
+
if (Array.isArray(updated.colorMap)) {
|
210
|
+
updated.colorMap = updated.colorMap.map(function (cm, i) {
|
211
|
+
return [cm[0], newColors[i]];
|
212
|
+
});
|
213
|
+
}
|
214
|
+
// update colorlegends
|
215
|
+
// keep value, replace color
|
216
|
+
if (updated.colorLegends) {
|
217
|
+
updated.colorLegends = Object.keys(updated.colorLegends).reduce(function (accu, key) {
|
218
|
+
var colorIdx = oldColors.findIndex(function (c) {
|
219
|
+
return c === key;
|
220
|
+
});
|
221
|
+
var newColor = newColors[colorIdx];
|
222
|
+
return newColor ? _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, newColor, updated.colorLegends[key])) : accu;
|
223
|
+
}, {});
|
224
|
+
}
|
225
|
+
return updated;
|
226
|
+
}
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Sort custom palette
|
230
|
+
*/
|
231
|
+
function sortCustomPaletteColor(customPalette, oldIndex, newIndex) {
|
232
|
+
var colors = customPalette.colors;
|
233
|
+
var newColors = (0, _utils.arrayMove)(colors, oldIndex, newIndex);
|
234
|
+
var update = replaceColorsInColorRange(customPalette, newColors);
|
235
|
+
|
236
|
+
// @ts-ignore
|
237
|
+
return _objectSpread(_objectSpread({}, customPalette), update);
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
* remove a color in custom palette at index
|
242
|
+
*/
|
243
|
+
function removeCustomPaletteColor(customPalette, index) {
|
244
|
+
var colors = customPalette.colors,
|
245
|
+
colorMap = customPalette.colorMap,
|
246
|
+
colorLegends = customPalette.colorLegends;
|
247
|
+
var oldValue = colors[index];
|
248
|
+
var update = {};
|
249
|
+
update.colors = (0, _toConsumableArray2["default"])(colors);
|
250
|
+
if (update.colors.length > 1) {
|
251
|
+
update.colors.splice(index, 1);
|
252
|
+
}
|
253
|
+
// update color map
|
254
|
+
if (Array.isArray(colorMap)) {
|
255
|
+
// find colorMap index
|
256
|
+
var colorMapIndex = colorMap.findIndex(function (cm) {
|
257
|
+
return cm[1] === oldValue;
|
258
|
+
});
|
259
|
+
if (colorMapIndex >= 0) {
|
260
|
+
update.colorMap = (0, _toConsumableArray2["default"])(colorMap);
|
261
|
+
update.colorMap.splice(colorMapIndex, 1);
|
262
|
+
}
|
263
|
+
}
|
264
|
+
// update color legend
|
265
|
+
if (colorLegends !== null && colorLegends !== void 0 && colorLegends[oldValue]) {
|
266
|
+
update.colorLegends = _objectSpread({}, colorLegends);
|
267
|
+
delete update.colorLegends[oldValue];
|
268
|
+
}
|
269
|
+
return _objectSpread(_objectSpread({}, customPalette), update);
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Update a color in custom palette at index
|
274
|
+
*/
|
275
|
+
function updateCustomPaletteColor(customPalette, index, newValue) {
|
276
|
+
var colors = customPalette.colors;
|
277
|
+
var hex = newValue.toUpperCase();
|
278
|
+
var newColors = (0, _toConsumableArray2["default"])(colors);
|
279
|
+
newColors[index] = hex;
|
280
|
+
var update = replaceColorsInColorRange(customPalette, newColors);
|
281
|
+
|
282
|
+
// @ts-ignore
|
283
|
+
return _objectSpread(_objectSpread({}, customPalette), update);
|
284
|
+
}
|
285
|
+
|
286
|
+
/**
|
287
|
+
* Get a reversed colorRange
|
288
|
+
*/
|
289
|
+
function reverseColorRange(reversed, colorRange) {
|
290
|
+
var newColors = colorRange === null || colorRange === void 0 ? void 0 : colorRange.colors.slice().reverse();
|
291
|
+
var updated = replaceColorsInColorRange(colorRange, newColors);
|
292
|
+
updated.reversed = reversed;
|
293
|
+
return updated;
|
294
|
+
}
|
295
|
+
|
296
|
+
/**
|
297
|
+
* Whether palette matches current ColorBlindSafe config
|
298
|
+
*/
|
299
|
+
function paletteIsColorBlindSafe(palette, colorBlindSafe) {
|
300
|
+
return !colorBlindSafe || colorBlindSafe && palette.colorBlindSafe;
|
301
|
+
}
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Whether palette matches current steps config
|
305
|
+
*/
|
306
|
+
function isQuaPalette(palette) {
|
307
|
+
return palette.type === _constants.PALETTE_TYPES.QUA;
|
308
|
+
}
|
309
|
+
|
310
|
+
/**
|
311
|
+
* Whether palette matches current steps config
|
312
|
+
*/
|
313
|
+
function paletteIsSteps(palette, steps) {
|
314
|
+
return !isQuaPalette(palette) || palette.maxStep >= steps;
|
315
|
+
}
|
316
|
+
|
317
|
+
/**
|
318
|
+
* Whether palette matches current type config
|
319
|
+
*/
|
320
|
+
function paletteIsType(palette, type) {
|
321
|
+
return type === 'all' || type === palette.type;
|
322
|
+
}
|
323
|
+
/**
|
324
|
+
* Find best match palette based on config, update color range by it
|
325
|
+
*/
|
326
|
+
function updateColorRangeByMatchingPalette(currentColorRange, config) {
|
327
|
+
var steps = config.steps,
|
328
|
+
colorBlindSafe = config.colorBlindSafe,
|
329
|
+
type = config.type;
|
330
|
+
var matchingPalette = _constants.KEPLER_COLOR_PALETTES.filter(function (palette) {
|
331
|
+
return (
|
332
|
+
// palette match type
|
333
|
+
paletteIsType(palette, type) &&
|
334
|
+
// palette has same step
|
335
|
+
paletteIsSteps(palette, steps) &&
|
336
|
+
// palette is colorBlindSafe
|
337
|
+
paletteIsColorBlindSafe(palette, colorBlindSafe)
|
338
|
+
);
|
339
|
+
});
|
340
|
+
var bestMatch = matchingPalette.length ? matchingPalette.find(function (p) {
|
341
|
+
return p.name === currentColorRange.name;
|
342
|
+
}) || matchingPalette[0] : null;
|
343
|
+
if (bestMatch) {
|
344
|
+
return updateColorRangeBySelectedPalette(currentColorRange, bestMatch, config);
|
345
|
+
}
|
346
|
+
// we do nothing
|
347
|
+
_console["default"].warn("we cant find any preset palette matches requirments: steps=".concat(steps, " && colorBlindSafe=").concat(colorBlindSafe));
|
348
|
+
return currentColorRange;
|
349
|
+
}
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Update custom palette when reverse the colors in custom palette, since changing 'steps',
|
353
|
+
* 'colorBindSafe', 'type' should fall back to predefined palette.
|
354
|
+
*/
|
355
|
+
function updateCustomColorRangeByColorUI(oldColorRange, colorConfig) {
|
356
|
+
var reversed = colorConfig.reversed;
|
357
|
+
var colors = oldColorRange.colors;
|
358
|
+
// for custom palette, one can only 'reverse' the colors in custom palette.
|
359
|
+
colors.reverse();
|
360
|
+
var colorRange = _objectSpread(_objectSpread(_objectSpread({
|
361
|
+
name: oldColorRange.name,
|
362
|
+
type: oldColorRange.type,
|
363
|
+
category: oldColorRange.category,
|
364
|
+
colors: colors
|
365
|
+
}, reversed ? {
|
366
|
+
reversed: reversed
|
367
|
+
} : {}), oldColorRange.colorMap ? {
|
368
|
+
colorMap: oldColorRange.colorMap
|
369
|
+
} : {}), oldColorRange.colorLegends ? {
|
370
|
+
colorLegends: oldColorRange.colorLegends
|
371
|
+
} : {});
|
372
|
+
return replaceColorsInColorRange(colorRange, colorRange.colors);
|
373
|
+
}
|
374
|
+
|
375
|
+
/**
|
376
|
+
* Update color range after selecting a palette from color range selectoer
|
377
|
+
* Copy over colorMap and colorLegends
|
378
|
+
*/
|
379
|
+
function updateColorRangeBySelectedPalette(oldColorRange, colorPalette, colorConfig) {
|
380
|
+
var _colorPaletteToColorR = (0, _constants.colorPaletteToColorRange)(colorPalette, colorConfig),
|
381
|
+
newColors = _colorPaletteToColorR.colors,
|
382
|
+
newColorRange = (0, _objectWithoutProperties2["default"])(_colorPaletteToColorR, _excluded);
|
383
|
+
var colorRange = _objectSpread(_objectSpread(_objectSpread({
|
384
|
+
colors: oldColorRange.colors
|
385
|
+
}, newColorRange), oldColorRange.colorMap ? {
|
386
|
+
colorMap: oldColorRange.colorMap
|
387
|
+
} : {}), oldColorRange.colorLegends ? {
|
388
|
+
colorLegends: oldColorRange.colorLegends
|
389
|
+
} : {});
|
390
|
+
return replaceColorsInColorRange(colorRange, newColors);
|
391
|
+
}
|
392
|
+
var UberNameRegex = new RegExp(/^([A-Za-z ])+/g);
|
393
|
+
var ColorBrewerRegex = new RegExp(/^ColorBrewer ([A-Za-z1-9])+/g);
|
394
|
+
|
395
|
+
/**
|
396
|
+
* convert saved colorRange to colorPalette objevt type/name/category/isColorBlind
|
397
|
+
*/
|
398
|
+
function colorRangeBackwardCompatibility(colorRange) {
|
399
|
+
if (!colorRange || colorRange.type === 'custom' || colorRange.colorMap) {
|
400
|
+
// don't do anything to custom color palette, or palette with custom breaks
|
401
|
+
return colorRange;
|
402
|
+
}
|
403
|
+
var trimName;
|
404
|
+
if (colorRange.category === 'Uber') {
|
405
|
+
var _colorRange$name;
|
406
|
+
var matchName = ((_colorRange$name = colorRange.name) !== null && _colorRange$name !== void 0 ? _colorRange$name : '').match(UberNameRegex);
|
407
|
+
trimName = matchName ? matchName[0].trim() : null;
|
408
|
+
// match Uber Viz Qualitative 1.4 -> Uber Viz Qualitative
|
409
|
+
} else if (colorRange.category === 'ColorBrewer') {
|
410
|
+
var _colorRange$name2;
|
411
|
+
var _matchName = ((_colorRange$name2 = colorRange.name) !== null && _colorRange$name2 !== void 0 ? _colorRange$name2 : '').match(ColorBrewerRegex);
|
412
|
+
trimName = _matchName ? _matchName[0].replace('ColorBrewer ', '').trim() : null;
|
413
|
+
}
|
414
|
+
if (trimName) {
|
415
|
+
var matchingPalette = _constants.KEPLER_COLOR_PALETTES.find(function (p) {
|
416
|
+
return p.name === trimName;
|
417
|
+
});
|
418
|
+
if (matchingPalette) {
|
419
|
+
return _objectSpread(_objectSpread({}, colorRange), {}, {
|
420
|
+
name: trimName,
|
421
|
+
type: matchingPalette === null || matchingPalette === void 0 ? void 0 : matchingPalette.type,
|
422
|
+
category: matchingPalette.category
|
423
|
+
});
|
424
|
+
}
|
425
|
+
}
|
426
|
+
return colorRange;
|
427
|
+
}
|
428
|
+
|
429
|
+
/**
|
430
|
+
* Initialize custom palette from current standard color range object
|
431
|
+
*/
|
432
|
+
function initializeCustomPalette(colorRange, colorMap) {
|
433
|
+
// TODO: check on `isReversed` key, whether we can remove it here
|
434
|
+
var customPalette = _objectSpread(_objectSpread({}, colorRange), {}, {
|
435
|
+
name: _constants.DEFAULT_CUSTOM_PALETTE.name,
|
436
|
+
type: _constants.DEFAULT_CUSTOM_PALETTE.type,
|
437
|
+
category: _constants.DEFAULT_CUSTOM_PALETTE.category
|
438
|
+
}, colorMap ? {
|
439
|
+
colorMap: colorMap
|
440
|
+
} : {});
|
441
|
+
return customPalette;
|
442
|
+
}
|
443
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29uc3RhbnRzIiwicmVxdWlyZSIsIl9kM0NvbG9yIiwiX2QzSW50ZXJwb2xhdGUiLCJfdXRpbHMiLCJfY29uc29sZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfZXhjbHVkZWQiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsImhleFRvUmdiIiwiaGV4IiwicmVzdWx0IiwiaXNIZXhDb2xvciIsInBhcnNlSW50IiwiZyIsImIiLCJleGVjIiwiUGFkTnVtIiwiYyIsInRvU3RyaW5nIiwiY29uY2F0IiwicmdiVG9IZXgiLCJfcmVmIiwiX3JlZjIiLCJfc2xpY2VkVG9BcnJheTIiLCJtYXAiLCJuIiwiam9pbiIsInRvVXBwZXJDYXNlIiwiaGFzQ29sb3JNYXAiLCJjb2xvclJhbmdlIiwiQXJyYXkiLCJpc0FycmF5IiwiY29sb3JNYXAiLCJCb29sZWFuIiwiY3JlYXRlTGluZWFyR3JhZGllbnQiLCJkaXJlY3Rpb24iLCJjb2xvcnMiLCJzdGVwIiwicGFyc2VGbG9hdCIsInRvRml4ZWQiLCJiYW5kcyIsInJnYiIsImluZGV4IiwiY29sb3JNYXliZVRvUkdCIiwiY29sb3IiLCJpc1JnYkNvbG9yIiwicmdiT2JqIiwiZDNSZ2IiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsImV2ZXJ5Iiwibm9ybWFsaXplQ29sb3IiLCJjb21wb25lbnQiLCJjb2xvck1heWJlVG9IZXgiLCJyZ2JDb2xvciIsImludGVycG9sYXRlSGV4IiwiaGV4MSIsImhleDIiLCJpbnRlcnBvbGF0ZSIsImFkZE5ld1F1YW50YXRpdmVDb2xvckJyZWFrQXRJbmRleCIsIm5ld0NvbG9ycyIsImkiLCJicmVha3MiLCJjbSIsInNsaWNlIiwibmV3VmFsdWUiLCJuZXdCcmVha3MiLCJhcnJheUluc2VydCIsInVuZGVmaW5lZCIsImFkZEN1c3RvbVBhbGV0dGVDb2xvciIsImN1c3RvbVBhbGV0dGUiLCJ1cGRhdGUiLCJuZXdDb2xvciIsInJlcGxhY2VDb2xvcnNJbkNvbG9yUmFuZ2UiLCJvbGRDb2xvcnMiLCJ1cGRhdGVkIiwiY29sb3JMZWdlbmRzIiwicmVkdWNlIiwiYWNjdSIsImtleSIsImNvbG9ySWR4IiwiZmluZEluZGV4Iiwic29ydEN1c3RvbVBhbGV0dGVDb2xvciIsIm9sZEluZGV4IiwibmV3SW5kZXgiLCJhcnJheU1vdmUiLCJyZW1vdmVDdXN0b21QYWxldHRlQ29sb3IiLCJvbGRWYWx1ZSIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJzcGxpY2UiLCJjb2xvck1hcEluZGV4IiwidXBkYXRlQ3VzdG9tUGFsZXR0ZUNvbG9yIiwicmV2ZXJzZUNvbG9yUmFuZ2UiLCJyZXZlcnNlZCIsInJldmVyc2UiLCJwYWxldHRlSXNDb2xvckJsaW5kU2FmZSIsInBhbGV0dGUiLCJjb2xvckJsaW5kU2FmZSIsImlzUXVhUGFsZXR0ZSIsInR5cGUiLCJQQUxFVFRFX1RZUEVTIiwiUVVBIiwicGFsZXR0ZUlzU3RlcHMiLCJzdGVwcyIsIm1heFN0ZXAiLCJwYWxldHRlSXNUeXBlIiwidXBkYXRlQ29sb3JSYW5nZUJ5TWF0Y2hpbmdQYWxldHRlIiwiY3VycmVudENvbG9yUmFuZ2UiLCJjb25maWciLCJtYXRjaGluZ1BhbGV0dGUiLCJLRVBMRVJfQ09MT1JfUEFMRVRURVMiLCJiZXN0TWF0Y2giLCJmaW5kIiwicCIsIm5hbWUiLCJ1cGRhdGVDb2xvclJhbmdlQnlTZWxlY3RlZFBhbGV0dGUiLCJDb25zb2xlIiwid2FybiIsInVwZGF0ZUN1c3RvbUNvbG9yUmFuZ2VCeUNvbG9yVUkiLCJvbGRDb2xvclJhbmdlIiwiY29sb3JDb25maWciLCJjYXRlZ29yeSIsImNvbG9yUGFsZXR0ZSIsIl9jb2xvclBhbGV0dGVUb0NvbG9yUiIsImNvbG9yUGFsZXR0ZVRvQ29sb3JSYW5nZSIsIm5ld0NvbG9yUmFuZ2UiLCJfb2JqZWN0V2l0aG91dFByb3BlcnRpZXMyIiwiVWJlck5hbWVSZWdleCIsIlJlZ0V4cCIsIkNvbG9yQnJld2VyUmVnZXgiLCJjb2xvclJhbmdlQmFja3dhcmRDb21wYXRpYmlsaXR5IiwidHJpbU5hbWUiLCJfY29sb3JSYW5nZSRuYW1lIiwibWF0Y2hOYW1lIiwibWF0Y2giLCJ0cmltIiwiX2NvbG9yUmFuZ2UkbmFtZTIiLCJyZXBsYWNlIiwiaW5pdGlhbGl6ZUN1c3RvbVBhbGV0dGUiLCJERUZBVUxUX0NVU1RPTV9QQUxFVFRFIl0sInNvdXJjZXMiOlsiLi4vc3JjL2NvbG9yLXV0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCB7XG4gIENhdGVnb3JpY2FsUGFsZXR0ZSxcbiAgQ29sb3JQYWxldHRlLFxuICBERUZBVUxUX0NVU1RPTV9QQUxFVFRFLFxuICBjb2xvclBhbGV0dGVUb0NvbG9yUmFuZ2Vcbn0gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtDb2xvck1hcCwgQ29sb3JSYW5nZSwgQ29sb3JSYW5nZUNvbmZpZywgSGV4Q29sb3IsIFJHQkNvbG9yfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7cmdiIGFzIGQzUmdifSBmcm9tICdkMy1jb2xvcic7XG5pbXBvcnQge2ludGVycG9sYXRlfSBmcm9tICdkMy1pbnRlcnBvbGF0ZSc7XG5pbXBvcnQge2FycmF5SW5zZXJ0LCBhcnJheU1vdmV9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IENvbnNvbGUgZnJvbSAnZ2xvYmFsL2NvbnNvbGUnO1xuaW1wb3J0IHtLRVBMRVJfQ09MT1JfUEFMRVRURVMsIFBBTEVUVEVfVFlQRVN9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcblxuLyoqXG4gKiBnZXQgciBnIGIgZnJvbSBoZXggY29kZVxuICpcbiAqIEBwYXJhbSBoZXhcbiAqIEByZXR1cm5zIGFycmF5IG9mIHIgZyBic1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGV4VG9SZ2IoaGV4OiBzdHJpbmcpOiBSR0JDb2xvciB7XG4gIGNvbnN0IHJlc3VsdCA9IGlzSGV4Q29sb3IoaGV4KTtcblxuICBpZiAoIXJlc3VsdCkge1xuICAgIHJldHVybiBbMCwgMCwgMF07XG4gIH1cblxuICBjb25zdCByID0gcGFyc2VJbnQocmVzdWx0WzFdLCAxNik7XG4gIGNvbnN0IGcgPSBwYXJzZUludChyZXN1bHRbMl0sIDE2KTtcbiAgY29uc3QgYiA9IHBhcnNlSW50KHJlc3VsdFszXSwgMTYpO1xuXG4gIHJldHVybiBbciwgZywgYl07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0hleENvbG9yKGhleDogc3RyaW5nKTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbCB7XG4gIGNvbnN0IHJlc3VsdCA9IC9eIz8oW2EtZlxcZF17Mn0pKFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkkL2kuZXhlYyhoZXgpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIFBhZE51bShjKSB7XG4gIGNvbnN0IGhleCA9IGMudG9TdHJpbmcoMTYpO1xuICByZXR1cm4gaGV4Lmxlbmd0aCA9PT0gMSA/IGAwJHtoZXh9YCA6IGhleDtcbn1cblxuLyoqXG4gKiBnZXQgaGV4IGZyb20gciBnIGJcbiAqXG4gKiBAcGFyYW0gcmdiXG4gKiBAcmV0dXJucyBoZXggc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZ2JUb0hleChbciwgZywgYl06IFJHQkNvbG9yKTogSGV4Q29sb3Ige1xuICByZXR1cm4gYCMke1tyLCBnLCBiXS5tYXAobiA9PiBQYWROdW0obikpLmpvaW4oJycpfWAudG9VcHBlckNhc2UoKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGNvbG9yIHJhbmdlIGhhcyBjdXN0b20gY29sb3IgbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNDb2xvck1hcChjb2xvclJhbmdlOiBDb2xvclJhbmdlKTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGNvbG9yUmFuZ2UuY29sb3JNYXApICYmIEJvb2xlYW4oY29sb3JSYW5nZS5jb2xvck1hcC5sZW5ndGgpO1xufVxuXG4vKipcbiAqIGdpdmVuIGEgbGlzdCBvZiByZ2IgYXJyYXlzIGl0IHdpbGwgZ2VuZXJhdGUgYSBsaW5lYXIgZ3JhZGllbnQgY3NzIHJ1bGVcbiAqIEBwYXJhbSBkaXJlY3Rpb25cbiAqIEBwYXJhbSBjb2xvcnNcbiAqIEByZXR1cm5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUxpbmVhckdyYWRpZW50KGRpcmVjdGlvbjogc3RyaW5nLCBjb2xvcnM6IFJHQkNvbG9yW10pOiBzdHJpbmcge1xuICBjb25zdCBzdGVwID0gcGFyc2VGbG9hdCgoMTAwLjAgLyBjb2xvcnMubGVuZ3RoKS50b0ZpeGVkKDIpKTtcbiAgY29uc3QgYmFuZHMgPSBjb2xvcnMubWFwKChyZ2IsIGluZGV4KSA9PiB7XG4gICAgcmV0dXJuIGByZ2JhKCR7cmdiLmpvaW4oJywnKX0sIDEpICR7c3RlcCAqIGluZGV4fSUsIHJnYmEoJHtyZ2Iuam9pbignLCcpfSwgMSkgJHtcbiAgICAgIHN0ZXAgKiAoaW5kZXggKyAxKVxuICAgIH0lYDtcbiAgfSk7XG5cbiAgcmV0dXJuIGBsaW5lYXItZ3JhZGllbnQodG8gJHtkaXJlY3Rpb259LCAke2JhbmRzLmpvaW4oJywnKX0pYDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIFJHQlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JNYXliZVRvUkdCKGNvbG9yOiB1bmtub3duKTogUkdCQ29sb3IgfCBudWxsIHtcbiAgaWYgKGlzUmdiQ29sb3IoY29sb3IpKSB7XG4gICAgcmV0dXJuIGNvbG9yIGFzIFJHQkNvbG9yO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCByZ2JPYmogPSBkM1JnYihjb2xvcik7XG4gICAgaWYgKE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LnIpICYmIE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LmcpICYmIE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LmIpKSB7XG4gICAgICByZXR1cm4gW3JnYk9iai5yLCByZ2JPYmouZywgcmdiT2JqLmJdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgY29sb3IgaXMgcmdiXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZ2JDb2xvcihjb2xvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gQm9vbGVhbihcbiAgICBjb2xvciAmJlxuICAgICAgQXJyYXkuaXNBcnJheShjb2xvcikgJiZcbiAgICAgIGNvbG9yLmxlbmd0aCA9PT0gMyAmJlxuICAgICAgY29sb3IuZXZlcnkobiA9PiBOdW1iZXIuaXNGaW5pdGUobikgJiYgbiA8PSAyNTUgJiYgbiA+PSAwKVxuICApO1xufVxuXG4vKipcbiAqIFRha2UgY29sb3IgdmFsdWVzIGluIDAtMjU1IHJhbmdlIGFuZCBtYXAgdG8gWzAsIDFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVDb2xvcihjb2xvcjogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gIHJldHVybiBjb2xvci5tYXAoY29tcG9uZW50ID0+IGNvbXBvbmVudCAvIDI1NS4wKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIEhleFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JNYXliZVRvSGV4KGNvbG9yOiB1bmtub3duKTogSGV4Q29sb3Ige1xuICBjb25zdCByZ2JDb2xvciA9IGNvbG9yTWF5YmVUb1JHQihjb2xvcik7XG4gIGlmIChyZ2JDb2xvcikgcmV0dXJuIHJnYlRvSGV4KHJnYkNvbG9yKTtcbiAgcmV0dXJuICcjMDAwMDAwJztcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIEhleFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnBvbGF0ZUhleChoZXgxOiBIZXhDb2xvciwgaGV4MjogSGV4Q29sb3IpOiBIZXhDb2xvciB7XG4gIHJldHVybiBkM1JnYihpbnRlcnBvbGF0ZShoZXgxLCBoZXgyKSgwLjUpKS5oZXgoKS50b1VwcGVyQ2FzZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkTmV3UXVhbnRhdGl2ZUNvbG9yQnJlYWtBdEluZGV4KGNvbG9yTWFwLCBpbmRleCwgbmV3Q29sb3JzKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShjb2xvck1hcCkgfHwgIWNvbG9yTWFwLmxlbmd0aCkge1xuICAgIHJldHVybiBjb2xvck1hcDtcbiAgfVxuXG4gIGlmIChjb2xvck1hcC5sZW5ndGggPCAyKSB7XG4gICAgLy8gbGVzcyB0aGVuIDIsIGFkZCAxIGF0IGVuZFxuICAgIC8vIGhvd2V2ZXIgc2hvdWxkbid0IGFsbG93IGRlbGV0ZSB3aGVuIHRoZXJlIGFyZSAyXG4gICAgcmV0dXJuIG5ld0NvbG9ycy5tYXAoKGMsIGkpID0+IChpID09PSAwID8gY29sb3JNYXBbaV0gOiBbbnVsbCwgY10pKTtcbiAgfVxuXG4gIC8vIGJyZWFrcyBzaG91bGQgYmUgMSBsZXNzIHRoYW4gY29sb3JzXG4gIGNvbnN0IGJyZWFrcyA9IGNvbG9yTWFwLm1hcChjbSA9PiBjbVswXSkuc2xpY2UoMCwgY29sb3JNYXAubGVuZ3RoIC0gMSk7XG5cbiAgLy8gaW5zZXJ0IG5ldyBicmVha1xuICBjb25zdCBuZXdWYWx1ZSA9XG4gICAgaW5kZXggPj0gYnJlYWtzLmxlbmd0aCAtIDFcbiAgICAgID8gYnJlYWtzW2JyZWFrcy5sZW5ndGggLSAxXSArXG4gICAgICAgIChicmVha3MubGVuZ3RoID4gMSA/IGJyZWFrc1ticmVha3MubGVuZ3RoIC0gMV0gLSBicmVha3NbYnJlYWtzLmxlbmd0aCAtIDJdIDogMClcbiAgICAgIDogKGJyZWFrc1tpbmRleF0gKyBicmVha3NbaW5kZXggKyAxXSkgLyAyO1xuXG4gIGNvbnN0IG5ld0JyZWFrcyA9IGFycmF5SW5zZXJ0KGJyZWFrcywgaW5kZXggKyAxLCBuZXdWYWx1ZSk7XG5cbiAgLy8gYXNpZ24gYnJlYWtzIHRvIGNvbG9yXG4gIHJldHVybiBuZXdDb2xvcnMubWFwKChjLCBpKSA9PlxuICAgIGkgPT09IG5ld0NvbG9ycy5sZW5ndGggLSAxID8gW251bGwsIGNdIDogW25ld0JyZWFrc1tpXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IG5ld0JyZWFrc1tpXSwgY11cbiAgKTtcbn1cblxuLyoqXG4gKiBBZGQgYSBuZXcgY29sb3IgdG8gY3VzdG9tIHBhbGV0dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZEN1c3RvbVBhbGV0dGVDb2xvcihjdXN0b21QYWxldHRlOiBDb2xvclJhbmdlLCBpbmRleDogbnVtYmVyKTogQ29sb3JSYW5nZSB7XG4gIGNvbnN0IHtjb2xvcnMsIGNvbG9yTWFwfSA9IGN1c3RvbVBhbGV0dGU7XG4gIGNvbnN0IHVwZGF0ZTogUGFydGlhbDxDb2xvclJhbmdlPiA9IHt9O1xuXG4gIGNvbnN0IG5ld0NvbG9yID1cbiAgICBpbmRleCA9PT0gY29sb3JzLmxlbmd0aCAtIDEgPyBjb2xvcnNbaW5kZXhdIDogaW50ZXJwb2xhdGVIZXgoY29sb3JzW2luZGV4XSwgY29sb3JzW2luZGV4ICsgMV0pO1xuXG4gIHVwZGF0ZS5jb2xvcnMgPSBhcnJheUluc2VydChjb2xvcnMsIGluZGV4ICsgMSwgbmV3Q29sb3IpO1xuXG4gIC8vIGFkZCBjb2xvciB0byBjb2xvck1hcFxuICBpZiAoY29sb3JNYXApIHtcbiAgICB1cGRhdGUuY29sb3JNYXAgPSBhZGROZXdRdWFudGF0aXZlQ29sb3JCcmVha0F0SW5kZXgoY29sb3JNYXAsIGluZGV4LCB1cGRhdGUuY29sb3JzKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uY3VzdG9tUGFsZXR0ZSxcbiAgICAuLi51cGRhdGVcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVwbGFjZUNvbG9yc0luQ29sb3JSYW5nZShjb2xvclJhbmdlLCBuZXdDb2xvcnMpIHtcbiAgY29uc3Qgb2xkQ29sb3JzID0gY29sb3JSYW5nZS5jb2xvcnM7XG4gIGNvbnN0IHVwZGF0ZWQgPSB7XG4gICAgLi4uY29sb3JSYW5nZSxcbiAgICBjb2xvcnM6IG5ld0NvbG9yc1xuICB9O1xuXG4gIC8vIHVwZGF0ZSBjb2xvciBtYXBcbiAgLy8ga2VlcCB2YWx1ZSwgcmVwbGFjZSBjb2xvclxuICBpZiAoQXJyYXkuaXNBcnJheSh1cGRhdGVkLmNvbG9yTWFwKSkge1xuICAgIHVwZGF0ZWQuY29sb3JNYXAgPSB1cGRhdGVkLmNvbG9yTWFwLm1hcCgoY20sIGkpID0+IFtjbVswXSwgbmV3Q29sb3JzW2ldXSk7XG4gIH1cbiAgLy8gdXBkYXRlIGNvbG9ybGVnZW5kc1xuICAvLyBrZWVwIHZhbHVlLCByZXBsYWNlIGNvbG9yXG4gIGlmICh1cGRhdGVkLmNvbG9yTGVnZW5kcykge1xuICAgIHVwZGF0ZWQuY29sb3JMZWdlbmRzID0gT2JqZWN0LmtleXModXBkYXRlZC5jb2xvckxlZ2VuZHMpLnJlZHVjZSgoYWNjdSwga2V5KSA9PiB7XG4gICAgICBjb25zdCBjb2xvcklkeCA9IG9sZENvbG9ycy5maW5kSW5kZXgoYyA9PiBjID09PSBrZXkpO1xuICAgICAgY29uc3QgbmV3Q29sb3IgPSBuZXdDb2xvcnNbY29sb3JJZHhdO1xuXG4gICAgICByZXR1cm4gbmV3Q29sb3JcbiAgICAgICAgPyB7XG4gICAgICAgICAgICAuLi5hY2N1LFxuICAgICAgICAgICAgW25ld0NvbG9yXTogdXBkYXRlZC5jb2xvckxlZ2VuZHNba2V5XVxuICAgICAgICAgIH1cbiAgICAgICAgOiBhY2N1O1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIHJldHVybiB1cGRhdGVkO1xufVxuXG4vKipcbiAqIFNvcnQgY3VzdG9tIHBhbGV0dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvcnRDdXN0b21QYWxldHRlQ29sb3IoXG4gIGN1c3RvbVBhbGV0dGU6IENvbG9yUmFuZ2UsXG4gIG9sZEluZGV4OiBudW1iZXIsXG4gIG5ld0luZGV4OiBudW1iZXJcbik6IENvbG9yUmFuZ2Uge1xuICBjb25zdCB7Y29sb3JzfSA9IGN1c3RvbVBhbGV0dGU7XG5cbiAgY29uc3QgbmV3Q29sb3JzID0gYXJyYXlNb3ZlKGNvbG9ycywgb2xkSW5kZXgsIG5ld0luZGV4KTtcbiAgY29uc3QgdXBkYXRlID0gcmVwbGFjZUNvbG9yc0luQ29sb3JSYW5nZShjdXN0b21QYWxldHRlLCBuZXdDb2xvcnMpO1xuXG4gIC8vIEB0cy1pZ25vcmVcbiAgcmV0dXJuIHtcbiAgICAuLi5jdXN0b21QYWxldHRlLFxuICAgIC4uLnVwZGF0ZVxuICB9O1xufVxuXG4vKipcbiAqIHJlbW92ZSBhIGNvbG9yIGluIGN1c3RvbSBwYWxldHRlIGF0IGluZGV4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVDdXN0b21QYWxldHRlQ29sb3IoY3VzdG9tUGFsZXR0ZTogQ29sb3JSYW5nZSwgaW5kZXg6IG51bWJlcik6IENvbG9yUmFuZ2Uge1xuICBjb25zdCB7Y29sb3JzLCBjb2xvck1hcCwgY29sb3JMZWdlbmRzfSA9IGN1c3RvbVBhbGV0dGU7XG4gIGNvbnN0IG9sZFZhbHVlID0gY29sb3JzW2luZGV4XTtcbiAgY29uc3QgdXBkYXRlOiBQYXJ0aWFsPENvbG9yUmFuZ2U+ID0ge307XG4gIHVwZGF0ZS5jb2xvcnMgPSBbLi4uY29sb3JzXTtcblxuICBpZiAodXBkYXRlLmNvbG9ycy5sZW5ndGggPiAxKSB7XG4gICAgdXBkYXRlLmNvbG9ycy5zcGxpY2UoaW5kZXgsIDEpO1xuICB9XG4gIC8vIHVwZGF0ZSBjb2xvciBtYXBcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3JNYXApKSB7XG4gICAgLy8gZmluZCBjb2xvck1hcCBpbmRleFxuICAgIGNvbnN0IGNvbG9yTWFwSW5kZXggPSBjb2xvck1hcC5maW5kSW5kZXgoY20gPT4gY21bMV0gPT09IG9sZFZhbHVlKTtcbiAgICBpZiAoY29sb3JNYXBJbmRleCA+PSAwKSB7XG4gICAgICB1cGRhdGUuY29sb3JNYXAgPSBbLi4uY29sb3JNYXBdO1xuICAgICAgdXBkYXRlLmNvbG9yTWFwLnNwbGljZShjb2xvck1hcEluZGV4LCAxKTtcbiAgICB9XG4gIH1cbiAgLy8gdXBkYXRlIGNvbG9yIGxlZ2VuZFxuICBpZiAoY29sb3JMZWdlbmRzPy5bb2xkVmFsdWVdKSB7XG4gICAgdXBkYXRlLmNvbG9yTGVnZW5kcyA9IHsuLi5jb2xvckxlZ2VuZHN9O1xuICAgIGRlbGV0ZSB1cGRhdGUuY29sb3JMZWdlbmRzW29sZFZhbHVlXTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uY3VzdG9tUGFsZXR0ZSxcbiAgICAuLi51cGRhdGVcbiAgfTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgYSBjb2xvciBpbiBjdXN0b20gcGFsZXR0ZSBhdCBpbmRleFxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQ3VzdG9tUGFsZXR0ZUNvbG9yKFxuICBjdXN0b21QYWxldHRlOiBDb2xvclJhbmdlLFxuICBpbmRleDogbnVtYmVyLFxuICBuZXdWYWx1ZTogSGV4Q29sb3Jcbik6IENvbG9yUmFuZ2Uge1xuICBjb25zdCB7Y29sb3JzfSA9IGN1c3RvbVBhbGV0dGU7XG4gIGNvbnN0IGhleCA9IG5ld1ZhbHVlLnRvVXBwZXJDYXNlKCk7XG4gIGNvbnN0IG5ld0NvbG9ycyA9IFsuLi5jb2xvcnNdO1xuICBuZXdDb2xvcnNbaW5kZXhdID0gaGV4O1xuXG4gIGNvbnN0IHVwZGF0ZSA9IHJlcGxhY2VDb2xvcnNJbkNvbG9yUmFuZ2UoY3VzdG9tUGFsZXR0ZSwgbmV3Q29sb3JzKTtcblxuICAvLyBAdHMtaWdub3JlXG4gIHJldHVybiB7XG4gICAgLi4uY3VzdG9tUGFsZXR0ZSxcbiAgICAuLi51cGRhdGVcbiAgfTtcbn1cblxuLyoqXG4gKiBHZXQgYSByZXZlcnNlZCBjb2xvclJhbmdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXZlcnNlQ29sb3JSYW5nZShyZXZlcnNlZDogYm9vbGVhbiwgY29sb3JSYW5nZTogQ29sb3JSYW5nZSk6IENvbG9yUmFuZ2Uge1xuICBjb25zdCBuZXdDb2xvcnMgPSBjb2xvclJhbmdlPy5jb2xvcnMuc2xpY2UoKS5yZXZlcnNlKCk7XG4gIGNvbnN0IHVwZGF0ZWQgPSByZXBsYWNlQ29sb3JzSW5Db2xvclJhbmdlKGNvbG9yUmFuZ2UsIG5ld0NvbG9ycyk7XG4gIHVwZGF0ZWQucmV2ZXJzZWQgPSByZXZlcnNlZDtcblxuICByZXR1cm4gdXBkYXRlZDtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIHBhbGV0dGUgbWF0Y2hlcyBjdXJyZW50IENvbG9yQmxpbmRTYWZlIGNvbmZpZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFsZXR0ZUlzQ29sb3JCbGluZFNhZmUocGFsZXR0ZTogQ29sb3JQYWxldHRlLCBjb2xvckJsaW5kU2FmZTogYm9vbGVhbikge1xuICByZXR1cm4gIWNvbG9yQmxpbmRTYWZlIHx8IChjb2xvckJsaW5kU2FmZSAmJiBwYWxldHRlLmNvbG9yQmxpbmRTYWZlKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIHBhbGV0dGUgbWF0Y2hlcyBjdXJyZW50IHN0ZXBzIGNvbmZpZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNRdWFQYWxldHRlKHBhbGV0dGU6IENvbG9yUGFsZXR0ZSk6IHBhbGV0dGUgaXMgQ2F0ZWdvcmljYWxQYWxldHRlIHtcbiAgcmV0dXJuIHBhbGV0dGUudHlwZSA9PT0gUEFMRVRURV9UWVBFUy5RVUE7XG59XG5cbi8qKlxuICogV2hldGhlciBwYWxldHRlIG1hdGNoZXMgY3VycmVudCBzdGVwcyBjb25maWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhbGV0dGVJc1N0ZXBzKHBhbGV0dGU6IENvbG9yUGFsZXR0ZSwgc3RlcHM6IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4gIWlzUXVhUGFsZXR0ZShwYWxldHRlKSB8fCBwYWxldHRlLm1heFN0ZXAgPj0gc3RlcHM7XG59XG5cbi8qKlxuICogV2hldGhlciBwYWxldHRlIG1hdGNoZXMgY3VycmVudCB0eXBlIGNvbmZpZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFsZXR0ZUlzVHlwZShwYWxldHRlOiBDb2xvclBhbGV0dGUsIHR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZSA9PT0gJ2FsbCcgfHwgdHlwZSA9PT0gcGFsZXR0ZS50eXBlO1xufVxuLyoqXG4gKiBGaW5kIGJlc3QgbWF0Y2ggcGFsZXR0ZSBiYXNlZCBvbiBjb25maWcsIHVwZGF0ZSBjb2xvciByYW5nZSBieSBpdFxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQ29sb3JSYW5nZUJ5TWF0Y2hpbmdQYWxldHRlKFxuICBjdXJyZW50Q29sb3JSYW5nZTogQ29sb3JSYW5nZSxcbiAgY29uZmlnOiBDb2xvclJhbmdlQ29uZmlnXG4pOiBDb2xvclJhbmdlIHtcbiAgY29uc3Qge3N0ZXBzLCBjb2xvckJsaW5kU2FmZSwgdHlwZX0gPSBjb25maWc7XG5cbiAgY29uc3QgbWF0Y2hpbmdQYWxldHRlID0gS0VQTEVSX0NPTE9SX1BBTEVUVEVTLmZpbHRlcihcbiAgICBwYWxldHRlID0+XG4gICAgICAvLyBwYWxldHRlIG1hdGNoIHR5cGVcbiAgICAgIHBhbGV0dGVJc1R5cGUocGFsZXR0ZSwgdHlwZSkgJiZcbiAgICAgIC8vIHBhbGV0dGUgaGFzIHNhbWUgc3RlcFxuICAgICAgcGFsZXR0ZUlzU3RlcHMocGFsZXR0ZSwgc3RlcHMpICYmXG4gICAgICAvLyBwYWxldHRlIGlzIGNvbG9yQmxpbmRTYWZlXG4gICAgICBwYWxldHRlSXNDb2xvckJsaW5kU2FmZShwYWxldHRlLCBjb2xvckJsaW5kU2FmZSlcbiAgKTtcblxuICBjb25zdCBiZXN0TWF0Y2ggPSBtYXRjaGluZ1BhbGV0dGUubGVuZ3RoXG4gICAgPyBtYXRjaGluZ1BhbGV0dGUuZmluZChwID0+IHAubmFtZSA9PT0gY3VycmVudENvbG9yUmFuZ2UubmFtZSkgfHwgbWF0Y2hpbmdQYWxldHRlWzBdXG4gICAgOiBudWxsO1xuXG4gIGlmIChiZXN0TWF0Y2gpIHtcbiAgICByZXR1cm4gdXBkYXRlQ29sb3JSYW5nZUJ5U2VsZWN0ZWRQYWxldHRlKGN1cnJlbnRDb2xvclJhbmdlLCBiZXN0TWF0Y2gsIGNvbmZpZyk7XG4gIH1cbiAgLy8gd2UgZG8gbm90aGluZ1xuICBDb25zb2xlLndhcm4oXG4gICAgYHdlIGNhbnQgZmluZCBhbnkgcHJlc2V0IHBhbGV0dGUgbWF0Y2hlcyByZXF1aXJtZW50czogc3RlcHM9JHtzdGVwc30gJiYgY29sb3JCbGluZFNhZmU9JHtjb2xvckJsaW5kU2FmZX1gXG4gICk7XG5cbiAgcmV0dXJuIGN1cnJlbnRDb2xvclJhbmdlO1xufVxuXG4vKipcbiAqIFVwZGF0ZSBjdXN0b20gcGFsZXR0ZSB3aGVuIHJldmVyc2UgdGhlIGNvbG9ycyBpbiBjdXN0b20gcGFsZXR0ZSwgc2luY2UgY2hhbmdpbmcgJ3N0ZXBzJyxcbiAqICdjb2xvckJpbmRTYWZlJywgJ3R5cGUnIHNob3VsZCBmYWxsIGJhY2sgdG8gcHJlZGVmaW5lZCBwYWxldHRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQ3VzdG9tQ29sb3JSYW5nZUJ5Q29sb3JVSShcbiAgb2xkQ29sb3JSYW5nZTogQ29sb3JSYW5nZSxcbiAgY29sb3JDb25maWc6IENvbG9yUmFuZ2VDb25maWdcbik6IENvbG9yUmFuZ2Uge1xuICBjb25zdCB7cmV2ZXJzZWR9ID0gY29sb3JDb25maWc7XG4gIGNvbnN0IGNvbG9ycyA9IG9sZENvbG9yUmFuZ2UuY29sb3JzO1xuICAvLyBmb3IgY3VzdG9tIHBhbGV0dGUsIG9uZSBjYW4gb25seSAncmV2ZXJzZScgdGhlIGNvbG9ycyBpbiBjdXN0b20gcGFsZXR0ZS5cbiAgY29sb3JzLnJldmVyc2UoKTtcblxuICBjb25zdCBjb2xvclJhbmdlID0ge1xuICAgIG5hbWU6IG9sZENvbG9yUmFuZ2UubmFtZSxcbiAgICB0eXBlOiBvbGRDb2xvclJhbmdlLnR5cGUsXG4gICAgY2F0ZWdvcnk6IG9sZENvbG9yUmFuZ2UuY2F0ZWdvcnksXG4gICAgY29sb3JzLFxuICAgIC4uLihyZXZlcnNlZCA/IHtyZXZlcnNlZH0gOiB7fSksXG4gICAgLi4uKG9sZENvbG9yUmFuZ2UuY29sb3JNYXAgPyB7Y29sb3JNYXA6IG9sZENvbG9yUmFuZ2UuY29sb3JNYXB9IDoge30pLFxuICAgIC4uLihvbGRDb2xvclJhbmdlLmNvbG9yTGVnZW5kcyA/IHtjb2xvckxlZ2VuZHM6IG9sZENvbG9yUmFuZ2UuY29sb3JMZWdlbmRzfSA6IHt9KVxuICB9O1xuXG4gIHJldHVybiByZXBsYWNlQ29sb3JzSW5Db2xvclJhbmdlKGNvbG9yUmFuZ2UsIGNvbG9yUmFuZ2UuY29sb3JzKTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgY29sb3IgcmFuZ2UgYWZ0ZXIgc2VsZWN0aW5nIGEgcGFsZXR0ZSBmcm9tIGNvbG9yIHJhbmdlIHNlbGVjdG9lclxuICogQ29weSBvdmVyIGNvbG9yTWFwIGFuZCBjb2xvckxlZ2VuZHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUNvbG9yUmFuZ2VCeVNlbGVjdGVkUGFsZXR0ZShvbGRDb2xvclJhbmdlLCBjb2xvclBhbGV0dGUsIGNvbG9yQ29uZmlnKSB7XG4gIGNvbnN0IHtjb2xvcnM6IG5ld0NvbG9ycywgLi4ubmV3Q29sb3JSYW5nZX0gPSBjb2xvclBhbGV0dGVUb0NvbG9yUmFuZ2UoY29sb3JQYWxldHRlLCBjb2xvckNvbmZpZyk7XG5cbiAgY29uc3QgY29sb3JSYW5nZSA9IHtcbiAgICBjb2xvcnM6IG9sZENvbG9yUmFuZ2UuY29sb3JzLFxuICAgIC4uLm5ld0NvbG9yUmFuZ2UsXG4gICAgLi4uKG9sZENvbG9yUmFuZ2UuY29sb3JNYXAgPyB7Y29sb3JNYXA6IG9sZENvbG9yUmFuZ2UuY29sb3JNYXB9IDoge30pLFxuICAgIC4uLihvbGRDb2xvclJhbmdlLmNvbG9yTGVnZW5kcyA/IHtjb2xvckxlZ2VuZHM6IG9sZENvbG9yUmFuZ2UuY29sb3JMZWdlbmRzfSA6IHt9KVxuICB9O1xuXG4gIHJldHVybiByZXBsYWNlQ29sb3JzSW5Db2xvclJhbmdlKGNvbG9yUmFuZ2UsIG5ld0NvbG9ycyk7XG59XG5cbmNvbnN0IFViZXJOYW1lUmVnZXggPSBuZXcgUmVnRXhwKC9eKFtBLVphLXogXSkrL2cpO1xuY29uc3QgQ29sb3JCcmV3ZXJSZWdleCA9IG5ldyBSZWdFeHAoL15Db2xvckJyZXdlciAoW0EtWmEtejEtOV0pKy9nKTtcblxuLyoqXG4gKiBjb252ZXJ0IHNhdmVkIGNvbG9yUmFuZ2UgdG8gY29sb3JQYWxldHRlIG9iamV2dCB0eXBlL25hbWUvY2F0ZWdvcnkvaXNDb2xvckJsaW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvclJhbmdlQmFja3dhcmRDb21wYXRpYmlsaXR5KGNvbG9yUmFuZ2U6IENvbG9yUmFuZ2UpOiBDb2xvclJhbmdlIHtcbiAgaWYgKCFjb2xvclJhbmdlIHx8IGNvbG9yUmFuZ2UudHlwZSA9PT0gJ2N1c3RvbScgfHwgY29sb3JSYW5nZS5jb2xvck1hcCkge1xuICAgIC8vIGRvbid0IGRvIGFueXRoaW5nIHRvIGN1c3RvbSBjb2xvciBwYWxldHRlLCBvciBwYWxldHRlIHdpdGggY3VzdG9tIGJyZWFrc1xuICAgIHJldHVybiBjb2xvclJhbmdlO1xuICB9XG4gIGxldCB0cmltTmFtZTtcbiAgaWYgKGNvbG9yUmFuZ2UuY2F0ZWdvcnkgPT09ICdVYmVyJykge1xuICAgIGNvbnN0IG1hdGNoTmFtZSA9IChjb2xvclJhbmdlLm5hbWUgPz8gJycpLm1hdGNoKFViZXJOYW1lUmVnZXgpO1xuICAgIHRyaW1OYW1lID0gbWF0Y2hOYW1lID8gbWF0Y2hOYW1lWzBdLnRyaW0oKSA6IG51bGw7XG4gICAgLy8gbWF0Y2ggVWJlciBWaXogUXVhbGl0YXRpdmUgMS40IC0+IFViZXIgVml6IFF1YWxpdGF0aXZlXG4gIH0gZWxzZSBpZiAoY29sb3JSYW5nZS5jYXRlZ29yeSA9PT0gJ0NvbG9yQnJld2VyJykge1xuICAgIGNvbnN0IG1hdGNoTmFtZSA9IChjb2xvclJhbmdlLm5hbWUgPz8gJycpLm1hdGNoKENvbG9yQnJld2VyUmVnZXgpO1xuICAgIHRyaW1OYW1lID0gbWF0Y2hOYW1lID8gbWF0Y2hOYW1lWzBdLnJlcGxhY2UoJ0NvbG9yQnJld2VyICcsICcnKS50cmltKCkgOiBudWxsO1xuICB9XG5cbiAgaWYgKHRyaW1OYW1lKSB7XG4gICAgY29uc3QgbWF0Y2hpbmdQYWxldHRlID0gS0VQTEVSX0NPTE9SX1BBTEVUVEVTLmZpbmQocCA9PiBwLm5hbWUgPT09IHRyaW1OYW1lKTtcbiAgICBpZiAobWF0Y2hpbmdQYWxldHRlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5jb2xvclJhbmdlLFxuICAgICAgICBuYW1lOiB0cmltTmFtZSxcbiAgICAgICAgdHlwZTogbWF0Y2hpbmdQYWxldHRlPy50eXBlLFxuICAgICAgICBjYXRlZ29yeTogbWF0Y2hpbmdQYWxldHRlLmNhdGVnb3J5XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb2xvclJhbmdlO1xufVxuXG4vKipcbiAqIEluaXRpYWxpemUgY3VzdG9tIHBhbGV0dGUgZnJvbSBjdXJyZW50IHN0YW5kYXJkIGNvbG9yIHJhbmdlIG9iamVjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUN1c3RvbVBhbGV0dGUoY29sb3JSYW5nZTogQ29sb3JSYW5nZSwgY29sb3JNYXA/OiBDb2xvck1hcCk6IENvbG9yUmFuZ2Uge1xuICAvLyBUT0RPOiBjaGVjayBvbiBgaXNSZXZlcnNlZGAga2V5LCB3aGV0aGVyIHdlIGNhbiByZW1vdmUgaXQgaGVyZVxuICBjb25zdCBjdXN0b21QYWxldHRlID0ge1xuICAgIC4uLmNvbG9yUmFuZ2UsXG4gICAgbmFtZTogREVGQVVMVF9DVVNUT01fUEFMRVRURS5uYW1lLFxuICAgIHR5cGU6IERFRkFVTFRfQ1VTVE9NX1BBTEVUVEUudHlwZSxcbiAgICBjYXRlZ29yeTogREVGQVVMVF9DVVNUT01fUEFMRVRURS5jYXRlZ29yeSxcbiAgICAuLi4oY29sb3JNYXAg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
|