Comparar commits
22 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| bf596dc023 | |||
| 220d88d654 | |||
| a254e64bdb | |||
| 1555b92fb8 | |||
| d5b7a40b39 | |||
| bd1ab7ab96 | |||
| 2ff991bfcf | |||
| 0b1378a539 | |||
| 723c908bd7 | |||
| 4874404701 | |||
| 4c1374840a | |||
| 5da01633fd | |||
| cdbd8af527 | |||
| a6fdc1bfd2 | |||
| 20b8facb05 | |||
| 909914f7af | |||
| 3f31ebc676 | |||
| f3c068a90c | |||
| 90d7e193d1 | |||
| c9f5bb6f17 | |||
| 9865a4c4f2 | |||
| f12baf32d4 |
@@ -1,4 +1,26 @@
|
||||
|
||||
2.0.0 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Fixed up index view path alternative.
|
||||
* Changed; `res.locals()` without object returns the locals
|
||||
|
||||
2.0.0rc3 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Added `res.locals(obj)` to compliment `res.local(key, val)`
|
||||
* Added `res.partial()` callback support
|
||||
* Fixed recursive error reporting issue in `res.render()`
|
||||
|
||||
2.0.0rc2 / 2011-03-17
|
||||
==================
|
||||
|
||||
* Changed; `partial()` "locals" are now optional
|
||||
* Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
|
||||
* Fixed .filename view engine option [reported by drudge]
|
||||
* Fixed blog example
|
||||
* Fixed `{req,res}.app` reference when mounting [Ben Weaver]
|
||||
|
||||
2.0.0rc / 2011-03-14
|
||||
==================
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ var fs = require('fs')
|
||||
* Framework version.
|
||||
*/
|
||||
|
||||
var version = '2.0.0rc';
|
||||
var version = '2.0.0';
|
||||
|
||||
/**
|
||||
* Add session support.
|
||||
|
||||
+26
-5
@@ -523,15 +523,15 @@ A good example of this is specifying custom _ejs_ opening and closing tags:
|
||||
### View Partials
|
||||
|
||||
The Express view system has built-in support for partials and collections, which are "mini" views representing a document fragment. For example rather than iterating
|
||||
in a view to display comments, we would use a partial with collection support:
|
||||
in a view to display comments, we could use partial collection:
|
||||
|
||||
partial('comment', { collection: comments });
|
||||
|
||||
If no other options are desired, we can omit the object and simply pass our array, which is equivalent to above:
|
||||
If no other options or local variables are desired, we can omit the object and simply pass our array, which is equivalent to above:
|
||||
|
||||
partial('comment', comments);
|
||||
|
||||
When using the partial collection support a few "magic" variables are provided
|
||||
When using the partial collection support a few "magic" locals are provided
|
||||
for free:
|
||||
|
||||
* _firstInCollection_ true if this is the first object
|
||||
@@ -938,7 +938,7 @@ of _movie.director_ we could use _this.director_.
|
||||
partial('movie', { collection: movies, as: this });
|
||||
// In view: this.director
|
||||
|
||||
Another alternative is to "explode" the properties of the collection item into
|
||||
Another alternative is to "expand" the properties of the collection item into
|
||||
pseudo globals (local variables) by using _as: global_, which again is syntactic sugar:
|
||||
|
||||
partial('movie', { collection: movies, as: global });
|
||||
@@ -960,9 +960,21 @@ This same logic applies to a single partial object usage:
|
||||
|
||||
When a non-collection (does _not_ have _.length_) is passed as the second argument, it is assumed to be the _object_, after which the object's local variable name is derived from the view name:
|
||||
|
||||
partial('movie', movie);
|
||||
var movie = new Movie('Nightmare Before Christmas', 'Tim Burton')
|
||||
partial('movie', movie)
|
||||
// => In view: movie.director
|
||||
|
||||
The exception of this, is when a "plain" object, aka "{}" or "new Object" is passed, which is considered an object with local variable. For example some may expect a "movie" local with the following, however since it is a plain object "director" and "title" are simply locals:
|
||||
|
||||
var movie = { title: 'Nightmare Before Christmas', director: 'Tim Burton' };
|
||||
partial('movie', movie)
|
||||
|
||||
For cases like this where passing a plain object is desired, simply assign it to a key, or use the `object` key which will use the filename-derived variable name. The examples below are equivalent:
|
||||
|
||||
partial('movie', { locals: { movie: movie }})
|
||||
partial('movie', { movie: movie })
|
||||
partial('movie', { object: movie })
|
||||
|
||||
This exact API can be utilized from within a route, to respond with a fragment via Ajax or WebSockets, for example we can render a collection of users directly from a route:
|
||||
|
||||
app.get('/users', function(req, res){
|
||||
@@ -995,6 +1007,15 @@ Get or set the given local variable _name_. The locals built up for a response a
|
||||
res.render('movie', { displayReviews: true });
|
||||
});
|
||||
|
||||
### res.local(obj)
|
||||
|
||||
Assign several locals with the given _obj_. The following are equivalent:
|
||||
|
||||
res.local('foo', bar);
|
||||
res.local('bar', baz);
|
||||
|
||||
res.locals({ foo: bar, bar, baz });
|
||||
|
||||
### app.set(name[, val])
|
||||
|
||||
Apply an application level setting _name_ to _val_, or
|
||||
|
||||
@@ -121,6 +121,29 @@ However now we have the alternative _maxAge_ property which may be used to set _
|
||||
// render a single comment
|
||||
res.partial('comment', comment);
|
||||
|
||||
### partial() locals
|
||||
|
||||
Both _res.partial()_ and the _partial()_ functions accept an single object consisting of both the options and the locals. Previously with Express 1.x you may pass _user_ to a partial, along with _date_ like so:
|
||||
|
||||
partial('user', { object: user, locals: { date: new Date }})
|
||||
|
||||
or perhaps if you preferred not to use the inferred name _user_ you may used a local for this as well:
|
||||
|
||||
partial('user', { locals: { user: user, date: new Date }})
|
||||
|
||||
With recent changes to Express 2.x the object passed is now both, so the following is valid for the _object_ option and locals:
|
||||
|
||||
partial('user', { object: user, date: new Date })
|
||||
|
||||
Or the following which is equivalent, however the local var name is explicitly set to _user_ instead of deduced from the filename.
|
||||
|
||||
partial('user', { user: user, date: new Date })
|
||||
|
||||
When a "basic" object aka _{}_ or _new Object_ is passed, it is considered options, otherwise it is considered the _object_. The following are equivalent:
|
||||
|
||||
partial('user', user);
|
||||
partial('user', { object: user });
|
||||
|
||||
### Template Engine Compliance
|
||||
|
||||
To comply with Express previously engines needed the following signature:
|
||||
|
||||
@@ -7,7 +7,7 @@ require.paths.unshift(__dirname + '/../../support');
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express')
|
||||
, messages = require('express-contrib/messages');
|
||||
, messages = require('express-messages');
|
||||
|
||||
var app = module.exports = express.createServer();
|
||||
|
||||
@@ -22,8 +22,8 @@ app.mounted(function(other){
|
||||
console.log('ive been mounted!');
|
||||
});
|
||||
|
||||
// Flash message helper provided by express-contrib
|
||||
// $ npm install express-contrib
|
||||
// Flash message helper provided by express-messages
|
||||
// $ npm install express-messages
|
||||
|
||||
app.dynamicHelpers({
|
||||
messages: messages
|
||||
|
||||
@@ -10,10 +10,10 @@ h1 Blog
|
||||
| It looks like you have no posts!
|
||||
p
|
||||
| Click
|
||||
a(href=base + '/post/add') here
|
||||
a(href=base + '/post/add') here
|
||||
| to create a post. Login
|
||||
| as
|
||||
em "admin"
|
||||
em "admin"
|
||||
| and
|
||||
em "express"
|
||||
| .
|
||||
|
||||
+26
-8
@@ -15,10 +15,11 @@ var pub = __dirname + '/public';
|
||||
// Auto-compile sass to css with "compiler"
|
||||
// and then serve with connect's staticProvider
|
||||
|
||||
var app = express.createServer(
|
||||
express.compiler({ src: pub, enable: ['sass'] })
|
||||
, express.static(pub)
|
||||
);
|
||||
var app = express.createServer();
|
||||
app.use(express.compiler({ src: pub, enable: ['sass'] }));
|
||||
app.use(app.router);
|
||||
app.use(express.static(pub));
|
||||
app.use(express.errorHandler({ dump: true, stack: true }));
|
||||
|
||||
// Optional since express defaults to CWD/views
|
||||
|
||||
@@ -29,17 +30,30 @@ app.set('views', __dirname + '/views');
|
||||
// (although you can still mix and match)
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function User(name, email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
// Dummy users
|
||||
var users = [
|
||||
{ name: 'tj', email: 'tj@vision-media.ca' }
|
||||
, { name: 'ciaran', email: 'ciaranj@gmail.com' }
|
||||
, { name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
|
||||
new User('tj', 'tj@vision-media.ca')
|
||||
, new User('ciaran', 'ciaranj@gmail.com')
|
||||
, new User('aaron', 'aaron.heckmann+github@gmail.com')
|
||||
];
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('users', { users: users });
|
||||
});
|
||||
|
||||
app.get('/users/callback', function(req, res){
|
||||
// a callback is also accepted
|
||||
res.partial('users/user', users, function(err, html){
|
||||
if (err) throw err;
|
||||
res.send(html);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/users', function(req, res){
|
||||
// we can use res.partial() as if
|
||||
// we were in a view, utilizing the same api
|
||||
@@ -48,7 +62,11 @@ app.get('/users', function(req, res){
|
||||
});
|
||||
|
||||
app.get('/users/list', function(req, res){
|
||||
res.partial('users/list', { object: users });
|
||||
// use "object" to utilize the name deduced from
|
||||
// the view filename. The examples below are equivalent
|
||||
|
||||
//res.partial('users/list', { object: users });
|
||||
res.partial('users/list', { list: users });
|
||||
});
|
||||
|
||||
app.get('/user/:id', function(req, res){
|
||||
|
||||
@@ -28,13 +28,8 @@ var ninja = {
|
||||
};
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('ninjas', { ninja: ninja });
|
||||
res.render('ninja', { ninja: ninja });
|
||||
});
|
||||
|
||||
app.get('/li', function(req, res){
|
||||
res.partial('li', { object: 'Testing', as: 'value' });
|
||||
});
|
||||
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
|
||||
+6
-2
@@ -1,8 +1,12 @@
|
||||
h1= ninja.name
|
||||
|
||||
// file, partial name, and partial object all match ('summary')
|
||||
// the partial filename prefix '_' is completely optional
|
||||
#summary!= partial('summary', ninja.summary)
|
||||
// the partial filename prefix '_' is completely optional.
|
||||
|
||||
// In this case we need to specify ninja.summary as the object
|
||||
// option, since it is a "plain" object Express cannot otherwise
|
||||
// tell if it is intended to be locals, or THE summary object
|
||||
#summary!= partial('summary', { object: ninja.summary })
|
||||
|
||||
// file, partial name = '_weapon', resolves to 'weapon' object within partial
|
||||
#weapons
|
||||
+1
-1
@@ -27,7 +27,7 @@ var exports = module.exports = connect.middleware;
|
||||
* Framework version.
|
||||
*/
|
||||
|
||||
exports.version = '2.0.0rc';
|
||||
exports.version = '2.0.0';
|
||||
|
||||
/**
|
||||
* Shortcut for `new Server(...)`.
|
||||
|
||||
+27
-16
@@ -51,7 +51,7 @@ Server.prototype.init = function(middleware){
|
||||
this.dynamicViewHelpers = {};
|
||||
this.errorHandlers = [];
|
||||
|
||||
// default "home" to /
|
||||
// default "home" to /
|
||||
this.set('home', '/');
|
||||
|
||||
// set "env" to NODE_ENV, defaulting to "development"
|
||||
@@ -133,25 +133,36 @@ Server.prototype.registerErrorHandlers = function(){
|
||||
*/
|
||||
|
||||
Server.prototype.use = function(route, middleware){
|
||||
var app, home;
|
||||
var app, home, handle;
|
||||
|
||||
if ('string' != typeof route) {
|
||||
middleware = route, route = '/';
|
||||
}
|
||||
|
||||
// express app
|
||||
if (middleware.handle && middleware.set) app = middleware;
|
||||
|
||||
// restore .app property on req and res
|
||||
if (app) {
|
||||
app.route = route;
|
||||
middleware = function(req, res, next) {
|
||||
var orig = req.app;
|
||||
app.handle(req, res, function(err){
|
||||
req.app = res.app = orig;
|
||||
next(err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
connect.HTTPServer.prototype.use.call(this, route, middleware);
|
||||
|
||||
// mounted an app
|
||||
if (middleware.handle) {
|
||||
app = middleware;
|
||||
// express app
|
||||
if (app.set) {
|
||||
home = app.set('home');
|
||||
if ('/' == home) home = '';
|
||||
app.set('home', app.route + home);
|
||||
app.parent = this;
|
||||
}
|
||||
// mounted hook
|
||||
// mounted an app, invoke the hook
|
||||
// and adjust some settings
|
||||
if (app) {
|
||||
home = app.set('home');
|
||||
if ('/' == home) home = '';
|
||||
app.set('home', app.route + home);
|
||||
app.parent = this;
|
||||
if (app.__mounted) app.__mounted.call(app, this);
|
||||
}
|
||||
|
||||
@@ -205,7 +216,7 @@ Server.prototype.register = function(){
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.helpers =
|
||||
Server.prototype.helpers =
|
||||
Server.prototype.locals = function(obj){
|
||||
utils.merge(this.viewHelpers, obj);
|
||||
return this;
|
||||
@@ -230,7 +241,7 @@ Server.prototype.dynamicHelpers = function(obj){
|
||||
*
|
||||
* Param mapping is used to provide pre-conditions to routes
|
||||
* which us normalized placeholders. For example ":user_id" may
|
||||
* attempt to load the user from the database, where as ":num" may
|
||||
* attempt to load the user from the database, where as ":num" may
|
||||
* pass the value through `parseInt(num, 10)`.
|
||||
*
|
||||
* When the callback function accepts only a single argument, the
|
||||
@@ -239,7 +250,7 @@ Server.prototype.dynamicHelpers = function(obj){
|
||||
* app.param('page', function(n){ return parseInt(n, 10); });
|
||||
*
|
||||
* After which "/users/:page" would automatically provide us with
|
||||
* an integer for `req.params.page`. If desired we could use the callback
|
||||
* an integer for `req.params.page`. If desired we could use the callback
|
||||
* signature shown below, and immediately `next(new Error('invalid page'))`
|
||||
* when `parseInt` fails.
|
||||
*
|
||||
|
||||
+24
-5
@@ -68,7 +68,7 @@ res.send = function(body, headers, status){
|
||||
}
|
||||
break;
|
||||
case 'object':
|
||||
if (body instanceof Buffer) {
|
||||
if (Buffer.isBuffer(body)) {
|
||||
if (!this.header('Content-Type')) {
|
||||
this.contentType('.bin');
|
||||
}
|
||||
@@ -87,7 +87,7 @@ res.send = function(body, headers, status){
|
||||
|
||||
// populate Content-Length
|
||||
if (!this.header('Content-Length')) {
|
||||
this.header('Content-Length', body instanceof Buffer
|
||||
this.header('Content-Length', Buffer.isBuffer(body)
|
||||
? body.length
|
||||
: Buffer.byteLength(body));
|
||||
}
|
||||
@@ -378,8 +378,27 @@ res.redirect = function(url, status){
|
||||
*/
|
||||
|
||||
res.local = function(name, val){
|
||||
this.locals = this.locals || {};
|
||||
this._locals = this._locals || {};
|
||||
return undefined === val
|
||||
? this.locals[name]
|
||||
: this.locals[name] = val;
|
||||
? this._locals[name]
|
||||
: this._locals[name] = val;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign several locals with the given `obj`,
|
||||
* or return the locals.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {Object|Undefined}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.locals = function(obj){
|
||||
if (obj) {
|
||||
for (var key in obj) {
|
||||
this.local(key, obj[key]);
|
||||
}
|
||||
} else {
|
||||
return this._locals;
|
||||
}
|
||||
};
|
||||
|
||||
+100
-51
@@ -47,30 +47,47 @@ exports.register = View.register;
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function renderPartial(res, view, options, locals, parent){
|
||||
function renderPartial(res, view, options, parentLocals, parent){
|
||||
var collection, object, locals;
|
||||
|
||||
// Inherit parent view extension when not present
|
||||
if (parent && !~view.indexOf('.')) {
|
||||
view += parent.extension;
|
||||
}
|
||||
|
||||
// Allow collection to be passed as second param
|
||||
if (options) {
|
||||
if ('length' in options) {
|
||||
options = { collection: options };
|
||||
} else if (!options.collection && !options.locals && !options.object) {
|
||||
options = { object: options };
|
||||
// collection
|
||||
if (options.collection) {
|
||||
collection = options.collection;
|
||||
delete options.collection;
|
||||
} else if ('length' in options) {
|
||||
collection = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// locals
|
||||
if (options.locals) {
|
||||
locals = options.locals;
|
||||
delete options.locals;
|
||||
}
|
||||
|
||||
// object
|
||||
if ('Object' != options.constructor.name) {
|
||||
object = options;
|
||||
options = {};
|
||||
} else if (undefined != options.object) {
|
||||
object = options.object;
|
||||
delete options.object;
|
||||
}
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
// Inherit locals from parent
|
||||
union(options, locals);
|
||||
union(options, parentLocals);
|
||||
|
||||
// Merge locals
|
||||
if (options.locals) {
|
||||
merge(options, options.locals);
|
||||
}
|
||||
if (locals) merge(options, locals);
|
||||
|
||||
// Partials dont need layouts
|
||||
options.renderPartial = true;
|
||||
@@ -81,31 +98,29 @@ function renderPartial(res, view, options, locals, parent){
|
||||
|
||||
// Render partial
|
||||
function render(){
|
||||
if (options.object) {
|
||||
if (object) {
|
||||
if ('string' == typeof name) {
|
||||
options[name] = options.object;
|
||||
options[name] = object;
|
||||
} else if (name === global) {
|
||||
merge(options, options.object);
|
||||
merge(options, object);
|
||||
} else {
|
||||
options.scope = options.object;
|
||||
options.scope = object;
|
||||
}
|
||||
}
|
||||
return res.render(view, options, null, parent);
|
||||
return res.render(view, options, null, parent, true);
|
||||
}
|
||||
|
||||
// Collection support
|
||||
var collection = options.collection;
|
||||
if (collection) {
|
||||
var len = collection.length
|
||||
, buf = '';
|
||||
delete options.collection;
|
||||
options.collectionLength = len;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
var val = collection[i];
|
||||
options.firstInCollection = i === 0;
|
||||
options.indexInCollection = i;
|
||||
options.lastInCollection = i === len - 1;
|
||||
options.object = val;
|
||||
object = val;
|
||||
buf += render();
|
||||
}
|
||||
return buf;
|
||||
@@ -115,7 +130,9 @@ function renderPartial(res, view, options, locals, parent){
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` partial with the given `options`.
|
||||
* Render `view` partial with the given `options`. Optionally a
|
||||
* callback `fn(err, str)` may be passed instead of writing to
|
||||
* the socket.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
@@ -130,16 +147,23 @@ function renderPartial(res, view, options, locals, parent){
|
||||
* For example _video.html_ will have a object _video_ available to it.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Array} options, collection, or object
|
||||
* @param {Object|Array|Function} options, collection, callback, or object
|
||||
* @param {Function} fn
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.partial = function(view, options){
|
||||
res.partial = function(view, options, fn){
|
||||
var app = this.app
|
||||
, options = options || {}
|
||||
, parent = {};
|
||||
|
||||
// accept callback as second argument
|
||||
if ('function' == typeof options) {
|
||||
fn = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// root "views" option
|
||||
parent.dirname = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
@@ -148,8 +172,23 @@ res.partial = function(view, options){
|
||||
parent.extension = '.' + app.set('view engine');
|
||||
}
|
||||
|
||||
var str = renderPartial(this, view, options, null, parent);
|
||||
this.send(str);
|
||||
// render the partial
|
||||
try {
|
||||
var str = renderPartial(this, view, options, null, parent);
|
||||
} catch (err) {
|
||||
if (fn) {
|
||||
fn(err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// callback or transfer
|
||||
if (fn) {
|
||||
fn(null, str);
|
||||
} else {
|
||||
this.send(str);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -169,12 +208,12 @@ res.partial = function(view, options){
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.render = function(view, opts, fn, parent){
|
||||
res.render = function(view, opts, fn, parent, sub){
|
||||
// support callback function as second arg
|
||||
if (typeof opts === 'function') {
|
||||
if ('function' == typeof opts) {
|
||||
fn = opts, opts = null;
|
||||
}
|
||||
|
||||
|
||||
var options = {}
|
||||
, self = this
|
||||
, app = this.app
|
||||
@@ -186,8 +225,8 @@ res.render = function(view, opts, fn, parent){
|
||||
// merge "view options"
|
||||
if (viewOptions) merge(options, viewOptions);
|
||||
|
||||
// merge res.locals
|
||||
if (this.locals) merge(options, this.locals);
|
||||
// merge res._locals
|
||||
if (this._locals) merge(options, this._locals);
|
||||
|
||||
// merge render() options
|
||||
if (opts) merge(options, opts);
|
||||
@@ -233,7 +272,8 @@ res.render = function(view, opts, fn, parent){
|
||||
// Try index ex: ./views/user/index.jade
|
||||
if (!view.exists) view = new View(orig.indexPath, options);
|
||||
|
||||
// Try ../name ../user from within ./user
|
||||
// Try ../<name>/index ex: ../user/index.jade
|
||||
// when calling partial('user') within the same dir
|
||||
if (!view.exists && !options.isLayout) view = new View(orig.upIndexPath, options);
|
||||
|
||||
// Try layout relative to the "views" dir
|
||||
@@ -270,13 +310,8 @@ res.render = function(view, opts, fn, parent){
|
||||
return renderPartial(self, path, opts, options, view);
|
||||
};
|
||||
|
||||
function error(err) {
|
||||
if (fn) {
|
||||
fn(err);
|
||||
} else {
|
||||
self.req.next(err);
|
||||
}
|
||||
}
|
||||
// Provide filename to engine
|
||||
options.filename = view.path;
|
||||
|
||||
// Attempt render
|
||||
try {
|
||||
@@ -285,22 +320,36 @@ res.render = function(view, opts, fn, parent){
|
||||
? cache[view.path] || (cache[view.path] = engine.compile(view.contents, options))
|
||||
: engine.compile(view.contents, options)
|
||||
, str = template.call(options.scope, options);
|
||||
} catch (err) {
|
||||
return error(err);
|
||||
}
|
||||
|
||||
// Layout support
|
||||
if (layout) {
|
||||
options.isLayout = true;
|
||||
options.layout = false;
|
||||
options.body = str;
|
||||
self.render(layout, options, fn, view);
|
||||
} else if (partial) {
|
||||
return str;
|
||||
} else if (fn) {
|
||||
fn(null, str);
|
||||
} else {
|
||||
this.send(str);
|
||||
// layout expected
|
||||
if (layout) {
|
||||
options.isLayout = true;
|
||||
options.layout = false;
|
||||
options.body = str;
|
||||
this.render(layout, options, fn, view, true);
|
||||
// partial return
|
||||
} else if (partial) {
|
||||
return str;
|
||||
// render complete, and
|
||||
// callback given
|
||||
} else if (fn) {
|
||||
fn(null, str);
|
||||
// respond
|
||||
} else {
|
||||
this.send(str);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
// callback given
|
||||
if (fn) {
|
||||
fn(err);
|
||||
// unwind to root call
|
||||
} else if (sub) {
|
||||
throw err;
|
||||
// root template, next(err)
|
||||
} else {
|
||||
this.req.next(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+3
-2
@@ -47,6 +47,7 @@ var View = exports = module.exports = function View(view, options) {
|
||||
this.basename = basename(view);
|
||||
this.engine = this.resolveEngine();
|
||||
this.extension = '.' + this.engine;
|
||||
this.name = this.basename.replace(this.extension, '');
|
||||
this.path = this.resolvePath();
|
||||
this.dirname = dirname(this.path);
|
||||
};
|
||||
@@ -160,14 +161,14 @@ View.prototype.__defineGetter__('indexPath', function(){
|
||||
});
|
||||
|
||||
/**
|
||||
* Return ../index path alternative.
|
||||
* Return ../<name>/index path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('upIndexPath', function(){
|
||||
return this.dirname + '/index' + this.extension;
|
||||
return this.dirname + '/../' + this.name + '/index' + this.extension;
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Sinatra inspired web development framework",
|
||||
"version": "2.0.0rc",
|
||||
"version": "2.0.0",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
|
||||
@@ -10,7 +10,7 @@
|
||||
{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }
|
||||
],
|
||||
"dependencies": {
|
||||
"connect": ">= 1.0.1 < 2.0.0",
|
||||
"connect": ">= 1.1.0 < 2.0.0",
|
||||
"mime": ">= 0.0.1",
|
||||
"qs": ">= 0.0.6"
|
||||
},
|
||||
|
||||
+26
-1
@@ -406,6 +406,31 @@ module.exports = {
|
||||
{ url: '/regular' },
|
||||
{ body: 'hey' });
|
||||
},
|
||||
|
||||
'test .app property after returning control to parent': function() {
|
||||
var app = express.createServer()
|
||||
, blog = express.createServer();
|
||||
|
||||
// Mounted servers did not restore `req.app` and `res.app` when
|
||||
// passing control back to parent via `out()` in `#handle()`.
|
||||
|
||||
blog.get('/', function(req, res, next){
|
||||
req.app.should.equal(blog);
|
||||
res.app.should.equal(blog);
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(blog);
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.send((res.app === app) ? 'restored' : 'not-restored');
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: 'restored' }
|
||||
);
|
||||
},
|
||||
|
||||
'test route middleware': function(){
|
||||
var app = express.createServer();
|
||||
@@ -534,4 +559,4 @@ module.exports = {
|
||||
{ url: '/user/12', method: 'OPTIONS' },
|
||||
{ headers: { Allow: 'GET,PUT' }});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
externo
+1
@@ -0,0 +1 @@
|
||||
li #{title} #{item}
|
||||
externo
+2
@@ -0,0 +1,2 @@
|
||||
p Hits #{hits}
|
||||
p Misses #{misses}
|
||||
+174
-88
@@ -105,68 +105,68 @@ module.exports = {
|
||||
'test #render()': function(){
|
||||
var app = create();
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index.jade', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/jade', function(req, res){
|
||||
res.render('index', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/haml', function(req, res){
|
||||
res.render('hello.haml', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/callback/layout/no-options', function(req, res){
|
||||
res.render('hello.jade', function(err, str){
|
||||
assert.ok(!err);
|
||||
res.send(str.replace(':(', ':)'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/callback/layout', function(req, res){
|
||||
res.render('hello.jade', {}, function(err, str){
|
||||
assert.ok(!err);
|
||||
res.send(str.replace(':(', ':)'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/callback', function(req, res){
|
||||
res.render('hello.haml', { layout: false }, function(err, str){
|
||||
assert.ok(!err);
|
||||
res.send(str.replace('Hello World', ':)'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/invalid', function(req, res){
|
||||
res.render('invalid.jade', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/invalid-async', function(req, res){
|
||||
process.nextTick(function(){
|
||||
res.render('invalid.jade', { layout: false });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/error', function(req, res){
|
||||
res.render('invalid.jade', { layout: false }, function(err){
|
||||
res.send(err.arguments[0]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/absolute', function(req, res){
|
||||
res.render(__dirname + '/fixtures/index.jade', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/ferret', function(req, res){
|
||||
res.render('ferret', { layout: false, ferret: { name: 'Tobi' }});
|
||||
});
|
||||
|
||||
|
||||
app.get('/status', function(req, res){
|
||||
res.render('hello.jade', { status: 500 });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/status' },
|
||||
{ status: 500 });
|
||||
@@ -214,14 +214,14 @@ module.exports = {
|
||||
'test #render() layout': function(){
|
||||
var app = create();
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index.jade');
|
||||
});
|
||||
app.get('/jade', function(req, res){
|
||||
res.render('index');
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<html><body><p>Welcome</p></body></html>' });
|
||||
@@ -230,7 +230,7 @@ module.exports = {
|
||||
'test #render() specific layout': function(beforeExit){
|
||||
var app = create()
|
||||
, called;
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index.jade', { layout: 'cool-layout.jade' }, function(err, html){
|
||||
called = true;
|
||||
@@ -249,7 +249,7 @@ module.exports = {
|
||||
app.get('/nope', function(req, res){
|
||||
res.render('index.jade', { layout: 'nope.jade' });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<cool><p>Welcome</p></cool>' });
|
||||
@@ -268,7 +268,7 @@ module.exports = {
|
||||
assert.ok(~res.body.indexOf('Error: failed to locate view'));
|
||||
assert.ok(~res.body.indexOf('nope'));
|
||||
});
|
||||
|
||||
|
||||
beforeExit(function(){
|
||||
assert.ok(called, 'Layout callback never called');
|
||||
});
|
||||
@@ -303,17 +303,17 @@ module.exports = {
|
||||
'test #render() view helpers': function(beforeExit){
|
||||
var app = create()
|
||||
, calls = 0;
|
||||
|
||||
|
||||
app.locals({
|
||||
lastName: 'holowaychuk'
|
||||
});
|
||||
|
||||
|
||||
app.helpers({
|
||||
greetings: function(sess, lastName){
|
||||
return 'Hello ' + sess.name + ' ' + lastName;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var ret = app.dynamicHelpers({
|
||||
session: function(req, res){
|
||||
++calls;
|
||||
@@ -323,19 +323,19 @@ module.exports = {
|
||||
return req.session;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
assert.equal(app, ret, 'Server#helpers() is not chainable');
|
||||
|
||||
app.get('/', function(req, res){
|
||||
req.session = { name: 'tj' };
|
||||
res.render('dynamic-helpers.jade', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/ejs', function(req, res){
|
||||
req.session = { name: 'tj' };
|
||||
res.render('dynamic-helpers.ejs', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/precedence', function(req, res){
|
||||
req.session = { name: 'tj' };
|
||||
res.render('dynamic-helpers.jade', {
|
||||
@@ -352,7 +352,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/precedence' },
|
||||
{ body: '<html><body><p>Hello tj foobar</p></body></html>' });
|
||||
|
||||
|
||||
beforeExit(function(){
|
||||
assert.equal(3, calls);
|
||||
});
|
||||
@@ -360,9 +360,9 @@ module.exports = {
|
||||
|
||||
'test #partial()': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
|
||||
// Auto-assigned local w/ collection option
|
||||
app.get('/', function(req, res){
|
||||
res.render('items.jade', { items: ['one', 'two'] });
|
||||
@@ -371,7 +371,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<html><body><ul><li>one</li><li>two</li></ul></body></html>' });
|
||||
|
||||
|
||||
// Auto-assigned local w/ collection array
|
||||
var movies = [
|
||||
{ title: 'Nightmare Before Christmas', director: 'Tim Burton' },
|
||||
@@ -380,7 +380,7 @@ module.exports = {
|
||||
app.get('/movies', function(req, res){
|
||||
res.render('movies.jade', { movies: movies });
|
||||
});
|
||||
|
||||
|
||||
var html = [
|
||||
'<html>',
|
||||
'<body>',
|
||||
@@ -397,11 +397,11 @@ module.exports = {
|
||||
'</body>',
|
||||
'</html>'
|
||||
].join('');
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/movies' },
|
||||
{ body: html });
|
||||
|
||||
|
||||
// as: str collection option
|
||||
app.get('/user', function(req, res){
|
||||
res.partial('user', {
|
||||
@@ -413,7 +413,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/user' },
|
||||
{ body: '<p>tj</p>' });
|
||||
|
||||
|
||||
// as: with object collection
|
||||
app.get('/user/object', function(req, res){
|
||||
res.partial('user.jade', {
|
||||
@@ -425,7 +425,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/user' },
|
||||
{ body: '<p>tj</p>' });
|
||||
|
||||
|
||||
// as: this collection option
|
||||
app.get('/person', function(req, res){
|
||||
res.partial('person.jade', {
|
||||
@@ -438,7 +438,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/person' },
|
||||
{ body: '<p>name: tj</p>' });
|
||||
|
||||
|
||||
// as: global collection option
|
||||
app.get('/videos', function(req, res){
|
||||
res.partial('video.jade', {
|
||||
@@ -446,7 +446,7 @@ module.exports = {
|
||||
collection: movies
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/videos' },
|
||||
{ body: '<p>Tim Burton</p><p>James Cameron</p>' });
|
||||
@@ -473,7 +473,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/movie' },
|
||||
{ body: '<li><div class="title">Nightmare Before Christmas</div><div class="director">Tim Burton</div></li>' });
|
||||
|
||||
|
||||
app.get('/video-global', function(req, res){
|
||||
res.partial('video.jade', {
|
||||
object: movies[0],
|
||||
@@ -485,7 +485,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/video-global' },
|
||||
{ body: '<p>Tim Burton</p>' });
|
||||
|
||||
|
||||
app.get('/person-this', function(req, res){
|
||||
res.partial('person.jade', {
|
||||
object: { name: 'tj' },
|
||||
@@ -498,7 +498,7 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/person-this' },
|
||||
{ body: '<p>User: tj</p>' });
|
||||
|
||||
|
||||
// No options
|
||||
app.get('/nothing', function(req, res){
|
||||
res.partial('hello.ejs');
|
||||
@@ -507,29 +507,103 @@ module.exports = {
|
||||
assert.response(app,
|
||||
{ url: '/nothing' },
|
||||
{ body: 'Hello' });
|
||||
|
||||
|
||||
// Path segments + "as"
|
||||
app.get('/role/as', function(req, res){
|
||||
res.partial('user/role.ejs', { as: 'role', collection: ['admin', 'member'] });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/role/as' },
|
||||
{ body: '<li>Role: admin</li><li>Role: member</li>' });
|
||||
|
||||
|
||||
// Deduce name from last segment
|
||||
app.get('/role', function(req, res){
|
||||
res.partial('user/role.ejs', ['admin', 'member']);
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/role' },
|
||||
{ body: '<li>Role: admin</li><li>Role: member</li>' });
|
||||
|
||||
// Non-basic object support
|
||||
function Movie(title, director){
|
||||
this.title = title;
|
||||
this.director = director;
|
||||
}
|
||||
|
||||
app.get('/movie/object', function(req, res){
|
||||
res.partial('movie', new Movie('The TJ', 'tj'));
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/movie/object' },
|
||||
{ body: '<li><div class="title">The TJ</div><div class="director">tj</div></li>' });
|
||||
|
||||
// Locals
|
||||
app.get('/stats', function(req, res){
|
||||
res.partial('stats', {
|
||||
hits: 12
|
||||
, misses: 1
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/stats' },
|
||||
{ body: '<p>Hits 12</p><p>Misses 1</p>' });
|
||||
|
||||
// Locals
|
||||
app.get('/stats/locals', function(req, res){
|
||||
res.partial('stats', {
|
||||
locals: {
|
||||
hits: 12
|
||||
, misses: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/stats/locals' },
|
||||
{ body: '<p>Hits 12</p><p>Misses 1</p>' });
|
||||
|
||||
// Collection + locals
|
||||
app.get('/items', function(req, res){
|
||||
res.partial('item-title', {
|
||||
collection: ['foo', 'bar']
|
||||
, title: 'test'
|
||||
, as: 'item'
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/items' },
|
||||
{ body: '<li>test foo</li><li>test bar</li>' });
|
||||
|
||||
app.get('/stats/callback', function(req, res){
|
||||
res.partial('stats', { hits: 12, misses: 1 }, function(err, html){
|
||||
res.send('got: ' + html);
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/stats/callback' },
|
||||
{ body: 'got: <p>Hits 12</p><p>Misses 1</p>' });
|
||||
|
||||
app.get('/stats/callback/2', function(req, res){
|
||||
res.locals({ hits: 12, misses: 1 });
|
||||
res.partial('stats', function(err, html){
|
||||
res.send('got: ' + html);
|
||||
});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/stats/callback/2' },
|
||||
{ body: 'got: <p>Hits 12</p><p>Misses 1</p>' });
|
||||
},
|
||||
|
||||
'test #partial() with several calls': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.render('list.jade', { layout: false });
|
||||
});
|
||||
@@ -541,7 +615,7 @@ module.exports = {
|
||||
|
||||
'test #partial() with several calls using locals': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.render('list2.jade', { layout: false });
|
||||
});
|
||||
@@ -553,9 +627,9 @@ module.exports = {
|
||||
|
||||
'test #partial() locals': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.partial('pet-count', {
|
||||
locals: {
|
||||
@@ -565,7 +639,7 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: 'We have 5 cool pets\n' });
|
||||
@@ -573,59 +647,71 @@ module.exports = {
|
||||
|
||||
'test #partial() locals precedence': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.render('greetings.jade', {
|
||||
name: 'TJ'
|
||||
, locals: { otherName: 'Overridden' }
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<html><body><h1>TJ</h1><p>Welcome Overridden</p></body></html>' });
|
||||
},
|
||||
|
||||
|
||||
'test #partial() index': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function Ferret(name){ this.name = name; };
|
||||
|
||||
app.get('/ferret', function(req, res){
|
||||
res.partial('ferret', { name: 'Tobi' });
|
||||
res.partial('ferret', new Ferret('Tobi'));
|
||||
});
|
||||
|
||||
app.get('/ferret/basic', function(req, res){
|
||||
res.partial('ferret', { ferret: { name: 'Tobi' }});
|
||||
});
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/ferret/basic' },
|
||||
{ body: '<li class="ferret">Tobi</li>' });
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/ferret' },
|
||||
{ body: '<li class="ferret">Tobi</li>' });
|
||||
},
|
||||
|
||||
|
||||
'test #partial() relative index': function(){
|
||||
var app = create();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
function Ferret(name) { this.name = name; }
|
||||
app.get('/ferret', function(req, res){
|
||||
var tobi = { name: 'Tobi' }
|
||||
, loki = { name: 'Loki' };
|
||||
var tobi = new Ferret('Tobi')
|
||||
, loki = new Ferret('Loki');
|
||||
res.partial('ferret/list', { object: [tobi, loki] });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/ferret' },
|
||||
{ body: '<ul id="ferrets"><li class="ferret">Tobi</li><li class="ferret">Loki</li></ul>' });
|
||||
},
|
||||
|
||||
|
||||
'test #partial() object': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.partial('movie.jade', {
|
||||
title: 'Foobar'
|
||||
, director: 'Tim Burton'
|
||||
});
|
||||
function Movie(title, director) {
|
||||
this.title = title;
|
||||
this.director = director;
|
||||
}
|
||||
res.partial('movie.jade', new Movie('Foobar', 'Tim Burton'));
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<li><div class="title">Foobar</div><div class="director">Tim Burton</div></li>' });
|
||||
@@ -633,13 +719,13 @@ module.exports = {
|
||||
|
||||
'test #partial() locals with collection': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
res.render('pet-land.jade', {
|
||||
pets: ['Ewald']
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ body: '<html><body><div><li>Ewald is the coolest of Animal land</li></div></body></html>' });
|
||||
@@ -647,14 +733,14 @@ module.exports = {
|
||||
|
||||
'test #partial() inheriting initial locals': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/pets', function(req, res, next){
|
||||
res.render('pets.jade', {
|
||||
site: 'My Cool Pets'
|
||||
, pets: ['Tobi', 'Jane', 'Bandit']
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var html = [
|
||||
'<html>',
|
||||
'<body>',
|
||||
@@ -668,7 +754,7 @@ module.exports = {
|
||||
'</body>',
|
||||
'</html>'
|
||||
].join('');
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/pets' },
|
||||
{ body: html });
|
||||
@@ -676,7 +762,7 @@ module.exports = {
|
||||
|
||||
'test #partial() with array-like collection': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
var movies = {
|
||||
0: { title: 'Nightmare Before Christmas', director: 'Tim Burton' },
|
||||
1: { title: 'Avatar', director: 'James Cameron' },
|
||||
@@ -702,7 +788,7 @@ module.exports = {
|
||||
'</body>',
|
||||
'</html>'
|
||||
].join('');
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/movies' },
|
||||
{ body: html });
|
||||
@@ -711,7 +797,7 @@ module.exports = {
|
||||
'test "partials" setting': function(){
|
||||
var app = create();
|
||||
app.set('partials', __dirname + '/fixtures/sub-templates');
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('items.jade', {
|
||||
layout: false,
|
||||
@@ -808,12 +894,12 @@ module.exports = {
|
||||
, open: '<?'
|
||||
, title: 'Original'
|
||||
});
|
||||
|
||||
|
||||
function setTitle(req, res, next) {
|
||||
res.local('title', 'Wahoo');
|
||||
next();
|
||||
}
|
||||
|
||||
|
||||
app.get('/video', setTitle, function(req, res, next){
|
||||
res.local('close', '?>');
|
||||
res.render('video.ejs', { layout: false, title: 'keyboard cat' });
|
||||
@@ -823,20 +909,20 @@ module.exports = {
|
||||
res.local('close', '?>');
|
||||
res.render('video.ejs', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
app.get('/video/3', function(req, res, next){
|
||||
res.local('close', '?>');
|
||||
res.render('video.ejs', { layout: false });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/video' },
|
||||
{ body: '<h1>keyboard cat</h1>' });
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/video/2' },
|
||||
{ body: '<h1>Wahoo</h1>' });
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/video/3' },
|
||||
{ body: '<h1>Original</h1>' });
|
||||
@@ -861,11 +947,11 @@ module.exports = {
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
app.get('/pets', function(req, res, next){
|
||||
res.render('pets.jade');
|
||||
});
|
||||
|
||||
|
||||
var html = [
|
||||
'<html>',
|
||||
'<body>',
|
||||
@@ -879,7 +965,7 @@ module.exports = {
|
||||
'</body>',
|
||||
'</html>'
|
||||
].join('');
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/pets' },
|
||||
{ body: html });
|
||||
@@ -887,12 +973,12 @@ module.exports = {
|
||||
|
||||
'test .charset with res.render()': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.charset = 'ISO-8859-1';
|
||||
res.render('hello.jade');
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ headers: { 'Content-Type': 'text/html; charset=ISO-8859-1' }});
|
||||
@@ -900,11 +986,11 @@ module.exports = {
|
||||
|
||||
'test charset res.render() option': function(){
|
||||
var app = create();
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('hello.jade', { charset: 'ISO-8859-1' });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ headers: { 'Content-Type': 'text/html; charset=ISO-8859-1' }});
|
||||
@@ -913,11 +999,11 @@ module.exports = {
|
||||
'test charset option': function(){
|
||||
var app = create();
|
||||
app.set('view options', { charset: 'ISO-8859-1' });
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('hello.jade');
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ headers: { 'Content-Type': 'text/html; charset=ISO-8859-1' }});
|
||||
@@ -926,11 +1012,11 @@ module.exports = {
|
||||
'test charset override': function(){
|
||||
var app = create();
|
||||
app.set('view options', { charset: 'ISO-8859-1' });
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('hello.jade', { charset: 'utf8' });
|
||||
});
|
||||
|
||||
|
||||
assert.response(app,
|
||||
{ url: '/' },
|
||||
{ headers: { 'Content-Type': 'text/html; charset=utf8' }});
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário