<commit_before>(function(global) {

  var defined = {};

  // indexOf polyfill for IE8
  var indexOf = Array.prototype.indexOf || function(item) {
    for (var i = 0, l = this.length; i < l; i++)
      if (this[i] === item)
        return i;
    return -1;
  }

  function dedupe(deps) {
    var newDeps = [];
    for (var i = 0, l = deps.length; i < l; i++)
      if (indexOf.call(newDeps, deps[i]) == -1)
        newDeps.push(deps[i])
    return newDeps;
  }

  function register(name, deps, declare, execute) {
    if (typeof name != 'string')
      throw "System.register provided no module name";

    var entry;

    // dynamic
    if (typeof declare == 'boolean') {
      entry = {
        declarative: false,
        deps: deps,
        execute: execute,
        executingRequire: declare
      };
    }
    else {
      // ES6 declarative
      entry = {
        declarative: true,
        deps: deps,
        declare: declare
      };
    }

    entry.name = name;

    // we never overwrite an existing define
    if (!(name in defined))
      defined[name] = entry;

    entry.deps = dedupe(entry.deps);

    // we have to normalize dependencies
    // (assume dependencies are normalized for now)
    // entry.normalizedDeps = entry.deps.map(normalize);
    entry.normalizedDeps = entry.deps;
  }

  function buildGroups(entry, groups) {
    groups[entry.groupIndex] = groups[entry.groupIndex] || [];

    if (indexOf.call(groups[entry.groupIndex], entry) != -1)
      return;

    groups[entry.groupIndex].push(entry);

    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = defined[depName];

      // not in the registry means already linked / ES6
      if (!depEntry || depEntry.evaluated)
        continue;

      // now we know the entry is in our unlinked linkage group
      var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);

      // the group index of an entry is always the maximum
      if (depEntry.groupIndex === undefined || depEntry.groupIndex < depGroupIndex) {

        // if already in a group, remove from the old group
        if (depEntry.groupIndex !== undefined) {
          groups[depEntry.groupIndex].splice(indexOf.call(groups[depEntry.groupIndex], depEntry), 1);

          // if the old group is empty, then we have a mixed depndency cycle
          if (groups[depEntry.groupIndex].length == 0)
            throw new TypeError("Mixed dependency cycle detected");
        }

        depEntry.groupIndex = depGroupIndex;
      }

      buildGroups(depEntry, groups);
    }
  }

  function link(name) {
    var startEntry = defined[name];

    startEntry.groupIndex = 0;

    var groups = [];

    buildGroups(startEntry, groups);

    var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
    for (var i = groups.length - 1; i >= 0; i--) {
      var group = groups[i];
      for (var j = 0; j < group.length; j++) {
        var entry = group[j];

        // link each group
        if (curGroupDeclarative)
          linkDeclarativeModule(entry);
        else
          linkDynamicModule(entry);
      }
      curGroupDeclarative = !curGroupDeclarative;
    }
  }

  // module binding records
  var moduleRecords = {};
  function getOrCreateModuleRecord(name) {
    return moduleRecords[name] || (moduleRecords[name] = {
      name: name,
      dependencies: [],
      exports: {}, // start from an empty module and extend
      importers: []
    })
  }

  function linkDeclarativeModule(entry) {
    // only link if already not already started linking (stops at circular)
    if (entry.module)
      return;

    var module = entry.module = getOrCreateModuleRecord(entry.name);
    var exports = entry.module.exports;

    var declaration = entry.declare.call(global, function(name, value) {
      module.locked = true;
      exports[name] = value;

      for (var i = 0, l = module.importers.length; i < l; i++) {
        var importerModule = module.importers[i];
        if (!importerModule.locked) {
          var importerIndex = indexOf.call(importerModule.dependencies, module);
          importerModule.setters[importerIndex](exports);
        }
      }

      module.locked = false;
      return value;
    });

    module.setters = declaration.setters;
    module.execute = declaration.execute;

    if (!module.setters || !module.execute)
      throw new TypeError("Invalid System.register form for " + entry.name);

    // now link all the module dependencies
    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = defined[depName];
      var depModule = moduleRecords[depName];

      // work out how to set depExports based on scenarios...
      var depExports;

      if (depModule) {
        depExports = depModule.exports;
      }
      else if (depEntry && !depEntry.declarative) {
        depExports = { 'default': depEntry.module.exports, __useDefault: true };
      }
      // in the module registry
      else if (!depEntry) {
        depExports = load(depName);
      }
      // we have an entry -> link
      else {
        linkDeclarativeModule(depEntry);
        depModule = depEntry.module;
        depExports = depModule.exports;
      }

      // only declarative modules have dynamic bindings
      if (depModule && depModule.importers) {
        depModule.importers.push(module);
        module.dependencies.push(depModule);
      }
      else
        module.dependencies.push(null);

      // run the setter for this dependency
      if (module.setters[i])
        module.setters[i](depExports);
    }
  }

  // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
  function getModule(name) {
    var exports;
    var entry = defined[name];

    if (!entry) {
      exports = load(name);
      if (!exports)
        throw new Error("Unable to load dependency " + name + ".");
    }

    else {
      if (entry.declarative)
        ensureEvaluated(name, []);

      else if (!entry.evaluated)
        linkDynamicModule(entry);

      exports = entry.module.exports;
    }

    if ((!entry || entry.declarative) && exports && exports.__useDefault)
      return exports['default'];

    return exports;
  }

  function linkDynamicModule(entry) {
    if (entry.module)
      return;

    var exports = {};

    var module = entry.module = { exports: exports, id: entry.name };

    // AMD requires execute the tree first
    if (!entry.executingRequire) {
      for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
        var depName = entry.normalizedDeps[i];
        var depEntry = defined[depName];
        if (depEntry)
          linkDynamicModule(depEntry);
      }
    }

    // now execute
    entry.evaluated = true;
    var output = entry.execute.call(global, function(name) {
      for (var i = 0, l = entry.deps.length; i < l; i++) {
        if (entry.deps[i] != name)
          continue;
        return getModule(entry.normalizedDeps[i]);
      }
      throw new TypeError('Module ' + name + ' not declared as a dependency.');
    }, exports, module);

    if (output)
      module.exports = output;
  }

  /*
   * Given a module, and the list of modules for this current branch,
   *  ensure that each of the dependencies of this module is evaluated
   *  (unless one is a circular dependency already in the list of seen
   *  modules, in which case we execute it)
   *
   * Then we evaluate the module itself depth-first left to right
   * execution to match ES6 modules
   */
  function ensureEvaluated(moduleName, seen) {
    var entry = defined[moduleName];

    // if already seen, that means it's an already-evaluated non circular dependency
    if (!entry || entry.evaluated || !entry.declarative)
      return;

    // this only applies to declarative modules which late-execute

    seen.push(moduleName);

    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      if (indexOf.call(seen, depName) == -1) {
        if (!defined[depName])
          load(depName);
        else
          ensureEvaluated(depName, seen);
      }
    }

    if (entry.evaluated)
      return;

    entry.evaluated = true;
    entry.module.execute.call(global);
  }

  // magical execution function
  var modules = {};
  function load(name) {
    if (modules[name])
      return modules[name];

    var entry = defined[name];

    // first we check if this module has already been defined in the registry
    if (!entry)
      throw "Module " + name + " not present.";

    // recursively ensure that the module and all its
    // dependencies are linked (with dependency group handling)
    link(name);

    // now handle dependency execution in correct order
    ensureEvaluated(name, []);

    // remove from the registry
    defined[name] = undefined;

    var module = entry.module.exports;

    if (!module || !entry.declarative && module.__esModule !== true)
      module = { 'default': module, __useDefault: true };

    // return the defined module object
    return modules[name] = module;
  };

  return function(mains, declare) {

    var System;
    var System = {
      register: register,
      get: load,
      set: function(name, module) {
        modules[name] = module;
      },
      newModule: function(module) {
        return module;
      },
      global: global
    };
    System.set('@empty', {});

    declare(System);

    for (var i = 0; i < mains.length; i++)
      load(mains[i]);
  }

})(typeof window != 'undefined' ? window : global)
/* (['mainModule'], function(System) {
  System.register(...);
}); */
<commit_msg>__esModule fix<commit_after>(function(global) {

  var defined = {};

  // indexOf polyfill for IE8
  var indexOf = Array.prototype.indexOf || function(item) {
    for (var i = 0, l = this.length; i < l; i++)
      if (this[i] === item)
        return i;
    return -1;
  }

  function dedupe(deps) {
    var newDeps = [];
    for (var i = 0, l = deps.length; i < l; i++)
      if (indexOf.call(newDeps, deps[i]) == -1)
        newDeps.push(deps[i])
    return newDeps;
  }

  function register(name, deps, declare, execute) {
    if (typeof name != 'string')
      throw "System.register provided no module name";

    var entry;

    // dynamic
    if (typeof declare == 'boolean') {
      entry = {
        declarative: false,
        deps: deps,
        execute: execute,
        executingRequire: declare
      };
    }
    else {
      // ES6 declarative
      entry = {
        declarative: true,
        deps: deps,
        declare: declare
      };
    }

    entry.name = name;

    // we never overwrite an existing define
    if (!(name in defined))
      defined[name] = entry;

    entry.deps = dedupe(entry.deps);

    // we have to normalize dependencies
    // (assume dependencies are normalized for now)
    // entry.normalizedDeps = entry.deps.map(normalize);
    entry.normalizedDeps = entry.deps;
  }

  function buildGroups(entry, groups) {
    groups[entry.groupIndex] = groups[entry.groupIndex] || [];

    if (indexOf.call(groups[entry.groupIndex], entry) != -1)
      return;

    groups[entry.groupIndex].push(entry);

    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = defined[depName];

      // not in the registry means already linked / ES6
      if (!depEntry || depEntry.evaluated)
        continue;

      // now we know the entry is in our unlinked linkage group
      var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);

      // the group index of an entry is always the maximum
      if (depEntry.groupIndex === undefined || depEntry.groupIndex < depGroupIndex) {

        // if already in a group, remove from the old group
        if (depEntry.groupIndex !== undefined) {
          groups[depEntry.groupIndex].splice(indexOf.call(groups[depEntry.groupIndex], depEntry), 1);

          // if the old group is empty, then we have a mixed depndency cycle
          if (groups[depEntry.groupIndex].length == 0)
            throw new TypeError("Mixed dependency cycle detected");
        }

        depEntry.groupIndex = depGroupIndex;
      }

      buildGroups(depEntry, groups);
    }
  }

  function link(name) {
    var startEntry = defined[name];

    startEntry.groupIndex = 0;

    var groups = [];

    buildGroups(startEntry, groups);

    var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
    for (var i = groups.length - 1; i >= 0; i--) {
      var group = groups[i];
      for (var j = 0; j < group.length; j++) {
        var entry = group[j];

        // link each group
        if (curGroupDeclarative)
          linkDeclarativeModule(entry);
        else
          linkDynamicModule(entry);
      }
      curGroupDeclarative = !curGroupDeclarative;
    }
  }

  // module binding records
  var moduleRecords = {};
  function getOrCreateModuleRecord(name) {
    return moduleRecords[name] || (moduleRecords[name] = {
      name: name,
      dependencies: [],
      exports: {}, // start from an empty module and extend
      importers: []
    })
  }

  function linkDeclarativeModule(entry) {
    // only link if already not already started linking (stops at circular)
    if (entry.module)
      return;

    var module = entry.module = getOrCreateModuleRecord(entry.name);
    var exports = entry.module.exports;

    var declaration = entry.declare.call(global, function(name, value) {
      module.locked = true;
      exports[name] = value;

      for (var i = 0, l = module.importers.length; i < l; i++) {
        var importerModule = module.importers[i];
        if (!importerModule.locked) {
          var importerIndex = indexOf.call(importerModule.dependencies, module);
          importerModule.setters[importerIndex](exports);
        }
      }

      module.locked = false;
      return value;
    });

    module.setters = declaration.setters;
    module.execute = declaration.execute;

    if (!module.setters || !module.execute)
      throw new TypeError("Invalid System.register form for " + entry.name);

    // now link all the module dependencies
    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      var depEntry = defined[depName];
      var depModule = moduleRecords[depName];

      // work out how to set depExports based on scenarios...
      var depExports;

      if (depModule) {
        depExports = depModule.exports;
      }
      else if (depEntry && !depEntry.declarative) {
        if (depEntry.module.exports && depEntry.module.exports.__esModule)
          depExports = depEntry.module.exports;
        else
          depExports = { 'default': depEntry.module.exports, __useDefault: true };
      }
      // in the module registry
      else if (!depEntry) {
        depExports = load(depName);
      }
      // we have an entry -> link
      else {
        linkDeclarativeModule(depEntry);
        depModule = depEntry.module;
        depExports = depModule.exports;
      }

      // only declarative modules have dynamic bindings
      if (depModule && depModule.importers) {
        depModule.importers.push(module);
        module.dependencies.push(depModule);
      }
      else
        module.dependencies.push(null);

      // run the setter for this dependency
      if (module.setters[i])
        module.setters[i](depExports);
    }
  }

  // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
  function getModule(name) {
    var exports;
    var entry = defined[name];

    if (!entry) {
      exports = load(name);
      if (!exports)
        throw new Error("Unable to load dependency " + name + ".");
    }

    else {
      if (entry.declarative)
        ensureEvaluated(name, []);

      else if (!entry.evaluated)
        linkDynamicModule(entry);

      exports = entry.module.exports;
    }

    if ((!entry || entry.declarative) && exports && exports.__useDefault)
      return exports['default'];

    return exports;
  }

  function linkDynamicModule(entry) {
    if (entry.module)
      return;

    var exports = {};

    var module = entry.module = { exports: exports, id: entry.name };

    // AMD requires execute the tree first
    if (!entry.executingRequire) {
      for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
        var depName = entry.normalizedDeps[i];
        var depEntry = defined[depName];
        if (depEntry)
          linkDynamicModule(depEntry);
      }
    }

    // now execute
    entry.evaluated = true;
    var output = entry.execute.call(global, function(name) {
      for (var i = 0, l = entry.deps.length; i < l; i++) {
        if (entry.deps[i] != name)
          continue;
        return getModule(entry.normalizedDeps[i]);
      }
      throw new TypeError('Module ' + name + ' not declared as a dependency.');
    }, exports, module);

    if (output)
      module.exports = output;
  }

  /*
   * Given a module, and the list of modules for this current branch,
   *  ensure that each of the dependencies of this module is evaluated
   *  (unless one is a circular dependency already in the list of seen
   *  modules, in which case we execute it)
   *
   * Then we evaluate the module itself depth-first left to right
   * execution to match ES6 modules
   */
  function ensureEvaluated(moduleName, seen) {
    var entry = defined[moduleName];

    // if already seen, that means it's an already-evaluated non circular dependency
    if (!entry || entry.evaluated || !entry.declarative)
      return;

    // this only applies to declarative modules which late-execute

    seen.push(moduleName);

    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
      var depName = entry.normalizedDeps[i];
      if (indexOf.call(seen, depName) == -1) {
        if (!defined[depName])
          load(depName);
        else
          ensureEvaluated(depName, seen);
      }
    }

    if (entry.evaluated)
      return;

    entry.evaluated = true;
    entry.module.execute.call(global);
  }

  // magical execution function
  var modules = {};
  function load(name) {
    if (modules[name])
      return modules[name];

    var entry = defined[name];

    // first we check if this module has already been defined in the registry
    if (!entry)
      throw "Module " + name + " not present.";

    // recursively ensure that the module and all its
    // dependencies are linked (with dependency group handling)
    link(name);

    // now handle dependency execution in correct order
    ensureEvaluated(name, []);

    // remove from the registry
    defined[name] = undefined;

    var module = entry.module.exports;

    if (!module || !entry.declarative && module.__esModule !== true)
      module = { 'default': module, __useDefault: true };

    // return the defined module object
    return modules[name] = module;
  };

  return function(mains, declare) {

    var System;
    var System = {
      register: register,
      get: load,
      set: function(name, module) {
        modules[name] = module;
      },
      newModule: function(module) {
        return module;
      },
      global: global
    };
    System.set('@empty', {});

    declare(System);

    for (var i = 0; i < mains.length; i++)
      load(mains[i]);
  }

})(typeof window != 'undefined' ? window : global)
/* (['mainModule'], function(System) {
  System.register(...);
}); */
<|endoftext|>


