master 4a6308d7da9e cached
50 files
127.0 KB
36.1k tokens
11 symbols
1 requests
Download .txt
Repository: cliftonc/express-mvc-bootstrap
Branch: master
Commit: 4a6308d7da9e
Files: 50
Total size: 127.0 KB

Directory structure:
gitextract_1e56a2is/

├── .npmignore
├── .project
├── README.md
├── app-cluster.js
├── app.js
├── conf/
│   ├── configuration.js
│   ├── development.js
│   ├── production.js
│   └── test.js
├── controllers/
│   └── AppController.js
├── eb
├── lib/
│   ├── AppController.js
│   ├── ExamplesController.js
│   ├── README
│   └── inflection.js
├── models/
│   └── README
├── package.json
├── public/
│   └── css/
│       ├── Aristo/
│       │   └── jquery-ui-1.8.7.custom.css
│       └── style.css
├── scripts/
│   ├── create-controller.js
│   ├── create-model.js
│   ├── create-test.js
│   ├── create-view.js
│   ├── generate-all.js
│   ├── help.js
│   └── templates/
│       ├── create-controller.help.ejs
│       ├── create-controller.template.ejs
│       ├── create-model.help.ejs
│       ├── create-model.template.ejs
│       ├── create-test.help.ejs
│       ├── create-test.template.functional.ejs
│       ├── create-test.template.integration.ejs
│       ├── create-test.template.unit.ejs
│       ├── create-view.help.ejs
│       ├── create-view.template.edit.ejs
│       ├── create-view.template.index.ejs
│       ├── create-view.template.show.ejs
│       └── help.ejs
├── tests/
│   ├── functional/
│   │   ├── README
│   │   └── SampleTests.js
│   ├── integration/
│   │   └── AppControllerTests.js
│   └── unit/
│       ├── README
│       └── SampleTests.js
├── utils/
│   ├── pager.js
│   └── socketio.js
└── views/
    ├── 404.html
    ├── 500.html
    ├── app/
    │   └── index.html
    ├── layout.html
    └── messages.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .npmignore
================================================
*.sock
logs/*
pids/*


================================================
FILE: .project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>express-mvc-bootstrap</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
	</natures>
</projectDescription>


================================================
FILE: README.md
================================================

# THIS PROJECT IS NO LONGER MAINTAINED, TRY THIS ONE:  https://github.com/niftylettuce/eskimo

# Express MVC Bootstrap

A MVC boilerplate for Express.js

## Description

I built this application to create a template MVC `style` app that I could then use as the start point for further development. I used the excellent examples in the main [Express github repository](https://github.com/visionmedia/express), specifically the MVC example, as the starting point. I have however changed it quite substantially to make it clearer and remove some of the `magic` that confused me at first when learning. If you are familiar with other MVC frameworks hopefully my file structure makes some sense.

## Requires

### You need to manually install: 

  - [Node.js](http://nodejs.org/): Amazing javascript asynchronous IO library, install manually.
  - [MongoDB](http://www.mongodb.org): NoSQL Database, install manually.
  - [NPM](http://npmjs.org/): Node package manager, used to install the remaining.

### And then install via NPM: 

  - [Express](http://expressjs.com/): Application Framework for Node.js
  - [Mongoose](http://mongoosejs.com/): Node.JS ORM for Mongo
  - [ejs](http://embeddedjs.com/): EmbeddedJS Templating
  - [cluster](http://learnboost.github.com/cluster): extensible multi-core server manager
  - log: Tiny logger with streaming reader
  - [connect](https://github.com/senchalabs/connect): High performance middleware framework
  - mime: A comprehensive library for mime-type mapping
  - qs: querystring parser
  - [expresso](https://github.com/visionmedia/expresso): TDD framework, light-weight, fast, CI-friendly
  - should: test framework agnostic BDD-style assertions
  - [socket.io](https://github.com/learnboost/Socket.IO-node): The cross-browser WebSocket

### But I've included in this project:

  - [jQuery](http://jquery.com/): Javascript Library
  - [jQuery UI](http://jqueryui.com/): UI Library
  - [jQuery Aristo Template](http://taitems.tumblr.com/post/482577430/introducing-aristo-a-jquery-ui-theme): Fantastic looking jQuery UI Template.

## Installation

  - Install node.js 

<!---->

      // on osx with brew
      brew update
      brew install node
    
      // build from source
      git clone git://github.com/joyent/node.git
      ./configure
      make
      make install
  
  - Ininstall mongodb
  
<!---->

      // on osx with brew
      brew update
      brew install mongodb
    
      // create db folder
      mkdir -p /usr/local/db/

> For more installation detail please see [this](http://www.mongodb.org/display/DOCS/Quickstart)
    
  - Install npm

<!---->

    curl http://npmjs.org/install.sh | clean=no sh
    
  - Install required packages

<!---->
    
      // install executable package globally
      npm install express-mvc-bootstrap -g
    
      // make project folder and go to that folder
      mkdir /path/to/project
      cd /path/to/project
    
      // install packages locally to be `require();`
      npm install socket.io should mongoose log cluster expresso qs mime ejs connect express express-mvc-bootstrap

## Setup
  - In you project folder run
  
<!---->

      // create app 
      eb create-app
    
      // running mongodb
      mongod --dbpath /usr/local/db/
    
      // running server
      eb
    
  - Browse to http://localhost:3000


## Commands:
    
      // Shows help
      eb script
    
      // Wrapper for 3 commands below
      eb script generate-all HelloWorld
    
      // Creates a model
      eb script create-model HelloWorld 
    
      // Creates a controller
      eb script create-controller HelloWorld
    
      // Creates views
      eb script create-view HelloWorld
    
      // Creates tests
      eb script create-test HelloWorld
    
      // Runs server on different port
      eb server server.port=3000
    
      // Creates a new app
      eb create-app

## TODO: 
Build some amazing apps!


================================================
FILE: app-cluster.js
================================================
/**
 * Module dependencies.
 */
var cluster = require('cluster');
var app;

/**
 * Initial bootstrapping
 */
exports.boot = function(port,path){
  
  //Create our express instance	
  app = require('./app').boot();
  
  // TODO : ENABLE Reload
  /**
   * var watchFolders = [path + '/models', 
                      path + '/controllers',
                      path + '/views',
                      path + '/utils']
  
     .use(cluster.reload(watchFolders,{ signal: 'SIGQUIT', interval: 60000 }))
   
   */    
  
  cluster(app)
  	  .set('working directory', path)
  	  .set('socket path',path)
	  .in('development')
	    .set('workers', 1)	    
	    .use(cluster.logger(path + '/logs', 'debug'))
	    .use(cluster.debug())	   
	    .use(cluster.pidfiles(path + '/pids'))
	  .in('test')
	    .set('workers', 1)
	    .use(cluster.logger(path + '/logs', 'warning'))	    
	    .use(cluster.pidfiles(path + '/pids'))
	  .in('production')
	    .set('workers', 2)
		.use(cluster.logger(path + '/logs'))	    
		.use(cluster.pidfiles(path + '/pids'))
	  .in('all')
	    .listen(parseInt(port));
	  
};



================================================
FILE: app.js
================================================
/**
 * Module dependencies.
 */
var fs = require('fs'),express = require('express'),
	 mongoose = require('mongoose'), nodepath = require('path');

var path = __dirname;
var app;

/**
 * Initial bootstrapping
 */
exports.boot = function(params){
	
  //Create our express instance
  app = express.createServer();	
	
   // Import configuration
  require(path + '/conf/configuration.js')(app,express);
  
  // Bootstrap application
  bootApplication(app);
  bootModels(app);
  bootControllers(app);
  
  return app;
  
};

/**
 *  App settings and middleware
 *  Any of these can be added into the by environment configuration files to 
 *  enable modification by env.
 */

function bootApplication(app) {	 
   
   // launch
  // app.use(express.logger({ format: ':method :url :status' }));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session({ secret: 'helloworld' }));
  app.use(express.static(path + '/public'));  // Before router to enable dynamic routing
  app.use(app.router);

  // Example 500 page
  app['error'](function(err, req, res){
    console.log('Internal Server Error: ' + err.message);
    res.render('500');
  });
  
  // Example 404 page via simple Connect middleware
  app.use(function(req, res){
    res.render('404');
  });

  // Setup ejs views as default, with .html as the extension
  app.set('views', path + '/views');
  app.register('.html', require('ejs'));
  app.set('view engine', 'html');

  // Some dynamic view helpers
  app.dynamicHelpers({
  
	request: function(req){
	   return req;
	},
	    
	hasMessages: function(req){
      return Object.keys(req.session.flash || {}).length;
    },

    messages: function(req){
      return function(){
        var msgs = req.flash();
        console.log(msgs);
        return Object.keys(msgs).reduce(function(arr, type){
          return arr.concat(msgs[type]);
        }, []);        
      }
    }
  });
}

//Bootstrap models 
function bootModels(app) {
	
  fs.readdir(path + '/models', function(err, files){
    if (err) throw err;
    files.forEach(function(file){
    	bootModel(app, file);
    });
  });
  
  // Connect to mongoose
  mongoose.connect(app.set('db-uri'));
  
}

// Bootstrap controllers
function bootControllers(app) {
  fs.readdir(path + '/controllers', function(err, files){
    if (err) throw err;
    files.forEach(function(file){    	
    	// bootController(app, file);    		
    });
	

  });
  
  require(path + '/controllers/AppController')(app);			// Include
  
}

// simplistic model support
function bootModel(app, file) {

    var name = file.replace('.js', ''),
    	schema = require(path + '/models/'+ name);				// Include the mongoose file        
    
}

// Load the controller, link to its view file from here
function bootController(app, file) {
	
	var name = file.replace('.js', ''),
    	controller = path + '/controllers/' + name,   // full controller to include
    	template = name.replace('Controller','').toLowerCase();									// template folder for html - remove the ...Controller part.
	
	// Include the controller
	// require(controller)(app,template);			// Include
	
}

// allow normal node loading if appropriate
if (!module.parent) {
  exports.boot().listen(3000);
  console.log("Express server %s listening on port %d", express.version, app.address().port)
}



================================================
FILE: conf/configuration.js
================================================

/**
 * Default configuration manager
 * Inject app and express reference
 */
module.exports = function(app,express) {
		
	// DEVELOPMENT
	app.configure('development', function() {
	  require("./development.js")(app,express);
	});

	// TEST
	app.configure('test', function() {
		require("./test.js")(app,express);
	});
	
	// PRODUCTION
	app.configure('production', function() {
		require("./production.js")(app,express);
	});		

}


================================================
FILE: conf/development.js
================================================

/**
 * DEVELOPMENT Environment settings
 */
module.exports = function(app,express) {
		
	app.set('db-uri', 'mongodb://localhost/mvc-development');	       
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
	
}


================================================
FILE: conf/production.js
================================================

/**
 * TEST Environment settings
 */
module.exports = function(app,express) {
		
	app.set('db-uri', 'mongodb://localhost/mvc-production');
    app.use(express.errorHandler({ dumpExceptions: true, showStack: false }));
	
}


================================================
FILE: conf/test.js
================================================

/**
 * PRODUCTION Environment settings
 */
module.exports = function(app,express) {
		
	app.set('db-uri', 'mongodb://localhost/mvc-production');
    app.use(express.errorHandler({ dumpExceptions: false, showStack: false }));
	
}


================================================
FILE: controllers/AppController.js
================================================
var fs = require('fs')
	, inflection = require('../lib/inflection');

module.exports = function(app) {
	
	// app.get("/favicon.ico", function() {}); // Required if you delete the favicon.ico from public
	
	// Plural
	app.get("/:controller?", router);				        // Index
	app.get("/:controller.:format?", router);				// Index
	app.get("/:controller/:from-:to.:format?", router);		// Index
	
	// Plural Create & Delete
	app.post("/:controller", router);			// Create
	app.del("/:controller", router);   			// Delete all
	
	// Singular - different variable to clarify routing
	app.get("/:controller/:id.:format?", router);  	// To support controller/index	
	app.get("/:controller/:id/:action", router);		// Show edit
	app.put("/:controller/:id", router);				// Update
	app.del("/:controller/:id", router);				// Delete	
	
}

///
function router(req, res, next) {
		
	var controller = req.params.controller ? req.params.controller : '';
	var action = req.params.action ? req.params.action : '';
	var id = req.params.id ? req.params.id : '';
	var method = req.method.toLowerCase();
	var fn = 'index';
	
	// Default route
	if(controller.length == 0) {
		index(req,res,next);
		return;
	}		
	
	// Determine the function to call based on controller / model and method
	if(id.length == 0) {
		
		// We are plural
		switch(method) {
			case 'get':
				fn = 'index';
				break;
			case 'post':
				fn = 'create';
				break;
			case 'delete':
				fn = 'destroyAll';
				break;		
		}		
		
	} else {
		
		// Controller name is now singular, need to switch it back 
		controller = controller.pluralize();
		
		switch(method) {
			case 'get':
				if(action.length > 0) {
					fn = action;
				} else {
					fn = 'show';
				}
				break;
			case 'put':
				fn = 'update';
				break;
			case 'delete':
				fn = 'destroy';
				break;		
		}		
		
	}
	try {			
		var controllerLibrary = require('./' + controller.capitalize() + 'Controller');			
		if(typeof controllerLibrary[fn] === 'function') {
			controllerLibrary[fn](req,res,next);		
		} else {
			res.render('404');
		}	
	} catch (e) {
		res.render('404');
	}
	  	
};


/**
 * Default Application index - shows a list of the controllers.
 * Redirect here if you prefer another controller to be your index.
 * @param req
 * @param res
 */
function index(req, res, next) {
		 
	/**
	 * If you want to redirect to another controller, uncomment
	 */
	// res.redirect('/controllerName');
	
	var controllers = [];
	
	  fs.readdir(__dirname + '/', function(err, files){
	    
		if (err) throw err;
	    
		files.forEach(function(file){
			if(file != "AppController.js") {
				controllers.push(file.replace('Controller.js','').toLowerCase());
			}
	    });
	    
		res.render('app',{controllers:controllers});
	  
	  });	
	
	  	
};


================================================
FILE: eb
================================================
#!/usr/bin/env node

/**
 * ExpressJs MVC Bootstrap
 * @Params - cmd - serve
 r | script | params
 */
 
 
/**
 * Framework version.
 */

var version = '0.1.2';
 

/**
 * Require everything in the library folder
 */
require.paths.unshift(__dirname + '/lib');

/**
 * Explicit module dependencies
 */
var fs = require('fs'), nodepath = require('path'), exec = require('child_process').exec;

