<commit_before>//- JavaScript source code

//- Q.js ~~
//  This mini-framework for "Quanah" requires only 'JSON' and 'curl' objects.
//                                                          ~~ SRW, 21 Jul 2010

if (!this.Q) {                          //- Check for the Q object's existence
    var Q = {};
}

(function () {                          //- Build Q inside an anonymous closure

//- PRIVATE MEMBERS

    var root = location.protocol + '//' + location.host + '/',
        db = root + 'app/',

        fresh_id = (function () {       //- Memoized (poorly) but not AJAX'ed
            var ideal = 100,
                source = root + '_uuids?count=' + ideal,
                the_uuids = [],
                refill_uuids = function () {
                    if (the_uuids.length < ideal / 2) {
                        var msg = curl.GET(source),     //- AJAX will go here
                            latest = JSON.parse(msg);
                        the_uuids = the_uuids.concat(latest.uuids);
                    }
                };
            refill_uuids();
            return function (n) {
                n = n || 1;
                var temp = the_uuids.splice(0,n);
                refill_uuids();
                return (n === 1) ? temp[0] : temp;
            };
        }()),

        author = (function () {
            var source = root + '_session',
                msg = JSON.parse(curl.GET(source));
            return msg.userCtx.name;
        }()),

        augment = function (branch, definition) {
            if (typeof Q[branch] !== 'function') {
                Q[branch] = definition;
            }
        },

        results = {
            "stdout":   [],
            "stderr":   []
        },

    //- I may replace this next bit with a "validate_doc_update.js" file ...
        validate = function (obj) {     //- fills in an object's missing fields
            obj["_id"] = obj["_id"] || fresh_id();
            obj.name = author;
            return obj;
        };

//- PUBLIC MEMBERS

    augment("print", function (msg) {   //- an all-purpose output function

        results.stdout.push(msg);

    });

    augment("up", function (obj) {      //- client --> cloud transfer

        validate(obj);

        var target = db + obj['_id'],
            source = JSON.stringify(obj),
            msg = curl.PUT(target, source);

        return JSON.parse(msg);

    });

    augment("down", function (doc_id) { //- cloud --> client transfer

        var source = db + doc_id,
            msg = curl.GET(source);

        return JSON.parse(msg);

    });

    augment("run", function (code) {    //- CLEARS RESULTS, then runs inline JS

        results.stdout.length = 0;      //- Sterilize the environment as much
        results.stderr.length = 0;      //  as possible before proceeding.

        try {                           //- Now, use a 'try/catch' statement
            eval(code);                 //  to evaluate the user's code and
        } catch (error) {               //  catch any exceptions that may have
            results.stderr.push(error); //  been thrown in the process.
        }
        return results;

    });

    augment("Doc", function () {        //- Constructor for new CouchDB docs

        var template = validate({}),    //- The '{}' will get validated twice,
            msg = Q.up(template);       //  but it's not a big deal right now.

        if (msg.ok === 'false') {
            throw msg;
        }

        template['_rev'] = msg.rev;
        return template;

    });

    augment("reval", function (func, argarray) {
        argarray = argarray || [];
        var dQ = new Q.Doc(),
            id = dQ._id;
        localStorage[id] = func;        //- stringify the function
        dQ.code = '(' + localStorage[id] + ')' +
            '.apply(this, ' + JSON.stringify(argarray) + ')';
        Q.up(dQ);
        delete localStorage[id];
        console.log('Waiting for response ...');
        while (!dQ.results) {
            dQ = Q.down(id);
        }
        return dQ.results.stdout;
    });

}());

if (this.console) {
    console.log("Welcome to the Quanah Lab :-)");
}

//- vim:set syntax=javascript:
<commit_msg>Quanah is now in a fully working but functionally limited state of operation, because it does not use asynchronous transfer. It does work, however, in its current state. I note this so I know what point to return to if the AJAX does not work out nicely ...<commit_after>//- JavaScript source code

//- Q.js ~~
//  This mini-framework for "Quanah" requires only 'JSON' and 'curl' objects.
//                                                          ~~ SRW, 21 Jul 2010

if (!this.Q) {                          //- Check for the Q object's existence
    var Q = {};
}

(function () {                          //- Build inside an anonymous closure

//- PRIVATE MEMBERS

    var root = location.protocol + '//' + location.host + '/',
        db = root + 'app/',

        fresh_id = (function () {       //- Constructor for memoized function
            var ideal = 100,
                source = root + '_uuids?count=' + ideal,
                the_uuids = [],
                refill_uuids = function () {
                    if (the_uuids.length < ideal / 2) {
                        var msg = curl.GET(source),     //- AJAX will go here
                            latest = JSON.parse(msg);
                        the_uuids = the_uuids.concat(latest.uuids);
                    }
                };
            refill_uuids();
            return function (n) {       //- the "actual" function
                n = n || 1;
                var temp = the_uuids.splice(0,n);
                refill_uuids();
                return (n === 1) ? temp[0] : temp;
            };
        }()),

        author = (function () {
            var source = root + '_session',
                msg = JSON.parse(curl.GET(source));
            return msg.userCtx.name;
        }()),

        augment = function (branch, definition) {
            if (typeof Q[branch] !== 'function') {
                Q[branch] = definition;
            }
        },

        results = {
            "stdout":   [],
            "stderr":   []
        };

//- PUBLIC MEMBERS

    augment("print", function (msg) {   //- an all-purpose output function

        results.stdout.push(msg);

    });

    augment("up", function (obj) {      //- client --> cloud transfer

        var target = db + obj.id,
            source = JSON.stringify(obj),
            msg = curl.PUT(target, source);
            //msg = curl.PUT(target, source),
            //check = JSON.parse(msg);

        //if (check.ok === 'true') {
        //    obj.rev = check.rev;
        //    return obj;
        //} else {
        //    return check.error;
        //}
        return JSON.parse(msg);
    });

    augment("down", function (id) {     //- cloud --> client transfer

        var source = db + id,
            msg = curl.GET(source);

        return JSON.parse(msg);

    });

    augment("run", function (code) {    //- CLEARS RESULTS, then runs inline JS

        results.stdout.length = 0;      //- Sterilize the environment as much
        results.stderr.length = 0;      //  as possible before proceeding.

        try {                           //- Now, use a 'try/catch' statement
            eval(code);                 //  to evaluate the user's code and
        } catch (error) {               //  catch any exceptions that may have
            results.stderr.push(error); //  been thrown in the process.
        }
        return results;

    });

    augment("Doc", function (obj) {     //- Constructor for new CouchDB docs

        obj = obj || {};
        obj.id = obj.id || fresh_id(1);
        obj.name = author;

        var msg = Q.up(obj);

        if (msg.ok === 'false') {
            throw msg;
        }

        obj._rev = msg.rev;
        return obj;

    });

    augment("reval", function (func, argarray) {
        argarray = argarray || [];
        var id = fresh_id(),
            dQ = new Q.Doc({
                "id":  id,
                "code": '(' + func.toString() + ').apply(this, ' +
                            JSON.stringify(argarray) + ')'
            });
        Q.up(dQ);
        console.log('Waiting for response ...');
        while (!dQ.results) {
            dQ = Q.down(id);
        }
        return dQ.results.stdout;
    });

})();

if (this.console) {
    console.log("Welcome to the Quanah Lab :-)");
}

//- vim:set syntax=javascript:
<|endoftext|>


<commit_before>/*

*/
/*
 * @page index steal
 * @tag home
 *
 * ###DIREKTSPEED Server
 *
 * Our steal only has two classes:
 *
 * * server
 * * server
 */
// needs reading of $PWD for accepting .
/*
var nodePath      = require("path")
var program       = require("commander")
var fse           = require("fs-extra")
var downloadRepo  = require("download-github-repo")
var pkg           = require("../../package.json")

var prerender     = require("../")()

var output = function(msg){
  var v = pkg.version
  console.log("------------")
  console.log("DIREKTSPEED Server - Modul Prerender v" + v + " – DIREKTSPEED. 2015–2017")
  if(msg){
    console.log(msg)
    console.log("Press Ctl+C to stop the server")
  }
  console.log("------------")
}

program
  .version(pkg.version)

program
  .command("init [path]")
  .usage("initializes a new DIREKTSPEED Server - PreRender project in the current directory.\n  See available boilerplates at https://github.com/steal-boilerplates")
  .option("-b, --boilerplate <github-username/repo>", "use a github repo as a boilerplate", "steal-boilerplates/default")
  .description("Initialize a new DIREKTSPEED Server project in current directory")
  .action(function(path, program){
    var projectPath     = nodePath.resolve(process.cwd(), path || "")
    var boilerplatePath = nodePath.resolve(__dirname, "..", "lib", "default_boilerplate")
    var repo            = program.boilerplate

    // Assume `harp-boilerplates` github org if boilerplate doesn't contain a slash
    repo.match(/\//) || (repo = "steal-boilerplates/"+repo)

    var done = function() {
      console.log("Initialized project at", projectPath)
    }

    fse.mkdirp(projectPath, function(err){
      if(err) return err

      fse.readdir(projectPath, function(err, contents){

        if(err) return err

        if(contents.length !== 0){
          console.log("Sorry,", projectPath, "must be empty.")
          return
        }

        console.log("Downloading boilerplate: https://github.com/"+repo)

        //fse.writeFileSync("/Desktop/harp-test-output.txt", repo + "::" + projectPath)

        downloadRepo(repo, projectPath, function(err) {
          if (!err) return done()

          if (require('util').isError(err) && err['code'] === 'ENOTFOUND') {
            console.error("You're not connected to the Internet, so we'll use the default boilerplate.")
            fse.copy(boilerplatePath, projectPath, function(err){
              if (err) return err
              return done()
            })
          } else {
            return console.error("Template not found:", "https://github.com/"+repo)
          }

        })

      })
    })
  })

program
  .command("server [path]")
  .option("-i, --ip <ip>", "Specify IP to bind to")
  .option("-p, --port <port>", "Specify a port to listen on")
  .option("-c, --config <path>", "Specify a port to listen on")
  .usage("starts a DIREKTSPEED Server in current directory, or in the specified directory.")
  .description("Start a DIREKTSPEED Server in current directory")
  .action(function(path, program){
    var projectPath = nodePath.resolve(process.cwd(), path || "")
    var ip          = program.ip || '0.0.0.0'
    var port        = program.port || 9000
    var options = {
      ip: ip,
      port: port
    }

    prerender.server(projectPath, options, function(){
      var address = ''
      if(ip == '0.0.0.0' || ip == '127.0.0.1') {
        address = 'localhost'
      } else {
        address = ip
      }
      var hostUrl = "http://" + address + ":" + port + "/"
      output("Your server is listening at " + hostUrl)
    })
  })

program
  .command("multihost [path]")
  .option("-i, --ip <ip>", "Specify IP to bind to")
  .option("-p, --port <port>", "Specify a port to listen on")
  .option("-c, --config <path>", "Specify a port to listen on")
  .usage("starts a DIREKTSPEED Server to host a directory of DIREKTSPEED Server projects.")
  .description("Start a DIREKTSPEED Server to host a directory of DIREKTSPEED Server projects")
  .action(function(path, program){
    var projectPath = nodePath.resolve(process.cwd(), path || "")
    var port        = program.port || 9000
    var options = {
      port: port
    }

    prerender.multihost(projectPath, options, function(){
      if(port == "80"){
        var loc = "http://localhost"
      }else{
        var loc = "http://localhost:" + port
      }
      output("Your server is hosting multiple projects at " + loc)
    })
  })

program
  .command("compile [projectPath] [outputPath]")
  .option("-o, --output <path>", "Specify the output directory for compiled assets (relative to project path)")
  .usage("compile your project files to static assets (HTML, JS and CSS). \n  Use this command if you want to host your application without using the DIREKTSPEED Server web server.")
  .description("Compile project to static assets (HTML, JS and CSS)")
  .action(function(projectPath, outputPath, program){

    if(!program){
      program    = outputPath
      outputPath = null
    }

    projectPath = nodePath.resolve(process.cwd(), projectPath || "")

    /**
     * We deal with output path 3 different ways
     *
     *  1. second argument (relative to directory called in)
     *  2. `--output` argument (relative to project root)
     *  3. implicitly projectPath + "/www"
     *
     *

    if(outputPath){
      outputPath = nodePath.resolve(process.cwd(), (outputPath || program.output || ''))
    }else{
      outputPath = nodePath.resolve(projectPath, (program.output || "www"))
    }

    prerender.compile(projectPath, outputPath, function(errors, output){
      if(errors) {
        console.log(JSON.stringify(errors, null, 2))
        process.exit(1)
      }
    })
  })

program.on("--help", function(){
  console.log("  Use 'steal <command> --help' to get more information or visit http://server.dspeed.eu/ to learn more.")
  console.log('')
})

module.exports = program
*/
var fs = require('fs');
var path = require("path");
var program = require('commander');
var pkg = require('../../package.json');

program.version(pkg.version)
  .usage('[path] [options]')
  .description(pkg.description)
  .option('-d, --develop', 'Enable development mode (live-reload)')
  .option('-p, --port <port>', 'The server port')
  .option('-r, --proxy <url>', 'A URL to an API that should be proxied')
  .option('-t, --proxy-to <path>', 'The path to proxy to (default: /api)')
  .option('--proxy-no-cert-check', 'Turn off SSL certificate verification')
  .option('-l, --no-live-reload', 'Turn off live-reload')
  .option('--timeout <ms>', 'The timeout in milliseconds', parseInt)
  .option('--debug', 'Turn on debugging in cases of timeouts')
  .option('-s, --static', 'Only serve static files, no server-side rendering')
  .option('-h, --html5shiv', 'Include html5shiv in the HTML')
  .option('--live-reload-port <port>', 'Port to use for live-reload')
  .option('--auth-cookie <name>', 'Cookie name for supporting SSR with JWT token auth.')
  .option('--auth-domains <name>', 'Domain names where the JWT tokens will be sent. Required if auth-cookie is enabled.')
  .option('--steal-tools-path <path>', 'Location of your steal-tools')
  .option('--error-page <filename>', 'Send a given file on 404 errors to enable HTML5 pushstate (only with --static)')
  .option('--key <path>', 'Private key, for https')
  .option('--cert <path>', 'Fullchain file or cert file, for https')
  .option('--strategy <name>', 'The rendering strategy (default: safe)');

exports.program = program;
const servers = require('../servers')
exports.servers = servers
exports.run = function(app){
	var makeServer = require("../index");
	var exec = require("child_process").exec;

  var port = program.port || process.env.PORT || 3030;

  let server = servers.filter(server=>server.address().port === port)
  if (server.length === 1) {
    return server[0]
  }

	function startServer(app){
		app = app || makeServer(options)
		let server =servers.filter(server=>server.address().port === port)
		 if (server.length === 1) {
			return server[0]
		 }
		// If using TLS, set up an HTTP2 server with automatic
		// http->https forwarding.
		if(options.key && options.cert) {
			var net = require("net");
			var spdy = require("donejs-spdy");
			port = Number(port);

			var httpPort = port + 1;
			var httpsPort = httpPort + 1;

			let httpsServerIndex = servers.push(spdy.createServer({
				key: fs.readFileSync(options.key),
				cert: fs.readFileSync(options.cert),
				spdy: {
					protocols: ['h2', 'http/1.1']
				}
			}, app));
			servers[httpsServerIndex].listen(httpsPort);
			let httpServerIndex = servers.push(require("http").createServer(function(req, res){
				var host = req.headers.host;
				res.writeHead(301, { "Location": "https://" + host + req.url });
				res.end();
			}))

			servers[httpServerIndex].listen(httpPort)
			servers[httpServerIndex].on('error', function(e) {
					if(e.code === 'EADDRINUSE') {
					console.error('ERROR: Can not start done-serve on port ' + port +
						'.\nAnother application is already using it.');
					} else {
					 console.error(e);
					console.error(e.stack);
					}
				});

	servers[httpServerIndex].on('listening', function() {
		var address = servers[0].address();
		var url = 'http://' + (address.address === '::' ?
				'localhost' : address.address) + ':' + port;

		console.log('done-serve starting on ' + url);
	});

			// This is a TCP server that forwards to the correct port for
			// http or https
			net.createServer(function(conn){
				conn.once("data", function (buf) {
			        // A TLS handshake record starts with byte 22.
			        var address = (buf[0] === 22) ? httpsPort : httpPort;
			        var proxy = net.createConnection(address, function (){
			            proxy.write(buf);
			            conn.pipe(proxy).pipe(conn);
			        });
			    });
			}).listen(port);

			servers.push(server);
		} else {
			servers.push(app.listen(port));
		}
		var server = http.createServer(app).listen();
		app.set('port', server.address().port);

		return servers;
	};

	var options = {
	  path: program.args[0] ? path.join(process.cwd(), program.args[0]) : process.cwd(),
	  liveReload: program.liveReload,
	  static: program.static,
	  debug: program.debug,
	  timeout: program.timeout,
	  errorPage: program.errorPage,
	  key: program.key,
	  cert: program.cert,
	  strategy: program.strategy
	};

	if(program.proxy) {
	  options.proxy = program.proxy;
	  options.proxyTo = program.proxyTo;
	  options.proxyCertCheck = program.proxyCertCheck;
	}

	if (program.authCookie || program.authDomains) {
		options.auth = {
			cookie: program.authCookie,
			domains: program.authDomains && program.authDomains.split(',')
		};
	}

	// Spawn a child process in development mode
	if(program.develop) {
		var stealToolsPath = program.stealToolsPath ||
			path.join("node_modules", ".bin", "steal-tools");
		if(!fs.existsSync(stealToolsPath)) {
			console.error('live-reload not available: ' +
				'No local steal-tools binary found. ' +
				'Run `npm install steal-tools --save-dev`.');
		} else {
			var cmd = stealToolsPath + ' live-reload';
			if(program.liveReloadPort) {
				cmd += ' --live-reload-port ' + program.liveReloadPort;
			}

			var child = exec(cmd, {
				cwd: process.cwd()
			});

			process.env.NODE_ENV = "development";

			child.stdout.pipe(process.stdout);
			child.stderr.pipe(process.stderr);

			var killOnExit = require('infanticide');
			killOnExit(child);
		}
	}

  return startServer(makeServer(options));
};
<commit_msg>Update index.js<commit_after>/*

*/
/*
 * @page index steal
 * @tag home
 *
 * ###DIREKTSPEED Server
 *
 * Our steal only has two classes:
 *
 * * server
 * * server
 */
