<commit_before>var G = 6.67408 * Math.pow(10, -11); // m^3 kg^-1 s^-2

// An enum of available levels of logging.
var loglevels = {
  critical: {name: 'critical', value: 0},
  error: {name: 'error', value: 1},
  warn: {name: 'warn', value: 2},
  debug: {name: 'debug', value: 3},
  info: {name: 'info', value: 4},
  trace: {name: 'trace', value: 5}
};
// The default level of logging.  Set this to null to avoid logging entirely.
var loglevel = loglevels.warn;
var log = function(level, message) {
  // Log a message.
  //
  // Args:
  //  level: A member of loglevels.
  //  message: A message to log.
  if (loglevel === null) return;
  var l = loglevels[level];
  if (l.value <= loglevel.value) console.log('[' + loglevel.name + ']');
};

var State = function(x, v, a, m) {
  // A state of a body in the simulation.
  var self = this;

  // The position (m).
  self.x = x;
  // The velocity (m s^-1).
  self.v = v;
  // The acceleration (m s^-2).
  self.a = a;
  // The mass (kg).
  self.m = m;

  self.hash = function() {
    // Generate a hash of the state for use in caching.
    //
    // Returns:
    //  A hash of the state.
    return '[' + self.x.hash() + ',' + self.v.hash() + ',' + self.m + ']';
  };

  // A cache of get_force calculations.
  self._forces = {};
  self.get_force = function(other) {
    // Get the force on this state by another.
    //
    // This function is cached for each value of other.  In addition, this
    // function sets the cache on other.
    //
    // Args:
    //  other: Another body instance.
    //
    // Returns:
    //  The gravitational force vector of other applied on this state.
    var r;
    var f;
    var hash;
    var other_hash = other.hash();

    if (self._forces[other_hash] === undefined) {
      hash = self.hash();
      r = other.x.subtract(self.x);
      f = r.unit().multiply(
        -1 * G * self.mass * other.mass /
        Math.pow(r.magnitude(), 2)); // (kg m s^-2)

      self._forces[other_hash] = f;
      // Every action has an equal and opposite reaction.
      other._forces[hash] = f.multiply(-1)
    }
    return self._forces[other_hash];
  };
};

var Body = function() {
  // A planetary body.
  //
  // Args:
  //  state: The initial state of the body.
  var self = this;

  // A list of states.
  self.states = [];

  self.set_state = function(state) {
    // Set the state of the body.
    //
    // Args:
    //  state: A State instance.
    //
    // Returns:
    //  self
    self.states.push(state);
    return self;
  };

  self.get_state = function() {
    // Get the current state of the body.
    //
    // Returns:
    //  The last State in the body's history.
    return self.states[self.states.length - 1];
  };

  self.get_force = function(other) {
    // Get the force on this object by another.
    //
    // Args:
    //  other: Another body instance.
    //
    // Returns:
    //  The gravitational force vector of other applied on this body.
    return self.current_state().get_force(other.current_state())
  };
};

var Simulation = function() {
  // An N-body simulation.
  var self = this;

  // The bodies of the simulation.
  self.bodies = [];

  // The size of the simulation timestep (s).
  self.step_size = .5;

  self.add_body = function(body) {
    // Add a body to the simulation.
    //
    // Args:
    //  body: A Body instance.
    //
    // Returns:
    //  self
    self.bodies.push(body);
    return self;
  };

  self.step = function() {
    // Generate the next step in the simulation and apply it.
    //
    // TODO: Add a half-step velocity calculation.
    // TODO: Add collision detection.
    //
    // Returns:
    //  self
    var i, j;
    var x, a, f;
    var old_state, new_state;
    var new_xs = [];
    var new_states = [];

    // Create a list of new states for each body in self.bodies.  And
    //  calculate their new position.
    for (i = 0; i < self.bodies.length; i++) {
      old_state = self.bodies[i].get_state();

      // Velocity verlet.
      // x = x + vt + .5at^2
      x = old_state.x
        .add(old_state.v.multiply(self.step_size))
        .add(old_state.a.multiply(.5 * Math.pow(self.step_size, 2)));

      // Initially create the state with just the new position.
      new_states.push(new State(x))
    }

    // Calculate the new velocity from the states created above.
    // This looks like it is O(n^2).  However, because State.get_force is
    //  cached (and reverse-cached), it's actually O(n log(n)).
    for (i = 0; i < new_states.length; i++) {
      old_state = self.bodies[i].get_state();
      new_state = new_states[i];

      // Calculate an force vector as the sum of the gravity due to every other
      //  body in the simulation.
      f = Vector([0, 0]);
      for (j = 0; j < new_states.length; i++) {
        if (i != j)
          f.add(new_state.get_force(new_states[j]));
      }
      a = f.divide(state.m);

      // Velocity verlet.
      new_state.a = a;
      new_state.m = old_state.m;
      // v = v + .5(old_a + a)t
      new_state.v = old_state.v
        .add(new_state.a
          .add(old_state.a)
          .multiply(.5 * self.step_size));
    }

    // Set the new states.
    for (i = 0; i < self.bodies.length; i++) {
      self.bodies[i].set_state(new_states[i]);
    }

    return self;
  };
};
<commit_msg>Fix adding to the force vector.<commit_after>var G = 6.67408 * Math.pow(10, -11); // m^3 kg^-1 s^-2

// An enum of available levels of logging.
var loglevels = {
  critical: {name: 'critical', value: 0},
  error: {name: 'error', value: 1},
  warn: {name: 'warn', value: 2},
  debug: {name: 'debug', value: 3},
  info: {name: 'info', value: 4},
  trace: {name: 'trace', value: 5}
};
// The default level of logging.  Set this to null to avoid logging entirely.
var loglevel = loglevels.warn;
var log = function(level, message) {
  // Log a message.
  //
  // Args:
  //  level: A member of loglevels.
  //  message: A message to log.
  if (loglevel === null) return;
  var l = loglevels[level];
  if (l.value <= loglevel.value) console.log('[' + loglevel.name + ']');
};

var State = function(x, v, a, m) {
  // A state of a body in the simulation.
  var self = this;

  // The position (m).
  self.x = x;
  // The velocity (m s^-1).
  self.v = v;
  // The acceleration (m s^-2).
  self.a = a;
  // The mass (kg).
  self.m = m;

  self.hash = function() {
    // Generate a hash of the state for use in caching.
    //
    // Returns:
    //  A hash of the state.
    return '[' + self.x.hash() + ',' + self.v.hash() + ',' + self.m + ']';
  };

  // A cache of get_force calculations.
  self._forces = {};
  self.get_force = function(other) {
    // Get the force on this state by another.
    //
    // This function is cached for each value of other.  In addition, this
    // function sets the cache on other.
    //
    // Args:
    //  other: Another body instance.
    //
    // Returns:
    //  The gravitational force vector of other applied on this state.
    var r;
    var f;
    var hash;
    var other_hash = other.hash();

    if (self._forces[other_hash] === undefined) {
      hash = self.hash();
      r = other.x.subtract(self.x);
      f = r.unit().multiply(
        -1 * G * self.mass * other.mass /
        Math.pow(r.magnitude(), 2)); // (kg m s^-2)

      self._forces[other_hash] = f;
      // Every action has an equal and opposite reaction.
      other._forces[hash] = f.multiply(-1)
    }
    return self._forces[other_hash];
  };
};

var Body = function() {
  // A planetary body.
  //
  // Args:
  //  state: The initial state of the body.
  var self = this;

  // A list of states.
  self.states = [];

  self.set_state = function(state) {
    // Set the state of the body.
    //
    // Args:
    //  state: A State instance.
    //
    // Returns:
    //  self
    self.states.push(state);
    return self;
  };

  self.get_state = function() {
    // Get the current state of the body.
    //
    // Returns:
    //  The last State in the body's history.
    return self.states[self.states.length - 1];
  };

  self.get_force = function(other) {
    // Get the force on this object by another.
    //
    // Args:
    //  other: Another body instance.
    //
    // Returns:
    //  The gravitational force vector of other applied on this body.
    return self.current_state().get_force(other.current_state())
  };
};

