<commit_before>function getLoc() {
    var url = document.createElement("a");
    url.href=document.URL;
    var loc = url.search;
    if (loc.indexOf("loc=") === 1) {
				       loc = loc.substring(5);
				       console.log("LOC TO PARSE IS: " + loc);
				   }
    return loc;
}

var epeek_theme = function() {
    "use strict";

    // Regular expressions for user input
    // TODO: species:gene?
    // TODO: Duplicated in compact.js (loc_re) and genome.js (ens_re)
    var loc_re = /^(\w+):(\w+):(\d+)-(\d+)$/;
    var ens_re = /^ENS\w+\d+$/;

    var path = epeek.scriptPath("compact.js");

    var gBrowser;
    var gBrowserTheme = function(gB, div) {
	gBrowser = gB;

	// Callbacks:
	gBrowser.gene_info_callback = gene_info_callback;
	var loc = getLoc();

	if (gBrowserTheme.isLocation(loc)) {
	    gBrowserTheme.parseLocation(loc);
	} else {
	    gBrowser.gene(loc);
	}

	gBrowser(div);
	gBrowser.start();

	gBrowserTheme.orientationChange();

    };

    /** parseLocation takes a string as input and guesses a location
        The expected location should be on the form:
        species:chr:from-to
    */
    gBrowserTheme.parseLocation = function(loc) {
    // TODO: What happens on error? i.e. if the string is not a valid location
    // TODO: We can make it smarter? allowing for examples species:gene?
	var loc_arr = loc_re.exec(loc);
	gBrowser.species(loc_arr[1]);
	gBrowser.chr(loc_arr[2]);
	gBrowser.from(loc_arr[3]);
	gBrowser.to(loc_arr[4]);

	return gBrowserTheme;
    };

    /** isLocation returns true if the argument looks like a location of the form
	species:chr:from-to or false otherwise
    */
    gBrowserTheme.isLocation = function(term) {
	// TODO: Can this method be abstracted out? (This is also defined in clients/lib/compact.js)
	if (term.match(loc_re)) {
	    return true;
	} else {
	    return false;
	}
    };

    var homologues_cbak = function (homologues) {
	console.log("HOMOLOGUES: ");
	console.log(homologues);

	var orthologues = homologues.orthologues;
	var paralogues  = homologues.paralogues;

	var orth_select = d3.select("#ePeek_orthologues_select")
	    .attr("id", "ePeek_orth_select");

	orth_select
	    .append("option")
	    .attr("class", "ePeek_orth_option")
	    .text("-- Jump to ortholog --")

	orth_select.selectAll("option2")
	    .data(orthologues, function(d){return d.id})
	    .enter()
	    .append("option")
	    .attr("class", "ePeek_orth_option")
	    .attr("value", function(d) {return d.id})
	    .text(function(d) {return d.id + " (" + d.species + " - " + d.type + ")"});

	// We fill the number of orthologues in the tab label
	d3.select("#ePeek_orthologues_label")
	    .html("Orthologues [" + (orthologues === undefined ? 0 : orthologues.length) + "]");

	// We listen on orthologues options
	orth_select.on("change", function() {
//	    d3.select("#ePeek_" + div_id + "_ensGene_select").remove();
	    gBrowser.start({
		gene : this.value
	    });
	});
     };

    var gene_info_callback = function(gene) {
	// We first remove previous data and elements
//	d3.select("#gene_content div").remove();
	d3.select("#gene_content ul").remove();

	// We update the text of the header in the info div
	d3.select("#gene_info h1").text(gene.external_name);

	// We then populate the gene info
	var gene_info_items_list = d3.select("#gene_content")
	    .append("ul")
	    .attr("class", "edgetoedge scroll");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .text("Gene Info")

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Ensembl ID: " + gene.ID);

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Description: " + gene.description);

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Source: " + gene.logic_name);

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .html("Location");

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Current species: " + gBrowser.species());

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Location: " + gene.seq_region_name + ":" + gene.start + "-" + gene.end + " (Strand: " + (gene.strand === "1" ? "+" : "-") + ")");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .attr("id", "ePeek_orthologues_label")
	    .html("Orthologues");

	var gene_info_items_orthologues = gene_info_items_list
	    .append("li")
	    .attr("class", "rounded");

	gene_info_items_orthologues
	    .append("img")
	    .attr("src", path + "../pics/compara_ortho_bw.png");

	gene_info_items_orthologues
	    .append("select")
	    .attr("id", "ePeek_orthologues_select");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .html("Open " + gene.external_name + " in...");

	gene_info_items_list
	    .append("li")
	    .attr("class", "arrow")
	    .append("a")
	    .attr("href", gBrowserTheme.buildEnsemblGeneLink(gene.ID))
	    .attr("target", "_blank")
	    .append("img")
	    .attr("src", path + "../pics/ensembl_logo_small.png");

	// Fill the orthologues select
	gBrowser.homologues(gene.ID, homologues_cbak);

	$("#ePeek_gene_info_link").trigger("tap");
	// TODO: This way of getting to the gene_info div prevents the use of
	// transitions. We may find a better way
//	window.location.href="#gene_info";

    };

    // TODO: Duplicated in default.js
    /** buildEnsemblGeneLink returns the Ensembl url pointing to the gene summary given in as argument
	The gene id shouuld be a valid ensembl gene id of the form "ENSG......XXXX"
    */
    gBrowserTheme.buildEnsemblGeneLink = function(ensID) {
	//"http://www.ensembl.org/Homo_sapiens/Gene/Summary?g=ENSG00000139618"
	var url = "http://www.ensembl.org/" + gBrowser.species() + "/Gene/Summary?g=" + ensID;
	return url;
    };

    gBrowserTheme.orientationChange = function() {

	// Default Android browser based on the WebKit engine
	// which also powers the Safari browser on desktops, laptops and Apple's iOS-based mobile devices
	// doesn't seem to understand window.matchMedia, so we need to use this alternative.
	window.onorientationchange = function() {
	    // Strangely enough, default android browser reverses clientWidth and clientHeight?
	    // TODO: Post a question somewhere? (StackOverflow?) -> DONE
	    // TODO: It seems that introducing a short delay (500ms) the clientWidth and clientHeight are properly set
            setTimeout(function() {
		// This may be needed for IE for mobiles?
		//        var w=window.innerWidth
		//           || document.documentElement.clientWidth
		//           || document.body.clientWidth;

		var w = document.documentElement.clientWidth;
		gBrowser.resize(w-20);
            }, 500);
	}
    };

    return gBrowserTheme;

};<commit_msg>bugfix: Resize is deprecated. Using width (which is dynamic) instead<commit_after>function getLoc() {
    var url = document.createElement("a");
    url.href=document.URL;
    var loc = url.search;
    if (loc.indexOf("loc=") === 1) {
				       loc = loc.substring(5);
				       console.log("LOC TO PARSE IS: " + loc);
				   }
    return loc;
}

var epeek_theme = function() {
    "use strict";

    // Regular expressions for user input
    // TODO: species:gene?
    // TODO: Duplicated in compact.js (loc_re) and genome.js (ens_re)
    var loc_re = /^(\w+):(\w+):(\d+)-(\d+)$/;
    var ens_re = /^ENS\w+\d+$/;

    var path = epeek.scriptPath("compact.js");

    var gBrowser;
    var gBrowserTheme = function(gB, div) {
	gBrowser = gB;

	// Callbacks:
	gBrowser.gene_info_callback = gene_info_callback;
	var loc = getLoc();

	if (gBrowserTheme.isLocation(loc)) {
	    gBrowserTheme.parseLocation(loc);
	} else {
	    gBrowser.gene(loc);
	}

	gBrowser(div);
	gBrowser.start();

	gBrowserTheme.orientationChange();

    };

    /** parseLocation takes a string as input and guesses a location
        The expected location should be on the form:
        species:chr:from-to
    */
    gBrowserTheme.parseLocation = function(loc) {
    // TODO: What happens on error? i.e. if the string is not a valid location
    // TODO: We can make it smarter? allowing for examples species:gene?
	var loc_arr = loc_re.exec(loc);
	gBrowser.species(loc_arr[1]);
	gBrowser.chr(loc_arr[2]);
	gBrowser.from(loc_arr[3]);
	gBrowser.to(loc_arr[4]);

	return gBrowserTheme;
    };

    /** isLocation returns true if the argument looks like a location of the form
	species:chr:from-to or false otherwise
    */
    gBrowserTheme.isLocation = function(term) {
	// TODO: Can this method be abstracted out? (This is also defined in clients/lib/compact.js)
	if (term.match(loc_re)) {
	    return true;
	} else {
	    return false;
	}
    };

    var homologues_cbak = function (homologues) {
	console.log("HOMOLOGUES: ");
	console.log(homologues);

	var orthologues = homologues.orthologues;
	var paralogues  = homologues.paralogues;

	var orth_select = d3.select("#ePeek_orthologues_select")
	    .attr("id", "ePeek_orth_select");

	orth_select
	    .append("option")
	    .attr("class", "ePeek_orth_option")
	    .text("-- Jump to ortholog --")

	orth_select.selectAll("option2")
	    .data(orthologues, function(d){return d.id})
	    .enter()
	    .append("option")
	    .attr("class", "ePeek_orth_option")
	    .attr("value", function(d) {return d.id})
	    .text(function(d) {return d.id + " (" + d.species + " - " + d.type + ")"});

	// We fill the number of orthologues in the tab label
	d3.select("#ePeek_orthologues_label")
	    .html("Orthologues [" + (orthologues === undefined ? 0 : orthologues.length) + "]");

	// We listen on orthologues options
	orth_select.on("change", function() {
//	    d3.select("#ePeek_" + div_id + "_ensGene_select").remove();
	    gBrowser.start({
		gene : this.value
	    });
	});
     };

    var gene_info_callback = function(gene) {
	// We first remove previous data and elements
//	d3.select("#gene_content div").remove();
	d3.select("#gene_content ul").remove();

	// We update the text of the header in the info div
	d3.select("#gene_info h1").text(gene.external_name);

	// We then populate the gene info
	var gene_info_items_list = d3.select("#gene_content")
	    .append("ul")
	    .attr("class", "edgetoedge scroll");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .text("Gene Info")

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Ensembl ID: " + gene.ID);

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Description: " + gene.description);

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Source: " + gene.logic_name);

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .html("Location");

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Current species: " + gBrowser.species());

	gene_info_items_list
	    .append("li")
	    .attr("class", "rounded")
	    .html("Location: " + gene.seq_region_name + ":" + gene.start + "-" + gene.end + " (Strand: " + (gene.strand === "1" ? "+" : "-") + ")");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .attr("id", "ePeek_orthologues_label")
	    .html("Orthologues");

	var gene_info_items_orthologues = gene_info_items_list
	    .append("li")
	    .attr("class", "rounded");

	gene_info_items_orthologues
	    .append("img")
	    .attr("src", path + "../pics/compara_ortho_bw.png");

	gene_info_items_orthologues
	    .append("select")
	    .attr("id", "ePeek_orthologues_select");

	gene_info_items_list
	    .append("li")
	    .attr("class", "sep")
	    .html("Open " + gene.external_name + " in...");

	gene_info_items_list
	    .append("li")
	    .attr("class", "arrow")
	    .append("a")
	    .attr("href", gBrowserTheme.buildEnsemblGeneLink(gene.ID))
	    .attr("target", "_blank")
	    .append("img")
	    .attr("src", path + "../pics/ensembl_logo_small.png");

	// Fill the orthologues select
	gBrowser.homologues(gene.ID, homologues_cbak);

	$("#ePeek_gene_info_link").trigger("tap");
	// TODO: This way of getting to the gene_info div prevents the use of
	// transitions. We may find a better way
//	window.location.href="#gene_info";

    };

    // TODO: Duplicated in default.js
    /** buildEnsemblGeneLink returns the Ensembl url pointing to the gene summary given in as argument
	The gene id shouuld be a valid ensembl gene id of the form "ENSG......XXXX"
    */
    gBrowserTheme.buildEnsemblGeneLink = function(ensID) {
	//"http://www.ensembl.org/Homo_sapiens/Gene/Summary?g=ENSG00000139618"
	var url = "http://www.ensembl.org/" + gBrowser.species() + "/Gene/Summary?g=" + ensID;
	return url;
    };

    gBrowserTheme.orientationChange = function() {

	// Default Android browser based on the WebKit engine
	// which also powers the Safari browser on desktops, laptops and Apple's iOS-based mobile devices
	// doesn't seem to understand window.matchMedia, so we need to use this alternative.
	window.onorientationchange = function() {
	    // Strangely enough, default android browser reverses clientWidth and clientHeight?
	    // TODO: Post a question somewhere? (StackOverflow?) -> DONE
	    // TODO: It seems that introducing a short delay (500ms) the clientWidth and clientHeight are properly set
            setTimeout(function() {
		// This may be needed for IE for mobiles?
		//        var w=window.innerWidth
		//           || document.documentElement.clientWidth
		//           || document.body.clientWidth;

		var w = document.documentElement.clientWidth;
		gBrowser.width(w-20);
            }, 500);
	}
    };

    return gBrowserTheme;

};<|endoftext|>


<commit_before>'use strict';

var passport = require('passport'),
    utils = require('../lib/utils'),
    sc = require('../lib/sc'),
    agentSchema = require('../schemata/agent'),
    extend = require('extend'),
    multiparty = require('connect-multiparty'),
    q = require('q'),
    winston = require('winston');

module.exports = function(email) {

    var logger = new (winston.Logger)({ transports: [ new (winston.transports.Console)({ colorize: true }) ] });

    // Turn the email into a mongo-friendly database name
    var dbName = utils.ensureDbName(email);
    var action = require('../actions')(dbName);

    /**
     * Handle incoming attempts to perform
     * actions on the data specified in the message
     */
    var _handler = function(req, res, done) {

        var message = req.body,
            agent = req.user;

        logger.info('message', JSON.stringify(message, null, 2));
        logger.info('req.files', JSON.stringify(req.files, null, 2));

        // Form a social commitment
        sc.form(agent, 'perform', message).
            then(function(socialCommitment) {
                _verify(agent, message).
                    then(function(verified) {

                        // There might be files attached to the message.
                        // They are included here, because it seems
                        // silly to attach them to the social commitment.
                        extend(true, message, req.files);

                        console.log('verified', verified);

                        /**
                         * Make sure this agent knows how to
                         * perform the requested action
                         */
                        if(!action[message.action]) {
                          res.send(501, 'I don\'t know how to ' + message.action);
                          done();
                        }
                        else {
                          action[message.action](verified, message).
                              then(function(data) {
                                 sc.fulfil(message.receiver, socialCommitment._id).
                                      then(function(sc) {
                                          logger.info('data', data);
                                          res.send(200, data);
                                          done();
                                        }).
                                      catch(function(err) {
                                          logger.error('Social commitment fulfil', err);
                                          res.send(401, err);
                                          done(err);
                                        });
                                }).
                              catch(function(err) {
                                      logger.error('Action', err);
                                      res.send(401, err);
                                      done(err);
                                });
                        }
                      }).
                    catch(function(err) {
                        logger.error('Verification', err);
                        res.send(401, err);
                        done(err);
                      });
              }).
            catch(function(err) {
                logger.error('Cannot commit', err);
                res.send(401, err);
                done(err);
              });
       };
    exports.handler = _handler;

    /**
     * Authenticate, if necessary
     */
    function _authenticate(req, res, next) {
        if (req.user) {
          return next();
        }

        passport.authenticate(['bearer'], { session: false })(req, res, next);
      };
    exports.authenticate = _authenticate;

    /**
     * Receive a perform attempt for consideration
     */
    var multipartyMiddleware = multiparty();
    exports.perform = [
        multipartyMiddleware,
        _authenticate,
        // _handler takes a callback for unit testing purposes.
        // passport.authenticate's next() callback screws everything up
        // when the server runs for real. This step, though goofy looking,
        // circumvents that issue.
        function(req, res, next) {
            _handler(req, res, function(){});
        }
      ];

    /**
     * Determine what permissions an agent has on a
     * given object
     *
     * @param Object
     * @param Object
     *
     * @return promise
     */
    function _verify(agent, message) {
        var deferred = q.defer();

	// A message's contents may be received as a string.
	if (typeof message.content === 'string') {
	  message.content = JSON.parse(message.content);
	}

        // A resource does not necessarily need to be specified
        // in every circumstance. The following is experimental
        var resource;
        if (message.content && message.content.resource) {
          resource = utils.getMongoCollectionName(message.content.resource);
        }
        // Experimental:
        // If no resource is set, it is assumed the call to action
        // is not tied with any resource. This is a temporary workaround.
        // At the moment, this behaviour is enabled by setting execute permissions
        // on the gebo agent's own email address.
        //
        // Obviously, this all needs to change
        else {
          resource = utils.getMongoCollectionName(message.receiver);
        }

        var verified = {
                collectionName: resource,
		admin: agent.admin,
		dbName: utils.getMongoDbName(message.receiver),
		read: false,
		write: false,
		execute: false,
            };

        if (!verified.dbName) {
          verified.dbName = utils.getMongoDbName(agent.email);
        }

        if (utils.getMongoDbName(agent.email) !== verified.dbName && !verified.admin) {
          var agentDb = new agentSchema(verified.dbName);

          agentDb.friendModel.findOne({ email: agent.email }, function(err, friend) {
                logger.info('friendo:', agent.email, JSON.stringify(friend, null, 2));
                if (err) {
                  deferred.reject(err);
                }
                if (!friend) {
                  deferred.resolve(verified);
                  //deferred.reject('I don\'t know you');
                }
                else {
                  // Search the array for relevant resource
                  var index = utils.getIndexOfObject(friend.hisPermissions, 'email', verified.collectionName);

                  if (index > -1) {
                    verified.read = friend.hisPermissions[index].read;
                    verified.write = friend.hisPermissions[index].write;
                    verified.execute = friend.hisPermissions[index].execute;
                  }

                  deferred.resolve(verified);
                }
              });
        }
        // This agent is attempting to perform an action on his own resource
        else {
          verified.read = true;
          verified.write = true;
          verified.execute = true;
          deferred.resolve(verified);
        }

        return deferred.promise;
      };
    exports.verify = _verify;

    return exports;
  };

<commit_msg>Init agentDb in global scope and deploy winston logger<commit_after>'use strict';

var action = require('../actions')(),
    passport = require('passport'),
    utils = require('../lib/utils'),
    sc = require('../lib/sc'),
    agentDb = require('../schemata/agent')(),
    extend = require('extend'),
    multiparty = require('connect-multiparty'),
    q = require('q'),
    winston = require('winston');

module.exports = function() {

    var logger = new (winston.Logger)({ transports: [ new (winston.transports.Console)({ colorize: true }) ] });

    /**
     * Handle incoming attempts to perform
     * actions on the data specified in the message
     */
    var _handler = function(req, res, done) {

        var message = req.body,
            agent = req.user;

        logger.info('message', JSON.stringify(message, null, 2));
        logger.info('req.files', JSON.stringify(req.files, null, 2));

        // Form a social commitment
        sc.form(agent, 'perform', message).
            then(function(socialCommitment) {
                _verify(agent, message).
                    then(function(verified) {

                        // There might be files attached to the message.
                        // They are included here, because it seems
                        // silly to attach them to the social commitment.
                        extend(true, message, req.files);

                        logger.info('verified', verified);

                        /**
                         * Make sure this agent knows how to
                         * perform the requested action
                         */
                        if(!action[message.action]) {
                          res.send(501, 'I don\'t know how to ' + message.action);
                          done();
                        }
                        else {
                          action[message.action](verified, message).
                              then(function(data) {
                                 sc.fulfil(message.receiver, socialCommitment._id).
                                      then(function(sc) {
                                          logger.info('data', data);
                                          res.send(200, data);
                                          done();
                                        }).
                                      catch(function(err) {
                                          logger.error('Social commitment fulfil', err);
                                          res.send(401, err);
                                          done(err);
                                        });
                                }).
                              catch(function(err) {
                                      logger.error('Action', err);
                                      res.send(401, err);
                                      done(err);
                                });
                        }
                      }).
                    catch(function(err) {
                        logger.error('Verification', err);
                        res.send(401, err);
                        done(err);
                      });
              }).
            catch(function(err) {
                logger.error('Cannot commit', err);
                res.send(401, err);
                done(err);
              });
       };
    exports.handler = _handler;

    /**
     * Authenticate, if necessary
     */
    function _authenticate(req, res, next) {
        if (req.user) {
          return next();
        }

        passport.authenticate(['bearer'], { session: false })(req, res, next);
      };
    exports.authenticate = _authenticate;

    /**
     * Receive a perform attempt for consideration
     */
    var multipartyMiddleware = multiparty();
    exports.perform = [
        multipartyMiddleware,
        _authenticate,
        // _handler takes a callback for unit testing purposes.
        // passport.authenticate's next() callback screws everything up
        // when the server runs for real. This step, though goofy looking,
        // circumvents that issue.
        function(req, res, next) {
            _handler(req, res, function(){});
        }
      ];

    /**
     * Determine what permissions an agent has on a
     * given object
     *
     * @param Object
     * @param Object
     *
     * @return promise
     */
    function _verify(agent, message) {
        var deferred = q.defer();

	// A message's contents may be received as a string.
	if (typeof message.content === 'string') {
	  message.content = JSON.parse(message.content);
	}

        // A resource does not necessarily need to be specified
        // in every circumstance. The following is experimental
        var resource;
        if (message.content && message.content.resource) {
          resource = utils.getMongoCollectionName(message.content.resource);
        }
        // Experimental:
        // If no resource is set, it is assumed the call to action
        // is not tied with any resource. This is a temporary workaround.
        // At the moment, this behaviour is enabled by setting execute permissions
        // on the gebo agent's own email address.
        //
        // Obviously, this all needs to change
        else {
          resource = utils.getMongoCollectionName(message.receiver);
        }

        var verified = {
                collectionName: resource,
		admin: agent.admin,
		dbName: utils.getMongoDbName(message.receiver),
		read: false,
		write: false,
		execute: false,
            };

        if (!verified.dbName) {
          verified.dbName = utils.getMongoDbName(agent.email);
        }

        if (utils.getMongoDbName(agent.email) !== verified.dbName && !verified.admin) {
          agentDb.friendModel.findOne({ email: agent.email }, function(err, friend) {
                logger.info('friendo:', agent.email, JSON.stringify(friend, null, 2));
                if (err) {
                  deferred.reject(err);
                }
                if (!friend) {
                  deferred.resolve(verified);
                  //deferred.reject('I don\'t know you');
                }
                else {
                  // Search the array for relevant resource
                  var index = utils.getIndexOfObject(friend.hisPermissions, 'email', verified.collectionName);

                  if (index > -1) {
                    verified.read = friend.hisPermissions[index].read;
                    verified.write = friend.hisPermissions[index].write;
                    verified.execute = friend.hisPermissions[index].execute;
                  }

                  deferred.resolve(verified);
                }
              });
        }
        // This agent is attempting to perform an action on his own resource
        else {
          verified.read = true;
          verified.write = true;
          verified.execute = true;
          deferred.resolve(verified);
        }

        return deferred.promise;
      };
    exports.verify = _verify;

    return exports;
  };

<|endoftext|>


<commit_before>import { isArrayLike, isUndefined } from './checkTypes';

export function iterate(object, mapFn) {
  const array = isArrayLike(object);

  let iterated = 0;

  for (const key in object) {
    if (object.hasOwnProperty(key)) {
      if (array && iterated++ === object.length) {
        break;
      }

      const value = mapFn(object[key], array ? Number(key) : key, object);

      if (!isUndefined(value)) {
        return value;
      }
    }
  }
}
<commit_msg>helpers.iterate: change break conditions.<commit_after>import { isArrayLike, isUndefined } from './checkTypes';

export function iterate(object, mapFn) {
  const array = isArrayLike(object);

  let iterated = 0;

  for (const key in object) {
    if (object.hasOwnProperty(key)) {
      if (array && iterated++ >= object.length) {
        break;
      }

      const value = mapFn(object[key], array ? Number(key) : key, object);

      if (!isUndefined(value)) {
        return value;
      }
    }
  }
}
<|endoftext|>


<commit_before>var WebdriverIOPrototype = require('./webdriverio'),
    EventHandler = require('./utils/EventHandler'),
    ErrorHandler = require('./utils/ErrorHandler'),
    Instance = require('./multibrowser/Instance'),
    nonSeleniumCommands = require('./multibrowser/static').nonSeleniumCommands;

/**
 * Constructor
 */
function Multibrowser(options) {
    var self = this,
        instances = {},
        flag = 0.5;

    this.commandState = [];
    this.commandQueue = [];
    this.origin = 'multibrowser';

    /**
     * create processes per instance
     */
    Object.keys(options).forEach(function(instanceName) {
        var instance = new Instance(instanceName, options[instanceName]);
        instance.cp.on('message', onMessage.bind(self, instance));
        instances[instanceName] = instance;
    });

    this.eventHandler = new EventHandler(this);
    this.instances = instances;

    /**
     * addCommand added here because it's synchronous and thus does not need
     * to be added to asynchronous chain.
     */
    this.addCommand = function(name, fn) {
        chainIt.add(this, name, fn);

        /**
         * promisify new commands
         */
        this[name] = PromiseHandler(name, this[name]);

        /**
         * we still returns the instance so that we can continue chaining
         */
        return this;
    };

    /**
     * helper for getting single browser instance
     */
    this.select = function(instanceName) {
        if(typeof instanceName !== 'string' || !this.instances[instanceName]) {
            throw ErrorHandler.CommandError('instance "' + instanceName.toString() + '" does not exist! You\'ve defined the following instances: ' + Object.keys(this.instances));
        }

        return this.instances[instanceName];
    }
};

/**
 * assign custom multibrowser methods to each WebdriverIO command to make sure they'll get chained
 */
Object.keys(WebdriverIOPrototype.prototype).forEach(function(fnName) {
    /**
     * skip non selenium commands so they still get handled like
     * normal chained commands
     */
    if(!Multibrowser.prototype[fnName] && nonSeleniumCommands.indexOf(fnName) > -1) {
        return Multibrowser.prototype[fnName] = WebdriverIOPrototype.prototype[fnName];
    }

    /**
     * handle Selenium methods as real chained methods but instead of doing
     * HTTP requests we listen on the result from all instances.
     * Therefor is the actual multibrowser command just the event listener
     * and gets triggered once one intances finishes the command
     */
    Multibrowser.prototype[fnName] = function() {

        var self = this,
            args = Array.prototype.slice.call(arguments),
            callback = args.pop(),
            instanceName;

        /**
         * cast all function parameters into strings to send them to the instance child_process
         */
        for(var i in args) {
            args[i] = typeof args[i] === 'function' ? args[i].toString() : args[i];
        }

        this.commandState.push({
            error: {},
            result: {},
            response: {}
        });

        var processMessage = {
            origin: this.origin,
            action: 'command',
            fnName: fnName,
            args: args,
            commandId: this.commandState.length - 1
        };

        /**
         * execute command with all instances
         */
        for(instanceName in this.instances) {
            this.instances[instanceName].cp.send(processMessage);
        }

        /**
         * listen on when command finishes and call callback to go to the next command
         */
        this.eventHandler.on(this.origin + '_' + (this.commandState.length - 1), finishCommand.bind(this, callback));

    }
});

