diff --git a/plugins/field-bitmap/README.html b/plugins/field-bitmap/README.html
index a680ee5ccb..69ab698a15 100644
--- a/plugins/field-bitmap/README.html
+++ b/plugins/field-bitmap/README.html
@@ -24,7 +24,7 @@
@blockly/field-bitmap Demo
A field that lets users input a pixel grid with their mouse.
- 4.1.0
+ 4.1.1
View code
View on npm
diff --git a/plugins/field-bitmap/build/test_bundle.js b/plugins/field-bitmap/build/test_bundle.js
index e9fa9c6e8d..3ca2f11387 100644
--- a/plugins/field-bitmap/build/test_bundle.js
+++ b/plugins/field-bitmap/build/test_bundle.js
@@ -437,7 +437,7 @@ eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPAC
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"DEFAULT_HEIGHT\": () => (/* binding */ DEFAULT_HEIGHT),\n/* harmony export */ \"DEFAULT_WIDTH\": () => (/* binding */ DEFAULT_WIDTH),\n/* harmony export */ \"FieldBitmap\": () => (/* binding */ FieldBitmap)\n/* harmony export */ });\n/* harmony import */ var blockly_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! blockly/core */ \"./node_modules/blockly/core-browser.js\");\n/* harmony import */ var blockly_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(blockly_core__WEBPACK_IMPORTED_MODULE_0__);\n/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_RANDOMIZE = 'Randomize';\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_CLEAR = 'Clear';\nconst DEFAULT_HEIGHT = 5;\nconst DEFAULT_WIDTH = 5;\nconst DEFAULT_PIXEL_SIZE = 15;\nconst DEFAULT_PIXEL_COLOURS = {\n empty: '#fff',\n filled: '#363d80',\n};\nconst DEFAULT_BUTTONS = {\n randomize: true,\n clear: true,\n};\n/**\n * Field for inputting a small bitmap image.\n * Includes a grid of clickable pixels that's exported as a bitmap.\n */\nclass FieldBitmap extends blockly_core__WEBPACK_IMPORTED_MODULE_0__.Field {\n /**\n * Constructor for the bitmap field.\n *\n * @param value 2D rectangular array of 1s and 0s.\n * @param validator A function that is called to validate.\n * @param config Config A map of options used to configure the field.\n */\n constructor(value, validator, config) {\n var _a, _b;\n super(value, validator, config);\n this.initialValue = null;\n /**\n * Array holding info needed to unbind events.\n * Used for disposing.\n */\n this.boundEvents = [];\n /** References to UI elements */\n this.editorPixels = null;\n this.blockDisplayPixels = null;\n /** Stateful variables */\n this.mouseIsDown = false;\n this.SERIALIZABLE = true;\n this.CURSOR = 'default';\n this.buttonOptions = Object.assign(Object.assign({}, DEFAULT_BUTTONS), config === null || config === void 0 ? void 0 : config.buttons);\n this.pixelColours = Object.assign(Object.assign({}, DEFAULT_PIXEL_COLOURS), config === null || config === void 0 ? void 0 : config.colours);\n // Configure value, height, and width\n const currentValue = this.getValue();\n if (currentValue !== null) {\n this.imgHeight = currentValue.length;\n this.imgWidth = currentValue[0].length || 0;\n }\n else {\n this.imgHeight = (_a = config === null || config === void 0 ? void 0 : config.height) !== null && _a !== void 0 ? _a : DEFAULT_HEIGHT;\n this.imgWidth = (_b = config === null || config === void 0 ? void 0 : config.width) !== null && _b !== void 0 ? _b : DEFAULT_WIDTH;\n // Set a default empty value\n this.setValue(this.getEmptyArray());\n }\n if (config === null || config === void 0 ? void 0 : config.fieldHeight) {\n this.pixelSize = config.fieldHeight / this.imgHeight;\n }\n else {\n this.pixelSize = DEFAULT_PIXEL_SIZE;\n }\n }\n /**\n * Constructs a FieldBitmap from a JSON arg object.\n *\n * @param options A JSON object with options.\n * @returns The new field instance.\n */\n static fromJson(options) {\n var _a;\n // `this` might be a subclass of FieldBitmap if that class doesn't override the static fromJson method.\n return new this((_a = options.value) !== null && _a !== void 0 ? _a : blockly_core__WEBPACK_IMPORTED_MODULE_0__.Field.SKIP_SETUP, undefined, options);\n }\n /**\n * Returns the width of the image in pixels.\n *\n * @returns The width in pixels.\n */\n getImageWidth() {\n return this.imgWidth;\n }\n /**\n * Returns the height of the image in pixels.\n *\n * @returns The height in pixels.\n */\n getImageHeight() {\n return this.imgHeight;\n }\n /**\n * Validates that a new value meets the requirements for a valid bitmap array.\n *\n * @param newValue The new value to be tested.\n * @returns The new value if it's valid, or null.\n */\n // eslint-disable-next-line\n doClassValidation_(newValue = undefined) {\n if (!newValue) {\n return null;\n }\n // Check if the new value is an array\n if (!Array.isArray(newValue)) {\n return null;\n }\n const newHeight = newValue.length;\n // The empty list is not an acceptable bitmap\n if (newHeight == 0) {\n return null;\n }\n // Check that the width matches the existing width of the image if it\n // already has a value.\n const newWidth = newValue[0].length;\n for (const row of newValue) {\n if (!Array.isArray(row)) {\n return null;\n }\n if (row.length !== newWidth) {\n return null;\n }\n }\n // Check if all contents of the arrays are either 0 or 1\n for (const row of newValue) {\n for (const cell of row) {\n if (cell !== 0 && cell !== 1) {\n return null;\n }\n }\n }\n return newValue;\n }\n /**\n * Called when a new value has been validated and is about to be set.\n *\n * @param newValue The value that's about to be set.\n */\n // eslint-disable-next-line\n doValueUpdate_(newValue) {\n super.doValueUpdate_(newValue);\n if (newValue) {\n this.imgHeight = newValue.length;\n this.imgWidth = newValue[0] ? newValue[0].length : 0;\n }\n }\n /**\n * Show the bitmap editor dialog.\n *\n * @param e Optional mouse event that triggered the field to open, or\n * undefined if triggered programmatically.\n */\n // eslint-disable-next-line\n showEditor_(e) {\n const editor = this.dropdownCreate();\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.getContentDiv().appendChild(editor);\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.showPositionedByField(this, this.dropdownDispose.bind(this));\n }\n /**\n * Updates the block display and editor dropdown when the field re-renders.\n */\n // eslint-disable-next-line\n render_() {\n super.render_();\n if (!this.getValue()) {\n return;\n }\n if (this.blockDisplayPixels) {\n this.forAllCells((r, c) => {\n const pixel = this.getPixel(r, c);\n if (this.blockDisplayPixels) {\n this.blockDisplayPixels[r][c].style.fill = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n if (this.editorPixels) {\n this.editorPixels[r][c].style.background = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n });\n }\n }\n /**\n * Determines whether the field is editable.\n *\n * @returns True since it is always editable.\n */\n updateEditable() {\n const editable = super.updateEditable();\n // Blockly.Field's implementation sets these classes as appropriate, but\n // since this field has no text they just mess up the rendering of the grid\n // lines.\n const svgRoot = this.getSvgRoot();\n if (svgRoot) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.removeClass(svgRoot, 'blocklyNonEditableText');\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.removeClass(svgRoot, 'blocklyEditableText');\n }\n return editable;\n }\n /**\n * Gets the rectangle built out of dimensions matching SVG's element.\n *\n * @returns The newly created rectangle of same size as the SVG element.\n */\n getScaledBBox() {\n var _a;\n const boundingBox = (_a = this.getSvgRoot()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();\n if (!boundingBox) {\n throw new Error('Tried to retrieve a bounding box without a rect');\n }\n return new blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.Rect(boundingBox.top, boundingBox.bottom, boundingBox.left, boundingBox.right);\n }\n /**\n * Creates the bitmap editor and add event listeners.\n *\n * @returns The newly created dropdown menu.\n */\n dropdownCreate() {\n const dropdownEditor = this.createElementWithClassname('div', 'dropdownEditor');\n const pixelContainer = this.createElementWithClassname('div', 'pixelContainer');\n dropdownEditor.appendChild(pixelContainer);\n this.bindEvent(dropdownEditor, 'mouseup', this.onMouseUp);\n this.bindEvent(dropdownEditor, 'mouseleave', this.onMouseUp);\n this.bindEvent(dropdownEditor, 'dragstart', (e) => {\n e.preventDefault();\n });\n this.editorPixels = [];\n for (let r = 0; r < this.imgHeight; r++) {\n this.editorPixels.push([]);\n const rowDiv = this.createElementWithClassname('div', 'pixelRow');\n for (let c = 0; c < this.imgWidth; c++) {\n // Add the button to the UI and save a reference to it\n const button = this.createElementWithClassname('div', 'pixelButton');\n this.editorPixels[r].push(button);\n rowDiv.appendChild(button);\n // Load the current pixel colour\n const isOn = this.getPixel(r, c);\n button.style.background = isOn\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n // Handle clicking a pixel\n this.bindEvent(button, 'mousedown', () => {\n this.onMouseDownInPixel(r, c);\n return true;\n });\n // Handle dragging into a pixel when mouse is down\n this.bindEvent(button, 'mouseenter', () => {\n this.onMouseEnterPixel(r, c);\n });\n }\n pixelContainer.appendChild(rowDiv);\n }\n // Add control buttons below the pixel grid\n if (this.buttonOptions.randomize) {\n this.addControlButton(dropdownEditor, blockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_RANDOMIZE, this.randomizePixels);\n }\n if (this.buttonOptions.clear) {\n this.addControlButton(dropdownEditor, blockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_CLEAR, this.clearPixels);\n }\n if (this.blockDisplayPixels) {\n this.forAllCells((r, c) => {\n const pixel = this.getPixel(r, c);\n if (this.editorPixels) {\n this.editorPixels[r][c].style.background = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n });\n }\n // Store the initial value at the start of the edit.\n this.initialValue = this.getValue();\n return dropdownEditor;\n }\n /**\n * Initializes the on-block display.\n */\n initView() {\n this.blockDisplayPixels = [];\n for (let r = 0; r < this.imgHeight; r++) {\n const row = [];\n for (let c = 0; c < this.imgWidth; c++) {\n const square = blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.createSvgElement('rect', {\n x: c * this.pixelSize,\n y: r * this.pixelSize,\n width: this.pixelSize,\n height: this.pixelSize,\n fill: this.pixelColours.empty,\n fill_opacity: 1, // eslint-disable-line\n }, this.getSvgRoot());\n row.push(square);\n }\n this.blockDisplayPixels.push(row);\n }\n }\n /**\n * Updates the size of the block based on the size of the underlying image.\n */\n // eslint-disable-next-line\n updateSize_() {\n {\n const newWidth = this.pixelSize * this.imgWidth;\n const newHeight = this.pixelSize * this.imgHeight;\n if (this.borderRect_) {\n this.borderRect_.setAttribute('width', String(newWidth));\n this.borderRect_.setAttribute('height', String(newHeight));\n }\n this.size_.width = newWidth;\n this.size_.height = newHeight;\n }\n }\n /**\n * Create control button.\n *\n * @param parent Parent HTML element to which control button will be added.\n * @param buttonText Text of the control button.\n * @param onClick Callback that will be attached to the control button.\n */\n addControlButton(parent, buttonText, onClick) {\n const button = this.createElementWithClassname('button', 'controlButton');\n button.innerText = buttonText;\n parent.appendChild(button);\n this.bindEvent(button, 'click', onClick);\n }\n /**\n * Disposes of events belonging to the bitmap editor.\n */\n dropdownDispose() {\n if (this.getSourceBlock() &&\n this.initialValue !== null &&\n this.initialValue !== this.getValue()) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.fire(new (blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.get(blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.BLOCK_CHANGE))(this.sourceBlock_, 'field', this.name || null, this.initialValue, this.getValue()));\n }\n for (const event of this.boundEvents) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.browserEvents.unbind(event);\n }\n this.boundEvents.length = 0;\n this.editorPixels = null;\n // Set this.initialValue back to null.\n this.initialValue = null;\n }\n /**\n * Constructs an array of zeros with the specified width and height.\n *\n * @returns The new value.\n */\n getEmptyArray() {\n const newVal = [];\n for (let r = 0; r < this.imgHeight; r++) {\n newVal.push([]);\n for (let c = 0; c < this.imgWidth; c++) {\n newVal[r].push(0);\n }\n }\n return newVal;\n }\n /**\n * Called when a mousedown event occurs within the bounds of a pixel.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n */\n onMouseDownInPixel(r, c) {\n // Toggle that pixel to the opposite of its value\n const newPixelValue = 1 - this.getPixel(r, c);\n this.setPixel(r, c, newPixelValue);\n this.mouseIsDown = true;\n this.valToPaintWith = newPixelValue;\n }\n /**\n * Called when the mouse drags over a pixel in the editor.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n */\n onMouseEnterPixel(r, c) {\n if (!this.mouseIsDown) {\n return;\n }\n if (this.valToPaintWith !== undefined &&\n this.getPixel(r, c) !== this.valToPaintWith) {\n this.setPixel(r, c, this.valToPaintWith);\n }\n }\n /**\n * Resets mouse state (e.g. After either a mouseup event or if the mouse\n * leaves the editor area).\n */\n onMouseUp() {\n this.mouseIsDown = false;\n this.valToPaintWith = undefined;\n }\n /**\n * Sets all the pixels in the image to a random value.\n */\n randomizePixels() {\n const getRandBinary = () => Math.floor(Math.random() * 2);\n this.forAllCells((r, c) => {\n this.setPixel(r, c, getRandBinary());\n });\n }\n /**\n * Sets all the pixels to 0.\n */\n clearPixels() {\n const cleared = this.getEmptyArray();\n this.fireIntermediateChangeEvent(cleared);\n this.setValue(cleared, false);\n }\n /**\n * Sets the value of a particular pixel.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n * @param newValue Value of the pixel.\n */\n setPixel(r, c, newValue) {\n const newGrid = JSON.parse(JSON.stringify(this.getValue()));\n newGrid[r][c] = newValue;\n this.fireIntermediateChangeEvent(newGrid);\n this.setValue(newGrid, false);\n }\n getPixel(row, column) {\n const value = this.getValue();\n if (!value) {\n throw new Error('Attempted to retrieve a pixel value when no value is set');\n }\n return value[row][column];\n }\n /**\n * Calls a given function for all cells in the image, with the cell\n * coordinates as the arguments.\n *\n * @param func A function to be applied.\n */\n forAllCells(func) {\n for (let r = 0; r < this.imgHeight; r++) {\n for (let c = 0; c < this.imgWidth; c++) {\n func(r, c);\n }\n }\n }\n /**\n * Creates a new element with the specified type and class.\n *\n * @param elementType Type of html element.\n * @param className ClassName of html element.\n * @returns The created element.\n */\n createElementWithClassname(elementType, className) {\n const newElt = document.createElement(elementType);\n newElt.className = className;\n return newElt;\n }\n /**\n * Binds an event listener to the specified element.\n *\n * @param element Specified element.\n * @param eventName Name of the event to bind.\n * @param callback Function to be called on specified event.\n */\n bindEvent(element, eventName, callback) {\n this.boundEvents.push(blockly_core__WEBPACK_IMPORTED_MODULE_0__.browserEvents.conditionalBind(element, eventName, this, callback));\n }\n fireIntermediateChangeEvent(newValue) {\n if (this.getSourceBlock()) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.fire(new (blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.get(blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.BLOCK_FIELD_INTERMEDIATE_CHANGE))(this.getSourceBlock(), this.name || null, this.getValue(), newValue));\n }\n }\n}\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.fieldRegistry.register('field_bitmap', FieldBitmap);\n/**\n * CSS for bitmap field.\n */\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Css.register(`\n.dropdownEditor {\n align-items: center;\n flex-direction: column;\n display: flex;\n justify-content: center;\n margin-bottom: 20px;\n}\n.pixelContainer {\n margin: 20px;\n}\n.pixelRow {\n display: flex;\n flex-direction: row;\n padding: 0;\n margin: 0;\n height: ${DEFAULT_PIXEL_SIZE}\n}\n.pixelButton {\n width: ${DEFAULT_PIXEL_SIZE}px;\n height: ${DEFAULT_PIXEL_SIZE}px;\n border: 1px solid #000;\n}\n.pixelDisplay {\n white-space:pre-wrap;\n}\n.controlButton {\n margin: 5px 0;\n}\n`);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Qjs7Ozs7Ozs7O0NBUzdCLENBQUMsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL0BibG9ja2x5L2ZpZWxkLWJpdG1hcC8uL3NyYy9maWVsZC1iaXRtYXAudHM/YWM2MyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCAqIGFzIEJsb2NrbHkgZnJvbSAnYmxvY2tseS9jb3JlJztcblxuQmxvY2tseS5Nc2dbJ0JVVFRPTl9MQUJFTF9SQU5ET01JWkUnXSA9ICdSYW5kb21pemUnO1xuQmxvY2tseS5Nc2dbJ0JVVFRPTl9MQUJFTF9DTEVBUiddID0gJ0NsZWFyJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfSEVJR0hUID0gNTtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1dJRFRIID0gNTtcbmNvbnN0IERFRkFVTFRfUElYRUxfU0laRSA9IDE1O1xuY29uc3QgREVGQVVMVF9QSVhFTF9DT0xPVVJTOiBQaXhlbENvbG91cnMgPSB7XG4gIGVtcHR5OiAnI2ZmZicsXG4gIGZpbGxlZDogJyMzNjNkODAnLFxufTtcbmNvbnN0IERFRkFVTFRfQlVUVE9OUzogQnV0dG9ucyA9IHtcbiAgcmFuZG9taXplOiB0cnVlLFxuICBjbGVhcjogdHJ1ZSxcbn07XG4vKipcbiAqIEZpZWxkIGZvciBpbnB1dHRpbmcgYSBzbWFsbCBiaXRtYXAgaW1hZ2UuXG4gKiBJbmNsdWRlcyBhIGdyaWQgb2YgY2xpY2thYmxlIHBpeGVscyB0aGF0J3MgZXhwb3J0ZWQgYXMgYSBiaXRtYXAuXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWVsZEJpdG1hcCBleHRlbmRzIEJsb2NrbHkuRmllbGQ8bnVtYmVyW11bXT4ge1xuICBwcml2YXRlIGluaXRpYWxWYWx1ZTogbnVtYmVyW11bXSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGltZ0hlaWdodDogbnVtYmVyO1xuICBwcml2YXRlIGltZ1dpZHRoOiBudW1iZXI7XG4gIC8qKlxuICAgKiBBcnJheSBob2xkaW5nIGluZm8gbmVlZGVkIHRvIHVuYmluZCBldmVudHMuXG4gICAqIFVzZWQgZm9yIGRpc3Bvc2luZy5cbiAgICovXG4gIHByaXZhdGUgYm91bmRFdmVudHM6IEJsb2NrbHkuYnJvd3NlckV2ZW50cy5EYXRhW10gPSBbXTtcbiAgLyoqIFJlZmVyZW5jZXMgdG8gVUkgZWxlbWVudHMgKi9cbiAgcHJpdmF0ZSBlZGl0b3JQaXhlbHM6IEhUTUxFbGVtZW50W11bXSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJsb2NrRGlzcGxheVBpeGVsczogU1ZHRWxlbWVudFtdW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIFN0YXRlZnVsIHZhcmlhYmxlcyAqL1xuICBwcml2YXRlIG1vdXNlSXNEb3duID0gZmFsc2U7XG4gIHByaXZhdGUgdmFsVG9QYWludFdpdGg/OiBudW1iZXI7XG4gIGJ1dHRvbk9wdGlvbnM6IEJ1dHRvbnM7XG4gIHBpeGVsU2l6ZTogbnVtYmVyO1xuICBwaXhlbENvbG91cnM6IHtlbXB0eTogc3RyaW5nOyBmaWxsZWQ6IHN0cmluZ307XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yIGZvciB0aGUgYml0bWFwIGZpZWxkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgMkQgcmVjdGFuZ3VsYXIgYXJyYXkgb2YgMXMgYW5kIDBzLlxuICAgKiBAcGFyYW0gdmFsaWRhdG9yIEEgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgdG8gdmFsaWRhdGUuXG4gICAqIEBwYXJhbSBjb25maWcgQ29uZmlnIEEgbWFwIG9mIG9wdGlvbnMgdXNlZCB0byBjb25maWd1cmUgdGhlIGZpZWxkLlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgdmFsdWU6IG51bWJlcltdW10gfCB0eXBlb2YgQmxvY2tseS5GaWVsZC5TS0lQX1NFVFVQLFxuICAgIHZhbGlkYXRvcj86IEJsb2NrbHkuRmllbGRWYWxpZGF0b3I8bnVtYmVyW11bXT4sXG4gICAgY29uZmlnPzogRmllbGRCaXRtYXBGcm9tSnNvbkNvbmZpZyxcbiAgKSB7XG4gICAgc3VwZXIodmFsdWUsIHZhbGlkYXRvciwgY29uZmlnKTtcblxuICAgIHRoaXMuU0VSSUFMSVpBQkxFID0gdHJ1ZTtcbiAgICB0aGlzLkNVUlNPUiA9ICdkZWZhdWx0JztcbiAgICB0aGlzLmJ1dHRvbk9wdGlvbnMgPSB7Li4uREVGQVVMVF9CVVRUT05TLCAuLi5jb25maWc/LmJ1dHRvbnN9O1xuICAgIHRoaXMucGl4ZWxDb2xvdXJzID0gey4uLkRFRkFVTFRfUElYRUxfQ09MT1VSUywgLi4uY29uZmlnPy5jb2xvdXJzfTtcblxuICAgIC8vIENvbmZpZ3VyZSB2YWx1ZSwgaGVpZ2h0LCBhbmQgd2lkdGhcbiAgICBjb25zdCBjdXJyZW50VmFsdWUgPSB0aGlzLmdldFZhbHVlKCk7XG4gICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5pbWdIZWlnaHQgPSBjdXJyZW50VmFsdWUubGVuZ3RoO1xuICAgICAgdGhpcy5pbWdXaWR0aCA9IGN1cnJlbnRWYWx1ZVswXS5sZW5ndGggfHwgMDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pbWdIZWlnaHQgPSBjb25maWc/LmhlaWdodCA/PyBERUZBVUxUX0hFSUdIVDtcbiAgICAgIHRoaXMuaW1nV2lkdGggPSBjb25maWc/LndpZHRoID8/IERFRkFVTFRfV0lEVEg7XG4gICAgICAvLyBTZXQgYSBkZWZhdWx0IGVtcHR5IHZhbHVlXG4gICAgICB0aGlzLnNldFZhbHVlKHRoaXMuZ2V0RW1wdHlBcnJheSgpKTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZz8uZmllbGRIZWlnaHQpIHtcbiAgICAgIHRoaXMucGl4ZWxTaXplID0gY29uZmlnLmZpZWxkSGVpZ2h0IC8gdGhpcy5pbWdIZWlnaHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGl4ZWxTaXplID0gREVGQVVMVF9QSVhFTF9TSVpFO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgRmllbGRCaXRtYXAgZnJvbSBhIEpTT04gYXJnIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgQSBKU09OIG9iamVjdCB3aXRoIG9wdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoZSBuZXcgZmllbGQgaW5zdGFuY2UuXG4gICAqL1xuICBzdGF0aWMgZnJvbUpzb24ob3B0aW9uczogRmllbGRCaXRtYXBGcm9tSnNvbkNvbmZpZykge1xuICAgIC8vIGB0aGlzYCBtaWdodCBiZSBhIHN1YmNsYXNzIG9mIEZpZWxkQml0bWFwIGlmIHRoYXQgY2xhc3MgZG9lc24ndCBvdmVycmlkZSB0aGUgc3RhdGljIGZyb21Kc29uIG1ldGhvZC5cbiAgICByZXR1cm4gbmV3IHRoaXMoXG4gICAgICBvcHRpb25zLnZhbHVlID8/IEJsb2NrbHkuRmllbGQuU0tJUF9TRVRVUCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIG9wdGlvbnMsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBvZiB0aGUgaW1hZ2UgaW4gcGl4ZWxzLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgd2lkdGggaW4gcGl4ZWxzLlxuICAgKi9cbiAgZ2V0SW1hZ2VXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpcy5pbWdXaWR0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBoZWlnaHQgb2YgdGhlIGltYWdlIGluIHBpeGVscy5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGhlaWdodCBpbiBwaXhlbHMuXG4gICAqL1xuICBnZXRJbWFnZUhlaWdodCgpIHtcbiAgICByZXR1cm4gdGhpcy5pbWdIZWlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgYSBuZXcgdmFsdWUgbWVldHMgdGhlIHJlcXVpcmVtZW50cyBmb3IgYSB2YWxpZCBiaXRtYXAgYXJyYXkuXG4gICAqXG4gICAqIEBwYXJhbSBuZXdWYWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGJlIHRlc3RlZC5cbiAgICogQHJldHVybnMgVGhlIG5ldyB2YWx1ZSBpZiBpdCdzIHZhbGlkLCBvciBudWxsLlxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gIHByb3RlY3RlZCBvdmVycmlkZSBkb0NsYXNzVmFsaWRhdGlvbl8obmV3VmFsdWU6IHVua25vd24gPSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIW5ld1ZhbHVlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gQ2hlY2sgaWYgdGhlIG5ldyB2YWx1ZSBpcyBhbiBhcnJheVxuICAgIGlmICghQXJyYXkuaXNBcnJheShuZXdWYWx1ZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBuZXdIZWlnaHQgPSBuZXdWYWx1ZS5sZW5ndGg7XG4gICAgLy8gVGhlIGVtcHR5IGxpc3QgaXMgbm90IGFuIGFjY2VwdGFibGUgYml0bWFwXG4gICAgaWYgKG5ld0hlaWdodCA9PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBDaGVjayB0aGF0IHRoZSB3aWR0aCBtYXRjaGVzIHRoZSBleGlzdGluZyB3aWR0aCBvZiB0aGUgaW1hZ2UgaWYgaXRcbiAgICAvLyBhbHJlYWR5IGhhcyBhIHZhbHVlLlxuICAgIGNvbnN0IG5ld1dpZHRoID0gbmV3VmFsdWVbMF0ubGVuZ3RoO1xuICAgIGZvciAoY29uc3Qgcm93IG9mIG5ld1ZhbHVlKSB7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkocm93KSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChyb3cubGVuZ3RoICE9PSBuZXdXaWR0aCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiBhbGwgY29udGVudHMgb2YgdGhlIGFycmF5cyBhcmUgZWl0aGVyIDAgb3IgMVxuICAgIGZvciAoY29uc3Qgcm93IG9mIG5ld1ZhbHVlKSB7XG4gICAgICBmb3IgKGNvbnN0IGNlbGwgb2Ygcm93KSB7XG4gICAgICAgIGlmIChjZWxsICE9PSAwICYmIGNlbGwgIT09IDEpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3VmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gYSBuZXcgdmFsdWUgaGFzIGJlZW4gdmFsaWRhdGVkIGFuZCBpcyBhYm91dCB0byBiZSBzZXQuXG4gICAqXG4gICAqIEBwYXJhbSBuZXdWYWx1ZSBUaGUgdmFsdWUgdGhhdCdzIGFib3V0IHRvIGJlIHNldC5cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZG9WYWx1ZVVwZGF0ZV8obmV3VmFsdWU6IG51bWJlcltdW10pIHtcbiAgICBzdXBlci5kb1ZhbHVlVXBkYXRlXyhuZXdWYWx1ZSk7XG4gICAgaWYgKG5ld1ZhbHVlKSB7XG4gICAgICB0aGlzLmltZ0hlaWdodCA9IG5ld1ZhbHVlLmxlbmd0aDtcbiAgICAgIHRoaXMuaW1nV2lkdGggPSBuZXdWYWx1ZVswXSA/IG5ld1ZhbHVlWzBdLmxlbmd0aCA6IDA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgdGhlIGJpdG1hcCBlZGl0b3IgZGlhbG9nLlxuICAgKlxuICAgKiBAcGFyYW0gZSBPcHRpb25hbCBtb3VzZSBldmVudCB0aGF0IHRyaWdnZXJlZCB0aGUgZmllbGQgdG8gb3Blbiwgb3JcbiAgICogICAgdW5kZWZpbmVkIGlmIHRyaWdnZXJlZCBwcm9ncmFtbWF0aWNhbGx5LlxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gIHByb3RlY3RlZCBvdmVycmlkZSBzaG93RWRpdG9yXyhlPzogRXZlbnQpIHtcbiAgICBjb25zdCBlZGl0b3IgPSB0aGlzLmRyb3Bkb3duQ3JlYXRlKCk7XG4gICAgQmxvY2tseS5Ecm9wRG93bkRpdi5nZXRDb250ZW50RGl2KCkuYXBwZW5kQ2hpbGQoZWRpdG9yKTtcbiAgICBCbG9ja2x5LkRyb3BEb3duRGl2LnNob3dQb3NpdGlvbmVkQnlGaWVsZChcbiAgICAgIHRoaXMsXG4gICAgICB0aGlzLmRyb3Bkb3duRGlzcG9zZS5iaW5kKHRoaXMpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgYmxvY2sgZGlzcGxheSBhbmQgZWRpdG9yIGRyb3Bkb3duIHdoZW4gdGhlIGZpZWxkIHJlLXJlbmRlcnMuXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHJlbmRlcl8oKSB7XG4gICAgc3VwZXIucmVuZGVyXygpO1xuXG4gICAgaWYgKCF0aGlzLmdldFZhbHVlKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5ibG9ja0Rpc3BsYXlQaXhlbHMpIHtcbiAgICAgIHRoaXMuZm9yQWxsQ2VsbHMoKHIsIGMpID0+IHtcbiAgICAgICAgY29uc3QgcGl4ZWwgPSB0aGlzLmdldFBpeGVsKHIsIGMpO1xuXG4gICAgICAgIGlmICh0aGlzLmJsb2NrRGlzcGxheVBpeGVscykge1xuICAgICAgICAgIHRoaXMuYmxvY2tEaXNwbGF5UGl4ZWxzW3JdW2NdLnN0eWxlLmZpbGwgPSBwaXhlbFxuICAgICAgICAgICAgPyB0aGlzLnBpeGVsQ29sb3Vycy5maWxsZWRcbiAgICAgICAgICAgIDogdGhpcy5waXhlbENvbG91cnMuZW1wdHk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZWRpdG9yUGl4ZWxzKSB7XG4gICAgICAgICAgdGhpcy5lZGl0b3JQaXhlbHNbcl1bY10uc3R5bGUuYmFja2dyb3VuZCA9IHBpeGVsXG4gICAgICAgICAgICA/IHRoaXMucGl4ZWxDb2xvdXJzLmZpbGxlZFxuICAgICAgICAgICAgOiB0aGlzLnBpeGVsQ29sb3Vycy5lbXB0eTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciB0aGUgZmllbGQgaXMgZWRpdGFibGUuXG4gICAqXG4gICAqIEByZXR1cm5zIFRydWUgc2luY2UgaXQgaXMgYWx3YXlzIGVkaXRhYmxlLlxuICAgKi9cbiAgb3ZlcnJpZGUgdXBkYXRlRWRpdGFibGUoKSB7XG4gICAgY29uc3QgZWRpdGFibGUgPSBzdXBlci51cGRhdGVFZGl0YWJsZSgpO1xuICAgIC8vIEJsb2NrbHkuRmllbGQncyBpbXBsZW1lbnRhdGlvbiBzZXRzIHRoZXNlIGNsYXNzZXMgYXMgYXBwcm9wcmlhdGUsIGJ1dFxuICAgIC8vIHNpbmNlIHRoaXMgZmllbGQgaGFzIG5vIHRleHQgdGhleSBqdXN0IG1lc3MgdXAgdGhlIHJlbmRlcmluZyBvZiB0aGUgZ3JpZFxuICAgIC8vIGxpbmVzLlxuICAgIGNvbnN0IHN2Z1Jvb3QgPSB0aGlzLmdldFN2Z1Jvb3QoKTtcbiAgICBpZiAoc3ZnUm9vdCkge1xuICAgICAgQmxvY2tseS51dGlscy5kb20ucmVtb3ZlQ2xhc3Moc3ZnUm9vdCwgJ2Jsb2NrbHlOb25FZGl0YWJsZVRleHQnKTtcbiAgICAgIEJsb2NrbHkudXRpbHMuZG9tLnJlbW92ZUNsYXNzKHN2Z1Jvb3QsICdibG9ja2x5RWRpdGFibGVUZXh0Jyk7XG4gICAgfVxuICAgIHJldHVybiBlZGl0YWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSByZWN0YW5nbGUgYnVpbHQgb3V0IG9mIGRpbWVuc2lvbnMgbWF0Y2hpbmcgU1ZHJ3MgPGc+IGVsZW1lbnQuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBuZXdseSBjcmVhdGVkIHJlY3RhbmdsZSBvZiBzYW1lIHNpemUgYXMgdGhlIFNWRyBlbGVtZW50LlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0U2NhbGVkQkJveCgpIHtcbiAgICBjb25zdCBib3VuZGluZ0JveCA9IHRoaXMuZ2V0U3ZnUm9vdCgpPy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBpZiAoIWJvdW5kaW5nQm94KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyaWVkIHRvIHJldHJpZXZlIGEgYm91bmRpbmcgYm94IHdpdGhvdXQgYSByZWN0Jyk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgQmxvY2tseS51dGlscy5SZWN0KFxuICAgICAgYm91bmRpbmdCb3gudG9wLFxuICAgICAgYm91bmRpbmdCb3guYm90dG9tLFxuICAgICAgYm91bmRpbmdCb3gubGVmdCxcbiAgICAgIGJvdW5kaW5nQm94LnJpZ2h0LFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgYml0bWFwIGVkaXRvciBhbmQgYWRkIGV2ZW50IGxpc3RlbmVycy5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgZHJvcGRvd24gbWVudS5cbiAgICovXG4gIHByaXZhdGUgZHJvcGRvd25DcmVhdGUoKSB7XG4gICAgY29uc3QgZHJvcGRvd25FZGl0b3IgPSB0aGlzLmNyZWF0ZUVsZW1lbnRXaXRoQ2xhc3NuYW1lKFxuICAgICAgJ2RpdicsXG4gICAgICAnZHJvcGRvd25FZGl0b3InLFxuICAgICk7XG4gICAgY29uc3QgcGl4ZWxDb250YWluZXIgPSB0aGlzLmNyZWF0ZUVsZW1lbnRXaXRoQ2xhc3NuYW1lKFxuICAgICAgJ2RpdicsXG4gICAgICAncGl4ZWxDb250YWluZXInLFxuICAgICk7XG4gICAgZHJvcGRvd25FZGl0b3IuYXBwZW5kQ2hpbGQocGl4ZWxDb250YWluZXIpO1xuXG4gICAgdGhpcy5iaW5kRXZlbnQoZHJvcGRvd25FZGl0b3IsICdtb3VzZXVwJywgdGhpcy5vbk1vdXNlVXApO1xuICAgIHRoaXMuYmluZEV2ZW50KGRyb3Bkb3duRWRpdG9yLCAnbW91c2VsZWF2ZScsIHRoaXMub25Nb3VzZVVwKTtcbiAgICB0aGlzLmJpbmRFdmVudChkcm9wZG93bkVkaXRvciwgJ2RyYWdzdGFydCcsIChlOiBFdmVudCkgPT4ge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5lZGl0b3JQaXhlbHMgPSBbXTtcbiAgICBmb3IgKGxldCByID0gMDsgciA8IHRoaXMuaW1nSGVpZ2h0OyByKyspIHtcbiAgICAgIHRoaXMuZWRpdG9yUGl4ZWxzLnB1c2goW10pO1xuICAgICAgY29uc3Qgcm93RGl2ID0gdGhpcy5jcmVhdGVFbGVtZW50V2l0aENsYXNzbmFtZSgnZGl2JywgJ3BpeGVsUm93Jyk7XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IHRoaXMuaW1nV2lkdGg7IGMrKykge1xuICAgICAgICAvLyBBZGQgdGhlIGJ1dHRvbiB0byB0aGUgVUkgYW5kIHNhdmUgYSByZWZlcmVuY2UgdG8gaXRcbiAgICAgICAgY29uc3QgYnV0dG9uID0gdGhpcy5jcmVhdGVFbGVtZW50V2l0aENsYXNzbmFtZSgnZGl2JywgJ3BpeGVsQnV0dG9uJyk7XG4gICAgICAgIHRoaXMuZWRpdG9yUGl4ZWxzW3JdLnB1c2goYnV0dG9uKTtcbiAgICAgICAgcm93RGl2LmFwcGVuZENoaWxkKGJ1dHRvbik7XG5cbiAgICAgICAgLy8gTG9hZCB0aGUgY3VycmVudCBwaXhlbCBjb2xvdXJcbiAgICAgICAgY29uc3QgaXNPbiA9IHRoaXMuZ2V0UGl4ZWwociwgYyk7XG4gICAgICAgIGJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kID0gaXNPblxuICAgICAgICAgID8gdGhpcy5waXhlbENvbG91cnMuZmlsbGVkXG4gICAgICAgICAgOiB0aGlzLnBpeGVsQ29sb3Vycy5lbXB0eTtcblxuICAgICAgICAvLyBIYW5kbGUgY2xpY2tpbmcgYSBwaXhlbFxuICAgICAgICB0aGlzLmJpbmRFdmVudChidXR0b24sICdtb3VzZWRvd24nLCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5vbk1vdXNlRG93bkluUGl4ZWwociwgYyk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEhhbmRsZSBkcmFnZ2luZyBpbnRvIGEgcGl4ZWwgd2hlbiBtb3VzZSBpcyBkb3duXG4gICAgICAgIHRoaXMuYmluZEV2ZW50KGJ1dHRvbiwgJ21vdXNlZW50ZXInLCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5vbk1vdXNlRW50ZXJQaXhlbChyLCBjKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBwaXhlbENvbnRhaW5lci5hcHBlbmRDaGlsZChyb3dEaXYpO1xuICAgIH1cblxuICAgIC8vIEFkZCBjb250cm9sIGJ1dHRvbnMgYmVsb3cgdGhlIHBpeGVsIGdyaWRcbiAgICBpZiAodGhpcy5idXR0b25PcHRpb25zLnJhbmRvbWl6ZSkge1xuICAgICAgdGhpcy5hZGRDb250cm9sQnV0dG9uKFxuICAgICAgICBkcm9wZG93bkVkaXRvcixcbiAgICAgICAgQmxvY2tseS5Nc2dbJ0JVVFRPTl9MQUJFTF9SQU5ET01JWkUnXSxcbiAgICAgICAgdGhpcy5yYW5kb21pemVQaXhlbHMsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodGhpcy5idXR0b25PcHRpb25zLmNsZWFyKSB7XG4gICAgICB0aGlzLmFkZENvbnRyb2xCdXR0b24oXG4gICAgICAgIGRyb3Bkb3duRWRpdG9yLFxuICAgICAgICBCbG9ja2x5Lk1zZ1snQlVUVE9OX0xBQkVMX0NMRUFSJ10sXG4gICAgICAgIHRoaXMuY2xlYXJQaXhlbHMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmJsb2NrRGlzcGxheVBpeGVscykge1xuICAgICAgdGhpcy5mb3JBbGxDZWxscygociwgYykgPT4ge1xuICAgICAgICBjb25zdCBwaXhlbCA9IHRoaXMuZ2V0UGl4ZWwociwgYyk7XG4gICAgICAgIGlmICh0aGlzLmVkaXRvclBpeGVscykge1xuICAgICAgICAgIHRoaXMuZWRpdG9yUGl4ZWxzW3JdW2NdLnN0eWxlLmJhY2tncm91bmQgPSBwaXhlbFxuICAgICAgICAgICAgPyB0aGlzLnBpeGVsQ29sb3Vycy5maWxsZWRcbiAgICAgICAgICAgIDogdGhpcy5waXhlbENvbG91cnMuZW1wdHk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIFN0b3JlIHRoZSBpbml0aWFsIHZhbHVlIGF0IHRoZSBzdGFydCBvZiB0aGUgZWRpdC5cbiAgICB0aGlzLmluaXRpYWxWYWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcblxuICAgIHJldHVybiBkcm9wZG93bkVkaXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyB0aGUgb24tYmxvY2sgZGlzcGxheS5cbiAgICovXG4gIG92ZXJyaWRlIGluaXRWaWV3KCkge1xuICAgIHRoaXMuYmxvY2tEaXNwbGF5UGl4ZWxzID0gW107XG4gICAgZm9yIChsZXQgciA9IDA7IHIgPCB0aGlzLmltZ0hlaWdodDsgcisrKSB7XG4gICAgICBjb25zdCByb3cgPSBbXTtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgdGhpcy5pbWdXaWR0aDsgYysrKSB7XG4gICAgICAgIGNvbnN0IHNxdWFyZSA9IEJsb2NrbHkudXRpbHMuZG9tLmNyZWF0ZVN2Z0VsZW1lbnQoXG4gICAgICAgICAgJ3JlY3QnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHg6IGMgKiB0aGlzLnBpeGVsU2l6ZSxcbiAgICAgICAgICAgIHk6IHIgKiB0aGlzLnBpeGVsU2l6ZSxcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLnBpeGVsU2l6ZSxcbiAgICAgICAgICAgIGhlaWdodDogdGhpcy5waXhlbFNpemUsXG4gICAgICAgICAgICBmaWxsOiB0aGlzLnBpeGVsQ29sb3Vycy5lbXB0eSxcbiAgICAgICAgICAgIGZpbGxfb3BhY2l0eTogMSwgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgdGhpcy5nZXRTdmdSb290KCksXG4gICAgICAgICk7XG4gICAgICAgIHJvdy5wdXNoKHNxdWFyZSk7XG4gICAgICB9XG4gICAgICB0aGlzLmJsb2NrRGlzcGxheVBpeGVscy5wdXNoKHJvdyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHNpemUgb2YgdGhlIGJsb2NrIGJhc2VkIG9uIHRoZSBzaXplIG9mIHRoZSB1bmRlcmx5aW5nIGltYWdlLlxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gIHByb3RlY3RlZCBvdmVycmlkZSB1cGRhdGVTaXplXygpIHtcbiAgICB7XG4gICAgICBjb25zdCBuZXdXaWR0aCA9IHRoaXMucGl4ZWxTaXplICogdGhpcy5pbWdXaWR0aDtcbiAgICAgIGNvbnN0IG5ld0hlaWdodCA9IHRoaXMucGl4ZWxTaXplICogdGhpcy5pbWdIZWlnaHQ7XG4gICAgICBpZiAodGhpcy5ib3JkZXJSZWN0Xykge1xuICAgICAgICB0aGlzLmJvcmRlclJlY3RfLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCBTdHJpbmcobmV3V2lkdGgpKTtcbiAgICAgICAgdGhpcy5ib3JkZXJSZWN0Xy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIFN0cmluZyhuZXdIZWlnaHQpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zaXplXy53aWR0aCA9IG5ld1dpZHRoO1xuICAgICAgdGhpcy5zaXplXy5oZWlnaHQgPSBuZXdIZWlnaHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBjb250cm9sIGJ1dHRvbi5cbiAgICpcbiAgICogQHBhcmFtIHBhcmVudCBQYXJlbnQgSFRNTCBlbGVtZW50IHRvIHdoaWNoIGNvbnRyb2wgYnV0dG9uIHdpbGwgYmUgYWRkZWQuXG4gICAqIEBwYXJhbSBidXR0b25UZXh0IFRleHQgb2YgdGhlIGNvbnRyb2wgYnV0dG9uLlxuICAgKiBAcGFyYW0gb25DbGljayBDYWxsYmFjayB0aGF0IHdpbGwgYmUgYXR0YWNoZWQgdG8gdGhlIGNvbnRyb2wgYnV0dG9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhZGRDb250cm9sQnV0dG9uKFxuICAgIHBhcmVudDogSFRNTEVsZW1lbnQsXG4gICAgYnV0dG9uVGV4dDogc3RyaW5nLFxuICAgIG9uQ2xpY2s6ICgpID0+IHZvaWQsXG4gICkge1xuICAgIGNvbnN0IGJ1dHRvbiA9IHRoaXMuY3JlYXRlRWxlbWVudFdpdGhDbGFzc25hbWUoJ2J1dHRvbicsICdjb250cm9sQnV0dG9uJyk7XG4gICAgYnV0dG9uLmlubmVyVGV4dCA9IGJ1dHRvblRleHQ7XG4gICAgcGFyZW50LmFwcGVuZENoaWxkKGJ1dHRvbik7XG4gICAgdGhpcy5iaW5kRXZlbnQoYnV0dG9uLCAnY2xpY2snLCBvbkNsaWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwb3NlcyBvZiBldmVudHMgYmVsb25naW5nIHRvIHRoZSBiaXRtYXAgZWRpdG9yLlxuICAgKi9cbiAgcHJpdmF0ZSBkcm9wZG93bkRpc3Bvc2UoKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5nZXRTb3VyY2VCbG9jaygpICYmXG4gICAgICB0aGlzLmluaXRpYWxWYWx1ZSAhPT0gbnVsbCAmJlxuICAgICAgdGhpcy5pbml0aWFsVmFsdWUgIT09IHRoaXMuZ2V0VmFsdWUoKVxuICAgICkge1xuICAgICAgQmxvY2tseS5FdmVudHMuZmlyZShcbiAgICAgICAgbmV3IChCbG9ja2x5LkV2ZW50cy5nZXQoQmxvY2tseS5FdmVudHMuQkxPQ0tfQ0hBTkdFKSkoXG4gICAgICAgICAgdGhpcy5zb3VyY2VCbG9ja18sXG4gICAgICAgICAgJ2ZpZWxkJyxcbiAgICAgICAgICB0aGlzLm5hbWUgfHwgbnVsbCxcbiAgICAgICAgICB0aGlzLmluaXRpYWxWYWx1ZSxcbiAgICAgICAgICB0aGlzLmdldFZhbHVlKCksXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZXZlbnQgb2YgdGhpcy5ib3VuZEV2ZW50cykge1xuICAgICAgQmxvY2tseS5icm93c2VyRXZlbnRzLnVuYmluZChldmVudCk7XG4gICAgfVxuICAgIHRoaXMuYm91bmRFdmVudHMubGVuZ3RoID0gMDtcbiAgICB0aGlzLmVkaXRvclBpeGVscyA9IG51bGw7XG4gICAgLy8gU2V0IHRoaXMuaW5pdGlhbFZhbHVlIGJhY2sgdG8gbnVsbC5cbiAgICB0aGlzLmluaXRpYWxWYWx1ZSA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhbiBhcnJheSBvZiB6ZXJvcyB3aXRoIHRoZSBzcGVjaWZpZWQgd2lkdGggYW5kIGhlaWdodC5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIG5ldyB2YWx1ZS5cbiAgICovXG4gIHByaXZhdGUgZ2V0RW1wdHlBcnJheSgpOiBudW1iZXJbXVtdIHtcbiAgICBjb25zdCBuZXdWYWw6IG51bWJlcltdW10gPSBbXTtcbiAgICBmb3IgKGxldCByID0gMDsgciA8IHRoaXMuaW1nSGVpZ2h0OyByKyspIHtcbiAgICAgIG5ld1ZhbC5wdXNoKFtdKTtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgdGhpcy5pbWdXaWR0aDsgYysrKSB7XG4gICAgICAgIG5ld1ZhbFtyXS5wdXNoKDApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3VmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIGEgbW91c2Vkb3duIGV2ZW50IG9jY3VycyB3aXRoaW4gdGhlIGJvdW5kcyBvZiBhIHBpeGVsLlxuICAgKlxuICAgKiBAcGFyYW0gciBSb3cgbnVtYmVyIG9mIGdyaWQuXG4gICAqIEBwYXJhbSBjIENvbHVtbiBudW1iZXIgb2YgZ3JpZC5cbiAgICovXG4gIHByaXZhdGUgb25Nb3VzZURvd25JblBpeGVsKHI6IG51bWJlciwgYzogbnVtYmVyKSB7XG4gICAgLy8gVG9nZ2xlIHRoYXQgcGl4ZWwgdG8gdGhlIG9wcG9zaXRlIG9mIGl0cyB2YWx1ZVxuICAgIGNvbnN0IG5ld1BpeGVsVmFsdWUgPSAxIC0gdGhpcy5nZXRQaXhlbChyLCBjKTtcbiAgICB0aGlzLnNldFBpeGVsKHIsIGMsIG5ld1BpeGVsVmFsdWUpO1xuICAgIHRoaXMubW91c2VJc0Rvd24gPSB0cnVlO1xuICAgIHRoaXMudmFsVG9QYWludFdpdGggPSBuZXdQaXhlbFZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBtb3VzZSBkcmFncyBvdmVyIGEgcGl4ZWwgaW4gdGhlIGVkaXRvci5cbiAgICpcbiAgICogQHBhcmFtIHIgUm93IG51bWJlciBvZiBncmlkLlxuICAgKiBAcGFyYW0gYyBDb2x1bW4gbnVtYmVyIG9mIGdyaWQuXG4gICAqL1xuICBwcml2YXRlIG9uTW91c2VFbnRlclBpeGVsKHI6IG51bWJlciwgYzogbnVtYmVyKSB7XG4gICAgaWYgKCF0aGlzLm1vdXNlSXNEb3duKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHRoaXMudmFsVG9QYWludFdpdGggIT09IHVuZGVmaW5lZCAmJlxuICAgICAgdGhpcy5nZXRQaXhlbChyLCBjKSAhPT0gdGhpcy52YWxUb1BhaW50V2l0aFxuICAgICkge1xuICAgICAgdGhpcy5zZXRQaXhlbChyLCBjLCB0aGlzLnZhbFRvUGFpbnRXaXRoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIG1vdXNlIHN0YXRlIChlLmcuIEFmdGVyIGVpdGhlciBhIG1vdXNldXAgZXZlbnQgb3IgaWYgdGhlIG1vdXNlXG4gICAqIGxlYXZlcyB0aGUgZWRpdG9yIGFyZWEpLlxuICAgKi9cbiAgcHJpdmF0ZSBvbk1vdXNlVXAoKSB7XG4gICAgdGhpcy5tb3VzZUlzRG93biA9IGZhbHNlO1xuICAgIHRoaXMudmFsVG9QYWludFdpdGggPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhbGwgdGhlIHBpeGVscyBpbiB0aGUgaW1hZ2UgdG8gYSByYW5kb20gdmFsdWUuXG4gICAqL1xuICBwcml2YXRlIHJhbmRvbWl6ZVBpeGVscygpIHtcbiAgICBjb25zdCBnZXRSYW5kQmluYXJ5ID0gKCkgPT4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMik7XG4gICAgdGhpcy5mb3JBbGxDZWxscygociwgYykgPT4ge1xuICAgICAgdGhpcy5zZXRQaXhlbChyLCBjLCBnZXRSYW5kQmluYXJ5KCkpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYWxsIHRoZSBwaXhlbHMgdG8gMC5cbiAgICovXG4gIHByaXZhdGUgY2xlYXJQaXhlbHMoKSB7XG4gICAgY29uc3QgY2xlYXJlZCA9IHRoaXMuZ2V0RW1wdHlBcnJheSgpO1xuICAgIHRoaXMuZmlyZUludGVybWVkaWF0ZUNoYW5nZUV2ZW50KGNsZWFyZWQpO1xuICAgIHRoaXMuc2V0VmFsdWUoY2xlYXJlZCwgZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHZhbHVlIG9mIGEgcGFydGljdWxhciBwaXhlbC5cbiAgICpcbiAgICogQHBhcmFtIHIgUm93IG51bWJlciBvZiBncmlkLlxuICAgKiBAcGFyYW0gYyBDb2x1bW4gbnVtYmVyIG9mIGdyaWQuXG4gICAqIEBwYXJhbSBuZXdWYWx1ZSBWYWx1ZSBvZiB0aGUgcGl4ZWwuXG4gICAqL1xuICBwcml2YXRlIHNldFBpeGVsKHI6IG51bWJlciwgYzogbnVtYmVyLCBuZXdWYWx1ZTogbnVtYmVyKSB7XG4gICAgY29uc3QgbmV3R3JpZCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5nZXRWYWx1ZSgpKSk7XG4gICAgbmV3R3JpZFtyXVtjXSA9IG5ld1ZhbHVlO1xuICAgIHRoaXMuZmlyZUludGVybWVkaWF0ZUNoYW5nZUV2ZW50KG5ld0dyaWQpO1xuICAgIHRoaXMuc2V0VmFsdWUobmV3R3JpZCwgZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQaXhlbChyb3c6IG51bWJlciwgY29sdW1uOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZSgpO1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0F0dGVtcHRlZCB0byByZXRyaWV2ZSBhIHBpeGVsIHZhbHVlIHdoZW4gbm8gdmFsdWUgaXMgc2V0JyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlW3Jvd11bY29sdW1uXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxscyBhIGdpdmVuIGZ1bmN0aW9uIGZvciBhbGwgY2VsbHMgaW4gdGhlIGltYWdlLCB3aXRoIHRoZSBjZWxsXG4gICAqIGNvb3JkaW5hdGVzIGFzIHRoZSBhcmd1bWVudHMuXG4gICAqXG4gICAqIEBwYXJhbSBmdW5jIEEgZnVuY3Rpb24gdG8gYmUgYXBwbGllZC5cbiAgICovXG4gIHByaXZhdGUgZm9yQWxsQ2VsbHMoZnVuYzogKHJvdzogbnVtYmVyLCBjb2w6IG51bWJlcikgPT4gdm9pZCkge1xuICAgIGZvciAobGV0IHIgPSAwOyByIDwgdGhpcy5pbWdIZWlnaHQ7IHIrKykge1xuICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCB0aGlzLmltZ1dpZHRoOyBjKyspIHtcbiAgICAgICAgZnVuYyhyLCBjKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBlbGVtZW50IHdpdGggdGhlIHNwZWNpZmllZCB0eXBlIGFuZCBjbGFzcy5cbiAgICpcbiAgICogQHBhcmFtIGVsZW1lbnRUeXBlIFR5cGUgb2YgaHRtbCBlbGVtZW50LlxuICAgKiBAcGFyYW0gY2xhc3NOYW1lIENsYXNzTmFtZSBvZiBodG1sIGVsZW1lbnQuXG4gICAqIEByZXR1cm5zIFRoZSBjcmVhdGVkIGVsZW1lbnQuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUVsZW1lbnRXaXRoQ2xhc3NuYW1lKGVsZW1lbnRUeXBlOiBzdHJpbmcsIGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgbmV3RWx0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlbGVtZW50VHlwZSk7XG4gICAgbmV3RWx0LmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgICByZXR1cm4gbmV3RWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEJpbmRzIGFuIGV2ZW50IGxpc3RlbmVyIHRvIHRoZSBzcGVjaWZpZWQgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGVsZW1lbnQgU3BlY2lmaWVkIGVsZW1lbnQuXG4gICAqIEBwYXJhbSBldmVudE5hbWUgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYmluZC5cbiAgICogQHBhcmFtIGNhbGxiYWNrIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBvbiBzcGVjaWZpZWQgZXZlbnQuXG4gICAqL1xuICBwcml2YXRlIGJpbmRFdmVudChcbiAgICBlbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBldmVudE5hbWU6IHN0cmluZyxcbiAgICBjYWxsYmFjazogKGU6IEV2ZW50KSA9PiB2b2lkLFxuICApIHtcbiAgICB0aGlzLmJvdW5kRXZlbnRzLnB1c2goXG4gICAgICBCbG9ja2x5LmJyb3dzZXJFdmVudHMuY29uZGl0aW9uYWxCaW5kKGVsZW1lbnQsIGV2ZW50TmFtZSwgdGhpcywgY2FsbGJhY2spLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGZpcmVJbnRlcm1lZGlhdGVDaGFuZ2VFdmVudChuZXdWYWx1ZTogbnVtYmVyW11bXSkge1xuICAgIGlmICh0aGlzLmdldFNvdXJjZUJsb2NrKCkpIHtcbiAgICAgIEJsb2NrbHkuRXZlbnRzLmZpcmUoXG4gICAgICAgIG5ldyAoQmxvY2tseS5FdmVudHMuZ2V0KFxuICAgICAgICAgIEJsb2NrbHkuRXZlbnRzLkJMT0NLX0ZJRUxEX0lOVEVSTUVESUFURV9DSEFOR0UsXG4gICAgICAgICkpKHRoaXMuZ2V0U291cmNlQmxvY2soKSwgdGhpcy5uYW1lIHx8IG51bGwsIHRoaXMuZ2V0VmFsdWUoKSwgbmV3VmFsdWUpLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuaW50ZXJmYWNlIEJ1dHRvbnMge1xuICByZWFkb25seSByYW5kb21pemU6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNsZWFyOiBib29sZWFuO1xufVxuaW50ZXJmYWNlIFBpeGVsQ29sb3VycyB7XG4gIHJlYWRvbmx5IGVtcHR5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZpbGxlZDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpZWxkQml0bWFwRnJvbUpzb25Db25maWcgZXh0ZW5kcyBCbG9ja2x5LkZpZWxkQ29uZmlnIHtcbiAgdmFsdWU/OiBudW1iZXJbXVtdO1xuICB3aWR0aD86IG51bWJlcjtcbiAgaGVpZ2h0PzogbnVtYmVyO1xuICBidXR0b25zPzogQnV0dG9ucztcbiAgZmllbGRIZWlnaHQ/OiBudW1iZXI7XG4gIGNvbG91cnM/OiBQaXhlbENvbG91cnM7XG59XG5cbkJsb2NrbHkuZmllbGRSZWdpc3RyeS5yZWdpc3RlcignZmllbGRfYml0bWFwJywgRmllbGRCaXRtYXApO1xuXG4vKipcbiAqIENTUyBmb3IgYml0bWFwIGZpZWxkLlxuICovXG5CbG9ja2x5LkNzcy5yZWdpc3RlcihgXG4uZHJvcGRvd25FZGl0b3Ige1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgbWFyZ2luLWJvdHRvbTogMjBweDtcbn1cbi5waXhlbENvbnRhaW5lciB7XG4gIG1hcmdpbjogMjBweDtcbn1cbi5waXhlbFJvdyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIHBhZGRpbmc6IDA7XG4gIG1hcmdpbjogMDtcbiAgaGVpZ2h0OiAke0RFRkFVTFRfUElYRUxfU0laRX1cbn1cbi5waXhlbEJ1dHRvbiB7XG4gIHdpZHRoOiAke0RFRkFVTFRfUElYRUxfU0laRX1weDtcbiAgaGVpZ2h0OiAke0RFRkFVTFRfUElYRUxfU0laRX1weDtcbiAgYm9yZGVyOiAxcHggc29saWQgIzAwMDtcbn1cbi5waXhlbERpc3BsYXkge1xuICB3aGl0ZS1zcGFjZTpwcmUtd3JhcDtcbn1cbi5jb250cm9sQnV0dG9uIHtcbiAgbWFyZ2luOiA1cHggMDtcbn1cbmApO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/field-bitmap.ts\n");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"DEFAULT_HEIGHT\": () => (/* binding */ DEFAULT_HEIGHT),\n/* harmony export */ \"DEFAULT_WIDTH\": () => (/* binding */ DEFAULT_WIDTH),\n/* harmony export */ \"FieldBitmap\": () => (/* binding */ FieldBitmap)\n/* harmony export */ });\n/* harmony import */ var blockly_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! blockly/core */ \"./node_modules/blockly/core-browser.js\");\n/* harmony import */ var blockly_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(blockly_core__WEBPACK_IMPORTED_MODULE_0__);\n/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_RANDOMIZE = 'Randomize';\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_CLEAR = 'Clear';\nconst DEFAULT_HEIGHT = 5;\nconst DEFAULT_WIDTH = 5;\nconst DEFAULT_PIXEL_SIZE = 15;\nconst DEFAULT_PIXEL_COLOURS = {\n empty: '#fff',\n filled: '#363d80',\n};\nconst DEFAULT_BUTTONS = {\n randomize: true,\n clear: true,\n};\n/**\n * Field for inputting a small bitmap image.\n * Includes a grid of clickable pixels that's exported as a bitmap.\n */\nclass FieldBitmap extends blockly_core__WEBPACK_IMPORTED_MODULE_0__.Field {\n /**\n * Constructor for the bitmap field.\n *\n * @param value 2D rectangular array of 1s and 0s.\n * @param validator A function that is called to validate.\n * @param config Config A map of options used to configure the field.\n */\n constructor(value, validator, config) {\n var _a, _b;\n super(value, validator, config);\n this.initialValue = null;\n /**\n * Array holding info needed to unbind events.\n * Used for disposing.\n */\n this.boundEvents = [];\n /** References to UI elements */\n this.editorPixels = null;\n this.blockDisplayPixels = null;\n /** Stateful variables */\n this.mouseIsDown = false;\n this.SERIALIZABLE = true;\n this.CURSOR = 'default';\n this.buttonOptions = Object.assign(Object.assign({}, DEFAULT_BUTTONS), config === null || config === void 0 ? void 0 : config.buttons);\n this.pixelColours = Object.assign(Object.assign({}, DEFAULT_PIXEL_COLOURS), config === null || config === void 0 ? void 0 : config.colours);\n // Configure value, height, and width\n const currentValue = this.getValue();\n if (currentValue !== null) {\n this.imgHeight = currentValue.length;\n this.imgWidth = currentValue[0].length || 0;\n }\n else {\n this.imgHeight = (_a = config === null || config === void 0 ? void 0 : config.height) !== null && _a !== void 0 ? _a : DEFAULT_HEIGHT;\n this.imgWidth = (_b = config === null || config === void 0 ? void 0 : config.width) !== null && _b !== void 0 ? _b : DEFAULT_WIDTH;\n // Set a default empty value\n this.setValue(this.getEmptyArray());\n }\n if (config === null || config === void 0 ? void 0 : config.fieldHeight) {\n this.pixelSize = config.fieldHeight / this.imgHeight;\n }\n else {\n this.pixelSize = DEFAULT_PIXEL_SIZE;\n }\n }\n /**\n * Constructs a FieldBitmap from a JSON arg object.\n *\n * @param options A JSON object with options.\n * @returns The new field instance.\n */\n static fromJson(options) {\n var _a;\n // `this` might be a subclass of FieldBitmap if that class doesn't override the static fromJson method.\n return new this((_a = options.value) !== null && _a !== void 0 ? _a : blockly_core__WEBPACK_IMPORTED_MODULE_0__.Field.SKIP_SETUP, undefined, options);\n }\n /**\n * Returns the width of the image in pixels.\n *\n * @returns The width in pixels.\n */\n getImageWidth() {\n return this.imgWidth;\n }\n /**\n * Returns the height of the image in pixels.\n *\n * @returns The height in pixels.\n */\n getImageHeight() {\n return this.imgHeight;\n }\n /**\n * Validates that a new value meets the requirements for a valid bitmap array.\n *\n * @param newValue The new value to be tested.\n * @returns The new value if it's valid, or null.\n */\n // eslint-disable-next-line\n doClassValidation_(newValue = undefined) {\n if (!newValue) {\n return null;\n }\n // Check if the new value is an array\n if (!Array.isArray(newValue)) {\n return null;\n }\n const newHeight = newValue.length;\n // The empty list is not an acceptable bitmap\n if (newHeight == 0) {\n return null;\n }\n // Check that the width matches the existing width of the image if it\n // already has a value.\n const newWidth = newValue[0].length;\n for (const row of newValue) {\n if (!Array.isArray(row)) {\n return null;\n }\n if (row.length !== newWidth) {\n return null;\n }\n }\n // Check if all contents of the arrays are either 0 or 1\n for (const row of newValue) {\n for (const cell of row) {\n if (cell !== 0 && cell !== 1) {\n return null;\n }\n }\n }\n return newValue;\n }\n /**\n * Called when a new value has been validated and is about to be set.\n *\n * @param newValue The value that's about to be set.\n */\n // eslint-disable-next-line\n doValueUpdate_(newValue) {\n super.doValueUpdate_(newValue);\n if (newValue) {\n this.imgHeight = newValue.length;\n this.imgWidth = newValue[0] ? newValue[0].length : 0;\n }\n }\n /**\n * Show the bitmap editor dialog.\n *\n * @param e Optional mouse event that triggered the field to open, or\n * undefined if triggered programmatically.\n */\n // eslint-disable-next-line\n showEditor_(e) {\n const editor = this.dropdownCreate();\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.getContentDiv().appendChild(editor);\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.showPositionedByField(this, this.dropdownDispose.bind(this));\n }\n /**\n * Updates the block display and editor dropdown when the field re-renders.\n */\n // eslint-disable-next-line\n render_() {\n super.render_();\n if (!this.getValue()) {\n return;\n }\n if (this.blockDisplayPixels) {\n this.forAllCells((r, c) => {\n const pixel = this.getPixel(r, c);\n if (this.blockDisplayPixels) {\n this.blockDisplayPixels[r][c].style.fill = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n if (this.editorPixels) {\n this.editorPixels[r][c].style.background = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n });\n }\n }\n /**\n * Determines whether the field is editable.\n *\n * @returns True since it is always editable.\n */\n updateEditable() {\n const editable = super.updateEditable();\n // Blockly.Field's implementation sets these classes as appropriate, but\n // since this field has no text they just mess up the rendering of the grid\n // lines.\n const svgRoot = this.getSvgRoot();\n if (svgRoot) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.removeClass(svgRoot, 'blocklyNonEditableText');\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.removeClass(svgRoot, 'blocklyEditableText');\n }\n return editable;\n }\n /**\n * Gets the rectangle built out of dimensions matching SVG's element.\n *\n * @returns The newly created rectangle of same size as the SVG element.\n */\n getScaledBBox() {\n var _a;\n const boundingBox = (_a = this.getSvgRoot()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();\n if (!boundingBox) {\n throw new Error('Tried to retrieve a bounding box without a rect');\n }\n return new blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.Rect(boundingBox.top, boundingBox.bottom, boundingBox.left, boundingBox.right);\n }\n /**\n * Creates the bitmap editor and add event listeners.\n *\n * @returns The newly created dropdown menu.\n */\n dropdownCreate() {\n const dropdownEditor = this.createElementWithClassname('div', 'dropdownEditor');\n if (this.buttonOptions.randomize || this.buttonOptions.clear) {\n dropdownEditor.classList.add('has-buttons');\n }\n const pixelContainer = this.createElementWithClassname('div', 'pixelContainer');\n dropdownEditor.appendChild(pixelContainer);\n // This prevents the normal max-height from adding a scroll bar for large images.\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.getContentDiv().classList.add('contains-bitmap-editor');\n this.bindEvent(dropdownEditor, 'mouseup', this.onMouseUp);\n this.bindEvent(dropdownEditor, 'mouseleave', this.onMouseUp);\n this.bindEvent(dropdownEditor, 'dragstart', (e) => {\n e.preventDefault();\n });\n this.editorPixels = [];\n for (let r = 0; r < this.imgHeight; r++) {\n this.editorPixels.push([]);\n const rowDiv = this.createElementWithClassname('div', 'pixelRow');\n for (let c = 0; c < this.imgWidth; c++) {\n // Add the button to the UI and save a reference to it\n const button = this.createElementWithClassname('div', 'pixelButton');\n this.editorPixels[r].push(button);\n rowDiv.appendChild(button);\n // Load the current pixel colour\n const isOn = this.getPixel(r, c);\n button.style.background = isOn\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n // Handle clicking a pixel\n this.bindEvent(button, 'mousedown', () => {\n this.onMouseDownInPixel(r, c);\n return true;\n });\n // Handle dragging into a pixel when mouse is down\n this.bindEvent(button, 'mouseenter', () => {\n this.onMouseEnterPixel(r, c);\n });\n }\n pixelContainer.appendChild(rowDiv);\n }\n // Add control buttons below the pixel grid\n if (this.buttonOptions.randomize) {\n this.addControlButton(dropdownEditor, blockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_RANDOMIZE, this.randomizePixels);\n }\n if (this.buttonOptions.clear) {\n this.addControlButton(dropdownEditor, blockly_core__WEBPACK_IMPORTED_MODULE_0__.Msg.BUTTON_LABEL_CLEAR, this.clearPixels);\n }\n if (this.blockDisplayPixels) {\n this.forAllCells((r, c) => {\n const pixel = this.getPixel(r, c);\n if (this.editorPixels) {\n this.editorPixels[r][c].style.background = pixel\n ? this.pixelColours.filled\n : this.pixelColours.empty;\n }\n });\n }\n // Store the initial value at the start of the edit.\n this.initialValue = this.getValue();\n return dropdownEditor;\n }\n /**\n * Initializes the on-block display.\n */\n initView() {\n this.blockDisplayPixels = [];\n for (let r = 0; r < this.imgHeight; r++) {\n const row = [];\n for (let c = 0; c < this.imgWidth; c++) {\n const square = blockly_core__WEBPACK_IMPORTED_MODULE_0__.utils.dom.createSvgElement('rect', {\n x: c * this.pixelSize,\n y: r * this.pixelSize,\n width: this.pixelSize,\n height: this.pixelSize,\n fill: this.pixelColours.empty,\n fill_opacity: 1, // eslint-disable-line\n }, this.getSvgRoot());\n row.push(square);\n }\n this.blockDisplayPixels.push(row);\n }\n }\n /**\n * Updates the size of the block based on the size of the underlying image.\n */\n // eslint-disable-next-line\n updateSize_() {\n {\n const newWidth = this.pixelSize * this.imgWidth;\n const newHeight = this.pixelSize * this.imgHeight;\n if (this.borderRect_) {\n this.borderRect_.setAttribute('width', String(newWidth));\n this.borderRect_.setAttribute('height', String(newHeight));\n }\n this.size_.width = newWidth;\n this.size_.height = newHeight;\n }\n }\n /**\n * Create control button.\n *\n * @param parent Parent HTML element to which control button will be added.\n * @param buttonText Text of the control button.\n * @param onClick Callback that will be attached to the control button.\n */\n addControlButton(parent, buttonText, onClick) {\n const button = this.createElementWithClassname('button', 'controlButton');\n button.innerText = buttonText;\n parent.appendChild(button);\n this.bindEvent(button, 'click', onClick);\n }\n /**\n * Disposes of events belonging to the bitmap editor.\n */\n dropdownDispose() {\n if (this.getSourceBlock() &&\n this.initialValue !== null &&\n this.initialValue !== this.getValue()) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.fire(new (blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.get(blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.BLOCK_CHANGE))(this.sourceBlock_, 'field', this.name || null, this.initialValue, this.getValue()));\n }\n for (const event of this.boundEvents) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.browserEvents.unbind(event);\n }\n this.boundEvents.length = 0;\n this.editorPixels = null;\n // Set this.initialValue back to null.\n this.initialValue = null;\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.DropDownDiv.getContentDiv().classList.remove('contains-bitmap-editor');\n }\n /**\n * Constructs an array of zeros with the specified width and height.\n *\n * @returns The new value.\n */\n getEmptyArray() {\n const newVal = [];\n for (let r = 0; r < this.imgHeight; r++) {\n newVal.push([]);\n for (let c = 0; c < this.imgWidth; c++) {\n newVal[r].push(0);\n }\n }\n return newVal;\n }\n /**\n * Called when a mousedown event occurs within the bounds of a pixel.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n */\n onMouseDownInPixel(r, c) {\n // Toggle that pixel to the opposite of its value\n const newPixelValue = 1 - this.getPixel(r, c);\n this.setPixel(r, c, newPixelValue);\n this.mouseIsDown = true;\n this.valToPaintWith = newPixelValue;\n }\n /**\n * Called when the mouse drags over a pixel in the editor.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n */\n onMouseEnterPixel(r, c) {\n if (!this.mouseIsDown) {\n return;\n }\n if (this.valToPaintWith !== undefined &&\n this.getPixel(r, c) !== this.valToPaintWith) {\n this.setPixel(r, c, this.valToPaintWith);\n }\n }\n /**\n * Resets mouse state (e.g. After either a mouseup event or if the mouse\n * leaves the editor area).\n */\n onMouseUp() {\n this.mouseIsDown = false;\n this.valToPaintWith = undefined;\n }\n /**\n * Sets all the pixels in the image to a random value.\n */\n randomizePixels() {\n const getRandBinary = () => Math.floor(Math.random() * 2);\n this.forAllCells((r, c) => {\n this.setPixel(r, c, getRandBinary());\n });\n }\n /**\n * Sets all the pixels to 0.\n */\n clearPixels() {\n const cleared = this.getEmptyArray();\n this.fireIntermediateChangeEvent(cleared);\n this.setValue(cleared, false);\n }\n /**\n * Sets the value of a particular pixel.\n *\n * @param r Row number of grid.\n * @param c Column number of grid.\n * @param newValue Value of the pixel.\n */\n setPixel(r, c, newValue) {\n const newGrid = JSON.parse(JSON.stringify(this.getValue()));\n newGrid[r][c] = newValue;\n this.fireIntermediateChangeEvent(newGrid);\n this.setValue(newGrid, false);\n }\n getPixel(row, column) {\n const value = this.getValue();\n if (!value) {\n throw new Error('Attempted to retrieve a pixel value when no value is set');\n }\n return value[row][column];\n }\n /**\n * Calls a given function for all cells in the image, with the cell\n * coordinates as the arguments.\n *\n * @param func A function to be applied.\n */\n forAllCells(func) {\n for (let r = 0; r < this.imgHeight; r++) {\n for (let c = 0; c < this.imgWidth; c++) {\n func(r, c);\n }\n }\n }\n /**\n * Creates a new element with the specified type and class.\n *\n * @param elementType Type of html element.\n * @param className ClassName of html element.\n * @returns The created element.\n */\n createElementWithClassname(elementType, className) {\n const newElt = document.createElement(elementType);\n newElt.className = className;\n return newElt;\n }\n /**\n * Binds an event listener to the specified element.\n *\n * @param element Specified element.\n * @param eventName Name of the event to bind.\n * @param callback Function to be called on specified event.\n */\n bindEvent(element, eventName, callback) {\n this.boundEvents.push(blockly_core__WEBPACK_IMPORTED_MODULE_0__.browserEvents.conditionalBind(element, eventName, this, callback));\n }\n fireIntermediateChangeEvent(newValue) {\n if (this.getSourceBlock()) {\n blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.fire(new (blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.get(blockly_core__WEBPACK_IMPORTED_MODULE_0__.Events.BLOCK_FIELD_INTERMEDIATE_CHANGE))(this.getSourceBlock(), this.name || null, this.getValue(), newValue));\n }\n }\n}\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.fieldRegistry.register('field_bitmap', FieldBitmap);\n/**\n * CSS for bitmap field.\n */\nblockly_core__WEBPACK_IMPORTED_MODULE_0__.Css.register(`\n.dropdownEditor {\n align-items: center;\n flex-direction: column;\n display: flex;\n justify-content: center;\n}\n.dropdownEditor.has-buttons {\n margin-bottom: 20px;\n}\n.pixelContainer {\n margin: 20px;\n}\n.pixelRow {\n display: flex;\n flex-direction: row;\n padding: 0;\n margin: 0;\n height: ${DEFAULT_PIXEL_SIZE}\n}\n.pixelButton {\n width: ${DEFAULT_PIXEL_SIZE}px;\n height: ${DEFAULT_PIXEL_SIZE}px;\n border: 1px solid #000;\n}\n.pixelDisplay {\n white-space:pre-wrap;\n}\n.controlButton {\n margin: 5px 0;\n}\n.blocklyDropDownContent.contains-bitmap-editor {\n max-height: none;\n}\n`);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Qy9DLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUN4RSxDQUFDO1NBQ0g7SUFDSCxDQUFDO0NBQ0Y7QUFvQkQsZ0VBQThCLENBQUMsY0FBYyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBRTVEOztHQUVHO0FBQ0gsc0RBQW9CLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7OztZQWtCVCxrQkFBa0I7OztXQUduQixrQkFBa0I7WUFDakIsa0JBQWtCOzs7Ozs7Ozs7Ozs7Q0FZN0IsQ0FBQyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQGJsb2NrbHkvZmllbGQtYml0bWFwLy4vc3JjL2ZpZWxkLWJpdG1hcC50cz9hYzYzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0ICogYXMgQmxvY2tseSBmcm9tICdibG9ja2x5L2NvcmUnO1xuXG5CbG9ja2x5Lk1zZ1snQlVUVE9OX0xBQkVMX1JBTkRPTUlaRSddID0gJ1JhbmRvbWl6ZSc7XG5CbG9ja2x5Lk1zZ1snQlVUVE9OX0xBQkVMX0NMRUFSJ10gPSAnQ2xlYXInO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9IRUlHSFQgPSA1O1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfV0lEVEggPSA1O1xuY29uc3QgREVGQVVMVF9QSVhFTF9TSVpFID0gMTU7XG5jb25zdCBERUZBVUxUX1BJWEVMX0NPTE9VUlM6IFBpeGVsQ29sb3VycyA9IHtcbiAgZW1wdHk6ICcjZmZmJyxcbiAgZmlsbGVkOiAnIzM2M2Q4MCcsXG59O1xuY29uc3QgREVGQVVMVF9CVVRUT05TOiBCdXR0b25zID0ge1xuICByYW5kb21pemU6IHRydWUsXG4gIGNsZWFyOiB0cnVlLFxufTtcbi8qKlxuICogRmllbGQgZm9yIGlucHV0dGluZyBhIHNtYWxsIGJpdG1hcCBpbWFnZS5cbiAqIEluY2x1ZGVzIGEgZ3JpZCBvZiBjbGlja2FibGUgcGl4ZWxzIHRoYXQncyBleHBvcnRlZCBhcyBhIGJpdG1hcC5cbiAqL1xuZXhwb3J0IGNsYXNzIEZpZWxkQml0bWFwIGV4dGVuZHMgQmxvY2tseS5GaWVsZDxudW1iZXJbXVtdPiB7XG4gIHByaXZhdGUgaW5pdGlhbFZhbHVlOiBudW1iZXJbXVtdIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaW1nSGVpZ2h0OiBudW1iZXI7XG4gIHByaXZhdGUgaW1nV2lkdGg6IG51bWJlcjtcbiAgLyoqXG4gICAqIEFycmF5IGhvbGRpbmcgaW5mbyBuZWVkZWQgdG8gdW5iaW5kIGV2ZW50cy5cbiAgICogVXNlZCBmb3IgZGlzcG9zaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBib3VuZEV2ZW50czogQmxvY2tseS5icm93c2VyRXZlbnRzLkRhdGFbXSA9IFtdO1xuICAvKiogUmVmZXJlbmNlcyB0byBVSSBlbGVtZW50cyAqL1xuICBwcml2YXRlIGVkaXRvclBpeGVsczogSFRNTEVsZW1lbnRbXVtdIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgYmxvY2tEaXNwbGF5UGl4ZWxzOiBTVkdFbGVtZW50W11bXSB8IG51bGwgPSBudWxsO1xuICAvKiogU3RhdGVmdWwgdmFyaWFibGVzICovXG4gIHByaXZhdGUgbW91c2VJc0Rvd24gPSBmYWxzZTtcbiAgcHJpdmF0ZSB2YWxUb1BhaW50V2l0aD86IG51bWJlcjtcbiAgYnV0dG9uT3B0aW9uczogQnV0dG9ucztcbiAgcGl4ZWxTaXplOiBudW1iZXI7XG4gIHBpeGVsQ29sb3Vyczoge2VtcHR5OiBzdHJpbmc7IGZpbGxlZDogc3RyaW5nfTtcblxuICAvKipcbiAgICogQ29uc3RydWN0b3IgZm9yIHRoZSBiaXRtYXAgZmllbGQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAyRCByZWN0YW5ndWxhciBhcnJheSBvZiAxcyBhbmQgMHMuXG4gICAqIEBwYXJhbSB2YWxpZGF0b3IgQSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB0byB2YWxpZGF0ZS5cbiAgICogQHBhcmFtIGNvbmZpZyBDb25maWcgQSBtYXAgb2Ygb3B0aW9ucyB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgZmllbGQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICB2YWx1ZTogbnVtYmVyW11bXSB8IHR5cGVvZiBCbG9ja2x5LkZpZWxkLlNLSVBfU0VUVVAsXG4gICAgdmFsaWRhdG9yPzogQmxvY2tseS5GaWVsZFZhbGlkYXRvcjxudW1iZXJbXVtdPixcbiAgICBjb25maWc/OiBGaWVsZEJpdG1hcEZyb21Kc29uQ29uZmlnLFxuICApIHtcbiAgICBzdXBlcih2YWx1ZSwgdmFsaWRhdG9yLCBjb25maWcpO1xuXG4gICAgdGhpcy5TRVJJQUxJWkFCTEUgPSB0cnVlO1xuICAgIHRoaXMuQ1VSU09SID0gJ2RlZmF1bHQnO1xuICAgIHRoaXMuYnV0dG9uT3B0aW9ucyA9IHsuLi5ERUZBVUxUX0JVVFRPTlMsIC4uLmNvbmZpZz8uYnV0dG9uc307XG4gICAgdGhpcy5waXhlbENvbG91cnMgPSB7Li4uREVGQVVMVF9QSVhFTF9DT0xPVVJTLCAuLi5jb25maWc/LmNvbG91cnN9O1xuXG4gICAgLy8gQ29uZmlndXJlIHZhbHVlLCBoZWlnaHQsIGFuZCB3aWR0aFxuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcbiAgICBpZiAoY3VycmVudFZhbHVlICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmltZ0hlaWdodCA9IGN1cnJlbnRWYWx1ZS5sZW5ndGg7XG4gICAgICB0aGlzLmltZ1dpZHRoID0gY3VycmVudFZhbHVlWzBdLmxlbmd0aCB8fCAwO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmltZ0hlaWdodCA9IGNvbmZpZz8uaGVpZ2h0ID8/IERFRkFVTFRfSEVJR0hUO1xuICAgICAgdGhpcy5pbWdXaWR0aCA9IGNvbmZpZz8ud2lkdGggPz8gREVGQVVMVF9XSURUSDtcbiAgICAgIC8vIFNldCBhIGRlZmF1bHQgZW1wdHkgdmFsdWVcbiAgICAgIHRoaXMuc2V0VmFsdWUodGhpcy5nZXRFbXB0eUFycmF5KCkpO1xuICAgIH1cbiAgICBpZiAoY29uZmlnPy5maWVsZEhlaWdodCkge1xuICAgICAgdGhpcy5waXhlbFNpemUgPSBjb25maWcuZmllbGRIZWlnaHQgLyB0aGlzLmltZ0hlaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5waXhlbFNpemUgPSBERUZBVUxUX1BJWEVMX1NJWkU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSBGaWVsZEJpdG1hcCBmcm9tIGEgSlNPTiBhcmcgb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyBBIEpTT04gb2JqZWN0IHdpdGggb3B0aW9ucy5cbiAgICogQHJldHVybnMgVGhlIG5ldyBmaWVsZCBpbnN0YW5jZS5cbiAgICovXG4gIHN0YXRpYyBmcm9tSnNvbihvcHRpb25zOiBGaWVsZEJpdG1hcEZyb21Kc29uQ29uZmlnKSB7XG4gICAgLy8gYHRoaXNgIG1pZ2h0IGJlIGEgc3ViY2xhc3Mgb2YgRmllbGRCaXRtYXAgaWYgdGhhdCBjbGFzcyBkb2Vzbid0IG92ZXJyaWRlIHRoZSBzdGF0aWMgZnJvbUpzb24gbWV0aG9kLlxuICAgIHJldHVybiBuZXcgdGhpcyhcbiAgICAgIG9wdGlvbnMudmFsdWUgPz8gQmxvY2tseS5GaWVsZC5TS0lQX1NFVFVQLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgb3B0aW9ucyxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHdpZHRoIG9mIHRoZSBpbWFnZSBpbiBwaXhlbHMuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSB3aWR0aCBpbiBwaXhlbHMuXG4gICAqL1xuICBnZXRJbWFnZVdpZHRoKCkge1xuICAgIHJldHVybiB0aGlzLmltZ1dpZHRoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGhlaWdodCBvZiB0aGUgaW1hZ2UgaW4gcGl4ZWxzLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgaGVpZ2h0IGluIHBpeGVscy5cbiAgICovXG4gIGdldEltYWdlSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLmltZ0hlaWdodDtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhhdCBhIG5ldyB2YWx1ZSBtZWV0cyB0aGUgcmVxdWlyZW1lbnRzIGZvciBhIHZhbGlkIGJpdG1hcCBhcnJheS5cbiAgICpcbiAgICogQHBhcmFtIG5ld1ZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gYmUgdGVzdGVkLlxuICAgKiBAcmV0dXJucyBUaGUgbmV3IHZhbHVlIGlmIGl0J3MgdmFsaWQsIG9yIG51bGwuXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGRvQ2xhc3NWYWxpZGF0aW9uXyhuZXdWYWx1ZTogdW5rbm93biA9IHVuZGVmaW5lZCkge1xuICAgIGlmICghbmV3VmFsdWUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICAvLyBDaGVjayBpZiB0aGUgbmV3IHZhbHVlIGlzIGFuIGFycmF5XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG5ld1ZhbHVlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IG5ld0hlaWdodCA9IG5ld1ZhbHVlLmxlbmd0aDtcbiAgICAvLyBUaGUgZW1wdHkgbGlzdCBpcyBub3QgYW4gYWNjZXB0YWJsZSBiaXRtYXBcbiAgICBpZiAobmV3SGVpZ2h0ID09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHRoYXQgdGhlIHdpZHRoIG1hdGNoZXMgdGhlIGV4aXN0aW5nIHdpZHRoIG9mIHRoZSBpbWFnZSBpZiBpdFxuICAgIC8vIGFscmVhZHkgaGFzIGEgdmFsdWUuXG4gICAgY29uc3QgbmV3V2lkdGggPSBuZXdWYWx1ZVswXS5sZW5ndGg7XG4gICAgZm9yIChjb25zdCByb3cgb2YgbmV3VmFsdWUpIHtcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShyb3cpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHJvdy5sZW5ndGggIT09IG5ld1dpZHRoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGFsbCBjb250ZW50cyBvZiB0aGUgYXJyYXlzIGFyZSBlaXRoZXIgMCBvciAxXG4gICAgZm9yIChjb25zdCByb3cgb2YgbmV3VmFsdWUpIHtcbiAgICAgIGZvciAoY29uc3QgY2VsbCBvZiByb3cpIHtcbiAgICAgICAgaWYgKGNlbGwgIT09IDAgJiYgY2VsbCAhPT0gMSkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXdWYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiBhIG5ldyB2YWx1ZSBoYXMgYmVlbiB2YWxpZGF0ZWQgYW5kIGlzIGFib3V0IHRvIGJlIHNldC5cbiAgICpcbiAgICogQHBhcmFtIG5ld1ZhbHVlIFRoZSB2YWx1ZSB0aGF0J3MgYWJvdXQgdG8gYmUgc2V0LlxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gIHByb3RlY3RlZCBvdmVycmlkZSBkb1ZhbHVlVXBkYXRlXyhuZXdWYWx1ZTogbnVtYmVyW11bXSkge1xuICAgIHN1cGVyLmRvVmFsdWVVcGRhdGVfKG5ld1ZhbHVlKTtcbiAgICBpZiAobmV3VmFsdWUpIHtcbiAgICAgIHRoaXMuaW1nSGVpZ2h0ID0gbmV3VmFsdWUubGVuZ3RoO1xuICAgICAgdGhpcy5pbWdXaWR0aCA9IG5ld1ZhbHVlWzBdID8gbmV3VmFsdWVbMF0ubGVuZ3RoIDogMDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2hvdyB0aGUgYml0bWFwIGVkaXRvciBkaWFsb2cuXG4gICAqXG4gICAqIEBwYXJhbSBlIE9wdGlvbmFsIG1vdXNlIGV2ZW50IHRoYXQgdHJpZ2dlcmVkIHRoZSBmaWVsZCB0byBvcGVuLCBvclxuICAgKiAgICB1bmRlZmluZWQgaWYgdHJpZ2dlcmVkIHByb2dyYW1tYXRpY2FsbHkuXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHNob3dFZGl0b3JfKGU/OiBFdmVudCkge1xuICAgIGNvbnN0IGVkaXRvciA9IHRoaXMuZHJvcGRvd25DcmVhdGUoKTtcbiAgICBCbG9ja2x5LkRyb3BEb3duRGl2LmdldENvbnRlbnREaXYoKS5hcHBlbmRDaGlsZChlZGl0b3IpO1xuICAgIEJsb2NrbHkuRHJvcERvd25EaXYuc2hvd1Bvc2l0aW9uZWRCeUZpZWxkKFxuICAgICAgdGhpcyxcbiAgICAgIHRoaXMuZHJvcGRvd25EaXNwb3NlLmJpbmQodGhpcyksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBibG9jayBkaXNwbGF5IGFuZCBlZGl0b3IgZHJvcGRvd24gd2hlbiB0aGUgZmllbGQgcmUtcmVuZGVycy5cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcmVuZGVyXygpIHtcbiAgICBzdXBlci5yZW5kZXJfKCk7XG5cbiAgICBpZiAoIXRoaXMuZ2V0VmFsdWUoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmJsb2NrRGlzcGxheVBpeGVscykge1xuICAgICAgdGhpcy5mb3JBbGxDZWxscygociwgYykgPT4ge1xuICAgICAgICBjb25zdCBwaXhlbCA9IHRoaXMuZ2V0UGl4ZWwociwgYyk7XG5cbiAgICAgICAgaWYgKHRoaXMuYmxvY2tEaXNwbGF5UGl4ZWxzKSB7XG4gICAgICAgICAgdGhpcy5ibG9ja0Rpc3BsYXlQaXhlbHNbcl1bY10uc3R5bGUuZmlsbCA9IHBpeGVsXG4gICAgICAgICAgICA/IHRoaXMucGl4ZWxDb2xvdXJzLmZpbGxlZFxuICAgICAgICAgICAgOiB0aGlzLnBpeGVsQ29sb3Vycy5lbXB0eTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lZGl0b3JQaXhlbHMpIHtcbiAgICAgICAgICB0aGlzLmVkaXRvclBpeGVsc1tyXVtjXS5zdHlsZS5iYWNrZ3JvdW5kID0gcGl4ZWxcbiAgICAgICAgICAgID8gdGhpcy5waXhlbENvbG91cnMuZmlsbGVkXG4gICAgICAgICAgICA6IHRoaXMucGl4ZWxDb2xvdXJzLmVtcHR5O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBmaWVsZCBpcyBlZGl0YWJsZS5cbiAgICpcbiAgICogQHJldHVybnMgVHJ1ZSBzaW5jZSBpdCBpcyBhbHdheXMgZWRpdGFibGUuXG4gICAqL1xuICBvdmVycmlkZSB1cGRhdGVFZGl0YWJsZSgpIHtcbiAgICBjb25zdCBlZGl0YWJsZSA9IHN1cGVyLnVwZGF0ZUVkaXRhYmxlKCk7XG4gICAgLy8gQmxvY2tseS5GaWVsZCdzIGltcGxlbWVudGF0aW9uIHNldHMgdGhlc2UgY2xhc3NlcyBhcyBhcHByb3ByaWF0ZSwgYnV0XG4gICAgLy8gc2luY2UgdGhpcyBmaWVsZCBoYXMgbm8gdGV4dCB0aGV5IGp1c3QgbWVzcyB1cCB0aGUgcmVuZGVyaW5nIG9mIHRoZSBncmlkXG4gICAgLy8gbGluZXMuXG4gICAgY29uc3Qgc3ZnUm9vdCA9IHRoaXMuZ2V0U3ZnUm9vdCgpO1xuICAgIGlmIChzdmdSb290KSB7XG4gICAgICBCbG9ja2x5LnV0aWxzLmRvbS5yZW1vdmVDbGFzcyhzdmdSb290LCAnYmxvY2tseU5vbkVkaXRhYmxlVGV4dCcpO1xuICAgICAgQmxvY2tseS51dGlscy5kb20ucmVtb3ZlQ2xhc3Moc3ZnUm9vdCwgJ2Jsb2NrbHlFZGl0YWJsZVRleHQnKTtcbiAgICB9XG4gICAgcmV0dXJuIGVkaXRhYmxlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHJlY3RhbmdsZSBidWlsdCBvdXQgb2YgZGltZW5zaW9ucyBtYXRjaGluZyBTVkcncyA8Zz4gZWxlbWVudC5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgcmVjdGFuZ2xlIG9mIHNhbWUgc2l6ZSBhcyB0aGUgU1ZHIGVsZW1lbnQuXG4gICAqL1xuICBvdmVycmlkZSBnZXRTY2FsZWRCQm94KCkge1xuICAgIGNvbnN0IGJvdW5kaW5nQm94ID0gdGhpcy5nZXRTdmdSb290KCk/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmICghYm91bmRpbmdCb3gpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHJpZWQgdG8gcmV0cmlldmUgYSBib3VuZGluZyBib3ggd2l0aG91dCBhIHJlY3QnKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBCbG9ja2x5LnV0aWxzLlJlY3QoXG4gICAgICBib3VuZGluZ0JveC50b3AsXG4gICAgICBib3VuZGluZ0JveC5ib3R0b20sXG4gICAgICBib3VuZGluZ0JveC5sZWZ0LFxuICAgICAgYm91bmRpbmdCb3gucmlnaHQsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBiaXRtYXAgZWRpdG9yIGFuZCBhZGQgZXZlbnQgbGlzdGVuZXJzLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgbmV3bHkgY3JlYXRlZCBkcm9wZG93biBtZW51LlxuICAgKi9cbiAgcHJpdmF0ZSBkcm9wZG93bkNyZWF0ZSgpIHtcbiAgICBjb25zdCBkcm9wZG93bkVkaXRvciA9IHRoaXMuY3JlYXRlRWxlbWVudFdpdGhDbGFzc25hbWUoXG4gICAgICAnZGl2JyxcbiAgICAgICdkcm9wZG93bkVkaXRvcicsXG4gICAgKTtcbiAgICBpZiAodGhpcy5idXR0b25PcHRpb25zLnJhbmRvbWl6ZSB8fCB0aGlzLmJ1dHRvbk9wdGlvbnMuY2xlYXIpIHtcbiAgICAgIGRyb3Bkb3duRWRpdG9yLmNsYXNzTGlzdC5hZGQoJ2hhcy1idXR0b25zJyk7XG4gICAgfVxuICAgIGNvbnN0IHBpeGVsQ29udGFpbmVyID0gdGhpcy5jcmVhdGVFbGVtZW50V2l0aENsYXNzbmFtZShcbiAgICAgICdkaXYnLFxuICAgICAgJ3BpeGVsQ29udGFpbmVyJyxcbiAgICApO1xuICAgIGRyb3Bkb3duRWRpdG9yLmFwcGVuZENoaWxkKHBpeGVsQ29udGFpbmVyKTtcblxuICAgIC8vIFRoaXMgcHJldmVudHMgdGhlIG5vcm1hbCBtYXgtaGVpZ2h0IGZyb20gYWRkaW5nIGEgc2Nyb2xsIGJhciBmb3IgbGFyZ2UgaW1hZ2VzLlxuICAgIEJsb2NrbHkuRHJvcERvd25EaXYuZ2V0Q29udGVudERpdigpLmNsYXNzTGlzdC5hZGQoJ2NvbnRhaW5zLWJpdG1hcC1lZGl0b3InKTtcblxuICAgIHRoaXMuYmluZEV2ZW50KGRyb3Bkb3duRWRpdG9yLCAnbW91c2V1cCcsIHRoaXMub25Nb3VzZVVwKTtcbiAgICB0aGlzLmJpbmRFdmVudChkcm9wZG93bkVkaXRvciwgJ21vdXNlbGVhdmUnLCB0aGlzLm9uTW91c2VVcCk7XG4gICAgdGhpcy5iaW5kRXZlbnQoZHJvcGRvd25FZGl0b3IsICdkcmFnc3RhcnQnLCAoZTogRXZlbnQpID0+IHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuZWRpdG9yUGl4ZWxzID0gW107XG4gICAgZm9yIChsZXQgciA9IDA7IHIgPCB0aGlzLmltZ0hlaWdodDsgcisrKSB7XG4gICAgICB0aGlzLmVkaXRvclBpeGVscy5wdXNoKFtdKTtcbiAgICAgIGNvbnN0IHJvd0RpdiA9IHRoaXMuY3JlYXRlRWxlbWVudFdpdGhDbGFzc25hbWUoJ2RpdicsICdwaXhlbFJvdycpO1xuICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCB0aGlzLmltZ1dpZHRoOyBjKyspIHtcbiAgICAgICAgLy8gQWRkIHRoZSBidXR0b24gdG8gdGhlIFVJIGFuZCBzYXZlIGEgcmVmZXJlbmNlIHRvIGl0XG4gICAgICAgIGNvbnN0IGJ1dHRvbiA9IHRoaXMuY3JlYXRlRWxlbWVudFdpdGhDbGFzc25hbWUoJ2RpdicsICdwaXhlbEJ1dHRvbicpO1xuICAgICAgICB0aGlzLmVkaXRvclBpeGVsc1tyXS5wdXNoKGJ1dHRvbik7XG4gICAgICAgIHJvd0Rpdi5hcHBlbmRDaGlsZChidXR0b24pO1xuXG4gICAgICAgIC8vIExvYWQgdGhlIGN1cnJlbnQgcGl4ZWwgY29sb3VyXG4gICAgICAgIGNvbnN0IGlzT24gPSB0aGlzLmdldFBpeGVsKHIsIGMpO1xuICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZCA9IGlzT25cbiAgICAgICAgICA/IHRoaXMucGl4ZWxDb2xvdXJzLmZpbGxlZFxuICAgICAgICAgIDogdGhpcy5waXhlbENvbG91cnMuZW1wdHk7XG5cbiAgICAgICAgLy8gSGFuZGxlIGNsaWNraW5nIGEgcGl4ZWxcbiAgICAgICAgdGhpcy5iaW5kRXZlbnQoYnV0dG9uLCAnbW91c2Vkb3duJywgKCkgPT4ge1xuICAgICAgICAgIHRoaXMub25Nb3VzZURvd25JblBpeGVsKHIsIGMpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgZHJhZ2dpbmcgaW50byBhIHBpeGVsIHdoZW4gbW91c2UgaXMgZG93blxuICAgICAgICB0aGlzLmJpbmRFdmVudChidXR0b24sICdtb3VzZWVudGVyJywgKCkgPT4ge1xuICAgICAgICAgIHRoaXMub25Nb3VzZUVudGVyUGl4ZWwociwgYyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcGl4ZWxDb250YWluZXIuYXBwZW5kQ2hpbGQocm93RGl2KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgY29udHJvbCBidXR0b25zIGJlbG93IHRoZSBwaXhlbCBncmlkXG4gICAgaWYgKHRoaXMuYnV0dG9uT3B0aW9ucy5yYW5kb21pemUpIHtcbiAgICAgIHRoaXMuYWRkQ29udHJvbEJ1dHRvbihcbiAgICAgICAgZHJvcGRvd25FZGl0b3IsXG4gICAgICAgIEJsb2NrbHkuTXNnWydCVVRUT05fTEFCRUxfUkFORE9NSVpFJ10sXG4gICAgICAgIHRoaXMucmFuZG9taXplUGl4ZWxzLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYnV0dG9uT3B0aW9ucy5jbGVhcikge1xuICAgICAgdGhpcy5hZGRDb250cm9sQnV0dG9uKFxuICAgICAgICBkcm9wZG93bkVkaXRvcixcbiAgICAgICAgQmxvY2tseS5Nc2dbJ0JVVFRPTl9MQUJFTF9DTEVBUiddLFxuICAgICAgICB0aGlzLmNsZWFyUGl4ZWxzLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5ibG9ja0Rpc3BsYXlQaXhlbHMpIHtcbiAgICAgIHRoaXMuZm9yQWxsQ2VsbHMoKHIsIGMpID0+IHtcbiAgICAgICAgY29uc3QgcGl4ZWwgPSB0aGlzLmdldFBpeGVsKHIsIGMpO1xuICAgICAgICBpZiAodGhpcy5lZGl0b3JQaXhlbHMpIHtcbiAgICAgICAgICB0aGlzLmVkaXRvclBpeGVsc1tyXVtjXS5zdHlsZS5iYWNrZ3JvdW5kID0gcGl4ZWxcbiAgICAgICAgICAgID8gdGhpcy5waXhlbENvbG91cnMuZmlsbGVkXG4gICAgICAgICAgICA6IHRoaXMucGl4ZWxDb2xvdXJzLmVtcHR5O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTdG9yZSB0aGUgaW5pdGlhbCB2YWx1ZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGVkaXQuXG4gICAgdGhpcy5pbml0aWFsVmFsdWUgPSB0aGlzLmdldFZhbHVlKCk7XG5cbiAgICByZXR1cm4gZHJvcGRvd25FZGl0b3I7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgdGhlIG9uLWJsb2NrIGRpc3BsYXkuXG4gICAqL1xuICBvdmVycmlkZSBpbml0VmlldygpIHtcbiAgICB0aGlzLmJsb2NrRGlzcGxheVBpeGVscyA9IFtdO1xuICAgIGZvciAobGV0IHIgPSAwOyByIDwgdGhpcy5pbWdIZWlnaHQ7IHIrKykge1xuICAgICAgY29uc3Qgcm93ID0gW107XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IHRoaXMuaW1nV2lkdGg7IGMrKykge1xuICAgICAgICBjb25zdCBzcXVhcmUgPSBCbG9ja2x5LnV0aWxzLmRvbS5jcmVhdGVTdmdFbGVtZW50KFxuICAgICAgICAgICdyZWN0JyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB4OiBjICogdGhpcy5waXhlbFNpemUsXG4gICAgICAgICAgICB5OiByICogdGhpcy5waXhlbFNpemUsXG4gICAgICAgICAgICB3aWR0aDogdGhpcy5waXhlbFNpemUsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMucGl4ZWxTaXplLFxuICAgICAgICAgICAgZmlsbDogdGhpcy5waXhlbENvbG91cnMuZW1wdHksXG4gICAgICAgICAgICBmaWxsX29wYWNpdHk6IDEsIC8vIGVzbGludC1kaXNhYmxlLWxpbmVcbiAgICAgICAgICB9LFxuICAgICAgICAgIHRoaXMuZ2V0U3ZnUm9vdCgpLFxuICAgICAgICApO1xuICAgICAgICByb3cucHVzaChzcXVhcmUpO1xuICAgICAgfVxuICAgICAgdGhpcy5ibG9ja0Rpc3BsYXlQaXhlbHMucHVzaChyb3cpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBzaXplIG9mIHRoZSBibG9jayBiYXNlZCBvbiB0aGUgc2l6ZSBvZiB0aGUgdW5kZXJseWluZyBpbWFnZS5cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgdXBkYXRlU2l6ZV8oKSB7XG4gICAge1xuICAgICAgY29uc3QgbmV3V2lkdGggPSB0aGlzLnBpeGVsU2l6ZSAqIHRoaXMuaW1nV2lkdGg7XG4gICAgICBjb25zdCBuZXdIZWlnaHQgPSB0aGlzLnBpeGVsU2l6ZSAqIHRoaXMuaW1nSGVpZ2h0O1xuICAgICAgaWYgKHRoaXMuYm9yZGVyUmVjdF8pIHtcbiAgICAgICAgdGhpcy5ib3JkZXJSZWN0Xy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgU3RyaW5nKG5ld1dpZHRoKSk7XG4gICAgICAgIHRoaXMuYm9yZGVyUmVjdF8uc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBTdHJpbmcobmV3SGVpZ2h0KSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2l6ZV8ud2lkdGggPSBuZXdXaWR0aDtcbiAgICAgIHRoaXMuc2l6ZV8uaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgY29udHJvbCBidXR0b24uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJlbnQgUGFyZW50IEhUTUwgZWxlbWVudCB0byB3aGljaCBjb250cm9sIGJ1dHRvbiB3aWxsIGJlIGFkZGVkLlxuICAgKiBAcGFyYW0gYnV0dG9uVGV4dCBUZXh0IG9mIHRoZSBjb250cm9sIGJ1dHRvbi5cbiAgICogQHBhcmFtIG9uQ2xpY2sgQ2FsbGJhY2sgdGhhdCB3aWxsIGJlIGF0dGFjaGVkIHRvIHRoZSBjb250cm9sIGJ1dHRvbi5cbiAgICovXG4gIHByaXZhdGUgYWRkQ29udHJvbEJ1dHRvbihcbiAgICBwYXJlbnQ6IEhUTUxFbGVtZW50LFxuICAgIGJ1dHRvblRleHQ6IHN0cmluZyxcbiAgICBvbkNsaWNrOiAoKSA9PiB2b2lkLFxuICApIHtcbiAgICBjb25zdCBidXR0b24gPSB0aGlzLmNyZWF0ZUVsZW1lbnRXaXRoQ2xhc3NuYW1lKCdidXR0b24nLCAnY29udHJvbEJ1dHRvbicpO1xuICAgIGJ1dHRvbi5pbm5lclRleHQgPSBidXR0b25UZXh0O1xuICAgIHBhcmVudC5hcHBlbmRDaGlsZChidXR0b24pO1xuICAgIHRoaXMuYmluZEV2ZW50KGJ1dHRvbiwgJ2NsaWNrJywgb25DbGljayk7XG4gIH1cblxuICAvKipcbiAgICogRGlzcG9zZXMgb2YgZXZlbnRzIGJlbG9uZ2luZyB0byB0aGUgYml0bWFwIGVkaXRvci5cbiAgICovXG4gIHByaXZhdGUgZHJvcGRvd25EaXNwb3NlKCkge1xuICAgIGlmIChcbiAgICAgIHRoaXMuZ2V0U291cmNlQmxvY2soKSAmJlxuICAgICAgdGhpcy5pbml0aWFsVmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHRoaXMuaW5pdGlhbFZhbHVlICE9PSB0aGlzLmdldFZhbHVlKClcbiAgICApIHtcbiAgICAgIEJsb2NrbHkuRXZlbnRzLmZpcmUoXG4gICAgICAgIG5ldyAoQmxvY2tseS5FdmVudHMuZ2V0KEJsb2NrbHkuRXZlbnRzLkJMT0NLX0NIQU5HRSkpKFxuICAgICAgICAgIHRoaXMuc291cmNlQmxvY2tfLFxuICAgICAgICAgICdmaWVsZCcsXG4gICAgICAgICAgdGhpcy5uYW1lIHx8IG51bGwsXG4gICAgICAgICAgdGhpcy5pbml0aWFsVmFsdWUsXG4gICAgICAgICAgdGhpcy5nZXRWYWx1ZSgpLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIHRoaXMuYm91bmRFdmVudHMpIHtcbiAgICAgIEJsb2NrbHkuYnJvd3NlckV2ZW50cy51bmJpbmQoZXZlbnQpO1xuICAgIH1cbiAgICB0aGlzLmJvdW5kRXZlbnRzLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5lZGl0b3JQaXhlbHMgPSBudWxsO1xuICAgIC8vIFNldCB0aGlzLmluaXRpYWxWYWx1ZSBiYWNrIHRvIG51bGwuXG4gICAgdGhpcy5pbml0aWFsVmFsdWUgPSBudWxsO1xuXG4gICAgQmxvY2tseS5Ecm9wRG93bkRpdi5nZXRDb250ZW50RGl2KCkuY2xhc3NMaXN0LnJlbW92ZShcbiAgICAgICdjb250YWlucy1iaXRtYXAtZWRpdG9yJyxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYW4gYXJyYXkgb2YgemVyb3Mgd2l0aCB0aGUgc3BlY2lmaWVkIHdpZHRoIGFuZCBoZWlnaHQuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBuZXcgdmFsdWUuXG4gICAqL1xuICBwcml2YXRlIGdldEVtcHR5QXJyYXkoKTogbnVtYmVyW11bXSB7XG4gICAgY29uc3QgbmV3VmFsOiBudW1iZXJbXVtdID0gW107XG4gICAgZm9yIChsZXQgciA9IDA7IHIgPCB0aGlzLmltZ0hlaWdodDsgcisrKSB7XG4gICAgICBuZXdWYWwucHVzaChbXSk7XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IHRoaXMuaW1nV2lkdGg7IGMrKykge1xuICAgICAgICBuZXdWYWxbcl0ucHVzaCgwKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ld1ZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiBhIG1vdXNlZG93biBldmVudCBvY2N1cnMgd2l0aGluIHRoZSBib3VuZHMgb2YgYSBwaXhlbC5cbiAgICpcbiAgICogQHBhcmFtIHIgUm93IG51bWJlciBvZiBncmlkLlxuICAgKiBAcGFyYW0gYyBDb2x1bW4gbnVtYmVyIG9mIGdyaWQuXG4gICAqL1xuICBwcml2YXRlIG9uTW91c2VEb3duSW5QaXhlbChyOiBudW1iZXIsIGM6IG51bWJlcikge1xuICAgIC8vIFRvZ2dsZSB0aGF0IHBpeGVsIHRvIHRoZSBvcHBvc2l0ZSBvZiBpdHMgdmFsdWVcbiAgICBjb25zdCBuZXdQaXhlbFZhbHVlID0gMSAtIHRoaXMuZ2V0UGl4ZWwociwgYyk7XG4gICAgdGhpcy5zZXRQaXhlbChyLCBjLCBuZXdQaXhlbFZhbHVlKTtcbiAgICB0aGlzLm1vdXNlSXNEb3duID0gdHJ1ZTtcbiAgICB0aGlzLnZhbFRvUGFpbnRXaXRoID0gbmV3UGl4ZWxWYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgbW91c2UgZHJhZ3Mgb3ZlciBhIHBpeGVsIGluIHRoZSBlZGl0b3IuXG4gICAqXG4gICAqIEBwYXJhbSByIFJvdyBudW1iZXIgb2YgZ3JpZC5cbiAgICogQHBhcmFtIGMgQ29sdW1uIG51bWJlciBvZiBncmlkLlxuICAgKi9cbiAgcHJpdmF0ZSBvbk1vdXNlRW50ZXJQaXhlbChyOiBudW1iZXIsIGM6IG51bWJlcikge1xuICAgIGlmICghdGhpcy5tb3VzZUlzRG93bikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0aGlzLnZhbFRvUGFpbnRXaXRoICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHRoaXMuZ2V0UGl4ZWwociwgYykgIT09IHRoaXMudmFsVG9QYWludFdpdGhcbiAgICApIHtcbiAgICAgIHRoaXMuc2V0UGl4ZWwociwgYywgdGhpcy52YWxUb1BhaW50V2l0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyBtb3VzZSBzdGF0ZSAoZS5nLiBBZnRlciBlaXRoZXIgYSBtb3VzZXVwIGV2ZW50IG9yIGlmIHRoZSBtb3VzZVxuICAgKiBsZWF2ZXMgdGhlIGVkaXRvciBhcmVhKS5cbiAgICovXG4gIHByaXZhdGUgb25Nb3VzZVVwKCkge1xuICAgIHRoaXMubW91c2VJc0Rvd24gPSBmYWxzZTtcbiAgICB0aGlzLnZhbFRvUGFpbnRXaXRoID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYWxsIHRoZSBwaXhlbHMgaW4gdGhlIGltYWdlIHRvIGEgcmFuZG9tIHZhbHVlLlxuICAgKi9cbiAgcHJpdmF0ZSByYW5kb21pemVQaXhlbHMoKSB7XG4gICAgY29uc3QgZ2V0UmFuZEJpbmFyeSA9ICgpID0+IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDIpO1xuICAgIHRoaXMuZm9yQWxsQ2VsbHMoKHIsIGMpID0+IHtcbiAgICAgIHRoaXMuc2V0UGl4ZWwociwgYywgZ2V0UmFuZEJpbmFyeSgpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGFsbCB0aGUgcGl4ZWxzIHRvIDAuXG4gICAqL1xuICBwcml2YXRlIGNsZWFyUGl4ZWxzKCkge1xuICAgIGNvbnN0IGNsZWFyZWQgPSB0aGlzLmdldEVtcHR5QXJyYXkoKTtcbiAgICB0aGlzLmZpcmVJbnRlcm1lZGlhdGVDaGFuZ2VFdmVudChjbGVhcmVkKTtcbiAgICB0aGlzLnNldFZhbHVlKGNsZWFyZWQsIGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB2YWx1ZSBvZiBhIHBhcnRpY3VsYXIgcGl4ZWwuXG4gICAqXG4gICAqIEBwYXJhbSByIFJvdyBudW1iZXIgb2YgZ3JpZC5cbiAgICogQHBhcmFtIGMgQ29sdW1uIG51bWJlciBvZiBncmlkLlxuICAgKiBAcGFyYW0gbmV3VmFsdWUgVmFsdWUgb2YgdGhlIHBpeGVsLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRQaXhlbChyOiBudW1iZXIsIGM6IG51bWJlciwgbmV3VmFsdWU6IG51bWJlcikge1xuICAgIGNvbnN0IG5ld0dyaWQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMuZ2V0VmFsdWUoKSkpO1xuICAgIG5ld0dyaWRbcl1bY10gPSBuZXdWYWx1ZTtcbiAgICB0aGlzLmZpcmVJbnRlcm1lZGlhdGVDaGFuZ2VFdmVudChuZXdHcmlkKTtcbiAgICB0aGlzLnNldFZhbHVlKG5ld0dyaWQsIGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UGl4ZWwocm93OiBudW1iZXIsIGNvbHVtbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcbiAgICBpZiAoIXZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdBdHRlbXB0ZWQgdG8gcmV0cmlldmUgYSBwaXhlbCB2YWx1ZSB3aGVuIG5vIHZhbHVlIGlzIHNldCcsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZVtyb3ddW2NvbHVtbl07XG4gIH1cblxuICAvKipcbiAgICogQ2FsbHMgYSBnaXZlbiBmdW5jdGlvbiBmb3IgYWxsIGNlbGxzIGluIHRoZSBpbWFnZSwgd2l0aCB0aGUgY2VsbFxuICAgKiBjb29yZGluYXRlcyBhcyB0aGUgYXJndW1lbnRzLlxuICAgKlxuICAgKiBAcGFyYW0gZnVuYyBBIGZ1bmN0aW9uIHRvIGJlIGFwcGxpZWQuXG4gICAqL1xuICBwcml2YXRlIGZvckFsbENlbGxzKGZ1bmM6IChyb3c6IG51bWJlciwgY29sOiBudW1iZXIpID0+IHZvaWQpIHtcbiAgICBmb3IgKGxldCByID0gMDsgciA8IHRoaXMuaW1nSGVpZ2h0OyByKyspIHtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgdGhpcy5pbWdXaWR0aDsgYysrKSB7XG4gICAgICAgIGZ1bmMociwgYyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgdHlwZSBhbmQgY2xhc3MuXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50VHlwZSBUeXBlIG9mIGh0bWwgZWxlbWVudC5cbiAgICogQHBhcmFtIGNsYXNzTmFtZSBDbGFzc05hbWUgb2YgaHRtbCBlbGVtZW50LlxuICAgKiBAcmV0dXJucyBUaGUgY3JlYXRlZCBlbGVtZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVFbGVtZW50V2l0aENsYXNzbmFtZShlbGVtZW50VHlwZTogc3RyaW5nLCBjbGFzc05hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IG5ld0VsdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoZWxlbWVudFR5cGUpO1xuICAgIG5ld0VsdC5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgcmV0dXJuIG5ld0VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCaW5kcyBhbiBldmVudCBsaXN0ZW5lciB0byB0aGUgc3BlY2lmaWVkIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50IFNwZWNpZmllZCBlbGVtZW50LlxuICAgKiBAcGFyYW0gZXZlbnROYW1lIE5hbWUgb2YgdGhlIGV2ZW50IHRvIGJpbmQuXG4gICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gc3BlY2lmaWVkIGV2ZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBiaW5kRXZlbnQoXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgZXZlbnROYW1lOiBzdHJpbmcsXG4gICAgY2FsbGJhY2s6IChlOiBFdmVudCkgPT4gdm9pZCxcbiAgKSB7XG4gICAgdGhpcy5ib3VuZEV2ZW50cy5wdXNoKFxuICAgICAgQmxvY2tseS5icm93c2VyRXZlbnRzLmNvbmRpdGlvbmFsQmluZChlbGVtZW50LCBldmVudE5hbWUsIHRoaXMsIGNhbGxiYWNrKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBmaXJlSW50ZXJtZWRpYXRlQ2hhbmdlRXZlbnQobmV3VmFsdWU6IG51bWJlcltdW10pIHtcbiAgICBpZiAodGhpcy5nZXRTb3VyY2VCbG9jaygpKSB7XG4gICAgICBCbG9ja2x5LkV2ZW50cy5maXJlKFxuICAgICAgICBuZXcgKEJsb2NrbHkuRXZlbnRzLmdldChcbiAgICAgICAgICBCbG9ja2x5LkV2ZW50cy5CTE9DS19GSUVMRF9JTlRFUk1FRElBVEVfQ0hBTkdFLFxuICAgICAgICApKSh0aGlzLmdldFNvdXJjZUJsb2NrKCksIHRoaXMubmFtZSB8fCBudWxsLCB0aGlzLmdldFZhbHVlKCksIG5ld1ZhbHVlKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbmludGVyZmFjZSBCdXR0b25zIHtcbiAgcmVhZG9ubHkgcmFuZG9taXplOiBib29sZWFuO1xuICByZWFkb25seSBjbGVhcjogYm9vbGVhbjtcbn1cbmludGVyZmFjZSBQaXhlbENvbG91cnMge1xuICByZWFkb25seSBlbXB0eTogc3RyaW5nO1xuICByZWFkb25seSBmaWxsZWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaWVsZEJpdG1hcEZyb21Kc29uQ29uZmlnIGV4dGVuZHMgQmxvY2tseS5GaWVsZENvbmZpZyB7XG4gIHZhbHVlPzogbnVtYmVyW11bXTtcbiAgd2lkdGg/OiBudW1iZXI7XG4gIGhlaWdodD86IG51bWJlcjtcbiAgYnV0dG9ucz86IEJ1dHRvbnM7XG4gIGZpZWxkSGVpZ2h0PzogbnVtYmVyO1xuICBjb2xvdXJzPzogUGl4ZWxDb2xvdXJzO1xufVxuXG5CbG9ja2x5LmZpZWxkUmVnaXN0cnkucmVnaXN0ZXIoJ2ZpZWxkX2JpdG1hcCcsIEZpZWxkQml0bWFwKTtcblxuLyoqXG4gKiBDU1MgZm9yIGJpdG1hcCBmaWVsZC5cbiAqL1xuQmxvY2tseS5Dc3MucmVnaXN0ZXIoYFxuLmRyb3Bkb3duRWRpdG9yIHtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG4uZHJvcGRvd25FZGl0b3IuaGFzLWJ1dHRvbnMge1xuICBtYXJnaW4tYm90dG9tOiAyMHB4O1xufVxuLnBpeGVsQ29udGFpbmVyIHtcbiAgbWFyZ2luOiAyMHB4O1xufVxuLnBpeGVsUm93IHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgcGFkZGluZzogMDtcbiAgbWFyZ2luOiAwO1xuICBoZWlnaHQ6ICR7REVGQVVMVF9QSVhFTF9TSVpFfVxufVxuLnBpeGVsQnV0dG9uIHtcbiAgd2lkdGg6ICR7REVGQVVMVF9QSVhFTF9TSVpFfXB4O1xuICBoZWlnaHQ6ICR7REVGQVVMVF9QSVhFTF9TSVpFfXB4O1xuICBib3JkZXI6IDFweCBzb2xpZCAjMDAwO1xufVxuLnBpeGVsRGlzcGxheSB7XG4gIHdoaXRlLXNwYWNlOnByZS13cmFwO1xufVxuLmNvbnRyb2xCdXR0b24ge1xuICBtYXJnaW46IDVweCAwO1xufVxuLmJsb2NrbHlEcm9wRG93bkNvbnRlbnQuY29udGFpbnMtYml0bWFwLWVkaXRvciB7XG4gIG1heC1oZWlnaHQ6IG5vbmU7XG59XG5gKTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/field-bitmap.ts\n");
/***/ }),
diff --git a/plugins/field-bitmap/test/index.html b/plugins/field-bitmap/test/index.html
index ac7f2245ac..3df35bae64 100644
--- a/plugins/field-bitmap/test/index.html
+++ b/plugins/field-bitmap/test/index.html
@@ -33,7 +33,7 @@
@blockly/field-bitmap Demo
A field that lets users input a pixel grid with their mouse.
- 4.1.0
+ 4.1.1
View code
View on npm