Fully end to end encrypted anonymous chat program. Server only stores public key lookup for users and the encrypted messages. No credentials are transfered to the server, but kept in local browser storage. This allows 100% safe chatting. https://safechat.ch
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
4.1 KiB

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