var Simulation = function() {
  // An N-body simulation.
  var self = this;

  // The bodies of the simulation.
  self.bodies = [];

  // The size of the simulation timestep (s).
  self.step_size = .5;

  self.add_body = function(body) {
    // Add a body to the simulation.
    //
    // Args:
    //  body: A Body instance.
    //
    // Returns:
    //  self
    self.bodies.push(body);
    return self;
  };

  self.step = function() {
    // Generate the next step in the simulation and apply it.
    //
    // TODO: Add a half-step velocity calculation.
    // TODO: Add collision detection.
    //
    // Returns:
    //  self
    var i, j;
    var x, a, f;
    var old_state, new_state;
    var new_xs = [];
    var new_states = [];

    // Create a list of new states for each body in self.bodies.  And
    //  calculate their new position.
    for (i = 0; i < self.bodies.length; i++) {
      old_state = self.bodies[i].get_state();

      // Velocity verlet.
      // x = x + vt + .5at^2
      x = old_state.x
        .add(old_state.v.multiply(self.step_size))
        .add(old_state.a.multiply(.5 * Math.pow(self.step_size, 2)));

      // Initially create the state with just the new position.
      new_states.push(new State(x))
    }

    // Calculate the new velocity from the states created above.
    // This looks like it is O(n^2).  However, because State.get_force is
    //  cached (and reverse-cached), it's actually O(n log(n)).
    for (i = 0; i < new_states.length; i++) {
      old_state = self.bodies[i].get_state();
      new_state = new_states[i];

      // Calculate an force vector as the sum of the gravity due to every other
      //  body in the simulation.
      f = Vector([0, 0]);
      for (j = 0; j < new_states.length; i++) {
        if (i != j)
          f = f.add(new_state.get_force(new_states[j]));
      }
      a = f.divide(state.m);

      // Velocity verlet.
      new_state.a = a;
      new_state.m = old_state.m;
      // v = v + .5(old_a + a)t
      new_state.v = old_state.v
        .add(new_state.a
          .add(old_state.a)
          .multiply(.5 * self.step_size));
    }

    // Set the new states.
    for (i = 0; i < self.bodies.length; i++) {
      self.bodies[i].set_state(new_states[i]);
    }

    return self;
  };
};
<|endoftext|>


