ember-scoped-css 2.2.2 → 3.0.0
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/cjs/all-BI7LOSuT.cjs +1519 -0
- package/dist/cjs/all.cjs +1 -1
- package/dist/cjs/babel.cjs +1 -1
- package/dist/cjs/rollup.cjs +1 -1
- package/dist/cjs/vite.cjs +1 -1
- package/dist/runtime/test-support.js +11 -1
- package/dist/runtime/test-support.js.map +1 -1
- package/package.json +1 -1
- package/src/build/template-plugin.js +14 -1
- package/src/lib/css/rewrite.attributes.test.ts +119 -0
- package/src/lib/css/rewrite.js +57 -5
- package/src/lib/css/utils.js +98 -6
- package/src/lib/renameClass.js +12 -4
- package/src/lib/rewriteHbs.attributes.test.ts +118 -0
- package/src/lib/rewriteHbs.js +65 -15
- package/dist/cjs/all-DYmccIER.cjs +0 -1416
|
@@ -0,0 +1,1519 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let node_assert = require("node:assert");
|
|
25
|
+
node_assert = __toESM(node_assert);
|
|
26
|
+
let node_fs = require("node:fs");
|
|
27
|
+
node_fs = __toESM(node_fs);
|
|
28
|
+
let node_module = require("node:module");
|
|
29
|
+
node_module = __toESM(node_module);
|
|
30
|
+
let node_path = require("node:path");
|
|
31
|
+
node_path = __toESM(node_path);
|
|
32
|
+
let path = require("path");
|
|
33
|
+
path = __toESM(path);
|
|
34
|
+
let unplugin = require("unplugin");
|
|
35
|
+
unplugin = __toESM(unplugin);
|
|
36
|
+
let postcss = require("postcss");
|
|
37
|
+
postcss = __toESM(postcss);
|
|
38
|
+
let postcss_selector_parser = require("postcss-selector-parser");
|
|
39
|
+
postcss_selector_parser = __toESM(postcss_selector_parser);
|
|
40
|
+
let fs = require("fs");
|
|
41
|
+
fs = __toESM(fs);
|
|
42
|
+
let postcss_scss = require("postcss-scss");
|
|
43
|
+
postcss_scss = __toESM(postcss_scss);
|
|
44
|
+
let node_process = require("node:process");
|
|
45
|
+
node_process = __toESM(node_process);
|
|
46
|
+
let ember_template_recast = require("ember-template-recast");
|
|
47
|
+
ember_template_recast = __toESM(ember_template_recast);
|
|
48
|
+
|
|
49
|
+
//#region src/lib/path/const.js
|
|
50
|
+
/**
|
|
51
|
+
* Join will convert to whatever is appropriate fro the current platform
|
|
52
|
+
*/
|
|
53
|
+
const leadingSlashPath = {
|
|
54
|
+
embroiderDir: path.default.join("/node_modules/.embroider/"),
|
|
55
|
+
atEmbroider: path.default.join("/@embroider"),
|
|
56
|
+
componentsDir: path.default.join("/components/"),
|
|
57
|
+
templatesDir: path.default.join("/templates/"),
|
|
58
|
+
routesDir: path.default.join("/routes/"),
|
|
59
|
+
testem: path.default.join("/testem"),
|
|
60
|
+
src: path.default.join("/src/"),
|
|
61
|
+
app: path.default.join("/app/")
|
|
62
|
+
};
|
|
63
|
+
const barePath = { pnpmDir: path.default.join("node_modules/.pnpm") };
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/lib/path/md5.js
|
|
67
|
+
/**
|
|
68
|
+
* Add integers, wrapping at 2^32.
|
|
69
|
+
* This uses 16-bit operations internally to work around bugs in interpreters.
|
|
70
|
+
*
|
|
71
|
+
* @param {number} x First integer
|
|
72
|
+
* @param {number} y Second integer
|
|
73
|
+
* @returns {number} Sum
|
|
74
|
+
*/
|
|
75
|
+
function safeAdd(x, y) {
|
|
76
|
+
var lsw = (x & 65535) + (y & 65535);
|
|
77
|
+
return (x >> 16) + (y >> 16) + (lsw >> 16) << 16 | lsw & 65535;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Bitwise rotate a 32-bit number to the left.
|
|
81
|
+
*
|
|
82
|
+
* @param {number} num 32-bit number
|
|
83
|
+
* @param {number} cnt Rotation count
|
|
84
|
+
* @returns {number} Rotated number
|
|
85
|
+
*/
|
|
86
|
+
function bitRotateLeft(num, cnt) {
|
|
87
|
+
return num << cnt | num >>> 32 - cnt;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Basic operation the algorithm uses.
|
|
91
|
+
*
|
|
92
|
+
* @param {number} q q
|
|
93
|
+
* @param {number} a a
|
|
94
|
+
* @param {number} b b
|
|
95
|
+
* @param {number} x x
|
|
96
|
+
* @param {number} s s
|
|
97
|
+
* @param {number} t t
|
|
98
|
+
* @returns {number} Result
|
|
99
|
+
*/
|
|
100
|
+
function md5cmn(q, a, b, x, s, t) {
|
|
101
|
+
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Basic operation the algorithm uses.
|
|
105
|
+
*
|
|
106
|
+
* @param {number} a a
|
|
107
|
+
* @param {number} b b
|
|
108
|
+
* @param {number} c c
|
|
109
|
+
* @param {number} d d
|
|
110
|
+
* @param {number} x x
|
|
111
|
+
* @param {number} s s
|
|
112
|
+
* @param {number} t t
|
|
113
|
+
* @returns {number} Result
|
|
114
|
+
*/
|
|
115
|
+
function md5ff(a, b, c, d, x, s, t) {
|
|
116
|
+
return md5cmn(b & c | ~b & d, a, b, x, s, t);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Basic operation the algorithm uses.
|
|
120
|
+
*
|
|
121
|
+
* @param {number} a a
|
|
122
|
+
* @param {number} b b
|
|
123
|
+
* @param {number} c c
|
|
124
|
+
* @param {number} d d
|
|
125
|
+
* @param {number} x x
|
|
126
|
+
* @param {number} s s
|
|
127
|
+
* @param {number} t t
|
|
128
|
+
* @returns {number} Result
|
|
129
|
+
*/
|
|
130
|
+
function md5gg(a, b, c, d, x, s, t) {
|
|
131
|
+
return md5cmn(b & d | c & ~d, a, b, x, s, t);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Basic operation the algorithm uses.
|
|
135
|
+
*
|
|
136
|
+
* @param {number} a a
|
|
137
|
+
* @param {number} b b
|
|
138
|
+
* @param {number} c c
|
|
139
|
+
* @param {number} d d
|
|
140
|
+
* @param {number} x x
|
|
141
|
+
* @param {number} s s
|
|
142
|
+
* @param {number} t t
|
|
143
|
+
* @returns {number} Result
|
|
144
|
+
*/
|
|
145
|
+
function md5hh(a, b, c, d, x, s, t) {
|
|
146
|
+
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Basic operation the algorithm uses.
|
|
150
|
+
*
|
|
151
|
+
* @param {number} a a
|
|
152
|
+
* @param {number} b b
|
|
153
|
+
* @param {number} c c
|
|
154
|
+
* @param {number} d d
|
|
155
|
+
* @param {number} x x
|
|
156
|
+
* @param {number} s s
|
|
157
|
+
* @param {number} t t
|
|
158
|
+
* @returns {number} Result
|
|
159
|
+
*/
|
|
160
|
+
function md5ii(a, b, c, d, x, s, t) {
|
|
161
|
+
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
|
165
|
+
*
|
|
166
|
+
* @param {Array} x Array of little-endian words
|
|
167
|
+
* @param {number} len Bit length
|
|
168
|
+
* @returns {Array<number>} MD5 Array
|
|
169
|
+
*/
|
|
170
|
+
function binlMD5(x, len) {
|
|
171
|
+
x[len >> 5] |= 128 << len % 32;
|
|
172
|
+
x[(len + 64 >>> 9 << 4) + 14] = len;
|
|
173
|
+
var i;
|
|
174
|
+
var olda;
|
|
175
|
+
var oldb;
|
|
176
|
+
var oldc;
|
|
177
|
+
var oldd;
|
|
178
|
+
var a = 1732584193;
|
|
179
|
+
var b = -271733879;
|
|
180
|
+
var c = -1732584194;
|
|
181
|
+
var d = 271733878;
|
|
182
|
+
for (i = 0; i < x.length; i += 16) {
|
|
183
|
+
olda = a;
|
|
184
|
+
oldb = b;
|
|
185
|
+
oldc = c;
|
|
186
|
+
oldd = d;
|
|
187
|
+
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
|
188
|
+
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
|
189
|
+
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
|
190
|
+
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
|
191
|
+
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
|
192
|
+
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
|
193
|
+
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
|
194
|
+
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
|
195
|
+
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
|
196
|
+
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
|
197
|
+
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
|
198
|
+
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
|
199
|
+
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
|
200
|
+
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
|
201
|
+
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
|
202
|
+
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
|
203
|
+
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
|
204
|
+
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
|
205
|
+
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
|
206
|
+
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
|
207
|
+
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
|
208
|
+
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
|
209
|
+
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
|
210
|
+
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
|
211
|
+
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
|
212
|
+
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
|
213
|
+
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
|
214
|
+
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
|
215
|
+
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
|
216
|
+
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
|
217
|
+
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
|
218
|
+
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
|
219
|
+
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
|
220
|
+
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
|
221
|
+
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
|
222
|
+
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
|
223
|
+
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
|
224
|
+
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
|
225
|
+
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
|
226
|
+
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
|
227
|
+
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
|
228
|
+
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
|
229
|
+
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
|
230
|
+
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
|
231
|
+
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
|
232
|
+
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
|
233
|
+
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
|
234
|
+
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
|
235
|
+
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
|
236
|
+
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
|
237
|
+
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
|
238
|
+
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
|
239
|
+
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
|
240
|
+
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
|
241
|
+
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
|
242
|
+
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
|
243
|
+
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
|
244
|
+
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
|
245
|
+
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
|
246
|
+
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
|
247
|
+
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
|
248
|
+
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
|
249
|
+
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
|
250
|
+
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
|
251
|
+
a = safeAdd(a, olda);
|
|
252
|
+
b = safeAdd(b, oldb);
|
|
253
|
+
c = safeAdd(c, oldc);
|
|
254
|
+
d = safeAdd(d, oldd);
|
|
255
|
+
}
|
|
256
|
+
return [
|
|
257
|
+
a,
|
|
258
|
+
b,
|
|
259
|
+
c,
|
|
260
|
+
d
|
|
261
|
+
];
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Convert an array of little-endian words to a string
|
|
265
|
+
*
|
|
266
|
+
* @param {Array<number>} input MD5 Array
|
|
267
|
+
* @returns {string} MD5 string
|
|
268
|
+
*/
|
|
269
|
+
function binl2rstr(input) {
|
|
270
|
+
var i;
|
|
271
|
+
var output = "";
|
|
272
|
+
var length32 = input.length * 32;
|
|
273
|
+
for (i = 0; i < length32; i += 8) output += String.fromCharCode(input[i >> 5] >>> i % 32 & 255);
|
|
274
|
+
return output;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Convert a raw string to an array of little-endian words
|
|
278
|
+
* Characters >255 have their high-byte silently ignored.
|
|
279
|
+
*
|
|
280
|
+
* @param {string} input Raw input string
|
|
281
|
+
* @returns {Array<number>} Array of little-endian words
|
|
282
|
+
*/
|
|
283
|
+
function rstr2binl(input) {
|
|
284
|
+
var i;
|
|
285
|
+
var output = [];
|
|
286
|
+
output[(input.length >> 2) - 1] = void 0;
|
|
287
|
+
for (i = 0; i < output.length; i += 1) output[i] = 0;
|
|
288
|
+
var length8 = input.length * 8;
|
|
289
|
+
for (i = 0; i < length8; i += 8) output[i >> 5] |= (input.charCodeAt(i / 8) & 255) << i % 32;
|
|
290
|
+
return output;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Calculate the MD5 of a raw string
|
|
294
|
+
*
|
|
295
|
+
* @param {string} s Input string
|
|
296
|
+
* @returns {string} Raw MD5 string
|
|
297
|
+
*/
|
|
298
|
+
function rstrMD5(s) {
|
|
299
|
+
return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Calculates the HMAC-MD5 of a key and some data (raw strings)
|
|
303
|
+
*
|
|
304
|
+
* @param {string} key HMAC key
|
|
305
|
+
* @param {string} data Raw input string
|
|
306
|
+
* @returns {string} Raw MD5 string
|
|
307
|
+
*/
|
|
308
|
+
function rstrHMACMD5(key, data) {
|
|
309
|
+
var i;
|
|
310
|
+
var bkey = rstr2binl(key);
|
|
311
|
+
var ipad = [];
|
|
312
|
+
var opad = [];
|
|
313
|
+
var hash$2;
|
|
314
|
+
ipad[15] = opad[15] = void 0;
|
|
315
|
+
if (bkey.length > 16) bkey = binlMD5(bkey, key.length * 8);
|
|
316
|
+
for (i = 0; i < 16; i += 1) {
|
|
317
|
+
ipad[i] = bkey[i] ^ 909522486;
|
|
318
|
+
opad[i] = bkey[i] ^ 1549556828;
|
|
319
|
+
}
|
|
320
|
+
hash$2 = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
|
|
321
|
+
return binl2rstr(binlMD5(opad.concat(hash$2), 640));
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Convert a raw string to a hex string
|
|
325
|
+
*
|
|
326
|
+
* @param {string} input Raw input string
|
|
327
|
+
* @returns {string} Hex encoded string
|
|
328
|
+
*/
|
|
329
|
+
function rstr2hex(input) {
|
|
330
|
+
var hexTab = "0123456789abcdef";
|
|
331
|
+
var output = "";
|
|
332
|
+
var x;
|
|
333
|
+
var i;
|
|
334
|
+
for (i = 0; i < input.length; i += 1) {
|
|
335
|
+
x = input.charCodeAt(i);
|
|
336
|
+
output += hexTab.charAt(x >>> 4 & 15) + hexTab.charAt(x & 15);
|
|
337
|
+
}
|
|
338
|
+
return output;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Encode a string as UTF-8
|
|
342
|
+
*
|
|
343
|
+
* @param {string} input Input string
|
|
344
|
+
* @returns {string} UTF8 string
|
|
345
|
+
*/
|
|
346
|
+
function str2rstrUTF8(input) {
|
|
347
|
+
return unescape(encodeURIComponent(input));
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Encodes input string as raw MD5 string
|
|
351
|
+
*
|
|
352
|
+
* @param {string} s Input string
|
|
353
|
+
* @returns {string} Raw MD5 string
|
|
354
|
+
*/
|
|
355
|
+
function rawMD5(s) {
|
|
356
|
+
return rstrMD5(str2rstrUTF8(s));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Encodes input string as Hex encoded string
|
|
360
|
+
*
|
|
361
|
+
* @param {string} s Input string
|
|
362
|
+
* @returns {string} Hex encoded string
|
|
363
|
+
*/
|
|
364
|
+
function hexMD5(s) {
|
|
365
|
+
return rstr2hex(rawMD5(s));
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Calculates the raw HMAC-MD5 for the given key and data
|
|
369
|
+
*
|
|
370
|
+
* @param {string} k HMAC key
|
|
371
|
+
* @param {string} d Input string
|
|
372
|
+
* @returns {string} Raw MD5 string
|
|
373
|
+
*/
|
|
374
|
+
function rawHMACMD5(k, d) {
|
|
375
|
+
return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Calculates the Hex encoded HMAC-MD5 for the given key and data
|
|
379
|
+
*
|
|
380
|
+
* @param {string} k HMAC key
|
|
381
|
+
* @param {string} d Input string
|
|
382
|
+
* @returns {string} Raw MD5 string
|
|
383
|
+
*/
|
|
384
|
+
function hexHMACMD5(k, d) {
|
|
385
|
+
return rstr2hex(rawHMACMD5(k, d));
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Calculates MD5 value for a given string.
|
|
389
|
+
* If a key is provided, calculates the HMAC-MD5 value.
|
|
390
|
+
* Returns a Hex encoded string unless the raw argument is given.
|
|
391
|
+
*
|
|
392
|
+
* @param {string} string Input string
|
|
393
|
+
* @param {string} [key] HMAC key
|
|
394
|
+
* @param {boolean} [raw] Raw output switch
|
|
395
|
+
* @returns {string} MD5 output
|
|
396
|
+
*/
|
|
397
|
+
function md5(string, key, raw) {
|
|
398
|
+
if (!key) {
|
|
399
|
+
if (!raw) return hexMD5(string);
|
|
400
|
+
return rawMD5(string);
|
|
401
|
+
}
|
|
402
|
+
if (!raw) return hexHMACMD5(key, string);
|
|
403
|
+
return rawHMACMD5(key, string);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/lib/path/hash-from-module-path.js
|
|
408
|
+
/**
|
|
409
|
+
* The intent of this function is to generate the suffix/postfix for the
|
|
410
|
+
* css classes, based on the module-scoped path name.
|
|
411
|
+
*
|
|
412
|
+
* for example,
|
|
413
|
+
* hash('my-app/components/foo')
|
|
414
|
+
* instead of
|
|
415
|
+
* hash('app/components/foo')
|
|
416
|
+
*
|
|
417
|
+
* (unless your app name is 'app')
|
|
418
|
+
*
|
|
419
|
+
* @param {string} modulePath
|
|
420
|
+
* @returns {string}
|
|
421
|
+
*/
|
|
422
|
+
function hash$1(modulePath) {
|
|
423
|
+
return "e" + md5(modulePath).substring(0, 8);
|
|
424
|
+
}
|
|
425
|
+
const hashFromModulePath$1 = hash$1;
|
|
426
|
+
|
|
427
|
+
//#endregion
|
|
428
|
+
//#region src/lib/path/utils.js
|
|
429
|
+
/**
|
|
430
|
+
*
|
|
431
|
+
* @param {string} filePath
|
|
432
|
+
* @returns {string}
|
|
433
|
+
*/
|
|
434
|
+
function hashFromModulePath(filePath) {
|
|
435
|
+
return hashFromModulePath$1(forcePosix(filePath));
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* @param {string} filePath
|
|
439
|
+
*/
|
|
440
|
+
function forcePosix(filePath) {
|
|
441
|
+
const parsed = node_path.default.parse(filePath);
|
|
442
|
+
if (parsed.root === "") return filePath.replaceAll(node_path.default.win32.sep, node_path.default.posix.sep);
|
|
443
|
+
return filePath.replace(/* @__PURE__ */ new RegExp(`^${RegExp.escape(parsed.root)}`), node_path.default.posix.sep).replaceAll(node_path.default.win32.sep, node_path.default.posix.sep);
|
|
444
|
+
}
|
|
445
|
+
let here = require("url").pathToFileURL(__filename).href;
|
|
446
|
+
let ourRequire = globalThis.require ? globalThis.require : here && (0, node_module.createRequire)(here);
|
|
447
|
+
if (!ourRequire) ourRequire = require;
|
|
448
|
+
const IRRELEVANT_PATHS = [barePath.pnpmDir, "__vite-"];
|
|
449
|
+
const UNSUPPORTED_DIRECTORIES = new Set(["tests"]);
|
|
450
|
+
const CWD = process.cwd();
|
|
451
|
+
/**
|
|
452
|
+
* Based on ember's component location conventions,
|
|
453
|
+
* this function will provide a path for where we
|
|
454
|
+
* expect the CSS to live.
|
|
455
|
+
*
|
|
456
|
+
* For co-located structure:
|
|
457
|
+
* - components/my-component.hbs
|
|
458
|
+
* - components/my-component.css
|
|
459
|
+
*
|
|
460
|
+
* For nested co-located structure
|
|
461
|
+
* - components/my-component/foo.hbs
|
|
462
|
+
* - components/my-component/foo.css
|
|
463
|
+
*
|
|
464
|
+
* For Pods routes structure
|
|
465
|
+
* - routes/my-route/template.{hbs,js}
|
|
466
|
+
* - routes/my-route/styles.css
|
|
467
|
+
*
|
|
468
|
+
* Deliberately not supported:
|
|
469
|
+
* - components w/ pods -- this is deprecated in 5.10
|
|
470
|
+
*
|
|
471
|
+
* @param {string} fileName - the hbs, js, gjs, gts or whatever co-located path.
|
|
472
|
+
* @returns {string} - expected css path
|
|
473
|
+
*/
|
|
474
|
+
function cssPathFor(fileName) {
|
|
475
|
+
let cssPath = withoutExtension(fileName) + ".css";
|
|
476
|
+
if (isPod(fileName)) cssPath = fileName.replace(/template\.js$/, "styles.css").replace(/template\.gjs/, "styles.css").replace(/template\.gts/, "styles.css").replace(/template\.hbs/, "styles.css");
|
|
477
|
+
return cssPath;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Note that components in the "pods" convention will
|
|
481
|
+
* never be supported.
|
|
482
|
+
*
|
|
483
|
+
* @param {string} filePath
|
|
484
|
+
*/
|
|
485
|
+
function isPodTemplate(filePath) {
|
|
486
|
+
if (filePath.includes(leadingSlashPath.componentsDir)) return false;
|
|
487
|
+
return filePath.endsWith("template.js") || filePath.endsWith("template.hbs") || filePath.endsWith("template.gjs") || filePath.endsWith("template.gts");
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Note that components in the "pods" convention will
|
|
491
|
+
* never be supported.
|
|
492
|
+
*
|
|
493
|
+
* Checks if a file ends with
|
|
494
|
+
* - template.js
|
|
495
|
+
* - template.hbs
|
|
496
|
+
* - styles.css
|
|
497
|
+
*
|
|
498
|
+
* @param {string} filePath
|
|
499
|
+
*/
|
|
500
|
+
function isPod(filePath) {
|
|
501
|
+
if (filePath.includes(leadingSlashPath.componentsDir)) return false;
|
|
502
|
+
if (isPodTemplate(filePath)) return true;
|
|
503
|
+
return filePath.endsWith("styles.css");
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
*
|
|
507
|
+
* @param {string} filePath
|
|
508
|
+
* @returns the same path, but without the extension
|
|
509
|
+
*/
|
|
510
|
+
function withoutExtension(filePath) {
|
|
511
|
+
let parsed = node_path.default.parse(filePath);
|
|
512
|
+
return node_path.default.join(parsed.dir, parsed.name);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Examples for fileName
|
|
516
|
+
* - absolute on-disk path
|
|
517
|
+
* - in webpack
|
|
518
|
+
* - URL-absolute path, starting with /
|
|
519
|
+
*
|
|
520
|
+
* @param {string} fileName
|
|
521
|
+
* @param {{ additionalRoots?: string[]; cwd: string }} options
|
|
522
|
+
* @returns
|
|
523
|
+
*/
|
|
524
|
+
function isRelevantFile(fileName, { additionalRoots, cwd }) {
|
|
525
|
+
if (fileName.startsWith(leadingSlashPath.testem)) return false;
|
|
526
|
+
if (fileName.startsWith("\0")) return false;
|
|
527
|
+
if (node_path.default.isAbsolute(fileName) === false) {
|
|
528
|
+
if (fileName.match(/^[a-zA-Z]/)) return false;
|
|
529
|
+
}
|
|
530
|
+
if (fileName.startsWith(leadingSlashPath.atEmbroider)) return false;
|
|
531
|
+
if (IRRELEVANT_PATHS.some((i) => fileName.includes(i))) return false;
|
|
532
|
+
let workspace = findWorkspacePath(fileName);
|
|
533
|
+
(0, node_assert.default)(cwd, `cwd was not passed to isRelevantFile`);
|
|
534
|
+
if (workspace !== findWorkspacePath(cwd)) return false;
|
|
535
|
+
let [, ...parts] = fileName.replace(workspace, "").split(node_path.default.sep).filter(Boolean);
|
|
536
|
+
if (UNSUPPORTED_DIRECTORIES.has(parts[0])) return false;
|
|
537
|
+
if (![
|
|
538
|
+
leadingSlashPath.componentsDir,
|
|
539
|
+
leadingSlashPath.templatesDir,
|
|
540
|
+
leadingSlashPath.routesDir,
|
|
541
|
+
...additionalRoots || []
|
|
542
|
+
].some((root) => fileName.includes(root))) return;
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
function packageScopedPathToModulePath(packageScopedPath) {
|
|
546
|
+
/**
|
|
547
|
+
* *By convention*, `src` is omitted from component paths.
|
|
548
|
+
* We can reflect the same behavior by replacing src/
|
|
549
|
+
* with an empty string.
|
|
550
|
+
*
|
|
551
|
+
* CSS isn't emitted as a co-located module, but
|
|
552
|
+
* to keep conventions consistent across languages,
|
|
553
|
+
* we can pretend it is.
|
|
554
|
+
*
|
|
555
|
+
* Any customization beyond removing `src` and `app` is potentially confusing.
|
|
556
|
+
* If we need further customizations, we'll want to match on `exports` in the
|
|
557
|
+
* corresponding package.json
|
|
558
|
+
*/
|
|
559
|
+
let packageRelative = packageScopedPath.replace(/* @__PURE__ */ new RegExp(`^${RegExp.escape(leadingSlashPath.src)}`), node_path.default.sep);
|
|
560
|
+
let parsed = node_path.default.parse(packageRelative);
|
|
561
|
+
if (isPod(packageRelative))
|
|
562
|
+
/**
|
|
563
|
+
* For pods, we chop off the whole file, and use the dir name as the "modulePath"
|
|
564
|
+
*/
|
|
565
|
+
return parsed.dir;
|
|
566
|
+
return node_path.default.join(parsed.dir, parsed.name);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* returns the app-module path of the source file
|
|
570
|
+
*
|
|
571
|
+
* This assumes normal ember app conventions
|
|
572
|
+
*
|
|
573
|
+
* which is `<package.json#name>/path-to-file`
|
|
574
|
+
*/
|
|
575
|
+
function appPath(sourcePath) {
|
|
576
|
+
let workspacePath = findWorkspacePath(sourcePath);
|
|
577
|
+
let name = moduleName(sourcePath);
|
|
578
|
+
/**
|
|
579
|
+
* Under embroider builds, the spec-compliant version of the app
|
|
580
|
+
* has all the files under a folder which represents the package name,
|
|
581
|
+
* rather than "app".
|
|
582
|
+
*/
|
|
583
|
+
let packageRelative = sourcePath.replace(workspacePath, "");
|
|
584
|
+
/**
|
|
585
|
+
* But we also don't want 'app' -- which is present in the v1 addon pipeline
|
|
586
|
+
*/
|
|
587
|
+
packageRelative = packageRelative.replace(leadingSlashPath.app, node_path.default.sep);
|
|
588
|
+
packageRelative = node_path.default.normalize(packageRelative);
|
|
589
|
+
return `${name}${packageScopedPathToModulePath(packageRelative)}`;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* To avoid hitting the filesysetm, we'll store all found
|
|
593
|
+
* project paths bere, so we can, in memory,
|
|
594
|
+
* get the folder where a package.json exists, rather than
|
|
595
|
+
* hit the file system every time.
|
|
596
|
+
*/
|
|
597
|
+
const SEEN = /* @__PURE__ */ new Set();
|
|
598
|
+
function getSeen(sourcePath) {
|
|
599
|
+
if (SEEN.has(sourcePath)) return sourcePath;
|
|
600
|
+
let parts = sourcePath.split(node_path.default.sep);
|
|
601
|
+
for (let i = parts.length - 1; i > 1; i--) {
|
|
602
|
+
let toCheck = parts.slice(0, i).join(node_path.default.sep);
|
|
603
|
+
if (SEEN.has(toCheck)) return toCheck;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
function findWorkspacePath(sourcePath, options) {
|
|
607
|
+
let cwd = options?.cwd ?? CWD;
|
|
608
|
+
if (sourcePath.endsWith(node_path.default.sep)) sourcePath = sourcePath.replace(/* @__PURE__ */ new RegExp(`${RegExp.escape(node_path.default.sep)}$`), "");
|
|
609
|
+
let seen = getSeen(sourcePath);
|
|
610
|
+
if (seen) return seen;
|
|
611
|
+
let candidatePath = node_path.default.join(sourcePath, "package.json");
|
|
612
|
+
if (node_fs.default.existsSync(candidatePath)) return sourcePath;
|
|
613
|
+
const packageJsonPath = findPackageJsonUp(sourcePath, { cwd });
|
|
614
|
+
if (!packageJsonPath) throw new Error(`Could not determine project for ${sourcePath}`);
|
|
615
|
+
const workspacePath = node_path.default.dirname(packageJsonPath);
|
|
616
|
+
SEEN.add(workspacePath);
|
|
617
|
+
return workspacePath;
|
|
618
|
+
}
|
|
619
|
+
function findPackageJsonUp(startPath, options) {
|
|
620
|
+
let cwd = options?.cwd ?? CWD;
|
|
621
|
+
let parts = startPath.split(node_path.default.sep);
|
|
622
|
+
for (let i = parts.length - 1; i > 1; i--) {
|
|
623
|
+
let toCheck = parts.slice(0, i).join(node_path.default.sep);
|
|
624
|
+
let packageJson = node_path.default.join(toCheck, "package.json");
|
|
625
|
+
if (node_fs.default.existsSync(packageJson)) return packageJson;
|
|
626
|
+
if (toCheck === cwd) break;
|
|
627
|
+
}
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
const MANIFEST_CACHE = /* @__PURE__ */ new Map();
|
|
631
|
+
/**
|
|
632
|
+
* Will return the package.json#name, or config/environment#moudlePrefix (if v1 app)
|
|
633
|
+
*
|
|
634
|
+
* @param {string} sourcePath
|
|
635
|
+
*/
|
|
636
|
+
function moduleName(sourcePath) {
|
|
637
|
+
return getManifest(findWorkspacePath(sourcePath)).name;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* @param {string} workspace
|
|
641
|
+
*/
|
|
642
|
+
function getManifest(workspace) {
|
|
643
|
+
let existing = MANIFEST_CACHE.get(workspace);
|
|
644
|
+
if (existing) return existing;
|
|
645
|
+
let content = node_fs.default.readFileSync(node_path.default.join(workspace, "package.json")).toString();
|
|
646
|
+
let json = JSON.parse(content);
|
|
647
|
+
MANIFEST_CACHE.set(workspace, json);
|
|
648
|
+
return json;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
//#endregion
|
|
652
|
+
//#region src/lib/renameClass.js
|
|
653
|
+
/**
|
|
654
|
+
* Splits a space-separated class list (the value of a `class` attribute or of
|
|
655
|
+
* a `[class="..."]` selector) into its individual class names.
|
|
656
|
+
*
|
|
657
|
+
* @param {string} classList
|
|
658
|
+
* @returns {string[]}
|
|
659
|
+
*/
|
|
660
|
+
function splitClassList(classList) {
|
|
661
|
+
return classList.split(/\s+/).filter(Boolean);
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
*
|
|
665
|
+
* @param {string} className
|
|
666
|
+
* @param {string} postfix
|
|
667
|
+
* @param {Set<string>} [classesInCss]
|
|
668
|
+
* @returns
|
|
669
|
+
*/
|
|
670
|
+
function renameClass(className, postfix, classesInCss) {
|
|
671
|
+
const renamedClasses = splitClassList(className).map((c) => {
|
|
672
|
+
if (!classesInCss || classesInCss.has(c)) {
|
|
673
|
+
if (c.endsWith(postfix)) return c;
|
|
674
|
+
return c + "_" + postfix;
|
|
675
|
+
}
|
|
676
|
+
return c;
|
|
677
|
+
}).join(" ");
|
|
678
|
+
return className.replace(className.trimStart().trimEnd(), renamedClasses);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
//#endregion
|
|
682
|
+
//#region src/build/babel-plugin.js
|
|
683
|
+
function _isRelevantFile(state, cwd) {
|
|
684
|
+
let fileName = state.file.opts.filename;
|
|
685
|
+
let additionalRoots = state.opts?.additionalRoots;
|
|
686
|
+
return isRelevantFile(fileName, {
|
|
687
|
+
additionalRoots,
|
|
688
|
+
cwd
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* @param {any} env - babel plugin env, env.types is most commonly used (esp in TS)
|
|
693
|
+
* @param {object} options - the options for scoped-css -- this is also available in each visitor's state.opts
|
|
694
|
+
* @param {string} workingDirectory
|
|
695
|
+
*/
|
|
696
|
+
const scopedCSS$1 = (config) => (env, options, workingDirectory) => {
|
|
697
|
+
options = {
|
|
698
|
+
...config,
|
|
699
|
+
...options
|
|
700
|
+
};
|
|
701
|
+
/**
|
|
702
|
+
* This babel plugin does two things:
|
|
703
|
+
* - removes the import of scopedClass, if it exists
|
|
704
|
+
* - if scopedClass was imported, it is removed from any component's "scope bag"
|
|
705
|
+
* (the scope bag being a low-level object used for passing what is "in scope" for a component)
|
|
706
|
+
*/
|
|
707
|
+
return { visitor: {
|
|
708
|
+
Program: { enter(path$8, state) {
|
|
709
|
+
if (!_isRelevantFile(state, workingDirectory)) {
|
|
710
|
+
state.canSkip = true;
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
state.postfix = hashFromModulePath(appPath(state.filename));
|
|
714
|
+
} },
|
|
715
|
+
ImportDeclaration(path$8, state) {
|
|
716
|
+
if (state.canSkip) return;
|
|
717
|
+
if (path$8.node.source.value === "ember-scoped-css") {
|
|
718
|
+
let specifier = path$8.node.specifiers.find((x) => x.imported.name === "scopedClass");
|
|
719
|
+
if (specifier) state.file.opts.importedScopedClass = specifier.local.name;
|
|
720
|
+
if (specifier.local.name !== "scopedClass") throw new Error(`The scopedClass import is a psuedo-helper, and may not be renamed as it is removed at build time.`);
|
|
721
|
+
path$8.remove();
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
CallExpression(path$8, state) {
|
|
725
|
+
if (state.canSkip) return;
|
|
726
|
+
if (path$8.node.callee.type === "Identifier" && path$8.node.callee.name === state.file.opts?.importedScopedClass) {
|
|
727
|
+
if (path$8.node.arguments.length !== 1 || path$8.node.arguments[0].type !== "StringLiteral") throw new Error(`The scopedClass helper only accepts a single, non-dynamic, string literal argument.`);
|
|
728
|
+
const original = path$8.node.arguments[0].value;
|
|
729
|
+
const renamed = renameClass(original, state.postfix, new Set([original]));
|
|
730
|
+
const transformedString = env.types.stringLiteral(renamed);
|
|
731
|
+
path$8.replaceWith(transformedString);
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
ObjectProperty(path$8, state) {
|
|
735
|
+
if (!state.file.opts?.importedScopedClass) return;
|
|
736
|
+
if (path$8.node.value.type === "Identifier" && path$8.node.value.name === state.file.opts?.importedScopedClass) path$8.remove();
|
|
737
|
+
}
|
|
738
|
+
} };
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
//#endregion
|
|
742
|
+
//#region src/lib/css/utils.js
|
|
743
|
+
/**
|
|
744
|
+
* @param {string} css
|
|
745
|
+
* @return {string} hashed down version of the CSS for disambiguating
|
|
746
|
+
*/
|
|
747
|
+
function hash(css) {
|
|
748
|
+
return `css-${md5(css)}`;
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Attribute selectors are scoped with one of two strategies:
|
|
752
|
+
*
|
|
753
|
+
* - **renamed value**: class-targeting selectors whose value names real
|
|
754
|
+
* class(es) (`[class="foo"]`, `[class~="foo"]`) are scoped by renaming the
|
|
755
|
+
* value the same way `.foo` is renamed to `.foo_postfix`. The renamed token
|
|
756
|
+
* is unique per file, so nothing else is needed.
|
|
757
|
+
* - **postfix class**: every other attribute selector keeps its discriminator
|
|
758
|
+
* and is scoped by the generated postfix class — appended to the selector
|
|
759
|
+
* in the CSS and added to matching elements in the template (the same
|
|
760
|
+
* strategy bare tag selectors use: `div` becomes `div.postfix`).
|
|
761
|
+
*
|
|
762
|
+
* This predicate decides between the two. It is shared by the CSS rewrite
|
|
763
|
+
* (which renames the selector value) and by discovery in this file (which
|
|
764
|
+
* registers the value's class names for template renaming) so both sides
|
|
765
|
+
* always classify a selector the same way.
|
|
766
|
+
*
|
|
767
|
+
* @param {import('postcss-selector-parser').Attribute} node
|
|
768
|
+
* @returns {boolean}
|
|
769
|
+
*/
|
|
770
|
+
function isRenamedClassAttribute(node) {
|
|
771
|
+
return node.attribute === "class" && (node.operator === "=" || node.operator === "~=") && Boolean(node.value);
|
|
772
|
+
}
|
|
773
|
+
function isInsideGlobal(node, func) {
|
|
774
|
+
const parent = node.parent;
|
|
775
|
+
if (!parent) return false;
|
|
776
|
+
if (parent.type === "pseudo" && parent.value === ":global") return true;
|
|
777
|
+
return isInsideGlobal(parent, func);
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* @param {string} cssPath path to a CSS file
|
|
781
|
+
*/
|
|
782
|
+
function getCSSInfo(cssPath) {
|
|
783
|
+
if (!(0, fs.existsSync)(cssPath)) return null;
|
|
784
|
+
return getCSSContentInfo((0, fs.readFileSync)(cssPath, "utf8"));
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* We use this function to check each class used in the template
|
|
788
|
+
* to see if we need to leave it alone or transform it
|
|
789
|
+
*
|
|
790
|
+
* @param {string} css the CSS's contents
|
|
791
|
+
* @param {string} [lang] optional language hint (e.g. 'scss', 'sass', 'less')
|
|
792
|
+
* @return {{ classes: Set<string>, tags: Set<string>, attributes: Set<string>, css: string, id: string }}
|
|
793
|
+
*/
|
|
794
|
+
function getCSSContentInfo(css, lang) {
|
|
795
|
+
const classes = /* @__PURE__ */ new Set();
|
|
796
|
+
const tags = /* @__PURE__ */ new Set();
|
|
797
|
+
const attributes = /* @__PURE__ */ new Set();
|
|
798
|
+
const parseOptions = lang === "scss" || lang === "sass" ? { syntax: postcss_scss.default } : {};
|
|
799
|
+
const ast = postcss.default.parse(css, parseOptions);
|
|
800
|
+
const isScss = lang === "scss" || lang === "sass";
|
|
801
|
+
ast.walk((node) => {
|
|
802
|
+
if (node.type === "rule") collectSelectorInfo(isScss ? resolveNestedSassSelector(node) : node.selector, classes, tags, attributes);
|
|
803
|
+
});
|
|
804
|
+
return {
|
|
805
|
+
classes,
|
|
806
|
+
tags,
|
|
807
|
+
attributes,
|
|
808
|
+
css,
|
|
809
|
+
id: hash(css)
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Resolves a nested SCSS selector by substituting `&` with the fully-resolved
|
|
814
|
+
* parent selector, recursively. This converts e.g. `&--modifier` (child of
|
|
815
|
+
* `.block`) into `.block--modifier`, and handles arbitrary nesting depth so
|
|
816
|
+
* that `&--modifier` inside `&--modifier` inside `.block` yields
|
|
817
|
+
* `.block--modifier--modifier`.
|
|
818
|
+
*
|
|
819
|
+
* @param {import('postcss').Rule} node
|
|
820
|
+
* @return {string}
|
|
821
|
+
*/
|
|
822
|
+
function resolveNestedSassSelector(node) {
|
|
823
|
+
const { selector } = node;
|
|
824
|
+
if (!selector.includes("&")) return selector;
|
|
825
|
+
const parent = node.parent;
|
|
826
|
+
if (!parent || parent.type !== "rule") return selector;
|
|
827
|
+
const resolvedParent = resolveNestedSassSelector(parent);
|
|
828
|
+
return selector.replace(/&/g, resolvedParent);
|
|
829
|
+
}
|
|
830
|
+
function collectSelectorInfo(sel, classes, tags, attributes) {
|
|
831
|
+
const transform = (sls) => {
|
|
832
|
+
sls.walk((selector) => {
|
|
833
|
+
if (isInsideGlobal(selector)) return;
|
|
834
|
+
if (selector.type === "class") classes.add(selector.value);
|
|
835
|
+
else if (selector.type === "tag") tags.add(selector.value);
|
|
836
|
+
else if (selector.type === "attribute") if (isRenamedClassAttribute(selector)) for (let token of splitClassList(selector.value)) classes.add(token);
|
|
837
|
+
else attributes.add(selector.attribute.toLowerCase());
|
|
838
|
+
});
|
|
839
|
+
};
|
|
840
|
+
(0, postcss_selector_parser.default)(transform).processSync(sel);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
//#endregion
|
|
844
|
+
//#region src/lib/css/rewrite.js
|
|
845
|
+
const SEP$1 = "__";
|
|
846
|
+
function isRule(node) {
|
|
847
|
+
return node.type === "rule";
|
|
848
|
+
}
|
|
849
|
+
function isDeclaration(node) {
|
|
850
|
+
return node.type === "decl";
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* NOTE: "keyframes" is a singular definition, in that it's a block containing keyframes
|
|
854
|
+
* using `@keyframes {}` with only one thing on the inside doesn't make sense.
|
|
855
|
+
*/
|
|
856
|
+
function rewriteReferenceable(node, postfix) {
|
|
857
|
+
let originalName = node.params;
|
|
858
|
+
let postfixedName = node.params + SEP$1 + postfix;
|
|
859
|
+
node.params = postfixedName;
|
|
860
|
+
return {
|
|
861
|
+
originalName,
|
|
862
|
+
postfixedName
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Walk left and right from `node` within its compound selector (bounded by
|
|
867
|
+
* combinators) to see if the postfix class has already been added. Used to add
|
|
868
|
+
* the postfix class at most once per compound, e.g. `input[type="text"]`
|
|
869
|
+
* becomes `input.postfix[type="text"]`, not `input.postfix[type="text"].postfix`.
|
|
870
|
+
*/
|
|
871
|
+
function compoundHasPostfixClass(node, postfix) {
|
|
872
|
+
const siblings = node.parent.nodes;
|
|
873
|
+
const index = siblings.indexOf(node);
|
|
874
|
+
for (let i = index; i >= 0; i--) {
|
|
875
|
+
if (siblings[i].type === "combinator") break;
|
|
876
|
+
if (siblings[i].type === "class" && siblings[i].value === postfix) return true;
|
|
877
|
+
}
|
|
878
|
+
for (let i = index + 1; i < siblings.length; i++) {
|
|
879
|
+
if (siblings[i].type === "combinator") break;
|
|
880
|
+
if (siblings[i].type === "class" && siblings[i].value === postfix) return true;
|
|
881
|
+
}
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
function addPostfixClass(node, postfix) {
|
|
885
|
+
if (compoundHasPostfixClass(node, postfix)) return;
|
|
886
|
+
node.parent.insertAfter(node, postcss_selector_parser.default.className({ value: postfix }));
|
|
887
|
+
}
|
|
888
|
+
function rewriteSelector(sel, postfix) {
|
|
889
|
+
const transform = (selectors) => {
|
|
890
|
+
const needsPostfixClass = [];
|
|
891
|
+
selectors.walk((selector) => {
|
|
892
|
+
if (isInsideGlobal(selector)) return;
|
|
893
|
+
if (selector.type === "psuedo") return;
|
|
894
|
+
if (isNthOfType(selector)) return;
|
|
895
|
+
if (selector.type === "class") selector.value += "_" + postfix;
|
|
896
|
+
else if (selector.type === "tag") needsPostfixClass.push(selector);
|
|
897
|
+
else if (selector.type === "attribute") if (isRenamedClassAttribute(selector)) {
|
|
898
|
+
selector.value = renameClass(selector.value, postfix);
|
|
899
|
+
if (!selector.quoteMark) selector.quoteMark = "\"";
|
|
900
|
+
} else needsPostfixClass.push(selector);
|
|
901
|
+
});
|
|
902
|
+
for (const node of needsPostfixClass) addPostfixClass(node, postfix);
|
|
903
|
+
selectors.walk((selector) => {
|
|
904
|
+
if (selector.type === "pseudo" && selector.value === ":global") selector.replaceWith(...selector.nodes);
|
|
905
|
+
});
|
|
906
|
+
};
|
|
907
|
+
return (0, postcss_selector_parser.default)(transform).processSync(sel);
|
|
908
|
+
}
|
|
909
|
+
function isNthOfType(node) {
|
|
910
|
+
if (!node) return false;
|
|
911
|
+
return node.parent?.value === ":nth-of-type" || isNthOfType(node.parent);
|
|
912
|
+
}
|
|
913
|
+
function isInsideKeyframes(node) {
|
|
914
|
+
const parent = node.parent;
|
|
915
|
+
if (!parent) return false;
|
|
916
|
+
if (parent.type === "atrule" && parent.name === "keyframes") return true;
|
|
917
|
+
return isInsideKeyframes(parent);
|
|
918
|
+
}
|
|
919
|
+
function rewriteCss(css, postfix, fileName, layerName) {
|
|
920
|
+
const ast = postcss.default.parse(css);
|
|
921
|
+
/**
|
|
922
|
+
* kind => originalName => postfixedName
|
|
923
|
+
* @type {{ [kind: string]: { [originalName: string]: string }}}
|
|
924
|
+
*/
|
|
925
|
+
const referenceables = {
|
|
926
|
+
keyframes: {},
|
|
927
|
+
"counter-style": {},
|
|
928
|
+
"position-try": {},
|
|
929
|
+
property: {}
|
|
930
|
+
};
|
|
931
|
+
const availableReferenceables = new Set(Object.keys(referenceables));
|
|
932
|
+
function isReferenceable(node) {
|
|
933
|
+
if (node.type !== "atrule") return;
|
|
934
|
+
return availableReferenceables.has(node.name);
|
|
935
|
+
}
|
|
936
|
+
function updateDirectReferences(node) {
|
|
937
|
+
if (!node.value) return;
|
|
938
|
+
for (let [, map] of Object.entries(referenceables)) if (map[node.value]) node.value = map[node.value];
|
|
939
|
+
}
|
|
940
|
+
function updateShorthandContents(node) {
|
|
941
|
+
if (node.prop === "animation") {
|
|
942
|
+
let match = node.value.split(" ").filter((x) => referenceables.keyframes[x]);
|
|
943
|
+
if (match.length) match.forEach((x) => {
|
|
944
|
+
let replacement = referenceables.keyframes[x];
|
|
945
|
+
if (!replacement) return;
|
|
946
|
+
node.value = node.value.replace(x, replacement);
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
for (let [lookFor, replaceWith] of Object.entries(referenceables.property)) {
|
|
950
|
+
let lookForVar = `var(${lookFor})`;
|
|
951
|
+
let replaceWithVar = `var(${replaceWith})`;
|
|
952
|
+
node.value = node.value.replace(lookForVar, replaceWithVar);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* We have to do two passes:
|
|
957
|
+
* 1. postfix all the referenceable syntax
|
|
958
|
+
* 2. postfix as normal, but also checking values of CSS properties
|
|
959
|
+
* that could match postfixed referenceables from step 1
|
|
960
|
+
*/
|
|
961
|
+
ast.walk((node) => {
|
|
962
|
+
/**
|
|
963
|
+
* @keyframes, @counter-style, etc
|
|
964
|
+
*/
|
|
965
|
+
if (isReferenceable(node)) {
|
|
966
|
+
let name = node.name;
|
|
967
|
+
let { originalName, postfixedName } = rewriteReferenceable(node, postfix);
|
|
968
|
+
referenceables[name][originalName] = postfixedName;
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
ast.walk((node) => {
|
|
973
|
+
if (isDeclaration(node)) {
|
|
974
|
+
updateDirectReferences(node);
|
|
975
|
+
updateShorthandContents(node);
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
if (isRule(node)) {
|
|
979
|
+
/**
|
|
980
|
+
* The inner-contents of a keyframe are percentages, rather than selectors
|
|
981
|
+
*/
|
|
982
|
+
if (isInsideKeyframes(node)) return;
|
|
983
|
+
node.selector = rewriteSelector(node.selector, postfix);
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
const rewrittenCss = ast.toString();
|
|
988
|
+
return [
|
|
989
|
+
`/* ${fileName} */`,
|
|
990
|
+
layerName ? `@layer ${layerName} {` : "",
|
|
991
|
+
rewrittenCss.trimEnd(),
|
|
992
|
+
layerName ? `}` : ""
|
|
993
|
+
].filter(Boolean).join("\n") + "\n";
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
//#endregion
|
|
997
|
+
//#region src/lib/request.js
|
|
998
|
+
const KEY = "ember-scoped.css";
|
|
999
|
+
const SEP = "___";
|
|
1000
|
+
const request = {
|
|
1001
|
+
is: {
|
|
1002
|
+
inline(request$1) {
|
|
1003
|
+
return request$1.includes(KEY);
|
|
1004
|
+
},
|
|
1005
|
+
colocated(request$1) {
|
|
1006
|
+
return request$1.includes(".css?scoped=");
|
|
1007
|
+
}
|
|
1008
|
+
},
|
|
1009
|
+
inline: {
|
|
1010
|
+
create(cssHash, postfix, cssContents, lang) {
|
|
1011
|
+
let url = `./${postfix}${SEP}${cssHash}.${KEY}?css=${encodeURIComponent(cssContents)}`;
|
|
1012
|
+
if (lang) url += `&lang=${encodeURIComponent(lang)}`;
|
|
1013
|
+
return url;
|
|
1014
|
+
},
|
|
1015
|
+
decode(request$1) {
|
|
1016
|
+
let [left, qps] = request$1.split("?");
|
|
1017
|
+
left = left.slice(2).replace(`.${KEY}`, "");
|
|
1018
|
+
let [postfix, hash$2] = left.split(SEP);
|
|
1019
|
+
let search = new URLSearchParams(qps);
|
|
1020
|
+
return {
|
|
1021
|
+
hash: hash$2,
|
|
1022
|
+
postfix,
|
|
1023
|
+
css: search.get("css"),
|
|
1024
|
+
from: search.get("from"),
|
|
1025
|
+
lang: search.get("lang")
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
colocated: {
|
|
1030
|
+
create(cssHash, postfix, filePath) {
|
|
1031
|
+
return `./${node_path.default.basename(filePath)}?scoped=${postfix}&cssHash=${cssHash}`;
|
|
1032
|
+
},
|
|
1033
|
+
decode(request$1) {
|
|
1034
|
+
const [fileName, qs] = request$1.split("?");
|
|
1035
|
+
const search = new URLSearchParams(qs);
|
|
1036
|
+
return {
|
|
1037
|
+
fileName,
|
|
1038
|
+
cssHash: search.get("cssHash"),
|
|
1039
|
+
postfix: search.get("scoped")
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/build/unplugin-colocated.js
|
|
1047
|
+
const META$1 = "scoped-css:colocated";
|
|
1048
|
+
/** File extensions that Vite can preprocess via its CSS preprocessor pipeline */
|
|
1049
|
+
const PREPROCESSED_EXTENSIONS = new Set([
|
|
1050
|
+
".scss",
|
|
1051
|
+
".sass",
|
|
1052
|
+
".less",
|
|
1053
|
+
".styl",
|
|
1054
|
+
".stylus"
|
|
1055
|
+
]);
|
|
1056
|
+
/**
|
|
1057
|
+
* Plugin for supporting colocated styles
|
|
1058
|
+
*
|
|
1059
|
+
* e.g.:
|
|
1060
|
+
* src/components/my-component.js
|
|
1061
|
+
* src/components/my-component.css
|
|
1062
|
+
*/
|
|
1063
|
+
function colocated(options = {}) {
|
|
1064
|
+
const CWD$1 = process.cwd();
|
|
1065
|
+
/** @type {import('vite').ResolvedConfig | undefined} */
|
|
1066
|
+
let viteConfig;
|
|
1067
|
+
/** @type {((code: string, filename: string, config: unknown) => Promise<{ code: string }>) | undefined} */
|
|
1068
|
+
let preprocessCSS;
|
|
1069
|
+
/**
|
|
1070
|
+
*
|
|
1071
|
+
* @param {string} id the request id / what was imported
|
|
1072
|
+
* @param {string} filePath path on disk
|
|
1073
|
+
* @returns
|
|
1074
|
+
*/
|
|
1075
|
+
function buildResponse(id, filePath) {
|
|
1076
|
+
const parsed = request.colocated.decode(id);
|
|
1077
|
+
const relativeFilePath = node_path.default.relative(CWD$1, filePath);
|
|
1078
|
+
return {
|
|
1079
|
+
id: filePath,
|
|
1080
|
+
meta: { [META$1]: {
|
|
1081
|
+
postfix: parsed.postfix,
|
|
1082
|
+
fileName: relativeFilePath,
|
|
1083
|
+
fullPath: filePath
|
|
1084
|
+
} }
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
name: "ember-scoped-css:colocated",
|
|
1089
|
+
resolveId(id, importer) {
|
|
1090
|
+
if (request.is.colocated(id)) {
|
|
1091
|
+
const parsed = request.colocated.decode(id);
|
|
1092
|
+
return buildResponse(id, node_path.default.resolve(node_path.default.dirname(importer), node_path.default.basename(parsed.fileName)));
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
load(id) {
|
|
1096
|
+
const meta = this.getModuleInfo(id)?.meta?.[META$1];
|
|
1097
|
+
if (meta) {
|
|
1098
|
+
this.addWatchFile(meta.fullPath);
|
|
1099
|
+
return rewriteCss((0, node_fs.readFileSync)(meta.fullPath, "utf-8"), meta.postfix, meta.fileName, options.layerName);
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
vite: {
|
|
1103
|
+
async configResolved(config) {
|
|
1104
|
+
viteConfig = config;
|
|
1105
|
+
try {
|
|
1106
|
+
preprocessCSS = (await import((0, node_module.createRequire)(node_path.default.join(config.root, "package.json")).resolve("vite"))).preprocessCSS;
|
|
1107
|
+
} catch {}
|
|
1108
|
+
},
|
|
1109
|
+
async load(id) {
|
|
1110
|
+
if (request.is.colocated(id)) {
|
|
1111
|
+
const parsed = request.colocated.decode(id);
|
|
1112
|
+
let code = (0, node_fs.readFileSync)(parsed.fileName, "utf-8");
|
|
1113
|
+
let relativeFilePath = node_path.default.relative(CWD$1, parsed.fileName);
|
|
1114
|
+
const ext = node_path.default.extname(parsed.fileName).toLowerCase();
|
|
1115
|
+
if (PREPROCESSED_EXTENSIONS.has(ext)) {
|
|
1116
|
+
if (!viteConfig || !preprocessCSS) throw new Error(`[ember-scoped-css] Colocated CSS file with extension '${ext}' requires Vite. CSS preprocessing is only supported in Vite builds.`);
|
|
1117
|
+
code = (await preprocessCSS(code, parsed.fileName, viteConfig)).code;
|
|
1118
|
+
}
|
|
1119
|
+
return rewriteCss(code, parsed.postfix, relativeFilePath, options.layerName);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
//#endregion
|
|
1127
|
+
//#region src/build/unplugin-inline.js
|
|
1128
|
+
const META = "scoped-css:inline";
|
|
1129
|
+
/**
|
|
1130
|
+
* Plugin for supporting the styles from
|
|
1131
|
+
*
|
|
1132
|
+
* <template>
|
|
1133
|
+
* <style>...</style>
|
|
1134
|
+
* </template>
|
|
1135
|
+
*
|
|
1136
|
+
* This plugin can't have HMR for CSS because changes to the CSS content alters the template content
|
|
1137
|
+
*/
|
|
1138
|
+
function inline(options = {}) {
|
|
1139
|
+
const CWD$1 = process.cwd();
|
|
1140
|
+
/** @type {import('vite').ResolvedConfig | undefined} */
|
|
1141
|
+
let viteConfig;
|
|
1142
|
+
/** @type {((code: string, filename: string, config: unknown) => Promise<{ code: string }>) | undefined} */
|
|
1143
|
+
let preprocessCSS;
|
|
1144
|
+
/**
|
|
1145
|
+
* @param {string} id the request id / what was imported
|
|
1146
|
+
*/
|
|
1147
|
+
function buildResponse(id, filePath) {
|
|
1148
|
+
const parsed = request.inline.decode(id);
|
|
1149
|
+
const relativeFilePath = node_path.default.relative(CWD$1, filePath);
|
|
1150
|
+
return {
|
|
1151
|
+
id: filePath.split("?")[0],
|
|
1152
|
+
meta: { [META]: {
|
|
1153
|
+
rawCss: parsed.css,
|
|
1154
|
+
postfix: parsed.postfix,
|
|
1155
|
+
fileName: relativeFilePath,
|
|
1156
|
+
lang: parsed.lang
|
|
1157
|
+
} }
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
return {
|
|
1161
|
+
name: "ember-scoped-css:inline",
|
|
1162
|
+
resolveId(id, importer) {
|
|
1163
|
+
if (request.is.inline(id)) {
|
|
1164
|
+
const parsed = request.inline.decode(id);
|
|
1165
|
+
return buildResponse(id, node_path.default.resolve(node_path.default.dirname(importer), `${node_path.default.basename(importer, node_path.default.extname(importer))}-${parsed.hash}.css`));
|
|
1166
|
+
}
|
|
1167
|
+
},
|
|
1168
|
+
async load(id) {
|
|
1169
|
+
const meta = this.getModuleInfo(id)?.meta?.[META];
|
|
1170
|
+
if (meta) {
|
|
1171
|
+
let rawCss = meta.rawCss;
|
|
1172
|
+
if (meta.lang) {
|
|
1173
|
+
if (!viteConfig || !preprocessCSS) throw new Error(`[ember-scoped-css] <style scoped lang="${meta.lang}"> requires Vite. CSS preprocessing via the 'lang' attribute is only supported in Vite builds.`);
|
|
1174
|
+
const fakeFilename = `${meta.fileName}.${meta.lang}`;
|
|
1175
|
+
rawCss = (await preprocessCSS(rawCss, fakeFilename, viteConfig)).code;
|
|
1176
|
+
}
|
|
1177
|
+
return rewriteCss(rawCss, meta.postfix, `<inline>/${meta.fileName}`, options.layerName);
|
|
1178
|
+
}
|
|
1179
|
+
},
|
|
1180
|
+
vite: { async configResolved(config) {
|
|
1181
|
+
viteConfig = config;
|
|
1182
|
+
try {
|
|
1183
|
+
preprocessCSS = (await import((0, node_module.createRequire)(node_path.default.join(config.root, "package.json")).resolve("vite"))).preprocessCSS;
|
|
1184
|
+
} catch {}
|
|
1185
|
+
} }
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region src/build/scoped-css-unplugin.js
|
|
1191
|
+
/**
|
|
1192
|
+
* The plugin that handles CSS requests for `<style>` elements and transforms
|
|
1193
|
+
* for existing files
|
|
1194
|
+
*
|
|
1195
|
+
* vite: CSS files are resolved by vite. We use their resolver to also get
|
|
1196
|
+
* HMR. That is, for all non-physical CSS files, we extend vite by our
|
|
1197
|
+
* resolver and also can enrich metadata to it (for better debugging)
|
|
1198
|
+
*/
|
|
1199
|
+
const unplugin$1 = (0, unplugin.createUnplugin)((options = {}) => {
|
|
1200
|
+
return [colocated(options), inline(options)];
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
//#endregion
|
|
1204
|
+
//#region src/lib/path/template-transform-paths.js
|
|
1205
|
+
/**
|
|
1206
|
+
* template plugins do not hand us the correct file path.
|
|
1207
|
+
* additionally, we may not be able to rely on this data in the future,
|
|
1208
|
+
* so this functions acts as a means of normalizing _whatever_ we're given
|
|
1209
|
+
* in the future.
|
|
1210
|
+
*
|
|
1211
|
+
* @param {string} filename
|
|
1212
|
+
* @returns {string} the absolute path to the file
|
|
1213
|
+
*/
|
|
1214
|
+
function fixFilename(filename) {
|
|
1215
|
+
let fileName = filename;
|
|
1216
|
+
let workspace = findWorkspacePath(fileName);
|
|
1217
|
+
/**
|
|
1218
|
+
* ember-source 5.8:
|
|
1219
|
+
* - the filename looks like an absolute path, but swapped out the 'app' part of the path
|
|
1220
|
+
* with the module name, so the file paths never exist on disk
|
|
1221
|
+
*
|
|
1222
|
+
* - in vite apps:
|
|
1223
|
+
* the 'app' part _may_ be `src`, so we also need to ensure that `src` is excluded as well
|
|
1224
|
+
*/
|
|
1225
|
+
let hasAppDir = fileName.includes(node_path.default.join(workspace, "app"));
|
|
1226
|
+
let hasSrcDir = fileName.includes(node_path.default.join(workspace, "src"));
|
|
1227
|
+
if (!(hasAppDir || hasSrcDir) && !fileName.includes(leadingSlashPath.embroiderDir)) {
|
|
1228
|
+
let [maybeScope, ...rest] = fileName.replace(workspace, "").split(node_path.default.sep).filter(Boolean);
|
|
1229
|
+
let parts = rest;
|
|
1230
|
+
if (maybeScope.startsWith("@")) {
|
|
1231
|
+
let [, ...rester] = rest;
|
|
1232
|
+
parts = rester;
|
|
1233
|
+
}
|
|
1234
|
+
let relative = node_path.default.join(...parts);
|
|
1235
|
+
return node_path.default.join(workspace, "app", relative);
|
|
1236
|
+
}
|
|
1237
|
+
if (!fileName.includes(workspace)) return fileName;
|
|
1238
|
+
return fileName;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
//#endregion
|
|
1242
|
+
//#region src/lib/rewriteHbs.js
|
|
1243
|
+
/**
|
|
1244
|
+
* Whether an element may carry an attribute that appears in a scoped
|
|
1245
|
+
* attribute selector. This includes component invocations: a component
|
|
1246
|
+
* receives the postfix class through its `...attributes` the same way it
|
|
1247
|
+
* receives the matched attribute, so `[type="text"]` scopes
|
|
1248
|
+
* `<Foo type="text">` just as it scopes `<input type="text">`.
|
|
1249
|
+
*
|
|
1250
|
+
* An element that spreads `...attributes` can receive any attribute from its
|
|
1251
|
+
* caller at runtime, so it counts as long as the CSS scopes by attribute at
|
|
1252
|
+
* all — the preserved attribute selector still decides which rules actually
|
|
1253
|
+
* apply.
|
|
1254
|
+
*
|
|
1255
|
+
* `attributes` comes from parsing the CSS, so it can only contain valid
|
|
1256
|
+
* attribute-selector names — `@args` can never be in it and needs no special
|
|
1257
|
+
* handling.
|
|
1258
|
+
*
|
|
1259
|
+
* Names in `attributes` are lowercased at discovery (CSS matches HTML
|
|
1260
|
+
* attribute names case-insensitively), so compare lowercased.
|
|
1261
|
+
*/
|
|
1262
|
+
function elementHasScopedAttribute(node, attributes) {
|
|
1263
|
+
if (attributes.size === 0) return false;
|
|
1264
|
+
return node.attributes.some((attr) => attr.name === "...attributes" || attributes.has(attr.name.toLowerCase()));
|
|
1265
|
+
}
|
|
1266
|
+
function templatePlugin({ classes, tags, attributes, postfix }) {
|
|
1267
|
+
let stack = [];
|
|
1268
|
+
let scopedClassCandidates = ["scoped-class", "scopedClass"];
|
|
1269
|
+
function isScopedClass(str) {
|
|
1270
|
+
if (!str) return false;
|
|
1271
|
+
return scopedClassCandidates.some((candidate) => candidate === str);
|
|
1272
|
+
}
|
|
1273
|
+
return {
|
|
1274
|
+
AttrNode(node) {
|
|
1275
|
+
if (node.name === "class") {
|
|
1276
|
+
if (node.value.type === "TextNode" && node.value.chars) {
|
|
1277
|
+
const renamedClass = renameClass(node.value.chars, postfix, classes);
|
|
1278
|
+
node.value.chars = renamedClass;
|
|
1279
|
+
} else if (node.value.type === "ConcatStatement") {
|
|
1280
|
+
for (let part of node.value.parts) if (part.type === "TextNode" && part.chars) part.chars = renameClass(part.chars, postfix, classes);
|
|
1281
|
+
else if (part.type === "MustacheStatement") ember_template_recast.traverse(part, { StringLiteral(node$1) {
|
|
1282
|
+
node$1.value = renameClass(node$1.value, postfix, classes);
|
|
1283
|
+
} });
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
},
|
|
1287
|
+
ElementNode(node) {
|
|
1288
|
+
if (!(tags.has(node.tag) || elementHasScopedAttribute(node, attributes))) return;
|
|
1289
|
+
const classAttr = node.attributes.find((attr) => attr.name === "class");
|
|
1290
|
+
if (!classAttr) node.attributes.push(ember_template_recast.builders.attr("class", ember_template_recast.builders.text(postfix)));
|
|
1291
|
+
else if (classAttr.value.type === "TextNode") classAttr.value.chars += " " + postfix;
|
|
1292
|
+
else if (classAttr.value.type === "ConcatStatement") classAttr.value.parts.push(ember_template_recast.builders.text(" " + postfix));
|
|
1293
|
+
else {
|
|
1294
|
+
classAttr.value = ember_template_recast.builders.concat([classAttr.value, ember_template_recast.builders.text(" " + postfix)]);
|
|
1295
|
+
classAttr.quoteType = "\"";
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
All: {
|
|
1299
|
+
enter(node) {
|
|
1300
|
+
stack.push(node);
|
|
1301
|
+
},
|
|
1302
|
+
exit() {
|
|
1303
|
+
stack.pop();
|
|
1304
|
+
}
|
|
1305
|
+
},
|
|
1306
|
+
MustacheStatement(node) {
|
|
1307
|
+
let cssClass;
|
|
1308
|
+
if (isScopedClass(getValue(node.path)) && node.params?.length === 1 && node.params[0].type === "StringLiteral") cssClass = node.params[0].value;
|
|
1309
|
+
if (isScopedClass(getValue(node.path?.path)) && node.path?.params?.length === 1 && node.path?.params[0].type === "StringLiteral") cssClass = node.path.params[0].value;
|
|
1310
|
+
if (cssClass) {
|
|
1311
|
+
const textNode = ember_template_recast.builders.text(renameClass(cssClass, postfix));
|
|
1312
|
+
const parent = stack[stack.length - 1];
|
|
1313
|
+
if (parent?.type === "AttrNode") parent.quoteType = "\"";
|
|
1314
|
+
return textNode;
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
SubExpression(node) {
|
|
1318
|
+
if (isScopedClass(getValue(node.path)) && node.params?.length === 1 && node.params[0].type === "StringLiteral") {
|
|
1319
|
+
const cssClass = node.params[0].value;
|
|
1320
|
+
return ember_template_recast.builders.literal("StringLiteral", renameClass(cssClass, postfix));
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
function getValue(path$8) {
|
|
1326
|
+
if (!path$8) return;
|
|
1327
|
+
if ("value" in path$8) return path$8.value;
|
|
1328
|
+
/**
|
|
1329
|
+
* Deprecated in ember 5.9+
|
|
1330
|
+
* (so we use the above for newer embers)
|
|
1331
|
+
*/
|
|
1332
|
+
return path$8.original;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region src/build/template-plugin.js
|
|
1337
|
+
const noopPlugin = {
|
|
1338
|
+
name: "ember-scoped-css:noop",
|
|
1339
|
+
visitor: {}
|
|
1340
|
+
};
|
|
1341
|
+
/**
|
|
1342
|
+
* @returns {ASTPlugin}
|
|
1343
|
+
*/
|
|
1344
|
+
function createPlugin(config) {
|
|
1345
|
+
/**
|
|
1346
|
+
*
|
|
1347
|
+
* @param {ASTPluginEnvironment} env
|
|
1348
|
+
*/
|
|
1349
|
+
return function scopedCss(env) {
|
|
1350
|
+
let cwd = node_process.default.cwd();
|
|
1351
|
+
if (!isRelevantFile(env.filename, {
|
|
1352
|
+
additionalRoots: config.additionalRoots,
|
|
1353
|
+
cwd
|
|
1354
|
+
})) return noopPlugin;
|
|
1355
|
+
let absolutePath = fixFilename(env.filename);
|
|
1356
|
+
let postfix = hashFromModulePath(appPath(absolutePath));
|
|
1357
|
+
/**
|
|
1358
|
+
* The list of naked tag selectors found in the CSS
|
|
1359
|
+
*
|
|
1360
|
+
* @type {Set<string>}
|
|
1361
|
+
*/
|
|
1362
|
+
let scopedTags = /* @__PURE__ */ new Set();
|
|
1363
|
+
/**
|
|
1364
|
+
* The list of classes found in the CSS
|
|
1365
|
+
*
|
|
1366
|
+
* @type {Set<string>}
|
|
1367
|
+
*/
|
|
1368
|
+
let scopedClasses = /* @__PURE__ */ new Set();
|
|
1369
|
+
/**
|
|
1370
|
+
* The attribute names found in attribute selectors in the CSS, used to
|
|
1371
|
+
* mark matching elements with the scope class.
|
|
1372
|
+
*
|
|
1373
|
+
* @type {Set<string>}
|
|
1374
|
+
*/
|
|
1375
|
+
let scopedAttributes = /* @__PURE__ */ new Set();
|
|
1376
|
+
/**
|
|
1377
|
+
* @param {{ tags: Set<string>; classes: Set<string>; attributes: Set<string> }} info
|
|
1378
|
+
*/
|
|
1379
|
+
function addInfo(info$1) {
|
|
1380
|
+
for (let item of info$1.tags) scopedTags.add(item);
|
|
1381
|
+
for (let item of info$1.classes) scopedClasses.add(item);
|
|
1382
|
+
for (let item of info$1.attributes) scopedAttributes.add(item);
|
|
1383
|
+
}
|
|
1384
|
+
let cssPath = cssPathFor(absolutePath);
|
|
1385
|
+
let info = getCSSInfo(cssPath);
|
|
1386
|
+
let localCssPath = forcePosix(cssPath.replace(cwd + node_path.default.sep, ""));
|
|
1387
|
+
/**
|
|
1388
|
+
* This will be falsey if we don't have a co-located CSS file.
|
|
1389
|
+
* We'll still want to check for embedded <style scoped> tags though.
|
|
1390
|
+
*/
|
|
1391
|
+
if (info) {
|
|
1392
|
+
addInfo(info);
|
|
1393
|
+
let cssRequest = request.colocated.create(info.id, postfix, localCssPath);
|
|
1394
|
+
/**
|
|
1395
|
+
* With this we don't need a JS plugin
|
|
1396
|
+
*/
|
|
1397
|
+
env.meta.jsutils.importForSideEffect(cssRequest);
|
|
1398
|
+
}
|
|
1399
|
+
let visitors = templatePlugin({
|
|
1400
|
+
classes: scopedClasses,
|
|
1401
|
+
tags: scopedTags,
|
|
1402
|
+
attributes: scopedAttributes,
|
|
1403
|
+
postfix
|
|
1404
|
+
});
|
|
1405
|
+
return {
|
|
1406
|
+
name: "ember-scoped-css:template-plugin",
|
|
1407
|
+
visitor: {
|
|
1408
|
+
...visitors,
|
|
1409
|
+
Template(node) {
|
|
1410
|
+
/**
|
|
1411
|
+
* We only allow a scoped <style> at the root
|
|
1412
|
+
*/
|
|
1413
|
+
let styleTag = node.body.find((n) => n.type === "ElementNode" && n.tag === "style");
|
|
1414
|
+
if (hasScopedAttribute(styleTag)) {
|
|
1415
|
+
let css = textContent(styleTag);
|
|
1416
|
+
let lang = getLangAttribute(styleTag);
|
|
1417
|
+
let info$1 = getCSSContentInfo(css, lang);
|
|
1418
|
+
addInfo(info$1);
|
|
1419
|
+
if (hasInlineAttributeWithoutLang(styleTag))
|
|
1420
|
+
/**
|
|
1421
|
+
* This will be handled in ElementNode traversal
|
|
1422
|
+
*/
|
|
1423
|
+
return;
|
|
1424
|
+
if (lang)
|
|
1425
|
+
/**
|
|
1426
|
+
* For <style scoped inline lang="..."> we cannot preprocess at Babel-time
|
|
1427
|
+
* (preprocessing is async and requires Vite's ResolvedConfig).
|
|
1428
|
+
* Remove the tag and inject via virtual CSS module and warn user.
|
|
1429
|
+
*/
|
|
1430
|
+
console.warn(`[ember-scoped-css] <style scoped inline lang="${lang}"> is not supported (preprocessing is async and cannot run at Babel-time). Downgrading to non-inline: the style tag will be removed and injected as a virtual CSS module.`);
|
|
1431
|
+
let cssRequest = request.inline.create(info$1.id, postfix, css, lang);
|
|
1432
|
+
env.meta.jsutils.importForSideEffect(cssRequest);
|
|
1433
|
+
}
|
|
1434
|
+
},
|
|
1435
|
+
AttrNode(...args) {
|
|
1436
|
+
return visitors.AttrNode(...args);
|
|
1437
|
+
},
|
|
1438
|
+
ElementNode(node, walker) {
|
|
1439
|
+
visitors.ElementNode(node, walker);
|
|
1440
|
+
if (hasScopedAttribute(node)) {
|
|
1441
|
+
if (walker.parent?.node.type !== "Template") throw new Error("<style scoped> tags must be at the root of the template, they cannot be nested");
|
|
1442
|
+
if (hasInlineAttributeWithoutLang(node)) {
|
|
1443
|
+
let scopedText = rewriteCss(textContent(node), postfix, localCssPath, config.layerName);
|
|
1444
|
+
/**
|
|
1445
|
+
* Traverse this and allow interpolation
|
|
1446
|
+
*/
|
|
1447
|
+
node.children = [env.syntax.builders.text(scopedText)];
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
return null;
|
|
1451
|
+
}
|
|
1452
|
+
if (hasInlineAttributeWithoutLang(node)) throw new Error(`<style inline> is not valid. Please add the scoped attribute: <style scoped inline>`);
|
|
1453
|
+
},
|
|
1454
|
+
MustacheStatement(...args) {
|
|
1455
|
+
return visitors.MustacheStatement(...args);
|
|
1456
|
+
},
|
|
1457
|
+
SubExpression(...args) {
|
|
1458
|
+
return visitors.SubExpression(...args);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Thanks, CardStack and @ef4 for this code.
|
|
1466
|
+
*/
|
|
1467
|
+
const SCOPED_ATTRIBUTE_NAME = "scoped";
|
|
1468
|
+
const INLINE_ATTRIBUTE_NAME = "inline";
|
|
1469
|
+
const LANG_ATTRIBUTE_NAME = "lang";
|
|
1470
|
+
function hasScopedAttribute(node) {
|
|
1471
|
+
if (!node) return;
|
|
1472
|
+
if (node.tag !== "style") return;
|
|
1473
|
+
if (node.type !== "ElementNode") return;
|
|
1474
|
+
return node.attributes.some((attribute) => attribute.name === SCOPED_ATTRIBUTE_NAME);
|
|
1475
|
+
}
|
|
1476
|
+
function hasInlineAttributeWithoutLang(node) {
|
|
1477
|
+
if (!node) return;
|
|
1478
|
+
if (node.tag !== "style") return;
|
|
1479
|
+
if (node.type !== "ElementNode") return;
|
|
1480
|
+
if (getLangAttribute(node)) return false;
|
|
1481
|
+
return node.attributes.some((attribute) => attribute.name === INLINE_ATTRIBUTE_NAME);
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Returns the value of the `lang` attribute on a `<style>` node, or null if absent.
|
|
1485
|
+
*
|
|
1486
|
+
* @param {object} node
|
|
1487
|
+
* @returns {string | null}
|
|
1488
|
+
*/
|
|
1489
|
+
function getLangAttribute(node) {
|
|
1490
|
+
if (!node) return null;
|
|
1491
|
+
if (node.tag !== "style") return null;
|
|
1492
|
+
if (node.type !== "ElementNode") return null;
|
|
1493
|
+
const attr = node.attributes.find((attribute) => attribute.name === LANG_ATTRIBUTE_NAME);
|
|
1494
|
+
if (!attr) return null;
|
|
1495
|
+
const value = attr.value;
|
|
1496
|
+
if (value?.type === "TextNode") return value.chars || null;
|
|
1497
|
+
return null;
|
|
1498
|
+
}
|
|
1499
|
+
function textContent(node) {
|
|
1500
|
+
return node.children.filter((c) => c.type === "TextNode").map((c) => c.chars).join("");
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
//#endregion
|
|
1504
|
+
//#region src/build/public-exports/all.js
|
|
1505
|
+
const scopedCSS = {
|
|
1506
|
+
vite: unplugin$1.vite,
|
|
1507
|
+
rollup: unplugin$1.rollup,
|
|
1508
|
+
babel: scopedCSS$1,
|
|
1509
|
+
template: createPlugin
|
|
1510
|
+
};
|
|
1511
|
+
|
|
1512
|
+
//#endregion
|
|
1513
|
+
Object.defineProperty(exports, 'scopedCSS', {
|
|
1514
|
+
enumerable: true,
|
|
1515
|
+
get: function () {
|
|
1516
|
+
return scopedCSS;
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1519
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsLUJJN0xPU3VULmNqcyIsIm5hbWVzIjpbImhhc2giLCJoYXNoIiwiaGFzaEZyb21Nb2R1bGVQYXRoIiwiaGFzaFBvc2l4TW9kdWxlUGF0aCIsInBhdGgiLCJmc1N5bmMiLCJzY29wZWRDU1MiLCJwYXRoIiwic2Nzc1N5bnRheCIsIlNFUCIsInBhcnNlciIsInJlcXVlc3QiLCJoYXNoIiwicGF0aCIsIk1FVEEiLCJDV0QiLCJwYXRoIiwiQ1dEIiwicGF0aCIsInVucGx1Z2luIiwicGF0aCIsIm5vZGUiLCJyZWNhc3QiLCJwYXRoIiwicHJvY2VzcyIsImluZm8iLCJwYXRoIiwidW5wbHVnaW4iLCJiYWJlbC5zY29wZWRDU1MiLCJ0ZW1wbGF0ZS5jcmVhdGVQbHVnaW4iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3BhdGgvY29uc3QuanMiLCIuLi8uLi9zcmMvbGliL3BhdGgvbWQ1LmpzIiwiLi4vLi4vc3JjL2xpYi9wYXRoL2hhc2gtZnJvbS1tb2R1bGUtcGF0aC5qcyIsIi4uLy4uL3NyYy9saWIvcGF0aC91dGlscy5qcyIsIi4uLy4uL3NyYy9saWIvcmVuYW1lQ2xhc3MuanMiLCIuLi8uLi9zcmMvYnVpbGQvYmFiZWwtcGx1Z2luLmpzIiwiLi4vLi4vc3JjL2xpYi9jc3MvdXRpbHMuanMiLCIuLi8uLi9zcmMvbGliL2Nzcy9yZXdyaXRlLmpzIiwiLi4vLi4vc3JjL2xpYi9yZXF1ZXN0LmpzIiwiLi4vLi4vc3JjL2J1aWxkL3VucGx1Z2luLWNvbG9jYXRlZC5qcyIsIi4uLy4uL3NyYy9idWlsZC91bnBsdWdpbi1pbmxpbmUuanMiLCIuLi8uLi9zcmMvYnVpbGQvc2NvcGVkLWNzcy11bnBsdWdpbi5qcyIsIi4uLy4uL3NyYy9saWIvcGF0aC90ZW1wbGF0ZS10cmFuc2Zvcm0tcGF0aHMuanMiLCIuLi8uLi9zcmMvbGliL3Jld3JpdGVIYnMuanMiLCIuLi8uLi9zcmMvYnVpbGQvdGVtcGxhdGUtcGx1Z2luLmpzIiwiLi4vLi4vc3JjL2J1aWxkL3B1YmxpYy1leHBvcnRzL2FsbC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcblxuLyoqXG4gKiBKb2luIHdpbGwgY29udmVydCB0byB3aGF0ZXZlciBpcyBhcHByb3ByaWF0ZSBmcm8gdGhlIGN1cnJlbnQgcGxhdGZvcm1cbiAqL1xuXG5leHBvcnQgY29uc3QgbGVhZGluZ1NsYXNoUGF0aCA9IHtcbiAgZW1icm9pZGVyRGlyOiBwYXRoLmpvaW4oJy9ub2RlX21vZHVsZXMvLmVtYnJvaWRlci8nKSxcbiAgYXRFbWJyb2lkZXI6IHBhdGguam9pbignL0BlbWJyb2lkZXInKSxcbiAgY29tcG9uZW50c0RpcjogcGF0aC5qb2luKCcvY29tcG9uZW50cy8nKSxcbiAgdGVtcGxhdGVzRGlyOiBwYXRoLmpvaW4oJy90ZW1wbGF0ZXMvJyksXG4gIHJvdXRlc0RpcjogcGF0aC5qb2luKCcvcm91dGVzLycpLFxuICB0ZXN0ZW06IHBhdGguam9pbignL3Rlc3RlbScpLFxuICBzcmM6IHBhdGguam9pbignL3NyYy8nKSxcbiAgYXBwOiBwYXRoLmpvaW4oJy9hcHAvJyksXG59O1xuXG5leHBvcnQgY29uc3QgYmFyZVBhdGggPSB7XG4gIHBucG1EaXI6IHBhdGguam9pbignbm9kZV9tb2R1bGVzLy5wbnBtJyksXG59O1xuIiwiLypcbiAqIEphdmFTY3JpcHQgTUQ1XG4gKiBodHRwczovL2dpdGh1Yi5jb20vYmx1ZWltcC9KYXZhU2NyaXB0LU1ENVxuICpcbiAqIENvcHlyaWdodCAyMDExLCBTZWJhc3RpYW4gVHNjaGFuXG4gKiBodHRwczovL2JsdWVpbXAubmV0XG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlOlxuICogaHR0cHM6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVRcbiAqXG4gKiBCYXNlZCBvblxuICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBSU0EgRGF0YSBTZWN1cml0eSwgSW5jLiBNRDUgTWVzc2FnZVxuICogRGlnZXN0IEFsZ29yaXRobSwgYXMgZGVmaW5lZCBpbiBSRkMgMTMyMS5cbiAqIFZlcnNpb24gMi4yIENvcHlyaWdodCAoQykgUGF1bCBKb2huc3RvbiAxOTk5IC0gMjAwOVxuICogT3RoZXIgY29udHJpYnV0b3JzOiBHcmVnIEhvbHQsIEFuZHJldyBLZXBlcnQsIFlkbmFyLCBMb3N0aW5ldFxuICogRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIEJTRCBMaWNlbnNlXG4gKiBTZWUgaHR0cDovL3BhamhvbWUub3JnLnVrL2NyeXB0L21kNSBmb3IgbW9yZSBpbmZvLlxuICpcbiAqIE1vZGlmaWNhdGlvbnM6XG4gKiAtIHJlbW92ZWQgSUlGRSwgZXhwb3J0ZWQgbWQ1ICh0aGlzIGZpbGUgaXMgbm93IEVTTSlcbiAqL1xuXG4vKipcbiAqIEFkZCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi5cbiAqIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9ucyBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gaW50ZXJwcmV0ZXJzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IEZpcnN0IGludGVnZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFNlY29uZCBpbnRlZ2VyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBTdW1cbiAqL1xuZnVuY3Rpb24gc2FmZUFkZCh4LCB5KSB7XG4gIHZhciBsc3cgPSAoeCAmIDB4ZmZmZikgKyAoeSAmIDB4ZmZmZik7XG4gIHZhciBtc3cgPSAoeCA+PiAxNikgKyAoeSA+PiAxNikgKyAobHN3ID4+IDE2KTtcblxuICByZXR1cm4gKG1zdyA8PCAxNikgfCAobHN3ICYgMHhmZmZmKTtcbn1cblxuLyoqXG4gKiBCaXR3aXNlIHJvdGF0ZSBhIDMyLWJpdCBudW1iZXIgdG8gdGhlIGxlZnQuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG51bSAzMi1iaXQgbnVtYmVyXG4gKiBAcGFyYW0ge251bWJlcn0gY250IFJvdGF0aW9uIGNvdW50XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSb3RhdGVkIG51bWJlclxuICovXG5mdW5jdGlvbiBiaXRSb3RhdGVMZWZ0KG51bSwgY250KSB7XG4gIHJldHVybiAobnVtIDw8IGNudCkgfCAobnVtID4+PiAoMzIgLSBjbnQpKTtcbn1cblxuLyoqXG4gKiBCYXNpYyBvcGVyYXRpb24gdGhlIGFsZ29yaXRobSB1c2VzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBxIHFcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIGJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSBzIHNcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJlc3VsdFxuICovXG5mdW5jdGlvbiBtZDVjbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuICByZXR1cm4gc2FmZUFkZChiaXRSb3RhdGVMZWZ0KHNhZmVBZGQoc2FmZUFkZChhLCBxKSwgc2FmZUFkZCh4LCB0KSksIHMpLCBiKTtcbn1cblxuLyoqXG4gKiBCYXNpYyBvcGVyYXRpb24gdGhlIGFsZ29yaXRobSB1c2VzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIGJcbiAqIEBwYXJhbSB7bnVtYmVyfSBjIGNcbiAqIEBwYXJhbSB7bnVtYmVyfSBkIGRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSBzIHNcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJlc3VsdFxuICovXG5mdW5jdGlvbiBtZDVmZihhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBtZDVjbW4oKGIgJiBjKSB8ICh+YiAmIGQpLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuLyoqXG4gKiBCYXNpYyBvcGVyYXRpb24gdGhlIGFsZ29yaXRobSB1c2VzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIGJcbiAqIEBwYXJhbSB7bnVtYmVyfSBjIGNcbiAqIEBwYXJhbSB7bnVtYmVyfSBkIGRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSBzIHNcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJlc3VsdFxuICovXG5mdW5jdGlvbiBtZDVnZyhhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBtZDVjbW4oKGIgJiBkKSB8IChjICYgfmQpLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuLyoqXG4gKiBCYXNpYyBvcGVyYXRpb24gdGhlIGFsZ29yaXRobSB1c2VzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIGJcbiAqIEBwYXJhbSB7bnVtYmVyfSBjIGNcbiAqIEBwYXJhbSB7bnVtYmVyfSBkIGRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSBzIHNcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJlc3VsdFxuICovXG5mdW5jdGlvbiBtZDVoaChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBtZDVjbW4oYiBeIGMgXiBkLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuLyoqXG4gKiBCYXNpYyBvcGVyYXRpb24gdGhlIGFsZ29yaXRobSB1c2VzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIGJcbiAqIEBwYXJhbSB7bnVtYmVyfSBjIGNcbiAqIEBwYXJhbSB7bnVtYmVyfSBkIGRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSBzIHNcbiAqIEBwYXJhbSB7bnVtYmVyfSB0IHRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJlc3VsdFxuICovXG5mdW5jdGlvbiBtZDVpaShhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBtZDVjbW4oYyBeIChiIHwgfmQpLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIE1ENSBvZiBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzLCBhbmQgYSBiaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IHggQXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3Jkc1xuICogQHBhcmFtIHtudW1iZXJ9IGxlbiBCaXQgbGVuZ3RoXG4gKiBAcmV0dXJucyB7QXJyYXk8bnVtYmVyPn0gTUQ1IEFycmF5XG4gKi9cbmZ1bmN0aW9uIGJpbmxNRDUoeCwgbGVuKSB7XG4gIC8qIGFwcGVuZCBwYWRkaW5nICovXG4gIHhbbGVuID4+IDVdIHw9IDB4ODAgPDwgbGVuICUgMzI7XG4gIHhbKCgobGVuICsgNjQpID4+PiA5KSA8PCA0KSArIDE0XSA9IGxlbjtcblxuICB2YXIgaTtcbiAgdmFyIG9sZGE7XG4gIHZhciBvbGRiO1xuICB2YXIgb2xkYztcbiAgdmFyIG9sZGQ7XG4gIHZhciBhID0gMTczMjU4NDE5MztcbiAgdmFyIGIgPSAtMjcxNzMzODc5O1xuICB2YXIgYyA9IC0xNzMyNTg0MTk0O1xuICB2YXIgZCA9IDI3MTczMzg3ODtcblxuICBmb3IgKGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkgKz0gMTYpIHtcbiAgICBvbGRhID0gYTtcbiAgICBvbGRiID0gYjtcbiAgICBvbGRjID0gYztcbiAgICBvbGRkID0gZDtcblxuICAgIGEgPSBtZDVmZihhLCBiLCBjLCBkLCB4W2ldLCA3LCAtNjgwODc2OTM2KTtcbiAgICBkID0gbWQ1ZmYoZCwgYSwgYiwgYywgeFtpICsgMV0sIDEyLCAtMzg5NTY0NTg2KTtcbiAgICBjID0gbWQ1ZmYoYywgZCwgYSwgYiwgeFtpICsgMl0sIDE3LCA2MDYxMDU4MTkpO1xuICAgIGIgPSBtZDVmZihiLCBjLCBkLCBhLCB4W2kgKyAzXSwgMjIsIC0xMDQ0NTI1MzMwKTtcbiAgICBhID0gbWQ1ZmYoYSwgYiwgYywgZCwgeFtpICsgNF0sIDcsIC0xNzY0MTg4OTcpO1xuICAgIGQgPSBtZDVmZihkLCBhLCBiLCBjLCB4W2kgKyA1XSwgMTIsIDEyMDAwODA0MjYpO1xuICAgIGMgPSBtZDVmZihjLCBkLCBhLCBiLCB4W2kgKyA2XSwgMTcsIC0xNDczMjMxMzQxKTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgN10sIDIyLCAtNDU3MDU5ODMpO1xuICAgIGEgPSBtZDVmZihhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNywgMTc3MDAzNTQxNik7XG4gICAgZCA9IG1kNWZmKGQsIGEsIGIsIGMsIHhbaSArIDldLCAxMiwgLTE5NTg0MTQ0MTcpO1xuICAgIGMgPSBtZDVmZihjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE3LCAtNDIwNjMpO1xuICAgIGIgPSBtZDVmZihiLCBjLCBkLCBhLCB4W2kgKyAxMV0sIDIyLCAtMTk5MDQwNDE2Mik7XG4gICAgYSA9IG1kNWZmKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNywgMTgwNDYwMzY4Mik7XG4gICAgZCA9IG1kNWZmKGQsIGEsIGIsIGMsIHhbaSArIDEzXSwgMTIsIC00MDM0MTEwMSk7XG4gICAgYyA9IG1kNWZmKGMsIGQsIGEsIGIsIHhbaSArIDE0XSwgMTcsIC0xNTAyMDAyMjkwKTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgMTVdLCAyMiwgMTIzNjUzNTMyOSk7XG5cbiAgICBhID0gbWQ1Z2coYSwgYiwgYywgZCwgeFtpICsgMV0sIDUsIC0xNjU3OTY1MTApO1xuICAgIGQgPSBtZDVnZyhkLCBhLCBiLCBjLCB4W2kgKyA2XSwgOSwgLTEwNjk1MDE2MzIpO1xuICAgIGMgPSBtZDVnZyhjLCBkLCBhLCBiLCB4W2kgKyAxMV0sIDE0LCA2NDM3MTc3MTMpO1xuICAgIGIgPSBtZDVnZyhiLCBjLCBkLCBhLCB4W2ldLCAyMCwgLTM3Mzg5NzMwMik7XG4gICAgYSA9IG1kNWdnKGEsIGIsIGMsIGQsIHhbaSArIDVdLCA1LCAtNzAxNTU4NjkxKTtcbiAgICBkID0gbWQ1Z2coZCwgYSwgYiwgYywgeFtpICsgMTBdLCA5LCAzODAxNjA4Myk7XG4gICAgYyA9IG1kNWdnKGMsIGQsIGEsIGIsIHhbaSArIDE1XSwgMTQsIC02NjA0NzgzMzUpO1xuICAgIGIgPSBtZDVnZyhiLCBjLCBkLCBhLCB4W2kgKyA0XSwgMjAsIC00MDU1Mzc4NDgpO1xuICAgIGEgPSBtZDVnZyhhLCBiLCBjLCBkLCB4W2kgKyA5XSwgNSwgNTY4NDQ2NDM4KTtcbiAgICBkID0gbWQ1Z2coZCwgYSwgYiwgYywgeFtpICsgMTRdLCA5LCAtMTAxOTgwMzY5MCk7XG4gICAgYyA9IG1kNWdnKGMsIGQsIGEsIGIsIHhbaSArIDNdLCAxNCwgLTE4NzM2Mzk2MSk7XG4gICAgYiA9IG1kNWdnKGIsIGMsIGQsIGEsIHhbaSArIDhdLCAyMCwgMTE2MzUzMTUwMSk7XG4gICAgYSA9IG1kNWdnKGEsIGIsIGMsIGQsIHhbaSArIDEzXSwgNSwgLTE0NDQ2ODE0NjcpO1xuICAgIGQgPSBtZDVnZyhkLCBhLCBiLCBjLCB4W2kgKyAyXSwgOSwgLTUxNDAzNzg0KTtcbiAgICBjID0gbWQ1Z2coYywgZCwgYSwgYiwgeFtpICsgN10sIDE0LCAxNzM1MzI4NDczKTtcbiAgICBiID0gbWQ1Z2coYiwgYywgZCwgYSwgeFtpICsgMTJdLCAyMCwgLTE5MjY2MDc3MzQpO1xuXG4gICAgYSA9IG1kNWhoKGEsIGIsIGMsIGQsIHhbaSArIDVdLCA0LCAtMzc4NTU4KTtcbiAgICBkID0gbWQ1aGgoZCwgYSwgYiwgYywgeFtpICsgOF0sIDExLCAtMjAyMjU3NDQ2Myk7XG4gICAgYyA9IG1kNWhoKGMsIGQsIGEsIGIsIHhbaSArIDExXSwgMTYsIDE4MzkwMzA1NjIpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyAxNF0sIDIzLCAtMzUzMDk1NTYpO1xuICAgIGEgPSBtZDVoaChhLCBiLCBjLCBkLCB4W2kgKyAxXSwgNCwgLTE1MzA5OTIwNjApO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2kgKyA0XSwgMTEsIDEyNzI4OTMzNTMpO1xuICAgIGMgPSBtZDVoaChjLCBkLCBhLCBiLCB4W2kgKyA3XSwgMTYsIC0xNTU0OTc2MzIpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyAxMF0sIDIzLCAtMTA5NDczMDY0MCk7XG4gICAgYSA9IG1kNWhoKGEsIGIsIGMsIGQsIHhbaSArIDEzXSwgNCwgNjgxMjc5MTc0KTtcbiAgICBkID0gbWQ1aGgoZCwgYSwgYiwgYywgeFtpXSwgMTEsIC0zNTg1MzcyMjIpO1xuICAgIGMgPSBtZDVoaChjLCBkLCBhLCBiLCB4W2kgKyAzXSwgMTYsIC03MjI1MjE5NzkpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyA2XSwgMjMsIDc2MDI5MTg5KTtcbiAgICBhID0gbWQ1aGgoYSwgYiwgYywgZCwgeFtpICsgOV0sIDQsIC02NDAzNjQ0ODcpO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2kgKyAxMl0sIDExLCAtNDIxODE1ODM1KTtcbiAgICBjID0gbWQ1aGgoYywgZCwgYSwgYiwgeFtpICsgMTVdLCAxNiwgNTMwNzQyNTIwKTtcbiAgICBiID0gbWQ1aGgoYiwgYywgZCwgYSwgeFtpICsgMl0sIDIzLCAtOTk1MzM4NjUxKTtcblxuICAgIGEgPSBtZDVpaShhLCBiLCBjLCBkLCB4W2ldLCA2LCAtMTk4NjMwODQ0KTtcbiAgICBkID0gbWQ1aWkoZCwgYSwgYiwgYywgeFtpICsgN10sIDEwLCAxMTI2ODkxNDE1KTtcbiAgICBjID0gbWQ1aWkoYywgZCwgYSwgYiwgeFtpICsgMTRdLCAxNSwgLTE0MTYzNTQ5MDUpO1xuICAgIGIgPSBtZDVpaShiLCBjLCBkLCBhLCB4W2kgKyA1XSwgMjEsIC01NzQzNDA1NSk7XG4gICAgYSA9IG1kNWlpKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNiwgMTcwMDQ4NTU3MSk7XG4gICAgZCA9IG1kNWlpKGQsIGEsIGIsIGMsIHhbaSArIDNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xuICAgIGMgPSBtZDVpaShjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE1LCAtMTA1MTUyMyk7XG4gICAgYiA9IG1kNWlpKGIsIGMsIGQsIGEsIHhbaSArIDFdLCAyMSwgLTIwNTQ5MjI3OTkpO1xuICAgIGEgPSBtZDVpaShhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNiwgMTg3MzMxMzM1OSk7XG4gICAgZCA9IG1kNWlpKGQsIGEsIGIsIGMsIHhbaSArIDE1XSwgMTAsIC0zMDYxMTc0NCk7XG4gICAgYyA9IG1kNWlpKGMsIGQsIGEsIGIsIHhbaSArIDZdLCAxNSwgLTE1NjAxOTgzODApO1xuICAgIGIgPSBtZDVpaShiLCBjLCBkLCBhLCB4W2kgKyAxM10sIDIxLCAxMzA5MTUxNjQ5KTtcbiAgICBhID0gbWQ1aWkoYSwgYiwgYywgZCwgeFtpICsgNF0sIDYsIC0xNDU1MjMwNzApO1xuICAgIGQgPSBtZDVpaShkLCBhLCBiLCBjLCB4W2kgKyAxMV0sIDEwLCAtMTEyMDIxMDM3OSk7XG4gICAgYyA9IG1kNWlpKGMsIGQsIGEsIGIsIHhbaSArIDJdLCAxNSwgNzE4Nzg3MjU5KTtcbiAgICBiID0gbWQ1aWkoYiwgYywgZCwgYSwgeFtpICsgOV0sIDIxLCAtMzQzNDg1NTUxKTtcblxuICAgIGEgPSBzYWZlQWRkKGEsIG9sZGEpO1xuICAgIGIgPSBzYWZlQWRkKGIsIG9sZGIpO1xuICAgIGMgPSBzYWZlQWRkKGMsIG9sZGMpO1xuICAgIGQgPSBzYWZlQWRkKGQsIG9sZGQpO1xuICB9XG5cbiAgcmV0dXJuIFthLCBiLCBjLCBkXTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMgdG8gYSBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGlucHV0IE1ENSBBcnJheVxuICogQHJldHVybnMge3N0cmluZ30gTUQ1IHN0cmluZ1xuICovXG5mdW5jdGlvbiBiaW5sMnJzdHIoaW5wdXQpIHtcbiAgdmFyIGk7XG4gIHZhciBvdXRwdXQgPSAnJztcbiAgdmFyIGxlbmd0aDMyID0gaW5wdXQubGVuZ3RoICogMzI7XG5cbiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDMyOyBpICs9IDgpIHtcbiAgICBvdXRwdXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoaW5wdXRbaSA+PiA1XSA+Pj4gaSAlIDMyKSAmIDB4ZmYpO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgcmF3IHN0cmluZyB0byBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzXG4gKiBDaGFyYWN0ZXJzID4yNTUgaGF2ZSB0aGVpciBoaWdoLWJ5dGUgc2lsZW50bHkgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQgUmF3IGlucHV0IHN0cmluZ1xuICogQHJldHVybnMge0FycmF5PG51bWJlcj59IEFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHNcbiAqL1xuZnVuY3Rpb24gcnN0cjJiaW5sKGlucHV0KSB7XG4gIHZhciBpO1xuICB2YXIgb3V0cHV0ID0gW107XG4gIG91dHB1dFsoaW5wdXQubGVuZ3RoID4+IDIpIC0gMV0gPSB1bmRlZmluZWQ7XG5cbiAgZm9yIChpID0gMDsgaSA8IG91dHB1dC5sZW5ndGg7IGkgKz0gMSkge1xuICAgIG91dHB1dFtpXSA9IDA7XG4gIH1cblxuICB2YXIgbGVuZ3RoOCA9IGlucHV0Lmxlbmd0aCAqIDg7XG5cbiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDg7IGkgKz0gOCkge1xuICAgIG91dHB1dFtpID4+IDVdIHw9IChpbnB1dC5jaGFyQ29kZUF0KGkgLyA4KSAmIDB4ZmYpIDw8IGkgJSAzMjtcbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSBNRDUgb2YgYSByYXcgc3RyaW5nXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHMgSW5wdXQgc3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSYXcgTUQ1IHN0cmluZ1xuICovXG5mdW5jdGlvbiByc3RyTUQ1KHMpIHtcbiAgcmV0dXJuIGJpbmwycnN0cihiaW5sTUQ1KHJzdHIyYmlubChzKSwgcy5sZW5ndGggKiA4KSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgSE1BQy1NRDUgb2YgYSBrZXkgYW5kIHNvbWUgZGF0YSAocmF3IHN0cmluZ3MpXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBITUFDIGtleVxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgUmF3IGlucHV0IHN0cmluZ1xuICogQHJldHVybnMge3N0cmluZ30gUmF3IE1ENSBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gcnN0ckhNQUNNRDUoa2V5LCBkYXRhKSB7XG4gIHZhciBpO1xuICB2YXIgYmtleSA9IHJzdHIyYmlubChrZXkpO1xuICB2YXIgaXBhZCA9IFtdO1xuICB2YXIgb3BhZCA9IFtdO1xuICB2YXIgaGFzaDtcbiAgaXBhZFsxNV0gPSBvcGFkWzE1XSA9IHVuZGVmaW5lZDtcblxuICBpZiAoYmtleS5sZW5ndGggPiAxNikge1xuICAgIGJrZXkgPSBiaW5sTUQ1KGJrZXksIGtleS5sZW5ndGggKiA4KTtcbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCAxNjsgaSArPSAxKSB7XG4gICAgaXBhZFtpXSA9IGJrZXlbaV0gXiAweDM2MzYzNjM2O1xuICAgIG9wYWRbaV0gPSBia2V5W2ldIF4gMHg1YzVjNWM1YztcbiAgfVxuXG4gIGhhc2ggPSBiaW5sTUQ1KGlwYWQuY29uY2F0KHJzdHIyYmlubChkYXRhKSksIDUxMiArIGRhdGEubGVuZ3RoICogOCk7XG5cbiAgcmV0dXJuIGJpbmwycnN0cihiaW5sTUQ1KG9wYWQuY29uY2F0KGhhc2gpLCA1MTIgKyAxMjgpKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgcmF3IHN0cmluZyB0byBhIGhleCBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQgUmF3IGlucHV0IHN0cmluZ1xuICogQHJldHVybnMge3N0cmluZ30gSGV4IGVuY29kZWQgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHJzdHIyaGV4KGlucHV0KSB7XG4gIHZhciBoZXhUYWIgPSAnMDEyMzQ1Njc4OWFiY2RlZic7XG4gIHZhciBvdXRwdXQgPSAnJztcbiAgdmFyIHg7XG4gIHZhciBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkgKz0gMSkge1xuICAgIHggPSBpbnB1dC5jaGFyQ29kZUF0KGkpO1xuICAgIG91dHB1dCArPSBoZXhUYWIuY2hhckF0KCh4ID4+PiA0KSAmIDB4MGYpICsgaGV4VGFiLmNoYXJBdCh4ICYgMHgwZik7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufVxuXG4vKipcbiAqIEVuY29kZSBhIHN0cmluZyBhcyBVVEYtOFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dCBJbnB1dCBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFVURjggc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHN0cjJyc3RyVVRGOChpbnB1dCkge1xuICByZXR1cm4gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KGlucHV0KSk7XG59XG5cbi8qKlxuICogRW5jb2RlcyBpbnB1dCBzdHJpbmcgYXMgcmF3IE1ENSBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcyBJbnB1dCBzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJhdyBNRDUgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHJhd01ENShzKSB7XG4gIHJldHVybiByc3RyTUQ1KHN0cjJyc3RyVVRGOChzKSk7XG59XG5cbi8qKlxuICogRW5jb2RlcyBpbnB1dCBzdHJpbmcgYXMgSGV4IGVuY29kZWQgc3RyaW5nXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHMgSW5wdXQgc3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBIZXggZW5jb2RlZCBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gaGV4TUQ1KHMpIHtcbiAgcmV0dXJuIHJzdHIyaGV4KHJhd01ENShzKSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgcmF3IEhNQUMtTUQ1IGZvciB0aGUgZ2l2ZW4ga2V5IGFuZCBkYXRhXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGsgSE1BQyBrZXlcbiAqIEBwYXJhbSB7c3RyaW5nfSBkIElucHV0IHN0cmluZ1xuICogQHJldHVybnMge3N0cmluZ30gUmF3IE1ENSBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gcmF3SE1BQ01ENShrLCBkKSB7XG4gIHJldHVybiByc3RySE1BQ01ENShzdHIycnN0clVURjgoayksIHN0cjJyc3RyVVRGOChkKSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgSGV4IGVuY29kZWQgSE1BQy1NRDUgZm9yIHRoZSBnaXZlbiBrZXkgYW5kIGRhdGFcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gayBITUFDIGtleVxuICogQHBhcmFtIHtzdHJpbmd9IGQgSW5wdXQgc3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSYXcgTUQ1IHN0cmluZ1xuICovXG5mdW5jdGlvbiBoZXhITUFDTUQ1KGssIGQpIHtcbiAgcmV0dXJuIHJzdHIyaGV4KHJhd0hNQUNNRDUoaywgZCkpO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgTUQ1IHZhbHVlIGZvciBhIGdpdmVuIHN0cmluZy5cbiAqIElmIGEga2V5IGlzIHByb3ZpZGVkLCBjYWxjdWxhdGVzIHRoZSBITUFDLU1ENSB2YWx1ZS5cbiAqIFJldHVybnMgYSBIZXggZW5jb2RlZCBzdHJpbmcgdW5sZXNzIHRoZSByYXcgYXJndW1lbnQgaXMgZ2l2ZW4uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBJbnB1dCBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSBITUFDIGtleVxuICogQHBhcmFtIHtib29sZWFufSBbcmF3XSBSYXcgb3V0cHV0IHN3aXRjaFxuICogQHJldHVybnMge3N0cmluZ30gTUQ1IG91dHB1dFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWQ1KHN0cmluZywga2V5LCByYXcpIHtcbiAgaWYgKCFrZXkpIHtcbiAgICBpZiAoIXJhdykge1xuICAgICAgcmV0dXJuIGhleE1ENShzdHJpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiByYXdNRDUoc3RyaW5nKTtcbiAgfVxuXG4gIGlmICghcmF3KSB7XG4gICAgcmV0dXJuIGhleEhNQUNNRDUoa2V5LCBzdHJpbmcpO1xuICB9XG5cbiAgcmV0dXJuIHJhd0hNQUNNRDUoa2V5LCBzdHJpbmcpO1xufVxuIiwiaW1wb3J0IHsgbWQ1IH0gZnJvbSAnLi9tZDUuanMnO1xuXG4vKipcbiAqIFRoZSBpbnRlbnQgb2YgdGhpcyBmdW5jdGlvbiBpcyB0byBnZW5lcmF0ZSB0aGUgc3VmZml4L3Bvc3RmaXggZm9yIHRoZVxuICogY3NzIGNsYXNzZXMsIGJhc2VkIG9uIHRoZSBtb2R1bGUtc2NvcGVkIHBhdGggbmFtZS5cbiAqXG4gKiBmb3IgZXhhbXBsZSxcbiAqICAgIGhhc2goJ215LWFwcC9jb21wb25lbnRzL2ZvbycpXG4gKiAgaW5zdGVhZCBvZlxuICogICAgaGFzaCgnYXBwL2NvbXBvbmVudHMvZm9vJylcbiAqXG4gKiAgKHVubGVzcyB5b3VyIGFwcCBuYW1lIGlzICdhcHAnKVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2R1bGVQYXRoXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaChtb2R1bGVQYXRoKSB7XG4gIHJldHVybiAnZScgKyBtZDUobW9kdWxlUGF0aCkuc3Vic3RyaW5nKDAsIDgpO1xufVxuXG5pZiAoaW1wb3J0Lm1ldGEudml0ZXN0KSB7XG4gIGNvbnN0IHsgaXQsIGV4cGVjdCB9ID0gaW1wb3J0Lm1ldGEudml0ZXN0O1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHBvc3RmaXggPSBoYXNoKCdmb28uY3NzJyk7XG5cbiAgICBleHBlY3QocG9zdGZpeCkudG8uYmUuYSgnc3RyaW5nJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgc3RyaW5nIHN0YXJ0aW5nIHdpdGggXCJlXCInLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcG9zdGZpeCA9IGhhc2goJ2Zvby5jc3MnKTtcblxuICAgIGV4cGVjdChwb3N0Zml4KS50by5tYXRjaCgvXmUvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSBzdHJpbmcgb2YgbGVuZ3RoIDknLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcG9zdGZpeCA9IGhhc2goJ2Zvby5jc3MnKTtcblxuICAgIGV4cGVjdChwb3N0Zml4KS50by5oYXZlLmxlbmd0aE9mKDkpO1xuICB9KTtcbn1cblxuZXhwb3J0IGNvbnN0IGhhc2hGcm9tTW9kdWxlUGF0aCA9IGhhc2g7XG4iLCJpbXBvcnQgYXNzZXJ0IGZyb20gJ25vZGU6YXNzZXJ0JztcbmltcG9ydCBmc1N5bmMsIHsgZXhpc3RzU3luYyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5cbmltcG9ydCB7IGJhcmVQYXRoLCBsZWFkaW5nU2xhc2hQYXRoIH0gZnJvbSAnLi9jb25zdC5qcyc7XG5pbXBvcnQgeyBoYXNoRnJvbUFic29sdXRlUGF0aCB9IGZyb20gJy4vaGFzaC1mcm9tLWFic29sdXRlLXBhdGguanMnO1xuaW1wb3J0IHsgaGFzaEZyb21Nb2R1bGVQYXRoIGFzIGhhc2hQb3NpeE1vZHVsZVBhdGggfSBmcm9tICcuL2hhc2gtZnJvbS1tb2R1bGUtcGF0aC5qcyc7XG5cbmV4cG9ydCB7IGhhc2hGcm9tQWJzb2x1dGVQYXRoIH0gZnJvbSAnLi9oYXNoLWZyb20tYWJzb2x1dGUtcGF0aC5qcyc7XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aFxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hGcm9tTW9kdWxlUGF0aChmaWxlUGF0aCkge1xuICBsZXQgcG9zaXhQYXRoID0gZm9yY2VQb3NpeChmaWxlUGF0aCk7XG5cbiAgcmV0dXJuIGhhc2hQb3NpeE1vZHVsZVBhdGgocG9zaXhQYXRoKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcmNlUG9zaXgoZmlsZVBhdGgpIHtcbiAgY29uc3QgcGFyc2VkID0gcGF0aC5wYXJzZShmaWxlUGF0aCk7XG5cbiAgaWYgKHBhcnNlZC5yb290ID09PSAnJykge1xuICAgIHJldHVybiBmaWxlUGF0aC5yZXBsYWNlQWxsKHBhdGgud2luMzIuc2VwLCBwYXRoLnBvc2l4LnNlcCk7XG4gIH1cblxuICBsZXQgcm9vdGxlc3MgPSBmaWxlUGF0aC5yZXBsYWNlKFxuICAgIG5ldyBSZWdFeHAoYF4ke1JlZ0V4cC5lc2NhcGUocGFyc2VkLnJvb3QpfWApLFxuICAgIHBhdGgucG9zaXguc2VwLFxuICApO1xuXG4gIHJldHVybiByb290bGVzcy5yZXBsYWNlQWxsKHBhdGgud2luMzIuc2VwLCBwYXRoLnBvc2l4LnNlcCk7XG59XG5cbmNvbnN0IENPTVBPTkVOVF9FWFRFTlNJT05TID0gWycuZ3RzJywgJy5nanMnLCAnLnRzJywgJy5qcycsICcuaGJzJ107XG5cbi8vIENKUyAvIEVTTT9cbmxldCBoZXJlID0gaW1wb3J0Lm1ldGEudXJsO1xubGV0IG91clJlcXVpcmUgPSBnbG9iYWxUaGlzLnJlcXVpcmVcbiAgPyBnbG9iYWxUaGlzLnJlcXVpcmVcbiAgOiBoZXJlICYmIGNyZWF0ZVJlcXVpcmUoaGVyZSk7XG5cbmlmICghb3VyUmVxdWlyZSkge1xuICBvdXJSZXF1aXJlID0gcmVxdWlyZTtcbn1cblxuY29uc3QgSVJSRUxFVkFOVF9QQVRIUyA9IFtiYXJlUGF0aC5wbnBtRGlyLCAnX192aXRlLSddO1xuY29uc3QgVU5TVVBQT1JURURfRElSRUNUT1JJRVMgPSBuZXcgU2V0KFsndGVzdHMnXSk7XG5cbmNvbnN0IENXRCA9IHByb2Nlc3MuY3dkKCk7XG5cbi8qKlxuICogUmVnYXJkbGVzcyBvZiB3aGF0IHRoZSBmaWxlUGF0aCBmb3JtYXQgaXMsXG4gKiB0aGlzIHdpbGwgdHJ5IHRvIHJldHVybiB0aGUgY29ycmVjdCBwb3N0Zml4LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hGcm9tKGZpbGVQYXRoKSB7XG4gIGlmIChwYXRoLmlzQWJzb2x1dGUoZmlsZVBhdGgpKSB7XG4gICAgcmV0dXJuIGhhc2hGcm9tQWJzb2x1dGVQYXRoKGZpbGVQYXRoKTtcbiAgfVxuXG4gIHJldHVybiBoYXNoRnJvbU1vZHVsZVBhdGgoZmlsZVBhdGgpO1xufVxuXG4vKipcbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjc3NIYXNBc3NvY2lhdGVkQ29tcG9uZW50KGNzc1BhdGgpIHtcbiAgcmV0dXJuIGNzc0hhc1N0YW5kYXJkRmlsZShjc3NQYXRoKSB8fCBjc3NIYXNQb2RzRmlsZShjc3NQYXRoKTtcbn1cblxuZnVuY3Rpb24gY3NzSGFzU3RhbmRhcmRGaWxlKGlkKSB7XG4gIC8qKlxuICAgKiBOb3JtYWxseSB3ZSBkb24ndCBuZWVkIHRvIGNoZWNrIGEgSlMgcGF0aCBoZXJlLCBidXQgd2hlbiB1c2luZ1xuICAgKiBlbWJyb2lkZXJAMywgd2UgaGF2ZSBhIFwicmV3cml0dGVuIGFwcFwiLCB3aGljaCBoYXMgYWxsIG91ciBzb3VyY2VcbiAgICogcHJlcHJvY2Vzc2VkIGEgYml0IGJlZm9yZSBzY29wZWQtY3NzIHRyYW5zZm9ybWF0aW9ucy5cbiAgICpcbiAgICogKEluIFZpdGUsIHdlIG9wZXJhdGUgbW9yZSBkaXJlY3RseSB3aXRoIHRoZSBzb3VyY2UpXG4gICAqL1xuICBmb3IgKGxldCBleHQgb2YgQ09NUE9ORU5UX0VYVEVOU0lPTlMpIHtcbiAgICBsZXQgY2FuZGlkYXRlUGF0aCA9IGlkLnJlcGxhY2UoL1xcLmNzcyQvLCBleHQpO1xuXG4gICAgaWYgKGV4aXN0c1N5bmMoY2FuZGlkYXRlUGF0aCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gY3NzSGFzUG9kc0ZpbGUoaWQpIHtcbiAgaWYgKCFpZC5lbmRzV2l0aCgnc3R5bGVzLmNzcycpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGx5IHdlIGRvbid0IG5lZWQgdG8gY2hlY2sgYSBKUyBwYXRoIGhlcmUsIGJ1dCB3aGVuIHVzaW5nXG4gICAqIGVtYnJvaWRlckAzLCB3ZSBoYXZlIGEgXCJyZXdyaXR0ZW4gYXBwXCIsIHdoaWNoIGhhcyBhbGwgb3VyIHNvdXJjZVxuICAgKiBwcmVwcm9jZXNzZWQgYSBiaXQgYmVmb3JlIHNjb3BlZC1jc3MgdHJhbnNmb3JtYXRpb25zLlxuICAgKlxuICAgKiAoSW4gVml0ZSwgd2Ugb3BlcmF0ZSBtb3JlIGRpcmVjdGx5IHdpdGggdGhlIHNvdXJjZSlcbiAgICovXG4gIGZvciAobGV0IGV4dCBvZiBDT01QT05FTlRfRVhURU5TSU9OUykge1xuICAgIGxldCBjYW5kaWRhdGVQYXRoID0gaWQucmVwbGFjZSgvc3R5bGVzXFwuY3NzJC8sIGB0ZW1wbGF0ZSR7ZXh0fWApO1xuXG4gICAgaWYgKGV4aXN0c1N5bmMoY2FuZGlkYXRlUGF0aCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBCYXNlZCBvbiBlbWJlcidzIGNvbXBvbmVudCBsb2NhdGlvbiBjb252ZW50aW9ucyxcbiAqIHRoaXMgZnVuY3Rpb24gd2lsbCBwcm92aWRlIGEgcGF0aCBmb3Igd2hlcmUgd2VcbiAqIGV4cGVjdCB0aGUgQ1NTIHRvIGxpdmUuXG4gKlxuICogRm9yIGNvLWxvY2F0ZWQgc3RydWN0dXJlOlxuICogICAtIGNvbXBvbmVudHMvbXktY29tcG9uZW50Lmhic1xuICogICAtIGNvbXBvbmVudHMvbXktY29tcG9uZW50LmNzc1xuICpcbiAqIEZvciBuZXN0ZWQgY28tbG9jYXRlZCBzdHJ1Y3R1cmVcbiAqICAgLSBjb21wb25lbnRzL215LWNvbXBvbmVudC9mb28uaGJzXG4gKiAgIC0gY29tcG9uZW50cy9teS1jb21wb25lbnQvZm9vLmNzc1xuICpcbiAqIEZvciBQb2RzIHJvdXRlcyBzdHJ1Y3R1cmVcbiAqICAgLSByb3V0ZXMvbXktcm91dGUvdGVtcGxhdGUue2hicyxqc31cbiAqICAgLSByb3V0ZXMvbXktcm91dGUvc3R5bGVzLmNzc1xuICpcbiAqIERlbGliZXJhdGVseSBub3Qgc3VwcG9ydGVkOlxuICogICAtIGNvbXBvbmVudHMgdy8gcG9kcyAtLSB0aGlzIGlzIGRlcHJlY2F0ZWQgaW4gNS4xMFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlTmFtZSAtIHRoZSBoYnMsIGpzLCBnanMsIGd0cyBvciB3aGF0ZXZlciBjby1sb2NhdGVkIHBhdGguXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGV4cGVjdGVkIGNzcyBwYXRoXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjc3NQYXRoRm9yKGZpbGVOYW1lKSB7XG4gIGxldCB3aXRob3V0RXh0ID0gd2l0aG91dEV4dGVuc2lvbihmaWxlTmFtZSk7XG4gIGxldCBjc3NQYXRoID0gd2l0aG91dEV4dCArICcuY3NzJztcblxuICBpZiAoaXNQb2QoZmlsZU5hbWUpKSB7XG4gICAgY3NzUGF0aCA9IGZpbGVOYW1lXG4gICAgICAucmVwbGFjZSgvdGVtcGxhdGVcXC5qcyQvLCAnc3R5bGVzLmNzcycpXG4gICAgICAucmVwbGFjZSgvdGVtcGxhdGVcXC5nanMvLCAnc3R5bGVzLmNzcycpXG4gICAgICAucmVwbGFjZSgvdGVtcGxhdGVcXC5ndHMvLCAnc3R5bGVzLmNzcycpXG4gICAgICAucmVwbGFjZSgvdGVtcGxhdGVcXC5oYnMvLCAnc3R5bGVzLmNzcycpO1xuICB9XG5cbiAgcmV0dXJuIGNzc1BhdGg7XG59XG5cbi8qKlxuICogTm90ZSB0aGF0IGNvbXBvbmVudHMgaW4gdGhlIFwicG9kc1wiIGNvbnZlbnRpb24gd2lsbFxuICogbmV2ZXIgYmUgc3VwcG9ydGVkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQb2RUZW1wbGF0ZShmaWxlUGF0aCkge1xuICBpZiAoZmlsZVBhdGguaW5jbHVkZXMobGVhZGluZ1NsYXNoUGF0aC5jb21wb25lbnRzRGlyKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgZmlsZVBhdGguZW5kc1dpdGgoJ3RlbXBsYXRlLmpzJykgfHxcbiAgICBmaWxlUGF0aC5lbmRzV2l0aCgndGVtcGxhdGUuaGJzJykgfHxcbiAgICBmaWxlUGF0aC5lbmRzV2l0aCgndGVtcGxhdGUuZ2pzJykgfHxcbiAgICBmaWxlUGF0aC5lbmRzV2l0aCgndGVtcGxhdGUuZ3RzJylcbiAgKTtcbn1cblxuLyoqXG4gKiBOb3RlIHRoYXQgY29tcG9uZW50cyBpbiB0aGUgXCJwb2RzXCIgY29udmVudGlvbiB3aWxsXG4gKiBuZXZlciBiZSBzdXBwb3J0ZWQuXG4gKlxuICogQ2hlY2tzIGlmIGEgZmlsZSBlbmRzIHdpdGhcbiAqIC0gdGVtcGxhdGUuanNcbiAqIC0gdGVtcGxhdGUuaGJzXG4gKiAtIHN0eWxlcy5jc3NcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUG9kKGZpbGVQYXRoKSB7XG4gIGlmIChmaWxlUGF0aC5pbmNsdWRlcyhsZWFkaW5nU2xhc2hQYXRoLmNvbXBvbmVudHNEaXIpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGlzUG9kVGVtcGxhdGUoZmlsZVBhdGgpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmlsZVBhdGguZW5kc1dpdGgoJ3N0eWxlcy5jc3MnKTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVQYXRoXG4gKiBAcmV0dXJucyB0aGUgc2FtZSBwYXRoLCBidXQgd2l0aG91dCB0aGUgZXh0ZW5zaW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRob3V0RXh0ZW5zaW9uKGZpbGVQYXRoKSB7XG4gIGxldCBwYXJzZWQgPSBwYXRoLnBhcnNlKGZpbGVQYXRoKTtcblxuICByZXR1cm4gcGF0aC5qb2luKHBhcnNlZC5kaXIsIHBhcnNlZC5uYW1lKTtcbn1cblxuLyoqXG4gKiBFeGFtcGxlcyBmb3IgZmlsZU5hbWVcbiAqIC0gYWJzb2x1dGUgb24tZGlzayBwYXRoXG4gKiAtIGluIHdlYnBhY2tcbiAqICAgLSBVUkwtYWJzb2x1dGUgcGF0aCwgc3RhcnRpbmcgd2l0aCAvXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVOYW1lXG4gKiBAcGFyYW0ge3sgYWRkaXRpb25hbFJvb3RzPzogc3RyaW5nW107IGN3ZDogc3RyaW5nIH19IG9wdGlvbnNcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1JlbGV2YW50RmlsZShmaWxlTmFtZSwgeyBhZGRpdGlvbmFsUm9vdHMsIGN3ZCB9KSB7XG4gIC8vIEZha2UgZmlsZSBoYW5kbGVkIGJ5IHRlc3RlbSBzZXJ2ZXIgd2hlbiBpdCBydW5zXG4gIGlmIChmaWxlTmFtZS5zdGFydHNXaXRoKGxlYWRpbmdTbGFzaFBhdGgudGVzdGVtKSkgcmV0dXJuIGZhbHNlO1xuICAvLyBQcml2YXRlIFZpcnR1YWwgTW9kdWxlc1xuICBpZiAoZmlsZU5hbWUuc3RhcnRzV2l0aCgnXFwwJykpIHJldHVybiBmYWxzZTtcblxuICAvLyBUaGVzZSBhcmUgbm90IHZhbGlkIHVzZXJsYW5kIG5hbWVzIChvciBhcmUgZnJvbSBsaWJyYXJpZXMpXG4gIGlmIChwYXRoLmlzQWJzb2x1dGUoZmlsZU5hbWUpID09PSBmYWxzZSkge1xuICAgIGlmIChmaWxlTmFtZS5tYXRjaCgvXlthLXpBLVpdLykpIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIEV4dGVybmFsIHRvIHVzXG4gIGlmIChmaWxlTmFtZS5zdGFydHNXaXRoKGxlYWRpbmdTbGFzaFBhdGguYXRFbWJyb2lkZXIpKSByZXR1cm4gZmFsc2U7XG4gIGlmIChJUlJFTEVWQU5UX1BBVEhTLnNvbWUoKGkpID0+IGZpbGVOYW1lLmluY2x1ZGVzKGkpKSkgcmV0dXJuIGZhbHNlO1xuXG4gIGxldCB3b3Jrc3BhY2UgPSBmaW5kV29ya3NwYWNlUGF0aChmaWxlTmFtZSk7XG5cbiAgYXNzZXJ0KGN3ZCwgYGN3ZCB3YXMgbm90IHBhc3NlZCB0byBpc1JlbGV2YW50RmlsZWApO1xuXG4gIGxldCBvdXJXb3Jrc3BhY2UgPSBmaW5kV29ya3NwYWNlUGF0aChjd2QpO1xuXG4gIGlmICh3b3Jrc3BhY2UgIT09IG91cldvcmtzcGFjZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBsb2NhbCA9IGZpbGVOYW1lLnJlcGxhY2Uod29ya3NwYWNlLCAnJyk7XG4gIGxldCBbLCAuLi5wYXJ0c10gPSBsb2NhbC5zcGxpdChwYXRoLnNlcCkuZmlsdGVyKEJvb2xlYW4pO1xuXG4gIGlmIChVTlNVUFBPUlRFRF9ESVJFQ1RPUklFUy5oYXMocGFydHNbMF0pKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vc3RseSBwb2RzIHN1cHBvcnQuXG4gICAqIGZvbGtzIG5lZWQgdG8gb3B0IGluIHRvIHBvZHMgKHJvdXRlcyksIGJlY2F1c2UgZXZlcnkgcG9kcyBhcHAgY2FuIGJlIGNvbmZpZ3VyZWQgZGlmZmVyZW50bHlcbiAgICovXG4gIGxldCByb290cyA9IFtcbiAgICBsZWFkaW5nU2xhc2hQYXRoLmNvbXBvbmVudHNEaXIsXG4gICAgbGVhZGluZ1NsYXNoUGF0aC50ZW1wbGF0ZXNEaXIsXG4gICAgbGVhZGluZ1NsYXNoUGF0aC5yb3V0ZXNEaXIsXG4gICAgLi4uKGFkZGl0aW9uYWxSb290cyB8fCBbXSksXG4gIF07XG5cbiAgaWYgKCFyb290cy5zb21lKChyb290KSA9PiBmaWxlTmFtZS5pbmNsdWRlcyhyb290KSkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhY2thZ2VTY29wZWRQYXRoVG9Nb2R1bGVQYXRoKHBhY2thZ2VTY29wZWRQYXRoKSB7XG4gIC8qKlxuICAgKiAqQnkgY29udmVudGlvbiosIGBzcmNgIGlzIG9taXR0ZWQgZnJvbSBjb21wb25lbnQgcGF0aHMuXG4gICAqIFdlIGNhbiByZWZsZWN0IHRoZSBzYW1lIGJlaGF2aW9yIGJ5IHJlcGxhY2luZyBzcmMvXG4gICAqIHdpdGggYW4gZW1wdHkgc3RyaW5nLlxuICAgKlxuICAgKiBDU1MgaXNuJ3QgZW1pdHRlZCBhcyBhIGNvLWxvY2F0ZWQgbW9kdWxlLCBidXRcbiAgICogdG8ga2VlcCBjb252ZW50aW9ucyBjb25zaXN0ZW50IGFjcm9zcyBsYW5ndWFnZXMsXG4gICAqIHdlIGNhbiBwcmV0ZW5kIGl0IGlzLlxuICAgKlxuICAgKiBBbnkgY3VzdG9taXphdGlvbiBiZXlvbmQgcmVtb3ZpbmcgYHNyY2AgYW5kIGBhcHBgIGlzIHBvdGVudGlhbGx5IGNvbmZ1c2luZy5cbiAgICogSWYgd2UgbmVlZCBmdXJ0aGVyIGN1c3RvbWl6YXRpb25zLCB3ZSdsbCB3YW50IHRvIG1hdGNoIG9uIGBleHBvcnRzYCBpbiB0aGVcbiAgICogY29ycmVzcG9uZGluZyBwYWNrYWdlLmpzb25cbiAgICovXG4gIGxldCBwYWNrYWdlUmVsYXRpdmUgPSBwYWNrYWdlU2NvcGVkUGF0aC5yZXBsYWNlKFxuICAgIG5ldyBSZWdFeHAoYF4ke1JlZ0V4cC5lc2NhcGUobGVhZGluZ1NsYXNoUGF0aC5zcmMpfWApLFxuICAgIHBhdGguc2VwLFxuICApO1xuXG4gIGxldCBwYXJzZWQgPSBwYXRoLnBhcnNlKHBhY2thZ2VSZWxhdGl2ZSk7XG5cbiAgaWYgKGlzUG9kKHBhY2thZ2VSZWxhdGl2ZSkpIHtcbiAgICAvKipcbiAgICAgKiBGb3IgcG9kcywgd2UgY2hvcCBvZmYgdGhlIHdob2xlIGZpbGUsIGFuZCB1c2UgdGhlIGRpciBuYW1lIGFzIHRoZSBcIm1vZHVsZVBhdGhcIlxuICAgICAqL1xuICAgIHJldHVybiBwYXJzZWQuZGlyO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIGFuIGV4dGVuc2lvbiBpcyBwYXNzZWQsIHJlbW92ZSBpdC5cbiAgICogV2hlbiB1c2luZyBwYWNrYWdlcnMsIGZvbGtzIGFyZSB1c2VkIHRvIG5vdCBoYXZpbmcgdG8gc3BlY2lmeSBleHRlbnNpb25zIGZvciBmaWxlcy5cbiAgICogU2luY2Ugd2UgZG9uJ3QgZXZlbiBlbWl0IGNzcyBmaWxlcyBjby1sb2NhdGVkIHRvIGVhY2ggbW9kdWxlLFxuICAgKiB0aGlzIGhlbHBzIHVzIG5vdCBjb252ZXkgYSBsaWUgdGhhdCBhIGZpbGUgbWF5IGV4aXN0IGluIGF0IHJ1bnRpbWUuXG4gICAqXG4gICAqIEZvciBleGFtcGxlIGA8bW9kdWxlLW5hbWU+L2NvbXBvbmVudHMvYnV0dG9uYC5cbiAgICogSXQgZG9lc24ndCBtYXR0ZXIgd2hhdCB0aGUgZXh0ZW5zaW9uIGlzLCBiZWNhdXNlIHlvdSBjYW4gb25seSBoYXZlIG9uZSBjc3MgZmlsZVxuICAgKiBmb3IgdGhlIGJ1dHRvbiBtb2R1bGUgYW55d2F5LlxuICAgKi9cbiAgbGV0IGxvY2FsUGFja2FnZXJTdHlsZVBhdGggPSBwYXRoLmpvaW4ocGFyc2VkLmRpciwgcGFyc2VkLm5hbWUpO1xuXG4gIHJldHVybiBsb2NhbFBhY2thZ2VyU3R5bGVQYXRoO1xufVxuXG4vKipcbiAqIHJldHVybnMgdGhlIGFwcC1tb2R1bGUgcGF0aCBvZiB0aGUgc291cmNlIGZpbGVcbiAqXG4gKiBUaGlzIGFzc3VtZXMgbm9ybWFsIGVtYmVyIGFwcCBjb252ZW50aW9uc1xuICpcbiAqIHdoaWNoIGlzIGA8cGFja2FnZS5qc29uI25hbWU+L3BhdGgtdG8tZmlsZWBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcFBhdGgoc291cmNlUGF0aCkge1xuICBsZXQgd29ya3NwYWNlUGF0aCA9IGZpbmRXb3Jrc3BhY2VQYXRoKHNvdXJjZVBhdGgpO1xuICBsZXQgbmFtZSA9IG1vZHVsZU5hbWUoc291cmNlUGF0aCk7XG5cbiAgLyoqXG4gICAqICBVbmRlciBlbWJyb2lkZXIgYnVpbGRzLCB0aGUgc3BlYy1jb21wbGlhbnQgdmVyc2lvbiBvZiB0aGUgYXBwXG4gICAqIGhhcyBhbGwgdGhlIGZpbGVzIHVuZGVyIGEgZm9sZGVyIHdoaWNoIHJlcHJlc2VudHMgdGhlIHBhY2thZ2UgbmFtZSxcbiAgICogcmF0aGVyIHRoYW4gXCJhcHBcIi5cbiAgICovXG4gIGxldCBwYWNrYWdlUmVsYXRpdmUgPSBzb3VyY2VQYXRoLnJlcGxhY2Uod29ya3NwYWNlUGF0aCwgJycpO1xuXG4gIC8qKlxuICAgKiBCdXQgd2UgYWxzbyBkb24ndCB3YW50ICdhcHAnIC0tIHdoaWNoIGlzIHByZXNlbnQgaW4gdGhlIHYxIGFkZG9uIHBpcGVsaW5lXG4gICAqL1xuICBwYWNrYWdlUmVsYXRpdmUgPSBwYWNrYWdlUmVsYXRpdmUucmVwbGFjZShsZWFkaW5nU2xhc2hQYXRoLmFwcCwgcGF0aC5zZXApO1xuXG4gIC8vIEFueSBvZiB0aGUgYWJvdmUgcmVscGFjZW1lbnRzIGNvdWxkIGFjY2lkZW50YWxseSBnaXZlIHVzIGFuIGV4dHJhIC8gKGRlcGVuZGluZyBvbiBvdXIgYnVpbGQgZW52aXJvbm1lbnQpXG4gIHBhY2thZ2VSZWxhdGl2ZSA9IHBhdGgubm9ybWFsaXplKHBhY2thZ2VSZWxhdGl2ZSk7XG5cbiAgbGV0IGxvY2FsUGFja2FnZXJTdHlsZVBhdGggPSBwYWNrYWdlU2NvcGVkUGF0aFRvTW9kdWxlUGF0aChwYWNrYWdlUmVsYXRpdmUpO1xuXG4gIHJldHVybiBgJHtuYW1lfSR7bG9jYWxQYWNrYWdlclN0eWxlUGF0aH1gO1xufVxuXG4vKipcbiAqIFRvIGF2b2lkIGhpdHRpbmcgdGhlIGZpbGVzeXNldG0sIHdlJ2xsIHN0b3JlIGFsbCBmb3VuZFxuICogcHJvamVjdCBwYXRocyBiZXJlLCBzbyB3ZSBjYW4sIGluIG1lbW9yeSxcbiAqIGdldCB0aGUgZm9sZGVyIHdoZXJlIGEgcGFja2FnZS5qc29uIGV4aXN0cywgcmF0aGVyIHRoYW5cbiAqIGhpdCB0aGUgZmlsZSBzeXN0ZW0gZXZlcnkgdGltZS5cbiAqL1xuY29uc3QgU0VFTiA9IG5ldyBTZXQoKTtcblxuZnVuY3Rpb24gZ2V0U2Vlbihzb3VyY2VQYXRoKSB7XG4gIGlmIChTRUVOLmhhcyhzb3VyY2VQYXRoKSkgcmV0dXJuIHNvdXJjZVBhdGg7XG5cbiAgbGV0IHBhcnRzID0gc291cmNlUGF0aC5zcGxpdChwYXRoLnNlcCk7XG5cbiAgZm9yIChsZXQgaSA9IHBhcnRzLmxlbmd0aCAtIDE7IGkgPiAxOyBpLS0pIHtcbiAgICBsZXQgdG9DaGVjayA9IHBhcnRzLnNsaWNlKDAsIGkpLmpvaW4ocGF0aC5zZXApO1xuXG4gICAgbGV0IHNlZW4gPSBTRUVOLmhhcyh0b0NoZWNrKTtcblxuICAgIGlmIChzZWVuKSB7XG4gICAgICByZXR1cm4gdG9DaGVjaztcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRXb3Jrc3BhY2VQYXRoKHNvdXJjZVBhdGgsIG9wdGlvbnMpIHtcbiAgbGV0IGN3ZCA9IG9wdGlvbnM/LmN3ZCA/PyBDV0Q7XG5cbiAgaWYgKHNvdXJjZVBhdGguZW5kc1dpdGgocGF0aC5zZXApKSB7XG4gICAgc291cmNlUGF0aCA9IHNvdXJjZVBhdGgucmVwbGFjZShcbiAgICAgIG5ldyBSZWdFeHAoYCR7UmVnRXhwLmVzY2FwZShwYXRoLnNlcCl9JGApLFxuICAgICAgJycsXG4gICAgKTtcbiAgfVxuXG4gIGxldCBzZWVuID0gZ2V0U2Vlbihzb3VyY2VQYXRoKTtcblxuICBpZiAoc2Vlbikge1xuICAgIHJldHVybiBzZWVuO1xuICB9XG5cbiAgbGV0IGNhbmRpZGF0ZVBhdGggPSBwYXRoLmpvaW4oc291cmNlUGF0aCwgJ3BhY2thZ2UuanNvbicpO1xuXG4gIGNvbnN0IGlzV29ya3NwYWNlID0gZnNTeW5jLmV4aXN0c1N5bmMoY2FuZGlkYXRlUGF0aCk7XG5cbiAgaWYgKGlzV29ya3NwYWNlKSB7XG4gICAgcmV0dXJuIHNvdXJjZVBhdGg7XG4gIH1cblxuICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBmaW5kUGFja2FnZUpzb25VcChzb3VyY2VQYXRoLCB7IGN3ZCB9KTtcblxuICBpZiAoIXBhY2thZ2VKc29uUGF0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGRldGVybWluZSBwcm9qZWN0IGZvciAke3NvdXJjZVBhdGh9YCk7XG4gIH1cblxuICBjb25zdCB3b3Jrc3BhY2VQYXRoID0gcGF0aC5kaXJuYW1lKHBhY2thZ2VKc29uUGF0aCk7XG5cbiAgU0VFTi5hZGQod29ya3NwYWNlUGF0aCk7XG5cbiAgcmV0dXJuIHdvcmtzcGFjZVBhdGg7XG59XG5cbmZ1bmN0aW9uIGZpbmRQYWNrYWdlSnNvblVwKHN0YXJ0UGF0aCwgb3B0aW9ucykge1xuICBsZXQgY3dkID0gb3B0aW9ucz8uY3dkID8/IENXRDtcbiAgbGV0IHBhcnRzID0gc3RhcnRQYXRoLnNwbGl0KHBhdGguc2VwKTtcblxuICBmb3IgKGxldCBpID0gcGFydHMubGVuZ3RoIC0gMTsgaSA+IDE7IGktLSkge1xuICAgIGxldCB0b0NoZWNrID0gcGFydHMuc2xpY2UoMCwgaSkuam9pbihwYXRoLnNlcCk7XG5cbiAgICBsZXQgcGFja2FnZUpzb24gPSBwYXRoLmpvaW4odG9DaGVjaywgJ3BhY2thZ2UuanNvbicpO1xuICAgIGxldCBleGlzdHMgPSBmc1N5bmMuZXhpc3RzU3luYyhwYWNrYWdlSnNvbik7XG5cbiAgICBpZiAoZXhpc3RzKSB7XG4gICAgICByZXR1cm4gcGFja2FnZUpzb247XG4gICAgfVxuXG4gICAgLy8gRG9uJ3QgdHJhdmVyc2UgYWxsIHRoZSB3YXkgdG8gdGhlIHJvb3Qgb2YgdGhlIGZpbGUgc3lzdGVtLlxuICAgIGlmICh0b0NoZWNrID09PSBjd2QpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5jb25zdCBNQU5JRkVTVF9DQUNIRSA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBXaWxsIHJldHVybiB0aGUgcGFja2FnZS5qc29uI25hbWUsIG9yIGNvbmZpZy9lbnZpcm9ubWVudCNtb3VkbGVQcmVmaXggKGlmIHYxIGFwcClcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlUGF0aFxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kdWxlTmFtZShzb3VyY2VQYXRoKSB7XG4gIGNvbnN0IHdvcmtzcGFjZSA9IGZpbmRXb3Jrc3BhY2VQYXRoKHNvdXJjZVBhdGgpO1xuICBjb25zdCBtYW5pZmVzdCA9IGdldE1hbmlmZXN0KHdvcmtzcGFjZSk7XG5cbiAgcmV0dXJuIG1hbmlmZXN0Lm5hbWU7XG59XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHdvcmtzcGFjZVxuICovXG5mdW5jdGlvbiBnZXRNYW5pZmVzdCh3b3Jrc3BhY2UpIHtcbiAgbGV0IGV4aXN0aW5nID0gTUFOSUZFU1RfQ0FDSEUuZ2V0KHdvcmtzcGFjZSk7XG5cbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgbGV0IGJ1ZmZlciA9IGZzU3luYy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKHdvcmtzcGFjZSwgJ3BhY2thZ2UuanNvbicpKTtcbiAgbGV0IGNvbnRlbnQgPSBidWZmZXIudG9TdHJpbmcoKTtcbiAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGNvbnRlbnQpO1xuXG4gIE1BTklGRVNUX0NBQ0hFLnNldCh3b3Jrc3BhY2UsIGpzb24pO1xuXG4gIHJldHVybiBqc29uO1xufVxuIiwiLyoqXG4gKiBTcGxpdHMgYSBzcGFjZS1zZXBhcmF0ZWQgY2xhc3MgbGlzdCAodGhlIHZhbHVlIG9mIGEgYGNsYXNzYCBhdHRyaWJ1dGUgb3Igb2ZcbiAqIGEgYFtjbGFzcz1cIi4uLlwiXWAgc2VsZWN0b3IpIGludG8gaXRzIGluZGl2aWR1YWwgY2xhc3MgbmFtZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTGlzdFxuICogQHJldHVybnMge3N0cmluZ1tdfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRDbGFzc0xpc3QoY2xhc3NMaXN0KSB7XG4gIHJldHVybiBjbGFzc0xpc3Quc3BsaXQoL1xccysvKS5maWx0ZXIoQm9vbGVhbik7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc05hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwb3N0Zml4XG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBbY2xhc3Nlc0luQ3NzXVxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmFtZUNsYXNzKGNsYXNzTmFtZSwgcG9zdGZpeCwgY2xhc3Nlc0luQ3NzKSB7XG4gIGNvbnN0IHJlbmFtZWRDbGFzc2VzID0gc3BsaXRDbGFzc0xpc3QoY2xhc3NOYW1lKVxuICAgIC5tYXAoKGMpID0+IHtcbiAgICAgIGlmICghY2xhc3Nlc0luQ3NzIHx8IGNsYXNzZXNJbkNzcy5oYXMoYykpIHtcbiAgICAgICAgaWYgKGMuZW5kc1dpdGgocG9zdGZpeCkpIHJldHVybiBjO1xuXG4gICAgICAgIHJldHVybiBjICsgJ18nICsgcG9zdGZpeDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGM7XG4gICAgfSlcbiAgICAuam9pbignICcpO1xuXG4gIGNvbnN0IHJlbmFtZWRXaXRoUHJlc2VydmVkU3BhY2VzID0gY2xhc3NOYW1lLnJlcGxhY2UoXG4gICAgY2xhc3NOYW1lLnRyaW1TdGFydCgpLnRyaW1FbmQoKSxcbiAgICByZW5hbWVkQ2xhc3NlcyxcbiAgKTtcblxuICByZXR1cm4gcmVuYW1lZFdpdGhQcmVzZXJ2ZWRTcGFjZXM7XG59XG4iLCJpbXBvcnQge1xuICBhcHBQYXRoLFxuICBoYXNoRnJvbU1vZHVsZVBhdGgsXG4gIGlzUmVsZXZhbnRGaWxlLFxufSBmcm9tICcuLi9saWIvcGF0aC91dGlscy5qcyc7XG5pbXBvcnQgeyByZW5hbWVDbGFzcyB9IGZyb20gJy4uL2xpYi9yZW5hbWVDbGFzcy5qcyc7XG5cbmZ1bmN0aW9uIF9pc1JlbGV2YW50RmlsZShzdGF0ZSwgY3dkKSB7XG4gIGxldCBmaWxlTmFtZSA9IHN0YXRlLmZpbGUub3B0cy5maWxlbmFtZTtcbiAgbGV0IGFkZGl0aW9uYWxSb290cyA9IHN0YXRlLm9wdHM/LmFkZGl0aW9uYWxSb290cztcblxuICByZXR1cm4gaXNSZWxldmFudEZpbGUoZmlsZU5hbWUsIHtcbiAgICBhZGRpdGlvbmFsUm9vdHMsXG4gICAgY3dkLFxuICB9KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge2FueX0gZW52IC0gYmFiZWwgcGx1Z2luIGVudiwgZW52LnR5cGVzIGlzIG1vc3QgY29tbW9ubHkgdXNlZCAoZXNwIGluIFRTKVxuICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSB0aGUgb3B0aW9ucyBmb3Igc2NvcGVkLWNzcyAtLSB0aGlzIGlzIGFsc28gYXZhaWxhYmxlIGluIGVhY2ggdmlzaXRvcidzIHN0YXRlLm9wdHNcbiAqIEBwYXJhbSB7c3RyaW5nfSB3b3JraW5nRGlyZWN0b3J5XG4gKi9cbmV4cG9ydCBjb25zdCBzY29wZWRDU1MgPSAoY29uZmlnKSA9PiAoZW52LCBvcHRpb25zLCB3b3JraW5nRGlyZWN0b3J5KSA9PiB7XG4gIC8vIG5vdCByZWFsbHkgYSBkZWVwIG1lcmdlLCBidXQgdGhlIGlkZWEgaXMgdG8gdXNlIG9uZSBvciB0aGUgb3RoZXIgYW5kIG5vdCBtaXggdGhlIGNvbmZpZ3NcbiAgb3B0aW9ucyA9IHsgLi4uY29uZmlnLCAuLi5vcHRpb25zIH07XG5cbiAgLyoqXG4gICAqIFRoaXMgYmFiZWwgcGx1Z2luIGRvZXMgdHdvIHRoaW5nczpcbiAgICogLSByZW1vdmVzIHRoZSBpbXBvcnQgb2Ygc2NvcGVkQ2xhc3MsIGlmIGl0IGV4aXN0c1xuICAgKiAgIC0gaWYgc2NvcGVkQ2xhc3Mgd2FzIGltcG9ydGVkLCBpdCBpcyByZW1vdmVkIGZyb20gYW55IGNvbXBvbmVudCdzIFwic2NvcGUgYmFnXCJcbiAgICogICAgICh0aGUgc2NvcGUgYmFnIGJlaW5nIGEgbG93LWxldmVsIG9iamVjdCB1c2VkIGZvciBwYXNzaW5nIHdoYXQgaXMgXCJpbiBzY29wZVwiIGZvciBhIGNvbXBvbmVudClcbiAgICovXG4gIHJldHVybiB7XG4gICAgdmlzaXRvcjoge1xuICAgICAgUHJvZ3JhbToge1xuICAgICAgICBlbnRlcihwYXRoLCBzdGF0ZSkge1xuICAgICAgICAgIGlmICghX2lzUmVsZXZhbnRGaWxlKHN0YXRlLCB3b3JraW5nRGlyZWN0b3J5KSkge1xuICAgICAgICAgICAgc3RhdGUuY2FuU2tpcCA9IHRydWU7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgbW9kdWxlUGF0aCA9IGFwcFBhdGgoc3RhdGUuZmlsZW5hbWUpO1xuXG4gICAgICAgICAgc3RhdGUucG9zdGZpeCA9IGhhc2hGcm9tTW9kdWxlUGF0aChtb2R1bGVQYXRoKTtcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBJbXBvcnREZWNsYXJhdGlvbihwYXRoLCBzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUuY2FuU2tpcCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXRoLm5vZGUuc291cmNlLnZhbHVlID09PSAnZW1iZXItc2NvcGVkLWNzcycpIHtcbiAgICAgICAgICBsZXQgc3BlY2lmaWVyID0gcGF0aC5ub2RlLnNwZWNpZmllcnMuZmluZChcbiAgICAgICAgICAgICh4KSA9PiB4LmltcG9ydGVkLm5hbWUgPT09ICdzY29wZWRDbGFzcycsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmIChzcGVjaWZpZXIpIHtcbiAgICAgICAgICAgIHN0YXRlLmZpbGUub3B0cy5pbXBvcnRlZFNjb3BlZENsYXNzID0gc3BlY2lmaWVyLmxvY2FsLm5hbWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNwZWNpZmllci5sb2NhbC5uYW1lICE9PSAnc2NvcGVkQ2xhc3MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBUaGUgc2NvcGVkQ2xhc3MgaW1wb3J0IGlzIGEgcHN1ZWRvLWhlbHBlciwgYW5kIG1heSBub3QgYmUgcmVuYW1lZCBhcyBpdCBpcyByZW1vdmVkIGF0IGJ1aWxkIHRpbWUuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcGF0aC5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIC8qKlxuICAgICAgICogUmVuYW1lIHVzYWdlcyBpbiBKUy9UUy9HSlMvR1RTXG4gICAgICAgKi9cbiAgICAgIENhbGxFeHByZXNzaW9uKHBhdGgsIHN0YXRlKSB7XG4gICAgICAgIGlmIChzdGF0ZS5jYW5Ta2lwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIHBhdGgubm9kZS5jYWxsZWUudHlwZSA9PT0gJ0lkZW50aWZpZXInICYmXG4gICAgICAgICAgcGF0aC5ub2RlLmNhbGxlZS5uYW1lID09PSBzdGF0ZS5maWxlLm9wdHM/LmltcG9ydGVkU2NvcGVkQ2xhc3NcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgcGF0aC5ub2RlLmFyZ3VtZW50cy5sZW5ndGggIT09IDEgfHxcbiAgICAgICAgICAgIHBhdGgubm9kZS5hcmd1bWVudHNbMF0udHlwZSAhPT0gJ1N0cmluZ0xpdGVyYWwnXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBUaGUgc2NvcGVkQ2xhc3MgaGVscGVyIG9ubHkgYWNjZXB0cyBhIHNpbmdsZSwgbm9uLWR5bmFtaWMsIHN0cmluZyBsaXRlcmFsIGFyZ3VtZW50LmAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IG9yaWdpbmFsID0gcGF0aC5ub2RlLmFyZ3VtZW50c1swXS52YWx1ZTtcbiAgICAgICAgICBjb25zdCByZW5hbWVkID0gcmVuYW1lQ2xhc3MoXG4gICAgICAgICAgICBvcmlnaW5hbCxcbiAgICAgICAgICAgIHN0YXRlLnBvc3RmaXgsXG4gICAgICAgICAgICBuZXcgU2V0KFtvcmlnaW5hbF0pLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgdHJhbnNmb3JtZWRTdHJpbmcgPSBlbnYudHlwZXMuc3RyaW5nTGl0ZXJhbChyZW5hbWVkKTtcblxuICAgICAgICAgIHBhdGgucmVwbGFjZVdpdGgodHJhbnNmb3JtZWRTdHJpbmcpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgLyoqXG4gICAgICAgKiBPbmx5IGluIHN0cmljdCBtb2RlLCBkbyB3ZSBjYXJlIGFib3V0IHJlbW9uaW5nIHRoZSBzY29wZSBiYWcgcmVmZXJlbmNlXG4gICAgICAgKi9cbiAgICAgIE9iamVjdFByb3BlcnR5KHBhdGgsIHN0YXRlKSB7XG4gICAgICAgIGlmICghc3RhdGUuZmlsZS5vcHRzPy5pbXBvcnRlZFNjb3BlZENsYXNzKSByZXR1cm47XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIHBhdGgubm9kZS52YWx1ZS50eXBlID09PSAnSWRlbnRpZmllcicgJiZcbiAgICAgICAgICBwYXRoLm5vZGUudmFsdWUubmFtZSA9PT0gc3RhdGUuZmlsZS5vcHRzPy5pbXBvcnRlZFNjb3BlZENsYXNzXG4gICAgICAgICkge1xuICAgICAgICAgIHBhdGgucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMgfSBmcm9tICdmcyc7XG5pbXBvcnQgcG9zdGNzcyBmcm9tICdwb3N0Y3NzJztcbmltcG9ydCBzY3NzU3ludGF4IGZyb20gJ3Bvc3Rjc3Mtc2Nzcyc7XG5pbXBvcnQgcGFyc2VyIGZyb20gJ3Bvc3Rjc3Mtc2VsZWN0b3ItcGFyc2VyJztcblxuaW1wb3J0IHsgbWQ1IH0gZnJvbSAnLi4vcGF0aC9tZDUuanMnO1xuaW1wb3J0IHsgc3BsaXRDbGFzc0xpc3QgfSBmcm9tICcuLi9yZW5hbWVDbGFzcy5qcyc7XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IGNzc1xuICogQHJldHVybiB7c3RyaW5nfSBoYXNoZWQgZG93biB2ZXJzaW9uIG9mIHRoZSBDU1MgZm9yIGRpc2FtYmlndWF0aW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoKGNzcykge1xuICByZXR1cm4gYGNzcy0ke21kNShjc3MpfWA7XG59XG5cbi8qKlxuICogQXR0cmlidXRlIHNlbGVjdG9ycyBhcmUgc2NvcGVkIHdpdGggb25lIG9mIHR3byBzdHJhdGVnaWVzOlxuICpcbiAqIC0gKipyZW5hbWVkIHZhbHVlKio6IGNsYXNzLXRhcmdldGluZyBzZWxlY3RvcnMgd2hvc2UgdmFsdWUgbmFtZXMgcmVhbFxuICogICBjbGFzcyhlcykgKGBbY2xhc3M9XCJmb29cIl1gLCBgW2NsYXNzfj1cImZvb1wiXWApIGFyZSBzY29wZWQgYnkgcmVuYW1pbmcgdGhlXG4gKiAgIHZhbHVlIHRoZSBzYW1lIHdheSBgLmZvb2AgaXMgcmVuYW1lZCB0byBgLmZvb19wb3N0Zml4YC4gVGhlIHJlbmFtZWQgdG9rZW5cbiAqICAgaXMgdW5pcXVlIHBlciBmaWxlLCBzbyBub3RoaW5nIGVsc2UgaXMgbmVlZGVkLlxuICogLSAqKnBvc3RmaXggY2xhc3MqKjogZXZlcnkgb3RoZXIgYXR0cmlidXRlIHNlbGVjdG9yIGtlZXBzIGl0cyBkaXNjcmltaW5hdG9yXG4gKiAgIGFuZCBpcyBzY29wZWQgYnkgdGhlIGdlbmVyYXRlZCBwb3N0Zml4IGNsYXNzIOKAlCBhcHBlbmRlZCB0byB0aGUgc2VsZWN0b3JcbiAqICAgaW4gdGhlIENTUyBhbmQgYWRkZWQgdG8gbWF0Y2hpbmcgZWxlbWVudHMgaW4gdGhlIHRlbXBsYXRlICh0aGUgc2FtZVxuICogICBzdHJhdGVneSBiYXJlIHRhZyBzZWxlY3RvcnMgdXNlOiBgZGl2YCBiZWNvbWVzIGBkaXYucG9zdGZpeGApLlxuICpcbiAqIFRoaXMgcHJlZGljYXRlIGRlY2lkZXMgYmV0d2VlbiB0aGUgdHdvLiBJdCBpcyBzaGFyZWQgYnkgdGhlIENTUyByZXdyaXRlXG4gKiAod2hpY2ggcmVuYW1lcyB0aGUgc2VsZWN0b3IgdmFsdWUpIGFuZCBieSBkaXNjb3ZlcnkgaW4gdGhpcyBmaWxlICh3aGljaFxuICogcmVnaXN0ZXJzIHRoZSB2YWx1ZSdzIGNsYXNzIG5hbWVzIGZvciB0ZW1wbGF0ZSByZW5hbWluZykgc28gYm90aCBzaWRlc1xuICogYWx3YXlzIGNsYXNzaWZ5IGEgc2VsZWN0b3IgdGhlIHNhbWUgd2F5LlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KCdwb3N0Y3NzLXNlbGVjdG9yLXBhcnNlcicpLkF0dHJpYnV0ZX0gbm9kZVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1JlbmFtZWRDbGFzc0F0dHJpYnV0ZShub2RlKSB7XG4gIHJldHVybiAoXG4gICAgbm9kZS5hdHRyaWJ1dGUgPT09ICdjbGFzcycgJiZcbiAgICAobm9kZS5vcGVyYXRvciA9PT0gJz0nIHx8IG5vZGUub3BlcmF0b3IgPT09ICd+PScpICYmXG4gICAgQm9vbGVhbihub2RlLnZhbHVlKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNJbnNpZGVHbG9iYWwobm9kZSwgZnVuYykge1xuICBjb25zdCBwYXJlbnQgPSBub2RlLnBhcmVudDtcblxuICBpZiAoIXBhcmVudCkgcmV0dXJuIGZhbHNlO1xuICBpZiAocGFyZW50LnR5cGUgPT09ICdwc2V1ZG8nICYmIHBhcmVudC52YWx1ZSA9PT0gJzpnbG9iYWwnKSByZXR1cm4gdHJ1ZTtcblxuICByZXR1cm4gaXNJbnNpZGVHbG9iYWwocGFyZW50LCBmdW5jKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gY3NzUGF0aCBwYXRoIHRvIGEgQ1NTIGZpbGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENTU0luZm8oY3NzUGF0aCkge1xuICBpZiAoIWV4aXN0c1N5bmMoY3NzUGF0aCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGxldCBjc3MgPSByZWFkRmlsZVN5bmMoY3NzUGF0aCwgJ3V0ZjgnKTtcblxuICByZXR1cm4gZ2V0Q1NTQ29udGVudEluZm8oY3NzKTtcbn1cblxuLyoqXG4gKiBXZSB1c2UgdGhpcyBmdW5jdGlvbiB0byBjaGVjayBlYWNoIGNsYXNzIHVzZWQgaW4gdGhlIHRlbXBsYXRlXG4gKiB0byBzZWUgaWYgd2UgbmVlZCB0byBsZWF2ZSBpdCBhbG9uZSBvciB0cmFuc2Zvcm0gaXRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY3NzIHRoZSBDU1MncyBjb250ZW50c1xuICogQHBhcmFtIHtzdHJpbmd9IFtsYW5nXSBvcHRpb25hbCBsYW5ndWFnZSBoaW50IChlLmcuICdzY3NzJywgJ3Nhc3MnLCAnbGVzcycpXG4gKiBAcmV0dXJuIHt7IGNsYXNzZXM6IFNldDxzdHJpbmc+LCB0YWdzOiBTZXQ8c3RyaW5nPiwgYXR0cmlidXRlczogU2V0PHN0cmluZz4sIGNzczogc3RyaW5nLCBpZDogc3RyaW5nIH19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDU1NDb250ZW50SW5mbyhjc3MsIGxhbmcpIHtcbiAgY29uc3QgY2xhc3NlcyA9IG5ldyBTZXQoKTtcbiAgY29uc3QgdGFncyA9IG5ldyBTZXQoKTtcbiAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBTZXQoKTtcblxuICBjb25zdCBwYXJzZU9wdGlvbnMgPVxuICAgIGxhbmcgPT09ICdzY3NzJyB8fCBsYW5nID09PSAnc2FzcycgPyB7IHN5bnRheDogc2Nzc1N5bnRheCB9IDoge307XG5cbiAgY29uc3QgYXN0ID0gcG9zdGNzcy5wYXJzZShjc3MsIHBhcnNlT3B0aW9ucyk7XG5cbiAgY29uc3QgaXNTY3NzID0gbGFuZyA9PT0gJ3Njc3MnIHx8IGxhbmcgPT09ICdzYXNzJztcblxuICBhc3Qud2Fsaygobm9kZSkgPT4ge1xuICAgIGlmIChub2RlLnR5cGUgPT09ICdydWxlJykge1xuICAgICAgY29uc3Qgc2VsZWN0b3IgPSBpc1Njc3MgPyByZXNvbHZlTmVzdGVkU2Fzc1NlbGVjdG9yKG5vZGUpIDogbm9kZS5zZWxlY3RvcjtcblxuICAgICAgY29sbGVjdFNlbGVjdG9ySW5mbyhzZWxlY3RvciwgY2xhc3NlcywgdGFncywgYXR0cmlidXRlcyk7XG4gICAgfVxuICB9KTtcblxuICBsZXQgaWQgPSBoYXNoKGNzcyk7XG5cbiAgcmV0dXJuIHsgY2xhc3NlcywgdGFncywgYXR0cmlidXRlcywgY3NzLCBpZCB9O1xufVxuXG4vKipcbiAqIFJlc29sdmVzIGEgbmVzdGVkIFNDU1Mgc2VsZWN0b3IgYnkgc3Vic3RpdHV0aW5nIGAmYCB3aXRoIHRoZSBmdWxseS1yZXNvbHZlZFxuICogcGFyZW50IHNlbGVjdG9yLCByZWN1cnNpdmVseS4gVGhpcyBjb252ZXJ0cyBlLmcuIGAmLS1tb2RpZmllcmAgKGNoaWxkIG9mXG4gKiBgLmJsb2NrYCkgaW50byBgLmJsb2NrLS1tb2RpZmllcmAsIGFuZCBoYW5kbGVzIGFyYml0cmFyeSBuZXN0aW5nIGRlcHRoIHNvXG4gKiB0aGF0IGAmLS1tb2RpZmllcmAgaW5zaWRlIGAmLS1tb2RpZmllcmAgaW5zaWRlIGAuYmxvY2tgIHlpZWxkc1xuICogYC5ibG9jay0tbW9kaWZpZXItLW1vZGlmaWVyYC5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydCgncG9zdGNzcycpLlJ1bGV9IG5vZGVcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZU5lc3RlZFNhc3NTZWxlY3Rvcihub2RlKSB7XG4gIGNvbnN0IHsgc2VsZWN0b3IgfSA9IG5vZGU7XG5cbiAgaWYgKCFzZWxlY3Rvci5pbmNsdWRlcygnJicpKSB7XG4gICAgcmV0dXJuIHNlbGVjdG9yO1xuICB9XG5cbiAgY29uc3QgcGFyZW50ID0gbm9kZS5wYXJlbnQ7XG5cbiAgaWYgKCFwYXJlbnQgfHwgcGFyZW50LnR5cGUgIT09ICdydWxlJykge1xuICAgIC8vIE5vIHBhcmVudCBydWxlIOKAlCBgJmAgaGFzIG5vdGhpbmcgdG8gc3Vic3RpdHV0ZSwgcmV0dXJuIGFzLWlzXG4gICAgcmV0dXJuIHNlbGVjdG9yO1xuICB9XG5cbiAgLy8gUmVjdXJzaXZlbHkgcmVzb2x2ZSB0aGUgcGFyZW50IGZpcnN0LCB0aGVuIHN1YnN0aXR1dGUgaW50byB0aGlzIHNlbGVjdG9yXG4gIGNvbnN0IHJlc29sdmVkUGFyZW50ID0gcmVzb2x2ZU5lc3RlZFNhc3NTZWxlY3RvcihwYXJlbnQpO1xuXG4gIHJldHVybiBzZWxlY3Rvci5yZXBsYWNlKC8mL2csIHJlc29sdmVkUGFyZW50KTtcbn1cblxuZnVuY3Rpb24gY29sbGVjdFNlbGVjdG9ySW5mbyhzZWwsIGNsYXNzZXMsIHRhZ3MsIGF0dHJpYnV0ZXMpIHtcbiAgY29uc3QgdHJhbnNmb3JtID0gKHNscykgPT4ge1xuICAgIHNscy53YWxrKChzZWxlY3RvcikgPT4ge1xuICAgICAgaWYgKGlzSW5zaWRlR2xvYmFsKHNlbGVjdG9yKSkgcmV0dXJuO1xuXG4gICAgICBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ2NsYXNzJykge1xuICAgICAgICBjbGFzc2VzLmFkZChzZWxlY3Rvci52YWx1ZSk7XG4gICAgICB9IGVsc2UgaWYgKHNlbGVjdG9yLnR5cGUgPT09ICd0YWcnKSB7XG4gICAgICAgIHRhZ3MuYWRkKHNlbGVjdG9yLnZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ2F0dHJpYnV0ZScpIHtcbiAgICAgICAgaWYgKGlzUmVuYW1lZENsYXNzQXR0cmlidXRlKHNlbGVjdG9yKSkge1xuICAgICAgICAgIC8vIFJlZ2lzdGVyIHRoZSB2YWx1ZSdzIGNsYXNzIG5hbWVzIHNvIHRoZSB0ZW1wbGF0ZSByZW5hbWVzIHRoZW0uXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyBwb3N0Y3NzLXNlbGVjdG9yLXBhcnNlciBleHBvc2VzIHRoZSBhdHRyaWJ1dGUgdmFsdWUgb25seSBhcyBhblxuICAgICAgICAgIC8vIG9wYXF1ZSBzdHJpbmcsIHNvIHNwbGl0dGluZyBgW2NsYXNzPVwiZm9vIGJhclwiXWAgaW50byBpdHNcbiAgICAgICAgICAvLyBzcGFjZS1zZXBhcmF0ZWQgY2xhc3MgbmFtZXMgaXMgb24gdXMg4oCUIGBzcGxpdENsYXNzTGlzdGAgaXMgdGhlXG4gICAgICAgICAgLy8gc2FtZSB0b2tlbml6YXRpb24gYHJlbmFtZUNsYXNzYCBhcHBsaWVzLlxuICAgICAgICAgIGZvciAobGV0IHRva2VuIG9mIHNwbGl0Q2xhc3NMaXN0KHNlbGVjdG9yLnZhbHVlKSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5hZGQodG9rZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBFbGVtZW50cyBjYXJyeWluZyB0aGlzIGF0dHJpYnV0ZSBnZXQgdGhlIHBvc3RmaXggY2xhc3MuIEZvclxuICAgICAgICAgIC8vIGNsYXNzLXRhcmdldCBvcGVyYXRvcnMgKF49LCAqPSwgJD0sIHw9KSBhbmQgcHJlc2VuY2UsIHRoZSBuYW1lXG4gICAgICAgICAgLy8gaXMgYGNsYXNzYC5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIENTUyBtYXRjaGVzIEhUTUwgYXR0cmlidXRlIG5hbWVzIGNhc2UtaW5zZW5zaXRpdmVseSwgc28gc3RvcmUgdGhlXG4gICAgICAgICAgLy8gbmFtZSBsb3dlcmNhc2VkIGFuZCBjb21wYXJlIGFnYWluc3QgbG93ZXJjYXNlZCB0ZW1wbGF0ZSBhdHRyaWJ1dGVcbiAgICAgICAgICAvLyBuYW1lcy4gKENvYXJzZXIgdGhhbiBTVkcncyBjYXNlLXNlbnNpdGl2ZSBtYXRjaGluZywgYnV0IHRoZSB0d29cbiAgICAgICAgICAvLyBzaWRlcyBhbHdheXMgYWdyZWU7IHdvcnN0IGNhc2UgYW4gZWxlbWVudCBnZXRzIHRoZSBwb3N0Zml4IGNsYXNzXG4gICAgICAgICAgLy8gaXQgZGlkbid0IHN0cmljdGx5IG5lZWQuKVxuICAgICAgICAgIGF0dHJpYnV0ZXMuYWRkKHNlbGVjdG9yLmF0dHJpYnV0ZS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIHBhcnNlcih0cmFuc2Zvcm0pLnByb2Nlc3NTeW5jKHNlbCk7XG59XG5cbmlmIChpbXBvcnQubWV0YS52aXRlc3QpIHtcbiAgY29uc3QgeyBpdCwgZXhwZWN0IH0gPSBpbXBvcnQubWV0YS52aXRlc3Q7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gY2xhc3NlcyBhbmQgdGFncyB0aGF0IGFyZSBub3QgaW4gOmdsb2JhbCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBjc3MgPSAnLmJheiA6Z2xvYmFsKC5mb28pIC5iYXIgZGl2IDpnbG9iYWwocCkgIHsgY29sb3I6IHJlZDsgfSc7XG4gICAgY29uc3QgeyBjbGFzc2VzLCB0YWdzIH0gPSBnZXRDU1NDb250ZW50SW5mbyhjc3MpO1xuXG4gICAgLy8gY2xhc3NlcyBzaG91bGQgYmUgYmF6IGFuZCBiYXJcbiAgICBleHBlY3QoY2xhc3Nlcy5zaXplKS50by5lcXVhbCgyKTtcbiAgICBleHBlY3QoWy4uLmNsYXNzZXNdKS50by5oYXZlLm1lbWJlcnMoWydiYXonLCAnYmFyJ10pO1xuICAgIGV4cGVjdCh0YWdzLnNpemUpLnRvLmVxdWFsKDEpO1xuICAgIGV4cGVjdChbLi4udGFnc10pLnRvLmhhdmUubWVtYmVycyhbJ2RpdiddKTtcbiAgfSk7XG5cbiAgaXQoJ2NvbGxlY3RzIGF0dHJpYnV0ZSBuYW1lcyBmb3IgcG9zdGZpeC1jbGFzcyBzY29waW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNzcyA9ICdbZGlzYWJsZWRdIFtkYXRhLXg9XCJ5XCJdIHsgY29sb3I6IHJlZDsgfSc7XG4gICAgY29uc3QgeyBhdHRyaWJ1dGVzIH0gPSBnZXRDU1NDb250ZW50SW5mbyhjc3MpO1xuXG4gICAgZXhwZWN0KGF0dHJpYnV0ZXMpLnRvLmRlZXAuZXF1YWwobmV3IFNldChbJ2Rpc2FibGVkJywgJ2RhdGEteCddKSk7XG4gIH0pO1xuXG4gIGl0KCd0cmVhdHMgPS9+PSBjbGFzcyBhdHRyaWJ1dGUgdmFsdWVzIGFzIHJlbmFtZWQgY2xhc3NlcycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBjc3MgPSAnW2NsYXNzPVwiZm9vIGJhclwiXSBbY2xhc3N+PVwiYmF6XCJdIHsgY29sb3I6IHJlZDsgfSc7XG4gICAgY29uc3QgeyBjbGFzc2VzLCBhdHRyaWJ1dGVzIH0gPSBnZXRDU1NDb250ZW50SW5mbyhjc3MpO1xuXG4gICAgZXhwZWN0KGNsYXNzZXMpLnRvLmRlZXAuZXF1YWwobmV3IFNldChbJ2ZvbycsICdiYXInLCAnYmF6J10pKTtcbiAgICBleHBlY3QoYXR0cmlidXRlcykudG8uZGVlcC5lcXVhbChuZXcgU2V0KCkpO1xuICB9KTtcblxuICBpdCgndHJlYXRzIG90aGVyIGNsYXNzIGF0dHJpYnV0ZSBvcGVyYXRvcnMgYXMgcG9zdGZpeC1jbGFzcyBhdHRyaWJ1dGVzJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNzcyA9ICdbY2xhc3NePVwiZm9vXCJdIFtjbGFzcyo9XCJiYXJcIl0geyBjb2xvcjogcmVkOyB9JztcbiAgICBjb25zdCB7IGNsYXNzZXMsIGF0dHJpYnV0ZXMgfSA9IGdldENTU0NvbnRlbnRJbmZvKGNzcyk7XG5cbiAgICBleHBlY3QoY2xhc3NlcykudG8uZGVlcC5lcXVhbChuZXcgU2V0KCkpO1xuICAgIGV4cGVjdChhdHRyaWJ1dGVzKS50by5kZWVwLmVxdWFsKG5ldyBTZXQoWydjbGFzcyddKSk7XG4gIH0pO1xuXG4gIGl0KCdsb3dlcmNhc2VzIGF0dHJpYnV0ZSBuYW1lcyAoQ1NTIG1hdGNoZXMgdGhlbSBjYXNlLWluc2Vuc2l0aXZlbHkpJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNzcyA9ICdbVFlQRT1cInN1Ym1pdFwiXSB7IGNvbG9yOiByZWQ7IH0nO1xuICAgIGNvbnN0IHsgYXR0cmlidXRlcyB9ID0gZ2V0Q1NTQ29udGVudEluZm8oY3NzKTtcblxuICAgIGV4cGVjdChhdHRyaWJ1dGVzKS50by5kZWVwLmVxdWFsKG5ldyBTZXQoWyd0eXBlJ10pKTtcbiAgfSk7XG5cbiAgaXQoJ2lnbm9yZXMgYXR0cmlidXRlIHNlbGVjdG9ycyBpbnNpZGUgOmdsb2JhbCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBjc3MgPSAnOmdsb2JhbChbZGF0YS14XSkgW2RhdGEteV0geyBjb2xvcjogcmVkOyB9JztcbiAgICBjb25zdCB7IGF0dHJpYnV0ZXMgfSA9IGdldENTU0NvbnRlbnRJbmZvKGNzcyk7XG5cbiAgICBleHBlY3QoYXR0cmlidXRlcykudG8uZGVlcC5lcXVhbChuZXcgU2V0KFsnZGF0YS15J10pKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwYXJzZSBTQ1NTIG5lc3Rpbmcgc3ludGF4IHdpdGhvdXQgY3Jhc2hpbmcgd2hlbiBsYW5nPXNjc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgc2NzcyA9IGBcbiAgICAgICRiYXNlLWNvbG9yOiAjYzY1MzhjO1xuICAgICAgJGJvcmRlci1kYXJrOiByZ2JhKCRiYXNlLWNvbG9yLCAwLjg4KTtcblxuICAgICAgLnBhcmVudCB7XG4gICAgICAgICY6aG92ZXIgeyBjb2xvcjogJGJhc2UtY29sb3I7IH1cbiAgICAgICAgLmNoaWxkIHsgYm9yZGVyOiAxcHggc29saWQgJGJvcmRlci1kYXJrOyB9XG4gICAgICAgIGNvbG9yOiByZWQ7XG4gICAgICB9XG4gICAgYDtcbiAgICBjb25zdCB7IGNsYXNzZXMgfSA9IGdldENTU0NvbnRlbnRJbmZvKHNjc3MsICdzY3NzJyk7XG5cbiAgICBleHBlY3QoWy4uLmNsYXNzZXNdKS50b01hdGNoSW5saW5lU25hcHNob3QoYFxuICAgICAgW1xuICAgICAgICBcInBhcmVudFwiLFxuICAgICAgICBcImNoaWxkXCIsXG4gICAgICBdXG4gICAgYCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcGFyc2UgU0NTUyBuZXN0aW5nIHN5bnRheCB3aXRob3V0IGNyYXNoaW5nIHdoZW4gbGFuZz1zYXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNjc3MgPSBgXG4gICAgICAkYmFzZS1jb2xvcjogZ3JlZW47XG4gICAgICAuYmxvY2sge1xuICAgICAgICAmLS1tb2RpZmllciB7IGNvbG9yOiAkYmFzZS1jb2xvcjsgfVxuICAgICAgfVxuICAgIGA7XG4gICAgY29uc3QgeyBjbGFzc2VzIH0gPSBnZXRDU1NDb250ZW50SW5mbyhzY3NzLCAnc2FzcycpO1xuXG4gICAgZXhwZWN0KFsuLi5jbGFzc2VzXSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcbiAgICAgIFtcbiAgICAgICAgXCJibG9ja1wiLFxuICAgICAgICBcImJsb2NrLS1tb2RpZmllclwiLFxuICAgICAgXVxuICAgIGApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHBhcnNlIFNDU1MgZGVlcGx5IG5lc3RlZCBCRU0gd2hlbiBsYW5nPXNhc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgc2NzcyA9IGBcbiAgICAgICRiYXNlLWNvbG9yOiBncmVlbjtcbiAgICAgIC5ibG9jayB7XG4gICAgICAgICYtLW1vZGlmaWVyIHtcbiAgICAgICAgICBjb2xvcjogJGJhc2UtY29sb3I7XG4gICAgICAgICAgJi0tbW9kaWZpZXIge1xuICAgICAgICAgICAgY29sb3I6ICRiYXNlLWNvbG9yO1xuICAgICAgICAgICAgJi0tbW9kaWZpZXIge1xuICAgICAgICAgICAgICBjb2xvcjogJGJhc2UtY29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgYDtcbiAgICBjb25zdCB7IGNsYXNzZXMgfSA9IGdldENTU0NvbnRlbnRJbmZvKHNjc3MsICdzYXNzJyk7XG5cbiAgICBleHBlY3QoWy4uLmNsYXNzZXNdKS50b01hdGNoSW5saW5lU25hcHNob3QoYFxuICAgICAgW1xuICAgICAgICBcImJsb2NrXCIsXG4gICAgICAgIFwiYmxvY2stLW1vZGlmaWVyXCIsXG4gICAgICAgIFwiYmxvY2stLW1vZGlmaWVyLS1tb2RpZmllclwiLFxuICAgICAgICBcImJsb2NrLS1tb2RpZmllci0tbW9kaWZpZXItLW1vZGlmaWVyXCIsXG4gICAgICBdXG4gICAgYCk7XG4gIH0pO1xufVxuIiwiLyoqXG4gKiBJbXBvcnRhbnQgZG9jczpcbiAqIC0gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL1xuICovXG5pbXBvcnQgcG9zdGNzcyBmcm9tICdwb3N0Y3NzJztcbmltcG9ydCBwYXJzZXIgZnJvbSAncG9zdGNzcy1zZWxlY3Rvci1wYXJzZXInO1xuXG5pbXBvcnQgeyByZW5hbWVDbGFzcyB9IGZyb20gJy4uL3JlbmFtZUNsYXNzLmpzJztcbmltcG9ydCB7IGlzSW5zaWRlR2xvYmFsLCBpc1JlbmFtZWRDbGFzc0F0dHJpYnV0ZSB9IGZyb20gJy4vdXRpbHMuanMnO1xuXG5jb25zdCBTRVAgPSAnX18nO1xuXG5mdW5jdGlvbiBpc1J1bGUobm9kZSkge1xuICByZXR1cm4gbm9kZS50eXBlID09PSAncnVsZSc7XG59XG5cbmZ1bmN0aW9uIGlzRGVjbGFyYXRpb24obm9kZSkge1xuICByZXR1cm4gbm9kZS50eXBlID09PSAnZGVjbCc7XG59XG5cbi8qKlxuICogTk9URTogXCJrZXlmcmFtZXNcIiBpcyBhIHNpbmd1bGFyIGRlZmluaXRpb24sIGluIHRoYXQgaXQncyBhIGJsb2NrIGNvbnRhaW5pbmcga2V5ZnJhbWVzXG4gKiAgICAgICB1c2luZyBgQGtleWZyYW1lcyB7fWAgd2l0aCBvbmx5IG9uZSB0aGluZyBvbiB0aGUgaW5zaWRlIGRvZXNuJ3QgbWFrZSBzZW5zZS5cbiAqL1xuZnVuY3Rpb24gcmV3cml0ZVJlZmVyZW5jZWFibGUobm9kZSwgcG9zdGZpeCkge1xuICBsZXQgb3JpZ2luYWxOYW1lID0gbm9kZS5wYXJhbXM7XG4gIGxldCBwb3N0Zml4ZWROYW1lID0gbm9kZS5wYXJhbXMgKyBTRVAgKyBwb3N0Zml4O1xuXG4gIG5vZGUucGFyYW1zID0gcG9zdGZpeGVkTmFtZTtcblxuICByZXR1cm4ge1xuICAgIG9yaWdpbmFsTmFtZSxcbiAgICBwb3N0Zml4ZWROYW1lLFxuICB9O1xufVxuXG4vKipcbiAqIFdhbGsgbGVmdCBhbmQgcmlnaHQgZnJvbSBgbm9kZWAgd2l0aGluIGl0cyBjb21wb3VuZCBzZWxlY3RvciAoYm91bmRlZCBieVxuICogY29tYmluYXRvcnMpIHRvIHNlZSBpZiB0aGUgcG9zdGZpeCBjbGFzcyBoYXMgYWxyZWFkeSBiZWVuIGFkZGVkLiBVc2VkIHRvIGFkZFxuICogdGhlIHBvc3RmaXggY2xhc3MgYXQgbW9zdCBvbmNlIHBlciBjb21wb3VuZCwgZS5nLiBgaW5wdXRbdHlwZT1cInRleHRcIl1gXG4gKiBiZWNvbWVzIGBpbnB1dC5wb3N0Zml4W3R5cGU9XCJ0ZXh0XCJdYCwgbm90IGBpbnB1dC5wb3N0Zml4W3R5cGU9XCJ0ZXh0XCJdLnBvc3RmaXhgLlxuICovXG5mdW5jdGlvbiBjb21wb3VuZEhhc1Bvc3RmaXhDbGFzcyhub2RlLCBwb3N0Zml4KSB7XG4gIGNvbnN0IHNpYmxpbmdzID0gbm9kZS5wYXJlbnQubm9kZXM7XG4gIGNvbnN0IGluZGV4ID0gc2libGluZ3MuaW5kZXhPZihub2RlKTtcblxuICBmb3IgKGxldCBpID0gaW5kZXg7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHNpYmxpbmdzW2ldLnR5cGUgPT09ICdjb21iaW5hdG9yJykgYnJlYWs7XG4gICAgaWYgKHNpYmxpbmdzW2ldLnR5cGUgPT09ICdjbGFzcycgJiYgc2libGluZ3NbaV0udmFsdWUgPT09IHBvc3RmaXgpXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSBpbmRleCArIDE7IGkgPCBzaWJsaW5ncy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChzaWJsaW5nc1tpXS50eXBlID09PSAnY29tYmluYXRvcicpIGJyZWFrO1xuICAgIGlmIChzaWJsaW5nc1tpXS50eXBlID09PSAnY2xhc3MnICYmIHNpYmxpbmdzW2ldLnZhbHVlID09PSBwb3N0Zml4KVxuICAgICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFkZFBvc3RmaXhDbGFzcyhub2RlLCBwb3N0Zml4KSB7XG4gIGlmIChjb21wb3VuZEhhc1Bvc3RmaXhDbGFzcyhub2RlLCBwb3N0Zml4KSkgcmV0dXJuO1xuXG4gIG5vZGUucGFyZW50Lmluc2VydEFmdGVyKG5vZGUsIHBhcnNlci5jbGFzc05hbWUoeyB2YWx1ZTogcG9zdGZpeCB9KSk7XG59XG5cbmZ1bmN0aW9uIHJld3JpdGVTZWxlY3RvcihzZWwsIHBvc3RmaXgpIHtcbiAgY29uc3QgdHJhbnNmb3JtID0gKHNlbGVjdG9ycykgPT4ge1xuICAgIC8vIE5vZGVzIHRoYXQgbmVlZCB0aGUgcG9zdGZpeCBjbGFzcyBhZGRlZCBuZXh0IHRvIHRoZW0uIFdlIGNvbGxlY3QgdGhlbVxuICAgIC8vIGR1cmluZyB0aGUgd2FsayBhbmQgaW5zZXJ0IHRoZSBjbGFzc2VzIGFmdGVyd2FyZHMgc28gdGhlIGZyZXNobHktaW5zZXJ0ZWRcbiAgICAvLyBjbGFzc2VzIGFyZSBuZXZlciB0aGVtc2VsdmVzIHJlLXZpc2l0ZWQgYnkgdGhlIHdhbGsuXG4gICAgY29uc3QgbmVlZHNQb3N0Zml4Q2xhc3MgPSBbXTtcblxuICAgIHNlbGVjdG9ycy53YWxrKChzZWxlY3RvcikgPT4ge1xuICAgICAgaWYgKGlzSW5zaWRlR2xvYmFsKHNlbGVjdG9yKSkgcmV0dXJuO1xuXG4gICAgICAvLyBXZSBuZXZlciB3YW50IHRvIHRvdWNoIHBzdWVkbyBzZWxlY3RvcnMgc2luY2Ugd2UgYW5kIHRoZSB1c2VyIGRvZXNuJ3Qgb3duIHRoZW0uXG4gICAgICBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ3BzdWVkbycpIHJldHVybjtcblxuICAgICAgLy8gOm50aC1vZi10eXBlIGhhcyBzcGVjaWFsIHN5bnRheCB3aGVyZSB0aGUgdmFsdWVzIHBhc3NlZCB0byBudGgtb2YtdHlwZSgpXG4gICAgICAvLyBtdXN0IGVpdGhlciBiZSBleGFjdGx5IFwib2RkXCIsIFwiZXZlblwiLCBvciBhIHNpbXBsZSBmb3JtdWxhXG4gICAgICAvL1xuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTLzpudGgtb2YtdHlwZVxuICAgICAgaWYgKGlzTnRoT2ZUeXBlKHNlbGVjdG9yKSkgcmV0dXJuO1xuXG4gICAgICBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ2NsYXNzJykge1xuICAgICAgICBzZWxlY3Rvci52YWx1ZSArPSAnXycgKyBwb3N0Zml4O1xuICAgICAgfSBlbHNlIGlmIChzZWxlY3Rvci50eXBlID09PSAndGFnJykge1xuICAgICAgICBuZWVkc1Bvc3RmaXhDbGFzcy5wdXNoKHNlbGVjdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ2F0dHJpYnV0ZScpIHtcbiAgICAgICAgaWYgKGlzUmVuYW1lZENsYXNzQXR0cmlidXRlKHNlbGVjdG9yKSkge1xuICAgICAgICAgIC8vIFRoZSByZW5hbWVkIHRva2VuIChlLmcuIGBmb29fcG9zdGZpeGApIGlzIGFscmVhZHkgdW5pcXVlIHBlclxuICAgICAgICAgIC8vIGZpbGUsIHNvIG5vIHBvc3RmaXggY2xhc3MgaXMgbmVlZGVkLlxuICAgICAgICAgIHNlbGVjdG9yLnZhbHVlID0gcmVuYW1lQ2xhc3Moc2VsZWN0b3IudmFsdWUsIHBvc3RmaXgpO1xuICAgICAgICAgIGlmICghc2VsZWN0b3IucXVvdGVNYXJrKSBzZWxlY3Rvci5xdW90ZU1hcmsgPSAnXCInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGBbY2xhc3N8PVwiZm9vXCJdYCBhbmQgYFtjbGFzcyQ9XCJmb29cIl1gIGNhbm5vdCBiZSByZWxpYWJseSBzY29wZWRcbiAgICAgICAgICAvLyB3aXRoIHRoZSBwb3N0Zml4IGNsYXNzICh0aGUgcG9zdGZpeCBjbGFzcyBkZWZlYXRzIHRoZW0pLiBUaGF0IGlzXG4gICAgICAgICAgLy8gc3VyZmFjZWQgdG8gYXV0aG9ycyBieSB0aGVcbiAgICAgICAgICAvLyBgZW1iZXItc2NvcGVkLWNzcy9uby11bnNjb3BhYmxlLWNsYXNzLWF0dHJpYnV0ZS1zZWxlY3RvcnNgXG4gICAgICAgICAgLy8gc3R5bGVsaW50IHJ1bGUgcmF0aGVyIHRoYW4gYSBydW50aW1lIHdhcm5pbmcuXG4gICAgICAgICAgbmVlZHNQb3N0Zml4Q2xhc3MucHVzaChzZWxlY3Rvcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBuZWVkc1Bvc3RmaXhDbGFzcykge1xuICAgICAgYWRkUG9zdGZpeENsYXNzKG5vZGUsIHBvc3RmaXgpO1xuICAgIH1cblxuICAgIC8vIHJlbW92ZSA6Z2xvYmFsXG4gICAgc2VsZWN0b3JzLndhbGsoKHNlbGVjdG9yKSA9PiB7XG4gICAgICBpZiAoc2VsZWN0b3IudHlwZSA9PT0gJ3BzZXVkbycgJiYgc2VsZWN0b3IudmFsdWUgPT09ICc6Z2xvYmFsJykge1xuICAgICAgICBzZWxlY3Rvci5yZXBsYWNlV2l0aCguLi5zZWxlY3Rvci5ub2Rlcyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG4gIGNvbnN0IHRyYW5zZm9ybWVkID0gcGFyc2VyKHRyYW5zZm9ybSkucHJvY2Vzc1N5bmMoc2VsKTtcblxuICByZXR1cm4gdHJhbnNmb3JtZWQ7XG59XG5cbmZ1bmN0aW9uIGlzTnRoT2ZUeXBlKG5vZGUpIHtcbiAgaWYgKCFub2RlKSByZXR1cm4gZmFsc2U7XG5cbiAgcmV0dXJuIG5vZGUucGFyZW50Py52YWx1ZSA9PT0gJzpudGgtb2YtdHlwZScgfHwgaXNOdGhPZlR5cGUobm9kZS5wYXJlbnQpO1xufVxuXG5mdW5jdGlvbiBpc0luc2lkZUtleWZyYW1lcyhub2RlKSB7XG4gIGNvbnN0IHBhcmVudCA9IG5vZGUucGFyZW50O1xuXG4gIGlmICghcGFyZW50KSByZXR1cm4gZmFsc2U7XG4gIGlmIChwYXJlbnQudHlwZSA9PT0gJ2F0cnVsZScgJiYgcGFyZW50Lm5hbWUgPT09ICdrZXlmcmFtZXMnKSByZXR1cm4gdHJ1ZTtcblxuICByZXR1cm4gaXNJbnNpZGVLZXlmcmFtZXMocGFyZW50KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJld3JpdGVDc3MoY3NzLCBwb3N0Zml4LCBmaWxlTmFtZSwgbGF5ZXJOYW1lKSB7XG4gIGNvbnN0IGFzdCA9IHBvc3Rjc3MucGFyc2UoY3NzKTtcbiAgLyoqXG4gICAqIGtpbmQgPT4gb3JpZ2luYWxOYW1lID0+IHBvc3RmaXhlZE5hbWVcbiAgICogQHR5cGUge3sgW2tpbmQ6IHN0cmluZ106IHsgW29yaWdpbmFsTmFtZTogc3RyaW5nXTogc3RyaW5nIH19fVxuICAgKi9cbiAgY29uc3QgcmVmZXJlbmNlYWJsZXMgPSB7XG4gICAga2V5ZnJhbWVzOiB7fSxcbiAgICAnY291bnRlci1zdHlsZSc6IHt9LFxuICAgICdwb3NpdGlvbi10cnknOiB7fSxcbiAgICBwcm9wZXJ0eToge30sXG4gIH07XG5cbiAgY29uc3QgYXZhaWxhYmxlUmVmZXJlbmNlYWJsZXMgPSBuZXcgU2V0KE9iamVjdC5rZXlzKHJlZmVyZW5jZWFibGVzKSk7XG5cbiAgZnVuY3Rpb24gaXNSZWZlcmVuY2VhYmxlKG5vZGUpIHtcbiAgICBpZiAobm9kZS50eXBlICE9PSAnYXRydWxlJykgcmV0dXJuO1xuXG4gICAgcmV0dXJuIGF2YWlsYWJsZVJlZmVyZW5jZWFibGVzLmhhcyhub2RlLm5hbWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gdXBkYXRlRGlyZWN0UmVmZXJlbmNlcyhub2RlKSB7XG4gICAgaWYgKCFub2RlLnZhbHVlKSByZXR1cm47XG5cbiAgICBmb3IgKGxldCBbLCBtYXBdIG9mIE9iamVjdC5lbnRyaWVzKHJlZmVyZW5jZWFibGVzKSkge1xuICAgICAgaWYgKG1hcFtub2RlLnZhbHVlXSkge1xuICAgICAgICBub2RlLnZhbHVlID0gbWFwW25vZGUudmFsdWVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVNob3J0aGFuZENvbnRlbnRzKG5vZGUpIHtcbiAgICBpZiAobm9kZS5wcm9wID09PSAnYW5pbWF0aW9uJykge1xuICAgICAgbGV0IHBhcnRzID0gbm9kZS52YWx1ZS5zcGxpdCgnICcpO1xuICAgICAgbGV0IG1hdGNoID0gcGFydHMuZmlsdGVyKCh4KSA9PiByZWZlcmVuY2VhYmxlcy5rZXlmcmFtZXNbeF0pO1xuXG4gICAgICBpZiAobWF0Y2gubGVuZ3RoKSB7XG4gICAgICAgIG1hdGNoLmZvckVhY2goKHgpID0+IHtcbiAgICAgICAgICBsZXQgcmVwbGFjZW1lbnQgPSByZWZlcmVuY2VhYmxlcy5rZXlmcmFtZXNbeF07XG5cbiAgICAgICAgICBpZiAoIXJlcGxhY2VtZW50KSByZXR1cm47XG5cbiAgICAgICAgICBub2RlLnZhbHVlID0gbm9kZS52YWx1ZS5yZXBsYWNlKHgsIHJlcGxhY2VtZW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChsZXQgW2xvb2tGb3IsIHJlcGxhY2VXaXRoXSBvZiBPYmplY3QuZW50cmllcyhcbiAgICAgIHJlZmVyZW5jZWFibGVzLnByb3BlcnR5LFxuICAgICkpIHtcbiAgICAgIGxldCBsb29rRm9yVmFyID0gYHZhcigke2xvb2tGb3J9KWA7XG4gICAgICBsZXQgcmVwbGFjZVdpdGhWYXIgPSBgdmFyKCR7cmVwbGFjZVdpdGh9KWA7XG5cbiAgICAgIG5vZGUudmFsdWUgPSBub2RlLnZhbHVlLnJlcGxhY2UobG9va0ZvclZhciwgcmVwbGFjZVdpdGhWYXIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXZSBoYXZlIHRvIGRvIHR3byBwYXNzZXM6XG4gICAqIDEuIHBvc3RmaXggYWxsIHRoZSByZWZlcmVuY2VhYmxlIHN5bnRheFxuICAgKiAyLiBwb3N0Zml4IGFzIG5vcm1hbCwgYnV0IGFsc28gY2hlY2tpbmcgdmFsdWVzIG9mIENTUyBwcm9wZXJ0aWVzXG4gICAqICAgIHRoYXQgY291bGQgbWF0Y2ggcG9zdGZpeGVkIHJlZmVyZW5jZWFibGVzIGZyb20gc3RlcCAxXG4gICAqL1xuXG4gIC8vIFN0ZXAgMTogZmluZCByZWZlcmVuY2VhYmxlc1xuICBhc3Qud2Fsaygobm9kZSkgPT4ge1xuICAgIC8qKlxuICAgICAqIEBrZXlmcmFtZXMsIEBjb3VudGVyLXN0eWxlLCBldGNcbiAgICAgKi9cbiAgICBpZiAoaXNSZWZlcmVuY2VhYmxlKG5vZGUpKSB7XG4gICAgICBsZXQgbmFtZSA9IG5vZGUubmFtZTtcbiAgICAgIGxldCB7IG9yaWdpbmFsTmFtZSwgcG9zdGZpeGVkTmFtZSB9ID0gcmV3cml0ZVJlZmVyZW5jZWFibGUobm9kZSwgcG9zdGZpeCk7XG5cbiAgICAgIHJlZmVyZW5jZWFibGVzW25hbWVdW29yaWdpbmFsTmFtZV0gPSBwb3N0Zml4ZWROYW1lO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICB9KTtcblxuICAvLyBTdGVwIDI6IHBvc3RmaXggYW5kIHVwZGF0ZSByZWZlcmVuY2VkIHJlZmVyZW5jZWFibGVzXG4gIGFzdC53YWxrKChub2RlKSA9PiB7XG4gICAgaWYgKGlzRGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgIHVwZGF0ZURpcmVjdFJlZmVyZW5jZXMobm9kZSk7XG4gICAgICB1cGRhdGVTaG9ydGhhbmRDb250ZW50cyhub2RlKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpc1J1bGUobm9kZSkpIHtcbiAgICAgIC8qKlxuICAgICAgICogVGhlIGlubmVyLWNvbnRlbnRzIG9mIGEga2V5ZnJhbWUgYXJlIHBlcmNlbnRhZ2VzLCByYXRoZXIgdGhhbiBzZWxlY3RvcnNcbiAgICAgICAqL1xuICAgICAgaWYgKGlzSW5zaWRlS2V5ZnJhbWVzKG5vZGUpKSByZXR1cm47XG5cbiAgICAgIG5vZGUuc2VsZWN0b3IgPSByZXdyaXRlU2VsZWN0b3Iobm9kZS5zZWxlY3RvciwgcG9zdGZpeCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHJld3JpdHRlbkNzcyA9IGFzdC50b1N0cmluZygpO1xuXG4gIHJldHVybiAoXG4gICAgW1xuICAgICAgYC8qICR7ZmlsZU5hbWV9ICovYCxcbiAgICAgIGxheWVyTmFtZSA/IGBAbGF5ZXIgJHtsYXllck5hbWV9IHtgIDogJycsXG4gICAgICByZXdyaXR0ZW5Dc3MudHJpbUVuZCgpLFxuICAgICAgbGF5ZXJOYW1lID8gYH1gIDogJycsXG4gICAgXVxuICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgLmpvaW4oJ1xcbicpICsgJ1xcbidcbiAgKTtcbn1cbiIsImltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5cbmNvbnN0IEtFWSA9ICdlbWJlci1zY29wZWQuY3NzJztcbmNvbnN0IFNFUCA9ICdfX18nO1xuXG5leHBvcnQgY29uc3QgcmVxdWVzdCA9IHtcbiAgaXM6IHtcbiAgICBpbmxpbmUocmVxdWVzdCkge1xuICAgICAgcmV0dXJuIHJlcXVlc3QuaW5jbHVkZXMoS0VZKTtcbiAgICB9LFxuICAgIGNvbG9jYXRlZChyZXF1ZXN0KSB7XG4gICAgICByZXR1cm4gcmVxdWVzdC5pbmNsdWRlcygnLmNzcz9zY29wZWQ9Jyk7XG4gICAgfSxcbiAgfSxcbiAgaW5saW5lOiB7XG4gICAgLyoqXG4gICAgICogTWFrZXMgcmVxdWVzdCBVUkwgZm9yIGVtYmVkZGluZyBgPHN0eWxlPmAgYXMgYDxsaW5rPmAgaW50byB0aGUgYDxoZWFkPmBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjc3NIYXNoIHRoZSBoYXNoIG9mIHRoZSBDU1MgY29udGVudHNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcG9zdGZpeCB0aGUgaGFzaCBvZiB0aGUgZmlsZSB0aGF0IF9pbmNsdWRlc18gdGhlIGxpbmtlZCBmaWxlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNzc0NvbnRlbnRzIHRoZSBjb250ZW50cyBvZiB0aGUgQ1NTIGZpbGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhbmddIG9wdGlvbmFsIHByZXByb2Nlc3NvciBsYW5ndWFnZSAoZS5nLiAnc2NzcycsICdzYXNzJywgJ2xlc3MnKVxuICAgICAqL1xuICAgIGNyZWF0ZShjc3NIYXNoLCBwb3N0Zml4LCBjc3NDb250ZW50cywgbGFuZykge1xuICAgICAgbGV0IHVybCA9IGAuLyR7cG9zdGZpeH0ke1NFUH0ke2Nzc0hhc2h9LiR7S0VZfT9jc3M9JHtlbmNvZGVVUklDb21wb25lbnQoY3NzQ29udGVudHMpfWA7XG5cbiAgICAgIGlmIChsYW5nKSB7XG4gICAgICAgIHVybCArPSBgJmxhbmc9JHtlbmNvZGVVUklDb21wb25lbnQobGFuZyl9YDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHVybDtcbiAgICB9LFxuICAgIGRlY29kZShyZXF1ZXN0KSB7XG4gICAgICBsZXQgW2xlZnQsIHFwc10gPSByZXF1ZXN0LnNwbGl0KCc/Jyk7XG5cbiAgICAgIGxlZnQgPSBsZWZ0LnNsaWNlKDIpLnJlcGxhY2UoYC4ke0tFWX1gLCAnJyk7XG5cbiAgICAgIGxldCBbcG9zdGZpeCwgaGFzaF0gPSBsZWZ0LnNwbGl0KFNFUCk7XG5cbiAgICAgIGxldCBzZWFyY2ggPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHFwcyk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc2gsXG4gICAgICAgIHBvc3RmaXgsXG4gICAgICAgIGNzczogc2VhcmNoLmdldCgnY3NzJyksXG4gICAgICAgIGZyb206IHNlYXJjaC5nZXQoJ2Zyb20nKSxcbiAgICAgICAgbGFuZzogc2VhcmNoLmdldCgnbGFuZycpLFxuICAgICAgfTtcbiAgICB9LFxuICB9LFxuICBjb2xvY2F0ZWQ6IHtcbiAgICAvKipcbiAgICAgKiBNYWtlcyByZXF1ZXN0IFVSTCBmb3IgZW1iZWRkaW5nIHNlcGFyYXRlIENTUyBGaWxlIGFzIGA8bGluaz5gIGludG8gdGhlIGA8aGVhZD5gXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY3NzSGFzaCB0aGUgaGFzaCBvZiB0aGUgQ1NTIGNvbnRlbnRzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBvc3RmaXggdGhlIGhhc2ggb2YgdGhlIGZpbGUgdGhhdCBfaW5jbHVkZXNfIHRoZSBsaW5rZWQgZmlsZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aCBwYXRoIHRvIHRoZSBzZXBhcmF0ZSBDU1MgRmlsZVxuICAgICAqL1xuICAgIGNyZWF0ZShjc3NIYXNoLCBwb3N0Zml4LCBmaWxlUGF0aCkge1xuICAgICAgcmV0dXJuIGAuLyR7cGF0aC5iYXNlbmFtZShmaWxlUGF0aCl9P3Njb3BlZD0ke3Bvc3RmaXh9JmNzc0hhc2g9JHtjc3NIYXNofWA7XG4gICAgfSxcbiAgICBkZWNvZGUocmVxdWVzdCkge1xuICAgICAgY29uc3QgW2ZpbGVOYW1lLCBxc10gPSByZXF1ZXN0LnNwbGl0KCc/Jyk7XG4gICAgICBjb25zdCBzZWFyY2ggPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHFzKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZU5hbWUsXG4gICAgICAgIGNzc0hhc2g6IHNlYXJjaC5nZXQoJ2Nzc0hhc2gnKSxcbiAgICAgICAgcG9zdGZpeDogc2VhcmNoLmdldCgnc2NvcGVkJyksXG4gICAgICB9O1xuICAgIH0sXG4gIH0sXG59O1xuIiwiaW1wb3J0IHsgcmVhZEZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSAnbm9kZTptb2R1bGUnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcblxuaW1wb3J0IHsgcmV3cml0ZUNzcyB9IGZyb20gJy4uL2xpYi9jc3MvcmV3cml0ZS5qcyc7XG5pbXBvcnQgeyByZXF1ZXN0IH0gZnJvbSAnLi4vbGliL3JlcXVlc3QuanMnO1xuXG5jb25zdCBNRVRBID0gJ3Njb3BlZC1jc3M6Y29sb2NhdGVkJztcblxuLyoqIEZpbGUgZXh0ZW5zaW9ucyB0aGF0IFZpdGUgY2FuIHByZXByb2Nlc3MgdmlhIGl0cyBDU1MgcHJlcHJvY2Vzc29yIHBpcGVsaW5lICovXG5jb25zdCBQUkVQUk9DRVNTRURfRVhURU5TSU9OUyA9IG5ldyBTZXQoW1xuICAnLnNjc3MnLFxuICAnLnNhc3MnLFxuICAnLmxlc3MnLFxuICAnLnN0eWwnLFxuICAnLnN0eWx1cycsXG5dKTtcblxuLyoqXG4gKiBQbHVnaW4gZm9yIHN1cHBvcnRpbmcgY29sb2NhdGVkIHN0eWxlc1xuICpcbiAqIGUuZy46XG4gKiAgc3JjL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmpzXG4gKiAgc3JjL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmNzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb2NhdGVkKG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCBDV0QgPSBwcm9jZXNzLmN3ZCgpO1xuXG4gIC8qKiBAdHlwZSB7aW1wb3J0KCd2aXRlJykuUmVzb2x2ZWRDb25maWcgfCB1bmRlZmluZWR9ICovXG4gIGxldCB2aXRlQ29uZmlnO1xuXG4gIC8qKiBAdHlwZSB7KChjb2RlOiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcsIGNvbmZpZzogdW5rbm93bikgPT4gUHJvbWlzZTx7IGNvZGU6IHN0cmluZyB9PikgfCB1bmRlZmluZWR9ICovXG4gIGxldCBwcmVwcm9jZXNzQ1NTO1xuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgdGhlIHJlcXVlc3QgaWQgLyB3aGF0IHdhcyBpbXBvcnRlZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGggIHBhdGggb24gZGlza1xuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgZnVuY3Rpb24gYnVpbGRSZXNwb25zZShpZCwgZmlsZVBhdGgpIHtcbiAgICBjb25zdCBwYXJzZWQgPSByZXF1ZXN0LmNvbG9jYXRlZC5kZWNvZGUoaWQpO1xuICAgIGNvbnN0IHJlbGF0aXZlRmlsZVBhdGggPSBwYXRoLnJlbGF0aXZlKENXRCwgZmlsZVBhdGgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBmaWxlUGF0aCxcbiAgICAgIG1ldGE6IHtcbiAgICAgICAgW01FVEFdOiB7XG4gICAgICAgICAgcG9zdGZpeDogcGFyc2VkLnBvc3RmaXgsXG4gICAgICAgICAgZmlsZU5hbWU6IHJlbGF0aXZlRmlsZVBhdGgsXG4gICAgICAgICAgZnVsbFBhdGg6IGZpbGVQYXRoLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnZW1iZXItc2NvcGVkLWNzczpjb2xvY2F0ZWQnLFxuICAgIHJlc29sdmVJZChpZCwgaW1wb3J0ZXIpIHtcbiAgICAgIC8vIGhhbmRsZXM6IHNvbWUtZmlsZS5jc3M/c2NvcGVkPVtwb3N0Zml4XVxuICAgICAgLy8gdGhpcyBpcyBvbmx5IHJ1biBpbiByb2xsdXAsIHZpdGUgaGFuZGxlcyBpdCBkaWZmZXJlbnRseVxuICAgICAgaWYgKHJlcXVlc3QuaXMuY29sb2NhdGVkKGlkKSkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSByZXF1ZXN0LmNvbG9jYXRlZC5kZWNvZGUoaWQpO1xuXG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKFxuICAgICAgICAgIHBhdGguZGlybmFtZShpbXBvcnRlciksXG4gICAgICAgICAgcGF0aC5iYXNlbmFtZShwYXJzZWQuZmlsZU5hbWUpLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBidWlsZFJlc3BvbnNlKGlkLCBmaWxlUGF0aCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBsb2FkKGlkKSB7XG4gICAgICBjb25zdCBtZXRhID0gdGhpcy5nZXRNb2R1bGVJbmZvKGlkKT8ubWV0YT8uW01FVEFdO1xuXG4gICAgICBpZiAobWV0YSkge1xuICAgICAgICB0aGlzLmFkZFdhdGNoRmlsZShtZXRhLmZ1bGxQYXRoKTtcblxuICAgICAgICBsZXQgY29kZSA9IHJlYWRGaWxlU3luYyhtZXRhLmZ1bGxQYXRoLCAndXRmLTgnKTtcblxuICAgICAgICBsZXQgY3NzID0gcmV3cml0ZUNzcyhcbiAgICAgICAgICBjb2RlLFxuICAgICAgICAgIG1ldGEucG9zdGZpeCxcbiAgICAgICAgICBtZXRhLmZpbGVOYW1lLFxuICAgICAgICAgIG9wdGlvbnMubGF5ZXJOYW1lLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBjc3M7XG4gICAgICB9XG4gICAgfSxcbiAgICB2aXRlOiB7XG4gICAgICBhc3luYyBjb25maWdSZXNvbHZlZChjb25maWcpIHtcbiAgICAgICAgdml0ZUNvbmZpZyA9IGNvbmZpZztcblxuICAgICAgICAvLyBSZXNvbHZlIFZpdGUncyBwcmVwcm9jZXNzQ1NTIGZyb20gdGhlIGFwcCByb290IHRvIGVuc3VyZSB3ZSBmaW5kXG4gICAgICAgIC8vIHRoZSBjb3JyZWN0IFZpdGUgaW5zdGFsbGF0aW9uIChub3QgYSBzdGFsZSBvciBtaXNzaW5nIG9uZSkuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUocGF0aC5qb2luKGNvbmZpZy5yb290LCAncGFja2FnZS5qc29uJykpO1xuICAgICAgICAgIGNvbnN0IHZpdGVQYXRoID0gcmVxdWlyZS5yZXNvbHZlKCd2aXRlJyk7XG4gICAgICAgICAgY29uc3Qgdml0ZU1vZHVsZSA9IGF3YWl0IGltcG9ydCh2aXRlUGF0aCk7XG5cbiAgICAgICAgICBwcmVwcm9jZXNzQ1NTID0gdml0ZU1vZHVsZS5wcmVwcm9jZXNzQ1NTO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBWaXRlIG1heSBub3QgYmUgcmVzb2x2YWJsZSBmcm9tIHRoZSBjb25maWcgcm9vdCBpbiBzb21lIHNldHVwcztcbiAgICAgICAgICAvLyBwcmVwcm9jZXNzb3Igc3VwcG9ydCBmb3IgY29sb2NhdGVkIC5zY3NzIGZpbGVzIHdpbGwgdGhyb3cgYSBjbGVhclxuICAgICAgICAgIC8vIGVycm9yIGF0IGxvYWQgdGltZSBpZiB1c2VkLlxuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZXJlIG1heSBub3QgYmUgbWV0YSBmb3IgdGhpcyByZXF1ZXN0IHlldC5cbiAgICAgICAqXG4gICAgICAgKiBAcGFyYW0geyp9IGlkXG4gICAgICAgKi9cbiAgICAgIGFzeW5jIGxvYWQoaWQpIHtcbiAgICAgICAgaWYgKHJlcXVlc3QuaXMuY29sb2NhdGVkKGlkKSkge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHJlcXVlc3QuY29sb2NhdGVkLmRlY29kZShpZCk7XG5cbiAgICAgICAgICBsZXQgY29kZSA9IHJlYWRGaWxlU3luYyhwYXJzZWQuZmlsZU5hbWUsICd1dGYtOCcpO1xuICAgICAgICAgIGxldCByZWxhdGl2ZUZpbGVQYXRoID0gcGF0aC5yZWxhdGl2ZShDV0QsIHBhcnNlZC5maWxlTmFtZSk7XG5cbiAgICAgICAgICBjb25zdCBleHQgPSBwYXRoLmV4dG5hbWUocGFyc2VkLmZpbGVOYW1lKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgICAgaWYgKFBSRVBST0NFU1NFRF9FWFRFTlNJT05TLmhhcyhleHQpKSB7XG4gICAgICAgICAgICBpZiAoIXZpdGVDb25maWcgfHwgIXByZXByb2Nlc3NDU1MpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBbZW1iZXItc2NvcGVkLWNzc10gQ29sb2NhdGVkIENTUyBmaWxlIHdpdGggZXh0ZW5zaW9uICcke2V4dH0nIHJlcXVpcmVzIFZpdGUuIGAgK1xuICAgICAgICAgICAgICAgICAgYENTUyBwcmVwcm9jZXNzaW5nIGlzIG9ubHkgc3VwcG9ydGVkIGluIFZpdGUgYnVpbGRzLmAsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHByZXByb2Nlc3NDU1MoXG4gICAgICAgICAgICAgIGNvZGUsXG4gICAgICAgICAgICAgIHBhcnNlZC5maWxlTmFtZSxcbiAgICAgICAgICAgICAgdml0ZUNvbmZpZyxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNvZGUgPSByZXN1bHQuY29kZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgY3NzID0gcmV3cml0ZUNzcyhcbiAgICAgICAgICAgIGNvZGUsXG4gICAgICAgICAgICBwYXJzZWQucG9zdGZpeCxcbiAgICAgICAgICAgIHJlbGF0aXZlRmlsZVBhdGgsXG4gICAgICAgICAgICBvcHRpb25zLmxheWVyTmFtZSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgcmV0dXJuIGNzcztcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICB9O1xufVxuIiwiaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5cbmltcG9ydCB7IHJld3JpdGVDc3MgfSBmcm9tICcuLi9saWIvY3NzL3Jld3JpdGUuanMnO1xuaW1wb3J0IHsgcmVxdWVzdCB9IGZyb20gJy4uL2xpYi9yZXF1ZXN0LmpzJztcblxuY29uc3QgTUVUQSA9ICdzY29wZWQtY3NzOmlubGluZSc7XG5cbi8qKlxuICogUGx1Z2luIGZvciBzdXBwb3J0aW5nIHRoZSBzdHlsZXMgZnJvbVxuICpcbiAqIDx0ZW1wbGF0ZT5cbiAqICAgPHN0eWxlPi4uLjwvc3R5bGU+XG4gKiA8L3RlbXBsYXRlPlxuICpcbiAqIFRoaXMgcGx1Z2luIGNhbid0IGhhdmUgSE1SIGZvciBDU1MgYmVjYXVzZSBjaGFuZ2VzIHRvIHRoZSBDU1MgY29udGVudCBhbHRlcnMgdGhlIHRlbXBsYXRlIGNvbnRlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlubGluZShvcHRpb25zID0ge30pIHtcbiAgY29uc3QgQ1dEID0gcHJvY2Vzcy5jd2QoKTtcblxuICAvKiogQHR5cGUge2ltcG9ydCgndml0ZScpLlJlc29sdmVkQ29uZmlnIHwgdW5kZWZpbmVkfSAqL1xuICBsZXQgdml0ZUNvbmZpZztcblxuICAvKiogQHR5cGUgeygoY29kZTogc3RyaW5nLCBmaWxlbmFtZTogc3RyaW5nLCBjb25maWc6IHVua25vd24pID0+IFByb21pc2U8eyBjb2RlOiBzdHJpbmcgfT4pIHwgdW5kZWZpbmVkfSAqL1xuICBsZXQgcHJlcHJvY2Vzc0NTUztcblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIHRoZSByZXF1ZXN0IGlkIC8gd2hhdCB3YXMgaW1wb3J0ZWRcbiAgICovXG4gIGZ1bmN0aW9uIGJ1aWxkUmVzcG9uc2UoaWQsIGZpbGVQYXRoKSB7XG4gICAgY29uc3QgcGFyc2VkID0gcmVxdWVzdC5pbmxpbmUuZGVjb2RlKGlkKTtcblxuICAgIGNvbnN0IHJlbGF0aXZlRmlsZVBhdGggPSBwYXRoLnJlbGF0aXZlKENXRCwgZmlsZVBhdGgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBmaWxlUGF0aC5zcGxpdCgnPycpWzBdLFxuICAgICAgbWV0YToge1xuICAgICAgICBbTUVUQV06IHtcbiAgICAgICAgICByYXdDc3M6IHBhcnNlZC5jc3MsXG4gICAgICAgICAgcG9zdGZpeDogcGFyc2VkLnBvc3RmaXgsXG4gICAgICAgICAgZmlsZU5hbWU6IHJlbGF0aXZlRmlsZVBhdGgsXG4gICAgICAgICAgbGFuZzogcGFyc2VkLmxhbmcsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdlbWJlci1zY29wZWQtY3NzOmlubGluZScsXG4gICAgcmVzb2x2ZUlkKGlkLCBpbXBvcnRlcikge1xuICAgICAgaWYgKHJlcXVlc3QuaXMuaW5saW5lKGlkKSkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSByZXF1ZXN0LmlubGluZS5kZWNvZGUoaWQpO1xuXG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKFxuICAgICAgICAgIHBhdGguZGlybmFtZShpbXBvcnRlciksXG4gICAgICAgICAgYCR7cGF0aC5iYXNlbmFtZShpbXBvcnRlciwgcGF0aC5leHRuYW1lKGltcG9ydGVyKSl9LSR7cGFyc2VkLmhhc2h9LmNzc2AsXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIGJ1aWxkUmVzcG9uc2UoaWQsIGZpbGVQYXRoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGFzeW5jIGxvYWQoaWQpIHtcbiAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldE1vZHVsZUluZm8oaWQpPy5tZXRhPy5bTUVUQV07XG5cbiAgICAgIGlmIChtZXRhKSB7XG4gICAgICAgIGxldCByYXdDc3MgPSBtZXRhLnJhd0NzcztcblxuICAgICAgICBpZiAobWV0YS5sYW5nKSB7XG4gICAgICAgICAgaWYgKCF2aXRlQ29uZmlnIHx8ICFwcmVwcm9jZXNzQ1NTKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBbZW1iZXItc2NvcGVkLWNzc10gPHN0eWxlIHNjb3BlZCBsYW5nPVwiJHttZXRhLmxhbmd9XCI+IHJlcXVpcmVzIFZpdGUuIGAgK1xuICAgICAgICAgICAgICAgIGBDU1MgcHJlcHJvY2Vzc2luZyB2aWEgdGhlICdsYW5nJyBhdHRyaWJ1dGUgaXMgb25seSBzdXBwb3J0ZWQgaW4gVml0ZSBidWlsZHMuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZmFrZUZpbGVuYW1lID0gYCR7bWV0YS5maWxlTmFtZX0uJHttZXRhLmxhbmd9YDtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcmVwcm9jZXNzQ1NTKHJhd0NzcywgZmFrZUZpbGVuYW1lLCB2aXRlQ29uZmlnKTtcblxuICAgICAgICAgIHJhd0NzcyA9IHJlc3VsdC5jb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY3NzID0gcmV3cml0ZUNzcyhcbiAgICAgICAgICByYXdDc3MsXG4gICAgICAgICAgbWV0YS5wb3N0Zml4LFxuICAgICAgICAgIGA8aW5saW5lPi8ke21ldGEuZmlsZU5hbWV9YCxcbiAgICAgICAgICBvcHRpb25zLmxheWVyTmFtZSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gY3NzO1xuICAgICAgfVxuICAgIH0sXG4gICAgdml0ZToge1xuICAgICAgYXN5bmMgY29uZmlnUmVzb2x2ZWQoY29uZmlnKSB7XG4gICAgICAgIHZpdGVDb25maWcgPSBjb25maWc7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBWaXRlJ3MgcHJlcHJvY2Vzc0NTUyBmcm9tIHRoZSBhcHAgcm9vdCB0byBlbnN1cmUgd2UgZmluZFxuICAgICAgICAvLyB0aGUgY29ycmVjdCBWaXRlIGluc3RhbGxhdGlvbiAobm90IGEgc3RhbGUgb3IgbWlzc2luZyBvbmUpLlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKHBhdGguam9pbihjb25maWcucm9vdCwgJ3BhY2thZ2UuanNvbicpKTtcbiAgICAgICAgICBjb25zdCB2aXRlUGF0aCA9IHJlcXVpcmUucmVzb2x2ZSgndml0ZScpO1xuICAgICAgICAgIGNvbnN0IHZpdGVNb2R1bGUgPSBhd2FpdCBpbXBvcnQodml0ZVBhdGgpO1xuXG4gICAgICAgICAgcHJlcHJvY2Vzc0NTUyA9IHZpdGVNb2R1bGUucHJlcHJvY2Vzc0NTUztcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gVml0ZSBtYXkgbm90IGJlIHJlc29sdmFibGUgZnJvbSB0aGUgY29uZmlnIHJvb3QgaW4gc29tZSBzZXR1cHM7XG4gICAgICAgICAgLy8gbGFuZz0gc3VwcG9ydCB3aWxsIHRocm93IGEgY2xlYXIgZXJyb3IgYXQgbG9hZCB0aW1lIGlmIHVzZWQuXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcbn1cbiIsImltcG9ydCB7IGNyZWF0ZVVucGx1Z2luIH0gZnJvbSAndW5wbHVnaW4nO1xuXG5pbXBvcnQgeyBjb2xvY2F0ZWQgfSBmcm9tICcuL3VucGx1Z2luLWNvbG9jYXRlZC5qcyc7XG5pbXBvcnQgeyBpbmxpbmUgfSBmcm9tICcuL3VucGx1Z2luLWlubGluZS5qcyc7XG5cbi8qKlxuICogVGhlIHBsdWdpbiB0aGF0IGhhbmRsZXMgQ1NTIHJlcXVlc3RzIGZvciBgPHN0eWxlPmAgZWxlbWVudHMgYW5kIHRyYW5zZm9ybXNcbiAqIGZvciBleGlzdGluZyBmaWxlc1xuICpcbiAqIHZpdGU6IENTUyBmaWxlcyBhcmUgcmVzb2x2ZWQgYnkgdml0ZS4gV2UgdXNlIHRoZWlyIHJlc29sdmVyIHRvIGFsc28gZ2V0XG4gKiAgICAgICBITVIuIFRoYXQgaXMsIGZvciBhbGwgbm9uLXBoeXNpY2FsIENTUyBmaWxlcywgd2UgZXh0ZW5kIHZpdGUgYnkgb3VyXG4gKiAgICAgICByZXNvbHZlciBhbmQgYWxzbyBjYW4gZW5yaWNoIG1ldGFkYXRhIHRvIGl0IChmb3IgYmV0dGVyIGRlYnVnZ2luZylcbiAqL1xuZXhwb3J0IGNvbnN0IHVucGx1Z2luID0gY3JlYXRlVW5wbHVnaW4oKG9wdGlvbnMgPSB7fSkgPT4ge1xuICByZXR1cm4gW2NvbG9jYXRlZChvcHRpb25zKSwgaW5saW5lKG9wdGlvbnMpXTtcbn0pO1xuIiwiaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcblxuaW1wb3J0IHsgbGVhZGluZ1NsYXNoUGF0aCB9IGZyb20gJy4vY29uc3QuanMnO1xuaW1wb3J0IHsgZmluZFdvcmtzcGFjZVBhdGggfSBmcm9tICcuL3V0aWxzLmpzJztcblxuLyoqXG4gKiB0ZW1wbGF0ZSBwbHVnaW5zIGRvIG5vdCBoYW5kIHVzIHRoZSBjb3JyZWN0IGZpbGUgcGF0aC5cbiAqIGFkZGl0aW9uYWxseSwgd2UgbWF5IG5vdCBiZSBhYmxlIHRvIHJlbHkgb24gdGhpcyBkYXRhIGluIHRoZSBmdXR1cmUsXG4gKiBzbyB0aGlzIGZ1bmN0aW9ucyBhY3RzIGFzIGEgbWVhbnMgb2Ygbm9ybWFsaXppbmcgX3doYXRldmVyXyB3ZSdyZSBnaXZlblxuICogaW4gdGhlIGZ1dHVyZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSBmaWxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaXhGaWxlbmFtZShmaWxlbmFtZSkge1xuICBsZXQgZmlsZU5hbWUgPSBmaWxlbmFtZTtcbiAgbGV0IHdvcmtzcGFjZSA9IGZpbmRXb3Jrc3BhY2VQYXRoKGZpbGVOYW1lKTtcblxuICAvKipcbiAgICogZW1iZXItc291cmNlIDUuODpcbiAgICogLSB0aGUgZmlsZW5hbWUgbG9va3MgbGlrZSBhbiBhYnNvbHV0ZSBwYXRoLCBidXQgc3dhcHBlZCBvdXQgdGhlICdhcHAnIHBhcnQgb2YgdGhlIHBhdGhcbiAgICogICB3aXRoIHRoZSBtb2R1bGUgbmFtZSwgc28gdGhlIGZpbGUgcGF0aHMgbmV2ZXIgZXhpc3Qgb24gZGlza1xuICAgKlxuICAgKiAtIGluIHZpdGUgYXBwczpcbiAgICogICB0aGUgJ2FwcCcgcGFydCBfbWF5XyBiZSBgc3JjYCwgc28gd2UgYWxzbyBuZWVkIHRvIGVuc3VyZSB0aGF0IGBzcmNgIGlzIGV4Y2x1ZGVkIGFzIHdlbGxcbiAgICovXG4gIGxldCBoYXNBcHBEaXIgPSBmaWxlTmFtZS5pbmNsdWRlcyhwYXRoLmpvaW4od29ya3NwYWNlLCAnYXBwJykpO1xuICBsZXQgaGFzU3JjRGlyID0gZmlsZU5hbWUuaW5jbHVkZXMocGF0aC5qb2luKHdvcmtzcGFjZSwgJ3NyYycpKTtcblxuICBpZiAoXG4gICAgIShoYXNBcHBEaXIgfHwgaGFzU3JjRGlyKSAmJlxuICAgICFmaWxlTmFtZS5pbmNsdWRlcyhsZWFkaW5nU2xhc2hQYXRoLmVtYnJvaWRlckRpcilcbiAgKSB7XG4gICAgbGV0IG1heWJlTW9kdWxlID0gZmlsZU5hbWUucmVwbGFjZSh3b3Jrc3BhY2UsICcnKTtcbiAgICBsZXQgW21heWJlU2NvcGUsIC4uLnJlc3RdID0gbWF5YmVNb2R1bGUuc3BsaXQocGF0aC5zZXApLmZpbHRlcihCb29sZWFuKTtcbiAgICBsZXQgcGFydHMgPSByZXN0O1xuXG4gICAgaWYgKG1heWJlU2NvcGUuc3RhcnRzV2l0aCgnQCcpKSB7XG4gICAgICBsZXQgWywgLi4ucmVzdGVyXSA9IHJlc3Q7XG5cbiAgICAgIHBhcnRzID0gcmVzdGVyO1xuICAgIH1cblxuICAgIGxldCByZWxhdGl2ZSA9IHBhdGguam9pbiguLi5wYXJ0cyk7XG5cbiAgICAvKipcbiAgICAgKiBXZSBkb24ndCBhY3R1YWxseSBrbm93IGlmIHRoaXMgZmlsZSBpcyBhbiBhcHAuXG4gICAgICogaXQgY291bGQgYmUgYW4gYWRkb24gKHYxIG9yIHYyKVxuICAgICAqXG4gICAgICogU28gaGVyZSB3ZSBsb2cgdG8gc2VlIGlmIHdlIGhhdmUgdW5oYW5kbGVkIHNpdHVhdGlvbnMuXG4gICAgICovXG4gICAgbGV0IGNhbmRpZGF0ZVBhdGggPSBwYXRoLmpvaW4od29ya3NwYWNlLCAnYXBwJywgcmVsYXRpdmUpO1xuXG4gICAgcmV0dXJuIGNhbmRpZGF0ZVBhdGg7XG4gIH1cblxuICAvLyBUT0RPOiB3aHkgYXJlIHdlIHBhc3NlZCBmaWxlcyB0byBvdGhlciBwcm9qZWN0cz9cbiAgaWYgKCFmaWxlTmFtZS5pbmNsdWRlcyh3b3Jrc3BhY2UpKSB7XG4gICAgcmV0dXJuIGZpbGVOYW1lO1xuICB9XG5cbiAgLy8gRmFsbGJhY2sgdG8gd2hhdCB0aGUgcGx1Z2luIHN5c3RlbSBnaXZlcyB1cy5cbiAgLy8gVGhpcyBtYXkgYmUgd3JvbmcsIGFuZCBpZiB3cm9uZywgcmV2ZWFsc1xuICAvLyB1bmhhbmRsZWQgc2NlbmFyaW9zIHdpdGggdGhlIGZpbGUgbmFtZXMgaW4gdGhlIHBsdWdpbiBpbmZyYVxuICByZXR1cm4gZmlsZU5hbWU7XG59XG4iLCJpbXBvcnQgKiBhcyByZWNhc3QgZnJvbSAnZW1iZXItdGVtcGxhdGUtcmVjYXN0JztcblxuaW1wb3J0IHsgcmVuYW1lQ2xhc3MgfSBmcm9tICcuL3JlbmFtZUNsYXNzLmpzJztcblxuLyoqXG4gKiBXaGV0aGVyIGFuIGVsZW1lbnQgbWF5IGNhcnJ5IGFuIGF0dHJpYnV0ZSB0aGF0IGFwcGVhcnMgaW4gYSBzY29wZWRcbiAqIGF0dHJpYnV0ZSBzZWxlY3Rvci4gVGhpcyBpbmNsdWRlcyBjb21wb25lbnQgaW52b2NhdGlvbnM6IGEgY29tcG9uZW50XG4gKiByZWNlaXZlcyB0aGUgcG9zdGZpeCBjbGFzcyB0aHJvdWdoIGl0cyBgLi4uYXR0cmlidXRlc2AgdGhlIHNhbWUgd2F5IGl0XG4gKiByZWNlaXZlcyB0aGUgbWF0Y2hlZCBhdHRyaWJ1dGUsIHNvIGBbdHlwZT1cInRleHRcIl1gIHNjb3Blc1xuICogYDxGb28gdHlwZT1cInRleHRcIj5gIGp1c3QgYXMgaXQgc2NvcGVzIGA8aW5wdXQgdHlwZT1cInRleHRcIj5gLlxuICpcbiAqIEFuIGVsZW1lbnQgdGhhdCBzcHJlYWRzIGAuLi5hdHRyaWJ1dGVzYCBjYW4gcmVjZWl2ZSBhbnkgYXR0cmlidXRlIGZyb20gaXRzXG4gKiBjYWxsZXIgYXQgcnVudGltZSwgc28gaXQgY291bnRzIGFzIGxvbmcgYXMgdGhlIENTUyBzY29wZXMgYnkgYXR0cmlidXRlIGF0XG4gKiBhbGwg4oCUIHRoZSBwcmVzZXJ2ZWQgYXR0cmlidXRlIHNlbGVjdG9yIHN0aWxsIGRlY2lkZXMgd2hpY2ggcnVsZXMgYWN0dWFsbHlcbiAqIGFwcGx5LlxuICpcbiAqIGBhdHRyaWJ1dGVzYCBjb21lcyBmcm9tIHBhcnNpbmcgdGhlIENTUywgc28gaXQgY2FuIG9ubHkgY29udGFpbiB2YWxpZFxuICogYXR0cmlidXRlLXNlbGVjdG9yIG5hbWVzIOKAlCBgQGFyZ3NgIGNhbiBuZXZlciBiZSBpbiBpdCBhbmQgbmVlZHMgbm8gc3BlY2lhbFxuICogaGFuZGxpbmcuXG4gKlxuICogTmFtZXMgaW4gYGF0dHJpYnV0ZXNgIGFyZSBsb3dlcmNhc2VkIGF0IGRpc2NvdmVyeSAoQ1NTIG1hdGNoZXMgSFRNTFxuICogYXR0cmlidXRlIG5hbWVzIGNhc2UtaW5zZW5zaXRpdmVseSksIHNvIGNvbXBhcmUgbG93ZXJjYXNlZC5cbiAqL1xuZnVuY3Rpb24gZWxlbWVudEhhc1Njb3BlZEF0dHJpYnV0ZShub2RlLCBhdHRyaWJ1dGVzKSB7XG4gIGlmIChhdHRyaWJ1dGVzLnNpemUgPT09IDApIHJldHVybiBmYWxzZTtcblxuICByZXR1cm4gbm9kZS5hdHRyaWJ1dGVzLnNvbWUoXG4gICAgKGF0dHIpID0+XG4gICAgICBhdHRyLm5hbWUgPT09ICcuLi5hdHRyaWJ1dGVzJyB8fCBhdHRyaWJ1dGVzLmhhcyhhdHRyLm5hbWUudG9Mb3dlckNhc2UoKSksXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0ZW1wbGF0ZVBsdWdpbih7IGNsYXNzZXMsIHRhZ3MsIGF0dHJpYnV0ZXMsIHBvc3RmaXggfSkge1xuICBsZXQgc3RhY2sgPSBbXTtcbiAgLy8gc2NvcGVkLWNsYXNzIGlzIGEgZ2xvYmFsIHdlIGFsbG93IGluIGhic1xuICAvLyBzY29wZWRDbGFzcyBpcyBpbXBvcnRhYmxlLCBhbmQgd2UnbGwgZXJyb3IgaWYgc29tZW9uZSB0cmllcyB0byByZW5hbWUgaXRcbiAgbGV0IHNjb3BlZENsYXNzQ2FuZGlkYXRlcyA9IFsnc2NvcGVkLWNsYXNzJywgJ3Njb3BlZENsYXNzJ107XG5cbiAgZnVuY3Rpb24gaXNTY29wZWRDbGFzcyhzdHIpIHtcbiAgICBpZiAoIXN0cikgcmV0dXJuIGZhbHNlO1xuXG4gICAgcmV0dXJuIHNjb3BlZENsYXNzQ2FuZGlkYXRlcy5zb21lKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZSA9PT0gc3RyKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgQXR0ck5vZGUobm9kZSkge1xuICAgICAgaWYgKG5vZGUubmFtZSA9PT0gJ2NsYXNzJykge1xuICAgICAgICBpZiAobm9kZS52YWx1ZS50eXBlID09PSAnVGV4dE5vZGUnICYmIG5vZGUudmFsdWUuY2hhcnMpIHtcbiAgICAgICAgICBjb25zdCByZW5hbWVkQ2xhc3MgPSByZW5hbWVDbGFzcyhub2RlLnZhbHVlLmNoYXJzLCBwb3N0Zml4LCBjbGFzc2VzKTtcblxuICAgICAgICAgIG5vZGUudmFsdWUuY2hhcnMgPSByZW5hbWVkQ2xhc3M7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZS52YWx1ZS50eXBlID09PSAnQ29uY2F0U3RhdGVtZW50Jykge1xuICAgICAgICAgIGZvciAobGV0IHBhcnQgb2Ygbm9kZS52YWx1ZS5wYXJ0cykge1xuICAgICAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gJ1RleHROb2RlJyAmJiBwYXJ0LmNoYXJzKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlbmFtZWRDbGFzcyA9IHJlbmFtZUNsYXNzKHBhcnQuY2hhcnMsIHBvc3RmaXgsIGNsYXNzZXMpO1xuXG4gICAgICAgICAgICAgIHBhcnQuY2hhcnMgPSByZW5hbWVkQ2xhc3M7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBhcnQudHlwZSA9PT0gJ011c3RhY2hlU3RhdGVtZW50Jykge1xuICAgICAgICAgICAgICByZWNhc3QudHJhdmVyc2UocGFydCwge1xuICAgICAgICAgICAgICAgIFN0cmluZ0xpdGVyYWwobm9kZSkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgcmVuYW1lZENsYXNzID0gcmVuYW1lQ2xhc3MoXG4gICAgICAgICAgICAgICAgICAgIG5vZGUudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHBvc3RmaXgsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzZXMsXG4gICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICBub2RlLnZhbHVlID0gcmVuYW1lZENsYXNzO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBFbGVtZW50Tm9kZShub2RlKSB7XG4gICAgICAvLyBBbiBlbGVtZW50IGlzIGluIHNjb3BlIGlmIGl0cyB0YWcgbWF0Y2hlcyBhIHRhZyBzZWxlY3Rvciwgb3IgaWYgaXRcbiAgICAgIC8vIGNhcnJpZXMgYW4gYXR0cmlidXRlIG5hbWVkIGluIGEgc2NvcGVkIGF0dHJpYnV0ZSBzZWxlY3Rvci4gV2UgYWRkIHRoZVxuICAgICAgLy8gcG9zdGZpeCBjbGFzcyBhdCBtb3N0IG9uY2UgcmVnYXJkbGVzcyBvZiBob3cgbWFueSB0aGluZ3MgbWF0Y2hlZC5cbiAgICAgIGNvbnN0IHNob3VsZFNjb3BlID1cbiAgICAgICAgdGFncy5oYXMobm9kZS50YWcpIHx8IGVsZW1lbnRIYXNTY29wZWRBdHRyaWJ1dGUobm9kZSwgYXR0cmlidXRlcyk7XG5cbiAgICAgIGlmICghc2hvdWxkU2NvcGUpIHJldHVybjtcblxuICAgICAgLy8gY2hlY2sgaWYgY2xhc3MgYXR0cmlidXRlIGFscmVhZHkgZXhpc3RzXG4gICAgICBjb25zdCBjbGFzc0F0dHIgPSBub2RlLmF0dHJpYnV0ZXMuZmluZCgoYXR0cikgPT4gYXR0ci5uYW1lID09PSAnY2xhc3MnKTtcblxuICAgICAgaWYgKCFjbGFzc0F0dHIpIHtcbiAgICAgICAgLy8gcHVzaCBjbGFzcyBhdHRyaWJ1dGVcbiAgICAgICAgbm9kZS5hdHRyaWJ1dGVzLnB1c2goXG4gICAgICAgICAgcmVjYXN0LmJ1aWxkZXJzLmF0dHIoJ2NsYXNzJywgcmVjYXN0LmJ1aWxkZXJzLnRleHQocG9zdGZpeCkpLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChjbGFzc0F0dHIudmFsdWUudHlwZSA9PT0gJ1RleHROb2RlJykge1xuICAgICAgICBjbGFzc0F0dHIudmFsdWUuY2hhcnMgKz0gJyAnICsgcG9zdGZpeDtcbiAgICAgIH0gZWxzZSBpZiAoY2xhc3NBdHRyLnZhbHVlLnR5cGUgPT09ICdDb25jYXRTdGF0ZW1lbnQnKSB7XG4gICAgICAgIC8vIGNsYXNzPVwiZm9vIHt7YmFyfX1cIlxuICAgICAgICBjbGFzc0F0dHIudmFsdWUucGFydHMucHVzaChyZWNhc3QuYnVpbGRlcnMudGV4dCgnICcgKyBwb3N0Zml4KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjbGFzcz17e3RoaXMuZm9vfX0g4oCUIHdyYXAgaW4gYSBjb25jYXQgc28gd2UgY2FuIGFwcGVuZCB0aGUgdGV4dCBwYXJ0XG4gICAgICAgIGNsYXNzQXR0ci52YWx1ZSA9IHJlY2FzdC5idWlsZGVycy5jb25jYXQoW1xuICAgICAgICAgIGNsYXNzQXR0ci52YWx1ZSxcbiAgICAgICAgICByZWNhc3QuYnVpbGRlcnMudGV4dCgnICcgKyBwb3N0Zml4KSxcbiAgICAgICAgXSk7XG4gICAgICAgIGNsYXNzQXR0ci5xdW90ZVR5cGUgPSAnXCInO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBBbGw6IHtcbiAgICAgIGVudGVyKG5vZGUpIHtcbiAgICAgICAgc3RhY2sucHVzaChub2RlKTtcbiAgICAgIH0sXG4gICAgICBleGl0KCkge1xuICAgICAgICBzdGFjay5wb3AoKTtcbiAgICAgIH0sXG4gICAgfSxcblxuICAgIE11c3RhY2hlU3RhdGVtZW50KG5vZGUpIHtcbiAgICAgIGxldCBjc3NDbGFzcztcblxuICAgICAgaWYgKFxuICAgICAgICBpc1Njb3BlZENsYXNzKGdldFZhbHVlKG5vZGUucGF0aCkpICYmXG4gICAgICAgIG5vZGUucGFyYW1zPy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgbm9kZS5wYXJhbXNbMF0udHlwZSA9PT0gJ1N0cmluZ0xpdGVyYWwnXG4gICAgICApIHtcbiAgICAgICAgY3NzQ2xhc3MgPSBub2RlLnBhcmFtc1swXS52YWx1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBpc1Njb3BlZENsYXNzKGdldFZhbHVlKG5vZGUucGF0aD8ucGF0aCkpICYmXG4gICAgICAgIG5vZGUucGF0aD8ucGFyYW1zPy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgbm9kZS5wYXRoPy5wYXJhbXNbMF0udHlwZSA9PT0gJ1N0cmluZ0xpdGVyYWwnXG4gICAgICApIHtcbiAgICAgICAgY3NzQ2xhc3MgPSBub2RlLnBhdGgucGFyYW1zWzBdLnZhbHVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY3NzQ2xhc3MpIHtcbiAgICAgICAgY29uc3QgdGV4dE5vZGUgPSByZWNhc3QuYnVpbGRlcnMudGV4dChyZW5hbWVDbGFzcyhjc3NDbGFzcywgcG9zdGZpeCkpO1xuICAgICAgICBjb25zdCBwYXJlbnQgPSBzdGFja1tzdGFjay5sZW5ndGggLSAxXTtcblxuICAgICAgICBpZiAocGFyZW50Py50eXBlID09PSAnQXR0ck5vZGUnKSB7XG4gICAgICAgICAgcGFyZW50LnF1b3RlVHlwZSA9ICdcIic7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGV4dE5vZGU7XG4gICAgICB9XG4gICAgfSxcblxuICAgIFN1YkV4cHJlc3Npb24obm9kZSkge1xuICAgICAgaWYgKFxuICAgICAgICBpc1Njb3BlZENsYXNzKGdldFZhbHVlKG5vZGUucGF0aCkpICYmXG4gICAgICAgIG5vZGUucGFyYW1zPy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgbm9kZS5wYXJhbXNbMF0udHlwZSA9PT0gJ1N0cmluZ0xpdGVyYWwnXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgY3NzQ2xhc3MgPSBub2RlLnBhcmFtc1swXS52YWx1ZTtcbiAgICAgICAgY29uc3QgdGV4dE5vZGUgPSByZWNhc3QuYnVpbGRlcnMubGl0ZXJhbChcbiAgICAgICAgICAnU3RyaW5nTGl0ZXJhbCcsXG4gICAgICAgICAgcmVuYW1lQ2xhc3MoY3NzQ2xhc3MsIHBvc3RmaXgpLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB0ZXh0Tm9kZTtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRWYWx1ZShwYXRoKSB7XG4gIGlmICghcGF0aCkgcmV0dXJuO1xuXG4gIGlmICgndmFsdWUnIGluIHBhdGgpIHtcbiAgICByZXR1cm4gcGF0aC52YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGVtYmVyIDUuOStcbiAgICogKHNvIHdlIHVzZSB0aGUgYWJvdmUgZm9yIG5ld2VyIGVtYmVycylcbiAgICovXG4gIHJldHVybiBwYXRoLm9yaWdpbmFsO1xufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiByZXdyaXRlSGJzKFxuICBoYnMsXG4gIGNsYXNzZXMsXG4gIHRhZ3MsXG4gIHBvc3RmaXgsXG4gIGF0dHJpYnV0ZXMgPSBuZXcgU2V0KCksXG4pIHtcbiAgbGV0IGFzdCA9IHJlY2FzdC5wYXJzZShoYnMpO1xuXG4gIHJlY2FzdC50cmF2ZXJzZShhc3QsIHRlbXBsYXRlUGx1Z2luKHsgY2xhc3NlcywgdGFncywgYXR0cmlidXRlcywgcG9zdGZpeCB9KSk7XG5cbiAgbGV0IHJlc3VsdCA9IHJlY2FzdC5wcmludChhc3QpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG4iLCIvKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoJ0BnbGltbWVyL3N5bnRheCcpLkFTVFBsdWdpbn0gQVNUUGx1Z2luXG4gKiBAdHlwZWRlZiB7aW1wb3J0KCdAZ2xpbW1lci9zeW50YXgnKS5BU1RQbHVnaW5FbnZpcm9ubWVudH0gQVNUUGx1Z2luRW52aXJvbm1lbnRcbiAqXG4gKi9cblxuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbmltcG9ydCB7IHJld3JpdGVDc3MgfSBmcm9tICcuLi9saWIvY3NzL3Jld3JpdGUuanMnO1xuaW1wb3J0IHsgZ2V0Q1NTQ29udGVudEluZm8sIGdldENTU0luZm8gfSBmcm9tICcuLi9saWIvY3NzL3V0aWxzLmpzJztcbmltcG9ydCB7IGZpeEZpbGVuYW1lIH0gZnJvbSAnLi4vbGliL3BhdGgvdGVtcGxhdGUtdHJhbnNmb3JtLXBhdGhzLmpzJztcbmltcG9ydCB7XG4gIGFwcFBhdGgsXG4gIGNzc1BhdGhGb3IsXG4gIGZvcmNlUG9zaXgsXG4gIGhhc2hGcm9tTW9kdWxlUGF0aCxcbiAgaXNSZWxldmFudEZpbGUsXG59IGZyb20gJy4uL2xpYi9wYXRoL3V0aWxzLmpzJztcbmltcG9ydCB7IHJlcXVlc3QgfSBmcm9tICcuLi9saWIvcmVxdWVzdC5qcyc7XG5pbXBvcnQgeyB0ZW1wbGF0ZVBsdWdpbiB9IGZyb20gJy4uL2xpYi9yZXdyaXRlSGJzLmpzJztcblxuY29uc3Qgbm9vcFBsdWdpbiA9IHtcbiAgbmFtZTogJ2VtYmVyLXNjb3BlZC1jc3M6bm9vcCcsXG4gIHZpc2l0b3I6IHt9LFxufTtcblxuLyoqXG4gKiBAcmV0dXJucyB7QVNUUGx1Z2lufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUGx1Z2luKGNvbmZpZykge1xuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtBU1RQbHVnaW5FbnZpcm9ubWVudH0gZW52XG4gICAqL1xuICByZXR1cm4gZnVuY3Rpb24gc2NvcGVkQ3NzKGVudikge1xuICAgIGxldCBjd2QgPSBwcm9jZXNzLmN3ZCgpO1xuXG4gICAgbGV0IGlzUmVsZXZhbnQgPSBpc1JlbGV2YW50RmlsZShlbnYuZmlsZW5hbWUsIHtcbiAgICAgIGFkZGl0aW9uYWxSb290czogY29uZmlnLmFkZGl0aW9uYWxSb290cyxcbiAgICAgIGN3ZCxcbiAgICB9KTtcblxuICAgIGlmICghaXNSZWxldmFudCkge1xuICAgICAgcmV0dXJuIG5vb3BQbHVnaW47XG4gICAgfVxuXG4gICAgbGV0IGFic29sdXRlUGF0aCA9IGZpeEZpbGVuYW1lKGVudi5maWxlbmFtZSk7XG4gICAgbGV0IG1vZHVsZVBhdGggPSBhcHBQYXRoKGFic29sdXRlUGF0aCk7XG4gICAgbGV0IHBvc3RmaXggPSBoYXNoRnJvbU1vZHVsZVBhdGgobW9kdWxlUGF0aCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbGlzdCBvZiBuYWtlZCB0YWcgc2VsZWN0b3JzIGZvdW5kIGluIHRoZSBDU1NcbiAgICAgKlxuICAgICAqIEB0eXBlIHtTZXQ8c3RyaW5nPn1cbiAgICAgKi9cbiAgICBsZXQgc2NvcGVkVGFncyA9IG5ldyBTZXQoKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBsaXN0IG9mIGNsYXNzZXMgZm91bmQgaW4gdGhlIENTU1xuICAgICAqXG4gICAgICogQHR5cGUge1NldDxzdHJpbmc+fVxuICAgICAqL1xuICAgIGxldCBzY29wZWRDbGFzc2VzID0gbmV3IFNldCgpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGF0dHJpYnV0ZSBuYW1lcyBmb3VuZCBpbiBhdHRyaWJ1dGUgc2VsZWN0b3JzIGluIHRoZSBDU1MsIHVzZWQgdG9cbiAgICAgKiBtYXJrIG1hdGNoaW5nIGVsZW1lbnRzIHdpdGggdGhlIHNjb3BlIGNsYXNzLlxuICAgICAqXG4gICAgICogQHR5cGUge1NldDxzdHJpbmc+fVxuICAgICAqL1xuICAgIGxldCBzY29wZWRBdHRyaWJ1dGVzID0gbmV3IFNldCgpO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHt7IHRhZ3M6IFNldDxzdHJpbmc+OyBjbGFzc2VzOiBTZXQ8c3RyaW5nPjsgYXR0cmlidXRlczogU2V0PHN0cmluZz4gfX0gaW5mb1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFkZEluZm8oaW5mbykge1xuICAgICAgZm9yIChsZXQgaXRlbSBvZiBpbmZvLnRhZ3MpIHtcbiAgICAgICAgc2NvcGVkVGFncy5hZGQoaXRlbSk7XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGl0ZW0gb2YgaW5mby5jbGFzc2VzKSB7XG4gICAgICAgIHNjb3BlZENsYXNzZXMuYWRkKGl0ZW0pO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpdGVtIG9mIGluZm8uYXR0cmlidXRlcykge1xuICAgICAgICBzY29wZWRBdHRyaWJ1dGVzLmFkZChpdGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgY3NzUGF0aCA9IGNzc1BhdGhGb3IoYWJzb2x1dGVQYXRoKTtcbiAgICBsZXQgaW5mbyA9IGdldENTU0luZm8oY3NzUGF0aCk7XG4gICAgbGV0IGxvY2FsQ3NzUGF0aCA9IGZvcmNlUG9zaXgoY3NzUGF0aC5yZXBsYWNlKGN3ZCArIHBhdGguc2VwLCAnJykpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyB3aWxsIGJlIGZhbHNleSBpZiB3ZSBkb24ndCBoYXZlIGEgY28tbG9jYXRlZCBDU1MgZmlsZS5cbiAgICAgKiBXZSdsbCBzdGlsbCB3YW50IHRvIGNoZWNrIGZvciBlbWJlZGRlZCA8c3R5bGUgc2NvcGVkPiB0YWdzIHRob3VnaC5cbiAgICAgKi9cbiAgICBpZiAoaW5mbykge1xuICAgICAgYWRkSW5mbyhpbmZvKTtcblxuICAgICAgbGV0IGNzc1JlcXVlc3QgPSByZXF1ZXN0LmNvbG9jYXRlZC5jcmVhdGUoaW5mby5pZCwgcG9zdGZpeCwgbG9jYWxDc3NQYXRoKTtcblxuICAgICAgLyoqXG4gICAgICAgKiBXaXRoIHRoaXMgd2UgZG9uJ3QgbmVlZCBhIEpTIHBsdWdpblxuICAgICAgICovXG4gICAgICBlbnYubWV0YS5qc3V0aWxzLmltcG9ydEZvclNpZGVFZmZlY3QoY3NzUmVxdWVzdCk7XG4gICAgfVxuXG4gICAgbGV0IHZpc2l0b3JzID0gdGVtcGxhdGVQbHVnaW4oe1xuICAgICAgY2xhc3Nlczogc2NvcGVkQ2xhc3NlcyxcbiAgICAgIHRhZ3M6IHNjb3BlZFRhZ3MsXG4gICAgICBhdHRyaWJ1dGVzOiBzY29wZWRBdHRyaWJ1dGVzLFxuICAgICAgcG9zdGZpeCxcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnZW1iZXItc2NvcGVkLWNzczp0ZW1wbGF0ZS1wbHVnaW4nLFxuICAgICAgdmlzaXRvcjoge1xuICAgICAgICAvLyBTdGFjayBNYW5hZ2VyXG4gICAgICAgIC4uLnZpc2l0b3JzLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSBoYXZlIHRvIGVhZ2VybHkgZ2V0IHRoZSA8c3R5bGUgc2NvcGVkPiBjb250ZW50cywgc28gd2UgY2FuIHByZS1wYXJzZVxuICAgICAgICAgKiB0aGUgdGFncyBhbmQgY2xhc3NlcyB0byB0aGVuIHBhc3MgdG8gdGhlIG90aGVyIHZpc2l0b3JzIHNvIHRoYXQgdGhleSBjYW5cbiAgICAgICAgICogYXBwcm9wcmlhdGVseSBjaGFuZ2UgbWF0Y2hpbmcgY2xhc3NlcyAvIHRhZ3MuXG4gICAgICAgICAqL1xuICAgICAgICBUZW1wbGF0ZShub2RlKSB7XG4gICAgICAgICAgLyoqXG4gICAgICAgICAgICogV2Ugb25seSBhbGxvdyBhIHNjb3BlZCA8c3R5bGU+IGF0IHRoZSByb290XG4gICAgICAgICAgICovXG4gICAgICAgICAgbGV0IHN0eWxlVGFnID0gbm9kZS5ib2R5LmZpbmQoXG4gICAgICAgICAgICAobikgPT4gbi50eXBlID09PSAnRWxlbWVudE5vZGUnICYmIG4udGFnID09PSAnc3R5bGUnLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoaGFzU2NvcGVkQXR0cmlidXRlKHN0eWxlVGFnKSkge1xuICAgICAgICAgICAgbGV0IGNzcyA9IHRleHRDb250ZW50KHN0eWxlVGFnKTtcbiAgICAgICAgICAgIGxldCBsYW5nID0gZ2V0TGFuZ0F0dHJpYnV0ZShzdHlsZVRhZyk7XG4gICAgICAgICAgICBsZXQgaW5mbyA9IGdldENTU0NvbnRlbnRJbmZvKGNzcywgbGFuZyk7XG5cbiAgICAgICAgICAgIGFkZEluZm8oaW5mbyk7XG5cbiAgICAgICAgICAgIGlmIChoYXNJbmxpbmVBdHRyaWJ1dGVXaXRob3V0TGFuZyhzdHlsZVRhZykpIHtcbiAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAqIFRoaXMgd2lsbCBiZSBoYW5kbGVkIGluIEVsZW1lbnROb2RlIHRyYXZlcnNhbFxuICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobGFuZykge1xuICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICogRm9yIDxzdHlsZSBzY29wZWQgaW5saW5lIGxhbmc9XCIuLi5cIj4gd2UgY2Fubm90IHByZXByb2Nlc3MgYXQgQmFiZWwtdGltZVxuICAgICAgICAgICAgICAgKiAocHJlcHJvY2Vzc2luZyBpcyBhc3luYyBhbmQgcmVxdWlyZXMgVml0ZSdzIFJlc29sdmVkQ29uZmlnKS5cbiAgICAgICAgICAgICAgICogUmVtb3ZlIHRoZSB0YWcgYW5kIGluamVjdCB2aWEgdmlydHVhbCBDU1MgbW9kdWxlIGFuZCB3YXJuIHVzZXIuXG4gICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgYFtlbWJlci1zY29wZWQtY3NzXSA8c3R5bGUgc2NvcGVkIGlubGluZSBsYW5nPVwiJHtsYW5nfVwiPiBpcyBub3Qgc3VwcG9ydGVkIGAgK1xuICAgICAgICAgICAgICAgICAgYChwcmVwcm9jZXNzaW5nIGlzIGFzeW5jIGFuZCBjYW5ub3QgcnVuIGF0IEJhYmVsLXRpbWUpLiBgICtcbiAgICAgICAgICAgICAgICAgIGBEb3duZ3JhZGluZyB0byBub24taW5saW5lOiB0aGUgc3R5bGUgdGFnIHdpbGwgYmUgcmVtb3ZlZCBhbmQgaW5qZWN0ZWQgYXMgYSB2aXJ0dWFsIENTUyBtb2R1bGUuYCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGNzc1JlcXVlc3QgPSByZXF1ZXN0LmlubGluZS5jcmVhdGUoaW5mby5pZCwgcG9zdGZpeCwgY3NzLCBsYW5nKTtcblxuICAgICAgICAgICAgZW52Lm1ldGEuanN1dGlscy5pbXBvcnRGb3JTaWRlRWZmZWN0KGNzc1JlcXVlc3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICAvLyBWaXNpdG9ycyBicm9rZW4gb3V0IGxpa2UgdGhpcyBzbyB3ZSBjYW4gY29uZGl0aW9uYWxseVxuICAgICAgICAvLyBkZWJ1ZyBiYXNlZCBvbiBmaWxlIHBhdGguXG4gICAgICAgIEF0dHJOb2RlKC4uLmFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gdmlzaXRvcnMuQXR0ck5vZGUoLi4uYXJncyk7XG4gICAgICAgIH0sXG4gICAgICAgIEVsZW1lbnROb2RlKG5vZGUsIHdhbGtlcikge1xuICAgICAgICAgIC8vIGNsYXNzIGF0dHJpYnV0ZSBoYW5kbGluZ1xuICAgICAgICAgIHZpc2l0b3JzLkVsZW1lbnROb2RlKG5vZGUsIHdhbGtlcik7XG5cbiAgICAgICAgICBpZiAoaGFzU2NvcGVkQXR0cmlidXRlKG5vZGUpKSB7XG4gICAgICAgICAgICBpZiAod2Fsa2VyLnBhcmVudD8ubm9kZS50eXBlICE9PSAnVGVtcGxhdGUnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAnPHN0eWxlIHNjb3BlZD4gdGFncyBtdXN0IGJlIGF0IHRoZSByb290IG9mIHRoZSB0ZW1wbGF0ZSwgdGhleSBjYW5ub3QgYmUgbmVzdGVkJyxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhhc0lubGluZUF0dHJpYnV0ZVdpdGhvdXRMYW5nKG5vZGUpKSB7XG4gICAgICAgICAgICAgIGxldCB0ZXh0ID0gdGV4dENvbnRlbnQobm9kZSk7XG4gICAgICAgICAgICAgIGxldCBzY29wZWRUZXh0ID0gcmV3cml0ZUNzcyhcbiAgICAgICAgICAgICAgICB0ZXh0LFxuICAgICAgICAgICAgICAgIHBvc3RmaXgsXG4gICAgICAgICAgICAgICAgbG9jYWxDc3NQYXRoLFxuICAgICAgICAgICAgICAgIGNvbmZpZy5sYXllck5hbWUsXG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAqIFRyYXZlcnNlIHRoaXMgYW5kIGFsbG93IGludGVycG9sYXRpb25cbiAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgIG5vZGUuY2hpbGRyZW4gPSBbZW52LnN5bnRheC5idWlsZGVycy50ZXh0KHNjb3BlZFRleHQpXTtcblxuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJldHVybmluZyBudWxsIHJlbW92ZXMgdGhlIG5vZGVcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYXNJbmxpbmVBdHRyaWJ1dGVXaXRob3V0TGFuZyhub2RlKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgPHN0eWxlIGlubGluZT4gaXMgbm90IHZhbGlkLiBQbGVhc2UgYWRkIHRoZSBzY29wZWQgYXR0cmlidXRlOiA8c3R5bGUgc2NvcGVkIGlubGluZT5gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIE11c3RhY2hlU3RhdGVtZW50KC4uLmFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gdmlzaXRvcnMuTXVzdGFjaGVTdGF0ZW1lbnQoLi4uYXJncyk7XG4gICAgICAgIH0sXG4gICAgICAgIFN1YkV4cHJlc3Npb24oLi4uYXJncykge1xuICAgICAgICAgIHJldHVybiB2aXNpdG9ycy5TdWJFeHByZXNzaW9uKC4uLmFyZ3MpO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9O1xufVxuXG4vKipcbiAqIFRoYW5rcywgQ2FyZFN0YWNrIGFuZCBAZWY0IGZvciB0aGlzIGNvZGUuXG4gKi9cbmNvbnN0IFNDT1BFRF9BVFRSSUJVVEVfTkFNRSA9ICdzY29wZWQnO1xuY29uc3QgSU5MSU5FX0FUVFJJQlVURV9OQU1FID0gJ2lubGluZSc7XG5jb25zdCBMQU5HX0FUVFJJQlVURV9OQU1FID0gJ2xhbmcnO1xuXG5mdW5jdGlvbiBoYXNTY29wZWRBdHRyaWJ1dGUobm9kZSkge1xuICBpZiAoIW5vZGUpIHJldHVybjtcbiAgaWYgKG5vZGUudGFnICE9PSAnc3R5bGUnKSByZXR1cm47XG4gIGlmIChub2RlLnR5cGUgIT09ICdFbGVtZW50Tm9kZScpIHJldHVybjtcblxuICByZXR1cm4gbm9kZS5hdHRyaWJ1dGVzLnNvbWUoXG4gICAgKGF0dHJpYnV0ZSkgPT4gYXR0cmlidXRlLm5hbWUgPT09IFNDT1BFRF9BVFRSSUJVVEVfTkFNRSxcbiAgKTtcbn1cblxuZnVuY3Rpb24gaGFzSW5saW5lQXR0cmlidXRlV2l0aG91dExhbmcobm9kZSkge1xuICBpZiAoIW5vZGUpIHJldHVybjtcbiAgaWYgKG5vZGUudGFnICE9PSAnc3R5bGUnKSByZXR1cm47XG4gIGlmIChub2RlLnR5cGUgIT09ICdFbGVtZW50Tm9kZScpIHJldHVybjtcblxuICBpZiAoZ2V0TGFuZ0F0dHJpYnV0ZShub2RlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBub2RlLmF0dHJpYnV0ZXMuc29tZShcbiAgICAoYXR0cmlidXRlKSA9PiBhdHRyaWJ1dGUubmFtZSA9PT0gSU5MSU5FX0FUVFJJQlVURV9OQU1FLFxuICApO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBgbGFuZ2AgYXR0cmlidXRlIG9uIGEgYDxzdHlsZT5gIG5vZGUsIG9yIG51bGwgaWYgYWJzZW50LlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBub2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nIHwgbnVsbH1cbiAqL1xuZnVuY3Rpb24gZ2V0TGFuZ0F0dHJpYnV0ZShub2RlKSB7XG4gIGlmICghbm9kZSkgcmV0dXJuIG51bGw7XG4gIGlmIChub2RlLnRhZyAhPT0gJ3N0eWxlJykgcmV0dXJuIG51bGw7XG4gIGlmIChub2RlLnR5cGUgIT09ICdFbGVtZW50Tm9kZScpIHJldHVybiBudWxsO1xuXG4gIGNvbnN0IGF0dHIgPSBub2RlLmF0dHJpYnV0ZXMuZmluZChcbiAgICAoYXR0cmlidXRlKSA9PiBhdHRyaWJ1dGUubmFtZSA9PT0gTEFOR19BVFRSSUJVVEVfTkFNRSxcbiAgKTtcblxuICBpZiAoIWF0dHIpIHJldHVybiBudWxsO1xuXG4gIC8vIFRoZSBhdHRyaWJ1dGUgdmFsdWUgaXMgYSBUZXh0Tm9kZSBjaGlsZCBvZiB0aGUgQXR0ck5vZGUncyB2YWx1ZVxuICBjb25zdCB2YWx1ZSA9IGF0dHIudmFsdWU7XG5cbiAgaWYgKHZhbHVlPy50eXBlID09PSAnVGV4dE5vZGUnKSByZXR1cm4gdmFsdWUuY2hhcnMgfHwgbnVsbDtcblxuICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gdGV4dENvbnRlbnQobm9kZSkge1xuICBsZXQgdGV4dENoaWxkcmVuID0gbm9kZS5jaGlsZHJlbi5maWx0ZXIoKGMpID0+IGMudHlwZSA9PT0gJ1RleHROb2RlJyk7XG5cbiAgcmV0dXJuIHRleHRDaGlsZHJlbi5tYXAoKGMpID0+IGMuY2hhcnMpLmpvaW4oJycpO1xufVxuIiwiaW1wb3J0ICogYXMgYmFiZWwgZnJvbSAnLi4vYmFiZWwtcGx1Z2luLmpzJztcbmltcG9ydCB7IHVucGx1Z2luIH0gZnJvbSAnLi4vc2NvcGVkLWNzcy11bnBsdWdpbi5qcyc7XG5pbXBvcnQgKiBhcyB0ZW1wbGF0ZSBmcm9tICcuLi90ZW1wbGF0ZS1wbHVnaW4uanMnO1xuXG5leHBvcnQgY29uc3Qgc2NvcGVkQ1NTID0ge1xuICB2aXRlOiB1bnBsdWdpbi52aXRlLFxuICByb2xsdXA6IHVucGx1Z2luLnJvbGx1cCxcbiAgYmFiZWw6IGJhYmVsLnNjb3BlZENTUyxcbiAgdGVtcGxhdGU6IHRlbXBsYXRlLmNyZWF0ZVBsdWdpbixcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFNQSxNQUFhLG1CQUFtQjtDQUM5QixjQUFjLGFBQUssS0FBSyw0QkFBNEI7Q0FDcEQsYUFBYSxhQUFLLEtBQUssY0FBYztDQUNyQyxlQUFlLGFBQUssS0FBSyxlQUFlO0NBQ3hDLGNBQWMsYUFBSyxLQUFLLGNBQWM7Q0FDdEMsV0FBVyxhQUFLLEtBQUssV0FBVztDQUNoQyxRQUFRLGFBQUssS0FBSyxVQUFVO0NBQzVCLEtBQUssYUFBSyxLQUFLLFFBQVE7Q0FDdkIsS0FBSyxhQUFLLEtBQUssUUFBUTtDQUN4QjtBQUVELE1BQWEsV0FBVyxFQUN0QixTQUFTLGFBQUssS0FBSyxxQkFBcUIsRUFDekM7Ozs7Ozs7Ozs7OztBQ1dELFNBQVMsUUFBUSxHQUFHLEdBQUc7Q0FDckIsSUFBSSxPQUFPLElBQUksVUFBVyxJQUFJO0FBRzlCLFNBRlcsS0FBSyxPQUFPLEtBQUssT0FBTyxPQUFPLE9BRTNCLEtBQU8sTUFBTTs7Ozs7Ozs7O0FBVTlCLFNBQVMsY0FBYyxLQUFLLEtBQUs7QUFDL0IsUUFBUSxPQUFPLE1BQVEsUUFBUyxLQUFLOzs7Ozs7Ozs7Ozs7O0FBY3ZDLFNBQVMsT0FBTyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRztBQUNoQyxRQUFPLFFBQVEsY0FBYyxRQUFRLFFBQVEsR0FBRyxFQUFFLEVBQUUsUUFBUSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFOzs7Ozs7Ozs7Ozs7OztBQWU1RSxTQUFTLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRztBQUNsQyxRQUFPLE9BQVEsSUFBSSxJQUFNLENBQUMsSUFBSSxHQUFJLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRTs7Ozs7Ozs7Ozs7Ozs7QUFlbEQsU0FBUyxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUc7QUFDbEMsUUFBTyxPQUFRLElBQUksSUFBTSxJQUFJLENBQUMsR0FBSSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUU7Ozs7Ozs7Ozs7Ozs7O0FBZWxELFNBQVMsTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHO0FBQ2xDLFFBQU8sT0FBTyxJQUFJLElBQUksR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUU7Ozs7Ozs7Ozs7Ozs7O0FBZXpDLFNBQVMsTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHO0FBQ2xDLFFBQU8sT0FBTyxLQUFLLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRTs7Ozs7Ozs7O0FBVTVDLFNBQVMsUUFBUSxHQUFHLEtBQUs7QUFFdkIsR0FBRSxPQUFPLE1BQU0sT0FBUSxNQUFNO0FBQzdCLElBQUssTUFBTSxPQUFRLEtBQU0sS0FBSyxNQUFNO0NBRXBDLElBQUk7Q0FDSixJQUFJO0NBQ0osSUFBSTtDQUNKLElBQUk7Q0FDSixJQUFJO0NBQ0osSUFBSSxJQUFJO0NBQ1IsSUFBSSxJQUFJO0NBQ1IsSUFBSSxJQUFJO0NBQ1IsSUFBSSxJQUFJO0FBRVIsTUFBSyxJQUFJLEdBQUcsSUFBSSxFQUFFLFFBQVEsS0FBSyxJQUFJO0FBQ2pDLFNBQU87QUFDUCxTQUFPO0FBQ1AsU0FBTztBQUNQLFNBQU87QUFFUCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksR0FBRyxXQUFXO0FBQzFDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksV0FBVztBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxJQUFJLFVBQVU7QUFDOUMsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxZQUFZO0FBQ2hELE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLEdBQUcsV0FBVztBQUM5QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxJQUFJLFdBQVc7QUFDL0MsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxZQUFZO0FBQ2hELE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksVUFBVTtBQUM5QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxHQUFHLFdBQVc7QUFDOUMsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxZQUFZO0FBQ2hELE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLElBQUksT0FBTztBQUM1QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFlBQVk7QUFDakQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssR0FBRyxXQUFXO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLElBQUksVUFBVTtBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFlBQVk7QUFDakQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxXQUFXO0FBRWhELE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLEdBQUcsV0FBVztBQUM5QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxHQUFHLFlBQVk7QUFDL0MsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxVQUFVO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLFdBQVc7QUFDM0MsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxXQUFXO0FBQzlDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLEdBQUcsU0FBUztBQUM3QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFdBQVc7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxXQUFXO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLEdBQUcsVUFBVTtBQUM3QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxHQUFHLFlBQVk7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxXQUFXO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksV0FBVztBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxHQUFHLFlBQVk7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxVQUFVO0FBQzdDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksV0FBVztBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFlBQVk7QUFFakQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxRQUFRO0FBQzNDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksWUFBWTtBQUNoRCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFdBQVc7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxVQUFVO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLEdBQUcsWUFBWTtBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxJQUFJLFdBQVc7QUFDL0MsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxXQUFXO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLElBQUksWUFBWTtBQUNqRCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxHQUFHLFVBQVU7QUFDOUMsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksV0FBVztBQUMzQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxJQUFJLFdBQVc7QUFDL0MsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxTQUFTO0FBQzdDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLEdBQUcsV0FBVztBQUM5QyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFdBQVc7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxVQUFVO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksV0FBVztBQUUvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksR0FBRyxXQUFXO0FBQzFDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksV0FBVztBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFlBQVk7QUFDakQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksSUFBSSxVQUFVO0FBQzlDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLEdBQUcsV0FBVztBQUMvQyxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxJQUFJLFlBQVk7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxTQUFTO0FBQzlDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksWUFBWTtBQUNoRCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxHQUFHLFdBQVc7QUFDOUMsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLEtBQUssSUFBSSxVQUFVO0FBQy9DLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLElBQUksWUFBWTtBQUNoRCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksS0FBSyxJQUFJLFdBQVc7QUFDaEQsTUFBSSxNQUFNLEdBQUcsR0FBRyxHQUFHLEdBQUcsRUFBRSxJQUFJLElBQUksR0FBRyxXQUFXO0FBQzlDLE1BQUksTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxLQUFLLElBQUksWUFBWTtBQUNqRCxNQUFJLE1BQU0sR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFF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
|