Skip to content

Instantly share code, notes, and snippets.

@unixcult
Forked from juliangruber/head.html
Created July 27, 2013 19:58
Show Gist options
  • Select an option

  • Save unixcult/6096073 to your computer and use it in GitHub Desktop.

Select an option

Save unixcult/6096073 to your computer and use it in GitHub Desktop.

Revisions

  1. unixcult revised this gist Jul 27, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion requirebin.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    view on [requirebin](http://requirebin.com?gist=5940808)
    view on [requirebin](http://requirebin.com?gist=6096073)
  2. unixcult revised this gist Jul 27, 2013. 4 changed files with 18 additions and 811 deletions.
    19 changes: 14 additions & 5 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,16 @@
    var Spinning = require('spinning');
    function eat(food, digest){
    var ateTheFood = food + " got eaten";
    digest(ateTheFood);
    }

    var spinner = Spinning().text('loading...').light().size(200);
    //eat('pizza', function(poop){
    // console.log(poop);
    //});

    setTimeout(function () {
    spinner.remove();
    }, 3000);
    //the line below more elegantly does the work of the lines above

    eat('pizza', poop);

    function poop(food) {
    console.log(food);
    }
    807 changes: 1 addition & 806 deletions minified.js
    Original file line number Diff line number Diff line change
    @@ -1,806 +1 @@
    require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
    module.exports = '.spinner, .overlay {\n position: fixed;\n opacity: 0;\n}\n\n.spinner {\n left: 50%;\n top: 50%;\n margin-left: -100px;\n margin-top: -100px;\n z-index: 2222222222;\n}\n\n.overlay {\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n background-color: white;\n z-index: 1111111111;\n}\n';
    },{}],"spinning":[function(require,module,exports){
    module.exports=require('JGIiXp');
    },{}],"JGIiXp":[function(require,module,exports){
    (function(){var Spinner = require('spinner-browserify');
    var insertCss = require('insert-css');
    var style = require('./style');
    var fade = require('fade');
    var process = require('process'); // be nice to browserify

    module.exports = Spin;

    function Spin () {
    insertCss(style);

    // durations
    var fadeIn = 1000;
    var fadeOut = 300;

    var overlay = document.createElement('div');
    overlay.className = 'overlay';
    document.body.appendChild(overlay);

    var spinner = new Spinner();
    spinner.el.className = 'spinner';
    document.body.appendChild(spinner.el);

    process.nextTick(function () {
    fade(overlay, 0.8, fadeIn);
    fade.in(spinner.el, fadeIn);
    });

    spinner.remove = function () {
    fade.out(overlay, fadeOut);
    fade.out(spinner.el, fadeOut);

    setTimeout(function () {
    spinner.stop();
    document.body.removeChild(overlay);
    document.body.removeChild(spinner.el);
    }, fadeOut);
    };

    // reposition
    var size = spinner.size;
    spinner.size = function (n) {
    spinner.el.style.marginLeft =
    spinner.el.style.marginTop = '-' + (n/2) + 'px';
    return size.call(spinner, n);
    };

    var light = spinner.light;
    spinner.light = function () {
    overlay.style.backgroundColor = 'black';
    return light.call(spinner);
    };

    // set durations
    spinner['in'] = function (ms) { fadeIn = ms };
    spinner.out = function (ms) { fadeOut = ms };

    return spinner;
    }

    })()
    },{"process":2,"./style":1,"insert-css":3,"fade":4,"spinner-browserify":5}],2:[function(require,module,exports){
    (function(){var process = module.exports = {};

    process.nextTick = (function () {
    var canSetImmediate = typeof window !== 'undefined'
    && window.setImmediate;
    var canPost = typeof window !== 'undefined'
    && window.postMessage && window.addEventListener
    ;

    if (canSetImmediate) {
    return function (f) { return window.setImmediate(f) };
    }

    if (canPost) {
    var queue = [];
    window.addEventListener('message', function (ev) {
    if (ev.source === window && ev.data === 'browserify-tick') {
    ev.stopPropagation();
    if (queue.length > 0) {
    var fn = queue.shift();
    fn();
    }
    }
    }, true);

    return function nextTick(fn) {
    queue.push(fn);
    window.postMessage('browserify-tick', '*');
    };
    }

    return function nextTick(fn) {
    setTimeout(fn, 0);
    };
    })();

    process.title = 'browser';
    process.browser = true;
    process.env = {};
    process.argv = [];

    process.binding = function (name) {
    if (name === 'evals') return (require)('vm')
    else throw new Error('No such module. (Possibly not yet loaded)')
    };

    (function () {
    var cwd = '/';
    var path;
    process.cwd = function () { return cwd };
    process.chdir = function (dir) {
    if (!path) path = require('path');
    cwd = path.resolve(dir, cwd);
    };
    })();

    })()
    },{"path":6,"vm":7}],8:[function(require,module,exports){
    // shim for using process in browser

    var process = module.exports = {};

    process.nextTick = (function () {
    var canSetImmediate = typeof window !== 'undefined'
    && window.setImmediate;
    var canPost = typeof window !== 'undefined'
    && window.postMessage && window.addEventListener
    ;

    if (canSetImmediate) {
    return function (f) { return window.setImmediate(f) };
    }

    if (canPost) {
    var queue = [];
    window.addEventListener('message', function (ev) {
    if (ev.source === window && ev.data === 'process-tick') {
    ev.stopPropagation();
    if (queue.length > 0) {
    var fn = queue.shift();
    fn();
    }
    }
    }, true);

    return function nextTick(fn) {
    queue.push(fn);
    window.postMessage('process-tick', '*');
    };
    }

    return function nextTick(fn) {
    setTimeout(fn, 0);
    };
    })();

    process.title = 'browser';
    process.browser = true;
    process.env = {};
    process.argv = [];

    process.binding = function (name) {
    throw new Error('process.binding is not supported');
    }

    // TODO(shtylman)
    process.cwd = function () { return '/' };
    process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
    };

    },{}],6:[function(require,module,exports){
    (function(process){function filter (xs, fn) {
    var res = [];
    for (var i = 0; i < xs.length; i++) {
    if (fn(xs[i], i, xs)) res.push(xs[i]);
    }
    return res;
    }

    // resolves . and .. elements in a path array with directory names there
    // must be no slashes, empty elements, or device names (c:\) in the array
    // (so also no leading and trailing slashes - it does not distinguish
    // relative and absolute paths)
    function normalizeArray(parts, allowAboveRoot) {
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = parts.length; i >= 0; i--) {
    var last = parts[i];
    if (last == '.') {
    parts.splice(i, 1);
    } else if (last === '..') {
    parts.splice(i, 1);
    up++;
    } else if (up) {
    parts.splice(i, 1);
    up--;
    }
    }

    // if the path is allowed to go above the root, restore leading ..s
    if (allowAboveRoot) {
    for (; up--; up) {
    parts.unshift('..');
    }
    }

    return parts;
    }

    // Regex to split a filename into [*, dir, basename, ext]
    // posix version
    var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;

    // path.resolve([from ...], to)
    // posix version
    exports.resolve = function() {
    var resolvedPath = '',
    resolvedAbsolute = false;

    for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
    var path = (i >= 0)
    ? arguments[i]
    : process.cwd();

    // Skip empty and invalid entries
    if (typeof path !== 'string' || !path) {
    continue;
    }

    resolvedPath = path + '/' + resolvedPath;
    resolvedAbsolute = path.charAt(0) === '/';
    }

    // At this point the path should be resolved to a full absolute path, but
    // handle relative paths to be safe (might happen when process.cwd() fails)

    // Normalize the path
    resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
    return !!p;
    }), !resolvedAbsolute).join('/');

    return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
    };

    // path.normalize(path)
    // posix version
    exports.normalize = function(path) {
    var isAbsolute = path.charAt(0) === '/',
    trailingSlash = path.slice(-1) === '/';

    // Normalize the path
    path = normalizeArray(filter(path.split('/'), function(p) {
    return !!p;
    }), !isAbsolute).join('/');

    if (!path && !isAbsolute) {
    path = '.';
    }
    if (path && trailingSlash) {
    path += '/';
    }

    return (isAbsolute ? '/' : '') + path;
    };


    // posix version
    exports.join = function() {
    var paths = Array.prototype.slice.call(arguments, 0);
    return exports.normalize(filter(paths, function(p, index) {
    return p && typeof p === 'string';
    }).join('/'));
    };


    exports.dirname = function(path) {
    var dir = splitPathRe.exec(path)[1] || '';
    var isWindows = false;
    if (!dir) {
    // No dirname
    return '.';
    } else if (dir.length === 1 ||
    (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
    // It is just a slash or a drive letter with a slash
    return dir;
    } else {
    // It is a full dirname, strip trailing slash
    return dir.substring(0, dir.length - 1);
    }
    };


    exports.basename = function(path, ext) {
    var f = splitPathRe.exec(path)[2] || '';
    // TODO: make this comparison case-insensitive on windows?
    if (ext && f.substr(-1 * ext.length) === ext) {
    f = f.substr(0, f.length - ext.length);
    }
    return f;
    };


    exports.extname = function(path) {
    return splitPathRe.exec(path)[3] || '';
    };

    exports.relative = function(from, to) {
    from = exports.resolve(from).substr(1);
    to = exports.resolve(to).substr(1);

    function trim(arr) {
    var start = 0;
    for (; start < arr.length; start++) {
    if (arr[start] !== '') break;
    }

    var end = arr.length - 1;
    for (; end >= 0; end--) {
    if (arr[end] !== '') break;
    }

    if (start > end) return [];
    return arr.slice(start, end - start + 1);
    }

    var fromParts = trim(from.split('/'));
    var toParts = trim(to.split('/'));

    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
    if (fromParts[i] !== toParts[i]) {
    samePartsLength = i;
    break;
    }
    }

    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
    outputParts.push('..');
    }

    outputParts = outputParts.concat(toParts.slice(samePartsLength));

    return outputParts.join('/');
    };

    })(require("__browserify_process"))
    },{"__browserify_process":8}],3:[function(require,module,exports){
    var inserted = [];

    module.exports = function (css) {
    if (inserted.indexOf(css) >= 0) return;
    inserted.push(css);

    var elem = document.createElement('style');
    var text = document.createTextNode(css);
    elem.appendChild(text);

    if (document.head.childNodes.length) {
    document.head.insertBefore(elem, document.head.childNodes[0]);
    }
    else {
    document.head.appendChild(elem);
    }
    };

    },{}],7:[function(require,module,exports){
    var Object_keys = function (obj) {
    if (Object.keys) return Object.keys(obj)
    else {
    var res = [];
    for (var key in obj) res.push(key)
    return res;
    }
    };

    var forEach = function (xs, fn) {
    if (xs.forEach) return xs.forEach(fn)
    else for (var i = 0; i < xs.length; i++) {
    fn(xs[i], i, xs);
    }
    };

    var Script = exports.Script = function NodeScript (code) {
    if (!(this instanceof Script)) return new Script(code);
    this.code = code;
    };

    Script.prototype.runInNewContext = function (context) {
    if (!context) context = {};

    var iframe = document.createElement('iframe');
    if (!iframe.style) iframe.style = {};
    iframe.style.display = 'none';

    document.body.appendChild(iframe);

    var win = iframe.contentWindow;

    forEach(Object_keys(context), function (key) {
    win[key] = context[key];
    });

    if (!win.eval && win.execScript) {
    // win.eval() magically appears when this is called in IE:
    win.execScript('null');
    }

    var res = win.eval(this.code);

    forEach(Object_keys(win), function (key) {
    context[key] = win[key];
    });

    document.body.removeChild(iframe);

    return res;
    };

    Script.prototype.runInThisContext = function () {
    return eval(this.code); // maybe...
    };

    Script.prototype.runInContext = function (context) {
    // seems to be just runInNewContext on magical context objects which are
    // otherwise indistinguishable from objects except plain old objects
    // for the parameter segfaults node
    return this.runInNewContext(context);
    };

    forEach(Object_keys(Script.prototype), function (name) {
    exports[name] = Script[name] = function (code) {
    var s = Script(code);
    return s[name].apply(s, [].slice.call(arguments, 1));
    };
    });

    exports.createScript = function (code) {
    return exports.Script(code);
    };

    exports.createContext = Script.createContext = function (context) {
    // not really sure what this one does
    // seems to just make a shallow copy
    var copy = {};
    if(typeof context === 'object') {
    forEach(Object_keys(context), function (key) {
    copy[key] = context[key];
    });
    }
    return copy;
    };

    },{}],4:[function(require,module,exports){
    /**
    * Module dependencies.
    */

    var prefixed = require('prefixed');

    /**
    * Expose `fade`.
    */

    module.exports = fade;

    /**
    * Fade `el` to `opacity` in `duration` seconds.
    *
    * @param {Element} el
    * @param {Number} opacity
    * @param {Number=} duration
    *
    * @todo Add other vendor prefixes
    * @todo Properly clear transition
    */

    function fade (el, opacity, duration) {
    if (typeof duration === 'undefined') duration = 1000;

    var oldTransition = prefixed.get(el.style, 'transition') || '';
    prefixed(el.style, 'transition', 'opacity ' + (duration/1000) + 's');
    el.style.opacity = opacity;

    setTimeout(function () {
    prefixed(el.style, 'transition', oldTransition);
    }, duration);
    }

    /**
    * Fade in `el`.
    *
    * @param {Element} el
    * @param {Number=} duration
    */

    fade.out = function (el, duration) {
    fade(el, 0, duration);
    };

    /**
    * Fade out `el`.
    *
    * @param {Element} el
    * @param {Number=} duration
    */

    fade['in'] = function (el, duration) {
    fade(el, 1, duration);
    };

    },{"prefixed":9}],5:[function(require,module,exports){
    /**
    * Module dependencies.
    */

    var autoscale = require('autoscale-canvas');
    var raf = require('raf-component');

    /**
    * Expose `Spinner`.
    */

    module.exports = Spinner;

    /**
    * Initialize a new `Spinner`.
    */

    function Spinner() {
    var self = this;
    this.percent = 0;
    this.el = document.createElement('canvas');
    this.ctx = this.el.getContext('2d');
    this.size(50);
    this.fontSize(11);
    this.speed(60);
    this.font('helvetica, arial, sans-serif');
    this.stopped = false;

    (function animate() {
    if (self.stopped) return;
    raf(animate);
    self.percent = (self.percent + self._speed / 36) % 100;
    self.draw(self.ctx);
    })();
    }

    /**
    * Stop the animation.
    *
    * @api public
    */

    Spinner.prototype.stop = function(){
    this.stopped = true;
    };

    /**
    * Set spinner size to `n`.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.size = function(n){
    this.el.width = n;
    this.el.height = n;
    autoscale(this.el);
    return this;
    };

    /**
    * Set text to `str`.
    *
    * @param {String} str
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.text = function(str){
    this._text = str;
    return this;
    };

    /**
    * Set font size to `n`.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.fontSize = function(n){
    this._fontSize = n;
    return this;
    };

    /**
    * Set font `family`.
    *
    * @param {String} family
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.font = function(family){
    this._font = family;
    return this;
    };

    /**
    * Set speed to `n` rpm.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.speed = function(n) {
    this._speed = n;
    return this;
    };

    /**
    * Make the spinner light colored.
    *
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.light = function(){
    this._light = true;
    return this;
    };

    /**
    * Draw on `ctx`.
    *
    * @param {CanvasRenderingContext2d} ctx
    * @return {Spinner}
    * @api private
    */

    Spinner.prototype.draw = function(ctx){
    var percent = Math.min(this.percent, 100)
    , ratio = window.devicePixelRatio || 1
    , size = this.el.width / ratio
    , half = size / 2
    , x = half
    , y = half
    , rad = half - 1
    , fontSize = this._fontSize
    , light = this._light;

    ctx.font = fontSize + 'px ' + this._font;

    var angle = Math.PI * 2 * (percent / 100);
    ctx.clearRect(0, 0, size, size);

    // outer circle
    var grad = ctx.createLinearGradient(
    half + Math.sin(Math.PI * 1.5 - angle) * half,
    half + Math.cos(Math.PI * 1.5 - angle) * half,
    half + Math.sin(Math.PI * 0.5 - angle) * half,
    half + Math.cos(Math.PI * 0.5 - angle) * half
    );

    // color
    if (light) {
    grad.addColorStop(0, 'rgba(255, 255, 255, 0)');
    grad.addColorStop(1, 'rgba(255, 255, 255, 1)');
    } else {
    grad.addColorStop(0, 'rgba(0, 0, 0, 0)');
    grad.addColorStop(1, 'rgba(0, 0, 0, 1)');
    }

    ctx.strokeStyle = grad;
    ctx.beginPath();
    ctx.arc(x, y, rad, angle - Math.PI, angle, false);
    ctx.stroke();

    // inner circle
    ctx.strokeStyle = light ? 'rgba(255, 255, 255, .4)' : '#eee';
    ctx.beginPath();
    ctx.arc(x, y, rad - 1, 0, Math.PI * 2, true);
    ctx.stroke();

    // text
    var text = this._text || ''
    , w = ctx.measureText(text).width;

    if (light) ctx.fillStyle = 'rgba(255, 255, 255, .9)';
    ctx.fillText(
    text
    , x - w / 2 + 1
    , y + fontSize / 2 - 1);

    return this;
    };


    },{"autoscale-canvas":10,"raf-component":11}],9:[function(require,module,exports){
    /**
    * Supported prefixes.
    */

    var prefixes = [
    '-webkit-', '-moz-', '-o-', '-ms-', ''
    ];

    /**
    * Expose `prefixed`.
    */

    module.exports = prefixed;

    /**
    * Set a style with all the vendor prefixes.
    *
    * @param {Object} style
    * @param {String} attribute
    * @param {String} value
    */

    function prefixed (style, attribute, value) {
    for (var i = 0; i < prefixes.length; i++) {
    style[prefixes[i] + attribute] = value;
    }
    };

    /**
    * Get a (possibly prefixed) value.
    *
    * @param {Object} style
    * @param {String} attribute
    * @return {String}
    */

    prefixed.get = function (style, attribute) {
    for (var i = 0; i < prefixes.length; i++) {
    var value = style[prefixes[i] + attribute];
    if (value && value != '') return value;
    }
    return '';
    };


    },{}],10:[function(require,module,exports){

    /**
    * Retina-enable the given `canvas`.
    *
    * @param {Canvas} canvas
    * @return {Canvas}
    * @api public
    */

    module.exports = function(canvas){
    var ctx = canvas.getContext('2d');
    var ratio = window.devicePixelRatio || 1;
    if (1 != ratio) {
    canvas.style.width = canvas.width + 'px';
    canvas.style.height = canvas.height + 'px';
    canvas.width *= ratio;
    canvas.height *= ratio;
    ctx.scale(ratio, ratio);
    }
    return canvas;
    };
    },{}],11:[function(require,module,exports){

    module.exports = window.requestAnimationFrame
    || window.webkitRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.oRequestAnimationFrame
    || window.msRequestAnimationFrame
    || fallback;

    var prev = new Date().getTime();
    function fallback(fn) {
    var curr = new Date().getTime();
    var ms = Math.max(0, 16 - (curr - prev));
    setTimeout(fn, ms);
    prev = curr;
    }

    },{}]},{},[])
    //@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvdG1wL3NwaW5uaW5nMTEzNjYtMTEyODEtOTkyZXVyL25vZGVfbW9kdWxlcy9zcGlubmluZy9zdHlsZS5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL2luZGV4LmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItYnVpbHRpbnMvYnVpbHRpbi9wcm9jZXNzLmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2luc2VydC1tb2R1bGUtZ2xvYmFscy9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItYnVpbHRpbnMvYnVpbHRpbi9wYXRoLmpzIiwiL3RtcC9zcGlubmluZzExMzY2LTExMjgxLTk5MmV1ci9ub2RlX21vZHVsZXMvc3Bpbm5pbmcvbm9kZV9tb2R1bGVzL2luc2VydC1jc3MvaW5kZXguanMiLCIvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1idWlsdGlucy9ub2RlX21vZHVsZXMvdm0tYnJvd3NlcmlmeS9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9mYWRlL2luZGV4LmpzIiwiL3RtcC9zcGlubmluZzExMzY2LTExMjgxLTk5MmV1ci9ub2RlX21vZHVsZXMvc3Bpbm5pbmcvbm9kZV9tb2R1bGVzL3NwaW5uZXItYnJvd3NlcmlmeS9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9mYWRlL25vZGVfbW9kdWxlcy9wcmVmaXhlZC9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9zcGlubmVyLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2F1dG9zY2FsZS1jYW52YXMvaW5kZXguanMiLCIvdG1wL3NwaW5uaW5nMTEzNjYtMTEyODEtOTkyZXVyL25vZGVfbW9kdWxlcy9zcGlubmluZy9ub2RlX21vZHVsZXMvc3Bpbm5lci1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9yYWYtY29tcG9uZW50L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gJy5zcGlubmVyLCAub3ZlcmxheSB7XFxuICBwb3NpdGlvbjogZml4ZWQ7XFxuICBvcGFjaXR5OiAwO1xcbn1cXG5cXG4uc3Bpbm5lciB7XFxuICBsZWZ0OiA1MCU7XFxuICB0b3A6IDUwJTtcXG4gIG1hcmdpbi1sZWZ0OiAtMTAwcHg7XFxuICBtYXJnaW4tdG9wOiAtMTAwcHg7XFxuICB6LWluZGV4OiAyMjIyMjIyMjIyO1xcbn1cXG5cXG4ub3ZlcmxheSB7XFxuICBsZWZ0OiAwO1xcbiAgdG9wOiAwO1xcbiAgd2lkdGg6IDEwMCU7XFxuICBoZWlnaHQ6IDEwMCU7XFxuICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTtcXG4gIHotaW5kZXg6IDExMTExMTExMTE7XFxufVxcbic7IiwiKGZ1bmN0aW9uKCl7dmFyIFNwaW5uZXIgPSByZXF1aXJlKCdzcGlubmVyLWJyb3dzZXJpZnknKTtcbnZhciBpbnNlcnRDc3MgPSByZXF1aXJlKCdpbnNlcnQtY3NzJyk7XG52YXIgc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG52YXIgZmFkZSA9IHJlcXVpcmUoJ2ZhZGUnKTtcbnZhciBwcm9jZXNzID0gcmVxdWlyZSgncHJvY2VzcycpOyAvLyBiZSBuaWNlIHRvIGJyb3dzZXJpZnlcblxubW9kdWxlLmV4cG9ydHMgPSBTcGluO1xuXG5mdW5jdGlvbiBTcGluICgpIHtcbiAgaW5zZXJ0Q3NzKHN0eWxlKTtcblxuICAvLyBkdXJhdGlvbnNcbiAgdmFyIGZhZGVJbiA9IDEwMDA7XG4gIHZhciBmYWRlT3V0ID0gMzAwO1xuXG4gIHZhciBvdmVybGF5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIG92ZXJsYXkuY2xhc3NOYW1lID0gJ292ZXJsYXknO1xuICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKG92ZXJsYXkpO1xuXG4gIHZhciBzcGlubmVyID0gbmV3IFNwaW5uZXIoKTtcbiAgc3Bpbm5lci5lbC5jbGFzc05hbWUgPSAnc3Bpbm5lcic7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc3Bpbm5lci5lbCk7XG5cbiAgcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgZmFkZShvdmVybGF5LCAwLjgsIGZhZGVJbik7XG4gICAgZmFkZS5pbihzcGlubmVyLmVsLCBmYWRlSW4pO1xuICB9KTtcblxuICBzcGlubmVyLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBmYWRlLm91dChvdmVybGF5LCBmYWRlT3V0KTtcbiAgICBmYWRlLm91dChzcGlubmVyLmVsLCBmYWRlT3V0KTtcblxuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgc3Bpbm5lci5zdG9wKCk7XG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKG92ZXJsYXkpO1xuICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzcGlubmVyLmVsKTtcbiAgICB9LCBmYWRlT3V0KTtcbiAgfTtcblxuICAvLyByZXBvc2l0aW9uXG4gIHZhciBzaXplID0gc3Bpbm5lci5zaXplO1xuICBzcGlubmVyLnNpemUgPSBmdW5jdGlvbiAobikge1xuICAgIHNwaW5uZXIuZWwuc3R5bGUubWFyZ2luTGVmdCA9XG4gICAgc3Bpbm5lci5lbC5zdHlsZS5tYXJnaW5Ub3AgPSAnLScgKyAobi8yKSArICdweCc7XG4gICAgcmV0dXJuIHNpemUuY2FsbChzcGlubmVyLCBuKTtcbiAgfTtcblxuICB2YXIgbGlnaHQgPSBzcGlubmVyLmxpZ2h0O1xuICBzcGlubmVyLmxpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgIG92ZXJsYXkuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ2JsYWNrJztcbiAgICByZXR1cm4gbGlnaHQuY2FsbChzcGlubmVyKTtcbiAgfTtcblxuICAvLyBzZXQgZHVyYXRpb25zXG4gIHNwaW5uZXJbJ2luJ10gPSBmdW5jdGlvbiAobXMpIHsgZmFkZUluID0gbXMgfTtcbiAgc3Bpbm5lci5vdXQgPSBmdW5jdGlvbiAobXMpIHsgZmFkZU91dCA9IG1zIH07XG5cbiAgcmV0dXJuIHNwaW5uZXI7XG59XG5cbn0pKCkiLCIoZnVuY3Rpb24oKXt2YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbnByb2Nlc3MubmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5TZXRJbW1lZGlhdGUgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICAmJiB3aW5kb3cuc2V0SW1tZWRpYXRlO1xuICAgIHZhciBjYW5Qb3N0ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChldi5zb3VyY2UgPT09IHdpbmRvdyAmJiBldi5kYXRhID09PSAnYnJvd3NlcmlmeS10aWNrJykge1xuICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdicm93c2VyaWZ5LXRpY2snLCAnKicpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICB9O1xufSkoKTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKG5hbWUgPT09ICdldmFscycpIHJldHVybiAocmVxdWlyZSkoJ3ZtJylcbiAgICBlbHNlIHRocm93IG5ldyBFcnJvcignTm8gc3VjaCBtb2R1bGUuIChQb3NzaWJseSBub3QgeWV0IGxvYWRlZCknKVxufTtcblxuKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgY3dkID0gJy8nO1xuICAgIHZhciBwYXRoO1xuICAgIHByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gY3dkIH07XG4gICAgcHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgaWYgKCFwYXRoKSBwYXRoID0gcmVxdWlyZSgncGF0aCcpO1xuICAgICAgICBjd2QgPSBwYXRoLnJlc29sdmUoZGlyLCBjd2QpO1xuICAgIH07XG59KSgpO1xuXG59KSgpIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChldi5zb3VyY2UgPT09IHdpbmRvdyAmJiBldi5kYXRhID09PSAncHJvY2Vzcy10aWNrJykge1xuICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdwcm9jZXNzLXRpY2snLCAnKicpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICB9O1xufSkoKTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCIoZnVuY3Rpb24ocHJvY2Vzcyl7ZnVuY3Rpb24gZmlsdGVyICh4cywgZm4pIHtcbiAgICB2YXIgcmVzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB4cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZm4oeHNbaV0sIGksIHhzKSkgcmVzLnB1c2goeHNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyByZXNvbHZlcyAuIGFuZCAuLiBlbGVtZW50cyBpbiBhIHBhdGggYXJyYXkgd2l0aCBkaXJlY3RvcnkgbmFtZXMgdGhlcmVcbi8vIG11c3QgYmUgbm8gc2xhc2hlcywgZW1wdHkgZWxlbWVudHMsIG9yIGRldmljZSBuYW1lcyAoYzpcXCkgaW4gdGhlIGFycmF5XG4vLyAoc28gYWxzbyBubyBsZWFkaW5nIGFuZCB0cmFpbGluZyBzbGFzaGVzIC0gaXQgZG9lcyBub3QgZGlzdGluZ3Vpc2hcbi8vIHJlbGF0aXZlIGFuZCBhYnNvbHV0ZSBwYXRocylcbmZ1bmN0aW9uIG5vcm1hbGl6ZUFycmF5KHBhcnRzLCBhbGxvd0Fib3ZlUm9vdCkge1xuICAvLyBpZiB0aGUgcGF0aCB0cmllcyB0byBnbyBhYm92ZSB0aGUgcm9vdCwgYHVwYCBlbmRzIHVwID4gMFxuICB2YXIgdXAgPSAwO1xuICBmb3IgKHZhciBpID0gcGFydHMubGVuZ3RoOyBpID49IDA7IGktLSkge1xuICAgIHZhciBsYXN0ID0gcGFydHNbaV07XG4gICAgaWYgKGxhc3QgPT0gJy4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgfSBlbHNlIGlmIChsYXN0ID09PSAnLi4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICB1cCsrO1xuICAgIH0gZWxzZSBpZiAodXApIHtcbiAgICAgIHBhcnRzLnNwbGljZShpLCAxKTtcbiAgICAgIHVwLS07XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhdGggaXMgYWxsb3dlZCB0byBnbyBhYm92ZSB0aGUgcm9vdCwgcmVzdG9yZSBsZWFkaW5nIC4uc1xuICBpZiAoYWxsb3dBYm92ZVJvb3QpIHtcbiAgICBmb3IgKDsgdXAtLTsgdXApIHtcbiAgICAgIHBhcnRzLnVuc2hpZnQoJy4uJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG4vLyBSZWdleCB0byBzcGxpdCBhIGZpbGVuYW1lIGludG8gWyosIGRpciwgYmFzZW5hbWUsIGV4dF1cbi8vIHBvc2l4IHZlcnNpb25cbnZhciBzcGxpdFBhdGhSZSA9IC9eKC4rXFwvKD8hJCl8XFwvKT8oKD86Lis/KT8oXFwuW14uXSopPykkLztcblxuLy8gcGF0aC5yZXNvbHZlKFtmcm9tIC4uLl0sIHRvKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5yZXNvbHZlID0gZnVuY3Rpb24oKSB7XG52YXIgcmVzb2x2ZWRQYXRoID0gJycsXG4gICAgcmVzb2x2ZWRBYnNvbHV0ZSA9IGZhbHNlO1xuXG5mb3IgKHZhciBpID0gYXJndW1lbnRzLmxlbmd0aDsgaSA+PSAtMSAmJiAhcmVzb2x2ZWRBYnNvbHV0ZTsgaS0tKSB7XG4gIHZhciBwYXRoID0gKGkgPj0gMClcbiAgICAgID8gYXJndW1lbnRzW2ldXG4gICAgICA6IHByb2Nlc3MuY3dkKCk7XG5cbiAgLy8gU2tpcCBlbXB0eSBhbmQgaW52YWxpZCBlbnRyaWVzXG4gIGlmICh0eXBlb2YgcGF0aCAhPT0gJ3N0cmluZycgfHwgIXBhdGgpIHtcbiAgICBjb250aW51ZTtcbiAgfVxuXG4gIHJlc29sdmVkUGF0aCA9IHBhdGggKyAnLycgKyByZXNvbHZlZFBhdGg7XG4gIHJlc29sdmVkQWJzb2x1dGUgPSBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nO1xufVxuXG4vLyBBdCB0aGlzIHBvaW50IHRoZSBwYXRoIHNob3VsZCBiZSByZXNvbHZlZCB0byBhIGZ1bGwgYWJzb2x1dGUgcGF0aCwgYnV0XG4vLyBoYW5kbGUgcmVsYXRpdmUgcGF0aHMgdG8gYmUgc2FmZSAobWlnaHQgaGFwcGVuIHdoZW4gcHJvY2Vzcy5jd2QoKSBmYWlscylcblxuLy8gTm9ybWFsaXplIHRoZSBwYXRoXG5yZXNvbHZlZFBhdGggPSBub3JtYWxpemVBcnJheShmaWx0ZXIocmVzb2x2ZWRQYXRoLnNwbGl0KCcvJyksIGZ1bmN0aW9uKHApIHtcbiAgICByZXR1cm4gISFwO1xuICB9KSwgIXJlc29sdmVkQWJzb2x1dGUpLmpvaW4oJy8nKTtcblxuICByZXR1cm4gKChyZXNvbHZlZEFic29sdXRlID8gJy8nIDogJycpICsgcmVzb2x2ZWRQYXRoKSB8fCAnLic7XG59O1xuXG4vLyBwYXRoLm5vcm1hbGl6ZShwYXRoKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5ub3JtYWxpemUgPSBmdW5jdGlvbihwYXRoKSB7XG52YXIgaXNBYnNvbHV0ZSA9IHBhdGguY2hhckF0KDApID09PSAnLycsXG4gICAgdHJhaWxpbmdTbGFzaCA9IHBhdGguc2xpY2UoLTEpID09PSAnLyc7XG5cbi8vIE5vcm1hbGl6ZSB0aGUgcGF0aFxucGF0aCA9IG5vcm1hbGl6ZUFycmF5KGZpbHRlcihwYXRoLnNwbGl0KCcvJyksIGZ1bmN0aW9uKHApIHtcbiAgICByZXR1cm4gISFwO1xuICB9KSwgIWlzQWJzb2x1dGUpLmpvaW4oJy8nKTtcblxuICBpZiAoIXBhdGggJiYgIWlzQWJzb2x1dGUpIHtcbiAgICBwYXRoID0gJy4nO1xuICB9XG4gIGlmIChwYXRoICYmIHRyYWlsaW5nU2xhc2gpIHtcbiAgICBwYXRoICs9ICcvJztcbiAgfVxuICBcbiAgcmV0dXJuIChpc0Fic29sdXRlID8gJy8nIDogJycpICsgcGF0aDtcbn07XG5cblxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5qb2luID0gZnVuY3Rpb24oKSB7XG4gIHZhciBwYXRocyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG4gIHJldHVybiBleHBvcnRzLm5vcm1hbGl6ZShmaWx0ZXIocGF0aHMsIGZ1bmN0aW9uKHAsIGluZGV4KSB7XG4gICAgcmV0dXJuIHAgJiYgdHlwZW9mIHAgPT09ICdzdHJpbmcnO1xuICB9KS5qb2luKCcvJykpO1xufTtcblxuXG5leHBvcnRzLmRpcm5hbWUgPSBmdW5jdGlvbihwYXRoKSB7XG4gIHZhciBkaXIgPSBzcGxpdFBhdGhSZS5leGVjKHBhdGgpWzFdIHx8ICcnO1xuICB2YXIgaXNXaW5kb3dzID0gZmFsc2U7XG4gIGlmICghZGlyKSB7XG4gICAgLy8gTm8gZGlybmFtZVxuICAgIHJldHVybiAnLic7XG4gIH0gZWxzZSBpZiAoZGlyLmxlbmd0aCA9PT0gMSB8fFxuICAgICAgKGlzV2luZG93cyAmJiBkaXIubGVuZ3RoIDw9IDMgJiYgZGlyLmNoYXJBdCgxKSA9PT0gJzonKSkge1xuICAgIC8vIEl0IGlzIGp1c3QgYSBzbGFzaCBvciBhIGRyaXZlIGxldHRlciB3aXRoIGEgc2xhc2hcbiAgICByZXR1cm4gZGlyO1xuICB9IGVsc2Uge1xuICAgIC8vIEl0IGlzIGEgZnVsbCBkaXJuYW1lLCBzdHJpcCB0cmFpbGluZyBzbGFzaFxuICAgIHJldHVybiBkaXIuc3Vic3RyaW5nKDAsIGRpci5sZW5ndGggLSAxKTtcbiAgfVxufTtcblxuXG5leHBvcnRzLmJhc2VuYW1lID0gZnVuY3Rpb24ocGF0aCwgZXh0KSB7XG4gIHZhciBmID0gc3BsaXRQYXRoUmUuZXhlYyhwYXRoKVsyXSB8fCAnJztcbiAgLy8gVE9ETzogbWFrZSB0aGlzIGNvbXBhcmlzb24gY2FzZS1pbnNlbnNpdGl2ZSBvbiB3aW5kb3dzP1xuICBpZiAoZXh0ICYmIGYuc3Vic3RyKC0xICogZXh0Lmxlbmd0aCkgPT09IGV4dCkge1xuICAgIGYgPSBmLnN1YnN0cigwLCBmLmxlbmd0aCAtIGV4dC5sZW5ndGgpO1xuICB9XG4gIHJldHVybiBmO1xufTtcblxuXG5leHBvcnRzLmV4dG5hbWUgPSBmdW5jdGlvbihwYXRoKSB7XG4gIHJldHVybiBzcGxpdFBhdGhSZS5leGVjKHBhdGgpWzNdIHx8ICcnO1xufTtcblxuZXhwb3J0cy5yZWxhdGl2ZSA9IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gIGZyb20gPSBleHBvcnRzLnJlc29sdmUoZnJvbSkuc3Vic3RyKDEpO1xuICB0byA9IGV4cG9ydHMucmVzb2x2ZSh0bykuc3Vic3RyKDEpO1xuXG4gIGZ1bmN0aW9uIHRyaW0oYXJyKSB7XG4gICAgdmFyIHN0YXJ0ID0gMDtcbiAgICBmb3IgKDsgc3RhcnQgPCBhcnIubGVuZ3RoOyBzdGFydCsrKSB7XG4gICAgICBpZiAoYXJyW3N0YXJ0XSAhPT0gJycpIGJyZWFrO1xuICAgIH1cblxuICAgIHZhciBlbmQgPSBhcnIubGVuZ3RoIC0gMTtcbiAgICBmb3IgKDsgZW5kID49IDA7IGVuZC0tKSB7XG4gICAgICBpZiAoYXJyW2VuZF0gIT09ICcnKSBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoc3RhcnQgPiBlbmQpIHJldHVybiBbXTtcbiAgICByZXR1cm4gYXJyLnNsaWNlKHN0YXJ0LCBlbmQgLSBzdGFydCArIDEpO1xuICB9XG5cbiAgdmFyIGZyb21QYXJ0cyA9IHRyaW0oZnJvbS5zcGxpdCgnLycpKTtcbiAgdmFyIHRvUGFydHMgPSB0cmltKHRvLnNwbGl0KCcvJykpO1xuXG4gIHZhciBsZW5ndGggPSBNYXRoLm1pbihmcm9tUGFydHMubGVuZ3RoLCB0b1BhcnRzLmxlbmd0aCk7XG4gIHZhciBzYW1lUGFydHNMZW5ndGggPSBsZW5ndGg7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZnJvbVBhcnRzW2ldICE9PSB0b1BhcnRzW2ldKSB7XG4gICAgICBzYW1lUGFydHNMZW5ndGggPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgdmFyIG91dHB1dFBhcnRzID0gW107XG4gIGZvciAodmFyIGkgPSBzYW1lUGFydHNMZW5ndGg7IGkgPCBmcm9tUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICBvdXRwdXRQYXJ0cy5wdXNoKCcuLicpO1xuICB9XG5cbiAgb3V0cHV0UGFydHMgPSBvdXRwdXRQYXJ0cy5jb25jYXQodG9QYXJ0cy5zbGljZShzYW1lUGFydHNMZW5ndGgpKTtcblxuICByZXR1cm4gb3V0cHV0UGFydHMuam9pbignLycpO1xufTtcblxufSkocmVxdWlyZShcIl9fYnJvd3NlcmlmeV9wcm9jZXNzXCIpKSIsInZhciBpbnNlcnRlZCA9IFtdO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjc3MpIHtcbiAgICBpZiAoaW5zZXJ0ZWQuaW5kZXhPZihjc3MpID49IDApIHJldHVybjtcbiAgICBpbnNlcnRlZC5wdXNoKGNzcyk7XG4gICAgXG4gICAgdmFyIGVsZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuICAgIHZhciB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKTtcbiAgICBlbGVtLmFwcGVuZENoaWxkKHRleHQpO1xuICAgIFxuICAgIGlmIChkb2N1bWVudC5oZWFkLmNoaWxkTm9kZXMubGVuZ3RoKSB7XG4gICAgICAgIGRvY3VtZW50LmhlYWQuaW5zZXJ0QmVmb3JlKGVsZW0sIGRvY3VtZW50LmhlYWQuY2hpbGROb2Rlc1swXSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGVsZW0pO1xuICAgIH1cbn07XG4iLCJ2YXIgT2JqZWN0X2tleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgaWYgKE9iamVjdC5rZXlzKSByZXR1cm4gT2JqZWN0LmtleXMob2JqKVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHJlcy5wdXNoKGtleSlcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG59O1xuXG52YXIgZm9yRWFjaCA9IGZ1bmN0aW9uICh4cywgZm4pIHtcbiAgICBpZiAoeHMuZm9yRWFjaCkgcmV0dXJuIHhzLmZvckVhY2goZm4pXG4gICAgZWxzZSBmb3IgKHZhciBpID0gMDsgaSA8IHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZuKHhzW2ldLCBpLCB4cyk7XG4gICAgfVxufTtcblxudmFyIFNjcmlwdCA9IGV4cG9ydHMuU2NyaXB0ID0gZnVuY3Rpb24gTm9kZVNjcmlwdCAoY29kZSkge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTY3JpcHQpKSByZXR1cm4gbmV3IFNjcmlwdChjb2RlKTtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xufTtcblxuU2NyaXB0LnByb3RvdHlwZS5ydW5Jbk5ld0NvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIGlmICghY29udGV4dCkgY29udGV4dCA9IHt9O1xuICAgIFxuICAgIHZhciBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZiAoIWlmcmFtZS5zdHlsZSkgaWZyYW1lLnN0eWxlID0ge307XG4gICAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChpZnJhbWUpO1xuICAgIFxuICAgIHZhciB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcbiAgICBcbiAgICBmb3JFYWNoKE9iamVjdF9rZXlzKGNvbnRleHQpLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHdpbltrZXldID0gY29udGV4dFtrZXldO1xuICAgIH0pO1xuICAgICBcbiAgICBpZiAoIXdpbi5ldmFsICYmIHdpbi5leGVjU2NyaXB0KSB7XG4gICAgICAgIC8vIHdpbi5ldmFsKCkgbWFnaWNhbGx5IGFwcGVhcnMgd2hlbiB0aGlzIGlzIGNhbGxlZCBpbiBJRTpcbiAgICAgICAgd2luLmV4ZWNTY3JpcHQoJ251bGwnKTtcbiAgICB9XG4gICAgXG4gICAgdmFyIHJlcyA9IHdpbi5ldmFsKHRoaXMuY29kZSk7XG4gICAgXG4gICAgZm9yRWFjaChPYmplY3Rfa2V5cyh3aW4pLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGNvbnRleHRba2V5XSA9IHdpbltrZXldO1xuICAgIH0pO1xuICAgIFxuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcbiAgICBcbiAgICByZXR1cm4gcmVzO1xufTtcblxuU2NyaXB0LnByb3RvdHlwZS5ydW5JblRoaXNDb250ZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBldmFsKHRoaXMuY29kZSk7IC8vIG1heWJlLi4uXG59O1xuXG5TY3JpcHQucHJvdG90eXBlLnJ1bkluQ29udGV4dCA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgLy8gc2VlbXMgdG8gYmUganVzdCBydW5Jbk5ld0NvbnRleHQgb24gbWFnaWNhbCBjb250ZXh0IG9iamVjdHMgd2hpY2ggYXJlXG4gICAgLy8gb3RoZXJ3aXNlIGluZGlzdGluZ3Vpc2hhYmxlIGZyb20gb2JqZWN0cyBleGNlcHQgcGxhaW4gb2xkIG9iamVjdHNcbiAgICAvLyBmb3IgdGhlIHBhcmFtZXRlciBzZWdmYXVsdHMgbm9kZVxuICAgIHJldHVybiB0aGlzLnJ1bkluTmV3Q29udGV4dChjb250ZXh0KTtcbn07XG5cbmZvckVhY2goT2JqZWN0X2tleXMoU2NyaXB0LnByb3RvdHlwZSksIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgZXhwb3J0c1tuYW1lXSA9IFNjcmlwdFtuYW1lXSA9IGZ1bmN0aW9uIChjb2RlKSB7XG4gICAgICAgIHZhciBzID0gU2NyaXB0KGNvZGUpO1xuICAgICAgICByZXR1cm4gc1tuYW1lXS5hcHBseShzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIH07XG59KTtcblxuZXhwb3J0cy5jcmVhdGVTY3JpcHQgPSBmdW5jdGlvbiAoY29kZSkge1xuICAgIHJldHVybiBleHBvcnRzLlNjcmlwdChjb2RlKTtcbn07XG5cbmV4cG9ydHMuY3JlYXRlQ29udGV4dCA9IFNjcmlwdC5jcmVhdGVDb250ZXh0ID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAvLyBub3QgcmVhbGx5IHN1cmUgd2hhdCB0aGlzIG9uZSBkb2VzXG4gICAgLy8gc2VlbXMgdG8ganVzdCBtYWtlIGEgc2hhbGxvdyBjb3B5XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICBpZih0eXBlb2YgY29udGV4dCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZm9yRWFjaChPYmplY3Rfa2V5cyhjb250ZXh0KSwgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgY29weVtrZXldID0gY29udGV4dFtrZXldO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGNvcHk7XG59O1xuIiwiLyoqXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzLlxuICovXG5cbnZhciBwcmVmaXhlZCA9IHJlcXVpcmUoJ3ByZWZpeGVkJyk7XG5cbi8qKlxuICogRXhwb3NlIGBmYWRlYC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZhZGU7XG5cbi8qKlxuICogRmFkZSBgZWxgIHRvIGBvcGFjaXR5YCBpbiBgZHVyYXRpb25gIHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbFxuICogQHBhcmFtIHtOdW1iZXJ9IG9wYWNpdHlcbiAqIEBwYXJhbSB7TnVtYmVyPX0gZHVyYXRpb25cbiAqXG4gKiBAdG9kbyBBZGQgb3RoZXIgdmVuZG9yIHByZWZpeGVzXG4gKiBAdG9kbyBQcm9wZXJseSBjbGVhciB0cmFuc2l0aW9uXG4gKi9cblxuZnVuY3Rpb24gZmFkZSAoZWwsIG9wYWNpdHksIGR1cmF0aW9uKSB7XG4gIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICd1bmRlZmluZWQnKSBkdXJhdGlvbiA9IDEwMDA7XG5cbiAgdmFyIG9sZFRyYW5zaXRpb24gPSBwcmVmaXhlZC5nZXQoZWwuc3R5bGUsICd0cmFuc2l0aW9uJykgfHwgJyc7XG4gIHByZWZpeGVkKGVsLnN0eWxlLCAndHJhbnNpdGlvbicsICdvcGFjaXR5ICcgKyAoZHVyYXRpb24vMTAwMCkgKyAncycpO1xuICBlbC5zdHlsZS5vcGFjaXR5ID0gb3BhY2l0eTtcblxuICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICBwcmVmaXhlZChlbC5zdHlsZSwgJ3RyYW5zaXRpb24nLCBvbGRUcmFuc2l0aW9uKTtcbiAgfSwgZHVyYXRpb24pO1xufVxuXG4vKipcbiAqIEZhZGUgaW4gYGVsYC5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge051bWJlcj19IGR1cmF0aW9uXG4gKi9cblxuZmFkZS5vdXQgPSBmdW5jdGlvbiAoZWwsIGR1cmF0aW9uKSB7XG4gIGZhZGUoZWwsIDAsIGR1cmF0aW9uKTtcbn07XG5cbi8qKlxuICogRmFkZSBvdXQgYGVsYC5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge051bWJlcj19IGR1cmF0aW9uXG4gKi9cblxuZmFkZVsnaW4nXSA9IGZ1bmN0aW9uIChlbCwgZHVyYXRpb24pIHtcbiAgZmFkZShlbCwgMSwgZHVyYXRpb24pO1xufTtcbiIsIi8qKlxuICogTW9kdWxlIGRlcGVuZGVuY2llcy5cbiAqL1xuXG52YXIgYXV0b3NjYWxlID0gcmVxdWlyZSgnYXV0b3NjYWxlLWNhbnZhcycpO1xudmFyIHJhZiA9IHJlcXVpcmUoJ3JhZi1jb21wb25lbnQnKTtcblxuLyoqXG4gKiBFeHBvc2UgYFNwaW5uZXJgLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gU3Bpbm5lcjtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBTcGlubmVyYC5cbiAqL1xuXG5mdW5jdGlvbiBTcGlubmVyKCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHRoaXMucGVyY2VudCA9IDA7XG4gIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgdGhpcy5jdHggPSB0aGlzLmVsLmdldENvbnRleHQoJzJkJyk7XG4gIHRoaXMuc2l6ZSg1MCk7XG4gIHRoaXMuZm9udFNpemUoMTEpO1xuICB0aGlzLnNwZWVkKDYwKTtcbiAgdGhpcy5mb250KCdoZWx2ZXRpY2EsIGFyaWFsLCBzYW5zLXNlcmlmJyk7XG4gIHRoaXMuc3RvcHBlZCA9IGZhbHNlO1xuXG4gIChmdW5jdGlvbiBhbmltYXRlKCkge1xuICAgIGlmIChzZWxmLnN0b3BwZWQpIHJldHVybjtcbiAgICByYWYoYW5pbWF0ZSk7XG4gICAgc2VsZi5wZXJjZW50ID0gKHNlbGYucGVyY2VudCArIHNlbGYuX3NwZWVkIC8gMzYpICUgMTAwO1xuICAgIHNlbGYuZHJhdyhzZWxmLmN0eCk7XG4gIH0pKCk7XG59XG5cbi8qKlxuICogU3RvcCB0aGUgYW5pbWF0aW9uLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuU3Bpbm5lci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uKCl7XG4gIHRoaXMuc3RvcHBlZCA9IHRydWU7XG59O1xuXG4vKipcbiAqIFNldCBzcGlubmVyIHNpemUgdG8gYG5gLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcmV0dXJuIHtTcGlubmVyfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5TcGlubmVyLnByb3RvdHlwZS5zaXplID0gZnVuY3Rpb24obil7XG4gIHRoaXMuZWwud2lkdGggPSBuO1xuICB0aGlzLmVsLmhlaWdodCA9IG47XG4gIGF1dG9zY2FsZSh0aGlzLmVsKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCB0ZXh0IHRvIGBzdHJgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLnRleHQgPSBmdW5jdGlvbihzdHIpe1xuICB0aGlzLl90ZXh0ID0gc3RyO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IGZvbnQgc2l6ZSB0byBgbmAuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLmZvbnRTaXplID0gZnVuY3Rpb24obil7XG4gIHRoaXMuX2ZvbnRTaXplID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBmb250IGBmYW1pbHlgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBmYW1pbHlcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLmZvbnQgPSBmdW5jdGlvbihmYW1pbHkpe1xuICB0aGlzLl9mb250ID0gZmFtaWx5O1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHNwZWVkIHRvIGBuYCBycG0uXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLnNwZWVkID0gZnVuY3Rpb24obikge1xuICB0aGlzLl9zcGVlZCA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBNYWtlIHRoZSBzcGlubmVyIGxpZ2h0IGNvbG9yZWQuXG4gKlxuICogQHJldHVybiB7U3Bpbm5lcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuU3Bpbm5lci5wcm90b3R5cGUubGlnaHQgPSBmdW5jdGlvbigpe1xuICB0aGlzLl9saWdodCA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBEcmF3IG9uIGBjdHhgLlxuICpcbiAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJkfSBjdHhcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5TcGlubmVyLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24oY3R4KXtcbiAgdmFyIHBlcmNlbnQgPSBNYXRoLm1pbih0aGlzLnBlcmNlbnQsIDEwMClcbiAgICAsIHJhdGlvID0gd2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMVxuICAgICwgc2l6ZSA9IHRoaXMuZWwud2lkdGggLyByYXRpb1xuICAgICwgaGFsZiA9IHNpemUgLyAyXG4gICAgLCB4ID0gaGFsZlxuICAgICwgeSA9IGhhbGZcbiAgICAsIHJhZCA9IGhhbGYgLSAxXG4gICAgLCBmb250U2l6ZSA9IHRoaXMuX2ZvbnRTaXplXG4gICAgLCBsaWdodCA9IHRoaXMuX2xpZ2h0O1xuXG4gIGN0eC5mb250ID0gZm9udFNpemUgKyAncHggJyArIHRoaXMuX2ZvbnQ7XG5cbiAgdmFyIGFuZ2xlID0gTWF0aC5QSSAqIDIgKiAocGVyY2VudCAvIDEwMCk7XG4gIGN0eC5jbGVhclJlY3QoMCwgMCwgc2l6ZSwgc2l6ZSk7XG5cbiAgLy8gb3V0ZXIgY2lyY2xlXG4gIHZhciBncmFkID0gY3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KFxuICAgIGhhbGYgKyBNYXRoLnNpbihNYXRoLlBJICogMS41IC0gYW5nbGUpICogaGFsZixcbiAgICBoYWxmICsgTWF0aC5jb3MoTWF0aC5QSSAqIDEuNSAtIGFuZ2xlKSAqIGhhbGYsXG4gICAgaGFsZiArIE1hdGguc2luKE1hdGguUEkgKiAwLjUgLSBhbmdsZSkgKiBoYWxmLFxuICAgIGhhbGYgKyBNYXRoLmNvcyhNYXRoLlBJICogMC41IC0gYW5nbGUpICogaGFsZlxuICApO1xuXG4gIC8vIGNvbG9yXG4gIGlmIChsaWdodCkge1xuICAgIGdyYWQuYWRkQ29sb3JTdG9wKDAsICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDApJyk7XG4gICAgZ3JhZC5hZGRDb2xvclN0b3AoMSwgJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMSknKTtcbiAgfSBlbHNlIHtcbiAgICBncmFkLmFkZENvbG9yU3RvcCgwLCAncmdiYSgwLCAwLCAwLCAwKScpO1xuICAgIGdyYWQuYWRkQ29sb3JTdG9wKDEsICdyZ2JhKDAsIDAsIDAsIDEpJyk7XG4gIH1cblxuICBjdHguc3Ryb2tlU3R5bGUgPSBncmFkO1xuICBjdHguYmVnaW5QYXRoKCk7XG4gIGN0eC5hcmMoeCwgeSwgcmFkLCBhbmdsZSAtIE1hdGguUEksIGFuZ2xlLCBmYWxzZSk7XG4gIGN0eC5zdHJva2UoKTtcblxuICAvLyBpbm5lciBjaXJjbGVcbiAgY3R4LnN0cm9rZVN0eWxlID0gbGlnaHQgPyAncmdiYSgyNTUsIDI1NSwgMjU1LCAuNCknIDogJyNlZWUnO1xuICBjdHguYmVnaW5QYXRoKCk7XG4gIGN0eC5hcmMoeCwgeSwgcmFkIC0gMSwgMCwgTWF0aC5QSSAqIDIsIHRydWUpO1xuICBjdHguc3Ryb2tlKCk7XG5cbiAgLy8gdGV4dFxuICB2YXIgdGV4dCA9IHRoaXMuX3RleHQgfHwgJydcbiAgICAsIHcgPSBjdHgubWVhc3VyZVRleHQodGV4dCkud2lkdGg7XG5cbiAgaWYgKGxpZ2h0KSBjdHguZmlsbFN0eWxlID0gJ3JnYmEoMjU1LCAyNTUsIDI1NSwgLjkpJztcbiAgY3R4LmZpbGxUZXh0KFxuICAgICAgdGV4dFxuICAgICwgeCAtIHcgLyAyICsgMVxuICAgICwgeSArIGZvbnRTaXplIC8gMiAtIDEpO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuIiwiLyoqXG4gKiBTdXBwb3J0ZWQgcHJlZml4ZXMuXG4gKi9cblxudmFyIHByZWZpeGVzID0gW1xuICAnLXdlYmtpdC0nLCAnLW1vei0nLCAnLW8tJywgJy1tcy0nLCAnJ1xuXTtcblxuLyoqXG4gKiBFeHBvc2UgYHByZWZpeGVkYC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHByZWZpeGVkO1xuXG4vKipcbiAqIFNldCBhIHN0eWxlIHdpdGggYWxsIHRoZSB2ZW5kb3IgcHJlZml4ZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlXG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAqL1xuXG5mdW5jdGlvbiBwcmVmaXhlZCAoc3R5bGUsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgIHN0eWxlW3ByZWZpeGVzW2ldICsgYXR0cmlidXRlXSA9IHZhbHVlO1xuICB9XG59O1xuXG4vKipcbiAqIEdldCBhIChwb3NzaWJseSBwcmVmaXhlZCkgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cblxucHJlZml4ZWQuZ2V0ID0gZnVuY3Rpb24gKHN0eWxlLCBhdHRyaWJ1dGUpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciB2YWx1ZSA9IHN0eWxlW3ByZWZpeGVzW2ldICsgYXR0cmlidXRlXTtcbiAgICBpZiAodmFsdWUgJiYgdmFsdWUgIT0gJycpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gJyc7XG59O1xuXG4iLCJcbi8qKlxuICogUmV0aW5hLWVuYWJsZSB0aGUgZ2l2ZW4gYGNhbnZhc2AuXG4gKlxuICogQHBhcmFtIHtDYW52YXN9IGNhbnZhc1xuICogQHJldHVybiB7Q2FudmFzfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNhbnZhcyl7XG4gIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgdmFyIHJhdGlvID0gd2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMTtcbiAgaWYgKDEgIT0gcmF0aW8pIHtcbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSBjYW52YXMud2lkdGggKyAncHgnO1xuICAgIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0ICsgJ3B4JztcbiAgICBjYW52YXMud2lkdGggKj0gcmF0aW87XG4gICAgY2FudmFzLmhlaWdodCAqPSByYXRpbztcbiAgICBjdHguc2NhbGUocmF0aW8sIHJhdGlvKTtcbiAgfVxuICByZXR1cm4gY2FudmFzO1xufTsiLCJcbm1vZHVsZS5leHBvcnRzID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZVxuICB8fCB3aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gIHx8IHdpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgfHwgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgfHwgd2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gIHx8IGZhbGxiYWNrO1xuXG52YXIgcHJldiA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuZnVuY3Rpb24gZmFsbGJhY2soZm4pIHtcbiAgdmFyIGN1cnIgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgdmFyIG1zID0gTWF0aC5tYXgoMCwgMTYgLSAoY3VyciAtIHByZXYpKTtcbiAgc2V0VGltZW91dChmbiwgbXMpO1xuICBwcmV2ID0gY3Vycjtcbn1cbiJdfQ==
    ;var Spinning = require('spinning');

    var spinner = Spinning().text('loading...').light().size(200);

    setTimeout(function () {
    spinner.remove();
    }, 3000);
    function eat(o,n){var t=o+" got eaten";n(t)}function poop(o){console.log(o)}eat("pizza",poop);
    2 changes: 2 additions & 0 deletions page-head.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    <style type='text/css'>html, body { margin: 0; padding: 0; border: 0; }
    body, html { height: 100%; width: 100%; }</style>
    1 change: 1 addition & 0 deletions requirebin.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    view on [requirebin](http://requirebin.com?gist=5940808)
  3. @juliangruber juliangruber created this gist Jul 6, 2013.
    1 change: 1 addition & 0 deletions head.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    <style type='text/css'> html, body { margin: 0; padding: 0; border: 0; } </style>
    7 changes: 7 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    var Spinning = require('spinning');

    var spinner = Spinning().text('loading...').light().size(200);

    setTimeout(function () {
    spinner.remove();
    }, 3000);
    806 changes: 806 additions & 0 deletions minified.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,806 @@
    require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
    module.exports = '.spinner, .overlay {\n position: fixed;\n opacity: 0;\n}\n\n.spinner {\n left: 50%;\n top: 50%;\n margin-left: -100px;\n margin-top: -100px;\n z-index: 2222222222;\n}\n\n.overlay {\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n background-color: white;\n z-index: 1111111111;\n}\n';
    },{}],"spinning":[function(require,module,exports){
    module.exports=require('JGIiXp');
    },{}],"JGIiXp":[function(require,module,exports){
    (function(){var Spinner = require('spinner-browserify');
    var insertCss = require('insert-css');
    var style = require('./style');
    var fade = require('fade');
    var process = require('process'); // be nice to browserify

    module.exports = Spin;

    function Spin () {
    insertCss(style);

    // durations
    var fadeIn = 1000;
    var fadeOut = 300;

    var overlay = document.createElement('div');
    overlay.className = 'overlay';
    document.body.appendChild(overlay);

    var spinner = new Spinner();
    spinner.el.className = 'spinner';
    document.body.appendChild(spinner.el);

    process.nextTick(function () {
    fade(overlay, 0.8, fadeIn);
    fade.in(spinner.el, fadeIn);
    });

    spinner.remove = function () {
    fade.out(overlay, fadeOut);
    fade.out(spinner.el, fadeOut);

    setTimeout(function () {
    spinner.stop();
    document.body.removeChild(overlay);
    document.body.removeChild(spinner.el);
    }, fadeOut);
    };

    // reposition
    var size = spinner.size;
    spinner.size = function (n) {
    spinner.el.style.marginLeft =
    spinner.el.style.marginTop = '-' + (n/2) + 'px';
    return size.call(spinner, n);
    };

    var light = spinner.light;
    spinner.light = function () {
    overlay.style.backgroundColor = 'black';
    return light.call(spinner);
    };

    // set durations
    spinner['in'] = function (ms) { fadeIn = ms };
    spinner.out = function (ms) { fadeOut = ms };

    return spinner;
    }

    })()
    },{"process":2,"./style":1,"insert-css":3,"fade":4,"spinner-browserify":5}],2:[function(require,module,exports){
    (function(){var process = module.exports = {};

    process.nextTick = (function () {
    var canSetImmediate = typeof window !== 'undefined'
    && window.setImmediate;
    var canPost = typeof window !== 'undefined'
    && window.postMessage && window.addEventListener
    ;

    if (canSetImmediate) {
    return function (f) { return window.setImmediate(f) };
    }

    if (canPost) {
    var queue = [];
    window.addEventListener('message', function (ev) {
    if (ev.source === window && ev.data === 'browserify-tick') {
    ev.stopPropagation();
    if (queue.length > 0) {
    var fn = queue.shift();
    fn();
    }
    }
    }, true);

    return function nextTick(fn) {
    queue.push(fn);
    window.postMessage('browserify-tick', '*');
    };
    }

    return function nextTick(fn) {
    setTimeout(fn, 0);
    };
    })();

    process.title = 'browser';
    process.browser = true;
    process.env = {};
    process.argv = [];

    process.binding = function (name) {
    if (name === 'evals') return (require)('vm')
    else throw new Error('No such module. (Possibly not yet loaded)')
    };

    (function () {
    var cwd = '/';
    var path;
    process.cwd = function () { return cwd };
    process.chdir = function (dir) {
    if (!path) path = require('path');
    cwd = path.resolve(dir, cwd);
    };
    })();

    })()
    },{"path":6,"vm":7}],8:[function(require,module,exports){
    // shim for using process in browser

    var process = module.exports = {};

    process.nextTick = (function () {
    var canSetImmediate = typeof window !== 'undefined'
    && window.setImmediate;
    var canPost = typeof window !== 'undefined'
    && window.postMessage && window.addEventListener
    ;

    if (canSetImmediate) {
    return function (f) { return window.setImmediate(f) };
    }

    if (canPost) {
    var queue = [];
    window.addEventListener('message', function (ev) {
    if (ev.source === window && ev.data === 'process-tick') {
    ev.stopPropagation();
    if (queue.length > 0) {
    var fn = queue.shift();
    fn();
    }
    }
    }, true);

    return function nextTick(fn) {
    queue.push(fn);
    window.postMessage('process-tick', '*');
    };
    }

    return function nextTick(fn) {
    setTimeout(fn, 0);
    };
    })();

    process.title = 'browser';
    process.browser = true;
    process.env = {};
    process.argv = [];

    process.binding = function (name) {
    throw new Error('process.binding is not supported');
    }

    // TODO(shtylman)
    process.cwd = function () { return '/' };
    process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
    };

    },{}],6:[function(require,module,exports){
    (function(process){function filter (xs, fn) {
    var res = [];
    for (var i = 0; i < xs.length; i++) {
    if (fn(xs[i], i, xs)) res.push(xs[i]);
    }
    return res;
    }

    // resolves . and .. elements in a path array with directory names there
    // must be no slashes, empty elements, or device names (c:\) in the array
    // (so also no leading and trailing slashes - it does not distinguish
    // relative and absolute paths)
    function normalizeArray(parts, allowAboveRoot) {
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = parts.length; i >= 0; i--) {
    var last = parts[i];
    if (last == '.') {
    parts.splice(i, 1);
    } else if (last === '..') {
    parts.splice(i, 1);
    up++;
    } else if (up) {
    parts.splice(i, 1);
    up--;
    }
    }

    // if the path is allowed to go above the root, restore leading ..s
    if (allowAboveRoot) {
    for (; up--; up) {
    parts.unshift('..');
    }
    }

    return parts;
    }

    // Regex to split a filename into [*, dir, basename, ext]
    // posix version
    var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;

    // path.resolve([from ...], to)
    // posix version
    exports.resolve = function() {
    var resolvedPath = '',
    resolvedAbsolute = false;

    for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
    var path = (i >= 0)
    ? arguments[i]
    : process.cwd();

    // Skip empty and invalid entries
    if (typeof path !== 'string' || !path) {
    continue;
    }

    resolvedPath = path + '/' + resolvedPath;
    resolvedAbsolute = path.charAt(0) === '/';
    }

    // At this point the path should be resolved to a full absolute path, but
    // handle relative paths to be safe (might happen when process.cwd() fails)

    // Normalize the path
    resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
    return !!p;
    }), !resolvedAbsolute).join('/');

    return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
    };

    // path.normalize(path)
    // posix version
    exports.normalize = function(path) {
    var isAbsolute = path.charAt(0) === '/',
    trailingSlash = path.slice(-1) === '/';

    // Normalize the path
    path = normalizeArray(filter(path.split('/'), function(p) {
    return !!p;
    }), !isAbsolute).join('/');

    if (!path && !isAbsolute) {
    path = '.';
    }
    if (path && trailingSlash) {
    path += '/';
    }

    return (isAbsolute ? '/' : '') + path;
    };


    // posix version
    exports.join = function() {
    var paths = Array.prototype.slice.call(arguments, 0);
    return exports.normalize(filter(paths, function(p, index) {
    return p && typeof p === 'string';
    }).join('/'));
    };


    exports.dirname = function(path) {
    var dir = splitPathRe.exec(path)[1] || '';
    var isWindows = false;
    if (!dir) {
    // No dirname
    return '.';
    } else if (dir.length === 1 ||
    (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
    // It is just a slash or a drive letter with a slash
    return dir;
    } else {
    // It is a full dirname, strip trailing slash
    return dir.substring(0, dir.length - 1);
    }
    };


    exports.basename = function(path, ext) {
    var f = splitPathRe.exec(path)[2] || '';
    // TODO: make this comparison case-insensitive on windows?
    if (ext && f.substr(-1 * ext.length) === ext) {
    f = f.substr(0, f.length - ext.length);
    }
    return f;
    };


    exports.extname = function(path) {
    return splitPathRe.exec(path)[3] || '';
    };

    exports.relative = function(from, to) {
    from = exports.resolve(from).substr(1);
    to = exports.resolve(to).substr(1);

    function trim(arr) {
    var start = 0;
    for (; start < arr.length; start++) {
    if (arr[start] !== '') break;
    }

    var end = arr.length - 1;
    for (; end >= 0; end--) {
    if (arr[end] !== '') break;
    }

    if (start > end) return [];
    return arr.slice(start, end - start + 1);
    }

    var fromParts = trim(from.split('/'));
    var toParts = trim(to.split('/'));

    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
    if (fromParts[i] !== toParts[i]) {
    samePartsLength = i;
    break;
    }
    }

    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
    outputParts.push('..');
    }

    outputParts = outputParts.concat(toParts.slice(samePartsLength));

    return outputParts.join('/');
    };

    })(require("__browserify_process"))
    },{"__browserify_process":8}],3:[function(require,module,exports){
    var inserted = [];

    module.exports = function (css) {
    if (inserted.indexOf(css) >= 0) return;
    inserted.push(css);

    var elem = document.createElement('style');
    var text = document.createTextNode(css);
    elem.appendChild(text);

    if (document.head.childNodes.length) {
    document.head.insertBefore(elem, document.head.childNodes[0]);
    }
    else {
    document.head.appendChild(elem);
    }
    };

    },{}],7:[function(require,module,exports){
    var Object_keys = function (obj) {
    if (Object.keys) return Object.keys(obj)
    else {
    var res = [];
    for (var key in obj) res.push(key)
    return res;
    }
    };

    var forEach = function (xs, fn) {
    if (xs.forEach) return xs.forEach(fn)
    else for (var i = 0; i < xs.length; i++) {
    fn(xs[i], i, xs);
    }
    };

    var Script = exports.Script = function NodeScript (code) {
    if (!(this instanceof Script)) return new Script(code);
    this.code = code;
    };

    Script.prototype.runInNewContext = function (context) {
    if (!context) context = {};

    var iframe = document.createElement('iframe');
    if (!iframe.style) iframe.style = {};
    iframe.style.display = 'none';

    document.body.appendChild(iframe);

    var win = iframe.contentWindow;

    forEach(Object_keys(context), function (key) {
    win[key] = context[key];
    });

    if (!win.eval && win.execScript) {
    // win.eval() magically appears when this is called in IE:
    win.execScript('null');
    }

    var res = win.eval(this.code);

    forEach(Object_keys(win), function (key) {
    context[key] = win[key];
    });

    document.body.removeChild(iframe);

    return res;
    };

    Script.prototype.runInThisContext = function () {
    return eval(this.code); // maybe...
    };

    Script.prototype.runInContext = function (context) {
    // seems to be just runInNewContext on magical context objects which are
    // otherwise indistinguishable from objects except plain old objects
    // for the parameter segfaults node
    return this.runInNewContext(context);
    };

    forEach(Object_keys(Script.prototype), function (name) {
    exports[name] = Script[name] = function (code) {
    var s = Script(code);
    return s[name].apply(s, [].slice.call(arguments, 1));
    };
    });

    exports.createScript = function (code) {
    return exports.Script(code);
    };

    exports.createContext = Script.createContext = function (context) {
    // not really sure what this one does
    // seems to just make a shallow copy
    var copy = {};
    if(typeof context === 'object') {
    forEach(Object_keys(context), function (key) {
    copy[key] = context[key];
    });
    }
    return copy;
    };

    },{}],4:[function(require,module,exports){
    /**
    * Module dependencies.
    */

    var prefixed = require('prefixed');

    /**
    * Expose `fade`.
    */

    module.exports = fade;

    /**
    * Fade `el` to `opacity` in `duration` seconds.
    *
    * @param {Element} el
    * @param {Number} opacity
    * @param {Number=} duration
    *
    * @todo Add other vendor prefixes
    * @todo Properly clear transition
    */

    function fade (el, opacity, duration) {
    if (typeof duration === 'undefined') duration = 1000;

    var oldTransition = prefixed.get(el.style, 'transition') || '';
    prefixed(el.style, 'transition', 'opacity ' + (duration/1000) + 's');
    el.style.opacity = opacity;

    setTimeout(function () {
    prefixed(el.style, 'transition', oldTransition);
    }, duration);
    }

    /**
    * Fade in `el`.
    *
    * @param {Element} el
    * @param {Number=} duration
    */

    fade.out = function (el, duration) {
    fade(el, 0, duration);
    };

    /**
    * Fade out `el`.
    *
    * @param {Element} el
    * @param {Number=} duration
    */

    fade['in'] = function (el, duration) {
    fade(el, 1, duration);
    };

    },{"prefixed":9}],5:[function(require,module,exports){
    /**
    * Module dependencies.
    */

    var autoscale = require('autoscale-canvas');
    var raf = require('raf-component');

    /**
    * Expose `Spinner`.
    */

    module.exports = Spinner;

    /**
    * Initialize a new `Spinner`.
    */

    function Spinner() {
    var self = this;
    this.percent = 0;
    this.el = document.createElement('canvas');
    this.ctx = this.el.getContext('2d');
    this.size(50);
    this.fontSize(11);
    this.speed(60);
    this.font('helvetica, arial, sans-serif');
    this.stopped = false;

    (function animate() {
    if (self.stopped) return;
    raf(animate);
    self.percent = (self.percent + self._speed / 36) % 100;
    self.draw(self.ctx);
    })();
    }

    /**
    * Stop the animation.
    *
    * @api public
    */

    Spinner.prototype.stop = function(){
    this.stopped = true;
    };

    /**
    * Set spinner size to `n`.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.size = function(n){
    this.el.width = n;
    this.el.height = n;
    autoscale(this.el);
    return this;
    };

    /**
    * Set text to `str`.
    *
    * @param {String} str
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.text = function(str){
    this._text = str;
    return this;
    };

    /**
    * Set font size to `n`.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.fontSize = function(n){
    this._fontSize = n;
    return this;
    };

    /**
    * Set font `family`.
    *
    * @param {String} family
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.font = function(family){
    this._font = family;
    return this;
    };

    /**
    * Set speed to `n` rpm.
    *
    * @param {Number} n
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.speed = function(n) {
    this._speed = n;
    return this;
    };

    /**
    * Make the spinner light colored.
    *
    * @return {Spinner}
    * @api public
    */

    Spinner.prototype.light = function(){
    this._light = true;
    return this;
    };

    /**
    * Draw on `ctx`.
    *
    * @param {CanvasRenderingContext2d} ctx
    * @return {Spinner}
    * @api private
    */

    Spinner.prototype.draw = function(ctx){
    var percent = Math.min(this.percent, 100)
    , ratio = window.devicePixelRatio || 1
    , size = this.el.width / ratio
    , half = size / 2
    , x = half
    , y = half
    , rad = half - 1
    , fontSize = this._fontSize
    , light = this._light;

    ctx.font = fontSize + 'px ' + this._font;

    var angle = Math.PI * 2 * (percent / 100);
    ctx.clearRect(0, 0, size, size);

    // outer circle
    var grad = ctx.createLinearGradient(
    half + Math.sin(Math.PI * 1.5 - angle) * half,
    half + Math.cos(Math.PI * 1.5 - angle) * half,
    half + Math.sin(Math.PI * 0.5 - angle) * half,
    half + Math.cos(Math.PI * 0.5 - angle) * half
    );

    // color
    if (light) {
    grad.addColorStop(0, 'rgba(255, 255, 255, 0)');
    grad.addColorStop(1, 'rgba(255, 255, 255, 1)');
    } else {
    grad.addColorStop(0, 'rgba(0, 0, 0, 0)');
    grad.addColorStop(1, 'rgba(0, 0, 0, 1)');
    }

    ctx.strokeStyle = grad;
    ctx.beginPath();
    ctx.arc(x, y, rad, angle - Math.PI, angle, false);
    ctx.stroke();

    // inner circle
    ctx.strokeStyle = light ? 'rgba(255, 255, 255, .4)' : '#eee';
    ctx.beginPath();
    ctx.arc(x, y, rad - 1, 0, Math.PI * 2, true);
    ctx.stroke();

    // text
    var text = this._text || ''
    , w = ctx.measureText(text).width;

    if (light) ctx.fillStyle = 'rgba(255, 255, 255, .9)';
    ctx.fillText(
    text
    , x - w / 2 + 1
    , y + fontSize / 2 - 1);

    return this;
    };


    },{"autoscale-canvas":10,"raf-component":11}],9:[function(require,module,exports){
    /**
    * Supported prefixes.
    */

    var prefixes = [
    '-webkit-', '-moz-', '-o-', '-ms-', ''
    ];

    /**
    * Expose `prefixed`.
    */

    module.exports = prefixed;

    /**
    * Set a style with all the vendor prefixes.
    *
    * @param {Object} style
    * @param {String} attribute
    * @param {String} value
    */

    function prefixed (style, attribute, value) {
    for (var i = 0; i < prefixes.length; i++) {
    style[prefixes[i] + attribute] = value;
    }
    };

    /**
    * Get a (possibly prefixed) value.
    *
    * @param {Object} style
    * @param {String} attribute
    * @return {String}
    */

    prefixed.get = function (style, attribute) {
    for (var i = 0; i < prefixes.length; i++) {
    var value = style[prefixes[i] + attribute];
    if (value && value != '') return value;
    }
    return '';
    };


    },{}],10:[function(require,module,exports){

    /**
    * Retina-enable the given `canvas`.
    *
    * @param {Canvas} canvas
    * @return {Canvas}
    * @api public
    */

    module.exports = function(canvas){
    var ctx = canvas.getContext('2d');
    var ratio = window.devicePixelRatio || 1;
    if (1 != ratio) {
    canvas.style.width = canvas.width + 'px';
    canvas.style.height = canvas.height + 'px';
    canvas.width *= ratio;
    canvas.height *= ratio;
    ctx.scale(ratio, ratio);
    }
    return canvas;
    };
    },{}],11:[function(require,module,exports){

    module.exports = window.requestAnimationFrame
    || window.webkitRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.oRequestAnimationFrame
    || window.msRequestAnimationFrame
    || fallback;

    var prev = new Date().getTime();
    function fallback(fn) {
    var curr = new Date().getTime();
    var ms = Math.max(0, 16 - (curr - prev));
    setTimeout(fn, ms);
    prev = curr;
    }

    },{}]},{},[])
    //@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvdG1wL3NwaW5uaW5nMTEzNjYtMTEyODEtOTkyZXVyL25vZGVfbW9kdWxlcy9zcGlubmluZy9zdHlsZS5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL2luZGV4LmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItYnVpbHRpbnMvYnVpbHRpbi9wcm9jZXNzLmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2luc2VydC1tb2R1bGUtZ2xvYmFscy9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItYnVpbHRpbnMvYnVpbHRpbi9wYXRoLmpzIiwiL3RtcC9zcGlubmluZzExMzY2LTExMjgxLTk5MmV1ci9ub2RlX21vZHVsZXMvc3Bpbm5pbmcvbm9kZV9tb2R1bGVzL2luc2VydC1jc3MvaW5kZXguanMiLCIvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1idWlsdGlucy9ub2RlX21vZHVsZXMvdm0tYnJvd3NlcmlmeS9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9mYWRlL2luZGV4LmpzIiwiL3RtcC9zcGlubmluZzExMzY2LTExMjgxLTk5MmV1ci9ub2RlX21vZHVsZXMvc3Bpbm5pbmcvbm9kZV9tb2R1bGVzL3NwaW5uZXItYnJvd3NlcmlmeS9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9mYWRlL25vZGVfbW9kdWxlcy9wcmVmaXhlZC9pbmRleC5qcyIsIi90bXAvc3Bpbm5pbmcxMTM2Ni0xMTI4MS05OTJldXIvbm9kZV9tb2R1bGVzL3NwaW5uaW5nL25vZGVfbW9kdWxlcy9zcGlubmVyLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2F1dG9zY2FsZS1jYW52YXMvaW5kZXguanMiLCIvdG1wL3NwaW5uaW5nMTEzNjYtMTEyODEtOTkyZXVyL25vZGVfbW9kdWxlcy9zcGlubmluZy9ub2RlX21vZHVsZXMvc3Bpbm5lci1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9yYWYtY29tcG9uZW50L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gJy5zcGlubmVyLCAub3ZlcmxheSB7XFxuICBwb3NpdGlvbjogZml4ZWQ7XFxuICBvcGFjaXR5OiAwO1xcbn1cXG5cXG4uc3Bpbm5lciB7XFxuICBsZWZ0OiA1MCU7XFxuICB0b3A6IDUwJTtcXG4gIG1hcmdpbi1sZWZ0OiAtMTAwcHg7XFxuICBtYXJnaW4tdG9wOiAtMTAwcHg7XFxuICB6LWluZGV4OiAyMjIyMjIyMjIyO1xcbn1cXG5cXG4ub3ZlcmxheSB7XFxuICBsZWZ0OiAwO1xcbiAgdG9wOiAwO1xcbiAgd2lkdGg6IDEwMCU7XFxuICBoZWlnaHQ6IDEwMCU7XFxuICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTtcXG4gIHotaW5kZXg6IDExMTExMTExMTE7XFxufVxcbic7IiwiKGZ1bmN0aW9uKCl7dmFyIFNwaW5uZXIgPSByZXF1aXJlKCdzcGlubmVyLWJyb3dzZXJpZnknKTtcbnZhciBpbnNlcnRDc3MgPSByZXF1aXJlKCdpbnNlcnQtY3NzJyk7XG52YXIgc3R5bGUgPSByZXF1aXJlKCcuL3N0eWxlJyk7XG52YXIgZmFkZSA9IHJlcXVpcmUoJ2ZhZGUnKTtcbnZhciBwcm9jZXNzID0gcmVxdWlyZSgncHJvY2VzcycpOyAvLyBiZSBuaWNlIHRvIGJyb3dzZXJpZnlcblxubW9kdWxlLmV4cG9ydHMgPSBTcGluO1xuXG5mdW5jdGlvbiBTcGluICgpIHtcbiAgaW5zZXJ0Q3NzKHN0eWxlKTtcblxuICAvLyBkdXJhdGlvbnNcbiAgdmFyIGZhZGVJbiA9IDEwMDA7XG4gIHZhciBmYWRlT3V0ID0gMzAwO1xuXG4gIHZhciBvdmVybGF5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIG92ZXJsYXkuY2xhc3NOYW1lID0gJ292ZXJsYXknO1xuICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKG92ZXJsYXkpO1xuXG4gIHZhciBzcGlubmVyID0gbmV3IFNwaW5uZXIoKTtcbiAgc3Bpbm5lci5lbC5jbGFzc05hbWUgPSAnc3Bpbm5lcic7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc3Bpbm5lci5lbCk7XG5cbiAgcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgZmFkZShvdmVybGF5LCAwLjgsIGZhZGVJbik7XG4gICAgZmFkZS5pbihzcGlubmVyLmVsLCBmYWRlSW4pO1xuICB9KTtcblxuICBzcGlubmVyLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBmYWRlLm91dChvdmVybGF5LCBmYWRlT3V0KTtcbiAgICBmYWRlLm91dChzcGlubmVyLmVsLCBmYWRlT3V0KTtcblxuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgc3Bpbm5lci5zdG9wKCk7XG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKG92ZXJsYXkpO1xuICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzcGlubmVyLmVsKTtcbiAgICB9LCBmYWRlT3V0KTtcbiAgfTtcblxuICAvLyByZXBvc2l0aW9uXG4gIHZhciBzaXplID0gc3Bpbm5lci5zaXplO1xuICBzcGlubmVyLnNpemUgPSBmdW5jdGlvbiAobikge1xuICAgIHNwaW5uZXIuZWwuc3R5bGUubWFyZ2luTGVmdCA9XG4gICAgc3Bpbm5lci5lbC5zdHlsZS5tYXJnaW5Ub3AgPSAnLScgKyAobi8yKSArICdweCc7XG4gICAgcmV0dXJuIHNpemUuY2FsbChzcGlubmVyLCBuKTtcbiAgfTtcblxuICB2YXIgbGlnaHQgPSBzcGlubmVyLmxpZ2h0O1xuICBzcGlubmVyLmxpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgIG92ZXJsYXkuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gJ2JsYWNrJztcbiAgICByZXR1cm4gbGlnaHQuY2FsbChzcGlubmVyKTtcbiAgfTtcblxuICAvLyBzZXQgZHVyYXRpb25zXG4gIHNwaW5uZXJbJ2luJ10gPSBmdW5jdGlvbiAobXMpIHsgZmFkZUluID0gbXMgfTtcbiAgc3Bpbm5lci5vdXQgPSBmdW5jdGlvbiAobXMpIHsgZmFkZU91dCA9IG1zIH07XG5cbiAgcmV0dXJuIHNwaW5uZXI7XG59XG5cbn0pKCkiLCIoZnVuY3Rpb24oKXt2YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbnByb2Nlc3MubmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5TZXRJbW1lZGlhdGUgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICAmJiB3aW5kb3cuc2V0SW1tZWRpYXRlO1xuICAgIHZhciBjYW5Qb3N0ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChldi5zb3VyY2UgPT09IHdpbmRvdyAmJiBldi5kYXRhID09PSAnYnJvd3NlcmlmeS10aWNrJykge1xuICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdicm93c2VyaWZ5LXRpY2snLCAnKicpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICB9O1xufSkoKTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKG5hbWUgPT09ICdldmFscycpIHJldHVybiAocmVxdWlyZSkoJ3ZtJylcbiAgICBlbHNlIHRocm93IG5ldyBFcnJvcignTm8gc3VjaCBtb2R1bGUuIChQb3NzaWJseSBub3QgeWV0IGxvYWRlZCknKVxufTtcblxuKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgY3dkID0gJy8nO1xuICAgIHZhciBwYXRoO1xuICAgIHByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gY3dkIH07XG4gICAgcHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgaWYgKCFwYXRoKSBwYXRoID0gcmVxdWlyZSgncGF0aCcpO1xuICAgICAgICBjd2QgPSBwYXRoLnJlc29sdmUoZGlyLCBjd2QpO1xuICAgIH07XG59KSgpO1xuXG59KSgpIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChldi5zb3VyY2UgPT09IHdpbmRvdyAmJiBldi5kYXRhID09PSAncHJvY2Vzcy10aWNrJykge1xuICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdwcm9jZXNzLXRpY2snLCAnKicpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICB9O1xufSkoKTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCIoZnVuY3Rpb24ocHJvY2Vzcyl7ZnVuY3Rpb24gZmlsdGVyICh4cywgZm4pIHtcbiAgICB2YXIgcmVzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB4cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZm4oeHNbaV0sIGksIHhzKSkgcmVzLnB1c2goeHNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyByZXNvbHZlcyAuIGFuZCAuLiBlbGVtZW50cyBpbiBhIHBhdGggYXJyYXkgd2l0aCBkaXJlY3RvcnkgbmFtZXMgdGhlcmVcbi8vIG11c3QgYmUgbm8gc2xhc2hlcywgZW1wdHkgZWxlbWVudHMsIG9yIGRldmljZSBuYW1lcyAoYzpcXCkgaW4gdGhlIGFycmF5XG4vLyAoc28gYWxzbyBubyBsZWFkaW5nIGFuZCB0cmFpbGluZyBzbGFzaGVzIC0gaXQgZG9lcyBub3QgZGlzdGluZ3Vpc2hcbi8vIHJlbGF0aXZlIGFuZCBhYnNvbHV0ZSBwYXRocylcbmZ1bmN0aW9uIG5vcm1hbGl6ZUFycmF5KHBhcnRzLCBhbGxvd0Fib3ZlUm9vdCkge1xuICAvLyBpZiB0aGUgcGF0aCB0cmllcyB0byBnbyBhYm92ZSB0aGUgcm9vdCwgYHVwYCBlbmRzIHVwID4gMFxuICB2YXIgdXAgPSAwO1xuICBmb3IgKHZhciBpID0gcGFydHMubGVuZ3RoOyBpID49IDA7IGktLSkge1xuICAgIHZhciBsYXN0ID0gcGFydHNbaV07XG4gICAgaWYgKGxhc3QgPT0gJy4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgfSBlbHNlIGlmIChsYXN0ID09PSAnLi4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICB1cCsrO1xuICAgIH0gZWxzZSBpZiAodXApIHtcbiAgICAgIHBhcnRzLnNwbGljZShpLCAxKTtcbiAgICAgIHVwLS07XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhdGggaXMgYWxsb3dlZCB0byBnbyBhYm92ZSB0aGUgcm9vdCwgcmVzdG9yZSBsZWFkaW5nIC4uc1xuICBpZiAoYWxsb3dBYm92ZVJvb3QpIHtcbiAgICBmb3IgKDsgdXAtLTsgdXApIHtcbiAgICAgIHBhcnRzLnVuc2hpZnQoJy4uJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG4vLyBSZWdleCB0byBzcGxpdCBhIGZpbGVuYW1lIGludG8gWyosIGRpciwgYmFzZW5hbWUsIGV4dF1cbi8vIHBvc2l4IHZlcnNpb25cbnZhciBzcGxpdFBhdGhSZSA9IC9eKC4rXFwvKD8hJCl8XFwvKT8oKD86Lis/KT8oXFwuW14uXSopPykkLztcblxuLy8gcGF0aC5yZXNvbHZlKFtmcm9tIC4uLl0sIHRvKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5yZXNvbHZlID0gZnVuY3Rpb24oKSB7XG52YXIgcmVzb2x2ZWRQYXRoID0gJycsXG4gICAgcmVzb2x2ZWRBYnNvbHV0ZSA9IGZhbHNlO1xuXG5mb3IgKHZhciBpID0gYXJndW1lbnRzLmxlbmd0aDsgaSA+PSAtMSAmJiAhcmVzb2x2ZWRBYnNvbHV0ZTsgaS0tKSB7XG4gIHZhciBwYXRoID0gKGkgPj0gMClcbiAgICAgID8gYXJndW1lbnRzW2ldXG4gICAgICA6IHByb2Nlc3MuY3dkKCk7XG5cbiAgLy8gU2tpcCBlbXB0eSBhbmQgaW52YWxpZCBlbnRyaWVzXG4gIGlmICh0eXBlb2YgcGF0aCAhPT0gJ3N0cmluZycgfHwgIXBhdGgpIHtcbiAgICBjb250aW51ZTtcbiAgfVxuXG4gIHJlc29sdmVkUGF0aCA9IHBhdGggKyAnLycgKyByZXNvbHZlZFBhdGg7XG4gIHJlc29sdmVkQWJzb2x1dGUgPSBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nO1xufVxuXG4vLyBBdCB0aGlzIHBvaW50IHRoZSBwYXRoIHNob3VsZCBiZSByZXNvbHZlZCB0byBhIGZ1bGwgYWJzb2x1dGUgcGF0aCwgYnV0XG4vLyBoYW5kbGUgcmVsYXRpdmUgcGF0aHMgdG8gYmUgc2FmZSAobWlnaHQgaGFwcGVuIHdoZW4gcHJvY2Vzcy5jd2QoKSBmYWlscylcblxuLy8gTm9ybWFsaXplIHRoZSBwYXRoXG5yZXNvbHZlZFBhdGggPSBub3JtYWxpemVBcnJheShmaWx0ZXIocmVzb2x2ZWRQYXRoLnNwbGl0KCcvJyksIGZ1bmN0aW9uKHApIHtcbiAgICByZXR1cm4gISFwO1xuICB9KSwgIXJlc29sdmVkQWJzb2x1dGUpLmpvaW4oJy8nKTtcblxuICByZXR1cm4gKChyZXNvbHZlZEFic29sdXRlID8gJy8nIDogJycpICsgcmVzb2x2ZWRQYXRoKSB8fCAnLic7XG59O1xuXG4vLyBwYXRoLm5vcm1hbGl6ZShwYXRoKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5ub3JtYWxpemUgPSBmdW5jdGlvbihwYXRoKSB7XG52YXIgaXNBYnNvbHV0ZSA9IHBhdGguY2hhckF0KDApID09PSAnLycsXG4gICAgdHJhaWxpbmdTbGFzaCA9IHBhdGguc2xpY2UoLTEpID09PSAnLyc7XG5cbi8vIE5vcm1hbGl6ZSB0aGUgcGF0aFxucGF0aCA9IG5vcm1hbGl6ZUFycmF5KGZpbHRlcihwYXRoLnNwbGl0KCcvJyksIGZ1bmN0aW9uKHApIHtcbiAgICByZXR1cm4gISFwO1xuICB9KSwgIWlzQWJzb2x1dGUpLmpvaW4oJy8nKTtcblxuICBpZiAoIXBhdGggJiYgIWlzQWJzb2x1dGUpIHtcbiAgICBwYXRoID0gJy4nO1xuICB9XG4gIGlmIChwYXRoICYmIHRyYWlsaW5nU2xhc2gpIHtcbiAgICBwYXRoICs9ICcvJztcbiAgfVxuICBcbiAgcmV0dXJuIChpc0Fic29sdXRlID8gJy8nIDogJycpICsgcGF0aDtcbn07XG5cblxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5qb2luID0gZnVuY3Rpb24oKSB7XG4gIHZhciBwYXRocyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG4gIHJldHVybiBleHBvcnRzLm5vcm1hbGl6ZShmaWx0ZXIocGF0aHMsIGZ1bmN0aW9uKHAsIGluZGV4KSB7XG4gICAgcmV0dXJuIHAgJiYgdHlwZW9mIHAgPT09ICdzdHJpbmcnO1xuICB9KS5qb2luKCcvJykpO1xufTtcblxuXG5leHBvcnRzLmRpcm5hbWUgPSBmdW5jdGlvbihwYXRoKSB7XG4gIHZhciBkaXIgPSBzcGxpdFBhdGhSZS5leGVjKHBhdGgpWzFdIHx8ICcnO1xuICB2YXIgaXNXaW5kb3dzID0gZmFsc2U7XG4gIGlmICghZGlyKSB7XG4gICAgLy8gTm8gZGlybmFtZVxuICAgIHJldHVybiAnLic7XG4gIH0gZWxzZSBpZiAoZGlyLmxlbmd0aCA9PT0gMSB8fFxuICAgICAgKGlzV2luZG93cyAmJiBkaXIubGVuZ3RoIDw9IDMgJiYgZGlyLmNoYXJBdCgxKSA9PT0gJzonKSkge1xuICAgIC8vIEl0IGlzIGp1c3QgYSBzbGFzaCBvciBhIGRyaXZlIGxldHRlciB3aXRoIGEgc2xhc2hcbiAgICByZXR1cm4gZGlyO1xuICB9IGVsc2Uge1xuICAgIC8vIEl0IGlzIGEgZnVsbCBkaXJuYW1lLCBzdHJpcCB0cmFpbGluZyBzbGFzaFxuICAgIHJldHVybiBkaXIuc3Vic3RyaW5nKDAsIGRpci5sZW5ndGggLSAxKTtcbiAgfVxufTtcblxuXG5leHBvcnRzLmJhc2VuYW1lID0gZnVuY3Rpb24ocGF0aCwgZXh0KSB7XG4gIHZhciBmID0gc3BsaXRQYXRoUmUuZXhlYyhwYXRoKVsyXSB8fCAnJztcbiAgLy8gVE9ETzogbWFrZSB0aGlzIGNvbXBhcmlzb24gY2FzZS1pbnNlbnNpdGl2ZSBvbiB3aW5kb3dzP1xuICBpZiAoZXh0ICYmIGYuc3Vic3RyKC0xICogZXh0Lmxlbmd0aCkgPT09IGV4dCkge1xuICAgIGYgPSBmLnN1YnN0cigwLCBmLmxlbmd0aCAtIGV4dC5sZW5ndGgpO1xuICB9XG4gIHJldHVybiBmO1xufTtcblxuXG5leHBvcnRzLmV4dG5hbWUgPSBmdW5jdGlvbihwYXRoKSB7XG4gIHJldHVybiBzcGxpdFBhdGhSZS5leGVjKHBhdGgpWzNdIHx8ICcnO1xufTtcblxuZXhwb3J0cy5yZWxhdGl2ZSA9IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gIGZyb20gPSBleHBvcnRzLnJlc29sdmUoZnJvbSkuc3Vic3RyKDEpO1xuICB0byA9IGV4cG9ydHMucmVzb2x2ZSh0bykuc3Vic3RyKDEpO1xuXG4gIGZ1bmN0aW9uIHRyaW0oYXJyKSB7XG4gICAgdmFyIHN0YXJ0ID0gMDtcbiAgICBmb3IgKDsgc3RhcnQgPCBhcnIubGVuZ3RoOyBzdGFydCsrKSB7XG4gICAgICBpZiAoYXJyW3N0YXJ0XSAhPT0gJycpIGJyZWFrO1xuICAgIH1cblxuICAgIHZhciBlbmQgPSBhcnIubGVuZ3RoIC0gMTtcbiAgICBmb3IgKDsgZW5kID49IDA7IGVuZC0tKSB7XG4gICAgICBpZiAoYXJyW2VuZF0gIT09ICcnKSBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoc3RhcnQgPiBlbmQpIHJldHVybiBbXTtcbiAgICByZXR1cm4gYXJyLnNsaWNlKHN0YXJ0LCBlbmQgLSBzdGFydCArIDEpO1xuICB9XG5cbiAgdmFyIGZyb21QYXJ0cyA9IHRyaW0oZnJvbS5zcGxpdCgnLycpKTtcbiAgdmFyIHRvUGFydHMgPSB0cmltKHRvLnNwbGl0KCcvJykpO1xuXG4gIHZhciBsZW5ndGggPSBNYXRoLm1pbihmcm9tUGFydHMubGVuZ3RoLCB0b1BhcnRzLmxlbmd0aCk7XG4gIHZhciBzYW1lUGFydHNMZW5ndGggPSBsZW5ndGg7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZnJvbVBhcnRzW2ldICE9PSB0b1BhcnRzW2ldKSB7XG4gICAgICBzYW1lUGFydHNMZW5ndGggPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgdmFyIG91dHB1dFBhcnRzID0gW107XG4gIGZvciAodmFyIGkgPSBzYW1lUGFydHNMZW5ndGg7IGkgPCBmcm9tUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICBvdXRwdXRQYXJ0cy5wdXNoKCcuLicpO1xuICB9XG5cbiAgb3V0cHV0UGFydHMgPSBvdXRwdXRQYXJ0cy5jb25jYXQodG9QYXJ0cy5zbGljZShzYW1lUGFydHNMZW5ndGgpKTtcblxuICByZXR1cm4gb3V0cHV0UGFydHMuam9pbignLycpO1xufTtcblxufSkocmVxdWlyZShcIl9fYnJvd3NlcmlmeV9wcm9jZXNzXCIpKSIsInZhciBpbnNlcnRlZCA9IFtdO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjc3MpIHtcbiAgICBpZiAoaW5zZXJ0ZWQuaW5kZXhPZihjc3MpID49IDApIHJldHVybjtcbiAgICBpbnNlcnRlZC5wdXNoKGNzcyk7XG4gICAgXG4gICAgdmFyIGVsZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuICAgIHZhciB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY3NzKTtcbiAgICBlbGVtLmFwcGVuZENoaWxkKHRleHQpO1xuICAgIFxuICAgIGlmIChkb2N1bWVudC5oZWFkLmNoaWxkTm9kZXMubGVuZ3RoKSB7XG4gICAgICAgIGRvY3VtZW50LmhlYWQuaW5zZXJ0QmVmb3JlKGVsZW0sIGRvY3VtZW50LmhlYWQuY2hpbGROb2Rlc1swXSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGVsZW0pO1xuICAgIH1cbn07XG4iLCJ2YXIgT2JqZWN0X2tleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgaWYgKE9iamVjdC5rZXlzKSByZXR1cm4gT2JqZWN0LmtleXMob2JqKVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHJlcy5wdXNoKGtleSlcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG59O1xuXG52YXIgZm9yRWFjaCA9IGZ1bmN0aW9uICh4cywgZm4pIHtcbiAgICBpZiAoeHMuZm9yRWFjaCkgcmV0dXJuIHhzLmZvckVhY2goZm4pXG4gICAgZWxzZSBmb3IgKHZhciBpID0gMDsgaSA8IHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZuKHhzW2ldLCBpLCB4cyk7XG4gICAgfVxufTtcblxudmFyIFNjcmlwdCA9IGV4cG9ydHMuU2NyaXB0ID0gZnVuY3Rpb24gTm9kZVNjcmlwdCAoY29kZSkge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTY3JpcHQpKSByZXR1cm4gbmV3IFNjcmlwdChjb2RlKTtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xufTtcblxuU2NyaXB0LnByb3RvdHlwZS5ydW5Jbk5ld0NvbnRleHQgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIGlmICghY29udGV4dCkgY29udGV4dCA9IHt9O1xuICAgIFxuICAgIHZhciBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZiAoIWlmcmFtZS5zdHlsZSkgaWZyYW1lLnN0eWxlID0ge307XG4gICAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgXG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChpZnJhbWUpO1xuICAgIFxuICAgIHZhciB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcbiAgICBcbiAgICBmb3JFYWNoKE9iamVjdF9rZXlzKGNvbnRleHQpLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHdpbltrZXldID0gY29udGV4dFtrZXldO1xuICAgIH0pO1xuICAgICBcbiAgICBpZiAoIXdpbi5ldmFsICYmIHdpbi5leGVjU2NyaXB0KSB7XG4gICAgICAgIC8vIHdpbi5ldmFsKCkgbWFnaWNhbGx5IGFwcGVhcnMgd2hlbiB0aGlzIGlzIGNhbGxlZCBpbiBJRTpcbiAgICAgICAgd2luLmV4ZWNTY3JpcHQoJ251bGwnKTtcbiAgICB9XG4gICAgXG4gICAgdmFyIHJlcyA9IHdpbi5ldmFsKHRoaXMuY29kZSk7XG4gICAgXG4gICAgZm9yRWFjaChPYmplY3Rfa2V5cyh3aW4pLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGNvbnRleHRba2V5XSA9IHdpbltrZXldO1xuICAgIH0pO1xuICAgIFxuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcbiAgICBcbiAgICByZXR1cm4gcmVzO1xufTtcblxuU2NyaXB0LnByb3RvdHlwZS5ydW5JblRoaXNDb250ZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBldmFsKHRoaXMuY29kZSk7IC8vIG1heWJlLi4uXG59O1xuXG5TY3JpcHQucHJvdG90eXBlLnJ1bkluQ29udGV4dCA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgLy8gc2VlbXMgdG8gYmUganVzdCBydW5Jbk5ld0NvbnRleHQgb24gbWFnaWNhbCBjb250ZXh0IG9iamVjdHMgd2hpY2ggYXJlXG4gICAgLy8gb3RoZXJ3aXNlIGluZGlzdGluZ3Vpc2hhYmxlIGZyb20gb2JqZWN0cyBleGNlcHQgcGxhaW4gb2xkIG9iamVjdHNcbiAgICAvLyBmb3IgdGhlIHBhcmFtZXRlciBzZWdmYXVsdHMgbm9kZVxuICAgIHJldHVybiB0aGlzLnJ1bkluTmV3Q29udGV4dChjb250ZXh0KTtcbn07XG5cbmZvckVhY2goT2JqZWN0X2tleXMoU2NyaXB0LnByb3RvdHlwZSksIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgZXhwb3J0c1tuYW1lXSA9IFNjcmlwdFtuYW1lXSA9IGZ1bmN0aW9uIChjb2RlKSB7XG4gICAgICAgIHZhciBzID0gU2NyaXB0KGNvZGUpO1xuICAgICAgICByZXR1cm4gc1tuYW1lXS5hcHBseShzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIH07XG59KTtcblxuZXhwb3J0cy5jcmVhdGVTY3JpcHQgPSBmdW5jdGlvbiAoY29kZSkge1xuICAgIHJldHVybiBleHBvcnRzLlNjcmlwdChjb2RlKTtcbn07XG5cbmV4cG9ydHMuY3JlYXRlQ29udGV4dCA9IFNjcmlwdC5jcmVhdGVDb250ZXh0ID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAvLyBub3QgcmVhbGx5IHN1cmUgd2hhdCB0aGlzIG9uZSBkb2VzXG4gICAgLy8gc2VlbXMgdG8ganVzdCBtYWtlIGEgc2hhbGxvdyBjb3B5XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICBpZih0eXBlb2YgY29udGV4dCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZm9yRWFjaChPYmplY3Rfa2V5cyhjb250ZXh0KSwgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgY29weVtrZXldID0gY29udGV4dFtrZXldO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGNvcHk7XG59O1xuIiwiLyoqXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzLlxuICovXG5cbnZhciBwcmVmaXhlZCA9IHJlcXVpcmUoJ3ByZWZpeGVkJyk7XG5cbi8qKlxuICogRXhwb3NlIGBmYWRlYC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZhZGU7XG5cbi8qKlxuICogRmFkZSBgZWxgIHRvIGBvcGFjaXR5YCBpbiBgZHVyYXRpb25gIHNlY29uZHMuXG4gKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbFxuICogQHBhcmFtIHtOdW1iZXJ9IG9wYWNpdHlcbiAqIEBwYXJhbSB7TnVtYmVyPX0gZHVyYXRpb25cbiAqXG4gKiBAdG9kbyBBZGQgb3RoZXIgdmVuZG9yIHByZWZpeGVzXG4gKiBAdG9kbyBQcm9wZXJseSBjbGVhciB0cmFuc2l0aW9uXG4gKi9cblxuZnVuY3Rpb24gZmFkZSAoZWwsIG9wYWNpdHksIGR1cmF0aW9uKSB7XG4gIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICd1bmRlZmluZWQnKSBkdXJhdGlvbiA9IDEwMDA7XG5cbiAgdmFyIG9sZFRyYW5zaXRpb24gPSBwcmVmaXhlZC5nZXQoZWwuc3R5bGUsICd0cmFuc2l0aW9uJykgfHwgJyc7XG4gIHByZWZpeGVkKGVsLnN0eWxlLCAndHJhbnNpdGlvbicsICdvcGFjaXR5ICcgKyAoZHVyYXRpb24vMTAwMCkgKyAncycpO1xuICBlbC5zdHlsZS5vcGFjaXR5ID0gb3BhY2l0eTtcblxuICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICBwcmVmaXhlZChlbC5zdHlsZSwgJ3RyYW5zaXRpb24nLCBvbGRUcmFuc2l0aW9uKTtcbiAgfSwgZHVyYXRpb24pO1xufVxuXG4vKipcbiAqIEZhZGUgaW4gYGVsYC5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge051bWJlcj19IGR1cmF0aW9uXG4gKi9cblxuZmFkZS5vdXQgPSBmdW5jdGlvbiAoZWwsIGR1cmF0aW9uKSB7XG4gIGZhZGUoZWwsIDAsIGR1cmF0aW9uKTtcbn07XG5cbi8qKlxuICogRmFkZSBvdXQgYGVsYC5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge051bWJlcj19IGR1cmF0aW9uXG4gKi9cblxuZmFkZVsnaW4nXSA9IGZ1bmN0aW9uIChlbCwgZHVyYXRpb24pIHtcbiAgZmFkZShlbCwgMSwgZHVyYXRpb24pO1xufTtcbiIsIi8qKlxuICogTW9kdWxlIGRlcGVuZGVuY2llcy5cbiAqL1xuXG52YXIgYXV0b3NjYWxlID0gcmVxdWlyZSgnYXV0b3NjYWxlLWNhbnZhcycpO1xudmFyIHJhZiA9IHJlcXVpcmUoJ3JhZi1jb21wb25lbnQnKTtcblxuLyoqXG4gKiBFeHBvc2UgYFNwaW5uZXJgLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gU3Bpbm5lcjtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBTcGlubmVyYC5cbiAqL1xuXG5mdW5jdGlvbiBTcGlubmVyKCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHRoaXMucGVyY2VudCA9IDA7XG4gIHRoaXMuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgdGhpcy5jdHggPSB0aGlzLmVsLmdldENvbnRleHQoJzJkJyk7XG4gIHRoaXMuc2l6ZSg1MCk7XG4gIHRoaXMuZm9udFNpemUoMTEpO1xuICB0aGlzLnNwZWVkKDYwKTtcbiAgdGhpcy5mb250KCdoZWx2ZXRpY2EsIGFyaWFsLCBzYW5zLXNlcmlmJyk7XG4gIHRoaXMuc3RvcHBlZCA9IGZhbHNlO1xuXG4gIChmdW5jdGlvbiBhbmltYXRlKCkge1xuICAgIGlmIChzZWxmLnN0b3BwZWQpIHJldHVybjtcbiAgICByYWYoYW5pbWF0ZSk7XG4gICAgc2VsZi5wZXJjZW50ID0gKHNlbGYucGVyY2VudCArIHNlbGYuX3NwZWVkIC8gMzYpICUgMTAwO1xuICAgIHNlbGYuZHJhdyhzZWxmLmN0eCk7XG4gIH0pKCk7XG59XG5cbi8qKlxuICogU3RvcCB0aGUgYW5pbWF0aW9uLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuU3Bpbm5lci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uKCl7XG4gIHRoaXMuc3RvcHBlZCA9IHRydWU7XG59O1xuXG4vKipcbiAqIFNldCBzcGlubmVyIHNpemUgdG8gYG5gLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gKiBAcmV0dXJuIHtTcGlubmVyfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5TcGlubmVyLnByb3RvdHlwZS5zaXplID0gZnVuY3Rpb24obil7XG4gIHRoaXMuZWwud2lkdGggPSBuO1xuICB0aGlzLmVsLmhlaWdodCA9IG47XG4gIGF1dG9zY2FsZSh0aGlzLmVsKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCB0ZXh0IHRvIGBzdHJgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLnRleHQgPSBmdW5jdGlvbihzdHIpe1xuICB0aGlzLl90ZXh0ID0gc3RyO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IGZvbnQgc2l6ZSB0byBgbmAuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLmZvbnRTaXplID0gZnVuY3Rpb24obil7XG4gIHRoaXMuX2ZvbnRTaXplID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBmb250IGBmYW1pbHlgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBmYW1pbHlcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLmZvbnQgPSBmdW5jdGlvbihmYW1pbHkpe1xuICB0aGlzLl9mb250ID0gZmFtaWx5O1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHNwZWVkIHRvIGBuYCBycG0uXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblNwaW5uZXIucHJvdG90eXBlLnNwZWVkID0gZnVuY3Rpb24obikge1xuICB0aGlzLl9zcGVlZCA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBNYWtlIHRoZSBzcGlubmVyIGxpZ2h0IGNvbG9yZWQuXG4gKlxuICogQHJldHVybiB7U3Bpbm5lcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuU3Bpbm5lci5wcm90b3R5cGUubGlnaHQgPSBmdW5jdGlvbigpe1xuICB0aGlzLl9saWdodCA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBEcmF3IG9uIGBjdHhgLlxuICpcbiAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJkfSBjdHhcbiAqIEByZXR1cm4ge1NwaW5uZXJ9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5TcGlubmVyLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24oY3R4KXtcbiAgdmFyIHBlcmNlbnQgPSBNYXRoLm1pbih0aGlzLnBlcmNlbnQsIDEwMClcbiAgICAsIHJhdGlvID0gd2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMVxuICAgICwgc2l6ZSA9IHRoaXMuZWwud2lkdGggLyByYXRpb1xuICAgICwgaGFsZiA9IHNpemUgLyAyXG4gICAgLCB4ID0gaGFsZlxuICAgICwgeSA9IGhhbGZcbiAgICAsIHJhZCA9IGhhbGYgLSAxXG4gICAgLCBmb250U2l6ZSA9IHRoaXMuX2ZvbnRTaXplXG4gICAgLCBsaWdodCA9IHRoaXMuX2xpZ2h0O1xuXG4gIGN0eC5mb250ID0gZm9udFNpemUgKyAncHggJyArIHRoaXMuX2ZvbnQ7XG5cbiAgdmFyIGFuZ2xlID0gTWF0aC5QSSAqIDIgKiAocGVyY2VudCAvIDEwMCk7XG4gIGN0eC5jbGVhclJlY3QoMCwgMCwgc2l6ZSwgc2l6ZSk7XG5cbiAgLy8gb3V0ZXIgY2lyY2xlXG4gIHZhciBncmFkID0gY3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50KFxuICAgIGhhbGYgKyBNYXRoLnNpbihNYXRoLlBJICogMS41IC0gYW5nbGUpICogaGFsZixcbiAgICBoYWxmICsgTWF0aC5jb3MoTWF0aC5QSSAqIDEuNSAtIGFuZ2xlKSAqIGhhbGYsXG4gICAgaGFsZiArIE1hdGguc2luKE1hdGguUEkgKiAwLjUgLSBhbmdsZSkgKiBoYWxmLFxuICAgIGhhbGYgKyBNYXRoLmNvcyhNYXRoLlBJICogMC41IC0gYW5nbGUpICogaGFsZlxuICApO1xuXG4gIC8vIGNvbG9yXG4gIGlmIChsaWdodCkge1xuICAgIGdyYWQuYWRkQ29sb3JTdG9wKDAsICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDApJyk7XG4gICAgZ3JhZC5hZGRDb2xvclN0b3AoMSwgJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMSknKTtcbiAgfSBlbHNlIHtcbiAgICBncmFkLmFkZENvbG9yU3RvcCgwLCAncmdiYSgwLCAwLCAwLCAwKScpO1xuICAgIGdyYWQuYWRkQ29sb3JTdG9wKDEsICdyZ2JhKDAsIDAsIDAsIDEpJyk7XG4gIH1cblxuICBjdHguc3Ryb2tlU3R5bGUgPSBncmFkO1xuICBjdHguYmVnaW5QYXRoKCk7XG4gIGN0eC5hcmMoeCwgeSwgcmFkLCBhbmdsZSAtIE1hdGguUEksIGFuZ2xlLCBmYWxzZSk7XG4gIGN0eC5zdHJva2UoKTtcblxuICAvLyBpbm5lciBjaXJjbGVcbiAgY3R4LnN0cm9rZVN0eWxlID0gbGlnaHQgPyAncmdiYSgyNTUsIDI1NSwgMjU1LCAuNCknIDogJyNlZWUnO1xuICBjdHguYmVnaW5QYXRoKCk7XG4gIGN0eC5hcmMoeCwgeSwgcmFkIC0gMSwgMCwgTWF0aC5QSSAqIDIsIHRydWUpO1xuICBjdHguc3Ryb2tlKCk7XG5cbiAgLy8gdGV4dFxuICB2YXIgdGV4dCA9IHRoaXMuX3RleHQgfHwgJydcbiAgICAsIHcgPSBjdHgubWVhc3VyZVRleHQodGV4dCkud2lkdGg7XG5cbiAgaWYgKGxpZ2h0KSBjdHguZmlsbFN0eWxlID0gJ3JnYmEoMjU1LCAyNTUsIDI1NSwgLjkpJztcbiAgY3R4LmZpbGxUZXh0KFxuICAgICAgdGV4dFxuICAgICwgeCAtIHcgLyAyICsgMVxuICAgICwgeSArIGZvbnRTaXplIC8gMiAtIDEpO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuIiwiLyoqXG4gKiBTdXBwb3J0ZWQgcHJlZml4ZXMuXG4gKi9cblxudmFyIHByZWZpeGVzID0gW1xuICAnLXdlYmtpdC0nLCAnLW1vei0nLCAnLW8tJywgJy1tcy0nLCAnJ1xuXTtcblxuLyoqXG4gKiBFeHBvc2UgYHByZWZpeGVkYC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHByZWZpeGVkO1xuXG4vKipcbiAqIFNldCBhIHN0eWxlIHdpdGggYWxsIHRoZSB2ZW5kb3IgcHJlZml4ZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlXG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAqL1xuXG5mdW5jdGlvbiBwcmVmaXhlZCAoc3R5bGUsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgIHN0eWxlW3ByZWZpeGVzW2ldICsgYXR0cmlidXRlXSA9IHZhbHVlO1xuICB9XG59O1xuXG4vKipcbiAqIEdldCBhIChwb3NzaWJseSBwcmVmaXhlZCkgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cblxucHJlZml4ZWQuZ2V0ID0gZnVuY3Rpb24gKHN0eWxlLCBhdHRyaWJ1dGUpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciB2YWx1ZSA9IHN0eWxlW3ByZWZpeGVzW2ldICsgYXR0cmlidXRlXTtcbiAgICBpZiAodmFsdWUgJiYgdmFsdWUgIT0gJycpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gJyc7XG59O1xuXG4iLCJcbi8qKlxuICogUmV0aW5hLWVuYWJsZSB0aGUgZ2l2ZW4gYGNhbnZhc2AuXG4gKlxuICogQHBhcmFtIHtDYW52YXN9IGNhbnZhc1xuICogQHJldHVybiB7Q2FudmFzfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNhbnZhcyl7XG4gIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgdmFyIHJhdGlvID0gd2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMTtcbiAgaWYgKDEgIT0gcmF0aW8pIHtcbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSBjYW52YXMud2lkdGggKyAncHgnO1xuICAgIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0ICsgJ3B4JztcbiAgICBjYW52YXMud2lkdGggKj0gcmF0aW87XG4gICAgY2FudmFzLmhlaWdodCAqPSByYXRpbztcbiAgICBjdHguc2NhbGUocmF0aW8sIHJhdGlvKTtcbiAgfVxuICByZXR1cm4gY2FudmFzO1xufTsiLCJcbm1vZHVsZS5leHBvcnRzID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZVxuICB8fCB3aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gIHx8IHdpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgfHwgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgfHwgd2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gIHx8IGZhbGxiYWNrO1xuXG52YXIgcHJldiA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuZnVuY3Rpb24gZmFsbGJhY2soZm4pIHtcbiAgdmFyIGN1cnIgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgdmFyIG1zID0gTWF0aC5tYXgoMCwgMTYgLSAoY3VyciAtIHByZXYpKTtcbiAgc2V0VGltZW91dChmbiwgbXMpO1xuICBwcmV2ID0gY3Vycjtcbn1cbiJdfQ==
    ;var Spinning = require('spinning');

    var spinner = Spinning().text('loading...').light().size(200);

    setTimeout(function () {
    spinner.remove();
    }, 3000);