<commit_before>var BufferList = require("bl"),
    stream = require("readable-stream");

var Dissolve = module.exports = function Dissolve(options) {
  if (!(this instanceof Dissolve)) { return new Dissolve(options); }

  if (!options) {
    options = {};
  }

  if (!options.hasOwnProperty('objectMode')) {
    options.objectMode = true;
  }

  stream.Transform.call(this, options);

  this.jobs = [];
  this.vars = Object.create(null);
  this.vars_list = [];

  this._buffer = new BufferList();
};
Dissolve.prototype = Object.create(stream.Transform.prototype, {constructor: {value: Dissolve}});

Dissolve.prototype._job_down = function _job_down(job) {
  var tmp = this.vars;
  this.vars_list.push(tmp);
  this.vars = tmp[job.into] = Object.create(tmp);
};

Dissolve.prototype._job_up = function _job_up() {
  this.vars.__proto__ = null;
  this.vars = this.vars_list.pop();
};

Dissolve.prototype._exec_down = function _exec_down(job) {
  this.jobs.shift();
  this._job_down(job);
};

Dissolve.prototype._exec_up = function _exec_up(job) {
  this.jobs.shift();
  this._job_up();
};

Dissolve.prototype._exec_tap = function _exec_tap(job) {
  this.jobs.shift();

  var jobs = this.jobs;

  this.jobs = [];

  if (job.name) {
    this.jobs.push({type: "down", into: job.name});
    this.jobs.push({type: "tap", args: job.args, fn: job.fn});
    this.jobs.push({type: "up"});
  } else {
    job.fn.apply(this, job.args || []);
  }

  Array.prototype.push.apply(this.jobs, jobs);
};

Dissolve.prototype._exec_loop = function _exec_loop(job) {
  if (job.finished) {
    this.jobs.shift();
    return;
  }

  var jobs = this.jobs;
  this.jobs = [];

  if (job.name) {
    if (typeof this.vars[job.name] === "undefined") {
      this.vars[job.name] = [];
    }

    // private scope so _job doesn't get redefined later
    (function() {
      var _job = job;

      this.jobs.push({
        type: "tap",
        name: "__loop_temp",
        args: [job.finish],
        fn: job.fn,
      });

      this.jobs.push({
        type: "tap",
        fn: function() {
          if (!_job.cancelled) {
            this.vars[_job.name].push(this.vars.__loop_temp);
          }

          delete this.vars.__loop_temp;
        },
      });
    }).call(this);
  } else {
    this.jobs.push({
      type: "tap",
      args: [job.finish],
      fn: job.fn,
    });
  }
  Array.prototype.push.apply(this.jobs, jobs);
};

Dissolve.prototype._exec_string = function _exec_string(job, offset, length) {
  this.vars[job.name] = this._buffer.toString("utf8", offset, offset + length);
  this.jobs.shift();
};

Dissolve.prototype._exec_buffer = function _exec_buffer(job, offset, length) {
  this.vars[job.name] = this._buffer.slice(offset, offset+length);
  this.jobs.shift();
};

Dissolve.prototype._transform = function _transform(input, encoding, done) {
  var offset = 0;

  this._buffer.append(input);

  while (this.jobs.length) {
    var job = this.jobs[0];

    if (job.type === "down") {
      this._exec_down(job);
      continue;
    }

    if (job.type === "up") {
      this._exec_up(job);
      continue;
    }

    if (job.type === "tap") {
      this._exec_tap(job);
      continue;
    }

    if (job.type === "loop") {
      this._exec_loop(job);
      continue;
    }

    var length;
    if (typeof job.length === "string") {
      length = this.vars[job.length];
    } else {
      length = job.length;
    }

    if (this._buffer.length - offset < length) {
      break;
    }

    if (job.type === "buffer") {
      this._exec_buffer(job, offset, length);
      offset += length;
      continue;
    }

    if (job.type === "string") {
      this._exec_string(job, offset, length);
      offset += length;
      continue;
    }

    switch (job.type) {
      case "int8le":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
      case "uint8le": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
      case "int8be":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
      case "uint8be": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
      case "int16le":  { this.vars[job.name] = this._buffer.readInt16LE(offset);  break; }
      case "uint16le": { this.vars[job.name] = this._buffer.readUInt16LE(offset); break; }
      case "int16be":  { this.vars[job.name] = this._buffer.readInt16BE(offset);  break; }
      case "uint16be": { this.vars[job.name] = this._buffer.readUInt16BE(offset); break; }
      case "int32le":  { this.vars[job.name] = this._buffer.readInt32LE(offset);  break; }
      case "uint32le": { this.vars[job.name] = this._buffer.readUInt32LE(offset); break; }
      case "int32be":  { this.vars[job.name] = this._buffer.readInt32BE(offset);  break; }
      case "uint32be": { this.vars[job.name] = this._buffer.readUInt32BE(offset); break; }
      case "int64le":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32LE(offset + 4)) + ((this._buffer[offset + 4] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32LE(offset)); break; }
      case "uint64le": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32LE(offset + 4)) + this._buffer.readUInt32LE(offset); break; }
      case "int64be":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32BE(offset)) + ((this._buffer[offset] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32BE(offset + 4)); break; }
      case "uint64be": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32BE(offset)) + this._buffer.readUInt32BE(offset + 4); break; }
      case "floatle":  { this.vars[job.name] = this._buffer.readFloatLE(offset);  break; }
      case "floatbe":  { this.vars[job.name] = this._buffer.readFloatBE(offset);  break; }
      case "doublele": { this.vars[job.name] = this._buffer.readDoubleLE(offset); break; }
      case "doublebe": { this.vars[job.name] = this._buffer.readDoubleBE(offset); break; }
      default: { return done(new Error("invalid job type")); }
    }

    this.jobs.shift();

    offset += length;
  }

  this._buffer.consume(offset);

  if (this.jobs.length === 0) {
    this.push(null);
  }

  return done();
};

[["float", 4], ["double", 8]].forEach(function(t) {
  ["", "le", "be"].forEach(function(e) {
    var id = [t[0], e].join(""),
        type = [t[0], e || "le"].join(""),
        length = t[1];

    Dissolve.prototype[id] = function(name) {
      this.jobs.push({
        type: type,
        length: length,
        name: name,
      });

      return this;
    };
  });
});

[8, 16, 32, 64].forEach(function(b) {
  ["", "u"].forEach(function(s) {
    ["", "le", "be"].forEach(function(e) {
      var id = [s, "int", b, e].join(""),
          type = [s, "int", b, e || "le"].join(""),
          length = b / 8;

      Dissolve.prototype[id] = function(name) {
        this.jobs.push({
          type: type,
          length: length,
          name: name,
        });

        return this;
      };
    });
  });
});

["tap", "loop"].forEach(function(e) {
  Dissolve.prototype[e] = function(name, fn) {
    if (typeof name === "function") {
      fn = name;
      name = null;
    }

    var job = {
      type: e,
      name: name,
      fn: fn,
    };

    if (e === "loop") {
      job.finish = function(cancel) {
        job.finished = true;
        job.cancelled = !!cancel;
      };
    }

    this.jobs.push(job);

    return this;
  };
});

["buffer", "string"].forEach(function(e) {
  Dissolve.prototype[e] = function(name, length) {
    this.jobs.push({
      type: e,
      name: name,
      length: length,
    });

    return this;
  };
});
<commit_msg>skip() method<commit_after>var BufferList = require("bl"),
    stream = require("readable-stream");

var Dissolve = module.exports = function Dissolve(options) {
  if (!(this instanceof Dissolve)) { return new Dissolve(options); }

  if (!options) {
    options = {};
  }

  if (!options.hasOwnProperty('objectMode')) {
    options.objectMode = true;
  }

  stream.Transform.call(this, options);

  this.jobs = [];
  this.vars = Object.create(null);
  this.vars_list = [];

  this._buffer = new BufferList();
};
Dissolve.prototype = Object.create(stream.Transform.prototype, {constructor: {value: Dissolve}});

Dissolve.prototype._job_down = function _job_down(job) {
  var tmp = this.vars;
  this.vars_list.push(tmp);
  this.vars = tmp[job.into] = Object.create(tmp);
};

Dissolve.prototype._job_up = function _job_up() {
  this.vars.__proto__ = null;
  this.vars = this.vars_list.pop();
};

Dissolve.prototype._exec_down = function _exec_down(job) {
  this.jobs.shift();
  this._job_down(job);
};

Dissolve.prototype._exec_up = function _exec_up(job) {
  this.jobs.shift();
  this._job_up();
};

Dissolve.prototype._exec_tap = function _exec_tap(job) {
  this.jobs.shift();

  var jobs = this.jobs;

  this.jobs = [];

  if (job.name) {
    this.jobs.push({type: "down", into: job.name});
    this.jobs.push({type: "tap", args: job.args, fn: job.fn});
    this.jobs.push({type: "up"});
  } else {
    job.fn.apply(this, job.args || []);
  }

  Array.prototype.push.apply(this.jobs, jobs);
};

Dissolve.prototype._exec_loop = function _exec_loop(job) {
  if (job.finished) {
    this.jobs.shift();
    return;
  }

  var jobs = this.jobs;
  this.jobs = [];

  if (job.name) {
    if (typeof this.vars[job.name] === "undefined") {
      this.vars[job.name] = [];
    }

    // private scope so _job doesn't get redefined later
    (function() {
      var _job = job;

      this.jobs.push({
        type: "tap",
        name: "__loop_temp",
        args: [job.finish],
        fn: job.fn,
      });

      this.jobs.push({
        type: "tap",
        fn: function() {
          if (!_job.cancelled) {
            this.vars[_job.name].push(this.vars.__loop_temp);
          }

          delete this.vars.__loop_temp;
        },
      });
    }).call(this);
  } else {
    this.jobs.push({
      type: "tap",
      args: [job.finish],
      fn: job.fn,
    });
  }
  Array.prototype.push.apply(this.jobs, jobs);
};

Dissolve.prototype._exec_string = function _exec_string(job, offset, length) {
  this.vars[job.name] = this._buffer.toString("utf8", offset, offset + length);
  this.jobs.shift();
};

Dissolve.prototype._exec_buffer = function _exec_buffer(job, offset, length) {
  this.vars[job.name] = this._buffer.slice(offset, offset+length);
  this.jobs.shift();
};