<commit_before>'use strict';

const Transformer   = require('shark-transformer');
const zopfli        = require('node-zopfli');
const extend        = require('node.extend');
const co            = require('co');
const VError        = require('verror');
const path          = require('path');
const Tree          = require('shark-tree');

const loggerOpName = 'transformer-zopfli';

module.exports = Transformer.extend({
	init: function() {
		this.options = extend({}, this.optionsDefault, this.options);
		this.zopfliResults = {};
	},

	parseBless: function(content, destPath, options) {
		var time = this.logger.time();
		var sizeBefore = content.length;
		try {
			if (!this.logger.inPipe()) {
				this.logger.info({
					opName: loggerOpName,
					opType: this.logger.OP_TYPE.STARTED
				}, path.basename(destPath));
			}

			var result = zopfli.gzipSync(new Buffer(content), options);

			this.logger.info({
				opName: loggerOpName,
				opType: this.logger.OP_TYPE.FINISHED_SUCCESS,
				duration: time.delta(),
				size: {before: sizeBefore, after: result.toString('utf8').length}
			}, this.logger.inPipe() ? '' : path.basename(destPath));

			return result;
		}
		catch (error) {
			this.logger.warn({
				opName: loggerOpName,
				opType: this.logger.OP_TYPE.FINISHED_ERROR,
				duration: time.delta()
			}, path.basename(destPath), error.message);
			throw new VError(error, 'Zopfli error');
		}
	},

	transformTree: function *() {
		try {
			var _tree = this.tree.getTree();
			for (var destPath in _tree) {
				if (_tree.hasOwnProperty(destPath)) {
					yield this.transformTreeConcreteDest(destPath, _tree[destPath]);
				}
			}
		}
		catch (error) {
			throw new VError(error, 'TransformerZopfli#transformTree');
		}
	},

	transformTreeConcreteDest: function *(destPath, srcCollection) {
		return srcCollection.forEachSeries(co.wrap(function *(srcFile, index, done) {
			try {
				var options = extend({}, this.options, srcCollection.getOptions().zopfli);

				if (options.enabled === false) {
					done();
					return;
				}

				var data = this.parseBless(
					srcFile.getContent(),
					destPath,
					options
				);

				this.zopfliResults[destPath] = data;
				done();
			}
			catch (error) {
				done(new VError(error, 'Bless#transformTreeConcreteDest error'));
			}
		}.bind(this)));
	},

	transformTreeWithZopfliResults: function *() {
		var zopfliResults = this.zopfliResults;
		if (Object.keys(zopfliResults).length === 0) {
			return;
		}

		for (var destPath in zopfliResults) {
			if (!zopfliResults.hasOwnProperty(destPath)) {
				continue;
			}

			var ext = path.extname(destPath);

			if (ext === '.gz') {
				continue;
			}

			var basename = path.basename(destPath, ext);
			var dirname = path.dirname(destPath);

			var newDestPath = path.join(dirname, basename + ext + '.gz');
			var newFiles = {};
			newFiles[newDestPath] = {
				files: [],
				options: this.tree.getSrcCollectionByDest(destPath).getOptions()
			};

			var newTree = yield Tree(newFiles, this.logger);

			var zopfliResult = zopfliResults[destPath];
			newTree.getSrcCollectionByDest(newDestPath).setContent(zopfliResult);

			this.tree.merge(newTree);
		}
	},

	treeToTree: function *() {
		try {
			yield this.tree.fillContent();

			yield this.transformTree();
			yield this.transformTreeWithZopfliResults();

			return this.tree;
		}
		catch (error) {
			throw new VError(error, 'TransformerZopfli#treeToTree');
		}
	}
});<commit_msg>Change logger opName<commit_after>'use strict';

const Transformer   = require('shark-transformer');
const zopfli        = require('node-zopfli');
const extend        = require('node.extend');
const co            = require('co');
const VError        = require('verror');
const path          = require('path');
const Tree          = require('shark-tree');

const loggerOpName = 'zopfli';

module.exports = Transformer.extend({
	init: function() {
		this.options = extend({}, this.optionsDefault, this.options);
		this.zopfliResults = {};
	},

	parseBless: function(content, destPath, options) {
		var time = this.logger.time();
		var sizeBefore = content.length;
		try {
			if (!this.logger.inPipe()) {
				this.logger.info({
					opName: loggerOpName,
					opType: this.logger.OP_TYPE.STARTED
				}, path.basename(destPath));
			}

			var result = zopfli.gzipSync(new Buffer(content), options);

			this.logger.info({
				opName: loggerOpName,
				opType: this.logger.OP_TYPE.FINISHED_SUCCESS,
				duration: time.delta(),
				size: {before: sizeBefore, after: result.toString('utf8').length}
			}, this.logger.inPipe() ? '' : path.basename(destPath));

			return result;
		}
		catch (error) {
			this.logger.warn({
				opName: loggerOpName,
				opType: this.logger.OP_TYPE.FINISHED_ERROR,
				duration: time.delta()
			}, path.basename(destPath), error.message);
			throw new VError(error, 'Zopfli error');
		}
	},

	transformTree: function *() {
		try {
			var _tree = this.tree.getTree();
			for (var destPath in _tree) {
				if (_tree.hasOwnProperty(destPath)) {
					yield this.transformTreeConcreteDest(destPath, _tree[destPath]);
				}
			}
		}
		catch (error) {
			throw new VError(error, 'TransformerZopfli#transformTree');
		}
	},

	transformTreeConcreteDest: function *(destPath, srcCollection) {
		return srcCollection.forEachSeries(co.wrap(function *(srcFile, index, done) {
			try {
				var options = extend({}, this.options, srcCollection.getOptions().zopfli);

				if (options.enabled === false) {
					this.logger.info('%s disabled, passing...', loggerOpName);
					done();
					return;
				}

				var data = this.parseBless(
					srcFile.getContent(),
					destPath,
					options
				);

				this.zopfliResults[destPath] = data;
				done();
			}
			catch (error) {
				done(new VError(error, 'Bless#transformTreeConcreteDest error'));
			}
		}.bind(this)));
	},

	transformTreeWithZopfliResults: function *() {
		var zopfliResults = this.zopfliResults;
		if (Object.keys(zopfliResults).length === 0) {
			return;
		}

		for (var destPath in zopfliResults) {
			if (!zopfliResults.hasOwnProperty(destPath)) {
				continue;
			}

			var ext = path.extname(destPath);

			if (ext === '.gz') {
				continue;
			}

			var basename = path.basename(destPath, ext);
			var dirname = path.dirname(destPath);

			var newDestPath = path.join(dirname, basename + ext + '.gz');
			var newFiles = {};
			newFiles[newDestPath] = {
				files: [],
				options: this.tree.getSrcCollectionByDest(destPath).getOptions()
			};

			var newTree = yield Tree(newFiles, this.logger);

			var zopfliResult = zopfliResults[destPath];
			newTree.getSrcCollectionByDest(newDestPath).setContent(zopfliResult);

			this.tree.merge(newTree);
		}
	},

	treeToTree: function *() {
		try {
			yield this.tree.fillContent();

			yield this.transformTree();
			yield this.transformTreeWithZopfliResults();

			return this.tree;
		}
		catch (error) {
			throw new VError(error, 'TransformerZopfli#treeToTree');
		}
	}
});<|endoftext|>


<commit_before>'use strict';
var events = require('events');
var _translatorImplements = [];
var _translator = {
  translate: function (word, callback) {
    for (var i in _translatorImplements) {
      var eachTranslator = _translatorImplements[i];
      if (!eachTranslator.translate) continue;
      eachTranslator.translate(word, callback);
    }
  }
};
module.exports = function init(translators) {
  _translatorImplements = translators || [];
  return _translator;
};<commit_msg>remove unused variable<commit_after>'use strict';
var _translatorImplements = [];
var _translator = {
  translate: function (word, callback) {
    for (var i in _translatorImplements) {
      var eachTranslator = _translatorImplements[i];
      if (!eachTranslator.translate) continue;
      eachTranslator.translate(word, callback);
    }
  }
};
module.exports = function init(translators) {
  _translatorImplements = translators || [];
  return _translator;
};<|endoftext|>


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

var Transport = require('../transport')
  , util = require('../util')
  , parser = require('engine.io-parser')
  , debug = require('debug')('engine.io-client:polling');

/**
 * Module exports.
 */

module.exports = Polling;

/**
 * Global reference.
 */

var global = util.global();

/**
 * Polling interface.
 *
 * @param {Object} opts
 * @api private
 */

function Polling(opts){
  Transport.call(this, opts);
}

/**
 * Inherits from Transport.
 */

util.inherits(Polling, Transport);

/**
 * Transport name.
 */

Polling.prototype.name = 'polling';

/**
 * Opens the socket (triggers polling). We write a PING message to determine
 * when the transport is open.
 *
 * @api private
 */

Polling.prototype.doOpen = function(){
  this.poll();
};

/**
 * Pauses polling.
 *
 * @param {Function} callback upon buffers are flushed and transport is paused
 * @api private
 */

Polling.prototype.pause = function(onPause){
  var pending = 0;
  var self = this;

  this.readyState = 'pausing';

  function pause(){
    debug('paused');
    self.readyState = 'paused';
    onPause();
  }

  if (this.polling || !this.writable) {
    var total = 0;

    if (this.polling) {
      debug('we are currently polling - waiting to pause');
      total++;
      this.once('pollComplete', function(){
        debug('pre-pause polling complete');
        --total || pause();
      });
    }

    if (!this.writable) {
      debug('we are currently writing - waiting to pause');
      total++;
      this.once('drain', function(){
        debug('pre-pause writing complete');
        --total || pause();
      });
    }
  } else {
    pause();
  }
};

/**
 * Starts polling cycle.
 *
 * @api public
 */

Polling.prototype.poll = function(){
  debug('polling');
  this.polling = true;
  this.doPoll();
  this.emit('poll');
};

/**
 * Overloads onData to detect payloads.
 *
 * @api private
 */

Polling.prototype.onData = function(data){
  var self = this;
  debug('polling got data %s', data);

  // decode payload
  parser.decodePayload(data, function(packet, index, total) {
    // if its the first message we consider the transport open
    if ('opening' == self.readyState) {
      self.onOpen();
    }

    // if its a close packet, we close the ongoing requests
    if ('close' == packet.type) {
      self.onClose();
      return false;
    }

    // otherwise bypass onData and handle the message
    self.onPacket(packet);

    // if we got data we're not polling
    self.polling = false;
    self.emit('pollComplete');

    if ('open' == self.readyState) {
      self.poll();
    } else {
      debug('ignoring poll - transport state "%s"', self.readyState);
    }
  });
};

/**
 * For polling, send a close packet.
 *
 * @api private
 */

Polling.prototype.doClose = function(){
  debug('sending close packet');
  this.send([{ type: 'close' }]);
};

/**
 * Writes a packets payload.
 *
 * @param {Array} data packets
 * @param {Function} drain callback
 * @api private
 */

Polling.prototype.write = function(packets){
  var self = this;
  this.writable = false;
  this.doWrite(parser.encodePayload(packets), function(){
    self.writable = true;
    self.emit('drain');
  });
};

/**
 * Generates uri for connection.
 *
 * @api private
 */

Polling.prototype.uri = function(){
  var query = this.query || {};
  var schema = this.secure ? 'https' : 'http';
  var port = '';

  // cache busting is forced for IE / android / iOS6 ಠ_ಠ
  if (global.ActiveXObject || util.ua.android || util.ua.ios6 ||
      this.timestampRequests) {
    query[this.timestampParam] = +new Date;
  }

  query = util.qs(query);

  // avoid port if default for schema
  if (this.port && (('https' == schema && this.port != 443) ||
     ('http' == schema && this.port != 80))) {
    port = ':' + this.port;
  }

  // prepend ? to query
  if (query.length) {
    query = '?' + query;
  }

  return schema + '://' + this.hostname + port + this.path + query;
};
<commit_msg>polling: consider the possibility of an event changing readyState<commit_after>/**
 * Module dependencies.
 */

var Transport = require('../transport')
  , util = require('../util')
  , parser = require('engine.io-parser')
  , debug = require('debug')('engine.io-client:polling');

/**
 * Module exports.
 */

module.exports = Polling;

/**
 * Global reference.
 */

var global = util.global();

/**
 * Polling interface.
 *
 * @param {Object} opts
 * @api private
 */

function Polling(opts){
  Transport.call(this, opts);
}

/**
 * Inherits from Transport.
 */

util.inherits(Polling, Transport);

/**
 * Transport name.
 */

Polling.prototype.name = 'polling';

/**
 * Opens the socket (triggers polling). We write a PING message to determine
 * when the transport is open.
 *
 * @api private
 */

Polling.prototype.doOpen = function(){
  this.poll();
};

/**
 * Pauses polling.
 *
 * @param {Function} callback upon buffers are flushed and transport is paused
 * @api private
 */

Polling.prototype.pause = function(onPause){
  var pending = 0;
  var self = this;

  this.readyState = 'pausing';

  function pause(){
    debug('paused');
    self.readyState = 'paused';
    onPause();
  }

  if (this.polling || !this.writable) {
    var total = 0;

    if (this.polling) {
      debug('we are currently polling - waiting to pause');
      total++;
      this.once('pollComplete', function(){
        debug('pre-pause polling complete');
        --total || pause();
      });
    }

    if (!this.writable) {
      debug('we are currently writing - waiting to pause');
      total++;
      this.once('drain', function(){
        debug('pre-pause writing complete');
        --total || pause();
      });
    }
  } else {
    pause();
  }
};

