UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

283 lines (221 loc) 29.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getScaleFromImageSize = getScaleFromImageSize; exports.calculateExportImageSize = calculateExportImageSize; exports.convertToPng = convertToPng; exports.dataURItoBlob = dataURItoBlob; exports.downloadFile = downloadFile; exports.exportImage = exportImage; exports.exportToJsonString = exportToJsonString; exports.getMapJSON = getMapJSON; exports.exportJson = exportJson; exports.exportHtml = exportHtml; exports.exportData = exportData; exports.exportMap = exportMap; exports["default"] = exports.DEFAULT_EXPORT_JSON_SETTINGS = exports.DEFAULT_DATA_NAME = exports.DEFAULT_JSON_NAME = exports.DEFAULT_HTML_NAME = exports.DEFAULT_IMAGE_NAME = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _domToImage = _interopRequireDefault(require("./dom-to-image")); var _window = require("global/window"); var _defaultSettings = require("../constants/default-settings"); var _exportMapHtml = require("../templates/export-map-html"); var _dataProcessor = require("../processors/data-processor"); var _lodash = _interopRequireDefault(require("lodash.get")); var _utils = require("./utils"); var _schemas = _interopRequireDefault(require("../schemas")); 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; } /** * Default file names */ var DEFAULT_IMAGE_NAME = 'kepler-gl.png'; exports.DEFAULT_IMAGE_NAME = DEFAULT_IMAGE_NAME; var DEFAULT_HTML_NAME = 'kepler.gl.html'; exports.DEFAULT_HTML_NAME = DEFAULT_HTML_NAME; var DEFAULT_JSON_NAME = 'keplergl.json'; exports.DEFAULT_JSON_NAME = DEFAULT_JSON_NAME; var DEFAULT_DATA_NAME = 'kepler-gl'; /** * Default json export settings * @type {{hasData: boolean}} */ exports.DEFAULT_DATA_NAME = DEFAULT_DATA_NAME; var DEFAULT_EXPORT_JSON_SETTINGS = { hasData: true }; exports.DEFAULT_EXPORT_JSON_SETTINGS = DEFAULT_EXPORT_JSON_SETTINGS; var defaultResolution = _defaultSettings.EXPORT_IMG_RESOLUTION_OPTIONS.find(function (op) { return op.id === _defaultSettings.RESOLUTIONS.ONE_X; }); var defaultRatio = _defaultSettings.EXPORT_IMG_RATIO_OPTIONS.find(function (op) { return op.id === _defaultSettings.EXPORT_IMG_RATIOS.FOUR_BY_THREE; }); function getScaleFromImageSize(imageW, imageH, mapW, mapH) { if ([imageW, imageH, mapW, mapH].some(function (d) { return d <= 0; })) { return 1; } var base = imageW / imageH > 1 ? imageW : imageH; var mapBase = imageW / imageH > 1 ? mapW : mapH; var scale = base / mapBase; return scale; } function calculateExportImageSize(_ref) { var mapW = _ref.mapW, mapH = _ref.mapH, ratio = _ref.ratio, resolution = _ref.resolution; if (mapW <= 0 || mapH <= 0) { return null; } var ratioItem = _defaultSettings.EXPORT_IMG_RATIO_OPTIONS.find(function (op) { return op.id === ratio; }) || defaultRatio; var resolutionItem = _defaultSettings.EXPORT_IMG_RESOLUTION_OPTIONS.find(function (op) { return op.id === resolution; }) || defaultResolution; var _resolutionItem$getSi = resolutionItem.getSize(mapW, mapH), scaledWidth = _resolutionItem$getSi.width, scaledHeight = _resolutionItem$getSi.height; var _ratioItem$getSize = ratioItem.getSize(scaledWidth, scaledHeight), imageW = _ratioItem$getSize.width, imageH = _ratioItem$getSize.height; var _ref2 = ratioItem.id === _defaultSettings.EXPORT_IMG_RATIOS.CUSTOM ? {} : resolutionItem, scale = _ref2.scale; return { scale: scale, imageW: imageW, imageH: imageH }; } function convertToPng(sourceElem, options) { return _domToImage["default"].toPng(sourceElem, options); } function dataURItoBlob(dataURI) { var binary = (0, _window.atob)(dataURI.split(',')[1]); // separate out the mime component var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // write the bytes of the string to an ArrayBuffer var ab = new _window.ArrayBuffer(binary.length); // create a view into the buffer var ia = new _window.Uint8Array(ab); for (var i = 0; i < binary.length; i++) { ia[i] = binary.charCodeAt(i); } return new _window.Blob([ab], { type: mimeString }); } function downloadFile(fileBlob, filename) { var url = _window.URL.createObjectURL(fileBlob); var link = _window.document.createElement('a'); link.setAttribute('href', url); link.setAttribute('download', filename); _window.document.body.appendChild(link); link.click(); _window.document.body.removeChild(link); _window.URL.revokeObjectURL(url); } function exportImage(state) { var imageDataUri = state.uiState.exportImage.imageDataUri; if (imageDataUri) { var file = dataURItoBlob(imageDataUri); downloadFile(file, DEFAULT_IMAGE_NAME); } } function exportToJsonString(data) { try { return JSON.stringify(data); } catch (e) { return e.description; } } function getMapJSON(state) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_EXPORT_JSON_SETTINGS; var hasData = options.hasData; if (!hasData) { return _schemas["default"].getConfigToSave(state); } var mapToSave = _schemas["default"].save(state); // add file name if title is not provided var title = (0, _lodash["default"])(mapToSave, ['info', 'title']); if (!title || !title.length) { mapToSave = (0, _utils.set)(['info', 'title'], "keplergl_".concat((0, _utils.generateHashId)(6)), mapToSave); } return mapToSave; } function exportJson(state) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var map = getMapJSON(state, options); var fileBlob = new _window.Blob([exportToJsonString(map)], { type: 'application/json' }); downloadFile(fileBlob, DEFAULT_JSON_NAME); } function exportHtml(state, options) { var userMapboxToken = options.userMapboxToken, exportMapboxAccessToken = options.exportMapboxAccessToken, mode = options.mode; var data = _objectSpread({}, getMapJSON(state), { mapboxApiAccessToken: (userMapboxToken || '') !== '' ? userMapboxToken : exportMapboxAccessToken, mode: mode }); var fileBlob = new _window.Blob([(0, _exportMapHtml.exportMapToHTML)(data)], { type: 'text/html' }); downloadFile(fileBlob, DEFAULT_HTML_NAME); } function exportData(state, option) { var visState = state.visState; var datasets = visState.datasets; var selectedDataset = option.selectedDataset, dataType = option.dataType, filtered = option.filtered; // get the selected data var filename = DEFAULT_DATA_NAME; var selectedDatasets = datasets[selectedDataset] ? [datasets[selectedDataset]] : Object.values(datasets); if (!selectedDatasets.length) { // error: selected dataset not found. return; } selectedDatasets.forEach(function (selectedData) { var allData = selectedData.allData, fields = selectedData.fields, label = selectedData.label, _selectedData$filtere = selectedData.filteredIdxCPU, filteredIdxCPU = _selectedData$filtere === void 0 ? [] : _selectedData$filtere; var toExport = filtered ? filteredIdxCPU.map(function (i) { return allData[i]; }) : allData; // start to export data according to selected data type switch (dataType) { case _defaultSettings.EXPORT_DATA_TYPE.CSV: { var csv = (0, _dataProcessor.formatCsv)(toExport, fields); var fileBlob = new _window.Blob([csv], { type: 'text/csv' }); downloadFile(fileBlob, "".concat(filename, "_").concat(label, ".csv")); break; } // TODO: support more file types. default: break; } }); } function exportMap(state, option) { var imageDataUri = state.uiState.exportImage.imageDataUri; var thumbnail = imageDataUri ? dataURItoBlob(imageDataUri) : null; var mapToSave = getMapJSON(state, option); return { map: mapToSave, thumbnail: thumbnail }; } var exporters = { exportImage: exportImage, exportJson: exportJson, exportHtml: exportHtml, exportData: exportData }; var _default = exporters; exports["default"] = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9leHBvcnQtdXRpbHMuanMiXSwibmFtZXMiOlsiREVGQVVMVF9JTUFHRV9OQU1FIiwiREVGQVVMVF9IVE1MX05BTUUiLCJERUZBVUxUX0pTT05fTkFNRSIsIkRFRkFVTFRfREFUQV9OQU1FIiwiREVGQVVMVF9FWFBPUlRfSlNPTl9TRVRUSU5HUyIsImhhc0RhdGEiLCJkZWZhdWx0UmVzb2x1dGlvbiIsIkVYUE9SVF9JTUdfUkVTT0xVVElPTl9PUFRJT05TIiwiZmluZCIsIm9wIiwiaWQiLCJSRVNPTFVUSU9OUyIsIk9ORV9YIiwiZGVmYXVsdFJhdGlvIiwiRVhQT1JUX0lNR19SQVRJT19PUFRJT05TIiwiRVhQT1JUX0lNR19SQVRJT1MiLCJGT1VSX0JZX1RIUkVFIiwiZ2V0U2NhbGVGcm9tSW1hZ2VTaXplIiwiaW1hZ2VXIiwiaW1hZ2VIIiwibWFwVyIsIm1hcEgiLCJzb21lIiwiZCIsImJhc2UiLCJtYXBCYXNlIiwic2NhbGUiLCJjYWxjdWxhdGVFeHBvcnRJbWFnZVNpemUiLCJyYXRpbyIsInJlc29sdXRpb24iLCJyYXRpb0l0ZW0iLCJyZXNvbHV0aW9uSXRlbSIsImdldFNpemUiLCJzY2FsZWRXaWR0aCIsIndpZHRoIiwic2NhbGVkSGVpZ2h0IiwiaGVpZ2h0IiwiQ1VTVE9NIiwiY29udmVydFRvUG5nIiwic291cmNlRWxlbSIsIm9wdGlvbnMiLCJkb210b2ltYWdlIiwidG9QbmciLCJkYXRhVVJJdG9CbG9iIiwiZGF0YVVSSSIsImJpbmFyeSIsInNwbGl0IiwibWltZVN0cmluZyIsImFiIiwiQXJyYXlCdWZmZXIiLCJsZW5ndGgiLCJpYSIsIlVpbnQ4QXJyYXkiLCJpIiwiY2hhckNvZGVBdCIsIkJsb2IiLCJ0eXBlIiwiZG93bmxvYWRGaWxlIiwiZmlsZUJsb2IiLCJmaWxlbmFtZSIsInVybCIsIlVSTCIsImNyZWF0ZU9iamVjdFVSTCIsImxpbmsiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJzZXRBdHRyaWJ1dGUiLCJib2R5IiwiYXBwZW5kQ2hpbGQiLCJjbGljayIsInJlbW92ZUNoaWxkIiwicmV2b2tlT2JqZWN0VVJMIiwiZXhwb3J0SW1hZ2UiLCJzdGF0ZSIsImltYWdlRGF0YVVyaSIsInVpU3RhdGUiLCJmaWxlIiwiZXhwb3J0VG9Kc29uU3RyaW5nIiwiZGF0YSIsIkpTT04iLCJzdHJpbmdpZnkiLCJlIiwiZGVzY3JpcHRpb24iLCJnZXRNYXBKU09OIiwiS2VwbGVyR2xTY2hlbWEiLCJnZXRDb25maWdUb1NhdmUiLCJtYXBUb1NhdmUiLCJzYXZlIiwidGl0bGUiLCJleHBvcnRKc29uIiwibWFwIiwiZXhwb3J0SHRtbCIsInVzZXJNYXBib3hUb2tlbiIsImV4cG9ydE1hcGJveEFjY2Vzc1Rva2VuIiwibW9kZSIsIm1hcGJveEFwaUFjY2Vzc1Rva2VuIiwiZXhwb3J0RGF0YSIsIm9wdGlvbiIsInZpc1N0YXRlIiwiZGF0YXNldHMiLCJzZWxlY3RlZERhdGFzZXQiLCJkYXRhVHlwZSIsImZpbHRlcmVkIiwic2VsZWN0ZWREYXRhc2V0cyIsIk9iamVjdCIsInZhbHVlcyIsImZvckVhY2giLCJzZWxlY3RlZERhdGEiLCJhbGxEYXRhIiwiZmllbGRzIiwibGFiZWwiLCJmaWx0ZXJlZElkeENQVSIsInRvRXhwb3J0IiwiRVhQT1JUX0RBVEFfVFlQRSIsIkNTViIsImNzdiIsImV4cG9ydE1hcCIsInRodW1ibmFpbCIsImV4cG9ydGVycyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBQ0E7O0FBT0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7Ozs7OztBQUVBOzs7QUFHTyxJQUFNQSxrQkFBa0IsR0FBRyxlQUEzQjs7QUFDQSxJQUFNQyxpQkFBaUIsR0FBRyxnQkFBMUI7O0FBQ0EsSUFBTUMsaUJBQWlCLEdBQUcsZUFBMUI7O0FBQ0EsSUFBTUMsaUJBQWlCLEdBQUcsV0FBMUI7QUFFUDs7Ozs7O0FBSU8sSUFBTUMsNEJBQTRCLEdBQUc7QUFDMUNDLEVBQUFBLE9BQU8sRUFB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QUFDRSxXQUFLWSxrQ0FBaUJDLEdBQXRCO0FBQTJCO0FBQ3pCLGNBQU1DLEdBQUcsR0FBRyw4QkFBVUgsUUFBVixFQUFvQkgsTUFBcEIsQ0FBWjtBQUVBLGNBQU1uRCxRQUFRLEdBQUcsSUFBSUgsWUFBSixDQUFTLENBQUM0RCxHQUFELENBQVQsRUFBZ0I7QUFBQzNELFlBQUFBLElBQUksRUFBRTtBQUFQLFdBQWhCLENBQWpCO0FBQ0FDLFVBQUFBLFlBQVksQ0FBQ0MsUUFBRCxZQUFjQyxRQUFkLGNBQTBCbUQsS0FBMUIsVUFBWjtBQUNBO0FBQ0Q7QUFDRDs7QUFDQTtBQUNFO0FBVko7QUFZRCxHQWhCRDtBQWlCRDs7QUFFTSxTQUFTTSxTQUFULENBQW1CM0MsS0FBbkIsRUFBMEJ3QixNQUExQixFQUFrQztBQUFBLE1BQ2hDdkIsWUFEZ0MsR0FDaEJELEtBQUssQ0FBQ0UsT0FBTixDQUFjSCxXQURFLENBQ2hDRSxZQURnQztBQUV2QyxNQUFNMkMsU0FBUyxHQUFHM0MsWUFBWSxHQUFHL0IsYUFBYSxDQUFDK0IsWUFBRCxDQUFoQixHQUFpQyxJQUEvRDtBQUNBLE1BQU1ZLFNBQVMsR0FBR0gsVUFBVSxDQUFDVixLQUFELEVBQVF3QixNQUFSLENBQTVCO0FBRUEsU0FBTztBQUNMUCxJQUFBQSxHQUFHLEVBQUVKLFNBREE7QUFFTCtCLElBQUFBLFNBQVMsRUFBVEE7QUFGSyxHQUFQO0FBSUQ7O0FBRUQsSUFBTUMsU0FBUyxHQUFHO0FBQ2hCOUMsRUFBQUEsV0FBVyxFQUFYQSxXQURnQjtBQUVoQmlCLEVBQUFBLFVBQVUsRUFBVkEsVUFGZ0I7QUFHaEJFLEVBQUFBLFVBQVUsRUFBVkEsVUFIZ0I7QUFJaEJLLEVBQUFBLFVBQVUsRUFBVkE7QUFKZ0IsQ0FBbEI7ZUFPZXNCLFMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjAgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgZG9tdG9pbWFnZSBmcm9tICd1dGlscy9kb20tdG8taW1hZ2UnO1xuaW1wb3J0IHtCbG9iLCBVUkwsIGF0b2IsIFVpbnQ4QXJyYXksIEFycmF5QnVmZmVyLCBkb2N1bWVudH0gZnJvbSAnZ2xvYmFsL3dpbmRvdyc7XG5pbXBvcnQge1xuICBFWFBPUlRfSU1HX1JFU09MVVRJT05fT1BUSU9OUyxcbiAgRVhQT1JUX0lNR19SQVRJT19PUFRJT05TLFxuICBSRVNPTFVUSU9OUyxcbiAgRVhQT1JUX0lNR19SQVRJT1MsXG4gIEVYUE9SVF9EQVRBX1RZUEVcbn0gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuaW1wb3J0IHtleHBvcnRNYXBUb0hUTUx9IGZyb20gJ3RlbXBsYXRlcy9leHBvcnQtbWFwLWh0bWwnO1xuaW1wb3J0IHtmb3JtYXRDc3Z9IGZyb20gJ3Byb2Nlc3NvcnMvZGF0YS1wcm9jZXNzb3InO1xuaW1wb3J0IGdldCBmcm9tICdsb2Rhc2guZ2V0JztcbmltcG9ydCB7c2V0LCBnZW5lcmF0ZUhhc2hJZH0gZnJvbSAndXRpbHMvdXRpbHMnO1xuXG5pbXBvcnQgS2VwbGVyR2xTY2hlbWEgZnJvbSAnc2NoZW1hcyc7XG5cbi8qKlxuICogRGVmYXVsdCBmaWxlIG5hbWVzXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0lNQUdFX05BTUUgPSAna2VwbGVyLWdsLnBuZyc7XG5leHBvcnQgY29uc3QgREVGQVVMVF9IVE1MX05BTUUgPSAna2VwbGVyLmdsLmh0bWwnO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfSlNPTl9OQU1FID0gJ2tlcGxlcmdsLmpzb24nO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfREFUQV9OQU1FID0gJ2tlcGxlci1nbCc7XG5cbi8qKlxuICogRGVmYXVsdCBqc29uIGV4cG9ydCBzZXR0aW5nc1xuICogQHR5cGUge3toYXNEYXRhOiBib29sZWFufX1cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhQT1JUX0pTT05fU0VUVElOR1MgPSB7XG4gIGhhc0RhdGE6IHRydWVcbn07XG5cbmNvbnN0IGRlZmF1bHRSZXNvbHV0aW9uID0gRVhQT1JUX0lNR19SRVNPTFVUSU9OX09QVElPTlMuZmluZChvcCA9PiBvcC5pZCA9PT0gUkVTT0xVVElPTlMuT05FX1gpO1xuXG5jb25zdCBkZWZhdWx0UmF0aW8gPSBFWFBPUlRfSU1HX1JBVElPX09QVElPTlMuZmluZChvcCA9PiBvcC5pZCA9PT0gRVhQT1JUX0lNR19SQVRJT1MuRk9VUl9CWV9USFJFRSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTY2FsZUZyb21JbWFnZVNpemUoaW1hZ2VXLCBpbWFnZUgsIG1hcFcsIG1hcEgpIHtcbiAgaWYgKFtpbWFnZVcsIGltYWdlSCwgbWFwVywgbWFwSF0uc29tZShkID0+IGQgPD0gMCkpIHtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGNvbnN0IGJhc2UgPSBpbWFnZVcgLyBpbWFnZUggPiAxID8gaW1hZ2VXIDogaW1hZ2VIO1xuICBjb25zdCBtYXBCYXNlID0gaW1hZ2VXIC8gaW1hZ2VIID4gMSA/IG1hcFcgOiBtYXBIO1xuICBjb25zdCBzY2FsZSA9IGJhc2UgLyBtYXBCYXNlO1xuXG4gIHJldHVybiBzY2FsZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUV4cG9ydEltYWdlU2l6ZSh7bWFwVywgbWFwSCwgcmF0aW8sIHJlc29sdXRpb259KSB7XG4gIGlmIChtYXBXIDw9IDAgfHwgbWFwSCA8PSAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCByYXRpb0l0ZW0gPSBFWFBPUlRfSU1HX1JBVElPX09QVElPTlMuZmluZChvcCA9PiBvcC5pZCA9PT0gcmF0aW8pIHx8IGRlZmF1bHRSYXRpbztcblxuICBjb25zdCByZXNvbHV0aW9uSXRlbSA9XG4gICAgRVhQT1JUX0lNR19SRVNPTFVUSU9OX09QVElPTlMuZmluZChvcCA9PiBvcC5pZCA9PT0gcmVzb2x1dGlvbikgfHwgZGVmYXVsdFJlc29sdXRpb247XG5cbiAgY29uc3Qge3dpZHRoOiBzY2FsZWRXaWR0aCwgaGVpZ2h0OiBzY2FsZWRIZWlnaHR9ID0gcmVzb2x1dGlvbkl0ZW0uZ2V0U2l6ZShtYXBXLCBtYXBIKTtcblxuICBjb25zdCB7d2lkdGg6IGltYWdlVywgaGVpZ2h0OiBpbWFnZUh9ID0gcmF0aW9JdGVtLmdldFNpemUoc2NhbGVkV2lkdGgsIHNjYWxlZEhlaWdodCk7XG5cbiAgY29uc3Qge3NjYWxlfSA9IHJhdGlvSXRlbS5pZCA9PT0gRVhQT1JUX0lNR19SQVRJT1MuQ1VTVE9NID8ge30gOiByZXNvbHV0aW9uSXRlbTtcblxuICByZXR1cm4ge1xuICAgIHNjYWxlLFxuICAgIGltYWdlVyxcbiAgICBpbWFnZUhcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRUb1BuZyhzb3VyY2VFbGVtLCBvcHRpb25zKSB7XG4gIHJldHVybiBkb210b2ltYWdlLnRvUG5nKHNvdXJjZUVsZW0sIG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGF0YVVSSXRvQmxvYihkYXRhVVJJKSB7XG4gIGNvbnN0IGJpbmFyeSA9IGF0b2IoZGF0YVVSSS5zcGxpdCgnLCcpWzFdKTtcblxuICAvLyBzZXBhcmF0ZSBvdXQgdGhlIG1pbWUgY29tcG9uZW50XG4gIGNvbnN0IG1pbWVTdHJpbmcgPSBkYXRhVVJJXG4gICAgLnNwbGl0KCcsJylbMF1cbiAgICAuc3BsaXQoJzonKVsxXVxuICAgIC5zcGxpdCgnOycpWzBdO1xuXG4gIC8vIHdyaXRlIHRoZSBieXRlcyBvZiB0aGUgc3RyaW5nIHRvIGFuIEFycmF5QnVmZmVyXG4gIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJpbmFyeS5sZW5ndGgpO1xuXG4gIC8vIGNyZWF0ZSBhIHZpZXcgaW50byB0aGUgYnVmZmVyXG4gIGNvbnN0IGlhID0gbmV3IFVpbnQ4QXJyYXkoYWIpO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYmluYXJ5Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWFbaV0gPSBiaW5hcnkuY2hhckNvZGVBdChpKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgQmxvYihbYWJdLCB7dHlwZTogbWltZVN0cmluZ30pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZG93bmxvYWRGaWxlKGZpbGVCbG9iLCBmaWxlbmFtZSkge1xuICBjb25zdCB1cmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGZpbGVCbG9iKTtcblxuICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICBsaW5rLnNldEF0dHJpYnV0ZSgnaHJlZicsIHVybCk7XG4gIGxpbmsuc2V0QXR0cmlidXRlKCdkb3dubG9hZCcsIGZpbGVuYW1lKTtcblxuICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuICBsaW5rLmNsaWNrKCk7XG4gIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQobGluayk7XG4gIFVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4cG9ydEltYWdlKHN0YXRlKSB7XG4gIGNvbnN0IHtpbWFnZURhdGFVcml9ID0gc3RhdGUudWlTdGF0ZS5leHBvcnRJbWFnZTtcbiAgaWYgKGltYWdlRGF0YVVyaSkge1xuICAgIGNvbnN0IGZpbGUgPSBkYXRhVVJJdG9CbG9iKGltYWdlRGF0YVVyaSk7XG4gICAgZG93bmxvYWRGaWxlKGZpbGUsIERFRkFVTFRfSU1BR0VfTkFNRSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4cG9ydFRvSnNvblN0cmluZyhkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGRhdGEpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGUuZGVzY3JpcHRpb247XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1hcEpTT04oc3RhdGUsIG9wdGlvbnMgPSBERUZBVUxUX0VYUE9SVF9KU09OX1NFVFRJTkdTKSB7XG4gIGNvbnN0IHtoYXNEYXRhfSA9IG9wdGlvbnM7XG5cbiAgaWYgKCFoYXNEYXRhKSB7XG4gICAgcmV0dXJuIEtlcGxlckdsU2NoZW1hLmdldENvbmZpZ1RvU2F2ZShzdGF0ZSk7XG4gIH1cblxuICBsZXQgbWFwVG9TYXZlID0gS2VwbGVyR2xTY2hlbWEuc2F2ZShzdGF0ZSk7XG4gIC8vIGFkZCBmaWxlIG5hbWUgaWYgdGl0bGUgaXMgbm90IHByb3ZpZGVkXG4gIGNvbnN0IHRpdGxlID0gZ2V0KG1hcFRvU2F2ZSwgWydpbmZvJywgJ3RpdGxlJ10pO1xuICBpZiAoIXRpdGxlIHx8ICF0aXRsZS5sZW5ndGgpIHtcbiAgICBtYXBUb1NhdmUgPSBzZXQoWydpbmZvJywgJ3RpdGxlJ10sIGBrZXBsZXJnbF8ke2dlbmVyYXRlSGFzaElkKDYpfWAsIG1hcFRvU2F2ZSk7XG4gIH1cbiAgcmV0dXJuIG1hcFRvU2F2ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4cG9ydEpzb24oc3RhdGUsIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCBtYXAgPSBnZXRNYXBKU09OKHN0YXRlLCBvcHRpb25zKTtcblxuICBjb25zdCBmaWxlQmxvYiA9IG5ldyBCbG9iKFtleHBvcnRUb0pzb25TdHJpbmcobWFwKV0sIHt0eXBlOiAnYXBwbGljYXRpb24vanNvbid9KTtcbiAgZG93bmxvYWRGaWxlKGZpbGVCbG9iLCBERUZBVUxUX0pTT05fTkFNRSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHBvcnRIdG1sKHN0YXRlLCBvcHRpb25zKSB7XG4gIGNvbnN0IHt1c2VyTWFwYm94VG9rZW4sIGV4cG9ydE1hcGJveEFjY2Vzc1Rva2VuLCBtb2RlfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgZGF0YSA9IHtcbiAgICAuLi5nZXRNYXBKU09OKHN0YXRlKSxcbiAgICBtYXBib3hBcGlBY2Nlc3NUb2tlbjpcbiAgICAgICh1c2VyTWFwYm94VG9rZW4gfHwgJycpICE9PSAnJyA/IHVzZXJNYXBib3hUb2tlbiA6IGV4cG9ydE1hcGJveEFjY2Vzc1Rva2VuLFxuICAgIG1vZGVcbiAgfTtcblxuICBjb25zdCBmaWxlQmxvYiA9IG5ldyBCbG9iKFtleHBvcnRNYXBUb0hUTUwoZGF0YSldLCB7dHlwZTogJ3RleHQvaHRtbCd9KTtcbiAgZG93bmxvYWRGaWxlKGZpbGVCbG9iLCBERUZBVUxUX0hUTUxfTkFNRSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHBvcnREYXRhKHN0YXRlLCBvcHRpb24pIHtcbiAgY29uc3Qge3Zpc1N0YXRlfSA9IHN0YXRlO1xuICBjb25zdCB7ZGF0YXNldHN9ID0gdmlzU3RhdGU7XG4gIGNvbnN0IHtzZWxlY3RlZERhdGFzZXQsIGRhdGFUeXBlLCBmaWx0ZXJlZH0gPSBvcHRpb247XG4gIC8vIGdldCB0aGUgc2VsZWN0ZWQgZGF0YVxuICBjb25zdCBmaWxlbmFtZSA9IERFRkFVTFRfREFUQV9OQU1FO1xuICBjb25zdCBzZWxlY3RlZERhdGFzZXRzID0gZGF0YXNldHNbc2VsZWN0ZWREYXRhc2V0XVxuICAgID8gW2RhdGFzZXRzW3NlbGVjdGVkRGF0YXNldF1dXG4gICAgOiBPYmplY3QudmFsdWVzKGRhdGFzZXRzKTtcbiAgaWYgKCFzZWxlY3RlZERhdGFzZXRzLmxlbmd0aCkge1xuICAgIC8vIGVycm9yOiBzZWxlY3RlZCBkYXRhc2V0IG5vdCBmb3VuZC5cbiAgICByZXR1cm47XG4gIH1cblxuICBzZWxlY3RlZERhdGFzZXRzLmZvckVhY2goc2VsZWN0ZWREYXRhID0+IHtcbiAgICBjb25zdCB7YWxsRGF0YSwgZmllbGRzLCBsYWJlbCwgZmlsdGVyZWRJZHhDUFUgPSBbXX0gPSBzZWxlY3RlZERhdGE7XG4gICAgY29uc3QgdG9FeHBvcnQgPSBmaWx0ZXJlZCA/IGZpbHRlcmVkSWR4Q1BVLm1hcChpID0+IGFsbERhdGFbaV0pIDogYWxsRGF0YTtcbiAgICAvLyBzdGFydCB0byBleHBvcnQgZGF0YSBhY2NvcmRpbmcgdG8gc2VsZWN0ZWQgZGF0YSB0eXBlXG4gICAgc3dpdGNoIChkYXRhVHlwZSkge1xuICAgICAgY2FzZSBFWFBPUlRfREFUQV9UWVBFLkNTVjoge1xuICAgICAgICBjb25zdCBjc3YgPSBmb3JtYXRDc3YodG9FeHBvcnQsIGZpZWxkcyk7XG5cbiAgICAgICAgY29uc3QgZmlsZUJsb2IgPSBuZXcgQmxvYihbY3N2XSwge3R5cGU6ICd0ZXh0L2Nzdid9KTtcbiAgICAgICAgZG93bmxvYWRGaWxlKGZpbGVCbG9iLCBgJHtmaWxlbmFtZX1fJHtsYWJlbH0uY3N2YCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgLy8gVE9ETzogc3VwcG9ydCBtb3JlIGZpbGUgdHlwZXMuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXhwb3J0TWFwKHN0YXRlLCBvcHRpb24pIHtcbiAgY29uc3Qge2ltYWdlRGF0YVVyaX0gPSBzdGF0ZS51aVN0YXRlLmV4cG9ydEltYWdlO1xuICBjb25zdCB0aHVtYm5haWwgPSBpbWFnZURhdGFVcmkgPyBkYXRhVVJJdG9CbG9iKGltYWdlRGF0YVVyaSkgOiBudWxsO1xuICBjb25zdCBtYXBUb1NhdmUgPSBnZXRNYXBKU09OKHN0YXRlLCBvcHRpb24pO1xuXG4gIHJldHVybiB7XG4gICAgbWFwOiBtYXBUb1NhdmUsXG4gICAgdGh1bWJuYWlsXG4gIH07XG59XG5cbmNvbnN0IGV4cG9ydGVycyA9IHtcbiAgZXhwb3J0SW1hZ2UsXG4gIGV4cG9ydEpzb24sXG4gIGV4cG9ydEh0bWwsXG4gIGV4cG9ydERhdGFcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGV4cG9ydGVycztcbiJdfQ==