Dissolve.prototype._transform = function _transform(input, encoding, done) {
  var offset = 0;

  this._buffer.append(input);

  while (this.jobs.length) {
    var job = this.jobs[0];

    if (job.type === "down") {
      this._exec_down(job);
      continue;
    }

    if (job.type === "up") {
      this._exec_up(job);
      continue;
    }

    if (job.type === "tap") {
      this._exec_tap(job);
      continue;
    }

    if (job.type === "loop") {
      this._exec_loop(job);
      continue;
    }

    var length;
    if (typeof job.length === "string") {
      length = this.vars[job.length];
    } else {
      length = job.length;
    }

    if (this._buffer.length - offset < length) {
      break;
    }

    if (job.type === "buffer") {
      this._exec_buffer(job, offset, length);
      offset += length;
      continue;
    }

    if (job.type === "string") {
      this._exec_string(job, offset, length);
      offset += length;
      continue;
    }

    if (job.type === "skip") {
      this.jobs.shift();

      offset += job.length;

      continue;
    }

    switch (job.type) {
      case "int8le":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
      case "uint8le": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
      case "int8be":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
      case "uint8be": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
      case "int16le":  { this.vars[job.name] = this._buffer.readInt16LE(offset);  break; }
      case "uint16le": { this.vars[job.name] = this._buffer.readUInt16LE(offset); break; }
      case "int16be":  { this.vars[job.name] = this._buffer.readInt16BE(offset);  break; }
      case "uint16be": { this.vars[job.name] = this._buffer.readUInt16BE(offset); break; }
      case "int32le":  { this.vars[job.name] = this._buffer.readInt32LE(offset);  break; }
      case "uint32le": { this.vars[job.name] = this._buffer.readUInt32LE(offset); break; }
      case "int32be":  { this.vars[job.name] = this._buffer.readInt32BE(offset);  break; }
      case "uint32be": { this.vars[job.name] = this._buffer.readUInt32BE(offset); break; }
      case "int64le":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32LE(offset + 4)) + ((this._buffer[offset + 4] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32LE(offset)); break; }
      case "uint64le": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32LE(offset + 4)) + this._buffer.readUInt32LE(offset); break; }
      case "int64be":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32BE(offset)) + ((this._buffer[offset] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32BE(offset + 4)); break; }
      case "uint64be": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32BE(offset)) + this._buffer.readUInt32BE(offset + 4); break; }
      case "floatle":  { this.vars[job.name] = this._buffer.readFloatLE(offset);  break; }
      case "floatbe":  { this.vars[job.name] = this._buffer.readFloatBE(offset);  break; }
      case "doublele": { this.vars[job.name] = this._buffer.readDoubleLE(offset); break; }
      case "doublebe": { this.vars[job.name] = this._buffer.readDoubleBE(offset); break; }
      default: { return done(new Error("invalid job type")); }
    }

    this.jobs.shift();

    offset += length;
  }

  this._buffer.consume(offset);

  if (this.jobs.length === 0) {
    this.push(null);
  }

  return done();
};

[["float", 4], ["double", 8]].forEach(function(t) {
  ["", "le", "be"].forEach(function(e) {
    var id = [t[0], e].join(""),
        type = [t[0], e || "le"].join(""),
        length = t[1];

    Dissolve.prototype[id] = function(name) {
      this.jobs.push({
        type: type,
        length: length,
        name: name,
      });

      return this;
    };
  });
});

[8, 16, 32, 64].forEach(function(b) {
  ["", "u"].forEach(function(s) {
    ["", "le", "be"].forEach(function(e) {
      var id = [s, "int", b, e].join(""),
          type = [s, "int", b, e || "le"].join(""),
          length = b / 8;

      Dissolve.prototype[id] = function(name) {
        this.jobs.push({
          type: type,
          length: length,
          name: name,
        });

        return this;
      };
    });
  });
});

["tap", "loop"].forEach(function(e) {
  Dissolve.prototype[e] = function(name, fn) {
    if (typeof name === "function") {
      fn = name;
      name = null;
    }

    var job = {
      type: e,
      name: name,
      fn: fn,
    };

    if (e === "loop") {
      job.finish = function(cancel) {
        job.finished = true;
        job.cancelled = !!cancel;
      };
    }

    this.jobs.push(job);

    return this;
  };
});

["buffer", "string"].forEach(function(e) {
  Dissolve.prototype[e] = function(name, length) {
    this.jobs.push({
      type: e,
      name: name,
      length: length,
    });

    return this;
  };
});

["skip"].forEach(function(e) {
  Dissolve.prototype[e] = function(length) {
    this.jobs.push({
      type: e,
      length: length,
    });

    return this;
  };
});
<|endoftext|>


<commit_before>'use strict';

var Url = require('url');
var type = require('utils-type');
var merge = require('utils-merge');

exports = module.exports = Parth;

function Parth(cache){

  if( !(this instanceof Parth) ){
    return new Parth(cache);
  }

  function parth(path, opts){
    return parth.set(path, opts);
  }
  merge(parth, this);

  parth.cache = type(cache).plainObject || { };
  parth.cache.paths = type(parth.cache.paths).array || [ ];
  parth.cache.regexp = type(parth.cache.regexp).array || [ ];
  parth.cache.masterRE = type(parth.cache.masterRE).array || [ ];

  return parth;
}

//----
// ## tokenize path
//  > use / and . to tokenize a path to an invariant
//----

Parth.prototype.tokenize = function(path, opt){
  var p = type(path).plainObject
    || { input : (type(path).string || '').trim() };
  // return early
  if(!p.input){ return null; } if(p.argv){ return p; }

  opt = type(opt).plainObject || { };
  opt.sep = type(opt.sep).regexp || /[\/\.]+/g;
  opt.param = type(opt.group).regexp || /\:(\w+)(\(.+?\))?/g;

  p.path = p.input;

  var url;
  if((url = p.input.match(/\/\S+/))){
    url = Url.parse(url[0]);
    if(url.hash){ p.hash = url.hash; }
    if(url.query){ p.query = url.search; }
    p.path = p.input.replace(url.path, url.pathname);
  }

  p.path = p.path
    .replace(new RegExp(opt.sep.source+'$'), '').trim();

  // use space as invariant sep token
  p.argv = p.path
    .replace(/\S+/g, function($0){
      var sep = $0.match(/[\/]+/) || $0.match(/[\.]/);
      $0.replace(opt.param, function($0, label, regexp){
        p.params = p.params || { };
        p.params[label] = regexp || '([^\\' +(sep || '/')+ ' ]+)';
      });
      if(!sep){ return $0; }  sep = '\\' + sep[0];
      return $0.replace(new RegExp(sep,'g'), ' ');
    }).trim().replace(/[ ]+/g, ' ');

  p.depth = p.argv.split(/[ ]/).length;

  // wipe
  url = null;
  return p;
};

//----
// ## parse path
//  > parse the path using previous tokens
//----

Parth.prototype.parse = function(path, opt){
  var p = this.tokenize(path, (opt = opt || { }));
  if(!p){ return null; }

  // parse regexp
  if(!p.regexp){

    opt.flag = type(opt.flag).string || 'i';
    p.regexp = p.path
      .replace(/\(.+?\)/, '')
      .replace(/\S+$/,
        function($0){ return $0 + ($0.match(opt.sep) || [' '])[0]; })
      .replace(opt.sep, '\\$&')
      .replace(/[ ]+/g, '[ ]+').replace(/\+$/,'')
      .replace(/\:(\w+)/g, function($0, label){ return p.params[label]; });

    p.regexp = new RegExp('^' + p.regexp + '?', opt.flag);
    return p;
  }

  // parse params for this.get
  p.params = { };

  var index = 0;
  var params = p.input
    .replace(p.query, '')
    .match(p.regexp).slice(1);

  p.path.replace(/\:(\w+)/g,
    function($0, label){
      return (p.params[label] = params[index++]);
    });

  return p;
};
//
// ## set a path
//
Parth.prototype.set = function(path, opt){
  var p = this.parse(path, (opt = opt || { }));
  if(!p){ return this; }

  var index, cache = this.cache;
  // check + prepare paths and regexes
  if(cache.regexp.length < p.depth+1){
    index = cache.regexp.length;
    while(index < p.depth+1){
      cache.paths.push([ ]);
      cache.regexp.push([ ]);
      index = cache.masterRE.push(null);
    }
  }

  // already in cache?
  if(cache.paths[p.depth].indexOf(p.path) > -1){
    p = method = index = null; // wipe
    return this;
  }

  // prepend for custom regexp, append for default
  var method = !(/\(.+?\)/).test(p.input) ? 'unshift' : 'push';
  cache.paths[p.depth][method](p.path);
  cache.regexp[p.depth][method](p.regexp);

  // adjust masterRE
  cache.masterRE[p.depth] =
    new RegExp(
      cache.regexp[p.depth]
        .map(function(regexp){ return regexp.source; })
        .join('|'),
    opt.flag);

  // wipe
  p = method = index = null;
  return this;
};

//
// ## get a previously set path
//

Parth.prototype.get = function(path, opt){
  var p = this.tokenize(path, (opt = opt || { }));
  if(!p.path){ return null; }

  var fallback = true;
  var index = 0, depth = p.depth;

  while(fallback){
    p.regexp = this.cache.masterRE[depth];
    fallback = !p.regexp && (this.cache.fallback || opt.fallback);
    if(!p.regexp || !p.regexp.test(p.input)){
      if(!fallback){ return null; }
      depth--; p.fallback = true;
    }
    if(depth < 0){ return null; }
  }

  p.regexp = this.cache.regexp[depth];
  while( !p.regexp[index].test(p.path) ){ index++; }
  p.regexp = this.cache.regexp[depth][index];
  p.path = this.cache.paths[depth][index];

  // wipe
  fallback = index = depth = null;
  return this.parse(p, opt);
};
<commit_msg>it really matters<commit_after>'use strict';

var Url = require('url');
var type = require('utils-type');
var merge = require('utils-merge');

exports = module.exports = Parth;

function Parth(cache){

  if( !(this instanceof Parth) ){
    return new Parth(cache);
  }

  function parth(path, opts){
    return parth.set(path, opts);
  }
  merge(parth, this);

  parth.cache = type(cache).plainObject || { };
  parth.cache.paths = type(parth.cache.paths).array || [ ];
  parth.cache.regexp = type(parth.cache.regexp).array || [ ];
  parth.cache.masterRE = type(parth.cache.masterRE).array || [ ];

  return parth;
}

//----
// ## tokenize path
//  > use / and . to tokenize a path to an invariant
//----

Parth.prototype.tokenize = function(path, opt){
  var p = type(path).plainObject
    || { input : (type(path).string || '').trim() };
  // return early
  if(!p.input){ return null; } if(p.argv){ return p; }

  opt = type(opt).plainObject || { };
  opt.sep = type(opt.sep).regexp || /[\/\.]+/g;
  opt.param = type(opt.group).regexp || /\:(\w+)(\(.+?\))?/g;

  p.path = p.input;

  var url;
  if((url = p.input.match(/\/\S+/))){
    url = Url.parse(url[0]);
    if(url.hash){ p.hash = url.hash; }
    if(url.query){ p.query = url.search; }
    p.path = p.input.replace(url.path, url.pathname);
  }

  p.path = p.path
    .replace(new RegExp(opt.sep.source+'$'), '').trim();

  // use space as invariant sep token
  p.argv = p.path
    .replace(/\S+/g, function($0){
      var sep = $0.match(/[\/]+/) || $0.match(/[\.]/);
      $0.replace(opt.param, function($0, label, regexp){
        p.params = p.params || { };
        p.params[label] = regexp || '([^\\' +(sep || '/')+ ' ]+)';
      });
      if(!sep){ return $0; }  sep = '\\' + sep[0];
      return $0.replace(new RegExp(sep,'g'), ' ');
    }).trim().replace(/[ ]+/g, ' ');

  p.depth = p.argv.split(/[ ]/).length;

  // wipe
  url = null;
  return p;
};

//----
// ## parse path
//  > parse the path using previous tokens
//----

