Skip to content

Instantly share code, notes, and snippets.

@BinaryMuse
Created July 23, 2017 03:24
Show Gist options
  • Save BinaryMuse/270f137a6ecc28aaf0832337b7036b57 to your computer and use it in GitHub Desktop.
Save BinaryMuse/270f137a6ecc28aaf0832337b7036b57 to your computer and use it in GitHub Desktop.
requirebin sketch
const etch = require('etch')
function toHTMLElement(vdom) {
const component = {
update() { /* noop */ },
render () { return vdom }
}
etch.initialize(component)
return component.element
}
const domElement = toHTMLElement(etch.dom.div(null, etch.dom.span(null, 'Hello!')))
document.body.appendChild(domElement)
setTimeout(function(){
;require=(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){
const render = require('./render')
const patch = require('./patch')
const {getScheduler} = require('./scheduler-assignment')
const componentsWithPendingUpdates = new WeakSet()
let syncUpdatesInProgressCounter = 0
let syncDestructionsInProgressCounter = 0
function isValidVirtualNode (virtualNode) {
return virtualNode != null && virtualNode !== false
}
// This function associates a component object with a DOM element by calling
// the components `render` method, assigning an `.element` property on the
// object and also returning the element.
//
// It also assigns a `virtualNode` property based on the return value of the
// `render` method. This will be used later by `performElementUpdate` to diff
// the new results of `render` with the previous results when updating the
// component's element.
//
// Finally, this function also associates the component with a `refs` object,
// which is populated with references to elements based on `ref` properties on
// nodes of the `virtual-dom` tree. Before calling into `virtual-dom` to create
// the DOM tree, it pushes this `refs` object to a shared stack so it can be
// accessed by hooks during the creation of individual elements.
function initialize(component) {
if (typeof component.update !== 'function') {
throw new Error('Etch components must implement `update(props, children)`.')
}
let virtualNode = component.render()
if (!isValidVirtualNode(virtualNode)) {
let namePart = component.constructor && component.constructor.name ? ' in ' + component.constructor.name : ''
throw new Error('invalid falsy value ' + virtualNode + ' returned from render()' + namePart)
}
component.refs = {}
component.virtualNode = virtualNode
component.element = render(component.virtualNode, {
refs: component.refs, listenerContext: component
})
}
// This function receives a component that has already been associated with an
// element via a previous call to `initialize` and updates this element by
// calling `render` on the component.
//
// When called in normal circumstances, it uses the scheduler to defer this
// update until the next animation frame, and will only perform one update of a
// given component in a given frame. This means you can call `update`
// repeatedly in a given tick without causing redundant updates.
//
// If this function called during another synchronous update (for example, as a
// result of a call to `update` on a child component), the update is performed
// synchronously.
//
// Returns a promise that will resolve when the requested update has been
// completed.
function update (component, replaceNode=true) {
if (syncUpdatesInProgressCounter > 0) {
updateSync(component, replaceNode)
return Promise.resolve()
}
let scheduler = getScheduler()
if (!componentsWithPendingUpdates.has(component)) {
componentsWithPendingUpdates.add(component)
scheduler.updateDocument(function () {
componentsWithPendingUpdates.delete(component)
updateSync(component, replaceNode)
})
}
return scheduler.getNextUpdatePromise()
}
// Synchronsly updates the DOM element associated with a component object. .
// This method assumes the presence of `.element` and `.virtualNode`
// properties on the component, which are assigned in the `initialize`
// function.
//
// It calls `render` on the component to obtain the desired state of the DOM,
// then `diff`s it with the previous state and `patch`es the element based on
// the resulting diff. During the patch operation, it pushes the component's
// `refs` object to a shared stack so that references to DOM elements can be
// updated.
//
// If `update` is called during the invocation of `updateSync`,
// the requests are processed synchronously as well. We track whether this is
// the case by incrementing and decrementing `syncUpdatesInProgressCounter`
// around the call.
//
// For now, etch does not allow the root tag of the `render` method to change
// between invocations, because we want to preserve a one-to-one relationship
// between component objects and DOM elements for simplicity.
function updateSync (component, replaceNode=true) {
let newVirtualNode = component.render()
if (!isValidVirtualNode(newVirtualNode)) {
let namePart = component.constructor && component.constructor.name ? ' in ' + component.constructor.name : ''
throw new Error('invalid falsy value ' + newVirtualNode + ' returned from render()' + namePart)
}
syncUpdatesInProgressCounter++
let oldVirtualNode = component.virtualNode
let oldDomNode = component.element
let newDomNode = patch(oldVirtualNode, newVirtualNode, {
refs: component.refs,
listenerContext: component
})
component.virtualNode = newVirtualNode
if (newDomNode !== oldDomNode && !replaceNode) {
throw new Error('The root node type changed on update, but the update was performed with the replaceNode option set to false')
} else {
component.element = newDomNode
}
// We can safely perform additional writes after a DOM update synchronously,
// but any reads need to be deferred until all writes are completed to avoid
// DOM thrashing. Requested reads occur at the end of the the current frame
// if this method was invoked via the scheduler. Otherwise, if `updateSync`
// was invoked outside of the scheduler, the default scheduler will defer
// reads until the next animation frame.
if (typeof component.writeAfterUpdate === 'function') {
component.writeAfterUpdate()
}
if (typeof component.readAfterUpdate === 'function') {
getScheduler().readDocument(function () {
component.readAfterUpdate()
})
}
syncUpdatesInProgressCounter--
}
// Removes the component's associated element and calls `destroy` on any child
// components. Normally, this function is asynchronous and will perform the
// destruction on the next animation frame. If called as the result of another
// update or destruction, it calls `destroy` on child components synchronously.
// If called as the result of destroying a component higher in the DOM, the
// element is not removed to avoid redundant DOM manipulation. Returns a promise
// that resolves when the destruction is completed.
function destroy (component, removeNode=true) {
if (syncUpdatesInProgressCounter > 0 || syncDestructionsInProgressCounter > 0) {
destroySync(component, removeNode)
return Promise.resolve()
}
let scheduler = getScheduler()
scheduler.updateDocument(function () {
destroySync(component, removeNode)
})
return scheduler.getNextUpdatePromise()
}
// A synchronous version of `destroy`.
//
// Note that we track whether `destroy` calls are in progress and only remove
// the element if we are not a nested call.
function destroySync (component, removeNode=true) {
syncDestructionsInProgressCounter++
destroyChildComponents(component.virtualNode)
if (syncDestructionsInProgressCounter === 1 && removeNode) component.element.remove()
syncDestructionsInProgressCounter--
}
function destroyChildComponents(virtualNode) {
if (virtualNode.component && typeof virtualNode.component.destroy === 'function') {
virtualNode.component.destroy()
} else if (virtualNode.children) {
virtualNode.children.forEach(destroyChildComponents)
}
}
module.exports = {
initialize,
update, updateSync,
destroy, destroySync
}
},{"./patch":5,"./render":6,"./scheduler-assignment":7}],2:[function(require,module,exports){
// If the scheduler is not customized via `etch.setScheduler`, an instance of
// this class will be used to schedule updates to the document. The
// `updateDocument` method accepts functions to be run at some point in the
// future, then runs them on the next animation frame.
module.exports = class DefaultScheduler {
constructor () {
this.updateRequests = []
this.readRequests = []
this.pendingAnimationFrame = null
this.performUpdates = this.performUpdates.bind(this)
this.performingUpdates = false
}
// Enqueues functions that write to the DOM to be performed on the next
// animation frame. Functions passed to this method should *never* read from
// the DOM, because that could cause synchronous reflows.
updateDocument (fn) {
this.updateRequests.push(fn)
if (!this.pendingAnimationFrame) {
this.pendingAnimationFrame = window.requestAnimationFrame(this.performUpdates)
}
}
readDocument (fn) {
this.readRequests.push(fn)
if (!this.pendingAnimationFrame) {
this.pendingAnimationFrame = window.requestAnimationFrame(this.performUpdates)
}
}
// Returns a promise that will resolve at the end of the next update cycle,
// after all the functions passed to `updateDocument` and `updateDocumentSync`
// have been run.
getNextUpdatePromise () {
if (!this.nextUpdatePromise) {
this.nextUpdatePromise = new Promise(resolve => {
this.resolveNextUpdatePromise = resolve
})
}
return this.nextUpdatePromise
}
// Performs all the pending document updates. If running these update
// functions causes *more* updates to be enqueued, they are run synchronously
// in this update cycle without waiting for another frame.
performUpdates () {
while (this.updateRequests.length > 0) {
this.updateRequests.shift()()
}
// We don't clear the pending frame until all update requests are processed.
// This ensures updates requested within other updates are processed in the
// current frame.
this.pendingAnimationFrame = null
// Now that updates are processed, we can perform all pending document reads
// without the risk of interleaving them with writes and causing layout
// thrashing.
while (this.readRequests.length > 0) {
this.readRequests.shift()()
}
if (this.nextUpdatePromise) {
let resolveNextUpdatePromise = this.resolveNextUpdatePromise
this.nextUpdatePromise = null
this.resolveNextUpdatePromise = null
resolveNextUpdatePromise()
}
}
}
},{}],3:[function(require,module,exports){
const EVENT_LISTENER_PROPS = require('./event-listener-props')
const SVG_TAGS = require('./svg-tags')
function dom (tag, props, ...children) {
for (let i = 0; i < children.length;) {
const child = children[i]
switch (typeof child) {
case 'string':
case 'number':
children[i] = {text: child}
i++
break;
case 'object':
if (Array.isArray(child)) {
children.splice(i, 1, ...child)
} else if (!child) {
children.splice(i, 1)
} else {
i++
}
break;
default:
throw new Error(`Invalid child node: ${child}`)
}
}
if (props) {
for (const propName in props) {
const eventName = EVENT_LISTENER_PROPS[propName]
if (eventName) {
if (!props.on) props.on = {}
props.on[eventName] = props[propName]
}
}
if (props.class) {
props.className = props.class
}
}
return {tag, props, children}
}
const HTML_TAGS = [
'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo',
'blockquote', 'body', 'button', 'canvas', 'caption', 'cite', 'code',
'colgroup', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl',
'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2',
'h3', 'h4', 'h5', 'h6', 'head', 'header', 'html', 'i', 'iframe', 'ins', 'kbd',
'label', 'legend', 'li', 'main', 'map', 'mark', 'menu', 'meter', 'nav',
'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'pre',
'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section',
'select', 'small', 'span', 'strong', 'style', 'sub', 'summary', 'sup',
'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title',
'tr', 'u', 'ul', 'var', 'video', 'area', 'base', 'br', 'col', 'command',
'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source',
'track', 'wbr'
]
for (const tagName of HTML_TAGS) {
dom[tagName] = (props, ...children) => {
return dom(tagName, props, ...children)
}
}
for (const tagName of SVG_TAGS) {
dom[tagName] = (props, ...children) => {
return dom(tagName, props, ...children)
}
}
module.exports = dom
},{"./event-listener-props":4,"./svg-tags":9}],4:[function(require,module,exports){
module.exports = {
onCopy: 'copy',
onCut: 'cut',
onPaste: 'paste',
onCompositionEnd: 'compositionend',
onCompositionStart: 'compositionstart',
onCompositionUpdate: 'compositionupdate',
onKeyDown: 'keydown',
onKeyPress: 'keypress',
onKeyUp: 'keyup',
onFocus: 'focus',
onBlur: 'blur',
onChange: 'change',
onInput: 'input',
onSubmit: 'submit',
onClick: 'click',
onContextMenu: 'contextmenu',
onDoubleClick: 'doubleclick',
onDrag: 'drag',
onDragEnd: 'dragend',
onDragEnter: 'dragenter',
onDragExit: 'dragexit',
onDragLeave: 'dragleave',
onDragOver: 'dragover',
onDragStart: 'dragstart',
onDrop: 'drop',
onMouseDown: 'mousedown',
onMouseEnter: 'mousenter',
onMouseLeave: 'mouseleave',
onMouseMove: 'mousemove',
onMouseOut: 'mouseout',
onMouseOver: 'mouseover',
onMouseUp: 'mouseup',
onSelect: 'select',
onTouchCancel: 'touchcancel',
onTouchEnd: 'touchend',
onTouchMove: 'touchmove',
onTouchStart: 'touchstart',
onScroll: 'scroll',
onWheel: 'wheel',
onAbort: 'abort',
onCanPlay: 'canplay',
onCanPlayThrough: 'canplaythrough',
onDurationChange: 'durationchange',
onEmptied: 'emptied',
onEncrypted: 'encrypted',
onEnded: 'ended',
onError: 'error',
onLoadedData: 'loadeddata',
onLoadedMetadata: 'loadedmetadat',
onLoadStart: 'loadstart',
onPause: 'pause',
onPlay: 'play',
onPlaying: 'playing',
onProgress: 'progress',
onRateChange: 'ratechange',
onSeeked: 'seeked',
onSeeking: 'seeking',
onStalled: 'stalled',
onSuspend: 'suspend',
onTimeUpdate: 'timeupdate',
onVolumeChange: 'volumechange',
onWaiting: 'waiting',
onLoad: 'load',
onError: 'error',
onAnimationStart: 'animationstart',
onAnimationEnd: 'animationend',
onAnimationIteration: 'animationiteration',
onTransitionEnd: 'transitionend'
}
},{}],5:[function(require,module,exports){
const render = require('./render')
const updateProps = require('./update-props')
function patch (oldVirtualNode, newVirtualNode, options) {
const oldNode = oldVirtualNode.domNode
if (virtualNodesAreEqual(oldVirtualNode, newVirtualNode)) {
let newNode
if (newVirtualNode.text != null) {
oldNode.nodeValue = newVirtualNode.text
newNode = oldNode
} else {
if (typeof newVirtualNode.tag === 'function') {
newNode = updateComponent(oldVirtualNode, newVirtualNode, options)
} else {
updateChildren(oldNode, oldVirtualNode.children, newVirtualNode.children, options)
updateProps(oldNode, oldVirtualNode, newVirtualNode, options)
newNode = oldNode
}
}
newVirtualNode.domNode = newNode
if (newNode !== oldNode && oldNode.parentNode) {
oldNode.parentNode.replaceChild(newNode, oldNode)
}
return newNode
} else {
const parentNode = oldNode.parentNode
const nextSibling = oldNode.nextSibling
removeVirtualNode(oldVirtualNode, options && options.refs)
const newNode = render(newVirtualNode, options)
if (parentNode) parentNode.insertBefore(newNode, nextSibling)
newVirtualNode.domNode = newNode
return newNode
}
}
function updateComponent (oldVirtualNode, newVirtualNode, options) {
const {component, props: oldProps} = oldVirtualNode
let {props: newProps, children: newChildren} = newVirtualNode
newVirtualNode.component = component
if (options && options.refs) {
const refs = options.refs
const oldRefName = oldProps && oldProps.ref
const newRefName = newProps && newProps.ref
if (newRefName !== oldRefName) {
if (oldRefName && refs[oldRefName] === component) delete refs[oldRefName]
if (newRefName) refs[newRefName] = component
}
}
component.update(newProps || {}, newChildren)
return component.element
}
function updateChildren (parentElement, oldChildren, newChildren, options) {
let oldStartIndex = 0
let oldEndIndex = oldChildren.length - 1
let oldStartChild = oldChildren[0]
let oldEndChild = oldChildren[oldEndIndex]
let newStartIndex = 0
let newEndIndex = newChildren.length - 1
let newStartChild = newChildren[0]
let newEndChild = newChildren[newEndIndex]
let oldIndicesByKey
while (oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) {
if (!oldStartChild) {
oldStartChild = oldChildren[++oldStartIndex]
} else if (!oldEndChild) {
oldEndChild = oldChildren[--oldEndIndex]
} else if (virtualNodesAreEqual(oldStartChild, newStartChild)) {
patch(oldStartChild, newStartChild, options)
oldStartChild = oldChildren[++oldStartIndex]
newStartChild = newChildren[++newStartIndex]
} else if (virtualNodesAreEqual(oldEndChild, newEndChild)) {
patch(oldEndChild, newEndChild, options)
oldEndChild = oldChildren[--oldEndIndex]
newEndChild = newChildren[--newEndIndex]
} else if (virtualNodesAreEqual(oldStartChild, newEndChild)) {
patch(oldStartChild, newEndChild, options)
parentElement.insertBefore(oldStartChild.domNode, oldEndChild.domNode.nextSibling)
oldStartChild = oldChildren[++oldStartIndex]
newEndChild = newChildren[--newEndIndex]
} else if (virtualNodesAreEqual(oldEndChild, newStartChild)) {
patch(oldEndChild, newStartChild, options)
parentElement.insertBefore(oldEndChild.domNode, oldStartChild.domNode);
oldEndChild = oldChildren[--oldEndIndex]
newStartChild = newChildren[++newStartIndex]
} else {
if (!oldIndicesByKey) oldIndicesByKey = mapOldKeysToIndices(oldChildren, oldStartIndex, oldEndIndex)
const key = getKey(newStartChild)
const oldIndex = key ? oldIndicesByKey.get(key) : null
if (oldIndex == null) {
parentElement.insertBefore(render(newStartChild, options), oldStartChild.domNode)
newStartChild = newChildren[++newStartIndex]
} else {
const oldChildToMove = oldChildren[oldIndex]
patch(oldChildToMove, newStartChild, options)
oldChildren[oldIndex] = undefined
parentElement.insertBefore(oldChildToMove.domNode, oldStartChild.domNode)
newStartChild = newChildren[++newStartIndex]
}
}
}
if (oldStartIndex > oldEndIndex) {
const subsequentElement = newChildren[newEndIndex + 1] ? newChildren[newEndIndex + 1].domNode : null
for (let i = newStartIndex; i <= newEndIndex; i++) {
parentElement.insertBefore(render(newChildren[i], options), subsequentElement)
}
} else if (newStartIndex > newEndIndex) {
for (let i = oldStartIndex; i <= oldEndIndex; i++) {
const child = oldChildren[i]
if (child) removeVirtualNode(child, options && options.refs)
}
}
}
function removeVirtualNode (virtualNode, refs, removeDOMNode = true) {
const {domNode, props, children, component} = virtualNode
const ref = props && props.ref
if (component) {
if (refs && ref && refs[ref] === component) delete refs[ref]
if (typeof component.destroy === 'function') component.destroy()
} else {
if (refs && ref && refs[ref] === domNode) delete refs[ref]
if (children) {
for (let i = 0; i < children.length; i++) {
removeVirtualNode(children[i], refs, false)
}
}
}
if (removeDOMNode) domNode.remove()
}
function virtualNodesAreEqual (oldVirtualNode, newVirtualNode) {
return (
getKey(oldVirtualNode) === getKey(newVirtualNode)
&& oldVirtualNode.tag === newVirtualNode.tag
)
}
function getKey (virtualNode) {
return virtualNode.props ? virtualNode.props.key : undefined
}
function mapOldKeysToIndices (children, startIndex, endIndex) {
let oldIndicesByKey = new Map()
for (let i = startIndex; i <= endIndex; i++) {
const key = getKey(children[i])
if (key) oldIndicesByKey.set(key, i)
}
return oldIndicesByKey
}
module.exports = patch
},{"./render":6,"./update-props":10}],6:[function(require,module,exports){
const updateProps = require('./update-props')
const SVG_TAGS = require('./svg-tags')
function render (virtualNode, options) {
let domNode
if (virtualNode.text != null) {
domNode = document.createTextNode(virtualNode.text)
} else {
const {tag, children} = virtualNode
let {props} = virtualNode
if (typeof tag === 'function') {
let ref
if (props && props.ref) {
ref = props.ref
}
const component = new tag(props || {}, children)
virtualNode.component = component
domNode = component.element
if (options && options.refs && ref) {
options.refs[ref] = component
}
} else if (SVG_TAGS.has(tag)) {
domNode = document.createElementNS("http://www.w3.org/2000/svg", tag);
if (children) addChildren(domNode, children, options)
if (props) updateProps(domNode, null, virtualNode, options)
} else {
domNode = document.createElement(tag)
if (children) addChildren(domNode, children, options)
if (props) updateProps(domNode, null, virtualNode, options)
}
}
virtualNode.domNode = domNode
return domNode
}
function addChildren (parent, children, options) {
for (let i = 0; i < children.length; i++) {
parent.appendChild(render(children[i], options))
}
}
module.exports = render
},{"./svg-tags":9,"./update-props":10}],7:[function(require,module,exports){
// This file implements getter and setter functions for a scheduler to be used
// by this library when updating the DOM. The scheduler's job is to ensure that
// DOM interaction is performed efficiently. When using `etch` in Atom, you
// should tell `etch` to use Atom's scheduler by calling
// `setScheduler(atom.views)`.
//
// Schedulers should support the following interface:
// * `updateDocument(fn)` This method is asynchronous. It enqueues functions to
// be executed later.
// * `getNextUpdatePromise()` This function should return a promise that
// resolves after all pending document update functions have been invoked.
//
// Schedulers could support the following optional methods, which are supported
// by Atom's scheduler.
//
// * `readDocument` This method can be invoked by clients other than `etch` when
// it is necessary to read from the DOM. Functions enqueued via this method
// should not be run until all document update functions have been executed.
// Batching updates and reads in this way will prevent forced synchronous
// reflows.
// * `pollDocument` This method is similar to `readDocument`, but it runs the
// associated functions repeatedly. Again, they should be scheduled in such a
// way so as to avoid synchronous reflows.
const DefaultScheduler = require('./default-scheduler')
let scheduler = null
module.exports.setScheduler = function setScheduler (customScheduler) {
scheduler = customScheduler
}
module.exports.getScheduler = function getScheduler () {
if (!scheduler) {
scheduler = new DefaultScheduler()
}
return scheduler
}
},{"./default-scheduler":2}],8:[function(require,module,exports){
// Based on https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
module.exports = new Map([
['accentHeight', 'accent-height'],
['alignmentBaseline', 'alignment-baseline'],
['arabicForm', 'arabic-form'],
['baselineShift', 'baseline-shift'],
['capHeight', 'cap-height'],
['className', 'class'],
['clipPath', 'clip-path'],
['clipRule', 'clip-rule'],
['colorInterpolation', 'color-interpolation'],
['colorInterpolationFilters', 'color-interpolation-filters'],
['colorProfile', 'color-profile'],
['colorRendering', 'color-rendering'],
['dominantBaseline', 'dominant-baseline'],
['enableBackground', 'enable-background'],
['fillOpacity', 'fill-opacity'],
['fillRule', 'fill-rule'],
['floodColor', 'flood-color'],
['floodOpacity', 'flood-opacity'],
['fontFamily', 'font-family'],
['fontSize', 'font-size'],
['fontSizeAdjust', 'font-size-adjust'],
['fontStretch', 'font-stretch'],
['fontStyle', 'font-style'],
['fontVariant', 'font-variant'],
['fontWeight', 'font-weight'],
['glyphName', 'glyph-name'],
['glyphOrientationHorizontal', 'glyph-orientation-horizontal'],
['glyphOrientationVertical', 'glyph-orientation-vertical'],
['horizAdvX', 'horiz-adv-x'],
['horizOriginX', 'horiz-origin-x'],
['letterSpacing', 'letter-spacing'],
['lightingColor', 'lighting-color'],
['markerEnd', 'marker-end'],
['markerMid', 'marker-mid'],
['markerStart', 'marker-start'],
['overlinePosition', 'overline-position'],
['overlineThickness', 'overline-thickness'],
['panose1', 'panose-1'],
['paintOrder', 'paint-order'],
['pointerEvents', 'pointer-events'],
['renderingIntent', 'rendering-intent'],
['shapeRendering', 'shape-rendering'],
['stopColor', 'stop-color'],
['stopOpacity', 'stop-opacity'],
['strikethroughPosition', 'strikethrough-position'],
['strikethroughThickness', 'strikethrough-thickness'],
['strokeDasharray', 'stroke-dasharray'],
['strokeDashoffset', 'stroke-dashoffset'],
['strokeLinecap', 'stroke-linecap'],
['strokeLinejoin', 'stroke-linejoin'],
['strokeMiterlimit', 'stroke-miterlimit'],
['strokeOpacity', 'stroke-opacity'],
['strokeWidth', 'stroke-width'],
['textAnchor', 'text-anchor'],
['textDecoration', 'text-decoration'],
['textRendering', 'text-rendering'],
['underlinePosition', 'underline-position'],
['underlineThickness', 'underline-thickness'],
['unicodeBidi', 'unicode-bidi'],
['unicodeRange', 'unicode-range'],
['unitsPerEm', 'units-per-em'],
['vAlphabetic', 'v-alphabetic'],
['vHanging', 'v-hanging'],
['vIdeographic', 'v-ideographic'],
['vMathematical', 'v-mathematical'],
['vertAdvY', 'vert-adv-y'],
['vertOriginX', 'vert-origin-x'],
['vertOriginY', 'vert-origin-y'],
['wordSpacing', 'word-spacing'],
['writingMode', 'writing-mode'],
['xHeight', 'x-height'],
])
},{}],9:[function(require,module,exports){
// taken from https://github.com/facebook/react/blob/67f8524e88abbf1ac0fd86d38a0477d11fbc7b3e/src/isomorphic/classic/element/ReactDOMFactories.js#L153
module.exports = new Set([
'circle',
'clipPath',
'defs',
'ellipse',
'g',
'image',
'line',
'linearGradient',
'mask',
'path',
'pattern',
'polygon',
'polyline',
'radialGradient',
'rect',
'stop',
'svg',
'text',
'tspan'
])
},{}],10:[function(require,module,exports){
const EVENT_LISTENER_PROPS = require('./event-listener-props')
const SVG_TAGS = require('./svg-tags')
const SVG_ATTRIBUTE_TRANSLATIONS = require('./svg-attribute-translations')
const EMPTY = ''
module.exports = function (domNode, oldVirtualNode, newVirtualNode, options) {
const oldProps = oldVirtualNode && oldVirtualNode.props
const newProps = newVirtualNode.props
let refs, listenerContext
if (options) {
refs = options.refs
listenerContext = options.listenerContext
}
updateProps(domNode, oldVirtualNode, oldProps, newVirtualNode, newProps)
if (refs) updateRef(domNode, oldProps && oldProps.ref, newProps && newProps.ref, refs)
updateEventListeners(domNode, oldVirtualNode, newVirtualNode, listenerContext)
}
function updateProps (domNode, oldVirtualNode, oldProps, newVirtualNode, newProps) {
if (oldProps) {
const oldPropsNames = Object.keys(oldProps)
for (let i = 0; i < oldPropsNames.length; i++) {
const name = oldPropsNames[i]
if (name === 'ref' || name === 'on') continue
if (name in EVENT_LISTENER_PROPS) continue
if (!newProps || !(name in newProps)) {
if (name === 'dataset') {
updateProps(domNode.dataset, null, oldProps && oldProps.dataset, null, null)
} else if (name !== 'innerHTML' && oldVirtualNode && SVG_TAGS.has(oldVirtualNode.tag)) {
domNode.removeAttribute(SVG_ATTRIBUTE_TRANSLATIONS.get(name) || name)
} else {
// Clear property for objects that don't support deletion (e.g. style
// or className). If we used null instead of an empty string, the DOM
// could sometimes stringify the value and mistakenly assign 'null'.
domNode[name] = EMPTY
delete domNode[name]
}
}
}
}
if (newProps) {
const newPropsNames = Object.keys(newProps)
for (let i = 0; i < newPropsNames.length; i++) {
const name = newPropsNames[i]
if (name === 'ref' || name === 'on') continue
if (name in EVENT_LISTENER_PROPS) continue
const oldValue = oldProps && oldProps[name]
const newValue = newProps[name]
if (name === 'dataset') {
updateNestedProps(domNode.dataset, oldValue, newValue, false)
} else if (name === 'style' && typeof newValue !== 'string') {
let oldProps = oldValue
if (typeof oldProps === 'string') {
domNode.style = ''
oldProps = null
}
updateNestedProps(domNode.style, oldProps, newValue, true)
} else if (name === 'attributes') {
updateAttributes(domNode, oldValue, newValue)
} else {
if (newValue !== oldValue) {
if (name !== 'innerHTML' && newVirtualNode && SVG_TAGS.has(newVirtualNode.tag)) {
domNode.setAttribute(SVG_ATTRIBUTE_TRANSLATIONS.get(name) || name, newValue)
} else {
domNode[name] = newValue
}
}
}
}
}
}
function updateNestedProps (domProps, oldProps, newProps, isStyleObject) {
if (oldProps) {
const oldPropsNames = Object.keys(oldProps)
for (let i = 0; i < oldPropsNames.length; i++) {
const name = oldPropsNames[i]
if (!newProps || !(name in newProps)) {
if (isStyleObject) {
domProps[name] = EMPTY
} else {
delete domProps[name]
}
}
}
}
if (newProps) {
const newPropsNames = Object.keys(newProps)
for (let i = 0; i < newPropsNames.length; i++) {
const name = newPropsNames[i]
const oldValue = oldProps && oldProps[name]
const newValue = newProps[name]
if (newValue !== oldValue) {
domProps[name] = newValue
}
}
}
}
function updateAttributes (domNode, oldAttributes, newAttributes) {
if (oldAttributes) {
const oldAttributeNames = Object.keys(oldAttributes)
for (let i = 0; i < oldAttributeNames.length; i++) {
const name = oldAttributeNames[i]
if (!newAttributes || !(name in newAttributes)) {
domNode.removeAttribute(name)
}
}
}
if (newAttributes) {
const newAttributeNames = Object.keys(newAttributes)
for (let i = 0; i < newAttributeNames.length; i++) {
const name = newAttributeNames[i]
const oldValue = oldAttributes && oldAttributes[name]
const newValue = newAttributes[name]
if (newValue !== oldValue) {
domNode.setAttribute(name, newValue)
}
}
}
}
function updateRef (domNode, oldRefName, newRefName, refs) {
if (newRefName !== oldRefName) {
if (oldRefName && refs[oldRefName] === domNode) delete refs[oldRefName]
if (newRefName) refs[newRefName] = domNode
}
}
function updateEventListeners (domNode, oldVirtualNode, newVirtualNode, listenerContext) {
const oldListeners = oldVirtualNode && oldVirtualNode.props && oldVirtualNode.props.on
const newListeners = newVirtualNode.props && newVirtualNode.props.on
for (const eventName in oldListeners) {
if (!(newListeners && eventName in newListeners)) {
let listenerToRemove
if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) {
listenerToRemove = oldVirtualNode.boundListeners[eventName]
} else {
listenerToRemove =oldListeners[eventName]
}
domNode.removeEventListener(eventName, listenerToRemove)
}
}
for (const eventName in newListeners) {
const oldListener = oldListeners && oldListeners[eventName]
const newListener = newListeners[eventName]
if (newListener !== oldListener) {
if (oldListener) {
let listenerToRemove
if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) {
listenerToRemove = oldVirtualNode.boundListeners[eventName]
} else {
listenerToRemove = oldListener
}
domNode.removeEventListener(eventName, listenerToRemove)
}
let listenerToAdd
if (listenerContext) {
listenerToAdd = newListener.bind(listenerContext)
if (!newVirtualNode.boundListeners) newVirtualNode.boundListeners = {}
newVirtualNode.boundListeners[eventName] = listenerToAdd
} else {
listenerToAdd = newListener
}
domNode.addEventListener(eventName, listenerToAdd)
}
}
}
},{"./event-listener-props":4,"./svg-attribute-translations":8,"./svg-tags":9}],"etch":[function(require,module,exports){
const dom = require('./dom')
const render = require('./render')
const {initialize, update, updateSync, destroy, destroySync} = require('./component-helpers')
const {setScheduler, getScheduler} = require('./scheduler-assignment')
module.exports = {
dom, render,
initialize, update, updateSync, destroy, destroySync,
setScheduler, getScheduler
}
},{"./component-helpers":1,"./dom":3,"./render":6,"./scheduler-assignment":7}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImxpYi9jb21wb25lbnQtaGVscGVycy5qcyIsImxpYi9kZWZhdWx0LXNjaGVkdWxlci5qcyIsImxpYi9kb20uanMiLCJsaWIvZXZlbnQtbGlzdGVuZXItcHJvcHMuanMiLCJsaWIvcGF0Y2guanMiLCJsaWIvcmVuZGVyLmpzIiwibGliL3NjaGVkdWxlci1hc3NpZ25tZW50LmpzIiwibGliL3N2Zy1hdHRyaWJ1dGUtdHJhbnNsYXRpb25zLmpzIiwibGliL3N2Zy10YWdzLmpzIiwibGliL3VwZGF0ZS1wcm9wcy5qcyIsImV0Y2giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImNvbnN0IHJlbmRlciA9IHJlcXVpcmUoJy4vcmVuZGVyJylcbmNvbnN0IHBhdGNoID0gcmVxdWlyZSgnLi9wYXRjaCcpXG5jb25zdCB7Z2V0U2NoZWR1bGVyfSA9IHJlcXVpcmUoJy4vc2NoZWR1bGVyLWFzc2lnbm1lbnQnKVxuXG5jb25zdCBjb21wb25lbnRzV2l0aFBlbmRpbmdVcGRhdGVzID0gbmV3IFdlYWtTZXQoKVxubGV0IHN5bmNVcGRhdGVzSW5Qcm9ncmVzc0NvdW50ZXIgPSAwXG5sZXQgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyID0gMFxuXG5mdW5jdGlvbiBpc1ZhbGlkVmlydHVhbE5vZGUgKHZpcnR1YWxOb2RlKSB7XG4gIHJldHVybiB2aXJ0dWFsTm9kZSAhPSBudWxsICYmIHZpcnR1YWxOb2RlICE9PSBmYWxzZVxufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGFzc29jaWF0ZXMgYSBjb21wb25lbnQgb2JqZWN0IHdpdGggYSBET00gZWxlbWVudCBieSBjYWxsaW5nXG4vLyB0aGUgY29tcG9uZW50cyBgcmVuZGVyYCBtZXRob2QsIGFzc2lnbmluZyBhbiBgLmVsZW1lbnRgIHByb3BlcnR5IG9uIHRoZVxuLy8gb2JqZWN0IGFuZCBhbHNvIHJldHVybmluZyB0aGUgZWxlbWVudC5cbi8vXG4vLyBJdCBhbHNvIGFzc2lnbnMgYSBgdmlydHVhbE5vZGVgIHByb3BlcnR5IGJhc2VkIG9uIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlXG4vLyBgcmVuZGVyYCBtZXRob2QuIFRoaXMgd2lsbCBiZSB1c2VkIGxhdGVyIGJ5IGBwZXJmb3JtRWxlbWVudFVwZGF0ZWAgdG8gZGlmZlxuLy8gdGhlIG5ldyByZXN1bHRzIG9mIGByZW5kZXJgIHdpdGggdGhlIHByZXZpb3VzIHJlc3VsdHMgd2hlbiB1cGRhdGluZyB0aGVcbi8vIGNvbXBvbmVudCdzIGVsZW1lbnQuXG4vL1xuLy8gRmluYWxseSwgdGhpcyBmdW5jdGlvbiBhbHNvIGFzc29jaWF0ZXMgdGhlIGNvbXBvbmVudCB3aXRoIGEgYHJlZnNgIG9iamVjdCxcbi8vIHdoaWNoIGlzIHBvcHVsYXRlZCB3aXRoIHJlZmVyZW5jZXMgdG8gZWxlbWVudHMgYmFzZWQgb24gYHJlZmAgcHJvcGVydGllcyBvblxuLy8gbm9kZXMgb2YgdGhlIGB2aXJ0dWFsLWRvbWAgdHJlZS4gQmVmb3JlIGNhbGxpbmcgaW50byBgdmlydHVhbC1kb21gIHRvIGNyZWF0ZVxuLy8gdGhlIERPTSB0cmVlLCBpdCBwdXNoZXMgdGhpcyBgcmVmc2Agb2JqZWN0IHRvIGEgc2hhcmVkIHN0YWNrIHNvIGl0IGNhbiBiZVxuLy8gYWNjZXNzZWQgYnkgaG9va3MgZHVyaW5nIHRoZSBjcmVhdGlvbiBvZiBpbmRpdmlkdWFsIGVsZW1lbnRzLlxuZnVuY3Rpb24gaW5pdGlhbGl6ZShjb21wb25lbnQpIHtcbiAgaWYgKHR5cGVvZiBjb21wb25lbnQudXBkYXRlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFdGNoIGNvbXBvbmVudHMgbXVzdCBpbXBsZW1lbnQgYHVwZGF0ZShwcm9wcywgY2hpbGRyZW4pYC4nKVxuICB9XG5cbiAgbGV0IHZpcnR1YWxOb2RlID0gY29tcG9uZW50LnJlbmRlcigpXG4gIGlmICghaXNWYWxpZFZpcnR1YWxOb2RlKHZpcnR1YWxOb2RlKSkge1xuICAgIGxldCBuYW1lUGFydCA9IGNvbXBvbmVudC5jb25zdHJ1Y3RvciAmJiBjb21wb25lbnQuY29uc3RydWN0b3IubmFtZSA/ICcgaW4gJyArIGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lIDogJydcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgZmFsc3kgdmFsdWUgJyArIHZpcnR1YWxOb2RlICsgJyByZXR1cm5lZCBmcm9tIHJlbmRlcigpJyArIG5hbWVQYXJ0KVxuICB9XG5cbiAgY29tcG9uZW50LnJlZnMgPSB7fVxuICBjb21wb25lbnQudmlydHVhbE5vZGUgPSB2aXJ0dWFsTm9kZVxuICBjb21wb25lbnQuZWxlbWVudCA9IHJlbmRlcihjb21wb25lbnQudmlydHVhbE5vZGUsIHtcbiAgICByZWZzOiBjb21wb25lbnQucmVmcywgbGlzdGVuZXJDb250ZXh0OiBjb21wb25lbnRcbiAgfSlcbn1cblxuLy8gVGhpcyBmdW5jdGlvbiByZWNlaXZlcyBhIGNvbXBvbmVudCB0aGF0IGhhcyBhbHJlYWR5IGJlZW4gYXNzb2NpYXRlZCB3aXRoIGFuXG4vLyBlbGVtZW50IHZpYSBhIHByZXZpb3VzIGNhbGwgdG8gYGluaXRpYWxpemVgIGFuZCB1cGRhdGVzIHRoaXMgZWxlbWVudCBieVxuLy8gY2FsbGluZyBgcmVuZGVyYCBvbiB0aGUgY29tcG9uZW50LlxuLy9cbi8vIFdoZW4gY2FsbGVkIGluIG5vcm1hbCBjaXJjdW1zdGFuY2VzLCBpdCB1c2VzIHRoZSBzY2hlZHVsZXIgdG8gZGVmZXIgdGhpc1xuLy8gdXBkYXRlIHVudGlsIHRoZSBuZXh0IGFuaW1hdGlvbiBmcmFtZSwgYW5kIHdpbGwgb25seSBwZXJmb3JtIG9uZSB1cGRhdGUgb2YgYVxuLy8gZ2l2ZW4gY29tcG9uZW50IGluIGEgZ2l2ZW4gZnJhbWUuIFRoaXMgbWVhbnMgeW91IGNhbiBjYWxsIGB1cGRhdGVgXG4vLyByZXBlYXRlZGx5IGluIGEgZ2l2ZW4gdGljayB3aXRob3V0IGNhdXNpbmcgcmVkdW5kYW50IHVwZGF0ZXMuXG4vL1xuLy8gSWYgdGhpcyBmdW5jdGlvbiBjYWxsZWQgZHVyaW5nIGFub3RoZXIgc3luY2hyb25vdXMgdXBkYXRlIChmb3IgZXhhbXBsZSwgYXMgYVxuLy8gcmVzdWx0IG9mIGEgY2FsbCB0byBgdXBkYXRlYCBvbiBhIGNoaWxkIGNvbXBvbmVudCksIHRoZSB1cGRhdGUgaXMgcGVyZm9ybWVkXG4vLyBzeW5jaHJvbm91c2x5LlxuLy9cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCByZXNvbHZlIHdoZW4gdGhlIHJlcXVlc3RlZCB1cGRhdGUgaGFzIGJlZW5cbi8vIGNvbXBsZXRlZC5cbmZ1bmN0aW9uIHVwZGF0ZSAoY29tcG9uZW50LCByZXBsYWNlTm9kZT10cnVlKSB7XG4gIGlmIChzeW5jVXBkYXRlc0luUHJvZ3Jlc3NDb3VudGVyID4gMCkge1xuICAgIHVwZGF0ZVN5bmMoY29tcG9uZW50LCByZXBsYWNlTm9kZSlcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfVxuXG4gIGxldCBzY2hlZHVsZXIgPSBnZXRTY2hlZHVsZXIoKVxuXG4gIGlmICghY29tcG9uZW50c1dpdGhQZW5kaW5nVXBkYXRlcy5oYXMoY29tcG9uZW50KSkge1xuICAgIGNvbXBvbmVudHNXaXRoUGVuZGluZ1VwZGF0ZXMuYWRkKGNvbXBvbmVudClcbiAgICBzY2hlZHVsZXIudXBkYXRlRG9jdW1lbnQoZnVuY3Rpb24gKCkge1xuICAgICAgY29tcG9uZW50c1dpdGhQZW5kaW5nVXBkYXRlcy5kZWxldGUoY29tcG9uZW50KVxuICAgICAgdXBkYXRlU3luYyhjb21wb25lbnQsIHJlcGxhY2VOb2RlKVxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gc2NoZWR1bGVyLmdldE5leHRVcGRhdGVQcm9taXNlKClcbn1cblxuLy8gU3luY2hyb25zbHkgdXBkYXRlcyB0aGUgRE9NIGVsZW1lbnQgYXNzb2NpYXRlZCB3aXRoIGEgY29tcG9uZW50IG9iamVjdC4gLlxuLy8gVGhpcyBtZXRob2QgYXNzdW1lcyB0aGUgcHJlc2VuY2Ugb2YgYC5lbGVtZW50YCBhbmQgYC52aXJ0dWFsTm9kZWBcbi8vIHByb3BlcnRpZXMgb24gdGhlIGNvbXBvbmVudCwgd2hpY2ggYXJlIGFzc2lnbmVkIGluIHRoZSBgaW5pdGlhbGl6ZWBcbi8vIGZ1bmN0aW9uLlxuLy9cbi8vIEl0IGNhbGxzIGByZW5kZXJgIG9uIHRoZSBjb21wb25lbnQgdG8gb2J0YWluIHRoZSBkZXNpcmVkIHN0YXRlIG9mIHRoZSBET00sXG4vLyB0aGVuIGBkaWZmYHMgaXQgd2l0aCB0aGUgcHJldmlvdXMgc3RhdGUgYW5kIGBwYXRjaGBlcyB0aGUgZWxlbWVudCBiYXNlZCBvblxuLy8gdGhlIHJlc3VsdGluZyBkaWZmLiBEdXJpbmcgdGhlIHBhdGNoIG9wZXJhdGlvbiwgaXQgcHVzaGVzIHRoZSBjb21wb25lbnQnc1xuLy8gYHJlZnNgIG9iamVjdCB0byBhIHNoYXJlZCBzdGFjayBzbyB0aGF0IHJlZmVyZW5jZXMgdG8gRE9NIGVsZW1lbnRzIGNhbiBiZVxuLy8gdXBkYXRlZC5cbi8vXG4vLyBJZiBgdXBkYXRlYCBpcyBjYWxsZWQgZHVyaW5nIHRoZSBpbnZvY2F0aW9uIG9mIGB1cGRhdGVTeW5jYCxcbi8vIHRoZSByZXF1ZXN0cyBhcmUgcHJvY2Vzc2VkIHN5bmNocm9ub3VzbHkgYXMgd2VsbC4gV2UgdHJhY2sgd2hldGhlciB0aGlzIGlzXG4vLyB0aGUgY2FzZSBieSBpbmNyZW1lbnRpbmcgYW5kIGRlY3JlbWVudGluZyBgc3luY1VwZGF0ZXNJblByb2dyZXNzQ291bnRlcmBcbi8vIGFyb3VuZCB0aGUgY2FsbC5cbi8vXG4vLyBGb3Igbm93LCBldGNoIGRvZXMgbm90IGFsbG93IHRoZSByb290IHRhZyBvZiB0aGUgYHJlbmRlcmAgbWV0aG9kIHRvIGNoYW5nZVxuLy8gYmV0d2VlbiBpbnZvY2F0aW9ucywgYmVjYXVzZSB3ZSB3YW50IHRvIHByZXNlcnZlIGEgb25lLXRvLW9uZSByZWxhdGlvbnNoaXBcbi8vIGJldHdlZW4gY29tcG9uZW50IG9iamVjdHMgYW5kIERPTSBlbGVtZW50cyBmb3Igc2ltcGxpY2l0eS5cbmZ1bmN0aW9uIHVwZGF0ZVN5bmMgKGNvbXBvbmVudCwgcmVwbGFjZU5vZGU9dHJ1ZSkge1xuICBsZXQgbmV3VmlydHVhbE5vZGUgPSBjb21wb25lbnQucmVuZGVyKClcbiAgaWYgKCFpc1ZhbGlkVmlydHVhbE5vZGUobmV3VmlydHVhbE5vZGUpKSB7XG4gICAgbGV0IG5hbWVQYXJ0ID0gY29tcG9uZW50LmNvbnN0cnVjdG9yICYmIGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lID8gJyBpbiAnICsgY29tcG9uZW50LmNvbnN0cnVjdG9yLm5hbWUgOiAnJ1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBmYWxzeSB2YWx1ZSAnICsgbmV3VmlydHVhbE5vZGUgKyAnIHJldHVybmVkIGZyb20gcmVuZGVyKCknICsgbmFtZVBhcnQpXG4gIH1cblxuICBzeW5jVXBkYXRlc0luUHJvZ3Jlc3NDb3VudGVyKytcbiAgbGV0IG9sZFZpcnR1YWxOb2RlID0gY29tcG9uZW50LnZpcnR1YWxOb2RlXG4gIGxldCBvbGREb21Ob2RlID0gY29tcG9uZW50LmVsZW1lbnRcbiAgbGV0IG5ld0RvbU5vZGUgPSBwYXRjaChvbGRWaXJ0dWFsTm9kZSwgbmV3VmlydHVhbE5vZGUsIHtcbiAgICByZWZzOiBjb21wb25lbnQucmVmcyxcbiAgICBsaXN0ZW5lckNvbnRleHQ6IGNvbXBvbmVudFxuICB9KVxuICBjb21wb25lbnQudmlydHVhbE5vZGUgPSBuZXdWaXJ0dWFsTm9kZVxuICBpZiAobmV3RG9tTm9kZSAhPT0gb2xkRG9tTm9kZSAmJiAhcmVwbGFjZU5vZGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSByb290IG5vZGUgdHlwZSBjaGFuZ2VkIG9uIHVwZGF0ZSwgYnV0IHRoZSB1cGRhdGUgd2FzIHBlcmZvcm1lZCB3aXRoIHRoZSByZXBsYWNlTm9kZSBvcHRpb24gc2V0IHRvIGZhbHNlJylcbiAgfSBlbHNlIHtcbiAgICBjb21wb25lbnQuZWxlbWVudCA9IG5ld0RvbU5vZGVcbiAgfVxuXG4gIC8vIFdlIGNhbiBzYWZlbHkgcGVyZm9ybSBhZGRpdGlvbmFsIHdyaXRlcyBhZnRlciBhIERPTSB1cGRhdGUgc3luY2hyb25vdXNseSxcbiAgLy8gYnV0IGFueSByZWFkcyBuZWVkIHRvIGJlIGRlZmVycmVkIHVudGlsIGFsbCB3cml0ZXMgYXJlIGNvbXBsZXRlZCB0byBhdm9pZFxuICAvLyBET00gdGhyYXNoaW5nLiBSZXF1ZXN0ZWQgcmVhZHMgb2NjdXIgYXQgdGhlIGVuZCBvZiB0aGUgdGhlIGN1cnJlbnQgZnJhbWVcbiAgLy8gaWYgdGhpcyBtZXRob2Qgd2FzIGludm9rZWQgdmlhIHRoZSBzY2hlZHVsZXIuIE90aGVyd2lzZSwgaWYgYHVwZGF0ZVN5bmNgXG4gIC8vIHdhcyBpbnZva2VkIG91dHNpZGUgb2YgdGhlIHNjaGVkdWxlciwgdGhlIGRlZmF1bHQgc2NoZWR1bGVyIHdpbGwgZGVmZXJcbiAgLy8gcmVhZHMgdW50aWwgdGhlIG5leHQgYW5pbWF0aW9uIGZyYW1lLlxuICBpZiAodHlwZW9mIGNvbXBvbmVudC53cml0ZUFmdGVyVXBkYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29tcG9uZW50LndyaXRlQWZ0ZXJVcGRhdGUoKVxuICB9XG4gIGlmICh0eXBlb2YgY29tcG9uZW50LnJlYWRBZnRlclVwZGF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGdldFNjaGVkdWxlcigpLnJlYWREb2N1bWVudChmdW5jdGlvbiAoKSB7XG4gICAgICBjb21wb25lbnQucmVhZEFmdGVyVXBkYXRlKClcbiAgICB9KVxuICB9XG5cbiAgc3luY1VwZGF0ZXNJblByb2dyZXNzQ291bnRlci0tXG59XG5cbi8vIFJlbW92ZXMgdGhlIGNvbXBvbmVudCdzIGFzc29jaWF0ZWQgZWxlbWVudCBhbmQgY2FsbHMgYGRlc3Ryb3lgIG9uIGFueSBjaGlsZFxuLy8gY29tcG9uZW50cy4gTm9ybWFsbHksIHRoaXMgZnVuY3Rpb24gaXMgYXN5bmNocm9ub3VzIGFuZCB3aWxsIHBlcmZvcm0gdGhlXG4vLyBkZXN0cnVjdGlvbiBvbiB0aGUgbmV4dCBhbmltYXRpb24gZnJhbWUuIElmIGNhbGxlZCBhcyB0aGUgcmVzdWx0IG9mIGFub3RoZXJcbi8vIHVwZGF0ZSBvciBkZXN0cnVjdGlvbiwgaXQgY2FsbHMgYGRlc3Ryb3lgIG9uIGNoaWxkIGNvbXBvbmVudHMgc3luY2hyb25vdXNseS5cbi8vIElmIGNhbGxlZCBhcyB0aGUgcmVzdWx0IG9mIGRlc3Ryb3lpbmcgYSBjb21wb25lbnQgaGlnaGVyIGluIHRoZSBET00sIHRoZVxuLy8gZWxlbWVudCBpcyBub3QgcmVtb3ZlZCB0byBhdm9pZCByZWR1bmRhbnQgRE9NIG1hbmlwdWxhdGlvbi4gUmV0dXJucyBhIHByb21pc2Vcbi8vIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZGVzdHJ1Y3Rpb24gaXMgY29tcGxldGVkLlxuZnVuY3Rpb24gZGVzdHJveSAoY29tcG9uZW50LCByZW1vdmVOb2RlPXRydWUpIHtcbiAgaWYgKHN5bmNVcGRhdGVzSW5Qcm9ncmVzc0NvdW50ZXIgPiAwIHx8IHN5bmNEZXN0cnVjdGlvbnNJblByb2dyZXNzQ291bnRlciA+IDApIHtcbiAgICBkZXN0cm95U3luYyhjb21wb25lbnQsIHJlbW92ZU5vZGUpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBsZXQgc2NoZWR1bGVyID0gZ2V0U2NoZWR1bGVyKClcbiAgc2NoZWR1bGVyLnVwZGF0ZURvY3VtZW50KGZ1bmN0aW9uICgpIHtcbiAgICBkZXN0cm95U3luYyhjb21wb25lbnQsIHJlbW92ZU5vZGUpXG4gIH0pXG4gIHJldHVybiBzY2hlZHVsZXIuZ2V0TmV4dFVwZGF0ZVByb21pc2UoKVxufVxuXG4vLyBBIHN5bmNocm9ub3VzIHZlcnNpb24gb2YgYGRlc3Ryb3lgLlxuLy9cbi8vIE5vdGUgdGhhdCB3ZSB0cmFjayB3aGV0aGVyIGBkZXN0cm95YCBjYWxscyBhcmUgaW4gcHJvZ3Jlc3MgYW5kIG9ubHkgcmVtb3ZlXG4vLyB0aGUgZWxlbWVudCBpZiB3ZSBhcmUgbm90IGEgbmVzdGVkIGNhbGwuXG5mdW5jdGlvbiBkZXN0cm95U3luYyAoY29tcG9uZW50LCByZW1vdmVOb2RlPXRydWUpIHtcbiAgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyKytcbiAgZGVzdHJveUNoaWxkQ29tcG9uZW50cyhjb21wb25lbnQudmlydHVhbE5vZGUpXG4gIGlmIChzeW5jRGVzdHJ1Y3Rpb25zSW5Qcm9ncmVzc0NvdW50ZXIgPT09IDEgJiYgcmVtb3ZlTm9kZSkgY29tcG9uZW50LmVsZW1lbnQucmVtb3ZlKClcbiAgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyLS1cbn1cblxuZnVuY3Rpb24gZGVzdHJveUNoaWxkQ29tcG9uZW50cyh2aXJ0dWFsTm9kZSkge1xuICBpZiAodmlydHVhbE5vZGUuY29tcG9uZW50ICYmIHR5cGVvZiB2aXJ0dWFsTm9kZS5jb21wb25lbnQuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHZpcnR1YWxOb2RlLmNvbXBvbmVudC5kZXN0cm95KClcbiAgfSBlbHNlIGlmICh2aXJ0dWFsTm9kZS5jaGlsZHJlbikge1xuICAgIHZpcnR1YWxOb2RlLmNoaWxkcmVuLmZvckVhY2goZGVzdHJveUNoaWxkQ29tcG9uZW50cylcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaW5pdGlhbGl6ZSxcbiAgdXBkYXRlLCB1cGRhdGVTeW5jLFxuICBkZXN0cm95LCBkZXN0cm95U3luY1xufVxuIiwiLy8gSWYgdGhlIHNjaGVkdWxlciBpcyBub3QgY3VzdG9taXplZCB2aWEgYGV0Y2guc2V0U2NoZWR1bGVyYCwgYW4gaW5zdGFuY2Ugb2Zcbi8vIHRoaXMgY2xhc3Mgd2lsbCBiZSB1c2VkIHRvIHNjaGVkdWxlIHVwZGF0ZXMgdG8gdGhlIGRvY3VtZW50LiBUaGVcbi8vIGB1cGRhdGVEb2N1bWVudGAgbWV0aG9kIGFjY2VwdHMgZnVuY3Rpb25zIHRvIGJlIHJ1biBhdCBzb21lIHBvaW50IGluIHRoZVxuLy8gZnV0dXJlLCB0aGVuIHJ1bnMgdGhlbSBvbiB0aGUgbmV4dCBhbmltYXRpb24gZnJhbWUuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIERlZmF1bHRTY2hlZHVsZXIge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgdGhpcy51cGRhdGVSZXF1ZXN0cyA9IFtdXG4gICAgdGhpcy5yZWFkUmVxdWVzdHMgPSBbXVxuICAgIHRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lID0gbnVsbFxuICAgIHRoaXMucGVyZm9ybVVwZGF0ZXMgPSB0aGlzLnBlcmZvcm1VcGRhdGVzLmJpbmQodGhpcylcbiAgICB0aGlzLnBlcmZvcm1pbmdVcGRhdGVzID0gZmFsc2VcbiAgfVxuXG4gIC8vIEVucXVldWVzIGZ1bmN0aW9ucyB0aGF0IHdyaXRlIHRvIHRoZSBET00gdG8gYmUgcGVyZm9ybWVkIG9uIHRoZSBuZXh0XG4gIC8vIGFuaW1hdGlvbiBmcmFtZS4gRnVuY3Rpb25zIHBhc3NlZCB0byB0aGlzIG1ldGhvZCBzaG91bGQgKm5ldmVyKiByZWFkIGZyb21cbiAgLy8gdGhlIERPTSwgYmVjYXVzZSB0aGF0IGNvdWxkIGNhdXNlIHN5bmNocm9ub3VzIHJlZmxvd3MuXG4gIHVwZGF0ZURvY3VtZW50IChmbikge1xuICAgIHRoaXMudXBkYXRlUmVxdWVzdHMucHVzaChmbilcbiAgICBpZiAoIXRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lKSB7XG4gICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5wZXJmb3JtVXBkYXRlcylcbiAgICB9XG4gIH1cblxuICByZWFkRG9jdW1lbnQgKGZuKSB7XG4gICAgdGhpcy5yZWFkUmVxdWVzdHMucHVzaChmbilcbiAgICBpZiAoIXRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lKSB7XG4gICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5wZXJmb3JtVXBkYXRlcylcbiAgICB9XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgcmVzb2x2ZSBhdCB0aGUgZW5kIG9mIHRoZSBuZXh0IHVwZGF0ZSBjeWNsZSxcbiAgLy8gYWZ0ZXIgYWxsIHRoZSBmdW5jdGlvbnMgcGFzc2VkIHRvIGB1cGRhdGVEb2N1bWVudGAgYW5kIGB1cGRhdGVEb2N1bWVudFN5bmNgXG4gIC8vIGhhdmUgYmVlbiBydW4uXG4gIGdldE5leHRVcGRhdGVQcm9taXNlICgpIHtcbiAgICBpZiAoIXRoaXMubmV4dFVwZGF0ZVByb21pc2UpIHtcbiAgICAgIHRoaXMubmV4dFVwZGF0ZVByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgdGhpcy5yZXNvbHZlTmV4dFVwZGF0ZVByb21pc2UgPSByZXNvbHZlXG4gICAgICB9KVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5uZXh0VXBkYXRlUHJvbWlzZVxuICB9XG5cbiAgLy8gUGVyZm9ybXMgYWxsIHRoZSBwZW5kaW5nIGRvY3VtZW50IHVwZGF0ZXMuIElmIHJ1bm5pbmcgdGhlc2UgdXBkYXRlXG4gIC8vIGZ1bmN0aW9ucyBjYXVzZXMgKm1vcmUqIHVwZGF0ZXMgdG8gYmUgZW5xdWV1ZWQsIHRoZXkgYXJlIHJ1biBzeW5jaHJvbm91c2x5XG4gIC8vIGluIHRoaXMgdXBkYXRlIGN5Y2xlIHdpdGhvdXQgd2FpdGluZyBmb3IgYW5vdGhlciBmcmFtZS5cbiAgcGVyZm9ybVVwZGF0ZXMgKCkge1xuICAgIHdoaWxlICh0aGlzLnVwZGF0ZVJlcXVlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMudXBkYXRlUmVxdWVzdHMuc2hpZnQoKSgpXG4gICAgfVxuXG4gICAgLy8gV2UgZG9uJ3QgY2xlYXIgdGhlIHBlbmRpbmcgZnJhbWUgdW50aWwgYWxsIHVwZGF0ZSByZXF1ZXN0cyBhcmUgcHJvY2Vzc2VkLlxuICAgIC8vIFRoaXMgZW5zdXJlcyB1cGRhdGVzIHJlcXVlc3RlZCB3aXRoaW4gb3RoZXIgdXBkYXRlcyBhcmUgcHJvY2Vzc2VkIGluIHRoZVxuICAgIC8vIGN1cnJlbnQgZnJhbWUuXG4gICAgdGhpcy5wZW5kaW5nQW5pbWF0aW9uRnJhbWUgPSBudWxsXG5cbiAgICAvLyBOb3cgdGhhdCB1cGRhdGVzIGFyZSBwcm9jZXNzZWQsIHdlIGNhbiBwZXJmb3JtIGFsbCBwZW5kaW5nIGRvY3VtZW50IHJlYWRzXG4gICAgLy8gd2l0aG91dCB0aGUgcmlzayBvZiBpbnRlcmxlYXZpbmcgdGhlbSB3aXRoIHdyaXRlcyBhbmQgY2F1c2luZyBsYXlvdXRcbiAgICAvLyB0aHJhc2hpbmcuXG4gICAgd2hpbGUgKHRoaXMucmVhZFJlcXVlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucmVhZFJlcXVlc3RzLnNoaWZ0KCkoKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm5leHRVcGRhdGVQcm9taXNlKSB7XG4gICAgICBsZXQgcmVzb2x2ZU5leHRVcGRhdGVQcm9taXNlID0gdGhpcy5yZXNvbHZlTmV4dFVwZGF0ZVByb21pc2VcbiAgICAgIHRoaXMubmV4dFVwZGF0ZVByb21pc2UgPSBudWxsXG4gICAgICB0aGlzLnJlc29sdmVOZXh0VXBkYXRlUHJvbWlzZSA9IG51bGxcbiAgICAgIHJlc29sdmVOZXh0VXBkYXRlUHJvbWlzZSgpXG4gICAgfVxuICB9XG59XG4iLCJjb25zdCBFVkVOVF9MSVNURU5FUl9QUk9QUyA9IHJlcXVpcmUoJy4vZXZlbnQtbGlzdGVuZXItcHJvcHMnKVxuY29uc3QgU1ZHX1RBR1MgPSByZXF1aXJlKCcuL3N2Zy10YWdzJylcblxuZnVuY3Rpb24gZG9tICh0YWcsIHByb3BzLCAuLi5jaGlsZHJlbikge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuW2ldXG4gICAgc3dpdGNoICh0eXBlb2YgY2hpbGQpIHtcbiAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICBjaGlsZHJlbltpXSA9IHt0ZXh0OiBjaGlsZH1cbiAgICAgICAgaSsrXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjaGlsZCkpIHtcbiAgICAgICAgICBjaGlsZHJlbi5zcGxpY2UoaSwgMSwgLi4uY2hpbGQpXG4gICAgICAgIH0gZWxzZSBpZiAoIWNoaWxkKSB7XG4gICAgICAgICAgY2hpbGRyZW4uc3BsaWNlKGksIDEpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaSsrXG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjaGlsZCBub2RlOiAke2NoaWxkfWApXG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3BzKSB7XG4gICAgZm9yIChjb25zdCBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgY29uc3QgZXZlbnROYW1lID0gRVZFTlRfTElTVEVORVJfUFJPUFNbcHJvcE5hbWVdXG4gICAgICBpZiAoZXZlbnROYW1lKSB7XG4gICAgICAgIGlmICghcHJvcHMub24pIHByb3BzLm9uID0ge31cbiAgICAgICAgcHJvcHMub25bZXZlbnROYW1lXSA9IHByb3BzW3Byb3BOYW1lXVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwcm9wcy5jbGFzcykge1xuICAgICAgcHJvcHMuY2xhc3NOYW1lID0gcHJvcHMuY2xhc3NcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge3RhZywgcHJvcHMsIGNoaWxkcmVufVxufVxuXG5jb25zdCBIVE1MX1RBR1MgPSBbXG4gICdhJywgJ2FiYnInLCAnYWRkcmVzcycsICdhcnRpY2xlJywgJ2FzaWRlJywgJ2F1ZGlvJywgJ2InLCAnYmRpJywgJ2JkbycsXG4gICdibG9ja3F1b3RlJywgJ2JvZHknLCAnYnV0dG9uJywgJ2NhbnZhcycsICdjYXB0aW9uJywgJ2NpdGUnLCAnY29kZScsXG4gICdjb2xncm91cCcsICdkYXRhbGlzdCcsICdkZCcsICdkZWwnLCAnZGV0YWlscycsICdkZm4nLCAnZGlhbG9nJywgJ2RpdicsICdkbCcsXG4gICdkdCcsICdlbScsICdmaWVsZHNldCcsICdmaWdjYXB0aW9uJywgJ2ZpZ3VyZScsICdmb290ZXInLCAnZm9ybScsICdoMScsICdoMicsXG4gICdoMycsICdoNCcsICdoNScsICdoNicsICdoZWFkJywgJ2hlYWRlcicsICdodG1sJywgJ2knLCAnaWZyYW1lJywgJ2lucycsICdrYmQnLFxuICAnbGFiZWwnLCAnbGVnZW5kJywgJ2xpJywgJ21haW4nLCAnbWFwJywgJ21hcmsnLCAnbWVudScsICdtZXRlcicsICduYXYnLFxuICAnbm9zY3JpcHQnLCAnb2JqZWN0JywgJ29sJywgJ29wdGdyb3VwJywgJ29wdGlvbicsICdvdXRwdXQnLCAncCcsICdwcmUnLFxuICAncHJvZ3Jlc3MnLCAncScsICdycCcsICdydCcsICdydWJ5JywgJ3MnLCAnc2FtcCcsICdzY3JpcHQnLCAnc2VjdGlvbicsXG4gICdzZWxlY3QnLCAnc21hbGwnLCAnc3BhbicsICdzdHJvbmcnLCAnc3R5bGUnLCAnc3ViJywgJ3N1bW1hcnknLCAnc3VwJyxcbiAgJ3RhYmxlJywgJ3Rib2R5JywgJ3RkJywgJ3RleHRhcmVhJywgJ3Rmb290JywgJ3RoJywgJ3RoZWFkJywgJ3RpbWUnLCAndGl0bGUnLFxuICAndHInLCAndScsICd1bCcsICd2YXInLCAndmlkZW8nLCAnYXJlYScsICdiYXNlJywgJ2JyJywgJ2NvbCcsICdjb21tYW5kJyxcbiAgJ2VtYmVkJywgJ2hyJywgJ2ltZycsICdpbnB1dCcsICdrZXlnZW4nLCAnbGluaycsICdtZXRhJywgJ3BhcmFtJywgJ3NvdXJjZScsXG4gICd0cmFjaycsICd3YnInXG5dXG5cbmZvciAoY29uc3QgdGFnTmFtZSBvZiBIVE1MX1RBR1MpIHtcbiAgZG9tW3RhZ05hbWVdID0gKHByb3BzLCAuLi5jaGlsZHJlbikgPT4ge1xuICAgIHJldHVybiBkb20odGFnTmFtZSwgcHJvcHMsIC4uLmNoaWxkcmVuKVxuICB9XG59XG5cbmZvciAoY29uc3QgdGFnTmFtZSBvZiBTVkdfVEFHUykge1xuICBkb21bdGFnTmFtZV0gPSAocHJvcHMsIC4uLmNoaWxkcmVuKSA9PiB7XG4gICAgcmV0dXJuIGRvbSh0YWdOYW1lLCBwcm9wcywgLi4uY2hpbGRyZW4pXG4gIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGRvbVxuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIG9uQ29weTogJ2NvcHknLFxuICBvbkN1dDogJ2N1dCcsXG4gIG9uUGFzdGU6ICdwYXN0ZScsXG4gIG9uQ29tcG9zaXRpb25FbmQ6ICdjb21wb3NpdGlvbmVuZCcsXG4gIG9uQ29tcG9zaXRpb25TdGFydDogJ2NvbXBvc2l0aW9uc3RhcnQnLFxuICBvbkNvbXBvc2l0aW9uVXBkYXRlOiAnY29tcG9zaXRpb251cGRhdGUnLFxuICBvbktleURvd246ICdrZXlkb3duJyxcbiAgb25LZXlQcmVzczogJ2tleXByZXNzJyxcbiAgb25LZXlVcDogJ2tleXVwJyxcbiAgb25Gb2N1czogJ2ZvY3VzJyxcbiAgb25CbHVyOiAnYmx1cicsXG4gIG9uQ2hhbmdlOiAnY2hhbmdlJyxcbiAgb25JbnB1dDogJ2lucHV0JyxcbiAgb25TdWJtaXQ6ICdzdWJtaXQnLFxuICBvbkNsaWNrOiAnY2xpY2snLFxuICBvbkNvbnRleHRNZW51OiAnY29udGV4dG1lbnUnLFxuICBvbkRvdWJsZUNsaWNrOiAnZG91YmxlY2xpY2snLFxuICBvbkRyYWc6ICdkcmFnJyxcbiAgb25EcmFnRW5kOiAnZHJhZ2VuZCcsXG4gIG9uRHJhZ0VudGVyOiAnZHJhZ2VudGVyJyxcbiAgb25EcmFnRXhpdDogJ2RyYWdleGl0JyxcbiAgb25EcmFnTGVhdmU6ICdkcmFnbGVhdmUnLFxuICBvbkRyYWdPdmVyOiAnZHJhZ292ZXInLFxuICBvbkRyYWdTdGFydDogJ2RyYWdzdGFydCcsXG4gIG9uRHJvcDogJ2Ryb3AnLFxuICBvbk1vdXNlRG93bjogJ21vdXNlZG93bicsXG4gIG9uTW91c2VFbnRlcjogJ21vdXNlbnRlcicsXG4gIG9uTW91c2VMZWF2ZTogJ21vdXNlbGVhdmUnLFxuICBvbk1vdXNlTW92ZTogJ21vdXNlbW92ZScsXG4gIG9uTW91c2VPdXQ6ICdtb3VzZW91dCcsXG4gIG9uTW91c2VPdmVyOiAnbW91c2VvdmVyJyxcbiAgb25Nb3VzZVVwOiAnbW91c2V1cCcsXG4gIG9uU2VsZWN0OiAnc2VsZWN0JyxcbiAgb25Ub3VjaENhbmNlbDogJ3RvdWNoY2FuY2VsJyxcbiAgb25Ub3VjaEVuZDogJ3RvdWNoZW5kJyxcbiAgb25Ub3VjaE1vdmU6ICd0b3VjaG1vdmUnLFxuICBvblRvdWNoU3RhcnQ6ICd0b3VjaHN0YXJ0JyxcbiAgb25TY3JvbGw6ICdzY3JvbGwnLFxuICBvbldoZWVsOiAnd2hlZWwnLFxuICBvbkFib3J0OiAnYWJvcnQnLFxuICBvbkNhblBsYXk6ICdjYW5wbGF5JyxcbiAgb25DYW5QbGF5VGhyb3VnaDogJ2NhbnBsYXl0aHJvdWdoJyxcbiAgb25EdXJhdGlvbkNoYW5nZTogJ2R1cmF0aW9uY2hhbmdlJyxcbiAgb25FbXB0aWVkOiAnZW1wdGllZCcsXG4gIG9uRW5jcnlwdGVkOiAnZW5jcnlwdGVkJyxcbiAgb25FbmRlZDogJ2VuZGVkJyxcbiAgb25FcnJvcjogJ2Vycm9yJyxcbiAgb25Mb2FkZWREYXRhOiAnbG9hZGVkZGF0YScsXG4gIG9uTG9hZGVkTWV0YWRhdGE6ICdsb2FkZWRtZXRhZGF0JyxcbiAgb25Mb2FkU3RhcnQ6ICdsb2Fkc3RhcnQnLFxuICBvblBhdXNlOiAncGF1c2UnLFxuICBvblBsYXk6ICdwbGF5JyxcbiAgb25QbGF5aW5nOiAncGxheWluZycsXG4gIG9uUHJvZ3Jlc3M6ICdwcm9ncmVzcycsXG4gIG9uUmF0ZUNoYW5nZTogJ3JhdGVjaGFuZ2UnLFxuICBvblNlZWtlZDogJ3NlZWtlZCcsXG4gIG9uU2Vla2luZzogJ3NlZWtpbmcnLFxuICBvblN0YWxsZWQ6ICdzdGFsbGVkJyxcbiAgb25TdXNwZW5kOiAnc3VzcGVuZCcsXG4gIG9uVGltZVVwZGF0ZTogJ3RpbWV1cGRhdGUnLFxuICBvblZvbHVtZUNoYW5nZTogJ3ZvbHVtZWNoYW5nZScsXG4gIG9uV2FpdGluZzogJ3dhaXRpbmcnLFxuICBvbkxvYWQ6ICdsb2FkJyxcbiAgb25FcnJvcjogJ2Vycm9yJyxcbiAgb25BbmltYXRpb25TdGFydDogJ2FuaW1hdGlvbnN0YXJ0JyxcbiAgb25BbmltYXRpb25FbmQ6ICdhbmltYXRpb25lbmQnLFxuICBvbkFuaW1hdGlvbkl0ZXJhdGlvbjogJ2FuaW1hdGlvbml0ZXJhdGlvbicsXG4gIG9uVHJhbnNpdGlvbkVuZDogJ3RyYW5zaXRpb25lbmQnXG59XG4iLCJjb25zdCByZW5kZXIgPSByZXF1aXJlKCcuL3JlbmRlcicpXG5jb25zdCB1cGRhdGVQcm9wcyA9IHJlcXVpcmUoJy4vdXBkYXRlLXByb3BzJylcblxuZnVuY3Rpb24gcGF0Y2ggKG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucykge1xuICBjb25zdCBvbGROb2RlID0gb2xkVmlydHVhbE5vZGUuZG9tTm9kZVxuICBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlKSkge1xuICAgIGxldCBuZXdOb2RlXG4gICAgaWYgKG5ld1ZpcnR1YWxOb2RlLnRleHQgIT0gbnVsbCkge1xuICAgICAgb2xkTm9kZS5ub2RlVmFsdWUgPSBuZXdWaXJ0dWFsTm9kZS50ZXh0XG4gICAgICBuZXdOb2RlID0gb2xkTm9kZVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5ld1ZpcnR1YWxOb2RlLnRhZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBuZXdOb2RlID0gdXBkYXRlQ29tcG9uZW50KG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVwZGF0ZUNoaWxkcmVuKG9sZE5vZGUsIG9sZFZpcnR1YWxOb2RlLmNoaWxkcmVuLCBuZXdWaXJ0dWFsTm9kZS5jaGlsZHJlbiwgb3B0aW9ucylcbiAgICAgICAgdXBkYXRlUHJvcHMob2xkTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKVxuICAgICAgICBuZXdOb2RlID0gb2xkTm9kZVxuICAgICAgfVxuICAgIH1cbiAgICBuZXdWaXJ0dWFsTm9kZS5kb21Ob2RlID0gbmV3Tm9kZVxuICAgIGlmIChuZXdOb2RlICE9PSBvbGROb2RlICYmIG9sZE5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgb2xkTm9kZS5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBvbGROb2RlKVxuICAgIH1cbiAgICByZXR1cm4gbmV3Tm9kZVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IHBhcmVudE5vZGUgPSBvbGROb2RlLnBhcmVudE5vZGVcbiAgICBjb25zdCBuZXh0U2libGluZyA9IG9sZE5vZGUubmV4dFNpYmxpbmdcbiAgICByZW1vdmVWaXJ0dWFsTm9kZShvbGRWaXJ0dWFsTm9kZSwgb3B0aW9ucyAmJiBvcHRpb25zLnJlZnMpXG4gICAgY29uc3QgbmV3Tm9kZSA9IHJlbmRlcihuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICBpZiAocGFyZW50Tm9kZSkgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobmV3Tm9kZSwgbmV4dFNpYmxpbmcpXG4gICAgbmV3VmlydHVhbE5vZGUuZG9tTm9kZSA9IG5ld05vZGVcbiAgICByZXR1cm4gbmV3Tm9kZVxuICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNvbXBvbmVudCAob2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKSB7XG4gIGNvbnN0IHtjb21wb25lbnQsIHByb3BzOiBvbGRQcm9wc30gPSBvbGRWaXJ0dWFsTm9kZVxuICBsZXQge3Byb3BzOiBuZXdQcm9wcywgY2hpbGRyZW46IG5ld0NoaWxkcmVufSA9IG5ld1ZpcnR1YWxOb2RlXG4gIG5ld1ZpcnR1YWxOb2RlLmNvbXBvbmVudCA9IGNvbXBvbmVudFxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnJlZnMpIHtcbiAgICBjb25zdCByZWZzID0gb3B0aW9ucy5yZWZzXG4gICAgY29uc3Qgb2xkUmVmTmFtZSA9IG9sZFByb3BzICYmIG9sZFByb3BzLnJlZlxuICAgIGNvbnN0IG5ld1JlZk5hbWUgPSBuZXdQcm9wcyAmJiBuZXdQcm9wcy5yZWZcbiAgICBpZiAobmV3UmVmTmFtZSAhPT0gb2xkUmVmTmFtZSkge1xuICAgICAgaWYgKG9sZFJlZk5hbWUgJiYgcmVmc1tvbGRSZWZOYW1lXSA9PT0gY29tcG9uZW50KSBkZWxldGUgcmVmc1tvbGRSZWZOYW1lXVxuICAgICAgaWYgKG5ld1JlZk5hbWUpIHJlZnNbbmV3UmVmTmFtZV0gPSBjb21wb25lbnRcbiAgICB9XG4gIH1cbiAgY29tcG9uZW50LnVwZGF0ZShuZXdQcm9wcyB8fCB7fSwgbmV3Q2hpbGRyZW4pXG4gIHJldHVybiBjb21wb25lbnQuZWxlbWVudFxufVxuXG5mdW5jdGlvbiB1cGRhdGVDaGlsZHJlbiAocGFyZW50RWxlbWVudCwgb2xkQ2hpbGRyZW4sIG5ld0NoaWxkcmVuLCBvcHRpb25zKSB7XG4gIGxldCBvbGRTdGFydEluZGV4ID0gMFxuICBsZXQgb2xkRW5kSW5kZXggPSBvbGRDaGlsZHJlbi5sZW5ndGggLSAxXG4gIGxldCBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bMF1cbiAgbGV0IG9sZEVuZENoaWxkID0gb2xkQ2hpbGRyZW5bb2xkRW5kSW5kZXhdXG5cbiAgbGV0IG5ld1N0YXJ0SW5kZXggPSAwXG4gIGxldCBuZXdFbmRJbmRleCA9IG5ld0NoaWxkcmVuLmxlbmd0aCAtIDFcbiAgbGV0IG5ld1N0YXJ0Q2hpbGQgPSBuZXdDaGlsZHJlblswXVxuICBsZXQgbmV3RW5kQ2hpbGQgPSBuZXdDaGlsZHJlbltuZXdFbmRJbmRleF1cblxuICBsZXQgb2xkSW5kaWNlc0J5S2V5XG5cbiAgd2hpbGUgKG9sZFN0YXJ0SW5kZXggPD0gb2xkRW5kSW5kZXggJiYgbmV3U3RhcnRJbmRleCA8PSBuZXdFbmRJbmRleCkge1xuICAgIGlmICghb2xkU3RhcnRDaGlsZCkge1xuICAgICAgb2xkU3RhcnRDaGlsZCA9IG9sZENoaWxkcmVuWysrb2xkU3RhcnRJbmRleF1cbiAgICB9IGVsc2UgaWYgKCFvbGRFbmRDaGlsZCkge1xuICAgICAgb2xkRW5kQ2hpbGQgPSBvbGRDaGlsZHJlblstLW9sZEVuZEluZGV4XVxuICAgIH0gZWxzZSBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkU3RhcnRDaGlsZCwgbmV3U3RhcnRDaGlsZCkpIHtcbiAgICAgIHBhdGNoKG9sZFN0YXJ0Q2hpbGQsIG5ld1N0YXJ0Q2hpbGQsIG9wdGlvbnMpXG4gICAgICBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bKytvbGRTdGFydEluZGV4XVxuICAgICAgbmV3U3RhcnRDaGlsZCA9IG5ld0NoaWxkcmVuWysrbmV3U3RhcnRJbmRleF1cbiAgICB9IGVsc2UgaWYgKHZpcnR1YWxOb2Rlc0FyZUVxdWFsKG9sZEVuZENoaWxkLCBuZXdFbmRDaGlsZCkpIHtcbiAgICAgIHBhdGNoKG9sZEVuZENoaWxkLCBuZXdFbmRDaGlsZCwgb3B0aW9ucylcbiAgICAgIG9sZEVuZENoaWxkID0gb2xkQ2hpbGRyZW5bLS1vbGRFbmRJbmRleF1cbiAgICAgIG5ld0VuZENoaWxkID0gbmV3Q2hpbGRyZW5bLS1uZXdFbmRJbmRleF1cbiAgICB9IGVsc2UgaWYgKHZpcnR1YWxOb2Rlc0FyZUVxdWFsKG9sZFN0YXJ0Q2hpbGQsIG5ld0VuZENoaWxkKSkge1xuICAgICAgcGF0Y2gob2xkU3RhcnRDaGlsZCwgbmV3RW5kQ2hpbGQsIG9wdGlvbnMpXG4gICAgICBwYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZShvbGRTdGFydENoaWxkLmRvbU5vZGUsIG9sZEVuZENoaWxkLmRvbU5vZGUubmV4dFNpYmxpbmcpXG4gICAgICBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bKytvbGRTdGFydEluZGV4XVxuICAgICAgbmV3RW5kQ2hpbGQgPSBuZXdDaGlsZHJlblstLW5ld0VuZEluZGV4XVxuICAgIH0gZWxzZSBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkRW5kQ2hpbGQsIG5ld1N0YXJ0Q2hpbGQpKSB7XG4gICAgICBwYXRjaChvbGRFbmRDaGlsZCwgbmV3U3RhcnRDaGlsZCwgb3B0aW9ucylcbiAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG9sZEVuZENoaWxkLmRvbU5vZGUsIG9sZFN0YXJ0Q2hpbGQuZG9tTm9kZSk7XG4gICAgICBvbGRFbmRDaGlsZCA9IG9sZENoaWxkcmVuWy0tb2xkRW5kSW5kZXhdXG4gICAgICBuZXdTdGFydENoaWxkID0gbmV3Q2hpbGRyZW5bKytuZXdTdGFydEluZGV4XVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIW9sZEluZGljZXNCeUtleSkgb2xkSW5kaWNlc0J5S2V5ID0gbWFwT2xkS2V5c1RvSW5kaWNlcyhvbGRDaGlsZHJlbiwgb2xkU3RhcnRJbmRleCwgb2xkRW5kSW5kZXgpXG4gICAgICBjb25zdCBrZXkgPSBnZXRLZXkobmV3U3RhcnRDaGlsZClcbiAgICAgIGNvbnN0IG9sZEluZGV4ID0ga2V5ID8gb2xkSW5kaWNlc0J5S2V5LmdldChrZXkpIDogbnVsbFxuICAgICAgaWYgKG9sZEluZGV4ID09IG51bGwpIHtcbiAgICAgICAgcGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUocmVuZGVyKG5ld1N0YXJ0Q2hpbGQsIG9wdGlvbnMpLCBvbGRTdGFydENoaWxkLmRvbU5vZGUpXG4gICAgICAgIG5ld1N0YXJ0Q2hpbGQgPSBuZXdDaGlsZHJlblsrK25ld1N0YXJ0SW5kZXhdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBvbGRDaGlsZFRvTW92ZSA9IG9sZENoaWxkcmVuW29sZEluZGV4XVxuICAgICAgICBwYXRjaChvbGRDaGlsZFRvTW92ZSwgbmV3U3RhcnRDaGlsZCwgb3B0aW9ucylcbiAgICAgICAgb2xkQ2hpbGRyZW5bb2xkSW5kZXhdID0gdW5kZWZpbmVkXG4gICAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG9sZENoaWxkVG9Nb3ZlLmRvbU5vZGUsIG9sZFN0YXJ0Q2hpbGQuZG9tTm9kZSlcbiAgICAgICAgbmV3U3RhcnRDaGlsZCA9IG5ld0NoaWxkcmVuWysrbmV3U3RhcnRJbmRleF1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAob2xkU3RhcnRJbmRleCA+IG9sZEVuZEluZGV4KSB7XG4gICAgY29uc3Qgc3Vic2VxdWVudEVsZW1lbnQgPSBuZXdDaGlsZHJlbltuZXdFbmRJbmRleCArIDFdID8gbmV3Q2hpbGRyZW5bbmV3RW5kSW5kZXggKyAxXS5kb21Ob2RlIDogbnVsbFxuICAgIGZvciAobGV0IGkgPSBuZXdTdGFydEluZGV4OyBpIDw9IG5ld0VuZEluZGV4OyBpKyspIHtcbiAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKHJlbmRlcihuZXdDaGlsZHJlbltpXSwgb3B0aW9ucyksIHN1YnNlcXVlbnRFbGVtZW50KVxuICAgIH1cbiAgfSBlbHNlIGlmIChuZXdTdGFydEluZGV4ID4gbmV3RW5kSW5kZXgpIHtcbiAgICBmb3IgKGxldCBpID0gb2xkU3RhcnRJbmRleDsgaSA8PSBvbGRFbmRJbmRleDsgaSsrKSB7XG4gICAgICBjb25zdCBjaGlsZCA9IG9sZENoaWxkcmVuW2ldXG4gICAgICBpZiAoY2hpbGQpIHJlbW92ZVZpcnR1YWxOb2RlKGNoaWxkLCBvcHRpb25zICYmIG9wdGlvbnMucmVmcylcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlVmlydHVhbE5vZGUgKHZpcnR1YWxOb2RlLCByZWZzLCByZW1vdmVET01Ob2RlID0gdHJ1ZSkge1xuICBjb25zdCB7ZG9tTm9kZSwgcHJvcHMsIGNoaWxkcmVuLCBjb21wb25lbnR9ID0gdmlydHVhbE5vZGVcbiAgY29uc3QgcmVmID0gcHJvcHMgJiYgcHJvcHMucmVmXG4gIGlmIChjb21wb25lbnQpIHtcbiAgICBpZiAocmVmcyAmJiByZWYgJiYgcmVmc1tyZWZdID09PSBjb21wb25lbnQpIGRlbGV0ZSByZWZzW3JlZl1cbiAgICBpZiAodHlwZW9mIGNvbXBvbmVudC5kZXN0cm95ID09PSAnZnVuY3Rpb24nKSBjb21wb25lbnQuZGVzdHJveSgpXG4gIH0gZWxzZSB7XG4gICAgaWYgKHJlZnMgJiYgcmVmICYmIHJlZnNbcmVmXSA9PT0gZG9tTm9kZSkgZGVsZXRlIHJlZnNbcmVmXVxuICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICByZW1vdmVWaXJ0dWFsTm9kZShjaGlsZHJlbltpXSwgcmVmcywgZmFsc2UpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlbW92ZURPTU5vZGUpIGRvbU5vZGUucmVtb3ZlKClcbn1cblxuZnVuY3Rpb24gdmlydHVhbE5vZGVzQXJlRXF1YWwgKG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSkge1xuICByZXR1cm4gKFxuICAgIGdldEtleShvbGRWaXJ0dWFsTm9kZSkgPT09IGdldEtleShuZXdWaXJ0dWFsTm9kZSlcbiAgICAgICYmIG9sZFZpcnR1YWxOb2RlLnRhZyA9PT0gbmV3VmlydHVhbE5vZGUudGFnXG4gIClcbn1cblxuZnVuY3Rpb24gZ2V0S2V5ICh2aXJ0dWFsTm9kZSkge1xuICByZXR1cm4gdmlydHVhbE5vZGUucHJvcHMgPyB2aXJ0dWFsTm9kZS5wcm9wcy5rZXkgOiB1bmRlZmluZWRcbn1cblxuZnVuY3Rpb24gbWFwT2xkS2V5c1RvSW5kaWNlcyAoY2hpbGRyZW4sIHN0YXJ0SW5kZXgsIGVuZEluZGV4KSB7XG4gIGxldCBvbGRJbmRpY2VzQnlLZXkgPSBuZXcgTWFwKClcbiAgZm9yIChsZXQgaSA9IHN0YXJ0SW5kZXg7IGkgPD0gZW5kSW5kZXg7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IGdldEtleShjaGlsZHJlbltpXSlcbiAgICBpZiAoa2V5KSBvbGRJbmRpY2VzQnlLZXkuc2V0KGtleSwgaSlcbiAgfVxuICByZXR1cm4gb2xkSW5kaWNlc0J5S2V5XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcGF0Y2hcbiIsImNvbnN0IHVwZGF0ZVByb3BzID0gcmVxdWlyZSgnLi91cGRhdGUtcHJvcHMnKVxuY29uc3QgU1ZHX1RBR1MgPSByZXF1aXJlKCcuL3N2Zy10YWdzJylcblxuZnVuY3Rpb24gcmVuZGVyICh2aXJ0dWFsTm9kZSwgb3B0aW9ucykge1xuICBsZXQgZG9tTm9kZVxuICBpZiAodmlydHVhbE5vZGUudGV4dCAhPSBudWxsKSB7XG4gICAgZG9tTm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHZpcnR1YWxOb2RlLnRleHQpXG4gIH0gZWxzZSB7XG4gICAgY29uc3Qge3RhZywgY2hpbGRyZW59ID0gdmlydHVhbE5vZGVcbiAgICBsZXQge3Byb3BzfSA9IHZpcnR1YWxOb2RlXG5cbiAgICBpZiAodHlwZW9mIHRhZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbGV0IHJlZlxuICAgICAgaWYgKHByb3BzICYmIHByb3BzLnJlZikge1xuICAgICAgICByZWYgPSBwcm9wcy5yZWZcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbXBvbmVudCA9IG5ldyB0YWcocHJvcHMgfHwge30sIGNoaWxkcmVuKVxuICAgICAgdmlydHVhbE5vZGUuY29tcG9uZW50ID0gY29tcG9uZW50XG4gICAgICBkb21Ob2RlID0gY29tcG9uZW50LmVsZW1lbnRcbiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMucmVmcyAmJiByZWYpIHtcbiAgICAgICAgb3B0aW9ucy5yZWZzW3JlZl0gPSBjb21wb25lbnRcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKFNWR19UQUdTLmhhcyh0YWcpKSB7XG4gICAgICBkb21Ob2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKTtcbiAgICAgIGlmIChjaGlsZHJlbikgYWRkQ2hpbGRyZW4oZG9tTm9kZSwgY2hpbGRyZW4sIG9wdGlvbnMpXG4gICAgICBpZiAocHJvcHMpIHVwZGF0ZVByb3BzKGRvbU5vZGUsIG51bGwsIHZpcnR1YWxOb2RlLCBvcHRpb25zKVxuICAgIH0gZWxzZSB7XG4gICAgICBkb21Ob2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWcpXG4gICAgICBpZiAoY2hpbGRyZW4pIGFkZENoaWxkcmVuKGRvbU5vZGUsIGNoaWxkcmVuLCBvcHRpb25zKVxuICAgICAgaWYgKHByb3BzKSB1cGRhdGVQcm9wcyhkb21Ob2RlLCBudWxsLCB2aXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICB9XG4gIH1cbiAgdmlydHVhbE5vZGUuZG9tTm9kZSA9IGRvbU5vZGVcbiAgcmV0dXJuIGRvbU5vZGVcbn1cblxuZnVuY3Rpb24gYWRkQ2hpbGRyZW4gKHBhcmVudCwgY2hpbGRyZW4sIG9wdGlvbnMpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgIHBhcmVudC5hcHBlbmRDaGlsZChyZW5kZXIoY2hpbGRyZW5baV0sIG9wdGlvbnMpKVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcmVuZGVyXG4iLCIvLyBUaGlzIGZpbGUgaW1wbGVtZW50cyBnZXR0ZXIgYW5kIHNldHRlciBmdW5jdGlvbnMgZm9yIGEgc2NoZWR1bGVyIHRvIGJlIHVzZWRcbi8vIGJ5IHRoaXMgbGlicmFyeSB3aGVuIHVwZGF0aW5nIHRoZSBET00uIFRoZSBzY2hlZHVsZXIncyBqb2IgaXMgdG8gZW5zdXJlIHRoYXRcbi8vIERPTSBpbnRlcmFjdGlvbiBpcyBwZXJmb3JtZWQgZWZmaWNpZW50bHkuIFdoZW4gdXNpbmcgYGV0Y2hgIGluIEF0b20sIHlvdVxuLy8gc2hvdWxkIHRlbGwgYGV0Y2hgIHRvIHVzZSBBdG9tJ3Mgc2NoZWR1bGVyIGJ5IGNhbGxpbmdcbi8vIGBzZXRTY2hlZHVsZXIoYXRvbS52aWV3cylgLlxuLy9cbi8vIFNjaGVkdWxlcnMgc2hvdWxkIHN1cHBvcnQgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2U6XG4vLyAqIGB1cGRhdGVEb2N1bWVudChmbilgIFRoaXMgbWV0aG9kIGlzIGFzeW5jaHJvbm91cy4gSXQgZW5xdWV1ZXMgZnVuY3Rpb25zIHRvXG4vLyBiZSBleGVjdXRlZCBsYXRlci5cbi8vICogYGdldE5leHRVcGRhdGVQcm9taXNlKClgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIHByb21pc2UgdGhhdFxuLy8gcmVzb2x2ZXMgYWZ0ZXIgYWxsIHBlbmRpbmcgZG9jdW1lbnQgdXBkYXRlIGZ1bmN0aW9ucyBoYXZlIGJlZW4gaW52b2tlZC5cbi8vXG4vLyBTY2hlZHVsZXJzIGNvdWxkIHN1cHBvcnQgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBtZXRob2RzLCB3aGljaCBhcmUgc3VwcG9ydGVkXG4vLyBieSBBdG9tJ3Mgc2NoZWR1bGVyLlxuLy9cbi8vICogYHJlYWREb2N1bWVudGAgVGhpcyBtZXRob2QgY2FuIGJlIGludm9rZWQgYnkgY2xpZW50cyBvdGhlciB0aGFuIGBldGNoYCB3aGVuXG4vLyBpdCBpcyBuZWNlc3NhcnkgdG8gcmVhZCBmcm9tIHRoZSBET00uIEZ1bmN0aW9ucyBlbnF1ZXVlZCB2aWEgdGhpcyBtZXRob2Rcbi8vIHNob3VsZCBub3QgYmUgcnVuIHVudGlsIGFsbCBkb2N1bWVudCB1cGRhdGUgZnVuY3Rpb25zIGhhdmUgYmVlbiBleGVjdXRlZC5cbi8vIEJhdGNoaW5nIHVwZGF0ZXMgYW5kIHJlYWRzIGluIHRoaXMgd2F5IHdpbGwgcHJldmVudCBmb3JjZWQgc3luY2hyb25vdXNcbi8vIHJlZmxvd3MuXG4vLyAqIGBwb2xsRG9jdW1lbnRgIFRoaXMgbWV0aG9kIGlzIHNpbWlsYXIgdG8gYHJlYWREb2N1bWVudGAsIGJ1dCBpdCBydW5zIHRoZVxuLy8gYXNzb2NpYXRlZCBmdW5jdGlvbnMgcmVwZWF0ZWRseS4gQWdhaW4sIHRoZXkgc2hvdWxkIGJlIHNjaGVkdWxlZCBpbiBzdWNoIGFcbi8vIHdheSBzbyBhcyB0byBhdm9pZCBzeW5jaHJvbm91cyByZWZsb3dzLlxuXG5jb25zdCBEZWZhdWx0U2NoZWR1bGVyID0gcmVxdWlyZSgnLi9kZWZhdWx0LXNjaGVkdWxlcicpXG5cbmxldCBzY2hlZHVsZXIgPSBudWxsXG5cbm1vZHVsZS5leHBvcnRzLnNldFNjaGVkdWxlciA9IGZ1bmN0aW9uIHNldFNjaGVkdWxlciAoY3VzdG9tU2NoZWR1bGVyKSB7XG4gIHNjaGVkdWxlciA9IGN1c3RvbVNjaGVkdWxlclxufVxuXG5tb2R1bGUuZXhwb3J0cy5nZXRTY2hlZHVsZXIgPSBmdW5jdGlvbiBnZXRTY2hlZHVsZXIgKCkge1xuICBpZiAoIXNjaGVkdWxlcikge1xuICAgIHNjaGVkdWxlciA9IG5ldyBEZWZhdWx0U2NoZWR1bGVyKClcbiAgfVxuICByZXR1cm4gc2NoZWR1bGVyXG59XG4iLCIvLyBCYXNlZCBvbiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBNYXAoW1xuICBbJ2FjY2VudEhlaWdodCcsICdhY2NlbnQtaGVpZ2h0J10sXG4gIFsnYWxpZ25tZW50QmFzZWxpbmUnLCAnYWxpZ25tZW50LWJhc2VsaW5lJ10sXG4gIFsnYXJhYmljRm9ybScsICdhcmFiaWMtZm9ybSddLFxuICBbJ2Jhc2VsaW5lU2hpZnQnLCAnYmFzZWxpbmUtc2hpZnQnXSxcbiAgWydjYXBIZWlnaHQnLCAnY2FwLWhlaWdodCddLFxuICBbJ2NsYXNzTmFtZScsICdjbGFzcyddLFxuICBbJ2NsaXBQYXRoJywgJ2NsaXAtcGF0aCddLFxuICBbJ2NsaXBSdWxlJywgJ2NsaXAtcnVsZSddLFxuICBbJ2NvbG9ySW50ZXJwb2xhdGlvbicsICdjb2xvci1pbnRlcnBvbGF0aW9uJ10sXG4gIFsnY29sb3JJbnRlcnBvbGF0aW9uRmlsdGVycycsICdjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnMnXSxcbiAgWydjb2xvclByb2ZpbGUnLCAnY29sb3ItcHJvZmlsZSddLFxuICBbJ2NvbG9yUmVuZGVyaW5nJywgJ2NvbG9yLXJlbmRlcmluZyddLFxuICBbJ2RvbWluYW50QmFzZWxpbmUnLCAnZG9taW5hbnQtYmFzZWxpbmUnXSxcbiAgWydlbmFibGVCYWNrZ3JvdW5kJywgJ2VuYWJsZS1iYWNrZ3JvdW5kJ10sXG4gIFsnZmlsbE9wYWNpdHknLCAnZmlsbC1vcGFjaXR5J10sXG4gIFsnZmlsbFJ1bGUnLCAnZmlsbC1ydWxlJ10sXG4gIFsnZmxvb2RDb2xvcicsICdmbG9vZC1jb2xvciddLFxuICBbJ2Zsb29kT3BhY2l0eScsICdmbG9vZC1vcGFjaXR5J10sXG4gIFsnZm9udEZhbWlseScsICdmb250LWZhbWlseSddLFxuICBbJ2ZvbnRTaXplJywgJ2ZvbnQtc2l6ZSddLFxuICBbJ2ZvbnRTaXplQWRqdXN0JywgJ2ZvbnQtc2l6ZS1hZGp1c3QnXSxcbiAgWydmb250U3RyZXRjaCcsICdmb250LXN0cmV0Y2gnXSxcbiAgWydmb250U3R5bGUnLCAnZm9udC1zdHlsZSddLFxuICBbJ2ZvbnRWYXJpYW50JywgJ2ZvbnQtdmFyaWFudCddLFxuICBbJ2ZvbnRXZWlnaHQnLCAnZm9udC13ZWlnaHQnXSxcbiAgWydnbHlwaE5hbWUnLCAnZ2x5cGgtbmFtZSddLFxuICBbJ2dseXBoT3JpZW50YXRpb25Ib3Jpem9udGFsJywgJ2dseXBoLW9yaWVudGF0aW9uLWhvcml6b250YWwnXSxcbiAgWydnbHlwaE9yaWVudGF0aW9uVmVydGljYWwnLCAnZ2x5cGgtb3JpZW50YXRpb24tdmVydGljYWwnXSxcbiAgWydob3JpekFkdlgnLCAnaG9yaXotYWR2LXgnXSxcbiAgWydob3Jpek9yaWdpblgnLCAnaG9yaXotb3JpZ2luLXgnXSxcbiAgWydsZXR0ZXJTcGFjaW5nJywgJ2xldHRlci1zcGFjaW5nJ10sXG4gIFsnbGlnaHRpbmdDb2xvcicsICdsaWdodGluZy1jb2xvciddLFxuICBbJ21hcmtlckVuZCcsICdtYXJrZXItZW5kJ10sXG4gIFsnbWFya2VyTWlkJywgJ21hcmtlci1taWQnXSxcbiAgWydtYXJrZXJTdGFydCcsICdtYXJrZXItc3RhcnQnXSxcbiAgWydvdmVybGluZVBvc2l0aW9uJywgJ292ZXJsaW5lLXBvc2l0aW9uJ10sXG4gIFsnb3ZlcmxpbmVUaGlja25lc3MnLCAnb3ZlcmxpbmUtdGhpY2tuZXNzJ10sXG4gIFsncGFub3NlMScsICdwYW5vc2UtMSddLFxuICBbJ3BhaW50T3JkZXInLCAncGFpbnQtb3JkZXInXSxcbiAgWydwb2ludGVyRXZlbnRzJywgJ3BvaW50ZXItZXZlbnRzJ10sXG4gIFsncmVuZGVyaW5nSW50ZW50JywgJ3JlbmRlcmluZy1pbnRlbnQnXSxcbiAgWydzaGFwZVJlbmRlcmluZycsICdzaGFwZS1yZW5kZXJpbmcnXSxcbiAgWydzdG9wQ29sb3InLCAnc3RvcC1jb2xvciddLFxuICBbJ3N0b3BPcGFjaXR5JywgJ3N0b3Atb3BhY2l0eSddLFxuICBbJ3N0cmlrZXRocm91Z2hQb3NpdGlvbicsICdzdHJpa2V0aHJvdWdoLXBvc2l0aW9uJ10sXG4gIFsnc3RyaWtldGhyb3VnaFRoaWNrbmVzcycsICdzdHJpa2V0aHJvdWdoLXRoaWNrbmVzcyddLFxuICBbJ3N0cm9rZURhc2hhcnJheScsICdzdHJva2UtZGFzaGFycmF5J10sXG4gIFsnc3Ryb2tlRGFzaG9mZnNldCcsICdzdHJva2UtZGFzaG9mZnNldCddLFxuICBbJ3N0cm9rZUxpbmVjYXAnLCAnc3Ryb2tlLWxpbmVjYXAnXSxcbiAgWydzdHJva2VMaW5lam9pbicsICdzdHJva2UtbGluZWpvaW4nXSxcbiAgWydzdHJva2VNaXRlcmxpbWl0JywgJ3N0cm9rZS1taXRlcmxpbWl0J10sXG4gIFsnc3Ryb2tlT3BhY2l0eScsICdzdHJva2Utb3BhY2l0eSddLFxuICBbJ3N0cm9rZVdpZHRoJywgJ3N0cm9rZS13aWR0aCddLFxuICBbJ3RleHRBbmNob3InLCAndGV4dC1hbmNob3InXSxcbiAgWyd0ZXh0RGVjb3JhdGlvbicsICd0ZXh0LWRlY29yYXRpb24nXSxcbiAgWyd0ZXh0UmVuZGVyaW5nJywgJ3RleHQtcmVuZGVyaW5nJ10sXG4gIFsndW5kZXJsaW5lUG9zaXRpb24nLCAndW5kZXJsaW5lLXBvc2l0aW9uJ10sXG4gIFsndW5kZXJsaW5lVGhpY2tuZXNzJywgJ3VuZGVybGluZS10aGlja25lc3MnXSxcbiAgWyd1bmljb2RlQmlkaScsICd1bmljb2RlLWJpZGknXSxcbiAgWyd1bmljb2RlUmFuZ2UnLCAndW5pY29kZS1yYW5nZSddLFxuICBbJ3VuaXRzUGVyRW0nLCAndW5pdHMtcGVyLWVtJ10sXG4gIFsndkFscGhhYmV0aWMnLCAndi1hbHBoYWJldGljJ10sXG4gIFsndkhhbmdpbmcnLCAndi1oYW5naW5nJ10sXG4gIFsndklkZW9ncmFwaGljJywgJ3YtaWRlb2dyYXBoaWMnXSxcbiAgWyd2TWF0aGVtYXRpY2FsJywgJ3YtbWF0aGVtYXRpY2FsJ10sXG4gIFsndmVydEFkdlknLCAndmVydC1hZHYteSddLFxuICBbJ3ZlcnRPcmlnaW5YJywgJ3ZlcnQtb3JpZ2luLXgnXSxcbiAgWyd2ZXJ0T3JpZ2luWScsICd2ZXJ0LW9yaWdpbi15J10sXG4gIFsnd29yZFNwYWNpbmcnLCAnd29yZC1zcGFjaW5nJ10sXG4gIFsnd3JpdGluZ01vZGUnLCAnd3JpdGluZy1tb2RlJ10sXG4gIFsneEhlaWdodCcsICd4LWhlaWdodCddLFxuXSlcbiIsIi8vIHRha2VuIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlYWN0L2Jsb2IvNjdmODUyNGU4OGFiYmYxYWMwZmQ4NmQzOGEwNDc3ZDExZmJjN2IzZS9zcmMvaXNvbW9ycGhpYy9jbGFzc2ljL2VsZW1lbnQvUmVhY3RET01GYWN0b3JpZXMuanMjTDE1M1xubW9kdWxlLmV4cG9ydHMgPSBuZXcgU2V0KFtcbiAgJ2NpcmNsZScsXG4gICdjbGlwUGF0aCcsXG4gICdkZWZzJyxcbiAgJ2VsbGlwc2UnLFxuICAnZycsXG4gICdpbWFnZScsXG4gICdsaW5lJyxcbiAgJ2xpbmVhckdyYWRpZW50JyxcbiAgJ21hc2snLFxuICAncGF0aCcsXG4gICdwYXR0ZXJuJyxcbiAgJ3BvbHlnb24nLFxuICAncG9seWxpbmUnLFxuICAncmFkaWFsR3JhZGllbnQnLFxuICAncmVjdCcsXG4gICdzdG9wJyxcbiAgJ3N2ZycsXG4gICd0ZXh0JyxcbiAgJ3RzcGFuJ1xuXSlcbiIsImNvbnN0IEVWRU5UX0xJU1RFTkVSX1BST1BTID0gcmVxdWlyZSgnLi9ldmVudC1saXN0ZW5lci1wcm9wcycpXG5jb25zdCBTVkdfVEFHUyA9IHJlcXVpcmUoJy4vc3ZnLXRhZ3MnKVxuY29uc3QgU1ZHX0FUVFJJQlVURV9UUkFOU0xBVElPTlMgPSByZXF1aXJlKCcuL3N2Zy1hdHRyaWJ1dGUtdHJhbnNsYXRpb25zJylcbmNvbnN0IEVNUFRZID0gJydcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKSB7XG4gIGNvbnN0IG9sZFByb3BzID0gb2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUucHJvcHNcbiAgY29uc3QgbmV3UHJvcHMgPSBuZXdWaXJ0dWFsTm9kZS5wcm9wc1xuXG4gIGxldCByZWZzLCBsaXN0ZW5lckNvbnRleHRcbiAgaWYgKG9wdGlvbnMpIHtcbiAgICByZWZzID0gb3B0aW9ucy5yZWZzXG4gICAgbGlzdGVuZXJDb250ZXh0ID0gb3B0aW9ucy5saXN0ZW5lckNvbnRleHRcbiAgfVxuICB1cGRhdGVQcm9wcyhkb21Ob2RlLCBvbGRWaXJ0dWFsTm9kZSwgb2xkUHJvcHMsIG5ld1ZpcnR1YWxOb2RlLCBuZXdQcm9wcylcbiAgaWYgKHJlZnMpIHVwZGF0ZVJlZihkb21Ob2RlLCBvbGRQcm9wcyAmJiBvbGRQcm9wcy5yZWYsIG5ld1Byb3BzICYmIG5ld1Byb3BzLnJlZiwgcmVmcylcbiAgdXBkYXRlRXZlbnRMaXN0ZW5lcnMoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBsaXN0ZW5lckNvbnRleHQpXG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb3BzIChkb21Ob2RlLCBvbGRWaXJ0dWFsTm9kZSwgb2xkUHJvcHMsIG5ld1ZpcnR1YWxOb2RlLCBuZXdQcm9wcykge1xuICBpZiAob2xkUHJvcHMpIHtcbiAgICBjb25zdCBvbGRQcm9wc05hbWVzID0gT2JqZWN0LmtleXMob2xkUHJvcHMpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRQcm9wc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBuYW1lID0gb2xkUHJvcHNOYW1lc1tpXVxuICAgICAgaWYgKG5hbWUgPT09ICdyZWYnIHx8IG5hbWUgPT09ICdvbicpIGNvbnRpbnVlXG4gICAgICBpZiAobmFtZSBpbiBFVkVOVF9MSVNURU5FUl9QUk9QUykgY29udGludWVcbiAgICAgIGlmICghbmV3UHJvcHMgfHwgIShuYW1lIGluIG5ld1Byb3BzKSkge1xuICAgICAgICBpZiAobmFtZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgICAgdXBkYXRlUHJvcHMoZG9tTm9kZS5kYXRhc2V0LCBudWxsLCBvbGRQcm9wcyAmJiBvbGRQcm9wcy5kYXRhc2V0LCBudWxsLCBudWxsKVxuICAgICAgICB9IGVsc2UgaWYgKG5hbWUgIT09ICdpbm5lckhUTUwnICYmIG9sZFZpcnR1YWxOb2RlICYmIFNWR19UQUdTLmhhcyhvbGRWaXJ0dWFsTm9kZS50YWcpKSB7XG4gICAgICAgICAgZG9tTm9kZS5yZW1vdmVBdHRyaWJ1dGUoU1ZHX0FUVFJJQlVURV9UUkFOU0xBVElPTlMuZ2V0KG5hbWUpIHx8IG5hbWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gQ2xlYXIgcHJvcGVydHkgZm9yIG9iamVjdHMgdGhhdCBkb24ndCBzdXBwb3J0IGRlbGV0aW9uIChlLmcuIHN0eWxlXG4gICAgICAgICAgLy8gb3IgY2xhc3NOYW1lKS4gSWYgd2UgdXNlZCBudWxsIGluc3RlYWQgb2YgYW4gZW1wdHkgc3RyaW5nLCB0aGUgRE9NXG4gICAgICAgICAgLy8gY291bGQgc29tZXRpbWVzIHN0cmluZ2lmeSB0aGUgdmFsdWUgYW5kIG1pc3Rha2VubHkgYXNzaWduICdudWxsJy5cbiAgICAgICAgICBkb21Ob2RlW25hbWVdID0gRU1QVFlcbiAgICAgICAgICBkZWxldGUgZG9tTm9kZVtuYW1lXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld1Byb3BzKSB7XG4gICAgY29uc3QgbmV3UHJvcHNOYW1lcyA9IE9iamVjdC5rZXlzKG5ld1Byb3BzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3UHJvcHNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbmFtZSA9IG5ld1Byb3BzTmFtZXNbaV1cbiAgICAgIGlmIChuYW1lID09PSAncmVmJyB8fCBuYW1lID09PSAnb24nKSBjb250aW51ZVxuICAgICAgaWYgKG5hbWUgaW4gRVZFTlRfTElTVEVORVJfUFJPUFMpIGNvbnRpbnVlXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IG9sZFByb3BzICYmIG9sZFByb3BzW25hbWVdXG4gICAgICBjb25zdCBuZXdWYWx1ZSA9IG5ld1Byb3BzW25hbWVdXG4gICAgICBpZiAobmFtZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgIHVwZGF0ZU5lc3RlZFByb3BzKGRvbU5vZGUuZGF0YXNldCwgb2xkVmFsdWUsIG5ld1ZhbHVlLCBmYWxzZSlcbiAgICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3N0eWxlJyAmJiB0eXBlb2YgbmV3VmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxldCBvbGRQcm9wcyA9IG9sZFZhbHVlXG4gICAgICAgIGlmICh0eXBlb2Ygb2xkUHJvcHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZG9tTm9kZS5zdHlsZSA9ICcnXG4gICAgICAgICAgb2xkUHJvcHMgPSBudWxsXG4gICAgICAgIH1cbiAgICAgICAgdXBkYXRlTmVzdGVkUHJvcHMoZG9tTm9kZS5zdHlsZSwgb2xkUHJvcHMsIG5ld1ZhbHVlLCB0cnVlKVxuICAgICAgfSBlbHNlIGlmIChuYW1lID09PSAnYXR0cmlidXRlcycpIHtcbiAgICAgICAgdXBkYXRlQXR0cmlidXRlcyhkb21Ob2RlLCBvbGRWYWx1ZSwgbmV3VmFsdWUpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobmV3VmFsdWUgIT09IG9sZFZhbHVlKSB7XG4gICAgICAgICAgaWYgKG5hbWUgIT09ICdpbm5lckhUTUwnICYmIG5ld1ZpcnR1YWxOb2RlICYmIFNWR19UQUdTLmhhcyhuZXdWaXJ0dWFsTm9kZS50YWcpKSB7XG4gICAgICAgICAgICBkb21Ob2RlLnNldEF0dHJpYnV0ZShTVkdfQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5nZXQobmFtZSkgfHwgbmFtZSwgbmV3VmFsdWUpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvbU5vZGVbbmFtZV0gPSBuZXdWYWx1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVOZXN0ZWRQcm9wcyAoZG9tUHJvcHMsIG9sZFByb3BzLCBuZXdQcm9wcywgaXNTdHlsZU9iamVjdCkge1xuICBpZiAob2xkUHJvcHMpIHtcbiAgICBjb25zdCBvbGRQcm9wc05hbWVzID0gT2JqZWN0LmtleXMob2xkUHJvcHMpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRQcm9wc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBuYW1lID0gb2xkUHJvcHNOYW1lc1tpXVxuICAgICAgaWYgKCFuZXdQcm9wcyB8fCAhKG5hbWUgaW4gbmV3UHJvcHMpKSB7XG4gICAgICAgIGlmIChpc1N0eWxlT2JqZWN0KSB7XG4gICAgICAgICAgZG9tUHJvcHNbbmFtZV0gPSBFTVBUWVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBkb21Qcm9wc1tuYW1lXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld1Byb3BzKSB7XG4gICAgY29uc3QgbmV3UHJvcHNOYW1lcyA9IE9iamVjdC5rZXlzKG5ld1Byb3BzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3UHJvcHNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbmFtZSA9IG5ld1Byb3BzTmFtZXNbaV1cbiAgICAgIGNvbnN0IG9sZFZhbHVlID0gb2xkUHJvcHMgJiYgb2xkUHJvcHNbbmFtZV1cbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gbmV3UHJvcHNbbmFtZV1cbiAgICAgIGlmIChuZXdWYWx1ZSAhPT0gb2xkVmFsdWUpIHtcbiAgICAgICAgZG9tUHJvcHNbbmFtZV0gPSBuZXdWYWx1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVBdHRyaWJ1dGVzIChkb21Ob2RlLCBvbGRBdHRyaWJ1dGVzLCBuZXdBdHRyaWJ1dGVzKSB7XG4gIGlmIChvbGRBdHRyaWJ1dGVzKSB7XG4gICAgY29uc3Qgb2xkQXR0cmlidXRlTmFtZXMgPSBPYmplY3Qua2V5cyhvbGRBdHRyaWJ1dGVzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2xkQXR0cmlidXRlTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBvbGRBdHRyaWJ1dGVOYW1lc1tpXVxuICAgICAgaWYgKCFuZXdBdHRyaWJ1dGVzIHx8ICEobmFtZSBpbiBuZXdBdHRyaWJ1dGVzKSkge1xuICAgICAgICBkb21Ob2RlLnJlbW92ZUF0dHJpYnV0ZShuYW1lKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChuZXdBdHRyaWJ1dGVzKSB7XG4gICAgY29uc3QgbmV3QXR0cmlidXRlTmFtZXMgPSBPYmplY3Qua2V5cyhuZXdBdHRyaWJ1dGVzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3QXR0cmlidXRlTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBuZXdBdHRyaWJ1dGVOYW1lc1tpXVxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBvbGRBdHRyaWJ1dGVzICYmIG9sZEF0dHJpYnV0ZXNbbmFtZV1cbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gbmV3QXR0cmlidXRlc1tuYW1lXVxuICAgICAgaWYgKG5ld1ZhbHVlICE9PSBvbGRWYWx1ZSkge1xuICAgICAgICBkb21Ob2RlLnNldEF0dHJpYnV0ZShuYW1lLCBuZXdWYWx1ZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlUmVmIChkb21Ob2RlLCBvbGRSZWZOYW1lLCBuZXdSZWZOYW1lLCByZWZzKSB7XG4gIGlmIChuZXdSZWZOYW1lICE9PSBvbGRSZWZOYW1lKSB7XG4gICAgaWYgKG9sZFJlZk5hbWUgJiYgcmVmc1tvbGRSZWZOYW1lXSA9PT0gZG9tTm9kZSkgZGVsZXRlIHJlZnNbb2xkUmVmTmFtZV1cbiAgICBpZiAobmV3UmVmTmFtZSkgcmVmc1tuZXdSZWZOYW1lXSA9IGRvbU5vZGVcbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVFdmVudExpc3RlbmVycyAoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBsaXN0ZW5lckNvbnRleHQpIHtcbiAgY29uc3Qgb2xkTGlzdGVuZXJzID0gb2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUucHJvcHMgJiYgb2xkVmlydHVhbE5vZGUucHJvcHMub25cbiAgY29uc3QgbmV3TGlzdGVuZXJzID0gbmV3VmlydHVhbE5vZGUucHJvcHMgJiYgbmV3VmlydHVhbE5vZGUucHJvcHMub25cblxuICBmb3IgKGNvbnN0IGV2ZW50TmFtZSBpbiBvbGRMaXN0ZW5lcnMpIHtcbiAgICBpZiAoIShuZXdMaXN0ZW5lcnMgJiYgZXZlbnROYW1lIGluIG5ld0xpc3RlbmVycykpIHtcbiAgICAgIGxldCBsaXN0ZW5lclRvUmVtb3ZlXG4gICAgICBpZiAob2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnMgJiYgb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xuICAgICAgICBsaXN0ZW5lclRvUmVtb3ZlID0gb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGlzdGVuZXJUb1JlbW92ZSA9b2xkTGlzdGVuZXJzW2V2ZW50TmFtZV1cbiAgICAgIH1cbiAgICAgIGRvbU5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyVG9SZW1vdmUpXG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBldmVudE5hbWUgaW4gbmV3TGlzdGVuZXJzKSB7XG4gICAgY29uc3Qgb2xkTGlzdGVuZXIgPSBvbGRMaXN0ZW5lcnMgJiYgb2xkTGlzdGVuZXJzW2V2ZW50TmFtZV1cbiAgICBjb25zdCBuZXdMaXN0ZW5lciA9IG5ld0xpc3RlbmVyc1tldmVudE5hbWVdXG5cbiAgICBpZiAobmV3TGlzdGVuZXIgIT09IG9sZExpc3RlbmVyKSB7XG4gICAgICBpZiAob2xkTGlzdGVuZXIpIHtcbiAgICAgICAgbGV0IGxpc3RlbmVyVG9SZW1vdmVcbiAgICAgICAgaWYgKG9sZFZpcnR1YWxOb2RlICYmIG9sZFZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzICYmIG9sZFZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcbiAgICAgICAgICBsaXN0ZW5lclRvUmVtb3ZlID0gb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpc3RlbmVyVG9SZW1vdmUgPSBvbGRMaXN0ZW5lclxuICAgICAgICB9XG4gICAgICAgIGRvbU5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyVG9SZW1vdmUpXG4gICAgICB9XG4gICAgICBsZXQgbGlzdGVuZXJUb0FkZFxuICAgICAgaWYgKGxpc3RlbmVyQ29udGV4dCkge1xuICAgICAgICBsaXN0ZW5lclRvQWRkID0gbmV3TGlzdGVuZXIuYmluZChsaXN0ZW5lckNvbnRleHQpXG4gICAgICAgIGlmICghbmV3VmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnMpIG5ld1ZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzID0ge31cbiAgICAgICAgbmV3VmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGxpc3RlbmVyVG9BZGRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxpc3RlbmVyVG9BZGQgPSBuZXdMaXN0ZW5lclxuICAgICAgfVxuICAgICAgZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXJUb0FkZClcbiAgICB9XG4gIH1cbn1cbiIsImNvbnN0IGRvbSA9IHJlcXVpcmUoJy4vZG9tJylcbmNvbnN0IHJlbmRlciA9IHJlcXVpcmUoJy4vcmVuZGVyJylcbmNvbnN0IHtpbml0aWFsaXplLCB1cGRhdGUsIHVwZGF0ZVN5bmMsIGRlc3Ryb3ksIGRlc3Ryb3lTeW5jfSA9IHJlcXVpcmUoJy4vY29tcG9uZW50LWhlbHBlcnMnKVxuY29uc3Qge3NldFNjaGVkdWxlciwgZ2V0U2NoZWR1bGVyfSA9IHJlcXVpcmUoJy4vc2NoZWR1bGVyLWFzc2lnbm1lbnQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZG9tLCByZW5kZXIsXG4gIGluaXRpYWxpemUsIHVwZGF0ZSwgdXBkYXRlU3luYywgZGVzdHJveSwgZGVzdHJveVN5bmMsXG4gIHNldFNjaGVkdWxlciwgZ2V0U2NoZWR1bGVyXG59XG4iXX0=
const etch = require('etch')
function toHTMLElement(vdom) {
const component = {
update() { /* noop */ },
render () { return vdom }
}
etch.initialize(component)
return component.element
}
const domElement = toHTMLElement(etch.dom.div(null, etch.dom.span(null, 'Hello!')))
document.body.appendChild(domElement)
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"etch": "0.11.0"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment