<commit_before>"use strict";

var fs = require('fs');
var winston = require('winston');
var redis = require('redis');
var _ = require('underscore');
var async = require('async');

var Runner = require('./runner.js');
var pad = require('./pad');

var Topology = function (opts) {

  this.opts = opts;

  this.pipes = {};
  this.nodes = {};
  this.runners = {};

  // try to kill dangling processes from a previous run

  if(this.opts.pidsfile && fs.existsSync(this.opts.pidsfile)) {
    var pids = JSON.parse(fs.readFileSync(this.opts.pidsfile));
    _.each(pids, function(pid){
      try{
        process.kill(pid, 'SIGHUP');
      } catch (err){
        // catch error if no process
        //logger.log('info', err);
      }
    });
  }

  return this;

};

Topology.prototype.addPipe = function(id) {
  if(!this.pipes.hasOwnProperty(id)){
    this.pipes[id] = {
      id: id,
      outputs: [],
      inputs: []
    };
  }
};

Topology.prototype.addPipeOut = function(pipe_id, node_id) {
  this.addPipe(pipe_id);
  this.pipes[pipe_id].outputs.push(node_id);
};

Topology.prototype.addPipeIn = function(pipe_id, node_id) {
  this.addPipe(pipe_id);
  this.pipes[pipe_id].inputs.push(node_id);
};

/*
 * Add a node to the topology by spawning it in it's own process. The
 * Runner takes care of setting up the process and starting the node
 * in it.
 */
Topology.prototype.add = function(node, done) {

  var self = this;

  // array of nodes was given
  if (Array.isArray(node)) {
    return async.eachSeries(node, function(x, next){
      Topology.prototype.add.call(self, x, next);
    }, function(){
      return done && done();
    });
  }

  if(this.opts.nodes_dir){
    node.node = this.opts.nodes_dir + '/' + node.node + '.js';
  }

  if(this.nodes.hasOwnProperty(node.id)){
    this.opts.logger.log(
      'info',
      pad.timestamp(),
      'ADD FAIL',
      node.id,
      'ALREADY EXISTS'
    );
    return done(new Error('Node ID already exists'));
  }

  this.opts.logger.log(
    'info',
    pad.timestamp(),
    'ADD     ',
    node.id
  );

  //this.opts.logger.log('info', 'Adding Node %s', node.id);

  // if(!fs.existsSync(node.node)) {
  //   return done(new Error('Node file not found'));
  // }

  // create references to the pipes this node uses. Actual plumbing is
  // done using Redis, but we keep account of it here so we can pull
  // stats and otherwise control pipes, e.g. purge them

  // input
  if(!node.hasOwnProperty('input')){
    node.input = [];
  }

  // this node receives input from `pipe`. Input can be received from
  // many pipes. If a single key was supplied, convert to array.
  if (!Array.isArray(node.input)) {
    node.input = [node.input];
  }

  // out of pipe, to this node
  _.each(node.input, function(x){
    self.addPipeOut(x, node.id);
  });

  // default output
  if(!node.hasOwnProperty('output')){
    node.output = [];
  }

  // default output can go to many pipes. if a single key was
  // provided, convert to array.
  if (!Array.isArray(node.output)) {
    node.output = [node.output];
  }

  // out of node, to these pipes
  _.each(node.output, function(x){
    self.addPipeIn(x, node.id);
  });

  // named outputs
  if(!node.hasOwnProperty('outputs')){
    node.outputs = {};
  }

  // each named output can go to many pipes. If a single key was
  // supplied, convert to array.
  _.each(node.outputs, function(x, id){
    if (!Array.isArray(x)) {
      node.outputs[id] = [x];
    }
  });

  // out of pipe, to this node
  _.each(node.outputs, function(outputs){
    _.each(outputs, function(x){
      self.addPipeIn(x, node.id);
    });
  });

  this.nodes[node.id] = node;

  this.runners[node.id] = new Runner (
    node,
    this.opts,
    function(err, pid) {
      if(done){
        return done(err, pid);
      }
    });

};

// start all nodes in the topo
Topology.prototype.start = function(done) {
  var self = this;
  var opts = {};

  if (typeof arguments[0] === 'object'){
    opts = arguments[0];
    done = arguments[1];
  }

  if(!opts.hasOwnProperty('purge')){
    opts.purge = false;
  }

  var purge = function(next){
    if(!opts.purge){
      return next();
    }
    self.purge(function(){
      next();
    });
  };

  var start = function(next){
    async.each(
      _.toArray(self.runners),
      function(runner, next){
        runner.start(next);
      }, function(){
        self.opts.logger.log(
          'info',
          pad.timestamp(),
          'TOPOLOGY',
          'STARTED '
        );
        next();
      });
  };

  async.series([
    purge,
    start
  ], function(){
    if(done && typeof done === 'function'){
      done();
    }
  });

};

// stop all nodes in the topo
Topology.prototype.stop = function(done) {
  var self = this;
  async.eachSeries(
    _.toArray(this.runners),
    function(runner, next){
      runner.stop(next);
    }, function(){
      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'STOPPED '
      );
      if(done && typeof done === 'function'){
        done();
      }
    });
};

// remove messages from all pipes
Topology.prototype.purge = function(done) {

  var prefix = this.opts.redis.prefix + ':';
  var client = redis.createClient(this.opts.redis);

  var self = this;

  async.each(
    _.toArray(this.pipes),
    function(pipe, next){

      // FYI how many elements in the pipe
      client.llen(
        prefix + pipe.id,
        function(err, length){

          self.opts.logger.log(
            'info',
            pad.timestamp(),
            'PIPE    ',
            pipe.id + ' ' + length
          );

          // remove all elements from pipe
          client.del(
            prefix + pipe.id,
            function(err, length){
              next();
            });

        });

    }, function(){

      client.quit();

      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'PURGED'
      );

      if(done && typeof done === 'function'){
        done();
      }
    });

};

// quit all the nodes in the topology
Topology.prototype.destroy = function(done) {

  var self = this;

  async.each(
    _.toArray(this.runners),
    function(runner, next){
      runner.quit(next);

    }, function(){

      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'DESTROYED'
      );

      if(done && typeof done === 'function'){
        done();
      }
    });

};

var create = function(){

  var opts;

  opts = {};

  if ( typeof arguments[0] === 'object' ) {
    opts = arguments[0];
  }

  if(!opts.hasOwnProperty('pidsfile')){
    opts.pidsfile = false;
  }

  if(!opts.hasOwnProperty('nodes_dir')){
    opts.nodes_dir = false;
  }

  if(!opts.hasOwnProperty('redis')){
    opts.redis = {
      host: '127.0.0.1',
      port: 6379
    };
  }

  if(!opts.redis.hasOwnProperty('prefix')){
    opts.redis.prefix = 'straw';
  }

  if(!opts.hasOwnProperty('logger')){

    var transports = [];
    if(opts.hasOwnProperty('log_f')){
      transports.push(new (winston.transports.File)({ filename: 'somefile.log' }));
    } else {
      transports.push(new (winston.transports.Console)());
    }

    opts.logger = new (winston.Logger)({
      transports: transports
    });

  }

  var topo = new Topology(opts);

  return topo;

};

module.exports = {
  create: create
};

// /*
// * extract nodes and pipes from supplied Topo
// */
// Topology.prototype.create = function(topo, opts, done) {

//   var self = this;

//   var pkey, tkey, skey, def, i, x;

//   var pipes = {};
//   var nodes = {};

//   var nodeCount = 0;

//   var pids = {};

//   var client = redis.createClient();

//   client.on("error", function (err) {
//     self.opts.logger.log('info', err);
//     process.exit(0);
//   });

//   // pull pipes from the topo map

//   var prefix = opts.redis.prefix + ':';

//   // use purge:false to retain messages in queues across restarts
//   if(!opts.hasOwnProperty('purge') || opts.purge){
//     _.each(topo, function(node){

//       if(node.hasOwnProperty('input')){
//         var input = node.input;
//         if (!Array.isArray(input)) {
//           input = [input];
//         }
//         _.each(input, function(x){
//           client.del(prefix + x);
//         });
//       }

//       if(node.hasOwnProperty('inputs')){
//         _.each(node.inputs, function(x){
//           client.del(prefix + x);
//         });
//       }

//       if(node.hasOwnProperty('output')){
//         var output = node.output;
//         if (!Array.isArray(output)) {
//           output = [output];
//         }
//         _.each(output, function(x){
//           client.del(prefix + x);
//         });
//       }

//       if(node.hasOwnProperty('outputs')){
//         _.each(node.outputs, function(x){
//           client.del(prefix + x);
//         });
//       }

//     });
//   }

//   client.quit();

//   // pull nodes from the topo and tell them about their pipes

//   /*jshint loopfunc:true */
//   for ( tkey in topo ) {

//     if (!topo[tkey].hasOwnProperty('node')) {
//       continue;
//     }

//     def = topo[tkey];

//     // expand default input to include pipe definitions
//     if ( typeof def.input === 'undefined' ) {
//       def.input = [];
//     } else {
//       if (!Array.isArray(def.input)) {
//         def.input = [def.input];
//       }
//     }

//     // expand default outputs to include pipe definitions
//     if (typeof def.output !== 'undefined' ) {
//       if ( ! Array.isArray(def.output)) {
//         def.output = [def.output];
//       }
//     } else {
//       def.output = [];
//     }

//     if (!def.hasOwnProperty('outputs')) {
//       def.outputs = {};
//     }

//     nodes[tkey] = topo[tkey];
//     nodeCount = nodeCount + 1;
//   }

//   /*jshint loopfunc:false */

//   // spawn the nodes. wait until they are ready before callback
//   var finished = function(err) {
//     nodeCount = nodeCount - 1;
//     if ( nodeCount === 0 ) {
//       self.opts.logger.log('info', pad.timestamp(), 'TOPOLOGY STARTED');
//       if(done && typeof done === 'function'){
//         done(false, pids);
//       }
//     }
//   };

//   _.each(nodes, function(node, skey) {
//     self.spawn(skey, node, opts, function(err, res){
//       pids[skey] = res.pid;
//       finished(false);
//     });
//   });

// };

<commit_msg>Remove old code<commit_after>"use strict";

var fs = require('fs');
var winston = require('winston');
var redis = require('redis');
var _ = require('underscore');
var async = require('async');

var Runner = require('./runner.js');
var pad = require('./pad');

var Topology = function (opts) {

  this.opts = opts;

  this.pipes = {};
  this.nodes = {};
  this.runners = {};

  // try to kill dangling processes from a previous run

  if(this.opts.pidsfile && fs.existsSync(this.opts.pidsfile)) {
    var pids = JSON.parse(fs.readFileSync(this.opts.pidsfile));
    _.each(pids, function(pid){
      try{
        process.kill(pid, 'SIGHUP');
      } catch (err){
        // catch error if no process
        //logger.log('info', err);
      }
    });
  }

  return this;

};

Topology.prototype.addPipe = function(id) {
  if(!this.pipes.hasOwnProperty(id)){
    this.pipes[id] = {
      id: id,
      outputs: [],
      inputs: []
    };
  }
};

Topology.prototype.addPipeOut = function(pipe_id, node_id) {
  this.addPipe(pipe_id);
  this.pipes[pipe_id].outputs.push(node_id);
};

Topology.prototype.addPipeIn = function(pipe_id, node_id) {
  this.addPipe(pipe_id);
  this.pipes[pipe_id].inputs.push(node_id);
};

/*
 * Add a node to the topology by spawning it in it's own process. The
 * Runner takes care of setting up the process and starting the node
 * in it.
 */
Topology.prototype.add = function(node, done) {

  var self = this;

  // array of nodes was given
  if (Array.isArray(node)) {
    return async.eachSeries(node, function(x, next){
      Topology.prototype.add.call(self, x, next);
    }, function(){
      return done && done();
    });
  }

  if(this.opts.nodes_dir){
    node.node = this.opts.nodes_dir + '/' + node.node + '.js';
  }

  if(this.nodes.hasOwnProperty(node.id)){
    this.opts.logger.log(
      'info',
      pad.timestamp(),
      'ADD FAIL',
      node.id,
      'ALREADY EXISTS'
    );
    return done(new Error('Node ID already exists'));
  }

  this.opts.logger.log(
    'info',
    pad.timestamp(),
    'ADD     ',
    node.id
  );

  //this.opts.logger.log('info', 'Adding Node %s', node.id);

  // if(!fs.existsSync(node.node)) {
  //   return done(new Error('Node file not found'));
  // }

  // create references to the pipes this node uses. Actual plumbing is
  // done using Redis, but we keep account of it here so we can pull
  // stats and otherwise control pipes, e.g. purge them

  // input
  if(!node.hasOwnProperty('input')){
    node.input = [];
  }

  // this node receives input from `pipe`. Input can be received from
  // many pipes. If a single key was supplied, convert to array.
  if (!Array.isArray(node.input)) {
    node.input = [node.input];
  }

  // out of pipe, to this node
  _.each(node.input, function(x){
    self.addPipeOut(x, node.id);
  });

  // default output
  if(!node.hasOwnProperty('output')){
    node.output = [];
  }

  // default output can go to many pipes. if a single key was
  // provided, convert to array.
  if (!Array.isArray(node.output)) {
    node.output = [node.output];
  }

  // out of node, to these pipes
  _.each(node.output, function(x){
    self.addPipeIn(x, node.id);
  });

  // named outputs
  if(!node.hasOwnProperty('outputs')){
    node.outputs = {};
  }

  // each named output can go to many pipes. If a single key was
  // supplied, convert to array.
  _.each(node.outputs, function(x, id){
    if (!Array.isArray(x)) {
      node.outputs[id] = [x];
    }
  });

  // out of pipe, to this node
  _.each(node.outputs, function(outputs){
    _.each(outputs, function(x){
      self.addPipeIn(x, node.id);
    });
  });

  this.nodes[node.id] = node;

  this.runners[node.id] = new Runner (
    node,
    this.opts,
    function(err, pid) {
      if(done){
        return done(err, pid);
      }
    });

};

// start all nodes in the topo
Topology.prototype.start = function(done) {
  var self = this;
  var opts = {};

  if (typeof arguments[0] === 'object'){
    opts = arguments[0];
    done = arguments[1];
  }

  if(!opts.hasOwnProperty('purge')){
    opts.purge = false;
  }

  var purge = function(next){
    if(!opts.purge){
      return next();
    }
    self.purge(function(){
      next();
    });
  };

  var start = function(next){
    async.each(
      _.toArray(self.runners),
      function(runner, next){
        runner.start(next);
      }, function(){
        self.opts.logger.log(
          'info',
          pad.timestamp(),
          'TOPOLOGY',
          'STARTED '
        );
        next();
      });
  };

  async.series([
    purge,
    start
  ], function(){
    if(done && typeof done === 'function'){
      done();
    }
  });

};

// stop all nodes in the topo
Topology.prototype.stop = function(done) {
  var self = this;
  async.eachSeries(
    _.toArray(this.runners),
    function(runner, next){
      runner.stop(next);
    }, function(){
      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'STOPPED '
      );
      if(done && typeof done === 'function'){
        done();
      }
    });
};

// remove messages from all pipes
Topology.prototype.purge = function(done) {

  var prefix = this.opts.redis.prefix + ':';
  var client = redis.createClient(this.opts.redis);

  var self = this;

  async.each(
    _.toArray(this.pipes),
    function(pipe, next){

      // FYI how many elements in the pipe
      client.llen(
        prefix + pipe.id,
        function(err, length){

          self.opts.logger.log(
            'info',
            pad.timestamp(),
            'PIPE    ',
            pipe.id + ' ' + length
          );

          // remove all elements from pipe
          client.del(
            prefix + pipe.id,
            function(err, length){
              next();
            });

        });

    }, function(){

      client.quit();

      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'PURGED'
      );

      if(done && typeof done === 'function'){
        done();
      }
    });

};

// quit all the nodes in the topology
Topology.prototype.destroy = function(done) {

  var self = this;

  async.each(
    _.toArray(this.runners),
    function(runner, next){
      runner.quit(next);

    }, function(){

      self.opts.logger.log(
        'info',
        pad.timestamp(),
        'TOPOLOGY',
        'DESTROYED'
      );

      if(done && typeof done === 'function'){
        done();
      }
    });

};

var create = function(){

  var opts;

  opts = {};

  if ( typeof arguments[0] === 'object' ) {
    opts = arguments[0];
  }

  if(!opts.hasOwnProperty('pidsfile')){
    opts.pidsfile = false;
  }

  if(!opts.hasOwnProperty('nodes_dir')){
    opts.nodes_dir = false;
  }

  if(!opts.hasOwnProperty('redis')){
    opts.redis = {
      host: '127.0.0.1',
      port: 6379
    };
  }

  if(!opts.redis.hasOwnProperty('prefix')){
    opts.redis.prefix = 'straw';
  }

  if(!opts.hasOwnProperty('logger')){

    var transports = [];
    if(opts.hasOwnProperty('log_f')){
      transports.push(new (winston.transports.File)({ filename: 'somefile.log' }));
    } else {
      transports.push(new (winston.transports.Console)());
    }

    opts.logger = new (winston.Logger)({
      transports: transports
    });

  }

  var topo = new Topology(opts);

  return topo;

};

module.exports = {
  create: create
};
<|endoftext|>


<commit_before><commit_msg>Ensure console.log is defined.<commit_after>if(!window.console) console = {log: function() {}};
<|endoftext|>


<commit_before>'use strict';

/**
 * The `kss/lib/traverse` module is normally accessed via the
 * [`traverse()`]{@link module:kss.traverse} method of the `kss` module:
 * ```
 * var kss = require('kss');
 * kss.traverse(directory, options, callback);
 * ```
 * @private
 * @module kss/lib/traverse
 */

var parse = require('./parse.js'),
  path = require('path'),
  fs = require('fs');

var traverse;

/**
 * Traverse a directory, parse its contents, and create a KssStyleguide.
 *
 * Callbacks receive an instance of `KssStyleguide`.
 *
 * If you want to parse anything other than css, less, sass, or stylus files
 * then you'll want to use options.mask to target a different set of file
 * extensions.
 *
 * ```
 * kss.traverse('./stylesheets', { mask: '*.css' }, function(err, styleguide) {
 *     if (err) throw err;
 *
 *     styleguide.section('2.1.1') // <KssSection>
 * });
 * ```
 *
 * There a few extra `options` you can pass to `kss.traverse` which will effect
 * the output generated:
 *
 * - mask: Use a regex or string (e.g. `*.less|*.css`) to only parse files
 *   matching this value. Defaults to:
 *   `*.css|*.less|*.sass|*.scss|*.styl|*.stylus`
 * - markdown: kss-node supports built-in Markdown formatting of its
 *   documentation, thanks to [marked](https://github.com/chjj/marked). It's
 *   enabled by default, but you can disable it by adding `markdown: false` to
 *   the `options` object.
 * - multiline: kss-node makes the header available separately from the
 *   description. To make kss-node behave like the Ruby KSS, disable this option
 *   and the title will remain a part of the description. This setting is
 *   enabled by default, but you can disable it by adding `multiline: false` to
 *   your options.
 * - typos: Thanks to [natural](https://github.com/NaturalNode/natural),
 *   kss-node can parse keywords phonetically rather then by their string value.
 *   In short: make a typo and the library will do its best to read it anyway.
 *   Enabled by default.
 *
 * @alias module:kss.traverse
 * @param {String|Array} directory The directory(s) to traverse
 * @param {Object}       options   Options to alter the output content (optional)
 * @param {Function}     callback  Called when traversal AND parsing is complete
 */
traverse = function(directory, options, callback) {
  var fileNames = [],
    fileCounter = 0,
    filesRemaining = 0,
    loopsRemaining = 0,
    walkFinished,
    walk;

  options = options || {};
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  if (typeof callback === 'undefined') {
    throw new Error('No callback supplied for kss.traverse()!');
  }

  // Mask to search for particular file types - defaults to common precompilers.
  options.mask = options.mask || /\.css|\.less|\.sass|\.scss|\.styl|\.stylus/;

  // If the mask is a string, convert it into a RegExp.
  if (!(options.mask instanceof RegExp)) {
    options.mask = new RegExp(
      '(?:' + options.mask.replace(/\./g, '\\.').replace(/\*/g, '.*') + ')$'
    );
  }

  // Normalize all the directory paths.
  if (!Array.isArray(directory)) {
    directory = [directory];
  }
  for (var key in directory) {
    directory[key] = path.normalize(directory[key]);
  }

  // Callback for walk() when it has finished traversing all directories.
  walkFinished = function() {
    /*eslint-disable no-loop-func*/
    var i, l = fileNames.length, files = [], orderedObject = {};

    fileNames.sort();
    for (i = 0; i < l; i += 1) {
      (function(j) {
        fs.readFile(fileNames[j], 'utf8', function(err, contents) {
          if (err) { callback(err); return; }

          files[j] = contents;
          fileCounter -= 1;

          if (fileCounter === 0) {
            files.map(function(fileContent, index) {
              var filename = fileNames[index];
              orderedObject[filename] = fileContent;
              return '';
            });
            parse(orderedObject, options, callback);
          }
        });
      }(i));
    }
  };

  // Courtesy of [stygstra](https://gist.github.com/514983)
  walk = function(directories, opts, cb) {
    opts = opts || {};
    if (typeof cb !== 'function') { cb = function() {}; }

    if (!Array.isArray(directories)) {
      directories = [directories];
    }

    // Loop through all the given directories.
    loopsRemaining += directories.length;
    directories.forEach(function(dir) {
      loopsRemaining -= 1;

      // Start an asynchronous search of the file system.
      filesRemaining += 1;
      fs.readdir(dir, function(err, relnames) {
        if (err) {
          cb(err);
          return;
        }

        // About to start looping through the directory contents.
        loopsRemaining += relnames.length;
        // The fs.readdir() callback has returned.
        filesRemaining -= 1;

        // If there is no more file system to search, call .finished().
        if (filesRemaining === 0 && loopsRemaining === 0) {
          cb(null);
        }

        // Otherwise, if readdir() has results, loop through them.
        relnames.forEach(function(relname) {
          loopsRemaining -= 1;
          var name = path.join(dir, relname);

          // Start an asynchronous stat of this file system item.
          filesRemaining += 1;
          fs.stat(name, function(error, stat) {
            if (error) {
              cb(error);
              return;
            }

            if (stat.isDirectory()) {
              if (name !== '.svn' && name !== '.git') {
                walk(name, opts, cb);
              }
            } else if (!opts.mask || name.match(opts.mask)) {
              name = name.replace(/\\/g, '/');
              fileNames.push(name);
              fileCounter += 1;
            }

            // The fs.stat() callback has returned.
            filesRemaining -= 1;

            // If there is no more file system to search, call .finished().
            if (filesRemaining === 0 && loopsRemaining === 0) {
              cb(null);
              return;
            }
          });
        });
      });
    });
  };

  // Get each file in the target directory, order them alphabetically and then
  // parse their output.
  walk(directory, options, walkFinished);
};

module.exports = traverse;
<commit_msg>Add better checking of callback in traverse().<commit_after>'use strict';

/**
 * The `kss/lib/traverse` module is normally accessed via the
 * [`traverse()`]{@link module:kss.traverse} method of the `kss` module:
 * ```
 * var kss = require('kss');
 * kss.traverse(directory, options, callback);
 * ```
 * @private
 * @module kss/lib/traverse
 */

var parse = require('./parse.js'),
  path = require('path'),
  fs = require('fs');

var traverse;

/**
 * Traverse a directory, parse its contents, and create a KssStyleguide.
 *
 * Callbacks receive an instance of `KssStyleguide`.
 *
 * If you want to parse anything other than css, less, sass, or stylus files
 * then you'll want to use options.mask to target a different set of file
 * extensions.
 *
 * ```
 * kss.traverse('./stylesheets', { mask: '*.css' }, function(err, styleguide) {
 *     if (err) throw err;
 *
 *     styleguide.section('2.1.1') // <KssSection>
 * });
 * ```
 *
 * There a few extra `options` you can pass to `kss.traverse` which will effect
 * the output generated:
 *
 * - mask: Use a regex or string (e.g. `*.less|*.css`) to only parse files
 *   matching this value. Defaults to:
 *   `*.css|*.less|*.sass|*.scss|*.styl|*.stylus`
 * - markdown: kss-node supports built-in Markdown formatting of its
 *   documentation, thanks to [marked](https://github.com/chjj/marked). It's
 *   enabled by default, but you can disable it by adding `markdown: false` to
 *   the `options` object.
 * - multiline: kss-node makes the header available separately from the
 *   description. To make kss-node behave like the Ruby KSS, disable this option
 *   and the title will remain a part of the description. This setting is
 *   enabled by default, but you can disable it by adding `multiline: false` to
 *   your options.
 * - typos: Thanks to [natural](https://github.com/NaturalNode/natural),
 *   kss-node can parse keywords phonetically rather then by their string value.
 *   In short: make a typo and the library will do its best to read it anyway.
 *   Enabled by default.
 *
 * @alias module:kss.traverse
 * @param {String|Array} directory The directory(s) to traverse
 * @param {Object}       options   Options to alter the output content (optional)
 * @param {Function}     callback  Called when traversal AND parsing is complete
 */
traverse = function(directory, options, callback) {
  var fileNames = [],
    fileCounter = 0,
    filesRemaining = 0,
    loopsRemaining = 0,
    walkFinished,
    walk;

  options = options || {};
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  if (typeof callback !== 'function') {
    throw new Error('No callback supplied for kss.traverse()!');
  }

  // Mask to search for particular file types - defaults to common precompilers.
  options.mask = options.mask || /\.css|\.less|\.sass|\.scss|\.styl|\.stylus/;

  // If the mask is a string, convert it into a RegExp.
  if (!(options.mask instanceof RegExp)) {
    options.mask = new RegExp(
      '(?:' + options.mask.replace(/\./g, '\\.').replace(/\*/g, '.*') + ')$'
    );
  }

  // Normalize all the directory paths.
  if (!Array.isArray(directory)) {
    directory = [directory];
  }
  for (var key in directory) {
    directory[key] = path.normalize(directory[key]);
  }

  // Callback for walk() when it has finished traversing all directories.
  walkFinished = function() {
    /*eslint-disable no-loop-func*/
    var i, l = fileNames.length, files = [], orderedObject = {};

    fileNames.sort();
    for (i = 0; i < l; i += 1) {
      (function(j) {
        fs.readFile(fileNames[j], 'utf8', function(err, contents) {
          if (err) { callback(err); return; }

          files[j] = contents;
          fileCounter -= 1;

          if (fileCounter === 0) {
            files.map(function(fileContent, index) {
              var filename = fileNames[index];
              orderedObject[filename] = fileContent;
              return '';
            });
            parse(orderedObject, options, callback);
          }
        });
      }(i));
    }
  };

  // Courtesy of [stygstra](https://gist.github.com/514983)
  walk = function(directories, opts, cb) {
    opts = opts || {};
    if (typeof cb !== 'function') { cb = function() {}; }

    if (!Array.isArray(directories)) {
      directories = [directories];
    }

    // Loop through all the given directories.
    loopsRemaining += directories.length;
    directories.forEach(function(dir) {
      loopsRemaining -= 1;

      // Start an asynchronous search of the file system.
      filesRemaining += 1;
      fs.readdir(dir, function(err, relnames) {
        if (err) {
          cb(err);
          return;
        }

        // About to start looping through the directory contents.
        loopsRemaining += relnames.length;
        // The fs.readdir() callback has returned.
        filesRemaining -= 1;

        // If there is no more file system to search, call .finished().
        if (filesRemaining === 0 && loopsRemaining === 0) {
          cb(null);
        }

        // Otherwise, if readdir() has results, loop through them.
        relnames.forEach(function(relname) {
          loopsRemaining -= 1;
          var name = path.join(dir, relname);

          // Start an asynchronous stat of this file system item.
          filesRemaining += 1;
          fs.stat(name, function(error, stat) {
            if (error) {
              cb(error);
              return;
            }

            if (stat.isDirectory()) {
              if (name !== '.svn' && name !== '.git') {
                walk(name, opts, cb);
              }
            } else if (!opts.mask || name.match(opts.mask)) {
              name = name.replace(/\\/g, '/');
              fileNames.push(name);
              fileCounter += 1;
            }

            // The fs.stat() callback has returned.
            filesRemaining -= 1;

            // If there is no more file system to search, call .finished().
            if (filesRemaining === 0 && loopsRemaining === 0) {
              cb(null);
              return;
            }
          });
        });
      });
    });
  };

  // Get each file in the target directory, order them alphabetically and then
  // parse their output.
  walk(directory, options, walkFinished);
};

module.exports = traverse;
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var Remo = (function (_React$Component) {
  _inherits(Remo, _React$Component);

  function Remo() {
    _classCallCheck(this, Remo);

    _get(Object.getPrototypeOf(Remo.prototype), 'constructor', this).apply(this, arguments);
  }

  _createClass(Remo, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      this.node = document.createElement('div');
      this.node.className = 'RemoOverlay';
      document.body.appendChild(this.node);
      this.toggleModal(this.props.isOpen);
      this.node.addEventListener("click", this.hideModal.bind(this), false);
    }
  }, {
    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      this.node.removeEventListener('click', this.hideModal.bind(this), false);
      document.body.removeChild(this.node);
    }
  }, {
    key: 'componentWillReceiveProps',
    value: function componentWillReceiveProps(newProps) {
      this.toggleModal(newProps.isOpen);
    }
  }, {
    key: 'hideModal',
    value: function hideModal() {
      this.toggleModal(false);
    }
  }, {
    key: 'toggleModal',
    value: function toggleModal(isOpen) {
      var displayStyle = 'none';
      if (isOpen) {
        displayStyle = 'inline';
      }
      if (parseFloat(_react2['default'].version) >= 0.14) {
        this.refs.rmod.style.display = displayStyle;
      } else {
        this.refs.rmod.getDOMNode().style.display = displayStyle;
      }
      this.node.style.display = displayStyle;
    }
  }, {
    key: 'render',
    value: function render() {
      return _react2['default'].createElement(
        'div',
        { className: 'RemoModal', ref: 'rmod' },
        this.props.children
      );
    }
  }]);

  return Remo;
})(_react2['default'].Component);

