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