/**
 * Starts polling cycle.
 *
 * @api public
 */

Polling.prototype.poll = function(){
  debug('polling');
  this.polling = true;
  this.doPoll();
  this.emit('poll');
};

/**
 * Overloads onData to detect payloads.
 *
 * @api private
 */

Polling.prototype.onData = function(data){
  var self = this;
  debug('polling got data %s', data);

  // decode payload
  parser.decodePayload(data, function(packet, index, total) {
    // if its the first message we consider the transport open
    if ('opening' == self.readyState) {
      self.onOpen();
    }

    // if its a close packet, we close the ongoing requests
    if ('close' == packet.type) {
      self.onClose();
      return false;
    }

    // otherwise bypass onData and handle the message
    self.onPacket(packet);
  });

  // if an event did not trigger closing
  if ('closed' != this.readyState) {
    // if we got data we're not polling
    this.polling = false;
    this.emit('pollComplete');

    if ('open' == this.readyState) {
      this.poll();
    } else {
      debug('ignoring poll - transport state "%s"', this.readyState);
    }
  }
};

/**
 * For polling, send a close packet.
 *
 * @api private
 */

Polling.prototype.doClose = function(){
  debug('sending close packet');
  this.send([{ type: 'close' }]);
};

/**
 * Writes a packets payload.
 *
 * @param {Array} data packets
 * @param {Function} drain callback
 * @api private
 */

Polling.prototype.write = function(packets){
  var self = this;
  this.writable = false;
  this.doWrite(parser.encodePayload(packets), function(){
    self.writable = true;
    self.emit('drain');
  });
};

/**
 * Generates uri for connection.
 *
 * @api private
 */

Polling.prototype.uri = function(){
  var query = this.query || {};
  var schema = this.secure ? 'https' : 'http';
  var port = '';

  // cache busting is forced for IE / android / iOS6 ಠ_ಠ
  if (global.ActiveXObject || util.ua.android || util.ua.ios6 ||
      this.timestampRequests) {
    query[this.timestampParam] = +new Date;
  }

  query = util.qs(query);

  // avoid port if default for schema
  if (this.port && (('https' == schema && this.port != 443) ||
     ('http' == schema && this.port != 80))) {
    port = ':' + this.port;
  }

  // prepend ? to query
  if (query.length) {
    query = '?' + query;
  }

  return schema + '://' + this.hostname + port + this.path + query;
};
<|endoftext|>


<commit_before>

var $ = require('jquery');
var d3 = require('d3');

/**
 * Click on the heatmap, scroll the source.
 *
 * @param {Heatmap} heatmap: A Heatmap instance.
 */

var ClickScroll = function(heatmap) {
  this.heatmap = heatmap;
  this._initEvents();
};

/**
 * Scroll the source when the heatmap is clicked.
 */

ClickScroll.prototype._initEvents = function() {

  var self = this;

  this.heatmap.target.on('click', function() {

    // Get the click offset in source-space pixels
    var height = self.heatmap.getSourcePx(d3.mouse(this)[1]);

    // Scroll the source container.
    $('body').animate({
      scrollTop: height - 200
    }, {
      duration: 200
    });

  });

};

module.exports = ClickScroll;
<commit_msg>Makes it possible to pass options into ClickScroll.<commit_after>

var $ = require('jquery');
var _ = require('lodash');
var d3 = require('d3');

/**
 * Click on the heatmap, scroll the source.
 *
 * @param {Heatmap} heatmap: A Heatmap instance.
 * @param {Options} options: Custom options.
 */

var ClickScroll = function(heatmap, options) {

  this.heatmap = heatmap;

  var opts = {
    container:  $('body'),
    padding:    200,
    duration:   200
  };

  this.options = _.extend(opts, options);
  this._initEvents();

};

/**
 * Scroll the source when the heatmap is clicked.
 */

ClickScroll.prototype._initEvents = function() {

  var self = this;

  this.heatmap.target.on('click', function() {

    // Get the click offset in source pixels
    var height = self.heatmap.getSourcePx(d3.mouse(this)[1]);

    // Scroll the source container.
    self.options.container.animate({
      scrollTop: height - self.options.padding
    }, {
      duration: self.options.duration
    });

  });

};

module.exports = ClickScroll;
<|endoftext|>


<commit_before>var Subscriber = require('./event_stream_sub');
var Synchronizer = require('./event_stream_sync');
var Client = require('./rrtw_client');
var util = require('./util');

var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var Agent = function(socket, partition) {
	EventEmitter.call(this);
	this._client = new Client(socket, '/tw');
	this._partition = partition;
	this._synchronizer = new Synchronizer(this._partition);
	this._subscriber = new Subscriber(this._client, this._versionProvider.bind(this), this._commitsCallback.bind(this));
};

inherits(Agent, EventEmitter);

Agent.prototype.start = function() {
	// :)
};

Agent.prototype.stop = function() {
	// :(
};

Agent.prototype.subscribe = function(streamId) {
	var handle = this._subscriber.subscribe(streamId);
	console.log('handle', handle);
	return handle;
};

Agent.prototype._commitsCallback = function(commits, callback) {
	var self = this;
	if(commits && commits.length > 0) {
		var commit = commits[0];
		var streamId = commit.streamId;
		var aggregateType = commit.aggregateType;
		this._synchronizer._processCommits(commits, streamId).then(function(conflicted) {
			// console.log("MERGE RESULT: " + conflicted);
			if(conflicted) {
				self.emit('conflict', {
					streamId: streamId,
					aggregateType: aggregateType
				});
			}
			callback(null, commits);
		});
	} else {
		callback(null, []);
	}
};

Agent.prototype._versionProvider = function(streamId) {
	return this._partition._queryStream(streamId).then(function(localCommits) {
		var lastCommit = util.getLastAuthorizedCommitSequence(localCommits);
		return lastCommit;
	});
};

module.exports = Agent;
<commit_msg>remove console log<commit_after>var Subscriber = require('./event_stream_sub');
var Synchronizer = require('./event_stream_sync');
var Client = require('./rrtw_client');
var util = require('./util');

var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;

var Agent = function(socket, partition) {
	EventEmitter.call(this);
	this._client = new Client(socket, '/tw');
	this._partition = partition;
	this._synchronizer = new Synchronizer(this._partition);
	this._subscriber = new Subscriber(this._client, this._versionProvider.bind(this), this._commitsCallback.bind(this));
};

inherits(Agent, EventEmitter);

Agent.prototype.start = function() {
	// :)
};

Agent.prototype.stop = function() {
	// :(
};

Agent.prototype.subscribe = function(streamId) {
	var handle = this._subscriber.subscribe(streamId);
	return handle;
};

Agent.prototype._commitsCallback = function(commits, callback) {
	var self = this;
	if(commits && commits.length > 0) {
		var commit = commits[0];
		var streamId = commit.streamId;
		var aggregateType = commit.aggregateType;
		this._synchronizer._processCommits(commits, streamId).then(function(conflicted) {
			// console.log("MERGE RESULT: " + conflicted);
			if(conflicted) {
				self.emit('conflict', {
					streamId: streamId,
					aggregateType: aggregateType
				});
			}
			callback(null, commits);
		});
	} else {
		callback(null, []);
	}
};

Agent.prototype._versionProvider = function(streamId) {
	return this._partition._queryStream(streamId).then(function(localCommits) {
		var lastCommit = util.getLastAuthorizedCommitSequence(localCommits);
		return lastCommit;
	});
};

module.exports = Agent;
<|endoftext|>


<commit_before>require('../common');

var Dirty = require('Dirty');
var db = new Dirty('undef-key.dirty');

db.set('now', Date.now());

db.set('gobble', 'adfasdf');

db.set('now', undefined, function() {
	// callback?
	// impossible yes?!
	console.log('blamo!')
});

db.set(undefined);

console.log(db.get('now'));

// db = require('Dirty')('undef-key.dirty');
<commit_msg>Delete unused test file<commit_after><|endoftext|>


<commit_before>var _ = require('lodash');

module.exports = function() {
  // This module is included into the `bookshelf` repository,
  // and run from the root of the directory.
  var path     = require('path');
  var basePath = process.cwd();
  var Sync = require(path.resolve(basePath + '/lib/sync'));

  describe('Sync', function() {
    var stubSync = function() {
      var qd = [];
      var stubQuery = function() {
        qd.push(_.toArray(arguments));
        return this;
      };
      return {
        id: 1,
        idAttribute: 'id',
        tableName: 'testtable',
        format: _.identity,
        isNew: function() {
          return true
        },
        queryData: qd,
        query: function() {
          return {
            where: stubQuery,
            limit: stubQuery
          };
        },
        resetQuery: function() {
          return this;
        }
      };
    };

    describe('prefixFields', function() {
      it('should prefix all keys of the passed in object with the tablename', function () {
        var sync = new Sync(stubSync());
        var attributes = {
          'some': 'column',
          'another': 'column'
        };

        expect(sync.prefixFields(attributes)).to.eql({
          'testtable.some':'column',
          'testtable.another':'column'
        });
      });

      it('should run after format', function() {
        var attributes = {
          'Some': 'column',
          'Another': 'column'
        };
        var sync = new Sync(_.extend(stubSync(), {
          format: function(attrs) {
            var data = {};
            for (var key in attrs) {
              data[key.toLowerCase()] = attrs[key];
            }
            return data;
          }
        }));

        sync.select = function() {
          expect(this.syncing.queryData[0]).to.eql([{
            "testtable.some": "column",
            "testtable.another": "column"
          }]);
        };

        return sync.first(attributes);
      });
    });

    describe('update', function() {
      it('doesn\'t try to update the primary key if it hasn\'t changed', function() {
        var sync = new Sync(stubSync())
        _.extend(sync.query, {
          update: function(attrs) {
            expect(attrs).to.not.have.property('id');
          },
          where: function() {
            this._statements = [{grouping: 'where'}]
          }
        })

        return sync.update({id: 1, name: 'something'})
      })
    })
  });
};
<commit_msg>Add test to check that id can be updated<commit_after>var _ = require('lodash');