Parth.prototype.parse = function(path, opt){
  var p = this.tokenize(path, (opt = opt || { }));
  if(!p){ return null; }

  // parse regexp
  if(!p.regexp){

    opt.flag = type(opt.flag).string || 'i';
    p.regexp = p.path
      .replace(/\(.+?\)/, '')
      .replace(/\S+$/,
        function($0){ return $0 + ($0.match(opt.sep) || [' '])[0]; })
      .replace(opt.sep, '\\$&')
      .replace(/[ ]+/g, '[ ]+').replace(/\+$/,'')
      .replace(/\:(\w+)/g, function($0, label){ return p.params[label]; });

    p.regexp = new RegExp('^' + p.regexp + '?', opt.flag);
    return p;
  }

  // parse params for this.get
  p.params = { };

  var index = 0;
  var params = p.input
    .replace(p.query, '')
    .match(p.regexp).slice(1);

  p.path.replace(/\:(\w+)/g,
    function($0, label){
      return (p.params[label] = params[index++]);
    });

  return p;
};
//
// ## set a path
//
Parth.prototype.set = function(path, opt){
  var p = this.parse(path, (opt = opt || { }));
  if(!p){ return this; }

  var index, cache = this.cache;
  // check + prepare paths and regexes
  if(cache.regexp.length < p.depth+1){
    index = cache.regexp.length;
    while(index < p.depth+1){
      cache.paths.push([ ]);
      cache.regexp.push([ ]);
      index = cache.masterRE.push(null);
    }
  }

  // already in cache?
  if(cache.paths[p.depth].indexOf(p.path) > -1){
    p = method = index = null; // wipe
    return this;
  }

  // prepend for custom regexp or raw, append for default
  var method = ((/\(.+?\)/).test(p.input) || !(/\:\w+/).test(p.input))
    ? 'unshift' : 'push';
  cache.paths[p.depth][method](p.path);
  cache.regexp[p.depth][method](p.regexp);

  // adjust masterRE
  cache.masterRE[p.depth] =
    new RegExp(
      cache.regexp[p.depth]
        .map(function(regexp){ return regexp.source; })
        .join('|'),
    opt.flag);

  // wipe
  p = method = index = null;
  return this;
};

//
// ## get a previously set path
//

Parth.prototype.get = function(path, opt){
  var p = this.tokenize(path, (opt = opt || { }));
  if(!p.path){ return null; }

  var fallback = true;
  var index = 0, depth = p.depth;

  while(fallback){
    p.regexp = this.cache.masterRE[depth];
    fallback = !p.regexp && (this.cache.fallback || opt.fallback);
    if(!p.regexp || !p.regexp.test(p.input)){
      if(!fallback){ return null; }
      depth--; p.fallback = true;
    }
    if(depth < 0){ return null; }
  }

  p.regexp = this.cache.regexp[depth];
  while( !p.regexp[index].test(p.path) ){ index++; }
  p.regexp = this.cache.regexp[depth][index];
  p.path = this.cache.paths[depth][index];

  // wipe
  fallback = index = depth = null;
  return this.parse(p, opt);
};
<|endoftext|>


<commit_before>const lexed = require('lexed');
lexed.english();
const lexer = lexed.lexer;
const tagger = require('en-pos');
const parser = require('en-parse');

var langr = function(input){
	var lexResult = lexer(input);
	var tagResult = lexResult.map(sentence=>tagger(sentence.tokens,sentence.meta));
	var parseReulst = lexResult.map((sentence,i)=>parser(tagResult[i].tags,uncontract(sentence.tokens)));
	this.input = input;
	this.sentences = lexResult.map(sentence=>sentence.raw);
	this.output = lexResult.map((sentence,index)=>{
		return {
			raw:this.sentences[index],
			tokens:lexResult[index].tokens,
			tokenizationMeta:lexResult[index].meta,
			confidence:tagResult[index].confidence-10,
			tags:tagResult[index].tags,
			deps:parseReulst[index],
		};
	});
	return this;
};

langr.extend = function(detector){
	if(Array.isArray(detector)) detector.forEach((single)=>add(single));
	else add(detector);
	function add(detector){
		if(typeof detector === "object" && detector !== null && detector.id && detector.detector) langr.prototype[detector.id] = detector.detector;
		else console.warn("LANGR: The detector you're trying to add is invalid.");
	}
};

module.exports = langr;// solve contractions
// a necessary step for the dependency parser
var contractions = ["'m",	"'s",	"'d",	"'ll",	"'re",	"'ve"];
var replacements = ["am",	"is",	"would","will",	"are",	"have"];
function uncontract (arr){
	return arr.map((x)=>{
		var ci = contractions.indexOf(x);
		if(~ci) return replacements[ci];
		else return x;
	});
}

module.exports = fin;<commit_msg>add interception ability<commit_after>const lexed = require('lexed');
lexed.english();
const lexer = lexed.lexer;
const tagger = require('en-pos');
const parser = require('en-parse');

var interceptors = [];

var fin = function(input){
	// process interceptions
	interceptors.forEach(f=>input=f(input));
	// lex, tag then parse ..
	var lexResult = lexer(input);
	var tagResult = lexResult.map(sentence=>tagger(sentence.tokens,sentence.meta));
	var parseReulst = lexResult.map((sentence,i)=>parser(tagResult[i].tags,uncontract(sentence.tokens)));
	this.input = input;
	this.sentences = lexResult.map(sentence=>sentence.raw);
	this.output = lexResult.map((sentence,index)=>{
		return {
			raw:this.sentences[index],
			tokens:lexResult[index].tokens,
			tokenizationMeta:lexResult[index].meta,
			confidence:tagResult[index].confidence-10,
			tags:tagResult[index].tags,
			deps:parseReulst[index],
		};
	});
	return this;
};

fin.intercept = function(f){
	if(typeof f !== "function") console.warn("FIN: An interceptor must be a function");
	else interceptors.push(f);
};

fin.extend = function(detector){
	if(Array.isArray(detector)) detector.forEach((single)=>add(single));
	else add(detector);
	function add(detector){
		if(typeof detector === "object" && detector !== null && detector.id && detector.detector) langr.prototype[detector.id] = detector.detector;
		else console.warn("LANGR: The detector you're trying to add is invalid.");
	}
};

module.exports = langr;// solve contractions
// a necessary step for the dependency parser
var contractions = ["'m",	"'s",	"'d",	"'ll",	"'re",	"'ve"];
var replacements = ["am",	"is",	"would","will",	"are",	"have"];
function uncontract (arr){
	return arr.map((x)=>{
		var ci = contractions.indexOf(x);
		if(~ci) return replacements[ci];
		else return x;
	});
}

module.exports = fin;<|endoftext|>


<commit_before>/********************************************************************************
    vCards-js, Eric J Nesser, November 2014
********************************************************************************/
/*jslint node: true */
'use strict';

/**
 * Represents a contact that can be imported into Outlook, iOS, Mac OS, Android devices, and more
 */
var vCard = (function () {

  var fs   = require('fs');
  var path = require('path');

    /**
     * Get photo object for storing photos in vCards
     */
    function getPhoto() {
        return {
            url: '',
            mediaType: '',
            base64: false,

            /**
             * Attach a photo from a URL
             * @param  {string} url       URL where photo can be found
             * @param  {string} mediaType Media type of photo (JPEG, PNG, GIF)
             */
            attachFromUrl: function(url, mediaType) {
                this.url = url;
                this.mediaType = mediaType;
                this.base64 = false;
            },

            /**
             * Embed a photo from a file using base-64 encoding (not implemented yet)
             * @param  {string} filename
             */
            embedFromFile: function(fileLocation) {
              this.mediaType = path.extname(fileLocation).toUpperCase().replace(/\./g, "");
              var imgData = fs.readFileSync(fileLocation);
              this.url = imgData.toString('base64');
              this.base64 = true;
            }
        };
    }

    /**
     * Get a mailing address to attach to a vCard.
     */
    function getMailingAddress() {
        return {
            /**
             * Represents the actual text that should be put on the mailing label when delivering a physical package
             * @type {String}
             */
            label: '',

            /**
             * Street address
             * @type {String}
             */
            street: '',

            /**
             * City
             * @type {String}
             */
            city: '',

            /**
             * State or province
             * @type {String}
             */
            stateProvince: '',

            /**
             * Postal code
             * @type {String}
             */
            postalCode: '',

            /**
             * Country or region
             * @type {String}
             */
            countryRegion: ''
        };
    }

    /**
     * Get social media URLs
     * @return {object} Social media URL hash group
     */
    function getSocialUrls() {
        return {
            'facebook': '',
            'linkedIn': '',
            'twitter': '',
            'flickr': ''
        };
    }

    /********************************************************************************
     * Public interface for vCard
     ********************************************************************************/
    return {

        /**
         * Date of birth
         * @type {Datetime}
         */
        birthday: '',

        /**
         * Cell phone number
         * @type {String}
         */
        cellPhone: '',

        /**
         * Other cell phone number or pager
         * @type {String}
         */
        pagerPhone: '',

        /**
         * The address for private electronic mail communication
         * @type {String}
         */
        email: '',

        /**
         * The address for work-related electronic mail communication
         * @type {String}
         */
        workEmail: '',

        /**
         * First name
         * @type {String}
         */
        firstName: '',

        /**
         * Formatted name string associated with the vCard object (will automatically populate if not set)
         * @type {String}
         */
        formattedName: '',

        /**
         * Gender.
         * @type {String} Must be M or F for Male or Female
         */
        gender: '',

        /**
         * Home mailing address
         * @type {object}
         */
        homeAddress: getMailingAddress(),

        /**
         * Home phone
         * @type {String}
         */
        homePhone: '',

        /**
         * Home facsimile
         * @type {String}
         */
        homeFax: '',

        /**
         * Last name
         * @type {String}
         */
        lastName: '',

        /**
         * Logo
         * @type {object}
         */
        logo: getPhoto(),

        /**
         * Middle name
         * @type {String}
         */
        middleName: '',

        /**
         * Prefix for individual's name
         * @type {String}
         */
        namePrefix: '',

        /**
         * Suffix for individual's name
         * @type {String}
         */
        nameSuffix: '',

        /**
         * Nickname of individual
         * @type {String}
         */
        nickname: '',

        /**
         * Specifies supplemental information or a comment that is associated with the vCard
         * @type {String}
         */
        note: '',

        /**
         * The name and optionally the unit(s) of the organization associated with the vCard object
         * @type {String}
         */
        organization: '',

        /**
         * Individual's photo
         * @type {object}
         */
        photo: getPhoto(),

        /**
         * The role, occupation, or business category of the vCard object within an organization
         * @type {String}
         */
        role: '',

        /**
         * Social URLs attached to the vCard object (ex: Facebook, Twitter, LinkedIn)
         * @type {String}
         */
        socialUrls: getSocialUrls(),

        /**
         * A URL that can be used to get the latest version of this vCard
         * @type {String}
         */
        source: '',

        /**
         * Specifies the job title, functional position or function of the individual within an organization
         * @type {String}
         */
        title: '',

        /**
         * URL pointing to a website that represents the person in some way
         * @type {String}
         */
        url: '',

        /**
         * URL pointing to a website that represents the person's work in some way
         * @type {String}
         */
        workUrl: '',

        /**
         * Work mailing address
         * @type {object}
         */
        workAddress: getMailingAddress(),

        /**
         * Work phone
         * @type {String}
         */
        workPhone: '',

        /**
         * Work facsimile
         * @type {String}
         */
        workFax: '',

        /**
         * vCard version
         * @type {String}
         */
        version: '3.0',

        /**
         * Get major version of the vCard format
         * @return {integer}
         */
        getMajorVersion: function() {
            var majorVersionString = this.version ? this.version.split('.')[0] : '4';
            if (!isNaN(majorVersionString)) {
                return parseInt(majorVersionString);
            }
            return 4;
        },

        /**
         * Get formatted vCard
         * @return {String} Formatted vCard in VCF format
         */
        getFormattedString: function() {
            var vCardFormatter = require('./lib/vCardFormatter');
            return vCardFormatter.getFormattedString(this);
        },

        /**
         * Save formatted vCard to file
         * @param  {String} filename
         */
        saveToFile: function(filename) {
            var vCardFormatter = require('./lib/vCardFormatter');
            var contents = vCardFormatter.getFormattedString(this);

            var fs = require('fs');
            fs.writeFileSync(filename, contents, { encoding: 'utf8' });
        }
    };
});

module.exports = vCard;
<commit_msg>Allow embedding image from base64 string. Require node-specific packages inside methods that require them, making it easier to use this package in the browser.<commit_after>/********************************************************************************
    vCards-js, Eric J Nesser, November 2014
********************************************************************************/
/*jslint node: true */
'use strict';