/**
 * gets called once an instance finishes a command
 */
var finishCommand = function(callback, instance, message){

    var commandResult = this.commandState[message.commandId];
    commandResult.result[instance.name] = message.args[1];
    commandResult.response[instance.name] = message.args[2];

    /**
     * only set error if there actually was an error
     */
    if(message.args[0]) {
        commandResult.error[instance.name] = message.args[0];
    }

    /**
     * only execute callback and finish command once all instances have finished this command
     */
    if(Object.keys(commandResult.result).length !== Object.keys(this.instances).length) {
        return;
    }

    /**
     * kill child processes on end
     */
    if(message.fnName === 'end') {
        for(instanceName in this.instances) {
            this.instances[instanceName].cp.send({ action: 'kill' });
        }
    }

    /**
     * set error parameter to undefined if no instance reported an issue
     */
    if(Object.keys(commandResult.error).length === 0) {
        commandResult.error = undefined;
    }

    callback.call(this, commandResult.error, commandResult.result, commandResult.response);

};

/**
 * process message listener
 * gets called once an instance finishes a command
 */
var onMessage = function(instance, message) {

    /**
     * only handle messages executed by multibrowser
     */
    if(message.origin !== this.origin) {
        return;
    }

    /**
     * emit that instance has finished the command
     */
    this.eventHandler.emit(message.origin + '_' + message.commandId, instance, message);

};

module.exports = Multibrowser;<commit_msg>just in case, happended several times due to wrong scopes<commit_after>var WebdriverIOPrototype = require('./webdriverio'),
    EventHandler = require('./utils/EventHandler'),
    ErrorHandler = require('./utils/ErrorHandler'),
    Instance = require('./multibrowser/Instance'),
    nonSeleniumCommands = require('./multibrowser/static').nonSeleniumCommands;

/**
 * Constructor
 */
function Multibrowser(options) {
    var self = this,
        instances = {},
        flag = 0.5;

    this.commandState = [];
    this.commandQueue = [];
    this.origin = 'multibrowser';

    /**
     * create processes per instance
     */
    Object.keys(options).forEach(function(instanceName) {
        var instance = new Instance(instanceName, options[instanceName]);
        instance.cp.on('message', onMessage.bind(self, instance));
        instances[instanceName] = instance;
    });

    this.eventHandler = new EventHandler(this);
    this.instances = instances;

    /**
     * addCommand added here because it's synchronous and thus does not need
     * to be added to asynchronous chain.
     */
    this.addCommand = function(name, fn) {
        chainIt.add(this, name, fn);

        /**
         * promisify new commands
         */
        this[name] = PromiseHandler(name, this[name]);

        /**
         * we still returns the instance so that we can continue chaining
         */
        return this;
    };

    /**
     * helper for getting single browser instance
     */
    this.select = function(instanceName) {
        if(typeof instanceName !== 'string' || !this.instances[instanceName]) {
            throw ErrorHandler.CommandError('instance "' + instanceName.toString() + '" does not exist! You\'ve defined the following instances: ' + Object.keys(this.instances));
        }

        return this.instances[instanceName];
    }
};

/**
 * assign custom multibrowser methods to each WebdriverIO command to make sure they'll get chained
 */
Object.keys(WebdriverIOPrototype.prototype).forEach(function(fnName) {
    /**
     * skip non selenium commands so they still get handled like
     * normal chained commands
     */
    if(!Multibrowser.prototype[fnName] && nonSeleniumCommands.indexOf(fnName) > -1) {
        return Multibrowser.prototype[fnName] = WebdriverIOPrototype.prototype[fnName];
    }

    /**
     * handle Selenium methods as real chained methods but instead of doing
     * HTTP requests we listen on the result from all instances.
     * Therefor is the actual multibrowser command just the event listener
     * and gets triggered once one intances finishes the command
     */
    Multibrowser.prototype[fnName] = function() {

        var self = this,
            args = Array.prototype.slice.call(arguments),
            callback = args.pop(),
            instanceName;

        /**
         * cast all function parameters into strings to send them to the instance child_process
         */
        for(var i in args) {
            args[i] = typeof args[i] === 'function' ? args[i].toString() : args[i];
        }

        this.commandState.push({
            error: {},
            result: {},
            response: {}
        });

        var processMessage = {
            origin: this.origin,
            action: 'command',
            fnName: fnName,
            args: args,
            commandId: this.commandState.length - 1
        };

        /**
         * execute command with all instances
         */
        for(instanceName in this.instances) {
            this.instances[instanceName].cp.send(processMessage);
        }

        /**
         * listen on when command finishes and call callback to go to the next command
         */
        this.eventHandler.on(this.origin + '_' + (this.commandState.length - 1), finishCommand.bind(this, callback));

    }
});

/**
 * gets called once an instance finishes a command
 */
var finishCommand = function(callback, instance, message){

    var commandResult = this.commandState[message.commandId];
    commandResult.result[instance.name] = message.args[1];
    commandResult.response[instance.name] = message.args[2];

    /**
     * only set error if there actually was an error
     */
    if(message.args[0]) {
        commandResult.error[instance.name] = message.args[0];
    }

    /**
     * only execute callback and finish command once all instances have finished this command
     */
    if(Object.keys(commandResult.result).length !== Object.keys(this.instances).length) {
        return;
    }

    /**
     * kill child processes on end
     */
    if(message.fnName === 'end') {
        for(instanceName in this.instances) {
            this.instances[instanceName].cp.send({ action: 'kill' });
        }
    }

    /**
     * set error parameter to undefined if no instance reported an issue
     */
    if(commandResult.error && Object.keys(commandResult.error).length === 0) {
        commandResult.error = undefined;
    }

    callback.call(this, commandResult.error, commandResult.result, commandResult.response);

};

/**
 * process message listener
 * gets called once an instance finishes a command
 */
var onMessage = function(instance, message) {

    /**
     * only handle messages executed by multibrowser
     */
    if(message.origin !== this.origin) {
        return;
    }

    /**
     * emit that instance has finished the command
     */
    this.eventHandler.emit(message.origin + '_' + message.commandId, instance, message);

};

module.exports = Multibrowser;<|endoftext|>


<commit_before>var Busboy = require('busboy')
var crypto = require('crypto')
var ecb = require('ecb')
var fs = require('fs')
var methodNotAllowed = require('./method-not-allowed')
var mkdirp = require('mkdirp')
var mustache = require('mustache')
var path = require('path')
var pump = require('pump')
var readKeypair = require('../read-keypair')
var runParallel = require('run-parallel')
var runSeries = require('run-series')
var sodium = require('sodium-prebuilt').api
var stringify = require('json-stable-stringify')
var through2 = require('through2')
var uuid = require('uuid/v4')

var JOURNALS = require('pct-minimum-documentation')
  .map(function (element) {
    return element.B
  })
  .sort()

var TEMPLATE = path.join(
  __dirname, '..', 'templates', 'publish.html'
)

var get = function (request, response) {
  response.setHeader('Content-Type', 'text/html; charset=UTF-8')
  fs.readFile(TEMPLATE, 'utf8', function (error, template) {
    /* istanbul ignore if */
    if (error) {
      response.statusCode = 500
      response.end()
    } else {
      response.end(
        mustache.render(template, {
          journals: JOURNALS
        })
      )
    }
  })
}