;

Remo.propTypes = {
  isOpen: _react2['default'].PropTypes.bool.isRequired
};

exports['default'] = Remo;
module.exports = exports['default'];
<commit_msg>[changed] Remo.js file<commit_after>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var Remo = (function (_React$Component) {
  _inherits(Remo, _React$Component);

  function Remo() {
    _classCallCheck(this, Remo);

    _get(Object.getPrototypeOf(Remo.prototype), 'constructor', this).apply(this, arguments);
  }

  _createClass(Remo, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      this.node = document.createElement('div');
      this.node.className = 'RemoOverlay';
      document.body.appendChild(this.node);
      this.toggleModal(this.props.isOpen);
      this.node.addEventListener("click", this.hideModal.bind(this), false);
    }
  }, {
    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      this.node.removeEventListener('click', this.hideModal.bind(this), false);
      document.body.removeChild(this.node);
    }
  }, {
    key: 'componentWillReceiveProps',
    value: function componentWillReceiveProps(newProps) {
      this.toggleModal(newProps.isOpen);
    }
  }, {
    key: 'hideModal',
    value: function hideModal() {
      this.toggleModal(false);
    }
  }, {
    key: 'toggleModal',
    value: function toggleModal(isOpen) {
      var displayStyle = 'none';
      if (isOpen) {
        displayStyle = 'inline';
      }
      if (parseFloat(_react2['default'].version) >= 0.14) {
        this.refs.rmod.style.display = displayStyle;
      } else {
        this.refs.rmod.getDOMNode().style.display = displayStyle;
      }
      this.node.style.display = displayStyle;
    }
  }, {
    key: 'render',
    value: function render() {
      return _react2['default'].createElement(
        'div',
        { className: 'RemoModal', ref: 'rmod' },
        this.props.children
      );
    }
  }]);

  return Remo;
})(_react2['default'].Component);

;

Remo.propTypes = {
  isOpen: _react2['default'].PropTypes.bool.isRequired
};

exports['default'] = Remo;
module.exports = exports['default'];<|endoftext|>


<commit_before>var vows = require('vows');
var assert = require('assert');
var path_module = require('path');

var view_component = require('../../components/view');
var View = view_component.View;

vows.describe('View Component').addBatch({
    'An html view': {
        topic: function () {
        	var view = new View();
        	var _topic = this;
        	view.setContentType('text/html');
        	view.dir = path_module.normalize(__dirname + '/../testing_resources/');
        	view.error(function (error) {
        		throw error;
        	});
        	view.setResponse({
        		buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});

        	view.render('view_example.html');
        },
        'renders correctly': function (view) {
		assert.equal(view.buffer, "this is a  test");
        },
        'is complete' : function (view) {
        	console.log(view);
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with data' : {
        topic: function () {
        	var _topic = this;
        	var view = new View();
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	view.set('status', 'single view');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});
        	view.render('view_example.html');
        },
        'renders correctly' : function (view) {
			assert.equal(view.buffer, "this is a single view test");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with children rendered first' : {
        topic: function () {
        	var _topic = this;
        	var view = new View();
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	var child = view.child('status');
        	child.set('status', 'child');
        	child.render('view_example.html');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});
        	view.render('view_example.html');
        },
        'renders correctly' : function (view) {
        	assert.equal(view.buffer, "this is a this is a child test test");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with children rendered last' : {
        topic: function () {
        	var view = new View();
        	var _topic = this;
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	var child = view.child('status');

        	view.render('view_example.html');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});

        	child.set('status', 'child');
        	child.render('view_example.html');
        },
        'renders correctly' : function (view) {
        	assert.equal(view.buffer, "this is a this is a child test test");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    }
}).export(module); // Export the Suite
<commit_msg>clean up and fix view tests so they pass<commit_after>var vows = require('vows');
var assert = require('assert');
var path_module = require('path');
var util_module = require('util');

var view_component = require('../../components/view');
var View = view_component.View;
var Renderer = view_component.Renderer;

vows.describe('View Component').addBatch({
    'An html view': {
        topic: function () {
        	var view = new View();
        	var _topic = this;
        	view.setContentType('text/html');
        	view.dir = path_module.normalize(__dirname + '/../testing_resources/');
        	view.error(function (error) {
        		throw error;
        	});
        	view.setResponse({
        		buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});

        	view.render('view_example.html');
        },
        'renders correctly': function (view) {
			assert.equal(view.buffer, "view_example.html {}");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with data' : {
        topic: function () {
        	var _topic = this;
        	var view = new View();
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	view.set('status', 'single view');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});
        	view.render('view_example.html');
        },
        'renders correctly' : function (view) {
			assert.equal(view.buffer, "view_example.html {single view,}");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with children rendered first' : {
        topic: function () {
        	var _topic = this;
        	var view = new View();
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	var child = view.child('status');
        	child.set('status', 'child');
        	child.render('view_example.html');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});
        	view.render('view_example.html');
        },
        'renders correctly' : function (view) {
        	assert.equal(view.buffer, "view_example.html {view_example.html {child,},}");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    },
    'An html view with children rendered last' : {
        topic: function () {
        	var view = new View();
        	var _topic = this;
        	view.setContentType('text/html');
        	view.dir = __dirname.replace('/components', '/testing_resources') + '/';
        	view.error(function (error) {
        		throw error;
        	});
        	var child = view.child('status');

        	view.render('view_example.html');

        	view.setResponse({
    			buffer : '',
        		write : function (chunk) {
        			this.buffer += chunk;
        		},
        		end : function () {
        			_topic.callback(null, {view: view, buffer: this.buffer});
        		}
        	});

        	child.set('status', 'child');
        	child.render('view_example.html');
        },
        'renders correctly' : function (view) {
        	assert.equal(view.buffer, "view_example.html {view_example.html {child,},}");
        },
        'is complete' : function (view) {
        	assert.equal(view.view.render_state, view_component.RENDER_STATES.RENDER_COMPLETE);
        },
    }
}).export(module); // Export the Suite

var TestRenderer = function() {
	Renderer.call(this);
};
util_module.inherits(TestRenderer, Renderer);

/**
 * Requests the provided template to be rendered
 *
 * @param  {string} template
 */
TestRenderer.prototype.render = function (template) {
	var _self = this;
	var data = '';

	Object.keys(this.data).forEach(function (value) {
		data = data + _self.data[value] + ',';
	});
	template = template.split('/');
	template = template[template.length - 1];
	this.response.write(template + ' {' + data + '}');
	this._end();
	this.response.end();
};

view_component.addRenderer('text/html', TestRenderer);<|endoftext|>


<commit_before>var sys = require('sys'),
    Buffer = require('buffer').Buffer,
    dgram = require('dgram1');

host = "localhost";
port = 9999;

// slices a single byte into bits
// assuming only single bytes
var sliceBits = function(b, off, len) {
    var s = 7 - (off + len - 1);

    b = b >>> s;
    return b & ~(0xff << len);
};

var server = dgram.createSocket(function (msg, rinfo) {

    //split up the message into the dns request header info and the query
    var q = processRequest(msg);

    buf = createResponse(q);
    server.send(rinfo.port, rinfo.address, buf, 0, buf.length, function (err, sent) {

    });
});

//takes a buffer as a request
var processRequest = function(req) {
    //see rfc1035 for more details
    //http://tools.ietf.org/html/rfc1035#section-4.1.1

    var query = {};
    query.header = {};
    //TODO write code to break questions up into an array
    query.question = {};

    var tmpSlice;
    var tmpByte;

    //transaction id
    // 2 bytes
    query.header.id = req.slice(0,2);

    //slice out a byte for the next section to dice into binary.
    tmpSlice = req.slice(2,3);
    //convert the binary buf into a string and then pull the char code
    //for the byte
    tmpByte = tmpSlice.toString('binary', 0, 1).charCodeAt(0);

    //qr
    // 1 bit
    query.header.qr = sliceBits(tmpByte, 0,1);
    //opcode
    // 0 = standard, 1 = inverse, 2 = server status, 3-15 reserved
    // 4 bits
    query.header.opcode = sliceBits(tmpByte, 1,4);
    //authorative answer
    // 1 bit
    query.header.aa = sliceBits(tmpByte, 5,1);
    //truncated
    // 1 bit
    query.header.tc = sliceBits(tmpByte, 6,1);
    //recursion desired
    // 1 bit
    query.header.rd = sliceBits(tmpByte, 7,1);

    //slice out a byte to dice into binary
    tmpSlice = req.slice(3,4);
    //convert the binary buf into a string and then pull the char code
    //for the byte
    tmpByte = tmpSlice.toString('binary', 0, 1).charCodeAt(0);

    //recursion available
    // 1 bit
    query.header.ra = sliceBits(tmpByte, 0,1);

    //reserved 3 bits
    // rfc says always 0
    query.header.z = sliceBits(tmpByte, 1,3);

    //response code
    // 0 = no error, 1 = format error, 2 = server failure
    // 3 = name error, 4 = not implemented, 5 = refused
    // 6-15 reserved
    // 4 bits
    query.header.rcode = sliceBits(tmpByte, 4,4);

    //question count
    // 2 bytes
    query.header.qdcount = req.slice(4,6);
    //answer count
    // 2 bytes
    query.header.ancount = req.slice(6,8);
    //ns count
    // 2 bytes
    query.header.nscount = req.slice(8,10);
    //addition resources count
    // 2 bytes
    query.header.arcount = req.slice(10, 12);

    //assuming one question
    //qname is the sequence of domain labels
    //qname length is not fixed however it is 4
    //octets from the end of the buffer
    query.question.qname = req.slice(12, req.length - 4);
    //qtype
    query.question.qtype = req.slice(req.length - 4, req.length - 2);
    //qclass
    query.question.qclass = req.slice(req.length - 2, req.length);

    return query;
};