/**
 * Represents a contact that can be imported into Outlook, iOS, Mac OS, Android devices, and more
 */
var vCard = (function () {
    /**
     * Get photo object for storing photos in vCards
     */
    function getPhoto() {
        return {
            url: '',
            mediaType: '',
            base64: false,

            /**
             * Attach a photo from a URL
             * @param  {string} url       URL where photo can be found
             * @param  {string} mediaType Media type of photo (JPEG, PNG, GIF)
             */
            attachFromUrl: function(url, mediaType) {
                this.url = url;
                this.mediaType = mediaType;
                this.base64 = false;
            },

            /**
             * Embed a photo from a file using base-64 encoding (not implemented yet)
             * @param  {string} filename
             */
            embedFromFile: function(fileLocation) {
              var fs   = require('fs');
              var path = require('path');
              this.mediaType = path.extname(fileLocation).toUpperCase().replace(/\./g, "");
              var imgData = fs.readFileSync(fileLocation);
              this.url = imgData.toString('base64');
              this.base64 = true;
            },

            /**
             * Embed a photo from a base-64 string
             * @param  {string} base64String
             */
            embedFromString: function(base64String, mediaType) {
              this.mediaType = mediaType;
              this.url = base64String;
              this.base64 = true;
            }
        };
    }

    /**
     * Get a mailing address to attach to a vCard.
     */
    function getMailingAddress() {
        return {
            /**
             * Represents the actual text that should be put on the mailing label when delivering a physical package
             * @type {String}
             */
            label: '',

            /**
             * Street address
             * @type {String}
             */
            street: '',

            /**
             * City
             * @type {String}
             */
            city: '',

            /**
             * State or province
             * @type {String}
             */
            stateProvince: '',

            /**
             * Postal code
             * @type {String}
             */
            postalCode: '',

            /**
             * Country or region
             * @type {String}
             */
            countryRegion: ''
        };
    }

    /**
     * Get social media URLs
     * @return {object} Social media URL hash group
     */
    function getSocialUrls() {
        return {
            'facebook': '',
            'linkedIn': '',
            'twitter': '',
            'flickr': ''
        };
    }

    /********************************************************************************
     * Public interface for vCard
     ********************************************************************************/
    return {

        /**
         * Date of birth
         * @type {Datetime}
         */
        birthday: '',

        /**
         * Cell phone number
         * @type {String}
         */
        cellPhone: '',

        /**
         * Other cell phone number or pager
         * @type {String}
         */
        pagerPhone: '',

        /**
         * The address for private electronic mail communication
         * @type {String}
         */
        email: '',

        /**
         * The address for work-related electronic mail communication
         * @type {String}
         */
        workEmail: '',

        /**
         * First name
         * @type {String}
         */
        firstName: '',

        /**
         * Formatted name string associated with the vCard object (will automatically populate if not set)
         * @type {String}
         */
        formattedName: '',

        /**
         * Gender.
         * @type {String} Must be M or F for Male or Female
         */
        gender: '',

        /**
         * Home mailing address
         * @type {object}
         */
        homeAddress: getMailingAddress(),

        /**
         * Home phone
         * @type {String}
         */
        homePhone: '',

        /**
         * Home facsimile
         * @type {String}
         */
        homeFax: '',

        /**
         * Last name
         * @type {String}
         */
        lastName: '',

        /**
         * Logo
         * @type {object}
         */
        logo: getPhoto(),

        /**
         * Middle name
         * @type {String}
         */
        middleName: '',

        /**
         * Prefix for individual's name
         * @type {String}
         */
        namePrefix: '',

        /**
         * Suffix for individual's name
         * @type {String}
         */
        nameSuffix: '',

        /**
         * Nickname of individual
         * @type {String}
         */
        nickname: '',

        /**
         * Specifies supplemental information or a comment that is associated with the vCard
         * @type {String}
         */
        note: '',

        /**
         * The name and optionally the unit(s) of the organization associated with the vCard object
         * @type {String}
         */
        organization: '',

        /**
         * Individual's photo
         * @type {object}
         */
        photo: getPhoto(),

        /**
         * The role, occupation, or business category of the vCard object within an organization
         * @type {String}
         */
        role: '',

        /**
         * Social URLs attached to the vCard object (ex: Facebook, Twitter, LinkedIn)
         * @type {String}
         */
        socialUrls: getSocialUrls(),

        /**
         * A URL that can be used to get the latest version of this vCard
         * @type {String}
         */
        source: '',

        /**
         * Specifies the job title, functional position or function of the individual within an organization
         * @type {String}
         */
        title: '',

        /**
         * URL pointing to a website that represents the person in some way
         * @type {String}
         */
        url: '',

        /**
         * URL pointing to a website that represents the person's work in some way
         * @type {String}
         */
        workUrl: '',

        /**
         * Work mailing address
         * @type {object}
         */
        workAddress: getMailingAddress(),

        /**
         * Work phone
         * @type {String}
         */
        workPhone: '',

        /**
         * Work facsimile
         * @type {String}
         */
        workFax: '',

        /**
         * vCard version
         * @type {String}
         */
        version: '3.0',

        /**
         * Get major version of the vCard format
         * @return {integer}
         */
        getMajorVersion: function() {
            var majorVersionString = this.version ? this.version.split('.')[0] : '4';
            if (!isNaN(majorVersionString)) {
                return parseInt(majorVersionString);
            }
            return 4;
        },

        /**
         * Get formatted vCard
         * @return {String} Formatted vCard in VCF format
         */
        getFormattedString: function() {
            var vCardFormatter = require('./lib/vCardFormatter');
            return vCardFormatter.getFormattedString(this);
        },

        /**
         * Save formatted vCard to file
         * @param  {String} filename
         */
        saveToFile: function(filename) {
            var vCardFormatter = require('./lib/vCardFormatter');
            var contents = vCardFormatter.getFormattedString(this);

            var fs = require('fs');
            fs.writeFileSync(filename, contents, { encoding: 'utf8' });
        }
    };
});

module.exports = vCard;
<|endoftext|>


<commit_before>'use babel';

import os from 'os';
import path from 'path';
import execa from 'execa';

const unix = path.normalize(path.join(__dirname, 'node_modules', '.bin', 'svgo'));
const win = path.normalize(path.join(__dirname, 'node_modules', '.bin', 'svgo.cmd'));
const svgo = os.type() === 'Windows_NT' ? win : unix;

export function activate() {
  atom.commands.add('atom-text-editor:not([mini])', 'svgo:minify', () => {
    minify(atom.workspace.getActiveTextEditor());
  });

  atom.commands.add('atom-text-editor:not([mini])', 'svgo:prettify', () => {
    prettify(atom.workspace.getActiveTextEditor());
  });
}

export function minify(editor) {
  if (!editor) {
    return Promise.reject(new Error('editor is invalid'));
  }

  const indent = atom.config.get('svgo.indent');
  const disable = atom.config.get('svgo.disable');
  const disables = disable.length === 0 ? [] : disable.split(' ');

  const args = [
    '--string', editor.getText(),
    '--indent', indent,
    ...disables.map(name => `--disable=${name}`),
    '--output', '-'
  ];

  return process(args)
    .then(stdout => setText(editor, stdout.toString()))
    .catch(error => atom.notifications.addError(error.toString(), {}));
}

export function prettify(editor) {
  if (!editor) {
    return Promise.reject(new Error('editor is invalid'));
  }

  const indent = atom.config.get('svgo.indent');
  const disable = atom.config.get('svgo.disable');
  const disables = disable.length === 0 ? [] : disable.split(' ');

  const args = [
    '--string', editor.getText(),
    '--indent', indent,
    '--pretty',
    ...disables.map(name => `--disable=${name}`),
    '--output', '-'
  ];

  return process(args)
    .then(stdout => setText(editor, stdout.toString()))
    .catch(error => atom.notifications.addError(error.toString(), {}));
}

function process(args) {
  return execa.stdout(svgo, args, {
    encoding: null
  });
}

function setText(editor, text) {
  const position = editor.getCursorBufferPosition();
  editor.setText(text);
  editor.setCursorBufferPosition(position);
  return editor;
}
<commit_msg>fix: execa interface<commit_after>'use babel';

import os from 'os';
import path from 'path';
import execa from 'execa';

const unix = path.normalize(path.join(__dirname, 'node_modules', '.bin', 'svgo'));
const win = path.normalize(path.join(__dirname, 'node_modules', '.bin', 'svgo.cmd'));
const svgo = os.type() === 'Windows_NT' ? win : unix;

export function activate() {
  atom.commands.add('atom-text-editor:not([mini])', 'svgo:minify', () => {
    minify(atom.workspace.getActiveTextEditor());
  });

  atom.commands.add('atom-text-editor:not([mini])', 'svgo:prettify', () => {
    prettify(atom.workspace.getActiveTextEditor());
  });
}

export function minify(editor) {
  if (!editor) {
    return Promise.reject(new Error('editor is invalid'));
  }

  const indent = atom.config.get('svgo.indent');
  const disable = atom.config.get('svgo.disable');
  const disables = disable.length === 0 ? [] : disable.split(' ');

  const args = [
    '--string', editor.getText(),
    '--indent', indent,
    ...disables.map(name => `--disable=${name}`),
    '--output', '-'
  ];

  return process(args)
    .then(stdout => setText(editor, stdout.toString()))
    .catch(error => atom.notifications.addError(error.toString(), {}));
}

export function prettify(editor) {
  if (!editor) {
    return Promise.reject(new Error('editor is invalid'));
  }

  const indent = atom.config.get('svgo.indent');
  const disable = atom.config.get('svgo.disable');
  const disables = disable.length === 0 ? [] : disable.split(' ');

  const args = [
    '--string', editor.getText(),
    '--indent', indent,
    '--pretty',
    ...disables.map(name => `--disable=${name}`),
    '--output', '-'
  ];

  return process(args)
    .then(result => setText(editor, result.stdout.toString()))
    .catch(error => atom.notifications.addError(error.toString(), {}));
}

function process(args) {
  return execa(svgo, args, {
    encoding: null
  });
}

function setText(editor, text) {
  const position = editor.getCursorBufferPosition();
  editor.setText(text);
  editor.setCursorBufferPosition(position);
  return editor;
}
<|endoftext|>


<commit_before>'use strict';
let path = require('path');
let glob = require('glob-all');
let Transform = require('stream').Transform;
let Material = require('fuller-material-file');

let SrcFiles = function(fuller, options) {
  fuller.bind(this);
  this.src = options.src;
  this.dst = options.dst;
};

SrcFiles.prototype = {
  build: function(src, dst) {
    let self = this;

    let next = new Transform({
      objectMode: true,
      transform: function(mat, enc, cb) {
        cb(null, mat);
      }
    });

    if (Array.isArray(src)) {
      src = src.slice(0);
    }

    glob(src, { cwd: this.src }, function(err) {
      err && self.error(err);
    })
    .on('match', function(f) {
      let file = path.join(self.src, f);
      let newMat = new Material({ id: dst, path: file })
        .dst(path.join(self.dst, f))
        .error(function(err) {
          self.error(err);
        });
      self.addDependencies(file, dst);
      next.write(newMat);
    })
    .on('end', function() {
      next.end();
    })
    .on('error', function(err) {
      self.error(err);
    });

    return next;
  }
};

module.exports = SrcFiles;
<commit_msg>Updated dependencies<commit_after>'use strict';
const path = require('path');
const glob = require('glob-all');
const Transform = require('stream').Transform;
const Material = require('fuller-material-file');

const SrcFiles = function(fuller, options) {
  fuller.bind(this);
  this.src = options.src;
  this.dst = options.dst;
};