module.exports = function() {
  // This module is included into the `bookshelf` repository,
  // and run from the root of the directory.
  var path     = require('path');
  var basePath = process.cwd();
  var Sync = require(path.resolve(basePath + '/lib/sync'));

  describe('Sync', function() {
    var stubSync = function() {
      var qd = [];
      var stubQuery = function() {
        qd.push(_.toArray(arguments));
        return this;
      };
      return {
        id: 1,
        idAttribute: 'id',
        tableName: 'testtable',
        format: _.identity,
        isNew: function() {
          return true
        },
        queryData: qd,
        query: function() {
          return {
            where: stubQuery,
            limit: stubQuery
          };
        },
        resetQuery: function() {
          return this;
        }
      };
    };

    describe('prefixFields', function() {
      it('should prefix all keys of the passed in object with the tablename', function () {
        var sync = new Sync(stubSync());
        var attributes = {
          'some': 'column',
          'another': 'column'
        };

        expect(sync.prefixFields(attributes)).to.eql({
          'testtable.some':'column',
          'testtable.another':'column'
        });
      });

      it('should run after format', function() {
        var attributes = {
          'Some': 'column',
          'Another': 'column'
        };
        var sync = new Sync(_.extend(stubSync(), {
          format: function(attrs) {
            var data = {};
            for (var key in attrs) {
              data[key.toLowerCase()] = attrs[key];
            }
            return data;
          }
        }));

        sync.select = function() {
          expect(this.syncing.queryData[0]).to.eql([{
            "testtable.some": "column",
            "testtable.another": "column"
          }]);
        };

        return sync.first(attributes);
      });
    });

    describe('update', function() {
      it('doesn\'t try to update the primary key if it hasn\'t changed', function() {
        var sync = new Sync(stubSync());
        _.extend(sync.query, {
          update: function(attrs) {
            expect(attrs).to.not.have.property('id');
          },
          where: function() {
            this._statements = [{grouping: 'where'}];
          }
        });

        return sync.update({id: 1, name: 'something'});
      });

      it('will update the primary key if it has changed', function() {
        var sync = new Sync(stubSync());
        _.extend(sync.query, {
          update: function(attrs) {
            expect(attrs).to.have.property('id');
            expect(attrs.id).to.equal(2);
          },
          where: function() {
            this._statements = [{grouping: 'where'}];
          }
        });

        return sync.update({id: 2, name: 'something'});
      })
    })
  });
};
<|endoftext|>


<commit_before>/**
 * lei-crawler
 *
 * @author Zongmin Lei <leizongmin@gmail.com>
 */

var Redis = require('ioredis');
var async = require('async');
var utils = require('./utils');
var simpleRequest = require('./request')
var debug = utils.debug('collect_urls');

module.exports = exports = function (options) {
  return new URLCollector(options);
};

// 默认深度
exports.DEFAULT_DEPTH = 1;
// 默认URL列表缓存时间
exports.DEFAULT_CACHE_TTL = 3600 * 24;
// 默认用来筛选符合深度抓取URL的函数
exports.DEFAULT_FILTER_DEPTH = function (url, currentURL) {
  // 默认只抓取站内的数据
  var baseURL = utils.getBaseURLFromURL(currentURL) + '/';
  return (url.indexOf(baseURL) === 0);
};
// 默认用来筛选符合存储条件的URL的函数
exports.DEFAULT_FILTER_RESULT = function (url, currentURL) {
  // 默认收集全部URL
  return true;
};
// 默认request函数
exports.DEFAULT_REQUEST = simpleRequest();

/**
 * URLCollector
 *
 * @param {Object} options
 *   - {String} name
 *   - {Number} depth
 *   - {Number} cacheTTL
 *   - {Function} filterDepth
 *   - {Function} filterResult
 *   - {Object} store
 *   - {Function} request
 */
function URLCollector (options) {
  options = utils.merge({
    depth: exports.DEFAULT_DEPTH,
    cacheTTL: exports.DEFAULT_CACHE_TTL,
    filterDepth: exports.DEFAULT_FILTER_DEPTH,
    filterResult: exports.DEFAULT_FILTER_RESULT,
    request: exports.DEFAULT_REQUEST
  }, options || {});
  this._options = options;

  if (!options.name) return new TypeError('missing parameter `name`');
  if (!options.store) return new TypeError('missing parameter `store`');

  debug('new URLCollector(options=%j)', options);
}

URLCollector.prototype._getRedisKey = function (key) {
  return this._options.name + ':' + key;
};

URLCollector.prototype._getURLCacheKey = function (url) {
  return this._getRedisKey('cache:urls:' + utils.md5(url));
};

URLCollector.prototype._encodeURLValue = function (depth, url) {
  return depth + ':' + url;
};

URLCollector.prototype._decodeURLValue = function (str) {
  var i = str.indexOf(':');
  if (i === -1) return {depth: 0, url: str};
  return {depth: Number(str.slice(0, i)), url: str.slice(i + 1)};
};

URLCollector.prototype._collectPage = function (depth, url, callback) {
  debug('_collectPage[depth=%s]: %s', depth, url);
  var self = this;
  var value = self._encodeURLValue(depth, url);

  self._options.store.sExists(self._getRedisKey('collected'), value, function (err, yes) {
    if (err) return callback(err);
    if (yes) {
      debug('already collected [depth=%s]: %s', depth, url);
      return callback();
    }

    self._loadURL(url, function (err, list) {
      if (err) return callback(err);

      async.series([
        function (next) {

          // 将当前URL设置为已采集过
          debug('collected: %s', url);
          self._options.store.sAdd(self._getRedisKey('collected'), value, next);

        },
        function (next) {

          // 存储深度搜索的URL结果
          var nextDepth = depth - 1;
          if (nextDepth < 0) return next();
          var depthList = list.filter(function (item) {
            return self._options.filterDepth(item, url);
          }).map(function (item) {
            return self._encodeURLValue(nextDepth, item);
          });
          self._options.store.sAdd(self._getRedisKey('wait'), depthList, next);
          debug('add %s URLs to wait list => %j', depthList.length, depthList);

        },
        function (next) {

          // 存储采集到的URL结果
          var resultList = list.filter(function (item) {
            return self._options.filterResult(item, url);
          });

          self._options.store.sInter(self._getRedisKey('finished'), resultList, function (err, finishedList) {
            if (err) return next(err);

            // 仅存储不在finished中的结果
            resultList = resultList.filter(function (item) {
              return (finishedList.indexOf(item) === -1);
            });

            self._options.store.sAdd(self._getRedisKey('result'), resultList, next);
            debug('save %s URLs to result list => %j', resultList.length, resultList);
          });

        }
      ], callback);
    });
  });
};

URLCollector.prototype._loadURL = function (url, callback) {
  var self = this;
  self._loadURLFromCache(url, function (err, list) {
    if (err) return callback(err);
    if (list) return callback(null, list);

    self._loadURLFromRequest(url, callback);
  });
};

URLCollector.prototype._loadURLFromRequest = function (url, callback) {
  var self = this;
  self._options.request({url: url, cheerio: true}, function (err, contentType, body, $) {
    if (err) return callback(err);

    var list = [];
    if (contentType.indexOf('text/html') !== -1) {
      $('a').each(function () {
        var href = utils.trim($(this).attr('href'));
        if (href) {
          list.push(utils.getAbsoluteURL(url, href));
        }
      });
    } else {
      debug('contentType is %s, not text/html, ignore', contentType);
    }

    var key = self._getURLCacheKey(url);
    self._options.store.setCache(key, JSON.stringify(list), self._options.cacheTTL, function (err) {
      callback(err, list);
    });
  });
};

URLCollector.prototype._loadURLFromCache = function (url, callback) {
  var self = this;
  var key = self._getURLCacheKey(url)
  self._options.store.get(key, function (err, data) {
    if (err) return callback(err);
    if (!data) return callback(null, null);

    try {
      data = JSON.parse(data);
    } catch (err) {
      return callback(err);
    }

    callback(null, data);
  });
};

URLCollector.prototype.start = function (url, callback) {
  debug('start');
  var self = this;

  function ignoreError (fn) {
    return function (err) {
      if (err) console.error(err);
      var args = Array.prototype.slice.call(arguments);
      args[0] = null;
      fn.apply(null, args);
    };
  }

  async.series([
    function (next) {

      // 为了能正常开始，要将起始页面的URL先从已采集的结果中移除
      var value = self._encodeURLValue(self._options.depth, url);
      self._options.store.sRemove(self._getRedisKey('collected'), [value], ignoreError(next));

    },
    function (next) {

      // 删除当前URL的结果缓存，以便能重新开始
      self._options.store.delete(self._getURLCacheKey(url), next);

    },
    function (next) {

      // 采集起始URL
      self._collectPage(self._options.depth, url, ignoreError(next));

    },
    function (next) {

      var callback = ignoreError(next);

      // 采集wait列表中的URL，直到全部完成
      function nextPage (err) {
        if (err) console.error(err);

        self._options.store.sGet(self._getRedisKey('wait'), function (err, data) {
          if (err) callback(err);
          if (!data) {
            debug('end');
            return callback();
          }

          data = self._decodeURLValue(data);
          self._collectPage(data.depth, data.url, nextPage);
        });
      }

      nextPage();

    }
  ], callback);
};
<commit_msg>collectURLs() 增加 limit 选项<commit_after>/**
 * lei-crawler
 *
 * @author Zongmin Lei <leizongmin@gmail.com>
 */

var Redis = require('ioredis');
var async = require('async');
var utils = require('./utils');
var simpleRequest = require('./request')
var debug = utils.debug('collect_urls');

module.exports = exports = function (options) {
  return new URLCollector(options);
};

