<commit_before>var buster = (function (setTimeout, B) {
    var isNode = typeof require == "function" && typeof module == "object";
    var div = typeof document != "undefined" && document.createElement("div");
    var F = function () {};

    var buster = {
        bind: function bind(obj, methOrProp) {
            var method = typeof methOrProp == "string" ? obj[methOrProp] : methOrProp;
            var args = Array.prototype.slice.call(arguments, 2);
            return function () {
                var allArgs = args.concat(Array.prototype.slice.call(arguments));
                return method.apply(obj, allArgs);
            };
        },

        partial: function partial(fn) {
            var args = [].slice.call(arguments, 1);
            return function () {
                return fn.apply(this, args.concat([].slice.call(arguments)));
            };
        },

        create: function create(object) {
            F.prototype = object;
            return new F();
        },

        extend: function extend(target) {
            if (!target) { return; }
            for (var i = 1, l = arguments.length, prop; i < l; ++i) {
                for (prop in arguments[i]) {
                    target[prop] = arguments[i][prop];
                }
            }
            return target;
        },

        nextTick: function nextTick(callback) {
            if (typeof process != "undefined" && process.nextTick) {
                return process.nextTick(callback);
            }
            setTimeout(callback, 0);
        },

        functionName: function functionName(func) {
            if (!func) return "";
            if (func.displayName) return func.displayName;
            if (func.name) return func.name;
            var matches = func.toString().match(/function\s+([^\(]+)/m);
            return matches && matches[1] || "";
        },

        isNode: function isNode(obj) {
            if (!div) return false;
            try {
                obj.appendChild(div);
                obj.removeChild(div);
            } catch (e) {
                return false;
            }
            return true;
        },

        isElement: function isElement(obj) {
            return obj && buster.isNode(obj) && obj.nodeType === 1;
        },

        isArray: function isArray(arr) {
            return Object.prototype.toString.call(arr) == "[object Array]";
        },

        flatten: function flatten(arr) {
            var result = [], arr = arr || [];
            for (var i = 0, l = arr.length; i < l; ++i) {
                result = result.concat(buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i]);
            }
            return result;
        },

        each: function each(arr, callback) {
            for (var i = 0, l = arr.length; i < l; ++i) {
                callback(arr[i]);
            }
        },

        map: function map(arr, callback) {
            var results = [];
            for (var i = 0, l = arr.length; i < l; ++i) {
                results.push(callback(arr[i]));
            }
            return results;
        },

        parallel: function parallel(fns, callback) {
            function cb(err, res) {
                if (typeof callback == "function") {
                    callback(err, res);
                    callback = null;
                }
            }
            if (fns.length == 0) { return cb(null, []); }
            var remaining = fns.length, results = [];
            function makeDone(num) {
                return function done(err, result) {
                    if (err) { return cb(err); }
                    results[num] = result;
                    if (--remaining == 0) { cb(null, results); }
                };
            }
            for (var i = 0, l = fns.length; i < l; ++i) {
                fns[i](makeDone(i));
            }
        },

        series: function series(fns, callback) {
            function cb(err, res) {
                if (typeof callback == "function") {
                    callback(err, res);
                }
            }
            var remaining = fns.slice();
            var results = [];
            function callNext() {
                if (remaining.length == 0) return cb(null, results);
                var promise = remaining.shift()(next);
                if (promise && typeof promise.then == "function") {
                    promise.then(buster.partial(next, null), next);
                }
            }
            function next(err, result) {
                if (err) return cb(err);
                results.push(result);
                callNext();
            }
            callNext();
        },

        countdown: function countdown(num, done) {
            return function () {
                if (--num == 0) done();
            };
        }
    };

    if (!Array.prototype.some) {
        buster.some = function (arr, fn, thisp) {
            return arr.some(fn, thisp);
        };
    } else {
        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
        buster.some = function (arr, fun, thisp) {
            "use strict";
            if (arr == null) { throw new TypeError(); }
            arr = Object(arr);
            var len = arr.length >>> 0;
            if (typeof fun !== "function") { throw new TypeError(); }

            for (var i = 0; i < len; i++) {
                if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
                    return true;
                }
            }

            return false;
        };
    }

    if (isNode) {
        module.exports = buster;
        buster.eventEmitter = require("./buster-event-emitter");
        Object.defineProperty(buster, "defineVersionGetter", {
            get: function () {
                return require("./define-version-getter");
            }
        });
    }

    return buster.extend(B || {}, buster);
}(setTimeout, buster));
<commit_msg>Fix stupid bug<commit_after>var buster = (function (setTimeout, B) {
    var isNode = typeof require == "function" && typeof module == "object";
    var div = typeof document != "undefined" && document.createElement("div");
    var F = function () {};

    var buster = {
        bind: function bind(obj, methOrProp) {
            var method = typeof methOrProp == "string" ? obj[methOrProp] : methOrProp;
            var args = Array.prototype.slice.call(arguments, 2);
            return function () {
                var allArgs = args.concat(Array.prototype.slice.call(arguments));
                return method.apply(obj, allArgs);
            };
        },

        partial: function partial(fn) {
            var args = [].slice.call(arguments, 1);
            return function () {
                return fn.apply(this, args.concat([].slice.call(arguments)));
            };
        },

        create: function create(object) {
            F.prototype = object;
            return new F();
        },

        extend: function extend(target) {
            if (!target) { return; }
            for (var i = 1, l = arguments.length, prop; i < l; ++i) {
                for (prop in arguments[i]) {
                    target[prop] = arguments[i][prop];
                }
            }
            return target;
        },

        nextTick: function nextTick(callback) {
            if (typeof process != "undefined" && process.nextTick) {
                return process.nextTick(callback);
            }
            setTimeout(callback, 0);
        },

        functionName: function functionName(func) {
            if (!func) return "";
            if (func.displayName) return func.displayName;
            if (func.name) return func.name;
            var matches = func.toString().match(/function\s+([^\(]+)/m);
            return matches && matches[1] || "";
        },

        isNode: function isNode(obj) {
            if (!div) return false;
            try {
                obj.appendChild(div);
                obj.removeChild(div);
            } catch (e) {
                return false;
            }
            return true;
        },

        isElement: function isElement(obj) {
            return obj && buster.isNode(obj) && obj.nodeType === 1;
        },

        isArray: function isArray(arr) {
            return Object.prototype.toString.call(arr) == "[object Array]";
        },

        flatten: function flatten(arr) {
            var result = [], arr = arr || [];
            for (var i = 0, l = arr.length; i < l; ++i) {
                result = result.concat(buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i]);
            }
            return result;
        },

        each: function each(arr, callback) {
            for (var i = 0, l = arr.length; i < l; ++i) {
                callback(arr[i]);
            }
        },

        map: function map(arr, callback) {
            var results = [];
            for (var i = 0, l = arr.length; i < l; ++i) {
                results.push(callback(arr[i]));
            }
            return results;
        },

        parallel: function parallel(fns, callback) {
            function cb(err, res) {
                if (typeof callback == "function") {
                    callback(err, res);
                    callback = null;
                }
            }
            if (fns.length == 0) { return cb(null, []); }
            var remaining = fns.length, results = [];
            function makeDone(num) {
                return function done(err, result) {
                    if (err) { return cb(err); }
                    results[num] = result;
                    if (--remaining == 0) { cb(null, results); }
                };
            }
            for (var i = 0, l = fns.length; i < l; ++i) {
                fns[i](makeDone(i));
            }
        },

        series: function series(fns, callback) {
            function cb(err, res) {
                if (typeof callback == "function") {
                    callback(err, res);
                }
            }
            var remaining = fns.slice();
            var results = [];
            function callNext() {
                if (remaining.length == 0) return cb(null, results);
                var promise = remaining.shift()(next);
                if (promise && typeof promise.then == "function") {
                    promise.then(buster.partial(next, null), next);
                }
            }
            function next(err, result) {
                if (err) return cb(err);
                results.push(result);
                callNext();
            }
            callNext();
        },

        countdown: function countdown(num, done) {
            return function () {
                if (--num == 0) done();
            };
        }
    };

    if (Array.prototype.some) {
        buster.some = function (arr, fn, thisp) {
            return arr.some(fn, thisp);
        };
    } else {
        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
        buster.some = function (arr, fun, thisp) {
            "use strict";
            if (arr == null) { throw new TypeError(); }
            arr = Object(arr);
            var len = arr.length >>> 0;
            if (typeof fun !== "function") { throw new TypeError(); }

            for (var i = 0; i < len; i++) {
                if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
                    return true;
                }
            }

            return false;
        };
    }

    if (isNode) {
        module.exports = buster;
        buster.eventEmitter = require("./buster-event-emitter");
        Object.defineProperty(buster, "defineVersionGetter", {
            get: function () {
                return require("./define-version-getter");
            }
        });
    }

    return buster.extend(B || {}, buster);
}(setTimeout, buster));
<|endoftext|>