SrcFiles.prototype = {
  build: function(src, dst) {
    const next = new Transform({
      objectMode: true,
      transform: (mat, enc, cb) => {
        cb(null, mat);
      }
    });

    if (Array.isArray(src)) {
      src = src.slice(0);
    }

    glob(src, { cwd: this.src }, err => err && this.error(err))
      .on('match', f => {
        const file = path.join(this.src, f);
        const newMat = new Material({ id: dst, path: file })
          .dst(path.join(this.dst, f))
          .error(err => this.error(err));

        this.addDependencies(file, dst);
        next.write(newMat);
      })
      .on('end', () => next.end())
      .on('error', err => this.error(err));
    return next;
  }
};

module.exports = SrcFiles;
<|endoftext|>


<commit_before>'use strict';

var FreeList = require('freelist').FreeList
  , Librarian = require('./librarian')
  , Route = require('routable')
  , Primus = require('primus')
  , Page = require('./page')
  , path = require('path')
  , url = require('url')
  , fs = require('fs');

/**
 * Our pagelet managment.
 *
 * The following options are available:
 *
 * - transport: The transport engine we should use for real-time.
 * - cache: A object were we store our url->page mapping.
 * - stream: Where we should write our logs to.
 * - parser: Which parser should be used to send data in real-time.
 *
 * @constructor
 * @param {Server} server HTTP/S based server instance.
 * @param {Mixed} pages String or array of pages we serve.
 * @param {Object} options Configuration.
 * @api public
 */
function Pipe(server, pages, options) {
  options = options || {};

  this.statusCodes = Object.create(null);               // Stores error pages.
  this.stream = options.stream || process.stdout;       // Our log stream.
  this.pages = this.resolve(pages, this.transform);     // Our Page constructors.
  this.discover(this.pages);                            // Find error pages.
  this.cache = options.cache || null;                   // Enable URL lookup caching.

  //
  // Now that everything is procesed, we can setup our internals.
  //
  this.server = server;
  this.primus = new Primus(this.server, {
    transformer: options.transport || 'engine.io',
    parser: options.parser || 'json'
  });

  this.library = new Librarian(this);

  //
  // Start listening for incoming requests.
  //
  this.server.on('request', this.incoming.bind(this));
  this.primus.on('connection', this.connection.bind(this));
}

Pipe.prototype.__proto__ = require('events').EventEmitter.prototype;

/**
 * Simple log method.
 *
 * @param {String} type The log type.
 * @api private
 */
Pipe.prototype.log = function log(type) {
  this.stream.write(
    ['  '+ type].concat(                          // Add some padding.
      Array.prototype.slice.call(arguments, 1)    // Concat it with all args.
    ).join(' ') + '\n'                            // Join it as pretty string.
  );

  return this;
};

/**
 * Transform strings, array of strings, objects, things in to the actual
 * constructors.
 *
 * @param {String|Array|Object} files The files.
 * @param {Function} transform Transformation function
 * @returns {Array}
 * @api private
 */
Pipe.prototype.resolve = function resolve(files, transform) {
  if ('string' === typeof files) {
    files = fs.readdirSync(files).map(function locate(file) {
      return path.resolve(files, file);
    });
  } else if (!Array.isArray(files)) {
    files = Object.keys(files).map(function merge(name) {
      var constructor = files[name];
      constructor.prototype.name = constructor.prototype.name || name;

      return constructor;
    });
  }

  files = files.map(function map(constructor) {
    //
    // It's not required to supply us with instances, we can just
    // automatically require them if they are using the:
    //
    //   module.exports = base.extend();
    //
    // pattern for defining the pages/pagelets.
    //
    if ('string' === typeof constructor) {
      constructor = require(constructor);
    }

    //
    // We didn't receive a proper page instance.
    //
    if ('function' !== typeof constructor) {
      var invalid = (JSON.stringify(constructor) || constructor.toString());
      this.log('𝓦'.red, 'Ignorning invalid constructor: '+ invalid);
      return undefined;
    }
  }, this).filter(Boolean);

  return transform
    ? files.map(transform.bind(this))
    : files;
};

/**
 * Discover if the user supplied us with custom error pages so we use that
 * in case we need to handle a 404 or and 500 error page.
 *
 * @param {Array} pages All enabled pages.
 * @api private
 */
Pipe.prototype.discover = function discover(pages) {
  var fivehundered
    , fourofour;

  pages.forEach(function each(page) {
    if (page.router.test('/500')) fivehundered = page;
    if (page.router.test('/404')) fourofour = page;
  });

  //
  // We don't have any 500 or 404 handlers, so use some default pages that are
  // provided by us. But as these page are not processed yet, we need to kick
  // them through our transform process.
  //
  if (!fivehundered) fivehundered = this.transform(require('./pages/500'));
  if (!fourofour) fourofour = this.transform(require('./pages/404'));

  this.statusCodes[500] = fivehundered;
  this.statusCodes[404] = fourofour;

  return this;
};

/**
 * We need to extract items from the Page prototype and transform it in to
 * something useful.
 *
 * @param {Page} page Page constructor.
 * @return {Page} The upgrade page.
 * @api private
 */
Pipe.prototype.transform = function transform(Page) {
  var method = Page.prototype.method
    , router = Page.prototype.path
    , pipe = this;

  //
  // This page has already been processed, bailout.
  //
  if (Page.properties) return Page;

  //
  // Parse the methods to an array of accepted HTTP methods. We'll only accept
  // there requests and should deny every other possible method.
  //
  if (!Array.isArray(method)) method = method.split(/[\s,]+?/);
  method = method.filter(Boolean).map(function transformation(method) {
    return method.toUpperCase();
  });

  //
  // Update the pagelets, if any.
  //
  if (Page.prototype.pagelets) {
    var pagelets = this.resovle(Page.prototype.pagelets, function map(Pagelet) {
      //
      // This pagelet has already been processed before as pages can share
      // pagelets.
      //
      if (Pagelet.properties) return Pagelet;

      // 1. Update the paths of the assets, so they are absolute.
      // 2. Check if the assets exist.

      Pagelet.properties = Object.keys(Pagelet.prototype);

      return Pagelet;
    });

    //
    // Save the transformed pagelets.
    //
    Page.prototype.pagelets = pagelets;
  }

  //
  // Add the properties to the page.
  //
  Page.properties = Object.keys(Page.prototype);
  Page.router = new Route(router);
  Page.method = method;

  //
  // Setup a FreeList for the page so we can re-use the page instances and
  // reduce garbage collection to a bare minimum.
  //
  Page.collection = new FreeList('page', Page.prototype.freelist || 1000, function () {
    return new Page(pipe);
  });

  return Page;
};

/**
 * Find the correct Page constructor based on the given url.
 *
 * @param {String} url The url we need to find.
 * @returns {Mixed} either a Page constructor or undefined;
 * @api public
 */
Pipe.prototype.find = function find(url) {
  if (this.cache && url in this.cache) return this.cache[url];

  for (var i = 0, found, length = this.pages.length; i < length; i++) {
    if (this.pages[i].router.test(url)) {

      if (this.cache) this.cache[url] = this.pages[i];
      return this.pages[i];
    }
  }

  return undefined;
};

/**
 * Handle incoming requests.
 *
 * @param {Request} req HTTP request.
 * @param {Resposne} res HTTP response.
 * @api private
 */
Pipe.prototype.incoming = function incoming(req, res) {
  var page = this.find(page) || this.statusCodes[404];

  // example api:
  // this.post(req)(this.create(page))(this.querystring(req, page))
};

/**
 * Handle incoming real-time requests.
 *
 * @param {Spark} socket A real-time "socket"
 */
Pipe.prototype.connection = function connection(socket) {

};

/**
 * Create a new Pagelet/Pipe server.
 *
 * @param {Number} port Port number we should listen on.
 * @param {Array} pages List with pages.
 * @param {Object} options Configuration.
 * @returns {Pipe}
 * @api public
 */
Pipe.createServer = function createServer(port, pages, options) {
  options = options || {};

  var certs = 'key' in options && 'cert' in options
    , secure = certs || 443 === port
    , spdy = 'spdy' in options
    , server;

  //
  // We need to have SSL certs for SPDY and secure servers.
  //
  if (secure || spdy && !certs) {
    throw new Error('Missing the SSL key or certificate files in the options.');
  }

  if (spdy) {
    server = require('spdy').createServer(options);
  } else if (secure) {
    server = require('https').createServer(options);
  } else {
    server = require('http').createServer();
  }

  //
  // Now that we've got a server, we can setup the pipe and start listening.
  //
  var pipe = new Pipe(server, pages || options.pages, options);
  server.listen(port);

  return pipe;
};

//
// Expose the constructor.
//
module.exports = Pipe;
<commit_msg>[minor] process the view, css, js and dependencies<commit_after>'use strict';

var FreeList = require('freelist').FreeList
  , Librarian = require('./librarian')
  , Route = require('routable')
  , Primus = require('primus')
  , Page = require('./page')
  , path = require('path')
  , url = require('url')
  , fs = require('fs');

/**
 * Our pagelet managment.
 *
 * The following options are available:
 *
 * - transport: The transport engine we should use for real-time.
 * - cache: A object were we store our url->page mapping.
 * - stream: Where we should write our logs to.
 * - parser: Which parser should be used to send data in real-time.
 *
 * @constructor
 * @param {Server} server HTTP/S based server instance.
 * @param {Mixed} pages String or array of pages we serve.
 * @param {Object} options Configuration.
 * @api public
 */
function Pipe(server, pages, options) {
  options = options || {};

  this.statusCodes = Object.create(null);               // Stores error pages.
  this.stream = options.stream || process.stdout;       // Our log stream.
  this.pages = this.resolve(pages, this.transform);     // Our Page constructors.
  this.discover(this.pages);                            // Find error pages.
  this.cache = options.cache || null;                   // Enable URL lookup caching.

  //
  // Now that everything is procesed, we can setup our internals.
  //
  this.server = server;
  this.primus = new Primus(this.server, {
    transformer: options.transport || 'engine.io',
    parser: options.parser || 'json'
  });

  this.library = new Librarian(this);

  //
  // Start listening for incoming requests.
  //
  this.server.on('request', this.incoming.bind(this));
  this.primus.on('connection', this.connection.bind(this));
}

Pipe.prototype.__proto__ = require('events').EventEmitter.prototype;

/**
 * Simple log method.
 *
 * @param {String} type The log type.
 * @api private
 */
Pipe.prototype.log = function log(type) {
  this.stream.write(
    ['  '+ type].concat(                          // Add some padding.
      Array.prototype.slice.call(arguments, 1)    // Concat it with all args.
    ).join(' ') + '\n'                            // Join it as pretty string.
  );

  return this;
};

/**
 * Transform strings, array of strings, objects, things in to the actual
 * constructors.
 *
 * @param {String|Array|Object} files The files.
 * @param {Function} transform Transformation function
 * @returns {Array}
 * @api private
 */
Pipe.prototype.resolve = function resolve(files, transform) {
  if ('string' === typeof files) {
    files = fs.readdirSync(files).map(function locate(file) {
      return path.resolve(files, file);
    });
  } else if (!Array.isArray(files)) {
    files = Object.keys(files).map(function merge(name) {
      var constructor = files[name];
      constructor.prototype.name = constructor.prototype.name || name;

      return constructor;
    });
  }

  files = files.map(function map(constructor) {
    //
    // It's not required to supply us with instances, we can just
    // automatically require them if they are using the:
    //
    //   module.exports = base.extend();
    //
    // pattern for defining the pages/pagelets.
    //
    if ('string' === typeof constructor) {
      constructor = require(constructor);
    }

    //
    // We didn't receive a proper page instance.
    //
    if ('function' !== typeof constructor) {
      var invalid = (JSON.stringify(constructor) || constructor.toString());
      this.log('𝓦'.red, 'Ignorning invalid constructor: '+ invalid);
      return undefined;
    }
  }, this).filter(Boolean);

  return transform
    ? files.map(transform.bind(this))
    : files;
};