// 默认深度
exports.DEFAULT_DEPTH = 1;
// 默认URL列表缓存时间
exports.DEFAULT_CACHE_TTL = 3600 * 24;
// 默认用来筛选符合深度抓取URL的函数
exports.DEFAULT_FILTER_DEPTH = function (url, currentURL) {
  // 默认只抓取站内的数据
  var baseURL = utils.getBaseURLFromURL(currentURL) + '/';
  return (url.indexOf(baseURL) === 0);
};
// 默认用来筛选符合存储条件的URL的函数
exports.DEFAULT_FILTER_RESULT = function (url, currentURL) {
  // 默认收集全部URL
  return true;
};
// 默认request函数
exports.DEFAULT_REQUEST = simpleRequest();

/**
 * URLCollector
 *
 * @param {Object} options
 *   - {String} name
 *   - {Number} depth
 *   - {Number} cacheTTL
 *   - {Function} filterDepth
 *   - {Function} filterResult
 *   - {Object} store
 *   - {Function} request
 */
function URLCollector (options) {
  options = utils.merge({
    depth: exports.DEFAULT_DEPTH,
    cacheTTL: exports.DEFAULT_CACHE_TTL,
    filterDepth: exports.DEFAULT_FILTER_DEPTH,
    filterResult: exports.DEFAULT_FILTER_RESULT,
    request: exports.DEFAULT_REQUEST
  }, options || {});
  this._options = options;

  if (!options.name) return new TypeError('missing parameter `name`');
  if (!options.store) return new TypeError('missing parameter `store`');

  debug('new URLCollector(options=%j)', options);
}

URLCollector.prototype._getRedisKey = function (key) {
  return this._options.name + ':' + key;
};

URLCollector.prototype._getURLCacheKey = function (url) {
  return this._getRedisKey('cache:urls:' + utils.md5(url));
};

URLCollector.prototype._encodeURLValue = function (depth, url) {
  return depth + ':' + url;
};

URLCollector.prototype._decodeURLValue = function (str) {
  var i = str.indexOf(':');
  if (i === -1) return {depth: 0, url: str};
  return {depth: Number(str.slice(0, i)), url: str.slice(i + 1)};
};

URLCollector.prototype._collectPage = function (depth, url, callback) {
  debug('_collectPage[depth=%s]: %s', depth, url);
  var self = this;
  var value = self._encodeURLValue(depth, url);

  self._options.store.sExists(self._getRedisKey('collected'), value, function (err, yes) {
    if (err) return callback(err);
    if (yes) {
      debug('already collected [depth=%s]: %s', depth, url);
      return callback();
    }

    self._loadURL(url, function (err, list) {
      if (err) return callback(err);

      async.series([
        function (next) {

          // 将当前URL设置为已采集过
          debug('collected: %s', url);
          self._options.store.sAdd(self._getRedisKey('collected'), value, next);

        },
        function (next) {

          // 存储深度搜索的URL结果
          var nextDepth = depth - 1;
          if (nextDepth < 0) return next();
          var depthList = list.filter(function (item) {
            return self._options.filterDepth(item, url);
          }).map(function (item) {
            return self._encodeURLValue(nextDepth, item);
          });
          self._options.store.sAdd(self._getRedisKey('wait'), depthList, next);
          debug('add %s URLs to wait list => %j', depthList.length, depthList);

        },
        function (next) {

          // 存储采集到的URL结果
          var resultList = list.filter(function (item) {
            return self._options.filterResult(item, url);
          });

          self._options.store.sInter(self._getRedisKey('finished'), resultList, function (err, finishedList) {
            if (err) return next(err);

            // 仅存储不在finished中的结果
            resultList = resultList.filter(function (item) {
              return (finishedList.indexOf(item) === -1);
            });

            self._options.store.sAdd(self._getRedisKey('result'), resultList, next);
            debug('save %s URLs to result list => %j', resultList.length, resultList);
          });

        }
      ], callback);
    });
  });
};

URLCollector.prototype._loadURL = function (url, callback) {
  var self = this;
  self._loadURLFromCache(url, function (err, list) {
    if (err) return callback(err);
    if (list) return callback(null, list);

    self._loadURLFromRequest(url, callback);
  });
};

URLCollector.prototype._loadURLFromRequest = function (url, callback) {
  var self = this;
  self._options.request({url: url, cheerio: true}, function (err, contentType, body, $) {
    if (err) return callback(err);

    var list = [];
    if (contentType.indexOf('text/html') !== -1) {
      $('a').each(function () {
        var href = utils.trim($(this).attr('href'));
        if (href) {
          list.push(utils.getAbsoluteURL(url, href));
        }
      });
    } else {
      debug('contentType is %s, not text/html, ignore', contentType);
    }

    var key = self._getURLCacheKey(url);
    self._options.store.setCache(key, JSON.stringify(list), self._options.cacheTTL, function (err) {
      callback(err, list);
    });
  });
};

URLCollector.prototype._loadURLFromCache = function (url, callback) {
  var self = this;
  var key = self._getURLCacheKey(url)
  self._options.store.get(key, function (err, data) {
    if (err) return callback(err);
    if (!data) return callback(null, null);

    try {
      data = JSON.parse(data);
    } catch (err) {
      return callback(err);
    }

    callback(null, data);
  });
};

/**
 * start
 *
 * @param {Object} options
 *   - {String} url
 *   - {Number} limit
 */
URLCollector.prototype.start = function (options, callback) {
  options = options || {};
  if (typeof options === 'string') options = {url: options};
  debug('start: options=%j', options);
  if (!options.url) return callback(new TypeError('missing parameter `url`'));

  var self = this;

  function ignoreError (fn) {
    return function (err) {
      if (err) console.error(err);
      var args = Array.prototype.slice.call(arguments);
      args[0] = null;
      fn.apply(null, args);
    };
  }

  async.series([
    function (next) {

      // 为了能正常开始，要将起始页面的URL先从已采集的结果中移除
      var value = self._encodeURLValue(self._options.depth, options.url);
      self._options.store.sRemove(self._getRedisKey('collected'), [value], ignoreError(next));

    },
    function (next) {

      // 删除当前URL的结果缓存，以便能重新开始
      self._options.store.delete(self._getURLCacheKey(options.url), next);

    },
    function (next) {

      // 采集起始URL
      self._collectPage(self._options.depth, options.url, ignoreError(next));

    },
    function (next) {

      var callback = ignoreError(next);

      // 采集wait列表中的URL，直到全部完成
      var counter = 0;
      function nextPage (err) {
        if (err) console.error(err);

        counter++;
        if (options.limit > 0 && counter > options.limit) {
          debug('out of limit (limit=%s)', options.limit);
          return callback();
        }

        self._options.store.sGet(self._getRedisKey('wait'), function (err, data) {
          if (err) callback(err);
          if (!data) {
            debug('end');
            return callback();
          }

          debug('collect URLs #%s data=%j', counter, data);
          data = self._decodeURLValue(data);
          self._collectPage(data.depth, data.url, nextPage);
        });
      }

      nextPage();

    }
  ], callback);
};
<|endoftext|>


<commit_before>'use strict'
/* dependencies */
var request = require('request')
var Observable = require('vjs/lib/observable')
var EmitError = require('vjs/lib/emitter/error')
var isValidUrl = require('../is/validurl')
var InvalidFormat = require('../errors/invalidformat')
var HttpRequestError = require('../errors/httprequesterror')

var error = EmitError()

function checkUrl (url) {
  if (!isValidUrl(url)) {
    error.emit(InvalidFormat('Invalid URl format: ' + url))
    return false
  }
  return true
}

function manageResponse (err, res, body) {
  if (err) {
    error.emit(HttpRequestError('Error performing the HTTP request: ' + err.message))
    return
  }
  // TODO meybe better res.statusCode management
  if (res.statusCode !== 200) {
    error.emit(HttpRequestError('HTTP Request endedn with status code: ' + res.statusCode))
    return
  }
  this.emit('data', body)
}

var HttpRequest = new Observable({
  define: {
    GET: function (url) {
      if (!checkUrl(url)) return
      return request.get({
        uri: url,
        gzip: true
      }, manageResponse.bind(this))
    },
    POST: function (url, data, json) {
      if (!checkUrl(url)) return
      var options = {
        body: data,
        uri: url,
        gzip: true
      }
      json ? options.json = true : void 0
      return request.post(options, manageResponse.bind(this))
    },
    PUT: function (url, data, json) {
      if (!checkUrl(url)) return
      var options = {
        body: data,
        uri: url,
        gzip: true
      }
      json ? options.json = true : void 0
      return request.put(options, manageResponse.bind(this))
    }
  }
})

module.exports = HttpRequest.Constructor

// var req = new HttpRequest.Constructor({
//   on: {
//     data: function (data, event) {
//       console.log(data)
//     }
//   }
// })
//
// req.GET('http://jsonplaceholder.typicode.com/posts')
// req.POST('http://jsonplaceholder.typicode.com/posts', {
//   userId: 1,
//   title: 'Test post',
//   body: 'my test content'
// }, true)
<commit_msg>added inline documentation<commit_after>'use strict'
/* dependencies */
var request = require('request')
var Observable = require('vjs/lib/observable')
var isValidUrl = require('../is/validurl')
var InvalidFormat = require('../errors/invalidformat')
var HttpRequestError = require('../errors/httprequesterror')

/**
 * Check if the URL passed as parameter is a valid url
 * and emits an InvalidFormat error if URL is not valid
 * @param  {String} url The URL to check
 * @return {boolean}
 */
function checkUrl (url) {
  if (!isValidUrl(url)) {
    this.emit('error', InvalidFormat('Invalid URl format: ' + url))
    return false
  }
  return true
}

/**
 * Offers a way to manage reponses and emit a `data` event with the body
 * @param  {Object} err  Request error, if any
 * @param  {Object} res  The http response
 * @param  {Object} body The response body
 */
function manageResponse (err, res, body) {
  if (err) {
    this.emit('error', HttpRequestError('Error performing the HTTP request: ' + err.message))
    return
  }
  // TODO meybe better res.statusCode management
  if (res.statusCode !== 200) {
    this.emit('error', HttpRequestError('HTTP Request endedn with status code: ' + res.statusCode))
    return
  }
  this.emit('data', body)
}

