Name: js-handler/node_modules/nodeunit/deps/ejs/lib/ejs.js 
1:
/*!
2:
 * EJS
3:
 * Copyright(c) 2010 TJ Holowaychuk <[email protected]>
4:
 * MIT Licensed
5:
 */
6:
 
7:
/**
8:
 * Module dependencies.
9:
 */
10:
 
11:
var utils = require('./utils');
12:
 
13:
/**
14:
 * Library version.
15:
 */
16:
 
17:
exports.version = '0.4.3';
18:
 
19:
/**
20:
 * Filters.
21:
 *
22:
 * @type Object
23:
 */
24:
 
25:
var filters = exports.filters = require('./filters');
26:
 
27:
/**
28:
 * Intermediate js cache.
29:
 *
30:
 * @type Object
31:
 */
32:
 
33:
var cache = {};
34:
 
35:
/**
36:
 * Clear intermediate js cache.
37:
 *
38:
 * @api public
39:
 */
40:
 
41:
exports.clearCache = function(){
42:
  cache = {};
43:
};
44:
 
45:
/**
46:
 * Translate filtered code into function calls.
47:
 *
48:
 * @param {String} js
49:
 * @return {String}
50:
 * @api private
51:
 */
52:
 
53:
function filtered(js) {
54:
  return js.substr(1).split('|').reduce(function(js, filter){
55:
    var parts = filter.split(':')
56:
      , name = parts.shift()
57:
      , args = parts.shift() || '';
58:
    if (args) args = ', ' + args;
59:
    return 'filters.' + name + '(' + js + args + ')';
60:
  });
61:
};
62:
 
63:
/**
64:
 * Re-throw the given `err` in context to the
65:
 * `str` of ejs, `filename`, and `lineno`.
66:
 *
67:
 * @param {Error} err
68:
 * @param {String} str
69:
 * @param {String} filename
70:
 * @param {String} lineno
71:
 * @api private
72:
 */
73:
 
74:
function rethrow(err, str, filename, lineno){
75:
  var lines = str.split('\n')
76:
    , start = Math.max(lineno - 3, 0)
77:
    , end = Math.min(lines.length, lineno + 3);
78:
 
79:
  // Error context
80:
  var context = lines.slice(start, end).map(function(line, i){
81:
    var curr = i + start + 1;
82:
    return (curr == lineno ? ' >> ' : '    ')
83:
      + curr
84:
      + '| '
85:
      + line;
86:
  }).join('\n');
87:
 
88:
  // Alter exception message
89:
  err.path = filename;
90:
  err.message = (filename || 'ejs') + ':'
91:
    + lineno + '\n'
92:
    + context + '\n\n'
93:
    + err.message;
94:
  
95:
  throw err;
96:
}
97:
 
98:
/**
99:
 * Parse the given `str` of ejs, returning the function body.
100:
 *
101:
 * @param {String} str
102:
 * @return {String}
103:
 * @api public
104:
 */
105:
 