/**
 * Discover if the user supplied us with custom error pages so we use that
 * in case we need to handle a 404 or and 500 error page.
 *
 * @param {Array} pages All enabled pages.
 * @api private
 */
Pipe.prototype.discover = function discover(pages) {
  var fivehundered
    , fourofour;

  pages.forEach(function each(page) {
    if (page.router.test('/500')) fivehundered = page;
    if (page.router.test('/404')) fourofour = page;
  });

  //
  // We don't have any 500 or 404 handlers, so use some default pages that are
  // provided by us. But as these page are not processed yet, we need to kick
  // them through our transform process.
  //
  if (!fivehundered) fivehundered = this.transform(require('./pages/500'));
  if (!fourofour) fourofour = this.transform(require('./pages/404'));

  this.statusCodes[500] = fivehundered;
  this.statusCodes[404] = fourofour;

  return this;
};

/**
 * We need to extract items from the Page prototype and transform it in to
 * something useful.
 *
 * @param {Page} page Page constructor.
 * @return {Page} The upgrade page.
 * @api private
 */
Pipe.prototype.transform = function transform(Page) {
  var method = Page.prototype.method
    , router = Page.prototype.path
    , pipe = this;

  //
  // This page has already been processed, bailout.
  //
  if (Page.properties) return Page;

  //
  // Parse the methods to an array of accepted HTTP methods. We'll only accept
  // there requests and should deny every other possible method.
  //
  if (!Array.isArray(method)) method = method.split(/[\s,]+?/);
  method = method.filter(Boolean).map(function transformation(method) {
    return method.toUpperCase();
  });

  //
  // Update the pagelets, if any.
  //
  if (Page.prototype.pagelets) {
    var pagelets = this.resovle(Page.prototype.pagelets, function map(Pagelet) {
      //
      // This pagelet has already been processed before as pages can share
      // pagelets.
      //
      if (Pagelet.properties) return Pagelet;

      var prototype = Pagelet.prototype
        , dir = prototype.directory;

      Pagelet.prototype.view = path.resolve(dir, prototype.view);
      Pagelet.prototype.css = path.resolve(dir, prototype.css);
      Pagelet.prototype.js = path.resolve(dir, prototype.js);
      Pagelet.prototype.dependencies = prototype.dependencies.map(function (dep) {
        return path.resolve(dir, dep);
      });

      // 1. Update the paths of the assets, so they are absolute.
      // 2. Check if the assets exist.

      Pagelet.properties = Object.keys(Pagelet.prototype);

      return Pagelet;
    });

    //
    // Save the transformed pagelets.
    //
    Page.prototype.pagelets = pagelets;
  }

  //
  // Add the properties to the page.
  //
  Page.properties = Object.keys(Page.prototype);      // All properties before init.
  Page.router = new Route(router);                    // Actual HTTP route.
  Page.method = method;                               // Available HTTP methods.
  Page.id = router.toString() +'&&'+ method.join();   // Unique id.

  //
  // Setup a FreeList for the page so we can re-use the page instances and
  // reduce garbage collection to a bare minimum.
  //
  Page.collection = new FreeList('page', Page.prototype.freelist || 1000, function () {
    return new Page(pipe);
  });

  return Page;
};

/**
 * Find the correct Page constructor based on the given url.
 *
 * @param {String} url The url we need to find.
 * @returns {Mixed} either a Page constructor or undefined;
 * @api public
 */
Pipe.prototype.find = function find(url) {
  if (this.cache && url in this.cache) return this.cache[url];

  for (var i = 0, found, length = this.pages.length; i < length; i++) {
    if (this.pages[i].router.test(url)) {

      if (this.cache) this.cache[url] = this.pages[i];
      return this.pages[i];
    }
  }

  return undefined;
};

/**
 * Handle incoming requests.
 *
 * @param {Request} req HTTP request.
 * @param {Resposne} res HTTP response.
 * @api private
 */
Pipe.prototype.incoming = function incoming(req, res) {
  var page = this.find(page) || this.statusCodes[404];

  // example api:
  // this.post(req)(this.create(page))(this.querystring(req, page))
};

/**
 * Handle incoming real-time requests.
 *
 * @param {Spark} socket A real-time "socket"
 */
Pipe.prototype.connection = function connection(socket) {

};

/**
 * Create a new Pagelet/Pipe server.
 *
 * @param {Number} port Port number we should listen on.
 * @param {Array} pages List with pages.
 * @param {Object} options Configuration.
 * @returns {Pipe}
 * @api public
 */
Pipe.createServer = function createServer(port, pages, options) {
  options = options || {};

  var certs = 'key' in options && 'cert' in options
    , secure = certs || 443 === port
    , spdy = 'spdy' in options
    , server;

  //
  // We need to have SSL certs for SPDY and secure servers.
  //
  if (secure || spdy && !certs) {
    throw new Error('Missing the SSL key or certificate files in the options.');
  }

  if (spdy) {
    server = require('spdy').createServer(options);
  } else if (secure) {
    server = require('https').createServer(options);
  } else {
    server = require('http').createServer();
  }

  //
  // Now that we've got a server, we can setup the pipe and start listening.
  //
  var pipe = new Pipe(server, pages || options.pages, options);
  server.listen(port);

  return pipe;
};

//
// Expose the constructor.
//
module.exports = Pipe;
<|endoftext|>


<commit_before>
const colors = require('colors');
const processFiles = require('./processFiles');
const listFiles = require('./listFiles');

var markdownFiles = [
    '../azure-content-pr/includes/guidance-compute-single-vm-linux.md',
    '../azure-content-pr/includes/guidance-compute-single-vm-windows.md'
];

function renderDiff(diff) {

    process.stdout.write(`\n`);
    process.stdout.write(`\n>> ${diff.file}`);
    process.stdout.write(`\n>> lines ${diff.firstLine} - ${diff.lastLine}\n`);

    if (diff.length === 1) {
        process.stdout.write('no change');
        return;
    }

    diff.forEach(part => {
        // green for additions, red for deletions
        // grey for common parts
        var color = part.added ? 'green' :
            part.removed ? 'red' : 'grey';
        process.stderr.write(part.value[color]);
    });
}

function countDifferingBlocks(diffs) {
    return diffs.filter(x => x.filter(y => y.value.trim() !== '').length > 1).length;
}

listFiles().then(markdownFiles => {
    return processFiles(markdownFiles)
        .then(results => {

            // output for console
            results.forEach(r => {
                r.diffs.map(renderDiff);
            });

            console.log();
            results.forEach(r => {
                console.log(`${r.filePath}`);
                console.log(`>> ${countDifferingBlocks(r.diffs)} block(s) differ`);
            });
        });
});<commit_msg>improving output<commit_after>
const colors = require('colors');
const processFiles = require('./processFiles');
const listFiles = require('./listFiles');

var markdownFiles = [
    '../azure-content-pr/includes/guidance-compute-single-vm-linux.md',
    '../azure-content-pr/includes/guidance-compute-single-vm-windows.md'
];

function renderDiff(diff) {

    process.stdout.write(`\n`);
    process.stdout.write(`\n>> ${diff.file}`);
    process.stdout.write(`\n>> lines ${diff.firstLine} - ${diff.lastLine}\n`);

    if (diff.length === 1) {
        process.stdout.write('no change');
        return;
    }

    diff.forEach(part => {
        // green for additions, red for deletions
        // grey for common parts
        var color = part.added ? 'green' :
            part.removed ? 'red' : 'grey';
        process.stderr.write(part.value[color]);
    });
}

function countDifferingBlocks(diffs) {
    return diffs.filter(x => x.filter(y => y.value.trim() !== '').length > 1).length;
}

listFiles()
    .then(processFiles)
    .then(results => {

        // output for console
        results.forEach(r => {
            r.diffs.map(renderDiff);
        });

        console.log();
        console.log(`processed ${results.length} files`);

        results.forEach(r => {
            var count = countDifferingBlocks(r.diffs);
            if (count === 0) return;

            console.log(`${r.filePath}`);
            console.log(`>> ${count} block(s) differ`);
        });
    });<|endoftext|>


<commit_before>'use strict';

module.exports = walker;

var parser = require('./lib/parser');
var circular = require('./lib/circular');
var node_path = require('path');
var async = require('async');
var fs = require('fs');
var util = require('util');

function walker (entry, options, callback) {
  options || (options = {});
  if(arguments.length == 2){
    options = {};
    callback = arguments[1];
  }
  return new Walker(entry, options, callback);
}

function makeDefault (object, key, value) {
  object[key] = key in object
    ? object[key]
    : value
}

// [ref](http://nodejs.org/api/modules.html#modules_file_modules)
var EXTS_NODE = ['.js', '.json', '.node'];

function Walker (entry, options, callback) {
  this.nodes = {};
  this.entry = node_path.resolve(entry);
  this.options = options;

  makeDefault(options, 'detectCyclic', true);
  makeDefault(options, 'strictRequire', true);
  makeDefault(options, 'allowAbsolutePath', true);
  makeDefault(options, 'parseForeignModule', true);

  makeDefault(options, 'extFallbacks', EXTS_NODE);

  if (!this._checkExts()) {
    throw new Error('Invalid value of options.extFallbacks');
  }

  this.callback = callback;
  this._walk();
}

Walker.prototype._checkExts = function() {
  var exts = this.options.extFallbacks;

  if (!util.isArray(exts)) {
    return false;
  }

  return exts.every(function (ext, i) {
    return ext === EXTS_NODE[i];
  });
};

Walker.prototype._walk = function() {
  var self = this;
  var entry = this.entry;
  var called;

  function cb (err, tree) {
    if (called) {
      return;
    }

    called = true;

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

    // Returns the node of the entry point
    self.callback(null, self._getNode(entry), self.nodes);
  }

  var err;
  var q = async.queue(function (task, done) {
    function sub_node (err) {
      if (err) {
        cb(err);
      }

      done();
    }

    var path = task.path;
    var ext = self._getExt(path);
    var node = self._getNode(path);
    node.ext = ext;

    if (ext === '.json') {
      return self._parseJsonFile(path, sub_node);
    }

    if (ext === '.node') {
      return self._parseNodeFile(path, sub_node);
    }

    // Each node must be created before `._parseFile()`
    self._parseFile(path, function (err, data) {
      if (err) {
        cb(err);
        return done();
      }

      self._dealDependencies(data, sub_node);
    });
  });

  q.drain = cb;

  // Creates entry node
  this._createNode(entry);
  // Adds initial task
  q.push({
    path: entry
  });

  this.queue = q;
};

var REGEX_MATCH_EXT = /\.[a-z]+$/i;
Walker.prototype._getExt = function(file) {
  var match = file.match(REGEX_MATCH_EXT);
  if (!match) {
    return '';
  }

  return match[0].toLowerCase();
};

// Actually, we do nothing
Walker.prototype._parseNodeFile = function(path, callback) {
  this._parseJsonFile(path, callback);
};

Walker.prototype._parseJsonFile = function(path, callback) {
  var self = this;
  parser.read(path, function (err, content) {
    if (err) {
      return callback(err);
    }

    var node = self._getNode(path);
    node.code = content;
    node.dependencies = [];
    node.unresolvedDependencies = [];
    callback(null);
  });
};

Walker.prototype._parseFile = function(path, callback) {
  var self = this;

  parser.parse(path, {
    strictRequire: this.options.strictRequire

  }, callback);
};