<commit_before>// TODO ttl

var M = process.mono;
var fs = require('fs');
var zlib = require('zlib');
var mime = require('mime');

var dataKey = '_data';
var caches = {};

module.exports = factory;

// create a new cache instance
function factory (name, config) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    config = config || {};

    var cache = Cache.clone();
    cache[dataKey] = {};

    // set time to live
    if (config.ttl) {
        cache.ttl = config.ttl;
    }

    // set compression method
    if (config.zlib) {
        cache.zlib = config.zlib;
    }

    // save cache
    caches[name] = cache;

    return cache;
}

// cache class
var Cache = {

    // set default compression method
    zlib: 'gzip',

    // get an item
    get: function (key) {
        return this[dataKey][key];
    },

    // get all items
    all: function () {
        return this[dataKey];
    },

    // save an item or file if no data is given
    set: function (key, data) {

        if (typeof data === 'function') {
            return saveFile.call(this, key, data);
        }

        this[dataKey][key] = data;
    },

    // remove an item
    rm: function (key) {
        if (typeof this[dataKey][key] !== 'undefined') {
            delete this[dataKey][key];
        }
    },

    // update an item
    update: function (key, path, value) {
        if (this[dataKey][key]) {
            return updatePath(this[dataKey][key], path, value);
        }
    },

    // empty cache
    empty: function () {
        this[dataKey] = {};
    }
};

// update a specific path (ex. {path: {to: {prop: 321}}}, 'path.to.prop', 123)
function updatePath (object, path, value) {

    path = path.split('.');
    len = path.length - 1;

    // find keys in paths or return
    for (var i = 0; i < len; ++i) {
        if (!(object = object[path[i]])) {
            return;
        }
    }

    // update object
    object[path[len]] = value;

    return true;
}

// read a file in the cache and update file on change
function  saveFile (path, callback, dontWatch) {
    var self = this;

    fs.readFile(path, function (err, data) {

        if (err) {
            return callback(err);
        }

        zlib[self.zlib](data, function (err, data) {

            if (err) {
                return callback(err);
            }

            fs.stat(path, function (err, stats) {

                if (err) {
                    return callback(err);
                }

                // watch file and update cache on change (only in dev mode?)
                if (!dontWatch) {
                    fs.watchFile(path, function (curr, prev) {

                        // update cache data
                        if(curr.mtime !== prev.mtime) {
                            saveFile.call(self, path, function () {}, true);
                        }
                    });
                }

                // save zipped data in cache
                self[dataKey][path] = data = {
                    data: data,
                    stats: stats,
                    mime: mime.lookup(path)
                };

                // return data
                callback(null, data);
            });
        });
    });
}
<commit_msg>splitted cache logic<commit_after>// TODO ttl

// require factories
var pojo = require('./pojo');
var file = require('./file');
var comp = require('./comp');

// export factories
exports.pojo = pojo;
exports.file = file;
exports.comp = comp;
<|endoftext|>


<commit_before>/**
 * @file
 */
/**
 * @module checkremote
 * @requires url
 * @requires dns
 * @requires ip
 * @requires q
 * @todo implement is_port_acceptable function
 * @todo make each function can be call separately
 * @todo docs
 */
var checkremote = exports,
	urllib = require('url'),
	dns = require('dns'),
	ip = require('ip'),
	Q = require('q');

/**
 * get all IP addresses linked to the given host
 * @augments checkremote
 * @param {Object} data data must contain at min host element for use in this function
 * @return {Promise} data promise which contain all addrs
 */
function all_addrs(data) {
	var deferred = Q.defer();
	dns.resolve(data.host, function(err, addrs) {
		if (err) deferred.resolve(err);
		data['addrs'] = addrs;
		deferred.resolve(data);
	});
	return deferred.promise;
}

/**
 * check if an IP addresses is private
 * @augments checkremote
 * @param {String} addr
 * @return {boolean} return true if the given addresse (addr) is lcoal, else false
 */
function is_addr_local(addr) {
	if (ip.isPrivate(addr) == true) {
		return true;
	} else {
		return false;
	}
}
/**
 * Test if a hostname has local IP addresses.
 * This function check every IP address given, which are associated to an hostname.
 * @augments checkremote
 * @param {Object} data data must contain at min addrs (IP addresses tab) element for use in this function
 * @return {Object} return data Object which contain is_host_local boolean. His value will be true if local addresse detected, else false
 */
function is_host_local(data) {
	data['is_host_local'] = false;
	for (var index in data.addrs) {
		if (is_addr_local(data.addrs[index]) == true) {
			data['is_host_local'] = true;
		}
	}
	return data;
}
/**
 * Test if the hostname is not blacklisted
 * @augments checkremote
 * @param {Object} data data must contain at min blacklist array for use in this function
 * @return {Object} return data Object which contain is_blacklisted boolean. His value will be true if blacklisted hostname, else false
 */
function is_host_blacklisted(data) {
	if (data.blacklist.indexOf(data.host) == -1) {
		data['is_host_blacklisted'] = false;
	} else {
		data['is_host_blacklisted'] = true;
	}
	return data;
}
/**
 * Test if the protocol asked is acceptable.
 * @augments checkremote
 * @param {Object} data data must contain at min protocol of a parsed url & protocol_scheme array (list of acceptable protocols) for use in this function
 * @return {Object} return data Object which contain is_protocol_acceptable boolean. His value will be true if acceptable protocol, else false
 */
function is_protocol_acceptable(data) {
	if (data.protocol_scheme.indexOf(data.protocol) == -1) {
		data['is_protocol_acceptable'] = false;
	} else {
		data['is_protocol_acceptable'] = true;
	}
	return data;
}
/**
 * Run a check suite to control safety of an url given.
 * Result of the check suite is recover via callback given :
 * true if all checks passed else return a report with value (true or false) for each check.
 * @augments checkremote
 * @param {String} url
 * @param {function} cb callback
 * @param {Object} options
 * @param {Array} options.protocol_scheme list of protocols accepted. By default : http, https
 * @param {Array} options.blacklist list of blacklisted hostnames. By default : none
 */
checkremote.check_url_safety = function(url, cb, options) {
	if (!urllib.parse(url).host) {
		cb(false);
		return;
	}
	if (!urllib.parse(url).protocol) {
		cb(false);
		return;
	}
	if (!urllib.parse(url).hostname) {
		cb(false);
		return;
	}
	if (!options) {
		options = {};
		options.protocol_scheme = ['http', 'https'];
		options.blacklist = [];
	} else {
		if (!options.protocol_scheme) options.protocol_scheme = ['http', 'https'];
		if (!options.blacklist) options.blacklist = [];
	}
	var data = {
		url: url,
		host: urllib.parse(url)["hostname"],
		protocol: urllib.parse(url)["protocol"].split(':')[0],
		port: urllib.parse(url)["port"],
		protocol_scheme: options.protocol_scheme,
		blacklist: options.blacklist
	};
	all_addrs(data)
		.then(is_host_local)
		.then(is_protocol_acceptable)
		.then(is_host_blacklisted)
		.then(function(data) {
			if (data['is_protocol_acceptable'] == true && data['is_host_blacklisted'] == false && data['is_host_local'] == false) {
				return true;
			} else {
				return data;
			}
		}).then(cb);
	return;
}<commit_msg>delete checkremote file<commit_after><|endoftext|>


