UNPKG

treant

Version:

Dependency free component library for the browser

1,061 lines (908 loc) 76.4 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treant = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var hook = require("./src/hook") var register = require("./src/register") var component = require("./src/create") var storage = require("./src/storage") var Component = require("./src/Component") var delegate = require("./src/delegate") var fragment = require("./src/fragment") var treant = {} module.exports = treant treant.register = register treant.component = component treant.storage = storage treant.Component = Component treant.delegate = delegate treant.fragment = fragment treant.hook = hook var util = {} treant.util = util util.extend = require("./util/extend") util.merge = require("./util/merge") util.object = require("./util/object") },{"./src/Component":3,"./src/create":5,"./src/delegate":6,"./src/fragment":7,"./src/hook":8,"./src/register":9,"./src/storage":11,"./util/extend":12,"./util/merge":13,"./util/object":14}],2:[function(require,module,exports){ 'use strict'; module.exports = function (str) { str = str.trim(); if (str.length === 1 || !(/[_.\- ]+/).test(str) ) { if (str[0] === str[0].toLowerCase() && str.slice(1) !== str.slice(1).toLowerCase()) { return str; } return str.toLowerCase(); } return str .replace(/^[_.\- ]+/, '') .toLowerCase() .replace(/[_.\- ]+(\w|$)/g, function (m, p1) { return p1.toUpperCase(); }); }; },{}],3:[function(require,module,exports){ var hook = require("./hook") var registry = require("./registry") var storage = require("./storage") var delegate = require("./delegate") module.exports = Component function Component (element, options) { if (element && !(element instanceof Element)) { throw new Error("element should be an Element instance or null") } if (!(this instanceof Component)) { return new Component(element, options) } this._element = null this._id = null this.components = {} this.element = element || null } Component.create = function (name, element, options) { var ComponentConstructor = null if (registry.exists(name)) { ComponentConstructor = registry.get(name) } else { console.warn("Missing component definition: ", name) return null } return new ComponentConstructor(element, options) } Component.prototype = { constructor: Component, destroy: function () { storage.remove(this) this.element = null var components = this.components var component for (var name in components) { if (components.hasOwnProperty(name)) { component = components[name] if (component.destroy) { component.destroy() } } } this.components = null }, delegate: function (options) { options.element = this.element options.context = options.context || this return delegate(options) }, action: function (event) { return this.constructor.createAction(event) }, dispatch: function (type, detail) { var definition = this.constructor.getEventDefinition(type, detail) return this.element.dispatchEvent(new window.CustomEvent(type, definition)) }, findComponent: function (name) { return hook.findComponent(name, this.element) }, findAllComponents: function (name) { return hook.findAllComponents(name, this.element) }, findSubComponents: function () { //var subComponents = [] //var element = this.element //this.constructor.parents.forEach(function (ParentComponent) { // var components = hook.findSubComponents(ParentComponent.componentName, element) // subComponents = subComponents.concat(components) //}) //subComponents = subComponents.concat(hook.findSubComponents(this.getMainComponentName(false), element)) //return subComponents return hook.findSubComponents(this.getMainComponentName(false), this.element) }, getComponentName: function (cc) { return hook.getComponentName(this.constructor.componentName, cc) }, getMainComponentName: function (cc) { return hook.getMainComponentName(this.constructor.componentName, cc) }, getSubComponentName: function (cc) { return hook.getSubComponentName(this.constructor.componentName, cc) }, clearSubComponents: function () { var components = this.constructor.components for (var name in components) { if (components.hasOwnProperty(name)) { if (Array.isArray(components[name])) { this.components[name] = [] } else { this.components[name] = components[name] } } } }, assignSubComponents: function (transform) { if (!this.element) return var hostComponent = this var subComponents = this.findSubComponents() var constructor = this.constructor this.clearSubComponents() if (!subComponents.length) { return } if (typeof transform == "undefined" || transform === true) { transform = function (element, name) { // TODO: subclass subcomponents should be handled properly (B extends A that has a subcomponent A:a becomes B:a that's not in the registry) return registry.exists(name) ? Component.create(name, element, hostComponent) : element } } hook.assignSubComponents(this.components, subComponents, transform, function (components, name, element) { if (Array.isArray(constructor.components[name])) { components[name] = components[name] || [] components[name].push(element) } else { components[name] = element } }) } } Object.defineProperty(Component.prototype, "element", { get: function () { return this._element }, set: function (element) { this._element = element if (element && this.constructor.componentName) { if (this.constructor.autoSave) { storage.save(this) } if (this.constructor.autoAssign) { this.assignSubComponents() } this.constructor.resetAttributes(this) } } }) },{"./delegate":6,"./hook":8,"./registry":10,"./storage":11}],4:[function(require,module,exports){ var camelcase = require("camelcase") var extend = require("../util/extend") var merge = require("../util/merge") var object = require("../util/object") var delegate = require("./delegate") var storage = require("./storage") var registry = require("./registry") var hook = require("./hook") var defaultEventDefinition = { detail: null, view: window, bubbles: true, cancelable: true } module.exports = function (CustomComponent, componentName) { CustomComponent.componentName = componentName CustomComponent.autoAssign = true CustomComponent.autoSave = true CustomComponent.components = {} CustomComponent.parents = [] var prototype = CustomComponent.prototype var _events = CustomComponent._events = {} var _constructors = CustomComponent._constructors = [] var _attributes = CustomComponent._attributes = {} var _actions = CustomComponent._actions = [] CustomComponent.extend = function (BaseComponent) { prototype = CustomComponent.prototype = Object.create(BaseComponent.prototype) CustomComponent.prototype.constructor = CustomComponent if (BaseComponent.componentName) { CustomComponent.parents = CustomComponent.parents.concat(BaseComponent.parents) CustomComponent.parents.push(BaseComponent) CustomComponent.autoAssign = BaseComponent.autoAssign extend(CustomComponent.components, BaseComponent.components) extend(_events, BaseComponent._events) _constructors = _constructors.concat(BaseComponent._constructors) extend(_attributes, BaseComponent._attributes) BaseComponent._actions.forEach(function (args) { var event = args[0] var matches = args[1] var matcher = CustomComponent.action(event) matches.forEach(function (args) { matcher.match.apply(matcher, args) }) }) } } CustomComponent.onCreate = function (constructor) { _constructors.push(constructor) return CustomComponent } CustomComponent.create = function (instance, args) { _constructors.forEach(function (constructor) { constructor.apply(instance, args) }) } CustomComponent.method = function (name, fn) { object.method(prototype, name, fn) return CustomComponent } CustomComponent.property = function (name, fn) { object.property(prototype, name, fn) return CustomComponent } CustomComponent.get = function (name, fn) { object.defineGetter(prototype, name, fn) return CustomComponent } CustomComponent.set = function (name, fn) { object.defineSetter(prototype, name, fn) return CustomComponent } CustomComponent.accessor = function (name, get, set) { object.accessor(prototype, name, get, set) return CustomComponent } CustomComponent.proto = function (prototype) { for (var prop in prototype) { if (prototype.hasOwnProperty(prop)) { if (typeof prototype[prop] == "function") { if (prop === "onCreate") { CustomComponent.onCreate(prototype[prop]) } else { CustomComponent.method(prop, prototype[prop]) } } else { CustomComponent.property(prop, prototype[prop]) } } } return CustomComponent } CustomComponent.shortcut = function (name, componentName, extra) { CustomComponent.get(name, function () { var element = this.element.querySelector(hook.selector(componentName, "~=", extra)) return registry.exists(componentName) ? storage.get(element, componentName) : element }) } CustomComponent.action = function action(event) { var matches = [] var action = CustomComponent.createAction(event) var match = action.match _actions.push([event, matches]) action.match = function (components, cb) { matches.push([components, cb]) return match(components, cb) } return action } CustomComponent.createAction = function (event) { var delegator = delegate({element: window, event: event}) var action = {} action.match = function (components, cb) { if (!cb) { cb = components components = [] } if (typeof components == "string") { components = [components] } var selectors = components.map(function (component) { if (component[0] == ":") { component = componentName+component } return hook.selector(component, "~=") }) selectors.unshift(hook.selector(componentName, "~=")) delegator.match(selectors, function (e, main) { var instance = storage.get(main, componentName) || main var instanceComponents = instance.components var args = [e]; [].slice.call(arguments, 2).forEach(function (element, i) { var name = components[i] name = name[0] == ":" ? name.substr(1) : name var propertyName = camelcase(name) var arg if (instanceComponents && instanceComponents.hasOwnProperty(propertyName)) { arg = instance.components[propertyName] if (Array.isArray(arg)) { arg.some(function (member) { if (member == element || member.element == element) { arg = member return true } return false }) } } else { arg = storage.get(element, name) || element } args.push(arg) }) return cb.apply(instance, args) }) return action } return action } CustomComponent.event = function (type, definition) { _events[type] = definition return CustomComponent } CustomComponent.getEventDefinition = function (type, detail) { var definition = merge(defaultEventDefinition, _events[type]) definition.detail = typeof detail == "undefined" ? definition.detail : detail return definition } CustomComponent.resetAttributes = function (instance) { if (!instance.element) return var attribute var value for (var name in _attributes) { if (_attributes.hasOwnProperty(name)) { attribute = _attributes[name] value = attribute.get.call(instance, false) if (attribute.hasDefault && !attribute.has.call(instance, value)) { attribute.set.call(instance, attribute.defaultValue, false) } } } } CustomComponent.attribute = function (name, def) { if (def == null) { def = {} } var typeOfDef = typeof def var type var defaultValue var getter var setter var onchange var property = camelcase(name) switch (typeOfDef) { case "boolean": case "number": case "string": // the definition is a primitive value type = typeOfDef defaultValue = def break case "object": default: // or a definition object defaultValue = typeof def["default"] == "undefined" ? null : def["default"] if (typeof def["type"] == "undefined") { if (defaultValue == null) { type = "string" } else { type = typeof defaultValue } } else { type = def["type"] } getter = def["get"] setter = def["set"] onchange = def["onchange"] } var parseValue var stringifyValue var has has = function (value) { return value != null } switch (type) { case "boolean": has = function (value) { return value !== false } parseValue = function (value) { return value != null } stringifyValue = function () { return "" } break case "number": parseValue = function (value) { return value == null ? null : parseInt(value, 10) } break case "float": parseValue = function (value) { return value == null ? null : parseFloat(value) } break case "string": default: stringifyValue = function (value) { return value == null ? null : value ? ""+value : "" } } _attributes[property] = { get: get, set: set, has: has, defaultValue: defaultValue, hasDefault: defaultValue != null } function get(useDefault) { var value = this.element.getAttribute(name) if (value == null && useDefault == true) { return defaultValue } return parseValue ? parseValue(value) : value } function set(value, callOnchange) { var old = get.call(this, false) if (!has(value)) { this.element.removeAttribute(name) } else if (old === value) { return } else { var newValue = stringifyValue ? stringifyValue(value) : value this.element.setAttribute(name, newValue) } onchange && callOnchange != false && onchange.call(this, old, value) } Object.defineProperty(prototype, property, { get: getter || get, set: setter || set }) return CustomComponent } return CustomComponent } },{"../util/extend":12,"../util/merge":13,"../util/object":14,"./delegate":6,"./hook":8,"./registry":10,"./storage":11,"camelcase":2}],5:[function(require,module,exports){ var Component = require("./Component") var hook = require("./hook") module.exports = component function component (name, root, options) { // component("string"[, {}]) if (!(root instanceof Element)) { options = root root = null } var element = hook.findComponent(name, root) return Component.create(name, element, options) } component.all = function (name, root, options) { // component("string"[, {}]) if (!(root instanceof Element)) { options = root root = null } // component("string"[, Element]) var elements = hook.findAllComponents(name, root) return [].map.call(elements, function (element) { return Component.create(name, element, options) }) } },{"./Component":3,"./hook":8}],6:[function(require,module,exports){ /** * Registers an event listener on an element * and returns a delegator. * A delegated event runs matches to find an event target, * then executes the handler paired with the matcher. * Matchers can check if an event target matches a given selector, * or see if an of its parents do. * */ module.exports = function delegate( options ){ var element = options.element , event = options.event , capture = !!options.capture||false , context = options.context||element if( !element ){ console.log("Can't delegate undefined element") return null } if( !event ){ console.log("Can't delegate undefined event") return null } var delegator = createDelegator(context) element.addEventListener(event, delegator, capture) return delegator } /** * Returns a delegator that can be used as an event listener. * The delegator has static methods which can be used to register handlers. * */ function createDelegator( context ){ var matchers = [] function delegator( e ){ var l = matchers.length if( !l ){ return true } var el = this , i = -1 , handler , selector , delegateElement , stopPropagation , args while( ++i < l ){ args = matchers[i] handler = args[0] selector = args[1] delegateElement = matchCapturePath(selector, el, e) if( delegateElement && delegateElement.length ) { stopPropagation = false === handler.apply(context, [e].concat(delegateElement)) if( stopPropagation ) { return false } } } return true } /** * Registers a handler with a target finder logic * */ delegator.match = function( selector, handler ){ matchers.push([handler, selector]) return delegator } return delegator } function matchCapturePath( selector, el, e ){ var delegateElements = [] var delegateElement = null if( Array.isArray(selector) ){ var i = -1 var l = selector.length while( ++i < l ){ delegateElement = findParent(selector[i], el, e) if( !delegateElement ) return null delegateElements.push(delegateElement) } } else { delegateElement = findParent(selector, el, e) if( !delegateElement ) return null delegateElements.push(delegateElement) } return delegateElements } /** * Check if the target or any of its parent matches a selector * */ function findParent( selector, el, e ){ var target = e.target switch( typeof selector ){ case "string": while( target && target != el ){ if( target.matches && target.matches(selector) ) return target target = target.parentNode } break case "function": while( target && target != el ){ if( selector.call(el, target) ) return target target = target.parentNode } break default: return null } return null } },{}],7:[function(require,module,exports){ var merge = require("../util/merge") module.exports = fragment fragment.options = { variable: "f" } function fragment( html, compiler, compilerOptions ){ compilerOptions = merge(fragment.options, compilerOptions) var render = null return function( templateData ){ var temp = window.document.createElement("div") if( typeof compiler == "function" && !render ){ render = compiler(html, compilerOptions) } if( render ){ try{ html = render(templateData) } catch( e ){ console.error("Error rendering fragment with context:", templateData) console.error(render.toString()) console.error(e) throw e } } temp.innerHTML = html var fragment = window.document.createDocumentFragment() while( temp.childNodes.length ){ fragment.appendChild(temp.firstChild) } return fragment } } fragment.render = function( html, templateData ){ return fragment(html)(templateData) } },{"../util/merge":13}],8:[function(require,module,exports){ var camelcase = require("camelcase") var COMPONENT_ATTRIBUTE = "data-component" var hook = module.exports = {} hook.setHookAttribute = setHookAttribute hook.selector = selector hook.findComponent = findComponent hook.findAllComponents = findAllComponents hook.findSubComponents = findSubComponents hook.getComponentName = getComponentName hook.getMainComponentName = getMainComponentName hook.getSubComponentName = getSubComponentName hook.assignSubComponents = assignSubComponents hook.filter = filter function setHookAttribute (hook) { COMPONENT_ATTRIBUTE = hook } function selector (name, operator, extra) { name = name && '"' + name + '"' operator = name ? operator || "=" : "" extra = extra || "" return "[" + COMPONENT_ATTRIBUTE + operator + name + "]" + extra } function find (selector, root) { return (root || document).querySelector(selector) } function findAll (selector, root) { return (root || document).querySelectorAll(selector) } function findComponent (name, root) { return find(selector(name), root) } function findAllComponents (name, root) { return [].slice.call(findAll(selector(name), root)) } function getComponentName (element, cc) { if (!element) return "" cc = cc == undefined || cc var value = typeof element == "string" ? element : element.getAttribute(COMPONENT_ATTRIBUTE) || "" return cc ? camelcase(value) : value } function getMainComponentName (element, cc) { cc = cc == undefined || cc var value = getComponentName(element, false).split(":") value = value[0] || "" return cc && value ? camelcase(value) : value } function getSubComponentName (element, cc) { cc = cc == undefined || cc var value = getComponentName(element, false).split(":") value = value[1] || "" return cc && value ? camelcase(value) : value } function getComponentNameList (element, cc) { return getComponentName(element, cc).split(/\s+/) } function findSubComponents (mainName, root) { var elements = findAll(selector(mainName+":", "*="), root) return filter(elements, function (element, componentName) { return getComponentNameList(componentName, false).some(function (name) { return getMainComponentName(name, false) == mainName && getSubComponentName(name) }) }) } function assignSubComponents (obj, subComponents, transform, assign) { return subComponents.reduce(function (obj, element) { getComponentNameList(element, false).forEach(function (name) { var subName = getSubComponentName(name, true) element = typeof transform == "function" ? transform(element, name) : element if (typeof assign == "function") { assign(obj, subName, element) } else if (Array.isArray(obj[subName])) { obj[subName].push(element) } else { obj[subName] = element } }) return obj }, obj) } function filter (elements, filter) { switch (typeof filter) { case "function": return [].slice.call(elements).filter(function (element) { return filter(element, getComponentName(element, false)) }) break case "string": return [].slice.call(elements).filter(function (element) { return getComponentName(element) === filter }) break default: return null } } },{"camelcase":2}],9:[function(require,module,exports){ var registry = require("./registry") var Component = require("./Component") var Internals = require("./Internals") module.exports = function register (name, mixin) { mixin = [].slice.call(arguments, 1) function CustomComponent (element, options) { if (!(this instanceof CustomComponent)) { return new CustomComponent(element, options) } var instance = this this.name = name Component.call(instance, element, options) // at this point custom constructors can already access the element and sub components // so they only receive the options object for convenience CustomComponent.create(instance, [options]) } Internals(CustomComponent, name) CustomComponent.extend(Component) CustomComponent.autoAssign = true mixin.forEach(function (mixin) { if (typeof mixin == "function") { if (mixin.componentName) { CustomComponent.extend(mixin) } else { mixin.call(CustomComponent.prototype, CustomComponent) } } else { CustomComponent.proto(mixin) } }) return registry.set(name, CustomComponent) } },{"./Component":3,"./Internals":4,"./registry":10}],10:[function(require,module,exports){ var registry = module.exports = {} var components = {} registry.get = function exists (name) { return components[name] } registry.exists = function exists (name) { return !!components[name] } registry.set = function exists (name, ComponentConstructor) { return components[name] = ComponentConstructor } },{}],11:[function(require,module,exports){ var hook = require("./hook") var camelcase = require("camelcase") var storage = module.exports = {} var components = [] var elements = [] var counter = 0 function createProperty (componentName) { return camelcase(componentName+"-id") } function getId (element, componentName) { return element.dataset[createProperty(componentName)] } function setId (element, componentName, id) { element.dataset[createProperty(componentName)] = id } function hasId (element, componentName) { return !!(element.dataset[createProperty(componentName)]) } function removeId (element, componentName) { if (hasId(element, componentName)) { delete element.dataset[createProperty(componentName)] } } storage.get = function (element, componentName) { var store = components[getId(element, componentName)] return store ? store[componentName] : null } storage.save = function (component) { if (component.element) { var id = component._id var componentName = component.name var store if (!id) { id = ++counter setId(component.element, componentName, id) component._id = id } store = components[id] if (!store) { store = components[id] = {length: 0} } if (store[componentName] !== component) { ++store.length store[componentName] = component } var existingElement = elements[id] if (existingElement) { removeId(existingElement, componentName) setId(component.element, componentName, id) } elements[id] = component.element } } storage.remove = function (component, onlyComponent) { var element = component instanceof Element ? component : component.element var componentName = component.name var id = getId(element, componentName) var store = components[id] if (component instanceof Element) { if (onlyComponent) { if (delete store[onlyComponent]) --store.length } else { for (var prop in store) { if (store.hasOwnProperty(id)) { store[prop]._id = null //--store.length } } delete components[id] } } else { var existing = store[componentName] if (existing == component) { existing._id = null delete store[componentName] --store.length } } if (store && !store.length) { removeId(elements[id], componentName) delete elements[id] } } },{"./hook":8,"camelcase":2}],12:[function(require,module,exports){ module.exports = function extend( obj, extension ){ for( var name in extension ){ if( extension.hasOwnProperty(name) ) obj[name] = extension[name] } return obj } },{}],13:[function(require,module,exports){ var extend = require("./extend") module.exports = function( obj, extension ){ return extend(extend({}, obj), extension) } },{"./extend":12}],14:[function(require,module,exports){ var object = module.exports = {} object.accessor = function (obj, name, get, set) { Object.defineProperty(obj, name, { get: get, set: set }) } object.defineGetter = function (obj, name, fn) { Object.defineProperty(obj, name, { get: fn }) } object.defineSetter = function (obj, name, fn) { Object.defineProperty(obj, name, { set: fn }) } object.method = function (obj, name, fn) { Object.defineProperty(obj, name, { value: fn }) } object.property = function (obj, name, fn) { Object.defineProperty(obj, name, { value: fn, configurable: true }) } },{}]},{},[1])(1) }); //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJpbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jYW1lbGNhc2UvaW5kZXguanMiLCJzcmMvQ29tcG9uZW50LmpzIiwic3JjL0ludGVybmFscy5qcyIsInNyYy9jcmVhdGUuanMiLCJzcmMvZGVsZWdhdGUuanMiLCJzcmMvZnJhZ21lbnQuanMiLCJzcmMvaG9vay5qcyIsInNyYy9yZWdpc3Rlci5qcyIsInNyYy9yZWdpc3RyeS5qcyIsInNyYy9zdG9yYWdlLmpzIiwidXRpbC9leHRlbmQuanMiLCJ1dGlsL21lcmdlLmpzIiwidXRpbC9vYmplY3QuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgaG9vayA9IHJlcXVpcmUoXCIuL3NyYy9ob29rXCIpXG52YXIgcmVnaXN0ZXIgPSByZXF1aXJlKFwiLi9zcmMvcmVnaXN0ZXJcIilcbnZhciBjb21wb25lbnQgPSByZXF1aXJlKFwiLi9zcmMvY3JlYXRlXCIpXG52YXIgc3RvcmFnZSA9IHJlcXVpcmUoXCIuL3NyYy9zdG9yYWdlXCIpXG52YXIgQ29tcG9uZW50ID0gcmVxdWlyZShcIi4vc3JjL0NvbXBvbmVudFwiKVxudmFyIGRlbGVnYXRlID0gcmVxdWlyZShcIi4vc3JjL2RlbGVnYXRlXCIpXG52YXIgZnJhZ21lbnQgPSByZXF1aXJlKFwiLi9zcmMvZnJhZ21lbnRcIilcblxudmFyIHRyZWFudCA9IHt9XG5tb2R1bGUuZXhwb3J0cyA9IHRyZWFudFxuXG50cmVhbnQucmVnaXN0ZXIgPSByZWdpc3RlclxudHJlYW50LmNvbXBvbmVudCA9IGNvbXBvbmVudFxudHJlYW50LnN0b3JhZ2UgPSBzdG9yYWdlXG50cmVhbnQuQ29tcG9uZW50ID0gQ29tcG9uZW50XG50cmVhbnQuZGVsZWdhdGUgPSBkZWxlZ2F0ZVxudHJlYW50LmZyYWdtZW50ID0gZnJhZ21lbnRcbnRyZWFudC5ob29rID0gaG9va1xuXG52YXIgdXRpbCA9IHt9XG50cmVhbnQudXRpbCA9IHV0aWxcblxudXRpbC5leHRlbmQgPSByZXF1aXJlKFwiLi91dGlsL2V4dGVuZFwiKVxudXRpbC5tZXJnZSA9IHJlcXVpcmUoXCIuL3V0aWwvbWVyZ2VcIilcbnV0aWwub2JqZWN0ID0gcmVxdWlyZShcIi4vdXRpbC9vYmplY3RcIilcbiIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0cikge1xuXHRzdHIgPSBzdHIudHJpbSgpO1xuXG5cdGlmIChzdHIubGVuZ3RoID09PSAxIHx8ICEoL1tfLlxcLSBdKy8pLnRlc3Qoc3RyKSApIHtcblx0XHRpZiAoc3RyWzBdID09PSBzdHJbMF0udG9Mb3dlckNhc2UoKSAmJiBzdHIuc2xpY2UoMSkgIT09IHN0ci5zbGljZSgxKS50b0xvd2VyQ2FzZSgpKSB7XG5cdFx0XHRyZXR1cm4gc3RyO1xuXHRcdH1cblxuXHRcdHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcblx0fVxuXG5cdHJldHVybiBzdHJcblx0LnJlcGxhY2UoL15bXy5cXC0gXSsvLCAnJylcblx0LnRvTG93ZXJDYXNlKClcblx0LnJlcGxhY2UoL1tfLlxcLSBdKyhcXHd8JCkvZywgZnVuY3Rpb24gKG0sIHAxKSB7XG5cdFx0cmV0dXJuIHAxLnRvVXBwZXJDYXNlKCk7XG5cdH0pO1xufTtcbiIsInZhciBob29rID0gcmVxdWlyZShcIi4vaG9va1wiKVxudmFyIHJlZ2lzdHJ5ID0gcmVxdWlyZShcIi4vcmVnaXN0cnlcIilcbnZhciBzdG9yYWdlID0gcmVxdWlyZShcIi4vc3RvcmFnZVwiKVxudmFyIGRlbGVnYXRlID0gcmVxdWlyZShcIi4vZGVsZWdhdGVcIilcblxubW9kdWxlLmV4cG9ydHMgPSBDb21wb25lbnRcblxuZnVuY3Rpb24gQ29tcG9uZW50IChlbGVtZW50LCBvcHRpb25zKSB7XG4gIGlmIChlbGVtZW50ICYmICEoZWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiZWxlbWVudCBzaG91bGQgYmUgYW4gRWxlbWVudCBpbnN0YW5jZSBvciBudWxsXCIpXG4gIH1cbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIENvbXBvbmVudCkpIHtcbiAgICByZXR1cm4gbmV3IENvbXBvbmVudChlbGVtZW50LCBvcHRpb25zKVxuICB9XG5cbiAgdGhpcy5fZWxlbWVudCA9IG51bGxcbiAgdGhpcy5faWQgPSBudWxsXG4gIHRoaXMuY29tcG9uZW50cyA9IHt9XG4gIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQgfHwgbnVsbFxufVxuXG5Db21wb25lbnQuY3JlYXRlID0gZnVuY3Rpb24gKG5hbWUsIGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgdmFyIENvbXBvbmVudENvbnN0cnVjdG9yID0gbnVsbFxuXG4gIGlmIChyZWdpc3RyeS5leGlzdHMobmFtZSkpIHtcbiAgICBDb21wb25lbnRDb25zdHJ1Y3RvciA9IHJlZ2lzdHJ5LmdldChuYW1lKVxuICB9XG4gIGVsc2Uge1xuICAgIGNvbnNvbGUud2FybihcIk1pc3NpbmcgY29tcG9uZW50IGRlZmluaXRpb246IFwiLCBuYW1lKVxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICByZXR1cm4gbmV3IENvbXBvbmVudENvbnN0cnVjdG9yKGVsZW1lbnQsIG9wdGlvbnMpXG59XG5cbkNvbXBvbmVudC5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBDb21wb25lbnQsXG5cbiAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xuICAgIHN0b3JhZ2UucmVtb3ZlKHRoaXMpXG4gICAgdGhpcy5lbGVtZW50ID0gbnVsbFxuXG4gICAgdmFyIGNvbXBvbmVudHMgPSB0aGlzLmNvbXBvbmVudHNcbiAgICB2YXIgY29tcG9uZW50XG4gICAgZm9yICh2YXIgbmFtZSBpbiBjb21wb25lbnRzKSB7XG4gICAgICBpZiAoY29tcG9uZW50cy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICBjb21wb25lbnQgPSBjb21wb25lbnRzW25hbWVdXG4gICAgICAgIGlmIChjb21wb25lbnQuZGVzdHJveSkge1xuICAgICAgICAgIGNvbXBvbmVudC5kZXN0cm95KClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmNvbXBvbmVudHMgPSBudWxsXG4gIH0sXG5cbiAgZGVsZWdhdGU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgb3B0aW9ucy5lbGVtZW50ID0gdGhpcy5lbGVtZW50XG4gICAgb3B0aW9ucy5jb250ZXh0ID0gb3B0aW9ucy5jb250ZXh0IHx8IHRoaXNcbiAgICByZXR1cm4gZGVsZWdhdGUob3B0aW9ucylcbiAgfSxcbiAgYWN0aW9uOiBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5jcmVhdGVBY3Rpb24oZXZlbnQpXG4gIH0sXG5cbiAgZGlzcGF0Y2g6IGZ1bmN0aW9uICh0eXBlLCBkZXRhaWwpIHtcbiAgICB2YXIgZGVmaW5pdGlvbiA9IHRoaXMuY29uc3RydWN0b3IuZ2V0RXZlbnREZWZpbml0aW9uKHR5cGUsIGRldGFpbClcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50LmRpc3BhdGNoRXZlbnQobmV3IHdpbmRvdy5DdXN0b21FdmVudCh0eXBlLCBkZWZpbml0aW9uKSlcbiAgfSxcblxuICBmaW5kQ29tcG9uZW50OiBmdW5jdGlvbiAobmFtZSkge1xuICAgIHJldHVybiBob29rLmZpbmRDb21wb25lbnQobmFtZSwgdGhpcy5lbGVtZW50KVxuICB9LFxuICBmaW5kQWxsQ29tcG9uZW50czogZnVuY3Rpb24gKG5hbWUpIHtcbiAgICByZXR1cm4gaG9vay5maW5kQWxsQ29tcG9uZW50cyhuYW1lLCB0aGlzLmVsZW1lbnQpXG4gIH0sXG4gIGZpbmRTdWJDb21wb25lbnRzOiBmdW5jdGlvbiAoKSB7XG4gICAgLy92YXIgc3ViQ29tcG9uZW50cyA9IFtdXG4gICAgLy92YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudFxuICAgIC8vdGhpcy5jb25zdHJ1Y3Rvci5wYXJlbnRzLmZvckVhY2goZnVuY3Rpb24gKFBhcmVudENvbXBvbmVudCkge1xuICAgIC8vICB2YXIgY29tcG9uZW50cyA9IGhvb2suZmluZFN1YkNvbXBvbmVudHMoUGFyZW50Q29tcG9uZW50LmNvbXBvbmVudE5hbWUsIGVsZW1lbnQpXG4gICAgLy8gIHN1YkNvbXBvbmVudHMgPSBzdWJDb21wb25lbnRzLmNvbmNhdChjb21wb25lbnRzKVxuICAgIC8vfSlcbiAgICAvL3N1YkNvbXBvbmVudHMgPSBzdWJDb21wb25lbnRzLmNvbmNhdChob29rLmZpbmRTdWJDb21wb25lbnRzKHRoaXMuZ2V0TWFpbkNvbXBvbmVudE5hbWUoZmFsc2UpLCBlbGVtZW50KSlcbiAgICAvL3JldHVybiBzdWJDb21wb25lbnRzXG4gICAgcmV0dXJuIGhvb2suZmluZFN1YkNvbXBvbmVudHModGhpcy5nZXRNYWluQ29tcG9uZW50TmFtZShmYWxzZSksIHRoaXMuZWxlbWVudClcbiAgfSxcbiAgZ2V0Q29tcG9uZW50TmFtZTogZnVuY3Rpb24gKGNjKSB7XG4gICAgcmV0dXJuIGhvb2suZ2V0Q29tcG9uZW50TmFtZSh0aGlzLmNvbnN0cnVjdG9yLmNvbXBvbmVudE5hbWUsIGNjKVxuICB9LFxuICBnZXRNYWluQ29tcG9uZW50TmFtZTogZnVuY3Rpb24gKGNjKSB7XG4gICAgcmV0dXJuIGhvb2suZ2V0TWFpbkNvbXBvbmVudE5hbWUodGhpcy5jb25zdHJ1Y3Rvci5jb21wb25lbnROYW1lLCBjYylcbiAgfSxcbiAgZ2V0U3ViQ29tcG9uZW50TmFtZTogZnVuY3Rpb24gKGNjKSB7XG4gICAgcmV0dXJuIGhvb2suZ2V0U3ViQ29tcG9uZW50TmFtZSh0aGlzLmNvbnN0cnVjdG9yLmNvbXBvbmVudE5hbWUsIGNjKVxuICB9LFxuXG4gIGNsZWFyU3ViQ29tcG9uZW50czogZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb21wb25lbnRzID0gdGhpcy5jb25zdHJ1Y3Rvci5jb21wb25lbnRzXG5cbiAgICBmb3IgKHZhciBuYW1lIGluIGNvbXBvbmVudHMpIHtcbiAgICAgIGlmIChjb21wb25lbnRzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbXBvbmVudHNbbmFtZV0pKSB7XG4gICAgICAgICAgdGhpcy5jb21wb25lbnRzW25hbWVdID0gW11cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB0aGlzLmNvbXBvbmVudHNbbmFtZV0gPSBjb21wb25lbnRzW25hbWVdXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIGFzc2lnblN1YkNvbXBvbmVudHM6IGZ1bmN0aW9uICh0cmFuc2Zvcm0pIHtcbiAgICBpZiAoIXRoaXMuZWxlbWVudCkgcmV0dXJuXG5cbiAgICB2YXIgaG9zdENvbXBvbmVudCA9IHRoaXNcbiAgICB2YXIgc3ViQ29tcG9uZW50cyA9IHRoaXMuZmluZFN1YkNvbXBvbmVudHMoKVxuICAgIHZhciBjb25zdHJ1Y3RvciA9IHRoaXMuY29uc3RydWN0b3JcblxuICAgIHRoaXMuY2xlYXJTdWJDb21wb25lbnRzKClcblxuICAgIGlmICghc3ViQ29tcG9uZW50cy5sZW5ndGgpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdHJhbnNmb3JtID09IFwidW5kZWZpbmVkXCIgfHwgdHJhbnNmb3JtID09PSB0cnVlKSB7XG4gICAgICB0cmFuc2Zvcm0gPSBmdW5jdGlvbiAoZWxlbWVudCwgbmFtZSkge1xuICAgICAgICAvLyBUT0RPOiBzdWJjbGFzcyBzdWJjb21wb25lbnRzIHNob3VsZCBiZSBoYW5kbGVkIHByb3Blcmx5IChCIGV4dGVuZHMgQSB0aGF0IGhhcyBhIHN1YmNvbXBvbmVudCBBOmEgYmVjb21lcyBCOmEgdGhhdCdzIG5vdCBpbiB0aGUgcmVnaXN0cnkpXG4gICAgICAgIHJldHVybiByZWdpc3RyeS5leGlzdHMobmFtZSlcbiAgICAgICAgICAgID8gQ29tcG9uZW50LmNyZWF0ZShuYW1lLCBlbGVtZW50LCBob3N0Q29tcG9uZW50KVxuICAgICAgICAgICAgOiBlbGVtZW50XG4gICAgICB9XG4gICAgfVxuXG4gICAgaG9vay5hc3NpZ25TdWJDb21wb25lbnRzKHRoaXMuY29tcG9uZW50cywgc3ViQ29tcG9uZW50cywgdHJhbnNmb3JtLCBmdW5jdGlvbiAoY29tcG9uZW50cywgbmFtZSwgZWxlbWVudCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29uc3RydWN0b3IuY29tcG9uZW50c1tuYW1lXSkpIHtcbiAgICAgICAgY29tcG9uZW50c1tuYW1lXSA9IGNvbXBvbmVudHNbbmFtZV0gfHwgW11cbiAgICAgICAgY29tcG9uZW50c1tuYW1lXS5wdXNoKGVsZW1lbnQpXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgY29tcG9uZW50c1tuYW1lXSA9IGVsZW1lbnRcbiAgICAgIH1cbiAgICB9KVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShDb21wb25lbnQucHJvdG90eXBlLCBcImVsZW1lbnRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fZWxlbWVudFxuICB9LFxuICBzZXQ6IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnRcbiAgICBpZiAoZWxlbWVudCAmJiB0aGlzLmNvbnN0cnVjdG9yLmNvbXBvbmVudE5hbWUpIHtcbiAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLmF1dG9TYXZlKSB7XG4gICAgICAgIHN0b3JhZ2Uuc2F2ZSh0aGlzKVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IuYXV0b0Fzc2lnbikge1xuICAgICAgICB0aGlzLmFzc2lnblN1YkNvbXBvbmVudHMoKVxuICAgICAgfVxuICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5yZXNldEF0dHJpYnV0ZXModGhpcylcbiAgICB9XG4gIH1cbn0pXG4iLCJ2YXIgY2FtZWxjYXNlID0gcmVxdWlyZShcImNhbWVsY2FzZVwiKVxudmFyIGV4dGVuZCA9IHJlcXVpcmUoXCIuLi91dGlsL2V4dGVuZFwiKVxudmFyIG1lcmdlID0gcmVxdWlyZShcIi4uL3V0aWwvbWVyZ2VcIilcbnZhciBvYmplY3QgPSByZXF1aXJlKFwiLi4vdXRpbC9vYmplY3RcIilcbnZhciBkZWxlZ2F0ZSA9IHJlcXVpcmUoXCIuL2RlbGVnYXRlXCIpXG52YXIgc3RvcmFnZSA9IHJlcXVpcmUoXCIuL3N0b3JhZ2VcIilcbnZhciByZWdpc3RyeSA9IHJlcXVpcmUoXCIuL3JlZ2lzdHJ5XCIpXG52YXIgaG9vayA9IHJlcXVpcmUoXCIuL2hvb2tcIilcblxudmFyIGRlZmF1bHRFdmVudERlZmluaXRpb24gPSB7XG4gIGRldGFpbDogbnVsbCxcbiAgdmlldzogd2luZG93LFxuICBidWJibGVzOiB0cnVlLFxuICBjYW5jZWxhYmxlOiB0cnVlXG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKEN1c3RvbUNvbXBvbmVudCwgY29tcG9uZW50TmFtZSkge1xuXG4gIEN1c3RvbUNvbXBvbmVudC5jb21wb25lbnROYW1lID0gY29tcG9uZW50TmFtZVxuICBDdXN0b21Db21wb25lbnQuYXV0b0Fzc2lnbiA9IHRydWVcbiAgQ3VzdG9tQ29tcG9uZW50LmF1dG9TYXZlID0gdHJ1ZVxuICBDdXN0b21Db21wb25lbnQuY29tcG9uZW50cyA9IHt9XG4gIEN1c3RvbUNvbXBvbmVudC5wYXJlbnRzID0gW11cblxuICB2YXIgcHJvdG90eXBlID0gQ3VzdG9tQ29tcG9uZW50LnByb3RvdHlwZVxuXG4gIHZhciBfZXZlbnRzID0gQ3VzdG9tQ29tcG9uZW50Ll9ldmVudHMgPSB7fVxuICB2YXIgX2NvbnN0cnVjdG9ycyA9IEN1c3RvbUNvbXBvbmVudC5fY29uc3RydWN0b3JzID0gW11cbiAgdmFyIF9hdHRyaWJ1dGVzID0gQ3VzdG9tQ29tcG9uZW50Ll9hdHRyaWJ1dGVzID0ge31cbiAgdmFyIF9hY3Rpb25zID0gQ3VzdG9tQ29tcG9uZW50Ll9hY3Rpb25zID0gW11cblxuICBDdXN0b21Db21wb25lbnQuZXh0ZW5kID0gZnVuY3Rpb24gKEJhc2VDb21wb25lbnQpIHtcbiAgICBwcm90b3R5cGUgPSBDdXN0b21Db21wb25lbnQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShCYXNlQ29tcG9uZW50LnByb3RvdHlwZSlcbiAgICBDdXN0b21Db21wb25lbnQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQ3VzdG9tQ29tcG9uZW50XG4gICAgaWYgKEJhc2VDb21wb25lbnQuY29tcG9uZW50TmFtZSkge1xuICAgICAgQ3VzdG9tQ29tcG9uZW50LnBhcmVudHMgPSBDdXN0b21Db21wb25lbnQucGFyZW50cy5jb25jYXQoQmFzZUNvbXBvbmVudC5wYXJlbnRzKVxuICAgICAgQ3VzdG9tQ29tcG9uZW50LnBhcmVudHMucHVzaChCYXNlQ29tcG9uZW50KVxuICAgICAgQ3VzdG9tQ29tcG9uZW50LmF1dG9Bc3NpZ24gPSBCYXNlQ29tcG9uZW50LmF1dG9Bc3NpZ25cbiAgICAgIGV4dGVuZChDdXN0b21Db21wb25lbnQuY29tcG9uZW50cywgQmFzZUNvbXBvbmVudC5jb21wb25lbnRzKVxuICAgICAgZXh0ZW5kKF9ldmVudHMsIEJhc2VDb21wb25lbnQuX2V2ZW50cylcbiAgICAgIF9jb25zdHJ1Y3RvcnMgPSBfY29uc3RydWN0b3JzLmNvbmNhdChCYXNlQ29tcG9uZW50Ll9jb25zdHJ1Y3RvcnMpXG4gICAgICBleHRlbmQoX2F0dHJpYnV0ZXMsIEJhc2VDb21wb25lbnQuX2F0dHJpYnV0ZXMpXG4gICAgICBCYXNlQ29tcG9uZW50Ll9hY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgdmFyIGV2ZW50ID0gYXJnc1swXVxuICAgICAgICB2YXIgbWF0Y2hlcyA9IGFyZ3NbMV1cbiAgICAgICAgdmFyIG1hdGNoZXIgPSBDdXN0b21Db21wb25lbnQuYWN0aW9uKGV2ZW50KVxuICAgICAgICBtYXRjaGVzLmZvckVhY2goZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgICBtYXRjaGVyLm1hdGNoLmFwcGx5KG1hdGNoZXIsIGFyZ3MpXG4gICAgICAgIH0pXG4gICAgICB9KVxuICAgIH1cbiAgfVxuICBDdXN0b21Db21wb25lbnQub25DcmVhdGUgPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICBfY29uc3RydWN0b3JzLnB1c2goY29uc3RydWN0b3IpXG4gICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudFxuICB9XG5cbiAgQ3VzdG9tQ29tcG9uZW50LmNyZWF0ZSA9IGZ1bmN0aW9uIChpbnN0YW5jZSwgYXJncykge1xuICAgIF9jb25zdHJ1Y3RvcnMuZm9yRWFjaChmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICAgIGNvbnN0cnVjdG9yLmFwcGx5KGluc3RhbmNlLCBhcmdzKVxuICAgIH0pXG4gIH1cblxuICBDdXN0b21Db21wb25lbnQubWV0aG9kID0gZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgb2JqZWN0Lm1ldGhvZChwcm90b3R5cGUsIG5hbWUsIGZuKVxuICAgIHJldHVybiBDdXN0b21Db21wb25lbnRcbiAgfVxuXG4gIEN1c3RvbUNvbXBvbmVudC5wcm9wZXJ0eSA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIG9iamVjdC5wcm9wZXJ0eShwcm90b3R5cGUsIG5hbWUsIGZuKVxuICAgIHJldHVybiBDdXN0b21Db21wb25lbnRcbiAgfVxuXG4gIEN1c3RvbUNvbXBvbmVudC5nZXQgPSBmdW5jdGlvbiAobmFtZSwgZm4pIHtcbiAgICBvYmplY3QuZGVmaW5lR2V0dGVyKHByb3RvdHlwZSwgbmFtZSwgZm4pXG4gICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudFxuICB9XG5cbiAgQ3VzdG9tQ29tcG9uZW50LnNldCA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIG9iamVjdC5kZWZpbmVTZXR0ZXIocHJvdG90eXBlLCBuYW1lLCBmbilcbiAgICByZXR1cm4gQ3VzdG9tQ29tcG9uZW50XG4gIH1cblxuICBDdXN0b21Db21wb25lbnQuYWNjZXNzb3IgPSBmdW5jdGlvbiAobmFtZSwgZ2V0LCBzZXQpIHtcbiAgICBvYmplY3QuYWNjZXNzb3IocHJvdG90eXBlLCBuYW1lLCBnZXQsIHNldClcbiAgICByZXR1cm4gQ3VzdG9tQ29tcG9uZW50XG4gIH1cblxuICBDdXN0b21Db21wb25lbnQucHJvdG8gPSBmdW5jdGlvbiAocHJvdG90eXBlKSB7XG4gICAgZm9yICh2YXIgcHJvcCBpbiBwcm90b3R5cGUpIHtcbiAgICAgIGlmIChwcm90b3R5cGUuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm90b3R5cGVbcHJvcF0gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgaWYgKHByb3AgPT09IFwib25DcmVhdGVcIikge1xuICAgICAgICAgICAgQ3VzdG9tQ29tcG9uZW50Lm9uQ3JlYXRlKHByb3RvdHlwZVtwcm9wXSlcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBDdXN0b21Db21wb25lbnQubWV0aG9kKHByb3AsIHByb3RvdHlwZVtwcm9wXSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