electron-compile
Version:
Electron supporting package to compile JS and CSS in Electron applications
311 lines (232 loc) • 23.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
exports.rigHtmlDocumentToInitializeElectronCompile = rigHtmlDocumentToInitializeElectronCompile;
exports.initializeRendererProcess = initializeRendererProcess;
exports.initializeProtocolHook = initializeProtocolHook;
require('./babel-maybefill');
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _mimeTypes = require('mime-types');
var _mimeTypes2 = _interopRequireDefault(_mimeTypes);
var _compilerHost = require('./compiler-host');
var _compilerHost2 = _interopRequireDefault(_compilerHost);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var magicWords = "__magic__file__to__help__electron__compile.js";
var magicGlobalForRootCacheDir = '__electron_compile_root_cache_dir';
var magicGlobalForAppRootDir = '__electron_compile_app_root_dir';
var d = require('debug')('electron-compile:protocol-hook');
var protocol = null;
/**
* Adds our script header to the top of all HTML files
*
* @private
*/
function rigHtmlDocumentToInitializeElectronCompile(doc) {
var lines = doc.split("\n");
var replacement = '<head><script src="' + magicWords + '"></script>';
var replacedHead = false;
for (var i = 0; i < lines.length; i++) {
if (!lines[i].match(/<head>/i)) continue;
lines[i] = lines[i].replace(/<head>/i, replacement);
replacedHead = true;
break;
}
if (!replacedHead) {
replacement = '<html$1><head><script src="' + magicWords + '"></script></head>';
for (var i = 0; i < lines.length; i++) {
if (!lines[i].match(/<html/i)) continue;
lines[i] = lines[i].replace(/<html([^>]+)>/i, replacement);
break;
}
}
return lines.join("\n");
}
function requestFileJob(filePath, finish) {
_fs2.default.readFile(filePath, function (err, buf) {
if (err) {
if (err.errno === 34) {
finish(-6); // net::ERR_FILE_NOT_FOUND
return;
} else {
finish(-2); // net::FAILED
return;
}
}
finish({
data: buf,
mimeType: _mimeTypes2.default.lookup(filePath) || 'text/plain'
});
});
}
var rendererInitialized = false;
/**
* Called by our rigged script file at the top of every HTML file to set up
* the same compilers as the browser process that created us
*
* @private
*/
function initializeRendererProcess(readOnlyMode) {
if (rendererInitialized) return;
// NB: If we don't do this, we'll get a renderer crash if you enable debug
require('debug/browser');
var rootCacheDir = require('remote').getGlobal(magicGlobalForRootCacheDir);
var appRoot = require('remote').getGlobal(magicGlobalForAppRootDir);
var compilerHost = null;
// NB: This has to be synchronous because we need to block HTML parsing
// until we're set up
if (readOnlyMode) {
d('Setting up electron-compile in precompiled mode with cache dir: ' + rootCacheDir);
compilerHost = _compilerHost2.default.createReadonlyFromConfigurationSync(rootCacheDir, appRoot);
} else {
d('Setting up electron-compile in development mode with cache dir: ' + rootCacheDir);
var _require = require('./config-parser');
var createCompilers = _require.createCompilers;
var compilersByMimeType = createCompilers();
compilerHost = _compilerHost2.default.createFromConfigurationSync(rootCacheDir, appRoot, compilersByMimeType);
}
require('./x-require');
require('./require-hook').default(compilerHost);
rendererInitialized = true;
}
/**
* Initializes the protocol hook on file: that allows us to intercept files
* loaded by Chromium and rewrite them. This method along with
* {@link registerRequireExtension} are the top-level methods that electron-compile
* actually uses to intercept code that Electron loads.
*
* @param {CompilerHost} compilerHost The compiler host to use for compilation.
*/
function initializeProtocolHook(compilerHost) {
protocol = protocol || require('protocol');
global[magicGlobalForRootCacheDir] = compilerHost.rootCacheDir;
global[magicGlobalForAppRootDir] = compilerHost.appRoot;
var electronCompileSetupCode = 'if (window.require) require(\'electron-compile/lib/protocol-hook\').initializeRendererProcess(' + compilerHost.readOnlyMode + ');';
protocol.interceptBufferProtocol('file', function () {
var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(request, finish) {
var uri, filePath, _ret, result, err;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
uri = _url2.default.parse(request.url);
d('Intercepting url ' + request.url);
if (!(request.url.indexOf(magicWords) > -1)) {
_context.next = 5;
break;
}
finish({
mimeType: 'application/javascript',
data: new Buffer(electronCompileSetupCode, 'utf8')
});
return _context.abrupt('return');
case 5:
if (!(uri.host && uri.host.length > 1)) {
_context.next = 9;
break;
}
//let newUri = request.url.replace(/^file:/, "https:");
// TODO: Jump off this bridge later
d('TODO: Found bogus protocol-relative URL, can\'t fix it up!!');
finish(-2);
return _context.abrupt('return');
case 9:
filePath = decodeURIComponent(uri.pathname);
// NB: pathname has a leading '/' on Win32 for some reason
if (process.platform === 'win32') {
filePath = filePath.slice(1);
}
// NB: Special-case files coming from atom.asar or node_modules
if (!(filePath.match(/[\/\\]atom.asar/) || filePath.match(/[\/\\]node_modules/))) {
_context.next = 18;
break;
}
if (!filePath.match(/\.html?$/i)) {
_context.next = 16;
break;
}
_ret = function () {
var riggedContents = null;
_fs2.default.readFile(filePath, 'utf8', function (err, contents) {
if (err) {
if (err.errno === 34) {
finish(-6); // net::ERR_FILE_NOT_FOUND
return;
} else {
finish(-2); // net::FAILED
return;
}
}
riggedContents = rigHtmlDocumentToInitializeElectronCompile(contents);
finish({ data: new Buffer(riggedContents), mimeType: 'text/html' });
return;
});
return {
v: undefined
};
}();
if (!((typeof _ret === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret)) === "object")) {
_context.next = 16;
break;
}
return _context.abrupt('return', _ret.v);
case 16:
requestFileJob(filePath, finish);
return _context.abrupt('return');
case 18:
_context.prev = 18;
_context.next = 21;
return compilerHost.compile(filePath);
case 21:
result = _context.sent;
if (result.mimeType === 'text/html') {
result.code = rigHtmlDocumentToInitializeElectronCompile(result.code);
}
if (!(result.binaryData || result.code instanceof Buffer)) {
_context.next = 28;
break;
}
finish({ data: result.binaryData || result.code, mimeType: result.mimeType });
return _context.abrupt('return');
case 28:
finish({ data: new Buffer(result.code), mimeType: result.mimeType });
return _context.abrupt('return');
case 30:
_context.next = 41;
break;
case 32:
_context.prev = 32;
_context.t0 = _context['catch'](18);
err = 'Failed to compile ' + filePath + ': ' + _context.t0.message + '\n' + _context.t0.stack;
d(err);
if (!(_context.t0.errno === 34 /*ENOENT*/)) {
_context.next = 39;
break;
}
finish(-6); // net::ERR_FILE_NOT_FOUND
return _context.abrupt('return');
case 39:
finish({ mimeType: 'text/plain', data: new Buffer(err) });
return _context.abrupt('return');
case 41:
case 'end':
return _context.stop();
}
}
}, _callee, this, [[18, 32]]);
}));
return function (_x, _x2) {
return ref.apply(this, arguments);
};
}());
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm90b2NvbC1ob29rLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztRQW9CZ0I7UUFxREE7UUFxQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF2R2hCLElBQU0sYUFBYSwrQ0FBYjtBQUNOLElBQU0sNkJBQTZCLG1DQUE3QjtBQUNOLElBQU0sMkJBQTJCLGlDQUEzQjs7QUFFTixJQUFNLElBQUksUUFBUSxPQUFSLEVBQWlCLGdDQUFqQixDQUFKOztBQUVOLElBQUksV0FBVyxJQUFYOzs7Ozs7O0FBT0csU0FBUywwQ0FBVCxDQUFvRCxHQUFwRCxFQUF5RDtBQUM5RCxNQUFJLFFBQVEsSUFBSSxLQUFKLENBQVUsSUFBVixDQUFSLENBRDBEO0FBRTlELE1BQUksc0NBQW9DLDBCQUFwQyxDQUYwRDtBQUc5RCxNQUFJLGVBQWUsS0FBZixDQUgwRDs7QUFLOUQsT0FBSyxJQUFJLElBQUUsQ0FBRixFQUFLLElBQUksTUFBTSxNQUFOLEVBQWMsR0FBaEMsRUFBcUM7QUFDbkMsUUFBSSxDQUFDLE1BQU0sQ0FBTixFQUFTLEtBQVQsQ0FBZSxTQUFmLENBQUQsRUFBNEIsU0FBaEM7O0FBRUEsVUFBTSxDQUFOLElBQVcsS0FBQyxDQUFNLENBQU4sQ0FBRCxDQUFXLE9BQVgsQ0FBbUIsU0FBbkIsRUFBOEIsV0FBOUIsQ0FBWCxDQUhtQztBQUluQyxtQkFBZSxJQUFmLENBSm1DO0FBS25DLFVBTG1DO0dBQXJDOztBQVFBLE1BQUksQ0FBQyxZQUFELEVBQWU7QUFDakIsa0RBQTRDLGlDQUE1QyxDQURpQjtBQUVqQixTQUFLLElBQUksSUFBRSxDQUFGLEVBQUssSUFBSSxNQUFNLE1BQU4sRUFBYyxHQUFoQyxFQUFxQztBQUNuQyxVQUFJLENBQUMsTUFBTSxDQUFOLEVBQVMsS0FBVCxDQUFlLFFBQWYsQ0FBRCxFQUEyQixTQUEvQjs7QUFFQSxZQUFNLENBQU4sSUFBVyxLQUFDLENBQU0sQ0FBTixDQUFELENBQVcsT0FBWCxDQUFt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Ozs7Ozs7Ozs7O0FBSUUsMkNBQTJCLGtCQUFhLFlBQUUsT0FBRixVQUFjLFlBQUUsS0FBRjs7QUFDMUQsZ0JBQUUsR0FBRjs7b0JBRUksWUFBRSxLQUFGLEtBQVksRUFBWjs7Ozs7QUFDRixxQkFBTyxDQUFDLENBQUQsQ0FBUDs7Ozs7QUFJRixxQkFBTyxFQUFFLFVBQVUsWUFBVixFQUF3QixNQUFNLElBQUksTUFBSixDQUFXLEdBQVgsQ0FBTixFQUFqQzs7Ozs7Ozs7O0tBbEZxQzs7OztLQUF6QyxFQVJtRDtDQUE5QyIsImZpbGUiOiJwcm90b2NvbC1ob29rLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICcuL2JhYmVsLW1heWJlZmlsbCc7XG5pbXBvcnQgdXJsIGZyb20gJ3VybCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IG1pbWUgZnJvbSAnbWltZS10eXBlcyc7XG5cbmltcG9ydCBDb21waWxlckhvc3QgZnJvbSAnLi9jb21waWxlci1ob3N0JztcblxuY29uc3QgbWFnaWNXb3JkcyA9IFwiX19tYWdpY19fZmlsZV9fdG9fX2hlbHBfX2VsZWN0cm9uX19jb21waWxlLmpzXCI7XG5jb25zdCBtYWdpY0dsb2JhbEZvclJvb3RDYWNoZURpciA9ICdfX2VsZWN0cm9uX2NvbXBpbGVfcm9vdF9jYWNoZV9kaXInO1xuY29uc3QgbWFnaWNHbG9iYWxGb3JBcHBSb290RGlyID0gJ19fZWxlY3Ryb25fY29tcGlsZV9hcHBfcm9vdF9kaXInO1xuXG5jb25zdCBkID0gcmVxdWlyZSgnZGVidWcnKSgnZWxlY3Ryb24tY29tcGlsZTpwcm90b2NvbC1ob29rJyk7XG5cbmxldCBwcm90b2NvbCA9IG51bGw7XG5cbi8qKlxuICogQWRkcyBvdXIgc2NyaXB0IGhlYWRlciB0byB0aGUgdG9wIG9mIGFsbCBIVE1MIGZpbGVzXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJpZ0h0bWxEb2N1bWVudFRvSW5pdGlhbGl6ZUVsZWN0cm9uQ29tcGlsZShkb2MpIHtcbiAgbGV0IGxpbmVzID0gZG9jLnNwbGl0KFwiXFxuXCIpO1xuICBsZXQgcmVwbGFjZW1lbnQgPSBgPGhlYWQ+PHNjcmlwdCBzcmM9XCIke21hZ2ljV29yZHN9XCI+PC9zY3JpcHQ+YDtcbiAgbGV0IHJlcGxhY2VkSGVhZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGk9MDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFsaW5lc1tpXS5tYXRjaCgvPGhlYWQ+L2kpKSBjb250aW51ZTtcblxuICAgIGxpbmVzW2ldID0gKGxpbmVzW2ldKS5yZXBsYWNlKC88aGVhZD4vaSwgcmVwbGFjZW1lbnQpO1xuICAgIHJlcGxhY2VkSGVhZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkSGVhZCkge1xuICAgIHJlcGxhY2VtZW50ID0gYDxodG1sJDE+PGhlYWQ+PHNjcmlwdCBzcmM9XCIke21hZ2ljV29yZHN9XCI+PC9zY3JpcHQ+PC9oZWFkPmA7XG4gICAgZm9yIChsZXQgaT0wOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghbGluZXNbaV0ubWF0Y2goLzxodG1sL2kpKSBjb250aW51ZTtcblxuICAgICAgbGluZXNbaV0gPSAobGluZXNbaV0pLnJlcGxhY2UoLzxodG1sKFtePl0rKT4vaSwgcmVwbGFjZW1lbnQpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpbmVzLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RGaWxlSm9iKGZpbGVQYXRoLCBmaW5pc2gpIHtcbiAgZnMucmVhZEZpbGUoZmlsZVBhdGgsIChlcnIsIGJ1ZikgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGlmIChlcnIuZXJybm8gPT09IDM0KSB7XG4gICAgICAgIGZpbmlzaCgtNik7IC8vIG5ldDo6RVJSX0ZJTEVfTk9UX0ZPVU5EXG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZpbmlzaCgtMik7IC8vIG5ldDo6RkFJTEVEXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmaW5pc2goe1xuICAgICAgZGF0YTogYnVmLFxuICAgICAgbWltZVR5cGU6IG1pbWUubG9va3VwKGZpbGVQYXRoKSB8fCAndGV4dC9wbGFpbidcbiAgICB9KTtcbiAgfSk7XG59XG5cbmxldCByZW5kZXJlckluaXRpYWxpemVkID0gZmFsc2U7XG5cbi8qKlxuICogQ2FsbGVkIGJ5IG91ciByaWdnZWQgc2NyaXB0IGZpbGUgYXQgdGhlIHRvcCBvZiBldmVyeSBIVE1MIGZpbGUgdG8gc2V0IHVwXG4gKiB0aGUgc2FtZSBjb21waWxlcnMgYXMgdGhlIGJyb3dzZXIgcHJvY2VzcyB0aGF0IGNyZWF0ZWQgdXNcbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVJlbmRlcmVyUHJvY2VzcyhyZWFkT25seU1vZGUpIHtcbiAgaWYgKHJlbmRlcmVySW5pdGlhbGl6ZWQpIHJldHVybjtcblxuICAvLyBOQjogSWYgd2UgZG9uJ3QgZG8gdGhpcywgd2UnbGwgZ2V0IGEgcmVuZGVyZXIgY3Jhc2ggaWYgeW91IGVuYWJsZSBkZWJ1Z1xuICByZXF1aXJlKCdkZWJ1Zy9icm93c2VyJyk7XG5cbiAgbGV0IHJvb3RDYWNoZURpciA9IHJlcXVpcmUoJ3JlbW90ZScpLmdldEdsb2JhbChtYWdpY0dsb2JhbEZvclJvb3RDYWNoZURpcik7XG4gIGxldCBhcHBSb290ID0gcmVxdWlyZSgncmVtb3RlJykuZ2V0R2xvYmFsKG1hZ2ljR2xvYmFsRm9yQXBwUm9vdERpcik7XG4gIGxldCBjb21waWxlckhvc3QgPSBudWxsO1xuXG4gIC8vIE5COiBUaGlzIGhhcyB0byBiZSBzeW5jaHJvbm91cyBiZWNhdXNlIHdlIG5lZWQgdG8gYmxvY2sgSFRNTCBwYXJzaW5nXG4gIC8vIHVudGlsIHdlJ3JlIHNldCB1cFxuICBpZiAocmVhZE9ubHlNb2RlKSB7XG4gICAgZChgU2V0dGluZyB1cCBlbGVjdHJvbi1jb21waWxlIGluIHByZWNvbXBpbGVkIG1vZGUgd2l0aCBjYWNoZSBkaXI6ICR7cm9vdENhY2hlRGlyfWApO1xuICAgIGNvbXBpbGVySG9zdCA9IENvbXBpbGVySG9zdC5jcmVhdGVSZWFkb25seUZyb21Db25maWd1cmF0aW9uU3luYyhyb290Q2FjaGVEaXIsIGFwcFJvb3QpO1xuICB9IGVsc2Uge1xuICAgIGQoYFNldHRpbmcgdXAgZWxlY3Ryb24tY29tcGlsZSBpbiBkZXZlbG9wbWVudCBtb2RlIHdpdGggY2FjaGUgZGlyOiAke3Jvb3RDYWNoZURpcn1gKTtcbiAgICBjb25zdCB7IGNyZWF0ZUNvbXBpbGVycyB9ID0gcmVxdWlyZSgnLi9jb25maWctcGFyc2VyJyk7XG4gICAgY29uc3QgY29tcGlsZXJzQnlNaW1lVHlwZSA9IGNyZWF0ZUNvbXBpbGVycygpO1xuXG4gICAgY29tcGlsZXJIb3N0ID0gQ29tcGlsZXJIb3N0LmNyZWF0ZUZyb21Db25maWd1cmF0aW9uU3luYyhyb290Q2FjaGVEaXIsIGFwcFJvb3QsIGNvbXBpbGVyc0J5TWltZVR5cGUpO1xuICB9XG5cbiAgcmVxdWlyZSgnLi94LXJlcXVpcmUnKTtcbiAgcmVxdWlyZSgnLi9yZXF1aXJlLWhvb2snKS5kZWZhdWx0KGNvbXBpbGVySG9zdCk7XG4gIHJlbmRlcmVySW5pdGlhbGl6ZWQgPSB0cnVlO1xufVxuXG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgdGhlIHByb3RvY29sIGhvb2sgb24gZmlsZTogdGhhdCBhbGxvd3MgdXMgdG8gaW50ZXJjZXB0IGZpbGVzXG4gKiBsb2FkZWQgYnkgQ2hyb21pdW0gYW5kIHJld3JpdGUgdGhlbS4gVGhpcyBtZXRob2QgYWxvbmcgd2l0aFxuICoge0BsaW5rIHJlZ2lzdGVyUmVxdWlyZUV4dGVuc2lvbn0gYXJlIHRoZSB0b3AtbGV2ZWwgbWV0aG9kcyB0aGF0IGVsZWN0cm9uLWNvbXBpbGVcbiAqIGFjdHVhbGx5IHVzZXMgdG8gaW50ZXJjZXB0IGNvZGUgdGhhdCBFbGVjdHJvbiBsb2Fkcy5cbiAqXG4gKiBAcGFyYW0gIHtDb21waWxlckhvc3R9IGNvbXBpbGVySG9zdCAgVGhlIGNvbXBpbGVyIGhvc3QgdG8gdXNlIGZvciBjb21waWxhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVQcm90b2NvbEhvb2soY29tcGlsZXJIb3N0KSB7XG4gIHByb3RvY29sID0gcHJvdG9jb2wgfHwgcmVxdWlyZSgncHJvdG9jb2wnKTtcblxuICBnbG9iYWxbbWFnaWNHbG9iYWxGb3JSb290Q2FjaGVEaXJdID0gY29tcGlsZXJIb3N0LnJvb3RDYWNoZURpcjtcbiAgZ2xvYmFsW21hZ2ljR2xvYmFsRm9yQXBwUm9vdERpcl0gPSBjb21waWxlckhvc3QuYXBwUm9vdDtcblxuICBjb25zdCBlbGVjdHJvbkNvbXBpbGVTZXR1cENvZGUgPSBgaWYgKHdpbmRvdy5yZXF1aXJlKSByZXF1aXJlKCdlbGVjdHJvbi1jb21waWxlL2xpYi9wcm90b2NvbC1ob29rJykuaW5pdGlhbGl6ZVJlbmRlcmVyUHJvY2Vzcygke2NvbXBpbGVySG9zdC5yZWFkT25seU1vZGV9KTtgO1xuXG4gIHByb3RvY29sLmludGVyY2VwdEJ1ZmZlclByb3RvY29sKCdmaWxlJywgYXN5bmMgZnVuY3Rpb24ocmVxdWVzdCwgZmluaXNoKSB7XG4gICAgbGV0IHVyaSA9IHVybC5wYXJzZShyZXF1ZXN0LnVybCk7XG5cbiAgICBkKGBJbnRlcmNlcHRpbmcgdXJsICR7cmVxdWVzdC51cmx9YCk7XG4gICAgaWYgKHJlcXVlc3QudXJsLmluZGV4T2YobWFnaWNXb3JkcykgPiAtMSkge1xuICAgICAgZmluaXNoKHtcbiAgICAgICAgbWltZVR5cGU6ICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JyxcbiAgICAgICAgZGF0YTogbmV3IEJ1ZmZlcihlbGVjdHJvbkNvbXBpbGVTZXR1cENvZGUsICd1dGY4JylcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhpcyBpcyBhIHByb3RvY29sLXJlbGF0aXZlIFVSTCB0aGF0IGhhcyBnb25lIHBlYXItc2hhcGVkIGluIEVsZWN0cm9uLFxuICAgIC8vIGxldCdzIHJld3JpdGUgaXRcbiAgICBpZiAodXJpLmhvc3QgJiYgdXJpLmhvc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy9sZXQgbmV3VXJpID0gcmVxdWVzdC51cmwucmVwbGFjZSgvXmZpbGU6LywgXCJodHRwczpcIik7XG4gICAgICAvLyBUT0RPOiBKdW1wIG9mZiB0aGlzIGJyaWRnZSBsYXRlclxuICAgICAgZChgVE9ETzogRm91bmQgYm9ndXMgcHJvdG9jb2wtcmVsYXRpdmUgVVJMLCBjYW4ndCBmaXggaXQgdXAhIWApO1xuICAgICAgZmluaXNoKC0yKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZmlsZVBhdGggPSBkZWNvZGVVUklDb21wb25lbnQodXJpLnBhdGhuYW1lKTtcblxuICAgIC8vIE5COiBwYXRobmFtZSBoYXMgYSBsZWFkaW5nICcvJyBvbiBXaW4zMiBmb3Igc29tZSByZWFzb25cbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgICAgZmlsZVBhdGggPSBmaWxlUGF0aC5zbGljZSgxKTtcbiAgICB9XG5cbiAgICAvLyBOQjogU3BlY2lhbC1jYXNlIGZpbGVzIGNvbWluZyBmcm9tIGF0b20uYXNhciBvciBub2RlX21vZHVsZXNcbiAgICBpZiAoZmlsZVBhdGgubWF0Y2goL1tcXC9cXFxcXWF0b20uYXNhci8pIHx8IGZpbGVQYXRoLm1hdGNoKC9bXFwvXFxcXF1ub2RlX21vZHVsZXMvKSkge1xuICAgICAgLy8gTkJzIG9uIE5CczogSWYgd2UncmUgbG9hZGluZyBhbiBIVE1MIGZpbGUgZnJvbSBub2RlX21vZHVsZXMsIHdlIHN0aWxsIGhhdmVcbiAgICAgIC8vIHRvIGRvIHRoZSBIVE1MIGRvY3VtZW50IHJpZ2dpbmdcbiAgICAgIGlmIChmaWxlUGF0aC5tYXRjaCgvXFwuaHRtbD8kL2kpKSB7XG4gICAgICAgIGxldCByaWdnZWRDb250ZW50cyA9IG51bGw7XG4gICAgICAgIGZzLnJlYWRGaWxlKGZpbGVQYXRoLCAndXRmOCcsIChlcnIsIGNvbnRlbnRzKSA9PiB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgaWYgKGVyci5lcnJubyA9PT0gMzQpIHtcbiAgICAgICAgICAgICAgZmluaXNoKC02KTsgLy8gbmV0OjpFUlJfRklMRV9OT1RfRk9VTkRcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZmluaXNoKC0yKTsgLy8gbmV0OjpGQUlMRURcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJpZ2dlZENvbnRlbnRzID0gcmlnSHRtbERvY3VtZW50VG9Jbml0aWFsaXplRWxlY3Ryb25Db21waWxlKGNvbnRlbnRzKTtcbiAgICAgICAgICBmaW5pc2goeyBkYXRhOiBuZXcgQnVmZmVyKHJpZ2dlZENvbnRlbnRzKSwgbWltZVR5cGU6ICd0ZXh0L2h0bWwnIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXF1ZXN0RmlsZUpvYihmaWxlUGF0aCwgZmluaXNoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IGNvbXBpbGVySG9zdC5jb21waWxlKGZpbGVQYXRoKTtcblxuICAgICAgaWYgKHJlc3VsdC5taW1lVHlwZSA9PT0gJ3RleHQvaHRtbCcpIHtcbiAgICAgICAgcmVzdWx0LmNvZGUgPSByaWdIdG1sRG9jdW1lbnRUb0luaXRpYWxpemVFbGVjdHJvbkNvbXBpbGUocmVzdWx0LmNvZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzdWx0LmJpbmFyeURhdGEgfHwgcmVzdWx0LmNvZGUgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgICAgZmluaXNoKHsgZGF0YTogcmVzdWx0LmJpbmFyeURhdGEgfHwgcmVzdWx0LmNvZGUsIG1pbWVUeXBlOiByZXN1bHQubWltZVR5cGUgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZpbmlzaCh7IGRhdGE6IG5ldyBCdWZmZXIocmVzdWx0LmNvZGUpLCBtaW1lVHlwZTogcmVzdWx0Lm1pbWVUeXBlIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGVyciA9IGBGYWlsZWQgdG8gY29tcGlsZSAke2ZpbGVQYXRofTogJHtlLm1lc3NhZ2V9XFxuJHtlLnN0YWNrfWA7XG4gICAgICBkKGVycik7XG5cbiAgICAgIGlmIChlLmVycm5vID09PSAzNCAvKkVOT0VOVCovKSB7XG4gICAgICAgIGZpbmlzaCgtNik7IC8vIG5ldDo6RVJSX0ZJTEVfTk9UX0ZPVU5EXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgZmluaXNoKHsgbWltZVR5cGU6ICd0ZXh0L3BsYWluJywgZGF0YTogbmV3IEJ1ZmZlcihlcnIpIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfSk7XG59XG4iXX0=