kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
327 lines (271 loc) • 29.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _taggedTemplateLiteral2 = require('babel-runtime/helpers/taggedTemplateLiteral');
var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2);
var _class, _temp2;
var _templateObject = (0, _taggedTemplateLiteral3.default)(['\n margin-top: 10px;\n color: ', ';\n'], ['\n margin-top: 10px;\n color: ', ';\n']),
_templateObject2 = (0, _taggedTemplateLiteral3.default)(['\n color: ', ';\n'], ['\n color: ', ';\n']),
_templateObject3 = (0, _taggedTemplateLiteral3.default)(['\n background-color: white;\n border-radius: 4px;\n border-style: dashed;\n border-width: 1px;\n border-color: ', ';\n height: 414px;\n padding-top: 60px;\n text-align: center;\n width: 100%;\n\n .file-upload-or {\n color: ', ';\n padding-right: 4px;\n }\n'], ['\n background-color: white;\n border-radius: 4px;\n border-style: dashed;\n border-width: 1px;\n border-color: ', ';\n height: 414px;\n padding-top: 60px;\n text-align: center;\n width: 100%;\n\n .file-upload-or {\n color: ', ';\n padding-right: 4px;\n }\n']),
_templateObject4 = (0, _taggedTemplateLiteral3.default)(['\n color: ', ';\n font-size: 20px;\n height: 36px;\n'], ['\n color: ', ';\n font-size: 20px;\n height: 36px;\n']),
_templateObject5 = (0, _taggedTemplateLiteral3.default)(['\n color: ', ';\n margin-bottom: 60px;\n\n .file-type-row {\n margin-bottom: 26px;\n }\n'], ['\n color: ', ';\n margin-bottom: 60px;\n\n .file-type-row {\n margin-bottom: 26px;\n }\n']),
_templateObject6 = (0, _taggedTemplateLiteral3.default)(['\n .filter-upload__input {\n visibility: hidden;\n height: 0;\n position: absolute;\n }\n\n .file-drop {\n position: relative;\n }\n\n .file-upload__message {\n color: ', ';\n font-size: 14px;\n margin-bottom: 12px;\n }\n'], ['\n .filter-upload__input {\n visibility: hidden;\n height: 0;\n position: absolute;\n }\n\n .file-drop {\n position: relative;\n }\n\n .file-upload__message {\n color: ', ';\n font-size: 14px;\n margin-bottom: 12px;\n }\n']),
_templateObject7 = (0, _taggedTemplateLiteral3.default)(['\n display: flex;\n justify-content: center;\n align-items: center;\n'], ['\n display: flex;\n justify-content: center;\n align-items: center;\n']),
_templateObject8 = (0, _taggedTemplateLiteral3.default)(['\n position: absolute;\n bottom: 0;\n padding: 10px 30px;\n'], ['\n position: absolute;\n bottom: 0;\n padding: 10px 30px;\n']); // Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _styledComponents = require('styled-components');
var _styledComponents2 = _interopRequireDefault(_styledComponents);
var _uploadButton = require('./upload-button');
var _uploadButton2 = _interopRequireDefault(_uploadButton);
var _icons = require('../icons');
var _loadingSpinner = require('../loading-spinner');
var _loadingSpinner2 = _interopRequireDefault(_loadingSpinner);
var _utils = require('../../../utils/utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var FileDrop = typeof document !== 'undefined' ? require('react-file-drop') : null;
// File.type is not reliable if the OS does not have a
// registered mapping for the extension.
// NOTE: Shapefiles must be in a compressed format since
// it requires multiple files to be present.
var defaultValidFileExt = ['csv',
// 'tar.gz',
// 'tgz',
// 'zip',
// 'gpx',
// 'kml',
'json', 'geojson'];
var MESSAGE = ' Drag & Drop Your File(s) Here';
var CHROME_MSG = '*Chrome user: Limit file size to 250mb, if need to upload larger file, try Safari';
var DISCLAIMER = '*Kepler.gl is a client-side application with no server backend. Data lives only on your machine/browser. ' + 'No information or map data is sent to any server.';
var CONFIG_UPLOAD_MESSAGE = 'Upload data files or upload a saved map via previously exported single Json of both config and data';
var fileIconColor = '#D3D8E0';
var WarningMsg = _styledComponents2.default.span(_templateObject, function (props) {
return props.theme.errorColor;
});
var PositiveMsg = _styledComponents2.default.span(_templateObject2, function (props) {
return props.theme.primaryBtnActBgd;
});
var StyledFileDrop = _styledComponents2.default.div(_templateObject3, function (props) {
return props.theme.subtextColorLT;
}, function (props) {
return props.theme.linkBtnColor;
});
var MsgWrapper = _styledComponents2.default.div(_templateObject4, function (props) {
return props.theme.modalTitleColor;
});
var StyledDragNDropIcon = _styledComponents2.default.div(_templateObject5, fileIconColor);
var StyledFileUpload = _styledComponents2.default.div(_templateObject6, function (props) {
return props.theme.textColorLT;
});
var StyledMessage = _styledComponents2.default.div(_templateObject7);
var StyledDisclaimer = StyledMessage.extend(_templateObject8);
var FileUpload = (_temp2 = _class = function (_Component) {
(0, _inherits3.default)(FileUpload, _Component);
function FileUpload() {
var _ref;
var _temp, _this, _ret;
(0, _classCallCheck3.default)(this, FileUpload);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = FileUpload.__proto__ || Object.getPrototypeOf(FileUpload)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
dragOver: false,
files: [],
errorFiles: []
}, _this._isValidFileType = function (filename) {
var validFileExt = _this.props.validFileExt;
var fileExt = validFileExt.find(function (ext) {
return filename.endsWith(ext);
});
return Boolean(fileExt);
}, _this._handleFileDrop = function (files, e) {
if (e) {
e.stopPropagation();
}
var nextState = { files: [], errorFiles: [], dragOver: false };
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file && _this._isValidFileType(file.name)) {
nextState.files.push(file);
} else {
nextState.errorFiles.push(file.name);
}
}
_this.setState(nextState, function () {
return nextState.files.length ? _this.props.onFileUpload(nextState.files) : null;
});
}, _this._toggleDragState = function (newState) {
_this.setState({ dragOver: newState });
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
}
(0, _createClass3.default)(FileUpload, [{
key: '_renderMessage',
value: function _renderMessage() {
var _state = this.state,
errorFiles = _state.errorFiles,
files = _state.files;
if (errorFiles.length) {
return _react2.default.createElement(
WarningMsg,
null,
'File ' + errorFiles.join(', ') + ' is not supported.'
);
}
if (!files.length) {
return null;
}
return _react2.default.createElement(
StyledMessage,
{ className: 'file-uploader__message' },
_react2.default.createElement(
'div',
null,
'Uploading...'
),
_react2.default.createElement(
PositiveMsg,
null,
files.map(function (f) {
return f.name;
}).join(' and ') + '...'
),
_react2.default.createElement(_loadingSpinner2.default, { size: 20 })
);
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var _state2 = this.state,
dragOver = _state2.dragOver,
files = _state2.files;
var validFileExt = this.props.validFileExt;
return _react2.default.createElement(
StyledFileUpload,
{
className: 'file-uploader',
innerRef: function innerRef(cmp) {
return _this2.frame = cmp;
}
},
_react2.default.createElement('input', {
className: 'filter-upload__input',
type: 'file',
onChange: this._onChange
}),
FileDrop ? _react2.default.createElement(
FileDrop,
{
frame: this.frame,
targetAlwaysVisible: true,
onDragOver: function onDragOver() {
return _this2._toggleDragState(true);
},
onDragLeave: function onDragLeave() {
return _this2._toggleDragState(false);
},
onDrop: this._handleFileDrop
},
_react2.default.createElement(
'div',
{ className: 'file-upload__message' },
CONFIG_UPLOAD_MESSAGE
),
_react2.default.createElement(
StyledFileDrop,
{ dragOver: dragOver },
_react2.default.createElement(
'div',
{ style: { opacity: dragOver ? 0.5 : 1 } },
_react2.default.createElement(
StyledDragNDropIcon,
null,
_react2.default.createElement(
'div',
{ className: 'file-type-row' },
validFileExt.map(function (ext) {
return _react2.default.createElement(_icons.FileType, { key: ext, ext: ext, height: '50px', fontSize: '9px' });
})
),
_react2.default.createElement(_icons.DragNDrop, { height: '44px' })
),
_react2.default.createElement(
'div',
null,
this._renderMessage()
)
),
!files.length ? _react2.default.createElement(
'div',
null,
_react2.default.createElement(
MsgWrapper,
null,
MESSAGE
),
_react2.default.createElement(
'span',
{ className: 'file-upload-or' },
'or'
),
_react2.default.createElement(
_uploadButton2.default,
{ onUpload: this._handleFileDrop },
'browse your files'
)
) : null,
_react2.default.createElement(
StyledDisclaimer,
null,
DISCLAIMER
)
)
) : null,
_react2.default.createElement(
WarningMsg,
null,
(0, _utils.isChrome)() ? CHROME_MSG : ''
)
);
}
}]);
return FileUpload;
}(_react.Component), _class.defaultProps = {
validFileExt: defaultValidFileExt
}, _class.propTypes = {
onFileUpload: _propTypes2.default.func.isRequired,
validFileExt: _propTypes2.default.arrayOf(_propTypes2.default.string)
}, _temp2);
exports.default = FileUpload;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2NvbW1vbi9maWxlLXVwbG9hZGVyL2ZpbGUtdXBsb2FkLmpzIl0sIm5hbWVzIjpbIkZpbGVEcm9wIiwiZG9jdW1lbnQiLCJyZXF1aXJlIiwiZGVmYXVsdFZhbGlkRmlsZUV4dCIsIk1FU1NBR0UiLCJDSFJPTUVfTVNHIiwiRElTQ0xBSU1FUiIsIkNPTkZJR19VUExPQURfTUVTU0FHRSIsImZpbGVJY29uQ29sb3IiLCJXYXJuaW5nTXNnIiwic3R5bGVkIiwic3BhbiIsInByb3BzIiwidGhlbWUiLCJlcnJvckNvbG9yIiwiUG9zaXRpdmVNc2ciLCJwcmltYXJ5QnRuQWN0QmdkIiwiU3R5bGVkRmlsZURyb3AiLCJkaXYiLCJzdWJ0ZXh0Q29sb3JMVCIsImxpbmtCdG5Db2xvciIsIk1zZ1dyYXBwZXIiLCJtb2RhbFRpdGxlQ29sb3IiLCJTdHlsZWREcmFnTkRyb3BJY29uIiwiU3R5bGVkRmlsZVVwbG9hZCIsInRleHRDb2xvckxUIiwiU3R5bGVkTWVzc2FnZSIsIlN0eWxlZERpc2NsYWltZXIiLCJleHRlbmQiLCJGaWxlVXBsb2FkIiwic3RhdGUiLCJkcmFnT3ZlciIsImZpbGVzIiwiZXJyb3JGaWxlcyIsIl9pc1ZhbGlkRmlsZVR5cGUiLCJ2YWxpZEZpbGVFeHQiLCJmaWxlRXh0IiwiZmluZCIsImZpbGVuYW1lIiwiZW5kc1dpdGgiLCJleHQiLCJCb29sZWFuIiwiX2hhbmRsZUZpbGVEcm9wIiwiZSIsInN0b3BQcm9wYWdhdGlvbiIsIm5leHRTdGF0ZSIsImkiLCJsZW5ndGgiLCJmaWxlIiwibmFtZSIsInB1c2giLCJzZXRTdGF0ZSIsIm9uRmlsZVVwbG9hZCIsIl90b2dnbGVEcmFnU3RhdGUiLCJuZXdTdGF0ZSIsImpvaW4iLCJtYXAiLCJmIiwiZnJhbWUiLCJjbXAiLCJfb25DaGFuZ2UiLCJvcGFjaXR5IiwiX3JlbmRlck1lc3NhZ2UiLCJDb21wb25lbnQiLCJkZWZhdWx0UHJvcHMiLCJwcm9wVHlwZXMiLCJQcm9wVHlwZXMiLCJmdW5jIiwiaXNSZXF1aXJlZCIsImFycmF5T2YiLCJzdHJpbmciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztxTUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFFQTs7OztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFFQSxJQUFNQSxXQUNKLE9BQU9DLFFBQVAsS0FBb0IsV0FBcEIsR0FBa0NDLFFBQVEsaUJBQVIsQ0FBbEMsR0FBK0QsSUFEakU7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFNQyxzQkFBc0IsQ0FDMUIsS0FEMEI7QUFFMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BUDBCLEVBUTFCLFNBUjBCLENBQTVCOztBQVdBLElBQU1DLFVBQVUsZ0NBQWhCO0FBQ0EsSUFBTUMsYUFDSixtRkFERjtBQUVBLElBQU1DLGFBQWEsOEdBQ2pCLG1EQURGO0FBRUEsSUFBTUMsd0JBQXdCLHFHQUE5Qjs7QUFFQSxJQUFNQyxnQkFBZ0IsU0FBdEI7O0FBRUEsSUFBTUMsYUFBYUMsMkJBQU9DLElBQXBCLGtCQUVLO0FBQUEsU0FBU0MsTUFBTUMsS0FBTixDQUFZQyxVQUFyQjtBQUFBLENBRkwsQ0FBTjs7QUFLQSxJQUFNQyxjQUFjTCwyQkFBT0MsSUFBckIsbUJBQ0s7QUFBQSxTQUFTQyxNQUFNQyxLQUFOLENBQVlHLGdCQUFyQjtBQUFBLENBREwsQ0FBTjs7QUFJQSxJQUFNQyxpQkFBaUJQLDJCQUFPUSxHQUF4QixtQkFLWTtBQUFBLFNBQVNOLE1BQU1DLEtBQU4sQ0FBWU0sY0FBckI7QUFBQSxDQUxaLEVBWU87QUFBQSxTQUFTUCxNQUFNQyxLQUFOLENBQVlPLFlBQXJCO0FBQUEsQ0FaUCxDQUFOOztBQWlCQSxJQUFNQyxhQUFhWCwyQkFBT1EsR0FBcEIsbUJBQ0s7QUFBQSxTQUFTTixNQUFNQyxLQUFOLENBQVlTLGVBQXJCO0FBQUEsQ0FETCxDQUFOOztBQU1BLElBQU1DLHNCQUFzQmIsMkJBQU9RLEdBQTdCLG1CQUNLVixhQURMLENBQU47O0FBU0EsSUFBTWdCLG1CQUFtQmQsMkJBQU9RLEdBQTFCLG1CQVlPO0FBQUEsU0FBU04sTUFBTUMsS0FBTixDQUFZWSxXQUFyQjtBQUFBLENBWlAsQ0FBTjs7QUFrQkEsSUFBTUMsZ0JBQWdCaEIsMkJBQU9RLEdBQXZCLGtCQUFOOztBQU1BLElBQU1TLG1CQUFtQkQsY0FBY0UsTUFBakMsa0JBQU47O0lBTXFCQyxVOzs7Ozs7Ozs7Ozs7Ozs0TUFVbkJDLEssR0FBUTtBQUNOQyxnQkFBVSxLQURKO0FBRU5DLGFBQU8sRUFGRDtBQUdOQyxrQkFBWTtBQUhOLEssUUFNUkMsZ0IsR0FBbUIsb0JBQVk7QUFBQSxVQUN0QkMsWUFEc0IsR0FDTixNQUFLdkIsS0FEQyxDQUN0QnVCLFlBRHNCOztBQUU3QixVQUFNQyxVQUFVRCxhQUFhRSxJQUFiLENBQWtCO0FBQUEsZUFBT0MsU0FBU0MsUUFBVCxDQUFrQkMsR0FBbEIsQ0FBUDtBQUFBLE9BQWxCLENBQWhCOztBQUVBLGFBQU9DLFFBQVFMLE9BQVIsQ0FBUDtBQUNELEssUUFFRE0sZSxHQUFrQixVQUFDVixLQUFELEVBQVFXLENBQVIsRUFBYztBQUM5QixVQUFJQSxDQUFKLEVBQU87QUFDTEEsVUFBRUMsZUFBRjtBQUNEOztBQUVELFVBQU1DLFlBQVksRUFBQ2IsT0FBTyxFQUFSLEVBQVlDLFlBQVksRUFBeEIsRUFBNEJGLFVBQVUsS0FBdEMsRUFBbEI7QUFDQSxXQUFLLElBQUllLElBQUksQ0FBYixFQUFnQkEsSUFBSWQsTUFBTWUsTUFBMUIsRUFBa0NELEdBQWxDLEVBQXVDO0FBQ3JDLFlBQU1FLE9BQU9oQixNQUFNYyxDQUFOLENBQWI7O0FBRUEsWUFBSUUsUUFBUSxNQUFLZCxnQkFBTCxDQUFzQmMsS0FBS0MsSUFBM0IsQ0FBWixFQUE4QztBQUM1Q0osb0JBQVViLEtBQVYsQ0FBZ0JrQixJQUFoQixDQUFxQkYsSUFBckI7QUFDRCxTQUZELE1BRU87QUFDTEgsb0JBQVVaLFVBQVYsQ0FBcUJpQixJQUFyQixDQUEwQkYsS0FBS0MsSUFBL0I7QUFDRDtBQUNGOztBQUVELFlBQUtFLFFBQUwsQ0FDRU4sU0FERixFQUVFO0FBQUEsZUFDRUEsVUFBVWIsS0FBVixDQUFnQmUsTUFBaEIsR0FBeUIsTUFBS25DLEtBQUwsQ0FBV3dDLFlBQVgsQ0FBd0JQLFVBQVViLEtBQWxDLENBQXpCLEdBQW9FLElBRHRFO0FBQUEsT0FGRjtBQUtELEssUUFFRHFCLGdCLEdBQW1CLG9CQUFZO0FBQzdCLFlBQUtGLFFBQUwsQ0FBYyxFQUFDcEIsVUFBVXVCLFFBQVgsRUFBZDtBQUNELEs7Ozs7O3FDQUVnQjtBQUFBLG1CQUNhLEtBQUt4QixLQURsQjtBQUFBLFVBQ1JHLFVBRFEsVUFDUkEsVUFEUTtBQUFBLFVBQ0lELEtBREosVUFDSUEsS0FESjs7O0FBR2YsVUFBSUMsV0FBV2MsTUFBZixFQUF1QjtBQUNyQixlQUNFO0FBQUMsb0JBQUQ7QUFBQTtBQUFBLG9CQUNXZCxXQUFXc0IsSUFBWCxDQUFnQixJQUFoQixDQURYO0FBQUEsU0FERjtBQUtEOztBQUVELFVBQUksQ0FBQ3ZCLE1BQU1lLE1BQVgsRUFBbUI7QUFDakIsZUFBTyxJQUFQO0FBQ0Q7O0FBRUQsYUFDRTtBQUFDLHFCQUFEO0FBQUEsVUFBZSxXQUFVLHdCQUF6QjtBQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUEsU0FERjtBQUVFO0FBQUMscUJBQUQ7QUFBQTtBQUNNZixnQkFBTXdCLEdBQU4sQ0FBVTtBQUFBLG1CQUFLQyxFQUFFUixJQUFQO0FBQUEsV0FBVixFQUF1Qk0sSUFBdkIsQ0FBNEIsT0FBNUIsQ0FETjtBQUFBLFNBRkY7QUFLRSxzQ0FBQyx3QkFBRCxJQUFnQixNQUFNLEVBQXRCO0FBTEYsT0FERjtBQVNEOzs7NkJBRVE7QUFBQTs7QUFBQSxvQkFDbUIsS0FBS3pCLEtBRHhCO0FBQUEsVUFDQUMsUUFEQSxXQUNBQSxRQURBO0FBQUEsVUFDVUMsS0FEVixXQUNVQSxLQURWO0FBQUEsVUFFQUcsWUFGQSxHQUVnQixLQUFLdkIsS0FGckIsQ0FFQXVCLFlBRkE7O0FBR1AsYUFDRTtBQUFDLHdCQUFEO0FBQUE7QUFDRSxxQkFBVSxlQURaO0FBRUUsb0JBQVU7QUFBQSxtQkFBUSxPQUFLdUIsS0FBTCxHQUFhQyxHQUFyQjtBQUFBO0FBRlo7QUFJRTtBQUNFLHFCQUFVLHNCQURaO0FBRUUsZ0JBQUssTUFGUDtBQUdFLG9CQUFVLEtBQUtDO0FBSGpCLFVBSkY7QUFTRzVELG1CQUNDO0FBQUMsa0JBQUQ7QUFBQTtBQUNFLG1CQUFPLEtBQUswRCxLQURkO0FBRUUscUNBRkY7QUFHRSx3QkFBWTtBQUFBLHFCQUFNLE9BQUtMLGdCQUFMLENBQXNCLElBQXRCLENBQU47QUFBQSxhQUhkO0FBSUUseUJBQWE7QUFBQSxxQkFBTSxPQUFLQSxnQkFBTCxDQUFzQixLQUF0QixDQUFOO0FBQUEsYUFKZjtBQUtFLG9CQUFRLEtBQUtYO0FBTGY7QUFPRTtBQUFBO0FBQUEsY0FBSyxXQUFVLHNCQUFmO0FBQXVDbkM7QUFBdkMsV0FQRjtBQVFFO0FBQUMsMEJBQUQ7QUFBQSxjQUFnQixVQUFVd0IsUUFBMUI7QUFDRTtBQUFBO0FBQUEsZ0JBQUssT0FBTyxFQUFDOEIsU0FBUzlCLFdBQVcsR0FBWCxHQUFpQixDQUEzQixFQUFaO0FBQ0U7QUFBQyxtQ0FBRDtBQUFBO0FBQ0U7QUFBQTtBQUFBLG9CQUFLLFdBQVUsZUFBZjtBQUNHSSwrQkFBYXFCLEdBQWIsQ0FBaUI7QUFBQSwyQkFDaEIsOEJBQUMsZUFBRCxJQUFVLEtBQUtoQixHQUFmLEVBQW9CLEtBQUtBLEdBQXpCLEVBQThCLFFBQU8sTUFBckMsRUFBNEMsVUFBUyxLQUFyRCxHQURnQjtBQUFBLG1CQUFqQjtBQURILGlCQURGO0FBTUUsOENBQUMsZ0JBQUQsSUFBVyxRQUFPLE1BQWxCO0FBTkYsZUFERjtBQVNFO0FBQUE7QUFBQTtBQUFNLHFCQUFLc0IsY0FBTDtBQUFOO0FBVEYsYUFERjtBQVlHLGFBQUM5QixNQUFNZSxNQUFQLEdBQWdCO0FBQUE7QUFBQTtBQUNmO0FBQUMsMEJBQUQ7QUFBQTtBQUFhM0M7QUFBYixlQURlO0FBRWY7QUFBQTtBQUFBLGtCQUFNLFdBQVUsZ0JBQWhCO0FBQUE7QUFBQSxlQUZlO0FBR2Y7QUFBQyxzQ0FBRDtBQUFBLGtCQUFjLFVBQVUsS0FBS3NDLGVBQTdCO0FBQUE7QUFBQTtBQUhlLGFBQWhCLEdBTVEsSUFsQlg7QUFtQkU7QUFBQyw4QkFBRDtBQUFBO0FBQW1CcEM7QUFBbkI7QUFuQkY7QUFSRixTQURELEdBK0JHLElBeENOO0FBMENFO0FBQUMsb0JBQUQ7QUFBQTtBQUFhLG1DQUFhRCxVQUFiLEdBQTBCO0FBQXZDO0FBMUNGLE9BREY7QUE4Q0Q7OztFQTdIcUMwRCxnQixVQUMvQkMsWSxHQUFlO0FBQ3BCN0IsZ0JBQWNoQztBQURNLEMsU0FJZjhELFMsR0FBWTtBQUNqQmIsZ0JBQWNjLG9CQUFVQyxJQUFWLENBQWVDLFVBRFo7QUFFakJqQyxnQkFBYytCLG9CQUFVRyxPQUFWLENBQWtCSCxvQkFBVUksTUFBNUI7QUFGRyxDO2tCQUxBekMsVSIsImZpbGUiOiJmaWxlLXVwbG9hZC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBSZWFjdCwge0NvbXBvbmVudH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnc3R5bGVkLWNvbXBvbmVudHMnO1xuXG5pbXBvcnQgVXBsb2FkQnV0dG9uIGZyb20gJy4vdXBsb2FkLWJ1dHRvbic7XG5pbXBvcnQge0ZpbGVUeXBlLCBEcmFnTkRyb3B9IGZyb20gJ2NvbXBvbmVudHMvY29tbW9uL2ljb25zJztcbmltcG9ydCBMb2FkaW5nU3Bpbm5lciBmcm9tICdjb21wb25lbnRzL2NvbW1vbi9sb2FkaW5nLXNwaW5uZXInO1xuaW1wb3J0IHtpc0Nocm9tZX0gZnJvbSAndXRpbHMvdXRpbHMnO1xuXG5jb25zdCBGaWxlRHJvcCA9XG4gIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyByZXF1aXJlKCdyZWFjdC1maWxlLWRyb3AnKSA6IG51bGw7XG5cbi8vIEZpbGUudHlwZSBpcyBub3QgcmVsaWFibGUgaWYgdGhlIE9TIGRvZXMgbm90IGhhdmUgYVxuLy8gcmVnaXN0ZXJlZCBtYXBwaW5nIGZvciB0aGUgZXh0ZW5zaW9uLlxuLy8gTk9URTogU2hhcGVmaWxlcyBtdXN0IGJlIGluIGEgY29tcHJlc3NlZCBmb3JtYXQgc2luY2Vcbi8vIGl0IHJlcXVpcmVzIG11bHRpcGxlIGZpbGVzIHRvIGJlIHByZXNlbnQuXG5jb25zdCBkZWZhdWx0VmFsaWRGaWxlRXh0ID0gW1xuICAnY3N2JyxcbiAgLy8gJ3Rhci5neicsXG4gIC8vICd0Z3onLFxuICAvLyAnemlwJyxcbiAgLy8gJ2dweCcsXG4gIC8vICdrbWwnLFxuICAnanNvbicsXG4gICdnZW9qc29uJ1xuXTtcblxuY29uc3QgTUVTU0FHRSA9ICcgRHJhZyAmIERyb3AgWW91ciBGaWxlKHMpIEhlcmUnO1xuY29uc3QgQ0hST01FX01TRyA9XG4gICcqQ2hyb21lIHVzZXI6IExpbWl0IGZpbGUgc2l6ZSB0byAyNTBtYiwgaWYgbmVlZCB0byB1cGxvYWQgbGFyZ2VyIGZpbGUsIHRyeSBTYWZhcmknO1xuY29uc3QgRElTQ0xBSU1FUiA9ICcqS2VwbGVyLmdsIGlzIGEgY2xpZW50LXNpZGUgYXBwbGljYXRpb24gd2l0aCBubyBzZXJ2ZXIgYmFja2VuZC4gRGF0YSBsaXZlcyBvbmx5IG9uIHlvdXIgbWFjaGluZS9icm93c2VyLiAnICtcbiAgJ05vIGluZm9ybWF0aW9uIG9yIG1hcCBkYXRhIGlzIHNlbnQgdG8gYW55IHNlcnZlci4nO1xuY29uc3QgQ09ORklHX1VQTE9BRF9NRVNTQUdFID0gJ1VwbG9hZCBkYXRhIGZpbGVzIG9yIHVwbG9hZCBhIHNhdmVkIG1hcCB2aWEgcHJldmlvdXNseSBleHBvcnRlZCBzaW5nbGUgSnNvbiBvZiBib3RoIGNvbmZpZyBhbmQgZGF0YSc7XG5cbmNvbnN0IGZpbGVJY29uQ29sb3IgPSAnI0QzRDhFMCc7XG5cbmNvbnN0IFdhcm5pbmdNc2cgPSBzdHlsZWQuc3BhbmBcbiAgbWFyZ2luLXRvcDogMTBweDtcbiAgY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZXJyb3JDb2xvcn07XG5gO1xuXG5jb25zdCBQb3NpdGl2ZU1zZyA9IHN0eWxlZC5zcGFuYFxuICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5wcmltYXJ5QnRuQWN0QmdkfTtcbmA7XG5cbmNvbnN0IFN0eWxlZEZpbGVEcm9wID0gc3R5bGVkLmRpdmBcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgYm9yZGVyLXN0eWxlOiBkYXNoZWQ7XG4gIGJvcmRlci13aWR0aDogMXB4O1xuICBib3JkZXItY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuc3VidGV4dENvbG9yTFR9O1xuICBoZWlnaHQ6IDQxNHB4O1xuICBwYWRkaW5nLXRvcDogNjBweDtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICB3aWR0aDogMTAwJTtcblxuICAuZmlsZS11cGxvYWQtb3Ige1xuICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmxpbmtCdG5Db2xvcn07XG4gICAgcGFkZGluZy1yaWdodDogNHB4O1xuICB9XG5gO1xuXG5jb25zdCBNc2dXcmFwcGVyID0gc3R5bGVkLmRpdmBcbiAgY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubW9kYWxUaXRsZUNvbG9yfTtcbiAgZm9udC1zaXplOiAyMHB4O1xuICBoZWlnaHQ6IDM2cHg7XG5gO1xuXG5jb25zdCBTdHlsZWREcmFnTkRyb3BJY29uID0gc3R5bGVkLmRpdmBcbiAgY29sb3I6ICR7ZmlsZUljb25Db2xvcn07XG4gIG1hcmdpbi1ib3R0b206IDYwcHg7XG5cbiAgLmZpbGUtdHlwZS1yb3cge1xuICAgIG1hcmdpbi1ib3R0b206IDI2cHg7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlZEZpbGVVcGxvYWQgPSBzdHlsZWQuZGl2YFxuICAuZmlsdGVyLXVwbG9hZF9faW5wdXQge1xuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgICBoZWlnaHQ6IDA7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICB9XG5cbiAgLmZpbGUtZHJvcCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICB9XG5cbiAgLmZpbGUtdXBsb2FkX19tZXNzYWdlIHtcbiAgICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS50ZXh0Q29sb3JMVH07XG4gICAgZm9udC1zaXplOiAxNHB4O1xuICAgIG1hcmdpbi1ib3R0b206IDEycHg7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlZE1lc3NhZ2UgPSBzdHlsZWQuZGl2YFxuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbmA7XG5cbmNvbnN0IFN0eWxlZERpc2NsYWltZXIgPSBTdHlsZWRNZXNzYWdlLmV4dGVuZGBcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICBib3R0b206IDA7XG4gIHBhZGRpbmc6IDEwcHggMzBweDtcbmA7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpbGVVcGxvYWQgZXh0ZW5kcyBDb21wb25lbnQge1xuICBzdGF0aWMgZGVmYXVsdFByb3BzID0ge1xuICAgIHZhbGlkRmlsZUV4dDogZGVmYXVsdFZhbGlkRmlsZUV4dFxuICB9O1xuXG4gIHN0YXRpYyBwcm9wVHlwZXMgPSB7XG4gICAgb25GaWxlVXBsb2FkOiBQcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuICAgIHZhbGlkRmlsZUV4dDogUHJvcFR5cGVzLmFycmF5T2YoUHJvcFR5cGVzLnN0cmluZylcbiAgfTtcblxuICBzdGF0ZSA9IHtcbiAgICBkcmFnT3ZlcjogZmFsc2UsXG4gICAgZmlsZXM6IFtdLFxuICAgIGVycm9yRmlsZXM6IFtdXG4gIH07XG5cbiAgX2lzVmFsaWRGaWxlVHlwZSA9IGZpbGVuYW1lID0+IHtcbiAgICBjb25zdCB7dmFsaWRGaWxlRXh0fSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3QgZmlsZUV4dCA9IHZhbGlkRmlsZUV4dC5maW5kKGV4dCA9PiBmaWxlbmFtZS5lbmRzV2l0aChleHQpKTtcblxuICAgIHJldHVybiBCb29sZWFuKGZpbGVFeHQpO1xuICB9O1xuXG4gIF9oYW5kbGVGaWxlRHJvcCA9IChmaWxlcywgZSkgPT4ge1xuICAgIGlmIChlKSB7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cblxuICAgIGNvbnN0IG5leHRTdGF0ZSA9IHtmaWxlczogW10sIGVycm9yRmlsZXM6IFtdLCBkcmFnT3ZlcjogZmFsc2V9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGZpbGUgPSBmaWxlc1tpXTtcblxuICAgICAgaWYgKGZpbGUgJiYgdGhpcy5faXNWYWxpZEZpbGVUeXBlKGZpbGUubmFtZSkpIHtcbiAgICAgICAgbmV4dFN0YXRlLmZpbGVzLnB1c2goZmlsZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXh0U3RhdGUuZXJyb3JGaWxlcy5wdXNoKGZpbGUubmFtZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zZXRTdGF0ZShcbiAgICAgIG5leHRTdGF0ZSxcbiAgICAgICgpID0+XG4gICAgICAgIG5leHRTdGF0ZS5maWxlcy5sZW5ndGggPyB0aGlzLnByb3BzLm9uRmlsZVVwbG9hZChuZXh0U3RhdGUuZmlsZXMpIDogbnVsbFxuICAgICk7XG4gIH07XG5cbiAgX3RvZ2dsZURyYWdTdGF0ZSA9IG5ld1N0YXRlID0+IHtcbiAgICB0aGlzLnNldFN0YXRlKHtkcmFnT3ZlcjogbmV3U3RhdGV9KTtcbiAgfTtcblxuICBfcmVuZGVyTWVzc2FnZSgpIHtcbiAgICBjb25zdCB7ZXJyb3JGaWxlcywgZmlsZXN9ID0gdGhpcy5zdGF0ZTtcblxuICAgIGlmIChlcnJvckZpbGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgPFdhcm5pbmdNc2c+XG4gICAgICAgICAge2BGaWxlICR7ZXJyb3JGaWxlcy5qb2luKCcsICcpfSBpcyBub3Qgc3VwcG9ydGVkLmB9XG4gICAgICAgIDwvV2FybmluZ01zZz5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFmaWxlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICA8U3R5bGVkTWVzc2FnZSBjbGFzc05hbWU9XCJmaWxlLXVwbG9hZGVyX19tZXNzYWdlXCI+XG4gICAgICAgIDxkaXY+VXBsb2FkaW5nLi4uPC9kaXY+XG4gICAgICAgIDxQb3NpdGl2ZU1zZz5cbiAgICAgICAgICB7YCR7ZmlsZXMubWFwKGYgPT4gZi5uYW1lKS5qb2luKCcgYW5kICcpfS4uLmB9XG4gICAgICAgIDwvUG9zaXRpdmVNc2c+XG4gICAgICAgIDxMb2FkaW5nU3Bpbm5lciBzaXplPXsyMH0gLz5cbiAgICAgIDwvU3R5bGVkTWVzc2FnZT5cbiAgICApO1xuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHtkcmFnT3ZlciwgZmlsZXN9ID0gdGhpcy5zdGF0ZTtcbiAgICBjb25zdCB7dmFsaWRGaWxlRXh0fSA9IHRoaXMucHJvcHM7XG4gICAgcmV0dXJuIChcbiAgICAgIDxTdHlsZWRGaWxlVXBsb2FkXG4gICAgICAgIGNsYXNzTmFtZT1cImZpbGUtdXBsb2FkZXJcIlxuICAgICAgICBpbm5lclJlZj17Y21wID0+ICh0aGlzLmZyYW1lID0gY21wKX1cbiAgICAgID5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3NOYW1lPVwiZmlsdGVyLXVwbG9hZF9faW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJmaWxlXCJcbiAgICAgICAgICBvbkNoYW5nZT17dGhpcy5fb25DaGFuZ2V9XG4gICAgICAgIC8+XG4gICAgICAgIHtGaWxlRHJvcCA/IChcbiAgICAgICAgICA8RmlsZURyb3BcbiAgICAgICAgICAgIGZyYW1lPXt0aGlzLmZyYW1lfVxuICAgICAgICAgICAgdGFyZ2V0QWx3YXlzVmlzaWJsZVxuICAgICAgICAgICAgb25EcmFnT3Zlcj17KCkgPT4gdGhpcy5fdG9nZ2xlRHJhZ1N0YXRlKHRydWUpfVxuICAgICAgICAgICAgb25EcmFnTGVhdmU9eygpID0+IHRoaXMuX3RvZ2dsZURyYWdTdGF0ZShmYWxzZSl9XG4gICAgICAgICAgICBvbkRyb3A9e3RoaXMuX2hhbmRsZUZpbGVEcm9wfVxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmlsZS11cGxvYWRfX21lc3NhZ2VcIj57Q09ORklHX1VQTE9BRF9NRVNTQUdFfTwvZGl2PlxuICAgICAgICAgICAgPFN0eWxlZEZpbGVEcm9wIGRyYWdPdmVyPXtkcmFnT3Zlcn0+XG4gICAgICAgICAgICAgIDxkaXYgc3R5bGU9e3tvcGFjaXR5OiBkcmFnT3ZlciA/IDAuNSA6IDF9fT5cbiAgICAgICAgICAgICAgICA8U3R5bGVkRHJhZ05Ecm9wSWNvbj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmlsZS10eXBlLXJvd1wiPlxuICAgICAgICAgICAgICAgICAgICB7dmFsaWRGaWxlRXh0Lm1hcChleHQgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgIDxGaWxlVHlwZSBrZXk9e2V4dH0gZXh0PXtleHR9IGhlaWdodD1cIjUwcHhcIiBmb250U2l6ZT1cIjlweFwiLz5cbiAgICAgICAgICAgICAgICAgICAgKSl9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxEcmFnTkRyb3AgaGVpZ2h0PVwiNDRweFwiIC8+XG4gICAgICAgICAgICAgICAgPC9TdHlsZWREcmFnTkRyb3BJY29uPlxuICAgICAgICAgICAgICAgIDxkaXY+e3RoaXMuX3JlbmRlck1lc3NhZ2UoKX08L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIHshZmlsZXMubGVuZ3RoID8gPGRpdj5cbiAgICAgICAgICAgICAgICA8TXNnV3JhcHBlcj57TUVTU0FHRX08L01zZ1dyYXBwZXI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwiZmlsZS11cGxvYWQtb3JcIj5vcjwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8VXBsb2FkQnV0dG9uIG9uVXBsb2FkPXt0aGlzLl9oYW5kbGVGaWxlRHJvcH0+XG4gICAgICAgICAgICAgICAgICBicm93c2UgeW91ciBmaWxlc1xuICAgICAgICAgICAgICAgIDwvVXBsb2FkQnV0dG9uPlxuICAgICAgICAgICAgICA8L2Rpdj4gOiBudWxsfVxuICAgICAgICAgICAgICA8U3R5bGVkRGlzY2xhaW1lcj57RElTQ0xBSU1FUn08L1N0eWxlZERpc2NsYWltZXI+XG4gICAgICAgICAgICA8L1N0eWxlZEZpbGVEcm9wPlxuICAgICAgICAgIDwvRmlsZURyb3A+XG4gICAgICAgICkgOiBudWxsfVxuXG4gICAgICAgIDxXYXJuaW5nTXNnPntpc0Nocm9tZSgpID8gQ0hST01FX01TRyA6ICcnfTwvV2FybmluZ01zZz5cbiAgICAgIDwvU3R5bGVkRmlsZVVwbG9hZD5cbiAgICApO1xuICB9XG59XG4iXX0=
;