var createResponse = function(query) {
    var response = {};
    response.header = {};

    //1 byte
    response.header.id = query.header.id;//same as query id

    //combined 1 byte
    response.header.qr = 1; //this is a response
    response.header.opcode = 0; //standard for now TODO: add other types 4-bit!
    response.header.aa = 0; //authority... TODO this should be modal
    response.header.tc = 0; //truncation
    response.header.rd = 1; //recursion asked for

    //combined 1 byte
    response.header.ra = 1; //no rescursion here TODO
    response.header.z = 0; // spec says this MUST always be 0. 3bit
    response.header.rcode = 0; //TODO add error codes 4 bit.

    //1 byte
    response.header.qdcount = 1; //1 question
    //1 byte
    response.header.ancount = 2; //1 answer TODO support multiple Qs/As
    //1 byte
    response.header.nscount = 0;
    //1 byte
    response.header.arcount = 0;

    response.question = {};
    response.question.qname = query.question.qname;
    response.question.qtype = query.question.qtype;
    response.question.qclass = query.question.qclass;

    response.rr = [];

    response.rr[0] = {}; // TODO should be an array or something
    response.rr[0].qname = query.question.qname;
    response.rr[0].qtype = query.question.qtype;
    response.rr[0].qclass = query.question.qclass;
    response.rr[0].ttl = 1;
    response.rr[0].rdlength = 4; //assuming a record ip addy
    response.rr[0].rdata = 0x7F000001 // 127.0.0.1 TODO encoding method

    response.rr[1] = {}; // TODO should be an array or something
    response.rr[1].qname = query.question.qname;
    response.rr[1].qtype = query.question.qtype;
    response.rr[1].qclass = query.question.qclass;
    response.rr[1].ttl = 1;
    response.rr[1].rdlength = 4; //assuming a record ip addy
    response.rr[1].rdata = 0x7F000001 // 127.0.0.1 TODO encoding method

    //TODO compression

    //TODO output to Buffer
    var buf = buildResponseBuffer(response);

    return buf;
};

var domainToQname = function(domain) {
    var tokens = domain.split(".");
    len = domain.length + 2;
    var qname = new Buffer(len);
    var offset = 0;
    for(var i=0; i<tokens.length;i++) {
        qname[offset]=tokens[i].length;
        offset++;
        for(var j=0;j<tokens[i].length;j++) {
            qname[offset] = tokens[i].toCharCode(j);
            offset++;
        }
    }
    qname[offset] = 0;

    return qname;
};

var getZeroBuf = function(len) {
    buf = new Buffer(len);
    for(var i=0;i<buf.length;i++) { buf[i]=0;}
    return buf;
}

var buildResponseBuffer = function(response) {
    //calculate len in octets
    //NB not calculating rr this is done later
    //headers(12) + qname(qname + 2 + 2)
    //e.g. 16 + 2 * qname;
    //qnames are Buffers so length is already in octs
    var qnameLen = response.question.qname.length;
    var len = 16 + qnameLen;
    var buf = getZeroBuf(len);

    response.header.id.copy(buf, 0, 0, 2);

    buf[2] = 0x00 | response.header.qr << 7 | response.header.opcode << 3 | response.header.aa << 2 | response.header.tc << 1 | response.header.rd;

    buf[3] = 0x00 | response.header.ra << 7 | response.header.z << 4 | response.header.rcode;

    numToBuffer(buf, 4, response.header.qdcount, 2);

    numToBuffer(buf, 6, response.header.ancount, 2);
    numToBuffer(buf, 8, response.header.nscount, 2);
    numToBuffer(buf, 10, response.header.arcount, 2);

    //end header

    response.question.qname.copy(buf, 12, 0, qnameLen);
    response.question.qtype.copy(buf, 12+qnameLen, response.question.qtype, 2);
    response.question.qclass.copy(buf, 12+qnameLen+2, response.question.qclass, 2);

    var rrStart = 12+qnameLen+4;

    for (var i=0;i<response.rr.length;i++) {
        //TODO figure out if this is actually cheaper than just iterating
        //over the rr section up front and counting before creating buf
        //
        //create a new buffer to hold the request plus the rr
        //len of each response is 14 bytes of stuff + qname len
        var tmpBuf = getZeroBuf(buf.length + response.rr[i].qname.length + 14);

        //console.log('buf len: ' + buf.length);
        //console.log('rrStart: ' + rrStart);
        //console.log('tmpBuf len: ' + tmpBuf.length);
        //console.log('qname len: ' + response.rr[i].qname.length);

        buf.copy(tmpBuf, 0, 0, buf.length);
        //console.log('copy');
        //console.log(sys.inspect(tmpBuf));
        response.rr[i].qname.copy(tmpBuf, rrStart, 0, response.rr[i].qname.length);
        response.rr[i].qtype.copy(tmpBuf, rrStart+response.rr[i].qname.length, response.rr[i].qtype, 2);
        response.rr[i].qclass.copy(tmpBuf, rrStart+response.rr[i].qname.length+2, response.rr[i].qclass, 2);
        numTotmpBuffer(tmpBuf, rrStart+response.rr[i].qname.length+4, response.rr[i].ttl, 4);
        numTotmpBuffer(tmpBuf, rrStart+response.rr[i].qname.length+8, response.rr[i].rdlength, 2);
        numTotmpBuffer(tmpBuf, rrStart+response.rr[i].qname.length+10, response.rr[i].rdata, response.rr[i].rdlength); // rdlength indicates rdata length

        rrStart = rrStart + response.rr[i].qname.length + 14;

        buf = tmpBuf;
    }

    return buf;
};

//take a number and make sure it's written to the buffer as
//the correct length of bytes with leading 0 padding where necessary
// takes buffer, offset, number, length in bytes to insert
var numToBuffer = function(buf, offset, num, len, debug) {
    if (typeof num != "number") {
        throw "Num must be a number";
    }

    for (var i=offset;i<offset+len;i++) {

            var shift = 8*((len - 1) - (i - offset));

            var insert = (num >> shift) & 255;

            buf[i] = insert;
    }

    return buf;
}

server.addListener("error", function (e) {
  throw e;
});

server.bind(port, host);
console.log("Started server on " + host + ":" + port);<commit_msg>removing debugging and whitespace lines<commit_after>var sys = require('sys'),
    Buffer = require('buffer').Buffer,
    dgram = require('dgram1');

host = "localhost";
port = 9999;

// slices a single byte into bits
// assuming only single bytes
var sliceBits = function(b, off, len) {
    var s = 7 - (off + len - 1);

    b = b >>> s;
    return b & ~(0xff << len);
};

var server = dgram.createSocket(function (msg, rinfo) {

    //split up the message into the dns request header info and the query
    var q = processRequest(msg);

    buf = createResponse(q);
    server.send(rinfo.port, rinfo.address, buf, 0, buf.length, function (err, sent) {

    });
});

//takes a buffer as a request
var processRequest = function(req) {
    //see rfc1035 for more details
    //http://tools.ietf.org/html/rfc1035#section-4.1.1

    var query = {};
    query.header = {};
    //TODO write code to break questions up into an array
    query.question = {};

    var tmpSlice;
    var tmpByte;

    //transaction id
    // 2 bytes
    query.header.id = req.slice(0,2);

    //slice out a byte for the next section to dice into binary.
    tmpSlice = req.slice(2,3);
    //convert the binary buf into a string and then pull the char code
    //for the byte
    tmpByte = tmpSlice.toString('binary', 0, 1).charCodeAt(0);

    //qr
    // 1 bit
    query.header.qr = sliceBits(tmpByte, 0,1);
    //opcode
    // 0 = standard, 1 = inverse, 2 = server status, 3-15 reserved
    // 4 bits
    query.header.opcode = sliceBits(tmpByte, 1,4);
    //authorative answer
    // 1 bit
    query.header.aa = sliceBits(tmpByte, 5,1);
    //truncated
    // 1 bit
    query.header.tc = sliceBits(tmpByte, 6,1);
    //recursion desired
    // 1 bit
    query.header.rd = sliceBits(tmpByte, 7,1);

    //slice out a byte to dice into binary
    tmpSlice = req.slice(3,4);
    //convert the binary buf into a string and then pull the char code
    //for the byte
    tmpByte = tmpSlice.toString('binary', 0, 1).charCodeAt(0);

    //recursion available
    // 1 bit
    query.header.ra = sliceBits(tmpByte, 0,1);

    //reserved 3 bits
    // rfc says always 0
    query.header.z = sliceBits(tmpByte, 1,3);

    //response code
    // 0 = no error, 1 = format error, 2 = server failure
    // 3 = name error, 4 = not implemented, 5 = refused
    // 6-15 reserved
    // 4 bits
    query.header.rcode = sliceBits(tmpByte, 4,4);

    //question count
    // 2 bytes
    query.header.qdcount = req.slice(4,6);
    //answer count
    // 2 bytes
    query.header.ancount = req.slice(6,8);
    //ns count
    // 2 bytes
    query.header.nscount = req.slice(8,10);
    //addition resources count
    // 2 bytes
    query.header.arcount = req.slice(10, 12);

    //assuming one question
    //qname is the sequence of domain labels
    //qname length is not fixed however it is 4
    //octets from the end of the buffer
    query.question.qname = req.slice(12, req.length - 4);
    //qtype
    query.question.qtype = req.slice(req.length - 4, req.length - 2);
    //qclass
    query.question.qclass = req.slice(req.length - 2, req.length);

    return query;
};