/**
 * Paths
 **/
var path = fs.realpathSync('.');
var bootstrapPath = __dirname;

/**
 * Main Command router
 */
var appLauncher = {
					command:'cluster',
				    server: { port:3000 },
				    script: { name:'help',
				    		  params: []
				    		}
				   };

for(var i in process.argv) {
	// Skip the first two - Node and app.js path
	if(i>1) {		
		processParam(process.argv[i],i);
	}	
}

runLauncher(appLauncher);

/**
 * Run the launcher
 * @param appLauncher
 */
function runLauncher(appLauncher) {
	
	// Always use current directory?
	console.log('\r\n\x1b[36mLaunching bootstrap from: \x1b[0m ' + path);
	console.log('\x1b[36mScript directory: \x1b[0m ' + bootstrapPath + '/scripts');	
	
	// Check if this is a bootstrap application?
	if(isLibrary()) {
		console.log('\x1b[1mDo not run this from the bootstrap library folder, please run from an empty directory or a bootstrapped app, or please run "npm install"\x1b[0m\r\n');		
		return;
	}
	
	// Check if this is a bootstrap application?
	if(!isBootstrap() && appLauncher.command != 'create-app') {
		console.log('\x1b[1mApplication not bootstrapped - you must run:\x1b[0m eb create-app\r\n');
		return;
	}
	
	switch(appLauncher.command) {
		case 'test':
			runTests(appLauncher.script);
			break;		
		case 'cluster':
			runCluster(appLauncher.server.port);
			break;
		case 'server':
			runServer(appLauncher.server.port);
			break;
		case 'script':
			runScript(appLauncher.script);
			break;			
		case 'create-app':
			createApplication(path);
			break;
		default:
			appLauncher.command = 'script';			
			runScript(appLauncher.script);			
	}
	
}

/**
 * Check if express app.js exists
 **/
function isLibrary() {	
	return nodepath.existsSync(path + '/eb');
}

/**
 * Check if .bootstrap exists
 **/
function isBootstrap() {	
	return nodepath.existsSync(path + '/.eb-status');		
}

/**
 * Run a script
 * @param appLauncher
 * Runs by default from path where bootstrap runs via __dirname.
 */
function runScript(scriptLauncher) {	
	var script = require(bootstrapPath + '/scripts/'+ scriptLauncher.name);
	script.execute(scriptLauncher.params,path);
}

/**
 * Process params into array to enable launch
 * @param param
 * @param params
 */
function processParam(param,depth) {
	
	var paramArray = param.split("=");
	
	// Run command - must always come after the app
	if(i == 2) {
		appLauncher.command = param;
	}
	
	// Server.port
	if(paramArray[0] == "server.port" && paramArray[1] != undefined) {
		appLauncher.server.port = paramArray[1];
	}
	
	// 
	if((appLauncher.command == "script" || appLauncher.command == "test") && i == 3) {
		appLauncher.script.name = param;
	}
	
	// Script params
	if(appLauncher.command == 'script' && i > 3) {
		appLauncher.script.params.push(param);
	}
	
}

/**
 * Run expresso tests
 */
function runTests(appLauncher) {

	var test = appLauncher.name ? appLauncher.name : 'all';
			
	if(test == 'help') {  // This is the default - ugly I know!
		test = ['unit','integration','functional'];
	} else {
		test = [test];
	}
	
	test.forEach(function (item, index) {
		exec('expresso -I . -s tests/' + item + '/* ', { timeout: 60000, cwd:path }, function (error, stdout, stderr) {
			console.log("Finished test: " + item);
	    	console.log(stdout);
	    	console.log(stderr);
    	});
    });
}


/**
 * Launch a server
 */
function runServer(port) {

	// Ensure we run in the local folder of the application
	process.chdir(path);	
	var app = require(path + '/app').boot();
	app.listen(port);		
	console.log('\r\n\x1b[36mApplication started on port:\x1b[0m ' + port);
}

/**
 * Launch a cluster
 */
function runCluster(port) {

	// Ensure we run in the local folder of the application	
	process.chdir(path);	
	require(path + '/app-cluster').boot(port,path);
	console.log('\r\n\x1b[36mLaunching cluster mode on port: \x1b[0m' + port);
		
}

/**
 * Application Creation - Borrowed from Express scripts
 **/

/**
 * Create application at the given directory `path`.
 *
 * @param {String} path
 */
function createApplicationAt(path) {
    
    
    mkdir(path + '/models',function() {
    	// Disabled as no default models            
	    // copy(bootstrapPath + '/models/*',path + '/models');
	});
    
    mkdir(path + '/controllers',function() {    
    	copy(bootstrapPath + '/controllers/*',path + '/controllers');
    });
    
    mkdir(path + '/conf',function() {
    	copy(bootstrapPath + '/conf/*',path + '/conf');
    });
    mkdir(path + '/utils',function() {
    	copy(bootstrapPath + '/utils/*',path + '/utils');
    });
    
	mkdir(path + '/views',function() {	
		copy(bootstrapPath + '/views/*',path + '/views');
	});
	mkdir(path + '/public',function() {
		copy(bootstrapPath + '/public/*',path + '/public');
	});
	
	mkdir(path + '/lib',function() {
    	copy(bootstrapPath + '/lib/*',path + '/lib');
    });
    
    mkdir(path + '/tests',function() {
    
    	mkdir(path + '/tests/unit',function() {
    		copy(bootstrapPath + '/tests/unit/*',path + '/tests/unit');
    	});
    	mkdir(path + '/tests/integration',function() {
    		copy(bootstrapPath + '/tests/integration/*',path + '/tests/integration');
    	});
    	mkdir(path + '/tests/functional',function() {
    		copy(bootstrapPath + '/tests/functional/*',path + '/tests/functional');
    	});
    	
    	
    });
    
	mkdir(path + '/logs');
	mkdir(path + '/pids');
	
	copy(bootstrapPath + '/app-cluster.js',path + '/');
	copy(bootstrapPath + '/app.js',path + '/');
	
	write(path + '/.eb-status','Created @ ' + new Date());	

}

function createApplication(path) {
  emptyDirectory(path, function(empty){
    if (empty) {
      createApplicationAt(path);
    } else {
      confirm('This will over-write the existing application, continue? ', function(ok){
        if (ok) {
          process.stdin.destroy();
          createApplicationAt(path);
        } else {
          abort('aborting');
        }
      });
    }
  });
};

/**
 * 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);
}

/**
 * Prompt confirmation with the given `msg`.
 *
 * @param {String} msg
 * @param {Function} fn
 */

function confirm(msg, fn) {
  prompt(msg, function(val){
    fn(/^ *y(es)?/i.test(val));
  });
}

/**
 * Prompt input with the given `msg` and callback `fn`.
 *
 * @param {String} msg
 * @param {Function} fn
 */

function prompt(msg, fn) {
  // prompt
  if (' ' == msg[msg.length - 1]) {
    process.stdout.write(msg);
  } else {
    console.log(msg);
  }

  // stdin
  process.stdin.setEncoding('ascii');
  process.stdin.once('data', function(data){
    fn(data);
  }).resume();
}

/**
 * Mkdir -p.
 *
 * @param {String} path
 * @param {Function} fn
 */

function mkdir(path, fn) {
  exec('mkdir -p ' + path, function(err){
    if (err) throw err;
    console.log('   \x1b[36mcreate\x1b[0m : ' + path);
    fn && fn();
  });
}


/**
 * cp -r
 *
 * @param {String} path
 * @param {Function} fn
 */

function copy(from, to, fn) {
  exec('cp -R ' + from + ' ' + to, function(err){
    if (err) throw err;
    console.log('   \x1b[36mCopied\x1b[0m : ' + from + ' to ' + to);
    fn && fn();
  });
}

/**
 * Exit with the given `str`.
 *
 * @param {String} str
 */

function abort(str) {
  console.error(str);
  process.exit(1);
}


================================================
FILE: lib/AppController.js
================================================
var fs = require('fs')
	, inflection = require('../lib/inflection');

module.exports = function(app) {
	
	// app.get("/favicon.ico", function() {}); // Required if you delete the favicon.ico from public
	
	// Plural
	app.get("/:controller?", router);				        // Index
	app.get("/:controller.:format?", router);				// Index
	app.get("/:controller/:from-:to.:format?", router);		// Index
	
	// Plural Create & Delete
	app.post("/:controller", router);			// Create
	app.del("/:controller", router);   			// Delete all
	
	// Singular - different variable to clarify routing
	app.get("/:controller/:id.:format?", router);  	// To support controller/index	
	app.get("/:controller/:id/:action", router);		// Show edit
	app.put("/:controller/:id", router);				// Update
	app.del("/:controller/:id", router);				// Delete	
	
}

///
function router(req, res, next) {
		
	var controller = req.params.controller ? req.params.controller : '';
	var action = req.params.action ? req.params.action : '';
	var id = req.params.id ? req.params.id : '';
	var method = req.method.toLowerCase();
	var fn = 'index';
	
	// Default route
	if(controller.length == 0) {
		index(req,res,next);
		return;
	}		
	
	// Determine the function to call based on controller / model and method
	if(id.length == 0) {
		
		// We are plural
		switch(method) {
			case 'get':
				fn = 'index';
				break;
			case 'post':
				fn = 'create';
				break;
			case 'delete':
				fn = 'destroyAll';
				break;		
		}		
		
	} else {
		
		// Controller name is now singular, need to switch it back 
		controller = controller.pluralize();
		
		switch(method) {
			case 'get':
				if(action.length > 0) {
					fn = action;
				} else {
					fn = 'show';
				}
				break;
			case 'put':
				fn = 'update';
				break;
			case 'delete':
				fn = 'destroy';
				break;		
		}		
		
	}
			
	var controllerLibrary = require('./' + controller.capitalize() + 'Controller');			
	if(typeof controllerLibrary[fn] === 'function') {
		controllerLibrary[fn](req,res,next);		
	} else {
		res.render('404');
	}
	  	
};


/**
 * Default Application index - shows a list of the controllers.
 * Redirect here if you prefer another controller to be your index.
 * @param req
 * @param res
 */
function index(req, res, next) {
		 
	/**
	 * If you want to redirect to another controller, uncomment
	 */
	// res.redirect('/controllerName');
	
	var controllers = [];
	
	  fs.readdir(__dirname + '/', function(err, files){
	    
		if (err) throw err;
	    
		files.forEach(function(file){
			if(file != "AppController.js") {
				controllers.push(file.replace('Controller.js','').toLowerCase());
			}
	    });
	    
		res.render('app',{controllers:controllers});
	  
	  });	
	
	  	
};

================================================
FILE: lib/ExamplesController.js
================================================

/**
 *  Examples Controller
 *  Created by create-controller script @ Fri Mar 11 2011 21:16:50 GMT+0000 (GMT)
 **/
 var mongoose = require('mongoose'),	
	Example = mongoose.model('Example'),
	pager = require('../utils/pager.js'),
	ViewTemplatePath = 'examples';

module.exports = {

	init: function(params) {
		ViewTemplatePath = params.viewPath   // Enable over-ride of view path for testing
	},
	
	/**
	 * Index action, returns a list either via the views/examples/index.html view or via json
	 * Default mapping to GET '/examples'
	 * For JSON use '/examples.json'
	 **/
	index: function(req, res, next) {
		  	 
		  var from = req.params.from ? parseInt(req.params.from) - 1 : 0;
		  var to = req.params.to ? parseInt(req.params.to) : 10;
	      var total = 0;
	      
	      Example.count({}, function (err, count) {
	    	total = count;  
	    	var pagerHtml = pager.render(from,to,total,'/examples');    	
	                  
			  Example.find({})
			  	.sort('name', 1)
			  	.skip(from).limit(to)
			  	.find(function (err, examples) {
				
				  if(err) return next(err);
				  
			      switch (req.params.format) {
			        case 'json':	          
			          res.send(examples.map(function(u) {
			              return u.toObject();
			          }));
			          break;
		
			        default:			        	
			        	res.render(ViewTemplatePath,{examples:examples,pagerHtml:pagerHtml});
			      }
			      
			  });
	      
	      });
	      	  	
	},
	
	/**
	 * Show action, returns shows a single item via views/examples/show.html view or via json
	 * Default mapping to GET '/example/:id'
	 * For JSON use '/example/:id.json'
	 **/	
	show: function(req, res, next) {	  		  
			
		  Example.findById(req.params.id, function(err, example) {
			  
			  if(err) return next(err);
			  
		      switch (req.params.format) {
		        case 'json':
		          res.send(example.toObject());
		          break;
	
		        default:
		        	res.render(ViewTemplatePath + "/show",{example:example});
		      }
		      
		  });
		      
	},
	
	/**
	 * Edit action, returns a form via views/examples/edit.html view no JSON view.
	 * Default mapping to GET '/example/:id/edit'
	 **/  	  
	edit: function(req, res, next){
		  Example.findById(req.params.id, function(err, example) {
			  if(err) return next(err);
			  res.render(ViewTemplatePath + "/edit",{example:example});
		});
	},
	  
	/**
	 * Update action, updates a single item and redirects to Show or returns the object as json
	 * Default mapping to PUT '/example/:id', no GET mapping	 
	 **/  
	update: function(req, res, next){
	    
		
		
	    Example.findById(req.params.id, function(err, example) {
	        
	    	if (!example) return next(err);
	        
	    	example.name = req.body.example.name;
	    	
	        example.save(function(err) {
	        
	    	  if (err) {
	    		  console.log(err);
	        	  req.flash('error','Could not update example: ' + err);
	          	  res.redirect('/examples');
	          	  return;
	    	  }
	    		
	          switch (req.params.format) {
	            case 'json':
	              res.send(example.toObject());
	              break;
	            default:
	              req.flash('info', 'Example updated');
	              res.redirect('/example/' + req.params.id);
	          }
	        });
	      });
	},
	  
	/**
	 * Create action, creates a single item and redirects to Show or returns the object as json
	 * Default mapping to POST '/examples', no GET mapping	 
	 **/  
	create: function(req, res, next){
		
		  var example = new Example(req.body.example);
		  
		  example.save(function(err) {
		   
			if (err) {
	    	  req.flash('error','Could not create example: ' + err);
	      	  res.redirect('/examples');
	      	  return;
			}
	
		    switch (req.params.format) {
		      case 'json':
		        res.send(example.toObject());
		        break;
	
		      default:
		    	  req.flash('info','Example created');
		      	  res.redirect('/example/' + example.id);
			 }
		  });	  
		  
	},
	  
	/**
	 * Delete action, deletes a single item and redirects to index
	 * Default mapping to DEL '/example/:id', no GET mapping	 
	 **/ 
	destroy: function(req, res, next){
		  
		  Example.findById(req.params.id, function(err, example) {
		        
		    	if (!example) { 
	  	    	  	req.flash('error','Unable to locate the example to delete!');
		    		res.render('404'); 
		    		return false; 
		    	};
		    		    
		    	example.remove(function(err) {
	    		  if(err) {
	    	    	  req.flash('error','There was an error deleting the example!');
	    			  res.send('false');
	    		  } else {
	    	    	  req.flash('info','Example deleted');
	    			  res.send('true');
	    		  }    	          
	   	      	}); 
		  });
		  
	}
	
};