// TODO:  Refactor.
function post (request, response, directory) {
  var fields = {}
  var parser
  /* istanbul ignore next */
  try {
    // TODO:  Give busboy file count and size limits.
    parser = new Busboy({headers: request.headers})
  } catch (error) {
    response.statusCode = 400
    response.end()
    return
  }
  var attachments = [/* {stream, temporaryFile, digest}, ... */]
  request.pipe(
    parser
      .on('field', function (field, value) {
        if (field.endsWith('[]')) {
          field = field.substring(0, field.length - 2)
          if (fields[field] && Array.isArray(fields[field])) {
            fields[field].push(value)
          } else {
            fields[field] = [value]
          }
        } else {
          fields[field] = value
        }
      })
      .on('file', function (field, file, filename, encoding, mimetype) {
        // Save to ./tmp/{UUID}.
        var temporaryFile = path.join(directory, 'tmp', uuid())
        var attachment = {
          stream: file,
          temporaryFile: temporaryFile,
          type: (
            mimetype + '; charset=' + encoding
          )
        }
        attachments.push(attachment)
        var hash = crypto.createHash('sha256')
        pump(
          file,
          // Compute SHA256 as we write to disk.
          through2(function (chunk, encoding, done) {
            hash.update(chunk, encoding)
            this.push(chunk, encoding)
            done()
          }),
          fs.createWriteStream(temporaryFile),
          function (error, done) {
            // TODO:  Fix this error handler.  Need more cleanup.
            if (error) {
              response.statusCode = 400
              response.end()
            } else {
              attachment.digest = hash.digest('hex')
            }
          }
        )
      })
      .once('finish', function () {
        readKeypair(directory, function (error, keypair) {
          /* istanbul ignore if */
          if (error) {
            response.statusCode = 500
            response.end()
          } else {
            var secretKey = keypair.secret
            fields.date = currentDate()
            fields.attachments = attachments
              .map(function (attachment) {
                return {
                  type: attachment.type,
                  digest: attachment.digest
                }
              })
              .sort()
            var record = Buffer.from(stringify(fields), 'utf8')
            var digest = sodium
              .crypto_hash_sha256(record)
              .toString('hex')
            var signature = sodium
              .crypto_sign_detached(record, secretKey)
              .toString('hex')
            var pathPrefix = path.join(
              directory, 'publications', digest
            )
            runSeries([
              function writeJSONFile (done) {
                fs.writeFile(pathPrefix + '.json', record, done)
              },
              function writeSignatureFile (done) {
                fs.writeFile(pathPrefix + '.sig', signature, done)
              },
              function writeAttachments (done) {
                if (attachments.length > 0) {
                  mkdirp(pathPrefix, ecb(done, function () {
                    runParallel(
                      attachments.reduce(function (tasks, attachment) {
                        var file = path.join(
                          pathPrefix, attachment.digest
                        )
                        return tasks.concat(
                          function writeTypeFile (done) {
                            fs.writeFile(
                              file + '.type',
                              attachment.type,
                              'utf8',
                              done
                            )
                          },
                          function moveFile (done) {
                            fs.rename(
                              attachment.temporaryFile, file, done
                            )
                          }
                        )
                      }, []),
                      done
                    )
                  }))
                } else {
                  done()
                }
              },
              function appendToAccessions (done) {
                fs.appendFile(
                  path.join(directory, 'accessions'),
                  fields.date + ',' + digest + '\n',
                  done
                )
              }
            ], function (error) {
              /* istanbul ignore if */
              if (error) {
                response.log.error(error)
                response.statusCode = 500
                response.end()
              } else {
                response.statusCode = 201
                response.setHeader(
                  'Location', '/publications/' + digest
                )
                response.end()
              }
            })
          }
        })
      })
  )
}

function currentDate () {
  return new Date()
    .toISOString()
    .substring(0, 10)
}

module.exports = function (request, response, directory) {
  var method = request.method
  if (method === 'GET') {
    get(request, response)
  } else if (request.method === 'POST') {
    post(request, response, directory)
  } else {
    methodNotAllowed(response)
  }
}
<commit_msg>Add ignore-coverage comment<commit_after>var Busboy = require('busboy')
var crypto = require('crypto')
var ecb = require('ecb')
var fs = require('fs')
var methodNotAllowed = require('./method-not-allowed')
var mkdirp = require('mkdirp')
var mustache = require('mustache')
var path = require('path')
var pump = require('pump')
var readKeypair = require('../read-keypair')
var runParallel = require('run-parallel')
var runSeries = require('run-series')
var sodium = require('sodium-prebuilt').api
var stringify = require('json-stable-stringify')
var through2 = require('through2')
var uuid = require('uuid/v4')

var JOURNALS = require('pct-minimum-documentation')
  .map(function (element) {
    return element.B
  })
  .sort()

var TEMPLATE = path.join(
  __dirname, '..', 'templates', 'publish.html'
)

var get = function (request, response) {
  response.setHeader('Content-Type', 'text/html; charset=UTF-8')
  fs.readFile(TEMPLATE, 'utf8', function (error, template) {
    /* istanbul ignore if */
    if (error) {
      response.statusCode = 500
      response.end()
    } else {
      response.end(
        mustache.render(template, {
          journals: JOURNALS
        })
      )
    }
  })
}

// TODO:  Refactor.
function post (request, response, directory) {
  var fields = {}
  var parser
  /* istanbul ignore next */
  try {
    // TODO:  Give busboy file count and size limits.
    parser = new Busboy({headers: request.headers})
  } catch (error) {
    response.statusCode = 400
    response.end()
    return
  }
  var attachments = [/* {stream, temporaryFile, digest}, ... */]
  request.pipe(
    parser
      .on('field', function (field, value) {
        if (field.endsWith('[]')) {
          field = field.substring(0, field.length - 2)
          if (fields[field] && Array.isArray(fields[field])) {
            fields[field].push(value)
          } else {
            fields[field] = [value]
          }
        } else {
          fields[field] = value
        }
      })
      .on('file', function (field, file, filename, encoding, mimetype) {
        // Save to ./tmp/{UUID}.
        var temporaryFile = path.join(directory, 'tmp', uuid())
        var attachment = {
          stream: file,
          temporaryFile: temporaryFile,
          type: (
            mimetype + '; charset=' + encoding
          )
        }
        attachments.push(attachment)
        var hash = crypto.createHash('sha256')
        pump(
          file,
          // Compute SHA256 as we write to disk.
          through2(function (chunk, encoding, done) {
            hash.update(chunk, encoding)
            this.push(chunk, encoding)
            done()
          }),
          fs.createWriteStream(temporaryFile),
          function (error, done) {
            // TODO:  Fix this error handler.  Need more cleanup.
            /* istanbul ignore next */
            if (error) {
              response.statusCode = 400
              response.end()
            } else {
              attachment.digest = hash.digest('hex')
            }
          }
        )
      })
      .once('finish', function () {
        readKeypair(directory, function (error, keypair) {
          /* istanbul ignore if */
          if (error) {
            response.statusCode = 500
            response.end()
          } else {
            var secretKey = keypair.secret
            fields.date = currentDate()
            fields.attachments = attachments
              .map(function (attachment) {
                return {
                  type: attachment.type,
                  digest: attachment.digest
                }
              })
              .sort()
            var record = Buffer.from(stringify(fields), 'utf8')
            var digest = sodium
              .crypto_hash_sha256(record)
              .toString('hex')
            var signature = sodium
              .crypto_sign_detached(record, secretKey)
              .toString('hex')
            var pathPrefix = path.join(
              directory, 'publications', digest
            )
            runSeries([
              function writeJSONFile (done) {
                fs.writeFile(pathPrefix + '.json', record, done)
              },
              function writeSignatureFile (done) {
                fs.writeFile(pathPrefix + '.sig', signature, done)
              },
              function writeAttachments (done) {
                if (attachments.length > 0) {
                  mkdirp(pathPrefix, ecb(done, function () {
                    runParallel(
                      attachments.reduce(function (tasks, attachment) {
                        var file = path.join(
                          pathPrefix, attachment.digest
                        )
                        return tasks.concat(
                          function writeTypeFile (done) {
                            fs.writeFile(
                              file + '.type',
                              attachment.type,
                              'utf8',
                              done
                            )
                          },
                          function moveFile (done) {
                            fs.rename(
                              attachment.temporaryFile, file, done
                            )
                          }
                        )
                      }, []),
                      done
                    )
                  }))
                } else {
                  done()
                }
              },
              function appendToAccessions (done) {
                fs.appendFile(
                  path.join(directory, 'accessions'),
                  fields.date + ',' + digest + '\n',
                  done
                )
              }
            ], function (error) {
              /* istanbul ignore if */
              if (error) {
                response.log.error(error)
                response.statusCode = 500
                response.end()
              } else {
                response.statusCode = 201
                response.setHeader(
                  'Location', '/publications/' + digest
                )
                response.end()
              }
            })
          }
        })
      })
  )
}

function currentDate () {
  return new Date()
    .toISOString()
    .substring(0, 10)
}

module.exports = function (request, response, directory) {
  var method = request.method
  if (method === 'GET') {
    get(request, response)
  } else if (request.method === 'POST') {
    post(request, response, directory)
  } else {
    methodNotAllowed(response)
  }
}
<|endoftext|>


<commit_before>/*

Note: At this time the plugin wrapper for this code is still under development.
It works with browsers that support foreignObject, but the logic for handling
tspans in Internet Explorer and other browsers that don't support foreignObject
has not yet been refactored for the D3 plugin format. That code will work if
carefully transplanted to other projects, and you're welcome to harvest it and
apply it in that manner, but it can't yet simply be applied to a selection by
calling d3.textwrap(). I know that's kind of the whole point! That is the
eventual goal here, of course; stay tuned.

*/

