123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- #!/usr/bin/env node
- /**
- * Module dependencies.
- */
- var exec = require('child_process').exec
- , program = require('commander')
- , mkdirp = require('mkdirp')
- , pkg = require('../package.json')
- , version = pkg.version
- , os = require('os')
- , fs = require('fs');
- // CLI
- program
- .version(version)
- .option('-s, --sessions', 'add session support')
- .option('-e, --ejs', 'add ejs engine support (defaults to jade)')
- .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
- .option('-H, --hogan', 'add hogan.js engine support')
- .option('-c, --css <engine>', 'add stylesheet <engine> support (less|stylus) (defaults to plain css)')
- .option('-f, --force', 'force on non-empty directory')
- .parse(process.argv);
- // Path
- var path = program.args.shift() || '.';
- // end-of-line code
- var eol = os.EOL
- // Template engine
- program.template = 'jade';
- if (program.ejs) program.template = 'ejs';
- if (program.jshtml) program.template = 'jshtml';
- if (program.hogan) program.template = 'hjs';
- /**
- * Routes index template.
- */
- var index = [
- ''
- , '/*'
- , ' * GET home page.'
- , ' */'
- , ''
- , 'exports.index = function(req, res){'
- , ' res.render(\'index\', { title: \'Express\' });'
- , '};'
- ].join(eol);
- /**
- * Routes users template.
- */
- var users = [
- ''
- , '/*'
- , ' * GET users listing.'
- , ' */'
- , ''
- , 'exports.list = function(req, res){'
- , ' res.send("respond with a resource");'
- , '};'
- ].join(eol);
- /**
- * Jade layout template.
- */
- var jadeLayout = [
- 'doctype 5'
- , 'html'
- , ' head'
- , ' title= title'
- , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
- , ' body'
- , ' block content'
- ].join(eol);
- /**
- * Jade index template.
- */
- var jadeIndex = [
- 'extends layout'
- , ''
- , 'block content'
- , ' h1= title'
- , ' p Welcome to #{title}'
- ].join(eol);
- /**
- * EJS index template.
- */
- var ejsIndex = [
- '<!DOCTYPE html>'
- , '<html>'
- , ' <head>'
- , ' <title><%= title %></title>'
- , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
- , ' </head>'
- , ' <body>'
- , ' <h1><%= title %></h1>'
- , ' <p>Welcome to <%= title %></p>'
- , ' </body>'
- , '</html>'
- ].join(eol);
- /**
- * JSHTML layout template.
- */
- var jshtmlLayout = [
- '<!DOCTYPE html>'
- , '<html>'
- , ' <head>'
- , ' <title> @write(title) </title>'
- , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
- , ' </head>'
- , ' <body>'
- , ' @write(body)'
- , ' </body>'
- , '</html>'
- ].join(eol);
- /**
- * JSHTML index template.
- */
- var jshtmlIndex = [
- '<h1>@write(title)</h1>'
- , '<p>Welcome to @write(title)</p>'
- ].join(eol);
- /**
- * Hogan.js index template.
- */
- var hoganIndex = [
- '<!DOCTYPE html>'
- , '<html>'
- , ' <head>'
- , ' <title>{{ title }}</title>'
- , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
- , ' </head>'
- , ' <body>'
- , ' <h1>{{ title }}</h1>'
- , ' <p>Welcome to {{ title }}</p>'
- , ' </body>'
- , '</html>'
- ].join(eol);
- /**
- * Default css template.
- */
- var css = [
- 'body {'
- , ' padding: 50px;'
- , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
- , '}'
- , ''
- , 'a {'
- , ' color: #00B7FF;'
- , '}'
- ].join(eol);
- /**
- * Default less template.
- */
- var less = [
- 'body {'
- , ' padding: 50px;'
- , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
- , '}'
- , ''
- , 'a {'
- , ' color: #00B7FF;'
- , '}'
- ].join(eol);
- /**
- * Default stylus template.
- */
- var stylus = [
- 'body'
- , ' padding: 50px'
- , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
- , 'a'
- , ' color: #00B7FF'
- ].join(eol);
- /**
- * App template.
- */
- var app = [
- ''
- , '/**'
- , ' * Module dependencies.'
- , ' */'
- , ''
- , 'var express = require(\'express\')'
- , ' , routes = require(\'./routes\')'
- , ' , user = require(\'./routes/user\')'
- , ' , http = require(\'http\')'
- , ' , path = require(\'path\');'
- , ''
- , 'var app = express();'
- , ''
- , '// all environments'
- , 'app.set(\'port\', process.env.PORT || 3000);'
- , 'app.set(\'views\', __dirname + \'/views\');'
- , 'app.set(\'view engine\', \':TEMPLATE\');'
- , 'app.use(express.favicon());'
- , 'app.use(express.logger(\'dev\'));'
- , 'app.use(express.bodyParser());'
- , 'app.use(express.methodOverride());{sess}'
- , 'app.use(app.router);{css}'
- , 'app.use(express.static(path.join(__dirname, \'public\')));'
- , ''
- , '// development only'
- , 'if (\'development\' == app.get(\'env\')) {'
- , ' app.use(express.errorHandler());'
- , '}'
- , ''
- , 'app.get(\'/\', routes.index);'
- , 'app.get(\'/users\', user.list);'
- , ''
- , 'http.createServer(app).listen(app.get(\'port\'), function(){'
- , ' console.log(\'Express server listening on port \' + app.get(\'port\'));'
- , '});'
- , ''
- ].join(eol);
- // Generate application
- (function createApplication(path) {
- emptyDirectory(path, function(empty){
- if (empty || program.force) {
- createApplicationAt(path);
- } else {
- program.confirm('destination is not empty, continue? ', function(ok){
- if (ok) {
- process.stdin.destroy();
- createApplicationAt(path);
- } else {
- abort('aborting');
- }
- });
- }
- });
- })(path);
- /**
- * Create application at the given directory `path`.
- *
- * @param {String} path
- */
- function createApplicationAt(path) {
- console.log();
- process.on('exit', function(){
- console.log();
- console.log(' install dependencies:');
- console.log(' $ cd %s && npm install', path);
- console.log();
- console.log(' run the app:');
- console.log(' $ node app');
- console.log();
- });
- mkdir(path, function(){
- mkdir(path + '/public');
- mkdir(path + '/public/javascripts');
- mkdir(path + '/public/images');
- mkdir(path + '/public/stylesheets', function(){
- switch (program.css) {
- case 'less':
- write(path + '/public/stylesheets/style.less', less);
- break;
- case 'stylus':
- write(path + '/public/stylesheets/style.styl', stylus);
- break;
- default:
- write(path + '/public/stylesheets/style.css', css);
- }
- });
- mkdir(path + '/routes', function(){
- write(path + '/routes/index.js', index);
- write(path + '/routes/user.js', users);
- });
- mkdir(path + '/views', function(){
- switch (program.template) {
- case 'ejs':
- write(path + '/views/index.ejs', ejsIndex);
- break;
- case 'jade':
- write(path + '/views/layout.jade', jadeLayout);
- write(path + '/views/index.jade', jadeIndex);
- break;
- case 'jshtml':
- write(path + '/views/layout.jshtml', jshtmlLayout);
- write(path + '/views/index.jshtml', jshtmlIndex);
- break;
- case 'hjs':
- write(path + '/views/index.hjs', hoganIndex);
- break;
- }
- });
- // CSS Engine support
- switch (program.css) {
- case 'less':
- app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
- break;
- case 'stylus':
- app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(__dirname + \'/public\'));');
- break;
- default:
- app = app.replace('{css}', '');
- }
- // Session support
- app = app.replace('{sess}', program.sessions
- ? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());'
- : '');
- // Template support
- app = app.replace(':TEMPLATE', program.template);
- // package.json
- var pkg = {
- name: 'application-name'
- , version: '0.0.1'
- , private: true
- , scripts: { start: 'node app.js' }
- , dependencies: {
- express: version
- }
- }
- if (program.template) pkg.dependencies[program.template] = '*';
- // CSS Engine support
- switch (program.css) {
- case 'less':
- pkg.dependencies['less-middleware'] = '*';
- break;
- default:
- if (program.css) {
- pkg.dependencies[program.css] = '*';
- }
- }
- write(path + '/package.json', JSON.stringify(pkg, null, 2));
- write(path + '/app.js', app);
- });
- }
- /**
- * Check if the given directory `path` is empty.
- *
- * @param {String} path
- * @param {Function} fn
- */
- function emptyDirectory(path, fn) {
- fs.readdir(path, function(err, files){
- if (err && 'ENOENT' != err.code) throw err;
- fn(!files || !files.length);
- });
- }
- /**
- * echo str > path.
- *
- * @param {String} path
- * @param {String} str
- */
- function write(path, str) {
- fs.writeFile(path, str);
- console.log(' \x1b[36mcreate\x1b[0m : ' + path);
- }
- /**
- * Mkdir -p.
- *
- * @param {String} path
- * @param {Function} fn
- */
- function mkdir(path, fn) {
- mkdirp(path, 0755, function(err){
- if (err) throw err;
- console.log(' \033[36mcreate\033[0m : ' + path);
- fn && fn();
- });
- }
- /**
- * Exit with the given `str`.
- *
- * @param {String} str
- */
- function abort(str) {
- console.error(str);
- process.exit(1);
- }
|