Created
July 4, 2018 16:23
-
-
Save spiralx/1326b73f02cc9c732a3153812694c749 to your computer and use it in GitHub Desktop.
A small module I've written to let you subscribe to DOM changes that match specified criteria
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Watcher = (function () { | |
'use strict'; | |
// ---------------------------------------------------- | |
var Css; | |
(function (Css) { | |
Css.Inverse = 'color: white; background: black'; | |
Css.Error = 'font-weight: bold; color: #f4f'; | |
Css.Link = 'color: #05f; font-weight: normal; text-decoration: underline'; | |
Css.Bold = 'font-weight: bold'; | |
Css.Blue = 'color: #05f'; | |
Css.Kw = 'color: #35b; font-weight: bold; font-style: normal; text-decoration: none'; | |
Css.Attr = 'color: #563; font-weight: normal; font-style: italic; text-decoration: none'; | |
Css.Val = 'color: #c36; font-weight: normal; font-style: normal; text-decoration: none'; | |
})(Css || (Css = {})); | |
// ---------------------------------------------------- | |
// ---------------------------------------------------- | |
var WatchEvents; | |
(function (WatchEvents) { | |
WatchEvents[WatchEvents["ElementsAdded"] = 1] = "ElementsAdded"; | |
WatchEvents[WatchEvents["ElementsRemoved"] = 2] = "ElementsRemoved"; | |
WatchEvents[WatchEvents["AttributesChanged"] = 4] = "AttributesChanged"; | |
WatchEvents[WatchEvents["TextChanged"] = 8] = "TextChanged"; | |
WatchEvents[WatchEvents["ElementsChanged"] = 3] = "ElementsChanged"; | |
WatchEvents[WatchEvents["AllChanges"] = 15] = "AllChanges"; | |
})(WatchEvents || (WatchEvents = {})); | |
// ---------------------------------------------------- | |
// ---------------------------------------------------- | |
class WatchResult { | |
constructor() { | |
this.added = new Array(); | |
this.removed = new Array(); | |
this.attributeChanges = new Array(); | |
this.textChanges = new Array(); | |
} | |
} | |
class ElementSet extends Set { | |
// get [Symbol.toStringTag]: string () { | |
// return 'ElementSet' | |
// } | |
// ---------------------------------------------------- | |
addAll(elements) { | |
for (const element of elements) { | |
super.add(element); | |
} | |
return this; | |
} | |
// ---------------------------------------------------- | |
toArray() { | |
return Array.from(this); | |
} | |
} | |
// ---------------------------------------------------- | |
function getSelectorFunction(selector) { | |
return function (element) { | |
const matches = []; | |
if (element.matches(selector)) { | |
matches.push(element); | |
} | |
return matches.concat(Array.from(element.querySelectorAll(selector))); | |
}; | |
} | |
// ---------------------------------------------------- | |
function getElementNodesFromNodeList(nodes) { | |
return getElementNodes(Array.from(nodes)); | |
} | |
// ---------------------------------------------------- | |
function getElementNodes(nodes) { | |
return nodes.filter(node => node instanceof HTMLElement); | |
} | |
// ---------------------------------------------------------- | |
class Watch { | |
// ---------------------------------------------------- | |
constructor(options, callback) { | |
this.options = options; | |
this.callback = callback; | |
this.attributes = new Set(); | |
this.selector = this.options.selector || '*'; | |
this.selectorFunction = getSelectorFunction(this.selector); | |
this.findExisting = typeof options.findExisting === 'boolean' | |
? options.findExisting | |
: true; | |
this.events = options.events || WatchEvents.ElementsChanged; | |
if (options.attributes) { | |
this.attributes = new Set(options.attributes); | |
} | |
else if (options.attribute) { | |
this.attributes.add(options.attribute); | |
} | |
} | |
// ---------------------------------------------------- | |
get [Symbol.toStringTag]() { | |
return 'Watch'; | |
} | |
// ---------------------------------------------------- | |
processSummary(summary, debug = false) { | |
const addedElements = getElementNodesFromNodeList(summary.addedNodes); | |
const removedElements = getElementNodesFromNodeList(summary.removedNodes); | |
const matchingAddedElements = this.processElements(addedElements); | |
const matchingRemovedElements = this.processElements(removedElements); | |
if (debug) { | |
console.groupCollapsed(`%cWatch.processSummary(%ctype=%c${summary.type}%c)`, Css.Kw, Css.Attr, Css.Val, Css.Kw); | |
if (addedElements.length) { | |
console.group(`Added elements`); | |
console.dir(addedElements); | |
console.dir(matchingAddedElements); | |
console.groupEnd(); | |
} | |
if (removedElements.length) { | |
console.group(`Removed elements`); | |
console.dir(removedElements); | |
console.dir(matchingRemovedElements); | |
console.groupEnd(); | |
} | |
console.groupEnd(); | |
} | |
this.invoke(matchingAddedElements.toArray(), matchingRemovedElements.toArray(), debug); | |
} | |
// ---------------------------------------------------- | |
processElement(element) { | |
this.invoke(this.selectorFunction(element), []); | |
} | |
// ---------------------------------------------------- | |
dump() { | |
console.groupCollapsed(`%cWatch(%cselector: %c"${this.options.selector}"%c)`, Css.Kw, Css.Attr, Css.Link, Css.Kw); | |
console.dir(this.options); | |
console.log(this.callback.toString()); | |
console.groupEnd(); | |
} | |
// ---------------------------------------------------- | |
processElements(elements) { | |
return elements.reduce((matches, element) => matches.addAll(this.selectorFunction(element)), new ElementSet()); | |
} | |
// ---------------------------------------------------- | |
invoke(added, removed, debug = false) { | |
if (added.length > 0 || removed.length > 0) { | |
const result = new WatchResult(); | |
result.added = added; | |
result.removed = removed; | |
if (debug) { | |
console.groupCollapsed(`%cWatch.invoke()`, Css.Kw); | |
console.dir(result); | |
console.groupEnd(); | |
} | |
this.callback(result); | |
// this.callback.call(this.context, result) | |
} | |
} | |
} | |
// ---------------------------------------------------------- | |
class Watcher { | |
// ---------------------------------------------------- | |
constructor(root = document.body, debug = false) { | |
this.root = root; | |
this.debug = debug; | |
this.observer = null; | |
// readonly watcheMap: Map<string, Watch> = new Map() | |
this.watches = []; | |
if (!(root instanceof HTMLElement)) { | |
throw new TypeError('Watch root is not a valid HTML element!'); | |
} | |
} | |
// ---------------------------------------------------- | |
get [Symbol.toStringTag]() { | |
return 'Watcher'; | |
} | |
add(options, callback) { | |
if (typeof options === 'string') { | |
options = { | |
selector: options | |
}; | |
} | |
else if (typeof options === 'function') { | |
callback = options; | |
options = {}; | |
} | |
if (!callback) { | |
throw new Error('No callback function specified when calling Watcher.add()'); | |
} | |
if (this.debug) { | |
console.groupCollapsed(`%cWatcher.add(selector: %c${options.selector}%c, %c${this.watchCount} watches%c)`, Css.Kw, Css.Link, Css.Kw, Css.Val, Css.Kw); | |
console.log(callback.toString()); | |
if (options) { | |
console.dir(options); | |
} | |
console.groupEnd(); | |
} | |
const watch = new Watch(options, callback); | |
this.watches.push(watch); | |
return watch; | |
} | |
// ---------------------------------------------------- | |
get observing() { | |
return !!this.observer; | |
} | |
// ---------------------------------------------------- | |
get watchCount() { | |
return this.watches.length; | |
} | |
// ---------------------------------------------------- | |
// get watches (): Watch[] { | |
// return [ ...this.watchMap.values() ] | |
// } | |
// ---------------------------------------------------- | |
processSummary(summary) { | |
if (this.debug) { | |
console.groupCollapsed(`%cWatcher.processSummary(%ctype=%c${summary.type}%c)`, Css.Kw, Css.Attr, Css.Val, Css.Kw); | |
console.dir(summary); | |
console.groupEnd(); | |
} | |
for (const watch of this.watches) { | |
watch.processSummary(summary, this.debug); | |
} | |
} | |
// ---------------------------------------------------- | |
start() { | |
if (!this.watchCount) { | |
throw new Error('Cannot start Watcher without any watches!'); | |
} | |
if (this.debug) { | |
console.info(`%cWatcher.start(%cenabled = %c${this.observing ? 'true' : 'false'}%c, %c${this.watchCount} watches%c)`, Css.Kw, Css.Attr, Css.Val, Css.Kw, Css.Val, Css.Kw); | |
} | |
if (!this.observer) { | |
// Check for existing elements, pass to callback | |
for (const watch of this.watches) { | |
if (watch.findExisting && watch.events & WatchEvents.ElementsAdded) { | |
watch.processElement(this.root); | |
} | |
} | |
this.observer = new MutationObserver(summaries => { | |
summaries.forEach(summary => this.processSummary(summary)); | |
}); | |
this.observer.observe(this.root, { | |
childList: true, | |
// attributes: true, | |
subtree: true | |
}); | |
} | |
return this; | |
} | |
// ---------------------------------------------------- | |
stop() { | |
if (this.observer) { | |
this.observer.takeRecords().forEach(summary => this.processSummary(summary)); | |
this.observer.disconnect(); | |
this.observer = null; | |
} | |
return this; | |
} | |
} | |
return Watcher; | |
}()); | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlci5qcyIsInNvdXJjZXMiOlsiLi4vc3JjL2ludGVyZmFjZXMudHMiLCIuLi9zcmMvd2F0Y2gtb3B0aW9ucy50cyIsIi4uL3NyYy93YXRjaC1yZXN1bHQudHMiLCIuLi9zcmMvZWxlbWVudC1zZXQudHMiLCIuLi9zcmMvdXRpbHMvZG9tLnRzIiwiLi4vc3JjL3dhdGNoLnRzIiwiLi4vc3JjL3dhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiXHJcbmludGVyZmFjZSBDb25zb2xlIHtcclxuICBncm91cCAoZ3JvdXBUaXRsZT86IHN0cmluZywgLi4ub3B0aW9uYWxQYXJhbXM6IGFueVtdKTogdm9pZFxyXG59XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgbmFtZXNwYWNlIENzcyB7XHJcbiAgZXhwb3J0IGNvbnN0IEludmVyc2UgPSAnY29sb3I6IHdoaXRlOyBiYWNrZ3JvdW5kOiBibGFjaydcclxuICBleHBvcnQgY29uc3QgRXJyb3IgPSAnZm9udC13ZWlnaHQ6IGJvbGQ7IGNvbG9yOiAjZjRmJ1xyXG4gIGV4cG9ydCBjb25zdCBMaW5rID0gJ2NvbG9yOiAjMDVmOyBmb250LXdlaWdodDogbm9ybWFsOyB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZSdcclxuICBleHBvcnQgY29uc3QgQm9sZCA9ICdmb250LXdlaWdodDogYm9sZCdcclxuICBleHBvcnQgY29uc3QgQmx1ZSA9ICdjb2xvcjogIzA1ZidcclxuICBleHBvcnQgY29uc3QgS3cgPSAnY29sb3I6ICMzNWI7IGZvbnQtd2VpZ2h0OiBib2xkOyBmb250LXN0eWxlOiBub3JtYWw7IHRleHQtZGVjb3JhdGlvbjogbm9uZSdcclxuICBleHBvcnQgY29uc3QgQXR0ciA9ICdjb2xvcjogIzU2MzsgZm9udC13ZWlnaHQ6IG5vcm1hbDsgZm9udC1zdHlsZTogaXRhbGljOyB0ZXh0LWRlY29yYXRpb246IG5vbmUnXHJcbiAgZXhwb3J0IGNvbnN0IFZhbCA9ICdjb2xvcjogI2MzNjsgZm9udC13ZWlnaHQ6IG5vcm1hbDsgZm9udC1zdHlsZTogbm9ybWFsOyB0ZXh0LWRlY29yYXRpb246IG5vbmUnXHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU5vZGUge1xyXG4gIG5vZGVzPzogSU5vZGVbXVxyXG59XHJcbiIsIlxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFdhdGNoT3B0aW9ucyB7XHJcbiAgc2VsZWN0b3I/OiBzdHJpbmdcclxuICBmaW5kRXhpc3Rpbmc/OiBib29sZWFuXHJcbiAgZXZlbnRzPzogV2F0Y2hFdmVudHNcclxuICBhdHRyaWJ1dGU/OiBzdHJpbmdcclxuICBhdHRyaWJ1dGVzPzogc3RyaW5nW11cclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuZXhwb3J0IGVudW0gV2F0Y2hFdmVudHMge1xyXG4gIEVsZW1lbnRzQWRkZWQgPSAxLFxyXG4gIEVsZW1lbnRzUmVtb3ZlZCA9IDIsXHJcbiAgQXR0cmlidXRlc0NoYW5nZWQgPSA0LFxyXG4gIFRleHRDaGFuZ2VkID0gOCxcclxuXHJcbiAgRWxlbWVudHNDaGFuZ2VkID0gRWxlbWVudHNBZGRlZCB8IEVsZW1lbnRzUmVtb3ZlZCxcclxuICBBbGxDaGFuZ2VzID0gRWxlbWVudHNBZGRlZCB8IEVsZW1lbnRzUmVtb3ZlZCB8IEF0dHJpYnV0ZXNDaGFuZ2VkIHwgVGV4dENoYW5nZWRcclxufVxyXG4iLCJcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBBdHRyaWJ1dGVDaGFuZ2Uge1xyXG4gIHRhcmdldDogSFRNTEVsZW1lbnRcclxuICBhdHRyaWJ1dGU6IHN0cmluZ1xyXG4gIHZhbHVlOiBzdHJpbmcgfCBTVkdOdW1iZXJMaXN0XHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVGV4dENoYW5nZSB7XHJcbiAgdGFyZ2V0OiBIVE1MRWxlbWVudFxyXG4gIHRleHQ6IHN0cmluZ1xyXG59XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgY2xhc3MgV2F0Y2hSZXN1bHQge1xyXG4gIGFkZGVkOiBBcnJheTxIVE1MRWxlbWVudD4gPSBuZXcgQXJyYXk8SFRNTEVsZW1lbnQ+KClcclxuICByZW1vdmVkOiBBcnJheTxIVE1MRWxlbWVudD4gPSBuZXcgQXJyYXk8SFRNTEVsZW1lbnQ+KClcclxuICBhdHRyaWJ1dGVDaGFuZ2VzOiBBcnJheTxBdHRyaWJ1dGVDaGFuZ2U+ID0gbmV3IEFycmF5PEF0dHJpYnV0ZUNoYW5nZT4oKVxyXG4gIHRleHRDaGFuZ2VzOiBBcnJheTxUZXh0Q2hhbmdlPiA9IG5ldyBBcnJheTxUZXh0Q2hhbmdlPigpXHJcbn1cclxuIiwiXHJcbmV4cG9ydCBjbGFzcyBFbGVtZW50U2V0IGV4dGVuZHMgU2V0PEhUTUxFbGVtZW50PiB7XHJcbiAgLy8gZ2V0IFtTeW1ib2wudG9TdHJpbmdUYWddOiBzdHJpbmcgKCkge1xyXG4gIC8vICAgcmV0dXJuICdFbGVtZW50U2V0J1xyXG4gIC8vIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBhZGRBbGwgKGVsZW1lbnRzOiBIVE1MRWxlbWVudFtdIHwgRWxlbWVudFNldCk6IHRoaXMge1xyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XHJcbiAgICAgIHN1cGVyLmFkZChlbGVtZW50KVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzXHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIHRvQXJyYXkgKCk6IEhUTUxFbGVtZW50W10ge1xyXG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcylcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgU2VsZWN0b3JGdW5jIH0gZnJvbSAnLi4vd2F0Y2gnXHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2VsZWN0b3JGdW5jdGlvbiAoc2VsZWN0b3I6IHN0cmluZyk6IFNlbGVjdG9yRnVuYyB7XHJcbiAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50W10ge1xyXG4gICAgY29uc3QgbWF0Y2hlczogSFRNTEVsZW1lbnRbXSA9IFtdXHJcblxyXG4gICAgaWYgKGVsZW1lbnQubWF0Y2hlcyhzZWxlY3RvcikpIHtcclxuICAgICAgbWF0Y2hlcy5wdXNoKGVsZW1lbnQpXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG1hdGNoZXMuY29uY2F0KEFycmF5LmZyb20oZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSkpXHJcbiAgfVxyXG59XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudE5vZGVzRnJvbU5vZGVMaXN0IChub2RlczogTm9kZUxpc3QpOiBIVE1MRWxlbWVudFtdIHtcclxuICByZXR1cm4gZ2V0RWxlbWVudE5vZGVzKEFycmF5LmZyb20obm9kZXMpKVxyXG59XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudE5vZGVzIChub2RlczogTm9kZVtdKTogSFRNTEVsZW1lbnRbXSB7XHJcbiAgcmV0dXJuIG5vZGVzLmZpbHRlcihub2RlID0+IG5vZGUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgYXMgSFRNTEVsZW1lbnRbXVxyXG59XHJcbiIsImltcG9ydCB7IENzcyB9IGZyb20gJy4vaW50ZXJmYWNlcydcclxuXHJcbmltcG9ydCB7IFdhdGNoT3B0aW9ucywgV2F0Y2hFdmVudHMgfSBmcm9tICcuL3dhdGNoLW9wdGlvbnMnXHJcbmltcG9ydCB7IFdhdGNoUmVzdWx0IH0gZnJvbSAnLi93YXRjaC1yZXN1bHQnXHJcbmltcG9ydCB7IEVsZW1lbnRTZXQgfSBmcm9tICcuL2VsZW1lbnQtc2V0J1xyXG5cclxuaW1wb3J0IHsgZ2V0U2VsZWN0b3JGdW5jdGlvbiwgZ2V0RWxlbWVudE5vZGVzRnJvbU5vZGVMaXN0IH0gZnJvbSAnLi91dGlscy9kb20nXHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5leHBvcnQgdHlwZSBTZWxlY3RvckZ1bmMgPSAoZWxlbWVudDogSFRNTEVsZW1lbnQpID0+IEhUTUxFbGVtZW50W11cclxuXHJcbmV4cG9ydCB0eXBlIFdhdGNoQ2FsbGJhY2sgPSAocmVzdWx0OiBXYXRjaFJlc3VsdCkgPT4gdm9pZFxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuZXhwb3J0IGNsYXNzIFdhdGNoIHtcclxuICBwdWJsaWMgc2VsZWN0b3I6IHN0cmluZ1xyXG4gIHB1YmxpYyBzZWxlY3RvckZ1bmN0aW9uOiBTZWxlY3RvckZ1bmNcclxuXHJcbiAgcHVibGljIGZpbmRFeGlzdGluZzogYm9vbGVhblxyXG5cclxuICBwdWJsaWMgZXZlbnRzOiBXYXRjaEV2ZW50c1xyXG4gIHB1YmxpYyBhdHRyaWJ1dGVzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIGdldCBbU3ltYm9sLnRvU3RyaW5nVGFnXSAoKSB7XHJcbiAgICByZXR1cm4gJ1dhdGNoJ1xyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBjb25zdHJ1Y3RvciAoXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgb3B0aW9uczogV2F0Y2hPcHRpb25zLFxyXG4gICAgcHVibGljIHJlYWRvbmx5IGNhbGxiYWNrOiBXYXRjaENhbGxiYWNrXHJcbiAgKSB7XHJcbiAgICB0aGlzLnNlbGVjdG9yID0gdGhpcy5vcHRpb25zLnNlbGVjdG9yIHx8ICcqJ1xyXG4gICAgdGhpcy5zZWxlY3RvckZ1bmN0aW9uID0gZ2V0U2VsZWN0b3JGdW5jdGlvbih0aGlzLnNlbGVjdG9yKVxyXG5cclxuICAgIHRoaXMuZmluZEV4aXN0aW5nID0gdHlwZW9mIG9wdGlvbnMuZmluZEV4aXN0aW5nID09PSAnYm9vbGVhbidcclxuICAgICAgPyBvcHRpb25zLmZpbmRFeGlzdGluZ1xyXG4gICAgICA6IHRydWVcclxuXHJcbiAgICB0aGlzLmV2ZW50cyA9IG9wdGlvbnMuZXZlbnRzIHx8IFdhdGNoRXZlbnRzLkVsZW1lbnRzQ2hhbmdlZFxyXG5cclxuICAgIGlmIChvcHRpb25zLmF0dHJpYnV0ZXMpIHtcclxuICAgICAgdGhpcy5hdHRyaWJ1dGVzID0gbmV3IFNldChvcHRpb25zLmF0dHJpYnV0ZXMpXHJcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMuYXR0cmlidXRlKSB7XHJcbiAgICAgIHRoaXMuYXR0cmlidXRlcy5hZGQob3B0aW9ucy5hdHRyaWJ1dGUpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIHByb2Nlc3NTdW1tYXJ5IChzdW1tYXJ5OiBNdXRhdGlvblJlY29yZCwgZGVidWc6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xyXG4gICAgY29uc3QgYWRkZWRFbGVtZW50cyA9IGdldEVsZW1lbnROb2Rlc0Zyb21Ob2RlTGlzdChzdW1tYXJ5LmFkZGVkTm9kZXMpXHJcbiAgICBjb25zdCByZW1vdmVkRWxlbWVudHMgPSBnZXRFbGVtZW50Tm9kZXNGcm9tTm9kZUxpc3Qoc3VtbWFyeS5yZW1vdmVkTm9kZXMpXHJcblxyXG4gICAgY29uc3QgbWF0Y2hpbmdBZGRlZEVsZW1lbnRzOiBFbGVtZW50U2V0ID0gdGhpcy5wcm9jZXNzRWxlbWVudHMoYWRkZWRFbGVtZW50cylcclxuICAgIGNvbnN0IG1hdGNoaW5nUmVtb3ZlZEVsZW1lbnRzOiBFbGVtZW50U2V0ID0gdGhpcy5wcm9jZXNzRWxlbWVudHMocmVtb3ZlZEVsZW1lbnRzKVxyXG5cclxuICAgIGlmIChkZWJ1Zykge1xyXG4gICAgICBjb25zb2xlLmdyb3VwQ29sbGFwc2VkKGAlY1dhdGNoLnByb2Nlc3NTdW1tYXJ5KCVjdHlwZT0lYyR7c3VtbWFyeS50eXBlfSVjKWAsIENzcy5LdywgQ3NzLkF0dHIsIENzcy5WYWwsIENzcy5LdylcclxuXHJcbiAgICAgIGlmIChhZGRlZEVsZW1lbnRzLmxlbmd0aCkge1xyXG4gICAgICAgIGNvbnNvbGUuZ3JvdXAoYEFkZGVkIGVsZW1lbnRzYClcclxuICAgICAgICBjb25zb2xlLmRpcihhZGRlZEVsZW1lbnRzKVxyXG4gICAgICAgIGNvbnNvbGUuZGlyKG1hdGNoaW5nQWRkZWRFbGVtZW50cylcclxuICAgICAgICBjb25zb2xlLmdyb3VwRW5kKClcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHJlbW92ZWRFbGVtZW50cy5sZW5ndGgpIHtcclxuICAgICAgICBjb25zb2xlLmdyb3VwKGBSZW1vdmVkIGVsZW1lbnRzYClcclxuICAgICAgICBjb25zb2xlLmRpcihyZW1vdmVkRWxlbWVudHMpXHJcbiAgICAgICAgY29uc29sZS5kaXIobWF0Y2hpbmdSZW1vdmVkRWxlbWVudHMpXHJcbiAgICAgICAgY29uc29sZS5ncm91cEVuZCgpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaW52b2tlKG1hdGNoaW5nQWRkZWRFbGVtZW50cy50b0FycmF5KCksIG1hdGNoaW5nUmVtb3ZlZEVsZW1lbnRzLnRvQXJyYXkoKSwgZGVidWcpXHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIHByb2Nlc3NFbGVtZW50IChlbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbnZva2UodGhpcy5zZWxlY3RvckZ1bmN0aW9uKGVsZW1lbnQpLCBbXSlcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgZHVtcCAoKSB7XHJcbiAgICBjb25zb2xlLmdyb3VwQ29sbGFwc2VkKGAlY1dhdGNoKCVjc2VsZWN0b3I6ICVjXCIke3RoaXMub3B0aW9ucy5zZWxlY3Rvcn1cIiVjKWAsIENzcy5LdywgQ3NzLkF0dHIsIENzcy5MaW5rLCBDc3MuS3cpXHJcbiAgICBjb25zb2xlLmRpcih0aGlzLm9wdGlvbnMpXHJcbiAgICBjb25zb2xlLmxvZyh0aGlzLmNhbGxiYWNrLnRvU3RyaW5nKCkpXHJcbiAgICBjb25zb2xlLmdyb3VwRW5kKClcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgcHJpdmF0ZSBwcm9jZXNzRWxlbWVudHMgKGVsZW1lbnRzOiBIVE1MRWxlbWVudFtdKTogRWxlbWVudFNldCB7XHJcbiAgICByZXR1cm4gZWxlbWVudHMucmVkdWNlKChtYXRjaGVzOiBFbGVtZW50U2V0LCBlbGVtZW50OiBIVE1MRWxlbWVudCkgPT4gbWF0Y2hlcy5hZGRBbGwodGhpcy5zZWxlY3RvckZ1bmN0aW9uKGVsZW1lbnQpKSwgbmV3IEVsZW1lbnRTZXQoKSlcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgcHJpdmF0ZSBpbnZva2UgKGFkZGVkOiBIVE1MRWxlbWVudFtdLCByZW1vdmVkOiBIVE1MRWxlbWVudFtdLCBkZWJ1ZzogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBpZiAoYWRkZWQubGVuZ3RoID4gMCB8fCByZW1vdmVkLmxlbmd0aCA+IDApIHtcclxuICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFdhdGNoUmVzdWx0KClcclxuICAgICAgcmVzdWx0LmFkZGVkID0gYWRkZWRcclxuICAgICAgcmVzdWx0LnJlbW92ZWQgPSByZW1vdmVkXHJcblxyXG4gICAgICBpZiAoZGVidWcpIHtcclxuICAgICAgICBjb25zb2xlLmdyb3VwQ29sbGFwc2VkKGAlY1dhdGNoLmludm9rZSgpYCwgQ3NzLkt3KVxyXG4gICAgICAgIGNvbnNvbGUuZGlyKHJlc3VsdClcclxuICAgICAgICBjb25zb2xlLmdyb3VwRW5kKClcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5jYWxsYmFjayhyZXN1bHQpXHJcbiAgICAgIC8vIHRoaXMuY2FsbGJhY2suY2FsbCh0aGlzLmNvbnRleHQsIHJlc3VsdClcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgQ3NzIH0gZnJvbSAnLi9pbnRlcmZhY2VzJ1xyXG5cclxuaW1wb3J0IHsgV2F0Y2hDYWxsYmFjaywgV2F0Y2ggfSBmcm9tICcuL3dhdGNoJ1xyXG5pbXBvcnQgeyBXYXRjaE9wdGlvbnMsIFdhdGNoRXZlbnRzIH0gZnJvbSAnLi93YXRjaC1vcHRpb25zJ1xyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2F0Y2hlciB7XHJcblxyXG4gIG9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyIHwgbnVsbCA9IG51bGxcclxuXHJcbiAgLy8gcmVhZG9ubHkgd2F0Y2hlTWFwOiBNYXA8c3RyaW5nLCBXYXRjaD4gPSBuZXcgTWFwKClcclxuICByZWFkb25seSB3YXRjaGVzOiBXYXRjaFtdID0gW11cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBnZXQgW1N5bWJvbC50b1N0cmluZ1RhZ10gKCkge1xyXG4gICAgcmV0dXJuICdXYXRjaGVyJ1xyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBjb25zdHJ1Y3RvciAoXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgcm9vdDogSFRNTEVsZW1lbnQgPSBkb2N1bWVudC5ib2R5LFxyXG4gICAgcHVibGljIHJlYWRvbmx5IGRlYnVnOiBib29sZWFuID0gZmFsc2VcclxuICApIHtcclxuICAgIGlmICghKHJvb3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcclxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignV2F0Y2ggcm9vdCBpcyBub3QgYSB2YWxpZCBIVE1MIGVsZW1lbnQhJylcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgYWRkIChjYWxsYmFjazogV2F0Y2hDYWxsYmFjayk6IFdhdGNoXHJcbiAgYWRkIChvcHRpb25zOiBzdHJpbmcgfCBXYXRjaE9wdGlvbnMsIGNhbGxiYWNrOiBXYXRjaENhbGxiYWNrKTogV2F0Y2hcclxuXHJcbiAgYWRkIChvcHRpb25zOiBzdHJpbmcgfCBXYXRjaE9wdGlvbnMgfCBXYXRjaENhbGxiYWNrLCBjYWxsYmFjaz86IFdhdGNoQ2FsbGJhY2spOiBXYXRjaCB7XHJcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIG9wdGlvbnMgPSB7XHJcbiAgICAgICAgc2VsZWN0b3I6IG9wdGlvbnNcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICBjYWxsYmFjayA9IG9wdGlvbnNcclxuICAgICAgb3B0aW9ucyA9IHt9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFjYWxsYmFjaykge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNhbGxiYWNrIGZ1bmN0aW9uIHNwZWNpZmllZCB3aGVuIGNhbGxpbmcgV2F0Y2hlci5hZGQoKScpXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuZGVidWcpIHtcclxuICAgICAgY29uc29sZS5ncm91cENvbGxhcHNlZChgJWNXYXRjaGVyLmFkZChzZWxlY3RvcjogJWMke29wdGlvbnMuc2VsZWN0b3J9JWMsICVjJHt0aGlzLndhdGNoQ291bnR9IHdhdGNoZXMlYylgLCBDc3MuS3csIENzcy5MaW5rLCBDc3MuS3csIENzcy5WYWwsIENzcy5LdylcclxuICAgICAgY29uc29sZS5sb2coY2FsbGJhY2sudG9TdHJpbmcoKSlcclxuICAgICAgaWYgKG9wdGlvbnMpIHtcclxuICAgICAgICBjb25zb2xlLmRpcihvcHRpb25zKVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHdhdGNoID0gbmV3IFdhdGNoKG9wdGlvbnMsIGNhbGxiYWNrKVxyXG5cclxuICAgIHRoaXMud2F0Y2hlcy5wdXNoKHdhdGNoKVxyXG5cclxuICAgIHJldHVybiB3YXRjaFxyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBnZXQgb2JzZXJ2aW5nICgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAhIXRoaXMub2JzZXJ2ZXJcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgZ2V0IHdhdGNoQ291bnQgKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy53YXRjaGVzLmxlbmd0aFxyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICAvLyBnZXQgd2F0Y2hlcyAoKTogV2F0Y2hbXSB7XHJcbiAgLy8gICByZXR1cm4gWyAuLi50aGlzLndhdGNoTWFwLnZhbHVlcygpIF1cclxuICAvLyB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgcHJvY2Vzc1N1bW1hcnkgKHN1bW1hcnk6IE11dGF0aW9uUmVjb3JkKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kZWJ1Zykge1xyXG4gICAgICBjb25zb2xlLmdyb3VwQ29sbGFwc2VkKGAlY1dhdGNoZXIucHJvY2Vzc1N1bW1hcnkoJWN0eXBlPSVjJHtzdW1tYXJ5LnR5cGV9JWMpYCwgQ3NzLkt3LCBDc3MuQXR0ciwgQ3NzLlZhbCwgQ3NzLkt3KVxyXG4gICAgICBjb25zb2xlLmRpcihzdW1tYXJ5KVxyXG4gICAgICBjb25zb2xlLmdyb3VwRW5kKClcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGNvbnN0IHdhdGNoIG9mIHRoaXMud2F0Y2hlcykge1xyXG4gICAgICB3YXRjaC5wcm9jZXNzU3VtbWFyeShzdW1tYXJ5LCB0aGlzLmRlYnVnKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBzdGFydCAoKTogdGhpcyB7XHJcbiAgICBpZiAoIXRoaXMud2F0Y2hDb3VudCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzdGFydCBXYXRjaGVyIHdpdGhvdXQgYW55IHdhdGNoZXMhJylcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5kZWJ1Zykge1xyXG4gICAgICBjb25zb2xlLmluZm8oYCVjV2F0Y2hlci5zdGFydCglY2VuYWJsZWQgPSAlYyR7dGhpcy5vYnNlcnZpbmcgPyAndHJ1ZScgOiAnZmFsc2UnfSVjLCAlYyR7dGhpcy53YXRjaENvdW50fSB3YXRjaGVzJWMpYCwgQ3NzLkt3LCBDc3MuQXR0ciwgQ3NzLlZhbCwgQ3NzLkt3LCBDc3MuVmFsLCBDc3MuS3cpXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLm9ic2VydmVyKSB7XHJcbiAgICAgIC8vIENoZWNrIGZvciBleGlzdGluZyBlbGVtZW50cywgcGFzcyB0byBjYWxsYmFja1xyXG4gICAgICBmb3IgKGNvbnN0IHdhdGNoIG9mIHRoaXMud2F0Y2hlcykge1xyXG4gICAgICAgIGlmICh3YXRjaC5maW5kRXhpc3RpbmcgJiYgd2F0Y2guZXZlbnRzICYgV2F0Y2hFdmVudHMuRWxlbWVudHNBZGRlZCkge1xyXG4gICAgICAgICAgd2F0Y2gucHJvY2Vzc0VsZW1lbnQodGhpcy5yb290KVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKHN1bW1hcmllcyA9PiB7XHJcbiAgICAgICAgc3VtbWFyaWVzLmZvckVhY2goc3VtbWFyeSA9PiB0aGlzLnByb2Nlc3NTdW1tYXJ5KHN1bW1hcnkpKVxyXG4gICAgICB9KVxyXG5cclxuICAgICAgdGhpcy5vYnNlcnZlci5vYnNlcnZlKHRoaXMucm9vdCwge1xyXG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcclxuICAgICAgICAvLyBhdHRyaWJ1dGVzOiB0cnVlLFxyXG4gICAgICAgIHN1YnRyZWU6IHRydWVcclxuICAgICAgfSlcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpc1xyXG4gIH1cclxuXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICBzdG9wICgpOiB0aGlzIHtcclxuICAgIGlmICh0aGlzLm9ic2VydmVyKSB7XHJcbiAgICAgIHRoaXMub2JzZXJ2ZXIudGFrZVJlY29yZHMoKS5mb3JFYWNoKHN1bW1hcnkgPT4gdGhpcy5wcm9jZXNzU3VtbWFyeShzdW1tYXJ5KSlcclxuXHJcbiAgICAgIHRoaXMub2JzZXJ2ZXIuZGlzY29ubmVjdCgpXHJcbiAgICAgIHRoaXMub2JzZXJ2ZXIgPSBudWxsXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXNcclxuICB9XHJcbn1cclxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUtBO0FBRUEsSUFBaUIsR0FBRyxDQVNuQjtBQVRELFdBQWlCLEdBQUc7SUFDTCxXQUFPLEdBQUcsaUNBQWlDLENBQUE7SUFDM0MsU0FBSyxHQUFHLGdDQUFnQyxDQUFBO0lBQ3hDLFFBQUksR0FBRyw4REFBOEQsQ0FBQTtJQUNyRSxRQUFJLEdBQUcsbUJBQW1CLENBQUE7SUFDMUIsUUFBSSxHQUFHLGFBQWEsQ0FBQTtJQUNwQixNQUFFLEdBQUcsMkVBQTJFLENBQUE7SUFDaEYsUUFBSSxHQUFHLDZFQUE2RSxDQUFBO0lBQ3BGLE9BQUcsR0FBRyw2RUFBNkUsQ0FBQTtDQUNqRyxFQVRnQixHQUFHLEtBQUgsR0FBRyxRQVNuQjs7QUNmRDs7QUFZQSxBQUFBLElBQVksV0FRWDtBQVJELFdBQVksV0FBVztJQUNyQiwr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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gist - Raw
RawGit - Development
RawGit - Production