<commit_before>'use strict'

const Logger = require('../util/logger')

class Analyse {
  constructor (config, jirascope) {
    this.config = config
    this.jirascope = jirascope
  }

  async run () {
    await this.jirascope.populate()
    await this.jirascope.store()
    Logger.global.info(`found ${this.jirascope.roots.length} root issues`)
    Logger.global.info(`found ${this.jirascope.leaves.length} leaf issues`)
    Logger.global.info(`found ${this.jirascope.orphans.length} orphaned issues`)
  }
}

exports = module.exports = Analyse
<commit_msg>log additional analysis<commit_after>'use strict'

const Logger = require('../util/logger')

class Analyse {
  constructor (config, jirascope) {
    this.config = config
    this.jirascope = jirascope
  }

  async run () {
    await this.jirascope.populate()
    await this.jirascope.store()
    Logger.global.info(`found ${Object.keys(this.jirascope.issues).length} issues`)
    Logger.global.info(`found ${this.jirascope.graphs.length} graphs of issues`)
    Logger.global.info(`found ${this.jirascope.roots.length} root issues`)
    Logger.global.info(`found ${this.jirascope.leaves.length} leaf issues`)
    Logger.global.info(`found ${this.jirascope.orphans.length} orphaned issues`)
  }
}

exports = module.exports = Analyse
<|endoftext|>


