postal.js/example/node/node_modules/express/lib/view/view.js

223 lines
4.2 KiB
JavaScript

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