Walker.prototype._dealDependencies = function(data, callback) {
  var dependencies = data.dependencies;
  var path = data.path;
  var node = this._getNode(path);

  node.unresolvedDependencies = dependencies;
  node.dependencies = [];
  node.code = data.code;

  var self = this;
  var options = this.options;
  async.each(dependencies, function (dep, done) {
    // Suppose:
    // origin ->
    // './a'
    // './b.js'
    var origin = dep;

    if (dep.indexOf('/') === 0 && !options.allowAbsolutePath) {
      return done({
        code: 'NOT_ALLOW_ABSOLUTE_PATH',
        message: 'Requiring an absolute path is not allowed',
        data: {
          dependency: dep,
          path: path
        }
      });
    }

    // Absolutize
    // -> '/path/to/a'
    // -> '/path/to/b.js'
    if (self._isRelativePath(dep)) {
      dep = node_path.join(node_path.dirname(path), dep);
    }

    // -> '/path/to/a.js'
    // -> '/path/to/b.js'
    var resolved = self._resolveDependency(dep);
    if (!resolved) {
      return done({
        code: 'MODULE_NOT_FOUND',
        message: 'Cannot find module \'' + origin + '\'',
        data: {
          path: dep,
          origin: origin
        }
      });
    }

    var sub_node = self._getNode(resolved);
    if (sub_node) {
      // We only check the node if it meets the conditions below:
      // 1. already exists: all new nodes are innocent.
      // 2. but assigned as a dependency of anothor node

      // If one of the ancestor dependents of `node` is `current`, it forms a circle.
      var circular_trace;
      if (
        options.detectCyclic

        // node -> sub_node
        && (circular_trace = circular.trace(sub_node, node))
      ) {
        return done({
          code: 'CYCLIC_DEPENDENCY',
          message: 'Cyclic dependency found: \n' + self._printCyclic(circular_trace),
          data: {
            trace: circular_trace,
            path: resolved
          }
        });
      }

      self._addDependent(node, sub_node);

      // If sub node is already exists, skip parsing.
      return done(null);
    }

    sub_node = self._createNode(resolved);
    self._addDependent(node, sub_node);

    if (sub_node.isForeign) {
      // We do NOT parse foreign modules
      return done(null);
    }

    self.queue.push({
      path: resolved
    });

    done(null);

  }, callback);
};

Walker.prototype._resolveDependency = function(dep) {
  // Foreign module with a top id
  if (!this._isAbsolutePath(dep)) {
    return dep;
  }

  var resolved = null;
  try {
    resolved = require.resolve(dep);
  } catch(e) {}

  // If require.resolve throws, resolved will be `null`
  if (resolved) {
    resolved = this._cleanResolvedDependency(resolved);
  }

  return resolved;
};

// `require.resolve` will always fallback to
// `.js`, then `.json`, and finally `.node`.
// But we not always do that, so we need to clean the resolved path.
Walker.prototype._cleanResolvedDependency = function(resolved) {
  var ext = this._getExt(resolved);
  // if no extension, the module must exist.
  if (!ext) {
    return resolved;
  }

  if (~this.options.extFallbacks.indexOf(ext)) {
    return resolved;
  }

  // if `options.extFallbacks` does not contain `ext`,
  // we consider it not found.
  return null;
};

Walker.prototype._addDependent = function(dependent, dependency) {
  if (!~dependency.dependents.indexOf(dependent)) {
    dependency.dependents.push(dependent);
  }

  dependent.dependencies.push(dependency);
};

// Creates the node by id if not exists.
// No fault tolerance for the sake of private method
// @param {string} id
// - `path` must be absolute path if is a relative module
// - package name for foreign module
Walker.prototype._createNode = function(id) {
  var node = this.nodes[id];

  if (!node) {
    node = this.nodes[id] = {
      id: id,
      dependents: []
      // version will be set later
    };

    if (id === this.entry) {
      node.isEntryPoint = true;
    }

    if (!this._isAbsolutePath(id)) {
      node.isForeign = true;
    }
  }

  return node;
};

Walker.prototype._isAbsolutePath = function(path) {
  return node_path.resolve(path) === path.replace(/[\/\\]+$/, '');
};

Walker.prototype._isRelativePath = function(dep) {
  // 'abc' -> true
  // './abc' -> false
  // '../abc' -> false
  return dep.indexOf('./') === 0 || dep.indexOf('../') === 0;
};

Walker.prototype._getNode = function(path) {
  return this.nodes[path];
};

// 1. <path>
// 2. <path>
//
Walker.prototype._printCyclic = function(trace) {
  var list = trace.map(function (node, index) {
    return index + 1 + ': ' + node.id;
  });

  list.pop();

  var flow = trace.map(function (node, index) {
    ++ index;

    return index === 1 || index === trace.length
      ? '[1]'
      : index;

  });

  return list.join('\n') + '\n\n' + flow.join(' -> ');
};

<commit_msg>index in progress: remove old invocations; #10<commit_after>'use strict';

module.exports = walker;

var parser = require('./lib/parser');
var circular = require('./lib/circular');
var node_path = require('path');
var async = require('async');
var fs = require('fs');
var util = require('util');
var mod = require('./lib/module');

function walker (entry, options, callback) {
  options || (options = {});
  if(arguments.length == 2){
    options = {};
    callback = arguments[1];
  }
  return new Walker(entry, options, callback);
}

walker.OPTIONS = {
  BROWSER: {
    detectCyclic: true,
    strictRequire: true,
    allowAbsolutePath: false,
    extFallbacks: ['.js', '.json'],
    parseForeignModule: false
  }
};

function makeDefault (object, key, value) {
  object[key] = key in object
    ? object[key]
    : value
}

// [ref](http://nodejs.org/api/modules.html#modules_file_modules)
var EXTS_NODE = ['.js', '.json', '.node'];

function Walker (entry, options, callback) {
  this.nodes = {};
  this.entry = node_path.resolve(entry);
  this.options = options;

  makeDefault(options, 'detectCyclic', true);
  makeDefault(options, 'strictRequire', true);
  makeDefault(options, 'allowAbsolutePath', true);
  makeDefault(options, 'parseForeignModule', true);
  makeDefault(options, 'extFallbacks', EXTS_NODE);

  if (!this._checkExts()) {
    throw new Error('Invalid value of `options.extFallbacks`');
  }

  this.callback = callback;
  this._walk();
}

// Checks if the `options.extFallbacks` is valid
Walker.prototype._checkExts = function() {
  var exts = this.options.extFallbacks;

  if (!util.isArray(exts)) {
    return false;
  }

  return exts.every(function (ext, i) {
    return ext === EXTS_NODE[i];
  });
};

Walker.prototype._walk = function() {
  var self = this;
  var entry = this.entry;

  var called;
  function cb (err) {
    if (called) {
      return;
    }
    called = true;

    if (err) {
      return self.callback(err);
    }
    // Returns the node of the entry point
    self.callback(null, self.nodes);
  }

  var err;
  var q = async.queue(function (task, done) {
    // `path` will always be an absolute path.
    var path = task.path;
    // Each node must be created before `._parseFileDependencies()`
    self._parseFileDependencies(path, function (err) {
      if (err) {
        return cb(err);
      }
      done();
    });
  });

  // Creates entry node
  this._createNode(entry);
  q.drain = cb;
  // Adds initial task
  q.push({
    path: entry
  });
  this.queue = q;
};

// Actually, we do nothing
Walker.prototype._parseNodeFile = function(path, callback) {
  this._parseJsonFile(path, callback);
};

// @param {Path} path Absolute path
Walker.prototype._parseJsonFile = function(path, callback) {
  var self = this;
  parser.read(path, function (err, content) {
    if (err) {
      return callback(err);
    }

    var node = self._getNode(path);
    node.code = content;
    node.dependencies = {};
    callback(null);
  });
};