/**
 * Build options to use for performing requets
 * @param  {String}   url   The URL to use for performing the request
 * @param  {Object}   body  Can be a Buffer, a String or a JSON
 * @param  {boolean}  gzip  Add the Accept-Encoding header to request compressed content
 * @return {Object}         The request options object
 */
function getRequestOptions (url, body, gzip) {
  var opts = {
    uri: url
  }
  if (body) opts.body = body
  if (gzip) opts.gzip = true
  return opts
}

var HttpRequest = new Observable({
  define: {
    /**
     * Performs a GET request
     * @param {String} url Destination URL
     */
    GET: function (url) {
      if (!checkUrl(url)) return
      var opts = getRequestOptions(url, null, true)
      return request.get(opts, manageResponse.bind(this))
    },
    /**
     * Performs a POST request
     * @param {String}  url     Destination URL
     * @param {Object}  data    Can be a Buffer, a String or a JSON
     * @param {boolean} json    Specify if the body is a JSON object
     */
    POST: function (url, data, json) {
      if (!checkUrl(url)) return
      var opts = getRequestOptions(url, data, true)
      if (json) opts.json = true
      return request.post(opts, manageResponse.bind(this))
    },
    /**
     * Performs a PUT request
     * @param {String}  url     Destination URL
     * @param {Object}  data    Can be a Buffer, a String or a JSON
     * @param {boolean} json    Specify if the body is a JSON object
     */
    PUT: function (url, data, json) {
      if (!checkUrl(url)) return
      var opts = getRequestOptions(url, data, true)
      if (json) opts.json = true
      return request.put(opts, manageResponse.bind(this))
    },
    /**
     * Performs a PATCH request
     * @param {String}  url     Destination URL
     * @param {Object}  data    Can be a Buffer, a String or a JSON
     * @param {boolean} json    Specify if the body is a JSON object
     */
    PATCH: function (url, data, json) {
      if (!checkUrl(url)) return
      var opts = getRequestOptions(url, data, true)
      if (json) opts.json = true
      return request.patch(opts, manageResponse.bind(this))
    },
    /**
     * Performs a DELETE request
     * @param {String} url Destination URL
     */
    DELETE: function (url) {
      if (!checkUrl(url)) return
      var opts = getRequestOptions(url, null, true)
      return request.del(opts, manageResponse.bind(this))
    }
  }
})

module.exports = HttpRequest.Constructor

// USAGE EXAMPLE
//
// var req = new HttpRequest.Constructor({
//   on: {
//     data: function (data, event) {
//       console.log(data)
//     }
//   }
// })
//
// req.GET('http://jsonplaceholder.typicode.com/posts')
// req.POST('http://jsonplaceholder.typicode.com/posts', {
//   userId: 1,
//   title: 'Test post',
//   body: 'my test content'
// }, true)
// req.PUT('http://jsonplaceholder.typicode.com/posts/1', {
//   title: 'New Test post'
// }, true)
// req.PATCH('http://jsonplaceholder.typicode.com/posts/1', {
//   title: 'New bazz post'
// }, true)
// req.DELETE('http://jsonplaceholder.typicode.com/posts/1')
<|endoftext|>


<commit_before>function find(directory) {
    var files = [];
    var route, name;
    //TODO: Figure out how to handle relative paths to doc
    fs.readdirSync(directory).forEach(function(file) {

        if (filterFile(file)) return

        name = file.substr(0, file.indexOf('.'));
        /*
         * Dynamically include and initialize all route files.
         */
        try {
            route = require(_path.join(directory, name));

            files.push(route);
        } catch (e) {
            this.logger.error(e);
        }

    }.bind(this));

    return files;
}<commit_msg>UTILS: ModuleLoader wip<commit_after>function find(directory) {
    var files = [];
    var route, name;
    //TODO: Figure out how to handle relative paths to doc
    fs.readdirSync(directory).forEach(function(file) {

        if (filterFile(file)) return

        name = file.substr(0, file.indexOf('.'));
        /*
         * Dynamically include and initialize all route files.
         */
        try {
            route = require(_path.join(directory, name));

            files.push(route);
        } catch (e) {
            this.logger.error(e);
        }

    }.bind(this));

    return files;
}

var fs = require('fs');

exports.isValidModulePath = function(path) {
    return fs.existsSync(path + '.js') || fs.existsSync(path);
};

exports.loader = function(app, modpath) {

    if(!exports.isValidModulePath(modpath)) return false;

    var module;
    try {
        module = require(mp);
    } catch (e) {
        console.log('ERROR: unable to load module', path);
    }

    if(typeof module === 'function') module(app);

    return module;
};<|endoftext|>


<commit_before>/**
 * UX Rocket
 * Hover/Tap transformation for touch screens
 * @author Bilal Cinarli
 */

;(function($){
    var ux,

        defaults = {
            subs: '.sub-navigation',

            // callbacks
            onReady: false,
            onTap: false
        },
		events = {
			touchstart: 'touchstart.uxTouchMenu',
			touchend  : 'touchend.uxTouchMenu',
			touchmove : 'touchmove.uxTouchMenu',

			pointerdown: 'pointerdown.uxTouchMenu',
			pointerup  : 'pointerup.uxTouchMenu',
			pointermove: 'pointermove.uxTouchMenu',

			MSPointerDown: 'MSPointerDown.uxTouchMenu',
			MSPointerUp  : 'MSPointerUp.uxTouchMenu',
			MSPointerMove: 'MSPointerMove.uxTouchMenu',

			click: 'click.uxTouchMenu'
		},
		ns = {
			rocket  : 'uxRocket',
			data	: 'uxTouchMenu',
			ready	: 'uxitd-touchmenu-ready',
			visible	: 'uxitd-touchmenu-visible'
		};

    var TouchMenu = function(el, options, selector){
        var $el = $(el),
            opts = $.extend({}, defaults, options, $el.data(), {'selector': selector});

		$el.data(ns.data, opts);

        // call onReady function if any
        callback(opts.onReady);

        // bind the ui interactions
        bindUIActions($el);
    };

    var bindUIActions = function($el){
        var _opts = $el.data(ns.data),
			visible,
            touchmoved = false;

        $el.find('a[aria-haspopup="true"]').on(events.click, function(e){
            e.preventDefault();
            $(this).parent().siblings().find(_opts.subs).removeClass(ns.visible).hide();
            $(this).siblings(_opts.subs).addClass(ns.visible).show();
        });

        $(document)
            .on(events.touchmove + ' ' + events.pointermove + ' ' + events.MSPointerMove, function(e){
                touchmoved = true;
            })
            .on(events.touchstart + ' ' + events.pointerdown + ' ' + events.MSPointerDown, function(e){
                $el.find('.' + ns.visible).show();
            })
            .on(events.touchend + ' ' + events.pointerup + ' ' + events.MSPointerUp, function(e){
                if(touchmoved == true){
                    $el.find('.' + ns.visible).show();
                    touchmoved = false;
                    return;
                }
            })
            .on(events.click, function(e){
                $el.find(_opts.subs).removeClass(ns.visible).hide();
                touchmoved = false;
            });

        $("iframe").on(events.click, function(){
            $el.find(_opts.subs).removeClass(ns.visible).hide();
        });

        $el.on(events.click, function(e){
            e.stopPropagation();
        });
    };

    // global callback
    var callback = function(fn){
        // if callback string is function call it directly
        if(typeof fn === 'function'){
            fn.apply(this);
        }

        // if callback defined via data-attribute, call it via new Function
        else {
            if(fn !== false){
                var func = new Function('return' + fn);
                func();
            }
        }
    };

    // touch checks
    var is_touchEnabled = function(){
        if( !( 'ontouchstart' in window ) &&
            !navigator.msMaxTouchPoints &&
            !navigator.userAgent.toLowerCase().match( /windows phone os 7/i )){
            return false;
        }

        return true;
    };

    ux = $.fn.touchmenu = $.uxtouchmenu = function(options){
		var selector = this.selector;

        return this.each(function(options){
            var $el = $(this),
				uxrocket = $el.data(ns.rocket) || {},
                tap;

            if($el.hasClass(ns.ready) || !is_touchEnabled()){
                return;
            }

            $el.addClass(ns.ready);

			uxrocket[ns.data] = {'hasWrapper': false, 'ready': ns.ready, 'selector': selector, 'options': options};

            $el.data(ns.rocket, uxrocket);

            tap = new TouchMenu(this, options, selector);
        });
    };

    ux.version = '0.1.0';

    ux.settings = defaults;
})(jQuery);<commit_msg>Change: event definitions simplified<commit_after>/**
 * UX Rocket
 * Hover/Tap transformation for touch screens
 * @author Bilal Cinarli
 */

