mirror of
https://github.com/zebrajr/express.git
synced 2025-12-06 12:19:51 +01:00
re-working view system
This commit is contained in:
parent
ce03cf49d8
commit
7710db4591
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -9,5 +9,6 @@ lib-cov
|
|||
*.swp
|
||||
*.swo
|
||||
benchmarks/graphs
|
||||
testing.js
|
||||
testing
|
||||
node_modules/
|
||||
testing
|
||||
|
|
|
|||
30
lib/http.js
30
lib/http.js
|
|
@ -60,6 +60,7 @@ app.__proto__ = connect.HTTPServer.prototype;
|
|||
app.init = function(middleware){
|
||||
var self = this;
|
||||
this.cache = {};
|
||||
this.engines = {};
|
||||
this.settings = {};
|
||||
this.redirects = {};
|
||||
this.isCallbacks = {};
|
||||
|
|
@ -278,9 +279,32 @@ app.mounted = function(fn){
|
|||
* @api public
|
||||
*/
|
||||
|
||||
app.register = function(){
|
||||
view.register.apply(this, arguments);
|
||||
return this;
|
||||
/**
|
||||
* Register the given template engine `exports`
|
||||
* as `ext`. For example we may wish to map ".html"
|
||||
* files to jade:
|
||||
*
|
||||
* app.register('.html', require('jade'));
|
||||
*
|
||||
* or
|
||||
*
|
||||
* app.register('html', require('jade'));
|
||||
*
|
||||
* This is also useful for libraries that may not
|
||||
* match extensions correctly. For example my haml.js
|
||||
* library is installed from npm as "hamljs" so instead
|
||||
* of layout.hamljs, we can register the engine as ".haml":
|
||||
*
|
||||
* app.register('.haml', require('haml-js'));
|
||||
*
|
||||
* @param {String} ext
|
||||
* @param {Object} obj
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.register = function(ext, exports) {
|
||||
if ('.' != ext[0]) ext = '.' + ext;
|
||||
this.engines[ext] = exports;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
54
lib/proto.js
54
lib/proto.js
|
|
@ -16,8 +16,13 @@ var connect = require('connect')
|
|||
, toArray = require('./utils').toArray
|
||||
, methods = router.methods.concat('del', 'all')
|
||||
, res = require('./response')
|
||||
, union = require('./utils').union
|
||||
, url = require('url')
|
||||
, utils = connect.utils
|
||||
, path = require('path')
|
||||
, extname = path.extname
|
||||
, join = path.join
|
||||
, fs = require('fs')
|
||||
, qs = require('qs');
|
||||
|
||||
/**
|
||||
|
|
@ -530,3 +535,52 @@ app.all = function(path){
|
|||
|
||||
app.del = app.delete;
|
||||
|
||||
/**
|
||||
* Render the given `view` name with `opts`
|
||||
* and a callback accepting an error and the
|
||||
* rendered template string.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {String|Function} opts or fn
|
||||
* @param {Function} fn
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.render = function(view, opts, fn){
|
||||
var self = this
|
||||
, options = {}
|
||||
, cache = this.cache
|
||||
, engines = this.engines
|
||||
, root = this.set('views') || process.cwd() + '/views';
|
||||
|
||||
// support callback function as second arg
|
||||
if ('function' == typeof opts) {
|
||||
fn = opts, opts = null;
|
||||
}
|
||||
|
||||
// merge app.locals
|
||||
union(options, this.locals);
|
||||
|
||||
// merge render() options
|
||||
if (opts) utils.merge(options, opts);
|
||||
|
||||
// join "view engine" if necessary
|
||||
var ext = extname(view);
|
||||
if (!ext) view += '.' + (ext = this.set('view engine'));
|
||||
|
||||
// pass .cache to the engine
|
||||
options.cache = this.enabled('view cache');
|
||||
|
||||
// when no extension nor "view engine" is given
|
||||
if (!ext) return fn(new Error('failed to find view "' + view + '"'));
|
||||
|
||||
// render
|
||||
try {
|
||||
var engine = cache[ext] = cache[ext] || require(ext);
|
||||
options.filename = join(root, view);
|
||||
view = fs.readFileSync(options.filename, 'utf8');
|
||||
engine.render(view, options, fn);
|
||||
} catch (err) {
|
||||
fn(err);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
420
lib/view.js
420
lib/view.js
|
|
@ -11,293 +11,28 @@
|
|||
|
||||
var path = require('path')
|
||||
, extname = path.extname
|
||||
, dirname = path.dirname
|
||||
, basename = path.basename
|
||||
, join = path.join
|
||||
, utils = require('connect').utils
|
||||
, View = require('./view/view')
|
||||
, partial = require('./view/partial')
|
||||
, union = require('./utils').union
|
||||
, merge = utils.merge
|
||||
, http = require('http')
|
||||
, fs = require('fs')
|
||||
, res = http.ServerResponse.prototype;
|
||||
|
||||
/**
|
||||
* Expose constructors.
|
||||
*/
|
||||
|
||||
exports = module.exports = View;
|
||||
|
||||
/**
|
||||
* Export template engine registrar.
|
||||
*/
|
||||
|
||||
exports.register = View.register;
|
||||
|
||||
/**
|
||||
* Lookup and compile `view` with cache support by supplying
|
||||
* both the `cache` object and `cid` string,
|
||||
* followed by `options` passed to `exports.lookup()`.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object} cache
|
||||
* @param {Object} cid
|
||||
* @param {Object} options
|
||||
* @return {View}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.compile = function(view, cache, cid, options){
|
||||
if (cache && cid && cache[cid]) return cache[cid];
|
||||
|
||||
// lookup
|
||||
view = exports.lookup(view, options);
|
||||
|
||||
// hints
|
||||
if (!view.exists) {
|
||||
if (options.hint) hintAtViewPaths(view.original, options);
|
||||
var err = new Error('failed to locate view "' + view.original.view + '"');
|
||||
err.view = view.original;
|
||||
throw err;
|
||||
}
|
||||
|
||||
// compile
|
||||
options.filename = view.path;
|
||||
view.fn = view.templateEngine.compile(view.contents, options);
|
||||
cache[cid] = view;
|
||||
|
||||
return view;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup `view`, returning an instanceof `View`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `root` root directory path
|
||||
* - `defaultEngine` default template engine
|
||||
* - `parentView` parent `View` object
|
||||
* - `cache` cache object
|
||||
* - `cacheid` optional cache id
|
||||
*
|
||||
* Lookup:
|
||||
*
|
||||
* - partial `_<name>`
|
||||
* - any `<name>/index`
|
||||
* - non-layout `../<name>/index`
|
||||
* - any `<root>/<name>`
|
||||
* - partial `<root>/_<name>`
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object} options
|
||||
* @return {View}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.lookup = function(view, options){
|
||||
var orig = view = new View(view, options)
|
||||
, partial = options.isPartial
|
||||
, layout = options.isLayout;
|
||||
|
||||
// Try _ prefix ex: ./views/_<name>.jade
|
||||
// taking precedence over the direct path
|
||||
if (partial) {
|
||||
view = new View(orig.prefixPath, options);
|
||||
if (!view.exists) view = orig;
|
||||
}
|
||||
|
||||
// Try index ex: ./views/user/index.jade
|
||||
if (!layout && !view.exists) view = new View(orig.indexPath, options);
|
||||
|
||||
// Try ../<name>/index ex: ../user/index.jade
|
||||
// when calling partial('user') within the same dir
|
||||
if (!layout && !view.exists) view = new View(orig.upIndexPath, options);
|
||||
|
||||
// Try root ex: <root>/user.jade
|
||||
if (!view.exists) view = new View(orig.rootPath, options);
|
||||
|
||||
// Try root _ prefix ex: <root>/_user.jade
|
||||
if (!view.exists && partial) view = new View(view.prefixPath, options);
|
||||
|
||||
view.original = orig;
|
||||
return view;
|
||||
};
|
||||
|
||||
/**
|
||||
* Partial render helper.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function renderPartial(res, view, options, parentLocals, parent){
|
||||
var collection, object, locals;
|
||||
|
||||
if (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, parentLocals);
|
||||
|
||||
// Merge locals
|
||||
if (locals) merge(options, locals);
|
||||
|
||||
// Partials dont need layouts
|
||||
options.isPartial = true;
|
||||
options.layout = false;
|
||||
|
||||
// Deduce name from view path
|
||||
var name = options.as || partial.resolveObjectName(view);
|
||||
|
||||
// Render partial
|
||||
function render(){
|
||||
if (object) {
|
||||
if ('string' == typeof name) {
|
||||
options[name] = object;
|
||||
} else if (name === global) {
|
||||
merge(options, object);
|
||||
}
|
||||
}
|
||||
return res.render(view, options, null, parent, true);
|
||||
}
|
||||
|
||||
// Collection support
|
||||
if (collection) {
|
||||
var len = collection.length
|
||||
, buf = ''
|
||||
, keys
|
||||
, key
|
||||
, val;
|
||||
|
||||
options.collectionLength = len;
|
||||
|
||||
if ('number' == typeof len || Array.isArray(collection)) {
|
||||
for (var i = 0; i < len; ++i) {
|
||||
val = collection[i];
|
||||
options.firstInCollection = i == 0;
|
||||
options.indexInCollection = i;
|
||||
options.lastInCollection = i == len - 1;
|
||||
object = val;
|
||||
buf += render();
|
||||
}
|
||||
} else {
|
||||
keys = Object.keys(collection);
|
||||
len = keys.length;
|
||||
options.collectionLength = len;
|
||||
options.collectionKeys = keys;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
key = keys[i];
|
||||
val = collection[key];
|
||||
options.keyInCollection = key;
|
||||
options.firstInCollection = i == 0;
|
||||
options.indexInCollection = i;
|
||||
options.lastInCollection = i == len - 1;
|
||||
object = val;
|
||||
buf += render();
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
} else {
|
||||
return render();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` partial with the given `options`. Optionally a
|
||||
* callback `fn(err, str)` may be passed instead of writing to
|
||||
* the socket.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `object` Single object with name derived from the view (unless `as` is present)
|
||||
*
|
||||
* - `as` Variable name for each `collection` value, defaults to the view name.
|
||||
* * as: 'something' will add the `something` local variable
|
||||
* * as: this will use the collection value as the template context
|
||||
* * as: global will merge the collection value's properties with `locals`
|
||||
*
|
||||
* - `collection` Array of objects, the name is derived from the view name itself.
|
||||
* For example _video.html_ will have a object _video_ available to it.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Array|Function} options, collection, callback, or object
|
||||
* @param {Function} fn
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.partial = function(view, options, fn){
|
||||
var app = this.app
|
||||
, options = options || {}
|
||||
, viewEngine = app.set('view engine')
|
||||
, parent = {};
|
||||
|
||||
// accept callback as second argument
|
||||
if ('function' == typeof options) {
|
||||
fn = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// root "views" option
|
||||
parent.dirname = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// utilize "view engine" option
|
||||
if (viewEngine) parent.engine = viewEngine;
|
||||
|
||||
// render the partial
|
||||
try {
|
||||
var str = renderPartial(this, view, options, null, parent);
|
||||
} catch (err) {
|
||||
if (fn) {
|
||||
fn(err);
|
||||
} else {
|
||||
this.req.next(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// callback or transfer
|
||||
if (fn) {
|
||||
fn(null, str);
|
||||
} else {
|
||||
this.send(str);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` with the given `options` and optional callback `fn`.
|
||||
* When a callback function is given a response will _not_ be made
|
||||
* automatically, however otherwise a response of _200_ and _text/html_ is given.
|
||||
* automatically, otherwise a response of _200_ and _text/html_ is given.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `scope` Template evaluation context (the value of `this`)
|
||||
* - `debug` Output debugging information
|
||||
* - `status` Response status code
|
||||
* - `status` Response status code (`res.statusCode`)
|
||||
* - `charset` Set the charset (`res.charset`)
|
||||
*
|
||||
* Reserved locals:
|
||||
*
|
||||
* - `cache` boolean hinting to the engine it should cache
|
||||
* - `filename` filename of the view being rendered
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Function} options or callback function
|
||||
|
|
@ -305,41 +40,20 @@ res.partial = function(view, options, fn){
|
|||
* @api public
|
||||
*/
|
||||
|
||||
res.render = function(view, opts, fn, parent, sub){
|
||||
res.render = function(view, opts, fn){
|
||||
var self = this
|
||||
, options = {}
|
||||
, app = this.app
|
||||
, req = this.req
|
||||
, cache = app.cache
|
||||
, engines = app.engines
|
||||
, root = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// support callback function as second arg
|
||||
if ('function' == typeof opts) {
|
||||
fn = opts, opts = null;
|
||||
}
|
||||
|
||||
try {
|
||||
return this._render(view, opts, fn, parent, sub);
|
||||
} catch (err) {
|
||||
// callback given
|
||||
if (fn) {
|
||||
fn(err);
|
||||
// unwind to root call to prevent multiple callbacks
|
||||
} else if (sub) {
|
||||
throw err;
|
||||
// root template, next(err)
|
||||
} else {
|
||||
this.req.next(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// private render()
|
||||
|
||||
res._render = function(view, opts, fn, parent, sub){
|
||||
var options = {}
|
||||
, self = this
|
||||
, app = this.app
|
||||
, root = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// cache id
|
||||
var cid = app.enabled('view cache')
|
||||
? view + (parent ? ':' + parent.path : '')
|
||||
: false;
|
||||
|
||||
// merge app.locals
|
||||
union(options, app.locals);
|
||||
|
||||
|
|
@ -349,86 +63,40 @@ res._render = function(view, opts, fn, parent, sub){
|
|||
// merge render() options
|
||||
if (opts) merge(options, opts);
|
||||
|
||||
// merge render() .locals
|
||||
if (opts && opts.locals) merge(options, opts.locals);
|
||||
|
||||
// status support
|
||||
if (options.status) this.statusCode = options.status;
|
||||
|
||||
// capture attempts
|
||||
options.attempts = [];
|
||||
|
||||
var partial = options.isPartial
|
||||
, layout = options.layout;
|
||||
|
||||
// Layout support
|
||||
if (true === layout || undefined === layout) {
|
||||
layout = 'layout';
|
||||
}
|
||||
|
||||
// Default execution scope to a plain object
|
||||
options.scope = options.scope || {};
|
||||
|
||||
// Populate view
|
||||
options.parentView = parent;
|
||||
|
||||
// "views" setting
|
||||
options.root = root;
|
||||
|
||||
// "view engine" setting
|
||||
options.defaultEngine = app.set('view engine');
|
||||
|
||||
// charset option
|
||||
if (options.charset) this.charset = options.charset;
|
||||
|
||||
// Always expose partial() as a local
|
||||
options.partial = function(path, opts){
|
||||
return renderPartial(self, path, opts, options, view);
|
||||
};
|
||||
// join "view engine" if necessary
|
||||
var ext = extname(view);
|
||||
if (!ext) view += '.' + (ext = app.set('view engine'));
|
||||
|
||||
// View lookup
|
||||
options.hint = app.enabled('hints');
|
||||
view = exports.compile(view, app.cache, cid, options);
|
||||
// pass .cache to the engine
|
||||
options.cache = app.enabled('view cache');
|
||||
|
||||
// layout helper
|
||||
options.layout = function(path){
|
||||
layout = path;
|
||||
// when no extension nor "view engine" is given warn
|
||||
if (!ext) {
|
||||
console.warn('Warning: cannot determine view engine for "%s"', view);
|
||||
console.warn('provide the "view engine" setting or an');
|
||||
console.warn('extension such as "foo.jade".');
|
||||
return this.end();
|
||||
}
|
||||
|
||||
// callback
|
||||
fn = fn || function(err, str){
|
||||
if (err) return req.next(err);
|
||||
self.send(str);
|
||||
};
|
||||
|
||||
// render
|
||||
var str = view.fn.call(options.scope, options);
|
||||
|
||||
// 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);
|
||||
try {
|
||||
var engine = cache[ext] = cache[ext] || require(ext);
|
||||
options.filename = join(root, view);
|
||||
view = fs.readFileSync(options.filename, 'utf8');
|
||||
engine.render(view, options, fn);
|
||||
} catch (err) {
|
||||
fn(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hint at view path resolution, outputting the
|
||||
* paths that Express has tried.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function hintAtViewPaths(view, options) {
|
||||
console.error();
|
||||
console.error('failed to locate view "' + view.view + '", tried:');
|
||||
options.attempts.forEach(function(path){
|
||||
console.error(' - %s', path);
|
||||
});
|
||||
console.error();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
|
||||
/*!
|
||||
* Express - view - Partial
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memory cache.
|
||||
*/
|
||||
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* Resolve partial object name from the view path.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* "user.ejs" becomes "user"
|
||||
* "forum thread.ejs" becomes "forumThread"
|
||||
* "forum/thread/post.ejs" becomes "post"
|
||||
* "blog-post.ejs" becomes "blogPost"
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.resolveObjectName = function(view){
|
||||
return cache[view] || (cache[view] = view
|
||||
.split('/')
|
||||
.slice(-1)[0]
|
||||
.split('.')[0]
|
||||
.replace(/^_/, '')
|
||||
.replace(/[^a-zA-Z0-9 ]+/g, ' ')
|
||||
.split(/ +/).map(function(word, i){
|
||||
return i
|
||||
? word[0].toUpperCase() + word.substr(1)
|
||||
: word;
|
||||
}).join(''));
|
||||
};
|
||||
210
lib/view/view.js
210
lib/view/view.js
|
|
@ -1,210 +0,0 @@
|
|||
|
||||
/*!
|
||||
* Express - View
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var path = require('path')
|
||||
, utils = require('../utils')
|
||||
, extname = path.extname
|
||||
, dirname = path.dirname
|
||||
, basename = path.basename
|
||||
, fs = require('fs')
|
||||
, stat = fs.statSync;
|
||||
|
||||
/**
|
||||
* Expose `View`.
|
||||
*/
|
||||
|
||||
exports = module.exports = View;
|
||||
|
||||
/**
|
||||
* Require cache.
|
||||
*/
|
||||
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* Initialize a new `View` with the given `view` path and `options`.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object} options
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function View(view, options) {
|
||||
options = options || {};
|
||||
this.view = view;
|
||||
this.root = options.root;
|
||||
this.relative = false !== options.relative;
|
||||
this.defaultEngine = options.defaultEngine;
|
||||
this.parent = options.parentView;
|
||||
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);
|
||||
if (options.attempts) {
|
||||
if (!~options.attempts.indexOf(this.path))
|
||||
options.attempts.push(this.path);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the view path exists.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('exists', function(){
|
||||
try {
|
||||
stat(this.path);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Resolve view engine.
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
View.prototype.resolveEngine = function(){
|
||||
// Explicit
|
||||
if (~this.basename.indexOf('.')) return extname(this.basename).substr(1);
|
||||
// Inherit from parent
|
||||
if (this.parent) return this.parent.engine;
|
||||
// Default
|
||||
return this.defaultEngine;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve view path.
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
View.prototype.resolvePath = function(){
|
||||
var path = this.view;
|
||||
// Implicit engine
|
||||
if (!~this.basename.indexOf('.')) path += this.extension;
|
||||
// Absolute
|
||||
if (utils.isAbsolute(path)) return path;
|
||||
// Relative to parent
|
||||
if (this.relative && this.parent) return this.parent.dirname + '/' + path;
|
||||
// Relative to root
|
||||
return this.root
|
||||
? this.root + '/' + path
|
||||
: path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get view contents. This is a one-time hit, so we
|
||||
* can afford to be sync.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('contents', function(){
|
||||
return fs.readFileSync(this.path, 'utf8');
|
||||
});
|
||||
|
||||
/**
|
||||
* Get template engine api, cache exports to reduce
|
||||
* require() calls.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('templateEngine', function(){
|
||||
var ext = this.extension;
|
||||
return cache[ext] || (cache[ext] = require(this.engine));
|
||||
});
|
||||
|
||||
/**
|
||||
* Return root path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('rootPath', function(){
|
||||
this.relative = false;
|
||||
return this.resolvePath();
|
||||
});
|
||||
|
||||
/**
|
||||
* Return index path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('indexPath', function(){
|
||||
return this.dirname
|
||||
+ '/' + this.basename.replace(this.extension, '')
|
||||
+ '/index' + this.extension;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return ../<name>/index path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('upIndexPath', function(){
|
||||
return this.dirname + '/../' + this.name + '/index' + this.extension;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return _ prefix path alternative
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('prefixPath', function(){
|
||||
return this.dirname + '/_' + this.basename;
|
||||
});
|
||||
|
||||
/**
|
||||
* Register the given template engine `exports`
|
||||
* as `ext`. For example we may wish to map ".html"
|
||||
* files to jade:
|
||||
*
|
||||
* app.register('.html', require('jade'));
|
||||
*
|
||||
* or
|
||||
*
|
||||
* app.register('html', require('jade'));
|
||||
*
|
||||
* This is also useful for libraries that may not
|
||||
* match extensions correctly. For example my haml.js
|
||||
* library is installed from npm as "hamljs" so instead
|
||||
* of layout.hamljs, we can register the engine as ".haml":
|
||||
*
|
||||
* app.register('.haml', require('haml-js'));
|
||||
*
|
||||
* @param {String} ext
|
||||
* @param {Object} obj
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.register = function(ext, exports) {
|
||||
if ('.' != ext[0]) ext = '.' + ext;
|
||||
cache[ext] = exports;
|
||||
};
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
"ejs": "0.4.2",
|
||||
"expresso": "0.8.1",
|
||||
"hamljs": "0.5.1",
|
||||
"jade": "0.13.0",
|
||||
"jade": "0.16.2",
|
||||
"stylus": "0.13.0",
|
||||
"should": "0.2.1",
|
||||
"express-messages": "0.0.2",
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../')
|
||||
, http = require('http');
|
||||
|
||||
var app = express();
|
||||
|
||||
app.use(express.logger('dev'));
|
||||
app.use(express.static(__dirname));
|
||||
|
||||
http.createServer(app).listen(3000);
|
||||
console.log('listening on port 3000');
|
||||
Loading…
Reference in New Issue
Block a user