var createResponse = function(query) {
    var response = {};
    response.header = {};

    //1 byte
    response.header.id = query.header.id;//same as query id

    //combined 1 byte
    response.header.qr = 1; //this is a response
    response.header.opcode = 0; //standard for now TODO: add other types 4-bit!
    response.header.aa = 0; //authority... TODO this should be modal
    response.header.tc = 0; //truncation
    response.header.rd = 1; //recursion asked for

    //combined 1 byte
    response.header.ra = 1; //no rescursion here TODO
    response.header.z = 0; // spec says this MUST always be 0. 3bit
    response.header.rcode = 0; //TODO add error codes 4 bit.

    //1 byte
    response.header.qdcount = 1; //1 question
    //1 byte
    response.header.ancount = 2; //1 answer TODO support multiple Qs/As
    //1 byte
    response.header.nscount = 0;
    //1 byte
    response.header.arcount = 0;

    response.question = {};
    response.question.qname = query.question.qname;
    response.question.qtype = query.question.qtype;
    response.question.qclass = query.question.qclass;

    response.rr = [];

    response.rr[0] = {}; // TODO should be an array or something
    response.rr[0].qname = query.question.qname;
    response.rr[0].qtype = query.question.qtype;
    response.rr[0].qclass = query.question.qclass;
    response.rr[0].ttl = 1;
    response.rr[0].rdlength = 4; //assuming a record ip addy
    response.rr[0].rdata = 0x7F000001 // 127.0.0.1 TODO encoding method

    response.rr[1] = {}; // TODO should be an array or something
    response.rr[1].qname = query.question.qname;
    response.rr[1].qtype = query.question.qtype;
    response.rr[1].qclass = query.question.qclass;
    response.rr[1].ttl = 1;
    response.rr[1].rdlength = 4; //assuming a record ip addy
    response.rr[1].rdata = 0x7F000001 // 127.0.0.1 TODO encoding method

    //TODO compression

    //TODO output to Buffer
    var buf = buildResponseBuffer(response);

    return buf;
};

var domainToQname = function(domain) {
    var tokens = domain.split(".");
    len = domain.length + 2;
    var qname = new Buffer(len);
    var offset = 0;
    for(var i=0; i<tokens.length;i++) {
        qname[offset]=tokens[i].length;
        offset++;
        for(var j=0;j<tokens[i].length;j++) {
            qname[offset] = tokens[i].toCharCode(j);
            offset++;
        }
    }
    qname[offset] = 0;

    return qname;
};

var getZeroBuf = function(len) {
    buf = new Buffer(len);
    for(var i=0;i<buf.length;i++) { buf[i]=0;}
    return buf;
}

var buildResponseBuffer = function(response) {
    //calculate len in octets
    //NB not calculating rr this is done later
    //headers(12) + qname(qname + 2 + 2)
    //e.g. 16 + 2 * qname;
    //qnames are Buffers so length is already in octs
    var qnameLen = response.question.qname.length;
    var len = 16 + qnameLen;
    var buf = getZeroBuf(len);

    response.header.id.copy(buf, 0, 0, 2);

    buf[2] = 0x00 | response.header.qr << 7 | response.header.opcode << 3 | response.header.aa << 2 | response.header.tc << 1 | response.header.rd;

    buf[3] = 0x00 | response.header.ra << 7 | response.header.z << 4 | response.header.rcode;

    numToBuffer(buf, 4, response.header.qdcount, 2);

    numToBuffer(buf, 6, response.header.ancount, 2);
    numToBuffer(buf, 8, response.header.nscount, 2);
    numToBuffer(buf, 10, response.header.arcount, 2);

    //end header

    response.question.qname.copy(buf, 12, 0, qnameLen);
    response.question.qtype.copy(buf, 12+qnameLen, response.question.qtype, 2);
    response.question.qclass.copy(buf, 12+qnameLen+2, response.question.qclass, 2);

    var rrStart = 12+qnameLen+4;

    for (var i=0;i<response.rr.length;i++) {
        //TODO figure out if this is actually cheaper than just iterating
        //over the rr section up front and counting before creating buf
        //
        //create a new buffer to hold the request plus the rr
        //len of each response is 14 bytes of stuff + qname len
        var tmpBuf = getZeroBuf(buf.length + response.rr[i].qname.length + 14);

        buf.copy(tmpBuf, 0, 0, buf.length);

        response.rr[i].qname.copy(tmpBuf, rrStart, 0, response.rr[i].qname.length);
        response.rr[i].qtype.copy(tmpBuf, rrStart+response.rr[i].qname.length, response.rr[i].qtype, 2);
        response.rr[i].qclass.copy(tmpBuf, rrStart+response.rr[i].qname.length+2, response.rr[i].qclass, 2);

        numToBuffer(tmpBuf, rrStart+response.rr[i].qname.length+4, response.rr[i].ttl, 4);
        numToBuffer(tmpBuf, rrStart+response.rr[i].qname.length+8, response.rr[i].rdlength, 2);
        numToBuffer(tmpBuf, rrStart+response.rr[i].qname.length+10, response.rr[i].rdata, response.rr[i].rdlength); // rdlength indicates rdata length

        rrStart = rrStart + response.rr[i].qname.length + 14;

        buf = tmpBuf;
    }

    return buf;
};

//take a number and make sure it's written to the buffer as
//the correct length of bytes with leading 0 padding where necessary
// takes buffer, offset, number, length in bytes to insert
var numToBuffer = function(buf, offset, num, len, debug) {
    if (typeof num != "number") {
        throw "Num must be a number";
    }

    for (var i=offset;i<offset+len;i++) {

            var shift = 8*((len - 1) - (i - offset));

            var insert = (num >> shift) & 255;

            buf[i] = insert;
    }

    return buf;
}

server.addListener("error", function (e) {
  throw e;
});

server.bind(port, host);
console.log("Started server on " + host + ":" + port);<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { browserHistory } from 'react-router';
import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
import Documents from '../../api/documents/documents';
import container from '../../modules/container';

const handleNav = _id => browserHistory.push(`/documents/${_id}`);

const DocumentsList = ({ documents }) => (
  documents.length > 0 ? <ListGroup className="DocumentsList">
    {documents.map(({ _id, title, released, rating }) => (
      <ListGroupItem key={ _id } onClick={ () => handleNav(_id) }>
        { title } { released } [{ rating }]
      </ListGroupItem>
    ))}
  </ListGroup> :
  <Alert bsStyle="warning">No documents yet.</Alert>
);

DocumentsList.propTypes = {
  documents: PropTypes.array,
};

export default container((props, onData) => {
  const subscription = Meteor.subscribe('documents.list');
  if (subscription.ready()) {
    const documents = Documents.find().fetch();
    onData(null, { documents });
  }
}, DocumentsList);
<commit_msg>Sort movies list by released year<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { browserHistory } from 'react-router';
import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
import Documents from '../../api/documents/documents';
import container from '../../modules/container';

const handleNav = _id => browserHistory.push(`/documents/${_id}`);

const DocumentsList = ({ documents }) => (
  documents.length > 0 ? <ListGroup className="DocumentsList">
    {documents.map(({ _id, title, released, rating }) => (
      <ListGroupItem key={ _id } onClick={ () => handleNav(_id) }>
        { title } { released } [{ rating }]
      </ListGroupItem>
    ))}
  </ListGroup> :
  <Alert bsStyle="warning">No documents yet.</Alert>
);

DocumentsList.propTypes = {
  documents: PropTypes.array,
};

export default container((props, onData) => {
  const subscription = Meteor.subscribe('documents.list');
  if (subscription.ready()) {
    const documents = Documents.find({},{sort:{released:-1}}).fetch();
    onData(null, { documents });
  }
}, DocumentsList);
<|endoftext|>


<commit_before>/*
   This file is part of Rogue Vison.

   Copyright (C) 2016 Daniel Reischl, Rene Rathmann, Peter Tan,
       Tobias Dorsch, Shefali Shukla, Vignesh Govindarajulu,
       Aleksander Penew, Abinav Puri

   ReqTracker is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   ReqTracker is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PUROSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with Rogue Vison.  If not, see <http://www.gnu.org/licenses/>.
*/

/* This file contains all Angualr JS Services*/

angular.module('app')

/* The carrierService, proved carrier data to all controllers
For now it is used to saves the carriers for comparison, chosen by the user and proved them to all controller
who need the data.
*/

.service('carrierService', function() {
    var carriersForComparison = [];

    // function adds a carrier with a given ID
    this.addCarrier = function(newCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == newCarrier) {
                return false;
             }
        }
        carriersForComparison.push({carrierNumber: newCarrier});
        return true;
    };

    // returns the array with CarrierIDs to be compared
    this.getCarrier = function(){
        return carriersForComparison;
    }

    // deletes a carrier with a given ID
    this.deleteCarrier = function(removeCarrier) {
         var toDelete =  carriersForComparison.indexOf(removeCarrier);
         carriersForComparison.splice(toDelete,1);
    }

    // this function empties the array, so that no carrier item is left inside anymore.
    this.emptyCarrierArray = function() {
        carriersForComparison.splice(0,carriersForComparison.length);
    }

     // this service returns 4 functions to the caller, which he can use.
    return {
        addCarrier: this.addCarrier,
        getCarrier: this.getCarrier,
        deleteCarrier: this.deleteCarrier,
        emptyCarrierArray: this.emptyCarrierArray,
    };
});

<commit_msg>Fixed a bug for removing carriers<commit_after>/*
   This file is part of Rogue Vison.

   Copyright (C) 2016 Daniel Reischl, Rene Rathmann, Peter Tan,
       Tobias Dorsch, Shefali Shukla, Vignesh Govindarajulu,
       Aleksander Penew, Abinav Puri

   ReqTracker is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   ReqTracker is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PUROSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with Rogue Vison.  If not, see <http://www.gnu.org/licenses/>.
*/

/* This file contains all Angualr JS Services*/

angular.module('app')

/* The carrierService, proved carrier data to all controllers
For now it is used to saves the carriers for comparison, chosen by the user and proved them to all controller
who need the data.
*/