================================================
FILE: lib/README
================================================
Place any dependent libraries in here


* inflection.js : http://code.google.com/p/inflection-js/

    Modified to remove the link to window.




================================================
FILE: lib/inflection.js
================================================
/*
Copyright (c) 2010 Ryan Schuft (ryan.schuft@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/*
  This code is based in part on the work done in Ruby to support
  infection as part of Ruby on Rails in the ActiveSupport's Inflector
  and Inflections classes.  It was initally ported to Javascript by
  Ryan Schuft (ryan.schuft@gmail.com) in 2007.

  The code is available at http://code.google.com/p/inflection-js/

  The basic usage is:
    1. Include this script on your web page.
    2. Call functions on any String object in Javascript

  Currently implemented functions:

    String.pluralize(plural) == String
      renders a singular English language noun into its plural form
      normal results can be overridden by passing in an alternative

    String.singularize(singular) == String
      renders a plural English language noun into its singular form
      normal results can be overridden by passing in an alterative

    String.camelize(lowFirstLetter) == String
      renders a lower case underscored word into camel case
      the first letter of the result will be upper case unless you pass true
      also translates "/" into "::" (underscore does the opposite)

    String.underscore() == String
      renders a camel cased word into words seperated by underscores
      also translates "::" back into "/" (camelize does the opposite)

    String.humanize(lowFirstLetter) == String
      renders a lower case and underscored word into human readable form
      defaults to making the first letter capitalized unless you pass true

    String.capitalize() == String
      renders all characters to lower case and then makes the first upper

    String.dasherize() == String
      renders all underbars and spaces as dashes

    String.titleize() == String
      renders words into title casing (as for book titles)

    String.demodulize() == String
      renders class names that are prepended by modules into just the class

    String.tableize() == String
      renders camel cased singular words into their underscored plural form

    String.classify() == String
      renders an underscored plural word into its camel cased singular form

    String.foreign_key(dropIdUbar) == String
      renders a class name (camel cased singular noun) into a foreign key
      defaults to seperating the class from the id with an underbar unless
      you pass true

    String.ordinalize() == String
      renders all numbers found in the string into their sequence like "22nd"
*/

/*
  This sets up a container for some constants in its own namespace
  We use the window (if available) to enable dynamic loading of this script
  Window won't necessarily exist for non-browsers.
if (window && !window.InflectionJS)
{
    window.InflectionJS = null;
}
*/

/*
  This sets up some constants for later use
  This should use the window namespace variable if available
*/
InflectionJS =
{
    /*
      This is a list of nouns that use the same form for both singular and plural.
      This list should remain entirely in lower case to correctly match Strings.
    */
    uncountable_words: [
        'equipment', 'information', 'rice', 'money', 'species', 'series',
        'fish', 'sheep', 'moose', 'deer', 'news'
    ],

    /*
      These rules translate from the singular form of a noun to its plural form.
    */
    plural_rules: [
        [new RegExp('(m)an$', 'gi'),                 '$1en'],
        [new RegExp('(pe)rson$', 'gi'),              '$1ople'],
        [new RegExp('(child)$', 'gi'),               '$1ren'],
        [new RegExp('^(ox)$', 'gi'),                 '$1en'],
        [new RegExp('(ax|test)is$', 'gi'),           '$1es'],
        [new RegExp('(octop|vir)us$', 'gi'),         '$1i'],
        [new RegExp('(alias|status)$', 'gi'),        '$1es'],
        [new RegExp('(bu)s$', 'gi'),                 '$1ses'],
        [new RegExp('(buffal|tomat|potat)o$', 'gi'), '$1oes'],
        [new RegExp('([ti])um$', 'gi'),              '$1a'],
        [new RegExp('sis$', 'gi'),                   'ses'],
        [new RegExp('(?:([^f])fe|([lr])f)$', 'gi'),  '$1$2ves'],
        [new RegExp('(hive)$', 'gi'),                '$1s'],
        [new RegExp('([^aeiouy]|qu)y$', 'gi'),       '$1ies'],
        [new RegExp('(x|ch|ss|sh)$', 'gi'),          '$1es'],
        [new RegExp('(matr|vert|ind)ix|ex$', 'gi'),  '$1ices'],
        [new RegExp('([m|l])ouse$', 'gi'),           '$1ice'],
        [new RegExp('(quiz)$', 'gi'),                '$1zes'],
        [new RegExp('s$', 'gi'),                     's'],
        [new RegExp('$', 'gi'),                      's']
    ],

    /*
      These rules translate from the plural form of a noun to its singular form.
    */
    singular_rules: [
        [new RegExp('(m)en$', 'gi'),                                                       '$1an'],
        [new RegExp('(pe)ople$', 'gi'),                                                    '$1rson'],
        [new RegExp('(child)ren$', 'gi'),                                                  '$1'],
        [new RegExp('([ti])a$', 'gi'),                                                     '$1um'],
        [new RegExp('((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$','gi'), '$1$2sis'],
        [new RegExp('(hive)s$', 'gi'),                                                     '$1'],
        [new RegExp('(tive)s$', 'gi'),                                                     '$1'],
        [new RegExp('(curve)s$', 'gi'),                                                    '$1'],
        [new RegExp('([lr])ves$', 'gi'),                                                   '$1f'],
        [new RegExp('([^fo])ves$', 'gi'),                                                  '$1fe'],
        [new RegExp('([^aeiouy]|qu)ies$', 'gi'),                                           '$1y'],
        [new RegExp('(s)eries$', 'gi'),                                                    '$1eries'],
        [new RegExp('(m)ovies$', 'gi'),                                                    '$1ovie'],
        [new RegExp('(x|ch|ss|sh)es$', 'gi'),                                              '$1'],
        [new RegExp('([m|l])ice$', 'gi'),                                                  '$1ouse'],
        [new RegExp('(bus)es$', 'gi'),                                                     '$1'],
        [new RegExp('(o)es$', 'gi'),                                                       '$1'],
        [new RegExp('(shoe)s$', 'gi'),                                                     '$1'],
        [new RegExp('(cris|ax|test)es$', 'gi'),                                            '$1is'],
        [new RegExp('(octop|vir)i$', 'gi'),                                                '$1us'],
        [new RegExp('(alias|status)es$', 'gi'),                                            '$1'],
        [new RegExp('^(ox)en', 'gi'),                                                      '$1'],
        [new RegExp('(vert|ind)ices$', 'gi'),                                              '$1ex'],
        [new RegExp('(matr)ices$', 'gi'),                                                  '$1ix'],
        [new RegExp('(quiz)zes$', 'gi'),                                                   '$1'],
        [new RegExp('s$', 'gi'),                                                           '']
    ],

    /*
      This is a list of words that should not be capitalized for title case
    */
    non_titlecased_words: [
        'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at',
        'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over',
        'with', 'for'
    ],

    /*
      These are regular expressions used for converting between String formats
    */
    id_suffix: new RegExp('(_ids|_id)$', 'g'),
    underbar: new RegExp('_', 'g'),
    space_or_underbar: new RegExp('[\ _]', 'g'),
    uppercase: new RegExp('([A-Z])', 'g'),
    underbar_prefix: new RegExp('^_'),
    
    /*
      This is a helper method that applies rules based replacement to a String
      Signature:
        InflectionJS.apply_rules(str, rules, skip, override) == String
      Arguments:
        str - String - String to modify and return based on the passed rules
        rules - Array: [RegExp, String] - Regexp to match paired with String to use for replacement
        skip - Array: [String] - Strings to skip if they match
        override - String (optional) - String to return as though this method succeeded (used to conform to APIs)
      Returns:
        String - passed String modified by passed rules
      Examples:
        InflectionJS.apply_rules("cows", InflectionJs.singular_rules) === 'cow'
    */
    apply_rules: function(str, rules, skip, override)
    {
        if (override)
        {
            str = override;
        }
        else
        {
            var ignore = (skip.indexOf(str.toLowerCase()) > -1);
            if (!ignore)
            {
                for (var x = 0; x < rules.length; x++)
                {
                    if (str.match(rules[x][0]))
                    {
                        str = str.replace(rules[x][0], rules[x][1]);
                        break;
                    }
                }
            }
        }
        return str;
    }
};

/*
  This lets us detect if an Array contains a given element
  Signature:
    Array.indexOf(item, fromIndex, compareFunc) == Integer
  Arguments:
    item - Object - object to locate in the Array
    fromIndex - Integer (optional) - starts checking from this position in the Array
    compareFunc - Function (optional) - function used to compare Array item vs passed item
  Returns:
    Integer - index position in the Array of the passed item
  Examples:
    ['hi','there'].indexOf("guys") === -1
    ['hi','there'].indexOf("hi") === 0
*/
if (!Array.prototype.indexOf)
{
    Array.prototype.indexOf = function(item, fromIndex, compareFunc)
    {
        if (!fromIndex)
        {
            fromIndex = -1;
        }
        var index = -1;
        for (var i = fromIndex; i < this.length; i++)
        {
            if (this[i] === item || compareFunc && compareFunc(this[i], item))
            {
                index = i;
                break;
            }
        }
        return index;
    };
}

/*
  You can override this list for all Strings or just one depending on if you
  set the new values on prototype or on a given String instance.
*/
if (!String.prototype._uncountable_words)
{
    String.prototype._uncountable_words = InflectionJS.uncountable_words;
}

/*
  You can override this list for all Strings or just one depending on if you
  set the new values on prototype or on a given String instance.
*/
if (!String.prototype._plural_rules)
{
    String.prototype._plural_rules = InflectionJS.plural_rules;
}

/*
  You can override this list for all Strings or just one depending on if you
  set the new values on prototype or on a given String instance.
*/
if (!String.prototype._singular_rules)
{
    String.prototype._singular_rules = InflectionJS.singular_rules;
}

/*
  You can override this list for all Strings or just one depending on if you
  set the new values on prototype or on a given String instance.
*/
if (!String.prototype._non_titlecased_words)
{
    String.prototype._non_titlecased_words = InflectionJS.non_titlecased_words;
}

/*
  This function adds plurilization support to every String object
    Signature:
      String.pluralize(plural) == String
    Arguments:
      plural - String (optional) - overrides normal output with said String
    Returns:
      String - singular English language nouns are returned in plural form
    Examples:
      "person".pluralize() == "people"
      "octopus".pluralize() == "octopi"
      "Hat".pluralize() == "Hats"
      "person".pluralize("guys") == "guys"
*/
if (!String.prototype.pluralize)
{
    String.prototype.pluralize = function(plural)
    {
        return InflectionJS.apply_rules(
            this,
            this._plural_rules,
            this._uncountable_words,
            plural
        );
    };
}

/*
  This function adds singularization support to every String object
    Signature:
      String.singularize(singular) == String
    Arguments:
      singular - String (optional) - overrides normal output with said String
    Returns:
      String - plural English language nouns are returned in singular form
    Examples:
      "people".singularize() == "person"
      "octopi".singularize() == "octopus"
      "Hats".singularize() == "Hat"
      "guys".singularize("person") == "person"
*/
if (!String.prototype.singularize)
{
    String.prototype.singularize = function(singular)
    {
        return InflectionJS.apply_rules(
            this,
            this._singular_rules,
            this._uncountable_words,
            singular
        );
    };
}

/*
  This function adds camelization support to every String object
    Signature:
      String.camelize(lowFirstLetter) == String
    Arguments:
      lowFirstLetter - boolean (optional) - default is to capitalize the first
        letter of the results... passing true will lowercase it
    Returns:
      String - lower case underscored words will be returned in camel case
        additionally '/' is translated to '::'
    Examples:
      "message_properties".camelize() == "MessageProperties"
      "message_properties".camelize(true) == "messageProperties"
*/
if (!String.prototype.camelize)
{
     String.prototype.camelize = function(lowFirstLetter)
     {
        var str = this.toLowerCase();
        var str_path = str.split('/');
        for (var i = 0; i < str_path.length; i++)
        {
            var str_arr = str_path[i].split('_');
            var initX = ((lowFirstLetter && i + 1 === str_path.length) ? (1) : (0));
            for (var x = initX; x < str_arr.length; x++)
            {
                str_arr[x] = str_arr[x].charAt(0).toUpperCase() + str_arr[x].substring(1);
            }
            str_path[i] = str_arr.join('');
        }
        str = str_path.join('::');
        return str;
    };
}

/*
  This function adds underscore support to every String object
    Signature:
      String.underscore() == String
    Arguments:
      N/A
    Returns:
      String - camel cased words are returned as lower cased and underscored
        additionally '::' is translated to '/'
    Examples:
      "MessageProperties".camelize() == "message_properties"
      "messageProperties".underscore() == "message_properties"
*/
if (!String.prototype.underscore)
{
     String.prototype.underscore = function()
     {
        var str = this;
        var str_path = str.split('::');
        for (var i = 0; i < str_path.length; i++)
        {
            str_path[i] = str_path[i].replace(InflectionJS.uppercase, '_$1');
            str_path[i] = str_path[i].replace(InflectionJS.underbar_prefix, '');
        }
        str = str_path.join('/').toLowerCase();
        return str;
    };
}

/*
  This function adds humanize support to every String object
    Signature:
      String.humanize(lowFirstLetter) == String
    Arguments:
      lowFirstLetter - boolean (optional) - default is to capitalize the first
        letter of the results... passing true will lowercase it
    Returns:
      String - lower case underscored words will be returned in humanized form
    Examples:
      "message_properties".humanize() == "Message properties"
      "message_properties".humanize(true) == "message properties"
*/
if (!String.prototype.humanize)
{
    String.prototype.humanize = function(lowFirstLetter)
    {
        var str = this.toLowerCase();
        str = str.replace(InflectionJS.id_suffix, '');
        str = str.replace(InflectionJS.underbar, ' ');
        if (!lowFirstLetter)
        {
            str = str.capitalize();
        }
        return str;
    };
}

