ejs.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. ejs = (function(){
  2. // CommonJS require()
  3. function require(p){
  4. if ('fs' == p) return {};
  5. if ('path' == p) return {};
  6. var path = require.resolve(p)
  7. , mod = require.modules[path];
  8. if (!mod) throw new Error('failed to require "' + p + '"');
  9. if (!mod.exports) {
  10. mod.exports = {};
  11. mod.call(mod.exports, mod, mod.exports, require.relative(path));
  12. }
  13. return mod.exports;
  14. }
  15. require.modules = {};
  16. require.resolve = function (path){
  17. var orig = path
  18. , reg = path + '.js'
  19. , index = path + '/index.js';
  20. return require.modules[reg] && reg
  21. || require.modules[index] && index
  22. || orig;
  23. };
  24. require.register = function (path, fn){
  25. require.modules[path] = fn;
  26. };
  27. require.relative = function (parent) {
  28. return function(p){
  29. if ('.' != p.substr(0, 1)) return require(p);
  30. var path = parent.split('/')
  31. , segs = p.split('/');
  32. path.pop();
  33. for (var i = 0; i < segs.length; i++) {
  34. var seg = segs[i];
  35. if ('..' == seg) path.pop();
  36. else if ('.' != seg) path.push(seg);
  37. }
  38. return require(path.join('/'));
  39. };
  40. };
  41. require.register("ejs.js", function(module, exports, require){
  42. /*!
  43. * EJS
  44. * Copyright(c) 2012 TJ Holowaychuk <tj@vision-media.ca>
  45. * MIT Licensed
  46. */
  47. /**
  48. * Module dependencies.
  49. */
  50. var utils = require('./utils')
  51. , path = require('path')
  52. , dirname = path.dirname
  53. , extname = path.extname
  54. , join = path.join
  55. , fs = require('fs')
  56. , read = fs.readFileSync;
  57. /**
  58. * Filters.
  59. *
  60. * @type Object
  61. */
  62. var filters = exports.filters = require('./filters');
  63. /**
  64. * Intermediate js cache.
  65. *
  66. * @type Object
  67. */
  68. var cache = {};
  69. /**
  70. * Clear intermediate js cache.
  71. *
  72. * @api public
  73. */
  74. exports.clearCache = function(){
  75. cache = {};
  76. };
  77. /**
  78. * Translate filtered code into function calls.
  79. *
  80. * @param {String} js
  81. * @return {String}
  82. * @api private
  83. */
  84. function filtered(js) {
  85. return js.substr(1).split('|').reduce(function(js, filter){
  86. var parts = filter.split(':')
  87. , name = parts.shift()
  88. , args = parts.join(':') || '';
  89. if (args) args = ', ' + args;
  90. return 'filters.' + name + '(' + js + args + ')';
  91. });
  92. };
  93. /**
  94. * Re-throw the given `err` in context to the
  95. * `str` of ejs, `filename`, and `lineno`.
  96. *
  97. * @param {Error} err
  98. * @param {String} str
  99. * @param {String} filename
  100. * @param {String} lineno
  101. * @api private
  102. */
  103. function rethrow(err, str, filename, lineno){
  104. var lines = str.split('\n')
  105. , start = Math.max(lineno - 3, 0)
  106. , end = Math.min(lines.length, lineno + 3);
  107. // Error context
  108. var context = lines.slice(start, end).map(function(line, i){
  109. var curr = i + start + 1;
  110. return (curr == lineno ? ' >> ' : ' ')
  111. + curr
  112. + '| '
  113. + line;
  114. }).join('\n');
  115. // Alter exception message
  116. err.path = filename;
  117. err.message = (filename || 'ejs') + ':'
  118. + lineno + '\n'
  119. + context + '\n\n'
  120. + err.message;
  121. throw err;
  122. }
  123. /**
  124. * Parse the given `str` of ejs, returning the function body.
  125. *
  126. * @param {String} str
  127. * @return {String}
  128. * @api public
  129. */
  130. var parse = exports.parse = function(str, options){
  131. var options = options || {}
  132. , open = options.open || exports.open || '<%'
  133. , close = options.close || exports.close || '%>'
  134. , filename = options.filename
  135. , compileDebug = options.compileDebug !== false
  136. , buf = "";
  137. buf += 'var buf = [];';
  138. if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ ';
  139. buf += '\n buf.push(\'';
  140. var lineno = 1;
  141. var consumeEOL = false;
  142. for (var i = 0, len = str.length; i < len; ++i) {
  143. var stri = str[i];
  144. if (str.slice(i, open.length + i) == open) {
  145. i += open.length
  146. var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno;
  147. switch (str[i]) {
  148. case '=':
  149. prefix = "', escape((" + line + ', ';
  150. postfix = ")), '";
  151. ++i;
  152. break;
  153. case '-':
  154. prefix = "', (" + line + ', ';
  155. postfix = "), '";
  156. ++i;
  157. break;
  158. default:
  159. prefix = "');" + line + ';';
  160. postfix = "; buf.push('";
  161. }
  162. var end = str.indexOf(close, i);
  163. if (end < 0){
  164. throw new Error('Could not find matching close tag "' + close + '".');
  165. }
  166. var js = str.substring(i, end)
  167. , start = i
  168. , include = null
  169. , n = 0;
  170. if ('-' == js[js.length-1]){
  171. js = js.substring(0, js.length - 2);
  172. consumeEOL = true;
  173. }
  174. if (0 == js.trim().indexOf('include')) {
  175. var name = js.trim().slice(7).trim();
  176. if (!filename) throw new Error('filename option is required for includes');
  177. var path = resolveInclude(name, filename);
  178. include = read(path, 'utf8');
  179. include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
  180. buf += "' + (function(){" + include + "})() + '";
  181. js = '';
  182. }
  183. while (~(n = js.indexOf("\n", n))) n++, lineno++;
  184. if (js.substr(0, 1) == ':') js = filtered(js);
  185. if (js) {
  186. if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n';
  187. buf += prefix;
  188. buf += js;
  189. buf += postfix;
  190. }
  191. i += end - start + close.length - 1;
  192. } else if (stri == "\\") {
  193. buf += "\\\\";
  194. } else if (stri == "'") {
  195. buf += "\\'";
  196. } else if (stri == "\r") {
  197. // ignore
  198. } else if (stri == "\n") {
  199. if (consumeEOL) {
  200. consumeEOL = false;
  201. } else {
  202. buf += "\\n";
  203. lineno++;
  204. }
  205. } else {
  206. buf += stri;
  207. }
  208. }
  209. if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');";
  210. else buf += "');\nreturn buf.join('');";
  211. return buf;
  212. };
  213. /**
  214. * Compile the given `str` of ejs into a `Function`.
  215. *
  216. * @param {String} str
  217. * @param {Object} options
  218. * @return {Function}
  219. * @api public
  220. */
  221. var compile = exports.compile = function(str, options){
  222. options = options || {};
  223. var escape = options.escape || utils.escape;
  224. var input = JSON.stringify(str)
  225. , compileDebug = options.compileDebug !== false
  226. , client = options.client
  227. , filename = options.filename
  228. ? JSON.stringify(options.filename)
  229. : 'undefined';
  230. if (compileDebug) {
  231. // Adds the fancy stack trace meta info
  232. str = [
  233. 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };',
  234. rethrow.toString(),
  235. 'try {',
  236. exports.parse(str, options),
  237. '} catch (err) {',
  238. ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);',
  239. '}'
  240. ].join("\n");
  241. } else {
  242. str = exports.parse(str, options);
  243. }
  244. if (options.debug) console.log(str);
  245. if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str;
  246. try {
  247. var fn = new Function('locals, filters, escape, rethrow', str);
  248. } catch (err) {
  249. if ('SyntaxError' == err.name) {
  250. err.message += options.filename
  251. ? ' in ' + filename
  252. : ' while compiling ejs';
  253. }
  254. throw err;
  255. }
  256. if (client) return fn;
  257. return function(locals){
  258. return fn.call(this, locals, filters, escape, rethrow);
  259. }
  260. };
  261. /**
  262. * Render the given `str` of ejs.
  263. *
  264. * Options:
  265. *
  266. * - `locals` Local variables object
  267. * - `cache` Compiled functions are cached, requires `filename`
  268. * - `filename` Used by `cache` to key caches
  269. * - `scope` Function execution context
  270. * - `debug` Output generated function body
  271. * - `open` Open tag, defaulting to "<%"
  272. * - `close` Closing tag, defaulting to "%>"
  273. *
  274. * @param {String} str
  275. * @param {Object} options
  276. * @return {String}
  277. * @api public
  278. */
  279. exports.render = function(str, options){
  280. var fn
  281. , options = options || {};
  282. if (options.cache) {
  283. if (options.filename) {
  284. fn = cache[options.filename] || (cache[options.filename] = compile(str, options));
  285. } else {
  286. throw new Error('"cache" option requires "filename".');
  287. }
  288. } else {
  289. fn = compile(str, options);
  290. }
  291. options.__proto__ = options.locals;
  292. return fn.call(options.scope, options);
  293. };
  294. /**
  295. * Render an EJS file at the given `path` and callback `fn(err, str)`.
  296. *
  297. * @param {String} path
  298. * @param {Object|Function} options or callback
  299. * @param {Function} fn
  300. * @api public
  301. */
  302. exports.renderFile = function(path, options, fn){
  303. var key = path + ':string';
  304. if ('function' == typeof options) {
  305. fn = options, options = {};
  306. }
  307. options.filename = path;
  308. var str;
  309. try {
  310. str = options.cache
  311. ? cache[key] || (cache[key] = read(path, 'utf8'))
  312. : read(path, 'utf8');
  313. } catch (err) {
  314. fn(err);
  315. return;
  316. }
  317. fn(null, exports.render(str, options));
  318. };
  319. /**
  320. * Resolve include `name` relative to `filename`.
  321. *
  322. * @param {String} name
  323. * @param {String} filename
  324. * @return {String}
  325. * @api private
  326. */
  327. function resolveInclude(name, filename) {
  328. var path = join(dirname(filename), name);
  329. var ext = extname(name);
  330. if (!ext) path += '.ejs';
  331. return path;
  332. }
  333. // express support
  334. exports.__express = exports.renderFile;
  335. /**
  336. * Expose to require().
  337. */
  338. if (require.extensions) {
  339. require.extensions['.ejs'] = function (module, filename) {
  340. filename = filename || module.filename;
  341. var options = { filename: filename, client: true }
  342. , template = fs.readFileSync(filename).toString()
  343. , fn = compile(template, options);
  344. module._compile('module.exports = ' + fn.toString() + ';', filename);
  345. };
  346. } else if (require.registerExtension) {
  347. require.registerExtension('.ejs', function(src) {
  348. return compile(src, {});
  349. });
  350. }
  351. }); // module: ejs.js
  352. require.register("filters.js", function(module, exports, require){
  353. /*!
  354. * EJS - Filters
  355. * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
  356. * MIT Licensed
  357. */
  358. /**
  359. * First element of the target `obj`.
  360. */
  361. exports.first = function(obj) {
  362. return obj[0];
  363. };
  364. /**
  365. * Last element of the target `obj`.
  366. */
  367. exports.last = function(obj) {
  368. return obj[obj.length - 1];
  369. };
  370. /**
  371. * Capitalize the first letter of the target `str`.
  372. */
  373. exports.capitalize = function(str){
  374. str = String(str);
  375. return str[0].toUpperCase() + str.substr(1, str.length);
  376. };
  377. /**
  378. * Downcase the target `str`.
  379. */
  380. exports.downcase = function(str){
  381. return String(str).toLowerCase();
  382. };
  383. /**
  384. * Uppercase the target `str`.
  385. */
  386. exports.upcase = function(str){
  387. return String(str).toUpperCase();
  388. };
  389. /**
  390. * Sort the target `obj`.
  391. */
  392. exports.sort = function(obj){
  393. return Object.create(obj).sort();
  394. };
  395. /**
  396. * Sort the target `obj` by the given `prop` ascending.
  397. */
  398. exports.sort_by = function(obj, prop){
  399. return Object.create(obj).sort(function(a, b){
  400. a = a[prop], b = b[prop];
  401. if (a > b) return 1;
  402. if (a < b) return -1;
  403. return 0;
  404. });
  405. };
  406. /**
  407. * Size or length of the target `obj`.
  408. */
  409. exports.size = exports.length = function(obj) {
  410. return obj.length;
  411. };
  412. /**
  413. * Add `a` and `b`.
  414. */
  415. exports.plus = function(a, b){
  416. return Number(a) + Number(b);
  417. };
  418. /**
  419. * Subtract `b` from `a`.
  420. */
  421. exports.minus = function(a, b){
  422. return Number(a) - Number(b);
  423. };
  424. /**
  425. * Multiply `a` by `b`.
  426. */
  427. exports.times = function(a, b){
  428. return Number(a) * Number(b);
  429. };
  430. /**
  431. * Divide `a` by `b`.
  432. */
  433. exports.divided_by = function(a, b){
  434. return Number(a) / Number(b);
  435. };
  436. /**
  437. * Join `obj` with the given `str`.
  438. */
  439. exports.join = function(obj, str){
  440. return obj.join(str || ', ');
  441. };
  442. /**
  443. * Truncate `str` to `len`.
  444. */
  445. exports.truncate = function(str, len, append){
  446. str = String(str);
  447. if (str.length > len) {
  448. str = str.slice(0, len);
  449. if (append) str += append;
  450. }
  451. return str;
  452. };
  453. /**
  454. * Truncate `str` to `n` words.
  455. */
  456. exports.truncate_words = function(str, n){
  457. var str = String(str)
  458. , words = str.split(/ +/);
  459. return words.slice(0, n).join(' ');
  460. };
  461. /**
  462. * Replace `pattern` with `substitution` in `str`.
  463. */
  464. exports.replace = function(str, pattern, substitution){
  465. return String(str).replace(pattern, substitution || '');
  466. };
  467. /**
  468. * Prepend `val` to `obj`.
  469. */
  470. exports.prepend = function(obj, val){
  471. return Array.isArray(obj)
  472. ? [val].concat(obj)
  473. : val + obj;
  474. };
  475. /**
  476. * Append `val` to `obj`.
  477. */
  478. exports.append = function(obj, val){
  479. return Array.isArray(obj)
  480. ? obj.concat(val)
  481. : obj + val;
  482. };
  483. /**
  484. * Map the given `prop`.
  485. */
  486. exports.map = function(arr, prop){
  487. return arr.map(function(obj){
  488. return obj[prop];
  489. });
  490. };
  491. /**
  492. * Reverse the given `obj`.
  493. */
  494. exports.reverse = function(obj){
  495. return Array.isArray(obj)
  496. ? obj.reverse()
  497. : String(obj).split('').reverse().join('');
  498. };
  499. /**
  500. * Get `prop` of the given `obj`.
  501. */
  502. exports.get = function(obj, prop){
  503. return obj[prop];
  504. };
  505. /**
  506. * Packs the given `obj` into json string
  507. */
  508. exports.json = function(obj){
  509. return JSON.stringify(obj);
  510. };
  511. }); // module: filters.js
  512. require.register("utils.js", function(module, exports, require){
  513. /*!
  514. * EJS
  515. * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
  516. * MIT Licensed
  517. */
  518. /**
  519. * Escape the given string of `html`.
  520. *
  521. * @param {String} html
  522. * @return {String}
  523. * @api private
  524. */
  525. exports.escape = function(html){
  526. return String(html)
  527. .replace(/&/g, '&amp;')
  528. .replace(/</g, '&lt;')
  529. .replace(/>/g, '&gt;')
  530. .replace(/'/g, '&#39;')
  531. .replace(/"/g, '&quot;');
  532. };
  533. }); // module: utils.js
  534. return require("ejs");
  535. })();