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

var WebSocketServer = require('ws').Server
var freeport = require('freeport')
var request = require('request')
var websocket = require('websocket-stream')
var docker = require('docker-browser-console')
var root = require('root')
var url = require('url')
var send = require('send')
var path = require('path')
var pump = require('pump')
var cors = require('cors')
var net = require('net')

module.exports = function(image, opts) {
  if (!opts) opts = {}

  var DOCKER_HOST = opts.docker || (process.env.DOCKER_HOST || '127.0.0.1').replace(/^.+:\/\//, '').replace(/:\d+$/, '').replace(/^\/.+$/, '127.0.0.1')

  var server = root()
  var wss = new WebSocketServer({server:server})
  var containers = {}

  wss.on('connection', function(connection) {
    var req = connection.upgradeReq
    var url = req.url.slice(1)
    var persist = opts.persist && !!url
    var id = url || Math.random().toString(36).slice(2)
    //TODO add user id
    //get userid and imagename
    var params = url.split('/')
      if(params.length<3){
          //close ws
          console.log("error params");
          connection.close();
      }
      //get userid and check user
      var user = params[1]
      //mock check user
      if(false){
          //close ws
          console.log("invalid user!");
          connection.close();
      }
      id = user

      //get image and check it
      var image = params[2]
      if(false){
          //close ws
          console.log("invalid image!");
          connection.close();
      }
      console.log(req.url)
      var stream = websocket(connection)
      //check is exists
    var container = containers.hasOwnProperty(id) && containers[id]
    if (container){//request('http://'+DOCKER_HOST+':'+container.ports.http)
        if(container.image=== image){
            console.log("already open one!");
            connection.close();
            return
        }else{
            console.log("kill one!");
            container.connection.close();
        }
    }
        var startProxy = function(httpPort, cb) {
            if (!opts.offline) return cb(null, id+'.c.'+req.headers.host)

            var proxy = net.createServer(function(socket) {
                //TODO cancel
                pump(socket, net.connect(httpPort, DOCKER_HOST), socket)
            })

            proxy.once('error', cb)
            proxy.listen(0, function() {
                var port = proxy.address().port
                cb(null, req.headers.host.split(':')[0]+':'+port, proxy)
            })
        }

        freeport(function(err, filesPort) {
            if (err) return connection.destroy()
            freeport(function(err, httpPort) {
                if (err) return connection.destroy()
                startProxy(httpPort, function(err, subdomain, proxy) {
                    if (err) {
                        console.log("create start proxy error");
                        console.log(err);
                        return connection.destroy();
                    }

                    var container = containers[id] = {
                        id: id,
                        image: image,
                        connection:connection,
                        host: 'http://'+subdomain,
                        ports: {http:httpPort, fs:filesPort}
                    }

                    server.emit('spawn', container)

                    var ports = {}

                    ports[httpPort] = 80
                    ports[filesPort] = 8441

                    var dopts = {
                        tty: opts.tty === undefined ? true : opts.tty,
                        env: {
                            CONTAINER_ID: container.id,
                            HOST: container.host,
                            PORT: 80
                        },
                        ports: ports,
                        volumes: opts.volumes || {}
                    }

                    if (persist) dopts.volumes['/tmp/'+id] = '/root'
                    if (opts.trusted) dopts.volumes['/var/run/docker.sock'] = '/var/run/docker.sock'

                    //TODO replace image with you wanted
                    pump(stream, docker(image, dopts), stream, function(err) {
                        console.log('error in create docker');
                        console.log(err);
                        if (proxy) proxy.close()
                        server.emit('kill', container)
                        delete containers[id]
                    })
                })
            })
        })
  })

  server.all(cors())

  server.all(function(req, res, next) {
    var host = req.headers.host || ''
    var i = host.indexOf('.c.')

    if (i > -1) {
      var id = host.slice(0, i)
      var container = containers.hasOwnProperty(id) && containers[id]
      if (container) return pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+req.url), res)
      return res.error(404, 'Could not find container')
    }

    next()
  })

  server.get('/-/*', function(req, res) {
    send(req, req.params.glob, {root:path.join(__dirname, 'web')}).pipe(res)
  })
    //TODO check docker containers is exist

  //server.get('/containers/{id}', function(req, res) {
  //  var id = req.params.id
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  res.send(container)
  //})
  //
  //server.all('/http/{id}/*', function(req, res) {
  //  var id = req.params.id
  //  var url = req.url.slice(('/http/'+id).length)
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+url), res)
  //})

  //server.all('/files/{id}/*', function(req, res) {
  //  var id = req.params.id
  //  var url = req.url.slice(('/files/'+id).length)
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  pump(req, request('http://'+DOCKER_HOST+':'+container.ports.fs+url), res)
  //})

  server.all(function(req, res, next) {
    if (!opts.offline) return next()
    var id = req.connection.address().address
    //var container = containers.hasOwnProperty(id) && containers[id]
    //if (container) return pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+req.url), res)
    next()
  })

    //TODO check container is exist
  server.get('/user/{userid}/{imagename}',function(req,res,next){
        var id = req.params.userid
        var image = req.params.imagename
        console.log(id)
        console.log(image)
        next()
    })
  server.get('/bundle.js', '/-/bundle.js')
  server.get('/index.html', '/-/index.html')
  server.get('/user/{userid}/{imagename}', '/-/index.html')

  return server
}
<commit_msg>finish index<commit_after>#!/usr/bin/env node

var WebSocketServer = require('ws').Server
var freeport = require('freeport')
var request = require('request')
var websocket = require('websocket-stream')
var docker = require('docker-browser-console')
var root = require('root')
var url = require('url')
var send = require('send')
var path = require('path')
var pump = require('pump')
var cors = require('cors')
var net = require('net')

module.exports = function(image, opts) {
  if (!opts) opts = {}

  var DOCKER_HOST = opts.docker || (process.env.DOCKER_HOST || '127.0.0.1').replace(/^.+:\/\//, '').replace(/:\d+$/, '').replace(/^\/.+$/, '127.0.0.1')

  var server = root()
  var wss = new WebSocketServer({server:server})
  var containers = {}

  wss.on('connection', function(connection) {
    var req = connection.upgradeReq
    var url = req.url.slice(1)
    var persist = opts.persist && !!url
    var id = url || Math.random().toString(36).slice(2)
    //TODO add user id
    //get userid and imagename
    var params = url.split('/')
      if(params.length<3){
          //close ws
          console.log("error params");
          connection.close();
      }
      //get userid and check user
      var user = params[1]
      //mock check user
      if(false){
          //close ws
          console.log("invalid user!");
          connection.close();
      }
      id = user

      //get image and check it
      var image = params[2]
      if(false){
          //close ws
          console.log("invalid image!");
          connection.close();
      }
      console.log(req.url)
      var stream = websocket(connection)
      //check is exists
    var container = containers.hasOwnProperty(id) && containers[id]
    if (container){//request('http://'+DOCKER_HOST+':'+container.ports.http)
        if(container.image=== image){
            console.log("already open one!");
            connection.close();
            return
        }else{
            console.log("kill one!");
            container.connection.close();
        }
    }
        var startProxy = function(httpPort, cb) {
            if (!opts.offline) return cb(null, id+'.c.'+req.headers.host)

            var proxy = net.createServer(function(socket) {
                //TODO cancel
                pump(socket, net.connect(httpPort, DOCKER_HOST), socket)
            })

            proxy.once('error', cb)
            proxy.listen(0, function() {
                var port = proxy.address().port
                cb(null, req.headers.host.split(':')[0]+':'+port, proxy)
            })
        }

        freeport(function(err, filesPort) {
            if (err) return connection.destroy()
            freeport(function(err, httpPort) {
                if (err) return connection.destroy()
                startProxy(httpPort, function(err, subdomain, proxy) {
                    if (err) {
                        console.log("create start proxy error");
                        console.log(err);
                        return connection.destroy();
                    }

                    var container = containers[id] = {
                        id: id,
                        image: image,
                        docker_run: null,
                        connection:connection,
                        host: 'http://'+subdomain,
                        ports: {http:httpPort, fs:filesPort}
                    }

                    server.emit('spawn', container)

                    var ports = {}

                    ports[httpPort] = 80
                    ports[filesPort] = 8441

                    var dopts = {
                        tty: opts.tty === undefined ? true : opts.tty,
                        env: {
                            CONTAINER_ID: container.id,
                            HOST: container.host,
                            PORT: 80,
                            CONTAINER_OBJ: container
                        },
                        ports: ports,
                        volumes: opts.volumes || {}
                    }

                    if (persist) dopts.volumes['/tmp/'+id] = '/root'
                    if (opts.trusted) dopts.volumes['/var/run/docker.sock'] = '/var/run/docker.sock'

                    //TODO replace image with you wanted
                    pump(stream, docker(image, dopts), stream, function(err) {
                        console.log('error in create docker');
                        console.log(err);
                        if (proxy) proxy.close()
                        server.emit('kill', container)
                        delete containers[id]
                    })
                })
            })
        })
  })

  server.all(cors())

  server.all(function(req, res, next) {
    var host = req.headers.host || ''
    var i = host.indexOf('.c.')

    if (i > -1) {
      var id = host.slice(0, i)
      var container = containers.hasOwnProperty(id) && containers[id]
      if (container) return pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+req.url), res)
      return res.error(404, 'Could not find container')
    }

    next()
  })

  server.get('/-/*', function(req, res) {
    send(req, req.params.glob, {root:path.join(__dirname, 'web')}).pipe(res)
  })
    //TODO check docker containers is exist

  //server.get('/containers/{id}', function(req, res) {
  //  var id = req.params.id
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  res.send(container)
  //})
  //
  //server.all('/http/{id}/*', function(req, res) {
  //  var id = req.params.id
  //  var url = req.url.slice(('/http/'+id).length)
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+url), res)
  //})

  //server.all('/files/{id}/*', function(req, res) {
  //  var id = req.params.id
  //  var url = req.url.slice(('/files/'+id).length)
  //  var container = containers.hasOwnProperty(id) && containers[id]
  //  if (!container) return res.error(404, 'Could not find container')
  //  pump(req, request('http://'+DOCKER_HOST+':'+container.ports.fs+url), res)
  //})

  server.all(function(req, res, next) {
    if (!opts.offline) return next()
    var id = req.connection.address().address
    //var container = containers.hasOwnProperty(id) && containers[id]
    //if (container) return pump(req, request('http://'+DOCKER_HOST+':'+container.ports.http+req.url), res)
    next()
  })

    //TODO check container is exist
  server.get('/user/{userid}/{imagename}',function(req,res,next){
        var id = req.params.userid
        var image = req.params.imagename
        console.log(id)
        console.log(image)
      console.log('second')
        next()
    })
    server.get('/user/{userid}/{imagename}',function(req,res,next){
        //var id = req.params.userid
        //var image = req.params.imagename
        //console.log(id)
        //console.log(image)
        console.log('first')
        next()
    })
  server.get('/bundle.js', '/-/bundle.js')
  server.get('/index.html', '/-/index.html')
  server.get('/user/{userid}/{imagename}', '/-/index.html')

  return server
}
<|endoftext|>


<commit_before>/**
 * Plugin dependencies.
 *
 * @type {exports}
 */
var _ = require('lodash');
var helpers = require('unibot-helpers');

/**
 * Weather plugin for UniBot.
 *
 * This plugin fetches weather data from http://api.openweathermap.org API.
 *
 * @param  {Object} options Plugin options object, description below.
 *   db: {mongoose} the mongodb connection
 *   bot: {irc} the irc bot
 *   web: {connect} a connect + connect-rest webserver
 *   config: {object} UniBot configuration
 *
 * @return  {Function}  Init function to access shared resources
 */
module.exports = function init(options) {
    var config = options.config;

    /**
     * Default plugin configuration. These can be override on your UniBot config.js file
     *
     * @type    {{
     *              showFetchMessage: boolean,
     *              units: string,
     *              messages: {
     *                  fetch: string,
     *                  success: string,
     *                  error: string
     *              }
     *          }}
     */
    var pluginConfig = {
        "showFetchMessage": true,
        "units": "metric",
        "messages": {
            "fetch": "${nick}: wait a moment fetching weather data for '${location}'...",
            "success": "${nick}: temperature: ${weather.main.temp}°C (min: ${weather.main.temp_min}°C, max: ${weather.main.temp_max}°C), wind speed: ${weather.wind.speed}m/s, ${weather.weather[0].main}: ${weather.weather[0].description}",
            "error": "${nick}: cannot find any weather data for '${location}'..."
        }
    };

    // Merge configuration for plugin
    if (!_.isUndefined(config.plugins) && !_.isUndefined(config.plugins.weather) && _.isObject(config.plugins.weather)) {
        pluginConfig = _.merge(pluginConfig, config.plugins.weather);
    }

    /**
     * Actual UniBot weather plugin implementation. This plugin will fetch weather data from OpenWeatherMap API
     * according to given city name.
     */
    return function plugin(channel) {
        /**
         * Actual function to fetch weather data for specified location.
         *
         * @param   {string}    location
         * @param   {string}    from
         */
        function getWeather(location, from) {
            var templateVars = {
                nick: from,
                location: location
            };

            if (pluginConfig.showFetchMessage) {
                channel.say(_.template(pluginConfig.messages.fetch, templateVars));
            }

            // Fetch weather data from OpenWeatherMap API
            helpers.download('http://api.openweathermap.org/data/2.5/find?units=' + pluginConfig.units + '&q=' + location, function(data) {
                try {
                    var weatherData = JSON.parse(data);

                    if (parseInt(weatherData.count, 10) === 0) {
                        channel.say(_.template(pluginConfig.messages.error, templateVars));
                    } else {
                        _.each(weatherData.list, function iterator(data) {
                            templateVars.weather = data;

                            channel.say(_.template(pluginConfig.messages.success, templateVars));
                        });
                    }
                } catch (error) {
                    channel.say('Oh noes, error: ' + error);
                }
            });
        }

        return {
            '^!weather (.+)': function(from, matches) {
                getWeather(matches[1], from);
            }
        };
    }
};
<commit_msg>Simplified plugin configuration merge.<commit_after>/**
 * Plugin dependencies.
 *
 * @type {exports}
 */
var _ = require('lodash');
var helpers = require('unibot-helpers');

/**
 * Weather plugin for UniBot.
 *
 * This plugin fetches weather data from http://api.openweathermap.org API.
 *
 * @param  {Object} options Plugin options object, description below.
 *   db: {mongoose} the mongodb connection
 *   bot: {irc} the irc bot
 *   web: {connect} a connect + connect-rest webserver
 *   config: {object} UniBot configuration
 *
 * @return  {Function}  Init function to access shared resources
 */
module.exports = function init(options) {
    var config = options.config;

    /**
     * Default plugin configuration. These can be override on your UniBot config.js file
     *
     * @type    {{
     *              showFetchMessage: boolean,
     *              units: string,
     *              messages: {
     *                  fetch: string,
     *                  success: string,
     *                  error: string
     *              }
     *          }}
     */
    var pluginConfig = {
        "showFetchMessage": true,
        "units": "metric",
        "messages": {
            "fetch": "${nick}: wait a moment fetching weather data for '${location}'...",
            "success": "${nick}: temperature: ${weather.main.temp}°C (min: ${weather.main.temp_min}°C, max: ${weather.main.temp_max}°C), wind speed: ${weather.wind.speed}m/s, ${weather.weather[0].main}: ${weather.weather[0].description}",
            "error": "${nick}: cannot find any weather data for '${location}'..."
        }
    };

    // Merge configuration for plugin
    if (_.isObject(config.plugins) && _.isObject(config.plugins.weather)) {
        pluginConfig = _.merge(pluginConfig, config.plugins.weather);
    }

    /**
     * Actual UniBot weather plugin implementation. This plugin will fetch weather data from OpenWeatherMap API
     * according to given city name.
     */
    return function plugin(channel) {
        /**
         * Actual function to fetch weather data for specified location.
         *
         * @param   {string}    location
         * @param   {string}    from
         */
        function getWeather(location, from) {
            var templateVars = {
                nick: from,
                location: location
            };

            if (pluginConfig.showFetchMessage) {
                channel.say(_.template(pluginConfig.messages.fetch, templateVars));
            }

            // Fetch weather data from OpenWeatherMap API
            helpers.download('http://api.openweathermap.org/data/2.5/find?units=' + pluginConfig.units + '&q=' + location, function(data) {
                try {
                    var weatherData = JSON.parse(data);

                    if (parseInt(weatherData.count, 10) === 0) {
                        channel.say(_.template(pluginConfig.messages.error, templateVars));
                    } else {
                        _.each(weatherData.list, function iterator(data) {
                            templateVars.weather = data;

                            channel.say(_.template(pluginConfig.messages.success, templateVars));
                        });
                    }
                } catch (error) {
                    channel.say('Oh noes, error: ' + error);
                }
            });
        }

        return {
            '^!weather (.+)': function(from, matches) {
                getWeather(matches[1], from);
            }
        };
    }
};
<|endoftext|>


<commit_before>/* jQRangeSlider
 * A javascript slider selector that supports dates
 *
 * Copyright (C) Guillaume Gautreau 2012
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 */

(function(){
	"use strict";
	/*jshint maxstatements: 100*/

	var editSetup = new TestCase(
		'Setup for EditSlider',
		function(){
			el.empty();
		},
		null);

	var ctorTest = new TestCase(
		"Default ctor test",
		function(){
			el.editRangeSlider();
		},
		function(){
			QUnit.ok(el.hasClass("ui-editRangeSlider"), "ui-editRangeSlider class should have been added " + el.attr("class"));

			var inputs = el.find(".ui-rangeSlider-label input.ui-editRangeSlider-inputValue");

			QUnit.equal(inputs.length, 2, "Input should have been created");
			QUnit.equal(inputs.attr("type"), "text", "Default type is text");
		}
	);

	var destroyTest = new TestCase(
		"Destroy test",
		function(){
			el.editRangeSlider("destroy");
		},
		function(){
			QUnit.equal(el.attr("class"), "", "Class should be empty after destroy");
		}
	);

	var destroy = new TestCase(
		"Destroy",
		function(){
			el.editRangeSlider("destroy");
		},
		null);

	var typeCtor = new TestCase(
		"Ctor specifying input type",
		function(){
			el.editRangeSlider({
				type: "number"
			});
		},
		function(){
			QUnit.equal(el.find("input").attr("type"), "number", "Input type should have been modified");
		}
	);

	var setType = new TestCase(
		"Input type setter",
		function(){},
		function(){
			testInputType("text");
			testInputType("number");
		}
	);

	function testInputType(type){
		el.editRangeSlider("option", "type", type);
		QUnit.equal(el.editRangeSlider("option", "type"), type, "Type option should have been set");
		QUnit.equal(el.find("input").attr("type"), type, "Type should be used by inputs");
	}

	var setInvalidType = new TestCase(
		"Invalid input type",
		function(){
			el.editRangeSlider("option", "type", "date");
		},
		function(){
			QUnit.ok(el.editRangeSlider("option", "type") !== "date", "Invalid input type should not be set");
			QUnit.ok(el.find("input").attr("type") !== "date", "Invalid input type");
		}
	);

	var enterKeyBindingTest = new TestCase(
		"Value change on enter",
		function(){
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]);

			input.val("40")
				.simulate("keyup", {which: 13});
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Entered value should have been set");
		}
	);

	var clickBindingTest = new TestCase(
		"Value change on click",
		function(){
			el.editRangeSlider("option", "type", "number");
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]);
			input.val("40").focus().click();
		},

		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Value should have been set " + this.min() + " " + this.max());
		}
	);

	var clickBindingWithoutFocusTest = new TestCase(
		"Click on number input without focus",
		function(){
			el.editRangeSlider("option", "type", "number");
			el.editRangeSlider("values", 11, 55);
			var input = $(el.find("input")[0]);

			input.blur().val("40").click();
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() !== 40 || this.max() !== 40, "Value should not have been set")
		}
	);

	var blurBinding = new TestCase(
		"Change values on blur",
		function(){
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]);
			input.focus().val("40").blur();
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Value should have been set")
		}
	);

	var nameBasedOnId = new TestCase(
		"#27 name based on id",
		function(){
		},
		function(){
			QUnit.equal(el.find(".ui-rangeSlider-leftLabel input").attr("name"), "testleft");
			QUnit.equal(el.find(".ui-rangeSlider-rightLabel input").attr("name"), "testright");
		}
	);

	var stepNumberCtor = new TestCase(
		"Step option on ctor, with number inputs",
		function(){
			el.editRangeSlider({
				step: 5,
				type: "number"
			});
		},
		function(){
			var input = el.find("input");

			QUnit.equal(2, input.length, "Should have found 2 inputs");
			QUnit.equal("number", input.attr("type"), "Should be number input");
			QUnit.equal("5", input.attr("step"), "Step should be propagated to inputs");
		}
	);

	var stepNumberSetter = new TestCase(
		"Step option with number inputs",
		function(){
			el.editRangeSlider({
				step: 10,
				type: "number"
			});
		},
		function(){
			var input = el.find("input");

			QUnit.equal(input.length, 2, "Should have found 2 inputs");
			QUnit.equal("number", input.attr("type"), "Should be number input");
			QUnit.equal(input.attr("step"), '10', "Step should be propagated to inputs");

			el.editRangeSlider("option", "step", false);
			input = el.find("input");
			QUnit.equal(input.attr("step"), "any", "Step should be propagated to inputs");
		}
	);

	var disabledTest = new TestCase(
		"Test disabled state",
		function(){
			el = $("#test");
			el.editRangeSlider({
				enabled: false
			});
		},
		function(){
			QUnit.ok(el.find(".ui-rangeSlider-leftLabel input").is(":disabled"), "Input should be disabled");
			QUnit.ok(el.find(".ui-rangeSlider-rightLabel input").is(":disabled"), "Input should be disabled");

			el.editRangeSlider("destroy");
			el.empty();
		}
	);

	testRunner.add("jQEditRangeSlider", [
		editSetup,
		ctorTest,
		destroy,

		typeCtor, setType, setInvalidType,
		enterKeyBindingTest, clickBindingTest, clickBindingWithoutFocusTest, blurBinding,
		nameBasedOnId,

		destroy,
		stepNumberCtor, stepNumberSetter,

		destroyTest,

		disabledTest
	]);
})();<commit_msg>Simulating keyup event<commit_after>/* jQRangeSlider
 * A javascript slider selector that supports dates
 *
 * Copyright (C) Guillaume Gautreau 2012
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 */

(function(){
	"use strict";
	/*jshint maxstatements: 100*/

	var editSetup = new TestCase(
		'Setup for EditSlider',
		function(){
			el.empty();
		},
		null);

	var ctorTest = new TestCase(
		"Default ctor test",
		function(){
			el.editRangeSlider();
		},
		function(){
			QUnit.ok(el.hasClass("ui-editRangeSlider"), "ui-editRangeSlider class should have been added " + el.attr("class"));

			var inputs = el.find(".ui-rangeSlider-label input.ui-editRangeSlider-inputValue");

			QUnit.equal(inputs.length, 2, "Input should have been created");
			QUnit.equal(inputs.attr("type"), "text", "Default type is text");
		}
	);

	var destroyTest = new TestCase(
		"Destroy test",
		function(){
			el.editRangeSlider("destroy");
		},
		function(){
			QUnit.equal(el.attr("class"), "", "Class should be empty after destroy");
		}
	);

	var destroy = new TestCase(
		"Destroy",
		function(){
			el.editRangeSlider("destroy");
		},
		null);

	var typeCtor = new TestCase(
		"Ctor specifying input type",
		function(){
			el.editRangeSlider({
				type: "number"
			});
		},
		function(){
			QUnit.equal(el.find("input").attr("type"), "number", "Input type should have been modified");
		}
	);

	var setType = new TestCase(
		"Input type setter",
		function(){},
		function(){
			testInputType("text");
			testInputType("number");
		}
	);

	function testInputType(type){
		el.editRangeSlider("option", "type", type);
		QUnit.equal(el.editRangeSlider("option", "type"), type, "Type option should have been set");
		QUnit.equal(el.find("input").attr("type"), type, "Type should be used by inputs");
	}

	var setInvalidType = new TestCase(
		"Invalid input type",
		function(){
			el.editRangeSlider("option", "type", "date");
		},
		function(){
			QUnit.ok(el.editRangeSlider("option", "type") !== "date", "Invalid input type should not be set");
			QUnit.ok(el.find("input").attr("type") !== "date", "Invalid input type");
		}
	);

	var enterKeyBindingTest = new TestCase(
		"Value change on enter",
		function(){
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]),
				e = jQuery.Event("keyup");

			input.val("40");

			e.which = 13;
			input.trigger(e);
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Entered value should have been set");
		}
	);

	var clickBindingTest = new TestCase(
		"Value change on click",
		function(){
			el.editRangeSlider("option", "type", "number");
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]);
			input.val("40").focus().click();
		},

		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Value should have been set " + this.min() + " " + this.max());
		}
	);

	var clickBindingWithoutFocusTest = new TestCase(
		"Click on number input without focus",
		function(){
			el.editRangeSlider("option", "type", "number");
			el.editRangeSlider("values", 11, 55);
			var input = $(el.find("input")[0]);

			input.blur().val("40").click();
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() !== 40 || this.max() !== 40, "Value should not have been set")
		}
	);

	var blurBinding = new TestCase(
		"Change values on blur",
		function(){
			el.editRangeSlider("values", 11, 55);

			var input = $(el.find("input")[0]);
			input.focus().val("40").blur();
		},
		function(){
			this.type = "editRangeSlider";
			QUnit.ok(this.min() === 40 || this.max() === 40, "Value should have been set")
		}
	);

	var nameBasedOnId = new TestCase(
		"#27 name based on id",
		function(){
		},
		function(){
			QUnit.equal(el.find(".ui-rangeSlider-leftLabel input").attr("name"), "testleft");
			QUnit.equal(el.find(".ui-rangeSlider-rightLabel input").attr("name"), "testright");
		}
	);

	var stepNumberCtor = new TestCase(
		"Step option on ctor, with number inputs",
		function(){
			el.editRangeSlider({
				step: 5,
				type: "number"
			});
		},
		function(){
			var input = el.find("input");

			QUnit.equal(2, input.length, "Should have found 2 inputs");
			QUnit.equal("number", input.attr("type"), "Should be number input");
			QUnit.equal("5", input.attr("step"), "Step should be propagated to inputs");
		}
	);

	var stepNumberSetter = new TestCase(
		"Step option with number inputs",
		function(){
			el.editRangeSlider({
				step: 10,
				type: "number"
			});
		},
		function(){
			var input = el.find("input");

			QUnit.equal(input.length, 2, "Should have found 2 inputs");
			QUnit.equal("number", input.attr("type"), "Should be number input");
			QUnit.equal(input.attr("step"), '10', "Step should be propagated to inputs");

			el.editRangeSlider("option", "step", false);
			input = el.find("input");
			QUnit.equal(input.attr("step"), "any", "Step should be propagated to inputs");
		}
	);

	var disabledTest = new TestCase(
		"Test disabled state",
		function(){
			el = $("#test");
			el.editRangeSlider({
				enabled: false
			});
		},
		function(){
			QUnit.ok(el.find(".ui-rangeSlider-leftLabel input").is(":disabled"), "Input should be disabled");
			QUnit.ok(el.find(".ui-rangeSlider-rightLabel input").is(":disabled"), "Input should be disabled");

			el.editRangeSlider("destroy");
			el.empty();
		}
	);

	testRunner.add("jQEditRangeSlider", [
		editSetup,
		ctorTest,
		destroy,

		typeCtor, setType, setInvalidType,
		enterKeyBindingTest, clickBindingTest, clickBindingWithoutFocusTest, blurBinding,
		nameBasedOnId,

		destroy,
		stepNumberCtor, stepNumberSetter,

		destroyTest,

		disabledTest
	]);
})();<|endoftext|>


