]> git.cworth.org Git - obsolete/notmuch-web/blob - node_modules/express/lib/view/view.js
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / lib / view / view.js
1
2 /*!
3  * Express - View
4  * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5  * MIT Licensed
6  */
7
8 /**
9  * Module dependencies.
10  */
11
12 var path = require('path')
13   , extname = path.extname
14   , dirname = path.dirname
15   , basename = path.basename
16   , fs = require('fs')
17   , stat = fs.statSync;
18
19 /**
20  * Expose `View`.
21  */
22
23 exports = module.exports = View;
24
25 /**
26  * Require cache.
27  */
28
29 var cache = {};
30
31 /**
32  * Initialize a new `View` with the given `view` path and `options`.
33  *
34  * @param {String} view
35  * @param {Object} options
36  * @api private
37  */
38
39 function View(view, options) {
40   options = options || {};
41   this.view = view;
42   this.root = options.root;
43   this.relative = false !== options.relative;
44   this.defaultEngine = options.defaultEngine;
45   this.parent = options.parentView;
46   this.basename = basename(view);
47   this.engine = this.resolveEngine();
48   this.extension = '.' + this.engine;
49   this.name = this.basename.replace(this.extension, '');
50   this.path = this.resolvePath();
51   this.dirname = dirname(this.path);
52   if (options.attempts) options.attempts.push(this.path);
53 };
54
55 /**
56  * Check if the view path exists.
57  *
58  * @return {Boolean}
59  * @api public
60  */
61
62 View.prototype.__defineGetter__('exists', function(){
63   try {
64     stat(this.path);
65     return true;
66   } catch (err) {
67     return false;
68   }
69 });
70
71 /**
72  * Resolve view engine.
73  *
74  * @return {String}
75  * @api private
76  */
77
78 View.prototype.resolveEngine = function(){
79   // Explicit
80   if (~this.basename.indexOf('.')) return extname(this.basename).substr(1);
81   // Inherit from parent
82   if (this.parent) return this.parent.engine;
83   // Default
84   return this.defaultEngine;
85 };
86
87 /**
88  * Resolve view path.
89  *
90  * @return {String}
91  * @api private
92  */
93
94 View.prototype.resolvePath = function(){
95   var path = this.view;
96   // Implicit engine
97   if (!~this.basename.indexOf('.')) path += this.extension;
98   // Absolute
99   if ('/' == path[0]) return path;
100   // Relative to parent
101   if (this.relative && this.parent) return this.parent.dirname + '/' + path;
102   // Relative to root
103   return this.root
104     ? this.root + '/' + path
105     : path;
106 };
107
108 /**
109  * Get view contents. This is a one-time hit, so we
110  * can afford to be sync.
111  *
112  * @return {String}
113  * @api public
114  */
115
116 View.prototype.__defineGetter__('contents', function(){
117   return fs.readFileSync(this.path, 'utf8');
118 });
119
120 /**
121  * Get template engine api, cache exports to reduce
122  * require() calls.
123  *
124  * @return {Object}
125  * @api public
126  */
127
128 View.prototype.__defineGetter__('templateEngine', function(){
129   var ext = this.extension;
130   return cache[ext] || (cache[ext] = require(this.engine));
131 });
132
133 /**
134  * Return root path alternative.
135  *
136  * @return {String}
137  * @api public
138  */
139
140 View.prototype.__defineGetter__('rootPath', function(){
141   this.relative = false;
142   return this.resolvePath();
143 });
144
145 /**
146  * Return index path alternative.
147  *
148  * @return {String}
149  * @api public
150  */
151
152 View.prototype.__defineGetter__('indexPath', function(){
153   return this.dirname
154     + '/' + this.basename.replace(this.extension, '')
155     + '/index' + this.extension;
156 });
157
158 /**
159  * Return ../<name>/index path alternative.
160  *
161  * @return {String}
162  * @api public
163  */
164
165 View.prototype.__defineGetter__('upIndexPath', function(){
166   return this.dirname + '/../' + this.name + '/index' + this.extension;
167 });
168
169 /**
170  * Return _ prefix path alternative
171  *
172  * @return {String}
173  * @api public
174  */
175
176 View.prototype.__defineGetter__('prefixPath', function(){
177   return this.dirname + '/_' + this.basename;
178 });
179
180 /**
181  * Register the given template engine `exports`
182  * as `ext`. For example we may wish to map ".html"
183  * files to jade:
184  *
185  *    app.register('.html', require('jade'));
186  *
187  * or
188  *
189  *    app.register('html', require('jade'));
190  *
191  * This is also useful for libraries that may not
192  * match extensions correctly. For example my haml.js
193  * library is installed from npm as "hamljs" so instead
194  * of layout.hamljs, we can register the engine as ".haml":
195  *
196  *    app.register('.haml', require('haml-js'));
197  *
198  * @param {String} ext
199  * @param {Object} obj
200  * @api public
201  */
202
203 exports.register = function(ext, exports) {
204   if ('.' != ext[0]) ext = '.' + ext;
205   cache[ext] = exports;
206 };