<commit_before>(function () {

    var spawn = require('child_process').spawn,
		path = require('path'),
		fs = require('fs');

    var extend = function (obj) {
        var args = Array.prototype.slice.call(arguments);
        if (args.length == 0) return {};
        args.slice(1).forEach(function (source) {
            for (var prop in source)
                obj[prop] = source[prop];
        });
        return obj;
    };

    exports.exec = function (cmd, opts, callback) {
        var command = spawn(cmd, opts || [], { customFds: [0, 1, 2] });
        command.on('exit', function (code) { if (callback) callback(code); });
    };

    exports.msbuild = (function () {

        var defaults = {
            processor: 'x86',
            version: 'net2.0'
        };

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            if (!opt.file) fail('msbuild failed - file required');

            if (!opt._exe) {
                if (!opt.processor) fail('msbuild failed - processor required');
                if (!opt.version) fail('msbuild failed - version required');
                opt._exe = exports.getDotNetVersionPath(opt.version, opt.processor) + 'MSBuild.exe';
            }

            args.push(opt.file);

            if (opt.targets)
                opts.targets.forEach(function (target) { args.push('/t:' + target); });
            if (opt.properties) {
                for (var key in opt.properties)
                    args.push('/p:' + key + '=' + opt.properties[key])
            }

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('msbuild failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.xunit = (function () {

        var defaults = {};

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            if (!opt._exe) fail('xunit failed - _exe required');
            if (!opt.assembly) fail('xunit failed - assembly required');

            args.push(opt.assembly);

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('xunit failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.nuget = (function () {

        var defaults = {
            _exe: 'NuGet.exe'
        };

        var task = {};

        task.pack = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            args.push('pack');

            if (!opt._exe) fail('nuget.pack failed - _exe required');
            if (!opt.nuspec) fail('nuget.pack failed - nuspec required');
            args.push(opt.nuspec);

            if (opt.outputDirectory) {
                args.push('-OutputDirectory')
                args.push(opt.outputDirectory);
            }

            if (opt.verbose) args.push('-Verbose');

            if (opt.version) {
                args.push('-Version');
                args.push(opt.version);
            }

            if (opt.properties) {
                for (var key in opt.properties) {
                    args.push('-Properties');
                    args.push(key + '=' + opt.properties[key])
                }
            }

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('nuget.pack failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.assemblyinfo = (function () {
        var defaults = {
            language: 'c#',
            namespaces: ['System.Reflection', 'System.Runtime.InteropServices']
        };

        var supportedLangagues = ['c#'];

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				contents = '',
				assemblyValue;

            if (!opt.file) fail('assemblyinfo failed - file required');
            if (!opt.language) fail('assemblyinfo failed - language required');

            if (opt.language === 'c#') {
                if (opt.namespaces) {
                    opt.namespaces.forEach(function (ns) {
                        contents += 'using ' + ns + ';\r\n';
                    });
                }
                if (opt.assembly) {
                    for (var key in opt.assembly) {
                        assemblyValue = opt.assembly[key];
                        if (typeof assemblyValue === 'function') {
                            contents += assemblyValue();
                            continue;
                        }
                        contents += '[assembly: ' + key + '(';
                        if (typeof assemblyValue === 'boolean')
                            contents += assemblyValue ? 'true' : 'false';
                        else
                            contents += '\"' + assemblyValue + '\"';
                        contents += ')]\r\n';
                    }
                }
                fs.writeFileSync(opt.file, contents);
            } else {
                fail('assemblyinfo failed - unsupported language. choose ' + supportedLangagues);
            }

            callback ? callback(0) : complete();
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        }

        return task;

    })();

    exports.getWinDir = function () {
        var winDir = process.env.WINDIR;
        return path.normalize((winDir.substr(-1) === '/' || winDir.substr(-1) === '\\') ? winDir : (winDir + '/')); // append / if absent
    };

    exports.dotNetVersionMapper = {
        'processor': {
            'x86': 'Framework',
            'x64': 'Framework64'
        },
        'version': {
            'net1.0': '1.0.3705',
            'net1.1': '1.1.4322',
            'net2.0': '2.0.50727',
            'net3.5': '3.5',
            'net4.0': '4.0.30319'
        }
    };

    exports.getDotNetVersionPath = function (version, processor) {

        // http://msdn.microsoft.com/en-us/library/dd414023.aspx
        // http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#Grouping_Assemblies_by_Framework_Version

        // make it processor instead of bit, just incase MS releases FrameworkARM ;)

        var actualProcessor = exports.dotNetVersionMapper['processor'][processor];
        var actualVersion = exports.dotNetVersionMapper['version'][version];
        if (typeof actualProcessor === 'undefined' || typeof actualVersion === 'undefined') {
            fail('specified .NET framework is not supported : ' + version + '(' + processor + ')');
            return;
        }

        var netFrameworkPath = exports.getWinDir() +
									'Microsoft.Net\\' +
									exports.dotNetVersionMapper['processor'][processor] + '\\v' +
									exports.dotNetVersionMapper['version'][version] + '\\';
        return netFrameworkPath;
    };

})();<commit_msg>fixed formatting<commit_after>(function () {

    var
        spawn = require('child_process').spawn,
		path = require('path'),
		fs = require('fs');

    var extend = function (obj) {
        var args = Array.prototype.slice.call(arguments);
        if (args.length == 0) return {};
        args.slice(1).forEach(function (source) {
            for (var prop in source)
                obj[prop] = source[prop];
        });
        return obj;
    };

    exports.exec = function (cmd, opts, callback) {
        var command = spawn(cmd, opts || [], { customFds: [0, 1, 2] });
        command.on('exit', function (code) { if (callback) callback(code); });
    };

    exports.msbuild = (function () {

        var defaults = {
            processor: 'x86',
            version: 'net2.0'
        };

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            if (!opt.file) fail('msbuild failed - file required');

            if (!opt._exe) {
                if (!opt.processor) fail('msbuild failed - processor required');
                if (!opt.version) fail('msbuild failed - version required');
                opt._exe = exports.getDotNetVersionPath(opt.version, opt.processor) + 'MSBuild.exe';
            }

            args.push(opt.file);

            if (opt.targets)
                opts.targets.forEach(function (target) { args.push('/t:' + target); });
            if (opt.properties) {
                for (var key in opt.properties)
                    args.push('/p:' + key + '=' + opt.properties[key])
            }

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('msbuild failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.xunit = (function () {

        var defaults = {};

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            if (!opt._exe) fail('xunit failed - _exe required');
            if (!opt.assembly) fail('xunit failed - assembly required');

            args.push(opt.assembly);

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('xunit failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.nuget = (function () {

        var defaults = {
            _exe: 'NuGet.exe'
        };

        var task = {};

        task.pack = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				args = [];

            args.push('pack');

            if (!opt._exe) fail('nuget.pack failed - _exe required');
            if (!opt.nuspec) fail('nuget.pack failed - nuspec required');
            args.push(opt.nuspec);

            if (opt.outputDirectory) {
                args.push('-OutputDirectory')
                args.push(opt.outputDirectory);
            }

            if (opt.verbose) args.push('-Verbose');

            if (opt.version) {
                args.push('-Version');
                args.push(opt.version);
            }

            if (opt.properties) {
                for (var key in opt.properties) {
                    args.push('-Properties');
                    args.push(key + '=' + opt.properties[key])
                }
            }

            args.push.apply(args, opt._parameters || []);

            exports.exec(opt._exe, args, function (code) {
                if (code !== 0) fail('nuget.pack failed')
                callback ? callback(code) : complete();
            });
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        };

        return task;

    })();

    exports.assemblyinfo = (function () {
        var defaults = {
            language: 'c#',
            namespaces: ['System.Reflection', 'System.Runtime.InteropServices']
        };

        var supportedLangagues = ['c#'];

        var task = function (opts, callback) {
            var opt = extend({}, defaults, opts),
				contents = '',
				assemblyValue;

            if (!opt.file) fail('assemblyinfo failed - file required');
            if (!opt.language) fail('assemblyinfo failed - language required');

            if (opt.language === 'c#') {
                if (opt.namespaces) {
                    opt.namespaces.forEach(function (ns) {
                        contents += 'using ' + ns + ';\r\n';
                    });
                }
                if (opt.assembly) {
                    for (var key in opt.assembly) {
                        assemblyValue = opt.assembly[key];
                        if (typeof assemblyValue === 'function') {
                            contents += assemblyValue();
                            continue;
                        }
                        contents += '[assembly: ' + key + '(';
                        if (typeof assemblyValue === 'boolean')
                            contents += assemblyValue ? 'true' : 'false';
                        else
                            contents += '\"' + assemblyValue + '\"';
                        contents += ')]\r\n';
                    }
                }
                fs.writeFileSync(opt.file, contents);
            } else {
                fail('assemblyinfo failed - unsupported language. choose ' + supportedLangagues);
            }

            callback ? callback(0) : complete();
        };

        task.setDefaults = function (opts) {
            extend(defaults, opts);
            return defaults;
        }

        return task;

    })();

    exports.getWinDir = function () {
        var winDir = process.env.WINDIR;
        return path.normalize((winDir.substr(-1) === '/' || winDir.substr(-1) === '\\') ? winDir : (winDir + '/')); // append / if absent
    };

    exports.dotNetVersionMapper = {
        'processor': {
            'x86': 'Framework',
            'x64': 'Framework64'
        },
        'version': {
            'net1.0': '1.0.3705',
            'net1.1': '1.1.4322',
            'net2.0': '2.0.50727',
            'net3.5': '3.5',
            'net4.0': '4.0.30319'
        }
    };

    exports.getDotNetVersionPath = function (version, processor) {

        // http://msdn.microsoft.com/en-us/library/dd414023.aspx
        // http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#Grouping_Assemblies_by_Framework_Version

        // make it processor instead of bit, just incase MS releases FrameworkARM ;)

        var actualProcessor = exports.dotNetVersionMapper['processor'][processor];
        var actualVersion = exports.dotNetVersionMapper['version'][version];
        if (typeof actualProcessor === 'undefined' || typeof actualVersion === 'undefined') {
            fail('specified .NET framework is not supported : ' + version + '(' + processor + ')');
            return;
        }

        var netFrameworkPath = exports.getWinDir() +
									'Microsoft.Net\\' +
									exports.dotNetVersionMapper['processor'][processor] + '\\v' +
									exports.dotNetVersionMapper['version'][version] + '\\';
        return netFrameworkPath;
    };

})();<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')
var rimraf = require('rimraf')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  if (platform === 'darwin') {
    buildDarwin(printDone)
  } else if (platform === 'win32') {
    buildWin32(printDone)
  } else if (platform === 'linux') {
    buildLinux(printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The application source directory.
  dir: config.ROOT_PATH,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|.appveyor.yml|appdmg|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.dependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.webtorrent',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.webtorrent-helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Copyright notices that apply to the file.
    LegalCopyright: config.APP_COPYRIGHT,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var plist = require('plist')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    infoPlist.NSHumanReadableCopyright = config.APP_COPYRIGHT

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      var appDmg = require('appdmg')
      var sign = require('electron-osx-sign')

      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.zip')
        cp.execSync(`pushd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'} && popd`)
        console.log('Created OS X .zip file.')

        var targetPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.dmg')
        rimraf.sync(targetPath)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: targetPath,
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          console.log('Created OS X disk image (.dmg) file.')
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  var installer = require('electron-winstaller')

  electronPackager(Object.assign({}, all, win32), function (err, buildPath) {
    if (err) return cb(err)

    console.log('Creating Windows installer...')
    installer.createWindowsInstaller({
      name: config.APP_NAME,
      productName: config.APP_NAME,
      title: config.APP_NAME,
      exe: config.APP_NAME + '.exe',

      appDirectory: buildPath[0],
      outputDirectory: path.join(config.ROOT_PATH, 'dist'),
      version: pkg.version,
      description: config.APP_NAME,
      authors: config.APP_TEAM,
      iconUrl: config.APP_ICON + '.ico',
      setupIcon: config.APP_ICON + '.ico',
      // certificateFile: '', // TODO
      usePackageJson: false,
      loadingGif: path.join(config.STATIC_PATH, 'loading.gif')
    }).then(function () {
      console.log('Created Windows installer.')
      cb(null, buildPath)
    }).catch(cb)
  })
}

function buildLinux (cb) {
  electronPackager(Object.assign({}, all, linux), cb)
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<commit_msg>package .zip files for Linux<commit_after>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')
var rimraf = require('rimraf')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  if (platform === 'darwin') {
    buildDarwin(printDone)
  } else if (platform === 'win32') {
    buildWin32(printDone)
  } else if (platform === 'linux') {
    buildLinux(printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The application source directory.
  dir: config.ROOT_PATH,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|.appveyor.yml|appdmg|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.dependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.webtorrent',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.webtorrent-helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Copyright notices that apply to the file.
    LegalCopyright: config.APP_COPYRIGHT,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var plist = require('plist')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    infoPlist.NSHumanReadableCopyright = config.APP_COPYRIGHT

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      var appDmg = require('appdmg')
      var sign = require('electron-osx-sign')

      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.zip')
        cp.execSync(`pushd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'} && popd`)
        console.log('Created OS X .zip file.')

        var targetPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '.dmg')
        rimraf.sync(targetPath)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: targetPath,
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          console.log('Created OS X disk image (.dmg) file.')
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  var installer = require('electron-winstaller')

  electronPackager(Object.assign({}, all, win32), function (err, buildPath) {
    if (err) return cb(err)

    console.log('Creating Windows installer...')
    installer.createWindowsInstaller({
      name: config.APP_NAME,
      productName: config.APP_NAME,
      title: config.APP_NAME,
      exe: config.APP_NAME + '.exe',

      appDirectory: buildPath[0],
      outputDirectory: path.join(config.ROOT_PATH, 'dist'),
      version: pkg.version,
      description: config.APP_NAME,
      authors: config.APP_TEAM,
      iconUrl: config.APP_ICON + '.ico',
      setupIcon: config.APP_ICON + '.ico',
      // certificateFile: '', // TODO
      usePackageJson: false,
      loadingGif: path.join(config.STATIC_PATH, 'loading.gif')
    }).then(function () {
      console.log('Created Windows installer.')
      cb(null, buildPath)
    }).catch(cb)
  })
}

function buildLinux (cb) {
  electronPackager(Object.assign({}, all, linux), function (err, buildPath) {
    if (err) return cb(err)

    // Create .zip file for Linux
    var distPath = path.join(config.ROOT_PATH, 'dist')
    var zipPath = path.join(config.ROOT_PATH, 'dist', BUILD_NAME + '-linux.zip')
    var appFolderName = path.basename(buildPath[0])
    cp.execSync(`pushd ${distPath} && zip -r -y ${zipPath} ${appFolderName} && popd`)
    console.log('Created Linux .zip file.')
  })
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<|endoftext|>


<commit_before>var convert = require('../lib/index');

var opts = require('nomnom')
  .option('input', {
    abbr: 'i',
    flag: false,
    help: 'SWT file'
  })
  .option('version', {
    flag: true,
    help: 'print version and exit',
    callback: function() {
      return require('../package.json').version;
    }
  })
  .option('small', {
    flag: true,
    abbr: 'p',
    help: 'No indent, no newlines'
  })
  .option('indent', {
    default: 2,
    help: 'number of spaces to indent XML sub-structures'
  })
  .option('newline', {
    default: '\n',
    help: 'newline separator'
  })
  .parse();

var xmlBuilderOptions = {
  pretty: (opts.small ? false : true),
  indent: (new Array(parseInt(opts.indent)+1)).join(' '),
  newline: opts.newline
}

if (opts.input) {
  // read from file
  convert(opts.input, xmlBuilderOptions, done);
}
else {
  // read from stdin
  var buffers = [];
  process.stdin.resume();
  process.stdin.on('data', function(buf) { buffers.push(buf); });
  process.stdin.on('end', function() {
    var buffer = Buffer.concat(buffers);
    convert(buffer, xmlBuilderOptions, done);
  });
}

function done(err, xml) {
  if (err)
    throw err;

  console.log(xml);
}<commit_msg>env for vin<commit_after>#!/usr/bin/env node

var convert = require('../lib/index');

var opts = require('nomnom')
  .option('input', {
    abbr: 'i',
    flag: false,
    help: 'SWT file'
  })
  .option('version', {
    flag: true,
    help: 'print version and exit',
    callback: function() {
      return require('../package.json').version;
    }
  })
  .option('small', {
    flag: true,
    abbr: 'p',
    help: 'No indent, no newlines'
  })
  .option('indent', {
    default: 2,
    help: 'number of spaces to indent XML sub-structures'
  })
  .option('newline', {
    default: '\n',
    help: 'newline separator'
  })
  .parse();

var xmlBuilderOptions = {
  pretty: (opts.small ? false : true),
  indent: (new Array(parseInt(opts.indent)+1)).join(' '),
  newline: opts.newline
}

if (opts.input) {
  // read from file
  convert(opts.input, xmlBuilderOptions, done);
}
else {
  // read from stdin
  var buffers = [];
  process.stdin.resume();
  process.stdin.on('data', function(buf) { buffers.push(buf); });
  process.stdin.on('end', function() {
    var buffer = Buffer.concat(buffers);
    convert(buffer, xmlBuilderOptions, done);
  });
}

function done(err, xml) {
  if (err)
    throw err;

  console.log(xml);
}<|endoftext|>


<commit_before>#! /usr/bin/env node

var program = require('starting');
var path = require('path');
var os = require('os');
var config = require('../lib/config');
var util = require('../lib/util');
var colors = require('colors/safe');

function getIpList() {
	var ipList = [];
	var ifaces = os.networkInterfaces();
	Object.keys(ifaces).forEach(function(ifname) {
		 ifaces[ifname].forEach(function (iface) {
			    if (iface.family == 'IPv4') {
			    	ipList.push(iface.address);
			    }
			  });
	});

	return ipList;
}

function error(msg) {
	console.log(colors.red(msg));
}

function warn(msg) {
	console.log(colors.yellow(msg));
}

function info(msg) {
	console.log(colors.green(msg));
}

function showUsage(isRunning, options, restart) {
	var port = options.port || config.port;
	if (isRunning) {
		warn('[!] ' + config.name + ' is running');
	} else {
		info('[i] ' + config.name + (restart ? ' restarted' : ' started'));
	}

	info('[i] First, use your device to visit the following URL list, gets the ' + colors.bold('IP') + ' of the URL you can visit:');
	info(getIpList().map(function(ip) {
		return '    http://' + colors.bold(ip) + (port ? ':' + port : '') + '/';
	}).join('\n'));

	warn('    Note: If the following URLs are unable to access, check the server\'s firewall settings');
	warn('          For more information, please visit ' + colors.bold('https://github.com/avwo/whistle'));
	info('[i] Second, configure your device to use ' + config.name + ' as its HTTP and HTTPS proxy on ' + colors.bold('IP:') + port);
	info('[i] Last, use ' + colors.bold('Chrome') + ' to visit ' + colors.bold('http://' + (options.localUIHost || config.localUIHost) + '/') + ' to get started');
}

function showStartupInfo(err, options, debugMode, restart) {
	if (!err || err === true) {
		return showUsage(err, options, restart);
	}
	if (/listen EADDRINUSE/.test(err)) {
		error('[!] Failed to bind proxy port ' + (options.port || config.port) + ': The port is already in use');
		info('[i] Please check if ' + config.name + ' is already running, you can ' + (debugMode ? 'stop whistle with `w2 stop` first' : 'restart whistle with `w2 restart`'));
		info('    or if another application is using the port, you can change the port with ' + (debugMode ? '`w2 run -p newPort`\n' : '`w2 start -p newPort`\n'));
	} else if (err.code == 'EACCES' || err.code == 'EPERM') {
		error('[!] Cannot start ' + config.name + ' owned by root');
		info('[i] Try to run command with `sudo`\n')
	}

	error(err.stack ? 'Date: ' + util.formatDate() + '\n' + err.stack : err);
}

program.setConfig({
	main: function(options) {
		var hash = options && options.storage && encodeURIComponent(options.storage);
		return path.join(__dirname, '../index.js') + (hash ? '#' + hash + '#' : '');
	},
	name: config.name,
	version: config.version,
	runCallback: function(err, options) {
		if (err) {
			showStartupInfo(err, options, true);
			return;
		}
		showUsage(false, options);
		console.log('Press [Ctrl+C] to stop ' + config.name + '...');
	},
	startCallback: showStartupInfo,
	restartCallback: function(err, options) {
		showStartupInfo(err, options, false, true);
	},
	stopCallback: function(err) {
		if (err === true) {
			info('[i] ' + config.name + ' killed.');
		} else if (err) {
				if (err.code === 'EPERM') {
					error('[!] Cannot kill ' + config.name + ' owned by root');
					info('[i] Try to run command with `sudo`');
				} else {
					error('[!] ' + err.message);
				}
		} else {
			warn('[!] No running ' + config.name);
		}
	}
});

program
	.option('-d, --debug', 'debug mode')
	.option('-l, --localUIHost [hostname]', 'local ui host(' + config.localUIHost + ' by default)', String, '')
	.option('-n, --username [username]', 'login username', String, '')
	.option('-w, --password [password]', 'login password', String, '')
	.option('-S, --storage [newStorageDir]', 'the new local storage directory', String, '')
	.option('-C, --copy [storageDir]', 'copy storageDir to newStorageDir', String, '')
	.option('-p, --port [port]', config.name + ' port(' + config.port + ' by default)', parseInt, config.port)
	.option('-m, --middlewares [script path or module name]', 'express middlewares path(as: xx,yy/zz.js)', String, '')
	.option('-u, --uipath [script path]', 'web ui plugin path', String, '')
	.option('-t, --timneout [ms]', 'request timeout(' + config.timeout + ' ms by default)', parseInt, config.port)
	.option('-s, --sockets [number]', 'max sockets', parseInt, config.port)
	.parse(process.argv);<commit_msg>refactor: Set default value<commit_after>#! /usr/bin/env node

var program = require('starting');
var path = require('path');
var os = require('os');
var config = require('../lib/config');
var util = require('../lib/util');
var colors = require('colors/safe');

function getIpList() {
	var ipList = [];
	var ifaces = os.networkInterfaces();
	Object.keys(ifaces).forEach(function(ifname) {
		 ifaces[ifname].forEach(function (iface) {
			    if (iface.family == 'IPv4') {
			    	ipList.push(iface.address);
			    }
			  });
	});

	return ipList;
}

function error(msg) {
	console.log(colors.red(msg));
}

function warn(msg) {
	console.log(colors.yellow(msg));
}

function info(msg) {
	console.log(colors.green(msg));
}

function showUsage(isRunning, options, restart) {
	var port = options.port || config.port;
	if (isRunning) {
		warn('[!] ' + config.name + ' is running');
	} else {
		info('[i] ' + config.name + (restart ? ' restarted' : ' started'));
	}

	info('[i] First, use your device to visit the following URL list, gets the ' + colors.bold('IP') + ' of the URL you can visit:');
	info(getIpList().map(function(ip) {
		return '    http://' + colors.bold(ip) + (port ? ':' + port : '') + '/';
	}).join('\n'));

	warn('    Note: If the following URLs are unable to access, check the server\'s firewall settings');
	warn('          For more information, please visit ' + colors.bold('https://github.com/avwo/whistle'));
	info('[i] Second, configure your device to use ' + config.name + ' as its HTTP and HTTPS proxy on ' + colors.bold('IP:') + port);
	info('[i] Last, use ' + colors.bold('Chrome') + ' to visit ' + colors.bold('http://' + (options.localUIHost || config.localUIHost) + '/') + ' to get started');
}

function showStartupInfo(err, options, debugMode, restart) {
	if (!err || err === true) {
		return showUsage(err, options, restart);
	}
	if (/listen EADDRINUSE/.test(err)) {
		error('[!] Failed to bind proxy port ' + (options.port || config.port) + ': The port is already in use');
		info('[i] Please check if ' + config.name + ' is already running, you can ' + (debugMode ? 'stop whistle with `w2 stop` first' : 'restart whistle with `w2 restart`'));
		info('    or if another application is using the port, you can change the port with ' + (debugMode ? '`w2 run -p newPort`\n' : '`w2 start -p newPort`\n'));
	} else if (err.code == 'EACCES' || err.code == 'EPERM') {
		error('[!] Cannot start ' + config.name + ' owned by root');
		info('[i] Try to run command with `sudo`\n')
	}

	error(err.stack ? 'Date: ' + util.formatDate() + '\n' + err.stack : err);
}

program.setConfig({
	main: function(options) {
		var hash = options && options.storage && encodeURIComponent(options.storage);
		return path.join(__dirname, '../index.js') + (hash ? '#' + hash + '#' : '');
	},
	name: config.name,
	version: config.version,
	runCallback: function(err, options) {
		if (err) {
			showStartupInfo(err, options, true);
			return;
		}
		showUsage(false, options);
		console.log('Press [Ctrl+C] to stop ' + config.name + '...');
	},
	startCallback: showStartupInfo,
	restartCallback: function(err, options) {
		showStartupInfo(err, options, false, true);
	},
	stopCallback: function(err) {
		if (err === true) {
			info('[i] ' + config.name + ' killed.');
		} else if (err) {
				if (err.code === 'EPERM') {
					error('[!] Cannot kill ' + config.name + ' owned by root');
					info('[i] Try to run command with `sudo`');
				} else {
					error('[!] ' + err.message);
				}
		} else {
			warn('[!] No running ' + config.name);
		}
	}
});

program
	.option('-d, --debug', 'debug mode')
	.option('-l, --localUIHost [hostname]', 'local ui host(' + config.localUIHost + ' by default)', String, '')
	.option('-n, --username [username]', 'login username', String, '')
	.option('-w, --password [password]', 'login password', String, '')
	.option('-S, --storage [newStorageDir]', 'the new local storage directory', String, '')
	.option('-C, --copy [storageDir]', 'copy storageDir to newStorageDir', String, '')
	.option('-p, --port [port]', config.name + ' port(' + config.port + ' by default)', parseInt, config.port)
	.option('-m, --middlewares [script path or module name]', 'express middlewares path(as: xx,yy/zz.js)', String, '')
	.option('-u, --uipath [script path]', 'web ui plugin path', String, '')
	.option('-t, --timneout [ms]', 'request timeout(' + config.timeout + ' ms by default)', parseInt, config.timeout)
	.option('-s, --sockets [number]', 'max sockets(' + config.sockets + ' by default)', parseInt, config.sockets)
	.parse(process.argv);<|endoftext|>


<commit_before>/*
Name:       nsapi.js - Unofficial NodeJS module for Nederlandse Spoorwegen API
Author:     Franklin van de Meent
Source:     https://github.com/fvdm/nodejs-ns-api
Feedback:   https://github.com/fvdm/nodejs-ns-api/issues
API Docs:   http://www.ns.nl/api/api
License:    Unlicense (Public Domain)
            (see UNLICENSE file or https://raw.github.com/fvdm/nodejs-ns-api/master/UNLICENSE)
*/

var util = require ('util');
var http = require ('httpreq');
var parsexml = require ('nodexml') .xml2obj;
var app = {username: '', password: ''};

// ! Vertrektijden
app.vertrektijden = function (station, callback) {
  app.talk ('avt', { station: station }, function (err, data) {
    if (!err) {
      if (!data.ActueleVertrekTijden || !data.ActueleVertrekTijden.VertrekkendeTrein) {
        callback (new Error ('unexpected response' ))
      } else {
        data = data.ActueleVertrekTijden.VertrekkendeTrein;
        if (data.RitNummer) {
          data = [data];
          callback (null, data);
        } else {
          var t;
          for (t in data) {
            data [t] .VertrekSpoorWijziging = data [t] .VertrekSpoor.wijziging;
            data [t] .VertrekSpoor = data [t] .VertrekSpoor.$t;
            delete data [t] .VertrekSpoor.$t;
          }
          callback (null, data);
        }
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Prijzen
app.prijzen = function (props, callback) {
  app.talk ('prijzen-v2', props, callback);
};

// ! Reisadviezen
app.reisadvies = function (props, callback) {
  app.talk ('treinplanner', props, function (err, data) {
    if (!err) {
      if (!data.ReisMogelijkheden || !data.ReisMogelijkheden.ReisMogelijkheid) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.ReisMogelijkheden.ReisMogelijkheid;

        if (!util.isArray (data)) {
          data = [data];
        }

        if (data.length >= 1) {
          for (var r in data) {
            var reis = data [r];
            if (!util.isArray (reis.ReisDeel)) {
              reis.ReisDeel = [reis.ReisDeel];
            }

            for (var d in reis.ReisDeel) {
              var deel = reis.ReisDeel [d];
              for (var s in deel.ReisStop) {
                var stop = deel.ReisStop [s];
                if (stop.Spoor) {
                  stop.SpoorWijziging = stop.Spoor.wijziging;
                  stop.Spoor = stop.Spoor.$t;
                  delete stop.Spoor.$t;
                  deel.ReisStop [s] = stop;
                }
              }
              reis.ReisDeel [d] = deel;
            }

            data [r] = reis;
          }
        }

        callback (null, data);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Stationslijst
app.stations = function (treeKey, callback) {
  if (typeof treeKey === 'function') {
    var callback = treeKey;
    var treeKey = 'code';
  }

  app.talk ('stations-v2', function (err, data) {
    if (!err) {
      if (!data.Stations.Station) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.Stations.Station;
        var tree = {};
        for (var s in data) {
          var station = data [s];

          if (treeKey === 'code') {
            tree [station.Code] = station;
          } else if (typeof station [treeKey] !== 'string') {
            callback (new Error ('key not found in station'));
            return;
          } else {
            if (!tree [station [treeKey]]) {
              tree [station [treeKey]] = {};
            }
            tree [station [treeKey]] [station.Code] = station;
          }
        }

        callback (null, tree);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Storingen
app.storingen = function (params, callback) {
  app.talk ('storingen', params, function (err, data) {
    if (!err) {
      if (!data.Storingen.Ongepland || !data.Storingen.Gepland) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.Storingen;
        data.Ongepland = data.Ongepland.Storing || [];
        data.Gepland = data.Gepland.Storing || [];

        if (!util.isArray (data.Ongepland)) {
          data.Ongepland = [data.Ongepland];
        }

        if (!util.isArray (data.Gepland)) {
          data.Gepland = [data.Gepland];
        }

        callback (null, data);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Communicate
app.talk = function (path, props, callback) {
  if (typeof props === 'function') {
    callback = props;
    props = {};
  }

  var url = 'https://webservices.ns.nl/ns-api-'+ path;
  var options = {
    parameters: props,
    auth: app.username +':'+ app.password
  };

  http.get (url, options, function (err, res) {
    var error = null;
    var data = res.body;

    if (err) {
      error = new Error ('request failed');
      error.details = err;
    }

    try {
      data = parsexml (data);
      data = objectOmit (data, '@');

      if (data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultcode']) {
        error = new Error ('API error');
        error.details = {
          code: data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultcode'],
          message: data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultstring']
        };
      }
    }
    catch (e) {
      if (!error) {
        error = new Error ('invalid reponse');
        error.details = {
          request: options,
          response: {
            headers: response.headers,
            data: data
          }
        };
      }
    }

    callback (error, !error && data);
  });
}

// ready
module.exports = app;

// Strip a key from object
function objectOmit (obj, key) {
  if (obj instanceof Object) {
    for (k in obj) {
      if (k === key) {
        delete obj [k];
      } else {
        obj [k] = objectOmit (obj [k], key);
      }
    }
  }
  else if (obj instanceof Array) {
    for (i in obj) {
      obj [i] = objectOmit (obj [i], key);
    }
  }
  return obj;
}
<commit_msg>Replaced util.isArray with instanceof<commit_after>/*
Name:       nsapi.js - Unofficial NodeJS module for Nederlandse Spoorwegen API
Author:     Franklin van de Meent
Source:     https://github.com/fvdm/nodejs-ns-api
Feedback:   https://github.com/fvdm/nodejs-ns-api/issues
API Docs:   http://www.ns.nl/api/api
License:    Unlicense (Public Domain)
            (see UNLICENSE file or https://raw.github.com/fvdm/nodejs-ns-api/master/UNLICENSE)
*/

var http = require ('httpreq');
var parsexml = require ('nodexml') .xml2obj;
var app = {username: '', password: ''};

// ! Vertrektijden
app.vertrektijden = function (station, callback) {
  app.talk ('avt', { station: station }, function (err, data) {
    if (!err) {
      if (!data.ActueleVertrekTijden || !data.ActueleVertrekTijden.VertrekkendeTrein) {
        callback (new Error ('unexpected response' ))
      } else {
        data = data.ActueleVertrekTijden.VertrekkendeTrein;
        if (data.RitNummer) {
          data = [data];
          callback (null, data);
        } else {
          var t;
          for (t in data) {
            data [t] .VertrekSpoorWijziging = data [t] .VertrekSpoor.wijziging;
            data [t] .VertrekSpoor = data [t] .VertrekSpoor.$t;
            delete data [t] .VertrekSpoor.$t;
          }
          callback (null, data);
        }
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Prijzen
app.prijzen = function (props, callback) {
  app.talk ('prijzen-v2', props, callback);
};

// ! Reisadviezen
app.reisadvies = function (props, callback) {
  app.talk ('treinplanner', props, function (err, data) {
    if (!err) {
      if (!data.ReisMogelijkheden || !data.ReisMogelijkheden.ReisMogelijkheid) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.ReisMogelijkheden.ReisMogelijkheid;

        if (!(data instanceof Array)) {
          data = [data];
        }

        if (data.length >= 1) {
          for (var r in data) {
            var reis = data [r];
            if (!(reis.ReisDeel instanceof Array)) {
              reis.ReisDeel = [reis.ReisDeel];
            }

            for (var d in reis.ReisDeel) {
              var deel = reis.ReisDeel [d];
              for (var s in deel.ReisStop) {
                var stop = deel.ReisStop [s];
                if (stop.Spoor) {
                  stop.SpoorWijziging = stop.Spoor.wijziging;
                  stop.Spoor = stop.Spoor.$t;
                  delete stop.Spoor.$t;
                  deel.ReisStop [s] = stop;
                }
              }
              reis.ReisDeel [d] = deel;
            }

            data [r] = reis;
          }
        }

        callback (null, data);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Stationslijst
app.stations = function (treeKey, callback) {
  if (typeof treeKey === 'function') {
    var callback = treeKey;
    var treeKey = 'code';
  }

  app.talk ('stations-v2', function (err, data) {
    if (!err) {
      if (!data.Stations.Station) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.Stations.Station;
        var tree = {};
        for (var s in data) {
          var station = data [s];

          if (treeKey === 'code') {
            tree [station.Code] = station;
          } else if (typeof station [treeKey] !== 'string') {
            callback (new Error ('key not found in station'));
            return;
          } else {
            if (!tree [station [treeKey]]) {
              tree [station [treeKey]] = {};
            }
            tree [station [treeKey]] [station.Code] = station;
          }
        }

        callback (null, tree);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Storingen
app.storingen = function (params, callback) {
  app.talk ('storingen', params, function (err, data) {
    if (!err) {
      if (!data.Storingen.Ongepland || !data.Storingen.Gepland) {
        callback (new Error ('unexpected response'));
      } else {
        data = data.Storingen;
        data.Ongepland = data.Ongepland.Storing || [];
        data.Gepland = data.Gepland.Storing || [];

        if (!(data.Ongepland instanceof Array)) {
          data.Ongepland = [data.Ongepland];
        }

        if (!(data.Gepland instanceof Array)) {
          data.Gepland = [data.Gepland];
        }

        callback (null, data);
      }
    } else {
      callback (err, data);
    }
  });
};

// ! Communicate
app.talk = function (path, props, callback) {
  if (typeof props === 'function') {
    callback = props;
    props = {};
  }

  var url = 'https://webservices.ns.nl/ns-api-'+ path;
  var options = {
    parameters: props,
    auth: app.username +':'+ app.password
  };

  http.get (url, options, function (err, res) {
    var error = null;
    var data = res.body;

    if (err) {
      error = new Error ('request failed');
      error.details = err;
    }

    try {
      data = parsexml (data);
      data = objectOmit (data, '@');

      if (data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultcode']) {
        error = new Error ('API error');
        error.details = {
          code: data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultcode'],
          message: data ['soap:Envelop'] ['soap:Body'] ['soap:Fault'] ['faultstring']
        };
      }
    }
    catch (e) {
      if (!error) {
        error = new Error ('invalid reponse');
        error.details = {
          request: options,
          response: {
            headers: response.headers,
            data: data
          }
        };
      }
    }

    callback (error, !error && data);
  });
}

// ready
module.exports = app;

// Strip a key from object
function objectOmit (obj, key) {
  if (obj instanceof Object) {
    for (k in obj) {
      if (k === key) {
        delete obj [k];
      } else {
        obj [k] = objectOmit (obj [k], key);
      }
    }
  }
  else if (obj instanceof Array) {
    for (i in obj) {
      obj [i] = objectOmit (obj [i], key);
    }
  }
  return obj;
}
<|endoftext|>


<commit_before>/*
    Pablo <https://github.com/dharmafly/pablo>

    by Premasagar Rose <http://premasagar.com>,
        Dharmafly <http://dharmafly.com>

    MIT license: http://opensource.org/licenses/mit-license.php
*/

var pablo = (function(document, Array, JSON){
    var svgns = 'http://www.w3.org/2000/svg',
        xlinkns = 'http://www.w3.org/1999/xlink',
        svgVersion = 1.1,
        pablo, pabloFn;

    function make(elementName){
        return document.createElementNS(svgns, elementName);
    }

    // Modified from http://diveintohtml5.org/everything.html#svg
    function isSupported(){
        return !!(
            document.querySelectorAll &&
            Array.prototype.forEach &&
            Array.isArray &&
            JSON && JSON.stringify &&
            document.createElementNS &&
            make('svg').createSVGRect
        );
    }

    function empty(el){
        while (el && el.firstChild) {
            el.removeChild(el.firstChild);
        }
        return el;
    }

    function extend(dest, src, withPrototype){
        var prop;
        dest = dest || {};
        for (prop in src){
            if (withPrototype || src.hasOwnProperty(prop)){
                dest[prop] = src[prop];
            }
        }
        return dest;
    }

    // e.g. 'font-color' -> 'fontColor'
    function hyphenatedToCamelCase(str){
        return str.replace(/-([a-z])/g, function(match, letter){
            return letter.toUpperCase();
        });
    }

    // e.g. 'fontColor' -> 'font-color'
    // NOTE: does not check for blank spaces, i.e. for multiple words 'font Color'
    function camelCaseToHyphenated(str){
        return str.replace(/[A-Z]/g, function(letter){
            return '-' + letter.toLowerCase();
        });
    }

    function getNode(node){
        return typeof node === 'string' ?
            document.querySelector(node) :
            isPablo(node) ? node.el : node;
    }

    function isSvg(node){
        return node.namespaceURI == svgns;
    }

    function isPablo(node){
        return typeof node === 'function' && node.pablo === true;
    }

    function pabloList(nodes){
        var result = [],
            i = 0;

        for(; i < nodes.length; i++) {
            if (isSvg(nodes[i])){
                result.push(pablo(nodes[i]));
            }
        }
        return result;
    }

    // return array of Pablo wrapped elements, according to the query selector
    // TODO: return Pablo-wrapped array (e.g. to allow further filtering)
    function queryAll(selector, parentNode){
        var nodes = (parentNode || document).querySelectorAll(selector),
            result = [],
            i = 0;

        for(; i < nodes.length; i++) {
          result.push(nodes[i]);
        }
        return result;
    }

    function queryAllNS(selector, parentNode){
        return pabloList(queryAll(selector, parentNode));
    }

    // Pablo node wrapper

    function Pablo(node, attr){
        this.el = typeof node === 'string' ?
            make(node) :
            isPablo(node) ? node.el : node;
        this.attr(attr);
    }

    // Pablo prototype
    pabloFn = Pablo.prototype;

    extend(pabloFn, {
        pablo: true,

        // https://developer.mozilla.org/en/SVG/Attribute
        attr: function(attr){
            var thisNode = this,
                prop, i, len, nodeAttr;

            if (!attr){
                attr = {};
                nodeAttr = this.el.attributes;
                for (i=0, len=nodeAttr.length; i<len; i++){
                    attr[nodeAttr[i].name] = nodeAttr[i].value;
                }
                return attr;
            }

            for (prop in attr){
                if (attr.hasOwnProperty(prop)){
                    var val = attr[prop];

                    switch (prop){
                        case '_content':
                        this.content(val);
                        continue;

                        case '_children':
                        thisNode.child(val);
                        continue;

                        case '_link':
                        thisNode.link(val);
                        continue;
                    }
                    this.el.setAttributeNS(null, prop, val);
                }
            }
            return this;
        },

        link: function(href){
            this.el.setAttributeNS(xlinkns, 'xlink:href', href);
            return this;
        },

        css: function(styleObj){
            extend(this.el.style, styleObj);
            return this;
        },

        on: function(eventType, handler, bubbles){
            this.el.addEventListener(eventType, handler, bubbles);
            return this;
        },

        off: function(eventType, handler, bubbles){
            this.el.removeEventListener(eventType, handler, bubbles);
            return this;
        },

        child: function(node, attr){
            var _this = this;

            if (Array.isArray(node)){
                node.forEach(function(pabloEl){
                    _this.child(pabloEl);
                });
            }
            else {
                isPablo(node) || (node = pablo(node, attr || {}));
                if (node.el){
                    this.el.appendChild(node.el);
                }
            }
            return node;
        },

        append: function(node, attr){
            this.child(node, attr);
            return this;
        },

        appendTo: function(node, attr){
            if (typeof node === 'string'){
                if (attr){
                    node = pablo(node, attr);
                }
                node = queryAll(node)[0];
            }
            if (node instanceof Pablo){
                node.append(this);
            }
            else if (node && typeof node.appendChild === 'function'){
                node.appendChild(this.el);
            }
            else if (node && typeof node.append === 'function'){
                node.append(this.el);
            }
            return this;
        },

        content: function(text){
            this.el.textContent = text;
            return this;
        },

        empty: function(){
            empty(this.el);
            return this;
        },

        find: function(selector){
            return queryAllNS(selector, this.el);
        },

        parent: function(){
            return pablo(this.el.parentNode);
        },

        // TODO: allow selector argument to filter the results
        children: function(){
            return pabloList(this.el.childNodes);
        },

        // https://developer.mozilla.org/en/CSS/CSS_Reference
        styles: function(css){
            !Array.isArray(css) || (css = css.join(''));
            return this('style', {_content:css});
        },

        toString: function(){
            return this.el.nodeName + ': ' + JSON.stringify(this.attr());
        }

        // innersvg, e.g. foo('<circle>')
        // helper: function(methodName, nodeName, defaultAttr){}
        // prepend

    });

    // Aliases
    extend(pabloFn, {
        _: pabloFn.append
    });

    // Public API
    pablo = extend(
        function(node, attr){
            var wrappedNode;

            // e.g. pablo('circle') to return all circles
            if (typeof node === 'string' && !attr){
                return queryAllNS(node);
            }
            // e.g. pablo('circle', {r:100}) to create a circle
            wrappedNode = new Pablo(node, attr);

            // functional
            // e.g. pablo('g')('circle', {r:100})
            var self = extend(function(node, attr){
                // selector passes
                if (typeof node === 'string' && !attr){
                    return wrappedNode.find(node);
                }
                // append child
                pabloFn.child.call(wrappedNode, node, attr);
                return self;
            }, wrappedNode, true);

            return self;
        },

        {
            v: '0.0.1',
            svgns: svgns,
            xlinkns: xlinkns,
            svgVersion: svgVersion,
            fn: pabloFn,
            isSupported: isSupported,
            isSvg: isSvg,
            isPablo: isPablo,
            list: pabloList,

            // Create SVG root wrapper
            root: function(parentNode, attr){
                parentNode = empty(getNode(parentNode));
                attr = extend(attr, {version:1.1});
                return pablo.svg(attr).appendTo(parentNode);
            }
        }
    );

    // Shortcut methods for all SVG elements
    'a altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform circle clipPath color-profile cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient marker mask metadata missing-glyph mpath path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tref tspan use view vkern'
        .split(' ').forEach(function(nodeName){
            var methodName = hyphenatedToCamelCase(nodeName);

            pablo[methodName] = function(attr){
                return pablo(nodeName, attr || {});
            };
            pabloFn[methodName] = function(attr){
                return this.child(nodeName, attr || {});
            }
        });

        return pablo;

}(window.document, window.Array, window.JSON));

/////////

/*

    var paper = pablo('svg'); // pablo.root(); pablo.create(); pablo()

    pablo('circle', {})
        .appendTo(paper);

    paper.circle({});

    pablo.circle({}).appendTo(paper)

    /////

    var paper = pablo();
    var c = paper.circle().line();
    var c = pablo.circle().appendTo(paper);
    c.line().line();

    jQuery(paper).append('<div/>')

    paper
        .circle({})
            .get().click(fn)
            .parent()

        .line({})
            .get().click(fn).hover()
            .parent()

    paper.append('circle', {})
         .appendChild('circle', {});

    paper.circle().parent().line().parent()
    paper.circle()
    paper.line()

    var c = paper.circle();
    c.click().line()

    paper.circle({}, true)

    paper.circle({}, function(circle){
        circle.click().line().line()
    })

    paper.circle class: 'red', (circle) ->
        circle.line (line) ->
            line.circle()
    .line (line) ->
         line

    pablo.circle({}).appendTo(paper).click()

    paper.circle().appendCircle()

    paper.append(
        pablo.circle(),

    )
*/<commit_msg>Add toPablo() and appendNode()<commit_after>/*
    Pablo <https://github.com/dharmafly/pablo>

    by Premasagar Rose <http://premasagar.com>,
        Dharmafly <http://dharmafly.com>

    MIT license: http://opensource.org/licenses/mit-license.php
*/

var pablo = (function(document, Array, JSON){
    var svgns = 'http://www.w3.org/2000/svg',
        xlinkns = 'http://www.w3.org/1999/xlink',
        svgVersion = 1.1,
        pablo, pabloFn;

    function make(elementName){
        return document.createElementNS(svgns, elementName);
    }

    // Modified from http://diveintohtml5.org/everything.html#svg
    function isSupported(){
        return !!(
            document.querySelectorAll &&
            Array.prototype.forEach &&
            Array.isArray &&
            JSON && JSON.stringify &&
            document.createElementNS &&
            make('svg').createSVGRect
        );
    }

    function empty(el){
        while (el && el.firstChild) {
            el.removeChild(el.firstChild);
        }
        return el;
    }

    function extend(dest, src, withPrototype){
        var prop;
        dest = dest || {};
        for (prop in src){
            if (withPrototype || src.hasOwnProperty(prop)){
                dest[prop] = src[prop];
            }
        }
        return dest;
    }

    // e.g. 'font-color' -> 'fontColor'
    function hyphenatedToCamelCase(str){
        return str.replace(/-([a-z])/g, function(match, letter){
            return letter.toUpperCase();
        });
    }

    // e.g. 'fontColor' -> 'font-color'
    // NOTE: does not check for blank spaces, i.e. for multiple words 'font Color'
    function camelCaseToHyphenated(str){
        return str.replace(/[A-Z]/g, function(letter){
            return '-' + letter.toLowerCase();
        });
    }

    function getNode(node){
        return typeof node === 'string' ?
            document.querySelector(node) :
            isPablo(node) ? node.el : node; // TODO return Pablo wrapper?
    }

    function toPablo(node, attr){
        return isPablo(node) ?
            node :
            pablo(node, attr || {});
    }

    function appendNode(node, attr, parentNode){
        node = toPablo(node, attr);
        if (node.el){
            (parentNode || document).appendChild(node.el);
        }
        return node;
    }

    function isSvg(node){
        return node.namespaceURI == svgns;
    }

    function isPablo(node){
        return typeof node === 'function' && node.pablo === true;
    }

    function pabloList(nodes){
        var result = [],
            i = 0;

        for(; i < nodes.length; i++) {
            if (isSvg(nodes[i])){
                result.push(pablo(nodes[i]));
            }
        }
        return result;
    }

    // return array of Pablo wrapped elements, according to the query selector
    // TODO: return Pablo-wrapped array (e.g. to allow further filtering)
    function queryAll(selector, parentNode){
        var nodes = (parentNode || document).querySelectorAll(selector),
            result = [],
            i = 0;

        for(; i < nodes.length; i++) {
          result.push(nodes[i]);
        }
        return result;
    }

    function queryAllNS(selector, parentNode){
        return pabloList(queryAll(selector, parentNode));
    }

    // Pablo node wrapper

    function Pablo(node, attr){
        this.el = typeof node === 'string' ?
            make(node) :
            isPablo(node) ? node.el : node || null;

        this.attr(attr);
    }

    // Pablo prototype
    pabloFn = Pablo.prototype;

    extend(pabloFn, {
        pablo: true,

        // https://developer.mozilla.org/en/SVG/Attribute
        attr: function(attr){
            var thisNode = this,
                prop, i, len, nodeAttr;

            if (!attr){
                attr = {};
                nodeAttr = this.el.attributes;
                for (i=0, len=nodeAttr.length; i<len; i++){
                    attr[nodeAttr[i].name] = nodeAttr[i].value;
                }
                return attr;
            }

            for (prop in attr){
                if (attr.hasOwnProperty(prop)){
                    var val = attr[prop];

                    switch (prop){
                        case '_content':
                        this.content(val);
                        continue;

                        case '_children':
                        thisNode.child(val);
                        continue;

                        case '_link':
                        thisNode.link(val);
                        continue;
                    }
                    this.el.setAttributeNS(null, prop, val);
                }
            }
            return this;
        },

        link: function(href){
            this.el.setAttributeNS(xlinkns, 'xlink:href', href);
            return this;
        },

        css: function(styleObj){
            extend(this.el.style, styleObj);
            return this;
        },

        on: function(eventType, handler, bubbles){
            this.el.addEventListener(eventType, handler, bubbles);
            return this;
        },

        off: function(eventType, handler, bubbles){
            this.el.removeEventListener(eventType, handler, bubbles);
            return this;
        },

        child: function(node, attr){
            var _this = this;

            if (Array.isArray(node)){
                node.forEach(function(node){
                    _this.child(node);
                });
            }
            else {
                node = appendNode(node, attr, this.el);
            }
            return node;
        },

        append: function(node, attr){
            this.child(node, attr);
            return this;
        },

        prepend: function(node, attr){
            var _this = this,
                parentNode;

            if (Array.isArray(node)){
                parentNode = _this.el.previousSibling;
                node.forEach(function(node){
                    node = toPablo(node);
                    if (node.el){
                        parentNode.appendChild(node.el);
                    }
                });
            }
            else {
                node = toPablo(node);
                if (node.el){
                    this.el.appendChild(node.el);
                }
            }
            return node;

            this.el.previousSibling(node.el);
        },

        appendTo: function(node, attr){
            if (typeof node === 'string'){
                if (attr){
                    node = pablo(node, attr);
                }
                node = queryAll(node)[0];
            }
            if (node instanceof Pablo){
                node.append(this);
            }
            else if (node && typeof node.appendChild === 'function'){
                node.appendChild(this.el);
            }
            else if (node && typeof node.append === 'function'){
                node.append(this.el);
            }
            return this;
        },

        content: function(text){
            this.el.textContent = text;
            return this;
        },

        empty: function(){
            empty(this.el);
            return this;
        },

        find: function(selector){
            return queryAllNS(selector, this.el);
        },

        parent: function(){
            return pablo(this.el.parentNode);
        },

        // TODO: allow selector argument to filter the results
        children: function(){
            return pabloList(this.el.childNodes);
        },

        // https://developer.mozilla.org/en/CSS/CSS_Reference
        styles: function(css){
            !Array.isArray(css) || (css = css.join(''));
            return this('style', {_content:css});
        },

        toString: function(){
            return this.el.nodeName + ': ' + JSON.stringify(this.attr());
        }

        // innersvg, e.g. foo('<circle>')
        // helper: function(methodName, nodeName, defaultAttr){}
        // prepend

    });

    // Aliases
    extend(pabloFn, {
        _: pabloFn.append
    });

    // Public API
    pablo = extend(
        function(node, attr){
            var wrappedNode;

            // e.g. pablo('circle') to return all circles
            if (typeof node === 'string' && !attr){
                return queryAllNS(node);
            }
            // e.g. pablo('circle', {r:100}) to create a circle
            wrappedNode = new Pablo(node, attr);

            // functional
            // e.g. pablo('g')('circle', {r:100})
            var self = extend(function(node, attr){
                // selector passes
                if (typeof node === 'string' && !attr){
                    return wrappedNode.find(node);
                }
                // append child
                pabloFn.child.call(wrappedNode, node, attr);
                return self;
            }, wrappedNode, true);

            return self;
        },

        {
            v: '0.0.1',
            svgns: svgns,
            xlinkns: xlinkns,
            svgVersion: svgVersion,
            fn: pabloFn,
            isSupported: isSupported,
            isSvg: isSvg,
            isPablo: isPablo,
            list: pabloList,

            // Create SVG root wrapper
            root: function(parentNode, attr){
                parentNode = empty(getNode(parentNode));
                attr = extend(attr, {version:1.1});
                return pablo.svg(attr).appendTo(parentNode);
            }
        }
    );

    // Shortcut methods for all SVG elements
    'a altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform circle clipPath color-profile cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient marker mask metadata missing-glyph mpath path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tref tspan use view vkern'
        .split(' ').forEach(function(nodeName){
            var methodName = hyphenatedToCamelCase(nodeName);

            pablo[methodName] = function(attr){
                return pablo(nodeName, attr || {});
            };
            pabloFn[methodName] = function(attr){
                return this.child(nodeName, attr || {});
            }
        });

        return pablo;

}(window.document, window.Array, window.JSON));

/////////

/*

    var paper = pablo('svg'); // pablo.root(); pablo.create(); pablo()

    pablo('circle', {})
        .appendTo(paper);

    paper.circle({});

    pablo.circle({}).appendTo(paper)

    /////

    var paper = pablo();
    var c = paper.circle().line();
    var c = pablo.circle().appendTo(paper);
    c.line().line();

    jQuery(paper).append('<div/>')

    paper
        .circle({})
            .get().click(fn)
            .parent()

        .line({})
            .get().click(fn).hover()
            .parent()

    paper.append('circle', {})
         .appendChild('circle', {});

    paper.circle().parent().line().parent()
    paper.circle()
    paper.line()

    var c = paper.circle();
    c.click().line()

    paper.circle({}, true)

    paper.circle({}, function(circle){
        circle.click().line().line()
    })

    paper.circle class: 'red', (circle) ->
        circle.line (line) ->
            line.circle()
    .line (line) ->
         line

    pablo.circle({}).appendTo(paper).click()

    paper.circle().appendCircle()

    paper.append(
        pablo.circle(),

    )
*/<|endoftext|>