<commit_before>var serve = (function (options) {
	const fs = require('fs');
	const express = require('express');
	const app = express();
	var http;
	var travisHandler;
	const path = require('path');
	const compression = require('compression');
	const session = require('express-session');
	const MongoStore = require('connect-mongo')(session);
	const mongoose = require('mongoose');
	const async = require('async');
	const Handlebars = require('handlebars');
	const bodyParser = require('body-parser');
	const nconf = require('nconf');
	const helpers = require('./helpers');
	const getTemplate = helpers.getTemplate;
	const doError = helpers.doError;
	const createTravisHandler = require('./travis-webhook');
	const childProcess = require('child_process');
	var isFunction = Handlebars.Utils.isFunction;
	nconf.argv()
		.env()
		.file({file: 'config.json'})
		.overrides(options)
		.defaults({
			database: {
				host: 'localhost',
				database: 'curlcsc',
				port: 27017
			},
			ssl: false,
			port: 2000,
			deploy: {
				"travis-token": null,
				script: ""
			},
			cookie_secret: "CHANGE THIS"
		});

	if (nconf.get('ssl')) {
		var SSLSettings = nconf.get('ssl');
		var newSSLSettings = {};
		if (SSLSettings.key) newSSLSettings.key = fs.readFileSync(SSLSettings.key);
		if (SSLSettings.cert) newSSLSettings.cert = fs.readFileSync(SSLSettings.cert);
		if (SSLSettings.pfx) newSSLSettings.pfx = fs.readFileSync(SSLSettings.pfx);
		http = require('https').createServer(Object.assign(SSLSettings, newSSLSettings), app);
	} else {
		http = require('http').createServer(app);
	}

	app.set('trust proxy', 'loopback');
	app.use((req, res, next)=> {
		req.path = path.normalize(req.path);
		next();
	});
	app.all("/content/*", (req, res, next)=> {
		req.content = true;
		req.url = path.normalize(req.params[0] === "" ? "/" : req.params[0]);
		next();
	});
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({extended: true}));
	function connectMongoose(cb) {
		mongoose.connect('mongodb://' + nconf.get('database:host') + ':' + nconf.get('database:port') + '/' + nconf.get('database:database'), {
			user: nconf.get('database:user'),
			pass: nconf.get('database:password')
		}, (err)=> {
			if (err) {
				console.error("Fatal Exception: Could not establish connection to MongoDB");
				console.error(err);
				cb(err);
			} else isFunction(cb) && cb(err);
		});
	}

	var sessionHandler = session({
		secret: nconf.get('cookie_secret'),
		cookie: {secure: 'auto'},
		resave: false,
		saveUninitialized: false
	});

	function connectMongoStore() {
		sessionHandler = session({
			store: new MongoStore({mongooseConnection: mongoose.connection}),
			secret: nconf.get('cookie_secret'),
			cookie: {secure: 'auto'},
			resave: false,
			saveUninitialized: false
		});
	}

	app.use((req, res, next)=> {
		sessionHandler(req, res, next);
	});
	app.use(compression());

	if (nconf.get('deploy:travis-token') !== null) {
		if (nconf.get('deploy:travis-token') === "") {
			travisHandler = createTravisHandler();
			app.use('/deploy', travisHandler);
		} else {
			travisHandler = createTravisHandler(nconf.get('travis-token'));
			app.use('/deploy', travisHandler);
		}
		travisHandler.on('success', data=> {
			if (data.type === 'push' && data.branch === 'master') {
				childProcess.exec(nconf.get('deploy:script'))
			}
		});
	}

	app.use(require('./routes/users'));
	app.use(require('./routes/spreadsheet'));
	app.use(require('./content'));
	app.use((req, res, next) => {
		var reqURI = req.path;
		var checkPath = path.normalize("public/" + reqURI);
		checkRaw(checkPath, result=> {
			if (result !== null) {
				if (result.isDir) {
					//TODO: add directory viewer
				} else if (!req.content) return res.sendFile(path.resolve(result.path));
				else if (req.content) return res.end(req.path);
			}
			next();
		});
	});

	function startServer() {
		http.listen(nconf.get('port'), () => {
			console.log('listening on *:' + nconf.get('port'));
		});
	}

	function checkRaw(checkPath, callback) {
		async.parallel([
			callback=>fs.stat(checkPath, (err, stats)=> {
				if (!err) {
					if (stats.isDirectory()) {
						fs.stat(checkPath + "/index.html", (err, stats)=> {
							if (!err && !stats.isDirectory()) callback(null, {
								path: path.normalize(checkPath + "/index.html"),
								isDir: false
							}); else callback(null, {path: path.normalize(checkPath), isDir: true});
						});
					} else callback(null, {path: path.normalize(checkPath), isDir: false});
				} else callback(null, null);
			}),
			callback=>fs.stat(checkPath + ".html", (err, stats)=> {
				if (!err && !stats.isDirectory()) {
					callback(null, {path: path.normalize(checkPath + ".html"), isDir: false})
				} else callback(null, null);
			})], (err, results)=> {
			var bestMatch = null;
			results.forEach(item=> {
				if (item !== null) {
					if (bestMatch === null) bestMatch = item;
					else if (item.isDir === false && bestMatch.isDir === true) bestMatch = item;
				}
			});
			!Handlebars.Utils.isFunction(callback) || callback(bestMatch);
		});
	}

	app.use((req, res) => {
		doError(404, req, res);
	});
	app.use((err, req, res, next) => {
		console.log(err);
		doError(500, req, res);
	});
	if (require.main === module) {
		try {
			connectMongoose(err=> {
				if (err) process.exit(1);
			});
			connectMongoStore();
			startServer();
		} catch (e) {
			process.exit(1);
		}
	} else {
		exports.connectMongoose = connectMongoose;
		exports.connectMongoStore = connectMongoStore;
		exports.startServer = startServer;
		exports.stop = () => {
			http.close();
			mongoose.disconnect()
		};
	}
});
if (require.main === module) {
	serve();
}else{
	exports.init = function(options){
		serve(options);
		return this;
	};
}<commit_msg>Add graceful stop<commit_after>var serve = (function (options) {
	const fs = require('fs');
	const express = require('express');
	const app = express();
	var http;
	var travisHandler;
	const path = require('path');
	const compression = require('compression');
	const session = require('express-session');
	const MongoStore = require('connect-mongo')(session);
	const mongoose = require('mongoose');
	const async = require('async');
	const Handlebars = require('handlebars');
	const bodyParser = require('body-parser');
	const nconf = require('nconf');
	const helpers = require('./helpers');
	const getTemplate = helpers.getTemplate;
	const doError = helpers.doError;
	const createTravisHandler = require('./travis-webhook');
	const childProcess = require('child_process');
	var isFunction = Handlebars.Utils.isFunction;
	nconf.argv()
		.env()
		.file({file: 'config.json'})
		.overrides(options)
		.defaults({
			database: {
				host: 'localhost',
				database: 'curlcsc',
				port: 27017
			},
			ssl: false,
			port: 2000,
			deploy: {
				"travis-token": null,
				script: ""
			},
			cookie_secret: "CHANGE THIS"
		});

	if (nconf.get('ssl')) {
		var SSLSettings = nconf.get('ssl');
		var newSSLSettings = {};
		if (SSLSettings.key) newSSLSettings.key = fs.readFileSync(SSLSettings.key);
		if (SSLSettings.cert) newSSLSettings.cert = fs.readFileSync(SSLSettings.cert);
		if (SSLSettings.pfx) newSSLSettings.pfx = fs.readFileSync(SSLSettings.pfx);
		http = require('https').createServer(Object.assign(SSLSettings, newSSLSettings), app);
	} else {
		http = require('http').createServer(app);
	}

	app.set('trust proxy', 'loopback');
	app.use((req, res, next)=> {
		req.path = path.normalize(req.path);
		next();
	});
	app.all("/content/*", (req, res, next)=> {
		req.content = true;
		req.url = path.normalize(req.params[0] === "" ? "/" : req.params[0]);
		next();
	});
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({extended: true}));
	function connectMongoose(cb) {
		mongoose.connect('mongodb://' + nconf.get('database:host') + ':' + nconf.get('database:port') + '/' + nconf.get('database:database'), {
			user: nconf.get('database:user'),
			pass: nconf.get('database:password')
		}, (err)=> {
			if (err) {
				console.error("Fatal Exception: Could not establish connection to MongoDB");
				console.error(err);
				cb(err);
			} else isFunction(cb) && cb(err);
		});
	}

	var sessionHandler = session({
		secret: nconf.get('cookie_secret'),
		cookie: {secure: 'auto'},
		resave: false,
		saveUninitialized: false
	});

	function connectMongoStore() {
		sessionHandler = session({
			store: new MongoStore({mongooseConnection: mongoose.connection}),
			secret: nconf.get('cookie_secret'),
			cookie: {secure: 'auto'},
			resave: false,
			saveUninitialized: false
		});
	}

	app.use((req, res, next)=> {
		sessionHandler(req, res, next);
	});
	app.use(compression());

	if (nconf.get('deploy:travis-token') !== null) {
		if (nconf.get('deploy:travis-token') === "") {
			travisHandler = createTravisHandler();
			app.use('/deploy', travisHandler);
		} else {
			travisHandler = createTravisHandler(nconf.get('travis-token'));
			app.use('/deploy', travisHandler);
		}
		travisHandler.on('success', data=> {
			if (data.type === 'push' && data.branch === 'master') {
				childProcess.exec(nconf.get('deploy:script'))
			}
		});
	}

	app.use(require('./routes/users'));
	app.use(require('./routes/spreadsheet'));
	app.use(require('./content'));
	app.use((req, res, next) => {
		var reqURI = req.path;
		var checkPath = path.normalize("public/" + reqURI);
		checkRaw(checkPath, result=> {
			if (result !== null) {
				if (result.isDir) {
					//TODO: add directory viewer
				} else if (!req.content) return res.sendFile(path.resolve(result.path));
				else if (req.content) return res.end(req.path);
			}
			next();
		});
	});

	function startServer() {
		http.listen(nconf.get('port'), () => {
			console.log('listening on *:' + nconf.get('port'));
		});
	}

	function checkRaw(checkPath, callback) {
		async.parallel([
			callback=>fs.stat(checkPath, (err, stats)=> {
				if (!err) {
					if (stats.isDirectory()) {
						fs.stat(checkPath + "/index.html", (err, stats)=> {
							if (!err && !stats.isDirectory()) callback(null, {
								path: path.normalize(checkPath + "/index.html"),
								isDir: false
							}); else callback(null, {path: path.normalize(checkPath), isDir: true});
						});
					} else callback(null, {path: path.normalize(checkPath), isDir: false});
				} else callback(null, null);
			}),
			callback=>fs.stat(checkPath + ".html", (err, stats)=> {
				if (!err && !stats.isDirectory()) {
					callback(null, {path: path.normalize(checkPath + ".html"), isDir: false})
				} else callback(null, null);
			})], (err, results)=> {
			var bestMatch = null;
			results.forEach(item=> {
				if (item !== null) {
					if (bestMatch === null) bestMatch = item;
					else if (item.isDir === false && bestMatch.isDir === true) bestMatch = item;
				}
			});
			!Handlebars.Utils.isFunction(callback) || callback(bestMatch);
		});
	}

	app.use((req, res) => {
		doError(404, req, res);
	});
	app.use((err, req, res, next) => {
		console.log(err);
		doError(500, req, res);
	});

	exports.connectMongoose = connectMongoose;
	exports.connectMongoStore = connectMongoStore;
	exports.startServer = startServer;
	exports.stop = () => {
		http.close();
		mongoose.disconnect()
	};
	if (require.main === module) {
		try {
			connectMongoose(err=> {
				if (err) process.exit(1);
			});
			connectMongoStore();
			startServer();
		} catch (e) {
			process.exit(1);
		}
	}
	if (process.platform === "win32") {
		var rl = require("readline").createInterface({
			input: process.stdin,
			output: process.stdout
		});

		rl.on("SIGINT", function () {
			process.emit("SIGINT");
		});
	}

	process.on("SIGINT", function () {
		exports.stop();
		console.log('stopping');
		process.exit();
	});
});
if (require.main === module) {
	serve();
}else{
	exports.init = function(options){
		serve(options);
		return this;
	};
}<|endoftext|>


<commit_before>import StyleSheetShim from 'dinosheets/shim';

let styleSheet = null;
let element = null;

// Retrieve the computed style of the element
function getStyles(element) {
  if (document.defaultView && document.defaultView.getComputedStyle) {
    return document.defaultView.getComputedStyle(element, null);
  }
  return element.currentStyle;
};

module('StyleSheetShim', {
  beforeEach() {
    element = document.createElement('style');
    const head = document.getElementsByTagName('head')[0] ||
                 document.documentElement;
    element.type = 'text/css';
    element.media = 'all';

    head.appendChild(element);

    styleSheet = new StyleSheetShim(document.styleSheets[document.styleSheets.length - 1]);
  },
  afterEach() {
    const head = document.getElementsByTagName('head')[0] ||
                 document.documentElement;
    head.removeChild(element);
  }
});

test('it returns a list of rules for the stylesheet', function (assert) {
  styleSheet.appendRule('body', {
    backgroundColor: 'green'
  });
  styleSheet.appendRule('p', {
    color: 'white'
  });
  assert.equal(styleSheet.rules().length, 2);
});

test('inserting a rule has the desired effect on the page', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  let styles = getStyles(document.body);
  assert.equal(styles.fontSize, '200px');
});

test('rules are returned in order of insertion', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  styleSheet.appendRule('p', {
    display: 'none'
  });
  styleSheet.appendRule('em', {
    color: 'green'
  });

  let rules = styleSheet.rules();
  assert.equal(rules[0].selectorText.toLowerCase(), 'body');
  assert.equal(rules[1].selectorText.toLowerCase(), 'p');
  assert.equal(rules[2].selectorText.toLowerCase(), 'em');
});

test('ruleFor returns the correct rules', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  styleSheet.appendRule('p', {
    display: 'none'
  });
  styleSheet.appendRule('em', {
    fontWeight: 'bold'
  });

  let rule = styleSheet.ruleFor('body').rule.style;
  assert.equal(rule.cssText, 'body { font-size: 200px; }')
  rule = styleSheet.ruleFor('p').rule.style;
  assert.equal(rule.cssText, 'p { display: none; }');
  rule = styleSheet.ruleFor('em').rule.style;
  assert.equal(rule.cssText, 'em { font-weight: bold; }');
});

test('rules can be updated', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });

  let styles = getStyles(document.body);
  assert.equal(styles.fontSize, '200px');

  styleSheet.updateRule('body', {
    fontSize: '10px'
  });

  styles = getStyles(document.body);
  assert.equal(styles.fontSize, '10px');
});
<commit_msg>normalize CSS text for IE testing<commit_after>import StyleSheetShim from 'dinosheets/shim';

let styleSheet = null;
let element = null;

