diff options
Diffstat (limited to 'node_modules/ejs')
50 files changed, 2311 insertions, 0 deletions
diff --git a/node_modules/ejs/.gitmodules b/node_modules/ejs/.gitmodules new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/node_modules/ejs/.gitmodules diff --git a/node_modules/ejs/.npmignore b/node_modules/ejs/.npmignore new file mode 100644 index 0000000..020ddac --- /dev/null +++ b/node_modules/ejs/.npmignore @@ -0,0 +1,4 @@ +# ignore any vim files: +*.sw[a-z] +vim/.netrwhist +node_modules diff --git a/node_modules/ejs/.travis.yml b/node_modules/ejs/.travis.yml new file mode 100644 index 0000000..1ccd299 --- /dev/null +++ b/node_modules/ejs/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - 0.11 + - 0.10 + - 0.9 + - 0.6 + - 0.8 diff --git a/node_modules/ejs/History.md b/node_modules/ejs/History.md new file mode 100644 index 0000000..df3ccf6 --- /dev/null +++ b/node_modules/ejs/History.md @@ -0,0 +1,138 @@ + +0.8.5 / 2013-11-21 +================== + + * fix: Escape apostrophe & don't over-match existing entities + * fix function name changed by uglify + * fixes require, closes #78 + +0.8.4 / 2013-05-08 +================== + + * fix support for colons in filter arguments + * fix double callback when the callback throws + * rename escape option + +0.8.3 / 2012-09-13 +================== + + * allow pre-compiling into a standalone function [seanmonstar] + +0.8.2 / 2012-08-16 +================== + + * fix include "open" / "close" options. Closes #64 + +0.8.1 / 2012-08-11 +================== + + * fix comments. Closes #62 [Nate Silva] + +0.8.0 / 2012-07-25 +================== + + * add `<% include file %>` support + * fix wrapping of custom require in build step. Closes #57 + +0.7.3 / 2012-04-25 +================== + + * Added repository to package.json [isaacs] + +0.7.1 / 2012-03-26 +================== + + * Fixed exception when using express in production caused by typo. [slaskis] + +0.7.0 / 2012-03-24 +================== + + * Added newline consumption support (`-%>`) [whoatemydomain] + +0.6.1 / 2011-12-09 +================== + + * Fixed `ejs.renderFile()` + +0.6.0 / 2011-12-09 +================== + + * Changed: you no longer need `{ locals: {} }` + +0.5.0 / 2011-11-20 +================== + + * Added express 3.x support + * Added ejs.renderFile() + * Added 'json' filter + * Fixed tests for 0.5.x + +0.4.3 / 2011-06-20 +================== + + * Fixed stacktraces line number when used multiline js expressions [Octave] + +0.4.2 / 2011-05-11 +================== + + * Added client side support + +0.4.1 / 2011-04-21 +================== + + * Fixed error context + +0.4.0 / 2011-04-21 +================== + + * Added; ported jade's error reporting to ejs. [slaskis] + +0.3.1 / 2011-02-23 +================== + + * Fixed optional `compile()` options + +0.3.0 / 2011-02-14 +================== + + * Added 'json' filter [Yuriy Bogdanov] + * Use exported version of parse function to allow monkey-patching [Anatoliy Chakkaev] + +0.2.1 / 2010-10-07 +================== + + * Added filter support + * Fixed _cache_ option. ~4x performance increase + +0.2.0 / 2010-08-05 +================== + + * Added support for global tag config + * Added custom tag support. Closes #5 + * Fixed whitespace bug. Closes #4 + +0.1.0 / 2010-08-04 +================== + + * Faster implementation [ashleydev] + +0.0.4 / 2010-08-02 +================== + + * Fixed single quotes for content outside of template tags. [aniero] + * Changed; `exports.compile()` now expects only "locals" + +0.0.3 / 2010-07-15 +================== + + * Fixed single quotes + +0.0.2 / 2010-07-09 +================== + + * Fixed newline preservation + +0.0.1 / 2010-07-09 +================== + + * Initial release diff --git a/node_modules/ejs/Makefile b/node_modules/ejs/Makefile new file mode 100644 index 0000000..a687a0a --- /dev/null +++ b/node_modules/ejs/Makefile @@ -0,0 +1,23 @@ + +SRC = $(shell find lib -name "*.js" -type f) +UGLIFY_FLAGS = --no-mangle + +all: ejs.min.js + +test: + @./node_modules/.bin/mocha \ + --reporter spec + +ejs.js: $(SRC) + @node support/compile.js $^ + +ejs.min.js: ejs.js + @uglifyjs $(UGLIFY_FLAGS) $< > $@ \ + && du ejs.min.js \ + && du ejs.js + +clean: + rm -f ejs.js + rm -f ejs.min.js + +.PHONY: test
\ No newline at end of file diff --git a/node_modules/ejs/Readme.md b/node_modules/ejs/Readme.md new file mode 100644 index 0000000..ab0a3dd --- /dev/null +++ b/node_modules/ejs/Readme.md @@ -0,0 +1,188 @@ +# EJS + +Embedded JavaScript templates. + +[](https://travis-ci.org/visionmedia/ejs) + +## Installation + + $ npm install ejs + +## Features + + * Complies with the [Express](http://expressjs.com) view system + * Static caching of intermediate JavaScript + * Unbuffered code for conditionals etc `<% code %>` + * Escapes html by default with `<%= code %>` + * Unescaped buffering with `<%- code %>` + * Supports tag customization + * Filter support for designer-friendly templates + * Includes + * Client-side support + * Newline slurping with `<% code -%>` or `<% -%>` or `<%= code -%>` or `<%- code -%>` + +## Example + + <% if (user) { %> + <h2><%= user.name %></h2> + <% } %> + +## Try out a live example now + +<a href="https://runnable.com/ejs" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a> + +## Usage + + ejs.compile(str, options); + // => Function + + ejs.render(str, options); + // => str + +## Options + + - `cache` Compiled functions are cached, requires `filename` + - `filename` Used by `cache` to key caches + - `scope` Function execution context + - `debug` Output generated function body + - `compileDebug` When `false` no debug instrumentation is compiled + - `client` Returns standalone compiled function + - `open` Open tag, defaulting to "<%" + - `close` Closing tag, defaulting to "%>" + - * All others are template-local variables + +## Includes + + Includes are relative to the template with the `include` statement, + for example if you have "./views/users.ejs" and "./views/user/show.ejs" + you would use `<% include user/show %>`. The included file(s) are literally + included into the template, _no_ IO is performed after compilation, thus + local variables are available to these included templates. + +``` +<ul> + <% users.forEach(function(user){ %> + <% include user/show %> + <% }) %> +</ul> +``` + +## Custom delimiters + +Custom delimiters can also be applied globally: + + var ejs = require('ejs'); + ejs.open = '{{'; + ejs.close = '}}'; + +Which would make the following a valid template: + + <h1>{{= title }}</h1> + +## Filters + +EJS conditionally supports the concept of "filters". A "filter chain" +is a designer friendly api for manipulating data, without writing JavaScript. + +Filters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters: + +Template: + + <p><%=: users | map:'name' | join %></p> + +Output: + + <p>Tj, Mape, Guillermo</p> + +Render call: + + ejs.render(str, { + users: [ + { name: 'tj' }, + { name: 'mape' }, + { name: 'guillermo' } + ] + }); + +Or perhaps capitalize the first user's name for display: + + <p><%=: users | first | capitalize %></p> + +## Filter list + +Currently these filters are available: + + - first + - last + - capitalize + - downcase + - upcase + - sort + - sort_by:'prop' + - size + - length + - plus:n + - minus:n + - times:n + - divided_by:n + - join:'val' + - truncate:n + - truncate_words:n + - replace:pattern,substitution + - prepend:val + - append:val + - map:'prop' + - reverse + - get:'prop' + +## Adding filters + + To add a filter simply add a method to the `.filters` object: + +```js +ejs.filters.last = function(obj) { + return obj[obj.length - 1]; +}; +``` + +## Layouts + + Currently EJS has no notion of blocks, only compile-time `include`s, + however you may still utilize this feature to implement "layouts" by + simply including a header and footer like so: + +```html +<% include head %> +<h1>Title</h1> +<p>My page</p> +<% include foot %> +``` + +## client-side support + + include `./ejs.js` or `./ejs.min.js` and `require("ejs").compile(str)`. + +## License + +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/ejs/benchmark.js b/node_modules/ejs/benchmark.js new file mode 100644 index 0000000..7b267e1 --- /dev/null +++ b/node_modules/ejs/benchmark.js @@ -0,0 +1,14 @@ + + +var ejs = require('./lib/ejs'), + str = '<% if (foo) { %><p><%= foo %></p><% } %>', + times = 50000; + +console.log('rendering ' + times + ' times'); + +var start = new Date; +while (times--) { + ejs.render(str, { cache: true, filename: 'test', locals: { foo: 'bar' }}); +} + +console.log('took ' + (new Date - start) + 'ms');
\ No newline at end of file diff --git a/node_modules/ejs/ejs.js b/node_modules/ejs/ejs.js new file mode 100644 index 0000000..ab44a80 --- /dev/null +++ b/node_modules/ejs/ejs.js @@ -0,0 +1,647 @@ +ejs = (function(){ + +// CommonJS require() + +function require(p){ + if ('fs' == p) return {}; + if ('path' == p) return {}; + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.substr(0, 1)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("ejs.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2012 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils') + , path = require('path') + , dirname = path.dirname + , extname = path.extname + , join = path.join + , fs = require('fs') + , read = fs.readFileSync; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.join(':') || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>' + , filename = options.filename + , compileDebug = options.compileDebug !== false + , buf = ""; + + buf += 'var buf = [];'; + if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ '; + buf += '\n buf.push(\''; + + var lineno = 1; + + var consumeEOL = false; + for (var i = 0, len = str.length; i < len; ++i) { + var stri = str[i]; + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno; + switch (str[i]) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var end = str.indexOf(close, i) + , js = str.substring(i, end) + , start = i + , include = null + , n = 0; + + if ('-' == js[js.length-1]){ + js = js.substring(0, js.length - 2); + consumeEOL = true; + } + + if (0 == js.trim().indexOf('include')) { + var name = js.trim().slice(7).trim(); + if (!filename) throw new Error('filename option is required for includes'); + var path = resolveInclude(name, filename); + include = read(path, 'utf8'); + include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug }); + buf += "' + (function(){" + include + "})() + '"; + js = ''; + } + + while (~(n = js.indexOf("\n", n))) n++, lineno++; + if (js.substr(0, 1) == ':') js = filtered(js); + if (js) { + if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n'; + buf += prefix; + buf += js; + buf += postfix; + } + i += end - start + close.length - 1; + + } else if (stri == "\\") { + buf += "\\\\"; + } else if (stri == "'") { + buf += "\\'"; + } else if (stri == "\r") { + // ignore + } else if (stri == "\n") { + if (consumeEOL) { + consumeEOL = false; + } else { + buf += "\\n"; + lineno++; + } + } else { + buf += stri; + } + } + + if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');"; + else buf += "');\nreturn buf.join('');"; + return buf; +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + var escape = options.escape || utils.escape; + + var input = JSON.stringify(str) + , compileDebug = options.compileDebug !== false + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + if (compileDebug) { + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + } else { + str = exports.parse(str, options); + } + + if (options.debug) console.log(str); + if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str; + + try { + var fn = new Function('locals, filters, escape, rethrow', str); + } catch (err) { + if ('SyntaxError' == err.name) { + err.message += options.filename + ? ' in ' + filename + : ' while compiling ejs'; + } + throw err; + } + + if (client) return fn; + + return function(locals){ + return fn.call(this, locals, filters, escape, rethrow); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + + options.__proto__ = options.locals; + return fn.call(options.scope, options); +}; + +/** + * Render an EJS file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + options.filename = path; + + var str; + try { + str = options.cache + ? cache[key] || (cache[key] = read(path, 'utf8')) + : read(path, 'utf8'); + } catch (err) { + fn(err); + return; + } + fn(null, exports.render(str, options)); +}; + +/** + * Resolve include `name` relative to `filename`. + * + * @param {String} name + * @param {String} filename + * @return {String} + * @api private + */ + +function resolveInclude(name, filename) { + var path = join(dirname(filename), name); + var ext = extname(name); + if (!ext) path += '.ejs'; + return path; +} + +// express support + +exports.__express = exports.renderFile; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function (module, filename) { + filename = filename || module.filename; + var options = { filename: filename, client: true } + , template = fs.readFileSync(filename).toString() + , fn = compile(template, options); + module._compile('module.exports = ' + fn.toString() + ';', filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} + +}); // module: ejs.js + +require.register("filters.js", function(module, exports, require){ +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len, append){ + str = String(str); + if (str.length > len) { + str = str.slice(0, len); + if (append) str += append; + } + return str; +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; + +}); // module: filters.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"'); +}; + + +}); // module: utils.js + + return require("ejs"); +})();
\ No newline at end of file diff --git a/node_modules/ejs/ejs.min.js b/node_modules/ejs/ejs.min.js new file mode 100644 index 0000000..cce06af --- /dev/null +++ b/node_modules/ejs/ejs.min.js @@ -0,0 +1 @@ +ejs=function(){function require(p){if("fs"==p)return{};if("path"==p)return{};var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');if(!mod.exports){mod.exports={};mod.call(mod.exports,mod,mod.exports,require.relative(path))}return mod.exports}require.modules={};require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig};require.register=function(path,fn){require.modules[path]=fn};require.relative=function(parent){return function(p){if("."!=p.substr(0,1))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i<segs.length;i++){var seg=segs[i];if(".."==seg)path.pop();else if("."!=seg)path.push(seg)}return require(path.join("/"))}};require.register("ejs.js",function(module,exports,require){var utils=require("./utils"),path=require("path"),dirname=path.dirname,extname=path.extname,join=path.join,fs=require("fs"),read=fs.readFileSync;var filters=exports.filters=require("./filters");var cache={};exports.clearCache=function(){cache={}};function filtered(js){return js.substr(1).split("|").reduce(function(js,filter){var parts=filter.split(":"),name=parts.shift(),args=parts.join(":")||"";if(args)args=", "+args;return"filters."+name+"("+js+args+")"})}function rethrow(err,str,filename,lineno){var lines=str.split("\n"),start=Math.max(lineno-3,0),end=Math.min(lines.length,lineno+3);var context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" >> ":" ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}var parse=exports.parse=function(str,options){var options=options||{},open=options.open||exports.open||"<%",close=options.close||exports.close||"%>",filename=options.filename,compileDebug=options.compileDebug!==false,buf="";buf+="var buf = [];";if(false!==options._with)buf+="\nwith (locals || {}) { (function(){ ";buf+="\n buf.push('";var lineno=1;var consumeEOL=false;for(var i=0,len=str.length;i<len;++i){var stri=str[i];if(str.slice(i,open.length+i)==open){i+=open.length;var prefix,postfix,line=(compileDebug?"__stack.lineno=":"")+lineno;switch(str[i]){case"=":prefix="', escape(("+line+", ";postfix=")), '";++i;break;case"-":prefix="', ("+line+", ";postfix="), '";++i;break;default:prefix="');"+line+";";postfix="; buf.push('"}var end=str.indexOf(close,i),js=str.substring(i,end),start=i,include=null,n=0;if("-"==js[js.length-1]){js=js.substring(0,js.length-2);consumeEOL=true}if(0==js.trim().indexOf("include")){var name=js.trim().slice(7).trim();if(!filename)throw new Error("filename option is required for includes");var path=resolveInclude(name,filename);include=read(path,"utf8");include=exports.parse(include,{filename:path,_with:false,open:open,close:close,compileDebug:compileDebug});buf+="' + (function(){"+include+"})() + '";js=""}while(~(n=js.indexOf("\n",n)))n++,lineno++;if(js.substr(0,1)==":")js=filtered(js);if(js){if(js.lastIndexOf("//")>js.lastIndexOf("\n"))js+="\n";buf+=prefix;buf+=js;buf+=postfix}i+=end-start+close.length-1}else if(stri=="\\"){buf+="\\\\"}else if(stri=="'"){buf+="\\'"}else if(stri=="\r"){}else if(stri=="\n"){if(consumeEOL){consumeEOL=false}else{buf+="\\n";lineno++}}else{buf+=stri}}if(false!==options._with)buf+="'); })();\n} \nreturn buf.join('');";else buf+="');\nreturn buf.join('');";return buf};var compile=exports.compile=function(str,options){options=options||{};var escape=options.escape||utils.escape;var input=JSON.stringify(str),compileDebug=options.compileDebug!==false,client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined";if(compileDebug){str=["var __stack = { lineno: 1, input: "+input+", filename: "+filename+" };",rethrow.toString(),"try {",exports.parse(str,options),"} catch (err) {"," rethrow(err, __stack.input, __stack.filename, __stack.lineno);","}"].join("\n")}else{str=exports.parse(str,options)}if(options.debug)console.log(str);if(client)str="escape = escape || "+escape.toString()+";\n"+str;try{var fn=new Function("locals, filters, escape, rethrow",str)}catch(err){if("SyntaxError"==err.name){err.message+=options.filename?" in "+filename:" while compiling ejs"}throw err}if(client)return fn;return function(locals){return fn.call(this,locals,filters,escape,rethrow)}};exports.render=function(str,options){var fn,options=options||{};if(options.cache){if(options.filename){fn=cache[options.filename]||(cache[options.filename]=compile(str,options))}else{throw new Error('"cache" option requires "filename".')}}else{fn=compile(str,options)}options.__proto__=options.locals;return fn.call(options.scope,options)};exports.renderFile=function(path,options,fn){var key=path+":string";if("function"==typeof options){fn=options,options={}}options.filename=path;var str;try{str=options.cache?cache[key]||(cache[key]=read(path,"utf8")):read(path,"utf8")}catch(err){fn(err);return}fn(null,exports.render(str,options))};function resolveInclude(name,filename){var path=join(dirname(filename),name);var ext=extname(name);if(!ext)path+=".ejs";return path}exports.__express=exports.renderFile;if(require.extensions){require.extensions[".ejs"]=function(module,filename){filename=filename||module.filename;var options={filename:filename,client:true},template=fs.readFileSync(filename).toString(),fn=compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}else if(require.registerExtension){require.registerExtension(".ejs",function(src){return compile(src,{})})}});require.register("filters.js",function(module,exports,require){exports.first=function(obj){return obj[0]};exports.last=function(obj){return obj[obj.length-1]};exports.capitalize=function(str){str=String(str);return str[0].toUpperCase()+str.substr(1,str.length)};exports.downcase=function(str){return String(str).toLowerCase()};exports.upcase=function(str){return String(str).toUpperCase()};exports.sort=function(obj){return Object.create(obj).sort()};exports.sort_by=function(obj,prop){return Object.create(obj).sort(function(a,b){a=a[prop],b=b[prop];if(a>b)return 1;if(a<b)return-1;return 0})};exports.size=exports.length=function(obj){return obj.length};exports.plus=function(a,b){return Number(a)+Number(b)};exports.minus=function(a,b){return Number(a)-Number(b)};exports.times=function(a,b){return Number(a)*Number(b)};exports.divided_by=function(a,b){return Number(a)/Number(b)};exports.join=function(obj,str){return obj.join(str||", ")};exports.truncate=function(str,len,append){str=String(str);if(str.length>len){str=str.slice(0,len);if(append)str+=append}return str};exports.truncate_words=function(str,n){var str=String(str),words=str.split(/ +/);return words.slice(0,n).join(" ")};exports.replace=function(str,pattern,substitution){return String(str).replace(pattern,substitution||"")};exports.prepend=function(obj,val){return Array.isArray(obj)?[val].concat(obj):val+obj};exports.append=function(obj,val){return Array.isArray(obj)?obj.concat(val):obj+val};exports.map=function(arr,prop){return arr.map(function(obj){return obj[prop]})};exports.reverse=function(obj){return Array.isArray(obj)?obj.reverse():String(obj).split("").reverse().join("")};exports.get=function(obj,prop){return obj[prop]};exports.json=function(obj){return JSON.stringify(obj)}});require.register("utils.js",function(module,exports,require){exports.escape=function(html){return String(html).replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""")}});return require("ejs")}();
\ No newline at end of file diff --git a/node_modules/ejs/examples/client.html b/node_modules/ejs/examples/client.html new file mode 100644 index 0000000..30dfea9 --- /dev/null +++ b/node_modules/ejs/examples/client.html @@ -0,0 +1,24 @@ +<html> + <head> + <script src="../ejs.js"></script> + <script id="users" type="text/template"> + <% if (names.length) { %> + <ul> + <% names.forEach(function(name){ %> + <li><%= name %></li> + <% }) %> + </ul> + <% } %> + </script> + <script> + onload = function(){ + var users = document.getElementById('users').innerHTML; + var names = ['loki', 'tobi', 'jane']; + var html = ejs.render(users, { names: names }); + document.body.innerHTML = html; + } + </script> + </head> + <body> + </body> +</html>
\ No newline at end of file diff --git a/node_modules/ejs/examples/functions.ejs b/node_modules/ejs/examples/functions.ejs new file mode 100644 index 0000000..bd5610e --- /dev/null +++ b/node_modules/ejs/examples/functions.ejs @@ -0,0 +1,9 @@ +<h1>Users</h1> + +<% function user(user) { %> + <li><strong><%= user.name %></strong> is a <%= user.age %> year old <%= user.species %>.</li> +<% } %> + +<ul> + <% users.map(user) %> +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/examples/functions.js b/node_modules/ejs/examples/functions.js new file mode 100644 index 0000000..607833f --- /dev/null +++ b/node_modules/ejs/examples/functions.js @@ -0,0 +1,22 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , fs = require('fs') + , path = __dirname + '/functions.ejs' + , str = fs.readFileSync(path, 'utf8'); + +var users = []; + +users.push({ name: 'Tobi', age: 2, species: 'ferret' }) +users.push({ name: 'Loki', age: 2, species: 'ferret' }) +users.push({ name: 'Jane', age: 6, species: 'ferret' }) + +var ret = ejs.render(str, { + users: users, + filename: path +}); + +console.log(ret);
\ No newline at end of file diff --git a/node_modules/ejs/examples/list.ejs b/node_modules/ejs/examples/list.ejs new file mode 100644 index 0000000..0b378a9 --- /dev/null +++ b/node_modules/ejs/examples/list.ejs @@ -0,0 +1,7 @@ +<% if (names.length) { %> + <ul> + <% names.forEach(function(name){ %> + <li foo='<%= name + "'" %>'><%= name %></li> + <% }) %> + </ul> +<% } %>
\ No newline at end of file diff --git a/node_modules/ejs/examples/list.js b/node_modules/ejs/examples/list.js new file mode 100644 index 0000000..ec614ed --- /dev/null +++ b/node_modules/ejs/examples/list.js @@ -0,0 +1,14 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , fs = require('fs') + , str = fs.readFileSync(__dirname + '/list.ejs', 'utf8'); + +var ret = ejs.render(str, { + names: ['foo', 'bar', 'baz'] +}); + +console.log(ret);
\ No newline at end of file diff --git a/node_modules/ejs/index.js b/node_modules/ejs/index.js new file mode 100644 index 0000000..20bf71a --- /dev/null +++ b/node_modules/ejs/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/ejs');
\ No newline at end of file diff --git a/node_modules/ejs/lib/ejs.js b/node_modules/ejs/lib/ejs.js new file mode 100644 index 0000000..f36944f --- /dev/null +++ b/node_modules/ejs/lib/ejs.js @@ -0,0 +1,357 @@ + +/*! + * EJS + * Copyright(c) 2012 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils') + , path = require('path') + , dirname = path.dirname + , extname = path.extname + , join = path.join + , fs = require('fs') + , read = fs.readFileSync; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.join(':') || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>' + , filename = options.filename + , compileDebug = options.compileDebug !== false + , buf = ""; + + buf += 'var buf = [];'; + if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ '; + buf += '\n buf.push(\''; + + var lineno = 1; + + var consumeEOL = false; + for (var i = 0, len = str.length; i < len; ++i) { + var stri = str[i]; + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno; + switch (str[i]) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var end = str.indexOf(close, i) + , js = str.substring(i, end) + , start = i + , include = null + , n = 0; + + if ('-' == js[js.length-1]){ + js = js.substring(0, js.length - 2); + consumeEOL = true; + } + + if (0 == js.trim().indexOf('include')) { + var name = js.trim().slice(7).trim(); + if (!filename) throw new Error('filename option is required for includes'); + var path = resolveInclude(name, filename); + include = read(path, 'utf8'); + include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug }); + buf += "' + (function(){" + include + "})() + '"; + js = ''; + } + + while (~(n = js.indexOf("\n", n))) n++, lineno++; + if (js.substr(0, 1) == ':') js = filtered(js); + if (js) { + if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n'; + buf += prefix; + buf += js; + buf += postfix; + } + i += end - start + close.length - 1; + + } else if (stri == "\\") { + buf += "\\\\"; + } else if (stri == "'") { + buf += "\\'"; + } else if (stri == "\r") { + // ignore + } else if (stri == "\n") { + if (consumeEOL) { + consumeEOL = false; + } else { + buf += "\\n"; + lineno++; + } + } else { + buf += stri; + } + } + + if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');"; + else buf += "');\nreturn buf.join('');"; + return buf; +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + var escape = options.escape || utils.escape; + + var input = JSON.stringify(str) + , compileDebug = options.compileDebug !== false + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + if (compileDebug) { + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + } else { + str = exports.parse(str, options); + } + + if (options.debug) console.log(str); + if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str; + + try { + var fn = new Function('locals, filters, escape, rethrow', str); + } catch (err) { + if ('SyntaxError' == err.name) { + err.message += options.filename + ? ' in ' + filename + : ' while compiling ejs'; + } + throw err; + } + + if (client) return fn; + + return function(locals){ + return fn.call(this, locals, filters, escape, rethrow); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + + options.__proto__ = options.locals; + return fn.call(options.scope, options); +}; + +/** + * Render an EJS file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + options.filename = path; + + var str; + try { + str = options.cache + ? cache[key] || (cache[key] = read(path, 'utf8')) + : read(path, 'utf8'); + } catch (err) { + fn(err); + return; + } + fn(null, exports.render(str, options)); +}; + +/** + * Resolve include `name` relative to `filename`. + * + * @param {String} name + * @param {String} filename + * @return {String} + * @api private + */ + +function resolveInclude(name, filename) { + var path = join(dirname(filename), name); + var ext = extname(name); + if (!ext) path += '.ejs'; + return path; +} + +// express support + +exports.__express = exports.renderFile; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function (module, filename) { + filename = filename || module.filename; + var options = { filename: filename, client: true } + , template = fs.readFileSync(filename).toString() + , fn = compile(template, options); + module._compile('module.exports = ' + fn.toString() + ';', filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} diff --git a/node_modules/ejs/lib/filters.js b/node_modules/ejs/lib/filters.js new file mode 100644 index 0000000..45b0478 --- /dev/null +++ b/node_modules/ejs/lib/filters.js @@ -0,0 +1,201 @@ +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len, append){ + str = String(str); + if (str.length > len) { + str = str.slice(0, len); + if (append) str += append; + } + return str; +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; diff --git a/node_modules/ejs/lib/utils.js b/node_modules/ejs/lib/utils.js new file mode 100644 index 0000000..8df6c6a --- /dev/null +++ b/node_modules/ejs/lib/utils.js @@ -0,0 +1,24 @@ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca> + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"'); +}; + diff --git a/node_modules/ejs/package.json b/node_modules/ejs/package.json new file mode 100644 index 0000000..627896b --- /dev/null +++ b/node_modules/ejs/package.json @@ -0,0 +1,51 @@ +{ + "name": "ejs", + "description": "Embedded JavaScript templates", + "version": "0.8.8", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "keywords": [ + "template", + "engine", + "ejs" + ], + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "./lib/ejs.js", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/ejs.git" + }, + "scripts": { + "test": "mocha --require should --reporter spec" + }, + "bugs": { + "url": "https://github.com/visionmedia/ejs/issues" + }, + "homepage": "https://github.com/visionmedia/ejs", + "_id": "ejs@0.8.8", + "dist": { + "shasum": "ffdc56dcc35d02926dd50ad13439bbc54061d598", + "tarball": "http://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz" + }, + "_from": "ejs@>=0.8.5 <0.9.0", + "_npmVersion": "1.4.6", + "_npmUser": { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "directories": {}, + "_shasum": "ffdc56dcc35d02926dd50ad13439bbc54061d598", + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/ejs/support/compile.js b/node_modules/ejs/support/compile.js new file mode 100644 index 0000000..6d3a5eb --- /dev/null +++ b/node_modules/ejs/support/compile.js @@ -0,0 +1,177 @@ + +/** + * Module dependencies. + */ + +var fs = require('fs'); + +/** + * Arguments. + */ + +var args = process.argv.slice(2) + , pending = args.length + , files = {}; + +console.log(''); + +// parse arguments + +args.forEach(function(file){ + var mod = file.replace('lib/', ''); + fs.readFile(file, 'utf8', function(err, js){ + if (err) throw err; + console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file); + files[file] = parse(js); + --pending || compile(); + }); +}); + +/** + * Parse the given `js`. + */ + +function parse(js) { + return parseInheritance(parseConditionals(js)); +} + +/** + * Parse __proto__. + */ + +function parseInheritance(js) { + return js + .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){ + return child + '.prototype = new ' + parent + ';\n' + + child + '.prototype.constructor = '+ child + ';\n'; + }); +} + +/** + * Parse the given `js`, currently supporting: + * + * 'if' ['node' | 'browser'] + * 'end' + * + */ + +function parseConditionals(js) { + var lines = js.split('\n') + , len = lines.length + , buffer = true + , browser = false + , buf = [] + , line + , cond; + + for (var i = 0; i < len; ++i) { + line = lines[i]; + if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) { + cond = RegExp.$1; + buffer = browser = 'browser' == cond; + } else if (/^ *\/\/ *end/.test(line)) { + buffer = true; + browser = false; + } else if (browser) { + buf.push(line.replace(/^( *)\/\//, '$1')); + } else if (buffer) { + buf.push(line); + } + } + + return buf.join('\n'); +} + +/** + * Compile the files. + */ + +function compile() { + var buf = ''; + buf += 'ejs = (function(){\n'; + buf += '\n// CommonJS require()\n\n'; + buf += browser.require + '\n\n'; + buf += 'require.modules = {};\n\n'; + buf += 'require.resolve = ' + browser.resolve + ';\n\n'; + buf += 'require.register = ' + browser.register + ';\n\n'; + buf += 'require.relative = ' + browser.relative + ';\n\n'; + args.forEach(function(file){ + var js = files[file]; + file = file.replace('lib/', ''); + buf += '\nrequire.register("' + file + '", function(module, exports, require){\n'; + buf += js; + buf += '\n}); // module: ' + file + '\n'; + }); + buf += '\n return require("ejs");\n})();'; + fs.writeFile('ejs.js', buf, function(err){ + if (err) throw err; + console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js'); + console.log(); + }); +} + +// refactored version of weepy's +// https://github.com/weepy/brequire/blob/master/browser/brequire.js + +var browser = { + + /** + * Require a module. + */ + + require: function require(p){ + if ('fs' == p) return {}; + if ('path' == p) return {}; + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + }, + + /** + * Resolve module path. + */ + + resolve: function(path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }, + + /** + * Return relative require(). + */ + + relative: function(parent) { + return function(p){ + if ('.' != p.substr(0, 1)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }, + + /** + * Register a module. + */ + + register: function(path, fn){ + require.modules[path] = fn; + } +};
\ No newline at end of file diff --git a/node_modules/ejs/test/ejs.js b/node_modules/ejs/test/ejs.js new file mode 100644 index 0000000..7df7ace --- /dev/null +++ b/node_modules/ejs/test/ejs.js @@ -0,0 +1,306 @@ +/** + * Module dependencies. + */ + +var ejs = require('..') + , fs = require('fs') + , read = fs.readFileSync + , assert = require('should'); + +/** + * Load fixture `name`. + */ + +function fixture(name) { + return read('test/fixtures/' + name, 'utf8').replace(/\r/g, ''); +} + +/** + * User fixtures. + */ + +var users = []; +users.push({ name: 'tobi' }); +users.push({ name: 'loki' }); +users.push({ name: 'jane' }); + +describe('ejs.compile(str, options)', function(){ + it('should compile to a function', function(){ + var fn = ejs.compile('<p>yay</p>'); + fn().should.equal('<p>yay</p>'); + }) + + it('should throw if there are syntax errors', function(){ + try { + ejs.compile(fixture('fail.ejs')); + } catch (err) { + err.message.should.include('compiling ejs'); + + try { + ejs.compile(fixture('fail.ejs'), { filename: 'fail.ejs' }); + } catch (err) { + err.message.should.include('fail.ejs'); + return; + } + } + + assert(false, 'compiling a file with invalid syntax should throw an exception'); + }) + + it('should allow customizing delimiters', function(){ + var fn = ejs.compile('<p>{= name }</p>', { open: '{', close: '}' }); + fn({ name: 'tobi' }).should.equal('<p>tobi</p>'); + + var fn = ejs.compile('<p>::= name ::</p>', { open: '::', close: '::' }); + fn({ name: 'tobi' }).should.equal('<p>tobi</p>'); + + var fn = ejs.compile('<p>(= name )</p>', { open: '(', close: ')' }); + fn({ name: 'tobi' }).should.equal('<p>tobi</p>'); + }) + + it('should default to using ejs.open and ejs.close', function(){ + ejs.open = '{'; + ejs.close = '}'; + var fn = ejs.compile('<p>{= name }</p>'); + fn({ name: 'tobi' }).should.equal('<p>tobi</p>'); + + var fn = ejs.compile('<p>|= name |</p>', { open: '|', close: '|' }); + fn({ name: 'tobi' }).should.equal('<p>tobi</p>'); + delete ejs.open; + delete ejs.close; + }) + + it('should have a working client option', function(){ + var fn = ejs.compile('<p><%= foo %></p>', { client: true }); + var str = fn.toString(); + eval('var preFn = ' + str); + preFn({ foo: 'bar' }).should.equal('<p>bar</p>'); + }) +}) + +describe('ejs.render(str, options)', function(){ + it('should render the template', function(){ + ejs.render('<p>yay</p>') + .should.equal('<p>yay</p>'); + }) + + it('should accept locals', function(){ + ejs.render('<p><%= name %></p>', { name: 'tobi' }) + .should.equal('<p>tobi</p>'); + }) +}) + +describe('ejs.renderFile(path, options, fn)', function(){ + it('should render a file', function(done){ + ejs.renderFile('test/fixtures/para.ejs', function(err, html){ + if (err) return done(err); + html.should.equal('<p>hey</p>'); + done(); + }); + }) + + it('should accept locals', function(done){ + var options = { name: 'tj', open: '{', close: '}' }; + ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ + if (err) return done(err); + html.should.equal('<h1>tj</h1>'); + done(); + }); + }) + + it('should not catch err threw by callback', function(done){ + var options = { name: 'tj', open: '{', close: '}' }; + var counter = 0; + try { + ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ + counter++; + if (err) { + err.message.should.not.equal('Exception in callback'); + return done(err); + } + throw new Error('Exception in callback'); + }); + } catch (err) { + counter.should.equal(1); + err.message.should.equal('Exception in callback'); + done(); + } + }) +}) + +describe('<%=', function(){ + it('should escape <script>', function(){ + ejs.render('<%= name %>', { name: '<script>' }) + .should.equal('<script>'); + }) + it("should escape '", function(){ + ejs.render('<%= name %>', { name: "The Jones's" }) + .should.equal('The Jones's'); + }) + it("shouldn't escape &", function(){ + ejs.render('<%= name %>', { name: "Us & Them" }) + .should.equal('Us & Them'); + }) + it("shouldn't escape ]", function(){ + ejs.render('<%= name %>', { name: "The Jones's" }) + .should.equal('The Jones's'); + }) + it("should escape &foo_bar;", function(){ + ejs.render('<%= name %>', { name: "&foo_bar;" }) + .should.equal('&foo_bar;'); + }) +}) + +describe('<%-', function(){ + it('should not escape', function(){ + ejs.render('<%- name %>', { name: '<script>' }) + .should.equal('<script>'); + }) +}) + +describe('%>', function(){ + it('should produce newlines', function(){ + ejs.render(fixture('newlines.ejs'), { users: users }) + .should.equal(fixture('newlines.html')); + }) +}) + +describe('-%>', function(){ + it('should not produce newlines', function(){ + ejs.render(fixture('no.newlines.ejs'), { users: users }) + .should.equal(fixture('no.newlines.html')); + }) +}) + +describe('single quotes', function(){ + it('should not mess up the constructed function', function(){ + ejs.render(fixture('single-quote.ejs')) + .should.equal(fixture('single-quote.html')); + }) +}) + +describe('double quotes', function(){ + it('should not mess up the constructed function', function(){ + ejs.render(fixture('double-quote.ejs')) + .should.equal(fixture('double-quote.html')); + }) +}) + +describe('backslashes', function(){ + it('should escape', function(){ + ejs.render(fixture('backslash.ejs')) + .should.equal(fixture('backslash.html')); + }) +}) + +describe('messed up whitespace', function(){ + it('should work', function(){ + ejs.render(fixture('messed.ejs'), { users: users }) + .should.equal(fixture('messed.html')); + }) +}) + +describe('filters', function(){ + it('should work', function(){ + var items = ['foo', 'bar', 'baz']; + ejs.render('<%=: items | reverse | first | reverse | capitalize %>', { items: items }) + .should.equal('Zab'); + }) + + it('should accept arguments', function(){ + ejs.render('<%=: users | map:"name" | join:", " %>', { users: users }) + .should.equal('tobi, loki, jane'); + }) + + it('should truncate string', function(){ + ejs.render('<%=: word | truncate: 3 %>', { word: 'World' }) + .should.equal('Wor'); + }) + + it('should append string if string is longer', function(){ + ejs.render('<%=: word | truncate: 2,"..." %>', { word: 'Testing' }) + .should.equal('Te...'); + }) + + it('should not append string if string is shorter', function(){ + ejs.render('<%=: word | truncate: 10,"..." %>', { word: 'Testing' }) + .should.equal('Testing'); + }) + + it('should accept arguments containing :', function(){ + ejs.render('<%=: users | map:"name" | join:"::" %>', { users: users }) + .should.equal('tobi::loki::jane'); + }) +}) + +describe('exceptions', function(){ + it('should produce useful stack traces', function(done){ + try { + ejs.render(fixture('error.ejs'), { filename: 'error.ejs' }); + } catch (err) { + err.path.should.equal('error.ejs'); + err.stack.split('\n').slice(0, 8).join('\n').should.equal(fixture('error.out')); + done(); + } + }) + + it('should not include __stack if compileDebug is false', function() { + try { + ejs.render(fixture('error.ejs'), { + filename: 'error.ejs', + compileDebug: false + }); + } catch (err) { + err.should.not.have.property('path'); + err.stack.split('\n').slice(0, 8).join('\n').should.not.equal(fixture('error.out')); + } + }); +}) + +describe('includes', function(){ + it('should include ejs', function(){ + var file = 'test/fixtures/include.ejs'; + ejs.render(fixture('include.ejs'), { filename: file, pets: users, open: '[[', close: ']]' }) + .should.equal(fixture('include.html')); + }) + + it('should work when nested', function(){ + var file = 'test/fixtures/menu.ejs'; + ejs.render(fixture('menu.ejs'), { filename: file, pets: users }) + .should.equal(fixture('menu.html')); + }) + + it('should include arbitrary files as-is', function(){ + var file = 'test/fixtures/include.css.ejs'; + ejs.render(fixture('include.css.ejs'), { filename: file, pets: users }) + .should.equal(fixture('include.css.html')); + }) + + it('should pass compileDebug to include', function(){ + var file = 'test/fixtures/include.ejs'; + var fn = ejs.compile(fixture('include.ejs'), { filename: file, open: '[[', close: ']]', compileDebug: false, client: true }) + var str = fn.toString(); + eval('var preFn = ' + str); + str.should.not.match(/__stack/); + (function() { + preFn({ pets: users }); + }).should.not.throw(); + }) +}) + +describe('comments', function() { + it('should fully render with comments removed', function() { + ejs.render(fixture('comments.ejs')) + .should.equal(fixture('comments.html')); + }) +}) + + +describe('require', function() { + it('should allow ejs templates to be required as node modules', function() { + var file = 'test/fixtures/include.ejs' + , template = require(__dirname + '/fixtures/menu.ejs'); + template({ filename: file, pets: users }) + .should.equal(fixture('menu.html')); + }) +}) diff --git a/node_modules/ejs/test/fixtures/backslash.ejs b/node_modules/ejs/test/fixtures/backslash.ejs new file mode 100644 index 0000000..eeb4a48 --- /dev/null +++ b/node_modules/ejs/test/fixtures/backslash.ejs @@ -0,0 +1 @@ +\foo
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/backslash.html b/node_modules/ejs/test/fixtures/backslash.html new file mode 100644 index 0000000..eeb4a48 --- /dev/null +++ b/node_modules/ejs/test/fixtures/backslash.html @@ -0,0 +1 @@ +\foo
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/comments.ejs b/node_modules/ejs/test/fixtures/comments.ejs new file mode 100644 index 0000000..ba34b0a --- /dev/null +++ b/node_modules/ejs/test/fixtures/comments.ejs @@ -0,0 +1,5 @@ +<li><a href="foo"><% // double-slash comment %>foo</li> +<li><a href="bar"><% /* C-style comment */ %>bar</li> +<li><a href="baz"><% // double-slash comment with newline + %>baz</li> +<li><a href="qux"><% var x = 'qux'; // double-slash comment @ end of line %><%= x %></li>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/comments.html b/node_modules/ejs/test/fixtures/comments.html new file mode 100644 index 0000000..f728923 --- /dev/null +++ b/node_modules/ejs/test/fixtures/comments.html @@ -0,0 +1,4 @@ +<li><a href="foo">foo</li> +<li><a href="bar">bar</li> +<li><a href="baz">baz</li> +<li><a href="qux">qux</li>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/double-quote.ejs b/node_modules/ejs/test/fixtures/double-quote.ejs new file mode 100644 index 0000000..3bccdcf --- /dev/null +++ b/node_modules/ejs/test/fixtures/double-quote.ejs @@ -0,0 +1 @@ +<p><%= "lo" + 'ki' %>'s "wheelchair"</p>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/double-quote.html b/node_modules/ejs/test/fixtures/double-quote.html new file mode 100644 index 0000000..6473979 --- /dev/null +++ b/node_modules/ejs/test/fixtures/double-quote.html @@ -0,0 +1 @@ +<p>loki's "wheelchair"</p>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/error.ejs b/node_modules/ejs/test/fixtures/error.ejs new file mode 100644 index 0000000..f032730 --- /dev/null +++ b/node_modules/ejs/test/fixtures/error.ejs @@ -0,0 +1,5 @@ +<ul> + <% if (users) { %> + <p>Has users</p> + <% } %> +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/error.out b/node_modules/ejs/test/fixtures/error.out new file mode 100644 index 0000000..a2c9108 --- /dev/null +++ b/node_modules/ejs/test/fixtures/error.out @@ -0,0 +1,8 @@ +ReferenceError: error.ejs:2 + 1| <ul> + >> 2| <% if (users) { %> + 3| <p>Has users</p> + 4| <% } %> + 5| </ul> + +users is not defined
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/fail.ejs b/node_modules/ejs/test/fixtures/fail.ejs new file mode 100644 index 0000000..1a7a0f7 --- /dev/null +++ b/node_modules/ejs/test/fixtures/fail.ejs @@ -0,0 +1 @@ +<% function foo() return 'foo'; %>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/include.css.ejs b/node_modules/ejs/test/fixtures/include.css.ejs new file mode 100644 index 0000000..f47358b --- /dev/null +++ b/node_modules/ejs/test/fixtures/include.css.ejs @@ -0,0 +1 @@ +<style><% var value = 'bar' %><% include style.css %></style>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/include.css.html b/node_modules/ejs/test/fixtures/include.css.html new file mode 100644 index 0000000..43343fe --- /dev/null +++ b/node_modules/ejs/test/fixtures/include.css.html @@ -0,0 +1,3 @@ +<style>body { + foo: 'bar'; +}</style>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/include.ejs b/node_modules/ejs/test/fixtures/include.ejs new file mode 100644 index 0000000..8017337 --- /dev/null +++ b/node_modules/ejs/test/fixtures/include.ejs @@ -0,0 +1,5 @@ +<ul> + [[ pets.forEach(function(pet){ ]] + [[ include pet ]] + [[ }) ]] +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/include.html b/node_modules/ejs/test/fixtures/include.html new file mode 100644 index 0000000..ca3e298 --- /dev/null +++ b/node_modules/ejs/test/fixtures/include.html @@ -0,0 +1,9 @@ +<ul> + + <li>tobi</li> + + <li>loki</li> + + <li>jane</li> + +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/includes/menu-item.ejs b/node_modules/ejs/test/fixtures/includes/menu-item.ejs new file mode 100644 index 0000000..37cca5f --- /dev/null +++ b/node_modules/ejs/test/fixtures/includes/menu-item.ejs @@ -0,0 +1 @@ +<li><% include menu/item %></li>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/includes/menu/item.ejs b/node_modules/ejs/test/fixtures/includes/menu/item.ejs new file mode 100644 index 0000000..8abc3fe --- /dev/null +++ b/node_modules/ejs/test/fixtures/includes/menu/item.ejs @@ -0,0 +1 @@ +<a href="/<%= url %>"><%= title %></a>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/menu.ejs b/node_modules/ejs/test/fixtures/menu.ejs new file mode 100644 index 0000000..61fad41 --- /dev/null +++ b/node_modules/ejs/test/fixtures/menu.ejs @@ -0,0 +1,11 @@ +<% var url = '/foo' -%> +<% var title = 'Foo' -%> +<% include includes/menu-item -%> + +<% var url = '/bar' -%> +<% var title = 'Bar' -%> +<% include includes/menu-item -%> + +<% var url = '/baz' -%> +<% var title = 'Baz' -%> +<% include includes/menu-item -%>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/menu.html b/node_modules/ejs/test/fixtures/menu.html new file mode 100644 index 0000000..1f9e45f --- /dev/null +++ b/node_modules/ejs/test/fixtures/menu.html @@ -0,0 +1,3 @@ +<li><a href="//foo">Foo</a></li> +<li><a href="//bar">Bar</a></li> +<li><a href="//baz">Baz</a></li>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/messed.ejs b/node_modules/ejs/test/fixtures/messed.ejs new file mode 100644 index 0000000..7d69033 --- /dev/null +++ b/node_modules/ejs/test/fixtures/messed.ejs @@ -0,0 +1 @@ +<ul><%users.forEach(function(user){%><li><%=user.name%></li><%})%></ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/messed.html b/node_modules/ejs/test/fixtures/messed.html new file mode 100644 index 0000000..1e49148 --- /dev/null +++ b/node_modules/ejs/test/fixtures/messed.html @@ -0,0 +1 @@ +<ul><li>tobi</li><li>loki</li><li>jane</li></ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/newlines.ejs b/node_modules/ejs/test/fixtures/newlines.ejs new file mode 100644 index 0000000..47401b2 --- /dev/null +++ b/node_modules/ejs/test/fixtures/newlines.ejs @@ -0,0 +1,5 @@ +<ul> + <% users.forEach(function(user){ %> + <li><%= user.name %></li> + <% }) %> +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/newlines.html b/node_modules/ejs/test/fixtures/newlines.html new file mode 100644 index 0000000..ca3e298 --- /dev/null +++ b/node_modules/ejs/test/fixtures/newlines.html @@ -0,0 +1,9 @@ +<ul> + + <li>tobi</li> + + <li>loki</li> + + <li>jane</li> + +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/no.newlines.ejs b/node_modules/ejs/test/fixtures/no.newlines.ejs new file mode 100644 index 0000000..029b461 --- /dev/null +++ b/node_modules/ejs/test/fixtures/no.newlines.ejs @@ -0,0 +1,5 @@ +<ul> + <% users.forEach(function(user){ -%> + <li><%= user.name %></li> + <% }) -%> +</ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/no.newlines.html b/node_modules/ejs/test/fixtures/no.newlines.html new file mode 100644 index 0000000..6efee2c --- /dev/null +++ b/node_modules/ejs/test/fixtures/no.newlines.html @@ -0,0 +1,5 @@ +<ul> + <li>tobi</li> + <li>loki</li> + <li>jane</li> + </ul>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/para.ejs b/node_modules/ejs/test/fixtures/para.ejs new file mode 100644 index 0000000..89da779 --- /dev/null +++ b/node_modules/ejs/test/fixtures/para.ejs @@ -0,0 +1 @@ +<p>hey</p>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/pet.ejs b/node_modules/ejs/test/fixtures/pet.ejs new file mode 100644 index 0000000..5788558 --- /dev/null +++ b/node_modules/ejs/test/fixtures/pet.ejs @@ -0,0 +1 @@ +<li>[[= pet.name ]]</li>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/single-quote.ejs b/node_modules/ejs/test/fixtures/single-quote.ejs new file mode 100644 index 0000000..1e35a95 --- /dev/null +++ b/node_modules/ejs/test/fixtures/single-quote.ejs @@ -0,0 +1 @@ +<p><%= 'loki' %>'s wheelchair</p>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/single-quote.html b/node_modules/ejs/test/fixtures/single-quote.html new file mode 100644 index 0000000..3125173 --- /dev/null +++ b/node_modules/ejs/test/fixtures/single-quote.html @@ -0,0 +1 @@ +<p>loki's wheelchair</p>
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/style.css b/node_modules/ejs/test/fixtures/style.css new file mode 100644 index 0000000..1630b8c --- /dev/null +++ b/node_modules/ejs/test/fixtures/style.css @@ -0,0 +1,3 @@ +body { + foo: '<%= value %>'; +}
\ No newline at end of file diff --git a/node_modules/ejs/test/fixtures/user.ejs b/node_modules/ejs/test/fixtures/user.ejs new file mode 100644 index 0000000..b312b5d --- /dev/null +++ b/node_modules/ejs/test/fixtures/user.ejs @@ -0,0 +1 @@ +<h1>{= name}</h1>
\ No newline at end of file |
