treant
Version:
Dependency free component library for the browser
1,061 lines (908 loc) • 76.4 kB
JavaScript
(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