socketioMEANseed/server/node_modules/express/lib/view.js
server/node_modules/express/lib/view.jsRaw
1/**
2 * Module dependencies.
3 */
4
5var debug = require('debug')('express:view');
6var path = require('path');
7var fs = require('fs');
8var utils = require('./utils');
9
10/**
11 * Module variables.
12 * @private
13 */
14
15var dirname = path.dirname;
16var basename = path.basename;
17var extname = path.extname;
18var join = path.join;
19var resolve = path.resolve;
20
21/**
22 * Expose `View`.
23 */
24
25module.exports = View;
26
27/**
28 * Initialize a new `View` with the given `name`.
29 *
30 * Options:
31 *
32 * - `defaultEngine` the default template engine name
33 * - `engines` template engine require() cache
34 * - `root` root path for view lookup
35 *
36 * @param {String} name
37 * @param {Object} options
38 * @api private
39 */
40
41function View(name, options) {
42 options = options || {};
43 this.name = name;
44 this.root = options.root;
45 var engines = options.engines;
46 this.defaultEngine = options.defaultEngine;
47 var ext = this.ext = extname(name);
48 if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
49 if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
50 this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
51 this.path = this.lookup(name);
52}
53
54/**
55 * Lookup view by the given `name`
56 *
57 * @param {String} name
58 * @return {String}
59 * @api private
60 */
61
62View.prototype.lookup = function lookup(name) {
63 var path;
64 var roots = [].concat(this.root);
65
66 debug('lookup "%s"', name);
67
68 for (var i = 0; i < roots.length && !path; i++) {
69 var root = roots[i];
70
71 // resolve the path
72 var loc = resolve(root, name);
73 var dir = dirname(loc);
74 var file = basename(loc);
75
76 // resolve the file
77 path = this.resolve(dir, file);
78 }
79
80 return path;
81};
82
83/**
84 * Render with the given `options` and callback `fn(err, str)`.
85 *
86 * @param {Object} options
87 * @param {Function} fn
88 * @api private
89 */
90
91View.prototype.render = function render(options, fn) {
92 debug('render "%s"', this.path);
93 this.engine(this.path, options, fn);
94};
95
96/**
97 * Resolve the file within the given directory.
98 *
99 * @param {string} dir
100 * @param {string} file
101 * @private
102 */
103
104View.prototype.resolve = function resolve(dir, file) {
105 var ext = this.ext;
106 var path;
107 var stat;
108
109 // <path>.<ext>
110 path = join(dir, file);
111 stat = tryStat(path);
112
113 if (stat && stat.isFile()) {
114 return path;
115 }
116
117 // <path>/index.<ext>
118 path = join(dir, basename(file, ext), 'index' + ext);
119 stat = tryStat(path);
120
121 if (stat && stat.isFile()) {
122 return path;
123 }
124};
125
126/**
127 * Return a stat, maybe.
128 *
129 * @param {string} path
130 * @return {fs.Stats}
131 * @private
132 */
133
134function tryStat(path) {
135 debug('stat "%s"', path);
136
137 try {
138 return fs.statSync(path);
139 } catch (e) {
140 return undefined;
141 }
142}