// Retrieve the computed style of the element
function getStyles(element) {
  if (document.defaultView && document.defaultView.getComputedStyle) {
    return document.defaultView.getComputedStyle(element, null);
  }
  return element.currentStyle;
};

function cssText(rule) {
  let style = rule.style.cssText;
  if (style.charAt(style.length - 1) !== ';') {
    style = style + ';';
  }
  return style.toLowerCase();
}

module('StyleSheetShim', {
  beforeEach() {
    element = document.createElement('style');
    const head = document.getElementsByTagName('head')[0] ||
                 document.documentElement;
    element.type = 'text/css';
    element.media = 'all';

    head.appendChild(element);

    styleSheet = new StyleSheetShim(document.styleSheets[document.styleSheets.length - 1]);
  },
  afterEach() {
    const head = document.getElementsByTagName('head')[0] ||
                 document.documentElement;
    head.removeChild(element);
  }
});

test('it returns a list of rules for the stylesheet', function (assert) {
  styleSheet.appendRule('body', {
    backgroundColor: 'green'
  });
  styleSheet.appendRule('p', {
    color: 'white'
  });
  assert.equal(styleSheet.rules().length, 2);
});

test('inserting a rule has the desired effect on the page', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  let styles = getStyles(document.body);
  assert.equal(styles.fontSize, '200px');
});

test('rules are returned in order of insertion', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  styleSheet.appendRule('p', {
    display: 'none'
  });
  styleSheet.appendRule('em', {
    color: 'green'
  });

  let rules = styleSheet.rules();
  assert.equal(rules[0].selectorText.toLowerCase(), 'body');
  assert.equal(rules[1].selectorText.toLowerCase(), 'p');
  assert.equal(rules[2].selectorText.toLowerCase(), 'em');
});

test('ruleFor returns the correct rules', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });
  styleSheet.appendRule('p', {
    display: 'none'
  });
  styleSheet.appendRule('em', {
    fontWeight: 'bold'
  });

  let rule = styleSheet.ruleFor('body').rule;
  assert.equal(cssText(rule), 'font-size: 200px')
  rule = styleSheet.ruleFor('p').rule.style;
  assert.equal(cssText(rule), 'display: none');
  rule = styleSheet.ruleFor('em').rule.style;
  assert.equal(cssText(rule), 'font-weight: bold');
});

test('rules can be updated', function (assert) {
  styleSheet.appendRule('body', {
    fontSize: '200px'
  });

  let styles = getStyles(document.body);
  assert.equal(styles.fontSize, '200px');

  styleSheet.updateRule('body', {
    fontSize: '10px'
  });

  styles = getStyles(document.body);
  assert.equal(styles.fontSize, '10px');
});
<|endoftext|>


<commit_before>/**
 * Expose the compile function
 */

exports = module.exports = compile;

/**
 * Expose the interpolate function
 */

exports.interpolate = interpolate;

/**
 * Interpolate a string without a compilation step
 *
 * THIS IS NOT RECOMMENDED FOR PRODUCTION USE
 *
 * @param {String} string
 * @param {Object?} params
 * @param {Object?} opts
 */

function interpolate(string, params, opts) {
  return compile(string, opts)(params).join('');
};

/**
 * Compile a string into an interpolate function
 *
 * @param {String} string
 * @param {Object?} opts
 * @return {Function}
 */

function compile(string, opts) {
  opts = opts || {};
  var open = escapeRegex(opts.open || '%{');
  var close = opts.close || '}';
  var char = close.charAt(0);
  var re = new RegExp('(' + escapeRegex(open) + ' *[^' + escapeRegex(char) + ']+ *' + escapeRegex(close) + ')', 'g');

  var params = 'params';

  var fallback = opts.fallback ?
        ' || ' + JSON.stringify(opts.fallback) :
        '';

  var rawParts = string.split(re);
  var parts = [], paramsObj = {};
  for (var i = 0, l = rawParts.length, part, prop; i < l; i++) {
    part = rawParts[i];

    // skip the blank parts
    if (!part) continue;

    // it's normal text
    if (part.indexOf(open) !== 0 && part.indexOf(close) !== part.length - close.length) {
      parts.push(JSON.stringify(part));
      continue;
    }

    // it's a interpolation part
    part = part.slice(open.length, -close.length);
    prop = formatProperty(part, params);
    paramsObj[prop[1] || part] = 1;
    parts.push(prop[0] + fallback);
  }

  var fn = new Function('exec, ' + params,
    params + ' = ' + params + ' || {};\nreturn [' + parts.join(', ') + '];');
  fn.params = paramsObj;
  return fn.bind(null, exec);
}

/**
 * Execute a function for a block
 *
 * @param {String} name
 * @param {String} contents
 * @param {Object} params
 * @return {Any}
 */

function exec(name, contents, params) {
  var fn = params[name];
  var type = typeof fn;
  if (type === 'function') return fn(contents, params);
  return type === 'undefined' ? contents : fn;
}

/**
 * Escape any reserved regex characters
 *
 * @param {String} str
 * @return {String}
 */

function escapeRegex(str) {
  return str.replace(/[\^\-\]\\]/g, function(c) {
    return '\\' + c;
  });
}

/**
 * Format a property accessor
 *
 * @param {String} prop
 * @param {String} params
 * @return {String}
 */

var re = /^[\w\d]+$/;
function formatProperty(prop, params) {
  if (!re.test(prop)) {
    var parts = prop.split(/ *: */);
    if (parts.length === 1) return [params + '[' + JSON.stringify(prop) + ']'];

    return ['exec("' + parts[0] + '", "' + parts[1] + '", ' + params + ')', parts[0]];
  }
  var int = parseInt(prop, 10);
  if (isNaN(int)) return [params + '.' + prop];
  return [params + '[' + prop + ']'];
}
<commit_msg>fix params on returned function<commit_after>/**
 * Expose the compile function
 */

exports = module.exports = compile;

/**
 * Expose the interpolate function
 */

exports.interpolate = interpolate;

/**
 * Interpolate a string without a compilation step
 *
 * THIS IS NOT RECOMMENDED FOR PRODUCTION USE
 *
 * @param {String} string
 * @param {Object?} params
 * @param {Object?} opts
 */

function interpolate(string, params, opts) {
  return compile(string, opts)(params).join('');
};

/**
 * Compile a string into an interpolate function
 *
 * @param {String} string
 * @param {Object?} opts
 * @return {Function}
 */

function compile(string, opts) {
  opts = opts || {};
  var open = escapeRegex(opts.open || '%{');
  var close = opts.close || '}';
  var char = close.charAt(0);
  var re = new RegExp('(' + escapeRegex(open) + ' *[^' + escapeRegex(char) + ']+ *' + escapeRegex(close) + ')', 'g');

  var params = 'params';

  var fallback = opts.fallback ?
        ' || ' + JSON.stringify(opts.fallback) :
        '';

  var rawParts = string.split(re);
  var parts = [], paramsObj = {};
  for (var i = 0, l = rawParts.length, part, prop; i < l; i++) {
    part = rawParts[i];

    // skip the blank parts
    if (!part) continue;

    // it's normal text
    if (part.indexOf(open) !== 0 && part.indexOf(close) !== part.length - close.length) {
      parts.push(JSON.stringify(part));
      continue;
    }

    // it's a interpolation part
    part = part.slice(open.length, -close.length);
    prop = formatProperty(part, params);
    paramsObj[prop[1] || part] = 1;
    parts.push(prop[0] + fallback);
  }

  var fn = new Function('exec, ' + params,
    params + ' = ' + params + ' || {};\nreturn [' + parts.join(', ') + '];').bind(null, exec);
  fn.params = paramsObj;
  return fn;
}

/**
 * Execute a function for a block
 *
 * @param {String} name
 * @param {String} contents
 * @param {Object} params
 * @return {Any}
 */

function exec(name, contents, params) {
  var fn = params[name];
  var type = typeof fn;
  if (type === 'function') return fn(contents, params);
  return type === 'undefined' ? contents : fn;
}

/**
 * Escape any reserved regex characters
 *
 * @param {String} str
 * @return {String}
 */

function escapeRegex(str) {
  return str.replace(/[\^\-\]\\]/g, function(c) {
    return '\\' + c;
  });
}

/**
 * Format a property accessor
 *
 * @param {String} prop
 * @param {String} params
 * @return {String}
 */

var re = /^[\w\d]+$/;
function formatProperty(prop, params) {
  if (!re.test(prop)) {
    var parts = prop.split(/ *: */);
    if (parts.length === 1) return [params + '[' + JSON.stringify(prop) + ']'];

    return ['exec("' + parts[0] + '", "' + parts[1] + '", ' + params + ')', parts[0]];
  }
  var int = parseInt(prop, 10);
  if (isNaN(int)) return [params + '.' + prop];
  return [params + '[' + prop + ']'];
}
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through2');
var concat = require('concat-stream');
var parents = require('parents');
var combine = require('stream-combiner2');
var duplexer = require('duplexer2');
var copy = require('shallow-copy');

var inherits = require('inherits');
var Transform = require('readable-stream').Transform;

module.exports = Deps;
inherits(Deps, Transform);

function Deps (opts) {
    var self = this;
    if (!(this instanceof Deps)) return new Deps(opts);
    Transform.call(this, { objectMode: true });

    if (!opts) opts = {};

    this.basedir = opts.basedir || process.cwd();
    this.cache = opts.cache;
    this.pkgCache = opts.packageCache || {};
    this.pkgFileCache = {};
    this.pkgFileCachePending = {};
    this.visited = {};
    this.walking = {};
    this.entries = [];
    this._input = [];

    this.paths = opts.paths || process.env.NODE_PATH;
    if (typeof this.paths === 'string') {
        this.paths = process.env.NODE_PATH.split(':');
    }
    if (!this.paths) this.paths = [];

    this.transforms = [].concat(opts.transform).filter(Boolean);
    this.globalTransforms = [].concat(opts.globalTransform).filter(Boolean);
    this.resolver = opts.resolve || browserResolve;
    this.options = copy(opts || {});
    if (!this.options.modules) this.options.modules = {};
    this.pending = 0;

    var topfile = path.join(this.basedir, '__fake.js');
    this.top = { id: topfile, filename: topfile, paths: this.paths };
}

Deps.prototype._transform = function (row, enc, next) {
    var self = this;
    if (typeof row === 'string') {
        row = { file: row };
    }
    if (row.transform && row.global) {
        this.globalTransforms.push([ row.transform, row.options ]);
        return next();
    }
    else if (row.transform) {
        this.transforms.push([ row.transform, row.options ]);
        return next();
    }

    self.pending ++;
    if (row.entry !== false) self.entries.push(row.file);

    self.lookupPackage(row.file, function (err, pkg) {
        if (err && self.options.ignoreMissing) {
            self.emit('missing', row.file, self.top);
            self.pending --;
            return next();
        }
        if (err) return self.emit('error', err)
        self.pending --;
        self._input.push({ row: row, pkg: pkg });
        next();
    });
};