.service('carrierService', function() {
    var carriersForComparison = [];

    // function adds a carrier with a given ID
    this.addCarrier = function(newCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == newCarrier) {
                return false;
             }
        }
        carriersForComparison.push({carrierNumber: newCarrier});
        return true;
    };

    // returns the array with CarrierIDs to be compared
    this.getCarrier = function(){
        return carriersForComparison;
    }

    // deletes a carrier with a given ID
    this.deleteCarrier = function(removeCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == removeCarrier) {
                carriersForComparison.splice(i,1);
                return true;
            }
        }
        return false;
    }

    // this function empties the array, so that no carrier item is left inside anymore.
    this.emptyCarrierArray = function() {
        carriersForComparison.splice(0,carriersForComparison.length);
    }

     // this service returns 4 functions to the caller, which he can use.
    return {
        hasCarrier: this.hasCarrier,
        addCarrier: this.addCarrier,
        getCarrier: this.getCarrier,
        deleteCarrier: this.deleteCarrier,
        emptyCarrierArray: this.emptyCarrierArray,
    };
});

<|endoftext|>


<commit_before>
var Class = require('../../../utils/Class');
var GameObject = require('../../GameObject');
var Components = require('../../components');
var CanvasPool = require('../../../display/canvas/CanvasPool');
var TextRender = require('./TextRender');
var TextStyle = require('../TextStyle');
var GetTextSize = require('../GetTextSize');

var Text = new Class({

    Extends: GameObject,

    Mixins: [
        Components.Alpha,
        Components.BlendMode,
        Components.Flip,
        Components.GetBounds,
        Components.Origin,
        Components.RenderTarget,
        Components.ScaleMode,
        Components.ScrollFactor,
        Components.Tint,
        Components.Transform,
        Components.Visible,
        TextRender
    ],

    initialize:

    function Text (scene, x, y, text, style)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = 0; }
        if (text === undefined) { text = ''; }

        //  Cast to string whatever our value may be (numeric, etc)
        text = text.toString();

        GameObject.call(this, scene, 'Text');

        this.setPosition(x, y);
        this.setOrigin(0, 0);

        /**
         * @property {HTMLCanvasElement} canvas - The canvas element that the text is rendered.
         */
        this.canvas = CanvasPool.create(this);

        /**
         * @property {HTMLCanvasElement} context - The context of the canvas element that the text is rendered to.
         */
        this.context = this.canvas.getContext('2d');

        this.style = new TextStyle(this, style);

        this.autoRound = true;

        /**
         * The Regular Expression that is used to split the text up into lines, in
         * multi-line text. By default this is `/(?:\r\n|\r|\n)/`.
         * You can change this RegExp to be anything else that you may need.
         * @property {Object} splitRegExp
         */
        this.splitRegExp = /(?:\r\n|\r|\n)/;

        this.text = (Array.isArray(text)) ? text.join('\n') : text;

        this.resolution = 1;

        /**
        * Specify a padding value which is added to the line width and height when calculating the Text size.
        * Allows you to add extra spacing if Phaser is unable to accurately determine the true font dimensions.
        * @property {Phaser.Point} padding
        */
        this.padding = { x: 0, y: 0 };

        this.width = 1;
        this.height = 1;

        this.canvasTexture = null;
        this.dirty = false;

        if (text !== '')
        {
            this.updateText();
        }

        var _this = this;

        scene.sys.game.renderer.addContextRestoredCallback(function ()
        {
            _this.canvasTexture = null;
            _this.dirty = true;
        });
    },

    setText: function (value)
    {
        if (Array.isArray(value))
        {
            value = value.join('\n');
        }

        if (value !== this.text)
        {
            this.text = value.toString();

            this.updateText();
        }

        return this;
    },

    setStyle: function (style)
    {
        return this.style.setStyle(style);
    },

    setFont: function (font)
    {
        return this.style.setFont(font);
    },

    setFixedSize: function (width, height)
    {
        return this.style.setFixedSize(width, height);
    },

    setBackgroundColor: function (color)
    {
        return this.style.setBackgroundColor(color);
    },

    setFill: function (color)
    {
        return this.style.setFill(color);
    },

    setStroke: function (color, thickness)
    {
        return this.style.setStroke(color, thickness);
    },

    setShadow: function (x, y, color, blur, shadowStroke, shadowFill)
    {
        return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill);
    },

    setShadowOffset: function (x, y)
    {
        return this.style.setShadowOffset(x, y);
    },

    setShadowColor: function (color)
    {
        return this.style.setShadowColor(color);
    },

    setShadowBlur: function (blur)
    {
        return this.style.setShadowBlur(blur);
    },

    setShadowStroke: function (enabled)
    {
        return this.style.setShadowStroke(enabled);
    },

    setShadowFill: function (enabled)
    {
        return this.style.setShadowFill(enabled);
    },

    setAlign: function (align)
    {
        return this.style.setAlign(align);
    },

    setMaxLines: function (max)
    {
        return this.style.setMaxLines(max);
    },

    updateText: function ()
    {
        var canvas = this.canvas;
        var context = this.context;
        var style = this.style;
        var size = style.metrics;

        var outputText = this.text;

        // if (style.wordWrap)
        // {
        //     outputText = this.runWordWrap(this.text);
        // }

        //  Split text into lines
        var lines = outputText.split(this.splitRegExp);

        var textSize = GetTextSize(this, size, lines);

        if (!style.fixedWidth)
        {
            this.width = textSize.width;
        }

        if (!style.fixedHeight)
        {
            this.height = textSize.height;
        }

        this.updateDisplayOrigin();

        var padding = this.padding;

        var w = (textSize.width + (padding.x * 2)) * this.resolution;
        var h = (textSize.height + (padding.y * 2)) * this.resolution;

        if (canvas.width !== w || canvas.height !== h)
        {
            canvas.width = w;
            canvas.height = h;
        }
        else
        {
            context.clearRect(0, 0, w, h);
        }

        if (style.backgroundColor)
        {
            context.fillStyle = style.backgroundColor;
            context.fillRect(0, 0, w, h);
        }

        style.syncFont(canvas, context);

        context.textBaseline = 'alphabetic';

        //  Apply padding
        context.translate(padding.x, padding.y);

        var linePositionX;
        var linePositionY;

        //  Draw text line by line
        for (var i = 0; i < textSize.lines; i++)
        {
            linePositionX = style.strokeThickness / 2;
            linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent;

            if (i > 0)
            {
                linePositionY += (textSize.lineSpacing * i);
            }

            if (style.align === 'right')
            {
                linePositionX += textSize.width - textSize.lineWidths[i];
            }
            else if (style.align === 'center')
            {
                linePositionX += (textSize.width - textSize.lineWidths[i]) / 2;
            }

            if (this.autoRound)
            {
                linePositionX = Math.round(linePositionX);
                linePositionY = Math.round(linePositionY);
            }

            if (style.strokeThickness)
            {
                this.style.syncShadow(context, style.shadowStroke);

                context.strokeText(lines[i], linePositionX, linePositionY);
            }

            if (style.fill)
            {
                this.style.syncShadow(context, style.shadowFill);

                context.fillText(lines[i], linePositionX, linePositionY);
            }
        }

        this.dirty = true;

        return this;
    },

    getTextMetrics: function ()
    {
        return this.style.getTextMetrics();
    },

    toJSON: function ()
    {
        var out = Components.ToJSON(this);

        //  Extra Text data is added here

        var data = {
            autoRound: this.autoRound,
            text: this.text,
            style: this.style.toJSON(),
            resolution: this.resolution,
            padding: {
                x: this.padding.x,
                y: this.padding.y
            }
        };

        out.data = data;

        return out;
    }
});

module.exports = Text;
<commit_msg>Fixed issue where an array passed in the constructor wasn't properly displayed<commit_after>
var Class = require('../../../utils/Class');
var GameObject = require('../../GameObject');
var Components = require('../../components');
var CanvasPool = require('../../../display/canvas/CanvasPool');
var TextRender = require('./TextRender');
var TextStyle = require('../TextStyle');
var GetTextSize = require('../GetTextSize');