/*
  This function adds capitalization support to every String object
    Signature:
      String.capitalize() == String
    Arguments:
      N/A
    Returns:
      String - all characters will be lower case and the first will be upper
    Examples:
      "message_properties".capitalize() == "Message_properties"
      "message properties".capitalize() == "Message properties"
*/
if (!String.prototype.capitalize)
{
    String.prototype.capitalize = function()
    {
        var str = this.toLowerCase();
        str = str.substring(0, 1).toUpperCase() + str.substring(1);
        return str;
    };
}

/*
  This function adds dasherization support to every String object
    Signature:
      String.dasherize() == String
    Arguments:
      N/A
    Returns:
      String - replaces all spaces or underbars with dashes
    Examples:
      "message_properties".capitalize() == "message-properties"
      "Message Properties".capitalize() == "Message-Properties"
*/
if (!String.prototype.dasherize)
{
    String.prototype.dasherize = function()
    {
        var str = this;
        str = str.replace(InflectionJS.space_or_underbar, '-');
        return str;
    };
}

/*
  This function adds titleize support to every String object
    Signature:
      String.titleize() == String
    Arguments:
      N/A
    Returns:
      String - capitalizes words as you would for a book title
    Examples:
      "message_properties".titleize() == "Message Properties"
      "message properties to keep".titleize() == "Message Properties to Keep"
*/
if (!String.prototype.titleize)
{
    String.prototype.titleize = function()
    {
        var str = this.toLowerCase();
        str = str.replace(InflectionJS.underbar, ' ');
        var str_arr = str.split(' ');
        for (var x = 0; x < str_arr.length; x++)
        {
            var d = str_arr[x].split('-');
            for (var i = 0; i < d.length; i++)
            {
                if (this._non_titlecased_words.indexOf(d[i].toLowerCase()) < 0)
                {
                    d[i] = d[i].capitalize();
                }
            }
            str_arr[x] = d.join('-');
        }
        str = str_arr.join(' ');
        str = str.substring(0, 1).toUpperCase() + str.substring(1);
        return str;
    };
}

/*
  This function adds demodulize support to every String object
    Signature:
      String.demodulize() == String
    Arguments:
      N/A
    Returns:
      String - removes module names leaving only class names (Ruby style)
    Examples:
      "Message::Bus::Properties".demodulize() == "Properties"
*/
if (!String.prototype.demodulize)
{
    String.prototype.demodulize = function()
    {
        var str = this;
        var str_arr = str.split('::');
        str = str_arr[str_arr.length - 1];
        return str;
    };
}

/*
  This function adds tableize support to every String object
    Signature:
      String.tableize() == String
    Arguments:
      N/A
    Returns:
      String - renders camel cased words into their underscored plural form
    Examples:
      "MessageBusProperty".tableize() == "message_bus_properties"
*/
if (!String.prototype.tableize)
{
    String.prototype.tableize = function()
    {
        var str = this;
        str = str.underscore().pluralize();
        return str;
    };
}

/*
  This function adds classification support to every String object
    Signature:
      String.classify() == String
    Arguments:
      N/A
    Returns:
      String - underscored plural nouns become the camel cased singular form
    Examples:
      "message_bus_properties".classify() == "MessageBusProperty"
*/
if (!String.prototype.classify)
{
    String.prototype.classify = function()
    {
        var str = this;
        str = str.camelize().singularize();
        return str;
    };
}

/*
  This function adds foreign key support to every String object
    Signature:
      String.foreign_key(dropIdUbar) == String
    Arguments:
      dropIdUbar - boolean (optional) - default is to seperate id with an
        underbar at the end of the class name, you can pass true to skip it
    Returns:
      String - camel cased singular class names become underscored with id
    Examples:
      "MessageBusProperty".foreign_key() == "message_bus_property_id"
      "MessageBusProperty".foreign_key(true) == "message_bus_propertyid"
*/
if (!String.prototype.foreign_key)
{
    String.prototype.foreign_key = function(dropIdUbar)
    {
        var str = this;
        str = str.demodulize().underscore() + ((dropIdUbar) ? ('') : ('_')) + 'id';
        return str;
    };
}

/*
  This function adds ordinalize support to every String object
    Signature:
      String.ordinalize() == String
    Arguments:
      N/A
    Returns:
      String - renders all found numbers their sequence like "22nd"
    Examples:
      "the 1 pitch".ordinalize() == "the 1st pitch"
*/
if (!String.prototype.ordinalize)
{
    String.prototype.ordinalize = function()
    {
        var str = this;
        var str_arr = str.split(' ');
        for (var x = 0; x < str_arr.length; x++)
        {
            var i = parseInt(str_arr[x]);
            if (i === NaN)
            {
                var ltd = str_arr[x].substring(str_arr[x].length - 2);
                var ld = str_arr[x].substring(str_arr[x].length - 1);
                var suf = "th";
                if (ltd != "11" && ltd != "12" && ltd != "13")
                {
                    if (ld === "1")
                    {
                        suf = "st";
                    }
                    else if (ld === "2")
                    {
                        suf = "nd";
                    }
                    else if (ld === "3")
                    {
                        suf = "rd";
                    }
                }
                str_arr[x] += suf;
            }
        }
        str = str_arr.join(' ');
        return str;
    };
}


================================================
FILE: models/README
================================================


================================================
FILE: package.json
================================================
{
  "name": "express-mvc-bootstrap",
  "description": "Express MVC Application Accelerator",
  "version": "0.1.2",
  "homepage": "http://cliftonc.github.com/express-mvc-bootstrap",
  "repository": {
    "type": "git",
    "url": "git://github.com/cliftonc/express-mvc-bootstrap.git"
  },
  "main":"bootstrap",
  "author": "Clifton Cunningham <clifton.cunningham@gmail.com> (cliftoncunningham.co.uk)",  
  "directories": {
    "lib": "./lib",
    "conf": "./conf",    
    "models": "./models",
    "controllers": "./controllers",
    "views": "./views",
    "public": "./public",
    "scripts": "./scripts",
    "utils": "./utils",    
    "tests": "./tests"    
  },
  "repository" :
             { "type" : "git"
             , "url" : "https://github.com/cliftonc/express-mvc-bootstrap.git"
  },  
  "engines" : { "node" : "0.4 || 0.5" },
  "dependencies" : { 
             "express" : ">=2.0.0beta3",
             "connect" : ">=1.0.3",
             "cluster" : ">=0.4.0",
             "ejs" : ">=0.3.1",
             "socket.io" : ">=0.6.16",
             "mongoose" : ">=1.1.3",
             "expresso" : ">=0.7.3",
             "should" : ">=0.0.4"              
  },
  "bin": { "eb": "./eb" }
                
}

================================================
FILE: public/css/Aristo/jquery-ui-1.8.7.custom.css
================================================
/*
 * jQuery UI CSS Framework 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 */

/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }


/* Icons
----------------------------------*/

/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }


/*
 * jQuery UI CSS Framework 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 *
 * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller
 */


