react-awesome-giphy
Version:
React wrapper for the Giphy API
336 lines (313 loc) • 72 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react'), require('@emotion/styled'), require('masonic')) :
typeof define === 'function' && define.amd ? define(['react', '@emotion/styled', 'masonic'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.index = factory(global.React, global.styled, global.masonic));
})(this, (function (React, styled, masonic) { 'use strict';
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
}
var theme = {
textColor: '#FEFEFF',
textAltColor: '#AFB1B2',
bgColor: '#2F3136',
bgAltColor: '#4e4e4e',
buttonColor: '#4F535C',
inputColor: '#212325',
accentColor: '#02AEF4'
};
var StoreContext = React.createContext(null);
var useStore = function () { return React.useContext(StoreContext); };
var StoreProvider = function (_a) {
var children = _a.children, value = _a.value;
return (React__default["default"].createElement(StoreContext.Provider, { value: value }, children));
};
var Stack = styled__default["default"].div(templateObject_1$7 || (templateObject_1$7 = __makeTemplateObject(["\n display: flex;\n ", "\n"], ["\n display: flex;\n ", "\n"])), function (props) { return props.css; });
var Row = function (_a) {
var children = _a.children, props = __rest(_a, ["children"]);
var left = props.left, right = props.right, top = props.top, bottom = props.bottom, centerx = props.centerx, centery = props.centery, center = props.center;
return (React__default["default"].createElement(Stack, { css: "\n flex-direction: row;\n\n align-items: ".concat(top ? 'flex-start' :
bottom ? 'flex-end' :
(centery || center) ? 'center' :
'stretch', ";\n \n justify-content: ").concat(left ? 'flex-start' :
right ? 'flex-end' :
(centerx || center) ? 'center' :
'stretch', ";\n ").concat(props.css, "\n ") }, children));
};
var Col = function (_a) {
var children = _a.children, props = __rest(_a, ["children"]);
var left = props.left, right = props.right, top = props.top, bottom = props.bottom, centerx = props.centerx, centery = props.centery, center = props.center;
return (React__default["default"].createElement(Stack, { css: "\n flex-direction: column;\n\n justify-content: ".concat(top ? 'flex-start' :
bottom ? 'flex-end' :
(centery || center) ? 'center' :
'stretch', ";\n \n align-items: ").concat(left ? 'flex-start' :
right ? 'flex-end' :
(centerx || center) ? 'center' :
'stretch', ";\n ").concat(props.css, "\n ") }, children));
};
var templateObject_1$7;
var Wrapper$2 = styled__default["default"].div(templateObject_1$6 || (templateObject_1$6 = __makeTemplateObject(["\n position: relative;\n ", "\n"], ["\n position: relative;\n ", "\n"])), function (props) { return props.css; });
var Skeleton = styled__default["default"].div(templateObject_2$1 || (templateObject_2$1 = __makeTemplateObject(["\n position: absolute;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n margin: 0.125em;\n user-select: none;\n\n ", "\n"], ["\n position: absolute;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n margin: 0.125em;\n user-select: none;\n\n ", "\n"])), function (props) { return props.css; });
var LazyLoad = function (_a) {
var children = _a.children, height = _a.height, width = _a.width;
// @ts-ignore
var bgAltColor = useStore().bgAltColor;
var placeholderRef = React.useRef(null);
var _b = React.useState(false), ready = _b[0], setReady = _b[1];
var removePlaceholder = function () {
placeholderRef.current && placeholderRef.current.remove();
};
return (React__default["default"].createElement(Wrapper$2, { css: "\n height: ".concat(height, "px;\n width: ").concat(width, "px;\n ") },
!ready && placeholderRef &&
React__default["default"].createElement(Skeleton, { ref: placeholderRef, css: "\n background-color: ".concat(bgAltColor, ";\n ") }),
React__default["default"].cloneElement(children, {
onLoad: function () { return setReady(true); },
onError: function () { return removePlaceholder(); }
})));
};
var templateObject_1$6, templateObject_2$1;
var Gif = styled__default["default"].img(templateObject_1$5 || (templateObject_1$5 = __makeTemplateObject(["\n max-width: ", "px;\n border: 2px solid transparent;\n cursor: pointer;\n\n ", "\n"], ["\n max-width: ", "px;\n border: 2px solid transparent;\n cursor: pointer;\n\n ", "\n"])), function (props) { return props.width; }, function (props) { return props.css; });
var MasonryItem = function (_a) {
var data = _a.data, width = _a.width;
// @ts-ignore
var _b = useStore(), callback = _b.callback, accentColor = _b.accentColor;
return (React__default["default"].createElement(LazyLoad, { height: Number(data.images.downsized.height) * ((width) / Number(data.images.downsized.width)), width: width },
React__default["default"].createElement(Gif, { className: 'giphy__masonry-item', alt: data.title, src: data.images.downsized.url, width: width - 10, onClick: function () { return callback(data); }, css: "\n &:hover {\n border-color: ".concat(accentColor, ";\n }\n ") })));
};
var Wrapper$1 = styled__default["default"].div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n overflow-x: hidden;\n overflow-y: scroll;\n max-height: ", "\n max-width: calc(100% - 18px);\n margin: auto;\n position: relative;\n top: 10px;\n\n &::-webkit-scrollbar {\n width: 5px;\n cursor: pointer;\n }\n\n &::-webkit-scrollbar-track {\n background-color: transparent;\n }\n\n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: 0.5em;\n opacity: 0.3;\n }\n\n &::-webkit-scrollbar-thumb:hover {\n opacity: 1;\n width: 10px;\n }\n\n &::-webkit-scrollbar-button {\n display: none;\n }\n"], ["\n overflow-x: hidden;\n overflow-y: scroll;\n max-height: ", "\n max-width: calc(100% - 18px);\n margin: auto;\n position: relative;\n top: 10px;\n\n &::-webkit-scrollbar {\n width: 5px;\n cursor: pointer;\n }\n\n &::-webkit-scrollbar-track {\n background-color: transparent;\n }\n\n &::-webkit-scrollbar-thumb {\n background: ", ";\n border-radius: 0.5em;\n opacity: 0.3;\n }\n\n &::-webkit-scrollbar-thumb:hover {\n opacity: 1;\n width: 10px;\n }\n\n &::-webkit-scrollbar-button {\n display: none;\n }\n"])), function (props) { return "calc(".concat(props.height, "px - 100px);"); }, function (props) { return props.scrollbarColor; });
var MasonryComponent = function (_a) {
var data = _a.data;
// @ts-ignore
var _b = useStore(), columns = _b.columns, width = _b.width, height = _b.height, bgAltColor = _b.bgAltColor;
return (React__default["default"].createElement(Wrapper$1, { height: height, scrollbarColor: bgAltColor, className: 'giphy__masonry' },
React__default["default"].createElement(masonic.Masonry, { items: data, render: MasonryItem, columnCount: columns, columnWidth: (width / columns) - 25, rowGutter: 0, style: { maxWidth: width - 25, overflow: 'hidden' } })));
};
var templateObject_1$5, templateObject_2;
var Loader = function (_a) {
var color = _a.color, _b = _a.css, css = _b === void 0 ? '' : _b;
var Wrapper = styled__default["default"].div(templateObject_1$4 || (templateObject_1$4 = __makeTemplateObject(["\n ", "\n "], ["\n ", "\n "])), css);
return (React__default["default"].createElement(Wrapper, null,
React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "100px", height: "100px", viewBox: "0 0 100 100", preserveAspectRatio: "xMidYMid", style: {
display: 'block',
margin: 'auto'
} },
React__default["default"].createElement("circle", { cx: "50", cy: "50", r: "30", stroke: "transparent", strokeWidth: "10", fill: "none" }),
React__default["default"].createElement("circle", { cx: "50", cy: "50", r: "30", stroke: color, strokeWidth: "8", strokeLinecap: "round", fill: "none" },
React__default["default"].createElement("animateTransform", { attributeName: "transform", type: "rotate", repeatCount: "indefinite", dur: "1.1363636363636365s", values: "0 50 50;180 50 50;720 50 50", keyTimes: "0;0.5;1" }),
React__default["default"].createElement("animate", { attributeName: "stroke-dasharray", repeatCount: "indefinite", dur: "1.1363636363636365s", values: "18.84955592153876 169.64600329384882;94.2477796076938 94.24777960769377;18.84955592153876 169.64600329384882", keyTimes: "0;0.5;1" })))));
};
var templateObject_1$4;
var Wrapper = styled__default["default"].div(templateObject_1$3 || (templateObject_1$3 = __makeTemplateObject(["\n padding-bottom: 0.25em;\n border-radius: 0.25em;\n position: relative;\n ", "\n"], ["\n padding-bottom: 0.25em;\n border-radius: 0.25em;\n position: relative;\n ", "\n"])), function (props) { return props.css; });
var WrapperComponent = function (_a) {
var children = _a.children;
// @ts-ignore
var _b = useStore(), bgColor = _b.bgColor, textColor = _b.textColor, height = _b.height, width = _b.width, css = _b.css;
return (React__default["default"].createElement(Wrapper, { css: "\n background-color: ".concat(bgColor, ";\n color: ").concat(textColor, ";\n height: ").concat(height, "px;\n width: ").concat(width, "px;\n ").concat(css, "\n ") }, children));
};
var templateObject_1$3;
var Input = styled__default["default"].input(templateObject_1$2 || (templateObject_1$2 = __makeTemplateObject(["\n width: 90%;\n margin: 0 auto 0.5em;\n border-radius: 0.25em;\n outline: none;\n border: none;\n padding: 0.25em;\n font-size: 0.95rem;\n\n ", "\n"], ["\n width: 90%;\n margin: 0 auto 0.5em;\n border-radius: 0.25em;\n outline: none;\n border: none;\n padding: 0.25em;\n font-size: 0.95rem;\n\n ", "\n"])), function (props) { return props.css; });
var InputComponent = function (props) {
var _a = React.useState(''), input = _a[0], setInput = _a[1];
// @ts-ignore
var _b = useStore(), inputColor = _b.inputColor, textAltColor = _b.textAltColor;
return (React__default["default"].createElement(Input, __assign({ value: input, className: 'giphy__input', css: "\n background-color: ".concat(inputColor, ";\n color: ").concat(textAltColor, ";\n ") }, props, { onChange: function (e) {
setInput(e.target.value);
props.callback(e.target.value);
} })));
};
var templateObject_1$2;
var Button = styled__default["default"].button(templateObject_1$1 || (templateObject_1$1 = __makeTemplateObject(["\n border: none; outline: none;\n padding: 0.5em;\n border-radius: 0.25em;\n margin: 0.5em;\n cursor: pointer;\n transition: background-color 0.25s;\n\n ", "\n"], ["\n border: none; outline: none;\n padding: 0.5em;\n border-radius: 0.25em;\n margin: 0.5em;\n cursor: pointer;\n transition: background-color 0.25s;\n\n ", "\n"])), function (props) { return props.css; });
var ButtonComponent = function (_a) {
var children = _a.children, active = _a.active, props = __rest(_a, ["children", "active"]);
// @ts-ignore
var _b = useStore(), textColor = _b.textColor, buttonColor = _b.buttonColor;
return (React__default["default"].createElement(Button, __assign({ className: 'giphy__button', css: "\n color: ".concat(textColor, ";\n background-color: ").concat(active ? buttonColor : 'transparent', ";\n &:hover {\n background-color: ").concat(buttonColor, ";\n }\n ") }, props), children));
};
var templateObject_1$1;
var Divider = styled__default["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n height: 0.125em;\n width: 100%;\n opacity: 0.3;\n\n ", "\n"], ["\n height: 0.125em;\n width: 100%;\n opacity: 0.3;\n\n ", "\n"])), function (props) { return props.css; });
var DividerComponent = function () {
// @ts-ignore
var bgAltColor = useStore().bgAltColor;
return (React__default["default"].createElement(Divider, { className: 'giphy__divider', css: "\n background-color: ".concat(bgAltColor, ";\n ") }));
};
var templateObject_1;
var Giphy = function (_a) {
var apiKey = _a.apiKey, _b = _a.callback, callback = _b === void 0 ? function (item) { return console.log('react-awesome-giphy:', item); } : _b, _c = _a.display, display = _c === void 0 ? 'gifs' : _c, _d = _a.limit, limit = _d === void 0 ? 12 : _d, _e = _a.height, height = _e === void 0 ? 425 : _e, _f = _a.width, width = _f === void 0 ? 425 : _f, _g = _a.columns, columns = _g === void 0 ? 2 : _g, _h = _a.textColor, textColor = _h === void 0 ? theme.textColor : _h, _j = _a.textAltColor, textAltColor = _j === void 0 ? theme.textAltColor : _j, _k = _a.bgColor, bgColor = _k === void 0 ? theme.bgColor : _k, _l = _a.bgAltColor, bgAltColor = _l === void 0 ? theme.bgAltColor : _l, _m = _a.buttonColor, buttonColor = _m === void 0 ? theme.buttonColor : _m, _o = _a.inputColor, inputColor = _o === void 0 ? theme.inputColor : _o, _p = _a.accentColor, accentColor = _p === void 0 ? theme.accentColor : _p, props = __rest(_a, ["apiKey", "callback", "display", "limit", "height", "width", "columns", "textColor", "textAltColor", "bgColor", "bgAltColor", "buttonColor", "inputColor", "accentColor"]);
var _q = React.useState(false), loading = _q[0], setLoading = _q[1];
var _r = React.useState([]), data = _r[0], setData = _r[1];
var _s = React.useState(display), currentDisplay = _s[0], setCurrentDisplay = _s[1];
var search = React.useRef("");
var isTyping = React.useRef(false);
var timeout = React.useRef();
var handleSearch = function (input) {
search.current = input;
var runSearch = function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(input.length > 0)) return [3 /*break*/, 2];
return [4 /*yield*/, getData(currentDisplay, 'search', input)];
case 1:
_a.sent();
return [3 /*break*/, 4];
case 2: return [4 /*yield*/, getData(currentDisplay, 'trending')];
case 3:
_a.sent();
_a.label = 4;
case 4:
isTyping.current = false;
return [2 /*return*/];
}
});
}); };
if (isTyping.current) {
clearTimeout(timeout.current);
timeout.current = setTimeout(runSearch, 500);
}
else {
setLoading(true);
isTyping.current = true;
timeout.current = setTimeout(runSearch, 500);
}
};
var getData = function (type, endpoint, query) { return __awaiter(void 0, void 0, void 0, function () {
var offset, rating, randomId, bundle;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
offset = props.offset, rating = props.rating, randomId = props.randomId, bundle = props.bundle;
setLoading(true);
return [4 /*yield*/, fetch("https://api.giphy.com/v1/".concat(type, "/").concat(endpoint, "?") +
"api_key=".concat(apiKey) +
"&limit=".concat(limit) +
[
query && "&q=".concat(query),
offset && "&offset=".concat(offset),
rating && "&rating=".concat(rating),
randomId && "&random_id=".concat(randomId),
bundle && "&bundle=".concat(bundle)
].join(''), {
headers: {
'Accept': 'application/json'
}
})
.then(function (res) { return res.json(); })
.then(function (data) { return setData(data.data); })];
case 1:
_a.sent();
setLoading(false);
return [2 /*return*/];
}
});
}); };
React.useEffect(function () {
if (props.displayCallback) {
props.displayCallback(currentDisplay);
}
}, [currentDisplay]);
React.useEffect(function () {
setCurrentDisplay(display);
}, [display]);
React.useEffect(function () {
if (!loading) {
setLoading(true);
}
if (search.current.length == 0) {
setTimeout(function () { return getData(currentDisplay, 'trending'); }, 500);
}
else {
setTimeout(function () { return getData(currentDisplay, 'search', search.current); }, 500);
}
}, [currentDisplay]);
return (React__default["default"].createElement(StoreProvider, { value: __assign({ apiKey: apiKey, callback: callback, height: height, width: width, columns: columns, textColor: textColor, textAltColor: textAltColor, bgColor: bgColor, bgAltColor: bgAltColor, buttonColor: buttonColor, inputColor: inputColor, accentColor: accentColor }, props) },
React__default["default"].createElement(WrapperComponent, null,
React__default["default"].createElement(Col, null,
React__default["default"].createElement(Row, { centerx: true },
React__default["default"].createElement(ButtonComponent, { active: currentDisplay == 'gifs', onClick: function () {
setCurrentDisplay('gifs');
} }, "GIFs"),
React__default["default"].createElement(ButtonComponent, { active: currentDisplay == 'stickers', onClick: function () {
setCurrentDisplay('stickers');
} }, "Stickers")),
React__default["default"].createElement(InputComponent, { type: 'text', spellCheck: false, placeholder: 'Search GIPHY', callback: handleSearch })),
React__default["default"].createElement(DividerComponent, null),
loading ?
React__default["default"].createElement(Loader, { color: accentColor, css: "\n position: absolute;\n top: 30%;\n width: 100%;\n align-self: center;\n margin: 0 auto;\n background-color: ".concat(bgColor, ";\n ") })
:
React__default["default"].createElement(MasonryComponent, { data: data }))));
};
return Giphy;
}));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9zdHlsZXMvdGhlbWUudHMiLCIuLi9zcmMvaG9va3MvdXNlU3RvcmUudHN4IiwiLi4vc3JjL2NvbXBvbmVudHMvY29tcG9zaXRpb24vRmxleC50c3giLCIuLi9zcmMvY29tcG9uZW50cy91dGlsaXR5L0xhenlMb2FkLnRzeCIsIi4uL3NyYy9jb21wb25lbnRzL2Jsb2NrL01hc29ucnkudHN4IiwiLi4vc3JjL2NvbXBvbmVudHMvYmxvY2svTG9hZGVyLnRzeCIsIi4uL3NyYy9jb21wb25lbnRzL2Jsb2NrL1dyYXBwZXIudHN4IiwiLi4vc3JjL2NvbXBvbmVudHMvYmxvY2svSW5wdXQudHN4IiwiLi4vc3JjL2NvbXBvbmVudHMvYmxvY2svQnV0dG9uLnRzeCIsIi4uL3NyYy9jb21wb25lbnRzL2Jsb2NrL0RpdmlkZXIudHN4IiwiLi4vc3JjL2luZGV4LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCB0aGVtZSA9IHtcbiAgICB0ZXh0Q29sb3I6ICcjRkVGRUZGJyxcbiAgICB0ZXh0QWx0Q29sb3I6ICcjQUZCMUIyJyxcbiAgICBiZ0NvbG9yOiAnIzJGMzEzNicsXG4gICAgYmdBbHRDb2xvcjogJyM0ZTRlNGUnLFxuICAgIGJ1dHRvbkNvbG9yOiAnIzRGNTM1QycsXG4gICAgaW5wdXRDb2xvcjogJyMyMTIzMjUnLFxuICAgIGFjY2VudENvbG9yOiAnIzAyQUVGNCdcbn1cblxuZXhwb3J0IGRlZmF1bHQgdGhlbWUiLCJpbXBvcnQgUmVhY3QsIHsgY3JlYXRlQ29udGV4dCwgdXNlQ29udGV4dCB9IGZyb20gJ3JlYWN0J1xuXG5pbXBvcnQgeyBQcm9wcyB9IGZyb20gJy4uL2luZGV4J1xuXG5jb25zdCBTdG9yZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0PFByb3BzIHwgbnVsbD4obnVsbClcblxuY29uc3QgdXNlU3RvcmUgPSAoKSA9PiB1c2VDb250ZXh0KFN0b3JlQ29udGV4dClcblxuaW50ZXJmYWNlIFN0b3JlUHJvcHMge1xuICAgIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGUsXG4gICAgdmFsdWU6IGFueVxufVxuXG5jb25zdCBTdG9yZVByb3ZpZGVyID0gKHsgY2hpbGRyZW4sIHZhbHVlIH06IFN0b3JlUHJvcHMpID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgICA8U3RvcmVDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+XG4gICAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvU3RvcmVDb250ZXh0LlByb3ZpZGVyPlxuICAgIClcbn1cblxuZXhwb3J0IHsgU3RvcmVQcm92aWRlciwgdXNlU3RvcmUgYXMgZGVmYXVsdCB9IiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmludGVyZmFjZSBQcm9wcyB7XG4gICAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZSxcbiAgICBjc3M/OiBzdHJpbmcsXG4gICAgbGVmdD86IGJvb2xlYW4sXG4gICAgcmlnaHQ/OiBib29sZWFuLFxuICAgIHRvcD86IGJvb2xlYW4sXG4gICAgYm90dG9tPzogYm9vbGVhbixcbiAgICBjZW50ZXJ4PzogYm9vbGVhbixcbiAgICBjZW50ZXJ5PzogYm9vbGVhbixcbiAgICBjZW50ZXI/OiBib29sZWFuXG59XG5cbmludGVyZmFjZSBTdGFja1Byb3BzIHtcbiAgICBjc3M6IHN0cmluZ1xufVxuXG5jb25zdCBTdGFjayA9IHN0eWxlZC5kaXY8U3RhY2tQcm9wcz5gXG4gICAgZGlzcGxheTogZmxleDtcbiAgICAke3Byb3BzID0+IHByb3BzLmNzc31cbmBcblxuZXhwb3J0IGNvbnN0IFJvdyA9ICh7XG4gICAgY2hpbGRyZW4sIC4uLnByb3BzXG59OiBQcm9wcykgPT4ge1xuXG4gICAgY29uc3Qge1xuICAgICAgICBsZWZ0LCByaWdodCwgdG9wLCBib3R0b20sIGNlbnRlcngsIGNlbnRlcnksIGNlbnRlclxuICAgIH0gPSBwcm9wc1xuXG4gICAgcmV0dXJuIChcbiAgICAgICAgPFN0YWNrXG4gICAgICAgICAgICBjc3M9e2BcbiAgICAgICAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuXG4gICAgICAgICAgICAgICAgYWxpZ24taXRlbXM6ICR7XG4gICAgICAgICAgICAgICAgICAgIHRvcCA/ICdmbGV4LXN0YXJ0JyA6XG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbSA/ICdmbGV4LWVuZCcgOlxuICAgICAgICAgICAgICAgICAgICAoY2VudGVyeSB8fCBjZW50ZXIpID8gJ2NlbnRlcicgOiBcbiAgICAgICAgICAgICAgICAgICAgJ3N0cmV0Y2gnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgXG4gICAgICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiAke1xuICAgICAgICAgICAgICAgICAgICBsZWZ0ID8gJ2ZsZXgtc3RhcnQnIDpcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQgPyAnZmxleC1lbmQnIDpcbiAgICAgICAgICAgICAgICAgICAgKGNlbnRlcnggfHwgY2VudGVyKSA/ICdjZW50ZXInIDogXG4gICAgICAgICAgICAgICAgICAgICdzdHJldGNoJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgJHtwcm9wcy5jc3N9XG4gICAgICAgICAgICBgfVxuICAgICAgICA+XG4gICAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvU3RhY2s+XG4gICAgKVxufVxuXG5leHBvcnQgY29uc3QgQ29sID0gKHtcbiAgICBjaGlsZHJlbiwgLi4ucHJvcHNcbn06IFByb3BzKSA9PiB7XG5cbiAgICBjb25zdCB7XG4gICAgICAgIGxlZnQsIHJpZ2h0LCB0b3AsIGJvdHRvbSwgY2VudGVyeCwgY2VudGVyeSwgY2VudGVyXG4gICAgfSA9IHByb3BzXG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8U3RhY2tcbiAgICAgICAgICAgIGNzcz17YFxuICAgICAgICAgICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG5cbiAgICAgICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6ICR7XG4gICAgICAgICAgICAgICAgICAgIHRvcCA/ICdmbGV4LXN0YXJ0JyA6XG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbSA/ICdmbGV4LWVuZCcgOlxuICAgICAgICAgICAgICAgICAgICAoY2VudGVyeSB8fCBjZW50ZXIpID8gJ2NlbnRlcicgOiBcbiAgICAgICAgICAgICAgICAgICAgJ3N0cmV0Y2gnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgXG4gICAgICAgICAgICAgICAgYWxpZ24taXRlbXM6ICR7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPyAnZmxleC1zdGFydCcgOlxuICAgICAgICAgICAgICAgICAgICByaWdodCA/ICdmbGV4LWVuZCcgOlxuICAgICAgICAgICAgICAgICAgICAoY2VudGVyeCB8fCBjZW50ZXIpID8gJ2NlbnRlcicgOiBcbiAgICAgICAgICAgICAgICAgICAgJ3N0cmV0Y2gnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAke3Byb3BzLmNzc31cbiAgICAgICAgICAgIGB9XG4gICAgICAgID5cbiAgICAgICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgPC9TdGFjaz5cbiAgICApXG59IiwiaW1wb3J0IFJlYWN0LCB7IHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5pbXBvcnQgdXNlU3RvcmUgZnJvbSAnLi4vLi4vaG9va3MvdXNlU3RvcmUnXG5cbmludGVyZmFjZSBQcm9wcyB7XG4gICAgY2hpbGRyZW4/OiBhbnksXG4gICAgaGVpZ2h0OiBudW1iZXIsXG4gICAgd2lkdGg6IG51bWJlclxufVxuXG5pbnRlcmZhY2UgQ29tcG9uZW50UHJvcHMge1xuICAgIGNzcz86IHN0cmluZ1xufVxuXG5jb25zdCBXcmFwcGVyID0gc3R5bGVkLmRpdjxDb21wb25lbnRQcm9wcz5gXG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICR7cHJvcHMgPT4gcHJvcHMuY3NzfVxuYFxuXG5jb25zdCBTa2VsZXRvbiA9IHN0eWxlZC5kaXY8Q29tcG9uZW50UHJvcHM+YFxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICBsZWZ0OiAwO1xuICAgIHRvcDogMDtcbiAgICByaWdodDogMDtcbiAgICBib3R0b206IDA7XG4gICAgbWFyZ2luOiAwLjEyNWVtO1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuXG4gICAgJHtwcm9wcyA9PiBwcm9wcy5jc3N9XG5gXG5cbmNvbnN0IExhenlMb2FkID0gKHsgY2hpbGRyZW4sIGhlaWdodCwgd2lkdGggfTogUHJvcHMpID0+IHtcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCB7IGJnQWx0Q29sb3IgfSA9IHVzZVN0b3JlKClcblxuICAgIGNvbnN0IHBsYWNlaG9sZGVyUmVmID0gdXNlUmVmPEhUTUxEaXZFbGVtZW50PihudWxsKVxuICAgIGNvbnN0IFsgcmVhZHksIHNldFJlYWR5IF0gPSB1c2VTdGF0ZShmYWxzZSlcbiAgICBjb25zdCByZW1vdmVQbGFjZWhvbGRlciA9ICgpID0+IHtcbiAgICAgICAgcGxhY2Vob2xkZXJSZWYuY3VycmVudCAmJiBwbGFjZWhvbGRlclJlZi5jdXJyZW50LnJlbW92ZSgpXG4gICAgfVxuICAgIFxuICAgIFxuICAgIHJldHVybiAoXG4gICAgICAgIDxXcmFwcGVyXG4gICAgICAgICAgICBjc3M9e2BcbiAgICAgICAgICAgICAgICBoZWlnaHQ6ICR7aGVpZ2h0fXB4O1xuICAgICAgICAgICAgICAgIHdpZHRoOiAke3dpZHRofXB4O1xuICAgICAgICAgICAgYH1cbiAgICAgICAgPlxuICAgICAgICAgICAgeyFyZWFkeSAmJiBwbGFjZWhvbGRlclJlZiAmJlxuICAgICAgICAgICAgICAgIDxTa2VsZXRvbiBcbiAgICAgICAgICAgICAgICAgICAgcmVmPXtwbGFjZWhvbGRlclJlZn0gXG4gICAgICAgICAgICAgICAgICAgIGNzcz17YFxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogJHtiZ0FsdENvbG9yfTtcbiAgICAgICAgICAgICAgICAgICAgYH1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAge1JlYWN0LmNsb25lRWxlbWVudChjaGlsZHJlbiwge1xuICAgICAgICAgICAgICAgIG9uTG9hZDogKCkgPT4gc2V0UmVhZHkodHJ1ZSksXG4gICAgICAgICAgICAgICAgb25FcnJvcjogKCkgPT4gcmVtb3ZlUGxhY2Vob2xkZXIoKVxuICAgICAgICAgICAgfSl9XG4gICAgICAgIDwvV3JhcHBlcj5cbiAgICApXG59XG5cbmV4cG9ydCBkZWZhdWx0IExhenlMb2FkIiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBNYXNvbnJ5IH0gZnJvbSAnbWFzb25pYydcblxuaW1wb3J0IHVzZVN0b3JlIGZyb20gJy4uLy4uL2hvb2tzL3VzZVN0b3JlJ1xuXG5pbXBvcnQgTGF6eUxvYWQgZnJvbSAnLi4vdXRpbGl0eS9MYXp5TG9hZCdcblxuaW50ZXJmYWNlIE1hc29ucnlJdGVtUHJvcHMge1xuICB3aWR0aDogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICBkYXRhOiB7XG4gICAgdGl0bGU6IHN0cmluZyxcbiAgICBpbWFnZXM6IHtcbiAgICAgIGRvd25zaXplZDoge1xuICAgICAgICB1cmw6IHN0cmluZyxcbiAgICAgICAgaGVpZ2h0OiBzdHJpbmcsXG4gICAgICAgIHdpZHRoOiBzdHJpbmdcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuY29uc3QgR2lmID0gc3R5bGVkLmltZzx7Y3NzOiBzdHJpbmd9PmBcbiAgbWF4LXdpZHRoOiAke3Byb3BzID0+IHByb3BzLndpZHRofXB4O1xuICBib3JkZXI6IDJweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuXG4gICR7cHJvcHMgPT4gcHJvcHMuY3NzfVxuYFxuXG5jb25zdCBNYXNvbnJ5SXRlbSA9ICh7IGRhdGEsIHdpZHRoIH06IE1hc29ucnlJdGVtUHJvcHMpID0+IHtcblxuICAvLyBAdHMtaWdub3JlXG4gIGNvbnN0IHsgY2FsbGJhY2ssIGFjY2VudENvbG9yIH0gPSB1c2VTdG9yZSgpXG5cbiAgcmV0dXJuIChcbiAgICAgIDxMYXp5TG9hZFxuICAgICAgICBoZWlnaHQ9e1xuICAgICAgICAgIE51bWJlcihkYXRhLmltYWdlcy5kb3duc2l6ZWQuaGVpZ2h0KSAqIChcbiAgICAgICAgICAgICh3aWR0aCkgLyBOdW1iZXIoZGF0YS5pbWFnZXMuZG93bnNpemVkLndpZHRoKVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgICB3aWR0aD17d2lkdGh9XG4gICAgICA+XG4gICAgICAgIDxHaWZcbiAgICAgICAgICBjbGFzc05hbWU9J2dpcGh5X19tYXNvbnJ5LWl0ZW0nXG4gICAgICAgICAgYWx0PXtkYXRhLnRpdGxlfVxuICAgICAgICAgIHNyYz17ZGF0YS5pbWFnZXMuZG93bnNpemVkLnVybH1cbiAgICAgICAgICB3aWR0aD17d2lkdGggLSAxMH1cbiAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBjYWxsYmFjayhkYXRhKX1cbiAgICAgICAgICBjc3M9e2BcbiAgICAgICAgICAgICY6aG92ZXIge1xuICAgICAgICAgICAgICBib3JkZXItY29sb3I6ICR7YWNjZW50Q29sb3J9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIGB9XG4gICAgICAgIC8+XG4gICAgICA8L0xhenlMb2FkPlxuICApXG59XG5cbmludGVyZmFjZSBQcm9wcyB7XG4gIGRhdGE6IGFueVtdXG59XG5cbmNvbnN0IFdyYXBwZXIgPSBzdHlsZWQuZGl2PHtoZWlnaHQ6IG51bWJlciwgc2Nyb2xsYmFyQ29sb3I6IHN0cmluZ30+YFxuICBvdmVyZmxvdy14OiBoaWRkZW47XG4gIG92ZXJmbG93LXk6IHNjcm9sbDtcbiAgbWF4LWhlaWdodDogJHtwcm9wcyA9PiBgY2FsYygke3Byb3BzLmhlaWdodH1weCAtIDEwMHB4KTtgfVxuICBtYXgtd2lkdGg6IGNhbGMoMTAwJSAtIDE4cHgpO1xuICBtYXJnaW46IGF1dG87XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgdG9wOiAxMHB4O1xuXG4gICY6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcbiAgICB3aWR0aDogNXB4O1xuICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICB9XG5cbiAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICB9XG5cbiAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIge1xuICAgIGJhY2tncm91bmQ6ICR7cHJvcHMgPT4gcHJvcHMuc2Nyb2xsYmFyQ29sb3J9O1xuICAgIGJvcmRlci1yYWRpdXM6IDAuNWVtO1xuICAgIG9wYWNpdHk6IDAuMztcbiAgfVxuXG4gICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcbiAgICBvcGFjaXR5OiAxO1xuICAgICAgd2lkdGg6IDEwcHg7XG4gIH1cblxuICAmOjotd2Via2l0LXNjcm9sbGJhci1idXR0b24ge1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gIH1cbmBcblxuY29uc3QgTWFzb25yeUNvbXBvbmVudDogUmVhY3QuRkM8UHJvcHM+ID0gKHsgZGF0YSB9KSA9PiB7XG5cbiAgLy8gQHRzLWlnbm9yZVxuICBjb25zdCB7IGNvbHVtbnMsIHdpZHRoLCBoZWlnaHQsIGJnQWx0Q29sb3IgfSA9IHVzZVN0b3JlKClcblxuICByZXR1cm4gKFxuICAgIDxXcmFwcGVyIFxuICAgICAgaGVpZ2h0PXtoZWlnaHR9XG4gICAgICBzY3JvbGxiYXJDb2xvcj17YmdBbHRDb2xvcn0gXG4gICAgICBjbGFzc05hbWU9J2dpcGh5X19tYXNvbnJ5J1xuICAgID5cbiAgICAgIDxNYXNvbnJ5IFxuICAgICAgICBpdGVtcz17ZGF0YX0gXG4gICAgICAgIHJlbmRlcj17TWFzb25yeUl0ZW19IFxuICAgICAgICBjb2x1bW5Db3VudD17Y29sdW1uc31cbiAgICAgICAgY29sdW1uV2lkdGg9eyh3aWR0aCAvIGNvbHVtbnMpIC0gMjV9XG4gICAgICAgIHJvd0d1dHRlcj17MH1cbiAgICAgICAgc3R5bGU9e3sgbWF4V2lkdGg6IHdpZHRoIC0gMjUsIG92ZXJmbG93OiAnaGlkZGVuJyB9fVxuICAgICAgLz5cbiAgICA8L1dyYXBwZXI+XG4gIClcbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFzb25yeUNvbXBvbmVudCIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5pbnRlcmZhY2UgUHJvcHMge1xuICAgIGNvbG9yOiBzdHJpbmcsXG4gICAgY3NzPzogc3RyaW5nXG59XG5cbmNvbnN0IExvYWRlciA9ICh7XG4gICAgY29sb3IsXG4gICAgY3NzID0gJydcbn06IFByb3BzKSA9PiB7XG5cbiAgICBjb25zdCBXcmFwcGVyID0gc3R5bGVkLmRpdmBcbiAgICAgICAgJHtjc3N9XG4gICAgYFxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgPFdyYXBwZXI+XG5cbiAgICAgICAgPHN2ZyBcbiAgICAgICAgICAgIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuICAgICAgICAgICAgd2lkdGg9XCIxMDBweFwiIFxuICAgICAgICAgICAgaGVpZ2h0PVwiMTAwcHhcIiBcbiAgICAgICAgICAgIHZpZXdCb3g9XCIwIDAgMTAwIDEwMFwiIFxuICAgICAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbz1cInhNaWRZTWlkXCJcbiAgICAgICAgICAgIHN0eWxlPXt7XG4gICAgICAgICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJyxcbiAgICAgICAgICAgICAgICBtYXJnaW46ICdhdXRvJ1xuICAgICAgICAgICAgfX1cbiAgICAgICAgPlxuICAgICAgICAgICAgPGNpcmNsZSBcbiAgICAgICAgICAgICAgICBjeD1cIjUwXCIgXG4gICAgICAgICAgICAgICAgY3k9XCI1MFwiIFxuICAgICAgICAgICAgICAgIHI9XCIzMFwiIFxuICAgICAgICAgICAgICAgIHN0cm9rZT1cInRyYW5zcGFyZW50XCIgXG4gICAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg9XCIxMFwiIFxuICAgICAgICAgICAgICAgIGZpbGw9XCJub25lXCIgXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGNpcmNsZSBcbiAgICAgICAgICAgICAgICBjeD1cIjUwXCIgXG4gICAgICAgICAgICAgICAgY3k9XCI1MFwiIFxuICAgICAgICAgICAgICAgIHI9XCIzMFwiIFxuICAgICAgICAgICAgICAgIHN0cm9rZT17Y29sb3J9IFxuICAgICAgICAgICAgICAgIHN0cm9rZVdpZHRoPVwiOFwiIFxuICAgICAgICAgICAgICAgIHN0cm9rZUxpbmVjYXA9XCJyb3VuZFwiIFxuICAgICAgICAgICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBcbiAgICAgICAgICAgICAgICAgICAgYXR0cmlidXRlTmFtZT1cInRyYW5zZm9ybVwiIFxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwicm90YXRlXCIgXG4gICAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PVwiaW5kZWZpbml0ZVwiIFxuICAgICAgICAgICAgICAgICAgICBkdXI9XCIxLjEzNjM2MzYzNjM2MzYzNjVzXCIgXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlcz1cIjAgNTAgNTA7MTgwIDUwIDUwOzcyMCA1MCA1MFwiIFxuICAgICAgICAgICAgICAgICAgICBrZXlUaW1lcz1cIjA7MC41OzFcIiBcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDxhbmltYXRlIFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZU5hbWU9XCJzdHJva2UtZGFzaGFycmF5XCIgXG4gICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9XCJpbmRlZmluaXRlXCIgXG4gICAgICAgICAgICAgICAgZHVyPVwiMS4xMzYzNjM2MzYzNjM2MzY1c1wiIFxuICAgICAgICAgICAgICAgIHZhbHVlcz1cIjE4Ljg0OTU1NTkyMTUzODc2IDE2OS42NDYwMDMyOTM4NDg4Mjs5NC4yNDc3Nzk2MDc2OTM4IDk0LjI0Nzc3OTYwNzY5Mzc3OzE4Ljg0OTU1NTkyMTUzODc2IDE2OS42NDYwMDMyOTM4NDg4MlwiIFxuICAgICAgICAgICAgICAgIGtleVRpbWVzPVwiMDswLjU7MVwiIC8+XG4gICAgICAgICAgICA8L2NpcmNsZT5cbiAgICAgICAgPC9zdmc+XG4gICAgICAgIFxuICAgICAgICA8L1dyYXBwZXI+XG4gICAgKVxufVxuXG5leHBvcnQgZGVmYXVsdCBMb2FkZXIiLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcblxuaW1wb3J0IHVzZVN0b3JlIGZyb20gJy4uLy4uL2hvb2tzL3VzZVN0b3JlJ1xuXG5pbnRlcmZhY2UgUHJvcHMge1xuICAgIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGVcbn1cblxuaW50ZXJmYWNlIFdyYXBwZXJQcm9wcyB7XG4gICAgY3NzPzogc3RyaW5nXG59XG5cbmNvbnN0IFdyYXBwZXIgPSBzdHlsZWQuZGl2PFdyYXBwZXJQcm9wcz5gXG4gICAgcGFkZGluZy1ib3R0b206IDAuMjVlbTtcbiAgICBib3JkZXItcmFkaXVzOiAwLjI1ZW07XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICR7cHJvcHMgPT4gcHJvcHMuY3NzfVxuYFxuXG5jb25zdCBXcmFwcGVyQ29tcG9uZW50ID0gKHsgY2hpbGRyZW4gfTogUHJvcHMpID0+IHtcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCB7IGJnQ29sb3IsIHRleHRDb2xvciwgaGVpZ2h0LCB3aWR0aCwgY3NzIH0gPSB1c2VTdG9yZSgpXG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8V3JhcHBlclxuICAgICAgICAgICAgY3NzPXtgXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogJHtiZ0NvbG9yfTtcbiAgICAgICAgICAgICAgICBjb2xvcjogJHt0ZXh0Q29sb3J9O1xuICAgICAgICAgICAgICAgIGhlaWdodDogJHtoZWlnaHR9cHg7XG4gICAgICAgICAgICAgICAgd2lkdGg6ICR7d2lkdGh9cHg7XG4gICAgICAgICAgICAgICAgJHtjc3N9XG4gICAgICAgICAgICBgfVxuICAgICAgICA+XG4gICAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvV3JhcHBlcj5cbiAgICApXG59XG5cbmV4cG9ydCBkZWZhdWx0IFdyYXBwZXJDb21wb25lbnQiLCJpbXBvcnQgUmVhY3QsIHsgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJ1xuXG5pbXBvcnQgdXNlU3RvcmUgZnJvbSAnLi4vLi4vaG9va3MvdXNlU3RvcmUnXG5cbmludGVyZmFjZSBQcm9wcyBleHRlbmRzIFxuICAgIFJlYWN0LklucHV0SFRNTEF0dHJpYnV0ZXM8SFRNTElucHV0RWxlbWVudD4ge1xuICAgICAgICBjYWxsYmFjazogKGlucHV0OiBzdHJpbmcpID0+IHZvaWRcbn1cblxuaW50ZXJmYWNlIElucHV0UHJvcHMge1xuICAgIGNzcz86IHN0cmluZ1xufVxuXG5jb25zdCBJbnB1dCA9IHN0eWxlZC5pbnB1dDxJbnB1dFByb3BzPmBcbiAgICB3aWR0aDogOTAlO1xuICAgIG1hcmdpbjogMCBhdXRvIDAuNWVtO1xuICAgIGJvcmRlci1yYWRpdXM6IDAuMjVlbTtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBwYWRkaW5nOiAwLjI1ZW07XG4gICAgZm9udC1zaXplOiAwLjk1cmVtO1xuXG4gICAgJHtwcm9wcyA9PiBwcm9wcy5jc3N9XG5gXG5cblxuY29uc3QgSW5wdXRDb21wb25lbnQgPSAocHJvcHM6IFByb3BzKSA9PiB7XG5cbiAgICBjb25zdCBbIGlucHV0LCBzZXRJbnB1dCBdID0gdXNlU3RhdGUoJycpXG5cbiAgICAvLyBAdHMtaWdub3JlXG4gICAgY29uc3QgeyBpbnB1dENvbG9yLCB0ZXh0QWx0Q29sb3IgfSA9IHVzZVN0b3JlKClcblxuICAgIHJldHVybiAoXG4gICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgdmFsdWU9e2lucHV0fVxuICAgICAgICAgICAgY2xhc3NOYW1lPSdnaXBoeV9faW5wdXQnXG4gICAgICAgICAgICBjc3M9e2BcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAke2lucHV0Q29sb3J9O1xuICAgICAgICAgICAgICAgIGNvbG9yOiAke3RleHRBbHRDb2xvcn07XG4gICAgICAgICAgICBgfVxuICAgICAgICAgICAgey4uLnByb3BzfVxuICAgICAgICAgICAgb25DaGFuZ2U9e2UgPT4ge1xuICAgICAgICAgICAgICAgIHNldElucHV0KGUudGFyZ2V0LnZhbHVlKVxuICAgICAgICAgICAgICAgIHByb3BzLmNhbGxiYWNrKGUudGFyZ2V0LnZhbHVlKVxuICAgICAgICAgICAgfX1cbiAgICAgICAgLz5cbiAgICApXG59XG5cbmV4cG9ydCBkZWZhdWx0IElucHV0Q29tcG9uZW50IiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5cbmltcG9ydCB1c2VTdG9yZSBmcm9tICcuLi8uLi9ob29rcy91c2VTdG9yZSdcblxuaW50ZXJmYWNlIFByb3BzIFxuICAgIGV4dGVuZHMgUmVhY3QuQnV0dG9uSFRNTEF0dHJpYnV0ZXM8SFRNTEJ1dHRvbkVsZW1lbnQ+IHtcbiAgICBjaGlsZHJlbj86IFJlYWN0LlJlYWN0Tm9kZSxcbiAgICBhY3RpdmU6IGJvb2xlYW4sXG4gICAgY3NzPzogc3RyaW5nXG59XG5cbmludGVyZmFjZSBCdXR0b25Qcm9wcyB7XG4gICAgY3NzPzogc3RyaW5nXG59XG5cbmNvbnN0IEJ1dHRvbiA9IHN0eWxlZC5idXR0b248QnV0dG9uUHJvcHM+YFxuICAgIGJvcmRlcjogbm9uZTsgb3V0bGluZTogbm9uZTtcbiAgICBwYWRkaW5nOiAwLjVlbTtcbiAgICBib3JkZXItcmFkaXVzOiAwLjI1ZW07XG4gICAgbWFyZ2luOiAwLjVlbTtcbiAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgdHJhbnNpdGlvbjogYmFja2dyb3VuZC1jb2xvciAwLjI1cztcblxuICAgICR7cHJvcHMgPT4gcHJvcHMuY3NzfVxuYFxuXG5jb25zdCBCdXR0b25Db21wb25lbnQgPSAoeyBjaGlsZHJlbiwgYWN0aXZlLCAuLi5wcm9wcyB9OiBQcm9wcykgPT4ge1xuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNvbnN0IHsgdGV4dENvbG9yLCBidXR0b25Db2xvciB9ID0gdXNlU3RvcmUoKVxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgPEJ1dHRvblxuICAgICAgICAgICAgY2xhc3NOYW1lPSdnaXBoeV9fYnV0dG9uJ1xuICAgICAgICAgICAgY3NzPXtgXG4gICAgICAgICAgICAgICAgY29sb3I6ICR7dGV4dENvbG9yfTtcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAke2FjdGl2ZSA/IGJ1dHRvbkNvbG9yIDogJ3RyYW5zcGFyZW50J307XG4gICAgICAgICAgICAgICAgJjpob3ZlciB7XG4gICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICR7YnV0dG9uQ29sb3J9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGB9XG4gICAgICAgICAgICB7Li4ucHJvcHN9XG4gICAgICAgID5cbiAgICAgICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgPC9CdXR0b24+XG4gICAgKVxufVxuXG5leHBvcnQgZGVmYXVsdCBCdXR0b25Db21wb25lbnQiLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCdcblxuaW1wb3J0IHVzZVN0b3JlIGZyb20gJy4uLy4uL2hvb2tzL3VzZVN0b3JlJ1xuXG5pbnRlcmZhY2UgRGl2aWRlclByb3BzIHtcbiAgICBjc3M/OiBzdHJpbmdcbn1cblxuY29uc3QgRGl2aWRlciA9IHN0eWxlZC5kaXY8RGl2aWRlclByb3BzPmBcbiAgICBoZWlnaHQ6IDAuMTI1ZW07XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgb3BhY2l0eTogMC4zO1xuXG4gICAgJHtwcm9wcyA9PiBwcm9wcy5jc3N9XG5gXG5cbmNvbnN0IERpdmlkZXJDb21wb25lbnQgPSAoKSA9PiB7XG5cbiAgICAvLyBAdHMtaWdub3JlXG4gICAgY29uc3QgeyBiZ0FsdENvbG9yIH0gPSB1c2VTdG9yZSgpXG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8RGl2aWRlclxuICAgICAgICAgICAgY2xhc3NOYW1lPSdnaXBoeV9fZGl2aWRlcidcbiAgICAgICAgICAgIGNzcz17YFxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICR7YmdBbHRDb2xvcn07XG4gICAgICAgICAgICBgfVxuICAgICAgICAvPlxuICAgIClcbn1cblxuZXhwb3J0IGRlZmF1bHQgRGl2aWRlckNvbXBvbmVudCIsImltcG9ydCBSZWFjdCwgeyB1c2VFZmZlY3QsIHVzZVN0YXRlLCB1c2VSZWYgfSBmcm9tICdyZWFjdCdcblxuaW1wb3J0IHRoZW1lIGZyb20gJy4vc3R5bGVzL3RoZW1lJ1xuXG5pbXBvcnQgeyBTdG9yZVByb3ZpZGVyIH0gZnJvbSAnLi9ob29rcy91c2VTdG9yZSdcbmltcG9ydCB7IFxuICAgIFJvdywgQ29sLCBMb2FkZXIsIE1hc29ucnksIFdyYXBwZXIsIElucHV0LCBCdXR0b24sIERpdmlkZXJcbn0gZnJvbSAnLi9jb21wb25lbnRzJ1xuXG5leHBvcnQgdHlwZSBQcm9wcyA9IHtcbiAgICBhcGlLZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChpdGVtOiBhbnkpID0+IHZvaWQsXG5cbiAgICBkaXNwbGF5Q2FsbGJhY2s/OiAoc3RhdGU6ICdnaWZzJyB8ICdzdGlja2VycycpID0+IHZvaWQsXG4gICAgZGlzcGxheT86ICdnaWZzJyB8ICdzdGlja2VycycsXG4gICAgLy8gdXBkYXRlRGlzcGxheT86IChzdGF0ZTogJ2dpZnMnIHwgJ3N0aWNrZXJzJykgPT4gdm9pZCxcblxuICAgIGxpbWl0PzogbnVtYmVyLFxuICAgIG9mZnNldD86IG51bWJlcixcbiAgICByYXRpbmc/OiAnZycgfCAncGcnIHwgJ3BnLTEzJyB8ICdyJyxcbiAgICByYW5kb21JZD86IHN0cmluZyxcbiAgICBidW5kbGU/OiBzdHJpbmcsXG5cbiAgICBoZWlnaHQ/OiBudW1iZXIsXG4gICAgd2lkdGg/OiBudW1iZXIsXG4gICAgY3NzPzogc3RyaW5nLFxuICAgIGNvbHVtbnM/OiBudW1iZXIsXG5cbiAgICB0ZXh0Q29sb3I/OiBzdHJpbmcsXG4gICAgdGV4dEFsdENvbG9yPzogc3RyaW5nLFxuICAgIGJnQ29sb3I/OiBzdHJpbmcsXG4gICAgYmdBbHRDb2xvcj86IHN0cmluZyxcbiAgICBidXR0b25Db2xvcj86IHN0cmluZyxcbiAgICBpbnB1dENvbG9yPzogc3RyaW5nLFxuICAgIGFjY2VudENvbG9yPzogc3RyaW5nXG59XG5cbmNvbnN0IEdpcGh5ID0gKHtcbiAgICBhcGlLZXksXG5cbiAgICBjYWxsYmFjayA9IGl0ZW0gPT4gY29uc29sZS5sb2coJ3JlYWN0LWF3ZXNvbWUtZ2lwaHk6JywgaXRlbSksXG4gICAgZGlzcGxheSA9ICdnaWZzJyxcblxuICAgIGxpbWl0ID0gMTIsXG5cbiAgICBoZWlnaHQgPSA0MjUsXG4gICAgd2lkdGggPSA0MjUsXG4gICAgY29sdW1ucyA9IDIsXG5cbiAgICB0ZXh0Q29sb3IgPSB0aGVtZS50ZXh0Q29sb3IsXG4gICAgdGV4dEFsdENvbG9yID0gdGhlbWUudGV4dEFsdENvbG9yLFxuICAgIGJnQ29sb3IgPSB0aGVtZS5iZ0NvbG9yLFxuICAgIGJnQWx0Q29sb3IgPSB0aGVtZS5iZ0FsdENvbG9yLFxuICAgIGJ1dHRvbkNvbG9yID0gdGhlbWUuYnV0dG9uQ29sb3IsXG4gICAgaW5wdXRDb2xvciA9IHRoZW1lLmlucHV0Q29sb3IsXG4gICAgYWNjZW50Q29sb3IgPSB0aGVtZS5hY2NlbnRDb2xvcixcblxuICAgIC4uLnByb3BzXG59OiBQcm9wcykgPT4ge1xuXG4gICAgY29uc3QgWyBsb2FkaW5nLCBzZXRMb2FkaW5nIF0gPSB1c2VTdGF0ZShmYWxzZSlcbiAgICBjb25zdCBbIGRhdGEsIHNldERhdGEgXSA9IHVzZVN0YXRlKFtdKVxuICAgIGNvbnN0IFsgY3VycmVudERpc3BsYXksIHNldEN1cnJlbnREaXNwbGF5IF0gPSB1c2VTdGF0ZTwnZ2lmcycgfCAnc3RpY2tlcnMnPihkaXNwbGF5KVxuXG4gICAgY29uc3Qgc2VhcmNoID0gdXNlUmVmPHN0cmluZz4oXCJcIilcbiAgICBjb25zdCBpc1R5cGluZyA9IHVzZVJlZjxib29sZWFuPihmYWxzZSlcbiAgICBjb25zdCB0aW1lb3V0ID0gdXNlUmVmPGFueT4oKVxuXG4gICAgY29uc3QgaGFuZGxlU2VhcmNoID0gKGlucHV0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgc2VhcmNoLmN1cnJlbnQgPSBpbnB1dFxuICAgICAgICBcbiAgICAgICAgY29uc3QgcnVuU2VhcmNoID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBnZXREYXRhKGN1cnJlbnREaXNwbGF5LCAnc2VhcmNoJywgaW5wdXQpXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IGdldERhdGEoY3VycmVudERpc3BsYXksICd0cmVuZGluZycpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpc1R5cGluZy5jdXJyZW50ID0gZmFsc2VcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc1R5cGluZy5jdXJyZW50KSB7IFxuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQuY3VycmVudClcbiAgICAgICAgICAgIHRpbWVvdXQuY3VycmVudCA9IHNldFRpbWVvdXQocnVuU2VhcmNoLCA1MDApXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzZXRMb2FkaW5nKHRydWUpXG4gICAgICAgICAgICBpc1R5cGluZy5jdXJyZW50ID0gdHJ1ZSBcbiAgICAgICAgICAgIHRpbWVvdXQuY3VycmVudCA9IHNldFRpbWVvdXQocnVuU2VhcmNoLCA1MDApXG4gICAgICAgIH0gXG4gICAgfVxuXG4gICAgY29uc3QgZ2V0RGF0YSA9IGFzeW5jIChcbiAgICAgICAgdHlwZTogJ2dpZnMnIHwgJ3N0aWNrZXJzJyxcbiAgICAgICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICAgICAgcXVlcnk/OiBzdHJpbmdcbiAgICApID0+IHtcbiAgICAgICAgY29uc3QgeyBcbiAgICAgICAgICAgIG9mZnNldCwgcmF0aW5nLCByYW5kb21JZCwgYnVuZGxlIFxuICAgICAgICB9ID0gcHJvcHNcblxuICAgICAgICBzZXRMb2FkaW5nKHRydWUpXG4gICAgICAgIGF3YWl0IGZldGNoKFxuICAgICAgICAgICAgYGh0dHBzOi8vYXBpLmdpcGh5LmNvbS92MS8ke3R5cGV9LyR7ZW5kcG9pbnR9P2AgK1xuICAgICAgICAgICAgYGFwaV9rZXk9JHthcGlLZXl9YCArXG4gICAgICAgICAgICBgJmxpbWl0PSR7bGltaXR9YCArXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgcXVlcnkgJiYgYCZxPSR7cXVlcnl9YCxcbiAgICAgICAgICAgICAgICBvZmZzZXQgJiYgYCZvZmZzZXQ9JHtvZmZzZXR9YCxcbiAgICAgICAgICAgICAgICByYXRpbmcgJiYgYCZyYXRpbmc9JHtyYXRpbmd9YCxcbiAgICAgICAgICAgICAgICByYW5kb21JZCAmJiBgJnJhbmRvbV9pZD0ke3JhbmRvbUlkfWAsXG4gICAgICAgICAgICAgICAgYnVuZGxlICYmIGAmYnVuZGxlPSR7YnVuZGxlfWBcbiAgICAgICAgICAgIF0uam9pbignJylcbiAgICAgICAgICAgICwge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihyZXMgPT4gcmVzLmpzb24oKSlcbiAgICAgICAgICAgIC50aGVuKGRhdGEgPT4gc2V0RGF0YShkYXRhLmRhdGEpKVxuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKVxuICAgIH1cblxuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChwcm9wcy5kaXNwbGF5Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIHByb3BzLmRpc3BsYXlDYWxsYmFjayhjdXJyZW50RGlzcGxheSlcbiAgICAgICAgfSBcbiAgICB9LCBbY3VycmVudERpc3BsYXldKVxuXG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgc2V0Q3VycmVudERpc3BsYXkoZGlzcGxheSlcbiAgICB9LCBbZGlzcGxheV0pXG5cbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoIWxvYWRpbmcpIHtcbiAgICAgICAgICAgIHNldExvYWRpbmcodHJ1ZSlcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2VhcmNoLmN1cnJlbnQubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gZ2V0RGF0YShjdXJyZW50RGlzcGxheSwgJ3RyZW5kaW5nJyksIDUwMClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gZ2V0RGF0YShjdXJyZW50RGlzcGxheSwgJ3NlYXJjaCcsIHNlYXJjaC5jdXJyZW50KSwgNTAwKVxuICAgICAgICB9XG4gICAgfSwgW2N1cnJlbnREaXNwbGF5XSlcblxuICAgIHJldHVybiAoXG4gICAgICAgIDxTdG9yZVByb3ZpZGVyIHZhbHVlPXt7XG4gICAgICAgICAgICBhcGlLZXksXG4gICAgICAgICAgICBjYWxsYmFjayxcblxuICAgICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICBjb2x1bW5zLFxuICAgICAgICBcbiAgICAgICAgICAgIHRleHRDb2xvcixcbiAgICAgICAgICAgIHRleHRBbHRDb2xvcixcbiAgICAgICAgICAgIGJnQ29sb3IsXG4gICAgICAgICAgICBiZ0FsdENvbG9yLFxuICAgICAgICAgICAgYnV0dG9uQ29sb3IsXG4gICAgICAgICAgICBpbnB1dENvbG9yLFxuICAgICAgICAgICAgYWNjZW50Q29sb3IsXG4gICAgICAgICAgICAuLi5wcm9wc1xuICAgICAgICB9fT5cbiAgICAgICAgPFdyYXBwZXI+XG5cbiAgICAgICAgICAgIDxDb2w+XG5cbiAgICAgICAgICAgICAgICA8Um93IGNlbnRlcng+XG4gICAgICAgICAgICAgICAgICAgIDxCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZT17Y3VycmVudERpc3BsYXkgPT0gJ2dpZnMnfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEN1cnJlbnREaXNwbGF5KCdnaWZzJylcbiAgICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIEdJRnNcbiAgICAgICAgICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZT17Y3VycmVudERpc3BsYXkgPT0gJ3N0aWNrZXJzJ31cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRDdXJyZW50RGlzcGxheSgnc3RpY2tlcnMnKVxuICAgICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgU3RpY2tlcnNcbiAgICAgICAgICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICAgICAgPC9Sb3c+IFxuXG4gICAgICAgICAgICAgICAgPElucHV0XG4gICAgICAgICAgICAgICAgICAgIHR5cGU9J3RleHQnXG4gICAgICAgICAgICAgICAgICAgIHNwZWxsQ2hlY2s9e2ZhbHNlfVxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj17J1NlY