(function() {

    // exit immediately if this has already been defined
    // as a function; the plugin will defer to whatever
    // else you're doing in your code
    if(typeof d3.selection.prototype.textwrap == 'function') {
        return false;
    }

    var force_wrap_method;
    // set this variable to a string value to always force a particular
    // wrap method for development purposes. set to 'tspan' to
    // use tspans and 'foreignobject' to use foreignobject
    // force_wrap_method = 'tspans'; // uncomment statement to use tspans
    // force_wrap_method = 'foreignobjects'; // uncomment statement to use foreignobjects
    force_wrap_method = false; // by default no wrap method is forced

    // create the plugin method twice, both for regular use
    // and again for use inside the enter() selection
    d3.selection.prototype.textwrap = d3.selection.enter.prototype.textwrap = function(bounds) {

        // save callee into a variable so we can continue to refer to it
        // as the function scope changes
        var selection = this;

        // extract wrap boundaries from any d3-selected rect and return them
        // in a format that matches the simpler object argument option
        var extract_bounds = function(bounds) {
            // discard the nested array wrappers added by d3
            var bounding_rect = bounds[0][0];
            // sanitize the svg element name so we can test against it
            var element_type = bounding_rect.tagName.toString();
            // if it's not a rect, exit
            if(element_type !== 'rect') {
                return false;
            // if it's a rect, proceed to extracting the position attributes
            } else {
                var bounds_extracted = {};
                bounds_extracted.x = d3.select(bounding_rect).attr('x') || 0;
                bounds_extracted.y = d3.select(bounding_rect).attr('y') || 0;
                bounds_extracted.width = d3.select(bounding_rect).attr('width') || 0;
                bounds_extracted.height = d3.select(bounding_rect).attr('height') || 0;
                // also pass along the getter function
                bounds_extracted.attr = bounds.attr;
                return bounds_extracted;
            }
        }

        // double check the input argument for the wrapping
        // boundaries to make sure it actually contains all
        // the information we'll need in order to wrap successfully
        var verify_bounds = function(bounds) {
            // quickly add a simple getter method so you can use either
            // bounds.x or bounds.attr('x') as your notation,
            // the latter being a common convention among D3
            // developers
            if(!bounds.attr) {
                bounds.attr = function(property) {
                    if(this[property]) {
                        return this[property];
                    }
                }
            }
            // if it's an associative array, make sure it has all the
            // necessary properties represented directly
            if(
                (typeof bounds == 'object') &&
                (bounds.x) &&
                (bounds.y) &&
                (bounds.width) &&
                (bounds.height)
                // if that's the case, then the bounds are fine
            ) {
                // return the lightly modified bounds
                return bounds;
            // if it's a numerically indexed array, assume it's a
            // d3-selected rect and try to extract the positions
            } else if(
                    // first try to make sure it's an array using Array.isArray
                    (
                        (typeof Array.isArray == 'function') &&
                        (Array.isArray(bounds))
                    ) ||
                    // but since Array.isArray isn't always supported, fall
                    // back to casting to the object to string when it's not
                    (Object.prototype.toString.call(bounds) === '[object Array]')
            ) {
                // once you're sure it's an array, extract the boundaries
                // from the rect
                var extracted_bounds = extract_bounds(bounds);
                return extracted_bounds;
            } else {
            // but if the bounds are neither an object nor a numerical
            // array, then the bounds argument is invalid and you'll
            // need to fix it
                return false;
            }
        }

        var verified_bounds = verify_bounds(bounds);

        // check that we have the necessary conditions for this function to operate properly
        if(
            // selection it's operating on cannot be not empty
            (selection.length == 0) ||
            // d3 must be available
            (!d3) ||
            // desired wrapping bounds must be provided as an input argument
            (!bounds) ||
            // input bounds must validate
            (!verified_bounds)
        ) {
            // try to return the calling selection if possible
            // so as not to interfere with methods downstream in the
            // chain
            if(selection) {
                return selection;
            // if all else fails, just return false. if you hit this point then you're
            // almost trying to call the textwrap() method on something that
            // doesn't make sense!
            } else {
                return false;
            }
        // if we've validated everything then we can finally proceed
        // to the meat of this operation
        } else {

            // reassign the verified bounds as the set we want
            // to work with from here on; this ensures that we're
            // using the same data structure for our bounds regardless
            // of whether the input argument was a simple object or
            // a d3 selection
            bounds = verified_bounds;

            // wrap using html and foreignObjects if they are supported
            var wrap_with_foreignobjects = function(item) {
                console.log('wrapping with foreign object');
                // establish variables to quickly reference target nodes later
                var parent = d3.select(item[0].parentNode);
                var text_node = parent.selectAll('text');
                // extract our desired content from the single text element
                var text_to_wrap = text_node.text();
                // remove the text node and replace with a foreign object
                text_node.remove();
                var foreign_object = parent.append('foreignObject');
                // add foreign object and set dimensions, position, etc
                foreign_object
                    .attr("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility")
                    .attr('x', bounds.x)
                    .attr('y', bounds.y)
                    .attr('width', bounds.width)
                    .attr('height', bounds.height)
                ;
                // insert an HTML div
                var wrap_div = foreign_object
                    .append('xhtml:div')
                    // this class is currently hardcoded
                    // probably not necessary but easy to
                    // override using .classed() and for now
                    // it's nice to avoid a litany of input
                    // arguments
                    .attr('class', 'wrapped')
                ;
                // set div to same dimensions as foreign object
                wrap_div
                    .style('height', bounds.height)
                    .style('width', bounds.width)
                    // insert text content
                    .html(text_to_wrap)
                ;
            }

            // wrap with tspans if foreignObject is undefined
            var wrap_with_tspans = function(text_node) {
                console.log('wrapping with tspans');
                // only fire the rest of this if the text content
                // overflows the desired dimensions
                if(this.getBBox().width > max_width) {
                    // store whatever is inside the text node
                    // in a variable and then zero out the
                    // initial content; we'll reinsert in a moment
                    // using tspan elements.
                    var text_node = d3.select(this);
                    var text_to_wrap = text_node.text();
                    text_node.text('');

                    if(text_to_wrap) {
                        // split at spaces to create an array of individual words
                        var text_to_wrap_array;
                        if(text_to_wrap.indexOf(' ') !== -1) {
                            text_to_wrap_array = text_to_wrap.split(' ');
                        } else {
                            // if there are no spaces, chop it in half.
                            // this is a hack! better to apply
                            // CSS word-break: break-all in order
                            // to handle long single-word strings that
                            // might overflow without spaces. will fix to
                            // dynamically compute the appropriate number
                            // of cuts later.
                            var string_length = text_to_wrap.length;
                            var midpoint = parseInt(string_length / 2);
                            var first_half = text_to_wrap.substr(0, midpoint);
                            var second_half = text_to_wrap.substr(midpoint, string_length);
                            text_to_wrap_array = [first_half, second_half];
                        }

                        // new array where we'll store the words re-assembled into
                        // substrings that have been tested against the desired
                        // maximum wrapping width
                        var substrings = [];
                        // computed text length is arguably incorrectly reported for
                        // all tspans after the first one, in that they will include
                        // the width of previous separate tspans. to compensate we need
                        // to manually track the computed text length of all those
                        // previous tspans and substrings, and then use that to offset
                        // the miscalculation. this then gives us the actual correct
                        // position we want to use in rendering the text in the SVG.
                        var offset = 0;
                        // loop through the words and test the computed text length
                        // of the string against the maximum desired wrapping width
                        for(var i = 0; i < text_to_wrap_array.length; i++) {
                            var word = text_to_wrap_array[i];
                            var previous_string = text_node.text();
                            var previous_width = this.getComputedTextLength();
                            // initialize the current word as the first word
                            // or append to the previous string if one exists
                            var new_string;
                            if(previous_string) {
                                new_string = previous_string + ' ' + word;
                            } else {
                                new_string = word;
                            }
                            // add the newest substring back to the text node and
                            // measure the length
                            text_node.text(new_string);
                            var new_width = this.getComputedTextLength();
                            // adjust the length by the offset we've tracked
                            // due to the misreported length discussed above
                            var test_width = new_width - offset;
                            // if our latest version of the string is too
                            // big for the bounds, use the previous
                            // version of the string (without the newest word
                            // added) and use the latest word to restart the
                            // process with a new tspan
                            if(test_width > max_width) {
                                if(previous_string !== '') {
                                    var temp = {string: previous_string, width: previous_width - offset};
                                    substrings.push(temp);
                                    offset = offset + previous_width;
                                    text_node.text('');
                                    text_node.text(word);
                                }
                            }
                            // if we're up to the last word in the array,
                            // get the computed length as is without
                            // appending anything
                            if(i == text_to_wrap_array.length - 1) {
                                var final_string = new_string.substr(previous_string.length);
                                // remove leading spaces if present
                                if(final_string.substr(0, 1) == ' ') {
                                    final_string = final_string.substr(1);
                                }
                                if(final_string !== '') {
                                    if((new_width - offset) > 0) {new_width = new_width - offset}
                                    var temp = {string: final_string, width: new_width};
                                    substrings.push(temp);
                                    text_node.text('');
                                }
                            }
                        }
                        // double check that there are no empty substrings
                        // because those would create blank tspans
                        var substrings_clean = [];
                        for(var i = 0; i < substrings.length; i++) {
                            if(substrings[i].string.length > 0) {
                                substrings_clean.push(substrings[i]);
                            }
                        }
                        // append each substring as a tspan
                        var current_tspan;
                        var tspan_count;
                        for(var i = 0; i < substrings_clean.length; i++) {
                            var substring = substrings_clean[i].string;
                            if(i > 0) {
                                var previous_substring = substrings_clean[i - 1];
                            }
                            current_tspan = text_node.append('tspan')
                                .text(substring)
                            ;
                            current_tspan
                                .attr('dy', function(d) {
                                    if(i > 0) {
                                        // line height shouldn't be hard coded
                                        // will fix this later
                                        return '1.5em';
                                    }
                                })
                            ;
                            // shift left from default position, which
                            // is probably based on the full length of the
                            // text string until we make this adjustment
                            current_tspan
                                .attr('dx', function() {
                                    var render_offset = 0;
                                    if(i > 0) {
                                        render_offset = 0;
                                        for(j = 0; j < i; j++) {
                                            render_offset += substrings[j].width;
                                        }
                                    }
                                    return render_offset * -1;
                                })
                            ;
                        }
                    }
                }
            }

            // variable used to hold the functions that let us
            // switch between the wrap methods
            var wrap_method;

            // if a wrap method if being forced, assign that
            // function
            if(force_wrap_method) {
                if(force_wrap_method == 'foreignobjects') {
                    wrap_method = wrap_with_foreignobjects;
                } else if (force_wrap_method == 'tspans') {
                    wrap_method = wrap_with_tspans;
                }
            }

            // if no wrap method is being forced, then instead
            // test for browser support of foreignobject and
            // use whichever wrap method makes sense accordingly
            if(!force_wrap_method) {
                if(typeof SVGForeignObjectElement !== 'undefined') {
                    wrap_method = wrap_with_foreignobjects;
                } else {
                    wrap_method = wrap_with_tspans;
                }
            }

            // run the desired wrap function for each item
            // in the d3 selection that called .textwrap()
            for(var i = 0; i < selection.length; i++) {
                var item = selection[i];
                wrap_method(item);
            }

        }

    }

})();
<commit_msg>don't check typeof when deferring<commit_after>/*

