twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

view.js (3326B)


      1 /*!
      2  * express
      3  * Copyright(c) 2009-2013 TJ Holowaychuk
      4  * Copyright(c) 2013 Roman Shtylman
      5  * Copyright(c) 2014-2015 Douglas Christopher Wilson
      6  * MIT Licensed
      7  */
      8 
      9 'use strict';
     10 
     11 /**
     12  * Module dependencies.
     13  * @private
     14  */
     15 
     16 var debug = require('debug')('express:view');
     17 var path = require('path');
     18 var fs = require('fs');
     19 
     20 /**
     21  * Module variables.
     22  * @private
     23  */
     24 
     25 var dirname = path.dirname;
     26 var basename = path.basename;
     27 var extname = path.extname;
     28 var join = path.join;
     29 var resolve = path.resolve;
     30 
     31 /**
     32  * Module exports.
     33  * @public
     34  */
     35 
     36 module.exports = View;
     37 
     38 /**
     39  * Initialize a new `View` with the given `name`.
     40  *
     41  * Options:
     42  *
     43  *   - `defaultEngine` the default template engine name
     44  *   - `engines` template engine require() cache
     45  *   - `root` root path for view lookup
     46  *
     47  * @param {string} name
     48  * @param {object} options
     49  * @public
     50  */
     51 
     52 function View(name, options) {
     53   var opts = options || {};
     54 
     55   this.defaultEngine = opts.defaultEngine;
     56   this.ext = extname(name);
     57   this.name = name;
     58   this.root = opts.root;
     59 
     60   if (!this.ext && !this.defaultEngine) {
     61     throw new Error('No default engine was specified and no extension was provided.');
     62   }
     63 
     64   var fileName = name;
     65 
     66   if (!this.ext) {
     67     // get extension from default engine name
     68     this.ext = this.defaultEngine[0] !== '.'
     69       ? '.' + this.defaultEngine
     70       : this.defaultEngine;
     71 
     72     fileName += this.ext;
     73   }
     74 
     75   if (!opts.engines[this.ext]) {
     76     // load engine
     77     var mod = this.ext.substr(1)
     78     debug('require "%s"', mod)
     79 
     80     // default engine export
     81     var fn = require(mod).__express
     82 
     83     if (typeof fn !== 'function') {
     84       throw new Error('Module "' + mod + '" does not provide a view engine.')
     85     }
     86 
     87     opts.engines[this.ext] = fn
     88   }
     89 
     90   // store loaded engine
     91   this.engine = opts.engines[this.ext];
     92 
     93   // lookup path
     94   this.path = this.lookup(fileName);
     95 }
     96 
     97 /**
     98  * Lookup view by the given `name`
     99  *
    100  * @param {string} name
    101  * @private
    102  */
    103 
    104 View.prototype.lookup = function lookup(name) {
    105   var path;
    106   var roots = [].concat(this.root);
    107 
    108   debug('lookup "%s"', name);
    109 
    110   for (var i = 0; i < roots.length && !path; i++) {
    111     var root = roots[i];
    112 
    113     // resolve the path
    114     var loc = resolve(root, name);
    115     var dir = dirname(loc);
    116     var file = basename(loc);
    117 
    118     // resolve the file
    119     path = this.resolve(dir, file);
    120   }
    121 
    122   return path;
    123 };
    124 
    125 /**
    126  * Render with the given options.
    127  *
    128  * @param {object} options
    129  * @param {function} callback
    130  * @private
    131  */
    132 
    133 View.prototype.render = function render(options, callback) {
    134   debug('render "%s"', this.path);
    135   this.engine(this.path, options, callback);
    136 };
    137 
    138 /**
    139  * Resolve the file within the given directory.
    140  *
    141  * @param {string} dir
    142  * @param {string} file
    143  * @private
    144  */
    145 
    146 View.prototype.resolve = function resolve(dir, file) {
    147   var ext = this.ext;
    148 
    149   // <path>.<ext>
    150   var path = join(dir, file);
    151   var stat = tryStat(path);
    152 
    153   if (stat && stat.isFile()) {
    154     return path;
    155   }
    156 
    157   // <path>/index.<ext>
    158   path = join(dir, basename(file, ext), 'index' + ext);
    159   stat = tryStat(path);
    160 
    161   if (stat && stat.isFile()) {
    162     return path;
    163   }
    164 };
    165 
    166 /**
    167  * Return a stat, maybe.
    168  *
    169  * @param {string} path
    170  * @return {fs.Stats}
    171  * @private
    172  */
    173 
    174 function tryStat(path) {
    175   debug('stat "%s"', path);
    176 
    177   try {
    178     return fs.statSync(path);
    179   } catch (e) {
    180     return undefined;
    181   }
    182 }