// needs reading of $PWD for accepting .
/*
var nodePath      = require("path")
var program       = require("commander")
var fse           = require("fs-extra")
var downloadRepo  = require("download-github-repo")
var pkg           = require("../../package.json")

var prerender     = require("../")()

var output = function(msg){
  var v = pkg.version
  console.log("------------")
  console.log("DIREKTSPEED Server - Modul Prerender v" + v + " – DIREKTSPEED. 2015–2017")
  if(msg){
    console.log(msg)
    console.log("Press Ctl+C to stop the server")
  }
  console.log("------------")
}

program
  .version(pkg.version)

program
  .command("init [path]")
  .usage("initializes a new DIREKTSPEED Server - PreRender project in the current directory.\n  See available boilerplates at https://github.com/steal-boilerplates")
  .option("-b, --boilerplate <github-username/repo>", "use a github repo as a boilerplate", "steal-boilerplates/default")
  .description("Initialize a new DIREKTSPEED Server project in current directory")
  .action(function(path, program){
    var projectPath     = nodePath.resolve(process.cwd(), path || "")
    var boilerplatePath = nodePath.resolve(__dirname, "..", "lib", "default_boilerplate")
    var repo            = program.boilerplate

    // Assume `harp-boilerplates` github org if boilerplate doesn't contain a slash
    repo.match(/\//) || (repo = "steal-boilerplates/"+repo)

    var done = function() {
      console.log("Initialized project at", projectPath)
    }

    fse.mkdirp(projectPath, function(err){
      if(err) return err

      fse.readdir(projectPath, function(err, contents){

        if(err) return err

        if(contents.length !== 0){
          console.log("Sorry,", projectPath, "must be empty.")
          return
        }

        console.log("Downloading boilerplate: https://github.com/"+repo)

        //fse.writeFileSync("/Desktop/harp-test-output.txt", repo + "::" + projectPath)

        downloadRepo(repo, projectPath, function(err) {
          if (!err) return done()

          if (require('util').isError(err) && err['code'] === 'ENOTFOUND') {
            console.error("You're not connected to the Internet, so we'll use the default boilerplate.")
            fse.copy(boilerplatePath, projectPath, function(err){
              if (err) return err
              return done()
            })
          } else {
            return console.error("Template not found:", "https://github.com/"+repo)
          }

        })

      })
    })
  })

program
  .command("server [path]")
  .option("-i, --ip <ip>", "Specify IP to bind to")
  .option("-p, --port <port>", "Specify a port to listen on")
  .option("-c, --config <path>", "Specify a port to listen on")
  .usage("starts a DIREKTSPEED Server in current directory, or in the specified directory.")
  .description("Start a DIREKTSPEED Server in current directory")
  .action(function(path, program){
    var projectPath = nodePath.resolve(process.cwd(), path || "")
    var ip          = program.ip || '0.0.0.0'
    var port        = program.port || 9000
    var options = {
      ip: ip,
      port: port
    }

    prerender.server(projectPath, options, function(){
      var address = ''
      if(ip == '0.0.0.0' || ip == '127.0.0.1') {
        address = 'localhost'
      } else {
        address = ip
      }
      var hostUrl = "http://" + address + ":" + port + "/"
      output("Your server is listening at " + hostUrl)
    })
  })

program
  .command("multihost [path]")
  .option("-i, --ip <ip>", "Specify IP to bind to")
  .option("-p, --port <port>", "Specify a port to listen on")
  .option("-c, --config <path>", "Specify a port to listen on")
  .usage("starts a DIREKTSPEED Server to host a directory of DIREKTSPEED Server projects.")
  .description("Start a DIREKTSPEED Server to host a directory of DIREKTSPEED Server projects")
  .action(function(path, program){
    var projectPath = nodePath.resolve(process.cwd(), path || "")
    var port        = program.port || 9000
    var options = {
      port: port
    }

    prerender.multihost(projectPath, options, function(){
      if(port == "80"){
        var loc = "http://localhost"
      }else{
        var loc = "http://localhost:" + port
      }
      output("Your server is hosting multiple projects at " + loc)
    })
  })

program
  .command("compile [projectPath] [outputPath]")
  .option("-o, --output <path>", "Specify the output directory for compiled assets (relative to project path)")
  .usage("compile your project files to static assets (HTML, JS and CSS). \n  Use this command if you want to host your application without using the DIREKTSPEED Server web server.")
  .description("Compile project to static assets (HTML, JS and CSS)")
  .action(function(projectPath, outputPath, program){

    if(!program){
      program    = outputPath
      outputPath = null
    }

    projectPath = nodePath.resolve(process.cwd(), projectPath || "")

    /**
     * We deal with output path 3 different ways
     *
     *  1. second argument (relative to directory called in)
     *  2. `--output` argument (relative to project root)
     *  3. implicitly projectPath + "/www"
     *
     *

    if(outputPath){
      outputPath = nodePath.resolve(process.cwd(), (outputPath || program.output || ''))
    }else{
      outputPath = nodePath.resolve(projectPath, (program.output || "www"))
    }

    prerender.compile(projectPath, outputPath, function(errors, output){
      if(errors) {
        console.log(JSON.stringify(errors, null, 2))
        process.exit(1)
      }
    })
  })

program.on("--help", function(){
  console.log("  Use 'steal <command> --help' to get more information or visit http://server.dspeed.eu/ to learn more.")
  console.log('')
})

module.exports = program
*/
var fs = require('fs');
var path = require("path");
var program = require('commander');
var pkg = require('../../package.json');

program.version(pkg.version)
  .usage('[path] [options]')
  .description(pkg.description)
  .option('-d, --develop', 'Enable development mode (live-reload)')
  .option('-p, --port <port>', 'The server port')
  .option('-r, --proxy <url>', 'A URL to an API that should be proxied')
  .option('-t, --proxy-to <path>', 'The path to proxy to (default: /api)')
  .option('--proxy-no-cert-check', 'Turn off SSL certificate verification')
  .option('-l, --no-live-reload', 'Turn off live-reload')
  .option('--timeout <ms>', 'The timeout in milliseconds', parseInt)
  .option('--debug', 'Turn on debugging in cases of timeouts')
  .option('-s, --static', 'Only serve static files, no server-side rendering')
  .option('-h, --html5shiv', 'Include html5shiv in the HTML')
  .option('--live-reload-port <port>', 'Port to use for live-reload')
  .option('--auth-cookie <name>', 'Cookie name for supporting SSR with JWT token auth.')
  .option('--auth-domains <name>', 'Domain names where the JWT tokens will be sent. Required if auth-cookie is enabled.')
  .option('--steal-tools-path <path>', 'Location of your steal-tools')
  .option('--error-page <filename>', 'Send a given file on 404 errors to enable HTML5 pushstate (only with --static)')
  .option('--key <path>', 'Private key, for https')
  .option('--cert <path>', 'Fullchain file or cert file, for https')
  .option('--strategy <name>', 'The rendering strategy (default: safe)');

exports.program = program;
const servers = require('../servers')
exports.servers = servers
exports.run = function(app){
	var makeServer = require("../index");
	var exec = require("child_process").exec;

  var port = program.port || process.env.PORT || 3030;

  let server = servers.filter(server=>server.address().port === port)
  if (server.length === 1) {
    return server[0]
  }

	function startServer(app){
		app = app || makeServer(options)
		let server =servers.filter(server=>server.address().port === port)
		 if (server.length === 1) {
			return server[0]
		 }
		// If using TLS, set up an HTTP2 server with automatic
		// http->https forwarding.
		if(options.key && options.cert) {
			var net = require("net");
			var spdy = require("donejs-spdy");
			port = Number(port);

			var httpPort = port + 1;
			var httpsPort = httpPort + 1;

			let httpsServerIndex = servers.push(spdy.createServer({
				key: fs.readFileSync(options.key),
				cert: fs.readFileSync(options.cert),
				spdy: {
					protocols: ['h2', 'http/1.1']
				}
			}, app));
			servers[httpsServerIndex].listen(httpsPort);
			let httpServerIndex = servers.push(require("http").createServer(function(req, res){
				var host = req.headers.host;
				res.writeHead(301, { "Location": "https://" + host + req.url });
				res.end();
			}))

			servers[httpServerIndex].listen(httpPort)
			servers[httpServerIndex].on('error', function(e) {
					if(e.code === 'EADDRINUSE') {
					console.error('ERROR: Can not start done-serve on port ' + port +
						'.\nAnother application is already using it.');
					} else {
					 console.error(e);
					console.error(e.stack);
					}
				});

	servers[httpServerIndex].on('listening', function() {
		var address = servers[0].address();
		var url = 'http://' + (address.address === '::' ?
				'localhost' : address.address) + ':' + port;

		console.log('done-serve starting on ' + url);
	});

			// This is a TCP server that forwards to the correct port for
			// http or https
		let tcpServerIndex = servers.push(net.createServer(function(conn){
				conn.once("data", function (buf) {
			        // A TLS handshake record starts with byte 22.
			        var address = (buf[0] === 22) ? httpsPort : httpPort;
			        var proxy = net.createConnection(address, function (){
			            proxy.write(buf);
			            conn.pipe(proxy).pipe(conn);
			        });
			    });
			}));
		servers[tcpServerIndex].listen(port);
		} else {
		  servers.push(app.listen(port));
		}
		//TODO: Random Port
		//var server = http.createServer(app).listen();
		//app.set('port', server.address().port);

		return servers;
	};

	var options = {
	  path: program.args[0] ? path.join(process.cwd(), program.args[0]) : process.cwd(),
	  liveReload: program.liveReload,
	  static: program.static,
	  debug: program.debug,
	  timeout: program.timeout,
	  errorPage: program.errorPage,
	  key: program.key,
	  cert: program.cert,
	  strategy: program.strategy
	};

	if(program.proxy) {
	  options.proxy = program.proxy;
	  options.proxyTo = program.proxyTo;
	  options.proxyCertCheck = program.proxyCertCheck;
	}

	if (program.authCookie || program.authDomains) {
		options.auth = {
			cookie: program.authCookie,
			domains: program.authDomains && program.authDomains.split(',')
		};
	}

	// Spawn a child process in development mode
	if(program.develop) {
		var stealToolsPath = program.stealToolsPath ||
			path.join("node_modules", ".bin", "steal-tools");
		if(!fs.existsSync(stealToolsPath)) {
			console.error('live-reload not available: ' +
				'No local steal-tools binary found. ' +
				'Run `npm install steal-tools --save-dev`.');
		} else {
			var cmd = stealToolsPath + ' live-reload';
			if(program.liveReloadPort) {
				cmd += ' --live-reload-port ' + program.liveReloadPort;
			}

			var child = exec(cmd, {
				cwd: process.cwd()
			});

			process.env.NODE_ENV = "development";

			child.stdout.pipe(process.stdout);
			child.stderr.pipe(process.stderr);

			var killOnExit = require('infanticide');
			killOnExit(child);
		}
	}

  return startServer(makeServer(options));
};
<|endoftext|>


