UNPKG

react-awesome-giphy

Version:
336 lines (313 loc) 72 kB
(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