diff --git a/Project.toml b/Project.toml
index f34dbc66..0b0cefe7 100644
--- a/Project.toml
+++ b/Project.toml
@@ -9,4 +9,4 @@ Dash = "1b08a953-4be3-4667-9a23-3db579824955"
[compat]
julia = "1.2"
-Dash = "0.1.3"
+Dash = "0.1.3, 1.0"
diff --git a/R/cytoCytoscape.R b/R/cytoCytoscape.R
index 5c062452..afdf9831 100644
--- a/R/cytoCytoscape.R
+++ b/R/cytoCytoscape.R
@@ -1,5 +1,6 @@
# AUTO GENERATED FILE - DO NOT EDIT
+#' @export
cytoCytoscape <- function(id=NULL, autoRefreshLayout=NULL, autolock=NULL, autoungrabify=NULL, autounselectify=NULL, boxSelectionEnabled=NULL, className=NULL, elements=NULL, generateImage=NULL, imageData=NULL, layout=NULL, maxZoom=NULL, minZoom=NULL, mouseoverEdgeData=NULL, mouseoverNodeData=NULL, pan=NULL, panningEnabled=NULL, responsive=NULL, selectedEdgeData=NULL, selectedNodeData=NULL, style=NULL, stylesheet=NULL, tapEdge=NULL, tapEdgeData=NULL, tapNode=NULL, tapNodeData=NULL, userPanningEnabled=NULL, userZoomingEnabled=NULL, zoom=NULL, zoomingEnabled=NULL) {
props <- list(id=id, autoRefreshLayout=autoRefreshLayout, autolock=autolock, autoungrabify=autoungrabify, autounselectify=autounselectify, boxSelectionEnabled=boxSelectionEnabled, className=className, elements=elements, generateImage=generateImage, imageData=imageData, layout=layout, maxZoom=maxZoom, minZoom=minZoom, mouseoverEdgeData=mouseoverEdgeData, mouseoverNodeData=mouseoverNodeData, pan=pan, panningEnabled=panningEnabled, responsive=responsive, selectedEdgeData=selectedEdgeData, selectedNodeData=selectedNodeData, style=style, stylesheet=stylesheet, tapEdge=tapEdge, tapEdgeData=tapEdgeData, tapNode=tapNode, tapNodeData=tapNodeData, userPanningEnabled=userPanningEnabled, userZoomingEnabled=userZoomingEnabled, zoom=zoom, zoomingEnabled=zoomingEnabled)
diff --git a/README.md b/README.md
index 875226a8..dc0bb58c 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,18 @@ app.layout = html.Div([
Calling `cyto.load_extra_layouts()` also enables generating SVG images.
+### Panzoom
+
+This version contains the [panzoom](https://github.com/cytoscape/cytoscape.js-panzoom) extension to the dash cytoscape app. Note that you still need to add "Font Awesome" to your app's `external_stylesheets`. For example:
+
+```
+ {
+ 'href': 'https://use.fontawesome.com/releases/v5.8.1/css/all.css',
+ 'rel': 'stylesheet',
+ 'integrity': 'sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf',
+ 'crossorigin': 'anonymous'
+ },
+```
## Getting Started in R
diff --git a/dash_cytoscape/dash_cytoscape.dev.js b/dash_cytoscape/dash_cytoscape.dev.js
index 735d0c81..1d6e333d 100644
--- a/dash_cytoscape/dash_cytoscape.dev.js
+++ b/dash_cytoscape/dash_cytoscape.dev.js
@@ -87,6 +87,50 @@ window["dash_cytoscape"] =
/************************************************************************/
/******/ ({
+/***/ "./node_modules/css-loader/index.js!./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css":
+/*!*******************************************************************************************!*\
+ !*** ./node_modules/css-loader!./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css ***!
+ \*******************************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("exports = module.exports = __webpack_require__(/*! ../css-loader/lib/css-base.js */ \"./node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.i, \".cy-panzoom {\\n\\tposition: absolute;\\n\\tfont-size: 12px;\\n\\tcolor: #fff;\\n\\tfont-family: arial, helvetica, sans-serif;\\n\\tline-height: 1;\\n\\tcolor: #666;\\n\\tfont-size: 11px;\\n\\tz-index: 99999;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-zoom-button {\\n\\tcursor: pointer;\\n\\tpadding: 3px;\\n\\ttext-align: center;\\n\\tposition: absolute;\\n\\tborder-radius: 3px;\\n\\twidth: 10px;\\n\\theight: 10px;\\n\\tleft: 16px;\\n\\tbackground: #fff;\\n\\tborder: 1px solid #999;\\n\\tmargin-left: -1px;\\n\\tmargin-top: -1px;\\n\\tz-index: 1;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-zoom-button:active,\\n.cy-panzoom-slider-handle:active,\\n.cy-panzoom-slider-handle.active {\\n\\tbackground: #ddd;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-button {\\n\\tposition: absolute;\\n\\tz-index: 1;\\n\\theight: 16px;\\n\\twidth: 16px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-reset {\\n\\ttop: 55px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-zoom-in {\\n\\ttop: 80px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-zoom-out {\\n\\ttop: 197px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-up {\\n\\ttop: 0;\\n\\tleft: 50%;\\n\\tmargin-left: -5px;\\n\\twidth: 0;\\n\\theight: 0;\\n\\tborder-left: 5px solid transparent;\\n\\tborder-right: 5px solid transparent;\\n\\tborder-bottom: 5px solid #666;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-down {\\n\\tbottom: 0;\\n\\tleft: 50%;\\n\\tmargin-left: -5px;\\n\\twidth: 0;\\n\\theight: 0;\\n\\tborder-left: 5px solid transparent;\\n\\tborder-right: 5px solid transparent;\\n\\tborder-top: 5px solid #666;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-left {\\n\\ttop: 50%;\\n\\tleft: 0;\\n\\tmargin-top: -5px;\\n\\twidth: 0;\\n\\theight: 0;\\n\\tborder-top: 5px solid transparent;\\n\\tborder-bottom: 5px solid transparent;\\n\\tborder-right: 5px solid #666;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-right {\\n\\ttop: 50%;\\n\\tright: 0;\\n\\tmargin-top: -5px;\\n\\twidth: 0;\\n\\theight: 0;\\n\\tborder-top: 5px solid transparent;\\n\\tborder-bottom: 5px solid transparent;\\n\\tborder-left: 5px solid #666;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-pan-indicator {\\n\\tposition: absolute;\\n\\tleft: 0;\\n\\ttop: 0;\\n\\twidth: 8px;\\n\\theight: 8px;\\n\\tborder-radius: 8px;\\n\\tbackground: #000;\\n\\tborder-radius: 8px;\\n\\tmargin-left: -5px;\\n\\tmargin-top: -5px;\\n\\tdisplay: none;\\n\\tz-index: 999;\\n\\topacity: 0.6;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-slider {\\n\\tposition: absolute;\\n\\ttop: 97px;\\n\\tleft: 17px;\\n\\theight: 100px;\\n\\twidth: 15px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-slider-background {\\n\\tposition: absolute;\\n\\ttop: 0;\\n\\twidth: 2px;\\n\\theight: 100px;\\n\\tleft: 5px;\\n\\tbackground: #fff;\\n\\tborder-left: 1px solid #999;\\n\\tborder-right: 1px solid #999;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-slider-handle {\\n\\tposition: absolute;\\n\\twidth: 16px;\\n\\theight: 8px;\\n\\tbackground: #fff;\\n\\tborder: 1px solid #999;\\n\\tborder-radius: 2px;\\n\\tmargin-left: -2px;\\n\\tz-index: 999;\\n\\tline-height: 8px;\\n\\tcursor: default;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-slider-handle .icon {\\n\\tmargin: 0 4px;\\n\\tline-height: 10px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-no-zoom-tick {\\n\\tposition: absolute;\\n\\tbackground: #666;\\n\\tborder: 1px solid #fff;\\n\\tborder-radius: 2px;\\n\\tmargin-left: -1px;\\n\\twidth: 8px;\\n\\theight: 2px;\\n\\tleft: 3px;\\n\\tz-index: 1;\\n\\tmargin-top: 3px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-panner {\\n\\tposition: absolute;\\n\\tleft: 5px;\\n\\ttop: 5px;\\n\\theight: 40px;\\n\\twidth: 40px;\\n\\tbackground: #fff;\\n\\tborder: 1px solid #999;\\n\\tborder-radius: 40px;\\n\\tmargin-left: -1px;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-panner-handle {\\n\\tposition: absolute;\\n\\tleft: 0;\\n\\ttop: 0;\\n\\toutline: none;\\n\\theight: 40px;\\n\\twidth: 40px;\\n\\tposition: absolute;\\n\\tz-index: 999;\\n\\tbox-sizing: content-box;\\n}\\n\\n.cy-panzoom-zoom-only .cy-panzoom-slider,\\n.cy-panzoom-zoom-only .cy-panzoom-panner {\\n\\tdisplay: none;\\n}\\n\\n.cy-panzoom-zoom-only .cy-panzoom-reset {\\n\\ttop: 20px;\\n}\\n\\n.cy-panzoom-zoom-only .cy-panzoom-zoom-in {\\n\\ttop: 45px;\\n}\\n\\n.cy-panzoom-zoom-only .cy-panzoom-zoom-out {\\n\\ttop: 70px;\\n}\\n\", \"\"]);\n\n// exports\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUtcGFuem9vbS9jeXRvc2NhcGUuanMtcGFuem9vbS5jc3M/ZjcxMiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQkFBMkIsbUJBQU8sQ0FBQyxnRkFBK0I7QUFDbEU7OztBQUdBO0FBQ0EsY0FBYyxRQUFTLGdCQUFnQix1QkFBdUIsb0JBQW9CLGdCQUFnQiw4Q0FBOEMsbUJBQW1CLGdCQUFnQixvQkFBb0IsbUJBQW1CLDRCQUE0QixHQUFHLDZCQUE2QixvQkFBb0IsaUJBQWlCLHVCQUF1Qix1QkFBdUIsdUJBQXVCLGdCQUFnQixpQkFBaUIsZUFBZSxxQkFBcUIsMkJBQTJCLHNCQUFzQixxQkFBcUIsZUFBZSw0QkFBNEIsR0FBRywwR0FBMEcscUJBQXFCLDRCQUE0QixHQUFHLDRCQUE0Qix1QkFBdUIsZUFBZSxpQkFBaUIsZ0JBQWdCLDRCQUE0QixHQUFHLHVCQUF1QixjQUFjLDRCQUE0QixHQUFHLHlCQUF5QixjQUFjLDRCQUE0QixHQUFHLDBCQUEwQixlQUFlLDRCQUE0QixHQUFHLHdCQUF3QixXQUFXLGNBQWMsc0JBQXNCLGFBQWEsY0FBYyx1Q0FBdUMsd0NBQXdDLGtDQUFrQyw0QkFBNEIsR0FBRywwQkFBMEIsY0FBYyxjQUFjLHNCQUFzQixhQUFhLGNBQWMsdUNBQXVDLHdDQUF3QywrQkFBK0IsNEJBQTRCLEdBQUcsMEJBQTBCLGFBQWEsWUFBWSxxQkFBcUIsYUFBYSxjQUFjLHNDQUFzQyx5Q0FBeUMsaUNBQWlDLDRCQUE0QixHQUFHLDJCQUEyQixhQUFhLGFBQWEscUJBQXFCLGFBQWEsY0FBYyxzQ0FBc0MseUNBQXlDLGdDQUFnQyw0QkFBNEIsR0FBRywrQkFBK0IsdUJBQXVCLFlBQVksV0FBVyxlQUFlLGdCQUFnQix1QkFBdUIscUJBQXFCLHVCQUF1QixzQkFBc0IscUJBQXFCLGtCQUFrQixpQkFBaUIsaUJBQWlCLDRCQUE0QixHQUFHLHdCQUF3Qix1QkFBdUIsY0FBYyxlQUFlLGtCQUFrQixnQkFBZ0IsNEJBQTRCLEdBQUcsbUNBQW1DLHVCQUF1QixXQUFXLGVBQWUsa0JBQWtCLGNBQWMscUJBQXFCLGdDQUFnQyxpQ0FBaUMsNEJBQTRCLEdBQUcsK0JBQStCLHVCQUF1QixnQkFBZ0IsZ0JBQWdCLHFCQUFxQiwyQkFBMkIsdUJBQXVCLHNCQUFzQixpQkFBaUIscUJBQXFCLG9CQUFvQiw0QkFBNEIsR0FBRyxxQ0FBcUMsa0JBQWtCLHNCQUFzQiw0QkFBNEIsR0FBRyw4QkFBOEIsdUJBQXVCLHFCQUFxQiwyQkFBMkIsdUJBQXVCLHNCQUFzQixlQUFlLGdCQUFnQixjQUFjLGVBQWUsb0JBQW9CLDRCQUE0QixHQUFHLHdCQUF3Qix1QkFBdUIsY0FBYyxhQUFhLGlCQUFpQixnQkFBZ0IscUJBQXFCLDJCQUEyQix3QkFBd0Isc0JBQXNCLDRCQUE0QixHQUFHLCtCQUErQix1QkFBdUIsWUFBWSxXQUFXLGtCQUFrQixpQkFBaUIsZ0JBQWdCLHVCQUF1QixpQkFBaUIsNEJBQTRCLEdBQUcseUZBQXlGLGtCQUFrQixHQUFHLDZDQUE2QyxjQUFjLEdBQUcsK0NBQStDLGNBQWMsR0FBRyxnREFBZ0QsY0FBYyxHQUFHOztBQUU5K0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY3NzLWxvYWRlci9pbmRleC5qcyEuL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUtcGFuem9vbS9jeXRvc2NhcGUuanMtcGFuem9vbS5jc3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiLi4vY3NzLWxvYWRlci9saWIvY3NzLWJhc2UuanNcIikoZmFsc2UpO1xuLy8gaW1wb3J0c1xuXG5cbi8vIG1vZHVsZVxuZXhwb3J0cy5wdXNoKFttb2R1bGUuaWQsIFwiLmN5LXBhbnpvb20ge1xcblxcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG5cXHRmb250LXNpemU6IDEycHg7XFxuXFx0Y29sb3I6ICNmZmY7XFxuXFx0Zm9udC1mYW1pbHk6IGFyaWFsLCBoZWx2ZXRpY2EsIHNhbnMtc2VyaWY7XFxuXFx0bGluZS1oZWlnaHQ6IDE7XFxuXFx0Y29sb3I6ICM2NjY7XFxuXFx0Zm9udC1zaXplOiAxMXB4O1xcblxcdHotaW5kZXg6IDk5OTk5O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS16b29tLWJ1dHRvbiB7XFxuXFx0Y3Vyc29yOiBwb2ludGVyO1xcblxcdHBhZGRpbmc6IDNweDtcXG5cXHR0ZXh0LWFsaWduOiBjZW50ZXI7XFxuXFx0cG9zaXRpb246IGFic29sdXRlO1xcblxcdGJvcmRlci1yYWRpdXM6IDNweDtcXG5cXHR3aWR0aDogMTBweDtcXG5cXHRoZWlnaHQ6IDEwcHg7XFxuXFx0bGVmdDogMTZweDtcXG5cXHRiYWNrZ3JvdW5kOiAjZmZmO1xcblxcdGJvcmRlcjogMXB4IHNvbGlkICM5OTk7XFxuXFx0bWFyZ2luLWxlZnQ6IC0xcHg7XFxuXFx0bWFyZ2luLXRvcDogLTFweDtcXG5cXHR6LWluZGV4OiAxO1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS16b29tLWJ1dHRvbjphY3RpdmUsXFxuLmN5LXBhbnpvb20tc2xpZGVyLWhhbmRsZTphY3RpdmUsXFxuLmN5LXBhbnpvb20tc2xpZGVyLWhhbmRsZS5hY3RpdmUge1xcblxcdGJhY2tncm91bmQ6ICNkZGQ7XFxuXFx0Ym94LXNpemluZzogY29udGVudC1ib3g7XFxufVxcblxcbi5jeS1wYW56b29tLXBhbi1idXR0b24ge1xcblxcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG5cXHR6LWluZGV4OiAxO1xcblxcdGhlaWdodDogMTZweDtcXG5cXHR3aWR0aDogMTZweDtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tcmVzZXQge1xcblxcdHRvcDogNTVweDtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tem9vbS1pbiB7XFxuXFx0dG9wOiA4MHB4O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS16b29tLW91dCB7XFxuXFx0dG9wOiAxOTdweDtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tcGFuLXVwIHtcXG5cXHR0b3A6IDA7XFxuXFx0bGVmdDogNTAlO1xcblxcdG1hcmdpbi1sZWZ0OiAtNXB4O1xcblxcdHdpZHRoOiAwO1xcblxcdGhlaWdodDogMDtcXG5cXHRib3JkZXItbGVmdDogNXB4IHNvbGlkIHRyYW5zcGFyZW50O1xcblxcdGJvcmRlci1yaWdodDogNXB4IHNvbGlkIHRyYW5zcGFyZW50O1xcblxcdGJvcmRlci1ib3R0b206IDVweCBzb2xpZCAjNjY2O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1wYW4tZG93biB7XFxuXFx0Ym90dG9tOiAwO1xcblxcdGxlZnQ6IDUwJTtcXG5cXHRtYXJnaW4tbGVmdDogLTVweDtcXG5cXHR3aWR0aDogMDtcXG5cXHRoZWlnaHQ6IDA7XFxuXFx0Ym9yZGVyLWxlZnQ6IDVweCBzb2xpZCB0cmFuc3BhcmVudDtcXG5cXHRib3JkZXItcmlnaHQ6IDVweCBzb2xpZCB0cmFuc3BhcmVudDtcXG5cXHRib3JkZXItdG9wOiA1cHggc29saWQgIzY2NjtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tcGFuLWxlZnQge1xcblxcdHRvcDogNTAlO1xcblxcdGxlZnQ6IDA7XFxuXFx0bWFyZ2luLXRvcDogLTVweDtcXG5cXHR3aWR0aDogMDtcXG5cXHRoZWlnaHQ6IDA7XFxuXFx0Ym9yZGVyLXRvcDogNXB4IHNvbGlkIHRyYW5zcGFyZW50O1xcblxcdGJvcmRlci1ib3R0b206IDVweCBzb2xpZCB0cmFuc3BhcmVudDtcXG5cXHRib3JkZXItcmlnaHQ6IDVweCBzb2xpZCAjNjY2O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1wYW4tcmlnaHQge1xcblxcdHRvcDogNTAlO1xcblxcdHJpZ2h0OiAwO1xcblxcdG1hcmdpbi10b3A6IC01cHg7XFxuXFx0d2lkdGg6IDA7XFxuXFx0aGVpZ2h0OiAwO1xcblxcdGJvcmRlci10b3A6IDVweCBzb2xpZCB0cmFuc3BhcmVudDtcXG5cXHRib3JkZXItYm90dG9tOiA1cHggc29saWQgdHJhbnNwYXJlbnQ7XFxuXFx0Ym9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjNjY2O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1wYW4taW5kaWNhdG9yIHtcXG5cXHRwb3NpdGlvbjogYWJzb2x1dGU7XFxuXFx0bGVmdDogMDtcXG5cXHR0b3A6IDA7XFxuXFx0d2lkdGg6IDhweDtcXG5cXHRoZWlnaHQ6IDhweDtcXG5cXHRib3JkZXItcmFkaXVzOiA4cHg7XFxuXFx0YmFja2dyb3VuZDogIzAwMDtcXG5cXHRib3JkZXItcmFkaXVzOiA4cHg7XFxuXFx0bWFyZ2luLWxlZnQ6IC01cHg7XFxuXFx0bWFyZ2luLXRvcDogLTVweDtcXG5cXHRkaXNwbGF5OiBub25lO1xcblxcdHotaW5kZXg6IDk5OTtcXG5cXHRvcGFjaXR5OiAwLjY7XFxuXFx0Ym94LXNpemluZzogY29udGVudC1ib3g7XFxufVxcblxcbi5jeS1wYW56b29tLXNsaWRlciB7XFxuXFx0cG9zaXRpb246IGFic29sdXRlO1xcblxcdHRvcDogOTdweDtcXG5cXHRsZWZ0OiAxN3B4O1xcblxcdGhlaWdodDogMTAwcHg7XFxuXFx0d2lkdGg6IDE1cHg7XFxuXFx0Ym94LXNpemluZzogY29udGVudC1ib3g7XFxufVxcblxcbi5jeS1wYW56b29tLXNsaWRlci1iYWNrZ3JvdW5kIHtcXG5cXHRwb3NpdGlvbjogYWJzb2x1dGU7XFxuXFx0dG9wOiAwO1xcblxcdHdpZHRoOiAycHg7XFxuXFx0aGVpZ2h0OiAxMDBweDtcXG5cXHRsZWZ0OiA1cHg7XFxuXFx0YmFja2dyb3VuZDogI2ZmZjtcXG5cXHRib3JkZXItbGVmdDogMXB4IHNvbGlkICM5OTk7XFxuXFx0Ym9yZGVyLXJpZ2h0OiAxcHggc29saWQgIzk5OTtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tc2xpZGVyLWhhbmRsZSB7XFxuXFx0cG9zaXRpb246IGFic29sdXRlO1xcblxcdHdpZHRoOiAxNnB4O1xcblxcdGhlaWdodDogOHB4O1xcblxcdGJhY2tncm91bmQ6ICNmZmY7XFxuXFx0Ym9yZGVyOiAxcHggc29saWQgIzk5OTtcXG5cXHRib3JkZXItcmFkaXVzOiAycHg7XFxuXFx0bWFyZ2luLWxlZnQ6IC0ycHg7XFxuXFx0ei1pbmRleDogOTk5O1xcblxcdGxpbmUtaGVpZ2h0OiA4cHg7XFxuXFx0Y3Vyc29yOiBkZWZhdWx0O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1zbGlkZXItaGFuZGxlIC5pY29uIHtcXG5cXHRtYXJnaW46IDAgNHB4O1xcblxcdGxpbmUtaGVpZ2h0OiAxMHB4O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1uby16b29tLXRpY2sge1xcblxcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG5cXHRiYWNrZ3JvdW5kOiAjNjY2O1xcblxcdGJvcmRlcjogMXB4IHNvbGlkICNmZmY7XFxuXFx0Ym9yZGVyLXJhZGl1czogMnB4O1xcblxcdG1hcmdpbi1sZWZ0OiAtMXB4O1xcblxcdHdpZHRoOiA4cHg7XFxuXFx0aGVpZ2h0OiAycHg7XFxuXFx0bGVmdDogM3B4O1xcblxcdHotaW5kZXg6IDE7XFxuXFx0bWFyZ2luLXRvcDogM3B4O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1wYW5uZXIge1xcblxcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG5cXHRsZWZ0OiA1cHg7XFxuXFx0dG9wOiA1cHg7XFxuXFx0aGVpZ2h0OiA0MHB4O1xcblxcdHdpZHRoOiA0MHB4O1xcblxcdGJhY2tncm91bmQ6ICNmZmY7XFxuXFx0Ym9yZGVyOiAxcHggc29saWQgIzk5OTtcXG5cXHRib3JkZXItcmFkaXVzOiA0MHB4O1xcblxcdG1hcmdpbi1sZWZ0OiAtMXB4O1xcblxcdGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xcbn1cXG5cXG4uY3ktcGFuem9vbS1wYW5uZXItaGFuZGxlIHtcXG5cXHRwb3NpdGlvbjogYWJzb2x1dGU7XFxuXFx0bGVmdDogMDtcXG5cXHR0b3A6IDA7XFxuXFx0b3V0bGluZTogbm9uZTtcXG5cXHRoZWlnaHQ6IDQwcHg7XFxuXFx0d2lkdGg6IDQwcHg7XFxuXFx0cG9zaXRpb246IGFic29sdXRlO1xcblxcdHotaW5kZXg6IDk5OTtcXG5cXHRib3gtc2l6aW5nOiBjb250ZW50LWJveDtcXG59XFxuXFxuLmN5LXBhbnpvb20tem9vbS1vbmx5IC5jeS1wYW56b29tLXNsaWRlcixcXG4uY3ktcGFuem9vbS16b29tLW9ubHkgLmN5LXBhbnpvb20tcGFubmVyIHtcXG5cXHRkaXNwbGF5OiBub25lO1xcbn1cXG5cXG4uY3ktcGFuem9vbS16b29tLW9ubHkgLmN5LXBhbnpvb20tcmVzZXQge1xcblxcdHRvcDogMjBweDtcXG59XFxuXFxuLmN5LXBhbnpvb20tem9vbS1vbmx5IC5jeS1wYW56b29tLXpvb20taW4ge1xcblxcdHRvcDogNDVweDtcXG59XFxuXFxuLmN5LXBhbnpvb20tem9vbS1vbmx5IC5jeS1wYW56b29tLXpvb20tb3V0IHtcXG5cXHR0b3A6IDcwcHg7XFxufVxcblwiLCBcIlwiXSk7XG5cbi8vIGV4cG9ydHNcbiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/css-loader/index.js!./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css\n");
+
+/***/ }),
+
+/***/ "./node_modules/css-loader/lib/css-base.js":
+/*!*************************************************!*\
+ !*** ./node_modules/css-loader/lib/css-base.js ***!
+ \*************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9jc3MtbG9hZGVyL2xpYi9jc3MtYmFzZS5qcz8yMzUwIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsZ0JBQWdCO0FBQ25ELElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsaUJBQWlCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxvQkFBb0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9ELGNBQWM7O0FBRWxFO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY3NzLWxvYWRlci9saWIvY3NzLWJhc2UuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuXHRNSVQgTGljZW5zZSBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuXHRBdXRob3IgVG9iaWFzIEtvcHBlcnMgQHNva3JhXG4qL1xuLy8gY3NzIGJhc2UgY29kZSwgaW5qZWN0ZWQgYnkgdGhlIGNzcy1sb2FkZXJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odXNlU291cmNlTWFwKSB7XG5cdHZhciBsaXN0ID0gW107XG5cblx0Ly8gcmV0dXJuIHRoZSBsaXN0IG9mIG1vZHVsZXMgYXMgY3NzIHN0cmluZ1xuXHRsaXN0LnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uIChpdGVtKSB7XG5cdFx0XHR2YXIgY29udGVudCA9IGNzc1dpdGhNYXBwaW5nVG9TdHJpbmcoaXRlbSwgdXNlU291cmNlTWFwKTtcblx0XHRcdGlmKGl0ZW1bMl0pIHtcblx0XHRcdFx0cmV0dXJuIFwiQG1lZGlhIFwiICsgaXRlbVsyXSArIFwie1wiICsgY29udGVudCArIFwifVwiO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRlbnQ7XG5cdFx0XHR9XG5cdFx0fSkuam9pbihcIlwiKTtcblx0fTtcblxuXHQvLyBpbXBvcnQgYSBsaXN0IG9mIG1vZHVsZXMgaW50byB0aGUgbGlzdFxuXHRsaXN0LmkgPSBmdW5jdGlvbihtb2R1bGVzLCBtZWRpYVF1ZXJ5KSB7XG5cdFx0aWYodHlwZW9mIG1vZHVsZXMgPT09IFwic3RyaW5nXCIpXG5cdFx0XHRtb2R1bGVzID0gW1tudWxsLCBtb2R1bGVzLCBcIlwiXV07XG5cdFx0dmFyIGFscmVhZHlJbXBvcnRlZE1vZHVsZXMgPSB7fTtcblx0XHRmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIGlkID0gdGhpc1tpXVswXTtcblx0XHRcdGlmKHR5cGVvZiBpZCA9PT0gXCJudW1iZXJcIilcblx0XHRcdFx0YWxyZWFkeUltcG9ydGVkTW9kdWxlc1tpZF0gPSB0cnVlO1xuXHRcdH1cblx0XHRmb3IoaSA9IDA7IGkgPCBtb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgaXRlbSA9IG1vZHVsZXNbaV07XG5cdFx0XHQvLyBza2lwIGFscmVhZHkgaW1wb3J0ZWQgbW9kdWxlXG5cdFx0XHQvLyB0aGlzIGltcGxlbWVudGF0aW9uIGlzIG5vdCAxMDAlIHBlcmZlY3QgZm9yIHdlaXJkIG1lZGlhIHF1ZXJ5IGNvbWJpbmF0aW9uc1xuXHRcdFx0Ly8gIHdoZW4gYSBtb2R1bGUgaXMgaW1wb3J0ZWQgbXVsdGlwbGUgdGltZXMgd2l0aCBkaWZmZXJlbnQgbWVkaWEgcXVlcmllcy5cblx0XHRcdC8vICBJIGhvcGUgdGhpcyB3aWxsIG5ldmVyIG9jY3VyIChIZXkgdGhpcyB3YXkgd2UgaGF2ZSBzbWFsbGVyIGJ1bmRsZXMpXG5cdFx0XHRpZih0eXBlb2YgaXRlbVswXSAhPT0gXCJudW1iZXJcIiB8fCAhYWxyZWFkeUltcG9ydGVkTW9kdWxlc1tpdGVtWzBdXSkge1xuXHRcdFx0XHRpZihtZWRpYVF1ZXJ5ICYmICFpdGVtWzJdKSB7XG5cdFx0XHRcdFx0aXRlbVsyXSA9IG1lZGlhUXVlcnk7XG5cdFx0XHRcdH0gZWxzZSBpZihtZWRpYVF1ZXJ5KSB7XG5cdFx0XHRcdFx0aXRlbVsyXSA9IFwiKFwiICsgaXRlbVsyXSArIFwiKSBhbmQgKFwiICsgbWVkaWFRdWVyeSArIFwiKVwiO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGxpc3QucHVzaChpdGVtKTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cdHJldHVybiBsaXN0O1xufTtcblxuZnVuY3Rpb24gY3NzV2l0aE1hcHBpbmdUb1N0cmluZyhpdGVtLCB1c2VTb3VyY2VNYXApIHtcblx0dmFyIGNvbnRlbnQgPSBpdGVtWzFdIHx8ICcnO1xuXHR2YXIgY3NzTWFwcGluZyA9IGl0ZW1bM107XG5cdGlmICghY3NzTWFwcGluZykge1xuXHRcdHJldHVybiBjb250ZW50O1xuXHR9XG5cblx0aWYgKHVzZVNvdXJjZU1hcCAmJiB0eXBlb2YgYnRvYSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdHZhciBzb3VyY2VNYXBwaW5nID0gdG9Db21tZW50KGNzc01hcHBpbmcpO1xuXHRcdHZhciBzb3VyY2VVUkxzID0gY3NzTWFwcGluZy5zb3VyY2VzLm1hcChmdW5jdGlvbiAoc291cmNlKSB7XG5cdFx0XHRyZXR1cm4gJy8qIyBzb3VyY2VVUkw9JyArIGNzc01hcHBpbmcuc291cmNlUm9vdCArIHNvdXJjZSArICcgKi8nXG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gW2NvbnRlbnRdLmNvbmNhdChzb3VyY2VVUkxzKS5jb25jYXQoW3NvdXJjZU1hcHBpbmddKS5qb2luKCdcXG4nKTtcblx0fVxuXG5cdHJldHVybiBbY29udGVudF0uam9pbignXFxuJyk7XG59XG5cbi8vIEFkYXB0ZWQgZnJvbSBjb252ZXJ0LXNvdXJjZS1tYXAgKE1JVClcbmZ1bmN0aW9uIHRvQ29tbWVudChzb3VyY2VNYXApIHtcblx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmXG5cdHZhciBiYXNlNjQgPSBidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApKSkpO1xuXHR2YXIgZGF0YSA9ICdzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0PXV0Zi04O2Jhc2U2NCwnICsgYmFzZTY0O1xuXG5cdHJldHVybiAnLyojICcgKyBkYXRhICsgJyAqLyc7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/css-loader/lib/css-base.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/cytoscape-panzoom/cytoscape-panzoom.js":
+/*!*************************************************************!*\
+ !*** ./node_modules/cytoscape-panzoom/cytoscape-panzoom.js ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("var __WEBPACK_AMD_DEFINE_RESULT__;/*!\nCopyright (c) The Cytoscape Consortium\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the “Software”), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n;(function(){ 'use strict';\n\n // registers the extension on a cytoscape lib ref\n var register = function( cytoscape, $ ){\n if( !cytoscape || !$ ){ return; } // can't register if cytoscape or jquery unspecified\n\n $.fn.cyPanzoom = $.fn.cytoscapePanzoom = function( options ){\n panzoom.apply( this, [ options, cytoscape, $ ] );\n\n return this; // chainability\n };\n\n // if you want a core extension\n cytoscape('core', 'panzoom', function( options ){ // could use options object, but args are up to you\n panzoom.apply( this, [ options, cytoscape, $ ] );\n\n return this; // chainability\n });\n\n };\n\n var defaults = {\n zoomFactor: 0.05, // zoom factor per zoom tick\n zoomDelay: 45, // how many ms between zoom ticks\n minZoom: 0.1, // min zoom level\n maxZoom: 10, // max zoom level\n fitPadding: 50, // padding when fitting\n panSpeed: 10, // how many ms in between pan ticks\n panDistance: 10, // max pan distance per tick\n panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction)\n panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed)\n panInactiveArea: 8, // radius of inactive area in pan drag box\n panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0\n zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution)\n fitSelector: undefined, // selector of elements to fit\n animateOnFit: function(){ // whether to animate on fit\n return false;\n },\n fitAnimationDuration: 1000, // duration of animation on fit\n\n // icon class names\n sliderHandleIcon: 'fa fa-minus',\n zoomInIcon: 'fa fa-plus',\n zoomOutIcon: 'fa fa-minus',\n resetIcon: 'fa fa-expand'\n };\n\n var panzoom = function( params, cytoscape, $ ){\n var cyRef = this;\n var options = $.extend(true, {}, defaults, params);\n var fn = params;\n\n var functions = {\n destroy: function(){\n var $this = $(cyRef.container());\n var $pz = $this.find(\".cy-panzoom\");\n\n $pz.data('winbdgs').forEach(function( l ){\n $(window).unbind( l.evt, l.fn );\n });\n\n $pz.data('cybdgs').forEach(function( l ){\n cyRef.off( l.evt, l.fn );\n });\n\n $pz.remove();\n },\n\n init: function(){\n var browserIsMobile = 'ontouchstart' in window;\n\n return $(cyRef.container()).each(function(){\n var $container = $(this);\n $container.cytoscape = cytoscape;\n\n var winbdgs = [];\n var $win = $(window);\n\n var windowBind = function( evt, fn ){\n winbdgs.push({ evt: evt, fn: fn });\n\n $win.bind( evt, fn );\n };\n\n var windowUnbind = function( evt, fn ){\n for( var i = 0; i < winbdgs.length; i++ ){\n var l = winbdgs[i];\n\n if( l.evt === evt && l.fn === fn ){\n winbdgs.splice( i, 1 );\n break;\n }\n }\n\n $win.unbind( evt, fn );\n };\n\n var cybdgs = [];\n\n var cyOn = function( evt, fn ){\n cybdgs.push({ evt: evt, fn: fn });\n\n cyRef.on( evt, fn );\n };\n\n var cyOff = function( evt, fn ){\n for( var i = 0; i < cybdgs.length; i++ ){\n var l = cybdgs[i];\n\n if( l.evt === evt && l.fn === fn ){\n cybdgs.splice( i, 1 );\n break;\n }\n }\n\n cyRef.off( evt, fn );\n };\n\n var $panzoom = $('
');\n $container.prepend( $panzoom );\n\n $panzoom.css('position', 'absolute'); // must be absolute regardless of stylesheet\n\n $panzoom.data('winbdgs', winbdgs);\n $panzoom.data('cybdgs', cybdgs);\n\n if( options.zoomOnly ){\n $panzoom.addClass(\"cy-panzoom-zoom-only\");\n }\n\n // add base html elements\n /////////////////////////\n\n var $zoomIn = $('
');\n $panzoom.append( $zoomIn );\n\n var $zoomOut = $('
');\n $panzoom.append( $zoomOut );\n\n var $reset = $('
');\n $panzoom.append( $reset );\n\n var $slider = $('');\n $panzoom.append( $slider );\n\n $slider.append('');\n\n var $sliderHandle = $('
');\n $slider.append( $sliderHandle );\n\n var $noZoomTick = $('');\n $slider.append( $noZoomTick );\n\n var $panner = $('');\n $panzoom.append( $panner );\n\n var $pHandle = $('');\n $panner.append( $pHandle );\n\n var $pUp = $('');\n var $pDown = $('');\n var $pLeft = $('');\n var $pRight = $('');\n $panner.append( $pUp ).append( $pDown ).append( $pLeft ).append( $pRight );\n\n var $pIndicator = $('');\n $panner.append( $pIndicator );\n\n // functions for calculating panning\n ////////////////////////////////////\n\n function handle2pan(e){\n var v = {\n x: e.originalEvent.pageX - $panner.offset().left - $panner.width()/2,\n y: e.originalEvent.pageY - $panner.offset().top - $panner.height()/2\n }\n\n var r = options.panDragAreaSize;\n var d = Math.sqrt( v.x*v.x + v.y*v.y );\n var percent = Math.min( d/r, 1 );\n\n if( d < options.panInactiveArea ){\n return {\n x: NaN,\n y: NaN\n };\n }\n\n v = {\n x: v.x/d,\n y: v.y/d\n };\n\n percent = Math.max( options.panMinPercentSpeed, percent );\n\n var vnorm = {\n x: -1 * v.x * (percent * options.panDistance),\n y: -1 * v.y * (percent * options.panDistance)\n };\n\n return vnorm;\n }\n\n function donePanning(){\n clearInterval(panInterval);\n windowUnbind(\"mousemove\", handler);\n\n $pIndicator.hide();\n }\n\n function positionIndicator(pan){\n var v = pan;\n var d = Math.sqrt( v.x*v.x + v.y*v.y );\n var vnorm = {\n x: -1 * v.x/d,\n y: -1 * v.y/d\n };\n\n var w = $panner.width();\n var h = $panner.height();\n var percent = d/options.panDistance;\n var opacity = Math.max( options.panIndicatorMinOpacity, percent );\n var color = 255 - Math.round( opacity * 255 );\n\n $pIndicator.show().css({\n left: w/2 * vnorm.x + w/2,\n top: h/2 * vnorm.y + h/2,\n background: \"rgb(\" + color + \", \" + color + \", \" + color + \")\"\n });\n }\n\n function calculateZoomCenterPoint(){\n var pan = cyRef.pan();\n var zoom = cyRef.zoom();\n\n zx = $container.width()/2;\n zy = $container.height()/2;\n }\n\n var zooming = false;\n function startZooming(){\n zooming = true;\n\n calculateZoomCenterPoint();\n }\n\n\n function endZooming(){\n zooming = false;\n }\n\n var zx, zy;\n function zoomTo(level){\n if( !zooming ){ // for non-continuous zooming (e.g. click slider at pt)\n calculateZoomCenterPoint();\n }\n\n cyRef.zoom({\n level: level,\n renderedPosition: { x: zx, y: zy }\n });\n }\n\n var panInterval;\n\n var handler = function(e){\n e.stopPropagation(); // don't trigger dragging of panzoom\n e.preventDefault(); // don't cause text selection\n clearInterval(panInterval);\n\n var pan = handle2pan(e);\n\n if( isNaN(pan.x) || isNaN(pan.y) ){\n $pIndicator.hide();\n return;\n }\n\n positionIndicator(pan);\n panInterval = setInterval(function(){\n cyRef.panBy(pan);\n }, options.panSpeed);\n };\n\n $pHandle.bind(\"mousedown\", function(e){\n // handle click of icon\n handler(e);\n\n // update on mousemove\n windowBind(\"mousemove\", handler);\n });\n\n $pHandle.bind(\"mouseup\", function(){\n donePanning();\n });\n\n windowBind(\"mouseup blur\", function(){\n donePanning();\n });\n\n\n\n // set up slider behaviour\n //////////////////////////\n\n $slider.bind('mousedown', function(){\n return false; // so we don't pan close to the slider handle\n });\n\n var sliderVal;\n var sliding = false;\n var sliderPadding = 2;\n\n function setSliderFromMouse(evt, handleOffset){\n if( handleOffset === undefined ){\n handleOffset = 0;\n }\n\n var padding = sliderPadding;\n var min = 0 + padding;\n var max = $slider.height() - $sliderHandle.height() - 2*padding;\n var top = evt.pageY - $slider.offset().top - handleOffset;\n\n // constrain to slider bounds\n if( top < min ){ top = min }\n if( top > max ){ top = max }\n\n var percent = 1 - (top - min) / ( max - min );\n\n // move the handle\n $sliderHandle.css('top', top);\n\n var zmin = options.minZoom;\n var zmax = options.maxZoom;\n\n // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative\n var x = Math.log(zmin) / Math.log(zmax);\n var p = (1 - x)*percent + x;\n\n // change the zoom level\n var z = Math.pow( zmax, p );\n\n // bound the zoom value in case of floating pt rounding error\n if( z < zmin ){\n z = zmin;\n } else if( z > zmax ){\n z = zmax;\n }\n\n zoomTo( z );\n }\n\n var sliderMdownHandler, sliderMmoveHandler;\n $sliderHandle.bind('mousedown', sliderMdownHandler = function( mdEvt ){\n var handleOffset = mdEvt.target === $sliderHandle[0] ? mdEvt.offsetY : 0;\n sliding = true;\n\n startZooming();\n $sliderHandle.addClass(\"active\");\n\n var lastMove = 0;\n windowBind('mousemove', sliderMmoveHandler = function( mmEvt ){\n var now = +new Date;\n\n // throttle the zooms every 10 ms so we don't call zoom too often and cause lag\n if( now > lastMove + 10 ){\n lastMove = now;\n } else {\n return false;\n }\n\n setSliderFromMouse(mmEvt, handleOffset);\n\n return false;\n });\n\n // unbind when\n windowBind('mouseup', function(){\n windowUnbind('mousemove', sliderMmoveHandler);\n sliding = false;\n\n $sliderHandle.removeClass(\"active\");\n endZooming();\n });\n\n return false;\n });\n\n $slider.bind('mousedown', function(e){\n if( e.target !== $sliderHandle[0] ){\n sliderMdownHandler(e);\n setSliderFromMouse(e);\n }\n });\n\n function positionSliderFromZoom(){\n var z = cyRef.zoom();\n var zmin = options.minZoom;\n var zmax = options.maxZoom;\n\n // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative\n var x = Math.log(zmin) / Math.log(zmax);\n var p = Math.log(z) / Math.log(zmax);\n var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction\n\n var min = sliderPadding;\n var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;\n var top = percent * ( max - min );\n\n // constrain to slider bounds\n if( top < min ){ top = min }\n if( top > max ){ top = max }\n\n // move the handle\n $sliderHandle.css('top', top);\n }\n\n positionSliderFromZoom();\n\n cyOn('zoom', function(){\n if( !sliding ){\n positionSliderFromZoom();\n }\n });\n\n // set the position of the zoom=1 tick\n (function(){\n var z = 1;\n var zmin = options.minZoom;\n var zmax = options.maxZoom;\n\n // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative\n var x = Math.log(zmin) / Math.log(zmax);\n var p = Math.log(z) / Math.log(zmax);\n var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction\n\n if( percent > 1 || percent < 0 ){\n $noZoomTick.hide();\n return;\n }\n\n var min = sliderPadding;\n var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;\n var top = percent * ( max - min );\n\n // constrain to slider bounds\n if( top < min ){ top = min }\n if( top > max ){ top = max }\n\n $noZoomTick.css('top', top);\n })();\n\n // set up zoom in/out buttons\n /////////////////////////////\n\n function bindButton($button, factor){\n var zoomInterval;\n\n $button.bind(\"mousedown\", function(e){\n e.preventDefault();\n e.stopPropagation();\n\n if( e.button != 0 ){\n return;\n }\n\n var doZoom = function(){\n var zoom = cyRef.zoom();\n var lvl = cyRef.zoom() * factor;\n\n if( lvl < options.minZoom ){\n lvl = options.minZoom;\n }\n\n if( lvl > options.maxZoom ){\n lvl = options.maxZoom;\n }\n\n if( (lvl == options.maxZoom && zoom == options.maxZoom) ||\n (lvl == options.minZoom && zoom == options.minZoom)\n ){\n return;\n }\n\n zoomTo(lvl);\n };\n\n startZooming();\n doZoom();\n zoomInterval = setInterval(doZoom, options.zoomDelay);\n\n return false;\n });\n\n windowBind(\"mouseup blur\", function(){\n clearInterval(zoomInterval);\n endZooming();\n });\n }\n\n bindButton( $zoomIn, (1 + options.zoomFactor) );\n bindButton( $zoomOut, (1 - options.zoomFactor) );\n\n $reset.bind(\"mousedown\", function(e){\n if( e.button != 0 ){\n return;\n }\n\n var elesToFit = options.fitSelector?cyRef.elements(options.fitSelector):cyRef.elements();\n\n if( elesToFit.size() === 0 ){\n cyRef.reset();\n } else {\n var animateOnFit = typeof options.animateOnFit === 'function' ? options.animateOnFit.call() : options.animateOnFit;\n if(animateOnFit){\n cyRef.animate({\n fit: {\n eles: elesToFit,\n padding: options.fitPadding\n }\n }, {\n duration: options.fitAnimationDuration\n });\n }\n else{\n cyRef.fit( elesToFit, options.fitPadding );\n }\n\n }\n\n return false;\n });\n\n\n\n });\n }\n };\n\n if( functions[fn] ){\n return functions[fn].apply(this, Array.prototype.slice.call( arguments, 1 ));\n } else if( typeof fn == 'object' || !fn ) {\n return functions.init.apply( this, arguments );\n } else {\n $.error(\"No such function `\"+ fn +\"` for jquery.cytoscapePanzoom\");\n }\n\n return $(this);\n };\n\n\n if( true && module.exports ){ // expose as a commonjs module\n module.exports = function( cytoscape, jquery ){\n register( cytoscape, jquery || __webpack_require__(/*! jquery */ \"./node_modules/jquery/dist/jquery.js\") );\n }\n } else if( true ){ // expose as an amd/requirejs module\n !(__WEBPACK_AMD_DEFINE_RESULT__ = (function(){\n return register;\n }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n }\n\n if( typeof cytoscape !== 'undefined' && typeof jQuery !== 'undefined' ){ // expose to global cytoscape (i.e. window.cytoscape)\n register( cytoscape, jQuery );\n }\n\n})();\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUtcGFuem9vbS9jeXRvc2NhcGUtcGFuem9vbS5qcz8xZTE2Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLFlBQVk7O0FBRWI7QUFDQTtBQUNBLDJCQUEyQixRQUFRLEVBQUU7O0FBRXJDO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCOztBQUVBO0FBQ0EscURBQXFEO0FBQ3JEOztBQUVBLGtCQUFrQjtBQUNsQixLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxRkFBcUY7QUFDckY7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1DQUFtQztBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBLE9BQU87O0FBRVA7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQixtQkFBbUI7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsb0JBQW9CO0FBQy9DOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHlCQUF5QixtQkFBbUI7O0FBRTVDO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsbUJBQW1CO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtDQUErQzs7QUFFL0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakMsYUFBYTtBQUNiOztBQUVBOztBQUVBO0FBQ0EsZ0NBQWdDO0FBQ2hDLCtCQUErQjtBQUMvQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQSxXQUFXOzs7O0FBSVg7QUFDQTs7QUFFQTtBQUNBLHlCQUF5QjtBQUN6QixXQUFXOztBQUVYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDRCQUE0QjtBQUM1Qiw0QkFBNEI7O0FBRTVCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBOztBQUVBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw0QkFBNEI7QUFDNUIsNEJBQTRCOztBQUU1QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw0QkFBNEI7QUFDNUIsNEJBQTRCOztBQUU1QjtBQUNBLFdBQVc7O0FBRVg7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFdBQVc7Ozs7QUFJWCxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0EsTUFBTSxLQUE2QixxQkFBcUI7QUFDeEQ7QUFDQSxxQ0FBcUMsbUJBQU8sQ0FBQyxvREFBUTtBQUNyRDtBQUNBLEdBQUcsVUFBVSxJQUEyQyxHQUFHO0FBQzNELElBQUksbUNBQTRCO0FBQ2hDO0FBQ0EsS0FBSztBQUFBLG9HQUFDO0FBQ047O0FBRUEsMEVBQTBFO0FBQzFFO0FBQ0E7O0FBRUEsQ0FBQyIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUtcGFuem9vbS9jeXRvc2NhcGUtcGFuem9vbS5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIVxuQ29weXJpZ2h0IChjKSBUaGUgQ3l0b3NjYXBlIENvbnNvcnRpdW1cblxuUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weSBvZlxudGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUg4oCcU29mdHdhcmXigJ0pLCB0byBkZWFsIGluXG50aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvXG51c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllc1xub2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvXG5zbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIOKAnEFTIElT4oCdLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG5TT0ZUV0FSRS5cbiovXG5cbjsoZnVuY3Rpb24oKXsgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIHJlZ2lzdGVycyB0aGUgZXh0ZW5zaW9uIG9uIGEgY3l0b3NjYXBlIGxpYiByZWZcbiAgdmFyIHJlZ2lzdGVyID0gZnVuY3Rpb24oIGN5dG9zY2FwZSwgJCApe1xuICAgIGlmKCAhY3l0b3NjYXBlIHx8ICEkICl7IHJldHVybjsgfSAvLyBjYW4ndCByZWdpc3RlciBpZiBjeXRvc2NhcGUgb3IganF1ZXJ5IHVuc3BlY2lmaWVkXG5cbiAgICAkLmZuLmN5UGFuem9vbSA9ICQuZm4uY3l0b3NjYXBlUGFuem9vbSA9IGZ1bmN0aW9uKCBvcHRpb25zICl7XG4gICAgICBwYW56b29tLmFwcGx5KCB0aGlzLCBbIG9wdGlvbnMsIGN5dG9zY2FwZSwgJCBdICk7XG5cbiAgICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmFiaWxpdHlcbiAgICB9O1xuXG4gICAgLy8gaWYgeW91IHdhbnQgYSBjb3JlIGV4dGVuc2lvblxuICAgIGN5dG9zY2FwZSgnY29yZScsICdwYW56b29tJywgZnVuY3Rpb24oIG9wdGlvbnMgKXsgLy8gY291bGQgdXNlIG9wdGlvbnMgb2JqZWN0LCBidXQgYXJncyBhcmUgdXAgdG8geW91XG4gICAgICBwYW56b29tLmFwcGx5KCB0aGlzLCBbIG9wdGlvbnMsIGN5dG9zY2FwZSwgJCBdICk7XG5cbiAgICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmFiaWxpdHlcbiAgICB9KTtcblxuICB9O1xuXG4gIHZhciBkZWZhdWx0cyA9IHtcbiAgICB6b29tRmFjdG9yOiAwLjA1LCAvLyB6b29tIGZhY3RvciBwZXIgem9vbSB0aWNrXG4gICAgem9vbURlbGF5OiA0NSwgLy8gaG93IG1hbnkgbXMgYmV0d2VlbiB6b29tIHRpY2tzXG4gICAgbWluWm9vbTogMC4xLCAvLyBtaW4gem9vbSBsZXZlbFxuICAgIG1heFpvb206IDEwLCAvLyBtYXggem9vbSBsZXZlbFxuICAgIGZpdFBhZGRpbmc6IDUwLCAvLyBwYWRkaW5nIHdoZW4gZml0dGluZ1xuICAgIHBhblNwZWVkOiAxMCwgLy8gaG93IG1hbnkgbXMgaW4gYmV0d2VlbiBwYW4gdGlja3NcbiAgICBwYW5EaXN0YW5jZTogMTAsIC8vIG1heCBwYW4gZGlzdGFuY2UgcGVyIHRpY2tcbiAgICBwYW5EcmFnQXJlYVNpemU6IDc1LCAvLyB0aGUgbGVuZ3RoIG9mIHRoZSBwYW4gZHJhZyBib3ggaW4gd2hpY2ggdGhlIHZlY3RvciBmb3IgcGFubmluZyBpcyBjYWxjdWxhdGVkIChiaWdnZXIgPSBmaW5lciBjb250cm9sIG9mIHBhbiBzcGVlZCBhbmQgZGlyZWN0aW9uKVxuICAgIHBhbk1pblBlcmNlbnRTcGVlZDogMC4yNSwgLy8gdGhlIHNsb3dlc3Qgc3BlZWQgd2UgY2FuIHBhbiBieSAoYXMgYSBwZXJjZW50IG9mIHBhblNwZWVkKVxuICAgIHBhbkluYWN0aXZlQXJlYTogOCwgLy8gcmFkaXVzIG9mIGluYWN0aXZlIGFyZWEgaW4gcGFuIGRyYWcgYm94XG4gICAgcGFuSW5kaWNhdG9yTWluT3BhY2l0eTogMC41LCAvLyBtaW4gb3BhY2l0eSBvZiBwYW4gaW5kaWNhdG9yICh0aGUgZHJhZ2dhYmxlIG5pYik7IHNjYWxlcyBmcm9tIHRoaXMgdG8gMS4wXG4gICAgem9vbU9ubHk6IGZhbHNlLCAvLyBhIG1pbmltYWwgdmVyc2lvbiBvZiB0aGUgdWkgb25seSB3aXRoIHpvb21pbmcgKHVzZWZ1bCBvbiBzeXN0ZW1zIHdpdGggYmFkIG1vdXNld2hlZWwgcmVzb2x1dGlvbilcbiAgICBmaXRTZWxlY3RvcjogdW5kZWZpbmVkLCAvLyBzZWxlY3RvciBvZiBlbGVtZW50cyB0byBmaXRcbiAgICBhbmltYXRlT25GaXQ6IGZ1bmN0aW9uKCl7IC8vIHdoZXRoZXIgdG8gYW5pbWF0ZSBvbiBmaXRcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuICAgIGZpdEFuaW1hdGlvbkR1cmF0aW9uOiAxMDAwLCAvLyBkdXJhdGlvbiBvZiBhbmltYXRpb24gb24gZml0XG5cbiAgICAvLyBpY29uIGNsYXNzIG5hbWVzXG4gICAgc2xpZGVySGFuZGxlSWNvbjogJ2ZhIGZhLW1pbnVzJyxcbiAgICB6b29tSW5JY29uOiAnZmEgZmEtcGx1cycsXG4gICAgem9vbU91dEljb246ICdmYSBmYS1taW51cycsXG4gICAgcmVzZXRJY29uOiAnZmEgZmEtZXhwYW5kJ1xuICB9O1xuXG4gIHZhciBwYW56b29tID0gZnVuY3Rpb24oIHBhcmFtcywgY3l0b3NjYXBlLCAkICl7XG4gICAgdmFyIGN5UmVmID0gdGhpcztcbiAgICB2YXIgb3B0aW9ucyA9ICQuZXh0ZW5kKHRydWUsIHt9LCBkZWZhdWx0cywgcGFyYW1zKTtcbiAgICB2YXIgZm4gPSBwYXJhbXM7XG5cbiAgICB2YXIgZnVuY3Rpb25zID0ge1xuICAgICAgZGVzdHJveTogZnVuY3Rpb24oKXtcbiAgICAgICAgdmFyICR0aGlzID0gJChjeVJlZi5jb250YWluZXIoKSk7XG4gICAgICAgIHZhciAkcHogPSAkdGhpcy5maW5kKFwiLmN5LXBhbnpvb21cIik7XG5cbiAgICAgICAgJHB6LmRhdGEoJ3dpbmJkZ3MnKS5mb3JFYWNoKGZ1bmN0aW9uKCBsICl7XG4gICAgICAgICAgJCh3aW5kb3cpLnVuYmluZCggbC5ldnQsIGwuZm4gKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHB6LmRhdGEoJ2N5YmRncycpLmZvckVhY2goZnVuY3Rpb24oIGwgKXtcbiAgICAgICAgICBjeVJlZi5vZmYoIGwuZXZ0LCBsLmZuICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRwei5yZW1vdmUoKTtcbiAgICAgIH0sXG5cbiAgICAgIGluaXQ6IGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhciBicm93c2VySXNNb2JpbGUgPSAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3c7XG5cbiAgICAgICAgcmV0dXJuICQoY3lSZWYuY29udGFpbmVyKCkpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICAgICB2YXIgJGNvbnRhaW5lciA9ICQodGhpcyk7XG4gICAgICAgICAgJGNvbnRhaW5lci5jeXRvc2NhcGUgPSBjeXRvc2NhcGU7XG5cbiAgICAgICAgICB2YXIgd2luYmRncyA9IFtdO1xuICAgICAgICAgIHZhciAkd2luID0gJCh3aW5kb3cpO1xuXG4gICAgICAgICAgdmFyIHdpbmRvd0JpbmQgPSBmdW5jdGlvbiggZXZ0LCBmbiApe1xuICAgICAgICAgICAgd2luYmRncy5wdXNoKHsgZXZ0OiBldnQsIGZuOiBmbiB9KTtcblxuICAgICAgICAgICAgJHdpbi5iaW5kKCBldnQsIGZuICk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHZhciB3aW5kb3dVbmJpbmQgPSBmdW5jdGlvbiggZXZ0LCBmbiApe1xuICAgICAgICAgICAgZm9yKCB2YXIgaSA9IDA7IGkgPCB3aW5iZGdzLmxlbmd0aDsgaSsrICl7XG4gICAgICAgICAgICAgIHZhciBsID0gd2luYmRnc1tpXTtcblxuICAgICAgICAgICAgICBpZiggbC5ldnQgPT09IGV2dCAmJiBsLmZuID09PSBmbiApe1xuICAgICAgICAgICAgICAgIHdpbmJkZ3Muc3BsaWNlKCBpLCAxICk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJHdpbi51bmJpbmQoIGV2dCwgZm4gKTtcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgdmFyIGN5YmRncyA9IFtdO1xuXG4gICAgICAgICAgdmFyIGN5T24gPSBmdW5jdGlvbiggZXZ0LCBmbiApe1xuICAgICAgICAgICAgY3liZGdzLnB1c2goeyBldnQ6IGV2dCwgZm46IGZuIH0pO1xuXG4gICAgICAgICAgICBjeVJlZi5vbiggZXZ0LCBmbiApO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICB2YXIgY3lPZmYgPSBmdW5jdGlvbiggZXZ0LCBmbiApe1xuICAgICAgICAgICAgZm9yKCB2YXIgaSA9IDA7IGkgPCBjeWJkZ3MubGVuZ3RoOyBpKysgKXtcbiAgICAgICAgICAgICAgdmFyIGwgPSBjeWJkZ3NbaV07XG5cbiAgICAgICAgICAgICAgaWYoIGwuZXZ0ID09PSBldnQgJiYgbC5mbiA9PT0gZm4gKXtcbiAgICAgICAgICAgICAgICBjeWJkZ3Muc3BsaWNlKCBpLCAxICk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY3lSZWYub2ZmKCBldnQsIGZuICk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHZhciAkcGFuem9vbSA9ICQoJzxkaXYgY2xhc3M9XCJjeS1wYW56b29tXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgJGNvbnRhaW5lci5wcmVwZW5kKCAkcGFuem9vbSApO1xuXG4gICAgICAgICAgJHBhbnpvb20uY3NzKCdwb3NpdGlvbicsICdhYnNvbHV0ZScpOyAvLyBtdXN0IGJlIGFic29sdXRlIHJlZ2FyZGxlc3Mgb2Ygc3R5bGVzaGVldFxuXG4gICAgICAgICAgJHBhbnpvb20uZGF0YSgnd2luYmRncycsIHdpbmJkZ3MpO1xuICAgICAgICAgICRwYW56b29tLmRhdGEoJ2N5YmRncycsIGN5YmRncyk7XG5cbiAgICAgICAgICBpZiggb3B0aW9ucy56b29tT25seSApe1xuICAgICAgICAgICAgJHBhbnpvb20uYWRkQ2xhc3MoXCJjeS1wYW56b29tLXpvb20tb25seVwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBhZGQgYmFzZSBodG1sIGVsZW1lbnRzXG4gICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgdmFyICR6b29tSW4gPSAkKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS16b29tLWluIGN5LXBhbnpvb20tem9vbS1idXR0b25cIj48c3BhbiBjbGFzcz1cImljb24gJysgb3B0aW9ucy56b29tSW5JY29uICsnXCI+PC9zcGFuPjwvZGl2PicpO1xuICAgICAgICAgICRwYW56b29tLmFwcGVuZCggJHpvb21JbiApO1xuXG4gICAgICAgICAgdmFyICR6b29tT3V0ID0gJCgnPGRpdiBjbGFzcz1cImN5LXBhbnpvb20tem9vbS1vdXQgY3ktcGFuem9vbS16b29tLWJ1dHRvblwiPjxzcGFuIGNsYXNzPVwiaWNvbiAnICsgb3B0aW9ucy56b29tT3V0SWNvbiArICdcIj48L3NwYW4+PC9kaXY+Jyk7XG4gICAgICAgICAgJHBhbnpvb20uYXBwZW5kKCAkem9vbU91dCApO1xuXG4gICAgICAgICAgdmFyICRyZXNldCA9ICQoJzxkaXYgY2xhc3M9XCJjeS1wYW56b29tLXJlc2V0IGN5LXBhbnpvb20tem9vbS1idXR0b25cIj48c3BhbiBjbGFzcz1cImljb24gJyArIG9wdGlvbnMucmVzZXRJY29uICsgJ1wiPjwvc3Bhbj48L2Rpdj4nKTtcbiAgICAgICAgICAkcGFuem9vbS5hcHBlbmQoICRyZXNldCApO1xuXG4gICAgICAgICAgdmFyICRzbGlkZXIgPSAkKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS1zbGlkZXJcIj48L2Rpdj4nKTtcbiAgICAgICAgICAkcGFuem9vbS5hcHBlbmQoICRzbGlkZXIgKTtcblxuICAgICAgICAgICRzbGlkZXIuYXBwZW5kKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS1zbGlkZXItYmFja2dyb3VuZFwiPjwvZGl2PicpO1xuXG4gICAgICAgICAgdmFyICRzbGlkZXJIYW5kbGUgPSAkKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS1zbGlkZXItaGFuZGxlXCI+PHNwYW4gY2xhc3M9XCJpY29uICcgKyBvcHRpb25zLnNsaWRlckhhbmRsZUljb24gKyAnXCI+PC9zcGFuPjwvZGl2PicpO1xuICAgICAgICAgICRzbGlkZXIuYXBwZW5kKCAkc2xpZGVySGFuZGxlICk7XG5cbiAgICAgICAgICB2YXIgJG5vWm9vbVRpY2sgPSAkKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS1uby16b29tLXRpY2tcIj48L2Rpdj4nKTtcbiAgICAgICAgICAkc2xpZGVyLmFwcGVuZCggJG5vWm9vbVRpY2sgKTtcblxuICAgICAgICAgIHZhciAkcGFubmVyID0gJCgnPGRpdiBjbGFzcz1cImN5LXBhbnpvb20tcGFubmVyXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgJHBhbnpvb20uYXBwZW5kKCAkcGFubmVyICk7XG5cbiAgICAgICAgICB2YXIgJHBIYW5kbGUgPSAkKCc8ZGl2IGNsYXNzPVwiY3ktcGFuem9vbS1wYW5uZXItaGFuZGxlXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgJHBhbm5lci5hcHBlbmQoICRwSGFuZGxlICk7XG5cbiAgICAgICAgICB2YXIgJHBVcCA9ICQoJzxkaXYgY2xhc3M9XCJjeS1wYW56b29tLXBhbi11cCBjeS1wYW56b29tLXBhbi1idXR0b25cIj48L2Rpdj4nKTtcbiAgICAgICAgICB2YXIgJHBEb3duID0gJCgnPGRpdiBjbGFzcz1cImN5LXBhbnpvb20tcGFuLWRvd24gY3ktcGFuem9vbS1wYW4tYnV0dG9uXCI+PC9kaXY+Jyk7XG4gICAgICAgICAgdmFyICRwTGVmdCA9ICQoJzxkaXYgY2xhc3M9XCJjeS1wYW56b29tLXBhbi1sZWZ0IGN5LXBhbnpvb20tcGFuLWJ1dHRvblwiPjwvZGl2PicpO1xuICAgICAgICAgIHZhciAkcFJpZ2h0ID0gJCgnPGRpdiBjbGFzcz1cImN5LXBhbnpvb20tcGFuLXJpZ2h0IGN5LXBhbnpvb20tcGFuLWJ1dHRvblwiPjwvZGl2PicpO1xuICAgICAgICAgICRwYW5uZXIuYXBwZW5kKCAkcFVwICkuYXBwZW5kKCAkcERvd24gKS5hcHBlbmQoICRwTGVmdCApLmFwcGVuZCggJHBSaWdodCApO1xuXG4gICAgICAgICAgdmFyICRwSW5kaWNhdG9yID0gJCgnPGRpdiBjbGFzcz1cImN5LXBhbnpvb20tcGFuLWluZGljYXRvclwiPjwvZGl2PicpO1xuICAgICAgICAgICRwYW5uZXIuYXBwZW5kKCAkcEluZGljYXRvciApO1xuXG4gICAgICAgICAgLy8gZnVuY3Rpb25zIGZvciBjYWxjdWxhdGluZyBwYW5uaW5nXG4gICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgICAgICAgICBmdW5jdGlvbiBoYW5kbGUycGFuKGUpe1xuICAgICAgICAgICAgdmFyIHYgPSB7XG4gICAgICAgICAgICAgIHg6IGUub3JpZ2luYWxFdmVudC5wYWdlWCAtICRwYW5uZXIub2Zmc2V0KCkubGVmdCAtICRwYW5uZXIud2lkdGgoKS8yLFxuICAgICAgICAgICAgICB5OiBlLm9yaWdpbmFsRXZlbnQucGFnZVkgLSAkcGFubmVyLm9mZnNldCgpLnRvcCAtICRwYW5uZXIuaGVpZ2h0KCkvMlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgciA9IG9wdGlvbnMucGFuRHJhZ0FyZWFTaXplO1xuICAgICAgICAgICAgdmFyIGQgPSBNYXRoLnNxcnQoIHYueCp2LnggKyB2Lnkqdi55ICk7XG4gICAgICAgICAgICB2YXIgcGVyY2VudCA9IE1hdGgubWluKCBkL3IsIDEgKTtcblxuICAgICAgICAgICAgaWYoIGQgPCBvcHRpb25zLnBhbkluYWN0aXZlQXJlYSApe1xuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHg6IE5hTixcbiAgICAgICAgICAgICAgICB5OiBOYU5cbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdiA9IHtcbiAgICAgICAgICAgICAgeDogdi54L2QsXG4gICAgICAgICAgICAgIHk6IHYueS9kXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBwZXJjZW50ID0gTWF0aC5tYXgoIG9wdGlvbnMucGFuTWluUGVyY2VudFNwZWVkLCBwZXJjZW50ICk7XG5cbiAgICAgICAgICAgIHZhciB2bm9ybSA9IHtcbiAgICAgICAgICAgICAgeDogLTEgKiB2LnggKiAocGVyY2VudCAqIG9wdGlvbnMucGFuRGlzdGFuY2UpLFxuICAgICAgICAgICAgICB5OiAtMSAqIHYueSAqIChwZXJjZW50ICogb3B0aW9ucy5wYW5EaXN0YW5jZSlcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiB2bm9ybTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmdW5jdGlvbiBkb25lUGFubmluZygpe1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChwYW5JbnRlcnZhbCk7XG4gICAgICAgICAgICB3aW5kb3dVbmJpbmQoXCJtb3VzZW1vdmVcIiwgaGFuZGxlcik7XG5cbiAgICAgICAgICAgICRwSW5kaWNhdG9yLmhpZGUoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmdW5jdGlvbiBwb3NpdGlvbkluZGljYXRvcihwYW4pe1xuICAgICAgICAgICAgdmFyIHYgPSBwYW47XG4gICAgICAgICAgICB2YXIgZCA9IE1hdGguc3FydCggdi54KnYueCArIHYueSp2LnkgKTtcbiAgICAgICAgICAgIHZhciB2bm9ybSA9IHtcbiAgICAgICAgICAgICAgeDogLTEgKiB2LngvZCxcbiAgICAgICAgICAgICAgeTogLTEgKiB2LnkvZFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdmFyIHcgPSAkcGFubmVyLndpZHRoKCk7XG4gICAgICAgICAgICB2YXIgaCA9ICRwYW5uZXIuaGVpZ2h0KCk7XG4gICAgICAgICAgICB2YXIgcGVyY2VudCA9IGQvb3B0aW9ucy5wYW5EaXN0YW5jZTtcbiAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gTWF0aC5tYXgoIG9wdGlvbnMucGFuSW5kaWNhdG9yTWluT3BhY2l0eSwgcGVyY2VudCApO1xuICAgICAgICAgICAgdmFyIGNvbG9yID0gMjU1IC0gTWF0aC5yb3VuZCggb3BhY2l0eSAqIDI1NSApO1xuXG4gICAgICAgICAgICAkcEluZGljYXRvci5zaG93KCkuY3NzKHtcbiAgICAgICAgICAgICAgbGVmdDogdy8yICogdm5vcm0ueCArIHcvMixcbiAgICAgICAgICAgICAgdG9wOiBoLzIgKiB2bm9ybS55ICsgaC8yLFxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiBcInJnYihcIiArIGNvbG9yICsgXCIsIFwiICsgY29sb3IgKyBcIiwgXCIgKyBjb2xvciArIFwiKVwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmdW5jdGlvbiBjYWxjdWxhdGVab29tQ2VudGVyUG9pbnQoKXtcbiAgICAgICAgICAgIHZhciBwYW4gPSBjeVJlZi5wYW4oKTtcbiAgICAgICAgICAgIHZhciB6b29tID0gY3lSZWYuem9vbSgpO1xuXG4gICAgICAgICAgICB6eCA9ICRjb250YWluZXIud2lkdGgoKS8yO1xuICAgICAgICAgICAgenkgPSAkY29udGFpbmVyLmhlaWdodCgpLzI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHpvb21pbmcgPSBmYWxzZTtcbiAgICAgICAgICBmdW5jdGlvbiBzdGFydFpvb21pbmcoKXtcbiAgICAgICAgICAgIHpvb21pbmcgPSB0cnVlO1xuXG4gICAgICAgICAgICBjYWxjdWxhdGVab29tQ2VudGVyUG9pbnQoKTtcbiAgICAgICAgICB9XG5cblxuICAgICAgICAgIGZ1bmN0aW9uIGVuZFpvb21pbmcoKXtcbiAgICAgICAgICAgIHpvb21pbmcgPSBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgengsIHp5O1xuICAgICAgICAgIGZ1bmN0aW9uIHpvb21UbyhsZXZlbCl7XG4gICAgICAgICAgICBpZiggIXpvb21pbmcgKXsgLy8gZm9yIG5vbi1jb250aW51b3VzIHpvb21pbmcgKGUuZy4gY2xpY2sgc2xpZGVyIGF0IHB0KVxuICAgICAgICAgICAgICBjYWxjdWxhdGVab29tQ2VudGVyUG9pbnQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY3lSZWYuem9vbSh7XG4gICAgICAgICAgICAgIGxldmVsOiBsZXZlbCxcbiAgICAgICAgICAgICAgcmVuZGVyZWRQb3NpdGlvbjogeyB4OiB6eCwgeTogenkgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHBhbkludGVydmFsO1xuXG4gICAgICAgICAgdmFyIGhhbmRsZXIgPSBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIGRvbid0IHRyaWdnZXIgZHJhZ2dpbmcgb2YgcGFuem9vbVxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyBkb24ndCBjYXVzZSB0ZXh0IHNlbGVjdGlvblxuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChwYW5JbnRlcnZhbCk7XG5cbiAgICAgICAgICAgIHZhciBwYW4gPSBoYW5kbGUycGFuKGUpO1xuXG4gICAgICAgICAgICBpZiggaXNOYU4ocGFuLngpIHx8IGlzTmFOKHBhbi55KSApe1xuICAgICAgICAgICAgICAkcEluZGljYXRvci5oaWRlKCk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcG9zaXRpb25JbmRpY2F0b3IocGFuKTtcbiAgICAgICAgICAgIHBhbkludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgY3lSZWYucGFuQnkocGFuKTtcbiAgICAgICAgICAgIH0sIG9wdGlvbnMucGFuU3BlZWQpO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICAkcEhhbmRsZS5iaW5kKFwibW91c2Vkb3duXCIsIGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgLy8gaGFuZGxlIGNsaWNrIG9mIGljb25cbiAgICAgICAgICAgIGhhbmRsZXIoZSk7XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSBvbiBtb3VzZW1vdmVcbiAgICAgICAgICAgIHdpbmRvd0JpbmQoXCJtb3VzZW1vdmVcIiwgaGFuZGxlcik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAkcEhhbmRsZS5iaW5kKFwibW91c2V1cFwiLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgZG9uZVBhbm5pbmcoKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHdpbmRvd0JpbmQoXCJtb3VzZXVwIGJsdXJcIiwgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGRvbmVQYW5uaW5nKCk7XG4gICAgICAgICAgfSk7XG5cblxuXG4gICAgICAgICAgLy8gc2V0IHVwIHNsaWRlciBiZWhhdmlvdXJcbiAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgJHNsaWRlci5iaW5kKCdtb3VzZWRvd24nLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzbyB3ZSBkb24ndCBwYW4gY2xvc2UgdG8gdGhlIHNsaWRlciBoYW5kbGVcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHZhciBzbGlkZXJWYWw7XG4gICAgICAgICAgdmFyIHNsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB2YXIgc2xpZGVyUGFkZGluZyA9IDI7XG5cbiAgICAgICAgICBmdW5jdGlvbiBzZXRTbGlkZXJGcm9tTW91c2UoZXZ0LCBoYW5kbGVPZmZzZXQpe1xuICAgICAgICAgICAgaWYoIGhhbmRsZU9mZnNldCA9PT0gdW5kZWZpbmVkICl7XG4gICAgICAgICAgICAgIGhhbmRsZU9mZnNldCA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYWRkaW5nID0gc2xpZGVyUGFkZGluZztcbiAgICAgICAgICAgIHZhciBtaW4gPSAwICsgcGFkZGluZztcbiAgICAgICAgICAgIHZhciBtYXggPSAkc2xpZGVyLmhlaWdodCgpIC0gJHNsaWRlckhhbmRsZS5oZWlnaHQoKSAtIDIqcGFkZGluZztcbiAgICAgICAgICAgIHZhciB0b3AgPSBldnQucGFnZVkgLSAkc2xpZGVyLm9mZnNldCgpLnRvcCAtIGhhbmRsZU9mZnNldDtcblxuICAgICAgICAgICAgLy8gY29uc3RyYWluIHRvIHNsaWRlciBib3VuZHNcbiAgICAgICAgICAgIGlmKCB0b3AgPCBtaW4gKXsgdG9wID0gbWluIH1cbiAgICAgICAgICAgIGlmKCB0b3AgPiBtYXggKXsgdG9wID0gbWF4IH1cblxuICAgICAgICAgICAgdmFyIHBlcmNlbnQgPSAxIC0gKHRvcCAtIG1pbikgLyAoIG1heCAtIG1pbiApO1xuXG4gICAgICAgICAgICAvLyBtb3ZlIHRoZSBoYW5kbGVcbiAgICAgICAgICAgICRzbGlkZXJIYW5kbGUuY3NzKCd0b3AnLCB0b3ApO1xuXG4gICAgICAgICAgICB2YXIgem1pbiA9IG9wdGlvbnMubWluWm9vbTtcbiAgICAgICAgICAgIHZhciB6bWF4ID0gb3B0aW9ucy5tYXhab29tO1xuXG4gICAgICAgICAgICAvLyBhc3N1bWUgKHpvb20gPSB6bWF4IF4gcCkgd2hlcmUgcCByYW5nZXMgb24gKHgsIDEpIHdpdGggeCBuZWdhdGl2ZVxuICAgICAgICAgICAgdmFyIHggPSBNYXRoLmxvZyh6bWluKSAvIE1hdGgubG9nKHptYXgpO1xuICAgICAgICAgICAgdmFyIHAgPSAoMSAtIHgpKnBlcmNlbnQgKyB4O1xuXG4gICAgICAgICAgICAvLyBjaGFuZ2UgdGhlIHpvb20gbGV2ZWxcbiAgICAgICAgICAgIHZhciB6ID0gTWF0aC5wb3coIHptYXgsIHAgKTtcblxuICAgICAgICAgICAgLy8gYm91bmQgdGhlIHpvb20gdmFsdWUgaW4gY2FzZSBvZiBmbG9hdGluZyBwdCByb3VuZGluZyBlcnJvclxuICAgICAgICAgICAgaWYoIHogPCB6bWluICl7XG4gICAgICAgICAgICAgIHogPSB6bWluO1xuICAgICAgICAgICAgfSBlbHNlIGlmKCB6ID4gem1heCApe1xuICAgICAgICAgICAgICB6ID0gem1heDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgem9vbVRvKCB6ICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHNsaWRlck1kb3duSGFuZGxlciwgc2xpZGVyTW1vdmVIYW5kbGVyO1xuICAgICAgICAgICRzbGlkZXJIYW5kbGUuYmluZCgnbW91c2Vkb3duJywgc2xpZGVyTWRvd25IYW5kbGVyID0gZnVuY3Rpb24oIG1kRXZ0ICl7XG4gICAgICAgICAgICB2YXIgaGFuZGxlT2Zmc2V0ID0gbWRFdnQudGFyZ2V0ID09PSAkc2xpZGVySGFuZGxlWzBdID8gbWRFdnQub2Zmc2V0WSA6IDA7XG4gICAgICAgICAgICBzbGlkaW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgc3RhcnRab29taW5nKCk7XG4gICAgICAgICAgICAkc2xpZGVySGFuZGxlLmFkZENsYXNzKFwiYWN0aXZlXCIpO1xuXG4gICAgICAgICAgICB2YXIgbGFzdE1vdmUgPSAwO1xuICAgICAgICAgICAgd2luZG93QmluZCgnbW91c2Vtb3ZlJywgc2xpZGVyTW1vdmVIYW5kbGVyID0gZnVuY3Rpb24oIG1tRXZ0ICl7XG4gICAgICAgICAgICAgIHZhciBub3cgPSArbmV3IERhdGU7XG5cbiAgICAgICAgICAgICAgLy8gdGhyb3R0bGUgdGhlIHpvb21zIGV2ZXJ5IDEwIG1zIHNvIHdlIGRvbid0IGNhbGwgem9vbSB0b28gb2Z0ZW4gYW5kIGNhdXNlIGxhZ1xuICAgICAgICAgICAgICBpZiggbm93ID4gbGFzdE1vdmUgKyAxMCApe1xuICAgICAgICAgICAgICAgIGxhc3RNb3ZlID0gbm93O1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHNldFNsaWRlckZyb21Nb3VzZShtbUV2dCwgaGFuZGxlT2Zmc2V0KTtcblxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gdW5iaW5kIHdoZW5cbiAgICAgICAgICAgIHdpbmRvd0JpbmQoJ21vdXNldXAnLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgICB3aW5kb3dVbmJpbmQoJ21vdXNlbW92ZScsIHNsaWRlck1tb3ZlSGFuZGxlcik7XG4gICAgICAgICAgICAgIHNsaWRpbmcgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAkc2xpZGVySGFuZGxlLnJlbW92ZUNsYXNzKFwiYWN0aXZlXCIpO1xuICAgICAgICAgICAgICBlbmRab29taW5nKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgJHNsaWRlci5iaW5kKCdtb3VzZWRvd24nLCBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgIGlmKCBlLnRhcmdldCAhPT0gJHNsaWRlckhhbmRsZVswXSApe1xuICAgICAgICAgICAgICBzbGlkZXJNZG93bkhhbmRsZXIoZSk7XG4gICAgICAgICAgICAgIHNldFNsaWRlckZyb21Nb3VzZShlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGZ1bmN0aW9uIHBvc2l0aW9uU2xpZGVyRnJvbVpvb20oKXtcbiAgICAgICAgICAgIHZhciB6ID0gY3lSZWYuem9vbSgpO1xuICAgICAgICAgICAgdmFyIHptaW4gPSBvcHRpb25zLm1pblpvb207XG4gICAgICAgICAgICB2YXIgem1heCA9IG9wdGlvbnMubWF4Wm9vbTtcblxuICAgICAgICAgICAgLy8gYXNzdW1lICh6b29tID0gem1heCBeIHApIHdoZXJlIHAgcmFuZ2VzIG9uICh4LCAxKSB3aXRoIHggbmVnYXRpdmVcbiAgICAgICAgICAgIHZhciB4ID0gTWF0aC5sb2coem1pbikgLyBNYXRoLmxvZyh6bWF4KTtcbiAgICAgICAgICAgIHZhciBwID0gTWF0aC5sb2coeikgLyBNYXRoLmxvZyh6bWF4KTtcbiAgICAgICAgICAgIHZhciBwZXJjZW50ID0gMSAtIChwIC0geCkgLyAoMSAtIHgpOyAvLyB0aGUgMS0gYml0IGF0IHRoZSBmcm9udCBiL2MgdXAgaXMgaW4gdGhlIC12ZSB5IGRpcmVjdGlvblxuXG4gICAgICAgICAgICB2YXIgbWluID0gc2xpZGVyUGFkZGluZztcbiAgICAgICAgICAgIHZhciBtYXggPSAkc2xpZGVyLmhlaWdodCgpIC0gJHNsaWRlckhhbmRsZS5oZWlnaHQoKSAtIDIqc2xpZGVyUGFkZGluZztcbiAgICAgICAgICAgIHZhciB0b3AgPSBwZXJjZW50ICogKCBtYXggLSBtaW4gKTtcblxuICAgICAgICAgICAgLy8gY29uc3RyYWluIHRvIHNsaWRlciBib3VuZHNcbiAgICAgICAgICAgIGlmKCB0b3AgPCBtaW4gKXsgdG9wID0gbWluIH1cbiAgICAgICAgICAgIGlmKCB0b3AgPiBtYXggKXsgdG9wID0gbWF4IH1cblxuICAgICAgICAgICAgLy8gbW92ZSB0aGUgaGFuZGxlXG4gICAgICAgICAgICAkc2xpZGVySGFuZGxlLmNzcygndG9wJywgdG9wKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwb3NpdGlvblNsaWRlckZyb21ab29tKCk7XG5cbiAgICAgICAgICBjeU9uKCd6b29tJywgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGlmKCAhc2xpZGluZyApe1xuICAgICAgICAgICAgICBwb3NpdGlvblNsaWRlckZyb21ab29tKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzZXQgdGhlIHBvc2l0aW9uIG9mIHRoZSB6b29tPTEgdGlja1xuICAgICAgICAgIChmdW5jdGlvbigpe1xuICAgICAgICAgICAgdmFyIHogPSAxO1xuICAgICAgICAgICAgdmFyIHptaW4gPSBvcHRpb25zLm1pblpvb207XG4gICAgICAgICAgICB2YXIgem1heCA9IG9wdGlvbnMubWF4Wm9vbTtcblxuICAgICAgICAgICAgLy8gYXNzdW1lICh6b29tID0gem1heCBeIHApIHdoZXJlIHAgcmFuZ2VzIG9uICh4LCAxKSB3aXRoIHggbmVnYXRpdmVcbiAgICAgICAgICAgIHZhciB4ID0gTWF0aC5sb2coem1pbikgLyBNYXRoLmxvZyh6bWF4KTtcbiAgICAgICAgICAgIHZhciBwID0gTWF0aC5sb2coeikgLyBNYXRoLmxvZyh6bWF4KTtcbiAgICAgICAgICAgIHZhciBwZXJjZW50ID0gMSAtIChwIC0geCkgLyAoMSAtIHgpOyAvLyB0aGUgMS0gYml0IGF0IHRoZSBmcm9udCBiL2MgdXAgaXMgaW4gdGhlIC12ZSB5IGRpcmVjdGlvblxuXG4gICAgICAgICAgICBpZiggcGVyY2VudCA+IDEgfHwgcGVyY2VudCA8IDAgKXtcbiAgICAgICAgICAgICAgJG5vWm9vbVRpY2suaGlkZSgpO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBtaW4gPSBzbGlkZXJQYWRkaW5nO1xuICAgICAgICAgICAgdmFyIG1heCA9ICRzbGlkZXIuaGVpZ2h0KCkgLSAkc2xpZGVySGFuZGxlLmhlaWdodCgpIC0gMipzbGlkZXJQYWRkaW5nO1xuICAgICAgICAgICAgdmFyIHRvcCA9IHBlcmNlbnQgKiAoIG1heCAtIG1pbiApO1xuXG4gICAgICAgICAgICAvLyBjb25zdHJhaW4gdG8gc2xpZGVyIGJvdW5kc1xuICAgICAgICAgICAgaWYoIHRvcCA8IG1pbiApeyB0b3AgPSBtaW4gfVxuICAgICAgICAgICAgaWYoIHRvcCA+IG1heCApeyB0b3AgPSBtYXggfVxuXG4gICAgICAgICAgICAkbm9ab29tVGljay5jc3MoJ3RvcCcsIHRvcCk7XG4gICAgICAgICAgfSkoKTtcblxuICAgICAgICAgIC8vIHNldCB1cCB6b29tIGluL291dCBidXR0b25zXG4gICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgICAgIGZ1bmN0aW9uIGJpbmRCdXR0b24oJGJ1dHRvbiwgZmFjdG9yKXtcbiAgICAgICAgICAgIHZhciB6b29tSW50ZXJ2YWw7XG5cbiAgICAgICAgICAgICRidXR0b24uYmluZChcIm1vdXNlZG93blwiLCBmdW5jdGlvbihlKXtcbiAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgICAgIGlmKCBlLmJ1dHRvbiAhPSAwICl7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmFyIGRvWm9vbSA9IGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgdmFyIHpvb20gPSBjeVJlZi56b29tKCk7XG4gICAgICAgICAgICAgICAgdmFyIGx2bCA9IGN5UmVmLnpvb20oKSAqIGZhY3RvcjtcblxuICAgICAgICAgICAgICAgIGlmKCBsdmwgPCBvcHRpb25zLm1pblpvb20gKXtcbiAgICAgICAgICAgICAgICAgIGx2bCA9IG9wdGlvbnMubWluWm9vbTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiggbHZsID4gb3B0aW9ucy5tYXhab29tICl7XG4gICAgICAgICAgICAgICAgICBsdmwgPSBvcHRpb25zLm1heFpvb207XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoIChsdmwgPT0gb3B0aW9ucy5tYXhab29tICYmIHpvb20gPT0gb3B0aW9ucy5tYXhab29tKSB8fFxuICAgICAgICAgICAgICAgICAgKGx2bCA9PSBvcHRpb25zLm1pblpvb20gJiYgem9vbSA9PSBvcHRpb25zLm1pblpvb20pXG4gICAgICAgICAgICAgICAgKXtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB6b29tVG8obHZsKTtcbiAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICBzdGFydFpvb21pbmcoKTtcbiAgICAgICAgICAgICAgZG9ab29tKCk7XG4gICAgICAgICAgICAgIHpvb21JbnRlcnZhbCA9IHNldEludGVydmFsKGRvWm9vbSwgb3B0aW9ucy56b29tRGVsYXkpO1xuXG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB3aW5kb3dCaW5kKFwibW91c2V1cCBibHVyXCIsIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoem9vbUludGVydmFsKTtcbiAgICAgICAgICAgICAgZW5kWm9vbWluZygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYmluZEJ1dHRvbiggJHpvb21JbiwgKDEgKyBvcHRpb25zLnpvb21GYWN0b3IpICk7XG4gICAgICAgICAgYmluZEJ1dHRvbiggJHpvb21PdXQsICgxIC0gb3B0aW9ucy56b29tRmFjdG9yKSApO1xuXG4gICAgICAgICAgJHJlc2V0LmJpbmQoXCJtb3VzZWRvd25cIiwgZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICBpZiggZS5idXR0b24gIT0gMCApe1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBlbGVzVG9GaXQgPSBvcHRpb25zLmZpdFNlbGVjdG9yP2N5UmVmLmVsZW1lbnRzKG9wdGlvbnMuZml0U2VsZWN0b3IpOmN5UmVmLmVsZW1lbnRzKCk7XG5cbiAgICAgICAgICAgIGlmKCBlbGVzVG9GaXQuc2l6ZSgpID09PSAwICl7XG4gICAgICAgICAgICAgIGN5UmVmLnJlc2V0KCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2YXIgYW5pbWF0ZU9uRml0ID0gdHlwZW9mIG9wdGlvbnMuYW5pbWF0ZU9uRml0ID09PSAnZnVuY3Rpb24nID8gb3B0aW9ucy5hbmltYXRlT25GaXQuY2FsbCgpIDogb3B0aW9ucy5hbmltYXRlT25GaXQ7XG4gICAgICAgICAgICAgIGlmKGFuaW1hdGVPbkZpdCl7XG4gICAgICAgICAgICAgICAgY3lSZWYuYW5pbWF0ZSh7XG4gICAgICAgICAgICAgICAgICBmaXQ6IHtcbiAgICAgICAgICAgICAgICAgICAgZWxlczogZWxlc1RvRml0LFxuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nOiBvcHRpb25zLmZpdFBhZGRpbmdcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICBkdXJhdGlvbjogb3B0aW9ucy5maXRBbmltYXRpb25EdXJhdGlvblxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgY3lSZWYuZml0KCBlbGVzVG9GaXQsIG9wdGlvbnMuZml0UGFkZGluZyApO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH0pO1xuXG5cblxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYoIGZ1bmN0aW9uc1tmbl0gKXtcbiAgICAgIHJldHVybiBmdW5jdGlvbnNbZm5dLmFwcGx5KHRoaXMsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKCBhcmd1bWVudHMsIDEgKSk7XG4gICAgfSBlbHNlIGlmKCB0eXBlb2YgZm4gPT0gJ29iamVjdCcgfHwgIWZuICkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9ucy5pbml0LmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgJC5lcnJvcihcIk5vIHN1Y2ggZnVuY3Rpb24gYFwiKyBmbiArXCJgIGZvciBqcXVlcnkuY3l0b3NjYXBlUGFuem9vbVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gJCh0aGlzKTtcbiAgfTtcblxuXG4gIGlmKCB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cyApeyAvLyBleHBvc2UgYXMgYSBjb21tb25qcyBtb2R1bGVcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCBjeXRvc2NhcGUsIGpxdWVyeSApe1xuICAgICAgcmVnaXN0ZXIoIGN5dG9zY2FwZSwganF1ZXJ5IHx8IHJlcXVpcmUoJ2pxdWVyeScpICk7XG4gICAgfVxuICB9IGVsc2UgaWYoIHR5cGVvZiBkZWZpbmUgIT09ICd1bmRlZmluZWQnICYmIGRlZmluZS5hbWQgKXsgLy8gZXhwb3NlIGFzIGFuIGFtZC9yZXF1aXJlanMgbW9kdWxlXG4gICAgZGVmaW5lKCdjeXRvc2NhcGUtcGFuem9vbScsIGZ1bmN0aW9uKCl7XG4gICAgICByZXR1cm4gcmVnaXN0ZXI7XG4gICAgfSk7XG4gIH1cblxuICBpZiggdHlwZW9mIGN5dG9zY2FwZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGpRdWVyeSAhPT0gJ3VuZGVmaW5lZCcgKXsgLy8gZXhwb3NlIHRvIGdsb2JhbCBjeXRvc2NhcGUgKGkuZS4gd2luZG93LmN5dG9zY2FwZSlcbiAgICByZWdpc3RlciggY3l0b3NjYXBlLCBqUXVlcnkgKTtcbiAgfVxuXG59KSgpO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/cytoscape-panzoom/cytoscape-panzoom.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css":
+/*!*****************************************************************!*\
+ !*** ./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css ***!
+ \*****************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("\nvar content = __webpack_require__(/*! !../css-loader!./cytoscape.js-panzoom.css */ \"./node_modules/css-loader/index.js!./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css\");\n\nif(typeof content === 'string') content = [[module.i, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = __webpack_require__(/*! ../style-loader/lib/addStyles.js */ \"./node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(false) {}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9kYXNoX2N5dG9zY2FwZS8uL25vZGVfbW9kdWxlcy9jeXRvc2NhcGUtcGFuem9vbS9jeXRvc2NhcGUuanMtcGFuem9vbS5jc3M/OTU5ZCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsY0FBYyxtQkFBTyxDQUFDLCtJQUFxRDs7QUFFM0UsNENBQTRDLFFBQVM7O0FBRXJEO0FBQ0E7Ozs7QUFJQSxlQUFlOztBQUVmO0FBQ0E7O0FBRUEsYUFBYSxtQkFBTyxDQUFDLHNGQUFtQzs7QUFFeEQ7O0FBRUEsR0FBRyxLQUFVLEVBQUUiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY3l0b3NjYXBlLXBhbnpvb20vY3l0b3NjYXBlLmpzLXBhbnpvb20uY3NzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG52YXIgY29udGVudCA9IHJlcXVpcmUoXCIhIS4uL2Nzcy1sb2FkZXIvaW5kZXguanMhLi9jeXRvc2NhcGUuanMtcGFuem9vbS5jc3NcIik7XG5cbmlmKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykgY29udGVudCA9IFtbbW9kdWxlLmlkLCBjb250ZW50LCAnJ11dO1xuXG52YXIgdHJhbnNmb3JtO1xudmFyIGluc2VydEludG87XG5cblxuXG52YXIgb3B0aW9ucyA9IHtcImhtclwiOnRydWV9XG5cbm9wdGlvbnMudHJhbnNmb3JtID0gdHJhbnNmb3JtXG5vcHRpb25zLmluc2VydEludG8gPSB1bmRlZmluZWQ7XG5cbnZhciB1cGRhdGUgPSByZXF1aXJlKFwiIS4uL3N0eWxlLWxvYWRlci9saWIvYWRkU3R5bGVzLmpzXCIpKGNvbnRlbnQsIG9wdGlvbnMpO1xuXG5pZihjb250ZW50LmxvY2FscykgbW9kdWxlLmV4cG9ydHMgPSBjb250ZW50LmxvY2FscztcblxuaWYobW9kdWxlLmhvdCkge1xuXHRtb2R1bGUuaG90LmFjY2VwdChcIiEhLi4vY3NzLWxvYWRlci9pbmRleC5qcyEuL2N5dG9zY2FwZS5qcy1wYW56b29tLmNzc1wiLCBmdW5jdGlvbigpIHtcblx0XHR2YXIgbmV3Q29udGVudCA9IHJlcXVpcmUoXCIhIS4uL2Nzcy1sb2FkZXIvaW5kZXguanMhLi9jeXRvc2NhcGUuanMtcGFuem9vbS5jc3NcIik7XG5cblx0XHRpZih0eXBlb2YgbmV3Q29udGVudCA9PT0gJ3N0cmluZycpIG5ld0NvbnRlbnQgPSBbW21vZHVsZS5pZCwgbmV3Q29udGVudCwgJyddXTtcblxuXHRcdHZhciBsb2NhbHMgPSAoZnVuY3Rpb24oYSwgYikge1xuXHRcdFx0dmFyIGtleSwgaWR4ID0gMDtcblxuXHRcdFx0Zm9yKGtleSBpbiBhKSB7XG5cdFx0XHRcdGlmKCFiIHx8IGFba2V5XSAhPT0gYltrZXldKSByZXR1cm4gZmFsc2U7XG5cdFx0XHRcdGlkeCsrO1xuXHRcdFx0fVxuXG5cdFx0XHRmb3Ioa2V5IGluIGIpIGlkeC0tO1xuXG5cdFx0XHRyZXR1cm4gaWR4ID09PSAwO1xuXHRcdH0oY29udGVudC5sb2NhbHMsIG5ld0NvbnRlbnQubG9jYWxzKSk7XG5cblx0XHRpZighbG9jYWxzKSB0aHJvdyBuZXcgRXJyb3IoJ0Fib3J0aW5nIENTUyBITVIgZHVlIHRvIGNoYW5nZWQgY3NzLW1vZHVsZXMgbG9jYWxzLicpO1xuXG5cdFx0dXBkYXRlKG5ld0NvbnRlbnQpO1xuXHR9KTtcblxuXHRtb2R1bGUuaG90LmRpc3Bvc2UoZnVuY3Rpb24oKSB7IHVwZGF0ZSgpOyB9KTtcbn0iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/cytoscape-panzoom/cytoscape.js-panzoom.css\n");
+
+/***/ }),
+
/***/ "./node_modules/cytoscape/dist/cytoscape.cjs.js":
/*!******************************************************!*\
!*** ./node_modules/cytoscape/dist/cytoscape.cjs.js ***!
@@ -121,6 +165,17 @@ eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPAC
/***/ }),
+/***/ "./node_modules/jquery/dist/jquery.js":
+/*!********************************************!*\
+ !*** ./node_modules/jquery/dist/jquery.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * jQuery JavaScript Library v3.6.0\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright OpenJS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2021-03-02T17:08Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( true && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar flat = arr.flat ? function( array ) {\n\treturn arr.flat.call( array );\n} : function( array ) {\n\treturn arr.concat.apply( [], array );\n};\n\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n\t\t// Support: Chrome <=57, Firefox <=52\n\t\t// In some browsers, typeof returns \"function\" for HTML