<commit_before>#!/usr/bin/env node
var ejs = require('ejs'),
    fs = require('fs'),
    path = require('path'),
    hardhat = require('hardhat'),
    _ = require('underscore');

function dir_has_atlas_project(dir){
  var requiredItems = ["packages", "package.json", "config"]; //the proyect should have these items
  return requiredItems.every(function (item) { return fs.existsSync(path.join(dir, item));});
}

module.exports = {

  generate: function (project_dir, default_package, item_type, item_name, callback){

    var template_folder = path.join(__dirname, "../..", "samples"); //TODO: extract to parameter

    //Assert valid parameter usage
    var itemsToGenerate = ["widget", "dashboard", "job"];
    if (itemsToGenerate.indexOf(item_type) == -1) {
      return callback("Invalid generator \"%s\"\nUse one of %s", item_type, itemsToGenerate.join(", "));
    }

    //Assert a project already exists here
    if (!dir_has_atlas_project(project_dir)){
      return callback("It seems that no project exists here yet. Please navigate to your project's root directory, or generate one first.");
    }

    //Assert name given
    if (!item_name) {
      return callback("ERROR: No " + item_type + " name provided. Please try again with a name after the generate parameter");
    }

    //Assert no such item exists there yet
    var newItemBaseLocation = path.join(project_dir, "packages", default_package);
    var newItemLocation = path.join(newItemBaseLocation, item_type + "s", item_name);
    if (fs.existsSync(newItemLocation)) {
      return callback ("ERROR: This " + item_type + " already seems to exist at " + path.join(process.cwd()) + ". Path:" + newItemLocation);
    }

    //All is well. Generate the item based on the skeletons in the samples directory
    console.log("Creating new %s at %s...", item_type, newItemLocation);

    if (!fs.existsSync(newItemBaseLocation)) { //this could exist already
      fs.mkdirSync(newItemBaseLocation);
    }
    if (!fs.existsSync(newItemLocation)) {
      fs.mkdirSync(newItemLocation);
    }

    fs.readdir(path.join(template_folder, item_type), function(err, files) {
      if (err || !files) {
        return callback(err || "no files found");
      }
      files.forEach(function (file) {
        var targetFileName = path.join(newItemLocation, item_name + path.extname(file));
        var ejsOptions = {name: item_name};
        var item_path = path.join(template_folder, item_type, file);
        fs.writeFileSync(targetFileName,
            ejs.render(fs.readFileSync(item_path).toString(), ejsOptions));
      });
      callback(null, {path: newItemLocation});
      console.log("New %s created successfully", item_type);
    });
  },

  new_project: function(srcDir, destDir, callback) {
    //Generate a new project
    console.log("Generating a new AtlasBoard project at %s...", destDir);

    if (fs.existsSync(destDir)) {
      return callback("There is already a directory here called " + destDir + ". Please choose a new name.");
    }

    console.log("Directory %s/ does not exist. Creating it now.", destDir);
    fs.mkdirSync(destDir);

    console.log("Porting sample project across...");
    hardhat.scaffold(srcDir, destDir, {}, function(err) {
      if (err) {
        return callback ("Error when creating new project. Aborting. ERROR: " + err);
      } else {
        //todo: install dependencies after project copy
        callback(null);
      }
    });
  },

  start : function(){
    //Assert a project already exists here
    if (!dir_has_atlas_project(process.cwd())){
      console.log("I couldn't find a valid AtlasBoard dashboard. Try generating one with `atlasboard new DASHBOARDNAME`.");
      return false;
    }

    //Start AtlasBoard
    console.log("Starting AtlasBoard server...");
    require('../atlasboard')();
    return true;
  }
};
<commit_msg>Fix string concatenation<commit_after>#!/usr/bin/env node
var ejs = require('ejs'),
    fs = require('fs'),
    path = require('path'),
    hardhat = require('hardhat'),
    _ = require('underscore');

function dir_has_atlas_project(dir){
  var requiredItems = ["packages", "package.json", "config"]; //the proyect should have these items
  return requiredItems.every(function (item) { return fs.existsSync(path.join(dir, item));});
}

module.exports = {

  generate: function (project_dir, default_package, item_type, item_name, callback){

    var template_folder = path.join(__dirname, "../..", "samples"); //TODO: extract to parameter

    //Assert valid parameter usage
    var itemsToGenerate = ["widget", "dashboard", "job"];
    if (itemsToGenerate.indexOf(item_type) == -1) {
      return callback("Invalid generator " + item_type + "\nUse one of: " + itemsToGenerate.join(", "));
    }

    //Assert a project already exists here
    if (!dir_has_atlas_project(project_dir)){
      return callback("It seems that no project exists here yet. Please navigate to your project's root directory, or generate one first.");
    }

    //Assert name given
    if (!item_name) {
      return callback("ERROR: No " + item_type + " name provided. Please try again with a name after the generate parameter");
    }

    //Assert no such item exists there yet
    var newItemBaseLocation = path.join(project_dir, "packages", default_package);
    var newItemLocation = path.join(newItemBaseLocation, item_type + "s", item_name);
    if (fs.existsSync(newItemLocation)) {
      return callback ("ERROR: This " + item_type + " already seems to exist at " + path.join(process.cwd()) + ". Path:" + newItemLocation);
    }

    //All is well. Generate the item based on the skeletons in the samples directory
    console.log("Creating new %s at %s...", item_type, newItemLocation);

    if (!fs.existsSync(newItemBaseLocation)) { //this could exist already
      fs.mkdirSync(newItemBaseLocation);
    }
    if (!fs.existsSync(newItemLocation)) {
      fs.mkdirSync(newItemLocation);
    }

    fs.readdir(path.join(template_folder, item_type), function(err, files) {
      if (err || !files) {
        return callback(err || "no files found");
      }
      files.forEach(function (file) {
        var targetFileName = path.join(newItemLocation, item_name + path.extname(file));
        var ejsOptions = {name: item_name};
        var item_path = path.join(template_folder, item_type, file);
        fs.writeFileSync(targetFileName,
            ejs.render(fs.readFileSync(item_path).toString(), ejsOptions));
      });
      callback(null, {path: newItemLocation});
      console.log("New %s created successfully", item_type);
    });
  },

  new_project: function(srcDir, destDir, callback) {
    //Generate a new project
    console.log("Generating a new AtlasBoard project at %s...", destDir);

    if (fs.existsSync(destDir)) {
      return callback("There is already a directory here called " + destDir + ". Please choose a new name.");
    }

    console.log("Directory %s/ does not exist. Creating it now.", destDir);
    fs.mkdirSync(destDir);

    console.log("Porting sample project across...");
    hardhat.scaffold(srcDir, destDir, {}, function(err) {
      if (err) {
        return callback ("Error when creating new project. Aborting. ERROR: " + err);
      } else {
        //todo: install dependencies after project copy
        callback(null);
      }
    });
  },

  start : function(){
    //Assert a project already exists here
    if (!dir_has_atlas_project(process.cwd())){
      console.log("I couldn't find a valid AtlasBoard dashboard. Try generating one with `atlasboard new DASHBOARDNAME`.");
      return false;
    }

    //Start AtlasBoard
    console.log("Starting AtlasBoard server...");
    require('../atlasboard')();
    return true;
  }
};
<|endoftext|>


<commit_before>'use strict';

var format = require('util').format;

function scalarReverse(s) {
  return s.split('').reverse().join('');
}

function nameHash(name) {
	// Generate a vector hash for the name string, weighting early over
	// later characters. We want to pick the same colors for function
	// names across different flame graphs.
	var vector = 0
	  , weight = 1
	  , max = 1
	  , mod = 10
	  , ord

	// if module name present, trunc to 1st char
  name = name.replace(/.(.*?)`/, '');
  var splits = name.split('');
  for (var i = 0; i < splits.length; i++) {
    ord = splits[i].charCodeAt(0) % mod;
    vector += (ord / (mod++ - 1)) * weight;
    max += 1 * weight;
    weight *= 0.7;
    if (mod > 12) break;
  }

  return (1 - vector / max);
}

function color(type, hash, name) {
  var v1, v2, v3, r, g, b;
  if (!type) return 'rgb(0, 0, 0)';

  if (hash) {
    v1 = nameHash(name);
    v2 = v3 = nameHash(scalarReverse(name));
  } else {
		v1 = Math.random() + 1;
		v2 = Math.random() + 1;
		v3 = Math.random() + 1;
  }

  switch(type) {
    case 'hot':
      r = 205 + Math.round(50 * v3);
      g = 0 + Math.round(230 * v1);
      b = 0 + Math.round(55 * v2);
      return format('rgb(%s, %s, %s)',r, g, b);
    case 'mem':
      r = 0;
      g = 190 + Math.round(50 * v2);
      b = 0 + Math.round(210 * v1);
      return format('rgb(%s, %s, %s)',r, g, b);
    case 'io':
      r = 80 + Math.round(60 * v1);
      g = r;
      b = 190 + Math.round(55 * v2);
      return format('rgb(%s, %s, %s)',r, g, b);
    default:
      throw new Error('Unknown type ' + type);
  }
}

module.exports =

/**
 * Maps a function name to a color, while trying to create same colors for similar functions.
 *
 * @name colorMap
 * @function
 * @private
 * @param {Object.<string, string>} paletteMap current map of colors `func: color`
 * @param {string} colorTheme theme of colors to be used `hot | mem | io`
 * @param {boolean} hash if true colors will be created from name hash, otherwise they are random
 * @param {string} func the function name for which to select a color
 * @return {string} containing an rgb color, i.e. `'rgb(1, 2, 3)'`
 */
function colorMap(paletteMap, colorTheme, hash, func) {
  if (paletteMap[func]) return paletteMap[func];
  paletteMap[func] = color(colorTheme, hash, func);
  return paletteMap[func];
}
<commit_msg>minor fix<commit_after>'use strict';

var format = require('util').format;

function scalarReverse(s) {
  return s.split('').reverse().join('');
}

function nameHash(name) {
	// Generate a vector hash for the name string, weighting early over
	// later characters. We want to pick the same colors for function
	// names across different flame graphs.
	var vector = 0
	  , weight = 1
	  , max = 1
	  , mod = 10
	  , ord

	// if module name present, trunc to 1st char
  name = name.replace(/.(.*?)`/, '');
  var splits = name.split('');
  for (var i = 0; i < splits.length; i++) {
    ord = splits[i].charCodeAt(0) % mod;
    vector += (ord / (mod++ - 1)) * weight;
    max += weight;
    weight *= 0.70;
    if (mod > 12) break;
  }

  return (1 - vector / max);
}

