ejs.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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. , js = str.substring(i, end)
  164. , start = i
  165. , include = null
  166. , n = 0;
  167. if ('-' == js[js.length-1]){
  168. js = js.substring(0, js.length - 2);
  169. consumeEOL = true;
  170. }
  171. if (0 == js.trim().indexOf('include')) {
  172. var name = js.trim().slice(7).trim();
  173. if (!filename) throw new Error('filename option is required for includes');
  174. var path = resolveInclude(name, filename);
  175. include = read(path, 'utf8');
  176. include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
  177. buf += "' + (function(){" + include + "})() + '";
  178. js = '';
  179. }
  180. while (~(n = js.indexOf("\n", n))) n++, lineno++;
  181. if (js.substr(0, 1) == ':') js = filtered(js);
  182. if (js) {
  183. if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n';
  184. buf += prefix;
  185. buf += js;
  186. buf += postfix;
  187. }
  188. i += end - start + close.length - 1;
  189. } else if (stri == "\\") {
  190. buf += "\\\\";
  191. } else if (stri == "'") {
  192. buf += "\\'";
  193. } else if (stri == "\r") {
  194. // ignore
  195. } else if (stri == "\n") {
  196. if (consumeEOL) {
  197. consumeEOL = false;
  198. } else {
  199. buf += "\\n";
  200. lineno++;
  201. }
  202. } else {
  203. buf += stri;
  204. }
  205. }
  206. if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');";
  207. else buf += "');\nreturn buf.join('');";
  208. return buf;
  209. };
  210. /**
  211. * Compile the given `str` of ejs into a `Function`.
  212. *
  213. * @param {String} str
  214. * @param {Object} options
  215. * @return {Function}
  216. * @api public
  217. */
  218. var compile = exports.compile = function(str, options){
  219. options = options || {};
  220. var escape = options.escape || utils.escape;
  221. var input = JSON.stringify(str)
  222. , compileDebug = options.compileDebug !== false
  223. , client = options.client
  224. , filename = options.filename
  225. ? JSON.stringify(options.filename)
  226. : 'undefined';
  227. if (compileDebug) {
  228. // Adds the fancy stack trace meta info
  229. str = [
  230. 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };',
  231. rethrow.toString(),
  232. 'try {',
  233. exports.parse(str, options),
  234. '} catch (err) {',
  235. ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);',
  236. '}'
  237. ].join("\n");
  238. } else {
  239. str = exports.parse(str, options);
  240. }
  241. if (options.debug) console.log(str);
  242. if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str;
  243. try {
  244. var fn = new Function('locals, filters, escape, rethrow', str);
  245. } catch (err) {
  246. if ('SyntaxError' == err.name) {
  247. err.message += options.filename
  248. ? ' in ' + filename
  249. : ' while compiling ejs';
  250. }
  251. throw err;
  252. }
  253. if (client) return fn;
  254. return function(locals){
  255. return fn.call(this, locals, filters, escape, rethrow);
  256. }
  257. };
  258. /**
  259. * Render the given `str` of ejs.
  260. *
  261. * Options:
  262. *
  263. * - `locals` Local variables object
  264. * - `cache` Compiled functions are cached, requires `filename`
  265. * - `filename` Used by `cache` to key caches
  266. * - `scope` Function execution context
  267. * - `debug` Output generated function body
  268. * - `open` Open tag, defaulting to "<%"
  269. * - `close` Closing tag, defaulting to "%>"
  270. *
  271. * @param {String} str
  272. * @param {Object} options
  273. * @return {String}
  274. * @api public
  275. */
  276. exports.render = function(str, options){
  277. var fn
  278. , options = options || {};
  279. if (options.cache) {
  280. if (options.filename) {
  281. fn = cache[options.filename] || (cache[options.filename] = compile(str, options));
  282. } else {
  283. throw new Error('"cache" option requires "filename".');
  284. }
  285. } else {
  286. fn = compile(str, options);
  287. }
  288. options.__proto__ = options.locals;
  289. return fn.call(options.scope, options);
  290. };
  291. /**
  292. * Render an EJS file at the given `path` and callback `fn(err, str)`.
  293. *
  294. * @param {String} path
  295. * @param {Object|Function} options or callback
  296. * @param {Function} fn
  297. * @api public
  298. */
  299. exports.renderFile = function(path, options, fn){
  300. var key = path + ':string';
  301. if ('function' == typeof options) {
  302. fn = options, options = {};
  303. }
  304. options.filename = path;
  305. var str;
  306. try {
  307. str = options.cache
  308. ? cache[key] || (cache[key] = read(path, 'utf8'))
  309. : read(path, 'utf8');
  310. } catch (err) {
  311. fn(err);
  312. return;
  313. }
  314. fn(null, exports.render(str, options));
  315. };
  316. /**
  317. * Resolve include `name` relative to `filename`.
  318. *
  319. * @param {String} name
  320. * @param {String} filename
  321. * @return {String}
  322. * @api private
  323. */
  324. function resolveInclude(name, filename) {
  325. var path = join(dirname(filename), name);
  326. var ext = extname(name);
  327. if (!ext) path += '.ejs';
  328. return path;
  329. }
  330. // express support
  331. exports.__express = exports.renderFile;
  332. /**
  333. * Expose to require().
  334. */
  335. if (require.extensions) {
  336. require.extensions['.ejs'] = function (module, filename) {
  337. filename = filename || module.filename;
  338. var options = { filename: filename, client: true }
  339. , template = fs.readFileSync(filename).toString()
  340. , fn = compile(template, options);
  341. module._compile('module.exports = ' + fn.toString() + ';', filename);
  342. };
  343. } else if (require.registerExtension) {
  344. require.registerExtension('.ejs', function(src) {
  345. return compile(src, {});
  346. });
  347. }
  348. }); // module: ejs.js
  349. require.register("filters.js", function(module, exports, require){
  350. /*!
  351. * EJS - Filters
  352. * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
  353. * MIT Licensed
  354. */
  355. /**
  356. * First element of the target `obj`.
  357. */
  358. exports.first = function(obj) {
  359. return obj[0];
  360. };
  361. /**
  362. * Last element of the target `obj`.
  363. */
  364. exports.last = function(obj) {
  365. return obj[obj.length - 1];
  366. };
  367. /**
  368. * Capitalize the first letter of the target `str`.
  369. */
  370. exports.capitalize = function(str){
  371. str = String(str);
  372. return str[0].toUpperCase() + str.substr(1, str.length);
  373. };
  374. /**
  375. * Downcase the target `str`.
  376. */
  377. exports.downcase = function(str){
  378. return String(str).toLowerCase();
  379. };
  380. /**
  381. * Uppercase the target `str`.
  382. */
  383. exports.upcase = function(str){
  384. return String(str).toUpperCase();
  385. };
  386. /**
  387. * Sort the target `obj`.
  388. */
  389. exports.sort = function(obj){
  390. return Object.create(obj).sort();
  391. };
  392. /**
  393. * Sort the target `obj` by the given `prop` ascending.
  394. */
  395. exports.sort_by = function(obj, prop){
  396. return Object.create(obj).sort(function(a, b){
  397. a = a[prop], b = b[prop];
  398. if (a > b) return 1;
  399. if (a < b) return -1;
  400. return 0;
  401. });
  402. };
  403. /**
  404. * Size or length of the target `obj`.
  405. */
  406. exports.size = exports.length = function(obj) {
  407. return obj.length;
  408. };
  409. /**
  410. * Add `a` and `b`.
  411. */
  412. exports.plus = function(a, b){
  413. return Number(a) + Number(b);
  414. };
  415. /**
  416. * Subtract `b` from `a`.
  417. */
  418. exports.minus = function(a, b){
  419. return Number(a) - Number(b);
  420. };
  421. /**
  422. * Multiply `a` by `b`.
  423. */
  424. exports.times = function(a, b){
  425. return Number(a) * Number(b);
  426. };
  427. /**
  428. * Divide `a` by `b`.
  429. */
  430. exports.divided_by = function(a, b){
  431. return Number(a) / Number(b);
  432. };
  433. /**
  434. * Join `obj` with the given `str`.
  435. */
  436. exports.join = function(obj, str){
  437. return obj.join(str || ', ');
  438. };
  439. /**
  440. * Truncate `str` to `len`.
  441. */
  442. exports.truncate = function(str, len, append){
  443. str = String(str);
  444. if (str.length > len) {
  445. str = str.slice(0, len);
  446. if (append) str += append;
  447. }
  448. return str;
  449. };
  450. /**
  451. * Truncate `str` to `n` words.
  452. */
  453. exports.truncate_words = function(str, n){
  454. var str = String(str)
  455. , words = str.split(/ +/);
  456. return words.slice(0, n).join(' ');
  457. };
  458. /**
  459. * Replace `pattern` with `substitution` in `str`.
  460. */
  461. exports.replace = function(str, pattern, substitution){
  462. return String(str).replace(pattern, substitution || '');
  463. };
  464. /**
  465. * Prepend `val` to `obj`.
  466. */
  467. exports.prepend = function(obj, val){
  468. return Array.isArray(obj)
  469. ? [val].concat(obj)
  470. : val + obj;
  471. };
  472. /**
  473. * Append `val` to `obj`.
  474. */
  475. exports.append = function(obj, val){
  476. return Array.isArray(obj)
  477. ? obj.concat(val)
  478. : obj + val;
  479. };
  480. /**
  481. * Map the given `prop`.
  482. */
  483. exports.map = function(arr, prop){
  484. return arr.map(function(obj){
  485. return obj[prop];
  486. });
  487. };
  488. /**
  489. * Reverse the given `obj`.
  490. */
  491. exports.reverse = function(obj){
  492. return Array.isArray(obj)
  493. ? obj.reverse()
  494. : String(obj).split('').reverse().join('');
  495. };
  496. /**
  497. * Get `prop` of the given `obj`.
  498. */
  499. exports.get = function(obj, prop){
  500. return obj[prop];
  501. };
  502. /**
  503. * Packs the given `obj` into json string
  504. */
  505. exports.json = function(obj){
  506. return JSON.stringify(obj);
  507. };
  508. }); // module: filters.js
  509. require.register("utils.js", function(module, exports, require){
  510. /*!
  511. * EJS
  512. * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
  513. * MIT Licensed
  514. */
  515. /**
  516. * Escape the given string of `html`.
  517. *
  518. * @param {String} html
  519. * @return {String}
  520. * @api private
  521. */
  522. exports.escape = function(html){
  523. return String(html)
  524. .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
  525. .replace(/</g, '&lt;')
  526. .replace(/>/g, '&gt;')
  527. .replace(/'/g, '&#39;')
  528. .replace(/"/g, '&quot;');
  529. };
  530. }); // module: utils.js
  531. return require("ejs");
  532. })();