Note: At this time the plugin wrapper for this code is still under development.
It works with browsers that support foreignObject, but the logic for handling
tspans in Internet Explorer and other browsers that don't support foreignObject
has not yet been refactored for the D3 plugin format. That code will work if
carefully transplanted to other projects, and you're welcome to harvest it and
apply it in that manner, but it can't yet simply be applied to a selection by
calling d3.textwrap(). I know that's kind of the whole point! That is the
eventual goal here, of course; stay tuned.

*/

(function() {

    // exit immediately if this has already been defined
    // as a function; the plugin will defer to whatever
    // else you're doing in your code
    if(d3.selection.prototype.textwrap) {
        return false;
    }

    var force_wrap_method;
    // set this variable to a string value to always force a particular
    // wrap method for development purposes. set to 'tspan' to
    // use tspans and 'foreignobject' to use foreignobject
    // force_wrap_method = 'tspans'; // uncomment statement to use tspans
    // force_wrap_method = 'foreignobjects'; // uncomment statement to use foreignobjects
    force_wrap_method = false; // by default no wrap method is forced

    // create the plugin method twice, both for regular use
    // and again for use inside the enter() selection
    d3.selection.prototype.textwrap = d3.selection.enter.prototype.textwrap = function(bounds) {

        // save callee into a variable so we can continue to refer to it
        // as the function scope changes
        var selection = this;

        // extract wrap boundaries from any d3-selected rect and return them
        // in a format that matches the simpler object argument option
        var extract_bounds = function(bounds) {
            // discard the nested array wrappers added by d3
            var bounding_rect = bounds[0][0];
            // sanitize the svg element name so we can test against it
            var element_type = bounding_rect.tagName.toString();
            // if it's not a rect, exit
            if(element_type !== 'rect') {
                return false;
            // if it's a rect, proceed to extracting the position attributes
            } else {
                var bounds_extracted = {};
                bounds_extracted.x = d3.select(bounding_rect).attr('x') || 0;
                bounds_extracted.y = d3.select(bounding_rect).attr('y') || 0;
                bounds_extracted.width = d3.select(bounding_rect).attr('width') || 0;
                bounds_extracted.height = d3.select(bounding_rect).attr('height') || 0;
                // also pass along the getter function
                bounds_extracted.attr = bounds.attr;
                return bounds_extracted;
            }
        }

        // double check the input argument for the wrapping
        // boundaries to make sure it actually contains all
        // the information we'll need in order to wrap successfully
        var verify_bounds = function(bounds) {
            // quickly add a simple getter method so you can use either
            // bounds.x or bounds.attr('x') as your notation,
            // the latter being a common convention among D3
            // developers
            if(!bounds.attr) {
                bounds.attr = function(property) {
                    if(this[property]) {
                        return this[property];
                    }
                }
            }
            // if it's an associative array, make sure it has all the
            // necessary properties represented directly
            if(
                (typeof bounds == 'object') &&
                (bounds.x) &&
                (bounds.y) &&
                (bounds.width) &&
                (bounds.height)
                // if that's the case, then the bounds are fine
            ) {
                // return the lightly modified bounds
                return bounds;
            // if it's a numerically indexed array, assume it's a
            // d3-selected rect and try to extract the positions
            } else if(
                    // first try to make sure it's an array using Array.isArray
                    (
                        (typeof Array.isArray == 'function') &&
                        (Array.isArray(bounds))
                    ) ||
                    // but since Array.isArray isn't always supported, fall
                    // back to casting to the object to string when it's not
                    (Object.prototype.toString.call(bounds) === '[object Array]')
            ) {
                // once you're sure it's an array, extract the boundaries
                // from the rect
                var extracted_bounds = extract_bounds(bounds);
                return extracted_bounds;
            } else {
            // but if the bounds are neither an object nor a numerical
            // array, then the bounds argument is invalid and you'll
            // need to fix it
                return false;
            }
        }

        var verified_bounds = verify_bounds(bounds);

        // check that we have the necessary conditions for this function to operate properly
        if(
            // selection it's operating on cannot be not empty
            (selection.length == 0) ||
            // d3 must be available
            (!d3) ||
            // desired wrapping bounds must be provided as an input argument
            (!bounds) ||
            // input bounds must validate
            (!verified_bounds)
        ) {
            // try to return the calling selection if possible
            // so as not to interfere with methods downstream in the
            // chain
            if(selection) {
                return selection;
            // if all else fails, just return false. if you hit this point then you're
            // almost trying to call the textwrap() method on something that
            // doesn't make sense!
            } else {
                return false;
            }
        // if we've validated everything then we can finally proceed
        // to the meat of this operation
        } else {

            // reassign the verified bounds as the set we want
            // to work with from here on; this ensures that we're
            // using the same data structure for our bounds regardless
            // of whether the input argument was a simple object or
            // a d3 selection
            bounds = verified_bounds;

            // wrap using html and foreignObjects if they are supported
            var wrap_with_foreignobjects = function(item) {
                console.log('wrapping with foreign object');
                // establish variables to quickly reference target nodes later
                var parent = d3.select(item[0].parentNode);
                var text_node = parent.selectAll('text');
                // extract our desired content from the single text element
                var text_to_wrap = text_node.text();
                // remove the text node and replace with a foreign object
                text_node.remove();
                var foreign_object = parent.append('foreignObject');
                // add foreign object and set dimensions, position, etc
                foreign_object
                    .attr("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility")
                    .attr('x', bounds.x)
                    .attr('y', bounds.y)
                    .attr('width', bounds.width)
                    .attr('height', bounds.height)
                ;
                // insert an HTML div
                var wrap_div = foreign_object
                    .append('xhtml:div')
                    // this class is currently hardcoded
                    // probably not necessary but easy to
                    // override using .classed() and for now
                    // it's nice to avoid a litany of input
                    // arguments
                    .attr('class', 'wrapped')
                ;
                // set div to same dimensions as foreign object
                wrap_div
                    .style('height', bounds.height)
                    .style('width', bounds.width)
                    // insert text content
                    .html(text_to_wrap)
                ;
            }

            // wrap with tspans if foreignObject is undefined
            var wrap_with_tspans = function(text_node) {
                console.log('wrapping with tspans');
                // only fire the rest of this if the text content
                // overflows the desired dimensions
                if(this.getBBox().width > max_width) {
                    // store whatever is inside the text node
                    // in a variable and then zero out the
                    // initial content; we'll reinsert in a moment
                    // using tspan elements.
                    var text_node = d3.select(this);
                    var text_to_wrap = text_node.text();
                    text_node.text('');

                    if(text_to_wrap) {
                        // split at spaces to create an array of individual words
                        var text_to_wrap_array;
                        if(text_to_wrap.indexOf(' ') !== -1) {
                            text_to_wrap_array = text_to_wrap.split(' ');
                        } else {
                            // if there are no spaces, chop it in half.
                            // this is a hack! better to apply
                            // CSS word-break: break-all in order
                            // to handle long single-word strings that
                            // might overflow without spaces. will fix to
                            // dynamically compute the appropriate number
                            // of cuts later.
                            var string_length = text_to_wrap.length;
                            var midpoint = parseInt(string_length / 2);
                            var first_half = text_to_wrap.substr(0, midpoint);
                            var second_half = text_to_wrap.substr(midpoint, string_length);
                            text_to_wrap_array = [first_half, second_half];
                        }

                        // new array where we'll store the words re-assembled into
                        // substrings that have been tested against the desired
                        // maximum wrapping width
                        var substrings = [];
                        // computed text length is arguably incorrectly reported for
                        // all tspans after the first one, in that they will include
                        // the width of previous separate tspans. to compensate we need
                        // to manually track the computed text length of all those
                        // previous tspans and substrings, and then use that to offset
                        // the miscalculation. this then gives us the actual correct
                        // position we want to use in rendering the text in the SVG.
                        var offset = 0;
                        // loop through the words and test the computed text length
                        // of the string against the maximum desired wrapping width
                        for(var i = 0; i < text_to_wrap_array.length; i++) {
                            var word = text_to_wrap_array[i];
                            var previous_string = text_node.text();
                            var previous_width = this.getComputedTextLength();
                            // initialize the current word as the first word
                            // or append to the previous string if one exists
                            var new_string;
                            if(previous_string) {
                                new_string = previous_string + ' ' + word;
                            } else {
                                new_string = word;
                            }
                            // add the newest substring back to the text node and
                            // measure the length
                            text_node.text(new_string);
                            var new_width = this.getComputedTextLength();
                            // adjust the length by the offset we've tracked
                            // due to the misreported length discussed above
                            var test_width = new_width - offset;
                            // if our latest version of the string is too
                            // big for the bounds, use the previous
                            // version of the string (without the newest word
                            // added) and use the latest word to restart the
                            // process with a new tspan
                            if(test_width > max_width) {
                                if(previous_string !== '') {
                                    var temp = {string: previous_string, width: previous_width - offset};
                                    substrings.push(temp);
                                    offset = offset + previous_width;
                                    text_node.text('');
                                    text_node.text(word);
                                }
                            }
                            // if we're up to the last word in the array,
                            // get the computed length as is without
                            // appending anything
                            if(i == text_to_wrap_array.length - 1) {
                                var final_string = new_string.substr(previous_string.length);
                                // remove leading spaces if present
                                if(final_string.substr(0, 1) == ' ') {
                                    final_string = final_string.substr(1);
                                }
                                if(final_string !== '') {
                                    if((new_width - offset) > 0) {new_width = new_width - offset}
                                    var temp = {string: final_string, width: new_width};
                                    substrings.push(temp);
                                    text_node.text('');
                                }
                            }
                        }
                        // double check that there are no empty substrings
                        // because those would create blank tspans
                        var substrings_clean = [];
                        for(var i = 0; i < substrings.length; i++) {
                            if(substrings[i].string.length > 0) {
                                substrings_clean.push(substrings[i]);
                            }
                        }
                        // append each substring as a tspan
                        var current_tspan;
                        var tspan_count;
                        for(var i = 0; i < substrings_clean.length; i++) {
                            var substring = substrings_clean[i].string;
                            if(i > 0) {
                                var previous_substring = substrings_clean[i - 1];
                            }
                            current_tspan = text_node.append('tspan')
                                .text(substring)
                            ;
                            current_tspan
                                .attr('dy', function(d) {
                                    if(i > 0) {
                                        // line height shouldn't be hard coded
                                        // will fix this later
                                        return '1.5em';
                                    }
                                })
                            ;
                            // shift left from default position, which
                            // is probably based on the full length of the
                            // text string until we make this adjustment
                            current_tspan
                                .attr('dx', function() {
                                    var render_offset = 0;
                                    if(i > 0) {
                                        render_offset = 0;
                                        for(j = 0; j < i; j++) {
                                            render_offset += substrings[j].width;
                                        }
                                    }
                                    return render_offset * -1;
                                })
                            ;
                        }
                    }
                }
            }

            // variable used to hold the functions that let us
            // switch between the wrap methods
            var wrap_method;

            // if a wrap method if being forced, assign that
            // function
            if(force_wrap_method) {
                if(force_wrap_method == 'foreignobjects') {
                    wrap_method = wrap_with_foreignobjects;
                } else if (force_wrap_method == 'tspans') {
                    wrap_method = wrap_with_tspans;
                }
            }

            // if no wrap method is being forced, then instead
            // test for browser support of foreignobject and
            // use whichever wrap method makes sense accordingly
            if(!force_wrap_method) {
                if(typeof SVGForeignObjectElement !== 'undefined') {
                    wrap_method = wrap_with_foreignobjects;
                } else {
                    wrap_method = wrap_with_tspans;
                }
            }

            // run the desired wrap function for each item
            // in the d3 selection that called .textwrap()
            for(var i = 0; i < selection.length; i++) {
                var item = selection[i];
                wrap_method(item);
            }

        }

    }

})();
<|endoftext|>


<commit_before>/**
 * Core dependencies.
 */

var exec = require('child_process').exec;

/**
 * Internal dependencies.
 */

var Result = require('./result');

/**
 * Command to execute.
 *
 * This class is a simple wrapper of `child_process#exec`. All it does is
 * executing the command with the supplied options and then return a new
 * `Result`. It delegates the formatting of stdout and stderr to `Formatter`.
 *
 * @param {Formatter} formatter
 * @see child_process#exec
 * @see Formatter
 * @see Result
 * @constructor
 */

function Command(formatter) {
  this.formatter = formatter;
  this.envs = {};
}

/**
 * Set a command to be executed.
 *
 * @param {String} command
 * @api public
 */

Command.prototype.set = function(cmd) {
  this.cmd = cmd;
};

/**
 * Set a command timeout.
 *
 * @param {Number}
 * @api public
 */

Command.prototype.timeout = function(ms) {
  this.ms = ms;
};

/**
 * Set the current working directory for
 * the command.
 *
 * @param {String} path
 * @api public
 */

Command.prototype.cwd = function(cwd) {
  this.dir = cwd;
};

/**
 * Set environemnt variable.
 *
 * @param {String} key
 * @param {String} val
 * @api public
 */

Command.prototype.env = function(key, val) {
  this.envs[key] = val;
};

/**
 * Execute the command, load stdout and stderr into
 * the formatter and return a new `Result`.
 *
 * @param {Function} fn
 * @api public
 */

Command.prototype.exec = function(fn) {
  var self = this;
  var options = { cwd: this.dir, timeout: this.ms };

  if (Object.keys(this.envs).length) options.env = this.envs;

  exec(this.cmd, options, function(err, stdout, stderr) {
    self.formatter.load(stdout, stderr);
    fn(new Result(self.formatter, err, self.cmd));
  });
};

/**
 * Primary export.
 */

module.exports = Command;
<commit_msg>Always use the current env vars<commit_after>/**
 * Core dependencies.
 */

var exec = require('child_process').exec;

/**
 * External dependencies.
 */

var clone = require('clone');

/**
 * Internal dependencies.
 */

var Result = require('./result');

/**
 * Command to execute.
 *
 * This class is a simple wrapper of `child_process#exec`. All it does is
 * executing the command with the supplied options and then return a new
 * `Result`. It delegates the formatting of stdout and stderr to `Formatter`.
 *
 * @param {Formatter} formatter
 * @see child_process#exec
 * @see Formatter
 * @see Result
 * @constructor
 */

function Command(formatter) {
  this.formatter = formatter;
  this.envs = clone(process.env);
}

/**
 * Set a command to be executed.
 *
 * @param {String} command
 * @api public
 */

Command.prototype.set = function(cmd) {
  this.cmd = cmd;
};

/**
 * Set a command timeout.
 *
 * @param {Number}
 * @api public
 */

Command.prototype.timeout = function(ms) {
  this.ms = ms;
};

/**
 * Set the current working directory for
 * the command.
 *
 * @param {String} path
 * @api public
 */

Command.prototype.cwd = function(cwd) {
  this.dir = cwd;
};

/**
 * Set environemnt variable.
 *
 * @param {String} key
 * @param {String} val
 * @api public
 */

Command.prototype.env = function(key, val) {
  this.envs[key] = val;
};

/**
 * Execute the command, load stdout and stderr into
 * the formatter and return a new `Result`.
 *
 * @param {Function} fn
 * @api public
 */

Command.prototype.exec = function(fn) {
  var self = this;
  var options = { cwd: this.dir, timeout: this.ms, env: this.envs };

  exec(this.cmd, options, function(err, stdout, stderr) {
    self.formatter.load(stdout, stderr);
    fn(new Result(self.formatter, err, self.cmd));
  });
};

/**
 * Primary export.
 */

module.exports = Command;
<|endoftext|>


<commit_before>var middleware  = require('../middleware');
var Router      = require('express').Router();
var request     = require('superagent');

const IMG_URL = process.env.IMG_URL || 'http://localhost:9003';

Router.route('/version/api')
    .get(middleware.authenticate('user', 'guest'))
    .get(function(req, res) {
        var version = process.env.VERSION || 'unknown';
        version = {"version":version};
        return res.json(200, version);
    });

Router.route('/version/img')
    .get(middleware.authenticate('user', 'guest'))
    .get(function(req, res) {
        var version = {"version":"unknown"};
        request.get(IMG_URL+'/version')
            .end(function(err, response){
                version = {"version":response.body.version};
                return res.json(200, version);
            });
    });

module.exports = Router;
<commit_msg>Handle error in case img service is down.<commit_after>var middleware  = require('../middleware');
var Router      = require('express').Router();
var request     = require('superagent');

const IMG_URL = process.env.IMG_URL || 'http://localhost:9003';

Router.route('/version/api')
    .get(middleware.authenticate('user', 'guest'))
    .get(function(req, res) {
        var version = process.env.VERSION || 'unknown';
        version = {"version":version};
        return res.json(200, version);
    });

Router.route('/version/img')
    .get(middleware.authenticate('user', 'guest'))
    .get(function(req, res) {
        var version = {"version":"unknown"};
        request.get(IMG_URL+'/version')
            .end(function(err, response){
                try{
                    version = {"version":response.body.version};
                } catch(exception) {
                    version = {"version":"error"};
                }
                return res.json(200, version);
            });
    });

module.exports = Router;
<|endoftext|>