function color(type, hash, name) {
  var v1, v2, v3, r, g, b;
  if (!type) return 'rgb(0, 0, 0)';

  if (hash) {
    v1 = nameHash(name);
    v2 = v3 = nameHash(scalarReverse(name));
  } else {
		v1 = Math.random() + 1;
		v2 = Math.random() + 1;
		v3 = Math.random() + 1;
  }

  switch(type) {
    case 'hot':
      r = 205 + Math.round(50 * v3);
      g = 0 + Math.round(230 * v1);
      b = 0 + Math.round(55 * v2);
      return format('rgb(%s, %s, %s)',r, g, b);
    case 'mem':
      r = 0;
      g = 190 + Math.round(50 * v2);
      b = 0 + Math.round(210 * v1);
      return format('rgb(%s, %s, %s)',r, g, b);
    case 'io':
      r = 80 + Math.round(60 * v1);
      g = r;
      b = 190 + Math.round(55 * v2);
      return format('rgb(%s, %s, %s)',r, g, b);
    default:
      throw new Error('Unknown type ' + type);
  }
}

module.exports =

/**
 * Maps a function name to a color, while trying to create same colors for similar functions.
 *
 * @name colorMap
 * @function
 * @private
 * @param {Object.<string, string>} paletteMap current map of colors `func: color`
 * @param {string} colorTheme theme of colors to be used `hot | mem | io`
 * @param {boolean} hash if true colors will be created from name hash, otherwise they are random
 * @param {string} func the function name for which to select a color
 * @return {string} containing an rgb color, i.e. `'rgb(1, 2, 3)'`
 */
function colorMap(paletteMap, colorTheme, hash, func) {
  if (paletteMap[func]) return paletteMap[func];
  paletteMap[func] = color(colorTheme, hash, func);
  return paletteMap[func];
}
<|endoftext|>


<commit_before>/* eslint-env node */
const { reducePromiseFunctions, Ractive } = require( './util' );

const stringify = require( './parse' ).stringify;

const help = `
    component

      Read a single file component definition from STDIN or from a file via the
      -i option and compile it into an ES module to output either to STDOUT or to
      a file via the -o option. Linked stylesheets will be imported into the
      component from their external files and included alongside any style elements.
      Any script tags will be concatenated and used as the JS body of the template
      file. The remaining HTML will be turned into a template and inlined into the
      script anywhere $TEMPLATE is encountered. Any aggregated css will be injected
      into the script as a JS string (JSON.stringify-ed) anywhere $CSS is
      encountered.

      Any additional script tags encountered with type text/ractive or text/html
      and an id or name attribute will be automatically turned into partials on the
      main template. <template> tags with an id attribute will also be turned into
      partials on the main template.

      script and link tags can specify the path to a file to include directly using
      the src and href attributes, respectively. Paths to remote files should be
      relative to the source file.

      If you are only interested in the partials defined in and linked to the main
      file, you can reference $PARTIALS in your script and it will be replaced with
      an object containing a stringified partials object.

      -i, --input {file} - file to parse, otherwise STDIN
          This may also be a directory containing a component in index.html.
      -o, --output {file} - file to write, otherwise STDOUT
      -x, --nocsp - don't output expression functions
      -d, --delimiters {open} {close} - set the plain mustache delimiters (default {{ }})
      -s, --static {open} {close} - set the static mustache delimiters (default [[ ]])
      -r, --triple {open} {close} - set the triple mustache delimiters (default {{{ }}})
      -p, --static-triple {open} {close} - set the static triple delimiters (default [[[ ]]])
      -u, --escape-unicode - export non-ASCII characters in strings as UTF escapes
`;

function build ( string, opts, readFile ) {
	const rootOpts = Object.create( opts );
	rootOpts.interpolate = { script: false, style: false, template: false };
	const tpl = Ractive.parse( string, rootOpts );
	const partials = {};
	let script = [];
	const style = [];

	const promises = [];

	// walk the template finding any script, style, or link tags to process them as appropriate
	let i = tpl.t.length;
	while ( i-- ) {
		const item = tpl.t[i];
		// top-level elements
		if ( item.t === 7 ) {
			if ( item.e === 'script' ) {
				const type = getAttr( 'type', item );
				const id = getAttr( 'id', item ) || getAttr( 'name', item );
				const src = getAttr( 'src', item );

				if ( id && ( type === 'text/ractive' || type === 'text/html' ) ) {
					if ( !src ) {
						partials[id] = item.f[0];
					} else {
						promises.push( readFile( src ).then( str => partials[id] = str ) );
					}
				} else if ( !type || type === 'text/javascript' || type === 'application/javascript' ) {
					if ( !src ) {
						script.unshift( item.f );
					} else {
						script.unshift( `script!${src}` );
						promises.push( readFile( src ).then( str => script.splice( script.indexOf( `script!${src}` ), 1, str ) ) );
					}
				}

				i = drop( i, tpl.t );
			} else if ( item.e === 'template' ) {
				const id = getAttr( 'id', item ) || getAttr( 'name', item );
				if ( id ) {
					partials[id] = item.f[0];
				}

				i = drop( i, tpl.t );
			} else if ( item.e === 'style' ) {
				style.unshift( item.f[0] );

				i = drop( i, tpl.t );
			} else if ( item.e === 'link' ) {
				const href = getAttr( 'href', item );
				const type = getAttr( 'type', item );
				const rel = getAttr( 'rel', item );

				if ( href && ( type === 'component' || ( ( !type || type === 'text/css' ) && ( rel === 'ractive' || rel === 'component' ) ) ) ) {
					style.unshift( `style!${href}` );
					promises.push( readFile( href ).then( str => style.splice( style.indexOf( `style!${href}` ), 1, str ) ) );
					// only links that are consumed are removed
					i = drop( i, tpl.t );
				}
			}
		}
	}

	return Promise.all( promises ).then( () => {
		script = dedent( script.join( '' ) );

		for ( const k in partials ) {
			if ( !tpl.p ) tpl.p = {};

			// just in case, don't overwrite any existing partial
			if ( tpl.p[k] ) continue;

			const t = Ractive.parse( partials[k], opts );

			// copy any expressions
			if ( t.e ) {
				if ( !tpl.e ) tpl.e = {};
				for ( const e in t.e ) tpl.e[e] = t.e[e];
			}

			// copy any partials
			if ( t.p ) {
				for ( const p in t.p ) {
					if ( !tpl.p[p] ) tpl.p[p] = t.p[p];
				}
			}

			tpl.p[k] = t.t;
		}

		return Promise.all([
			reducePromiseFunctions( opts.styleProcessors, style.join( '' ) ).then( css => css.replace( /\s+/g, ' ' ) ),
			reducePromiseFunctions( opts.partialProcessors, partials ),
			reducePromiseFunctions( opts.templateProcessors, tpl )
		]).then( list => {
			script = script.replace( /\$TEMPLATE/g, stringify( list[2], opts ) );
			script = script.replace( /\$CSS/g, JSON.stringify( list[0] ) );
			script = script.replace( /\$PARTIALS/g, stringify( list[1], opts ) );

			return reducePromiseFunctions( opts.scriptProcessors, script );
		});
	});
}

function dedent ( string ) {
	const lines = string.split( /\r\n|\r|\n/ );
	let strip = /^\s*/.exec( lines[ lines.length - 1 ] );
	if ( !strip ) return string;
	strip = strip[0];
	return lines.map( l => l.replace( strip, '' ) ).join( '\n' );
}

const blank = /^\s*$/;
function drop ( i, tpl ) {
	tpl.splice( i, 1 );
	while ( blank.test( tpl[i] ) ) tpl.splice( i, 1 );
	let restart = i--;
	while ( blank.test( tpl[i] ) ) {
		tpl.splice( i, 1 );
		restart--;
	}
	return restart;
}

function getAttr( name, node ) {
	if ( node.m ) {
		let i = node.m.length;
		while ( i-- ) {
			const a = node.m[i];
			// plain attribute with a matching name
			if ( a.t === 13 && a.n === name && typeof a.f === 'string' ) return a.f;
		}
	}
}

module.exports = { help, build };
<commit_msg>keep component parser from trying to parse empty templates<commit_after>/* eslint-env node */
const { reducePromiseFunctions, Ractive } = require( './util' );

const stringify = require( './parse' ).stringify;