;
(function($) {
    var ux,

        defaults = {
            subs   : '.sub-navigation',

            // callbacks
            onReady: false,
            onTap  : false
        },
        events = {
            touchstart: 'touchstart.uxTouchMenu',
            touchend  : 'touchend.uxTouchMenu',
            touchmove : 'touchmove.uxTouchMenu',

            pointerdown: 'pointerdown.uxTouchMenu',
            pointerup  : 'pointerup.uxTouchMenu',
            pointermove: 'pointermove.uxTouchMenu',

            MSPointerDown: 'MSPointerDown.uxTouchMenu',
            MSPointerUp  : 'MSPointerUp.uxTouchMenu',
            MSPointerMove: 'MSPointerMove.uxTouchMenu',

            touchStart: function() {
                return this.touchstart + ' ' + this.pointerdown + ' ' + this.MSPointerDown;
            },

            touchEnd: function() {
                return this.touchend + ' ' + this.pointerup + ' ' + this.MSPointerUp;
            },

            touchMove: function() {
                return this.touchmove + ' ' + this.pointermove + ' ' + this.MSPointerMove;
            },

            click: 'click.uxTouchMenu'
        },
        ns = {
            rocket : 'uxRocket',
            data   : 'uxTouchMenu',
            ready  : 'uxitd-touchmenu-ready',
            visible: 'uxitd-touchmenu-visible'
        };

    var TouchMenu = function(el, options, selector) {
        var $el = $(el),
            opts = $.extend({}, defaults, options, $el.data(), {'selector': selector});

        $el.data(ns.data, opts);

        // call onReady function if any
        callback(opts.onReady);

        // bind the ui interactions
        bindUIActions($el);
    };

    var bindUIActions = function($el) {
        var _opts = $el.data(ns.data),
            visible,
            touchmoved = false;

        $el.find('a[aria-haspopup="true"]').on(events.click, function(e) {
            e.preventDefault();
            $(this).parent().siblings().find(_opts.subs).removeClass(ns.visible).hide();
            $(this).siblings(_opts.subs).addClass(ns.visible).show();
        });

        $(document)
            .on(events.touchStart(), function(e) {
                $el.find('.' + ns.visible).show();
            })
            .on(events.touchMove(), function(e) {
                touchmoved = true;
            })
            .on(events.touchEnd(), function(e) {
                if(touchmoved == true) {
                    $el.find('.' + ns.visible).show();
                    touchmoved = false;
                    return;
                }
            })
            .on(events.click, function(e) {
                $el.find(_opts.subs).removeClass(ns.visible).hide();
                touchmoved = false;
            });

        $("iframe").on(events.click, function() {
            $el.find(_opts.subs).removeClass(ns.visible).hide();
        });

        $el.on(events.click, function(e) {
            e.stopPropagation();
        });
    };

    // global callback
    var callback = function(fn) {
        // if callback string is function call it directly
        if(typeof fn === 'function') {
            fn.apply(this);
        }

        // if callback defined via data-attribute, call it via new Function
        else {
            if(fn !== false) {
                var func = new Function('return' + fn);
                func();
            }
        }
    };

    // touch checks
    var is_touchEnabled = function() {
        if(!('ontouchstart' in window)
           && !navigator.msMaxTouchPoints
           && !navigator.userAgent.toLowerCase().match(/windows phone os 7/i)) {
            return false;
        }

        return true;
    };

    ux = $.fn.touchmenu = $.uxtouchmenu = function(options) {
        var selector = this.selector;

        return this.each(function(options) {
            var $el = $(this),
                uxrocket = $el.data(ns.rocket) || {},
                tap;

            if($el.hasClass(ns.ready) || !is_touchEnabled()) {
                return;
            }

            $el.addClass(ns.ready);

            uxrocket[ns.data] = {'hasWrapper': false, 'ready': ns.ready, 'selector': selector, 'options': options};

            $el.data(ns.rocket, uxrocket);

            tap = new TouchMenu(this, options, selector);
        });
    };

    ux.version = '0.1.0';

    ux.settings = defaults;
})(jQuery);<|endoftext|>


<commit_before>// urlmaker-test.js
//
// Test the urlmaker module
//
// Copyright 2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require("assert"),
    vows = require("vows"),
    parseURL = require("url").parse;

vows.describe("urlmaker module interface").addBatch({
    "When we require the urlmaker module": {
        topic: function() {
            return require("../lib/urlmaker");
        },
        "it exists": function(urlmaker) {
            assert.isObject(urlmaker);
        },
        "and we get the URLMaker singleton": {
            topic: function(urlmaker) {
                return urlmaker.URLMaker;
            },
            "it exists": function(URLMaker) {
                assert.isObject(URLMaker);
            },
            "it has a hostname property": function(URLMaker) {
                assert.include(URLMaker, "hostname");
            },
            "it has a port property": function(URLMaker) {
                assert.include(URLMaker, "port");
            },
            "it has a makeURL method": function(URLMaker) {
                assert.include(URLMaker, "makeURL");
                assert.isFunction(URLMaker.makeURL);
            },
            "and we make an URL": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 3001;
                    return URLMaker.makeURL("login");
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    var parts = parseURL(url);
                    assert.equal(parts.hostname, "example.com");
                    assert.equal(parts.port, 3001);
                    assert.equal(parts.host, "example.com:3001");
                    assert.equal(parts.path, "/login");
                }
            },
            "and we set its properties to default port": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 80;
                    return URLMaker.makeURL("login");
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    var parts = parseURL(url);
                    assert.equal(parts.hostname, "example.com");
                    assert.isUndefined(parts.port);
                    assert.equal(parts.host, "example.com"); // NOT example.com:80
                    assert.equal(parts.path, "/login");
                }
            },
            "and we include parameters": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 2342;
                    return URLMaker.makeURL("/users", {offset: 10, count: 30});
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    // parse query params too
                    var parts = parseURL(url, true);
                    assert.equal(parts.hostname, "example.com");
                    assert.equal(parts.port, 2342);
                    assert.equal(parts.host, "example.com:2342");
                    assert.equal(parts.pathname, "/users");
                    assert.isObject(parts.query);
                    assert.include(parts.query, "offset");
                    assert.equal(parts.query.offset, 10);
                    assert.include(parts.query, "count");
                    assert.equal(parts.query.count, 30);
                }
            }
        }
    }
})["export"](module);

<commit_msg>Change port from undefined to null<commit_after>// urlmaker-test.js
//
// Test the urlmaker module
//
// Copyright 2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require("assert"),
    vows = require("vows"),
    parseURL = require("url").parse;

vows.describe("urlmaker module interface").addBatch({
    "When we require the urlmaker module": {
        topic: function() {
            return require("../lib/urlmaker");
        },
        "it exists": function(urlmaker) {
            assert.isObject(urlmaker);
        },
        "and we get the URLMaker singleton": {
            topic: function(urlmaker) {
                return urlmaker.URLMaker;
            },
            "it exists": function(URLMaker) {
                assert.isObject(URLMaker);
            },
            "it has a hostname property": function(URLMaker) {
                assert.include(URLMaker, "hostname");
            },
            "it has a port property": function(URLMaker) {
                assert.include(URLMaker, "port");
            },
            "it has a makeURL method": function(URLMaker) {
                assert.include(URLMaker, "makeURL");
                assert.isFunction(URLMaker.makeURL);
            },
            "and we make an URL": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 3001;
                    return URLMaker.makeURL("login");
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    var parts = parseURL(url);
                    assert.equal(parts.hostname, "example.com");
                    assert.equal(parts.port, 3001);
                    assert.equal(parts.host, "example.com:3001");
                    assert.equal(parts.path, "/login");
                }
            },
            "and we set its properties to default port": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 80;
                    return URLMaker.makeURL("login");
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    var parts = parseURL(url);
                    assert.equal(parts.hostname, "example.com");
                    assert.isNull(parts.port);
                    assert.equal(parts.host, "example.com"); // NOT example.com:80
                    assert.equal(parts.path, "/login");
                }
            },
            "and we include parameters": {
                topic: function(URLMaker) {
                    URLMaker.hostname = "example.com";
                    URLMaker.port     = 2342;
                    return URLMaker.makeURL("/users", {offset: 10, count: 30});
                },
                "it exists": function(url) {
                    assert.isString(url);
                },
                "its parts are correct": function(url) {
                    // parse query params too
                    var parts = parseURL(url, true);
                    assert.equal(parts.hostname, "example.com");
                    assert.equal(parts.port, 2342);
                    assert.equal(parts.host, "example.com:2342");
                    assert.equal(parts.pathname, "/users");
                    assert.isObject(parts.query);
                    assert.include(parts.query, "offset");
                    assert.equal(parts.query.offset, 10);
                    assert.include(parts.query, "count");
                    assert.equal(parts.query.count, 30);
                }
            }
        }
    }
})["export"](module);

<|endoftext|>


<commit_before>var vCard = require( '..' )
var fs = require( 'fs' )
var assert = require( 'assert' )

suite( 'vCard', function() {

  suite( 'vCard Version Strings', function() {

    test( 'toString version 4.0 should contain type with lowercase values', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-4.0.vcf' )
      var card = new vCard().parse( data )
      var v40String = card.toString('4.0')
      assert.notEqual( v40String.indexOf('TEL;TYPE=work,voice;'), -1 )
    })

    test( 'toString version 3.0 should contain type with uppercase values', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-4.0.vcf' )
      var card = new vCard().parse( data )
      var v30String = card.toString('3.0')
      assert.notEqual( v30String.indexOf('TEL;TYPE=WORK,VOICE;'), -1)
    })

    test( 'toString version 2.1 should contain values with uppercase but no type string', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-4.0.vcf' )
      var card = new vCard().parse( data )
      var v21String = card.toString('2.1')
      assert.notEqual( v21String.indexOf('TEL;WORK;VOICE;'), -1)
    })
  })

})
<commit_msg>update test cases for "adr" and "email"<commit_after>var vCard = require( '..' )
var fs = require( 'fs' )
var assert = require( 'assert' )

suite( 'vCard', function() {

  suite( 'vCard Version Strings', function() {

    test( 'toString version 4.0 should contain type with lowercase values', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-3.0.vcf' )
      var card = new vCard().parse( data )
      var v40String = card.toString('4.0')
      assert.notEqual( v40String.indexOf('TEL;TYPE=work,voice:'), -1 )
      assert.notEqual( v40String.indexOf('ADR;TYPE=work:'), -1 )
      assert.notEqual( v40String.indexOf('EMAIL;TYPE=pref,'), -1 )
    })

    test( 'toString version 3.0 should contain type with uppercase values', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-3.0.vcf' )
      var card = new vCard().parse( data )
      var v30String = card.toString('3.0')
      assert.notEqual( v30String.indexOf('TEL;TYPE=WORK,VOICE:'), -1)
      assert.notEqual( v30String.indexOf('ADR;TYPE=WORK:'), -1 )
      assert.notEqual( v30String.indexOf('EMAIL;TYPE=PREF,'), -1 )
    })

    test( 'toString version 2.1 should contain values with uppercase but no type string', function() {
      var data = fs.readFileSync( __dirname + '/data/vcard-3.0.vcf' )
      var card = new vCard().parse( data )
      var v21String = card.toString('2.1')
      assert.notEqual( v21String.indexOf('TEL;WORK;VOICE:'), -1)
      assert.notEqual( v21String.indexOf('ADR;WORK:'), -1 )
      assert.notEqual( v21String.indexOf('EMAIL;PREF;'), -1 )
    })
  })

})
<|endoftext|>