/* Component containers
----------------------------------*/
.ui-widget { font-family: Helvetica,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Helvetica,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #B6B6B6; background: #ffffff; color: #4F4F4F; }
.ui-widget-content a { color: #4F4F4F; }
.ui-widget-header { border: 1px solid #B6B6B6; color: #4F4F4F; font-weight: bold; }
.ui-widget-header {
	background: url(images/bg_fallback.png) 0 0 repeat-x;
	background: -webkit-gradient(
		linear,
		left bottom,
		left top,
		color-stop(1, rgb(237,237,237)),
		color-stop(0, rgb(196,196,196))
	);
	background: -moz-linear-gradient(
		center top,
		rgb(237,237,237),
		rgb(196,196,196)
	);
}
.ui-widget-header a { color: #4F4F4F; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #B6B6B6; font-weight: normal; color: #4F4F4F; }
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { 
	background: url(images/bg_fallback.png) 0 0 repeat-x;
	background: -webkit-gradient(
    linear,
    left bottom,
    left top,
    color-stop(1, rgb(237,237,237)),
    color-stop(0, rgb(196,196,196))
	);
	background: -moz-linear-gradient(
		center top,
		rgb(237,237,237),
		rgb(196,196,196)
	);
	-webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
	-moz-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
}
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #4F4F4F; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #9D9D9D; font-weight: normal; color: #313131; }
.ui-state-hover a, .ui-state-hover a:hover { color: #313131; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { 
	outline: none;
	color: #1c4257; border: 1px solid #7096ab;
	background: url(images/bg_fallback.png) 0 -50px repeat-x;
	background: -webkit-gradient(
    linear,
    left bottom,
    left top,
    color-stop(1, rgb(185,224,245)),
    color-stop(0, rgb(146,189,214))
	);
	background: -moz-linear-gradient(
		center top,
		rgb(185,224,245),
		rgb(146,189,214)
	);
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
}
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #313131; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  { border: 1px solid #d2dbf4; background: #f4f8fd; color: #0d2054; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { border: 1px solid #e2d0d0; background: #fcf0f0; color: #280b0b; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }

/* Icons
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { background: url(images/icon_sprite.png) -16px 0 no-repeat !important; }
.ui-state-highlight .ui-icon, .ui-state-error .ui-icon { margin-top: -1px; }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background: url(images/icon_sprite.png) 0 0 no-repeat !important; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; }
.ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; }
.ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
.ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
.ui-corner-top { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; }
.ui-corner-bottom { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
.ui-corner-right {  -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
.ui-corner-left { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
.ui-corner-all { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; }

/* Overlays */
.ui-widget-overlay { background: #262b33; opacity: .70;filter:Alpha(Opacity=70); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #000000; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
 * jQuery UI Resizable 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Resizable#theming
 */
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
 * jQuery UI Selectable 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectable#theming
 */
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
 * jQuery UI Accordion 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Accordion#theming
 */
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-header, .ui-accordion .ui-accordion-content { -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 12px; font-weight: bold; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }/*
 * jQuery UI Autocomplete 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Autocomplete#theming
 */
.ui-autocomplete {
	position: absolute; cursor: default;
	-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
	-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
	-webkit-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
}	

/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */

/*
 * jQuery UI Menu 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Menu#theming
 */
.ui-menu {
	list-style:none;
	padding: 2px;
	margin: 0;
	display:block;
	float: left;
}
.ui-menu .ui-menu {
	margin-top: -3px;
}
.ui-menu .ui-menu-item {
	margin:0;
	padding: 0;
	zoom: 1;
	float: left;
	clear: left;
	width: 100%;
}
.ui-menu .ui-menu-item a {
	text-decoration:none;
	display:block;
	padding:.2em .4em;
	line-height:1.5;
	zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
	font-weight: normal;
	margin: -1px;
	background: #5f83b9;
	color: #FFFFFF;
	text-shadow: 0px 1px 1px #234386;
	border-color: #466086;
	-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
}
/*
 * jQuery UI Button 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button#theming
 */
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; } 
button.ui-button-icons-only { width: 3.7em; } 

/*states*/
.ui-button.ui-state-hover { 
	-moz-box-shadow: 0 0 8px rgba(0, 0, 0, 0.15), 0 1px 0 rgba(255,255,255,0.8) inset; 
	-webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 0.15), 0 1px 0 rgba(255,255,255,0.8) inset;
}
.ui-button.ui-state-focus {
	outline: none;
	color: #1c4257; border-color: #7096ab;
	background-image: -webkit-gradient(
    linear,
    left bottom,
    left top,
    color-stop(1, rgb(185,224,245)),
    color-stop(0, rgb(146,189,214))
	);
	background-image: -moz-linear-gradient(
		center top,
		rgb(185,224,245),
		rgb(146,189,214)
	);
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
}
 
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; font-size: 14px; font-weight: bold; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }

/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }

/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
.ui-buttonset .ui-button.ui-state-active { color: #1c4257; border-color: #7096ab; }
.ui-buttonset .ui-button.ui-state-active {
	background-image: -webkit-gradient(
    linear,
    left bottom,
    left top,
    color-stop(1, rgb(185,224,245)),
    color-stop(0, rgb(146,189,214))
	);
	background-image: -moz-linear-gradient(
		center top,
		rgb(185,224,245),
		rgb(146,189,214)
	);
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
}

/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*
 * jQuery UI Dialog 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Dialog#theming
 */
.ui-dialog { position: absolute; padding: 0; width: 300px; overflow: hidden; }
.ui-dialog {
	-webkit-box-shadow: 0 2px 12px rgba(0,0,0,0.6);
	-moz-box-shadow: 0 2px 12px rgba(0,0,0,0.6);
}
.ui-dialog .ui-dialog-titlebar { padding: 0.7em 1em 0.6em 1em; position: relative; border: none; border-bottom: 1px solid #979797; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;  }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; font-size: 14px; text-shadow: 0 1px 0 rgba(255,255,255,0.5); } 
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .8em; top: 55%; width: 16px; margin: -10px 0 0 0; padding: 0; height: 16px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; background: url(images/icon_sprite.png) 0 -16px no-repeat; }
.ui-dialog .ui-dialog-titlebar-close:hover span { background-position: -16px -16px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; border: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*
 * jQuery UI Slider 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Slider#theming
 */
.ui-slider { position: relative; text-align: left; background: #d7d7d7; }
.ui-slider { -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; }
.ui-slider .ui-slider-handle { background: url(images/slider_handles.png) 0px -23px no-repeat; position: absolute; z-index: 2; width: 23px; height: 23px; cursor: default; border: none; outline: none; -moz-box-shadow: none; -webkit-box-shadow: none; }
.ui-slider  .ui-state-hover, .ui-slider  .ui-state-active { background-position: 0 0; }
.ui-slider .ui-slider-range { background: #a3cae0; position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider .ui-slider-range { -moz-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; -webkit-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; }


.ui-slider-horizontal { height: 5px; }
.ui-slider-horizontal .ui-slider-handle { top: -8px; margin-left: -13px; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }

.ui-slider-vertical { width: 5px; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -8px; margin-left: 0; margin-bottom: -13px; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
 * jQuery UI Tabs 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Tabs#theming
 */
.ui-tabs { position: relative; zoom: 1; border: 0; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: 0; background: transparent; border-width: 0 0 1px 0; }
.ui-tabs .ui-tabs-nav { 
	-moz-border-radius: 0;
	-webkit-border-radius: 0;
	border-radius: 0;
}
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; font-size: 12px; font-weight: bold; text-shadow: 0 1px 0 rgba(255,255,255,0.5); }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; background: #fff; border-color: #B6B6B6; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; outline: none; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0 1px 1px 1px; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-panel { 
	-moz-border-radius: 0;
	-webkit-border-radius: 0;
	border-radius: 0;
}
.ui-tabs .ui-tabs-hide { display: none !important; }
/*
 * jQuery UI Datepicker 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Datepicker#theming
 */
.ui-datepicker { width: 17em; padding: 0; display: none; border-color: #DDDDDD; }
.ui-datepicker {
	-moz-box-shadow: 0 4px 8px rgba(0,0,0,0.5);
	-webkit-box-shadow: 0 4px 8px rgba(0,0,0,0.5);
	box-shadow: 0 4px 8px rgba(0,0,0,0.5);
}
.ui-datepicker .ui-datepicker-header { position:relative; padding:.35em 0; border: none; border-bottom: 1px solid #B6B6B6; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 6px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { border: 1px none; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev span { background-position: 0px -32px !important; }
.ui-datepicker .ui-datepicker-next span { background-position: -16px -32px !important; }
.ui-datepicker .ui-datepicker-prev-hover span { background-position: 0px -48px !important; }
.ui-datepicker .ui-datepicker-next-hover span { background-position: -16px -48px !important; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; background: url(images/icon_sprite.png) no-repeat; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; font-size: 12px; text-shadow: 0 1px 0 rgba(255,255,255,0.6); }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month, 
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
.ui-datepicker .ui-state-default { background: transparent; border-color: #FFF; }
.ui-datepicker .ui-state-active { background: #5F83B9; border-color: #5F83B9; color: #FFF; font-weight: bold; text-shadow: 0 1px 1px #234386; }

/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; }

/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }

/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
    display: none; /*sorry for IE5*/
    display/**/: block; /*sorry for IE5*/
    position: absolute; /*must have*/
    z-index: -1; /*must have*/
    filter: mask(); /*must have*/
    top: -4px; /*must have*/
    left: -4px; /*must have*/
    width: 200px; /*must have*/
    height: 200px; /*must have*/
}/*
 * jQuery UI Progressbar 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Progressbar#theming
 */
.ui-progressbar { height: 12px; text-align: left; background: url(images/progress_bar.gif) 0 -14px repeat-x; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; background: url(images/progress_bar.gif) 0 0 repeat-x; }

================================================
FILE: public/css/style.css
================================================
/*--- Reset ---*/
* { margin: 0; padding: 0; }

html, body { height: 100%; min-height: 100%; background-color: #000000; }

/*--- Layout ---*/
body {
	font-family: Helvetica, Arial, sans-serif;
	font-size: 14px;
	line-height: 1.5em;
	color: #0d0d0d;
	background-color: #fff;
}

#container {
	position: relative;
	padding: 10px 10%;
}

/*--- Basics ---*/
h1, h2, h3, h4, h5, h6 {
	font-weight:normal;
	color:#111;
	line-height: 1;
	margin: 1.5em 0 0.5em 0;
}
h1 { font-size: 1.6em; }
h2, h5 { font-size: 1.3em; color: #666; }
h3, h6 { font-size: 1.2em; color: #00a8e6; }
h4 { font-size: 1.1em; }
h5 { font-size: 1.1em; }
h6 { font-size: 1em; }
p { margin-bottom: 1em; }
strong { font-weight: bold; }
em { font-style: italic; }
a { text-decoration: none; color: #333; }
a, h1 a, h2 a { text-decoration: none; }
a:hover { color: #232323; }
a:visited:hover { color: #232323; }
a img { border: none; }

/*--- Lists ---*/
li ul, li ol { margin: 0; }
ul, ol { margin: 0 0 1em 2.75em; }
dt, dd {
	font-style: italic;
	margin: .5em 0;
}
dt {
	font-weight: bold;
}
dd {
	margin-left: 1em;
}
/*--- Header ---*/
#header h1 {
	margin: .1em 0;
	font-size: 2.2em;
}
#header h2 {
	width: 70%;
	margin: .5em .5em 2em 0;
	color: #666;
	font-size: 1.3em;
	line-height: 22px;
}

/*--- Tables ---*/
table {
	clear: both;
	width: 100%;
	border-collapse: collapse;
	border-spacing: 0;
	border: 1px solid #e6e6e6;
	background: #eaeafa;
	margin: 12px 0;
}
td, th {
	padding: .25em 1em;
	border: 1px solid #a6a6c6;
	vertical-align: middle;
	text-align: left;
	font-weight: normal;
	color: #333;
	font-size: 0.85em;
}

table tr {
	background: #fff;
}

table.tabular tr:nth-child(even) {
	background: #eaeafa;
}

tfoot td {
	background: #d3d3f3;
	color: #333;
	text-align: left;	
	padding: 1em 0.5em;
	font-size: 0.7em;
}

th {
	background: #d3d3f3;
	color: #333;
	text-align: left;
	font-weight: bold;
	padding: .5em .75em;
}
/*--- Forms ---*/
form {
	display: block;
	clear: both;
	background: #eaeafa;
	padding: 1em 2em 2em 2em;
	border: 1px solid #a6a6c6;
}
fieldset {
	padding: 2em;
	margin: 0 0 1em 0;
	border: 1px solid #a6a6c6;
	background: #f3f3f3;
}
legend {
	padding: .5em 1em;
	border: 1px solid #a6a6c6;
	background: #fff;
	font-size: 22px;
}
label {
	padding: 0 1em 0 0;
	color: #454545;
	font-weight: normal;
}
input[type=text],[type=password], textarea {
	font-family: Helvetica, Arial, sans-serif;
	padding: 2px 4px;
	border: 1px solid #a6a6c6;
	color: #454545;
	font-size: 1em;
	line-height: 1.25em;
}
input[type=text], input[type=password], textarea {
	clear: both;
	display: block;
	padding: .25em .5em;
}
input[type=text], input[type=password], textarea {
	width: 97%;
	max-width: 950px;
	margin: .5em 0 1em 0;
	padding:.5em;
}
select {
	clear: both;
	display: block;
	margin: .5em 0 1em 0;
}
div.checkbox {
	clear: both;
	padding: 1em 0;
}
.checkbox label {
	display: inline;
}

input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus {
	border-color: #00a8e6;
	outline: none;
}

/*--- Misc ---*/
hr {
	border: none;
	height: 0;
	border-bottom: 1px solid #e6e6e6;
	margin:1em 0;
}
sup, sub {
	color: #666;
	font-size: .65em;
}
acronym {
	font-weight: bold;
	font-style: italic;
	color: #333;
}
abbr {
	color: #333;
}

blockquote {
	padding: 0.15em .5em;
	margin: 0.5em 0;
	font-size: 2em;
	color: #666;	
	display: block;
	font-style: italic;
}

blockquote:before, blockquote:after {
	display: inline;
	color: #e5e5e5;
	font-size: 3em;
	position: relative;
	top: 0.25em;
	left: -0.1em;
}

blockquote:before {
	content: '\D \201C';
}


span.pager-page {
	font-family: Helvetica, Arial, sans-serif;
	padding: 3px 3px;
	margin: 3px 3px 3px 3px;
	color: #454545;	
	line-height: 1.25em;	
}

input.pager-page {
	display: inline !important; 
	width: 30px;
	font-family: Helvetica, Arial, sans-serif;
	padding: 2px 2px;
	margin: 3px 3px 3px 3px;
	color: #454545;	
	line-height: 1.25em;	
	clear: none;
}

a.pager-page {
	font-family: Helvetica, Arial, sans-serif;
	padding: 3px 3px;
	margin: 3px 3px 3px 3px;	
	border: 1px solid #a6a6c6;
	color: #454545;	
	line-height: 1.25em;
	background-color: #efefef;
}

blockquote:after {
	content: '\201D';
}

pre.code {
	padding: 10px;
	color: white;
	background-color: #883434;
	margin-top: 10px;	
}

/*--- Shadows ---*/
pre.code {
	-moz-box-shadow: 0 0 3px rgba(0,0,0,.1);
	-webkit-box-shadow: 0 0 3px rgba(0,0,0,.1);
	box-shadow: 0 0 3px rgba(0,0,0,.1);	
}
table, form {
	margin-top: 0px;
	margin-bottom: 12px;
}
table, form, pre > code, .shadow {
	-moz-box-shadow: 2px 2px 12px rgba(0,0,0,.15);
	-webkit-box-shadow: 2px 2px 12px rgba(0,0,0,0.15);
	box-shadow: 2px 2px 12px rgba(0,0,0,.15);
}
img.shadow {
	border: 1px solid rgba(255,255,255,.15);
}

input[type=text],input[type=password], textarea {
	-moz-box-shadow: inset 0 0 5px rgba(0,0,0,.2);
	-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,.2);
	box-shadow: inset 0 0 5px rgba(0,0,0,.2);
}

================================================
FILE: scripts/create-controller.js
================================================
var ejs = require('ejs')
   , fs = require('fs')
   , path = require('path')
   , inflection = require('../lib/inflection');

/** 
 * Script to create a default controller, requires the model to exist
 */
exports.execute = function(params,appPath) {
		 
	if(params.length == 0 ) {
		console.log("You must specifiy a model name to generate the controller against!");
		return;
	}
	
	/**
	 * Create the model based on a singular (e.g. people becomes person, users becomes user)
	 */
	var modelName = params[0].singularize();	
	if(modelName != params[0]) {
		console.log("Using model name as singular not plural: " + modelName);	
	}
	
	// Capitalise
	modelName = modelName.capitalize();	
	
	var modelFile = appPath + "/models/" + modelName + '.js'
	
	var controllerName = modelName.pluralize();
	
	var controllerFile = appPath + "/controllers/" + controllerName + 'Controller.js'
	var controllerTemplate = __dirname + '/templates/create-controller.template.ejs';
		
	// Check if the model exists
	var fileCheck = path.existsSync(modelFile);
	if(!fileCheck) {		
		console.log("The model you have specified doesn't exist!");
		console.log("You need to create the model first.");
		console.log("e.g. script create-model " + modelName);
		return;		
	}

	// Check if the controller exists
	var fileCheck = path.existsSync(controllerFile);
	if(fileCheck) {		
		if(params[1] != "force") {
			console.log("The controller already exists!");
			console.log("Add an additional paramater of 'force' to over write the controller.");
			console.log("e.g. script create-controller " + modelName + " force");
			return;
		}
	}

	
	// Read the template
	var str = fs.readFileSync(controllerTemplate, 'utf8');		
	
	// Render the model
	var ret = ejs.render(str, {
	  locals: {		
	    controllerName:controllerName,
	    modelName:modelName
	  },open: "<?",close: "?>"
	});
	
	// Write the file
	fs.writeFileSync(controllerFile, ret,'utf8');
	
	console.log('Controller for model ' + modelName + ' created in controllers/' + controllerName + 'Controller.js');
	
	
};

================================================
FILE: scripts/create-model.js
================================================
var ejs = require('ejs')
   , fs = require('fs')
   , path = require('path'),
   	 inflection = require('../lib/inflection');

/** 
 * Script to create a default model
 */
exports.execute = function(params,appPath) {
		 
	if(params.length == 0 ) {
		console.log("You must specifiy a model name.");
		return;
	}
	
	/**
	 * Create the model based on a singular (e.g. people becomes person, users becomes user)
	 */
	var modelName = params[0].singularize();	
	if(modelName != params[0]) {
		console.log("Creating model using singular not plural: " + modelName);	
	}
	
	// Capitalise
	modelName = modelName.capitalize();
	
	// Define the files
	var modelFile = appPath + "/models/" + modelName + '.js'
	var modelTemplate = __dirname + '/templates/create-model.template.ejs';
		
	// Check if it already exists
	var fileCheck = path.existsSync(modelFile);
	if(fileCheck) {		
		if(params[1] != "force") {
			console.log("The model already exists!");
			console.log("Add an additional paramater of 'force' to over write the model.");
			console.log("e.g. script create-model " + modelName + " force");
			return;
		}
	}
	
	// Read the template
	var str = fs.readFileSync(modelTemplate, 'utf8');		
	
	// Render the model
	var ret = ejs.render(str, {
	  locals: {
	    name:modelName
	  },open: "<?",close: "?>"
	});
	
	// Write the file
	fs.writeFileSync(modelFile, ret,'utf8');
	
	console.log('Model ' + modelName + ' created in models/' + modelName + '.js');
	
	
};

================================================
FILE: scripts/create-test.js
================================================
var  ejs = require('ejs')
   , fs = require('fs')
   , path = require('path')
   , inflection = require('../lib/inflection');


/** 
 * Script to create a default test scripts, requires the model to exist
 */
exports.execute = function(params,appPath) {
		 
	if(params.length == 0 ) {
		console.log("You must specifiy a model name to generate the tests against!");
		return;
	}
	
	/**
	 * Create the model based on a singular (e.g. people becomes person, users becomes user)
	 */
	var modelName = params[0].singularize();	
	if(modelName != params[0]) {
		console.log("Using model name as singular not plural: " + modelName);	
	}
	
	// Capitalise
	modelName = modelName.capitalize();	
	
	var modelFile = appPath + "/models/" + modelName + '.js'
	
	var controllerName = modelName.pluralize();
	
	var testFolder = appPath + "/tests/";
	
	var unitTemplate = __dirname + '/templates/create-test.template.unit.ejs';
	var integrationTemplate = __dirname + '/templates/create-test.template.integration.ejs';
	var functionalTemplate = __dirname + '/templates/create-test.template.functional.ejs';
		
	// Check if the model exists
	var fileCheck = path.existsSync(modelFile);
	if(!fileCheck) {		
		console.log("The model you have specified doesn't exist!");
		console.log("You need to create the model first.");
		console.log("e.g. script create-model " + modelName);
		return;		
	}

	// Check if the unit test exists 
	var fileCheck = path.existsSync(testFolder + "/unit/" + modelName + '.js');
	if(fileCheck) {		
		if(params[1] != "force") {
			console.log("Tests appear to already exist for this model!");
			console.log("Add an additional paramater of 'force' to over write the tests.");
			console.log("e.g. script create-test " + modelName + " force");
			return;
		}
	}
	
	// Read the template
	var tmpUnit = fs.readFileSync(unitTemplate, 'utf8');
	var tmpIntegration = fs.readFileSync(integrationTemplate, 'utf8');
	var tmpFunctional = fs.readFileSync(functionalTemplate, 'utf8');
	
	// Render the views
	var retUnit = ejs.render(tmpUnit, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	var retIntegration = ejs.render(tmpIntegration, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	var retFunctional = ejs.render(tmpFunctional, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	
	// Write the file
	fs.writeFileSync(testFolder + "/unit/" + modelName + '.js', retUnit,'utf8');
	fs.writeFileSync(testFolder + "/integration/" + controllerName + 'Controller.js', retIntegration,'utf8');
	fs.writeFileSync(testFolder + "/functional/" + modelName + '.js', retFunctional,'utf8');	
	
	console.log('Tests for ' + modelName + ' created in tests.');

	
};

================================================
FILE: scripts/create-view.js
================================================
var  ejs = require('ejs')
   , fs = require('fs')
   , path = require('path')
   , inflection = require('../lib/inflection');


/** 
 * Script to create a default view, requires the model to exist
 */
exports.execute = function(params,appPath) {
		 
	if(params.length == 0 ) {
		console.log("You must specifiy a model name to generate the views against!");
		return;
	}
	
	/**
	 * Create the model based on a singular (e.g. people becomes person, users becomes user)
	 */
	var modelName = params[0].singularize();	
	if(modelName != params[0]) {
		console.log("Using model name as singular not plural: " + modelName);	
	}
	
	// Capitalise
	modelName = modelName.capitalize();	
	
	var modelFile = appPath + "/models/" + modelName + '.js'
	
	var controllerName = modelName.pluralize();
	
	var viewFolder = appPath + "/views/" + controllerName.toLowerCase();
	
	var viewIndexTemplate = __dirname + '/templates/create-view.template.index.ejs';
	var viewEditTemplate = __dirname + '/templates/create-view.template.edit.ejs';
	var viewShowTemplate = __dirname + '/templates/create-view.template.show.ejs';
		
	// Check if the model exists
	var fileCheck = path.existsSync(modelFile);
	if(!fileCheck) {		
		console.log("The model you have specified doesn't exist!");
		console.log("You need to create the model first.");
		console.log("e.g. script create-model " + modelName);
		return;		
	}

	// Check if the view exists
	var fileCheck = path.existsSync(viewFolder);
	if(fileCheck) {		
		if(params[1] != "force") {
			console.log("The views folder already exists for this model!");
			console.log("Add an additional paramater of 'force' to over write the views.");
			console.log("e.g. script create-view " + modelName + " force");
			return;
		}
	} else {
		fs.mkdirSync(viewFolder,'755');
	}	
	
	// Read the template
	var tmpIndex = fs.readFileSync(viewIndexTemplate, 'utf8');
	var tmpEdit = fs.readFileSync(viewEditTemplate, 'utf8');
	var tmpShow = fs.readFileSync(viewShowTemplate, 'utf8');
	
	// Render the views
	var retIndex = ejs.render(tmpIndex, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	var retEdit = ejs.render(tmpEdit, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	var retShow = ejs.render(tmpShow, { locals: { modelName:modelName, controllerName:controllerName },open: "<?",close: "?>" });
	
	// Write the file
	fs.writeFileSync(viewFolder + "/index.html", retIndex,'utf8');
	fs.writeFileSync(viewFolder + "/edit.html", retEdit,'utf8');
	fs.writeFileSync(viewFolder + "/show.html", retShow,'utf8');	
	
	console.log('Views ' + modelName + ' created in views/' + modelName.toLowerCase());
	
	
};

================================================
FILE: scripts/generate-all.js
================================================
/** 
 * Script to create a model, controller and views
 */
exports.execute = function(params,appPath) {
		 
	if(params.length == 0 ) {
		console.log("You must specifiy a model name to generate all of the assets for!");
		return;
	}
	
	var modelScript = require('./create-model');	
	var controllerScript = require('./create-controller');
	var viewScript = require('./create-view');
	var testScript = require('./create-test');
	
	modelScript.execute(params,appPath);
	controllerScript.execute(params,appPath);
	viewScript.execute(params,appPath);
	testScript.execute(params,appPath);
	
};

================================================
FILE: scripts/help.js
================================================
var ejs = require('ejs')
   , fs = require('fs');

/** 
 * Help file
 */
exports.execute = function(params,appPath) {
		 		
		if(params.length == 0) {
			var str = fs.readFileSync(__dirname + '/templates/help.ejs', 'utf8');	
		} else {
			var str = fs.readFileSync(__dirname + '/templates/' + params[0] + '.help.ejs', 'utf8');
		}		

		var scripts = [];
		
		fs.readdir(__dirname + '/', function(err, files){		    
		    
			if(err) {
				console.log(err);
			}
			
			files.forEach(function(file){
			   if(file.replace('.js','') != file) {
				   scripts.push(file.replace('.js',''));
			   }		       	
		    });			
						
			var ret = ejs.render(str, {
			  locals: {
			    params: params,
			    scripts: scripts
			  },open: "<?",close: "?>"			  
			});
			
			console.log(ret);
		
		});		  
		
		
};

================================================
FILE: scripts/templates/create-controller.help.ejs
================================================

Express MVC Bootstrapper - Version 0.10
This is the help file for 'create-controller' command.

Command format:
node app.js script create-controller [MODELNAME]

[MODELNAME]  The name (case sensitive) for the model you want to create a controller for.
 

================================================
FILE: scripts/templates/create-controller.template.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
/**
 *  <?= controllerName ?> Controller
 *  Created by create-controller script @ <?= new Date() ?>
 **/
 var mongoose = require('mongoose'),	
	<?= modelName ?> = mongoose.model('<?= modelName ?>'),
	pager = require('../utils/pager.js'),
	ViewTemplatePath = '<?= basePathPlural ?>';

module.exports = {

	/**
	 * Index action, returns a list either via the views/<?= basePathPlural ?>/index.html view or via json
	 * Default mapping to GET '/<?= basePathPlural ?>'
	 * For JSON use '/<?= basePathPlural ?>.json'
	 **/
	index: function(req, res, next) {
		  	 
		  var from = req.params.from ? parseInt(req.params.from) - 1 : 0;
		  var to = req.params.to ? parseInt(req.params.to) : 10;
	      var total = 0;
	      
	      <?= modelName ?>.count({}, function (err, count) {
	    	total = count;  
	    	var pagerHtml = pager.render(from,to,total,'/<?= basePathPlural ?>');    	
	                  
			  <?= modelName ?>.find({})
			  	.sort('name', 1)
			  	.skip(from).limit(to)
			  	.find(function (err, <?= basePathPlural ?>) {
				
				  if(err) return next(err);
				  
			      switch (req.params.format) {
			        case 'json':	          
			          res.send(<?= basePathPlural ?>.map(function(u) {
			              return u.toObject();
			          }));
			          break;
		
			        default:			        	
			        	res.render(ViewTemplatePath,{<?= basePathPlural ?>:<?= basePathPlural ?>,pagerHtml:pagerHtml});
			      }
			      
			  });
	      
	      });
	      	  	
	},
	
	/**
	 * Show action, returns shows a single item via views/<?= basePathPlural ?>/show.html view or via json
	 * Default mapping to GET '/<?= basePath ?>/:id'
	 * For JSON use '/<?= basePath ?>/:id.json'
	 **/	
	show: function(req, res, next) {	  		  
			
		  <?= modelName ?>.findById(req.params.id, function(err, <?= modelVariable ?>) {
			  
			  if(err) return next(err);
			  
		      switch (req.params.format) {
		        case 'json':
		          res.send(<?= modelVariable ?>.toObject());
		          break;
	
		        default:
		        	res.render(ViewTemplatePath + "/show",{<?= modelVariable ?>:<?= modelVariable ?>});
		      }
		      
		  });
		      
	},
	
	/**
	 * Edit action, returns a form via views/<?= basePathPlural ?>/edit.html view no JSON view.
	 * Default mapping to GET '/<?= basePath ?>/:id/edit'
	 **/  	  
	edit: function(req, res, next){
		  <?= modelName ?>.findById(req.params.id, function(err, <?= modelVariable ?>) {
			  if(err) return next(err);
			  res.render(ViewTemplatePath + "/edit",{<?= modelVariable ?>:<?= modelVariable ?>});
		});
	},
	  
	/**
	 * Update action, updates a single item and redirects to Show or returns the object as json
	 * Default mapping to PUT '/<?= basePath ?>/:id', no GET mapping	 
	 **/  
	update: function(req, res, next){
	    
	    <?= modelName ?>.findById(req.params.id, function(err, <?= modelVariable ?>) {
	        
	    	if (!<?= modelVariable ?>) return next(err);
	        
	    	<?= modelVariable ?>.name = req.body.<?= modelVariable ?>.name;
	    	
	        <?= modelVariable ?>.save(function(err) {
	        
	    	  if (err) {
	    		  console.log(err);
	        	  req.flash('error','Could not update <?= modelVariable ?>: ' + err);
	          	  res.redirect('/<?= basePathPlural ?>');
	          	  return;
	    	  }
	    		
	          switch (req.params.format) {
	            case 'json':
	              res.send(<?= modelVariable ?>.toObject());
	              break;
	            default:
	              req.flash('info', '<?= modelName ?> updated');
	              res.redirect('/<?= modelVariable ?>/' + req.params.id);
	          }
	        });
	      });
	},
	  
	/**
	 * Create action, creates a single item and redirects to Show or returns the object as json
	 * Default mapping to POST '/<?= basePathPlural ?>', no GET mapping	 
	 **/  
	create: function(req, res, next){
		  
		  var <?= modelVariable ?> = new <?= modelName ?>(req.body.<?= modelVariable ?>);
		  
		  <?= modelVariable ?>.save(function(err) {
		   
			if (err) {
	    	  req.flash('error','Could not create <?= modelVariable ?>: ' + err);
	      	  res.redirect('/<?= basePathPlural ?>');
	      	  return;
			}
	
		    switch (req.params.format) {
		      case 'json':
		        res.send(<?= modelVariable ?>.toObject());
		        break;
	
		      default:
		    	  req.flash('info','<?= modelName ?> created');
		      	  res.redirect('/<?= modelVariable ?>/' + <?= modelVariable ?>.id);
			 }
		  });	  
		  
	},
	  
	/**
	 * Delete action, deletes a single item and redirects to index
	 * Default mapping to DEL '/<?= basePath ?>/:id', no GET mapping	 
	 **/ 
	destroy: function(req, res, next){
		  
		  <?= modelName ?>.findById(req.params.id, function(err, <?= modelVariable ?>) {
		        
		    	if (!<?= modelVariable ?>) { 
	  	    	  	req.flash('error','Unable to locate the <?= modelVariable ?> to delete!');
		    		res.send('false'); 
		    		return false; 
		    	};
		    		    
		    	<?= modelVariable ?>.remove(function(err) {
	    		  if(err) {
	    	    	  req.flash('error','There was an error deleting the <?= modelVariable ?>!');
	    			  res.send('false');
	    		  } else {
	    	    	  req.flash('info','<?= modelName ?> deleted');
	    			  res.send('true');
	    		  }    	          
	   	      	}); 
		  });
		  
	}
	
};

================================================
FILE: scripts/templates/create-model.help.ejs
================================================

Express MVC Bootstrapper - Version 0.10
This is the help file for 'create-model' command.

Command format:
node app.js script create-model [MODELNAME]

[MODELNAME]  The name (case sensitive) for the model you want to create.
 

================================================
FILE: scripts/templates/create-model.template.ejs
================================================
/**
 *  <?= name ?> schema
 *  Created by create-model script  
 **/
 
var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

var <?= name ?> = new Schema({

	  // Single default property
	  name:{type: String, required: true}
	  
});

mongoose.model('<?= name ?>', <?= name ?>);


================================================
FILE: scripts/templates/create-test.help.ejs
================================================

Express MVC Bootstrapper
This is the help file for 'create-test' command.

Command format:
node app.js script create-test [MODELNAME]

[MODELNAME]  The name (case sensitive) for the model you want to create tests for.
 

================================================
FILE: scripts/templates/create-test.template.functional.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
/**
 *  <?= controllerName ?> Functional Test
 *  Created by create-test script @ <?= new Date() ?>
 **/
/**
 * Dependencies
 */
var     should = require('should');

/**
 * Simple expresso tests for the <?= modelName ?> model
 */
module.exports = {
		    
  'Placeholder for a real functional test': function(){	    
	    true.should.be.true;    
   }

};

================================================
FILE: scripts/templates/create-test.template.integration.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
/**
 *  <?= controllerName ?> Integration Test
 *  Created by create-test script @ <?= new Date() ?>
 **/
/**
 * Dependencies
 */
var assert = require('assert'), inflection = require('lib/inflection'), mongoose = require('mongoose'), should = require('should'); 

/**
 * Variables to drive testing
 */
var model = '<?= modelName.toLowerCase() ?>';
var app = require('app').boot();
var id;

/**
 * Simple expresso tests for the AppController
 */
module.exports = {
		    
		'Shows an index page that contains the container name in the response with a 200 status code': function(done){	
			
			var controller = model.pluralize().toLowerCase();			
			assert.response(app, {
			    url: '/' + controller ,
			    method: 'GET'
			}, function(res) {
				res.statusCode.should.equal(200);
				res.body.should.include.string(controller);
			    done();
			});			
			
		},
		'Adding a new object returns a 302 redirect where the new location contains the id of the newly created object': function(done){			
			
			var controller = model.pluralize().toLowerCase();
			var data = model + '[name]=OriginalName';		
			
			assert.response(app, {
			    url: '/' + controller,
			    method: 'POST',
			    headers: {'host':'dummyhost','Content-Length': data.length,'Content-Type':'application/x-www-form-urlencoded'},
			    data: data
			}, function(res) {
				res.statusCode.should.equal(302);
				id = res.headers['location'].split("/")[res.headers['location'].split("/").length-1];				
				done();
			});	
						
		},
		'Viewing an existing object returns a page that contains the object ID and a 200 status code': function(done){									
			assert.response(app, {
			    url: '/' + model + '/' + id,
			    method: 'GET'
			}, function(res) {
				res.statusCode.should.equal(200);
				res.body.should.include.string(id);				
				done();
			});							
		},		
		'Viewing a page limited view of the index with .json format returns a JSON list containing the object ID and 200 status code': function(done){									

			var controller = model.pluralize().toLowerCase();

			assert.response(app, {
			    url: '/' + controller + '/1-100.json',   // Test database should be empty for this test
			    method: 'GET'
			}, function(res) {
				res.statusCode.should.equal(200);
				res.body.should.include.string(id);
				res.headers['content-type'].should.equal('application/json');
				done();
			});							
		},		
		'View existing object with .json format returns a JSON object containing its ID and a 200 status code ': function(done){									
			assert.response(app, {
			    url: '/' + model + '/' + id + '.json',
			    method: 'GET'
			}, function(res) {
				// Find the ID text on the page
				res.statusCode.should.equal(200);
				res.body.should.include.string(id);
				res.headers['content-type'].should.equal('application/json');				
				done();
			});							
		},
		'Updating an object redirects to 302 where the new location contains the ID': function(done){			
			
			var data = model + '[name]=ModifiedName';			
			assert.response(app, {
			    url: '/' + model + '/' + id,
			    method: 'PUT',
			    headers: {'host':'dummyhost','Content-Length': data.length,'Content-Type':'application/x-www-form-urlencoded'},
			    data: data
			}, function(res) {
				res.statusCode.should.equal(302);
				res.headers['location'].should.include.string(id);
				res.headers['location'].should.equal('http://dummyhost/' + model + '/' + id);				
				done();
			});	
						
		},
		'Viewing the updated object shows the modified data and a 200 status code': function(done){			
			
			assert.response(app, {
			    url: '/' + model + '/' + id,
			    method: 'GET'
			}, function(res) {				
				res.statusCode.should.equal(200);
				res.body.should.include.string(id);
				res.body.should.include.string('ModifiedName');
				done();
			});		
						
		},		
		'Deleting the object returns a 200 status code': function(done){			
			
			assert.response(app, {
			    url: '/' + model + '/' + id,
			    method: 'DELETE'
			}, function(res) {
				res.statusCode.should.equal(200);
				done();
			});		
						
		},
		'Viewing a deleted object returns the default error page': function(done){  // Should this really be a 404???			
			
			assert.response(app, {
			    url: '/' + model + '/' + id,
			    method: 'GET'
			}, function(res) {
				res.statusCode.should.equal(200);
				res.body.should.include.string('Sorry an error has occurred');
				done();
			});	
						
		},
		tearDown: function(done){
		   mongoose.disconnect();
		   done();
		}
		
};

================================================
FILE: scripts/templates/create-test.template.unit.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
/**
 *  <?= controllerName ?> Unit Test
 *  Created by create-test script @ <?= new Date() ?>
 **/
/**
 * Dependencies
 */
var     should = require('should')
	  , mongoose = require('mongoose')
	  , example = require('models/<?= modelName ?>')
	  , Schema = mongoose.Schema
	  , SchemaType = mongoose.SchemaType
	  , ValidatorError = SchemaType.ValidatorError
	  , DocumentObjectId = mongoose.Types.ObjectId
	  , MongooseError = mongoose.Error;

/**
 * Simple expresso tests for the <?= modelName ?> model
 */
module.exports = {
		    
  'Test that a model can be created': function(){
	    var <?= modelName ?> = mongoose.model('<?= modelName ?>');
	    var model = new <?= modelName ?>();
	    model.isNew.should.be.true;    
   },
  'Test that the model is an instance of a mongoose schema': function(){
    var <?= modelName ?> = mongoose.model('<?= modelName ?>');
    <?= modelName ?>.schema.should.be.an.instanceof(Schema);
    <?= modelName ?>.prototype.schema.should.be.an.instanceof(Schema);
  },
  'Test that an <?= modelName ?> has all of the default fields and values': function(){
    
    var <?= modelName ?> = mongoose.model('<?= modelName ?>');

    var model = new <?= modelName ?>();
    model.isNew.should.be.true;

    model.get('_id').should.be.an.instanceof(DocumentObjectId);
    should.equal(undefined, model.get('name'));
    
   },
  'Test that saving a record with invalid fields returns a validation error': function(){
	  
	    var <?= modelName ?> = mongoose.model('<?= modelName ?>');	    
	    var model = new <?= modelName ?>();
	    model.set('name', '');
	    model.save(function(err){
	      
	      err.should.be.an.instanceof(MongooseError);
	      err.should.be.an.instanceof(ValidatorError);
	      
	      model.set('name', 'I exist!');
	      model.save(function(err){
	        should.strictEqual(err, null);
	      });
	      
	    });	    

  }

};

================================================
FILE: scripts/templates/create-view.help.ejs
================================================

Express MVC Bootstrapper - Version 0.10
This is the help file for 'create-view' command.

Command format:
node app.js script create-view [MODELNAME]

[MODELNAME]  The name (case sensitive) for the model you want to create views for.
 

================================================
FILE: scripts/templates/create-view.template.edit.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
<h1>Editing <?= modelName ?> <%= <?= modelVariable ?>.name %></h1>
<%- partial('../messages') %>
<form method="post" action="/<?= modelVariable ?>/<%= <?= modelVariable ?>.id %>">
  <input type="hidden" name="_method" value="put" />
  <p>Name: <input type="text" name="<?= modelVariable ?>[name]", value="<%= <?= modelVariable ?>.name %>" /></p>
  <p>
  	<button class="button-submit" type="submit" value="Update">Save</button>
  	<a class="button-cancel" href="/<?= modelVariable ?>/<%= <?= modelVariable ?>.id %>">Cancel</a>
  </p>
</form>


================================================
FILE: scripts/templates/create-view.template.index.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
<h1><?= basePathPlural ?></h1>
<%- partial('../messages') %>
<div style="float: left; width: 60%;">
	<table class="tabular">
		<tr>
			<th>Name</th>
		</tr>
		<% <?= basePathPlural ?>.forEach(function(<?= modelVariable ?>){ %>
		<tr>
			<td><a href="/<?= modelVariable ?>/<%= <?= modelVariable ?>.id %>"><%= <?= modelVariable ?>.name %></a></td>
		</tr>
		<% }) %>
		<tfoot>
			<tr>
				<td colspan='2'><%- pagerHtml %></td>
			</tr>
		</tfoot>
	</table>
</div>
<div style="float: left; margin-left: 5%; width: 35%;">
	<form method="post" action="/<?= basePathPlural ?>">
		<input type="hidden" name="_method" value="post" />
		<p>
			Name: <input type="text" name="<?= modelVariable ?>[name]" />
		</p>
		<p>
			<button class="button-submit" type="submit" value="Create">Create</button>
		</p>
	</form>
</div>


================================================
FILE: scripts/templates/create-view.template.show.ejs
================================================
<?
	var modelVariable = modelName.toLowerCase();
	var basePath = modelName.toLowerCase();
	var basePathPlural = controllerName.toLowerCase();
?>
<h1>Viewing <?= basePath ?></h1>
<script type="text/javascript">
	$(function(){

		// Delete User
		$('.button-delete').click(function(){
			
			var <?= modelVariable ?>Id = this.id;
			
			$("#dialog-confirm" ).dialog({
				resizable: false,
				height:180,
				width:400,
				modal: true,
				buttons: {
					"Delete": function() {
						$( this ).dialog( "close" );
						$.ajax({
							   type: "DELETE",
							   url: "/<?= modelVariable ?>/" + <?= modelVariable ?>Id,				   
							   success: function(msg) {				   	  
								  window.location.replace("/<?= modelVariable ?>s");
							   },
							   error: function(msg) {					  
								  alert("I was unable to delete the <?= modelVariable ?> - something has gone wrong, apologies!");
							   }
						});
					},
					Cancel: function() {
						$( this ).dialog( "close" );
					}
				}
			});			
			
		});
		
	});
</script>
<div id="dialog-confirm" style="display: none;" title="Delete <?= modelVariable ?>?">
	<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>This will be permanently deleted and cannot be recovered. Are you sure?</p>
</div>
<%- partial('../messages') %>
<table>
	<tr>
  		<th>ID</th><td><%= <?= modelVariable ?>.id %></td>
  	</tr>
  	<tr>
  		<th>Name</th><td><%= <?= modelVariable ?>.name %></td>
  	</tr> 	
</table>
<a class="button-edit" href="<%= <?= modelVariable ?>.id %>/edit" title="Edit <?= modelVariable ?> ...">
	Edit 
</a>
<button class="button-delete" id="<%= <?= modelVariable ?>.id %>"  title="Delete <?= modelVariable ?> ...">
	Delete
</button>
<a class="button-home" href="/<?= basePathPlural ?>" title="List <?= controllerName ?>">
	List <?= controllerName ?>
</a>


================================================
FILE: scripts/templates/help.ejs
================================================

Express MVC Bootstrapper

This is the help file for the Express based application bootstrapper.  Parameters marked with * are optional, and are shown with their defaults.

Command format:

eb                                   : Run the application using the cluster module.
eb cluster *server.port=3000         : Run the application using the cluster module.
eb server *server.port=3000          : Run the application as a server.

eb test                              : Run all tests.
eb test unit|integration|functional  : Run a particular type of test.

eb script help *<name>               : This help script, optional script name for additional help. 
eb script <name> *params             : Run a script with <name>, with params.
eb script <name> *params             : Run a script with <name>, with params.

Available scripts:
<? if (scripts.length) { scripts.forEach(function(name){ ?>
<?= name ?><? }) } ?>


================================================
FILE: tests/functional/README
================================================


================================================
FILE: tests/functional/SampleTests.js
================================================
/**
 * Dependencies
 */
var     should = require('should');

/**
 * Simple expresso tests for the Example model
 */
module.exports = {
		    
  'Placeholder for a real functional test': function(){	    
	    true.should.be.true;    
   }

};

================================================
FILE: tests/integration/AppControllerTests.js
================================================

var assert = require('assert'), should = require('should'), mongoose = require('mongoose');
var app = require('app').boot();

/**
 * Simple expresso tests for the AppController
 */
module.exports = {
		
		'Default route shows the home page with a 200 status code': function(done){									
			assert.response(app, {
			    url: '/',
			    method: 'GET'
			}, function(res) {
				res.statusCode.should.equal(200);
				res.body.should.include.string('Welcome!');
			    done();
			});						
		},
		'An invalid route shows the 404 Error page': function(done){			
			assert.response(app, {
			    url: '/this/is/an/invalid/route',
			}, function(res){
				res.statusCode.should.equal(200);
				res.body.should.include.string('Cannot find /this/is/an/invalid/route');		
				done();
			});						
		},
		tearDown: function(done){
		   mongoose.disconnect();
		   done();
		}
		
};

================================================
FILE: tests/unit/README
================================================


================================================
FILE: tests/unit/SampleTests.js
================================================
/**
 * Dependencies
 */
var     should = require('should');

/**
 * Simple expresso tests
 */
module.exports = {
		    
  'Placeholder for a real unit test': function(){	    
	    true.should.be.true;    
   }

};

================================================
FILE: utils/pager.js
================================================

/**
 * Simple pager - couldn't find one for Express that worked for me.
 */
exports.version = '0.0.1';
exports.render = function(skip,limit,total,path){

	var totalPages = Math.ceil(total/limit) + 1;
	var currentPage = skip/limit + 1;
	var result = "", start, finish;
	var selectedClass = 'page-selected';
	var visiblePages = 5;
	
	// Remember how many we have
	var totalPageLinks = 0;
	
	result += pageSpan(currentPage);
		
	var additionalForward = currentPage < visiblePages ? visiblePages - currentPage : 0;	
	for(i=currentPage + 1; (i < currentPage + visiblePages + additionalForward) && (i < totalPages); i++) {
		start = (i-1)*limit + 1;
		result += pageLink(path,start,limit,i); 		
	}
	
	if(currentPage < totalPages - 1) {
		result +=pageLink(path,skip + limit + 1,limit,">"); 				
		var lastPageStart = (totalPages-2)*limit + 1;
		result +=pageLink(path,lastPageStart,limit,">>"); 		
	}
	
	var additionalBackward = (totalPages - currentPage) < visiblePages ? visiblePages - (totalPages - currentPage) : 0;
	for(i=currentPage - 1; (i > currentPage - visiblePages - additionalBackward) && (i > 0); i--) {
		start = (i-1)*limit + 1;		
		
		result = pageLink(path,start,limit,i) + result;
	}
	
	if(currentPage > 1) {
		result = pageLink(path,(skip - limit + 1),limit,"<") + result;
		result = pageLink(path,1,limit,"<<") + result;			
	}
	
	result += "&nbsp;Go To: <input id='pagerGoto' type='text' name='skip' value='' class='pager-page' title='Go to a specific start point, type and enter ...' />";
	
	result += "<span style='float: right'>" + (skip + 1) + " to " + (skip + limit) + " of " + (total) + "</span>";		
	
	return result
	
}

function pageLink(path,skip,limit,page) {
	return "<a class='pager-page' href='" + path + "/" + skip + "-" + limit + "'>" + page + "</a>";
}

function pageSpan(page) {
	return "<span class='pager-page'>" + page + "</span>";
}


================================================
FILE: utils/socketio.js
================================================

/**
 * 	NOT YET USED 
 **/		
		
var io = require('socket.io');

exports.version = '0.0.1';
exports.initialise = function(app){

	// socket.io 
	var socket = io.listen(app); 
	socket.on('connection', function(client){ 
	  // new client is here! 
	  console.log("Connection: " . client);
	  client.on('message', function(){ 
		console.log("message");	
	  }); 
	  client.on('disconnect', function(){ 
		console.log("disconnect")
	  }); 
	});
	
};

================================================
FILE: views/404.html
================================================
<h1>Cannot find <%= request.url %></h1>
<p>Sorry we failed to locate this page or resource.</p>

================================================
FILE: views/500.html
================================================
<h1>Internal Server Error</h1>
<p>Sorry an error has occurred, please try refreshing the page or navigate back to <a href="/">home</a>.</p>

================================================
FILE: views/app/index.html
================================================
<h1>Welcome!</h1>
<p>The following controllers are available:</p>

<% if (controllers.length) { %>
  <ul>
    <% controllers.forEach(function(controller){ %>
      <li><a href="/<%= controller %>"><%= controller %></a></li>
    <% }) %>
  </ul>
<% } else { %>
<pre class='code'>
No controllers available - try 'eb script generate-all ModelName'
</pre>
<% } %>
<br/>
<pre class='code'>
You are viewing the default home page - edit views/app/index.html to edit this page!
</pre>
<br/>
<p>Credits:
<div style='font-size: 0.8em;'>
	<ul>
		<li><a href="http://nodejs.org/">Node.js</a>: Amazing javascript asynchronous IO library, install manually.</li>
		<li><a href="http://www.mongodb.org/">MongoDB</a>: NoSQL Database, install manually.</li>
		<li><a href="http://npmjs.org/">NPM</a>: Node package manager, used to install:
			<ul>
				<li><a href="http://expressjs.com/">Express</a>: Application Framework for Node.js</li>
				<li><a href="http://mongoosejs.com/">Mongoose</a>: Node.JS ORM for Mongo</li>
				<li><a href="http://embeddedjs.com/">EJS</a>: Embedded Javascript Templating Library</li>
			</ul>
		</li>
		<li><a href="http://jquery.com/">jQuery</a>: Javascript Library</li>
		<li><a href="http://jqueryui.com/">jQuery UI</a>: UI Library</li>
		<li><a href="http://taitems.tumblr.com/post/482577430/introducing-aristo-a-jquery-ui-theme">jQuery Aristo Template</a>: Fantastic looking jQuery UI Template.</li>
	</ul>
</div>
</p>


<p>Contact me via github : <a href="https://github.com/cliftonc" target="_new">Clifton @ Github</a></p>


================================================
FILE: views/layout.html
================================================
<html>
  <head>
    <title>Sample MVC Application</title>
    	<link rel="stylesheet" href="/css/style.css" />
    	<link type="text/css" href="/css/Aristo/jquery-ui-1.8.7.custom.css" rel="stylesheet" />	
		<script type="text/javascript" src="/js/jquery-1.4.4.min.js"></script>
		<script type="text/javascript" src="/js/jquery-ui-1.8.10.custom.min.js"></script>
		<script type="text/javascript">
			$(function(){
		
				// Style default buttons
				// TODO: Move this into an application js library
				$(".button-edit").button({ icons: {	primary: 'ui-icon-wrench' }	});
				$(".button-delete").button({ icons: { primary: 'ui-icon-trash' } });
				$(".button-home").button({ icons: {	primary: 'ui-icon-home'	} });
				$(".button-submit").button({ icons: { primary: 'ui-icon-disk' } });
				$(".button-cancel").button({ icons: {primary: 'ui-icon-close' } });
				
			});
			
		</script>
  </head>
  <body>  	
  	<div id="container">
	  	<div id="header">
			<h1><a href="/">Node.js + ExpressJs + Mongoose : Bootstrap</a></h1>
  			<h2>Simple Application Template and Scripts</h2>
		</div>
		<div id="content">
    		<%- body %>
    	</div>		
    </div>
  </body>
</html>

================================================
FILE: views/messages.html
================================================
<% if (hasMessages) { %>
  <div style="float: left; margin-bottom: 20px; padding: 10px; width: 100%;" class="ui-state-highlight ui-corner-all">  	
    <% messages().forEach(function(msg){ %>
      <span class="ui-icon ui-icon-info" style="float: left; margin-right: .7em;"></span><%- msg %><br/>
    <% }) %>
  </div>
  <div style="clear: both;"/>
<% } %>
Download .txt
gitextract_1e56a2is/

├── .npmignore
├── .project
├── README.md
├── app-cluster.js
├── app.js
├── conf/
│   ├── configuration.js
│   ├── development.js
│   ├── production.js
│   └── test.js
├── controllers/
│   └── AppController.js
├── eb
├── lib/
│   ├── AppController.js
│   ├── ExamplesController.js
│   ├── README
│   └── inflection.js
├── models/
│   └── README
├── package.json
├── public/
│   └── css/
│       ├── Aristo/
│       │   └── jquery-ui-1.8.7.custom.css
│       └── style.css
├── scripts/
│   ├── create-controller.js
│   ├── create-model.js
│   ├── create-test.js
│   ├── create-view.js
│   ├── generate-all.js
│   ├── help.js
│   └── templates/
│       ├── create-controller.help.ejs
│       ├── create-controller.template.ejs
│       ├── create-model.help.ejs
│       ├── create-model.template.ejs
│       ├── create-test.help.ejs
│       ├── create-test.template.functional.ejs
│       ├── create-test.template.integration.ejs
│       ├── create-test.template.unit.ejs
│       ├── create-view.help.ejs
│       ├── create-view.template.edit.ejs
│       ├── create-view.template.index.ejs
│       ├── create-view.template.show.ejs
│       └── help.ejs
├── tests/
│   ├── functional/
│   │   ├── README
│   │   └── SampleTests.js
│   ├── integration/
│   │   └── AppControllerTests.js
│   └── unit/
│       ├── README
│       └── SampleTests.js
├── utils/
│   ├── pager.js
│   └── socketio.js
└── views/
    ├── 404.html
    ├── 500.html
    ├── app/
    │   └── index.html
    ├── layout.html
    └── messages.html
Download .txt
SYMBOL INDEX (11 symbols across 4 files)

FILE: app.js
  function bootApplication (line 36) | function bootApplication(app) {
  function bootModels (line 87) | function bootModels(app) {
  function bootControllers (line 102) | function bootControllers(app) {
  function bootModel (line 117) | function bootModel(app, file) {
  function bootController (line 125) | function bootController(app, file) {

FILE: controllers/AppController.js
  function router (line 26) | function router(req, res, next) {
  function index (line 98) | function index(req, res, next) {

FILE: lib/AppController.js
  function router (line 26) | function router(req, res, next) {
  function index (line 95) | function index(req, res, next) {

FILE: utils/pager.js
  function pageLink (line 51) | function pageLink(path,skip,limit,page) {
  function pageSpan (line 55) | function pageSpan(page) {
Condensed preview — 50 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (141K chars).
[
  {
    "path": ".npmignore",
    "chars": 21,
    "preview": "*.sock\nlogs/*\npids/*\n"
  },
  {
    "path": ".project",
    "chars": 214,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>express-mvc-bootstrap</name>\n\t<comment></comment>\n\t<p"
  },
  {
    "path": "README.md",
    "chars": 3914,
    "preview": "\n# THIS PROJECT IS NO LONGER MAINTAINED, TRY THIS ONE:  https://github.com/niftylettuce/eskimo\n\n# Express MVC Bootstrap\n"
  },
  {
    "path": "app-cluster.js",
    "chars": 1097,
    "preview": "/**\n * Module dependencies.\n */\nvar cluster = require('cluster');\nvar app;\n\n/**\n * Initial bootstrapping\n */\nexports.boo"
  },
  {
    "path": "app.js",
    "chars": 3367,
    "preview": "/**\n * Module dependencies.\n */\nvar fs = require('fs'),express = require('express'),\n\t mongoose = require('mongoose'), n"
  },
  {
    "path": "conf/configuration.js",
    "chars": 431,
    "preview": "\n/**\n * Default configuration manager\n * Inject app and express reference\n */\nmodule.exports = function(app,express) {\n\t"
  },
  {
    "path": "conf/development.js",
    "chars": 238,
    "preview": "\n/**\n * DEVELOPMENT Environment settings\n */\nmodule.exports = function(app,express) {\n\t\t\n\tapp.set('db-uri', 'mongodb://l"
  },
  {
    "path": "conf/production.js",
    "chars": 223,
    "preview": "\n/**\n * TEST Environment settings\n */\nmodule.exports = function(app,express) {\n\t\t\n\tapp.set('db-uri', 'mongodb://localhos"
  },
  {
    "path": "conf/test.js",
    "chars": 230,
    "preview": "\n/**\n * PRODUCTION Environment settings\n */\nmodule.exports = function(app,express) {\n\t\t\n\tapp.set('db-uri', 'mongodb://lo"
  },
  {
    "path": "controllers/AppController.js",
    "chars": 2759,
    "preview": "var fs = require('fs')\n\t, inflection = require('../lib/inflection');\n\nmodule.exports = function(app) {\n\t\n\t// app.get(\"/f"
  },
  {
    "path": "eb",
    "chars": 7985,
    "preview": "#!/usr/bin/env node\n\n/**\n * ExpressJs MVC Bootstrap\n * @Params - cmd - serve\n r | script | params\n */\n \n \n/**\n * Framewo"
  },
  {
    "path": "lib/AppController.js",
    "chars": 2706,
    "preview": "var fs = require('fs')\n\t, inflection = require('../lib/inflection');\n\nmodule.exports = function(app) {\n\t\n\t// app.get(\"/f"
  },
  {
    "path": "lib/ExamplesController.js",
    "chars": 4773,
    "preview": "\n/**\n *  Examples Controller\n *  Created by create-controller script @ Fri Mar 11 2011 21:16:50 GMT+0000 (GMT)\n **/\n var"
  },
  {
    "path": "lib/README",
    "chars": 144,
    "preview": "Place any dependent libraries in here\n\n\n* inflection.js : http://code.google.com/p/inflection-js/\n\n    Modified to remov"
  },
  {
    "path": "lib/inflection.js",
    "chars": 22686,
    "preview": "/*\nCopyright (c) 2010 Ryan Schuft (ryan.schuft@gmail.com)\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "models/README",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "package.json",
    "chars": 1219,
    "preview": "{\n  \"name\": \"express-mvc-bootstrap\",\n  \"description\": \"Express MVC Application Accelerator\",\n  \"version\": \"0.1.2\",\n  \"ho"
  },
  {
    "path": "public/css/Aristo/jquery-ui-1.8.7.custom.css",
    "chars": 37489,
    "preview": "/*\n * jQuery UI CSS Framework 1.8.7\n *\n * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under"
  },
  {
    "path": "public/css/style.css",
    "chars": 4896,
    "preview": "/*--- Reset ---*/\n* { margin: 0; padding: 0; }\n\nhtml, body { height: 100%; min-height: 100%; background-color: #000000; "
  },
  {
    "path": "scripts/create-controller.js",
    "chars": 2043,
    "preview": "var ejs = require('ejs')\n   , fs = require('fs')\n   , path = require('path')\n   , inflection = require('../lib/inflectio"
  },
  {
    "path": "scripts/create-model.js",
    "chars": 1458,
    "preview": "var ejs = require('ejs')\n   , fs = require('fs')\n   , path = require('path'),\n   \t inflection = require('../lib/inflecti"
  },
  {
    "path": "scripts/create-test.js",
    "chars": 2776,
    "preview": "var  ejs = require('ejs')\n   , fs = require('fs')\n   , path = require('path')\n   , inflection = require('../lib/inflecti"
  },
  {
    "path": "scripts/create-view.js",
    "chars": 2697,
    "preview": "var  ejs = require('ejs')\n   , fs = require('fs')\n   , path = require('path')\n   , inflection = require('../lib/inflecti"
  },
  {
    "path": "scripts/generate-all.js",
    "chars": 586,
    "preview": "/** \n * Script to create a model, controller and views\n */\nexports.execute = function(params,appPath) {\n\t\t \n\tif(params.l"
  },
  {
    "path": "scripts/help.js",
    "chars": 806,
    "preview": "var ejs = require('ejs')\n   , fs = require('fs');\n\n/** \n * Help file\n */\nexports.execute = function(params,appPath) {\n\t\t"
  },
  {
    "path": "scripts/templates/create-controller.help.ejs",
    "chars": 254,
    "preview": "\nExpress MVC Bootstrapper - Version 0.10\nThis is the help file for 'create-controller' command.\n\nCommand format:\nnode ap"
  },
  {
    "path": "scripts/templates/create-controller.template.ejs",
    "chars": 5469,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-model.help.ejs",
    "chars": 227,
    "preview": "\nExpress MVC Bootstrapper - Version 0.10\nThis is the help file for 'create-model' command.\n\nCommand format:\nnode app.js "
  },
  {
    "path": "scripts/templates/create-model.template.ejs",
    "chars": 324,
    "preview": "/**\n *  <?= name ?> schema\n *  Created by create-model script  \n **/\n \nvar mongoose = require('mongoose'),\n    Schema = "
  },
  {
    "path": "scripts/templates/create-test.help.ejs",
    "chars": 220,
    "preview": "\nExpress MVC Bootstrapper\nThis is the help file for 'create-test' command.\n\nCommand format:\nnode app.js script create-te"
  },
  {
    "path": "scripts/templates/create-test.template.functional.ejs",
    "chars": 500,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-test.template.integration.ejs",
    "chars": 4680,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-test.template.unit.ejs",
    "chars": 2039,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-view.help.ejs",
    "chars": 235,
    "preview": "\nExpress MVC Bootstrapper - Version 0.10\nThis is the help file for 'create-view' command.\n\nCommand format:\nnode app.js s"
  },
  {
    "path": "scripts/templates/create-view.template.edit.ejs",
    "chars": 687,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-view.template.index.ejs",
    "chars": 956,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/create-view.template.show.ejs",
    "chars": 1853,
    "preview": "<?\n\tvar modelVariable = modelName.toLowerCase();\n\tvar basePath = modelName.toLowerCase();\n\tvar basePathPlural = controll"
  },
  {
    "path": "scripts/templates/help.ejs",
    "chars": 916,
    "preview": "\nExpress MVC Bootstrapper\n\nThis is the help file for the Express based application bootstrapper.  Parameters marked with"
  },
  {
    "path": "tests/functional/README",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/functional/SampleTests.js",
    "chars": 241,
    "preview": "/**\n * Dependencies\n */\nvar     should = require('should');\n\n/**\n * Simple expresso tests for the Example model\n */\nmodu"
  },
  {
    "path": "tests/integration/AppControllerTests.js",
    "chars": 875,
    "preview": "\nvar assert = require('assert'), should = require('should'), mongoose = require('mongoose');\nvar app = require('app').bo"
  },
  {
    "path": "tests/unit/README",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/unit/SampleTests.js",
    "chars": 213,
    "preview": "/**\n * Dependencies\n */\nvar     should = require('should');\n\n/**\n * Simple expresso tests\n */\nmodule.exports = {\n\t\t    \n"
  },
  {
    "path": "utils/pager.js",
    "chars": 1869,
    "preview": "\n/**\n * Simple pager - couldn't find one for Express that worked for me.\n */\nexports.version = '0.0.1';\nexports.render ="
  },
  {
    "path": "utils/socketio.js",
    "chars": 444,
    "preview": "\n/**\n * \tNOT YET USED \n **/\t\t\n\t\t\nvar io = require('socket.io');\n\nexports.version = '0.0.1';\nexports.initialise = functio"
  },
  {
    "path": "views/404.html",
    "chars": 95,
    "preview": "<h1>Cannot find <%= request.url %></h1>\n<p>Sorry we failed to locate this page or resource.</p>"
  },
  {
    "path": "views/500.html",
    "chars": 139,
    "preview": "<h1>Internal Server Error</h1>\n<p>Sorry an error has occurred, please try refreshing the page or navigate back to <a hre"
  },
  {
    "path": "views/app/index.html",
    "chars": 1544,
    "preview": "<h1>Welcome!</h1>\n<p>The following controllers are available:</p>\n\n<% if (controllers.length) { %>\n  <ul>\n    <% control"
  },
  {
    "path": "views/layout.html",
    "chars": 1169,
    "preview": "<html>\n  <head>\n    <title>Sample MVC Application</title>\n    \t<link rel=\"stylesheet\" href=\"/css/style.css\" />\n    \t<lin"
  },
  {
    "path": "views/messages.html",
    "chars": 355,
    "preview": "<% if (hasMessages) { %>\n  <div style=\"float: left; margin-bottom: 20px; padding: 10px; width: 100%;\" class=\"ui-state-hi"
  }
]

About this extraction

This page contains the full source code of the cliftonc/express-mvc-bootstrap GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 50 files (127.0 KB), approximately 36.1k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!