const help = `
    component

      Read a single file component definition from STDIN or from a file via the
      -i option and compile it into an ES module to output either to STDOUT or to
      a file via the -o option. Linked stylesheets will be imported into the
      component from their external files and included alongside any style elements.
      Any script tags will be concatenated and used as the JS body of the template
      file. The remaining HTML will be turned into a template and inlined into the
      script anywhere $TEMPLATE is encountered. Any aggregated css will be injected
      into the script as a JS string (JSON.stringify-ed) anywhere $CSS is
      encountered.

      Any additional script tags encountered with type text/ractive or text/html
      and an id or name attribute will be automatically turned into partials on the
      main template. <template> tags with an id attribute will also be turned into
      partials on the main template.

      script and link tags can specify the path to a file to include directly using
      the src and href attributes, respectively. Paths to remote files should be
      relative to the source file.

      If you are only interested in the partials defined in and linked to the main
      file, you can reference $PARTIALS in your script and it will be replaced with
      an object containing a stringified partials object.

      -i, --input {file} - file to parse, otherwise STDIN
          This may also be a directory containing a component in index.html.
      -o, --output {file} - file to write, otherwise STDOUT
      -x, --nocsp - don't output expression functions
      -d, --delimiters {open} {close} - set the plain mustache delimiters (default {{ }})
      -s, --static {open} {close} - set the static mustache delimiters (default [[ ]])
      -r, --triple {open} {close} - set the triple mustache delimiters (default {{{ }}})
      -p, --static-triple {open} {close} - set the static triple delimiters (default [[[ ]]])
      -u, --escape-unicode - export non-ASCII characters in strings as UTF escapes
`;

function build ( string, opts, readFile ) {
	const rootOpts = Object.create( opts );
	rootOpts.interpolate = { script: false, style: false, template: false };
	const tpl = Ractive.parse( string, rootOpts );
	const partials = {};
	let script = [];
	const style = [];

	const promises = [];

	// walk the template finding any script, style, or link tags to process them as appropriate
	let i = tpl.t.length;
	while ( i-- ) {
		const item = tpl.t[i];
		// top-level elements
		if ( item.t === 7 ) {
			if ( item.e === 'script' ) {
				const type = getAttr( 'type', item );
				const id = getAttr( 'id', item ) || getAttr( 'name', item );
				const src = getAttr( 'src', item );

				if ( id && ( type === 'text/ractive' || type === 'text/html' ) ) {
					if ( !src ) {
						partials[id] = item.f[0];
					} else {
						promises.push( readFile( src ).then( str => partials[id] = str ) );
					}
				} else if ( !type || type === 'text/javascript' || type === 'application/javascript' ) {
					if ( !src ) {
						script.unshift( item.f );
					} else {
						script.unshift( `script!${src}` );
						promises.push( readFile( src ).then( str => script.splice( script.indexOf( `script!${src}` ), 1, str ) ) );
					}
				}

				i = drop( i, tpl.t );
			} else if ( item.e === 'template' ) {
				const id = getAttr( 'id', item ) || getAttr( 'name', item );
				if ( id ) {
					partials[id] = item.f[0];
				}

				i = drop( i, tpl.t );
			} else if ( item.e === 'style' ) {
				style.unshift( item.f[0] );

				i = drop( i, tpl.t );
			} else if ( item.e === 'link' ) {
				const href = getAttr( 'href', item );
				const type = getAttr( 'type', item );
				const rel = getAttr( 'rel', item );

				if ( href && ( type === 'component' || ( ( !type || type === 'text/css' ) && ( rel === 'ractive' || rel === 'component' ) ) ) ) {
					style.unshift( `style!${href}` );
					promises.push( readFile( href ).then( str => style.splice( style.indexOf( `style!${href}` ), 1, str ) ) );
					// only links that are consumed are removed
					i = drop( i, tpl.t );
				}
			}
		}
	}

	return Promise.all( promises ).then( () => {
		script = dedent( script.join( '' ) );

		for ( const k in partials ) {
			if ( !tpl.p ) tpl.p = {};

			// just in case, don't overwrite any existing partial and skip empty partials
			if ( tpl.p[k] || !partials[k] ) continue;

			const t = Ractive.parse( partials[k], opts );

			// copy any expressions
			if ( t.e ) {
				if ( !tpl.e ) tpl.e = {};
				for ( const e in t.e ) tpl.e[e] = t.e[e];
			}

			// copy any partials
			if ( t.p ) {
				for ( const p in t.p ) {
					if ( !tpl.p[p] ) tpl.p[p] = t.p[p];
				}
			}

			tpl.p[k] = t.t;
		}

		return Promise.all([
			reducePromiseFunctions( opts.styleProcessors, style.join( '' ) ).then( css => css.replace( /\s+/g, ' ' ) ),
			reducePromiseFunctions( opts.partialProcessors, partials ),
			reducePromiseFunctions( opts.templateProcessors, tpl )
		]).then( list => {
			script = script.replace( /\$TEMPLATE/g, stringify( list[2], opts ) );
			script = script.replace( /\$CSS/g, JSON.stringify( list[0] ) );
			script = script.replace( /\$PARTIALS/g, stringify( list[1], opts ) );

			return reducePromiseFunctions( opts.scriptProcessors, script );
		});
	});
}

function dedent ( string ) {
	const lines = string.split( /\r\n|\r|\n/ );
	let strip = /^\s*/.exec( lines[ lines.length - 1 ] );
	if ( !strip ) return string;
	strip = strip[0];
	return lines.map( l => l.replace( strip, '' ) ).join( '\n' );
}

const blank = /^\s*$/;
function drop ( i, tpl ) {
	tpl.splice( i, 1 );
	while ( blank.test( tpl[i] ) ) tpl.splice( i, 1 );
	let restart = i--;
	while ( blank.test( tpl[i] ) ) {
		tpl.splice( i, 1 );
		restart--;
	}
	return restart;
}

function getAttr( name, node ) {
	if ( node.m ) {
		let i = node.m.length;
		while ( i-- ) {
			const a = node.m[i];
			// plain attribute with a matching name
			if ( a.t === 13 && a.n === name && typeof a.f === 'string' ) return a.f;
		}
	}
}

module.exports = { help, build };
<|endoftext|>


<commit_before>
"use strict";

/**
 * pview.js
 * @CreatedOn: 20-Sep-2017
 * @author: Kausik Dey
 * @version: 1.0.0
 * @description:This will create a View Engin Aka - pView, for render JSX virtual DOM to a real DOM.
 * "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties. nodeName, Attributes, children
 * The whole process (JSX -> VDOM -> DOM) in one step
 */

/**
 * mountTo will render virtual DOM Into Real DOM and add append element into the real DOM
 * @param {object} node - It will be a real DOM node or Virtual node which can be mount.
 * @param {object} targetNode - This will be the target DOM where actually mount will done.
 * @param {string='vnode'} nodeType - This flag decide node variable having real node or virtual node ['vnode' | 'rnode'].
 * @param {object=null} oldNode - This is a optional param. It is used to replace a node without removing other child of parent node.
 * @return {object} will be the component object.
 * */
function mountTo(node, targetNode, nodeType = 'vnode', oldNode = null) {

  if (!node || !targetNode) {
    throw new TypeError('Invalid vnode or target in render component');
  }
  let component = (nodeType === 'rnode' ? node : renderDOM.call({context: {}} , node));

  if (component.self && typeof component.self.componentWillMount === 'function') {
    component.self.componentWillMount.call(component.self);
  }

  if(!oldNode) {
    targetNode.innerHTML = '';
    targetNode.appendChild(component.node);
  } else {
    targetNode.replaceChild(component.node, oldNode);
  }

  if(component.eventStack && component.eventStack instanceof Array){
    component.eventStack.forEach(evt => evt());
  }

  if (component.self && typeof component.self.componentDidMount === 'function') {
    component.self.componentDidMount.call(component.self);
  }

  return component;
}

/** Render Virtual DOM to the real DOM */
function renderDOM(vnode) {
  let svgNS = "http://www.w3.org/2000/svg";
  if (typeof vnode === 'string' || typeof vnode === 'number') {
    return { node: document.createTextNode(vnode), children: [], eventStack: []};
  }
  let component = {
    node: undefined,
    children: [],
    eventStack: []
  };
  /* when vnode is string like - any tag [text, svg, line, path etc.] */
  if (typeof vnode.nodeName === 'string') {
    let isHtml = vnode.nodeName.match('html-');
    component.node = isHtml ? document.createElement(vnode.nodeName.substring('html-'.length)) : document.createElementNS(svgNS, vnode.nodeName);
    Object.keys(vnode.attributes || {}).forEach(key => {
      let attrVal = ((k) => {
        switch (k) {
          case 'style': return parseStyleProps(vnode.attributes[k]);
          case 'events': return parseEventsProps(vnode.attributes[k], component.node);
          default: return vnode.attributes[k];
        }
      })(key);
      component.node.setAttribute(key, attrVal);
    });
  }
  /* when vnode is a class constructor of type pview component */
  else if (typeof vnode.nodeName === 'function' && isNativeClass(vnode.nodeName, vnode.nodeName.constructor)) {
    vnode.attributes.extChildren = vnode.children;
    vnode.nodeName.prototype.context = this.context || {};
    let objComp = new vnode.nodeName(vnode.attributes);
    let objChildContext = Object.assign({}, objComp.context, (typeof objComp.passContext === 'function' ? objComp.passContext() : {}));
    let renderedComp = renderDOM.call({context: objChildContext}, objComp.getVirtualNode());

    component.self = objComp;
    ({ node: component.node, children: component.children } = renderedComp);
    component.eventStack.push.apply(component.eventStack, renderedComp.eventStack);
    ({ node: objComp.ref.node, children: objComp.ref.children} = component);

    return component;
  }
  /* when vnode is type of object which is previously constructed */
  else if (typeof vnode.nodeName === "object" && vnode.nodeName.ref) {
    let objComp = vnode.nodeName;
    objComp.__proto__.context = this.context || {};
    let objChildContext = Object.assign({}, objComp.context, (typeof objComp.passContext === 'function' ? objComp.passContext() : {}));
    let subNodes = vnode.nodeName.getVirtualNode();

    if(subNodes.children && subNodes.children.length){
      replaceClassWithObject(subNodes, objComp.ref);
    }

    let renderedComp = renderDOM.call({context: objChildContext}, subNodes);
    objComp.props.extChildren = vnode.children;
    component.self = objComp;
    ({ node: component.node, children: component.children } = renderedComp);
    component.eventStack.push.apply(component.eventStack, renderedComp.eventStack);
    ({ node: objComp.ref.node, children: objComp.ref.children} = component);

    return component;
  }
  /* when vnode is type normal function */
  else if (typeof vnode.nodeName === 'function') {
    ({ node: component.node, children: component.children } = renderDOM(vnode.nodeName(vnode.attributes)));
  }
  else {
    throw new TypeError('RenderDOM method accepts html node or function with render method or class extends Component', vnode);
  }

  /* loop for childrens */
  (vnode.children || []).forEach((c) => {
    let childComp = renderDOM.call(({context: this.context} || {}), c);

    if (childComp.self && typeof childComp.self.componentWillMount === 'function') {
      childComp.self.componentWillMount.call(childComp.self);
    }

    component.children.push(childComp);
    component.node.appendChild(childComp.node);

    if(childComp.eventStack && childComp.eventStack instanceof Array) {
      component.eventStack.push.apply(component.eventStack, childComp.eventStack);
    }

    if (childComp.self && typeof childComp.self.componentDidMount === 'function') {
      component.eventStack.push(childComp.self.componentDidMount.bind(childComp.self));
    }
  });

  return component;
}

/**
 * Method will recursively replace the vitual class with real object which previously constructed to avoid constructor call during
 * component update.
 * @param {*} subNodes virtual nodeds with component class
 * @param {*} refs real object that previously constructed
 */
function replaceClassWithObject(subNodes, refs) {
  try {
    for (let i = 0; i < subNodes.children.length; i++) {
      let subNode = subNodes.children[i];
      for (let c = 0; c < refs.children.length; c++) {
        let refChld = refs.children[c];
        if (refChld.self && typeof subNode.nodeName === 'function' && refChld.self instanceof subNode.nodeName) {
          /*Match instaceId for support multiple instace of same component type under same parent node */
          if(refChld.self.props.instanceId === subNode.attributes.instanceId){
            subNode.nodeName = refChld.self;
            if (refChld.self && typeof refChld.self.propsWillReceive === 'function') {
              refChld.self.propsWillReceive.call(refChld.self, subNode.attributes);
              refChld.self.props = Object.assign({}, refChld.self.props, subNode.attributes, { extChildren: subNode.children });
            }
            break;
          }
        }
      }
      if (subNode.children && subNode.children.length && refs.children[i] && refs.children[i].children.length) {
        replaceClassWithObject(subNode, refs.children[i]);
      }
    }
  } catch (ex) {
    throw ex;
  }
}

/**
 * Hyperscript generator, gets called by transpiled JSX
 */
window.__h__ = window.__h__ ||
function(nodeName, attributes, ...args) {
  args = args.filter((v) => {
    return !!v;
  });
  let children = args.length ? [].concat(...args) : null;
  return { nodeName, attributes: attributes|| {}, children };
};

/**
 * convert style JSON into string, gets called by transpiled JSX
 * @param {JSON} objStyle style json object
 * @returns {String} return string of css
 */
function parseStyleProps(objStyle) {
  if (typeof objStyle === "string") {
    return objStyle;
  }
  let sArr = [];
  Object.keys(objStyle).forEach(key => {
    sArr.push(`${key.replace(/([A-Z]+)/g, $1 => '-' + $1.toLowerCase())}:${objStyle[key]}`);
  });
  return sArr.join(';');
}

/**
 * Attach events with real DOM
 * @param {*} events JSON List of events
 * @param {*} node Real DOM Element
 * @return {String} Returns List of attached events as string
 */
function parseEventsProps(events, node) {
  Object.keys(events).forEach((e) => {
    node.addEventListener(e, events[e], false);
  });
  return Object.keys(events).join();
}

/** This will return true if instace is es6 class type  */
function isNativeClass(instance, Constructor) {
  return !!instance.toString().match(/_classCallCheck/);
}

/** This will return false if two node are exual other return true */
function detectDiff(vnode1, vnode2) {
  return !(JSON.stringify(vnode1) === JSON.stringify(vnode2));
}

/**
 * Component Class is the base class of all PView reusable component class.
 * All components must extends this Component class. And they should have render method.
 */

class Component {
  constructor(props) {
    this.props = props;
    this.state = {};
    this.ref = {};
  }

  /** Fires when setting new state of a component.*/
  setState(stateParams) {
    if (typeof stateParams === 'function') {
      stateParams = stateParams.call(this, this.state);
    }
    Object.keys(stateParams).forEach(key => {
      this.state[key] = stateParams[key];
    });
    return this.update();
  }

  /**
   * Fetch virtual node of a component by calling its render function and assign it into vnode property
   * @returns {virtual node} retrun its virtual node
   */
  getVirtualNode() {
    return this.vnode = this.render();
  }

  /**
   * Fires when we want to re-render a component
   * @returns {Object} Component type object
   */
  update() {
    let vnodeNow = this.render();

    if (detectDiff(this.vnode, vnodeNow)) {
      this.vnode = vnodeNow;
      let parent = this.ref.node.parentNode;
      let oldNode = this.ref.node;
      let objChildContext = Object.assign({}, this.context, (typeof this.passContext === 'function' ? this.passContext() : {}));
      let renderedComp = renderDOM.call(
        {context : objChildContext || {}},
        {nodeName: this, children: (this.props.extChildren), attributes: this.vnode.attributes});

      ({ node: this.ref.node, children: this.ref.children } = renderedComp);
      return mountTo({ node: renderedComp.node, children: renderedComp.children, self: this, eventStack: renderedComp.eventStack}, parent, 'rnode', oldNode);
    }
  }

  /**
   * Interface that child may override - returns context that will pass on child context
   */
  passContext() {
    return {} ;
  }

  /**
   * Interface that child must override - return virtual DOM of the component
   */
  render() {
    return (<g> child must override this render method </g>);
  }

  /**
   * Lifecycle event - fires just before passing props into a pre-exist Component
   * @param {Object} nextProps New set of props
   */
  propsWillReceive(nextProps) {}

  /**
   * Lifecycle event - fires before the mounting component on parent DOM
   */
  componentWillMount() {}

  /**
   * Lifecycle event - fires after the component mounted on parent DOM
   */
  componentDidMount() {}
}

export { mountTo, renderDOM, Component };
<commit_msg>Fix double rednering issue while update<commit_after>
"use strict";

/**
 * pview.js
 * @CreatedOn: 20-Sep-2017
 * @author: Kausik Dey
 * @version: 1.0.0
 * @description:This will create a View Engin Aka - pView, for render JSX virtual DOM to a real DOM.
 * "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties. nodeName, Attributes, children
 * The whole process (JSX -> VDOM -> DOM) in one step
 *
 * TODO: If the first element in jsx is a component type then behave incorrecly, Need to fix this.
 */

/**
 * mountTo will render virtual DOM Into Real DOM and add append element into the real DOM
 * @param {object} node - It will be a real DOM node or Virtual node which can be mount.
 * @param {object} targetNode - This will be the target DOM where actually mount will done.
 * @param {string='vnode'} nodeType - This flag decide node variable having real node or virtual node ['vnode' | 'rnode'].
 * @param {object=null} oldNode - This is a optional param. It is used to replace a node without removing other child of parent node.
 * @return {object} will be the component object.
 * */
function mountTo(node, targetNode, nodeType = 'vnode', oldNode = null) {

  if (!node || !targetNode) {
    throw new TypeError('Invalid vnode or target in render component');
  }
  let component = (nodeType === 'rnode' ? node : renderDOM.call({context: {}} , node));

  if (component.self && typeof component.self.componentWillMount === 'function') {
    component.self.componentWillMount.call(component.self);
  }

  if(!oldNode) {
    targetNode.innerHTML = '';
    targetNode.appendChild(component.node);
  } else {
    targetNode.replaceChild(component.node, oldNode);
  }

  if(component.eventStack && component.eventStack instanceof Array){
    component.eventStack.forEach(evt => evt());
  }

  if (component.self && typeof component.self.componentDidMount === 'function') {
    component.self.componentDidMount.call(component.self);
  }

  return component;
}