Deps.prototype._flush = function () {
    var self = this;
    var files = {};
    self._input.forEach(function (r) {
        var w = r.row, f = files[w.file || w.id];
        if (f) {
            f.row.entry = f.row.entry || w.entry;
            var ex = f.row.expose || w.expose;
            f.row.expose = ex;
            if (ex && f.row.file === f.row.id && w.file !== w.id) {
                f.row.id = w.id;
            }
        }
        else files[w.file || w.id] = r;
    });

    Object.keys(files).forEach(function (key) {
        var r = files[key];
        var pkg = r.pkg || {};
        if (!pkg.__dirname) pkg.__dirname = path.dirname(r.row.file);
        self.walk(r.row, self.top);
    });
    if (this.pending === 0) this.push(null);
    this._ended = true;
};

Deps.prototype.resolve = function (id, parent, cb) {
    var self = this;
    var opts = self.options;

    if (xhas(self.cache, parent.id, 'deps', id)
    && self.cache[parent.id].deps) {
        var file = self.cache[parent.id].deps[id];
        var pkg = self.pkgCache[file];
        if (pkg) return cb(null, file, pkg);
        return self.lookupPackage(file, function (err, pkg) {
            cb(null, file, pkg);
        });
    }

    var pkgdir;
    parent.packageFilter = function (p, x) {
        pkgdir = x;
        if (opts.packageFilter) return opts.packageFilter(p, x);
        else return p;
    };

    if (opts.extensions) parent.extensions = opts.extensions;
    if (opts.modules) parent.modules = opts.modules;

    self.resolver(id, parent, function onresolve (err, file, pkg) {
        if (err) return cb(err);
        if (!file) return cb(new Error(
            'module not found: "' + id + '" from file '
            + parent.filename
        ));

        if (pkg && pkgdir) pkg.__dirname = pkgdir;
        if (!pkg || !pkg.__dirname) {
            self.lookupPackage(file, function (err, p) {
                if (err) return cb(err);
                if (!p) p = {};
                if (!p.__dirname) p.__dirname = path.dirname(file);
                self.pkgCache[file] = p;
                onresolve(err, file, opts.packageFilter
                    ? opts.packageFilter(p, p.__dirname) : p
                );
            });
        }
        else cb(err, file, pkg);
    });
};

Deps.prototype.readFile = function (file, id, pkg) {
    var self = this;
    var tr = through();
    if (this.cache && this.cache[file]) {
        tr.push(this.cache[file].source);
        tr.push(null);
        return tr;
    }
    var rs = fs.createReadStream(file);
    rs.on('error', function (err) { self.emit('error', err) });
    this.emit('file', file, id);
    return rs;
};

Deps.prototype.getTransforms = function (file, pkg, opts) {
    if (!opts) opts = {};
    var self = this;

    var isTopLevel;
    if (opts.builtin) isTopLevel = false;
    else isTopLevel = this.entries.some(function (main) {
        var m = path.relative(path.dirname(main), file);
        return m.split(/[\\\/]/).indexOf('node_modules') < 0;
    });
    if (!isTopLevel && !opts.builtin) {
        var m = path.relative(this.basedir, file);
        isTopLevel = m.split(/[\\\/]/).indexOf('node_modules') < 0;
    }

    var transforms = [].concat(isTopLevel ? this.transforms : [])
        .concat(getTransforms(pkg, {
            globalTransform: this.globalTransforms,
            transformKey: this.options.transformKey
        }))
    ;
    if (transforms.length === 0) return through();

    var pending = transforms.length;
    var streams = [];
    var input = through();
    var output = through();
    var dup = duplexer(input, output);

    for (var i = 0; i < transforms.length; i++) (function (i) {
        makeTransform(transforms[i], function (err, trs) {
            if (err) return self.emit('error', err)
            streams[i] = trs;
            if (-- pending === 0) done();
        });
    })(i);
    return dup;

    function done () {
        var middle = combine.apply(null, streams);
        middle.on('error', function (err) {
            err.message += ' while parsing file: ' + file;
            if (!err.filename) err.filename = file;
            self.emit('error', err);
        });
        input.pipe(middle).pipe(output);
    }

    function makeTransform (tr, cb) {
        var trOpts = {};
        if (Array.isArray(tr)) {
            trOpts = tr[1];
            tr = tr[0];
        }
        if (typeof tr === 'function') {
            var t = tr(file, trOpts);
            self.emit('transform', t, file);
            nextTick(cb, null, wrapTransform(t));
        }
        else {
            loadTransform(tr, trOpts, function (err, trs) {
                if (err) return cb(err);
                cb(null, wrapTransform(trs));
            });
        }
    }

    function loadTransform (id, trOpts, cb) {
        var params = { basedir: path.dirname(file) };
        nodeResolve(id, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                params.basedir = pkg.__dirname;
                return nodeResolve(id, params, function (e, r) {
                    nr(e, r, true)
                });
            }

            if (!res) return cb(new Error(
                'cannot find transform module ' + tr
                + ' while transforming ' + file
            ));

            var r = require(res);
            if (typeof r !== 'function') {
                return cb(new Error('transform not a function'));
            }

            var trs = r(file, trOpts);
            self.emit('transform', trs, file);
            cb(null, trs);
        });
    }
};

Deps.prototype.walk = function (id, parent, cb) {
    var self = this;
    var opts = self.options;
    this.pending ++;

    var rec = {};
    if (typeof id === 'object') {
        rec = copy(id);
        if (rec.entry === false) delete rec.entry;
        id = rec.file || rec.id;
    }

    self.resolve(id, parent, function (err, file, pkg) {
        if (rec.expose) {
            self.options.modules[rec.expose] = file;
        }
        if (pkg) self.emit('package', pkg);

        if (opts.postFilter && !opts.postFilter(id, file, pkg)) {
            if (--self.pending === 0) self.push(null);
            return cb(null, undefined);
        }
        if (err && rec.source) {
            file = rec.file;

            var ts = self.getTransforms(file, pkg);
            ts.pipe(concat(function (body) {
                rec.source = body.toString('utf8');
                fromSource(rec.source);
            }));
            return ts.end(rec.source);
        }
        if (err && self.options.ignoreMissing) {
            if (--self.pending === 0) self.push(null);
            self.emit('missing', id, parent);
            return cb && cb(null, undefined);
        }
        if (err) return self.emit('error', err);
        if (self.visited[file]) {
            if (-- self.pending === 0) self.push(null);
            return cb && cb(null, file);
        }
        self.visited[file] = true;

        if (rec.source) {
            var ts = self.getTransforms(file, pkg);
            ts.pipe(concat(function (body) {
                rec.source = body.toString('utf8');
                fromSource(rec.source);
            }));
            return ts.end(rec.source);
        }

        var c = self.cache && self.cache[file];
        if (c) return fromDeps(file, c.source, c.package, Object.keys(c.deps));

        self.readFile(file, id, pkg)
            .pipe(self.getTransforms(file, pkg, {
                builtin: has(parent.modules, id)
            }))
            .pipe(concat(function (body) {
                fromSource(body.toString('utf8'));
            }))
        ;

        function fromSource (src) {
            var deps = rec.noparse ? [] : self.parseDeps(file, src);
            if (deps) fromDeps(file, src, pkg, deps);
        }
    });

    function fromDeps (file, src, pkg, deps) {
        var p = deps.length;
        var current = {
            id: file,
            filename: file,
            paths: self.paths,
            package: pkg
        };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }
            self.walk(id, current, function (err, r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            if (!rec.id) rec.id = file;
            if (!rec.source) rec.source = src;
            if (!rec.deps) rec.deps = resolved;
            if (!rec.file) rec.file = file;

            if (self.entries.indexOf(file) >= 0) {
                rec.entry = true;
            }
            self.push(rec);

            if (cb) cb(null, file);
            if (-- self.pending === 0) self.push(null);
        }
    }
};

Deps.prototype.parseDeps = function (file, src, cb) {
    if (this.options.noParse === true) return [];
    if (/\.json$/.test(file)) return [];

    if (Array.isArray(this.options.noParse)
    && this.options.noParse.indexOf(file) >= 0) {
        return [];
    }

    try { var deps = detective(src) }
    catch (ex) {
        var message = ex && ex.message ? ex.message : ex;
        this.emit('error', new Error(
            'Parsing file ' + file + ': ' + message
        ));
        return;
    }
    return deps;
};

Deps.prototype.lookupPackage = function (file, cb) {
    var self = this;

    var cached = this.pkgCache[file];
    if (cached) return nextTick(cb, null, cached);
    if (cached === false) return nextTick(cb, null, undefined);

    var dirs = parents(path.dirname(file));

    (function next () {
        if (dirs.length === 0) {
            self.pkgCache[file] = false;
            return cb(null, undefined);
        }
        var dir = dirs.shift();
        if (dir.split(/[\\\/]/).slice(-1)[0] === 'node_modules') {
            return cb(null, undefined);
        }

        var pkgfile = path.join(dir, 'package.json');

        var cached = self.pkgCache[pkgfile];
        if (cached) return nextTick(cb, null, cached);
        else if (cached === false) return next();

        var pcached = self.pkgFileCachePending[pkgfile];
        if (pcached) return pcached.push(onpkg);
        pcached = self.pkgFileCachePending[pkgfile] = [];

        fs.readFile(pkgfile, function (err, src) {
            if (err) return onpkg();
            try { var pkg = JSON.parse(src) }
            catch (err) {
                return onpkg(new Error([
                    err + ' while parsing json file ' + pkgfile
                ].join('')))
            }
            pkg.__dirname = dir;

            self.pkgCache[pkgfile] = pkg;
            self.pkgCache[file] = pkg;
            onpkg(null, pkg);
        });

        function onpkg (err, pkg) {
            if (self.pkgFileCachePending[pkgfile]) {
                var fns = self.pkgFileCachePending[pkgfile];
                delete self.pkgFileCachePending[pkgfile];
                fns.forEach(function (f) { f(err, pkg) });
            }
            if (err) cb(err)
            else if (pkg) cb(null, pkg)
            else {
                self.pkgCache[pkgfile] = false;
                next();
            }
        }
    })();
};

function getTransforms (pkg, opts) {
    var trx = [];
    if (opts.transformKey) {
        var n = pkg;
        var keys = opts.transformKey;
        for (var i = 0; i < keys.length; i++) {
            if (n && typeof n === 'object') n = n[keys[i]];
            else break;
        }
        if (i === keys.length) {
            trx = [].concat(n).filter(Boolean);
        }
    }
    return trx.concat(opts.globalTransform || []);
}

function nextTick (cb) {
    var args = [].slice.call(arguments, 1);
    process.nextTick(function () { cb.apply(null, args) });
}

