UNPKG

42.6 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.ShaderLibPreprocessor = exports.ShaderLibPlugin = exports.ShaderLib = exports.kDefaultShaderName = exports.kDefaultShaderLibVersion = exports.kDefaultShaderLibPrecision = undefined;
7
8var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
9
10var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
11
12var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
13
14var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
15
16var _dynamic = require('./dynamic');
17
18var _glsl = require('./glsl');
19
20var libglsl = _interopRequireWildcard(_glsl);
21
22var _command = require('./command');
23
24var _path = require('path');
25
26var _glslTokenDefines = require('glsl-token-defines');
27
28var _glslTokenDefines2 = _interopRequireDefault(_glslTokenDefines);
29
30var _glslTokenString = require('glsl-token-string');
31
32var _glslTokenString2 = _interopRequireDefault(_glslTokenString);
33
34var _glslInjectDefines = require('glsl-inject-defines');
35
36var _glslInjectDefines2 = _interopRequireDefault(_glslInjectDefines);
37
38var _glslTokenizer = require('glsl-tokenizer');
39
40var _glslTokenizer2 = _interopRequireDefault(_glslTokenizer);
41
42var _prepr = require('prepr');
43
44var _prepr2 = _interopRequireDefault(_prepr);
45
46var _defined = require('defined');
47
48var _defined2 = _interopRequireDefault(_defined);
49
50var _stringHash = require('string-hash');
51
52var _stringHash2 = _interopRequireDefault(_stringHash);
53
54function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
55
56function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
57
58function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
59
60function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
61
62function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
63
64var kGLSLTokenPreprocecsor = 'preprocessor';
65var kGLSLTokenBlockComment = 'block-comment';
66var kGLSLTokenLineComment = 'line-comment';
67var kDefaultShaderLibPrecision = exports.kDefaultShaderLibPrecision = 'mediump float';
68var kDefaultShaderLibVersion = exports.kDefaultShaderLibVersion = '100';
69var kDefaultShaderName = exports.kDefaultShaderName = '<anonymous>';
70
71var ShaderLib = exports.ShaderLib = function () {
72 _createClass(ShaderLib, null, [{
73 key: 'defaults',
74 value: function defaults() {
75 return {
76 precision: kDefaultShaderLibPrecision,
77 shaderName: kDefaultShaderName,
78 version: kDefaultShaderLibVersion,
79 defines: {},
80 name: kDefaultShaderName
81 };
82 }
83 }]);
84
85 function ShaderLib() {
86 var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
87 _ref$preprocessor = _ref.preprocessor,
88 preprocessor = _ref$preprocessor === undefined ? undefined : _ref$preprocessor,
89 _ref$middleware = _ref.middleware,
90 middleware = _ref$middleware === undefined ? [] : _ref$middleware,
91 _ref$precision = _ref.precision,
92 precision = _ref$precision === undefined ? kDefaultShaderLibPrecision : _ref$precision,
93 _ref$version = _ref.version,
94 version = _ref$version === undefined ? kDefaultShaderLibVersion : _ref$version,
95 _ref$defines = _ref.defines,
96 defines = _ref$defines === undefined ? {} : _ref$defines,
97 glsl = _ref.glsl;
98
99 _classCallCheck(this, ShaderLib);
100
101 this.cache = new _dynamic.DynamicValue(this);
102 this.store = new _dynamic.DynamicValue(this);
103 this.version = (0, _defined2.default)(version || kDefaultShaderLibVersion);
104 this.precision = (0, _defined2.default)(precision, kDefaultShaderLibPrecision);
105 this.middleware = (0, _defined2.default)(middleware, []);
106 this.preprocessor = (0, _defined2.default)(preprocessor, new ShaderLibPreprocessor(this));
107 this.preprocessor.define(defines);
108 this.add(_extends({}, libglsl, glsl));
109 }
110
111 _createClass(ShaderLib, [{
112 key: 'define',
113 value: function define(key, value) {
114 return this.preprocessor.define(key, value);
115 }
116 }, {
117 key: 'injectShaderNameDefine',
118 value: function injectShaderNameDefine(name, source) {
119 var regex = /\s?#ifndef SHADER_NAME\s?\n#define SHADER_NAME\s?.*\n#endif\n?$/g;
120 return String(source).replace(regex, '');
121 }
122 }, {
123 key: 'injectShaderPrecision',
124 value: function injectShaderPrecision(source) {
125 var _precision = this.precision,
126 precision = _precision === undefined ? kDefaultShaderLibPrecision : _precision;
127
128 var header = 'precision ' + precision + ';';
129 var regex = /[\s|\t]?precision\s+([a-z]+)\s+([a-z|A-Z]+)[\s+]?;[\s|\t|\r]?/g;
130 source = source.replace(header, '').replace(regex, '');
131 return header + '\n' + source;
132 }
133 }, {
134 key: 'add',
135 value: function add(name, source) {
136 var _this = this;
137
138 if ('string' == typeof name && 'string' == typeof source) {
139 name = name.replace(/[\/]+/g, '/');
140 this.store.set(name, source);
141 } else if (name && 'object' == (typeof name === 'undefined' ? 'undefined' : _typeof(name))) {
142 var walk = function walk(stack, scope) {
143 for (var key in scope) {
144 stack.push(key);
145 if ('object' == _typeof(scope[key])) {
146 walk(stack, scope[key]);
147 } else {
148 _this.add(stack.join('/'), scope[key]);
149 }
150 stack.pop();
151 }
152 };
153 walk([], name);
154 }
155 return this;
156 }
157 }, {
158 key: 'get',
159 value: function get(path) {
160 if ('string' == typeof path) {
161 if ('string' == typeof this.store[path]) {
162 return this.compile(path, this.store[path]);
163 }
164 }
165 return null;
166 }
167 }, {
168 key: 'resolve',
169 value: function resolve(path) {
170 var root = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : './';
171
172 root = (0, _path.resolve)('/', root);
173 path = path.replace((0, _path.extname)(path), '');
174 path = (0, _path.resolve)(root, path).slice(1);
175 return path;
176 }
177 }, {
178 key: 'hash',
179 value: function hash(source) {
180 if ('string' == typeof source) {
181 return (0, _stringHash2.default)(source);
182 }
183 return null;
184 }
185 }, {
186 key: 'isCached',
187 value: function isCached(source) {
188 return 'string' == typeof this.cache[this.hash(source) || ''];
189 }
190 }, {
191 key: 'preprocess',
192 value: function preprocess(source) {
193 var defines = this.defines;
194
195 source = (0, _prepr2.default)(source, defines);
196 source = source.split('\n').filter(function (line) {
197 return false == /^\s*$/.test(line);
198 }).join('\n');
199 return source;
200 }
201 }, {
202 key: 'compile',
203 value: function compile(name, source) {
204 if (!source && name) {
205 source = name;name = null;
206 }
207 if (!name) {
208 name = kDefaultShaderName;
209 }
210 if (!source) {
211 return null;
212 }
213 var hash = this.hash(source);
214 if (this.cache[hash]) {
215 return this.cache[hash];
216 }
217 source = this.injectShaderNameDefine(name, source);
218 source = this.preprocessor.process(name, source);
219 source = this.injectShaderPrecision(source);
220 source = source.split('\n').filter(function (line) {
221 return line.length;
222 }).map(function (line) {
223 return 1 == line.length ? line + '\n' : line;
224 }).join('\n') + '\n';
225 this.cache.set(hash, source);
226 return source;
227 }
228 }, {
229 key: 'use',
230 value: function use(middleware) {
231 if ('function' == typeof middleware) {
232 this.middleware.push(middleware);
233 }
234 return this;
235 }
236 }, {
237 key: 'defines',
238 get: function get() {
239 var _ref2 = this.preprocessor || {},
240 _ref2$defines = _ref2.defines,
241 defines = _ref2$defines === undefined ? null : _ref2$defines;
242
243 return defines;
244 }
245 }]);
246
247 return ShaderLib;
248}();
249
250var ShaderLibPlugin = exports.ShaderLibPlugin = function (_Command) {
251 _inherits(ShaderLibPlugin, _Command);
252
253 function ShaderLibPlugin() {
254 _classCallCheck(this, ShaderLibPlugin);
255
256 return _possibleConstructorReturn(this, (ShaderLibPlugin.__proto__ || Object.getPrototypeOf(ShaderLibPlugin)).apply(this, arguments));
257 }
258
259 return ShaderLibPlugin;
260}(_command.Command);
261
262var ShaderLibPreprocessor = exports.ShaderLibPreprocessor = function () {
263 function ShaderLibPreprocessor(shaderLib) {
264 _classCallCheck(this, ShaderLibPreprocessor);
265
266 this.defines = new _dynamic.DynamicValue(this);
267 this.shaderLib = shaderLib;
268 this.middleware = [];
269 }
270
271 _createClass(ShaderLibPreprocessor, [{
272 key: 'define',
273 value: function define(key, value) {
274 var _this3 = this;
275
276 if ('object' == (typeof key === 'undefined' ? 'undefined' : _typeof(key))) {
277 return Object.keys(key).map(function (k) {
278 return _this3.define(k, key[k]);
279 }).some(function (v) {
280 return true === v;
281 });
282 } else if ('string' == typeof key) {
283 // boolean -> number
284 if (true === value) {
285 value = 1;
286 } else if (false === value) {
287 value = 0;
288 }
289 if (null != value) {
290 // any -> string
291 value = String(value);
292 if (value != this.defines[key]) {
293 this.defines.set(key, value);
294 return true;
295 } else {
296 return false;
297 }
298 }
299 }
300 return false;
301 }
302 }, {
303 key: 'undefine',
304 value: function undefine(key) {
305 this.defines.unset(key);
306 return this;
307 }
308 }, {
309 key: 'process',
310 value: function process(name, source) {
311 var _this4 = this;
312
313 var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
314 var shaderLib = this.shaderLib,
315 defines = this.defines;
316 var middleware = shaderLib.middleware,
317 version = shaderLib.version;
318
319 var includeStack = [];
320 var stack = [];
321 opts = !opts || 'object' != (typeof opts === 'undefined' ? 'undefined' : _typeof(opts)) ? {} : opts;
322 if ('string' == typeof source) {
323 source = (0, _glslInjectDefines2.default)(source, _extends({}, defines, opts.defines));
324 }
325 visit('\n' + source + '\n', stack, name != kDefaultShaderName ? (0, _path.dirname)(name) : '/');
326 source = (0, _glslTokenString2.default)(stack);
327 return middleware.filter(function (ware) {
328 return 'function' == typeof ware;
329 }).reduce(function (src, ware) {
330 return (0, _defined2.default)(ware(shaderLib, _this4, src, opts), src);
331 }, source).replace('#define GLSLIFY 1\n', '');
332
333 function visit(source, stack, root) {
334 var tokens = (0, _glslTokenizer2.default)(source, { version: version });
335 var _iteratorNormalCompletion = true;
336 var _didIteratorError = false;
337 var _iteratorError = undefined;
338
339 try {
340 var _loop = function _loop() {
341 var token = _step.value;
342
343 var push = function push() {
344 return stack.push(token);
345 };
346 switch (token.type) {
347 case kGLSLTokenBlockComment:
348 case kGLSLTokenLineComment:
349 break;
350 case kGLSLTokenPreprocecsor:
351 var includeRegex = RegExp(/[\s|\t]?#include[\s]+([<|"]?.*[>|"]?)$/);
352 var directive = token.data.match(/(#[a-z]+)\s?/)[0].trim();
353 switch (directive) {
354 case '#define':
355 var match = token.data.match(/#define[\s]+(.*)/);
356 if (match) {
357 var kv = match[1].match(/.*[\s]+(.*)/);
358 if (!kv) {
359 token.data = token.data + ' 1';
360 }
361 }
362 push();
363 break;
364
365 case '#include':
366 var _ref3 = token.data.match(includeRegex) || [],
367 _ref4 = _slicedToArray(_ref3, 2),
368 statement = _ref4[0],
369 arg = _ref4[1];
370
371 var path = arg.replace(/^["|<](.*)["|>]/, '$1').trim();
372 var left = arg[0].trim();
373 var right = arg[arg.trim().length - 1].trim();
374 var createError = function createError(ErrorType, msg) {
375 return new ErrorType((msg || '') + '\n\tat (glsl) ' + includeStack.join('\n\tat (glsl) '));
376 };
377 if (-1 == ['<', '"'].indexOf(left)) {
378 var msg = 'Unexpected token \'' + left + '\'. Expecting \'<\' or \'"\'.';
379 throw createError(SyntaxError, msg);
380 } else if (-1 == ['>', '"'].indexOf(right)) {
381 var expected = '<' == left ? '\'>\'' : '\'"\'';
382 var _msg = 'Unexpected token \'' + right + '\'. Expecting ' + expected + '.';
383 throw createError(SyntaxError, _msg);
384 }
385
386 if ('<' == left && '>' != right) {
387 var _msg2 = 'Unexpected token \'' + right + '\'. Expecting \'>\'.';
388 throw createError(SyntaxError, _msg2);
389 } else if ('"' == left && '"' != right) {
390 var _msg3 = 'Unexpected token \'' + right + '\'. Expecting \'"\'.';
391 throw createError(SyntaxError, _msg3);
392 }
393
394 var nextRoot = '<' == left && '>' == right ? '/' : root;
395 var prefix = '.' != path[0] ? './' : '';
396 var resolvedPath = shaderLib.resolve('' + prefix + path, nextRoot);
397 var shader = shaderLib.get(resolvedPath);
398 if (shader) {
399 includeStack.push(path + ':' + token.line);
400 visit(shader + '\n', stack, nextRoot);
401 } else {
402 throw createError(ReferenceError, 'glsl lib ' + arg + ' not found.');
403 }
404 includeStack.pop();
405 break;
406
407 default:
408 push();
409 }
410 break;
411
412 default:
413 push();break;
414 }
415 };
416
417 for (var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
418 _loop();
419 }
420 } catch (err) {
421 _didIteratorError = true;
422 _iteratorError = err;
423 } finally {
424 try {
425 if (!_iteratorNormalCompletion && _iterator.return) {
426 _iterator.return();
427 }
428 } finally {
429 if (_didIteratorError) {
430 throw _iteratorError;
431 }
432 }
433 }
434 }
435 }
436 }]);
437
438 return ShaderLibPreprocessor;
439}();
440//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3NoYWRlcmxpYi5qcyJdLCJuYW1lcyI6WyJsaWJnbHNsIiwia0dMU0xUb2tlblByZXByb2NlY3NvciIsImtHTFNMVG9rZW5CbG9ja0NvbW1lbnQiLCJrR0xTTFRva2VuTGluZUNvbW1lbnQiLCJrRGVmYXVsdFNoYWRlckxpYlByZWNpc2lvbiIsImtEZWZhdWx0U2hhZGVyTGliVmVyc2lvbiIsImtEZWZhdWx0U2hhZGVyTmFtZSIsIlNoYWRlckxpYiIsInByZWNpc2lvbiIsInNoYWRlck5hbWUiLCJ2ZXJzaW9uIiwiZGVmaW5lcyIsIm5hbWUiLCJwcmVwcm9jZXNzb3IiLCJ1bmRlZmluZWQiLCJtaWRkbGV3YXJlIiwiZ2xzbCIsImNhY2hlIiwic3RvcmUiLCJTaGFkZXJMaWJQcmVwcm9jZXNzb3IiLCJkZWZpbmUiLCJhZGQiLCJrZXkiLCJ2YWx1ZSIsInNvdXJjZSIsInJlZ2V4IiwiU3RyaW5nIiwicmVwbGFjZSIsImhlYWRlciIsInNldCIsIndhbGsiLCJzdGFjayIsInNjb3BlIiwicHVzaCIsImpvaW4iLCJwb3AiLCJwYXRoIiwiY29tcGlsZSIsInJvb3QiLCJzbGljZSIsImhhc2giLCJzcGxpdCIsImZpbHRlciIsImxpbmUiLCJ0ZXN0IiwiaW5qZWN0U2hhZGVyTmFtZURlZmluZSIsInByb2Nlc3MiLCJpbmplY3RTaGFkZXJQcmVjaXNpb24iLCJsZW5ndGgiLCJtYXAiLCJTaGFkZXJMaWJQbHVnaW4iLCJzaGFkZXJMaWIiLCJPYmplY3QiLCJrZXlzIiwiayIsInNvbWUiLCJ2IiwidW5zZXQiLCJvcHRzIiwiaW5jbHVkZVN0YWNrIiwidmlzaXQiLCJ3YXJlIiwicmVkdWNlIiwic3JjIiwidG9rZW5zIiwidG9rZW4iLCJ0eXBlIiwiaW5jbHVkZVJlZ2V4IiwiUmVnRXhwIiwiZGlyZWN0aXZlIiwiZGF0YSIsIm1hdGNoIiwidHJpbSIsImt2Iiwic3RhdGVtZW50IiwiYXJnIiwibGVmdCIsInJpZ2h0IiwiY3JlYXRlRXJyb3IiLCJFcnJvclR5cGUiLCJtc2ciLCJpbmRleE9mIiwiU3ludGF4RXJyb3IiLCJleHBlY3RlZCIsIm5leHRSb290IiwicHJlZml4IiwicmVzb2x2ZWRQYXRoIiwicmVzb2x2ZSIsInNoYWRlciIsImdldCIsIlJlZmVyZW5jZUVycm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7SUFBWUEsTzs7QUFDWjs7QUFFQTs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFFQSxJQUFNQyx5QkFBeUIsY0FBL0I7QUFDQSxJQUFNQyx5QkFBeUIsZUFBL0I7QUFDQSxJQUFNQyx3QkFBd0IsY0FBOUI7QUFVTyxJQUFNQyxrRUFBNkIsZUFBbkM7QUFDQSxJQUFNQyw4REFBMkIsS0FBakM7QUFDQSxJQUFNQyxrREFBcUIsYUFBM0I7O0lBRU1DLFMsV0FBQUEsUzs7OytCQUNPO0FBQ2hCLGFBQU87QUFDTEMsbUJBQVdKLDBCQUROO0FBRUxLLG9CQUFZSCxrQkFGUDtBQUdMSSxpQkFBU0wsd0JBSEo7QUFJTE0saUJBQVMsRUFKSjtBQUtMQyxjQUFNTjtBQUxELE9BQVA7QUFPRDs7O0FBRUQsdUJBT1E7QUFBQSxtRkFBSixFQUFJO0FBQUEsaUNBTk5PLFlBTU07QUFBQSxRQU5OQSxZQU1NLHFDQU5TQyxTQU1UO0FBQUEsK0JBTE5DLFVBS007QUFBQSxRQUxOQSxVQUtNLG1DQUxPLEVBS1A7QUFBQSw4QkFKTlAsU0FJTTtBQUFBLFFBSk5BLFNBSU0sa0NBSk1KLDBCQUlOO0FBQUEsNEJBSE5NLE9BR007QUFBQSxRQUhOQSxPQUdNLGdDQUhJTCx3QkFHSjtBQUFBLDRCQUZOTSxPQUVNO0FBQUEsUUFGTkEsT0FFTSxnQ0FGSSxFQUVKO0FBQUEsUUFETkssSUFDTSxRQUROQSxJQUNNOztBQUFBOztBQUNOLFNBQUtDLEtBQUwsR0FBYSwwQkFBaUIsSUFBakIsQ0FBYjtBQUNBLFNBQUtDLEtBQUwsR0FBYSwwQkFBaUIsSUFBakIsQ0FB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WUFBZCxDQUFmO0FBQ0Esd0JBQUlFLE1BQUosRUFBWTtBQUNWN0IsbUNBQWExQixJQUFiLENBQXFCRyxJQUFyQixTQUE2QjZCLE1BQU10QixJQUFuQztBQUNBaUIsNEJBQU00QixTQUFTLElBQWYsRUFBcUJ6RCxLQUFyQixFQUE0QnFELFFBQTVCO0FBQ0QscUJBSEQsTUFHTztBQUNMLDRCQUFNTixZQUFZWSxjQUFaLGdCQUF3Q2YsR0FBeEMsaUJBQU47QUFDRDtBQUNEaEIsaUNBQWF4QixHQUFiO0FBQ0E7O0FBRUY7QUFBU0Y7QUFoRFg7QUFrREE7O0FBRUY7QUFBU0EsdUJBQVE7QUEzRG5CO0FBSmdDOztBQUVsQywrQkFBb0IrQixNQUFwQiw4SEFBNEI7QUFBQTtBQStEM0I7QUFqRWlDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrRW5DO0FBQ0YiLCJmaWxlIjoic2hhZGVybGliLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHluYW1pY1ZhbHVlIH0gZnJvbSAnLi9keW5hbWljJ1xuaW1wb3J0ICogYXMgbGliZ2xzbCBmcm9tICcuL2dsc2wnXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnLi9jb21tYW5kJ1xuXG5pbXBvcnQgeyBkaXJuYW1lLCBleHRuYW1lLCByZXNvbHZlIH0gZnJvbSAncGF0aCdcbmltcG9ydCBnbHNsVG9rZW5zVG9EZWZpbmVzIGZyb20gJ2dsc2wtdG9rZW4tZGVmaW5lcydcbmltcG9ydCBnbHNsVG9rZW5zVG9TdHJpbmcgZnJvbSAnZ2xzbC10b2tlbi1zdHJpbmcnXG5pbXBvcnQgaW5qZWN0RGVmaW5lcyBmcm9tICdnbHNsLWluamVjdC1kZWZpbmVzJ1xuaW1wb3J0IGdsc2xUb2tlbml6ZSBmcm9tICdnbHNsLXRva2VuaXplcidcbmltcG9ydCBwcmVwcm9jZXNzIGZyb20gJ3ByZXByJ1xuaW1wb3J0IGNvYWxlc2NlIGZyb20gJ2RlZmluZWQnXG5pbXBvcnQgaGFzaCBmcm9tICdzdHJpbmctaGFzaCdcblxuY29uc3Qga0dMU0xUb2tlblByZXByb2NlY3NvciA9ICdwcmVwcm9jZXNzb3InXG5jb25zdCBrR0xTTFRva2VuQmxvY2tDb21tZW50ID0gJ2Jsb2NrLWNvbW1lbnQnXG5jb25zdCBrR0xTTFRva2VuTGluZUNvbW1lbnQgPSAnbGluZS1jb21tZW50J1xuY29uc3Qga0dMU0xUb2tlbldoaXRlc3BhY2UgPSAnd2hpdGVzcGFjZSdcbmNvbnN0IGtHTFNMVG9rZW5JZGVudGlmaWVyID0gJ2lkZW50J1xuY29uc3Qga0dMU0xUb2tlbk9wZXJhdG9yID0gJ29wZXJhdG9yJ1xuY29uc3Qga0dMU0xUb2tlbkJ1aWx0aW4gPSAnYnVpbHRpbidcbmNvbnN0IGtHTFNMVG9rZW5LZXl3b3JkID0gJ2tleXdvcmQnXG5jb25zdCBrR0xTTFRva2VuSW50ZWdlciA9ICdpbnRlZ2VyJ1xuY29uc3Qga0dMU0xUb2tlbkZsb2F0ID0gJ2Zsb2F0J1xuY29uc3Qga0dMU0xUb2tlbkVPRiA9ICdlb2YnXG5cbmV4cG9ydCBjb25zdCBrRGVmYXVsdFNoYWRlckxpYlByZWNpc2lvbiA9ICdtZWRpdW1wIGZsb2F0J1xuZXhwb3J0IGNvbnN0IGtEZWZhdWx0U2hhZGVyTGliVmVyc2lvbiA9ICcxMDAnXG5leHBvcnQgY29uc3Qga0RlZmF1bHRTaGFkZXJOYW1lID0gJzxhbm9ueW1vdXM+J1xuXG5leHBvcnQgY2xhc3MgU2hhZGVyTGliIHtcbiAgc3RhdGljIGRlZmF1bHRzKCkge1xuICAgIHJldHVybiB7XG4gICAgICBwcmVjaXNpb246IGtEZWZhdWx0U2hhZGVyTGliUHJlY2lzaW9uLFxuICAgICAgc2hhZGVyTmFtZToga0RlZmF1bHRTaGFkZXJOYW1lLFxuICAgICAgdmVyc2lvbjoga0RlZmF1bHRTaGFkZXJMaWJWZXJzaW9uLFxuICAgICAgZGVmaW5lczoge30sXG4gICAgICBuYW1lOiBrRGVmYXVsdFNoYWRlck5hbWUsXG4gICAgfVxuICB9XG5cbiAgY29uc3RydWN0b3Ioe1xuICAgIHByZXByb2Nlc3NvciA9IHVuZGVmaW5lZCxcbiAgICBtaWRkbGV3YXJlID0gW10sXG4gICAgcHJlY2lzaW9uID0ga0RlZmF1bHRTaGFkZXJMaWJQcmVjaXNpb24sXG4gICAgdmVyc2lvbiA9IGtEZWZhdWx0U2hhZGVyTGliVmVyc2lvbixcbiAgICBkZWZpbmVzID0ge30sXG4gICAgZ2xzbCxcbiAgfSA9IHt9KSB7XG4gICAgdGhpcy5jYWNoZSA9IG5ldyBEeW5hbWljVmFsdWUodGhpcylcbiAgICB0aGlzLnN0b3JlID0gbmV3IER5bmFtaWNWYWx1ZSh0aGlzKVxuICAgIHRoaXMudmVyc2lvbiA9IGNvYWxlc2NlKHZlcnNpb24gfHwga0RlZmF1bHRTaGFkZXJMaWJWZXJzaW9uKVxuICAgIHRoaXMucHJlY2lzaW9uID0gY29hbGVzY2UocHJlY2lzaW9uLCBrRGVmYXVsdFNoYWRlckxpYlByZWNpc2lvbilcbiAgICB0aGlzLm1pZGRsZXdhcmUgPSBjb2FsZXNjZShtaWRkbGV3YXJlLCBbXSlcbiAgICB0aGlzLnByZXByb2Nlc3NvciA9IGNvYWxlc2NlKHByZXByb2Nlc3NvciwgbmV3IFNoYWRlckxpYlByZXByb2Nlc3Nvcih0aGlzKSlcbiAgICB0aGlzLnByZXByb2Nlc3Nvci5kZWZpbmUoZGVmaW5lcylcbiAgICB0aGlzLmFkZCh7IC4uLmxpYmdsc2wsIC4uLmdsc2wgfSlcbiAgfVxuXG4gIGdldCBkZWZpbmVzKCkge1xuICAgIGNvbnN0IHtkZWZpbmVzID0gbnVsbH0gPSB0aGlzLnByZXByb2Nlc3NvciB8fCB7fVxuICAgIHJldHVybiBkZWZpbmVzXG4gIH1cblxuICBkZWZpbmUoa2V5LCB2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLnByZXByb2Nlc3Nvci5kZWZpbmUoa2V5LCB2YWx1ZSlcbiAgfVxuXG4gIGluamVjdFNoYWRlck5hbWVEZWZpbmUobmFtZSwgc291cmNlKSB7XG4gICAgY29uc3QgcmVnZXggPVxuICAgICAgL1xccz8jaWZuZGVmIFNIQURFUl9OQU1FXFxzP1xcbiNkZWZpbmUgU0hBREVSX05BTUVcXHM/LipcXG4jZW5kaWZcXG4/JC9nXG4gICAgcmV0dXJuIFN0cmluZyhzb3VyY2UpLnJlcGxhY2UocmVnZXgsICcnKVxuICB9XG5cbiAgaW5qZWN0U2hhZGVyUHJlY2lzaW9uKHNvdXJjZSkge1xuICAgIGNvbnN0IHtwcmVjaXNpb24gPSBrRGVmYXVsdFNoYWRlckxpYlByZWNpc2lvbn0gPSB0aGlzXG4gICAgY29uc3QgaGVhZGVyID0gYHByZWNpc2lvbiAke3ByZWNpc2lvbn07YFxuICAgIGNvbnN0IHJlZ2V4ID1cbiAgICAgIC9bXFxzfFxcdF0/cHJlY2lzaW9uXFxzKyhbYS16XSspXFxzKyhbYS16fEEtWl0rKVtcXHMrXT87W1xcc3xcXHR8XFxyXT8vZ1xuICAgIHNvdXJjZSA9IHNvdXJjZVxuICAgICAgLnJlcGxhY2UoaGVhZGVyLCAnJylcbiAgICAgIC5yZXBsYWNlKHJlZ2V4LCAnJylcbiAgICByZXR1cm4gYCR7aGVhZGVyfVxcbiR7c291cmNlfWBcbiAgfVxuXG4gIGFkZChuYW1lLCBzb3VyY2UpIHtcbiAgICBpZiAoJ3N0cmluZycgPT0gdHlwZW9mIG5hbWUgJiYgJ3N0cmluZycgPT0gdHlwZW9mIHNvdXJjZSkge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvW1xcL10rL2csICcvJylcbiAgICAgIHRoaXMuc3RvcmUuc2V0KG5hbWUsIHNvdXJjZSlcbiAgICB9IGVsc2UgaWYgKG5hbWUgJiYgJ29iamVjdCcgPT0gdHlwZW9mIG5hbWUpIHtcbiAgICAgIGNvbnN0IHdhbGsgPSAoc3RhY2ssIHNjb3BlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNjb3BlKSB7XG4gICAgICAgICAgc3RhY2sucHVzaChrZXkpXG4gICAgICAgICAgaWYgKCdvYmplY3QnID09IHR5cGVvZiBzY29wZVtrZXldKSB7IHdhbGsoc3RhY2ssIHNjb3BlW2tleV0pIH1cbiAgICAgICAgICBlbHNlIHsgdGhpcy5hZGQoc3RhY2suam9pbignLycpLCBzY29wZVtrZXldKSB9XG4gICAgICAgICAgc3RhY2sucG9wKClcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2FsayhbXSwgbmFtZSlcbiAgICB9XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIGdldChwYXRoKSB7XG4gICAgaWYgKCdzdHJpbmcnID09IHR5cGVvZiBwYXRoKSB7XG4gICAgICBpZiAoJ3N0cmluZycgPT0gdHlwZW9mIHRoaXMuc3RvcmVbcGF0aF0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcGlsZShwYXRoLCB0aGlzLnN0b3JlW3BhdGhdKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgcmVzb2x2ZShwYXRoLCByb290ID0gJy4vJykge1xuICAgIHJvb3QgPSByZXNvbHZlKCcvJywgcm9vdClcbiAgICBwYXRoID0gcGF0aC5yZXBsYWNlKGV4dG5hbWUocGF0aCksICcnKVxuICAgIHBhdGggPSByZXNvbHZlKHJvb3QsIHBhdGgpLnNsaWNlKDEpXG4gICAgcmV0dXJuIHBhdGhcbiAgfVxuXG4gIGhhc2goc291cmNlKSB7XG4gICAgaWYgKCdzdHJpbmcnID09IHR5cGVvZiBzb3VyY2UpIHsgcmV0dXJuIGhhc2goc291cmNlKSB9XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIGlzQ2FjaGVkKHNvdXJjZSkge1xuICAgIHJldHVybiAnc3RyaW5nJyA9PSB0eXBlb2YgdGhpcy5jYWNoZVt0aGlzLmhhc2goc291cmNlKSB8fCAnJ11cbiAgfVxuXG4gIHByZXByb2Nlc3Moc291cmNlKSB7XG4gICAgY29uc3Qge2RlZmluZXN9ID0gdGhpc1xuICAgIGxldCB3aGl0ZXNwYWNlID0gMFxuICAgIHNvdXJjZSA9IHByZXByb2Nlc3Moc291cmNlLCBkZWZpbmVzKVxuICAgIHNvdXJjZSA9IHNvdXJjZVxuICAgICAgLnNwbGl0KCdcXG4nKVxuICAgICAgLmZpbHRlcigobGluZSkgPT4gZmFsc2UgPT0gL15cXHMqJC8udGVzdChsaW5lKSlcbiAgICAgIC5qb2luKCdcXG4nKVxuICAgIHJldHVybiBzb3VyY2VcbiAgfVxuXG4gIGNvbXBpbGUobmFtZSwgc291cmNlKSB7XG4gICAgaWYgKCFzb3VyY2UgJiYgbmFtZSkgeyBzb3VyY2UgPSBuYW1lOyBuYW1lID0gbnVsbCB9XG4gICAgaWYgKCFuYW1lKSB7IG5hbWUgPSBrRGVmYXVsdFNoYWRlck5hbWUgfVxuICAgIGlmICghc291cmNlKSB7IHJldHVybiBudWxsIH1cbiAgICBjb25zdCBoYXNoID0gdGhpcy5oYXNoKHNvdXJjZSlcbiAgICBpZiAodGhpcy5jYWNoZVtoYXNoXSkgeyByZXR1cm4gdGhpcy5jYWNoZVtoYXNoXSB9XG4gICAgc291cmNlID0gdGhpcy5pbmplY3RTaGFkZXJOYW1lRGVmaW5lKG5hbWUsIHNvdXJjZSlcbiAgICBzb3VyY2UgPSB0aGlzLnByZXByb2Nlc3Nvci5wcm9jZXNzKG5hbWUsIHNvdXJjZSlcbiAgICBzb3VyY2UgPSB0aGlzLmluamVjdFNoYWRlclByZWNpc2lvbihzb3VyY2UpXG4gICAgc291cmNlID0gc291cmNlXG4gICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lLmxlbmd0aClcbiAgICAgIC5tYXAoKGxpbmUpID0+IDEgPT0gbGluZS5sZW5ndGggPyBgJHtsaW5lfVxcbmAgOiBsaW5lKVxuICAgICAgLmpvaW4oJ1xcbicpXG4gICAgICArICdcXG4nXG4gICAgdGhpcy5jYWNoZS5zZXQoaGFzaCwgc291cmNlKVxuICAgIHJldHVybiBzb3VyY2VcbiAgfVxuXG4gIHVzZShtaWRkbGV3YXJlKSB7XG4gICAgaWYgKCdmdW5jdGlvbicgPT0gdHlwZW9mIG1pZGRsZXdhcmUpIHtcbiAgICAgIHRoaXMubWlkZGxld2FyZS5wdXNoKG1pZGRsZXdhcmUpXG4gICAgfVxuICAgIHJldHVybiB0aGlzXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNoYWRlckxpYlBsdWdpbiBleHRlbmRzIENvbW1hbmQgeyB9XG5cbmV4cG9ydCBjbGFzcyBTaGFkZXJMaWJQcmVwcm9jZXNzb3Ige1xuICBjb25zdHJ1Y3RvcihzaGFkZXJMaWIpIHtcbiAgICB0aGlzLmRlZmluZXMgPSBuZXcgRHluYW1pY1ZhbHVlKHRoaXMpXG4gICAgdGhpcy5zaGFkZXJMaWIgPSBzaGFkZXJMaWJcbiAgICB0aGlzLm1pZGRsZXdhcmUgPSBbXVxuICB9XG5cbiAgZGVmaW5lKGtleSwgdmFsdWUpIHtcbiAgICBpZiAoJ29iamVjdCcgPT0gdHlwZW9mIGtleSkge1xuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGtleSlcbiAgICAgICAgLm1hcCgoaykgPT4gdGhpcy5kZWZpbmUoaywga2V5W2tdKSlcbiAgICAgICAgLnNvbWUoKHYpID0+IHRydWUgPT09IHYpXG4gICAgfSBlbHNlIGlmICgnc3RyaW5nJyA9PSB0eXBlb2Yga2V5KSB7XG4gICAgICAvLyBib29sZWFuIC0+IG51bWJlclxuICAgICAgaWYgKHRydWUgPT09IHZhbHVlKSB7IHZhbHVlID0gMSB9XG4gICAgICBlbHNlIGlmIChmYWxzZSA9PT0gdmFsdWUpIHsgdmFsdWUgPSAwIH1cbiAgICAgIGlmIChudWxsICE9IHZhbHVlKSB7XG4gICAgICAgIC8vIGFueSAtPiBzdHJpbmdcbiAgICAgICAgdmFsdWUgPSBTdHJpbmcodmFsdWUpXG4gICAgICAgIGlmICh2YWx1ZSAhPSB0aGlzLmRlZmluZXNba2V5XSkge1xuICAgICAgICAgIHRoaXMuZGVmaW5lcy5zZXQoa2V5LCB2YWx1ZSlcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgdW5kZWZpbmUoa2V5KSB7XG4gICAgdGhpcy5kZWZpbmVzLnVuc2V0KGtleSlcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJvY2VzcyhuYW1lLCBzb3VyY2UsIG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IHsgc2hhZGVyTGliLCBkZWZpbmVzIH0gPSB0aGlzXG4gICAgY29uc3QgeyBtaWRkbGV3YXJlLCB2ZXJzaW9uIH0gPSBzaGFkZXJMaWJcbiAgICBjb25zdCBpbmNsdWRlU3RhY2sgPSBbXVxuICAgIGNvbnN0IHN0YWNrID0gW11cbiAgICBvcHRzID0gIW9wdHMgfHwgJ29iamVjdCcgIT0gdHlwZW9mIG9wdHMgPyB7fSA6IG9wdHNcbiAgICBpZiAoJ3N0cmluZycgPT0gdHlwZW9mIHNvdXJjZSkge1xuICAgICAgc291cmNlID0gaW5qZWN0RGVmaW5lcyhzb3VyY2UsIHsgLi4uZGVmaW5lcywgLi4ub3B0cy5kZWZpbmVzIH0pXG4gICAgfVxuICAgIHZpc2l0KGBcXG4ke3NvdXJjZX1cXG5gLCBzdGFjaywgbmFtZSAhPSBrRGVmYXVsdFNoYWRlck5hbWUgPyBkaXJuYW1lKG5hbWUpIDogJy8nKVxuICAgIHNvdXJjZSA9IGdsc2xUb2tlbnNUb1N0cmluZyhzdGFjaylcbiAgICByZXR1cm4gbWlkZGxld2FyZVxuICAgICAgLmZpbHRlcigod2FyZSkgPT4gJ2Z1bmN0aW9uJyA9PSB0eXBlb2Ygd2FyZSlcbiAgICAgIC5yZWR1Y2UoKHNyYywgd2FyZSkgPT4ge1xuICAgICAgICByZXR1cm4gY29hbGVzY2Uod2FyZShzaGFkZXJMaWIsIHRoaXMsIHNyYywgb3B0cyksIHNyYylcbiAgICAgIH0sIHNvdXJjZSlcbiAgICAgIC5yZXBsYWNlKCcjZGVmaW5lIEdMU0xJRlkgMVxcbicsICcnKVxuXG4gICAgZnVuY3Rpb24gdmlzaXQoc291cmNlLCBzdGFjaywgcm9vdCkge1xuICAgICAgY29uc3QgdG9rZW5zID0gZ2xzbFRva2VuaXplKHNvdXJjZSwge3ZlcnNpb259KVxuICAgICAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbnMpIHtcbiAgICAgICAgY29uc3QgcHVzaCA9ICgpID0+IHN0YWNrLnB1c2godG9rZW4pXG4gICAgICAgIHN3aXRjaCAodG9rZW4udHlwZSkge1xuICAgICAgICAgIGNhc2Uga0dMU0xUb2tlbkJsb2NrQ29tbWVudDpcbiAgICAgICAgICBjYXNlIGtHTFNMVG9rZW5MaW5lQ29tbWVudDpcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgY2FzZSBrR0xTTFRva2VuUHJlcHJvY2Vjc29yOlxuICAgICAgICAgICAgY29uc3QgaW5jbHVkZVJlZ2V4ID0gUmVnRXhwKC9bXFxzfFxcdF0/I2luY2x1ZGVbXFxzXSsoWzx8XCJdPy4qWz58XCJdPykkLylcbiAgICAgICAgICAgIGNvbnN0IGRpcmVjdGl2ZSA9IHRva2VuLmRhdGEubWF0Y2goLygjW2Etel0rKVxccz8vKVswXS50cmltKClcbiAgICAgICAgICAgIHN3aXRjaCAoZGlyZWN0aXZlKSB7XG4gICAgICAgICAgICAgIGNhc2UgJyNkZWZpbmUnOlxuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gdG9rZW4uZGF0YS5tYXRjaCgvI2RlZmluZVtcXHNdKyguKikvKVxuICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgY29uc3Qga3YgPSBtYXRjaFsxXS5tYXRjaCgvLipbXFxzXSsoLiopLylcbiAgICAgICAgICAgICAgICAgIGlmICgha3YpIHsgdG9rZW4uZGF0YSA9IGAke3Rva2VuLmRhdGF9IDFgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHVzaCgpXG4gICAgICAgICAgICAgICAgYnJlYWtcblxuICAgICAgICAgICAgICBjYXNlICcjaW5jbHVkZSc6XG4gICAgICAgICAgICAgICAgY29uc3QgW3N0YXRlbWVudCwgYXJnXSA9IHRva2VuLmRhdGEubWF0Y2goaW5jbHVkZVJlZ2V4KSB8fCBbXVxuICAgICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBhcmcucmVwbGFjZSgvXltcInw8XSguKilbXCJ8Pl0vLCAnJDEnKS50cmltKClcbiAgICAgICAgICAgICAgICBjb25zdCBsZWZ0ID0gYXJnWzBdLnRyaW0oKVxuICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gYXJnW2FyZy50cmltKCkubGVuZ3RoIC0gMV0udHJpbSgpXG4gICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlRXJyb3IgPSAoRXJyb3JUeXBlLCBtc2cpID0+IG5ldyBFcnJvclR5cGUoXG4gICAgICAgICAgICAgICAgICBgJHttc2cgfHwgJyd9XFxuXFx0YXQgKGdsc2wpICR7aW5jbHVkZVN0YWNrLmpvaW4oJ1xcblxcdGF0IChnbHNsKSAnKX1gXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIGlmICgtMSA9PSBbJzwnLCAnXCInXS5pbmRleE9mKGxlZnQpKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBtc2cgPSBgVW5leHBlY3RlZCB0b2tlbiAnJHtsZWZ0fScuIEV4cGVjdGluZyAnPCcgb3IgJ1wiJy5gXG4gICAgICAgICAgICAgICAgICB0aHJvdyBjcmVhdGVFcnJvcihTeW50YXhFcnJvciwgbXNnKVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoLTEgPT0gWyc+JywgJ1wiJ10uaW5kZXhPZihyaWdodCkpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkID0gJzwnID09IGxlZnQgPyBgJz4nYCA6IGAnXCInYFxuICAgICAgICAgICAgICAgICAgY29uc3QgbXNnID0gYFVuZXhwZWN0ZWQgdG9rZW4gJyR7cmlnaHR9Jy4gRXhwZWN0aW5nICR7ZXhwZWN0ZWR9LmBcbiAgICAgICAgICAgICAgICAgIHRocm93IGNyZWF0ZUVycm9yKFN5bnRheEVycm9yLCBtc2cpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCc8JyA9PSBsZWZ0ICYmICc+JyAhPSByaWdodCkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgbXNnID0gYFVuZXhwZWN0ZWQgdG9rZW4gJyR7cmlnaHR9Jy4gRXhwZWN0aW5nICc+Jy5gXG4gICAgICAgICAgICAgICAgICB0aHJvdyBjcmVhdGVFcnJvcihTeW50YXhFcnJvciwgbXNnKVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ1wiJyA9PSBsZWZ0ICYmICdcIicgIT0gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG1zZyA9IGBVbmV4cGVjdGVkIHRva2VuICcke3JpZ2h0fScuIEV4cGVjdGluZyAnXCInLmBcbiAgICAgICAgICAgICAgICAgIHRocm93IGNyZWF0ZUVycm9yKFN5bnRheEVycm9yLCBtc2cpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFJvb3QgPSAnPCcgPT0gbGVmdCAmJiAnPicgPT0gcmlnaHQgPyAnLycgOiByb290XG4gICAgICAgICAgICAgICAgY29uc3QgcHJlZml4ID0gJy4nICE9IHBhdGhbMF0gPyAnLi8nIDogJydcbiAgICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBzaGFkZXJMaWIucmVzb2x2ZShgJHtwcmVmaXh9JHtwYXRofWAsIG5leHRSb290KVxuICAgICAgICAgICAgICAgIGNvbnN0IHNoYWRlciA9IHNoYWRlckxpYi5nZXQocmVzb2x2ZWRQYXRoKVxuICAgICAgICAgICAgICAgIGlmIChzaGFkZXIpIHtcbiAgICAgICAgICAgICAgICAgIGluY2x1ZGVTdGFjay5wdXNoKGAke3BhdGh9OiR7dG9rZW4ubGluZX1gKVxuICAgICAgICAgICAgICAgICAgdmlzaXQoc2hhZGVyICsgJ1xcbicsIHN0YWNrLCBuZXh0Um9vdClcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgY3JlYXRlRXJyb3IoUmVmZXJlbmNlRXJyb3IsIGBnbHNsIGxpYiAke2FyZ30gbm90IGZvdW5kLmApXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGluY2x1ZGVTdGFjay5wb3AoKVxuICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgICAgICAgZGVmYXVsdDogcHVzaCgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVha1xuXG4gICAgICAgICAgZGVmYXVsdDogcHVzaCgpOyBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
\No newline at end of file