github.com/solo-io/unik@v0.0.0-20190717152701-a58d3e8e33b7/docs/examples/example-nodejs-fileserver/node_modules/express/lib/view.js (about) 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 var utils = require('./utils'); 20 21 /** 22 * Module variables. 23 * @private 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 * Module exports. 34 * @public 35 */ 36 37 module.exports = View; 38 39 /** 40 * Initialize a new `View` with the given `name`. 41 * 42 * Options: 43 * 44 * - `defaultEngine` the default template engine name 45 * - `engines` template engine require() cache 46 * - `root` root path for view lookup 47 * 48 * @param {string} name 49 * @param {object} options 50 * @public 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 // get extension from default engine name 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 // load engine 78 opts.engines[this.ext] = require(this.ext.substr(1)).__express; 79 } 80 81 // store loaded engine 82 this.engine = opts.engines[this.ext]; 83 84 // lookup path 85 this.path = this.lookup(fileName); 86 } 87 88 /** 89 * Lookup view by the given `name` 90 * 91 * @param {string} name 92 * @private 93 */ 94 95 View.prototype.lookup = function lookup(name) { 96 var path; 97 var roots = [].concat(this.root); 98 99 debug('lookup "%s"', name); 100 101 for (var i = 0; i < roots.length && !path; i++) { 102 var root = roots[i]; 103 104 // resolve the path 105 var loc = resolve(root, name); 106 var dir = dirname(loc); 107 var file = basename(loc); 108 109 // resolve the file 110 path = this.resolve(dir, file); 111 } 112 113 return path; 114 }; 115 116 /** 117 * Render with the given options. 118 * 119 * @param {object} options 120 * @param {function} callback 121 * @private 122 */ 123 124 View.prototype.render = function render(options, callback) { 125 debug('render "%s"', this.path); 126 this.engine(this.path, options, callback); 127 }; 128 129 /** 130 * Resolve the file within the given directory. 131 * 132 * @param {string} dir 133 * @param {string} file 134 * @private 135 */ 136 137 View.prototype.resolve = function resolve(dir, file) { 138 var ext = this.ext; 139 140 // <path>.<ext> 141 var path = join(dir, file); 142 var stat = tryStat(path); 143 144 if (stat && stat.isFile()) { 145 return path; 146 } 147 148 // <path>/index.<ext> 149 path = join(dir, basename(file, ext), 'index' + ext); 150 stat = tryStat(path); 151 152 if (stat && stat.isFile()) { 153 return path; 154 } 155 }; 156 157 /** 158 * Return a stat, maybe. 159 * 160 * @param {string} path 161 * @return {fs.Stats} 162 * @private 163 */ 164 165 function tryStat(path) { 166 debug('stat "%s"', path); 167 168 try { 169 return fs.statSync(path); 170 } catch (e) { 171 return undefined; 172 } 173 }