var Text = new Class({

    Extends: GameObject,

    Mixins: [
        Components.Alpha,
        Components.BlendMode,
        Components.Flip,
        Components.GetBounds,
        Components.Origin,
        Components.RenderTarget,
        Components.ScaleMode,
        Components.ScrollFactor,
        Components.Tint,
        Components.Transform,
        Components.Visible,
        TextRender
    ],

    initialize:

    function Text (scene, x, y, text, style)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = 0; }

        GameObject.call(this, scene, 'Text');

        this.setPosition(x, y);
        this.setOrigin(0, 0);

        /**
         * @property {HTMLCanvasElement} canvas - The canvas element that the text is rendered.
         */
        this.canvas = CanvasPool.create(this);

        /**
         * @property {HTMLCanvasElement} context - The context of the canvas element that the text is rendered to.
         */
        this.context = this.canvas.getContext('2d');

        this.style = new TextStyle(this, style);

        this.autoRound = true;

        /**
         * The Regular Expression that is used to split the text up into lines, in
         * multi-line text. By default this is `/(?:\r\n|\r|\n)/`.
         * You can change this RegExp to be anything else that you may need.
         * @property {Object} splitRegExp
         */
        this.splitRegExp = /(?:\r\n|\r|\n)/;

        //  This is populated in this.setText
        this.text = '';

        this.resolution = 1;

        /**
        * Specify a padding value which is added to the line width and height when calculating the Text size.
        * Allows you to add extra spacing if Phaser is unable to accurately determine the true font dimensions.
        * @property {Phaser.Point} padding
        */
        this.padding = { x: 0, y: 0 };

        this.width = 1;
        this.height = 1;

        this.canvasTexture = null;
        this.dirty = false;

        this.setText(text);

        var _this = this;

        scene.sys.game.renderer.addContextRestoredCallback(function ()
        {
            _this.canvasTexture = null;
            _this.dirty = true;
        });
    },

    setText: function (value)
    {
        if (Array.isArray(value))
        {
            value = value.join('\n');
        }

        if (value !== this.text)
        {
            this.text = value.toString();

            this.updateText();
        }

        return this;
    },

    setStyle: function (style)
    {
        return this.style.setStyle(style);
    },

    setFont: function (font)
    {
        return this.style.setFont(font);
    },

    setFixedSize: function (width, height)
    {
        return this.style.setFixedSize(width, height);
    },

    setBackgroundColor: function (color)
    {
        return this.style.setBackgroundColor(color);
    },

    setFill: function (color)
    {
        return this.style.setFill(color);
    },

    setStroke: function (color, thickness)
    {
        return this.style.setStroke(color, thickness);
    },

    setShadow: function (x, y, color, blur, shadowStroke, shadowFill)
    {
        return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill);
    },

    setShadowOffset: function (x, y)
    {
        return this.style.setShadowOffset(x, y);
    },

    setShadowColor: function (color)
    {
        return this.style.setShadowColor(color);
    },

    setShadowBlur: function (blur)
    {
        return this.style.setShadowBlur(blur);
    },

    setShadowStroke: function (enabled)
    {
        return this.style.setShadowStroke(enabled);
    },

    setShadowFill: function (enabled)
    {
        return this.style.setShadowFill(enabled);
    },

    setAlign: function (align)
    {
        return this.style.setAlign(align);
    },

    setMaxLines: function (max)
    {
        return this.style.setMaxLines(max);
    },

    updateText: function ()
    {
        var canvas = this.canvas;
        var context = this.context;
        var style = this.style;
        var size = style.metrics;

        var outputText = this.text;

        // if (style.wordWrap)
        // {
        //     outputText = this.runWordWrap(this.text);
        // }

        //  Split text into lines
        var lines = outputText.split(this.splitRegExp);

        var textSize = GetTextSize(this, size, lines);

        if (!style.fixedWidth)
        {
            this.width = textSize.width;
        }

        if (!style.fixedHeight)
        {
            this.height = textSize.height;
        }

        this.updateDisplayOrigin();

        var padding = this.padding;

        var w = (textSize.width + (padding.x * 2)) * this.resolution;
        var h = (textSize.height + (padding.y * 2)) * this.resolution;

        if (canvas.width !== w || canvas.height !== h)
        {
            canvas.width = w;
            canvas.height = h;
        }
        else
        {
            context.clearRect(0, 0, w, h);
        }

        if (style.backgroundColor)
        {
            context.fillStyle = style.backgroundColor;
            context.fillRect(0, 0, w, h);
        }

        style.syncFont(canvas, context);

        context.textBaseline = 'alphabetic';

        //  Apply padding
        context.translate(padding.x, padding.y);

        var linePositionX;
        var linePositionY;

        //  Draw text line by line
        for (var i = 0; i < textSize.lines; i++)
        {
            linePositionX = style.strokeThickness / 2;
            linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent;

            if (i > 0)
            {
                linePositionY += (textSize.lineSpacing * i);
            }

            if (style.align === 'right')
            {
                linePositionX += textSize.width - textSize.lineWidths[i];
            }
            else if (style.align === 'center')
            {
                linePositionX += (textSize.width - textSize.lineWidths[i]) / 2;
            }

            if (this.autoRound)
            {
                linePositionX = Math.round(linePositionX);
                linePositionY = Math.round(linePositionY);
            }

            if (style.strokeThickness)
            {
                this.style.syncShadow(context, style.shadowStroke);

                context.strokeText(lines[i], linePositionX, linePositionY);
            }

            if (style.fill)
            {
                this.style.syncShadow(context, style.shadowFill);

                context.fillText(lines[i], linePositionX, linePositionY);
            }
        }

        this.dirty = true;

        return this;
    },

    getTextMetrics: function ()
    {
        return this.style.getTextMetrics();
    },

    toJSON: function ()
    {
        var out = Components.ToJSON(this);

        //  Extra Text data is added here

        var data = {
            autoRound: this.autoRound,
            text: this.text,
            style: this.style.toJSON(),
            resolution: this.resolution,
            padding: {
                x: this.padding.x,
                y: this.padding.y
            }
        };

        out.data = data;

        return out;
    }
});

module.exports = Text;
<|endoftext|>


<commit_before>import {Store} from 'flummox';
import _m from 'mori';
import {Pending, Failed} from 'common/src/fetch-result';

class FullstopStore extends Store {
    constructor(flux) {
        super();

        const fullstopActions = flux.getActions('fullstop');

        this._empty();

        this.register(
            fullstopActions.deleteViolations,
            this.deleteViolations);

        this.registerAsync(
            fullstopActions.fetchViolations,
            this.beginFetchViolations,
            this.receiveViolations,
            this.failFetchViolations);

        this.registerAsync(
            fullstopActions.fetchViolation,
            this.beginFetchViolation,
            this.receiveViolation,
            this.failFetchViolation);

        this.registerAsync(
            fullstopActions.resolveViolation,
            this.beginFetchViolation,
            this.receiveViolation,
            this.failFetchViolation);
    }

    beginFetchViolations() {
        this.setState({
            pagingInfo: _m.toClj({
                last: true
            })
        });
    }
    failFetchViolations() { }
    beginFetchViolation(violationId) {
        this.setState({
            violations: _m.assoc(this.state.violations, String(violationId), new Pending())
        });
    }
    failFetchViolation(err) {
        this.setState({
            violations: _m.assoc(this.state.violations, String(err.violationId), new Failed(err))
        });
    }

    receiveViolation(violation) {
        this.receiveViolations([undefined, [violation]]);
    }

    receiveViolations([metadata, violations]) {
        let all = violations.reduce(
                            (coll, v) => {
                                v.timestamp = Date.parse(v.created) || 0;
                                return _m.assoc(coll, String(v.id), _m.toClj(v));
                            },
                            this.state.violations);
        this.setState({
            violations: all,
            pagingInfo: metadata ?
                            _m.toClj({
                                last: metadata.last
                            }) :
                            this.state.pagingInfo
        });
    }

    deleteViolations() {
        this.setState({
            violations: _m.hashMap()
        });
    }

    getPagingInfo() {
        return _m.toJs(this.state.pagingInfo);
    }

    getViolation(violationId) {
        return _m.toJs(_m.get(this.state.violations, String(violationId)));
    }

    getViolations(accounts, resolved) {
        let violations = _m.vals(this.state.violations);
        // collect violations from accounts
        if (accounts) {
            violations = _m.filter(v => accounts.indexOf(_m.get(v, 'account_id')) >= 0, violations);
        }

        // filter by resolution
        if (resolved === true) {
            violations = _m.filter(v => _m.get(v, 'comment') !== null, violations);
        } else if (resolved === false) {
            violations = _m.filter(v => _m.get(v, 'comment') === null, violations);
        }
        violations = _m.sortBy(v => _m.get(v, 'timestamp'), violations);
        return _m.toJs(violations);
    }

    _empty() {
        this.setState({
            violations: _m.hashMap(),
            pagingInfo: _m.toClj({
                last: true
            })
        });
    }
}

export default FullstopStore;
<commit_msg>#256 transition fullstop store to immutablejs<commit_after>import {Store} from 'flummox';
import Immutable from 'immutable';
import {Pending, Failed} from 'common/src/fetch-result';

class FullstopStore extends Store {
    constructor(flux) {
        super();

        const fullstopActions = flux.getActions('fullstop');

        this._empty();

        this.register(
            fullstopActions.deleteViolations,
            this.deleteViolations);

        this.registerAsync(
            fullstopActions.fetchViolations,
            this.beginFetchViolations,
            this.receiveViolations,
            this.failFetchViolations);

        this.registerAsync(
            fullstopActions.fetchViolation,
            this.beginFetchViolation,
            this.receiveViolation,
            this.failFetchViolation);

        this.registerAsync(
            fullstopActions.resolveViolation,
            this.beginFetchViolation,
            this.receiveViolation,
            this.failFetchViolation);
    }

    beginFetchViolations() {
        this.setState({
            pagingInfo: Immutable.Map({
                last: true
            })
        });
    }
    failFetchViolations() { }
    beginFetchViolation(violationId) {
        this.setState({
            violations: this.state.violations.set(String(violationId), new Pending())
        });
    }
    failFetchViolation(err) {
        this.setState({
            violations: this.state.violations.set(String(err.violationId), new Failed(err))
        });
    }

    receiveViolation(violation) {
        this.receiveViolations([undefined, [violation]]);
    }

    receiveViolations([metadata, violations]) {
        let all = violations.reduce(
                            (coll, v) => {
                                v.timestamp = Date.parse(v.created) || 0;
                                return coll.set(String(v.id), Immutable.fromJS(v));
                            },
                            this.state.violations);
        this.setState({
            violations: all,
            pagingInfo: metadata ?
                            Immutable.Map({
                                last: metadata.last
                            }) :
                            this.state.pagingInfo
        });
    }

    deleteViolations() {
        this.setState({
            violations: Immutable.Map()
        });
    }

    getPagingInfo() {
        return this.state.pagingInfo.toJS();
    }

    getViolation(violationId) {
        let violation = this.state.violations.get(String(violationId));
        return violation ? violation.toJS() : false;
    }

    getViolations(accounts, resolved) {
        let violations = this.state.violations.valueSeq();
        // collect violations from accounts
        if (accounts) {
            violations = violations.filter(v => accounts.indexOf(v.get('account_id')) >= 0);
        }

        // filter by resolution
        if (resolved === true) {
            violations = violations.filter(v => v.get('comment') !== null);
        } else if (resolved === false) {
            violations = violations.filter(v => v.get('comment') === null);
        }
        return violations
                .sortBy(v => v.get('timestamp'))
                .toJS();
    }

    _empty() {
        this.setState({
            violations: Immutable.Map(),
            pagingInfo: Immutable.fromJS({
                last: true
            })
        });
    }
}

export default FullstopStore;
<|endoftext|>