Walker.prototype._parseFileDependencies = function(path, callback) {
  var self = this;

  var path = task.path;
    mod(path, function (real) {
      if (!real) {
        return sub_done({
          code: 'MODULE_NOT_FOUND',
          message: "Cannot find module '" + path + "'",
          data: {
            path: path
          }
        });
      }

  parser.parse(path, {
    strictRequire: this.options.strictRequire

  }, callback);
};

Walker.prototype._dealDependencies = function(data, callback) {
  var dependencies = data.dependencies;
  var path = data.path;
  var node = this._getNode(path);

  node.unresolvedDependencies = dependencies;
  node.dependencies = [];
  node.code = data.code;

  var self = this;
  var options = this.options;
  async.each(dependencies, function (dep, done) {
    // Suppose:
    // origin ->
    // './a'
    // './b.js'
    var origin = dep;

    if (dep.indexOf('/') === 0 && !options.allowAbsolutePath) {
      return done({
        code: 'NOT_ALLOW_ABSOLUTE_PATH',
        message: 'Requiring an absolute path is not allowed',
        data: {
          dependency: dep,
          path: path
        }
      });
    }

    // Absolutize
    // -> '/path/to/a'
    // -> '/path/to/b.js'
    if (self._isRelativePath(dep)) {
      dep = node_path.join(node_path.dirname(path), dep);
    }

    // -> '/path/to/a.js'
    // -> '/path/to/b.js'
    var resolved = self._resolveDependency(dep);
    if (!resolved) {
      return done({
        code: 'MODULE_NOT_FOUND',
        message: 'Cannot find module \'' + origin + '\'',
        data: {
          path: dep,
          origin: origin
        }
      });
    }

    var sub_node = self._getNode(resolved);
    if (sub_node) {
      // We only check the node if it meets the conditions below:
      // 1. already exists: all new nodes are innocent.
      // 2. but assigned as a dependency of anothor node

      // If one of the ancestor dependents of `node` is `current`, it forms a circle.
      var circular_trace;
      if (
        options.detectCyclic

        // node -> sub_node
        && (circular_trace = circular.trace(sub_node, node))
      ) {
        return done({
          code: 'CYCLIC_DEPENDENCY',
          message: 'Cyclic dependency found: \n' + self._printCyclic(circular_trace),
          data: {
            trace: circular_trace,
            path: resolved
          }
        });
      }

      self._addDependent(node, sub_node);

      // If sub node is already exists, skip parsing.
      return done(null);
    }

    sub_node = self._createNode(resolved);
    self._addDependent(node, sub_node);

    if (sub_node.isForeign) {
      // We do NOT parse foreign modules
      return done(null);
    }

    self.queue.push({
      path: resolved
    });

    done(null);

  }, callback);
};

// Walker.prototype._resolveDependency = function(dep) {
//   // Foreign module with a top id
//   if (!this._isAbsolutePath(dep)) {
//     return dep;
//   }

//   var resolved = null;
//   try {
//     resolved = require.resolve(dep);
//   } catch(e) {}

//   // If require.resolve throws, resolved will be `null`
//   if (resolved) {
//     resolved = this._cleanResolvedDependency(resolved);
//   }

//   return resolved;
// };

// // `require.resolve` will always fallback to
// // `.js`, then `.json`, and finally `.node`.
// // But we not always do that, so we need to clean the resolved path.
// Walker.prototype._cleanResolvedDependency = function(resolved) {
//   var ext = this._getExt(resolved);
//   // if no extension, the module must exist.
//   if (!ext) {
//     return resolved;
//   }

//   if (~this.options.extFallbacks.indexOf(ext)) {
//     return resolved;
//   }

//   // if `options.extFallbacks` does not contain `ext`,
//   // we consider it not found.
//   return null;
// };

Walker.prototype._addDependent = function(dependent, dependency) {
  if (!~dependency.dependents.indexOf(dependent)) {
    dependency.dependents.push(dependent);
  }

  dependent.dependencies.push(dependency);
};

// Creates the node by id if not exists.
// No fault tolerance for the sake of private method
// @param {string} id
// - `path` must be absolute path if is a relative module
// - package name for foreign module
Walker.prototype._createNode = function(id) {
  var node = this.nodes[id];

  if (!node) {
    node = this.nodes[id] = {
      dependents: [],
      entry: id === this.entry,
      foreign: !this._isAbsolutePath(id)
    };
  }
  return node;
};

Walker.prototype._isAbsolutePath = function(path) {
  return node_path.resolve(path) === path.replace(/[\/\\]+$/, '');
};

Walker.prototype._isRelativePath = function(dep) {
  // 'abc' -> true
  // './abc' -> false
  // '../abc' -> false
  return dep.indexOf('./') === 0 || dep.indexOf('../') === 0;
};

Walker.prototype._getNode = function(path) {
  return this.nodes[path];
};

// 1. <path>
// 2. <path>
//
Walker.prototype._printCyclic = function(trace) {
  var list = trace.map(function (node, index) {
    return index + 1 + ': ' + node.id;
  });
  list.pop();

  var flow = trace.map(function (node, index) {
    ++ index;
    return index === 1 || index === trace.length
      ? '[1]'
      : index;
  });

  return list.join('\n') + '\n\n' + flow.join(' -> ');
};

<|endoftext|>


<commit_before>var Metalsmith = require("metalsmith");
var markdown = require("metalsmith-markdown");
var layouts = require("metalsmith-layouts");
var metadata = require("metalsmith-metadata");
var watch = require("metalsmith-watch");
var serve = require("metalsmith-serve");
var browserify = require("metalsmith-browserify");
var less = require("metalsmith-less");

var FeedParser = require("feedparser");
var request = require("request");

var path = require("path");

// all retrieved posts from the feed
var retrievedPosts = {
  // in the order they came in
  all: [],
  // indexed by the GUID (probably unique URL)
  byguid: {}
};

/**
 *  Add `path` metadata to each page, so the template can tell what page
 *  it is programatically.
 **/
var addPath = function(files, metalsmith, done) {
  var dirname;
  var basename;
  for (var filePath in files) {
    dirname = path.dirname(filePath);
    files[filePath].path = (dirname == ".") ? "/" : "/" + dirname;
  }
  done();
};

var addRetrievedPosts = function (files, metalsmith, done) {
  for (var filePath in files) {
    files[filePath].retrievedPosts = retrievedPosts;
  }
  done();
};

/**
 *  Add `currentNavigation` to point to the top-level navigation item for
 *  rendering sub-navigation on a page.  This depends on the `addPath` plugin
 *  above.
 **/
var addCurrentNav = function(files, metalsmith, done) {
  var navigation = metalsmith.metadata().navigation;

  var pagePath;
  var topLevelPagePath;
  var navItem;
  for (var filePath in files) {
    pagePath = files[filePath].path;
    topLevelPagePath = pagePath.split("/")[1];

    // find item in navigation metadata
    for (var navItemIndex in navigation) {
      navItem = navigation[navItemIndex];

      if (navItem.url.match(topLevelPagePath)) {
        //console.log(`Matched page '${pagePath}' with nav url '${navItem.url}'`);
        files[filePath].currentNavigation = navItem;
        break;
      }
    }

  }
  done();
};

var parseMonlamFeedItem = function (originalItem) {
  var enhancedItem = originalItem;

  if (originalItem) {

    //console.log("originalItem[\"rss:p\"]");
    //console.log(originalItem["rss:p"]);
    //console.log(originalItem["rss:p"][0]["a"]["img"]["@"]);
    //console.log(originalItem["rss:p"][1]["#"]);

    //console.log(originalItem.guid);

    enhancedItem.img = originalItem["rss:p"][0]["a"]["img"]["@"];
    enhancedItem.title = originalItem["rss:title"]["#"];
  }

  //console.log("enhancedItem");
  //console.log(enhancedItem);

  return enhancedItem;

};

/**
 *  Call this to begin to retrieve the monlam feed.
 *
 *  @param  {Function}  retrieveOrParserDone - This gets called when the
 *  retrieve is finished, because it failed or finished parsing successfully.
 **/
var retrieveMonlamTagFeed = function (retrieveOrParserDone) {
  var url = "http://kagyuoffice.org/tag/kagyu-monlam/feed",
    req,
    parser;

  req = request(url);
  parser = new FeedParser();

  req.on('error', retrieveOrParserDone);
  req.on('response', function(res) {
    if (res.statusCode != 200) return this.emit('error', new Error('Bad status code'));
    //var charset = getParams(res.headers['content-type'] || '').charset;
    //res = maybeTranslate(res, charset);
    // And boom goes the dynamite
    res.pipe(parser);
  });

  parser.on('error', retrieveOrParserDone);
  parser.on('end', retrieveOrParserDone);
  parser.on('readable', function() {
    var post;
    while (post = parseMonlamFeedItem(this.read())) {
      retrievedPosts.all.push(post);
      retrievedPosts.byguid[post.guid] = post;
    }
  });
};

var builder = Metalsmith(__dirname)
  .ignore(["*.js", "*.swp"])
  .use(metadata({
    navigation: "navigation.yaml"
  }))
  .use(markdown())
  .use(addPath)
  .use(addCurrentNav)
  .use(addRetrievedPosts)
  .use(layouts({
    engine: "nunjucks",
    directory: "layouts",
    settings: {
      views: 'layouts'
    }
  }));

builder.use(less({
  pattern: "styles/index.less",
  // options for less compiler
  render: {
    paths: "src/styles/"
  },
  useDynamicSourceMap: true
}));

builder.use(browserify('build.js', [
  'src/index.js'
]));

if (process.argv.length > 2 && process.argv[2] == "watch") {
  // watch files for changes
  builder.use(watch({
    paths: {
      //"${source}/**/*": true,
      "layouts/**/*": "**/*.md",
      "${source}/styles/**/*": "**/*.less",
      "${source}/**/*.md": true
    },
    livereload: true
  }));

  builder.use(serve());
};

//console.log("Retrieving monlam feed...");
//retrieveMonlamTagFeed(function (err) {

  //if (err) {
    //console.log(err.stack);
    //throw err;
  //} else {
    //console.log("Building site...");
    //builder.build(function (err) {
      //if (err) {
        //console.log(err.stack);
        //throw err;
      //} else {
        //console.log("Build complete!");
      //}
    //});
  //}
//});

console.log("Building site...");
builder.build(function (err) {
  if (err) {
    console.log(err.stack);
    throw err;
  } else {
    console.log("Build complete!");
  }
});
<commit_msg>auto reload for site js changes<commit_after>var Metalsmith = require("metalsmith");
var markdown = require("metalsmith-markdown");
var layouts = require("metalsmith-layouts");
var metadata = require("metalsmith-metadata");
var watch = require("metalsmith-watch");
var serve = require("metalsmith-serve");
var browserify = require("metalsmith-browserify");
var less = require("metalsmith-less");

var FeedParser = require("feedparser");
var request = require("request");

var path = require("path");

// all retrieved posts from the feed
var retrievedPosts = {
  // in the order they came in
  all: [],
  // indexed by the GUID (probably unique URL)
  byguid: {}
};

/**
 *  Add `path` metadata to each page, so the template can tell what page
 *  it is programatically.
 **/
var addPath = function(files, metalsmith, done) {
  var dirname;
  var basename;
  for (var filePath in files) {
    dirname = path.dirname(filePath);
    files[filePath].path = (dirname == ".") ? "/" : "/" + dirname;
  }
  done();
};

var addRetrievedPosts = function (files, metalsmith, done) {
  for (var filePath in files) {
    files[filePath].retrievedPosts = retrievedPosts;
  }
  done();
};

/**
 *  Add `currentNavigation` to point to the top-level navigation item for
 *  rendering sub-navigation on a page.  This depends on the `addPath` plugin
 *  above.
 **/
var addCurrentNav = function(files, metalsmith, done) {
  var navigation = metalsmith.metadata().navigation;

  var pagePath;
  var topLevelPagePath;
  var navItem;
  for (var filePath in files) {
    pagePath = files[filePath].path;
    topLevelPagePath = pagePath.split("/")[1];

    // find item in navigation metadata
    for (var navItemIndex in navigation) {
      navItem = navigation[navItemIndex];

      if (navItem.url.match(topLevelPagePath)) {
        //console.log(`Matched page '${pagePath}' with nav url '${navItem.url}'`);
        files[filePath].currentNavigation = navItem;
        break;
      }
    }

  }
  done();
};

var parseMonlamFeedItem = function (originalItem) {
  var enhancedItem = originalItem;

  if (originalItem) {

    //console.log("originalItem[\"rss:p\"]");
    //console.log(originalItem["rss:p"]);
    //console.log(originalItem["rss:p"][0]["a"]["img"]["@"]);
    //console.log(originalItem["rss:p"][1]["#"]);

    //console.log(originalItem.guid);

    enhancedItem.img = originalItem["rss:p"][0]["a"]["img"]["@"];
    enhancedItem.title = originalItem["rss:title"]["#"];
  }

  //console.log("enhancedItem");
  //console.log(enhancedItem);

  return enhancedItem;

};

/**
 *  Call this to begin to retrieve the monlam feed.
 *
 *  @param  {Function}  retrieveOrParserDone - This gets called when the
 *  retrieve is finished, because it failed or finished parsing successfully.
 **/
var retrieveMonlamTagFeed = function (retrieveOrParserDone) {
  var url = "http://kagyuoffice.org/tag/kagyu-monlam/feed",
    req,
    parser;

  req = request(url);
  parser = new FeedParser();

  req.on('error', retrieveOrParserDone);
  req.on('response', function(res) {
    if (res.statusCode != 200) return this.emit('error', new Error('Bad status code'));
    //var charset = getParams(res.headers['content-type'] || '').charset;
    //res = maybeTranslate(res, charset);
    // And boom goes the dynamite
    res.pipe(parser);
  });

  parser.on('error', retrieveOrParserDone);
  parser.on('end', retrieveOrParserDone);
  parser.on('readable', function() {
    var post;
    while (post = parseMonlamFeedItem(this.read())) {
      retrievedPosts.all.push(post);
      retrievedPosts.byguid[post.guid] = post;
    }
  });
};

var builder = Metalsmith(__dirname)
  .ignore(["*.js", "*.swp"])
  .use(metadata({
    navigation: "navigation.yaml"
  }))
  .use(markdown())
  .use(addPath)
  .use(addCurrentNav)
  .use(addRetrievedPosts)
  .use(layouts({
    engine: "nunjucks",
    directory: "layouts",
    settings: {
      views: 'layouts'
    }
  }));

builder.use(less({
  pattern: "styles/index.less",
  // options for less compiler
  render: {
    paths: "src/styles/"
  },
  useDynamicSourceMap: true
}));

builder.use(browserify('build.js', [
  'src/index.js'
]));

if (process.argv.length > 2 && process.argv[2] == "watch") {
  // watch files for changes
  builder.use(watch({
    paths: {
      //"${source}/**/*": true,
      "layouts/**/*": "**/*.md",
      "${source}/styles/**/*": "**/*.less",
      "${source}/**/*.md": true,
      "${source}/index.js": true
    },
    livereload: true
  }));

  builder.use(serve());
};

//console.log("Retrieving monlam feed...");
//retrieveMonlamTagFeed(function (err) {

  //if (err) {
    //console.log(err.stack);
    //throw err;
  //} else {
    //console.log("Building site...");
    //builder.build(function (err) {
      //if (err) {
        //console.log(err.stack);
        //throw err;
      //} else {
        //console.log("Build complete!");
      //}
    //});
  //}
//});

console.log("Building site...");
builder.build(function (err) {
  if (err) {
    console.log(err.stack);
    throw err;
  } else {
    console.log("Build complete!");
  }
});
<|endoftext|>