UNPKG

react-static

Version:

A progressive static site generator for React

349 lines (276 loc) 37.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getEmbeddedRouteInfoScript = getEmbeddedRouteInfoScript; exports["default"] = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _crypto = _interopRequireDefault(require("crypto")); var _react = _interopRequireDefault(require("react")); var _server = require("react-dom/server"); var _reactHelmet = _interopRequireDefault(require("react-helmet")); var _reactUniversalComponent = require("react-universal-component"); var _webpackFlushChunks = _interopRequireDefault(require("webpack-flush-chunks")); var _path = _interopRequireDefault(require("path")); var _fsExtra = _interopRequireDefault(require("fs-extra")); var _jsesc = _interopRequireDefault(require("jsesc")); var _Redirect = _interopRequireDefault(require("./components/Redirect")); var _plugins = _interopRequireDefault(require("./plugins")); var _utils = require("../utils"); var _chunkBuilder = require("../utils/chunkBuilder"); var _HtmlWithMeta = _interopRequireDefault(require("./components/HtmlWithMeta")); var _HeadWithMeta = _interopRequireDefault(require("./components/HeadWithMeta")); var _BodyWithMeta = _interopRequireDefault(require("./components/BodyWithMeta")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var cachedBasePath; var cachedHrefReplace; var cachedSrcReplace; function getSHA256(str) { var hash = _crypto["default"].createHash('sha256'); hash.update(str); return hash.digest('base64'); } function getSubresourceHash(str) { var sha256 = getSHA256(str); return "sha256-".concat(sha256); } function getEmbeddedRouteInfoScript(embeddedRouteInfo) { var routeInfoJSON = (0, _jsesc["default"])(JSON.stringify(embeddedRouteInfo), { isScriptContext: true, wrap: true, json: true }); var script = "window.__routeInfo = JSON.parse(".concat(routeInfoJSON, ");"); var hash = getSubresourceHash(script); return { hash: hash, script: script }; } var _default = /*#__PURE__*/function () { var _exportRoute = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(state) { var _state, config, DocumentTemplate, route, siteData, clientStats, incremental, _state2, Comp, sharedHashesByProp, template, data, sharedData, routePath, remove, removeLocation, basePath, hrefReplace, srcReplace, routeInfo, embeddedRouteInfo, inlineScripts, meta, chunkNames, head, clientScripts, clientStyleSheets, clientCss, FinalComp, renderToStringAndExtract, appHtml, RenderedComp, DocumentHtml, html, publicPath, htmlFilename, routeInfoFilename, res; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _state = state, config = _state.config, DocumentTemplate = _state.DocumentTemplate, route = _state.route, siteData = _state.siteData, clientStats = _state.clientStats, incremental = _state.incremental; _state2 = state, Comp = _state2.Comp; sharedHashesByProp = route.sharedHashesByProp, template = route.template, data = route.data, sharedData = route.sharedData, routePath = route.path, remove = route.remove; if (!(incremental && remove)) { _context.next = 8; break; } if (!((0, _utils.is404Path)(route.path) || route.path === '/')) { _context.next = 6; break; } throw new Error("You are attempting to incrementally remove the ".concat((0, _utils.is404Path)(route.path) ? '404' : 'index', " route from your export. This is currently not supported (or recommended) by React Static.")); case 6: removeLocation = _path["default"].join(config.paths.DIST, route.path); return _context.abrupt("return", _fsExtra["default"].remove(removeLocation)); case 8: basePath = cachedBasePath || (cachedBasePath = config.basePath); hrefReplace = cachedHrefReplace || (cachedHrefReplace = new RegExp("(href=[\"'])\\/(".concat(basePath ? "".concat(basePath, "\\/") : '', ")?([^\\/])"), 'gm')); srcReplace = cachedSrcReplace || (cachedSrcReplace = new RegExp("(src=[\"'])\\/(".concat(basePath ? "".concat(basePath, "\\/") : '', ")?([^\\/])"), 'gm')); // This routeInfo will be saved to disk. It should only include the // data and hashes to construct all of the props later. _context.next = 13; return _plugins["default"].routeInfo({ template: template, sharedHashesByProp: sharedHashesByProp, data: data, path: routePath }, state); case 13: routeInfo = _context.sent; // This embeddedRouteInfo will be inlined into the HTML for this route. // It should include all of the data, including shared data embeddedRouteInfo = _objectSpread(_objectSpread({}, routeInfo), {}, { sharedData: sharedData, siteData: siteData }); inlineScripts = { routeInfo: getEmbeddedRouteInfoScript(embeddedRouteInfo) }; state = _objectSpread(_objectSpread({}, state), {}, { routeInfo: routeInfo, embeddedRouteInfo: embeddedRouteInfo, inlineScripts: inlineScripts }); // Make a place to collect chunks, meta info and head tags meta = {}; chunkNames = []; head = {}; clientScripts = []; clientStyleSheets = []; clientCss = {}; // Get the react component from the Comp and pass it the export context. This // uses reactContext under the hood to pass down the exportContext, since // react's new context api doesn't survive across bundling. Comp = config.disableRuntime ? Comp : Comp(embeddedRouteInfo); if (route.redirect) { FinalComp = function FinalComp() { return /*#__PURE__*/_react["default"].createElement(_Redirect["default"], { fromPath: route.path, to: route.redirect }); }; } else { FinalComp = function FinalComp(props) { return /*#__PURE__*/_react["default"].createElement(_reactUniversalComponent.ReportChunks, { report: function report(chunkName) { // if we are building to a absolute path we must make the detected // chunkName relative and matching to the one we set in // generateTemplates if (!config.paths.DIST.startsWith(config.paths.ROOT)) { chunkName = (0, _chunkBuilder.absoluteToRelativeChunkName)(config.paths.ROOT, chunkName); } chunkNames.push(chunkName); } }, /*#__PURE__*/_react["default"].createElement(Comp, props)); }; } renderToStringAndExtract = function renderToStringAndExtract(comp) { // Rend the app to string! var appHtml = (0, _server.renderToString)(comp); var _flushChunks = (0, _webpackFlushChunks["default"])(clientStats, { chunkNames: chunkNames, outputPath: config.paths.DIST }), scripts = _flushChunks.scripts, stylesheets = _flushChunks.stylesheets, css = _flushChunks.css; clientScripts = scripts; clientStyleSheets = stylesheets; clientCss = css; // Extract head calls using Helmet synchronously right after renderToString // to not introduce any race conditions in the meta data rendering var helmet = _reactHelmet["default"].renderStatic(); head = { htmlProps: helmet.htmlAttributes.toComponent(), bodyProps: helmet.bodyAttributes.toComponent(), base: helmet.base.toComponent(), link: helmet.link.toComponent(), meta: helmet.meta.toComponent(), noscript: helmet.noscript.toComponent(), script: helmet.script.toComponent(), style: helmet.style.toComponent(), title: helmet.title.toComponent() }; return appHtml; }; state = _objectSpread(_objectSpread({}, state), {}, { meta: meta }); _context.prev = 27; _context.next = 30; return _plugins["default"].beforeRenderToElement(FinalComp, state); case 30: FinalComp = _context.sent; if (!config.renderToElement) { _context.next = 33; break; } throw new Error("config.renderToElement has been deprecated in favor of the " + "'beforeRenderToElement' or 'beforeRenderToHtml' hooks instead."); case 33: RenderedComp = /*#__PURE__*/_react["default"].createElement(FinalComp, null); // Run the beforeRenderToHtml hook // Rum the Html hook _context.next = 36; return _plugins["default"].beforeRenderToHtml(RenderedComp, state); case 36: RenderedComp = _context.sent; if (!config.renderToHtml) { _context.next = 39; break; } throw new Error("config.renderToHtml has been deprecated in favor of the " + "'beforeRenderToHtml' or 'beforeHtmlToDocument' hooks instead."); case 39: appHtml = renderToStringAndExtract(RenderedComp); _context.next = 42; return _plugins["default"].beforeHtmlToDocument(appHtml, state); case 42: appHtml = _context.sent; _context.next = 50; break; case 45: _context.prev = 45; _context.t0 = _context["catch"](27); if (_context.t0.then) { _context.t0.message = 'Components are not allowed to suspend during static export. Please ' + 'make its data available synchronously and try again!'; } _context.t0.message = "Failed exporting HTML for URL ".concat(route.path, " (").concat(route.template, "): ").concat(_context.t0.message); throw _context.t0; case 50: state = _objectSpread(_objectSpread({}, state), {}, { head: head, clientScripts: clientScripts, clientStyleSheets: clientStyleSheets, clientCss: clientCss }); _context.t1 = _server.renderToStaticMarkup; _context.t2 = _react["default"]; _context.t3 = DocumentTemplate; _context.next = 56; return (0, _HtmlWithMeta["default"])(state); case 56: _context.t4 = _context.sent; _context.next = 59; return (0, _HeadWithMeta["default"])(state); case 59: _context.t5 = _context.sent; _context.next = 62; return (0, _BodyWithMeta["default"])(state); case 62: _context.t6 = _context.sent; _context.t7 = state; _context.t8 = { Html: _context.t4, Head: _context.t5, Body: _context.t6, state: _context.t7 }; _context.t9 = /*#__PURE__*/_react["default"].createElement("div", { id: "root", dangerouslySetInnerHTML: { __html: appHtml } }); _context.t10 = _context.t2.createElement.call(_context.t2, _context.t3, _context.t8, _context.t9); DocumentHtml = (0, _context.t1)(_context.t10); // Render the html for the page inside of the base document. html = "<!DOCTYPE html>".concat(DocumentHtml); _context.next = 71; return _plugins["default"].beforeDocumentToFile(html, state); case 71: html = _context.sent; // If the siteRoot is set and we're not in staging, prefix all absolute URLs // with the siteRoot publicPath = (0, _utils.makePathAbsolute)(process.env.REACT_STATIC_PUBLIC_PATH); if (process.env.REACT_STATIC_DISABLE_ROUTE_PREFIXING !== 'true') { html = html.replace(hrefReplace, "$1".concat(publicPath, "$3")); } html = html.replace(srcReplace, "$1".concat(publicPath, "$3")); // If the route is a 404 page, write it directly to 404.html, instead of // inside a directory. htmlFilename = (0, _utils.is404Path)(route.path) ? _path["default"].join(config.paths.DIST, '404.html') : _path["default"].join(config.paths.DIST, route.path, 'index.html'); // Make the routeInfo sit right next to its companion html file routeInfoFilename = _path["default"].join(config.paths.DIST, route.path, 'routeInfo.json'); _context.next = 79; return Promise.all([_fsExtra["default"].outputFile(htmlFilename, html), !route.redirect ? _fsExtra["default"].outputJson(routeInfoFilename, routeInfo) : Promise.resolve()]); case 79: res = _context.sent; return _context.abrupt("return", res); case 81: case "end": return _context.stop(); } } }, _callee, null, [[27, 45]]); })); function exportRoute(_x) { return _exportRoute.apply(this, arguments); } return exportRoute; }(); exports["default"] = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdGF0aWMvZXhwb3J0Um91dGUuanMiXSwibmFtZXMiOlsiY2FjaGVkQmFzZVBhdGgiLCJjYWNoZWRIcmVmUmVwbGFjZSIsImNhY2hlZFNyY1JlcGxhY2UiLCJnZXRTSEEyNTYiLCJzdHIiLCJoYXNoIiwiY3J5cHRvIiwiY3JlYXRlSGFzaCIsInVwZGF0ZSIsImRpZ2VzdCIsImdldFN1YnJlc291cmNlSGFzaCIsInNoYTI1NiIsImdldEVtYmVkZGVkUm91dGVJbmZvU2NyaXB0IiwiZW1iZWRkZWRSb3V0ZUluZm8iLCJyb3V0ZUluZm9KU09OIiwiSlNPTiIsInN0cmluZ2lmeSIsImlzU2NyaXB0Q29udGV4dCIsIndyYXAiLCJqc29uIiwic2NyaXB0Iiwic3RhdGUiLCJjb25maWciLCJEb2N1bWVudFRlbXBsYXRlIiwicm91dGUiLCJzaXRlRGF0YSIsImNsaWVudFN0YXRzIiwiaW5jcmVtZW50YWwiLCJDb21wIiwic2hhcmVkSGFzaGVzQnlQcm9wIiwidGVtcGxhdGUiLCJkYXRhIiwic2hhcmVkRGF0YSIsInJvdXRlUGF0aCIsInBhdGgiLCJyZW1vdmUiLCJFcnJvciIsInJlbW92ZUxvY2F0aW9uIiwibm9kZVBhdGgiLCJqb2luIiwicGF0aHMiLCJESVNUIiwiZnMiLCJiYXNlUGF0aCIsImhyZWZSZXBsYWNlIiwiUmVnRXhwIiwic3JjUmVwbGFjZSIsInBsdWdpbnMiLCJyb3V0ZUluZm8iLCJpbmxpbmVTY3JpcHRzIiwibWV0YSIsImNodW5rTmFtZXMiLCJoZWFkIiwiY2xpZW50U2NyaXB0cyIsImNsaWVudFN0eWxlU2hlZXRzIiwiY2xpZW50Q3NzIiwiZGlzYWJsZVJ1bnRpbWUiLCJyZWRpcmVjdCIsIkZpbmFsQ29tcCIsInByb3BzIiwiY2h1bmtOYW1lIiwic3RhcnRzV2l0aCIsIlJPT1QiLCJwdXNoIiwicmVuZGVyVG9TdHJpbmdBbmRFeHRyYWN0IiwiY29tcCIsImFwcEh0bWwiLCJvdXRwdXRQYXRoIiwic2NyaXB0cyIsInN0eWxlc2hlZXRzIiwiY3NzIiwiaGVsbWV0IiwiSGVsbWV0IiwicmVuZGVyU3RhdGljIiwiaHRtbFByb3BzIiwiaHRtbEF0dHJpYnV0ZXMiLCJ0b0NvbXBvbmVudCIsImJvZHlQcm9wcyIsImJvZHlBdHRyaWJ1dGVzIiwiYmFzZSIsImxpbmsiLCJub3NjcmlwdCIsInN0eWxlIiwidGl0bGUiLCJiZWZvcmVSZW5kZXJUb0VsZW1lbnQiLCJyZW5kZXJUb0VsZW1lbnQiLCJSZW5kZXJlZENvbXAiLCJiZWZvcmVSZW5kZXJUb0h0bWwiLCJyZW5kZXJUb0h0bWwiLCJiZWZvcmVIdG1sVG9Eb2N1bWVudCIsInRoZW4iLCJtZXNzYWdlIiwicmVuZGVyVG9TdGF0aWNNYXJrdXAiLCJfX2h0bWwiLCJEb2N1bWVudEh0bWwiLCJodG1sIiwiYmVmb3JlRG9jdW1lbnRUb0ZpbGUiLCJwdWJsaWNQYXRoIiwicHJvY2VzcyIsImVudiIsIlJFQUNUX1NUQVRJQ19QVUJMSUNfUEFUSCIsIlJFQUNUX1NUQVRJQ19ESVNBQkxFX1JPVVRFX1BSRUZJWElORyIsInJlcGxhY2UiLCJodG1sRmlsZW5hbWUiLCJyb3V0ZUluZm9GaWxlbmFtZSIsIlByb21pc2UiLCJhbGwiLCJvdXRwdXRGaWxlIiwib3V0cHV0SnNvbiIsInJlc29sdmUiLCJyZXMiLCJleHBvcnRSb3V0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOzs7Ozs7QUFFQSxJQUFJQSxjQUFKO0FBQ0EsSUFBSUMsaUJBQUo7QUFDQSxJQUFJQyxnQkFBSjs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxHQUFuQixFQUF3QjtBQUN0QixNQUFNQyxJQUFJLEdBQUdDLG1CQUFPQyxVQUFQLENBQWtCLFFBQWxCLENBQWI7O0FBQ0FGLEVBQUFBLElBQUksQ0FBQ0csTUFBTCxDQUFZSixHQUFaO0FBQ0EsU0FBT0MsSUFB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YUMsSUFEVyxFQUV4QmpCLEtBQUssQ0FBQ1UsSUFGa0IsRUFHeEIsZ0JBSHdCLENBdk9aO0FBQUE7QUFBQSxtQkE2T0l1RSxPQUFPLENBQUNDLEdBQVIsQ0FBWSxDQUM1QmhFLG9CQUFHaUUsVUFBSCxDQUFjSixZQUFkLEVBQTRCUixJQUE1QixDQUQ0QixFQUU1QixDQUFDdkUsS0FBSyxDQUFDaUMsUUFBUCxHQUNJZixvQkFBR2tFLFVBQUgsQ0FBY0osaUJBQWQsRUFBaUN4RCxTQUFqQyxDQURKLEdBRUl5RCxPQUFPLENBQUNJLE9BQVIsRUFKd0IsQ0FBWixDQTdPSjs7QUFBQTtBQTZPUkMsWUFBQUEsR0E3T1E7QUFBQSw2Q0FtUFBBLEdBblBPOztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEc7O1dBQWVDLFc7Ozs7U0FBQUEsVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgcmVuZGVyVG9TdHJpbmcsIHJlbmRlclRvU3RhdGljTWFya3VwIH0gZnJvbSAncmVhY3QtZG9tL3NlcnZlcidcbmltcG9ydCBIZWxtZXQgZnJvbSAncmVhY3QtaGVsbWV0J1xuaW1wb3J0IHsgUmVwb3J0Q2h1bmtzIH0gZnJvbSAncmVhY3QtdW5pdmVyc2FsLWNvbXBvbmVudCdcbmltcG9ydCBmbHVzaENodW5rcyBmcm9tICd3ZWJwYWNrLWZsdXNoLWNodW5rcydcbmltcG9ydCBub2RlUGF0aCBmcm9tICdwYXRoJ1xuaW1wb3J0IGZzIGZyb20gJ2ZzLWV4dHJhJ1xuaW1wb3J0IGpzZXNjIGZyb20gJ2pzZXNjJ1xuXG5pbXBvcnQgUmVkaXJlY3QgZnJvbSAnLi9jb21wb25lbnRzL1JlZGlyZWN0J1xuaW1wb3J0IHBsdWdpbnMgZnJvbSAnLi9wbHVnaW5zJ1xuaW1wb3J0IHsgbWFrZVBhdGhBYnNvbHV0ZSwgaXM0MDRQYXRoIH0gZnJvbSAnLi4vdXRpbHMnXG5pbXBvcnQgeyBhYnNvbHV0ZVRvUmVsYXRpdmVDaHVua05hbWUgfSBmcm9tICcuLi91dGlscy9jaHVua0J1aWxkZXInXG5cbmltcG9ydCBtYWtlSHRtbFdpdGhNZXRhIGZyb20gJy4vY29tcG9uZW50cy9IdG1sV2l0aE1ldGEnXG5pbXBvcnQgbWFrZUhlYWRXaXRoTWV0YSBmcm9tICcuL2NvbXBvbmVudHMvSGVhZFdpdGhNZXRhJ1xuaW1wb3J0IG1ha2VCb2R5V2l0aE1ldGEgZnJvbSAnLi9jb21wb25lbnRzL0JvZHlXaXRoTWV0YSdcblxubGV0IGNhY2hlZEJhc2VQYXRoXG5sZXQgY2FjaGVkSHJlZlJlcGxhY2VcbmxldCBjYWNoZWRTcmNSZXBsYWNlXG5cbmZ1bmN0aW9uIGdldFNIQTI1NihzdHIpIHtcbiAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKVxuICBoYXNoLnVwZGF0ZShzdHIpXG4gIHJldHVybiBoYXNoLmRpZ2VzdCgnYmFzZTY0Jylcbn1cblxuZnVuY3Rpb24gZ2V0U3VicmVzb3VyY2VIYXNoKHN0cikge1xuICBjb25zdCBzaGEyNTYgPSBnZXRTSEEyNTYoc3RyKVxuICByZXR1cm4gYHNoYTI1Ni0ke3NoYTI1Nn1gXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbWJlZGRlZFJvdXRlSW5mb1NjcmlwdChlbWJlZGRlZFJvdXRlSW5mbykge1xuICBjb25zdCByb3V0ZUluZm9KU09OID0ganNlc2MoSlNPTi5zdHJpbmdpZnkoZW1iZWRkZWRSb3V0ZUluZm8pLCB7XG4gICAgaXNTY3JpcHRDb250ZXh0OiB0cnVlLFxuICAgIHdyYXA6IHRydWUsXG4gICAganNvbjogdHJ1ZSxcbiAgfSlcbiAgY29uc3Qgc2NyaXB0ID0gYHdpbmRvdy5fX3JvdXRlSW5mbyA9IEpTT04ucGFyc2UoJHtyb3V0ZUluZm9KU09OfSk7YFxuICBjb25zdCBoYXNoID0gZ2V0U3VicmVzb3VyY2VIYXNoKHNjcmlwdClcblxuICByZXR1cm4ge1xuICAgIGhhc2gsXG4gICAgc2NyaXB0LFxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IChhc3luYyBmdW5jdGlvbiBleHBvcnRSb3V0ZShzdGF0ZSkge1xuICBjb25zdCB7XG4gICAgY29uZmlnLFxuICAgIERvY3VtZW50VGVtcGxhdGUsXG4gICAgcm91dGUsXG4gICAgc2l0ZURhdGEsXG4gICAgY2xpZW50U3RhdHMsXG4gICAgaW5jcmVtZW50YWwsXG4gIH0gPSBzdGF0ZVxuXG4gIGxldCB7IENvbXAgfSA9IHN0YXRlXG5cbiAgY29uc3Qge1xuICAgIHNoYXJlZEhhc2hlc0J5UHJvcCxcbiAgICB0ZW1wbGF0ZSxcbiAgICBkYXRhLFxuICAgIHNoYXJlZERhdGEsXG4gICAgcGF0aDogcm91dGVQYXRoLFxuICAgIHJlbW92ZSxcbiAgfSA9IHJvdXRlXG5cbiAgaWYgKGluY3JlbWVudGFsICYmIHJlbW92ZSkge1xuICAgIGlmIChpczQwNFBhdGgocm91dGUucGF0aCkgfHwgcm91dGUucGF0aCA9PT0gJy8nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBZb3UgYXJlIGF0dGVtcHRpbmcgdG8gaW5jcmVtZW50YWxseSByZW1vdmUgdGhlICR7XG4gICAgICAgICAgaXM0MDRQYXRoKHJvdXRlLnBhdGgpID8gJzQwNCcgOiAnaW5kZXgnXG4gICAgICAgIH0gcm91dGUgZnJvbSB5b3VyIGV4cG9ydC4gVGhpcyBpcyBjdXJyZW50bHkgbm90IHN1cHBvcnRlZCAob3IgcmVjb21tZW5kZWQpIGJ5IFJlYWN0IFN0YXRpYy5gXG4gICAgICApXG4gICAgfVxuICAgIGNvbnN0IHJlbW92ZUxvY2F0aW9uID0gbm9kZVBhdGguam9pbihjb25maWcucGF0aHMuRElTVCwgcm91dGUucGF0aClcbiAgICByZXR1cm4gZnMucmVtb3ZlKHJlbW92ZUxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgYmFzZVBhdGggPSBjYWNoZWRCYXNlUGF0aCB8fCAoY2FjaGVkQmFzZVBhdGggPSBjb25maWcuYmFzZVBhdGgpXG5cbiAgY29uc3QgaHJlZlJlcGxhY2UgPVxuICAgIGNhY2hlZEhyZWZSZXBsYWNlIHx8XG4gICAgKGNhY2hlZEhyZWZSZXBsYWNlID0gbmV3IFJlZ0V4cChcbiAgICAgIGAoaHJlZj1bXCInXSlcXFxcLygke2Jhc2VQYXRoID8gYCR7YmFzZVBhdGh9XFxcXC9gIDogJyd9KT8oW15cXFxcL10pYCxcbiAgICAgICdnbSdcbiAgICApKVxuXG4gIGNvbnN0IHNyY1JlcGxhY2UgPVxuICAgIGNhY2hlZFNyY1JlcGxhY2UgfHxcbiAgICAoY2FjaGVkU3JjUmVwbGFjZSA9IG5ldyBSZWdFeHAoXG4gICAgICBgKHNyYz1bXCInXSlcXFxcLygke2Jhc2VQYXRoID8gYCR7YmFzZVBhdGh9XFxcXC9gIDogJyd9KT8oW15cXFxcL10pYCxcbiAgICAgICdnbSdcbiAgICApKVxuXG4gIC8vIFRoaXMgcm91dGVJbmZvIHdpbGwgYmUgc2F2ZWQgdG8gZGlzay4gSXQgc2hvdWxkIG9ubHkgaW5jbHVkZSB0aGVcbiAgLy8gZGF0YSBhbmQgaGFzaGVzIHRvIGNvbnN0cnVjdCBhbGwgb2YgdGhlIHByb3BzIGxhdGVyLlxuICBjb25zdCByb3V0ZUluZm8gPSBhd2FpdCBwbHVnaW5zLnJvdXRlSW5mbyhcbiAgICB7XG4gICAgICB0ZW1wbGF0ZSxcbiAgICAgIHNoYXJlZEhhc2hlc0J5UHJvcCxcbiAgICAgIGRhdGEsXG4gICAgICBwYXRoOiByb3V0ZVBhdGgsXG4gICAgfSxcbiAgICBzdGF0ZVxuICApXG5cbiAgLy8gVGhpcyBlbWJlZGRlZFJvdXRlSW5mbyB3aWxsIGJlIGlubGluZWQgaW50byB0aGUgSFRNTCBmb3IgdGhpcyByb3V0ZS5cbiAgLy8gSXQgc2hvdWxkIGluY2x1ZGUgYWxsIG9mIHRoZSBkYXRhLCBpbmNsdWRpbmcgc2hhcmVkIGRhdGFcbiAgY29uc3QgZW1iZWRkZWRSb3V0ZUluZm8gPSB7XG4gICAgLi4ucm91dGVJbmZvLFxuICAgIHNoYXJlZERhdGEsXG4gICAgc2l0ZURhdGEsXG4gIH1cblxuICBjb25zdCBpbmxpbmVTY3JpcHRzID0ge1xuICAgIHJvdXRlSW5mbzogZ2V0RW1iZWRkZWRSb3V0ZUluZm9TY3JpcHQoZW1iZWRkZWRSb3V0ZUluZm8pLFxuICB9XG5cbiAgc3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgcm91dGVJbmZvLFxuICAgIGVtYmVkZGVkUm91dGVJbmZvLFxuICAgIGlubGluZVNjcmlwdHMsXG4gIH1cblxuICAvLyBNYWtlIGEgcGxhY2UgdG8gY29sbGVjdCBjaHVua3MsIG1ldGEgaW5mbyBhbmQgaGVhZCB0YWdzXG4gIGNvbnN0IG1ldGEgPSB7fVxuICBjb25zdCBjaHVua05hbWVzID0gW11cbiAgbGV0IGhlYWQgPSB7fVxuICBsZXQgY2xpZW50U2NyaXB0cyA9IFtdXG4gIGxldCBjbGllbnRTdHlsZVNoZWV0cyA9IFtdXG4gIGxldCBjbGllbnRDc3MgPSB7fVxuXG4gIGxldCBGaW5hbENvbXBcblxuICAvLyBHZXQgdGhlIHJlYWN0IGNvbXBvbmVudCBmcm9tIHRoZSBDb21wIGFuZCBwYXNzIGl0IHRoZSBleHBvcnQgY29udGV4dC4gVGhpc1xuICAvLyB1c2VzIHJlYWN0Q29udGV4dCB1bmRlciB0aGUgaG9vZCB0byBwYXNzIGRvd24gdGhlIGV4cG9ydENvbnRleHQsIHNpbmNlXG4gIC8vIHJlYWN0J3MgbmV3IGNvbnRleHQgYXBpIGRvZXNuJ3Qgc3Vydml2ZSBhY3Jvc3MgYnVuZGxpbmcuXG4gIENvbXAgPSBjb25maWcuZGlzYWJsZVJ1bnRpbWUgPyBDb21wIDogQ29tcChlbWJlZGRlZFJvdXRlSW5mbylcblxuICBpZiAocm91dGUucmVkaXJlY3QpIHtcbiAgICBGaW5hbENvbXAgPSAoKSA9PiA8UmVkaXJlY3QgZnJvbVBhdGg9e3JvdXRlLnBhdGh9IHRvPXtyb3V0ZS5yZWRpcmVjdH0gLz5cbiAgfSBlbHNlIHtcbiAgICBGaW5hbENvbXAgPSBwcm9wcyA9PiAoXG4gICAgICA8UmVwb3J0Q2h1bmtzXG4gICAgICAgIHJlcG9ydD17Y2h1bmtOYW1lID0+IHtcbiAgICAgICAgICAvLyBpZiB3ZSBhcmUgYnVpbGRpbmcgdG8gYSBhYnNvbHV0ZSBwYXRoIHdlIG11c3QgbWFrZSB0aGUgZGV0ZWN0ZWRcbiAgICAgICAgICAvLyBjaHVua05hbWUgcmVsYXRpdmUgYW5kIG1hdGNoaW5nIHRvIHRoZSBvbmUgd2Ugc2V0IGluXG4gICAgICAgICAgLy8gZ2VuZXJhdGVUZW1wbGF0ZXNcbiAgICAgICAgICBpZiAoIWNvbmZpZy5wYXRocy5ESVNULnN0YXJ0c1dpdGgoY29uZmlnLnBhdGhzLlJPT1QpKSB7XG4gICAgICAgICAgICBjaHVua05hbWUgPSBhYnNvbHV0ZVRvUmVsYXRpdmVDaHVua05hbWUoXG4gICAgICAgICAgICAgIGNvbmZpZy5wYXRocy5ST09ULFxuICAgICAgICAgICAgICBjaHVua05hbWVcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjaHVua05hbWVzLnB1c2goY2h1bmtOYW1lKVxuICAgICAgICB9fVxuICAgICAgPlxuICAgICAgICA8Q29tcCB7Li4ucHJvcHN9IC8+XG4gICAgICA8L1JlcG9ydENodW5rcz5cbiAgICApXG4gIH1cblxuICBjb25zdCByZW5kZXJUb1N0cmluZ0FuZEV4dHJhY3QgPSBjb21wID0+IHtcbiAgICAvLyBSZW5kIHRoZSBhcHAgdG8gc3RyaW5nIVxuICAgIGNvbnN0IGFwcEh0bWwgPSByZW5kZXJUb1N0cmluZyhjb21wKVxuICAgIGNvbnN0IHsgc2NyaXB0cywgc3R5bGVzaGVldHMsIGNzcyB9ID0gZmx1c2hDaHVua3MoY2xpZW50U3RhdHMsIHtcbiAgICAgIGNodW5rTmFtZXMsXG4gICAgICBvdXRwdXRQYXRoOiBjb25maWcucGF0aHMuRElTVCxcbiAgICB9KVxuXG4gICAgY2xpZW50U2NyaXB0cyA9IHNjcmlwdHNcbiAgICBjbGllbnRTdHlsZVNoZWV0cyA9IHN0eWxlc2hlZXRzXG4gICAgY2xpZW50Q3NzID0gY3NzXG4gICAgLy8gRXh0cmFjdCBoZWFkIGNhbGxzIHVzaW5nIEhlbG1ldCBzeW5jaHJvbm91c2x5IHJpZ2h0IGFmdGVyIHJlbmRlclRvU3RyaW5nXG4gICAgLy8gdG8gbm90IGludHJvZHVjZSBhbnkgcmFjZSBjb25kaXRpb25zIGluIHRoZSBtZXRhIGRhdGEgcmVuZGVyaW5nXG4gICAgY29uc3QgaGVsbWV0ID0gSGVsbWV0LnJlbmRlclN0YXRpYygpXG4gICAgaGVhZCA9IHtcbiAgICAgIGh0bWxQcm9wczogaGVsbWV0Lmh0bWxBdHRyaWJ1dGVzLnRvQ29tcG9uZW50KCksXG4gICAgICBib2R5UHJvcHM6IGhlbG1ldC5ib2R5QXR0cmlidXRlcy50b0NvbXBvbmVudCgpLFxuICAgICAgYmFzZTogaGVsbWV0LmJhc2UudG9Db21wb25lbnQoKSxcbiAgICAgIGxpbms6IGhlbG1ldC5saW5rLnRvQ29tcG9uZW50KCksXG4gICAgICBtZXRhOiBoZWxtZXQubWV0YS50b0NvbXBvbmVudCgpLFxuICAgICAgbm9zY3JpcHQ6IGhlbG1ldC5ub3NjcmlwdC50b0NvbXBvbmVudCgpLFxuICAgICAgc2NyaXB0OiBoZWxtZXQuc2NyaXB0LnRvQ29tcG9uZW50KCksXG4gICAgICBzdHlsZTogaGVsbWV0LnN0eWxlLnRvQ29tcG9uZW50KCksXG4gICAgICB0aXRsZTogaGVsbWV0LnRpdGxlLnRvQ29tcG9uZW50KCksXG4gICAgfVxuXG4gICAgcmV0dXJuIGFwcEh0bWxcbiAgfVxuXG4gIGxldCBhcHBIdG1sXG5cbiAgc3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgbWV0YSxcbiAgfVxuXG4gIHRyeSB7XG4gICAgRmluYWxDb21wID0gYXdhaXQgcGx1Z2lucy5iZWZvcmVSZW5kZXJUb0VsZW1lbnQoRmluYWxDb21wLCBzdGF0ZSlcblxuICAgIGlmIChjb25maWcucmVuZGVyVG9FbGVtZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBjb25maWcucmVuZGVyVG9FbGVtZW50IGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgdGhlIGAgK1xuICAgICAgICAgIGAnYmVmb3JlUmVuZGVyVG9FbGVtZW50JyBvciAnYmVmb3JlUmVuZGVyVG9IdG1sJyBob29rcyBpbnN0ZWFkLmBcbiAgICAgIClcbiAgICB9XG5cbiAgICBsZXQgUmVuZGVyZWRDb21wID0gPEZpbmFsQ29tcCAvPlxuXG4gICAgLy8gUnVuIHRoZSBiZWZvcmVSZW5kZXJUb0h0bWwgaG9va1xuICAgIC8vIFJ1bSB0aGUgSHRtbCBob29rXG4gICAgUmVuZGVyZWRDb21wID0gYXdhaXQgcGx1Z2lucy5iZWZvcmVSZW5kZXJUb0h0bWwoUmVuZGVyZWRDb21wLCBzdGF0ZSlcblxuICAgIGlmIChjb25maWcucmVuZGVyVG9IdG1sKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBjb25maWcucmVuZGVyVG9IdG1sIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgdGhlIGAgK1xuICAgICAgICAgIGAnYmVmb3JlUmVuZGVyVG9IdG1sJyBvciAnYmVmb3JlSHRtbFRvRG9jdW1lbnQnIGhvb2tzIGluc3RlYWQuYFxuICAgICAgKVxuICAgIH1cblxuICAgIGFwcEh0bWwgPSByZW5kZXJUb1N0cmluZ0FuZEV4dHJhY3QoUmVuZGVyZWRDb21wKVxuXG4gICAgYXBwSHRtbCA9IGF3YWl0IHBsdWdpbnMuYmVmb3JlSHRtbFRvRG9jdW1lbnQoYXBwSHRtbCwgc3RhdGUpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yLnRoZW4pIHtcbiAgICAgIGVycm9yLm1lc3NhZ2UgPVxuICAgICAgICAnQ29tcG9uZW50cyBhcmUgbm90IGFsbG93ZWQgdG8gc3VzcGVuZCBkdXJpbmcgc3RhdGljIGV4cG9ydC4gUGxlYXNlICcgK1xuICAgICAgICAnbWFrZSBpdHMgZGF0YSBhdmFpbGFibGUgc3luY2hyb25vdXNseSBhbmQgdHJ5IGFnYWluISdcbiAgICB9XG4gICAgZXJyb3IubWVzc2FnZSA9IGBGYWlsZWQgZXhwb3J0aW5nIEhUTUwgZm9yIFVSTCAke3JvdXRlLnBhdGh9ICgke3JvdXRlLnRlbXBsYXRlfSk6ICR7ZXJyb3IubWVzc2FnZX1gXG4gICAgdGhyb3cgZXJyb3JcbiAgfVxuXG4gIHN0YXRlID0ge1xuICAgIC4uLnN0YXRlLFxuICAgIGhlYWQsXG4gICAgY2xpZW50U2NyaXB0cyxcbiAgICBjbGllbnRTdHlsZVNoZWV0cyxcbiAgICBjbGllbnRDc3MsXG4gIH1cblxuICBjb25zdCBEb2N1bWVudEh0bWwgPSByZW5kZXJUb1N0YXRpY01hcmt1cChcbiAgICA8RG9jdW1lbnRUZW1wbGF0ZVxuICAgICAgSHRtbD17YXdhaXQgbWFrZUh0bWxXaXRoTWV0YShzdGF0ZSl9XG4gICAgICBIZWFkPXthd2FpdCBtYWtlSGVhZFdpdGhNZXRhKHN0YXRlKX1cbiAgICAgIEJvZHk9e2F3YWl0IG1ha2VCb2R5V2l0aE1ldGEoc3RhdGUpfVxuICAgICAgc3RhdGU9e3N0YXRlfVxuICAgID5cbiAgICAgIDxkaXYgaWQ9XCJyb290XCIgZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUw9e3sgX19odG1sOiBhcHBIdG1sIH19IC8+XG4gICAgPC9Eb2N1bWVudFRlbXBsYXRlPlxuICApXG5cbiAgLy8gUmVuZGVyIHRoZSBodG1sIGZvciB0aGUgcGFnZSBpbnNpZGUgb2YgdGhlIGJhc2UgZG9jdW1lbnQuXG4gIGxldCBodG1sID0gYDwhRE9DVFlQRSBodG1sPiR7RG9jdW1lbnRIdG1sfWBcblxuICBodG1sID0gYXdhaXQgcGx1Z2lucy5iZWZvcmVEb2N1bWVudFRvRmlsZShodG1sLCBzdGF0ZSlcblxuICAvLyBJZiB0aGUgc2l0ZVJvb3QgaXMgc2V0IGFuZCB3ZSdyZSBub3QgaW4gc3RhZ2luZywgcHJlZml4IGFsbCBhYnNvbHV0ZSBVUkxzXG4gIC8vIHdpdGggdGhlIHNpdGVSb290XG4gIGNvbnN0IHB1YmxpY1BhdGggPSBtYWtlUGF0aEFic29sdXRlKHByb2Nlc3MuZW52LlJFQUNUX1NUQVRJQ19QVUJMSUNfUEFUSClcbiAgaWYgKHByb2Nlc3MuZW52LlJFQUNUX1NUQVRJQ19ESVNBQkxFX1JPVVRFX1BSRUZJWElORyAhPT0gJ3RydWUnKSB7XG4gICAgaHRtbCA9IGh0bWwucmVwbGFjZShocmVmUmVwbGFjZSwgYCQxJHtwdWJsaWNQYXRofSQzYClcbiAgfVxuXG4gIGh0bWwgPSBodG1sLnJlcGxhY2Uoc3JjUmVwbGFjZSwgYCQxJHtwdWJsaWNQYXRofSQzYClcblxuICAvLyBJZiB0aGUgcm91dGUgaXMgYSA0MDQgcGFnZSwgd3JpdGUgaXQgZGlyZWN0bHkgdG8gNDA0Lmh0bWwsIGluc3RlYWQgb2ZcbiAgLy8gaW5zaWRlIGEgZGlyZWN0b3J5LlxuICBjb25zdCBodG1sRmlsZW5hbWUgPSBpczQwNFBhdGgocm91dGUucGF0aClcbiAgICA/IG5vZGVQYXRoLmpvaW4oY29uZmlnLnBhdGhzLkRJU1QsICc0MDQuaHRtbCcpXG4gICAgOiBub2RlUGF0aC5qb2luKGNvbmZpZy5wYXRocy5ESVNULCByb3V0ZS5wYXRoLCAnaW5kZXguaHRtbCcpXG5cbiAgLy8gTWFrZSB0aGUgcm91dGVJbmZvIHNpdCByaWdodCBuZXh0IHRvIGl0cyBjb21wYW5pb24gaHRtbCBmaWxlXG4gIGNvbnN0IHJvdXRlSW5mb0ZpbGVuYW1lID0gbm9kZVBhdGguam9pbihcbiAgICBjb25maWcucGF0aHMuRElTVCxcbiAgICByb3V0ZS5wYXRoLFxuICAgICdyb3V0ZUluZm8uanNvbidcbiAgKVxuXG4gIGNvbnN0IHJlcyA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBmcy5vdXRwdXRGaWxlKGh0bWxGaWxlbmFtZSwgaHRtbCksXG4gICAgIXJvdXRlLnJlZGlyZWN0XG4gICAgICA/IGZzLm91dHB1dEpzb24ocm91dGVJbmZvRmlsZW5hbWUsIHJvdXRlSW5mbylcbiAgICAgIDogUHJvbWlzZS5yZXNvbHZlKCksXG4gIF0pXG4gIHJldHVybiByZXNcbn0pXG4iXX0=