106:
var parse = exports.parse = function(str, options){
107:
  var options = options || {}
108:
    , open = options.open || exports.open || '<%'
109:
    , close = options.close || exports.close || '%>';
110:
 
111:
  var buf = [
112:
      "var buf = [];"
113:
    , "\nwith (locals) {"
114:
    , "\n  buf.push('"
115:
  ];
116:
  
117:
  var lineno = 1;
118:
 
119:
  for (var i = 0, len = str.length; i < len; ++i) {
120:
    if (str.slice(i, open.length + i) == open) {
121:
      i += open.length
122:
  
123:
      var prefix, postfix, line = '__stack.lineno=' + lineno;
124:
      switch (str.substr(i, 1)) {
125:
        case '=':
126:
          prefix = "', escape((" + line + ', ';
127:
          postfix = ")), '";
128:
          ++i;
129:
          break;
130:
        case '-':
131:
          prefix = "', (" + line + ', ';
132:
          postfix = "), '";
133:
          ++i;
134:
          break;
135:
        default:
136:
          prefix = "');" + line + ';';
137:
          postfix = "; buf.push('";
138:
      }
139:
 
140:
      var end = str.indexOf(close, i)
141:
        , js = str.substring(i, end)
142:
        , start = i
143:
        , n = 0;
144:
 
145:
      while (~(n = js.indexOf("\n", n))) n++, lineno++;
146:
      if (js.substr(0, 1) == ':') js = filtered(js);
147:
      buf.push(prefix, js, postfix);
148:
      i += end - start + close.length - 1;
149:
 
150:
    } else if (str.substr(i, 1) == "\\") {
151:
      buf.push("\\\\");
152:
    } else if (str.substr(i, 1) == "'") {
153:
      buf.push("\\'");
154:
    } else if (str.substr(i, 1) == "\r") {
155:
      buf.push(" ");
156:
    } else if (str.substr(i, 1) == "\n") {
157:
      buf.push("\\n");
158:
      lineno++;
159:
    } else {
160:
      buf.push(str.substr(i, 1));
161:
    }
162:
  }
163:
 
164:
  buf.push("');\n}\nreturn buf.join('');");
165:
  return buf.join('');
166:
};
167:
 
168:
/**
169:
 * Compile the given `str` of ejs into a `Function`.
170:
 *
171:
 * @param {String} str
172:
 * @param {Object} options
173:
 * @return {Function}
174:
 * @api public
175:
 */
176:
 
177:
var compile = exports.compile = function(str, options){
178:
  options = options || {};
179:
  
180:
  var input = JSON.stringify(str)
181:
    , filename = options.filename
182:
        ? JSON.stringify(options.filename)
183:
        : 'undefined';
184:
  
185:
  // Adds the fancy stack trace meta info
186:
  str = [
187:
    'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };',
188:
    rethrow.toString(),
189:
    'try {',
190:
    exports.parse(str, options),
191:
    '} catch (err) {',
192:
    '  rethrow(err, __stack.input, __stack.filename, __stack.lineno);',
193:
    '}'
194:
  ].join("\n");
195:
  
196:
  if (options.debug) console.log(str);
197:
  var fn = new Function('locals, filters, escape', str);
198:
  return function(locals){
199:
    return fn.call(this, locals, filters, utils.escape);
200:
  }
201:
};
202:
 
203:
/**
204:
 * Render the given `str` of ejs.
205:
 *
206:
 * Options:
207:
 *
208:
 *   - `locals`          Local variables object
209:
 *   - `cache`           Compiled functions are cached, requires `filename`
210:
 *   - `filename`        Used by `cache` to key caches
211:
 *   - `scope`           Function execution context
212:
 *   - `debug`           Output generated function body
213:
 *   - `open`            Open tag, defaulting to "<%"
214:
 *   - `close`           Closing tag, defaulting to "%>"
215:
 *
216:
 * @param {String} str
217:
 * @param {Object} options
218:
 * @return {String}
219:
 * @api public
220:
 */
221:
 
222:
exports.render = function(str, options){
223:
  var fn
224:
    , options = options || {};
225:
  if (options.cache) {
226:
    if (options.filename) {
227:
      fn = cache[options.filename] || (cache[options.filename] = compile(str, options));
228:
    } else {
229:
      throw new Error('"cache" option requires "filename".');
230:
    }
231:
  } else {
232:
    fn = compile(str, options);
233:
  }
234:
  return fn.call(options.scope, options.locals || {});
235:
};
236:
 
237:
/**
238:
 * Expose to require().
239:
 */
240:
 
241:
if (require.extensions) {
242:
  require.extensions['.ejs'] = function(module, filename) {
243:
    source = require('fs').readFileSync(filename, 'utf-8');
244:
    module._compile(compile(source, {}), filename);
245:
   };
246:
} else if (require.registerExtension) {
247:
  require.registerExtension('.ejs', function(src) {
248:
    return compile(src, {});
249:
  });
250:
}