From 2a2ec3c100d1f8fc230d73fe0069bca98bdde0f4 Mon Sep 17 00:00:00 2001 From: Martin Donnelly Date: Tue, 18 Jul 2017 12:42:39 +0100 Subject: [PATCH] updated npm --- node_modules/ejs/Jakefile | 79 +- node_modules/ejs/README.md | 53 +- node_modules/ejs/ejs.js | 768 ++++++++++++------ node_modules/ejs/ejs.min.js | 2 +- node_modules/ejs/lib/ejs.js | 554 +++++++------ node_modules/ejs/lib/utils.js | 45 +- node_modules/ejs/package.json | 78 +- node_modules/ejs/test/ejs.js | 345 +++++--- .../ejs/test/fixtures/no.newlines.error.ejs | 2 +- node_modules/express/History.md | 208 +++++ node_modules/express/Readme.md | 7 +- node_modules/express/lib/application.js | 17 +- node_modules/express/lib/express.js | 12 +- node_modules/express/lib/request.js | 78 +- node_modules/express/lib/response.js | 63 +- node_modules/express/lib/router/index.js | 55 +- node_modules/express/lib/router/route.js | 10 +- node_modules/express/lib/utils.js | 9 +- node_modules/express/lib/view.js | 4 +- node_modules/express/package.json | 180 ++-- node_modules/lodash/package.json | 9 +- node_modules/rss-braider/.npmignore | 80 +- node_modules/rss-braider/README.md | 9 +- node_modules/rss-braider/examples/simple.js | 4 +- node_modules/rss-braider/lib/RssBraider.js | 346 ++++---- node_modules/rss-braider/package.json | 75 +- .../test/expected_output/dateAscOutput.xml | 17 +- .../test/expected_output/dateDescOutput.xml | 15 +- .../test/expected_output/emptyFeed.xml | 3 +- .../expected_output/fileFeedBadPlugin.xml | 3 +- .../test/expected_output/fileFeedOutput.xml | 7 +- .../expected_output/fileFeedOutputPlugins.xml | 7 +- node_modules/rss-braider/test/index.js | 1 - package.json | 46 +- test/BAEBF3BDF82B8FEF.rss | 1 + 35 files changed, 1982 insertions(+), 1210 deletions(-) create mode 100644 test/BAEBF3BDF82B8FEF.rss diff --git a/node_modules/ejs/Jakefile b/node_modules/ejs/Jakefile index 28defba..ec3defd 100644 --- a/node_modules/ejs/Jakefile +++ b/node_modules/ejs/Jakefile @@ -1,10 +1,12 @@ -var fs = require('fs') - , buildOpts = { - printStdout: true - , printStderr: true - }; +var fs = require('fs'); +var execSync = require('child_process').execSync; +var exec = function (cmd) { + execSync(cmd, {stdio: 'inherit'}); +}; -task('build', ['browserify', 'minify'], function () { +/* global jake, task, desc, publishTask */ + +task('build', ['lint', 'clean', 'browserify', 'minify'], function () { console.log('Build completed.'); }); @@ -12,35 +14,58 @@ desc('Cleans browerified/minified files and package files'); task('clean', ['clobber'], function () { jake.rmRf('./ejs.js'); jake.rmRf('./ejs.min.js'); + console.log('Cleaned up compiled files.'); }); -task('browserify', {async: true}, function () { - jake.exec('./node_modules/browserify/bin/cmd.js lib/ejs.js > ejs.js', - buildOpts, function () { - console.log('Browserification completed.'); - setTimeout(complete, 0); - }); +desc('Lints the source code'); +task('lint', function () { + exec('./node_modules/.bin/eslint \"**/*.js\" Jakefile'); + console.log('Linting completed.'); }); -task('minify', {async: true}, function () { - jake.exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js', - buildOpts, function () { - console.log('Minification completed.'); - setTimeout(complete, 0); - }); +task('browserify', function () { + exec('./node_modules/browserify/bin/cmd.js --standalone ejs lib/ejs.js > ejs.js'); + console.log('Browserification completed.'); +}); + +task('minify', function () { + exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js'); + console.log('Minification completed.'); +}); + +task('doc', function (dev) { + jake.rmRf('out'); + var p = dev ? '-p' : ''; + exec('./node_modules/.bin/jsdoc ' + p + ' -c jsdoc.json lib/* docs/jsdoc/*'); + console.log('Documentation generated.'); +}); + +task('docPublish', ['doc'], function () { + fs.writeFileSync('out/CNAME', 'api.ejs.co'); + console.log('Pushing docs to gh-pages...'); + exec('./node_modules/.bin/git-directory-deploy --directory out/'); + console.log('Docs published to gh-pages.'); +}); + +task('test', ['lint'], function () { + exec('./node_modules/.bin/mocha'); }); publishTask('ejs', ['build'], function () { this.packageFiles.include([ - 'Jakefile' - , 'README.md' - , 'LICENSE' - , 'package.json' - , 'ejs.js' - , 'ejs.min.js' - , 'lib/**' - , 'test/**' + 'Jakefile', + 'README.md', + 'LICENSE', + 'package.json', + 'ejs.js', + 'ejs.min.js', + 'lib/**', + 'test/**' ]); }); - +jake.Task.publish.on('complete', function () { + console.log('Updating hosted docs...'); + console.log('If this fails, run jake docPublish to re-try.'); + jake.Task.docPublish.invoke(); +}); diff --git a/node_modules/ejs/README.md b/node_modules/ejs/README.md index b88b7b4..1f3b9c7 100644 --- a/node_modules/ejs/README.md +++ b/node_modules/ejs/README.md @@ -3,7 +3,7 @@ Embedded JavaScript templates [![Build Status](https://img.shields.io/travis/mde/ejs/master.svg?style=flat)](https://travis-ci.org/mde/ejs) -[![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs#info=devDependencies) +[![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs?type=dev) ## Installation @@ -18,7 +18,7 @@ $ npm install ejs * Unescaped raw output with `<%- %>` * Newline-trim mode ('newline slurping') with `-%>` ending tag * Whitespace-trim mode (slurp all whitespace) for control flow with `<%_ _%>` - * Custom delimiters (e.g., use '' instead of '<% %>') + * Custom delimiters (e.g., use `` instead of `<% %>`) * Includes * Client-side support * Static caching of intermediate JavaScript @@ -33,6 +33,8 @@ $ npm install ejs <% } %> ``` +Try EJS online at: https://ionicabizau.github.io/ejs-playground/. + ## Usage ```javascript @@ -50,19 +52,20 @@ ejs.renderFile(filename, data, options, function(err, str){ It is also possible to use `ejs.render(dataAndOptions);` where you pass everything in a single object. In that case, you'll end up with local variables -for all the passed options. However, be aware that your code could break if we +for all the passed options. However, be aware that your code could break if we add an option with the same name as one of your data object's properties. Therefore, we do not recommend using this shortcut. ## Options - `cache` Compiled functions are cached, requires `filename` - - `filename` The name of the file being rendered. Not required if you + - `filename` The name of the file being rendered. Not required if you are using `renderFile()`. Used by `cache` to key caches, and for includes. + - `root` Set project root for includes with an absolute path (/file.ejs). - `context` Function execution context - `compileDebug` When `false` no debug instrumentation is compiled - - `client` When `true`, compiles a function that can be rendered - in the browser without needing to load the EJS Runtime + - `client` When `true`, compiles a function that can be rendered + in the browser without needing to load the EJS Runtime ([ejs.min.js](https://github.com/mde/ejs/releases/latest)). - `delimiter` Character to use with angle brackets for open/close - `debug` Output generated function body @@ -76,9 +79,9 @@ Therefore, we do not recommend using this shortcut. - `escape` The escaping function used with `<%=` construct. It is used in rendering and is `.toString()`ed in the generation of client functions. (By default escapes XML). -This project uses [JSDoc](http://usejsdoc.org/). For the full public API -documentation, clone the repository and run `npm run doc`. This will run JSDoc -with the proper options and output the documentation to `out/`. If you want +This project uses [JSDoc](http://usejsdoc.org/). For the full public API +documentation, clone the repository and run `npm run doc`. This will run JSDoc +with the proper options and output the documentation to `out/`. If you want the both the public & private API docs, run `npm run devdoc` instead. ## Tags @@ -89,6 +92,7 @@ the both the public & private API docs, run `npm run devdoc` instead. - `<%-` Outputs the unescaped value into the template - `<%#` Comment tag, no execution, no output - `<%%` Outputs a literal '<%' + - `%%>` Outputs a literal '%>' - `%>` Plain ending tag - `-%>` Trim-mode ('newline slurp') tag, trims following newline - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it @@ -98,11 +102,11 @@ For the full syntax documentation, please see [docs/syntax.md](https://github.co ## Includes Includes either have to be an absolute path, or, if not, are assumed as -relative to the template with the `include` call. For example if you are -including `./views/user/show.ejs` from `./views/users.ejs` you would +relative to the template with the `include` call. For example if you are +including `./views/user/show.ejs` from `./views/users.ejs` you would use `<%- include('user/show') %>`. -You must specify the `filename` option for the template with the `include` +You must specify the `filename` option for the template with the `include` call unless you are using `renderFile()`. You'll likely want to use the raw output tag (`<%-`) with your include to avoid @@ -158,6 +162,21 @@ If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the LRU cache and need a different limit, simple reset `ejs.cache` to a new instance of the LRU. +## Custom FileLoader + +The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader. + +```javascript +var ejs = require('ejs'); +var myFileLoad = function (filePath) { + return 'myFileLoad: ' + fs.readFileSync(filePath); +}; + +ejs.fileLoader = myFileLoad; +``` + +With this feature, you can preprocess the template before reading it. + ## Layouts EJS does not specifically support blocks, but layouts can be implemented by @@ -178,8 +197,8 @@ including headers and footers, like so: ## Client-side support Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download -`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning -the repository and running `jake build` (or `$(npm bin)/jake build` if jake is +`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning +the repository and running `jake build` (or `$(npm bin)/jake build` if jake is not installed globally). Include one of these files on your page, and `ejs` should be available globally. @@ -208,11 +227,11 @@ Most of EJS will work as expected; however, there are a few things to note: ```javascript var str = "Hello <%= include('file', {person: 'John'}); %>", fn = ejs.compile(str, {client: true}); - + fn(data, null, function(path, d){ // IncludeCallback // path -> 'file' // d -> {person: 'John'} - // Put your code here + // Put your code here // Return the contents of file as a string }); // returns rendered string ``` @@ -235,5 +254,3 @@ Licensed under the Apache License, Version 2.0 - - - EJS Embedded JavaScript templates copyright 2112 mde@fleegix.org. - - diff --git a/node_modules/ejs/ejs.js b/node_modules/ejs/ejs.js index 4b87155..7e6dba5 100644 --- a/node_modules/ejs/ejs.js +++ b/node_modules/ejs/ejs.js @@ -1,4 +1,4 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o * @author Tiancheng "Timothy" Gu * @project EJS @@ -45,19 +45,23 @@ * @public */ -var fs = require('fs') - , utils = require('./utils') - , scopeOptionWarned = false - , _VERSION_STRING = require('../package.json').version - , _DEFAULT_DELIMITER = '%' - , _DEFAULT_LOCALS_NAME = 'locals' - , _REGEX_STRING = '(<%%|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)' - , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context' - , 'debug', 'compileDebug', 'client', '_with', 'rmWhitespace' - , 'strict', 'localsName' - ] - , _TRAILING_SEMCOL = /;\s*$/ - , _BOM = /^\uFEFF/; +var fs = require('fs'); +var path = require('path'); +var utils = require('./utils'); + +var scopeOptionWarned = false; +var _VERSION_STRING = require('../package.json').version; +var _DEFAULT_DELIMITER = '%'; +var _DEFAULT_LOCALS_NAME = 'locals'; +var _NAME = 'ejs'; +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; +var _OPTS = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', + 'client', '_with', 'rmWhitespace', 'strict', 'filename']; +// We don't allow 'cache' option to be passed in the data obj +// for the normal `render` call, but this is where Express puts it +// so we make an exception for `renderFile` +var _OPTS_EXPRESS = _OPTS.concat('cache'); +var _BOM = /^\uFEFF/; /** * EJS template function cache. This can be a LRU object from lru-cache NPM @@ -69,10 +73,19 @@ var fs = require('fs') exports.cache = utils.cache; +/** + * Custom file loader. Useful for template preprocessing or restricting access + * to a certain part of the filesystem. + * + * @type {fileLoader} + */ + +exports.fileLoader = fs.readFileSync; + /** * Name of the object containing the locals. * - * This variable is overriden by {@link Options}`.localsName` if it is not + * This variable is overridden by {@link Options}`.localsName` if it is not * `undefined`. * * @type {String} @@ -85,24 +98,44 @@ exports.localsName = _DEFAULT_LOCALS_NAME; * Get the path to the included file from the parent file path and the * specified path. * - * @param {String} name specified path - * @param {String} filename parent file path + * @param {String} name specified path + * @param {String} filename parent file path + * @param {Boolean} isDir parent file path whether is directory * @return {String} */ - -exports.resolveInclude = function(name, filename) { - var path = require('path') - , dirname = path.dirname - , extname = path.extname - , resolve = path.resolve - , includePath = resolve(dirname(filename), name) - , ext = extname(name); +exports.resolveInclude = function(name, filename, isDir) { + var dirname = path.dirname; + var extname = path.extname; + var resolve = path.resolve; + var includePath = resolve(isDir ? filename : dirname(filename), name); + var ext = extname(name); if (!ext) { includePath += '.ejs'; } return includePath; }; +/** + * Get the path to the included file by Options + * + * @param {String} path specified path + * @param {Options} options compilation options + * @return {String} + */ +function getIncludePath(path, options){ + var includePath; + if (path.charAt(0) == '/') { + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); + } + else { + if (!options.filename) { + throw new Error('`include` use relative path requires the \'filename\' option.'); + } + includePath = exports.resolveInclude(path, options.filename); + } + return includePath; +} + /** * Get the template from a string or a file, either compiled on-the-fly or * read from cache (if enabled), and cache the template if needed. @@ -122,35 +155,70 @@ exports.resolveInclude = function(name, filename) { */ function handleCache(options, template) { - var fn - , path = options.filename - , hasTemplate = arguments.length > 1; + var func; + var filename = options.filename; + var hasTemplate = arguments.length > 1; if (options.cache) { - if (!path) { + if (!filename) { throw new Error('cache option requires a filename'); } - fn = exports.cache.get(path); - if (fn) { - return fn; + func = exports.cache.get(filename); + if (func) { + return func; } if (!hasTemplate) { - template = fs.readFileSync(path).toString().replace(_BOM, ''); + template = fileLoader(filename).toString().replace(_BOM, ''); } } else if (!hasTemplate) { // istanbul ignore if: should not happen at all - if (!path) { + if (!filename) { throw new Error('Internal EJS error: no file name or template ' + 'provided'); } - template = fs.readFileSync(path).toString().replace(_BOM, ''); + template = fileLoader(filename).toString().replace(_BOM, ''); } - fn = exports.compile(template, options); + func = exports.compile(template, options); if (options.cache) { - exports.cache.set(path, fn); + exports.cache.set(filename, func); } - return fn; + return func; +} + +/** + * Try calling handleCache with the given options and data and call the + * callback with the result. If an error occurs, call the callback with + * the error. Used by renderFile(). + * + * @memberof module:ejs-internal + * @param {Options} options compilation options + * @param {Object} data template data + * @param {RenderFileCallback} cb callback + * @static + */ + +function tryHandleCache(options, data, cb) { + var result; + try { + result = handleCache(options)(data); + } + catch (err) { + return cb(err); + } + return cb(null, result); +} + +/** + * fileLoader is independent + * + * @param {String} filePath ejs file path. + * @return {String} The contents of the specified file. + * @static + */ + +function fileLoader(filePath){ + return exports.fileLoader(filePath); } /** @@ -168,10 +236,7 @@ function handleCache(options, template) { function includeFile(path, options) { var opts = utils.shallowCopy({}, options); - if (!opts.filename) { - throw new Error('`include` requires the \'filename\' option.'); - } - opts.filename = exports.resolveInclude(path, opts.filename); + opts.filename = getIncludePath(path, opts); return handleCache(opts); } @@ -181,24 +246,24 @@ function includeFile(path, options) { * @memberof module:ejs-internal * @param {String} path path for the specified file * @param {Options} options compilation options - * @return {String} + * @return {Object} * @static */ function includeSource(path, options) { - var opts = utils.shallowCopy({}, options) - , includePath - , template; - if (!opts.filename) { - throw new Error('`include` requires the \'filename\' option.'); - } - includePath = exports.resolveInclude(path, opts.filename); - template = fs.readFileSync(includePath).toString().replace(_BOM, ''); - + var opts = utils.shallowCopy({}, options); + var includePath; + var template; + includePath = getIncludePath(path, opts); + template = fileLoader(includePath).toString().replace(_BOM, ''); opts.filename = includePath; var templ = new Template(template, opts); templ.generateSource(); - return templ.source; + return { + source: templ.source, + filename: includePath, + template: template + }; } /** @@ -214,11 +279,11 @@ function includeSource(path, options) { * @static */ -function rethrow(err, str, filename, lineno){ - var lines = str.split('\n') - , start = Math.max(lineno - 3, 0) - , end = Math.min(lines.length, lineno + 3); - +function rethrow(err, str, flnm, lineno, esc){ + var lines = str.split('\n'); + var start = Math.max(lineno - 3, 0); + var end = Math.min(lines.length, lineno + 3); + var filename = esc(flnm); // eslint-disable-line // Error context var context = lines.slice(start, end).map(function (line, i){ var curr = i + start + 1; @@ -238,24 +303,8 @@ function rethrow(err, str, filename, lineno){ throw err; } -/** - * Copy properties in data object that are recognized as options to an - * options object. - * - * This is used for compatibility with earlier versions of EJS and Express.js. - * - * @memberof module:ejs-internal - * @param {Object} data data object - * @param {Options} opts options object - * @static - */ - -function cpOptsInData(data, opts) { - _OPTS.forEach(function (p) { - if (typeof data[p] != 'undefined') { - opts[p] = data[p]; - } - }); +function stripSemi(str){ + return str.replace(/;(\s*$)/, '$1'); } /** @@ -303,15 +352,14 @@ exports.compile = function compile(template, opts) { * @public */ -exports.render = function (template, data, opts) { - data = data || {}; - opts = opts || {}; - var fn; +exports.render = function (template, d, o) { + var data = d || {}; + var opts = o || {}; // No options object -- if there are optiony names // in the data, copy them to options if (arguments.length == 2) { - cpOptsInData(data, opts); + utils.shallowCopyFromList(opts, data, _OPTS); } return handleCache(opts, template)(data); @@ -331,37 +379,38 @@ exports.render = function (template, data, opts) { */ exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments) - , path = args.shift() - , cb = args.pop() - , data = args.shift() || {} - , opts = args.pop() || {} - , result; + var filename = arguments[0]; + var cb = arguments[arguments.length - 1]; + var opts = {filename: filename}; + var data; - // Don't pollute passed in opts obj with new vals - opts = utils.shallowCopy({}, opts); + if (arguments.length > 2) { + data = arguments[1]; - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 3) { - // Express 4 - if (data.settings && data.settings['view options']) { - cpOptsInData(data.settings['view options'], opts); + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length === 3) { + // Express 4 + if (data.settings && data.settings['view options']) { + utils.shallowCopyFromList(opts, data.settings['view options'], _OPTS_EXPRESS); + } + // Express 3 and lower + else { + utils.shallowCopyFromList(opts, data, _OPTS_EXPRESS); + } } - // Express 3 and lower else { - cpOptsInData(data, opts); + // Use shallowCopy so we don't pollute passed in opts obj with new vals + utils.shallowCopy(opts, arguments[2]); } - } - opts.filename = path; - try { - result = handleCache(opts)(data); + opts.filename = filename; } - catch(err) { - return cb(err); + else { + data = {}; } - return cb(null, result); + + return tryHandleCache(opts, data, cb); }; /** @@ -392,6 +441,7 @@ function Template(text, opts) { options.context = opts.context; options.cache = opts.cache || false; options.rmWhitespace = opts.rmWhitespace; + options.root = opts.root; options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; if (options.strict) { @@ -407,39 +457,28 @@ function Template(text, opts) { } Template.modes = { - EVAL: 'eval' -, ESCAPED: 'escaped' -, RAW: 'raw' -, COMMENT: 'comment' -, LITERAL: 'literal' + EVAL: 'eval', + ESCAPED: 'escaped', + RAW: 'raw', + COMMENT: 'comment', + LITERAL: 'literal' }; Template.prototype = { createRegex: function () { - var str = _REGEX_STRING - , delim = utils.escapeRegExpChars(this.opts.delimiter); + var str = _REGEX_STRING; + var delim = utils.escapeRegExpChars(this.opts.delimiter); str = str.replace(/%/g, delim); return new RegExp(str); - } + }, -, compile: function () { - var src - , fn - , opts = this.opts - , prepended = '' - , appended = '' - , escape = opts.escapeFunction; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r`. - this.templateText = - this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); + compile: function () { + var src; + var fn; + var opts = this.opts; + var prepended = ''; + var appended = ''; + var escapeFn = opts.escapeFunction; if (!this.source) { this.generateSource(); @@ -460,7 +499,7 @@ Template.prototype = { + 'try {' + '\n' + this.source + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line);' + '\n' + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' + '}' + '\n'; } else { @@ -472,7 +511,7 @@ Template.prototype = { } if (opts.client) { - src = 'escape = escape || ' + escape.toString() + ';' + '\n' + src; + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; if (opts.compileDebug) { src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; } @@ -483,7 +522,7 @@ Template.prototype = { } try { - fn = new Function(opts.localsName + ', escape, include, rethrow', src); + fn = new Function(opts.localsName + ', escapeFn, include, rethrow', src); } catch(e) { // istanbul ignore else @@ -491,7 +530,9 @@ Template.prototype = { if (opts.filename) { e.message += ' in ' + opts.filename; } - e.message += ' while compiling ejs'; + e.message += ' while compiling ejs\n\n'; + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; + e.message += 'https://github.com/RyanZim/EJS-Lint'; } throw e; } @@ -512,28 +553,38 @@ Template.prototype = { } return includeFile(path, opts)(d); }; - return fn.apply(opts.context, [data || {}, escape, include, rethrow]); + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); }; returnedFn.dependencies = this.dependencies; return returnedFn; - } + }, -, generateSource: function () { - var self = this - , matches = this.parseTemplateText() - , d = this.opts.delimiter; + generateSource: function () { + var opts = this.opts; + + if (opts.rmWhitespace) { + // Have to use two separate replace here as `^` and `$` operators don't + // work well with `\r`. + this.templateText = + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); + } + + // Slurp spaces and tabs before <%_ and after _%> + this.templateText = + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); + + var self = this; + var matches = this.parseTemplateText(); + var d = this.opts.delimiter; if (matches && matches.length) { - if (this.opts.compileDebug && this.opts.filename) { - this.source = ' ; __lines = ' + JSON.stringify(this.templateText) + '\n'; - this.source += ' ; __filename = "' + this.opts.filename.replace(/\\/g, '/') + '"\n'; - } matches.forEach(function (line, index) { - var opening - , closing - , include - , includeOpts - , includeSrc; + var opening; + var closing; + var include; + var includeOpts; + var includeObj; + var includeSrc; // If this is an opening tag, check for closing tags // FIXME: May end up with some false positives here // Better to store modes as k/v with '<' + delimiter as key @@ -551,9 +602,23 @@ Template.prototype = { // Must be in EVAL or RAW mode if (opening && (opening == '<' + d || opening == '<' + d + '-' || opening == '<' + d + '_')) { includeOpts = utils.shallowCopy({}, self.opts); - includeSrc = includeSource(include[1], includeOpts); - includeSrc = ' ; (function(){' + '\n' + includeSrc + - ' ; })()' + '\n'; + includeObj = includeSource(include[1], includeOpts); + if (self.opts.compileDebug) { + includeSrc = + ' ; (function(){' + '\n' + + ' var __line = 1' + '\n' + + ' , __lines = ' + JSON.stringify(includeObj.template) + '\n' + + ' , __filename = ' + JSON.stringify(includeObj.filename) + ';' + '\n' + + ' try {' + '\n' + + includeObj.source + + ' } catch (e) {' + '\n' + + ' rethrow(e, __lines, __filename, __line);' + '\n' + + ' }' + '\n' + + ' ; }).call(this)' + '\n'; + }else{ + includeSrc = ' ; (function(){' + '\n' + includeObj.source + + ' ; }).call(this)' + '\n'; + } self.source += includeSrc; self.dependencies.push(exports.resolveInclude(include[1], includeOpts.filename)); @@ -564,19 +629,17 @@ Template.prototype = { }); } - } + }, -, parseTemplateText: function () { - var str = this.templateText - , pat = this.regex - , result = pat.exec(str) - , arr = [] - , firstPos - , lastPos; + parseTemplateText: function () { + var str = this.templateText; + var pat = this.regex; + var result = pat.exec(str); + var arr = []; + var firstPos; while (result) { firstPos = result.index; - lastPos = pat.lastIndex; if (firstPos !== 0) { arr.push(str.substring(0, firstPos)); @@ -593,12 +656,12 @@ Template.prototype = { } return arr; - } + }, -, scanLine: function (line) { - var self = this - , d = this.opts.delimiter - , newLineCount = 0; + scanLine: function (line) { + var self = this; + var d = this.opts.delimiter; + var newLineCount = 0; function _addOutput() { if (self.truncate) { @@ -607,13 +670,12 @@ Template.prototype = { // after the tag that the truncation mode replaces // Handle Win / Unix / old Mac linebreaks -- do the \r\n // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, '') + line = line.replace(/^(?:\r\n|\r|\n)/, ''); self.truncate = false; } else if (self.opts.rmWhitespace) { - // Gotta be more careful here. - // .replace(/^(\s*)\n/, '$1') might be more appropriate here but as - // rmWhitespace already removes trailing spaces anyway so meh. + // rmWhitespace has already removed trailing spaces, just need + // to remove linebreaks line = line.replace(/^\n/, ''); } if (!line) { @@ -636,73 +698,75 @@ Template.prototype = { newLineCount = (line.split('\n').length - 1); switch (line) { - case '<' + d: - case '<' + d + '_': - this.mode = Template.modes.EVAL; - break; - case '<' + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case '<' + d + '-': - this.mode = Template.modes.RAW; - break; - case '<' + d + '#': - this.mode = Template.modes.COMMENT; - break; - case '<' + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; - break; - case d + '>': - case '-' + d + '>': - case '_' + d + '>': - if (this.mode == Template.modes.LITERAL) { - _addOutput(); - } + case '<' + d: + case '<' + d + '_': + this.mode = Template.modes.EVAL; + break; + case '<' + d + '=': + this.mode = Template.modes.ESCAPED; + break; + case '<' + d + '-': + this.mode = Template.modes.RAW; + break; + case '<' + d + '#': + this.mode = Template.modes.COMMENT; + break; + case '<' + d + d: + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; + break; + case d + d + '>': + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace(d + d + '>', d + '>') + '")' + '\n'; + break; + case d + '>': + case '-' + d + '>': + case '_' + d + '>': + if (this.mode == Template.modes.LITERAL) { + _addOutput(); + } - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: + this.mode = null; + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; + break; + default: // In script mode, depends on type of tag - if (this.mode) { + if (this.mode) { // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } + switch (this.mode) { + case Template.modes.EVAL: + case Template.modes.ESCAPED: + case Template.modes.RAW: + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { + line += '\n'; } - switch (this.mode) { + } + switch (this.mode) { // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; + case Template.modes.EVAL: + this.source += ' ; ' + line + '\n'; + break; // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escape(' + - line.replace(_TRAILING_SEMCOL, '').trim() + '))' + '\n'; - break; + case Template.modes.ESCAPED: + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; + break; // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + - line.replace(_TRAILING_SEMCOL, '').trim() + ')' + '\n'; - break; - case Template.modes.COMMENT: + case Template.modes.RAW: + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; + break; + case Template.modes.COMMENT: // Do nothing - break; + break; // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - _addOutput(); - break; - } - } - // In string mode, just add the output - else { + case Template.modes.LITERAL: _addOutput(); + break; } + } + // In string mode, just add the output + else { + _addOutput(); + } } if (self.opts.compileDebug && newLineCount) { @@ -712,9 +776,17 @@ Template.prototype = { } }; -/* - * Export the internal function for escaping XML so people - * can use for manual escaping if needed +/** + * Escape characters reserved in XML. + * + * This is simply an export of {@link module:utils.escapeXML}. + * + * If `markup` is `undefined` or `null`, the empty string is returned. + * + * @param {String} markup Input string + * @return {String} Escaped string + * @public + * @func * */ exports.escapeXML = utils.escapeXML; @@ -732,14 +804,14 @@ exports.__express = exports.renderFile; // Add require support /* istanbul ignore else */ if (require.extensions) { - require.extensions['.ejs'] = function (module, filename) { - filename = filename || /* istanbul ignore next */ module.filename; + require.extensions['.ejs'] = function (module, flnm) { + var filename = flnm || /* istanbul ignore next */ module.filename; var options = { - filename: filename - , client: true - } - , template = fs.readFileSync(filename).toString() - , fn = exports.compile(template, options); + filename: filename, + client: true + }; + var template = fileLoader(filename).toString(); + var fn = exports.compile(template, options); module._compile('module.exports = ' + fn.toString() + ';', filename); }; } @@ -754,6 +826,16 @@ if (require.extensions) { exports.VERSION = _VERSION_STRING; +/** + * Name for detection of EJS. + * + * @readonly + * @type {String} + * @public + */ + +exports.name = _NAME; + /* istanbul ignore if */ if (typeof window != 'undefined') { window.ejs = exports; @@ -807,17 +889,17 @@ exports.escapeRegExpChars = function (string) { }; var _ENCODE_HTML_RULES = { - '&': '&' - , '<': '<' - , '>': '>' - , '"': '"' - , "'": ''' - } - , _MATCH_HTML = /[&<>\'"]/g; + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +}; +var _MATCH_HTML = /[&<>\'"]/g; function encode_char(c) { return _ENCODE_HTML_RULES[c] || c; -}; +} /** * Stringified version of constants used by {@link module:utils.escapeXML}. @@ -860,11 +942,13 @@ exports.escapeXML = function (markup) { .replace(_MATCH_HTML, encode_char); }; exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; }; /** - * Copy all properties from one object to another, in a shallow fashion. + * Naive copy of properties from one object to another. + * Does not recurse into non-scalar properties + * Does not check to see if the property has a value before copying * * @param {Object} to Destination object * @param {Object} from Source object @@ -880,6 +964,28 @@ exports.shallowCopy = function (to, from) { return to; }; +/** + * Naive copy of a list of key names, from one object to another. + * Only copies property if it is actually defined + * Does not recurse into non-scalar properties + * + * @param {Object} to Destination object + * @param {Object} from Source object + * @param {Array} list List of properties to copy + * @return {Object} Destination object + * @static + * @private + */ +exports.shallowCopyFromList = function (to, from, list) { + for (var i = 0; i < list.length; i++) { + var p = list[i]; + if (typeof from[p] != 'undefined') { + to[p] = from[p]; + } + } + return to; +}; + /** * Simple in-process cache implementation. Does not implement limits of any * sort. @@ -901,7 +1007,6 @@ exports.cache = { } }; - },{}],3:[function(require,module,exports){ },{}],4:[function(require,module,exports){ @@ -1134,36 +1239,159 @@ var substr = 'ab'.substr(-1) === 'b' }).call(this,require('_process')) },{"_process":5}],5:[function(require,module,exports){ // shim for using process in browser - var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} var queue = []; var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} function drainQueue() { if (draining) { return; } + var timeout = runTimeout(cleanUpNextTick); draining = true; - var currentQueue; + var len = queue.length; while(len) { currentQueue = queue; queue = []; - var i = -1; - while (++i < len) { - currentQueue[i](); + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } } + queueIndex = -1; len = queue.length; } + currentQueue = null; draining = false; + runClearTimeout(timeout); } + process.nextTick = function (fun) { - queue.push(fun); - if (!draining) { - setTimeout(drainQueue, 0); + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); } }; +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; process.title = 'browser'; process.browser = true; process.env = {}; @@ -1185,7 +1413,6 @@ process.binding = function (name) { throw new Error('process.binding is not supported'); }; -// TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); @@ -1201,7 +1428,7 @@ module.exports={ "engine", "ejs" ], - "version": "2.4.1", + "version": "2.5.5", "author": "Matthew Eernisse (http://fleegix.org)", "contributors": [ "Timothy Gu (https://timothygu.github.io)" @@ -1216,24 +1443,27 @@ module.exports={ "homepage": "https://github.com/mde/ejs", "dependencies": {}, "devDependencies": { - "browserify": "^8.0.3", - "istanbul": "~0.3.5", + "browserify": "^13.0.1", + "eslint": "^3.0.0", + "git-directory-deploy": "^1.5.1", + "istanbul": "~0.4.3", "jake": "^8.0.0", - "jsdoc": "^3.3.0-beta1", - "lru-cache": "^2.5.0", - "mocha": "^2.1.0", - "rimraf": "^2.2.8", - "uglify-js": "^2.4.16" + "jsdoc": "^3.4.0", + "lru-cache": "^4.0.1", + "mocha": "^3.0.2", + "uglify-js": "^2.6.2" }, "engines": { "node": ">=0.10.0" }, "scripts": { "test": "mocha", - "sample": "npm install express && node sample/index.js", + "lint": "eslint \"**/*.js\" Jakefile", "coverage": "istanbul cover node_modules/mocha/bin/_mocha", - "doc": "rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*", - "devdoc": "rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*" + "doc": "jake doc", + "devdoc": "jake doc[dev]" } } -},{}]},{},[1]); + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/node_modules/ejs/ejs.min.js b/node_modules/ejs/ejs.min.js index 46f5b39..559d386 100644 --- a/node_modules/ejs/ejs.min.js +++ b/node_modules/ejs/ejs.min.js @@ -1 +1 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o|-%>|_%>)",_OPTS=["cache","filename","delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","localsName"],_TRAILING_SEMCOL=/;\s*$/,_BOM=/^\uFEFF/;exports.cache=utils.cache;exports.localsName=_DEFAULT_LOCALS_NAME;exports.resolveInclude=function(name,filename){var path=require("path"),dirname=path.dirname,extname=path.extname,resolve=path.resolve,includePath=resolve(dirname(filename),name),ext=extname(name);if(!ext){includePath+=".ejs"}return includePath};function handleCache(options,template){var fn,path=options.filename,hasTemplate=arguments.length>1;if(options.cache){if(!path){throw new Error("cache option requires a filename")}fn=exports.cache.get(path);if(fn){return fn}if(!hasTemplate){template=fs.readFileSync(path).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!path){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fs.readFileSync(path).toString().replace(_BOM,"")}fn=exports.compile(template,options);if(options.cache){exports.cache.set(path,fn)}return fn}function includeFile(path,options){var opts=utils.shallowCopy({},options);if(!opts.filename){throw new Error("`include` requires the 'filename' option.")}opts.filename=exports.resolveInclude(path,opts.filename);return handleCache(opts)}function includeSource(path,options){var opts=utils.shallowCopy({},options),includePath,template;if(!opts.filename){throw new Error("`include` requires the 'filename' option.")}includePath=exports.resolveInclude(path,opts.filename);template=fs.readFileSync(includePath).toString().replace(_BOM,"");opts.filename=includePath;var templ=new Template(template,opts);templ.generateSource();return templ.source}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}function cpOptsInData(data,opts){_OPTS.forEach(function(p){if(typeof data[p]!="undefined"){opts[p]=data[p]}})}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,data,opts){data=data||{};opts=opts||{};var fn;if(arguments.length==2){cpOptsInData(data,opts)}return handleCache(opts,template)(data)};exports.renderFile=function(){var args=Array.prototype.slice.call(arguments),path=args.shift(),cb=args.pop(),data=args.shift()||{},opts=args.pop()||{},result;opts=utils.shallowCopy({},opts);if(arguments.length==3){if(data.settings&&data.settings["view options"]){cpOptsInData(data.settings["view options"],opts)}else{cpOptsInData(data,opts)}}opts.filename=path;try{result=handleCache(opts)(data)}catch(err){return cb(err)}return cb(null,result)};exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||{};var options={};this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";this.dependencies=[];options.client=opts.client||false;options.escapeFunction=opts.escape||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options.strict=opts.strict||false;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;if(options.strict){options._with=false}else{options._with=typeof opts._with!="undefined"?opts._with:true}this.opts=options;this.regex=this.createRegex()}Template.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"};Template.prototype={createRegex:function(){var str=_REGEX_STRING,delim=utils.escapeRegExpChars(this.opts.delimiter);str=str.replace(/%/g,delim);return new RegExp(str)},compile:function(){var src,fn,opts=this.opts,prepended="",appended="",escape=opts.escapeFunction;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/\r/g,"").replace(/^\s+|\s+$/gm,"")}this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");if(!this.source){this.generateSource();prepended+=" var __output = [], __append = __output.push.bind(__output);"+"\n";if(opts._with!==false){prepended+=" with ("+opts.localsName+" || {}) {"+"\n";appended+=" }"+"\n"}appended+=' return __output.join("");'+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+" , __lines = "+JSON.stringify(this.templateText)+"\n"+" , __filename = "+(opts.filename?JSON.stringify(opts.filename):"undefined")+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.debug){console.log(src)}if(opts.client){src="escape = escape || "+escape.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}if(opts.strict){src='"use strict";\n'+src}try{fn=new Function(opts.localsName+", escape, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs"}throw e}if(opts.client){fn.dependencies=this.dependencies;return fn}var returnedFn=function(data){var include=function(path,includeData){var d=utils.shallowCopy({},data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||{},escape,include,rethrow])};returnedFn.dependencies=this.dependencies;return returnedFn},generateSource:function(){var self=this,matches=this.parseTemplateText(),d=this.opts.delimiter;if(matches&&matches.length){if(this.opts.compileDebug&&this.opts.filename){this.source=" ; __lines = "+JSON.stringify(this.templateText)+"\n";this.source+=' ; __filename = "'+this.opts.filename.replace(/\\/g,"/")+'"\n'}matches.forEach(function(line,index){var opening,closing,include,includeOpts,includeSrc;if(line.indexOf("<"+d)===0&&line.indexOf("<"+d+d)!==0){closing=matches[index+2];if(!(closing==d+">"||closing=="-"+d+">"||closing=="_"+d+">")){throw new Error('Could not find matching close tag for "'+line+'".')}}if(include=line.match(/^\s*include\s+(\S+)/)){opening=matches[index-1];if(opening&&(opening=="<"+d||opening=="<"+d+"-"||opening=="<"+d+"_")){includeOpts=utils.shallowCopy({},self.opts);includeSrc=includeSource(include[1],includeOpts);includeSrc=" ; (function(){"+"\n"+includeSrc+" ; })()"+"\n";self.source+=includeSrc;self.dependencies.push(exports.resolveInclude(include[1],includeOpts.filename));return}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText,pat=this.regex,result=pat.exec(str),arr=[],firstPos,lastPos;while(result){firstPos=result.index;lastPos=pat.lastIndex;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str){arr.push(str)}return arr},scanLine:function(line){var self=this,d=this.opts.delimiter,newLineCount=0;function _addOutput(){if(self.truncate){line=line.replace(/^(?:\r\n|\r|\n)/,"");self.truncate=false}else if(self.opts.rmWhitespace){line=line.replace(/^\n/,"")}if(!line){return}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');self.source+=' ; __append("'+line+'")'+"\n"}newLineCount=line.split("\n").length-1;switch(line){case"<"+d:case"<"+d+"_":this.mode=Template.modes.EVAL;break;case"<"+d+"=":this.mode=Template.modes.ESCAPED;break;case"<"+d+"-":this.mode=Template.modes.RAW;break;case"<"+d+"#":this.mode=Template.modes.COMMENT;break;case"<"+d+d:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace("<"+d+d,"<"+d)+'")'+"\n";break;case d+">":case"-"+d+">":case"_"+d+">":if(this.mode==Template.modes.LITERAL){_addOutput()}this.mode=null;this.truncate=line.indexOf("-")===0||line.indexOf("_")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+=" ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+=" ; __append(escape("+line.replace(_TRAILING_SEMCOL,"").trim()+"))"+"\n";break;case Template.modes.RAW:this.source+=" ; __append("+line.replace(_TRAILING_SEMCOL,"").trim()+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:_addOutput();break}}else{_addOutput()}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+=" ; __line = "+this.currentLine+"\n"}}};exports.escapeXML=utils.escapeXML;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=exports.compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}exports.VERSION=_VERSION_STRING;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&","<":"<",">":">",'"':""","'":"'"},_MATCH_HTML=/[&<>\'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+' "&": "&"\n'+' , "<": "<"\n'+' , ">": ">"\n'+' , \'"\': """\n'+' , "\'": "'"\n'+" }\n"+" , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+" return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};exports.escapeXML.toString=function(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr};exports.shallowCopy=function(to,from){from=from||{};for(var p in from){to[p]=from[p]}return to};exports.cache={_data:{},set:function(key,val){this._data[key]=val},get:function(key){return this._data[key]},reset:function(){this._data={}}}},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i (http://fleegix.org)",contributors:["Timothy Gu (https://timothygu.github.io)"],license:"Apache-2.0",main:"./lib/ejs.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{},devDependencies:{browserify:"^8.0.3",istanbul:"~0.3.5",jake:"^8.0.0",jsdoc:"^3.3.0-beta1","lru-cache":"^2.5.0",mocha:"^2.1.0",rimraf:"^2.2.8","uglify-js":"^2.4.16"},engines:{node:">=0.10.0"},scripts:{test:"mocha",sample:"npm install express && node sample/index.js",coverage:"istanbul cover node_modules/mocha/bin/_mocha",doc:"rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*",devdoc:"rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*"}}},{}]},{},[1]); +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ejs=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1;if(options.cache){if(!filename){throw new Error("cache option requires a filename")}func=exports.cache.get(filename);if(func){return func}if(!hasTemplate){template=fileLoader(filename).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!filename){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fileLoader(filename).toString().replace(_BOM,"")}func=exports.compile(template,options);if(options.cache){exports.cache.set(filename,func)}return func}function tryHandleCache(options,data,cb){var result;try{result=handleCache(options)(data)}catch(err){return cb(err)}return cb(null,result)}function fileLoader(filePath){return exports.fileLoader(filePath)}function includeFile(path,options){var opts=utils.shallowCopy({},options);opts.filename=getIncludePath(path,opts);return handleCache(opts)}function includeSource(path,options){var opts=utils.shallowCopy({},options);var includePath;var template;includePath=getIncludePath(path,opts);template=fileLoader(includePath).toString().replace(_BOM,"");opts.filename=includePath;var templ=new Template(template,opts);templ.generateSource();return{source:templ.source,filename:includePath,template:template}}function rethrow(err,str,flnm,lineno,esc){var lines=str.split("\n");var start=Math.max(lineno-3,0);var end=Math.min(lines.length,lineno+3);var filename=esc(flnm);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}function stripSemi(str){return str.replace(/;(\s*$)/,"$1")}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,d,o){var data=d||{};var opts=o||{};if(arguments.length==2){utils.shallowCopyFromList(opts,data,_OPTS)}return handleCache(opts,template)(data)};exports.renderFile=function(){var filename=arguments[0];var cb=arguments[arguments.length-1];var opts={filename:filename};var data;if(arguments.length>2){data=arguments[1];if(arguments.length===3){if(data.settings&&data.settings["view options"]){utils.shallowCopyFromList(opts,data.settings["view options"],_OPTS_EXPRESS)}else{utils.shallowCopyFromList(opts,data,_OPTS_EXPRESS)}}else{utils.shallowCopy(opts,arguments[2])}opts.filename=filename}else{data={}}return tryHandleCache(opts,data,cb)};exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||{};var options={};this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";this.dependencies=[];options.client=opts.client||false;options.escapeFunction=opts.escape||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options.strict=opts.strict||false;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;options.root=opts.root;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;if(options.strict){options._with=false}else{options._with=typeof opts._with!="undefined"?opts._with:true}this.opts=options;this.regex=this.createRegex()}Template.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"};Template.prototype={createRegex:function(){var str=_REGEX_STRING;var delim=utils.escapeRegExpChars(this.opts.delimiter);str=str.replace(/%/g,delim);return new RegExp(str)},compile:function(){var src;var fn;var opts=this.opts;var prepended="";var appended="";var escapeFn=opts.escapeFunction;if(!this.source){this.generateSource();prepended+=" var __output = [], __append = __output.push.bind(__output);"+"\n";if(opts._with!==false){prepended+=" with ("+opts.localsName+" || {}) {"+"\n";appended+=" }"+"\n"}appended+=' return __output.join("");'+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+" , __lines = "+JSON.stringify(this.templateText)+"\n"+" , __filename = "+(opts.filename?JSON.stringify(opts.filename):"undefined")+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line, escapeFn);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.debug){console.log(src)}if(opts.client){src="escapeFn = escapeFn || "+escapeFn.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}if(opts.strict){src='"use strict";\n'+src}try{fn=new Function(opts.localsName+", escapeFn, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs\n\n";e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n";e.message+="https://github.com/RyanZim/EJS-Lint"}throw e}if(opts.client){fn.dependencies=this.dependencies;return fn}var returnedFn=function(data){var include=function(path,includeData){var d=utils.shallowCopy({},data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||{},escapeFn,include,rethrow])};returnedFn.dependencies=this.dependencies;return returnedFn},generateSource:function(){var opts=this.opts;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/\r/g,"").replace(/^\s+|\s+$/gm,"")}this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var self=this;var matches=this.parseTemplateText();var d=this.opts.delimiter;if(matches&&matches.length){matches.forEach(function(line,index){var opening;var closing;var include;var includeOpts;var includeObj;var includeSrc;if(line.indexOf("<"+d)===0&&line.indexOf("<"+d+d)!==0){closing=matches[index+2];if(!(closing==d+">"||closing=="-"+d+">"||closing=="_"+d+">")){throw new Error('Could not find matching close tag for "'+line+'".')}}if(include=line.match(/^\s*include\s+(\S+)/)){opening=matches[index-1];if(opening&&(opening=="<"+d||opening=="<"+d+"-"||opening=="<"+d+"_")){includeOpts=utils.shallowCopy({},self.opts);includeObj=includeSource(include[1],includeOpts);if(self.opts.compileDebug){includeSrc=" ; (function(){"+"\n"+" var __line = 1"+"\n"+" , __lines = "+JSON.stringify(includeObj.template)+"\n"+" , __filename = "+JSON.stringify(includeObj.filename)+";"+"\n"+" try {"+"\n"+includeObj.source+" } catch (e) {"+"\n"+" rethrow(e, __lines, __filename, __line);"+"\n"+" }"+"\n"+" ; }).call(this)"+"\n"}else{includeSrc=" ; (function(){"+"\n"+includeObj.source+" ; }).call(this)"+"\n"}self.source+=includeSrc;self.dependencies.push(exports.resolveInclude(include[1],includeOpts.filename));return}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText;var pat=this.regex;var result=pat.exec(str);var arr=[];var firstPos;while(result){firstPos=result.index;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str){arr.push(str)}return arr},scanLine:function(line){var self=this;var d=this.opts.delimiter;var newLineCount=0;function _addOutput(){if(self.truncate){line=line.replace(/^(?:\r\n|\r|\n)/,"");self.truncate=false}else if(self.opts.rmWhitespace){line=line.replace(/^\n/,"")}if(!line){return}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');self.source+=' ; __append("'+line+'")'+"\n"}newLineCount=line.split("\n").length-1;switch(line){case"<"+d:case"<"+d+"_":this.mode=Template.modes.EVAL;break;case"<"+d+"=":this.mode=Template.modes.ESCAPED;break;case"<"+d+"-":this.mode=Template.modes.RAW;break;case"<"+d+"#":this.mode=Template.modes.COMMENT;break;case"<"+d+d:this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace("<"+d+d,"<"+d)+'")'+"\n";break;case d+d+">":this.mode=Template.modes.LITERAL;this.source+=' ; __append("'+line.replace(d+d+">",d+">")+'")'+"\n";break;case d+">":case"-"+d+">":case"_"+d+">":if(this.mode==Template.modes.LITERAL){_addOutput()}this.mode=null;this.truncate=line.indexOf("-")===0||line.indexOf("_")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+=" ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+=" ; __append(escapeFn("+stripSemi(line)+"))"+"\n";break;case Template.modes.RAW:this.source+=" ; __append("+stripSemi(line)+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:_addOutput();break}}else{_addOutput()}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+=" ; __line = "+this.currentLine+"\n"}}};exports.escapeXML=utils.escapeXML;exports.__express=exports.renderFile;if(require.extensions){require.extensions[".ejs"]=function(module,flnm){var filename=flnm||module.filename;var options={filename:filename,client:true};var template=fileLoader(filename).toString();var fn=exports.compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}exports.VERSION=_VERSION_STRING;exports.name=_NAME;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&","<":"<",">":">",'"':""","'":"'"};var _MATCH_HTML=/[&<>\'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+' "&": "&"\n'+' , "<": "<"\n'+' , ">": ">"\n'+' , \'"\': """\n'+' , "\'": "'"\n'+" }\n"+" , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+" return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};exports.escapeXML.toString=function(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr};exports.shallowCopy=function(to,from){from=from||{};for(var p in from){to[p]=from[p]}return to};exports.shallowCopyFromList=function(to,from,list){for(var i=0;i=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i1){for(var i=1;i (http://fleegix.org)",contributors:["Timothy Gu (https://timothygu.github.io)"],license:"Apache-2.0",main:"./lib/ejs.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{},devDependencies:{browserify:"^13.0.1",eslint:"^3.0.0","git-directory-deploy":"^1.5.1",istanbul:"~0.4.3",jake:"^8.0.0",jsdoc:"^3.4.0","lru-cache":"^4.0.1",mocha:"^3.0.2","uglify-js":"^2.6.2"},engines:{node:">=0.10.0"},scripts:{test:"mocha",lint:'eslint "**/*.js" Jakefile',coverage:"istanbul cover node_modules/mocha/bin/_mocha",doc:"jake doc",devdoc:"jake doc[dev]"}}},{}]},{},[1])(1)}); diff --git a/node_modules/ejs/lib/ejs.js b/node_modules/ejs/lib/ejs.js index c0566a6..b53ee78 100644 --- a/node_modules/ejs/lib/ejs.js +++ b/node_modules/ejs/lib/ejs.js @@ -19,7 +19,7 @@ 'use strict'; /** - * @file Embedded JavaScript templating engine. + * @file Embedded JavaScript templating engine. {@link http://ejs.co} * @author Matthew Eernisse * @author Tiancheng "Timothy" Gu * @project EJS @@ -44,19 +44,23 @@ * @public */ -var fs = require('fs') - , utils = require('./utils') - , scopeOptionWarned = false - , _VERSION_STRING = require('../package.json').version - , _DEFAULT_DELIMITER = '%' - , _DEFAULT_LOCALS_NAME = 'locals' - , _REGEX_STRING = '(<%%|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)' - , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context' - , 'debug', 'compileDebug', 'client', '_with', 'rmWhitespace' - , 'strict', 'localsName' - ] - , _TRAILING_SEMCOL = /;\s*$/ - , _BOM = /^\uFEFF/; +var fs = require('fs'); +var path = require('path'); +var utils = require('./utils'); + +var scopeOptionWarned = false; +var _VERSION_STRING = require('../package.json').version; +var _DEFAULT_DELIMITER = '%'; +var _DEFAULT_LOCALS_NAME = 'locals'; +var _NAME = 'ejs'; +var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; +var _OPTS = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', + 'client', '_with', 'rmWhitespace', 'strict', 'filename']; +// We don't allow 'cache' option to be passed in the data obj +// for the normal `render` call, but this is where Express puts it +// so we make an exception for `renderFile` +var _OPTS_EXPRESS = _OPTS.concat('cache'); +var _BOM = /^\uFEFF/; /** * EJS template function cache. This can be a LRU object from lru-cache NPM @@ -68,10 +72,19 @@ var fs = require('fs') exports.cache = utils.cache; +/** + * Custom file loader. Useful for template preprocessing or restricting access + * to a certain part of the filesystem. + * + * @type {fileLoader} + */ + +exports.fileLoader = fs.readFileSync; + /** * Name of the object containing the locals. * - * This variable is overriden by {@link Options}`.localsName` if it is not + * This variable is overridden by {@link Options}`.localsName` if it is not * `undefined`. * * @type {String} @@ -84,24 +97,44 @@ exports.localsName = _DEFAULT_LOCALS_NAME; * Get the path to the included file from the parent file path and the * specified path. * - * @param {String} name specified path - * @param {String} filename parent file path + * @param {String} name specified path + * @param {String} filename parent file path + * @param {Boolean} isDir parent file path whether is directory * @return {String} */ - -exports.resolveInclude = function(name, filename) { - var path = require('path') - , dirname = path.dirname - , extname = path.extname - , resolve = path.resolve - , includePath = resolve(dirname(filename), name) - , ext = extname(name); +exports.resolveInclude = function(name, filename, isDir) { + var dirname = path.dirname; + var extname = path.extname; + var resolve = path.resolve; + var includePath = resolve(isDir ? filename : dirname(filename), name); + var ext = extname(name); if (!ext) { includePath += '.ejs'; } return includePath; }; +/** + * Get the path to the included file by Options + * + * @param {String} path specified path + * @param {Options} options compilation options + * @return {String} + */ +function getIncludePath(path, options){ + var includePath; + if (path.charAt(0) == '/') { + includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true); + } + else { + if (!options.filename) { + throw new Error('`include` use relative path requires the \'filename\' option.'); + } + includePath = exports.resolveInclude(path, options.filename); + } + return includePath; +} + /** * Get the template from a string or a file, either compiled on-the-fly or * read from cache (if enabled), and cache the template if needed. @@ -121,35 +154,70 @@ exports.resolveInclude = function(name, filename) { */ function handleCache(options, template) { - var fn - , path = options.filename - , hasTemplate = arguments.length > 1; + var func; + var filename = options.filename; + var hasTemplate = arguments.length > 1; if (options.cache) { - if (!path) { + if (!filename) { throw new Error('cache option requires a filename'); } - fn = exports.cache.get(path); - if (fn) { - return fn; + func = exports.cache.get(filename); + if (func) { + return func; } if (!hasTemplate) { - template = fs.readFileSync(path).toString().replace(_BOM, ''); + template = fileLoader(filename).toString().replace(_BOM, ''); } } else if (!hasTemplate) { // istanbul ignore if: should not happen at all - if (!path) { + if (!filename) { throw new Error('Internal EJS error: no file name or template ' + 'provided'); } - template = fs.readFileSync(path).toString().replace(_BOM, ''); + template = fileLoader(filename).toString().replace(_BOM, ''); } - fn = exports.compile(template, options); + func = exports.compile(template, options); if (options.cache) { - exports.cache.set(path, fn); + exports.cache.set(filename, func); } - return fn; + return func; +} + +/** + * Try calling handleCache with the given options and data and call the + * callback with the result. If an error occurs, call the callback with + * the error. Used by renderFile(). + * + * @memberof module:ejs-internal + * @param {Options} options compilation options + * @param {Object} data template data + * @param {RenderFileCallback} cb callback + * @static + */ + +function tryHandleCache(options, data, cb) { + var result; + try { + result = handleCache(options)(data); + } + catch (err) { + return cb(err); + } + return cb(null, result); +} + +/** + * fileLoader is independent + * + * @param {String} filePath ejs file path. + * @return {String} The contents of the specified file. + * @static + */ + +function fileLoader(filePath){ + return exports.fileLoader(filePath); } /** @@ -167,10 +235,7 @@ function handleCache(options, template) { function includeFile(path, options) { var opts = utils.shallowCopy({}, options); - if (!opts.filename) { - throw new Error('`include` requires the \'filename\' option.'); - } - opts.filename = exports.resolveInclude(path, opts.filename); + opts.filename = getIncludePath(path, opts); return handleCache(opts); } @@ -180,24 +245,24 @@ function includeFile(path, options) { * @memberof module:ejs-internal * @param {String} path path for the specified file * @param {Options} options compilation options - * @return {String} + * @return {Object} * @static */ function includeSource(path, options) { - var opts = utils.shallowCopy({}, options) - , includePath - , template; - if (!opts.filename) { - throw new Error('`include` requires the \'filename\' option.'); - } - includePath = exports.resolveInclude(path, opts.filename); - template = fs.readFileSync(includePath).toString().replace(_BOM, ''); - + var opts = utils.shallowCopy({}, options); + var includePath; + var template; + includePath = getIncludePath(path, opts); + template = fileLoader(includePath).toString().replace(_BOM, ''); opts.filename = includePath; var templ = new Template(template, opts); templ.generateSource(); - return templ.source; + return { + source: templ.source, + filename: includePath, + template: template + }; } /** @@ -213,11 +278,11 @@ function includeSource(path, options) { * @static */ -function rethrow(err, str, filename, lineno){ - var lines = str.split('\n') - , start = Math.max(lineno - 3, 0) - , end = Math.min(lines.length, lineno + 3); - +function rethrow(err, str, flnm, lineno, esc){ + var lines = str.split('\n'); + var start = Math.max(lineno - 3, 0); + var end = Math.min(lines.length, lineno + 3); + var filename = esc(flnm); // eslint-disable-line // Error context var context = lines.slice(start, end).map(function (line, i){ var curr = i + start + 1; @@ -237,24 +302,8 @@ function rethrow(err, str, filename, lineno){ throw err; } -/** - * Copy properties in data object that are recognized as options to an - * options object. - * - * This is used for compatibility with earlier versions of EJS and Express.js. - * - * @memberof module:ejs-internal - * @param {Object} data data object - * @param {Options} opts options object - * @static - */ - -function cpOptsInData(data, opts) { - _OPTS.forEach(function (p) { - if (typeof data[p] != 'undefined') { - opts[p] = data[p]; - } - }); +function stripSemi(str){ + return str.replace(/;(\s*$)/, '$1'); } /** @@ -302,15 +351,14 @@ exports.compile = function compile(template, opts) { * @public */ -exports.render = function (template, data, opts) { - data = data || {}; - opts = opts || {}; - var fn; +exports.render = function (template, d, o) { + var data = d || {}; + var opts = o || {}; // No options object -- if there are optiony names // in the data, copy them to options if (arguments.length == 2) { - cpOptsInData(data, opts); + utils.shallowCopyFromList(opts, data, _OPTS); } return handleCache(opts, template)(data); @@ -330,37 +378,38 @@ exports.render = function (template, data, opts) { */ exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments) - , path = args.shift() - , cb = args.pop() - , data = args.shift() || {} - , opts = args.pop() || {} - , result; + var filename = arguments[0]; + var cb = arguments[arguments.length - 1]; + var opts = {filename: filename}; + var data; - // Don't pollute passed in opts obj with new vals - opts = utils.shallowCopy({}, opts); + if (arguments.length > 2) { + data = arguments[1]; - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 3) { - // Express 4 - if (data.settings && data.settings['view options']) { - cpOptsInData(data.settings['view options'], opts); + // No options object -- if there are optiony names + // in the data, copy them to options + if (arguments.length === 3) { + // Express 4 + if (data.settings && data.settings['view options']) { + utils.shallowCopyFromList(opts, data.settings['view options'], _OPTS_EXPRESS); + } + // Express 3 and lower + else { + utils.shallowCopyFromList(opts, data, _OPTS_EXPRESS); + } } - // Express 3 and lower else { - cpOptsInData(data, opts); + // Use shallowCopy so we don't pollute passed in opts obj with new vals + utils.shallowCopy(opts, arguments[2]); } - } - opts.filename = path; - try { - result = handleCache(opts)(data); + opts.filename = filename; } - catch(err) { - return cb(err); + else { + data = {}; } - return cb(null, result); + + return tryHandleCache(opts, data, cb); }; /** @@ -391,6 +440,7 @@ function Template(text, opts) { options.context = opts.context; options.cache = opts.cache || false; options.rmWhitespace = opts.rmWhitespace; + options.root = opts.root; options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; if (options.strict) { @@ -406,39 +456,28 @@ function Template(text, opts) { } Template.modes = { - EVAL: 'eval' -, ESCAPED: 'escaped' -, RAW: 'raw' -, COMMENT: 'comment' -, LITERAL: 'literal' + EVAL: 'eval', + ESCAPED: 'escaped', + RAW: 'raw', + COMMENT: 'comment', + LITERAL: 'literal' }; Template.prototype = { createRegex: function () { - var str = _REGEX_STRING - , delim = utils.escapeRegExpChars(this.opts.delimiter); + var str = _REGEX_STRING; + var delim = utils.escapeRegExpChars(this.opts.delimiter); str = str.replace(/%/g, delim); return new RegExp(str); - } + }, -, compile: function () { - var src - , fn - , opts = this.opts - , prepended = '' - , appended = '' - , escape = opts.escapeFunction; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r`. - this.templateText = - this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); + compile: function () { + var src; + var fn; + var opts = this.opts; + var prepended = ''; + var appended = ''; + var escapeFn = opts.escapeFunction; if (!this.source) { this.generateSource(); @@ -459,7 +498,7 @@ Template.prototype = { + 'try {' + '\n' + this.source + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line);' + '\n' + + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' + '}' + '\n'; } else { @@ -471,7 +510,7 @@ Template.prototype = { } if (opts.client) { - src = 'escape = escape || ' + escape.toString() + ';' + '\n' + src; + src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; if (opts.compileDebug) { src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; } @@ -482,7 +521,7 @@ Template.prototype = { } try { - fn = new Function(opts.localsName + ', escape, include, rethrow', src); + fn = new Function(opts.localsName + ', escapeFn, include, rethrow', src); } catch(e) { // istanbul ignore else @@ -490,7 +529,9 @@ Template.prototype = { if (opts.filename) { e.message += ' in ' + opts.filename; } - e.message += ' while compiling ejs'; + e.message += ' while compiling ejs\n\n'; + e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; + e.message += 'https://github.com/RyanZim/EJS-Lint'; } throw e; } @@ -511,28 +552,38 @@ Template.prototype = { } return includeFile(path, opts)(d); }; - return fn.apply(opts.context, [data || {}, escape, include, rethrow]); + return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]); }; returnedFn.dependencies = this.dependencies; return returnedFn; - } + }, -, generateSource: function () { - var self = this - , matches = this.parseTemplateText() - , d = this.opts.delimiter; + generateSource: function () { + var opts = this.opts; + + if (opts.rmWhitespace) { + // Have to use two separate replace here as `^` and `$` operators don't + // work well with `\r`. + this.templateText = + this.templateText.replace(/\r/g, '').replace(/^\s+|\s+$/gm, ''); + } + + // Slurp spaces and tabs before <%_ and after _%> + this.templateText = + this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); + + var self = this; + var matches = this.parseTemplateText(); + var d = this.opts.delimiter; if (matches && matches.length) { - if (this.opts.compileDebug && this.opts.filename) { - this.source = ' ; __lines = ' + JSON.stringify(this.templateText) + '\n'; - this.source += ' ; __filename = "' + this.opts.filename.replace(/\\/g, '/') + '"\n'; - } matches.forEach(function (line, index) { - var opening - , closing - , include - , includeOpts - , includeSrc; + var opening; + var closing; + var include; + var includeOpts; + var includeObj; + var includeSrc; // If this is an opening tag, check for closing tags // FIXME: May end up with some false positives here // Better to store modes as k/v with '<' + delimiter as key @@ -550,9 +601,23 @@ Template.prototype = { // Must be in EVAL or RAW mode if (opening && (opening == '<' + d || opening == '<' + d + '-' || opening == '<' + d + '_')) { includeOpts = utils.shallowCopy({}, self.opts); - includeSrc = includeSource(include[1], includeOpts); - includeSrc = ' ; (function(){' + '\n' + includeSrc + - ' ; })()' + '\n'; + includeObj = includeSource(include[1], includeOpts); + if (self.opts.compileDebug) { + includeSrc = + ' ; (function(){' + '\n' + + ' var __line = 1' + '\n' + + ' , __lines = ' + JSON.stringify(includeObj.template) + '\n' + + ' , __filename = ' + JSON.stringify(includeObj.filename) + ';' + '\n' + + ' try {' + '\n' + + includeObj.source + + ' } catch (e) {' + '\n' + + ' rethrow(e, __lines, __filename, __line);' + '\n' + + ' }' + '\n' + + ' ; }).call(this)' + '\n'; + }else{ + includeSrc = ' ; (function(){' + '\n' + includeObj.source + + ' ; }).call(this)' + '\n'; + } self.source += includeSrc; self.dependencies.push(exports.resolveInclude(include[1], includeOpts.filename)); @@ -563,19 +628,17 @@ Template.prototype = { }); } - } + }, -, parseTemplateText: function () { - var str = this.templateText - , pat = this.regex - , result = pat.exec(str) - , arr = [] - , firstPos - , lastPos; + parseTemplateText: function () { + var str = this.templateText; + var pat = this.regex; + var result = pat.exec(str); + var arr = []; + var firstPos; while (result) { firstPos = result.index; - lastPos = pat.lastIndex; if (firstPos !== 0) { arr.push(str.substring(0, firstPos)); @@ -592,12 +655,12 @@ Template.prototype = { } return arr; - } + }, -, scanLine: function (line) { - var self = this - , d = this.opts.delimiter - , newLineCount = 0; + scanLine: function (line) { + var self = this; + var d = this.opts.delimiter; + var newLineCount = 0; function _addOutput() { if (self.truncate) { @@ -606,13 +669,12 @@ Template.prototype = { // after the tag that the truncation mode replaces // Handle Win / Unix / old Mac linebreaks -- do the \r\n // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, '') + line = line.replace(/^(?:\r\n|\r|\n)/, ''); self.truncate = false; } else if (self.opts.rmWhitespace) { - // Gotta be more careful here. - // .replace(/^(\s*)\n/, '$1') might be more appropriate here but as - // rmWhitespace already removes trailing spaces anyway so meh. + // rmWhitespace has already removed trailing spaces, just need + // to remove linebreaks line = line.replace(/^\n/, ''); } if (!line) { @@ -635,73 +697,75 @@ Template.prototype = { newLineCount = (line.split('\n').length - 1); switch (line) { - case '<' + d: - case '<' + d + '_': - this.mode = Template.modes.EVAL; - break; - case '<' + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case '<' + d + '-': - this.mode = Template.modes.RAW; - break; - case '<' + d + '#': - this.mode = Template.modes.COMMENT; - break; - case '<' + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; - break; - case d + '>': - case '-' + d + '>': - case '_' + d + '>': - if (this.mode == Template.modes.LITERAL) { - _addOutput(); - } + case '<' + d: + case '<' + d + '_': + this.mode = Template.modes.EVAL; + break; + case '<' + d + '=': + this.mode = Template.modes.ESCAPED; + break; + case '<' + d + '-': + this.mode = Template.modes.RAW; + break; + case '<' + d + '#': + this.mode = Template.modes.COMMENT; + break; + case '<' + d + d: + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace('<' + d + d, '<' + d) + '")' + '\n'; + break; + case d + d + '>': + this.mode = Template.modes.LITERAL; + this.source += ' ; __append("' + line.replace(d + d + '>', d + '>') + '")' + '\n'; + break; + case d + '>': + case '-' + d + '>': + case '_' + d + '>': + if (this.mode == Template.modes.LITERAL) { + _addOutput(); + } - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: + this.mode = null; + this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; + break; + default: // In script mode, depends on type of tag - if (this.mode) { + if (this.mode) { // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } + switch (this.mode) { + case Template.modes.EVAL: + case Template.modes.ESCAPED: + case Template.modes.RAW: + if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { + line += '\n'; } - switch (this.mode) { + } + switch (this.mode) { // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; + case Template.modes.EVAL: + this.source += ' ; ' + line + '\n'; + break; // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escape(' + - line.replace(_TRAILING_SEMCOL, '').trim() + '))' + '\n'; - break; + case Template.modes.ESCAPED: + this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; + break; // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + - line.replace(_TRAILING_SEMCOL, '').trim() + ')' + '\n'; - break; - case Template.modes.COMMENT: + case Template.modes.RAW: + this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; + break; + case Template.modes.COMMENT: // Do nothing - break; + break; // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - _addOutput(); - break; - } - } - // In string mode, just add the output - else { + case Template.modes.LITERAL: _addOutput(); + break; } + } + // In string mode, just add the output + else { + _addOutput(); + } } if (self.opts.compileDebug && newLineCount) { @@ -711,9 +775,17 @@ Template.prototype = { } }; -/* - * Export the internal function for escaping XML so people - * can use for manual escaping if needed +/** + * Escape characters reserved in XML. + * + * This is simply an export of {@link module:utils.escapeXML}. + * + * If `markup` is `undefined` or `null`, the empty string is returned. + * + * @param {String} markup Input string + * @return {String} Escaped string + * @public + * @func * */ exports.escapeXML = utils.escapeXML; @@ -731,14 +803,14 @@ exports.__express = exports.renderFile; // Add require support /* istanbul ignore else */ if (require.extensions) { - require.extensions['.ejs'] = function (module, filename) { - filename = filename || /* istanbul ignore next */ module.filename; + require.extensions['.ejs'] = function (module, flnm) { + var filename = flnm || /* istanbul ignore next */ module.filename; var options = { - filename: filename - , client: true - } - , template = fs.readFileSync(filename).toString() - , fn = exports.compile(template, options); + filename: filename, + client: true + }; + var template = fileLoader(filename).toString(); + var fn = exports.compile(template, options); module._compile('module.exports = ' + fn.toString() + ';', filename); }; } @@ -753,6 +825,16 @@ if (require.extensions) { exports.VERSION = _VERSION_STRING; +/** + * Name for detection of EJS. + * + * @readonly + * @type {String} + * @public + */ + +exports.name = _NAME; + /* istanbul ignore if */ if (typeof window != 'undefined') { window.ejs = exports; diff --git a/node_modules/ejs/lib/utils.js b/node_modules/ejs/lib/utils.js index 9e2c1d0..1b539da 100644 --- a/node_modules/ejs/lib/utils.js +++ b/node_modules/ejs/lib/utils.js @@ -45,17 +45,17 @@ exports.escapeRegExpChars = function (string) { }; var _ENCODE_HTML_RULES = { - '&': '&' - , '<': '<' - , '>': '>' - , '"': '"' - , "'": ''' - } - , _MATCH_HTML = /[&<>\'"]/g; + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +}; +var _MATCH_HTML = /[&<>\'"]/g; function encode_char(c) { return _ENCODE_HTML_RULES[c] || c; -}; +} /** * Stringified version of constants used by {@link module:utils.escapeXML}. @@ -98,11 +98,13 @@ exports.escapeXML = function (markup) { .replace(_MATCH_HTML, encode_char); }; exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; }; /** - * Copy all properties from one object to another, in a shallow fashion. + * Naive copy of properties from one object to another. + * Does not recurse into non-scalar properties + * Does not check to see if the property has a value before copying * * @param {Object} to Destination object * @param {Object} from Source object @@ -118,6 +120,28 @@ exports.shallowCopy = function (to, from) { return to; }; +/** + * Naive copy of a list of key names, from one object to another. + * Only copies property if it is actually defined + * Does not recurse into non-scalar properties + * + * @param {Object} to Destination object + * @param {Object} from Source object + * @param {Array} list List of properties to copy + * @return {Object} Destination object + * @static + * @private + */ +exports.shallowCopyFromList = function (to, from, list) { + for (var i = 0; i < list.length; i++) { + var p = list[i]; + if (typeof from[p] != 'undefined') { + to[p] = from[p]; + } + } + return to; +}; + /** * Simple in-process cache implementation. Does not implement limits of any * sort. @@ -138,4 +162,3 @@ exports.cache = { this._data = {}; } }; - diff --git a/node_modules/ejs/package.json b/node_modules/ejs/package.json index 8b0c0e9..462f098 100644 --- a/node_modules/ejs/package.json +++ b/node_modules/ejs/package.json @@ -1,42 +1,49 @@ { "_args": [ [ - "ejs@*", - "/Users/martin/newdev/Rinser" + { + "name": "ejs", + "raw": "ejs@2.5.6", + "rawSpec": "2.5.6", + "scope": null, + "spec": "2.5.6", + "type": "version" + }, + "/home/martind2000/dev/Rinser" ] ], - "_from": "ejs@*", - "_id": "ejs@2.4.2", + "_from": "ejs@2.5.6", + "_id": "ejs@2.5.6", "_inCache": true, "_installable": true, "_location": "/ejs", - "_nodeVersion": "4.4.4", + "_nodeVersion": "6.9.1", "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/ejs-2.4.2.tgz_1464117640663_0.8193834638223052" + "tmp": "tmp/ejs-2.5.6.tgz_1487277787176_0.4875628533773124" }, "_npmUser": { "email": "mde@fleegix.org", "name": "mde" }, - "_npmVersion": "2.15.1", + "_npmVersion": "3.10.8", "_phantomChildren": {}, "_requested": { "name": "ejs", - "raw": "ejs@*", - "rawSpec": "*", + "raw": "ejs@2.5.6", + "rawSpec": "2.5.6", "scope": null, - "spec": "*", - "type": "range" + "spec": "2.5.6", + "type": "version" }, "_requiredBy": [ "/" ], - "_resolved": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz", - "_shasum": "7057eb4812958fb731841cd9ca353343efe597b1", + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.6.tgz", + "_shasum": "479636bfa3fe3b1debd52087f0acb204b4f19c88", "_shrinkwrap": null, - "_spec": "ejs@*", - "_where": "/Users/martin/newdev/Rinser", + "_spec": "ejs@2.5.6", + "_where": "/home/martind2000/dev/Rinser", "author": { "email": "mde@fleegix.org", "name": "Matthew Eernisse", @@ -47,47 +54,44 @@ }, "contributors": [ { - "name": "Timothy Gu", "email": "timothygu99@gmail.com", + "name": "Timothy Gu", "url": "https://timothygu.github.io" } ], "dependencies": {}, "description": "Embedded JavaScript templates", "devDependencies": { - "browserify": "^8.0.3", - "istanbul": "~0.3.5", + "browserify": "^13.0.1", + "eslint": "^3.0.0", + "git-directory-deploy": "^1.5.1", + "istanbul": "~0.4.3", "jake": "^8.0.0", - "jsdoc": "^3.3.0-beta1", - "lru-cache": "^2.5.0", - "mocha": "^2.1.0", - "rimraf": "^2.2.8", - "uglify-js": "^2.4.16" + "jsdoc": "^3.4.0", + "lru-cache": "^4.0.1", + "mocha": "^3.0.2", + "uglify-js": "^2.6.2" }, "directories": {}, "dist": { - "shasum": "7057eb4812958fb731841cd9ca353343efe597b1", - "tarball": "https://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz" + "shasum": "479636bfa3fe3b1debd52087f0acb204b4f19c88", + "tarball": "https://registry.npmjs.org/ejs/-/ejs-2.5.6.tgz" }, "engines": { "node": ">=0.10.0" }, "homepage": "https://github.com/mde/ejs", "keywords": [ - "ejs", + "template", "engine", - "template" + "ejs" ], "license": "Apache-2.0", "main": "./lib/ejs.js", "maintainers": [ { - "name": "tjholowaychuk", - "email": "tj@vision-media.ca" - }, - { - "name": "mde", - "email": "mde@fleegix.org" + "email": "mde@fleegix.org", + "name": "mde" } ], "name": "ejs", @@ -99,10 +103,10 @@ }, "scripts": { "coverage": "istanbul cover node_modules/mocha/bin/_mocha", - "devdoc": "rimraf out && jsdoc -p -c jsdoc.json lib/* docs/jsdoc/*", - "doc": "rimraf out && jsdoc -c jsdoc.json lib/* docs/jsdoc/*", - "sample": "npm install express && node sample/index.js", + "devdoc": "jake doc[dev]", + "doc": "jake doc", + "lint": "eslint \"**/*.js\" Jakefile", "test": "mocha" }, - "version": "2.4.2" + "version": "2.5.6" } diff --git a/node_modules/ejs/test/ejs.js b/node_modules/ejs/test/ejs.js index 1baf07f..8960a1e 100644 --- a/node_modules/ejs/test/ejs.js +++ b/node_modules/ejs/test/ejs.js @@ -1,15 +1,16 @@ /* jshint mocha: true */ +/* eslint-env node, mocha */ /** * Module dependencies. */ -var ejs = require('..') - , fs = require('fs') - , read = fs.readFileSync - , assert = require('assert') - , path = require('path') - , LRU = require('lru-cache'); +var ejs = require('..'); +var fs = require('fs'); +var read = fs.readFileSync; +var assert = require('assert'); +var path = require('path'); +var LRU = require('lru-cache'); try { fs.mkdirSync(__dirname + '/tmp'); @@ -103,10 +104,28 @@ suite('ejs.compile(str, options)', function () { delete ejs.delimiter; }); + test('support custom escape function', function () { + var customEscape; + var fn; + customEscape = function customEscape(str) { + return !str ? '' : str.toUpperCase(); + }; + fn = ejs.compile('HELLO <%= name %>', {escape: customEscape}); + assert.equal(fn({name: 'world'}), 'HELLO WORLD'); + }); + + test('strict mode works', function () { + assert.equal(ejs.render(fixture('strict.ejs'), {}, {strict: true}), 'true'); + }); + +}); + +suite('client mode', function () { + test('have a working client option', function () { - var fn - , str - , preFn; + var fn; + var str; + var preFn; fn = ejs.compile('

<%= foo %>

', {client: true}); str = fn.toString(); if (!process.env.running_under_istanbul) { @@ -116,9 +135,9 @@ suite('ejs.compile(str, options)', function () { }); test('support client mode without locals', function () { - var fn - , str - , preFn; + var fn; + var str; + var preFn; fn = ejs.compile('

<%= "foo" %>

', {client: true}); str = fn.toString(); if (!process.env.running_under_istanbul) { @@ -129,27 +148,17 @@ suite('ejs.compile(str, options)', function () { test('not include rethrow() in client mode if compileDebug is false', function () { var fn = ejs.compile('

<%= "foo" %>

', { - client: true - , compileDebug: false - }); + client: true, + compileDebug: false + }); // There could be a `rethrow` in the function declaration assert((fn.toString().match(/rethrow/g) || []).length <= 1); }); - test('support custom escape function', function () { - var customEscape - , fn; - customEscape = function customEscape(str) { - return !str ? '' : str.toUpperCase(); - }; - fn = ejs.compile('HELLO <%= name %>', {escape: customEscape}); - assert.equal(fn({name: 'world'}), 'HELLO WORLD'); - }); - test('support custom escape function in client mode', function () { - var customEscape - , fn - , str; + var customEscape; + var fn; + var str; customEscape = function customEscape(str) { return !str ? '' : str.toUpperCase(); }; @@ -157,10 +166,31 @@ suite('ejs.compile(str, options)', function () { str = fn.toString(); if (!process.env.running_under_istanbul) { eval('var preFn = ' + str); - assert.equal(preFn({name: 'world'}), 'HELLO WORLD'); + assert.equal(preFn({name: 'world'}), 'HELLO WORLD'); // eslint-disable-line no-undef } }); + test('escape filename in errors in client mode', function () { + assert.throws(function () { + var fn = ejs.compile('<% throw new Error("whoops"); %>', {client: true, filename: '