<commit_before>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip, MenuIO;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Menu,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Events      = DOM.Events,
            RESTful     = DOM.RESTful,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig,
            ConfigView  = {
                beforeClose: function() {
                    isChanged();

                    if (Menu)
                        Menu.hide();
                },
                afterShow: function() {
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                    Ace.focus();
                }
            };

       function init() {
            Loading   = true;
            Util.exec.series([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                onMenu,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.load({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        notAppend : true
                    });

                    onMenu          = Util.exec.with(setMenu, Element);

                    initAce();

                    Events.addOnce('contextmenu', Element, onMenu)
                        .add(Element, {
                            drop          : onDrop,
                            dragover      : DOM.preventDefault
                        });
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);
                setEmmet(isHTML);

                Util.exec.if(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, ConfigView);

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.exec.if(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.load.js(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.exec.if(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.exec.if(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.exec.with(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.exec.if(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.exec.if(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, newValue);
                    Util.exec(callback, patch);
                }, function(func) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        func();
                    });
                });
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.exec.if(JSHintConfig, func, function() {
                DOM.load.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.exec.ret(callback);

            Util.exec.if(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.load.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function setMenu(element) {
            DOM.loadMenu(function() {
                var position    = CloudCmd.MousePosition,
                    options     = {
                        beforeShow: function(params) {
                            params.x -= 18;
                            params.y -= 27;
                        },
                        afterClick: function() {
                            Ace.focus();
                        }
                },
                menuData    = {
                    'Save           Ctrl+S' : save,
                    'Go To Line     Ctrl+G' : function() {
                        Edit.goToLine();
                    },
                    'Select All     Ctrl+A' : function() {
                        Ace.selectAll();
                    },
                    'Delete         Del'    : function() {
                        Ace.remove('right');
                    },
                    'Close          Esc'    : Edit.hide
                };

                Menu        = new MenuIO(element, options, menuData);

                Menu.show(position.x, position.y);
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.load.series([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files   = event.dataTransfer.files;

            Util.forEach(files, function(file) {
                reader  = new FileReader();
                Events.addLoad(reader, onLoad);
                reader.readAsBinaryString(file);
            });
        }

        this.showMessage    = function(text) {
            var parent,
                HIDE_TIME = 2000;

            if (!Msg) {
                DOM.load.style({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.load({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent
                });
            }

            Msg.innerHTML = text;
            DOM.show(Msg);
            setTimeout(Util.exec.ret(DOM.hide, Msg), HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>refactor(edit) showMessage<commit_after>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch, Zip, MenuIO;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto() {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Menu,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Events      = DOM.Events,
            RESTful     = DOM.RESTful,
            Dialog      = DOM.Dialog,
            Images      = DOM.Images,
            Element, JSHintConfig, EditConfig,
            ConfigView  = {
                beforeClose: function() {
                    isChanged();

                    if (Menu)
                        Menu.hide();
                },
                afterShow: function() {
                    Ace.clearSelection();
                    Ace.moveCursorTo(0, 0);
                    Ace.focus();
                }
            };

       function init() {
            Loading   = true;
            Util.exec.series([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(value) {
            var mode, htmlMode, jsMode, isHTML, isJS, modesByName,
                onMenu,
                isStr       = Util.isString(value),
                name        = Info.name,
                isDir       = Info.isDir;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.load({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position   : absolute;',
                        notAppend : true
                    });

                    onMenu          = Util.exec.with(setMenu, Element);

                    initAce();

                    Events.addOnce('contextmenu', Element, onMenu)
                        .add(Element, {
                            drop          : onDrop,
                            dragover      : DOM.preventDefault
                        });
                }

                modesByName = Modelist.modesByName;

                if (isDir)
                    mode    = modesByName.json.mode;
                else
                    mode    = Modelist.getModeForPath(name).mode;

                htmlMode    = modesByName.html.mode;
                jsMode      = modesByName.javascript.mode;

                isHTML      = mode === htmlMode;
                isJS        = mode === jsMode;

                Session.setMode(mode);
                setUseOfWorker(mode);
                setEmmet(isHTML);

                Util.exec.if(isStr, function() {
                    var UndoManager = ace.require('ace/undomanager').UndoManager;

                    Ace.setValue(Value);
                    CloudCmd.View.show(Element, ConfigView);

                    Session.setUndoManager(new UndoManager());
                }, function(callback) {
                    Info.getData(function(data) {
                        Value = data;

                        if (isJS && Session.getUseWorker())
                            setJsHintConfig();

                        callback();
                    });
                });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function isChanged() {
            var is,
                value   = Ace.getValue(),
                isEqual = value === Value,
                msg     = 'Do you want to save changes to ' + name + '?';

            if (!isEqual) {
                is = Dialog.confirm(msg);

                if (is)
                    save();
            }
        }

        function setEmmet(isHTML) {
            getEditConfig(function(config) {
                var extensions  = config.extensions,
                    isEmmet     = extensions.emmet;

                if (isEmmet)
                    Util.exec.if(Emmet, function() {
                            if (Emmet)
                                Ace.setOption('enableEmmet', isHTML);
                        }, function(callback) {
                            var url;

                            if (!isHTML)
                                Util.exec(callback);
                            else {
                                url = CloudFunc.getJoinURL([
                                    DIR + 'emmet.js',
                                    DIR + 'ext-emmet.js'
                                ]);

                                DOM.load.js(url, function() {
                                    Emmet = ace.require('ace/ext/emmet');
                                    Emmet.setCore(window.emmet);
                                    Util.exec(callback);
                                });
                            }
                        });
                });
        }

        function setUseOfWorker(mode) {
            var isMatch,
                isStr   = Util.isString(mode),
                regStr  = 'coffee|css|html|javascript|json|lua|php|xquery',
                regExp  = new RegExp(regStr);

            if (isStr)
                isMatch = mode.match(regExp);

            Session.setUseWorker(isMatch);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            getEditConfig(function(config) {
                var options      = config.options;

                Ace.setOptions(options);
            });
        }

        function save () {
            var path    = Info.path,
                value   = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff      = config.diff,
                    isZip       = config.zip;

                Util.exec.if(!isDiff, function(patch) {
                    var query           = '',
                        MAX_SIZE        = CloudFunc.MAX_FILE_SIZE,
                        patchLength     = patch.length,
                        length          = Value.length,
                        isLessMaxLength = length < MAX_SIZE,
                        isLessLength    = isLessMaxLength && patchLength < length,
                        isStr           = Util.isString(patch);

                    Value               = value;

                    if (isStr && patch && isLessLength)
                        query           = '?patch';
                    else
                        patch           = false;

                    Util.exec.if(!isZip || query, function(equal, data) {
                        var result  = data || patch || Value,
                            url     = path + query;

                        RESTful.write(url, result , onSave);
                    }, function(func) {
                        zip(value, function(error, data) {
                            if (error)
                                Util.log(error);

                            query = '?unzip';
                            func(null, data);
                        });
                    });

                }, Util.exec.with(doDiff, path));
            });
        }

        function doDiff(path, callback) {
            var value = Ace.getValue();

            diff(value, function(patch) {
                var isAllowed = DOM.Storage.isAllowed();

                Util.exec.if(!isAllowed, callback, function(func) {
                        DOM.checkStorageHash(path, function(error, equal) {
                            if (!equal)
                                patch = '';

                            func(patch);
                        });
                });
            });
        }

        function diff(newValue, callback) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.exec.if(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, newValue);
                    Util.exec(callback, patch);
                }, function(func) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        func();
                    });
                });
            });
        }

        function zip(value, callback) {
            var dir             = CloudCmd.LIBDIRCLIENT,
                libs            = [
                    dir + 'zip/dist/pako.js',
                    dir + 'zip.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.load.js(url, function() {
                Zip.pack(value, callback);
            });
        }

        function setJsHintConfig(callback) {
            var JSHINT_PATH = '/.jshintrc',
                func        = function() {
                    var worker  = Session.$worker;

                    if (worker)
                        worker.send('changeOptions', [JSHintConfig]);

                    Util.exec(callback);
                };

            Util.exec.if(JSHintConfig, func, function() {
                DOM.load.ajax({
                    url     :  JSHINT_PATH,
                    success : function(data) {
                        JSHintConfig = Util.parseJSON(data);
                        func();
                    }
                });
            });
        }

        function getEditConfig(callback) {
            var CONFIG_PATH = '/json/edit.json',
                func        = Util.exec.ret(callback);

            Util.exec.if(EditConfig, function() {
                func(EditConfig);
            }, function() {
                DOM.load.ajax({
                    url     : CONFIG_PATH,
                    success : function(data) {
                        EditConfig = data;
                        func(EditConfig);
                    }
                });
            });
        }

        function setMenu(element) {
            DOM.loadMenu(function() {
                var position    = CloudCmd.MousePosition,
                    options     = {
                        beforeShow: function(params) {
                            params.x -= 18;
                            params.y -= 27;
                        },
                        afterClick: function() {
                            Ace.focus();
                        }
                },
                menuData    = {
                    'Save           Ctrl+S' : save,
                    'Go To Line     Ctrl+G' : function() {
                        Edit.goToLine();
                    },
                    'Select All     Ctrl+A' : function() {
                        Ace.selectAll();
                    },
                    'Delete         Del'    : function() {
                        Ace.remove('right');
                    },
                    'Close          Esc'    : Edit.hide
                };

                Menu        = new MenuIO(element, options, menuData);

                Menu.show(position.x, position.y);
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.load.series([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
                DOM.setCurrentSize(Value.length);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    RESTful.write(path, Value, onSave);
            }
        }

         function onDrop(event) {
            var reader, files,
                onLoad   =  function(event) {
                    var data    = event.target.result;

                    Ace.setValue(data);
                };

            event.preventDefault();

            files   = event.dataTransfer.files;

            Util.forEach(files, function(file) {
                reader  = new FileReader();
                Events.addLoad(reader, onLoad);
                reader.readAsBinaryString(file);
            });
        }

        this.showMessage    = function(text) {
            var parent,
                HIDE_TIME = 2000;

            if (Msg) {
                Msg.innerHTML = text;
            } else {
                DOM.load.style({
                    id      : 'msg-css',
                    inner   : '#js-view .msg {'     +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.load({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent,
                    inner       : text
                });
            }

            DOM.show(Msg);

            setTimeout(function() {
                DOM.hide(Msg);
            }, HIDE_TIME);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new flow event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (_module_instance, outConfig, adapter) {

    /**
     * The flow event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (event, _data) {

        /*
        flow: [
            {
                // the event identifier name
                "in": "pattern",

                // react on data events
                "data": [
                    {
                        "emit": "{event}",
                        "call": "{method}",
                        "load": ["{instance}"],
                        "url": "/{url}",
                        "to": "{local|ws|http:instance}"
                    }
                ],

                // module defined outgoing event interface
                "out": {
                    "name": {
                        "emit": "{event}",
                        "call": "{method}",
                        "load": ["{instance}"],
                        "url": "/{url}",
                        "to": "{local|ws|http:instance}",
                    }
                }
            }
        ]
        */

        // create an event object
        event = event || {};
        event.ori = event.ori || _module_instance._name;

        // plug external events
        adapter && adapter.handler(event, adapter.data);

        // extend event with location data (hash, search, path)
        global.location && handleStateValues(event);

        // loop through out configs
        for (var i = 0, l = outConfig.length, config, to, module_instance; i < l; ++i) {

            config = outConfig[i];
            module_instance = _module_instance;

            // check if "to" module instance exists and role has access
            if (
                (config.to && !(module_instance = engine.instances[config.to])) ||
                (event.role && !engine.roleAccess(module_instance, event.role))
            ) {
                continue;
            }

            // check if event loads module instances
            if (config.load) {

                // load module instances
                for (var l = 0; l < config.load.length; ++l) {
                    engine.module(config.load[l]);
                }

                // remove load config, after module instances are loaded
                delete config.load;
            }

            // copy the static data or create a new data object
            var data = config.data ? JSON.parse(JSON.stringify(config.data)) : {};

            // complete dynamic paths
            for (var key in data) {
                if (typeof data[key] === 'string' && data[key].indexOf('{') > -1) {
                    data[key] = parsePath(data[key], event, data, module_instance);
                }
            }

            // merge argument data to data object
            if (_data) {
                for (var key in _data) {
                    data[key] = _data[key];
                }
            }

            // merge static and dynamic data
            data = handleDataMerging(config, event, data, _module_instance);

            // emit route
            if (config.route) {
                engine.route(parsePath(config.route, event, data, module_instance), event, data);
                // ..end event stream
            }

            // emit event
            if (config.emit) {
                module_instance.emit(config.emit, event, data);
            }

            // call method
            if (config.call) {

                // find call method when the event handler is called
                if (typeof config.call === 'string') {
                    config.call = engine.path(config.call, [module_instance, global]) || function () {};
                }

                // call method
                config.call.call(module_instance, event, data);
            }
        }
    };
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (event) {

    // add pathname to data object
    event._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !event._search) {
        event._search = searchToJSON(global.location.search);
    }

    // append url hash to data
    if (global.location.hash && !event._hash) {
        event._hash = global.location.hash.substr(1);
    }
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function handleDataMerging (config, event, data, module_instance) {

    // add dynamic data to the data object
    if (config.set) {

        // add data to the data object
        for (var key in config.set) {

            // parse path
            var path = config.set[key];

            // get an attribute value from a dom element or the element itself
            if (path[0] === '$') {
                path = path.substr(1).split(':');

                // get find an element in the document
                path[0] = document.querySelector(path[0]);

                // set data key to the dom attribute value or the dom element
                data[key] = path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

            // get search value with a path: 1. events, 2. data, 3. instance, 4. window
            } else {
                data[key] = engine.path(path, [event, data, module_instance, global]);
            }
        }

        // create deep object out of flat keys
        data = engine.deep(data);
    }

    return data;
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, event, data, module_instance) {
    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [event, data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = typeof value === 'object' ? value : path.replace(match[i], value);
            }
        }
    }

    return path;
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(search) {
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}
<commit_msg>working on flow event stream handler<commit_after>// regular expression patterns
var find_tmpl = /\{([\w\.]+)\}/g;
var find_braces = /\{|\}/g;

/**
 * Create a new flow event handler.
 *
 * @public
 * @param {object} The module instance.
 * @param {object} The "out" config.
 * @param {object} The adapter object (optional).
 */
engine.flow = function (_module_instance, config, adapter) {

    /**
     * The flow event handler.
     *
     * @public
     * @param {object} The event object.
     * @param {object} The event data.
     */
    return function handler (eventStream) {

        // data event handlers
        if (config.data) {

            for (var i = 0, l = config.data.length, flowConfig; i < l; ++i) {
                flowConfig = config.data[i];
                /*
                {
                    "pipe": "{event}",
                    "call": "{method}",
                    "load": ["{instance}"],
                    "url": "/{url}",
                    "to": "{local|ws|http:instance}"
                }
                */

                // load module instances
                if (flowConfig.load) {
                    // load module instances
                    for (var l = 0; l < flowConfig.load.length; ++l) {
                        engine.module(flowConfig.load[l]);
                    }

                    // remove load config, after module instances are loaded
                    delete flowConfig.load;
                }

                // pipe event to another event
                if (flowConfig.pipe) {
                    eventStream.data(function (err, data) {

                        // create event stream
                        if (typeof flowConfig.pipe === 'string') {
                            flowConfig.pipe = flowConfig.emit(flowConfig.emit);
                        }

                        // send data
                        flowConfig.pipe.send(err, data);
                    });
                }

                // route to url
                if (flowConfig.url) {
                    engine.route(flowConfig.url);
                }

                // append method call event data handlers
                if (flowConfig.call) {

                    // find call method when the event handler is called
                    if (typeof flowConfig.call === 'string') {
                        flowConfig.call = engine.path(flowConfig.call, [module_instance, global]);
                    }

                    // call method
                    if (flowConfig.call) {
                        // module_instance as this?
                        eventStream.data(module_instance, flowConfig.call);
                    }
                }
            }

            // ..create flow data object

            // send first data event with the configured flow data
            eventStream.send();
        }

        /*
        flow: [
            {
                // the event identifier name (handled in the observer)
                "in": "pattern",

                // react on data events (handled in the flow event handler)
                "data": [
                    {
                        "pipe": "{event}",
                        "call": "{method}",
                        "load": ["{instance}"],
                        "url": "/{url}",
                        "to": "{local|ws|http:instance}"
                    }
                ],

                // module defined outgoing event interface (prepared by the flow module, called from module code)
                // save the out handler to the event streams
                "out": {
                    "name": {
                        "pipe": "{event}",
                        "call": "{method}",
                        "load": ["{instance}"],
                        "url": "/{url}",
                        "to": "{local|ws|http:instance}",
                    }
                }
            }
        ]

        // create an event object
        event = event || {};
        event.ori = event.ori || _module_instance._name;

        // plug external events
        adapter && adapter.handler(event, adapter.data);

        // extend event with location data (hash, search, path)
        global.location && handleStateValues(event);

        // loop through out configs
        for (var i = 0, l = outConfig.length, config, to, module_instance; i < l; ++i) {

            config = outConfig[i];
            module_instance = _module_instance;

            // check if "to" module instance exists and role has access
            if (
                (config.to && !(module_instance = engine.instances[config.to])) ||
                (event.role && !engine.roleAccess(module_instance, event.role))
            ) {
                continue;
            }

            // check if event loads module instances
            if (config.load) {

                // load module instances
                for (var l = 0; l < config.load.length; ++l) {
                    engine.module(config.load[l]);
                }

                // remove load config, after module instances are loaded
                delete config.load;
            }

            // copy the static data or create a new data object
            var data = config.data ? JSON.parse(JSON.stringify(config.data)) : {};

            // complete dynamic paths
            for (var key in data) {
                if (typeof data[key] === 'string' && data[key].indexOf('{') > -1) {
                    data[key] = parsePath(data[key], event, data, module_instance);
                }
            }

            // merge argument data to data object
            if (_data) {
                for (var key in _data) {
                    data[key] = _data[key];
                }
            }

            // merge static and dynamic data
            data = handleDataMerging(config, event, data, _module_instance);

            // emit route
            if (config.route) {
                engine.route(parsePath(config.route, event, data, module_instance), event, data);
                // ..end event stream
            }

            // emit event
            if (config.emit) {
                module_instance.emit(config.emit, event, data);
            }

            // call method
            if (config.call) {

                // find call method when the event handler is called
                if (typeof config.call === 'string') {
                    config.call = engine.path(config.call, [module_instance, global]) || function () {};
                }

                // call method
                config.call.call(module_instance, event, data);
            }
        }
        */
    };
}

/**
 * Extend event object with location data.
 *
 * @private
 * @param {object} The event object.
 */
function handleStateValues (event) {

    // add pathname to data object
    event._path = global.location.pathname.substr(1).split('/');

    // parse and append url search to data
    if (global.location.search && !event._search) {
        event._search = searchToJSON(global.location.search);
    }

    // append url hash to data
    if (global.location.hash && !event._hash) {
        event._hash = global.location.hash.substr(1);
    }
}

/**
 * Merge dynamic data to the event data object.
 *
 * @private
 * @param {object} The module instance.
 * @param {object} The event config.
 * @param {object} The event data object.
 */
function handleDataMerging (config, event, data, module_instance) {

    // add dynamic data to the data object
    if (config.set) {

        // add data to the data object
        for (var key in config.set) {

            // parse path
            var path = config.set[key];

            // get an attribute value from a dom element or the element itself
            if (path[0] === '$') {
                path = path.substr(1).split(':');

                // get find an element in the document
                path[0] = document.querySelector(path[0]);

                // set data key to the dom attribute value or the dom element
                data[key] = path[1] && path[0][path[1]] !== undefined ? path[0][path[1]] : path[0];

            // get search value with a path: 1. events, 2. data, 3. instance, 4. window
            } else {
                data[key] = engine.path(path, [event, data, module_instance, global]);
            }
        }

        // create deep object out of flat keys
        data = engine.deep(data);
    }

    return data;
}

/**
 * Replace data fields in a string.
 *
 * @private
 * @param {string} The string.
 * @param {object} The data context.
 */
function parsePath (path, event, data, module_instance) {
    var match = path.match(find_tmpl);

    // replace route with data
    if (match) {
        for (var i = 0, value; i < match.length; ++i) {

            // get value from object
            value = engine.path(match[i].replace(find_braces, ''), [event, data, module_instance]);

            // replace value in route
            if (typeof value !== 'undefined') {
                path = typeof value === 'object' ? value : path.replace(match[i], value);
            }
        }
    }

    return path;
}

/**
 * Parse a state search string to JSON.
 * Credentials: http://snipplr.com/view/70905/search-string-to-json/
 *
 * @private
 */
function searchToJSON(search) {
    var rep = {'?':'{"','=':'":"','&':'","'};
    var s = search.replace(/[\?\=\&]/g, function(r) {
        return rep[r];
    });
    return JSON.parse(s.length? s+'"}' : "{}");
}
<|endoftext|>


<commit_before>/* jslint node: true */
"use strict";

var _ = require('./helpers.js');

function args(arr) {
  return Array.prototype.slice.call(arr);
}

function each(obj, callback) {
  var type = _.typeOf(obj),
      count = 0,
      keys = Object.keys(obj),
      length = keys.length;

  for(; count < length; count++) {
    var key = keys[count];
    callback(obj[key], type === 'object' ? key : count, obj);
  }
}

function isEmpty(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop))
      return false;
  }
  return true;
}

function mixin(dest) {
  var args = module.exports.args(arguments).splice(1),
      count = 0,
      length = args.length;
  for(; count < length; count++) {
    var arg = args[count];
    for(var prop in arg) {
      if(arg.hasOwnProperty(prop)) {
        dest[prop] = arg[prop];
      }
    }
  }
  return dest;
}

function map(obj, callback) {
  var type = _.typeOf(obj),
      count = 0,
      keys = Object.keys(obj),
      length = keys.length,
      returned = type === 'object' ? {} : [];

  for(; count < length; count++) {
    var key = keys[count];
    if(type === 'object') {
      returned[key] = callback(obj[key], key, obj);
    } else {
      returned.push(callback(obj[key], count, obj));
    }
  }

  return returned;
}

function removeWhere(arr, callback) {
  var returned = arr.slice();
  each(arr, function(value, count, obj) {
    if(callback(value, count, obj))
      returned = returned.splice(0, arr.indexOf(value)).concat(returned.splice(arr.indexOf(value) + 1));
  });
  return returned;
}

module.exports = {
  args: args,
  each: each,
  isEmpty: isEmpty,
  mixin: mixin,
  map: map,
  removeWhere: removeWhere
};
<commit_msg>thisArg for each and map.<commit_after>/* jslint node: true */
"use strict";

var _ = require('./helpers.js');

function args(arr) {
  return Array.prototype.slice.call(arr);
}

function each(obj, callback, thisArg) {
  if(typeof thisArg !== "undefined")
    callback = callback.bind(thisArg);

  var type = _.typeOf(obj),
      count = 0,
      keys = Object.keys(obj),
      length = keys.length;

  for(; count < length; count++) {
    var key = keys[count];
    callback(obj[key], type === 'object' ? key : count, obj);
  }
}

function isEmpty(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop))
      return false;
  }
  return true;
}

function mixin(dest) {
  var args = module.exports.args(arguments).splice(1),
      count = 0,
      length = args.length;
  for(; count < length; count++) {
    var arg = args[count];
    for(var prop in arg) {
      if(arg.hasOwnProperty(prop)) {
        dest[prop] = arg[prop];
      }
    }
  }
  return dest;
}

function map(obj, callback, thisArg) {
  if(typeof thisArg !== "undefined")
    callback = callback.bind(thisArg);

  var type = _.typeOf(obj),
      count = 0,
      keys = Object.keys(obj),
      length = keys.length,
      returned = type === 'object' ? {} : [];

  for(; count < length; count++) {
    var key = keys[count];
    if(type === 'object') {
      returned[key] = callback(obj[key], key, obj);
    } else {
      returned.push(callback(obj[key], count, obj));
    }
  }

  return returned;
}

function removeWhere(arr, callback) {
  var returned = arr.slice();
  each(arr, function(value, count, obj) {
    if(callback(value, count, obj))
      returned = returned.splice(0, arr.indexOf(value)).concat(returned.splice(arr.indexOf(value) + 1));
  });
  return returned;
}

module.exports = {
  args: args,
  each: each,
  isEmpty: isEmpty,
  mixin: mixin,
  map: map,
  removeWhere: removeWhere
};
<|endoftext|>


<commit_before>var commands = module.exports;

var support = require('../support'),
    app     = require('../app'),
    util    = require('utile'),
    list    = require('./list'),
    phpjs    = require('phpjs'),
    _       = require('lodash'),
    fs      = require('fs'),
    appTitle = require('../../package.json').title;

/**
 * The real purpose of SpeedDial - changes working directory to the
 * path specified in an entry. If a listing is specified, the children
 * of that directory will be listed and the user is prompted to make a
 * selection
 *
 * **Important**
 *
 * This command doesn't actually do anything in terms of physically changing
 * the terminal's working directory. This CLI runs through node in a child
 * process of the shell, so changing the terminal process' directory is
 * (as far as I know) impossible.
 *
 * Instead, this command stores the path for the new directory to a file in
 * /tmp which the `sd` bash script that SpeedDial is intended to be run through
 * will catch and
 */
var go = module.exports = function(group, alias, callback) {
  "use strict";

  // Initialize
  var key = 'Entry/Listing ID',
      entryResult;

  // Allow for arbitrary number of arguments
  if (alias === null) {
    alias    = group;
    group    = undefined;
  }

  // Help/support functions
      /**
       * Truncates and writes the selected new current working directory to the /tmp file
       * for the bash script to read
       */
  var writeTarget = function(result, output) {
        fs.open(app.config.get('tmpDirFile'), 'w+', 666, function(e, id) {
          fs.write( id, result.entry.path, null, 'utf8', function(){
            fs.close(id, function(){
              if (_.isUndefined(output)) {
                output  = util.format('The %s path', result.entry.path.yellow.bold);
                output += util.format(' from the %s', (result.type === 'listing') ? 'listings'.yellow.bold : util.format('%s group', result.groupName.yellow.bold));
                output += util.format(' with %s', result.entry.alias ? result.entry.alias.yellow.bold : 'no alias'.grey);
                output += ' has been selected';
              }

              app.log.info(output);
              app.log.info(util.format('The %s is now %s', 'current working directory'.yellow.bold, result.entry.path.green.bold));
            });
          });
        });
      },
      /**
       * Displays or retrieves child directory(ies) of a listing path
       *  - if an index is *not* provided, the child directories will be listed
       *    with an index value to be used in a prompt
       *  - if an index is provided, the child matching the index will be returned
       *    in a result object
       */
      listingChildren = function(dir, index) {
        var i    = 0,
            list = fs.readdirSync(dir),
            number, result;

        _.each(list, function(filename) {
          var file = support.normalizePath(dir + '/' + filename);
          if (fs.statSync(file).isDirectory()) {
            if (++i === +index) {
              result = {file: filename, path: file};
            } else if (_.isUndefined(index)) {
              number = phpjs.sprintf("%-26s", i.toString().yellow.bold);
              app.log.info(phpjs.sprintf('%s%-26s', number, filename.green.bold, file));
            }
          }
        });

        if (result) {
          return result;
        }
      },
      /**
       * Lists the entries for a single group and prompts the user to enter the ID
       * or alias associated with the entry they want to change to
       */
      askGroup = function(group, callback){
        list(group, {
          'single-listing': true,
          'exit-if-empty': true
        });

        var key = 'Directory alias or ID';

        app.prompt.get([{
          name: key,
          required: true,
          pattern: /^(\d+|[a-zA-Z][a-zA-Z0-9\-\_]+)$/,
          message: key.bold.grey + ' must match an alias or ID for a directory above',
          conform: function(id){
            return support.hasEntry(group, id);
          }
        }], function(err, result) {
          if (err) {
            return callback(err);
          }

          support.withEntry(group, result[key], function(entryResult) {
            if (!_.isUndefined(callback)) {
              callback(entryResult);
            } else {
              writeTarget(entryResult, util.format('The %s directory, an entry with %s in the %s group, has been selected', entryResult.entry.path.yellow.bold, (entryResult.entry.alias ? entryResult.entry.alias.yellow.bold : 'no alias'.grey), entryResult.groupName.yellow.bold));
            }
          });
        });
      },
      /**
       * Lists the entries for a single listing (@see listingChildren above) and
       * prompts the user to enter the ID or alias associated with the entry
       * they want to change to
       */
      askList = function(entryResult) {
        app.log.info('');
        app.log.info(util.format('Select the target directory within %s for the %s with alias %s', entryResult.entry.path.yellow.bold, 'listing'.yellow.bold, entryResult.entry.alias.yellow.bold));
        app.log.info('');

        listingChildren(entryResult.entry.path);
        var key = 'Directory ID';

        app.prompt.get([{
          name: key,
          required: true,
          pattern: /^\d+$/,
          message: key.bold.grey + ' must match an ID for a directory above',
          conform: function(id){
            return !_.isUndefined(listingChildren(entryResult.entry.path, id));
          }
        }], function(err, result) {
          if (err) {
            return callback(err);
          }

          var target = listingChildren(entryResult.entry.path, result[key]);
          writeTarget({ entry: { path: target.path }}, util.format('The %s directory, a child of %s, the %s with alias %s, has been selected', target.file.yellow.bold, entryResult.entry.path.yellow.bold, 'listing'.yellow.bold, entryResult.entry.alias.yellow.bold));
        });
      };

  // And now the branching logic for the various cases for how this command can be expected to run
  if (!_.isString(alias)) { // no args passed; print a single listing of everything and prompt for an id
    list({
      'single-listing': true,
      'exit-if-empty': true
    });

    app.prompt.get([{
      name: key,
      required: true,
      pattern: /\d+/,
      message: key.bold.grey + ' must match an id for an entry or listing above',
      conform: function(id){
        return support.hasEntry(id);
      }
    }], function(err, result) {
      if (err) {
        return callback(err);
      }

      entryResult = support.withEntry(result[key]);

      if (entryResult.type === 'listing') { // A listing was selected; list the children and prompt again
        askList(entryResult);
      } else {
        writeTarget(entryResult);
      }
    });
  } else if (_.isUndefined(group) && +alias > 0) { // an integer entry id was provided - go to the id within the current group
    entryResult = support.withEntry(app.config.get('currentGroup'), +alias);

    if (!entryResult) {
      return callback(new Error(util.format('The target %s does not match any %s in the %s group', alias.yellow.bold, 'entry ID'.yellow.bold, app.config.get('currentGroup').yellow.bold)));
    }

    writeTarget(entryResult);
  } else if (_.isString(alias) && _.isUndefined(group)) { // a string alias was provided - go to the alias within the current group
    entryResult = support.withEntry(app.config.get('currentGroup'), alias);

    if (!entryResult) {
      if (app.config.get('globalLookupFallback')) {
        entryResult = support.withEntry(alias);

        if (entryResult.type === 'entry') {
          return writeTarget(entryResult);
        }
      }

      // if it didn't match an alias in the current group, check if it's a group name, an alias for a listing or if 'listings' was passed (special case)
      if (alias === 'listings') {
        askGroup('listings', function(entryResult){ // 'listings' was passed - list the listings, prompt the user, list the children and prompt again
          askList(entryResult);
        });
      } else {
        if (entryResult = support.withEntry('listings', alias)) { // check the listing aliases for a match, list the children, and prompt again
          askList(entryResult);
        } else if (entryResult = support.withEntry(alias, 1)) { // check the group names for a match, list the group entries, and prompt again
          askGroup(alias);
        } else {
          return callback(new Error(util.format('The target %s does not match any %s in the %s group', alias.yellow.bold, 'alias'.yellow.bold, app.config.get('currentGroup').yellow.bold)));
        }
      }

      // @todo Add an option here (set through the config) to look further, at aliases for entries
      //       within other unspecified groups for a match.
    } else {
      writeTarget(entryResult);
    }
  } else if (_.isString(group) && (_.isString(alias) || +alias > 0)) { // a group and alias were entered - go to the alias within the specified group
    entryResult = support.withEntry(group, alias);

    if (!entryResult) {
      return callback(new Error(util.format('The target %s does not match any %s or id in the %s group', alias.yellow.bold, 'alias'.yellow.bold, group)));
    }

    writeTarget(entryResult);
  } else {
    return callback(new Error(util.format('The command format was not recognized by %s', appTitle.blue.bold)));
  }
};<commit_msg>Fixes issue writing the path to cd into to a /tmp file<commit_after>var commands = module.exports;

var support = require('../support'),
    app     = require('../app'),
    util    = require('utile'),
    list    = require('./list'),
    phpjs    = require('phpjs'),
    _       = require('lodash'),
    fs      = require('fs'),
    appTitle = require('../../package.json').title;

/**
 * The real purpose of SpeedDial - changes working directory to the
 * path specified in an entry. If a listing is specified, the children
 * of that directory will be listed and the user is prompted to make a
 * selection
 *
 * **Important**
 *
 * This command doesn't actually do anything in terms of physically changing
 * the terminal's working directory. This CLI runs through node in a child
 * process of the shell, so changing the terminal process' directory is
 * (as far as I know) impossible.
 *
 * Instead, this command stores the path for the new directory to a file in
 * /tmp which the `sd` bash script that SpeedDial is intended to be run through
 * will catch and
 */
var go = module.exports = function(group, alias, callback) {
  "use strict";

  // Initialize
  var key = 'Entry/Listing ID',
      entryResult;

  // Allow for arbitrary number of arguments
  if (alias === null) {
    alias    = group;
    group    = undefined;
  }

  // Help/support functions
      /**
       * Truncates and writes the selected new current working directory to the /tmp file
       * for the bash script to read
       */
  var writeTarget = function(result, output) {
        fs.writeFile(app.config.get('tmpDirFile'), result.entry.path, function(e) {
          if (e) {
            return callback(util.format('The path %s could not be written to: %s', app.config.get('tmpDirFile').yellow.bold, e.red.bold));
          } else {
            if (_.isUndefined(output)) {
              output  = util.format('The %s path', result.entry.path.yellow.bold);
              output += util.format(' from the %s', (result.type === 'listing') ? 'listings'.yellow.bold : util.format('%s group', result.groupName.yellow.bold));
              output += util.format(' with %s', result.entry.alias ? result.entry.alias.yellow.bold : 'no alias'.grey);
              output += ' has been selected';
            }

            app.log.info(output);
            app.log.info(util.format('The %s is now %s', 'current working directory'.yellow.bold, result.entry.path.green.bold));
          }
        });
      },
      /**
       * Displays or retrieves child directory(ies) of a listing path
       *  - if an index is *not* provided, the child directories will be listed
       *    with an index value to be used in a prompt
       *  - if an index is provided, the child matching the index will be returned
       *    in a result object
       */
      listingChildren = function(dir, index) {
        var i    = 0,
            list = fs.readdirSync(dir),
            number, result;

        _.each(list, function(filename) {
          var file = support.normalizePath(dir + '/' + filename);
          if (fs.statSync(file).isDirectory()) {
            if (++i === +index) {
              result = {file: filename, path: file};
            } else if (_.isUndefined(index)) {
              number = phpjs.sprintf("%-26s", i.toString().yellow.bold);
              app.log.info(phpjs.sprintf('%s%-26s', number, filename.green.bold, file));
            }
          }
        });

        if (result) {
          return result;
        }
      },
      /**
       * Lists the entries for a single group and prompts the user to enter the ID
       * or alias associated with the entry they want to change to
       */
      askGroup = function(group, callback){
        list(group, {
          'single-listing': true,
          'exit-if-empty': true
        });

        var key = 'Directory alias or ID';

        app.prompt.get([{
          name: key,
          required: true,
          pattern: /^(\d+|[a-zA-Z][a-zA-Z0-9\-\_]+)$/,
          message: key.bold.grey + ' must match an alias or ID for a directory above',
          conform: function(id){
            return support.hasEntry(group, id);
          }
        }], function(err, result) {
          if (err) {
            return callback(err);
          }

          support.withEntry(group, result[key], function(entryResult) {
            if (!_.isUndefined(callback)) {
              callback(entryResult);
            } else {
              writeTarget(entryResult, util.format('The %s directory, an entry with %s in the %s group, has been selected', entryResult.entry.path.yellow.bold, (entryResult.entry.alias ? entryResult.entry.alias.yellow.bold : 'no alias'.grey), entryResult.groupName.yellow.bold));
            }
          });
        });
      },
      /**
       * Lists the entries for a single listing (@see listingChildren above) and
       * prompts the user to enter the ID or alias associated with the entry
       * they want to change to
       */
      askList = function(entryResult) {
        app.log.info('');
        app.log.info(util.format('Select the target directory within %s for the %s with alias %s', entryResult.entry.path.yellow.bold, 'listing'.yellow.bold, entryResult.entry.alias.yellow.bold));
        app.log.info('');

        listingChildren(entryResult.entry.path);
        var key = 'Directory ID';

        app.prompt.get([{
          name: key,
          required: true,
          pattern: /^\d+$/,
          message: key.bold.grey + ' must match an ID for a directory above',
          conform: function(id){
            return !_.isUndefined(listingChildren(entryResult.entry.path, id));
          }
        }], function(err, result) {
          if (err) {
            return callback(err);
          }

          var target = listingChildren(entryResult.entry.path, result[key]);
          writeTarget({ entry: { path: target.path }}, util.format('The %s directory, a child of %s, the %s with alias %s, has been selected', target.file.yellow.bold, entryResult.entry.path.yellow.bold, 'listing'.yellow.bold, entryResult.entry.alias.yellow.bold));
        });
      };

  // And now the branching logic for the various cases for how this command can be expected to run
  if (!_.isString(alias)) { // no args passed; print a single listing of everything and prompt for an id
    list({
      'single-listing': true,
      'exit-if-empty': true
    });

    app.prompt.get([{
      name: key,
      required: true,
      pattern: /\d+/,
      message: key.bold.grey + ' must match an id for an entry or listing above',
      conform: function(id){
        return support.hasEntry(id);
      }
    }], function(err, result) {
      if (err) {
        return callback(err);
      }

      entryResult = support.withEntry(result[key]);

      if (entryResult.type === 'listing') { // A listing was selected; list the children and prompt again
        askList(entryResult);
      } else {
        writeTarget(entryResult);
      }
    });
  } else if (_.isUndefined(group) && +alias > 0) { // an integer entry id was provided - go to the id within the current group
    entryResult = support.withEntry(app.config.get('currentGroup'), +alias);

    if (!entryResult) {
      return callback(new Error(util.format('The target %s does not match any %s in the %s group', alias.yellow.bold, 'entry ID'.yellow.bold, app.config.get('currentGroup').yellow.bold)));
    }

    writeTarget(entryResult);
  } else if (_.isString(alias) && _.isUndefined(group)) { // a string alias was provided - go to the alias within the current group
    entryResult = support.withEntry(app.config.get('currentGroup'), alias);

    if (!entryResult) {
      if (app.config.get('globalLookupFallback')) {
        entryResult = support.withEntry(alias);

        if (entryResult.type === 'entry') {
          return writeTarget(entryResult);
        }
      }

      // if it didn't match an alias in the current group, check if it's a group name, an alias for a listing or if 'listings' was passed (special case)
      if (alias === 'listings') {
        askGroup('listings', function(entryResult){ // 'listings' was passed - list the listings, prompt the user, list the children and prompt again
          askList(entryResult);
        });
      } else {
        if (entryResult = support.withEntry('listings', alias)) { // check the listing aliases for a match, list the children, and prompt again
          askList(entryResult);
        } else if (entryResult = support.withEntry(alias, 1)) { // check the group names for a match, list the group entries, and prompt again
          askGroup(alias);
        } else {
          return callback(new Error(util.format('The target %s does not match any %s in the %s group', alias.yellow.bold, 'alias'.yellow.bold, app.config.get('currentGroup').yellow.bold)));
        }
      }

      // @todo Add an option here (set through the config) to look further, at aliases for entries
      //       within other unspecified groups for a match.
    } else {
      writeTarget(entryResult);
    }
  } else if (_.isString(group) && (_.isString(alias) || +alias > 0)) { // a group and alias were entered - go to the alias within the specified group
    entryResult = support.withEntry(group, alias);

    if (!entryResult) {
      return callback(new Error(util.format('The target %s does not match any %s or id in the %s group', alias.yellow.bold, 'alias'.yellow.bold, group)));
    }

    writeTarget(entryResult);
  } else {
    return callback(new Error(util.format('The command format was not recognized by %s', appTitle.blue.bold)));
  }
};
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var request = require('./util/request');
var debug = require('debug')('wpcom:commentlike');

/**
 * CommentLike methods
 *
 * @param {String} cid comment id
 * @param {String} sid site id
 * @param {WPCOM} wpcom
 * @api public
 */

function CommentLike(cid, sid, wpcom){
  if (!sid) {
    throw new Error('`side id` is not correctly defined');
  }

  if (!cid) {
    throw new Error('`comment id` is not correctly defined');
  }

  if (!(this instanceof CommentLike)) return new CommentLike(cid, sid, wpcom);

  this.wpcom = wpcom;
  this._cid = cid;
  this._sid = sid;
}

/**
 * Get your Like status for a Comment
 *
 * @param {Object} [query]
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype.state =
CommentLike.prototype.mine = function(query, fn){
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/mine';
  return request.get(this.wpcom, null, path, query, fn);
};

/**
 * Like a comment
 *
 * @param {Object} [query]
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype.add = function(query, body, fn){
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/new';
  return request.post(this.wpcom, null, path, query, body, fn);
};

/**
 * Remove your Like from a Comment
 *
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype['delete'] =
CommentLike.prototype.del = function(query, fn){
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/mine/delete';
  return request.del(this.wpcom, null, path, query, fn);
};

/**
 * Expose `CommentLike` module
 */

module.exports = CommentLike;
<commit_msg>commentlike: update coding<commit_after>
/**
 * Module dependencies.
 */

var request = require('./util/request');
var debug = require('debug')('wpcom:commentlike');

/**
 * CommentLike methods
 *
 * @param {String} cid comment id
 * @param {String} sid site id
 * @param {WPCOM} wpcom
 * @api public
 */

function CommentLike(cid, sid, wpcom) {
  if (!sid) {
    throw new Error('`side id` is not correctly defined');
  }

  if (!cid) {
    throw new Error('`comment id` is not correctly defined');
  }

  if (!(this instanceof CommentLike)) {
    return new CommentLike(cid, sid, wpcom);
  }

  this.wpcom = wpcom;
  this._cid = cid;
  this._sid = sid;
}

/**
 * Get your Like status for a Comment
 *
 * @param {Object} [query]
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype.state =
CommentLike.prototype.mine = function (query, fn) {
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/mine';
  return request.get(this.wpcom, null, path, query, fn);
};

/**
 * Like a comment
 *
 * @param {Object} [query]
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype.add = function (query, body, fn) {
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/new';
  return request.post(this.wpcom, null, path, query, body, fn);
};

/**
 * Remove your Like from a Comment
 *
 * @param {Function} fn
 * @api public
 */

CommentLike.prototype['delete'] =
CommentLike.prototype.del = function (query, fn) {
  var path = '/sites/' + this._sid + '/comments/' + this._cid + '/likes/mine/delete';
  return request.del(this.wpcom, null, path, query, fn);
};

/**
 * Expose `CommentLike` module
 */

module.exports = CommentLike;<|endoftext|>


<commit_before>module.exports = {
  root: true,

  parser: require.resolve('vue-eslint-parser'),

  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true
    }
  },

  env: {
    browser: true,
    es6: true
  },

  plugins: [
    'vue'
  ]
}
<commit_msg>Update base config to use objectSpread feature (#62)<commit_after>module.exports = {
  root: true,

  parser: require.resolve('vue-eslint-parser'),

  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true
    }
  },

  env: {
    browser: true,
    es6: true
  },

  plugins: [
    'vue'
  ]
}
<|endoftext|>