function xhas (obj) {
    if (!obj) return false;
    for (var i = 1; i < arguments.length; i++) {
        var key = arguments[i];
        if (!has(obj, key)) return false;
        obj = obj[key];
    }
    return true;
}

function has (obj, key) {
    return obj && Object.prototype.hasOwnProperty.call(obj, key);
}

function wrapTransform (tr) {
    if (typeof tr.read === 'function') return tr;
    var input = through(), output = through();
    input.pipe(tr).pipe(output);
    var wrapper = duplexer(input, output);
    tr.on('error', function (err) { wrapper.emit('error', err) });
    return wrapper;
}
<commit_msg>resolve paths relative to basedir<commit_after>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through2');
var concat = require('concat-stream');
var parents = require('parents');
var combine = require('stream-combiner2');
var duplexer = require('duplexer2');
var copy = require('shallow-copy');

var inherits = require('inherits');
var Transform = require('readable-stream').Transform;

module.exports = Deps;
inherits(Deps, Transform);

function Deps (opts) {
    var self = this;
    if (!(this instanceof Deps)) return new Deps(opts);
    Transform.call(this, { objectMode: true });

    if (!opts) opts = {};

    this.basedir = opts.basedir || process.cwd();
    this.cache = opts.cache;
    this.pkgCache = opts.packageCache || {};
    this.pkgFileCache = {};
    this.pkgFileCachePending = {};
    this.visited = {};
    this.walking = {};
    this.entries = [];
    this._input = [];

    this.paths = opts.paths || process.env.NODE_PATH;
    if (typeof this.paths === 'string') {
        this.paths = process.env.NODE_PATH.split(':');
    }
    if (!this.paths) this.paths = [];
    this.paths = this.paths.map(function (p) {
        return path.resolve(self.basedir, p);
    });

    this.transforms = [].concat(opts.transform).filter(Boolean);
    this.globalTransforms = [].concat(opts.globalTransform).filter(Boolean);
    this.resolver = opts.resolve || browserResolve;
    this.options = copy(opts || {});
    if (!this.options.modules) this.options.modules = {};
    this.pending = 0;

    var topfile = path.join(this.basedir, '__fake.js');
    this.top = { id: topfile, filename: topfile, paths: this.paths };
}

Deps.prototype._transform = function (row, enc, next) {
    var self = this;
    if (typeof row === 'string') {
        row = { file: row };
    }
    if (row.transform && row.global) {
        this.globalTransforms.push([ row.transform, row.options ]);
        return next();
    }
    else if (row.transform) {
        this.transforms.push([ row.transform, row.options ]);
        return next();
    }

    self.pending ++;
    if (row.entry !== false) self.entries.push(row.file);

    self.lookupPackage(row.file, function (err, pkg) {
        if (err && self.options.ignoreMissing) {
            self.emit('missing', row.file, self.top);
            self.pending --;
            return next();
        }
        if (err) return self.emit('error', err)
        self.pending --;
        self._input.push({ row: row, pkg: pkg });
        next();
    });
};

Deps.prototype._flush = function () {
    var self = this;
    var files = {};
    self._input.forEach(function (r) {
        var w = r.row, f = files[w.file || w.id];
        if (f) {
            f.row.entry = f.row.entry || w.entry;
            var ex = f.row.expose || w.expose;
            f.row.expose = ex;
            if (ex && f.row.file === f.row.id && w.file !== w.id) {
                f.row.id = w.id;
            }
        }
        else files[w.file || w.id] = r;
    });

    Object.keys(files).forEach(function (key) {
        var r = files[key];
        var pkg = r.pkg || {};
        if (!pkg.__dirname) pkg.__dirname = path.dirname(r.row.file);
        self.walk(r.row, self.top);
    });
    if (this.pending === 0) this.push(null);
    this._ended = true;
};

Deps.prototype.resolve = function (id, parent, cb) {
    var self = this;
    var opts = self.options;

    if (xhas(self.cache, parent.id, 'deps', id)
    && self.cache[parent.id].deps) {
        var file = self.cache[parent.id].deps[id];
        var pkg = self.pkgCache[file];
        if (pkg) return cb(null, file, pkg);
        return self.lookupPackage(file, function (err, pkg) {
            cb(null, file, pkg);
        });
    }

    var pkgdir;
    parent.packageFilter = function (p, x) {
        pkgdir = x;
        if (opts.packageFilter) return opts.packageFilter(p, x);
        else return p;
    };

    if (opts.extensions) parent.extensions = opts.extensions;
    if (opts.modules) parent.modules = opts.modules;

    self.resolver(id, parent, function onresolve (err, file, pkg) {
        if (err) return cb(err);
        if (!file) return cb(new Error(
            'module not found: "' + id + '" from file '
            + parent.filename
        ));

        if (pkg && pkgdir) pkg.__dirname = pkgdir;
        if (!pkg || !pkg.__dirname) {
            self.lookupPackage(file, function (err, p) {
                if (err) return cb(err);
                if (!p) p = {};
                if (!p.__dirname) p.__dirname = path.dirname(file);
                self.pkgCache[file] = p;
                onresolve(err, file, opts.packageFilter
                    ? opts.packageFilter(p, p.__dirname) : p
                );
            });
        }
        else cb(err, file, pkg);
    });
};

Deps.prototype.readFile = function (file, id, pkg) {
    var self = this;
    var tr = through();
    if (this.cache && this.cache[file]) {
        tr.push(this.cache[file].source);
        tr.push(null);
        return tr;
    }
    var rs = fs.createReadStream(file);
    rs.on('error', function (err) { self.emit('error', err) });
    this.emit('file', file, id);
    return rs;
};

Deps.prototype.getTransforms = function (file, pkg, opts) {
    if (!opts) opts = {};
    var self = this;

    var isTopLevel;
    if (opts.builtin) isTopLevel = false;
    else isTopLevel = this.entries.some(function (main) {
        var m = path.relative(path.dirname(main), file);
        return m.split(/[\\\/]/).indexOf('node_modules') < 0;
    });
    if (!isTopLevel && !opts.builtin) {
        var m = path.relative(this.basedir, file);
        isTopLevel = m.split(/[\\\/]/).indexOf('node_modules') < 0;
    }

    var transforms = [].concat(isTopLevel ? this.transforms : [])
        .concat(getTransforms(pkg, {
            globalTransform: this.globalTransforms,
            transformKey: this.options.transformKey
        }))
    ;
    if (transforms.length === 0) return through();

    var pending = transforms.length;
    var streams = [];
    var input = through();
    var output = through();
    var dup = duplexer(input, output);

    for (var i = 0; i < transforms.length; i++) (function (i) {
        makeTransform(transforms[i], function (err, trs) {
            if (err) return self.emit('error', err)
            streams[i] = trs;
            if (-- pending === 0) done();
        });
    })(i);
    return dup;

    function done () {
        var middle = combine.apply(null, streams);
        middle.on('error', function (err) {
            err.message += ' while parsing file: ' + file;
            if (!err.filename) err.filename = file;
            self.emit('error', err);
        });
        input.pipe(middle).pipe(output);
    }

    function makeTransform (tr, cb) {
        var trOpts = {};
        if (Array.isArray(tr)) {
            trOpts = tr[1];
            tr = tr[0];
        }
        if (typeof tr === 'function') {
            var t = tr(file, trOpts);
            self.emit('transform', t, file);
            nextTick(cb, null, wrapTransform(t));
        }
        else {
            loadTransform(tr, trOpts, function (err, trs) {
                if (err) return cb(err);
                cb(null, wrapTransform(trs));
            });
        }
    }

    function loadTransform (id, trOpts, cb) {
        var params = { basedir: path.dirname(file) };
        nodeResolve(id, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                params.basedir = pkg.__dirname;
                return nodeResolve(id, params, function (e, r) {
                    nr(e, r, true)
                });
            }

            if (!res) return cb(new Error(
                'cannot find transform module ' + tr
                + ' while transforming ' + file
            ));

            var r = require(res);
            if (typeof r !== 'function') {
                return cb(new Error('transform not a function'));
            }

            var trs = r(file, trOpts);
            self.emit('transform', trs, file);
            cb(null, trs);
        });
    }
};

Deps.prototype.walk = function (id, parent, cb) {
    var self = this;
    var opts = self.options;
    this.pending ++;

    var rec = {};
    if (typeof id === 'object') {
        rec = copy(id);
        if (rec.entry === false) delete rec.entry;
        id = rec.file || rec.id;
    }

    self.resolve(id, parent, function (err, file, pkg) {
        if (rec.expose) {
            self.options.modules[rec.expose] = file;
        }
        if (pkg) self.emit('package', pkg);

        if (opts.postFilter && !opts.postFilter(id, file, pkg)) {
            if (--self.pending === 0) self.push(null);
            return cb(null, undefined);
        }
        if (err && rec.source) {
            file = rec.file;

            var ts = self.getTransforms(file, pkg);
            ts.pipe(concat(function (body) {
                rec.source = body.toString('utf8');
                fromSource(rec.source);
            }));
            return ts.end(rec.source);
        }
        if (err && self.options.ignoreMissing) {
            if (--self.pending === 0) self.push(null);
            self.emit('missing', id, parent);
            return cb && cb(null, undefined);
        }
        if (err) return self.emit('error', err);
        if (self.visited[file]) {
            if (-- self.pending === 0) self.push(null);
            return cb && cb(null, file);
        }
        self.visited[file] = true;

        if (rec.source) {
            var ts = self.getTransforms(file, pkg);
            ts.pipe(concat(function (body) {
                rec.source = body.toString('utf8');
                fromSource(rec.source);
            }));
            return ts.end(rec.source);
        }

        var c = self.cache && self.cache[file];
        if (c) return fromDeps(file, c.source, c.package, Object.keys(c.deps));

        self.readFile(file, id, pkg)
            .pipe(self.getTransforms(file, pkg, {
                builtin: has(parent.modules, id)
            }))
            .pipe(concat(function (body) {
                fromSource(body.toString('utf8'));
            }))
        ;

        function fromSource (src) {
            var deps = rec.noparse ? [] : self.parseDeps(file, src);
            if (deps) fromDeps(file, src, pkg, deps);
        }
    });

    function fromDeps (file, src, pkg, deps) {
        var p = deps.length;
        var current = {
            id: file,
            filename: file,
            paths: self.paths,
            package: pkg
        };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }
            self.walk(id, current, function (err, r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            if (!rec.id) rec.id = file;
            if (!rec.source) rec.source = src;
            if (!rec.deps) rec.deps = resolved;
            if (!rec.file) rec.file = file;

            if (self.entries.indexOf(file) >= 0) {
                rec.entry = true;
            }
            self.push(rec);

            if (cb) cb(null, file);
            if (-- self.pending === 0) self.push(null);
        }
    }
};