/** Render Virtual DOM to the real DOM */
function renderDOM(vnode) {
  let svgNS = "http://www.w3.org/2000/svg";
  if (typeof vnode === 'string' || typeof vnode === 'number') {
    return { node: document.createTextNode(vnode), children: [], eventStack: []};
  }
  let component = {
    node: undefined,
    children: [],
    eventStack: []
  };
  /* when vnode is string like - any tag [text, svg, line, path etc.] */
  if (typeof vnode.nodeName === 'string') {
    let isHtml = vnode.nodeName.match('html-');
    component.node = isHtml ? document.createElement(vnode.nodeName.substring('html-'.length)) : document.createElementNS(svgNS, vnode.nodeName);
    Object.keys(vnode.attributes || {}).forEach(key => {
      let attrVal = ((k) => {
        switch (k) {
          case 'style': return parseStyleProps(vnode.attributes[k]);
          case 'events': return parseEventsProps(vnode.attributes[k], component.node);
          default: return vnode.attributes[k];
        }
      })(key);
      component.node.setAttribute(key, attrVal);
    });
  }
  /* when vnode is a class constructor of type pview component */
  else if (typeof vnode.nodeName === 'function' && isNativeClass(vnode.nodeName, vnode.nodeName.constructor)) {
    vnode.attributes.extChildren = vnode.children;
    vnode.nodeName.prototype.context = this.context || {};
    let objComp = new vnode.nodeName(vnode.attributes);
    let objChildContext = Object.assign({}, objComp.context, (typeof objComp.passContext === 'function' ? objComp.passContext() : {}));
    let renderedComp = renderDOM.call({context: objChildContext}, objComp.getVirtualNode());

    component.self = objComp;
    ({ node: component.node, children: component.children } = renderedComp);
    component.eventStack.push.apply(component.eventStack, renderedComp.eventStack);
    ({ node: objComp.ref.node, children: objComp.ref.children} = component);

    return component;
  }
  /* when vnode is type of object which is previously constructed */
  else if (typeof vnode.nodeName === "object" && vnode.nodeName.ref) {
    let objComp = vnode.nodeName;
    objComp.__proto__.context = this.context || {};
    let objChildContext = Object.assign({}, objComp.context, (typeof objComp.passContext === 'function' ? objComp.passContext() : {}));
    let subNodes = vnode.fromUpdate ? objComp.vnode : objComp.getVirtualNode();

    if(subNodes.children && subNodes.children.length){
      replaceClassWithObject(subNodes, objComp.ref);
    }

    let renderedComp = renderDOM.call({context: objChildContext}, subNodes);
    objComp.props.extChildren = vnode.children;
    component.self = objComp;
    ({ node: component.node, children: component.children } = renderedComp);
    component.eventStack.push.apply(component.eventStack, renderedComp.eventStack);
    ({ node: objComp.ref.node, children: objComp.ref.children} = component);

    return component;
  }
  /* when vnode is type normal function */
  else if (typeof vnode.nodeName === 'function') {
    ({ node: component.node, children: component.children } = renderDOM(vnode.nodeName(vnode.attributes)));
  }
  else {
    throw new TypeError('RenderDOM method accepts html node or function with render method or class extends Component', vnode);
  }

  /* loop for childrens */
  (vnode.children || []).forEach((c) => {
    let childComp = renderDOM.call(({context: this.context} || {}), c);

    if (childComp.self && typeof childComp.self.componentWillMount === 'function') {
      childComp.self.componentWillMount.call(childComp.self);
    }

    component.children.push(childComp);
    component.node.appendChild(childComp.node);

    if(childComp.eventStack && childComp.eventStack instanceof Array) {
      component.eventStack.push.apply(component.eventStack, childComp.eventStack);
    }

    if (childComp.self && typeof childComp.self.componentDidMount === 'function') {
      component.eventStack.push(childComp.self.componentDidMount.bind(childComp.self));
    }
  });

  return component;
}

/**
 * Method will recursively replace the vitual class with real object which previously constructed to avoid constructor call during
 * component update.
 * @param {*} subNodes virtual nodeds with component class
 * @param {*} refs real object that previously constructed
 */
function replaceClassWithObject(subNodes, refs) {
  try {
    for (let i = 0; i < subNodes.children.length; i++) {
      let subNode = subNodes.children[i];
      for (let c = 0; c < refs.children.length; c++) {
        let refChld = refs.children[c];
        if (refChld.self && typeof subNode.nodeName === 'function' && refChld.self instanceof subNode.nodeName) {
          /*Match instaceId for support multiple instace of same component type under same parent node */
          if(refChld.self.props.instanceId === subNode.attributes.instanceId){
            subNode.nodeName = refChld.self;
            if (refChld.self && typeof refChld.self.propsWillReceive === 'function') {
              refChld.self.propsWillReceive.call(refChld.self, subNode.attributes);
              refChld.self.props = Object.assign({}, refChld.self.props, subNode.attributes, { extChildren: subNode.children });
            }
            break;
          }
        }
      }
      if (subNode.children && subNode.children.length && refs.children[i] && refs.children[i].children.length) {
        replaceClassWithObject(subNode, refs.children[i]);
      }
    }
  } catch (ex) {
    throw ex;
  }
}

/**
 * Hyperscript generator, gets called by transpiled JSX
 */
window.__h__ = window.__h__ ||
function(nodeName, attributes, ...args) {
  args = args.filter((v) => {
    return !!v;
  });
  let children = args.length ? [].concat(...args) : null;
  return { nodeName, attributes: attributes|| {}, children };
};

/**
 * convert style JSON into string, gets called by transpiled JSX
 * @param {JSON} objStyle style json object
 * @returns {String} return string of css
 */
function parseStyleProps(objStyle) {
  if (typeof objStyle === "string") {
    return objStyle;
  }
  let sArr = [];
  Object.keys(objStyle).forEach(key => {
    sArr.push(`${key.replace(/([A-Z]+)/g, $1 => '-' + $1.toLowerCase())}:${objStyle[key]}`);
  });
  return sArr.join(';');
}

/**
 * Attach events with real DOM
 * @param {*} events JSON List of events
 * @param {*} node Real DOM Element
 * @return {String} Returns List of attached events as string
 */
function parseEventsProps(events, node) {
  Object.keys(events).forEach((e) => {
    node.addEventListener(e, events[e], false);
  });
  return Object.keys(events).join();
}

/** This will return true if instace is es6 class type  */
function isNativeClass(instance, Constructor) {
  return !!instance.toString().match(/_classCallCheck/);
}

/** This will return false if two node are exual other return true */
function detectDiff(vnode1, vnode2) {
  return !(JSON.stringify(vnode1) === JSON.stringify(vnode2));
}

/**
 * Component Class is the base class of all PView reusable component class.
 * All components must extends this Component class. And they should have render method.
 */

class Component {
  constructor(props) {
    this.props = props;
    this.state = {};
    this.ref = {};
  }

  /** Fires when setting new state of a component.*/
  setState(stateParams) {
    if (typeof stateParams === 'function') {
      stateParams = stateParams.call(this, this.state);
    }
    stateParams && Object.keys(stateParams).forEach(key => {
      this.state[key] = stateParams[key];
    });
    return this.update();
  }

  /**
   * Fetch virtual node of a component by calling its render function and assign it into vnode property
   * @returns {virtual node} retrun its virtual node
   */
  getVirtualNode() {
    return this.vnode = this.render();
  }

  /**
   * Fires when we want to re-render a component
   * @returns {Object} Component type object
   */
  update() {
    let vnodeNow = this.render();

    if (detectDiff(this.vnode, vnodeNow)) {
      this.vnode = vnodeNow;
      let parent = this.ref.node.parentNode;
      let oldNode = this.ref.node;
      let objChildContext = Object.assign({}, this.context, (typeof this.passContext === 'function' ? this.passContext() : {}));
      let renderedComp = renderDOM.call(
        {context : objChildContext || {}},
        {nodeName: this, children: (this.props.extChildren), attributes: this.vnode.attributes, fromUpdate:true});

      ({ node: this.ref.node, children: this.ref.children } = renderedComp);
      return mountTo({ node: renderedComp.node, children: renderedComp.children, self: this, eventStack: renderedComp.eventStack}, parent, 'rnode', oldNode);
    }
  }

  /**
   * Interface that child may override - returns context that will pass on child context
   */
  passContext() {
    return {} ;
  }

  /**
   * Interface that child must override - return virtual DOM of the component
   */
  render() {
    return (<g> child must override this render method </g>);
  }

  /**
   * Lifecycle event - fires just before passing props into a pre-exist Component
   * @param {Object} nextProps New set of props
   */
  propsWillReceive(nextProps) {}

  /**
   * Lifecycle event - fires before the mounting component on parent DOM
   */
  componentWillMount() {}

  /**
   * Lifecycle event - fires after the component mounted on parent DOM
   */
  componentDidMount() {}
}

export { mountTo, renderDOM, Component };
<|endoftext|>


<commit_before>var fs = require('fs');

var Canvas = require('canvas');

exports.composite = function(layout, destination, cb) {
    var canvas = new Canvas(layout.width, layout.height);
    var ctx = canvas.getContext('2d');
    layout.images.forEach(function(img) {
        ctx.drawImage(
            img.imageResource,
            // Native image dimensions at origin
            0, 0, img.imageResource.width, img.imageResource.height,
            // Sprited image dimensions and location
            img.x, img.y, img.width, img.height
        );
    });

    // Write the composited file to disk
    var out = fs.createWriteStream(destination);
    var stream = canvas.pngStream();
    stream.on('data', function(chunk) {
        out.write(chunk);
    });

    stream.on('end', cb);

};
<commit_msg>Clean up /lib/composite.js<commit_after>var fs = require('fs');

var Canvas = require('canvas');

/**
 * Composites a layout into a sprite image.
 * @param {Layout} layout The layout object to composite.
 * @param {string} destination The final location of the sprite file.
 * @param {function} cb A callback to execute on completion or error.
 * @returns void
 */
exports.composite = function composite(layout, destination, cb) {
    // Create a new canvas object
    var canvas = new Canvas(layout.width, layout.height);
    var ctx = canvas.getContext('2d');

    // Iterate each image and draw it at the appropraite location.
    layout.images.forEach(function(img) {
        ctx.drawImage(
            img.imageResource,
            // Native image dimensions at origin
            0, 0, img.imageResource.width, img.imageResource.height,
            // Sprited image dimensions and location
            img.x, img.y, img.width, img.height
        );
    });

    // Write the composited file to disk.
    var out = fs.createWriteStream(destination);
    var stream = canvas.pngStream();
    stream.on('data', function(chunk) {
        out.write(chunk);
    });

    stream.on('end', cb);
};
<|endoftext|>