Deps.prototype.parseDeps = function (file, src, cb) {
    if (this.options.noParse === true) return [];
    if (/\.json$/.test(file)) return [];

    if (Array.isArray(this.options.noParse)
    && this.options.noParse.indexOf(file) >= 0) {
        return [];
    }

    try { var deps = detective(src) }
    catch (ex) {
        var message = ex && ex.message ? ex.message : ex;
        this.emit('error', new Error(
            'Parsing file ' + file + ': ' + message
        ));
        return;
    }
    return deps;
};

Deps.prototype.lookupPackage = function (file, cb) {
    var self = this;

    var cached = this.pkgCache[file];
    if (cached) return nextTick(cb, null, cached);
    if (cached === false) return nextTick(cb, null, undefined);

    var dirs = parents(path.dirname(file));

    (function next () {
        if (dirs.length === 0) {
            self.pkgCache[file] = false;
            return cb(null, undefined);
        }
        var dir = dirs.shift();
        if (dir.split(/[\\\/]/).slice(-1)[0] === 'node_modules') {
            return cb(null, undefined);
        }

        var pkgfile = path.join(dir, 'package.json');

        var cached = self.pkgCache[pkgfile];
        if (cached) return nextTick(cb, null, cached);
        else if (cached === false) return next();

        var pcached = self.pkgFileCachePending[pkgfile];
        if (pcached) return pcached.push(onpkg);
        pcached = self.pkgFileCachePending[pkgfile] = [];

        fs.readFile(pkgfile, function (err, src) {
            if (err) return onpkg();
            try { var pkg = JSON.parse(src) }
            catch (err) {
                return onpkg(new Error([
                    err + ' while parsing json file ' + pkgfile
                ].join('')))
            }
            pkg.__dirname = dir;

            self.pkgCache[pkgfile] = pkg;
            self.pkgCache[file] = pkg;
            onpkg(null, pkg);
        });

        function onpkg (err, pkg) {
            if (self.pkgFileCachePending[pkgfile]) {
                var fns = self.pkgFileCachePending[pkgfile];
                delete self.pkgFileCachePending[pkgfile];
                fns.forEach(function (f) { f(err, pkg) });
            }
            if (err) cb(err)
            else if (pkg) cb(null, pkg)
            else {
                self.pkgCache[pkgfile] = false;
                next();
            }
        }
    })();
};

function getTransforms (pkg, opts) {
    var trx = [];
    if (opts.transformKey) {
        var n = pkg;
        var keys = opts.transformKey;
        for (var i = 0; i < keys.length; i++) {
            if (n && typeof n === 'object') n = n[keys[i]];
            else break;
        }
        if (i === keys.length) {
            trx = [].concat(n).filter(Boolean);
        }
    }
    return trx.concat(opts.globalTransform || []);
}

function nextTick (cb) {
    var args = [].slice.call(arguments, 1);
    process.nextTick(function () { cb.apply(null, args) });
}

function xhas (obj) {
    if (!obj) return false;
    for (var i = 1; i < arguments.length; i++) {
        var key = arguments[i];
        if (!has(obj, key)) return false;
        obj = obj[key];
    }
    return true;
}

function has (obj, key) {
    return obj && Object.prototype.hasOwnProperty.call(obj, key);
}

function wrapTransform (tr) {
    if (typeof tr.read === 'function') return tr;
    var input = through(), output = through();
    input.pipe(tr).pipe(output);
    var wrapper = duplexer(input, output);
    tr.on('error', function (err) { wrapper.emit('error', err) });
    return wrapper;
}
<|endoftext|>


<commit_before>require('child_process').exec(
  'node ' +
  './node_modules/istanbul/lib/cli.js' +
  ' cover ' +
  './node_modules/testing/all.js',
  (e, stdout, stderr) => {
    if (e) {
      console.error(e);
    }
    if (stderr) {
      console.error(stderr);
    }
    if (stdout) {
      console.log(stdout);
    }
  });
<commit_msg>Adding a cwd<commit_after>const path = require('path');

require('child_process').exec(
  'node ' +
  './node_modules/istanbul/lib/cli.js' +
  ' cover ' +
  './node_modules/testing/all.js',
  {
    cwd: path.normalize(__dirname + '/../../'),
    timeout: 900000 // 15 minute timeout
  },
  (e, stdout, stderr) => {
    if (e) {
      console.error(e);
    }
    if (stderr) {
      console.error(stderr);
    }
    if (stdout) {
      console.log(stdout);
    }
  });
<|endoftext|>


<commit_before>'use strict';

module.exports = generator;

var fs = require('fs');
var fse = require('fs-extra');
var node_path = require('path');
var async = require('async');
var ejs = require('ejs');

// Use '{%' which is more friendly to README.md instead of '<%'
var OPEN = '{%';
var CLOSE = '%}';

var clone = require('clone');
var scaffold = require('scaffold-generator');

// @param {Object} options
// - template {string='default'} template name
// - override
function generator(pkg, options, callback) {
  var template = options.template || 'default';
  var license = options.license || 'MIT';

  var cloned_pkg = generator._pkgData(pkg);

  if (!~generator.AVAILABLE_TEMPLATES.indexOf(template)) {
    return callback(new Error('Invalid template'));
  }

  if (!~generator.AVAILABLE_LICENSES.indexOf(license)) {
    return callback(new Error('Invalid license'));
  }

  var s = scaffold({
    data: cloned_pkg,
    override: options.override,
    renderer: {
      render: function (str, data) {
        // `ejs` confuse data with options, but there is no way out.
        // Dame it!
        data.open = OPEN;
        data.close = CLOSE;
        return ejs.render(str, data);
      }
    }
  });
  var template_root = node_path.join(__dirname, 'templates', template);

  function write_if_not_exists (file, data, done) {
    var template_file = node_path.join(template_root, file);
    fs.exists(template_file, function (exists) {
      if (exists) {
        return done(null);
      }
      var to = node_path.join(options.cwd, file);
      s.write(to, data, done);
    });
  }

  async.parallel([
    // copy template
    function (done) {
      s.copy(template_root, options.cwd, done);
    },

    // copy licenses
    function (done) {
      var file = node_path.join(__dirname, 'licenses', 'LICENSE-' + license);
      s.copy(file, options.cwd, done);
    },

    // write cortex.json
    function (done) {
      var content = JSON.stringify(pkg, null, 2);
      write_if_not_exists('cortex.json', content, done);
    },

    // write package.json
    function (done) {
      var p = clone(pkg);
      delete p.devDependencies;
      var content = JSON.stringify(p, null, 2);
      write_if_not_exists('package.json', content, done);
    }

  ], callback);
};

generator._pkgData = function (pkg) {
  pkg = clone(pkg);

  // `cortex-init-prompts` ensures that `name` is
  // - starts with a letter
  // - only contains letters, numbers, `-` and `.`
  var safe_javascript_name = pkg.name.replace(/[-\.]/g, '_');

  pkg.js_name = safe_javascript_name;

  pkg.main_in_test =
    // Relative to test files, pkg.main is outside the current folder
    node_path.join('..', pkg.main)
    // Removes ending `.js`
    // TODO: related to kaelzhang/node-commonjs-walker#10
    .replace(/\.js$/, '');

  return pkg;
};

generator.AVAILABLE_TEMPLATES = [
  'default'
];

generator.AVAILABLE_LICENSES = [
  'MIT',
  'Apache-2.0',
  'GPL-2.0',
  'MPL-2.0'
];

generator.availableLicenses = function() {
  return [].concat(generator.AVAILABLE_LICENSES);
};

generator.availableTemplates = function () {
  return [].concat(generator.AVAILABLE_TEMPLATES);
};
<commit_msg>adds a new filter: json to the renderer: #23<commit_after>'use strict';

module.exports = generator;

var fs = require('fs');
var fse = require('fs-extra');
var node_path = require('path');
var async = require('async');
var ejs = require('ejs');
var stringify = require('json-stringify');

ejs.filters.json = function (obj, offset) {
  return stringify(obj || {}, {
    offset: offset
  });
};

// Use '{%' which is more friendly to README.md instead of '<%'
var OPEN = '{%';
var CLOSE = '%}';

var clone = require('clone');
var scaffold = require('scaffold-generator');

// @param {Object} options
// - template {string='default'} template name
// - override
function generator(pkg, options, callback) {
  var template = options.template || 'default';
  var license = options.license || 'MIT';

  var cloned_pkg = generator._pkgData(pkg);

  if (!~generator.AVAILABLE_TEMPLATES.indexOf(template)) {
    return callback(new Error('Invalid template'));
  }

  if (!~generator.AVAILABLE_LICENSES.indexOf(license)) {
    return callback(new Error('Invalid license'));
  }

  var s = scaffold({
    data: cloned_pkg,
    override: options.override,
    renderer: {
      render: function (str, data) {
        // `ejs` confuse data with options, but there is no way out.
        // Dame it!
        data.open = OPEN;
        data.close = CLOSE;
        return ejs.render(str, data);
      }
    }
  });
  var template_root = node_path.join(__dirname, 'templates', template);

  function write_if_not_exists (file, data, done) {
    var template_file = node_path.join(template_root, file);
    fs.exists(template_file, function (exists) {
      if (exists) {
        return done(null);
      }
      var to = node_path.join(options.cwd, file);
      s.write(to, data, done);
    });
  }

  async.parallel([
    // copy template
    function (done) {
      s.copy(template_root, options.cwd, done);
    },

    // copy licenses
    function (done) {
      var file = node_path.join(__dirname, 'licenses', 'LICENSE-' + license);
      s.copy(file, options.cwd, done);
    },

    // write cortex.json
    function (done) {
      var content = JSON.stringify(pkg, null, 2);
      write_if_not_exists('cortex.json', content, done);
    },

    // write package.json
    function (done) {
      var p = clone(pkg);
      delete p.devDependencies;
      var content = JSON.stringify(p, null, 2);
      write_if_not_exists('package.json', content, done);
    }

  ], callback);
};

generator._pkgData = function (pkg) {
  pkg = clone(pkg);

  // `cortex-init-prompts` ensures that `name` is
  // - starts with a letter
  // - only contains letters, numbers, `-` and `.`
  var safe_javascript_name = pkg.name.replace(/[-\.]/g, '_');

  pkg.js_name = safe_javascript_name;

  pkg.main_in_test =
    // Relative to test files, pkg.main is outside the current folder
    node_path.join('..', pkg.main)
    // Removes ending `.js`
    // TODO: related to kaelzhang/node-commonjs-walker#10
    .replace(/\.js$/, '');

  return pkg;
};

generator.AVAILABLE_TEMPLATES = [
  'default'
];

generator.AVAILABLE_LICENSES = [
  'MIT',
  'Apache-2.0',
  'GPL-2.0',
  'MPL-2.0'
];

generator.availableLicenses = function() {
  return [].concat(generator.AVAILABLE_LICENSES);
};

generator.availableTemplates = function () {
  return [].concat(generator.AVAILABLE_TEMPLATES);
};
<|endoftext|>