This commit is contained in:
martin 2018-06-01 10:24:32 +01:00
parent 92fa8cef95
commit 8d592c458f
85 changed files with 10892 additions and 2428 deletions

File diff suppressed because it is too large Load Diff

29
news.js
View File

@ -12,6 +12,31 @@ var logger = log4js.getLogger();
// feeds.simple_test_feed = require("./config/feed").feed;
// Or define in-line
const f = ["http://qz.com/feed/",
"http://feeds2.feedburner.com/businessinsider",
"http://feeds.reuters.com/reuters/UKTopNews",
"http://feeds.reuters.com/reuters/UKdomesticNews",
"http://feeds.reuters.com/reuters/UKWorldNews",
"http://feeds.reuters.com/reuters/topNews",
"http://feeds.reuters.com/Reuters/worldNews",
"http://hosted2.ap.org/atom/APDEFAULT/cae69a7523db45408eeb2b3a98c0c9c5",
"http://www.cityam.com/feeds/main.xml",
"http://www.londonlovesbusiness.com/navrss?navsectioncode=121",
"http://www.ibtimes.co.uk/rss/uk",
"http://feeds.bbci.co.uk/news/rss.xml?edition=uk",
"http://feeds.bbci.co.uk/news/scotland/rss.xml?edition=uk",
"http://news.google.com/?output=rss",
"http://feeds.feedburner.com/TheAtlantic",
"http://www.telegraph.co.uk/news/rss.xml",
"http://www.guardian.co.uk/rssfeed/0,,1,00.xml",
"http://feeds.marketwatch.com/marketwatch/topstories",
"http://feeds.feedburner.com/wingsoverscotland/FgKv",
"http://bellacaledonia.org.uk/feed/",
"http://www.theweek.co.uk/feeds/all",
"http://fivethirtyeight.com/all/feed"];
feeds.simple_test_feed = {
'feed_name': 'feed',
'default_count': 1,
@ -68,9 +93,9 @@ feeds.simple_test_feed = {
'count': 100,
'feed_url': 'http://45.33.114.116:8080/http%3A%2F%2Fwww.theweek.co.uk%2Ffeeds%2Fall'
}, {'count': 100, 'feed_url': 'http://45.33.114.116:8080/http%3A%2F%2Ffivethirtyeight.com%2Fall%2Ffeed'}]
}
};
;
var braider_options = {
feeds: feeds,
indent: ' ',

78
node_modules/ejs/Jakefile generated vendored
View File

@ -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,57 @@ 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/**'
]);
});
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();
});

104
node_modules/ejs/README.md generated vendored
View File

@ -3,7 +3,8 @@
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)
[![Known Vulnerabilities](https://snyk.io/test/npm/ejs/badge.svg?style=flat-square)](https://snyk.io/test/npm/ejs)
## Installation
@ -18,7 +19,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,10 +34,12 @@ $ npm install ejs
<% } %>
```
Try EJS online at: https://ionicabizau.github.io/ejs-playground/.
## Usage
```javascript
var template = ejs.compile(str, options);
let template = ejs.compile(str, options);
template(data);
// => Rendered HTML string
@ -50,35 +53,43 @@ 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
- `cache` Compiled functions are cached, requires `filename`
- `filename` The name of the file being rendered. Not required if you
are using `renderFile()`. Used by `cache` to key caches, and for includes.
- `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
- `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
([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
- `strict` When set to `true`, generated function is in strict mode
- `_with` Whether or not to use `with() {}` constructs. If `false` then the locals will be stored in the `locals` object. Set to `false` in strict mode.
- `localsName` Name to use for the object storing local variables when not using `with` Defaults to `locals`
- `rmWhitespace` Remove all safe-to-remove whitespace, including leading
- `delimiter` Character to use with angle brackets for open/close
- `debug` Output generated function body
- `strict` When set to `true`, generated function is in strict mode
- `_with` Whether or not to use `with() {}` constructs. If `false`
then the locals will be stored in the `locals` object. Set to `false` in strict mode.
- `localsName` Name to use for the object storing local variables when not using
`with` Defaults to `locals`
- `rmWhitespace` Remove all safe-to-remove whitespace, including leading
and trailing whitespace. It also enables a safer version of `-%>` line
slurping for all scriptlet tags (it does not strip new lines of tags in
the middle of a line).
- `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).
- `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).
- `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print
output inside scriptlet tags.
- `async` When `true`, EJS will use an async function for rendering. (Depends
on async/await support in the JS runtime.
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 +100,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 +110,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
@ -129,7 +141,7 @@ still supported.
Custom delimiters can be applied on a per-template basis, or globally:
```javascript
var ejs = require('ejs'),
let ejs = require('ejs'),
users = ['geddy', 'neil', 'alex'];
// Just one template
@ -149,8 +161,8 @@ functions used to render templates. It's easy to plug in LRU caching using
Node's `lru-cache` library:
```javascript
var ejs = require('ejs')
, LRU = require('lru-cache');
let ejs = require('ejs'),
LRU = require('lru-cache');
ejs.cache = LRU(100); // LRU cache with 100-item limit
```
@ -158,6 +170,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 file loader
The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader.
```javascript
let ejs = require('ejs');
let 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 +205,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.
@ -190,7 +217,7 @@ Include one of these files on your page, and `ejs` should be available globally.
<div id="output"></div>
<script src="ejs.min.js"></script>
<script>
var people = ['geddy', 'neil', 'alex'],
let people = ['geddy', 'neil', 'alex'],
html = ejs.render('<%= people.join(", "); %>', {people: people});
// With jQuery:
$('#output').html(html);
@ -204,19 +231,23 @@ Include one of these files on your page, and `ejs` should be available globally.
Most of EJS will work as expected; however, there are a few things to note:
1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work.
2. For the same reason, `include`s do not work unless you use an `IncludeCallback`. Here is an example:
2. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example:
```javascript
var str = "Hello <%= include('file', {person: 'John'}); %>",
let str = "Hello <%= include('file', {person: 'John'}); %>",
fn = ejs.compile(str, {client: true});
fn(data, null, function(path, d){ // IncludeCallback
fn(data, null, function(path, d){ // include callback
// path -> 'file'
// d -> {person: 'John'}
// Put your code here
// Put your code here
// Return the contents of file as a string
}); // returns rendered string
```
### IDE Integration with Syntax Highlighting
VSCode:Javascript EJS by *DigitalBrainstem*
## Related projects
There are a number of implementations of EJS:
@ -226,6 +257,7 @@ There are a number of implementations of EJS:
* EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/
* Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs
* Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript
* DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar
## License
@ -235,5 +267,3 @@ Licensed under the Apache License, Version 2.0
- - -
EJS Embedded JavaScript templates copyright 2112
mde@fleegix.org.

976
node_modules/ejs/ejs.js generated vendored

File diff suppressed because it is too large Load Diff

2
node_modules/ejs/ejs.min.js generated vendored

File diff suppressed because one or more lines are too long

752
node_modules/ejs/lib/ejs.js generated vendored Normal file → Executable file
View File

@ -19,7 +19,7 @@
'use strict';
/**
* @file Embedded JavaScript templating engine.
* @file Embedded JavaScript templating engine. {@link http://ejs.co}
* @author Matthew Eernisse <mde@fleegix.org>
* @author Tiancheng "Timothy" Gu <timothygu99@gmail.com>
* @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_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',
'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async'];
// We don't allow 'cache' option to be passed in the data obj for
// the normal `render` call, but this is where Express 2 & 3 put it
// so we make an exception for `renderFile`
var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.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}
@ -80,28 +93,79 @@ exports.cache = utils.cache;
exports.localsName = _DEFAULT_LOCALS_NAME;
/**
* Promise implementation -- defaults to the native implementation if available
* This is mostly just for testability
*
* @type {Function}
* @public
*/
exports.promiseImpl = (new Function('return this;'))().Promise;
/**
* 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;
var filePath;
var views = options.views;
// Abs path
if (path.charAt(0) == '/') {
includePath = exports.resolveInclude(path.replace(/^\/*/,''), options.root || '/', true);
}
// Relative paths
else {
// Look relative to a passed filename first
if (options.filename) {
filePath = exports.resolveInclude(path, options.filename);
if (fs.existsSync(filePath)) {
includePath = filePath;
}
}
// Then look in any views directories
if (!includePath) {
if (Array.isArray(views) && views.some(function (v) {
filePath = exports.resolveInclude(path, v, true);
return fs.existsSync(filePath);
})) {
includePath = filePath;
}
}
if (!includePath) {
throw new Error('Could not find the include file "' +
options.escapeFunction(path) + '"');
}
}
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 +185,89 @@ 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;
if (!cb) {
if (typeof exports.promiseImpl == 'function') {
return new exports.promiseImpl(function (resolve, reject) {
try {
result = handleCache(options)(data);
resolve(result);
}
catch (err) {
reject(err);
}
});
}
else {
throw new Error('Please provide a callback function');
}
}
else {
try {
result = handleCache(options)(data);
}
catch (err) {
return cb(err);
}
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 +285,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 +295,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 +328,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 +352,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');
}
/**
@ -266,6 +365,7 @@ function cpOptsInData(data, opts) {
*
* @return {(TemplateFunction|ClientFunction)}
* Depending on the value of `opts.client`, either type might be returned.
* Note that the return type of the function also depends on the value of `opts.async`.
* @public
*/
@ -298,19 +398,19 @@ exports.compile = function compile(template, opts) {
* @param {String} template EJS template
* @param {Object} [data={}] template data
* @param {Options} [opts={}] compilation and rendering options
* @return {String}
* @return {(String|Promise<String>)}
* Return value type depends on `opts.async`.
* @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_PASSABLE_WITH_DATA);
}
return handleCache(opts, template)(data);
@ -330,37 +430,56 @@ 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 args = Array.prototype.slice.call(arguments);
var filename = args.shift();
var cb;
var opts = {filename: filename};
var data;
var viewOpts;
// Don't pollute passed in opts obj with new vals
opts = utils.shallowCopy({}, 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']) {
cpOptsInData(data.settings['view options'], opts);
// Do we have a callback?
if (typeof arguments[arguments.length - 1] == 'function') {
cb = args.pop();
}
// Do we have data/opts?
if (args.length) {
// Should always have data obj
data = args.shift();
// Normal passed opts (data obj + opts obj)
if (args.length) {
// Use shallowCopy so we don't pollute passed in opts obj with new vals
utils.shallowCopy(opts, args.pop());
}
// Express 3 and lower
// Special casing for Express (settings + opts-in-data)
else {
cpOptsInData(data, opts);
// Express 3 and 4
if (data.settings) {
// Pull a few things from known locations
if (data.settings.views) {
opts.views = data.settings.views;
}
if (data.settings['view cache']) {
opts.cache = true;
}
// Undocumented after Express 2, but still usable, esp. for
// items that are unsafe to be passed along with data, like `root`
viewOpts = data.settings['view options'];
if (viewOpts) {
utils.shallowCopy(opts, viewOpts);
}
}
// Express 2 and lower, values set in app.locals, or people who just
// want to pass options in their data. NOTE: These values will override
// anything previously set in settings or settings['view options']
utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);
}
opts.filename = filename;
}
else {
data = {};
}
opts.filename = path;
try {
result = handleCache(opts)(data);
}
catch(err) {
return cb(err);
}
return cb(null, result);
return tryHandleCache(opts, data, cb);
};
/**
@ -391,7 +510,11 @@ function Template(text, opts) {
options.context = opts.context;
options.cache = opts.cache || false;
options.rmWhitespace = opts.rmWhitespace;
options.root = opts.root;
options.outputFunctionName = opts.outputFunctionName;
options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME;
options.views = opts.views;
options.async = opts.async;
if (options.strict) {
options._with = false;
@ -406,43 +529,36 @@ 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;
var asyncCtor;
if (!this.source) {
this.generateSource();
prepended += ' var __output = [], __append = __output.push.bind(__output);' + '\n';
if (opts.outputFunctionName) {
prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n';
}
if (opts._with !== false) {
prepended += ' with (' + opts.localsName + ' || {}) {' + '\n';
appended += ' }' + '\n';
@ -453,25 +569,21 @@ Template.prototype = {
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';
+ ' , __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 = 'escape = escape || ' + escape.toString() + ';' + '\n' + src;
src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src;
if (opts.compileDebug) {
src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src;
}
@ -480,9 +592,30 @@ Template.prototype = {
if (opts.strict) {
src = '"use strict";\n' + src;
}
if (opts.debug) {
console.log(src);
}
try {
fn = new Function(opts.localsName + ', escape, include, rethrow', src);
if (opts.async) {
// Have to use generated function for this, since in envs without support,
// it breaks in parsing
try {
asyncCtor = (new Function('return (async function(){}).constructor;'))();
}
catch(e) {
if (e instanceof SyntaxError) {
throw new Error('This environment does not support async/await');
}
else {
throw e;
}
}
}
else {
asyncCtor = Function;
}
fn = new asyncCtor(opts.localsName + ', escapeFn, include, rethrow', src);
}
catch(e) {
// istanbul ignore else
@ -490,7 +623,13 @@ 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';
if (!e.async) {
e.message += '\n';
e.message += 'Or, if you meant to create an async function, pass async: true as an option.';
}
}
throw e;
}
@ -511,28 +650,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,12 +699,26 @@ 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, escapeFn);' + '\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));
includeOpts.filename));
return;
}
}
@ -563,19 +726,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,116 +753,117 @@ Template.prototype = {
}
return arr;
}
},
, scanLine: function (line) {
var self = this
, d = this.opts.delimiter
, newLineCount = 0;
function _addOutput() {
if (self.truncate) {
// Only replace single leading linebreak in the line after
// -%> tag -- this is the single, trailing linebreak
// 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)/, '')
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.
line = line.replace(/^\n/, '');
}
if (!line) {
return;
}
// Preserve literal slashes
line = line.replace(/\\/g, '\\\\');
// Convert linebreaks
line = line.replace(/\n/g, '\\n');
line = line.replace(/\r/g, '\\r');
// Escape double-quotes
// - this will be the delimiter during execution
line = line.replace(/"/g, '\\"');
self.source += ' ; __append("' + line + '")' + '\n';
_addOutput: function (line) {
if (this.truncate) {
// Only replace single leading linebreak in the line after
// -%> tag -- this is the single, trailing linebreak
// 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)/, '');
this.truncate = false;
}
else if (this.opts.rmWhitespace) {
// rmWhitespace has already removed trailing spaces, just need
// to remove linebreaks
line = line.replace(/^\n/, '');
}
if (!line) {
return line;
}
// Preserve literal slashes
line = line.replace(/\\/g, '\\\\');
// Convert linebreaks
line = line.replace(/\n/g, '\\n');
line = line.replace(/\r/g, '\\r');
// Escape double-quotes
// - this will be the delimiter during execution
line = line.replace(/"/g, '\\"');
this.source += ' ; __append("' + line + '")' + '\n';
},
scanLine: function (line) {
var self = this;
var d = this.opts.delimiter;
var newLineCount = 0;
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) {
this._addOutput(line);
}
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 '//' 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) {
// Just executing code
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;
// Exec and output
case Template.modes.RAW:
this.source += ' ; __append(' +
line.replace(_TRAILING_SEMCOL, '').trim() + ')' + '\n';
break;
case Template.modes.COMMENT:
// Do nothing
break;
// Literal <%% mode, append as raw output
case Template.modes.LITERAL:
_addOutput();
break;
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 '//' 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';
}
}
// In string mode, just add the output
else {
_addOutput();
switch (this.mode) {
// Just executing code
case Template.modes.EVAL:
this.source += ' ; ' + line + '\n';
break;
// Exec, esc, and output
case Template.modes.ESCAPED:
this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n';
break;
// Exec and output
case Template.modes.RAW:
this.source += ' ; __append(' + stripSemi(line) + ')' + '\n';
break;
case Template.modes.COMMENT:
// Do nothing
break;
// Literal <%% mode, append as raw output
case Template.modes.LITERAL:
this._addOutput(line);
break;
}
}
// In string mode, just add the output
else {
this._addOutput(line);
}
}
if (self.opts.compileDebug && newLineCount) {
@ -711,9 +873,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 +901,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 +923,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;

47
node_modules/ejs/lib/utils.js generated vendored
View File

@ -45,17 +45,17 @@ exports.escapeRegExpChars = function (string) {
};
var _ENCODE_HTML_RULES = {
'&': '&amp;'
, '<': '&lt;'
, '>': '&gt;'
, '"': '&#34;'
, "'": '&#39;'
}
, _MATCH_HTML = /[&<>\'"]/g;
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
"'": '&#39;'
};
var _MATCH_HTML = /[&<>'"]/g;
function encode_char(c) {
return _ENCODE_HTML_RULES[c] || c;
};
}
/**
* Stringified version of constants used by {@link module:utils.escapeXML}.
@ -95,14 +95,16 @@ exports.escapeXML = function (markup) {
return markup == undefined
? ''
: String(markup)
.replace(_MATCH_HTML, encode_char);
.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 = {};
}
};

58
node_modules/ejs/package.json generated vendored
View File

@ -1,30 +1,27 @@
{
"_args": [
[
"ejs@http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"/Users/martin/dev/Rinser"
]
],
"_from": "ejs@http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"_id": "ejs@http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"_from": "ejs@*",
"_id": "ejs@2.6.1",
"_inBundle": false,
"_integrity": "sha1-cFfrSBKVj7cxhBzZyjUzQ+/ll7E=",
"_integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==",
"_location": "/ejs",
"_phantomChildren": {},
"_requested": {
"type": "remote",
"raw": "ejs@http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"type": "range",
"registry": true,
"raw": "ejs@*",
"name": "ejs",
"escapedName": "ejs",
"rawSpec": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"saveSpec": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"fetchSpec": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz"
"rawSpec": "*",
"saveSpec": null,
"fetchSpec": "*"
},
"_requiredBy": [
"/"
],
"_spec": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz",
"_where": "/Users/martin/dev/Rinser",
"_resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz",
"_shasum": "498ec0d495655abc6f23cd61868d926464071aa0",
"_spec": "ejs@*",
"_where": "/Users/martin/dev/test/Rinser",
"author": {
"name": "Matthew Eernisse",
"email": "mde@fleegix.org",
@ -33,6 +30,7 @@
"bugs": {
"url": "https://github.com/mde/ejs/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Timothy Gu",
@ -41,16 +39,18 @@
}
],
"dependencies": {},
"deprecated": false,
"description": "Embedded JavaScript templates",
"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"
"browserify": "^13.1.1",
"eslint": "^4.14.0",
"git-directory-deploy": "^1.5.1",
"istanbul": "~0.4.3",
"jake": "^8.0.16",
"jsdoc": "^3.4.0",
"lru-cache": "^4.0.1",
"mocha": "^5.0.5",
"uglify-js": "^3.3.16"
},
"engines": {
"node": ">=0.10.0"
@ -70,10 +70,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",
"test": "mocha"
"devdoc": "jake doc[dev]",
"doc": "jake doc",
"lint": "eslint \"**/*.js\" Jakefile",
"test": "jake test"
},
"version": "http://registry.npmjs.org/ejs/-/ejs-2.4.2.tgz"
"version": "2.6.1"
}

932
node_modules/ejs/test/ejs.js generated vendored
View File

@ -1,932 +0,0 @@
/* jshint mocha: true */
/**
* Module dependencies.
*/
var ejs = require('..')
, fs = require('fs')
, read = fs.readFileSync
, assert = require('assert')
, path = require('path')
, LRU = require('lru-cache');
try {
fs.mkdirSync(__dirname + '/tmp');
} catch (ex) {
if (ex.code !== 'EEXIST') {
throw ex;
}
}
// From https://gist.github.com/pguillory/729616
function hook_stdio(stream, callback) {
var old_write = stream.write;
stream.write = (function() {
return function(string, encoding, fd) {
callback(string, encoding, fd);
};
})(stream.write);
return function() {
stream.write = old_write;
};
}
/**
* Load fixture `name`.
*/
function fixture(name) {
return read('test/fixtures/' + name, 'utf8');
}
/**
* User fixtures.
*/
var users = [];
users.push({name: 'geddy'});
users.push({name: 'neil'});
users.push({name: 'alex'});
suite('ejs.compile(str, options)', function () {
test('compile to a function', function () {
var fn = ejs.compile('<p>yay</p>');
assert.equal(fn(), '<p>yay</p>');
});
test('empty input works', function () {
var fn = ejs.compile('');
assert.equal(fn(), '');
});
test('throw if there are syntax errors', function () {
try {
ejs.compile(fixture('fail.ejs'));
}
catch (err) {
assert.ok(err.message.indexOf('compiling ejs') > -1);
try {
ejs.compile(fixture('fail.ejs'), {filename: 'fail.ejs'});
}
catch (err) {
assert.ok(err.message.indexOf('fail.ejs') > -1);
return;
}
}
throw new Error('no error reported when there should be');
});
test('allow customizing delimiter local var', function () {
var fn;
fn = ejs.compile('<p><?= name ?></p>', {delimiter: '?'});
assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
fn = ejs.compile('<p><:= name :></p>', {delimiter: ':'});
assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
fn = ejs.compile('<p><$= name $></p>', {delimiter: '$'});
assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
});
test('default to using ejs.delimiter', function () {
var fn;
ejs.delimiter = '&';
fn = ejs.compile('<p><&= name &></p>');
assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
fn = ejs.compile('<p><|= name |></p>', {delimiter: '|'});
assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
delete ejs.delimiter;
});
test('have a working client option', function () {
var fn
, str
, preFn;
fn = ejs.compile('<p><%= foo %></p>', {client: true});
str = fn.toString();
if (!process.env.running_under_istanbul) {
eval('var preFn = ' + str);
assert.equal(preFn({foo: 'bar'}), '<p>bar</p>');
}
});
test('support client mode without locals', function () {
var fn
, str
, preFn;
fn = ejs.compile('<p><%= "foo" %></p>', {client: true});
str = fn.toString();
if (!process.env.running_under_istanbul) {
eval('var preFn = ' + str);
assert.equal(preFn(), '<p>foo</p>');
}
});
test('not include rethrow() in client mode if compileDebug is false', function () {
var fn = ejs.compile('<p><%= "foo" %></p>', {
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;
customEscape = function customEscape(str) {
return !str ? '' : str.toUpperCase();
};
fn = ejs.compile('HELLO <%= name %>', {escape: customEscape, client: true});
str = fn.toString();
if (!process.env.running_under_istanbul) {
eval('var preFn = ' + str);
assert.equal(preFn({name: 'world'}), 'HELLO WORLD');
}
});
});
suite('ejs.render(str, data, opts)', function () {
test('render the template', function () {
assert.equal(ejs.render('<p>yay</p>'), '<p>yay</p>');
});
test('empty input works', function () {
assert.equal(ejs.render(''), '');
});
test('undefined renders nothing escaped', function () {
assert.equal(ejs.render('<%= undefined %>'), '');
});
test('undefined renders nothing raw', function () {
assert.equal(ejs.render('<%- undefined %>'), '');
});
test('null renders nothing escaped', function () {
assert.equal(ejs.render('<%= null %>'), '');
});
test('null renders nothing raw', function () {
assert.equal(ejs.render('<%- null %>'), '');
});
test('zero-value data item renders something escaped', function () {
assert.equal(ejs.render('<%= 0 %>'), '0');
});
test('zero-value data object renders something raw', function () {
assert.equal(ejs.render('<%- 0 %>'), '0');
});
test('accept locals', function () {
assert.equal(ejs.render('<p><%= name %></p>', {name: 'geddy'}),
'<p>geddy</p>');
});
test('accept locals without using with() {}', function () {
assert.equal(ejs.render('<p><%= locals.name %></p>', {name: 'geddy'},
{_with: false}),
'<p>geddy</p>');
assert.throws(function() {
ejs.render('<p><%= name %></p>', {name: 'geddy'},
{_with: false});
}, /name is not defined/);
});
test('accept custom name for locals', function () {
ejs.localsName = 'it';
assert.equal(ejs.render('<p><%= it.name %></p>', {name: 'geddy'},
{_with: false}),
'<p>geddy</p>');
assert.throws(function() {
ejs.render('<p><%= name %></p>', {name: 'geddy'},
{_with: false});
}, /name is not defined/);
ejs.localsName = 'locals';
});
test('support caching', function () {
var file = __dirname + '/tmp/render.ejs'
, options = {cache: true, filename: file}
, out = ejs.render('<p>Old</p>', {}, options)
, expected = '<p>Old</p>';
assert.equal(out, expected);
// Assert no change, still in cache
out = ejs.render('<p>New</p>', {}, options);
assert.equal(out, expected);
});
test('support LRU caching', function () {
var oldCache = ejs.cache
, file = __dirname + '/tmp/render.ejs'
, options = {cache: true, filename: file}
, out
, expected = '<p>Old</p>';
// Switch to LRU
ejs.cache = LRU();
out = ejs.render('<p>Old</p>', {}, options);
assert.equal(out, expected);
// Assert no change, still in cache
out = ejs.render('<p>New</p>', {}, options);
assert.equal(out, expected);
// Restore system cache
ejs.cache = oldCache;
});
test('opts.context', function () {
var ctxt = {foo: 'FOO'}
, out = ejs.render('<%= this.foo %>', {}, {context: ctxt});
assert.equal(out, ctxt.foo);
});
});
suite('ejs.renderFile(path, [data], [options], fn)', function () {
test('render a file', function(done) {
ejs.renderFile('test/fixtures/para.ejs', function(err, html) {
if (err) {
return done(err);
}
assert.equal(html, '<p>hey</p>\n');
done();
});
});
test('accept locals', function(done) {
var data = {name: 'fonebone'}
, options = {delimiter: '$'};
ejs.renderFile('test/fixtures/user.ejs', data, options, function(err, html) {
if (err) {
return done(err);
}
assert.equal(html, '<h1>fonebone</h1>\n');
done();
});
});
test('accept locals without using with() {}', function(done) {
var data = {name: 'fonebone'}
, options = {delimiter: '$', _with: false}
, doneCount = 0;
ejs.renderFile('test/fixtures/user-no-with.ejs', data, options,
function(err, html) {
if (err) {
if (doneCount === 2) {
return;
}
doneCount = 2;
return done(err);
}
assert.equal(html, '<h1>fonebone</h1>\n');
doneCount++;
if (doneCount === 2) {
done();
}
});
ejs.renderFile('test/fixtures/user.ejs', data, options, function(err) {
if (!err) {
if (doneCount === 2) {
return;
}
doneCount = 2;
return done(new Error('error not thrown'));
}
doneCount++;
if (doneCount === 2) {
done();
}
});
});
test('not catch err thrown by callback', function(done) {
var data = {name: 'fonebone'}
, options = {delimiter: '$'}
, counter = 0;
var d = require('domain').create();
d.on('error', function (err) {
assert.equal(counter, 1);
assert.equal(err.message, 'Exception in callback');
done();
});
d.run(function () {
// process.nextTick() needed to work around mochajs/mocha#513
//
// tl;dr: mocha doesn't support synchronous exception throwing in
// domains. Have to make it async. Ticket closed because: "domains are
// deprecated :D"
process.nextTick(function () {
ejs.renderFile('test/fixtures/user.ejs', data, options,
function(err) {
counter++;
if (err) {
assert.notEqual(err.message, 'Exception in callback');
return done(err);
}
throw new Error('Exception in callback');
});
});
});
});
test('support caching', function (done) {
var expected = '<p>Old</p>'
, file = __dirname + '/tmp/renderFile.ejs'
, options = {cache: true};
fs.writeFileSync(file, '<p>Old</p>');
ejs.renderFile(file, {}, options, function (err, out) {
if (err) {
done(err);
}
fs.writeFileSync(file, '<p>New</p>');
assert.equal(out, expected);
ejs.renderFile(file, {}, options, function (err, out) {
if (err) {
done(err);
}
// Assert no change, still in cache
assert.equal(out, expected);
done();
});
});
});
test('opts.context', function (done) {
var ctxt = {foo: 'FOO'};
ejs.renderFile('test/fixtures/with-context.ejs', {},
{context: ctxt}, function(err, html) {
if (err) {
return done(err);
}
assert.equal(html, ctxt.foo + '\n');
done();
});
});
});
suite('cache specific', function () {
test('`clearCache` work properly', function () {
var expected = '<p>Old</p>'
, file = __dirname + '/tmp/clearCache.ejs'
, options = {cache: true, filename: file}
, out = ejs.render('<p>Old</p>', {}, options);
assert.equal(out, expected);
ejs.clearCache();
expected = '<p>New</p>';
out = ejs.render('<p>New</p>', {}, options);
assert.equal(out, expected);
});
test('`clearCache` work properly, LRU', function () {
var expected = '<p>Old</p>'
, oldCache = ejs.cache
, file = __dirname + '/tmp/clearCache.ejs'
, options = {cache: true, filename: file}
, out;
ejs.cache = LRU();
out = ejs.render('<p>Old</p>', {}, options);
assert.equal(out, expected);
ejs.clearCache();
expected = '<p>New</p>';
out = ejs.render('<p>New</p>', {}, options);
assert.equal(out, expected);
ejs.cache = oldCache;
});
test('LRU with cache-size 1', function () {
var oldCache = ejs.cache
, options
, out
, expected
, file;
ejs.cache = LRU(1);
file = __dirname + '/tmp/render1.ejs';
options = {cache: true, filename: file};
out = ejs.render('<p>File1</p>', {}, options);
expected = '<p>File1</p>';
assert.equal(out, expected);
// Same filename, different template, but output
// should be the same because cache
file = __dirname + '/tmp/render1.ejs';
options = {cache: true, filename: file};
out = ejs.render('<p>ChangedFile1</p>', {}, options);
expected = '<p>File1</p>';
assert.equal(out, expected);
// Different filiename -- output should be different,
// and previous cache-entry should be evicted
file = __dirname + '/tmp/render2.ejs';
options = {cache: true, filename: file};
out = ejs.render('<p>File2</p>', {}, options);
expected = '<p>File2</p>';
assert.equal(out, expected);
// Entry with first filename should now be out of cache,
// results should be different
file = __dirname + '/tmp/render1.ejs';
options = {cache: true, filename: file};
out = ejs.render('<p>ChangedFile1</p>', {}, options);
expected = '<p>ChangedFile1</p>';
assert.equal(out, expected);
ejs.cache = oldCache;
});
});
suite('<%', function () {
test('without semicolons', function () {
assert.equal(ejs.render(fixture('no.semicolons.ejs')),
fixture('no.semicolons.html'));
});
});
suite('<%=', function () {
test('escape &amp;<script>', function () {
assert.equal(ejs.render('<%= name %>', {name: '&nbsp;<script>'}),
'&amp;nbsp;&lt;script&gt;');
});
test('should escape \'', function () {
assert.equal(ejs.render('<%= name %>', {name: 'The Jones\'s'}),
'The Jones&#39;s');
});
test('should escape &foo_bar;', function () {
assert.equal(ejs.render('<%= name %>', {name: '&foo_bar;'}),
'&amp;foo_bar;');
});
test('should accept custom function', function() {
var customEscape = function customEscape(str) {
return !str ? '' : str.toUpperCase();
};
assert.equal(
ejs.render('<%= name %>', {name: 'The Jones\'s'}, {escape: customEscape}),
'THE JONES\'S'
);
});
});
suite('<%-', function () {
test('not escape', function () {
assert.equal(ejs.render('<%- name %>', {name: '<script>'}),
'<script>');
});
test('terminate gracefully if no close tag is found', function () {
try {
ejs.compile('<h1>oops</h1><%- name ->');
throw new Error('Expected parse failure');
}
catch (err) {
assert.ok(err.message.indexOf('Could not find matching close tag for') > -1);
}
});
});
suite('%>', function () {
test('produce newlines', function () {
assert.equal(ejs.render(fixture('newlines.ejs'), {users: users}),
fixture('newlines.html'));
});
test('works with `-%>` interspersed', function () {
assert.equal(ejs.render(fixture('newlines.mixed.ejs'), {users: users}),
fixture('newlines.mixed.html'));
});
test('consecutive tags work', function () {
assert.equal(ejs.render(fixture('consecutive-tags.ejs')),
fixture('consecutive-tags.html'));
});
});
suite('-%>', function () {
test('not produce newlines', function () {
assert.equal(ejs.render(fixture('no.newlines.ejs'), {users: users}),
fixture('no.newlines.html'));
});
test('stack traces work', function () {
try {
ejs.render(fixture('no.newlines.error.ejs'));
}
catch (e) {
if (e.message.indexOf('>> 4| <%= qdata %>') > -1) {
return;
}
throw e;
}
throw new Error('Expected ReferenceError');
});
test('works with unix style', function () {
var content = "<ul><% -%>\n"
+ "<% users.forEach(function(user){ -%>\n"
+ "<li><%= user.name -%></li>\n"
+ "<% }) -%>\n"
+ "</ul><% -%>\n";
var expectedResult = "<ul><li>geddy</li>\n<li>neil</li>\n<li>alex</li>\n</ul>";
var fn;
fn = ejs.compile(content);
assert.equal(fn({users: users}),
expectedResult);
});
test('works with windows style', function () {
var content = "<ul><% -%>\r\n"
+ "<% users.forEach(function(user){ -%>\r\n"
+ "<li><%= user.name -%></li>\r\n"
+ "<% }) -%>\r\n"
+ "</ul><% -%>\r\n";
var expectedResult = "<ul><li>geddy</li>\r\n<li>neil</li>\r\n<li>alex</li>\r\n</ul>";
var fn;
fn = ejs.compile(content);
assert.equal(fn({users: users}),
expectedResult);
});
});
suite('<%%', function () {
test('produce literals', function () {
assert.equal(ejs.render('<%%- "foo" %>'),
'<%- "foo" %>');
});
test('work without an end tag', function () {
assert.equal(ejs.render('<%%'), '<%');
assert.equal(ejs.render(fixture('literal.ejs'), {}, {delimiter: ' '}),
fixture('literal.html'));
});
});
suite('<%_ and _%>', function () {
test('slurps spaces and tabs', function () {
assert.equal(ejs.render(fixture('space-and-tab-slurp.ejs'), {users: users}),
fixture('space-and-tab-slurp.html'));
});
});
suite('single quotes', function () {
test('not mess up the constructed function', function () {
assert.equal(ejs.render(fixture('single-quote.ejs')),
fixture('single-quote.html'));
});
});
suite('double quotes', function () {
test('not mess up the constructed function', function () {
assert.equal(ejs.render(fixture('double-quote.ejs')),
fixture('double-quote.html'));
});
});
suite('backslashes', function () {
test('escape', function () {
assert.equal(ejs.render(fixture('backslash.ejs')),
fixture('backslash.html'));
});
});
suite('messed up whitespace', function () {
test('work', function () {
assert.equal(ejs.render(fixture('messed.ejs'), {users: users}),
fixture('messed.html'));
});
});
suite('exceptions', function () {
test('produce useful stack traces', function () {
try {
ejs.render(fixture('error.ejs'), {}, {filename: 'error.ejs'});
}
catch (err) {
assert.equal(err.path, 'error.ejs');
assert.equal(err.stack.split('\n').slice(0, 8).join('\n'), fixture('error.out'));
return;
}
throw new Error('no error reported when there should be');
});
test('not include fancy stack info if compileDebug is false', function () {
try {
ejs.render(fixture('error.ejs'), {}, {
filename: 'error.ejs',
compileDebug: false
});
}
catch (err) {
assert.ok(!err.path);
assert.notEqual(err.stack.split('\n').slice(0, 8).join('\n'), fixture('error.out'));
return;
}
throw new Error('no error reported when there should be');
});
var unhook = null;
test('log JS source when debug is set', function (done) {
var out = ''
, needToExit = false;
unhook = hook_stdio(process.stdout, function (str) {
out += str;
if (needToExit) {
return;
}
if (out.indexOf('__output')) {
needToExit = true;
unhook();
unhook = null;
return done();
}
});
ejs.render(fixture('hello-world.ejs'), {}, {debug: true});
});
teardown(function() {
if (!unhook) {
return;
}
unhook();
unhook = null;
});
});
suite('rmWhitespace', function () {
test('works', function () {
assert.equal(ejs.render(fixture('rmWhitespace.ejs'), {}, {rmWhitespace: true}),
fixture('rmWhitespace.html'));
});
});
suite('include()', function () {
test('include ejs', function () {
var file = 'test/fixtures/include-simple.ejs';
assert.equal(ejs.render(fixture('include-simple.ejs'), {}, {filename: file}),
fixture('include-simple.html'));
});
test('include ejs fails without `filename`', function () {
try {
ejs.render(fixture('include-simple.ejs'));
}
catch (err) {
assert.ok(err.message.indexOf('requires the \'filename\' option') > -1);
return;
}
throw new Error('expected inclusion error');
});
test('strips BOM', function () {
assert.equal(
ejs.render('<%- include("fixtures/includes/bom.ejs") %>',
{}, {filename: path.join(__dirname, 'f.ejs')}),
'<p>This is a file with BOM.</p>\n');
});
test('include ejs with locals', function () {
var file = 'test/fixtures/include.ejs';
assert.equal(ejs.render(fixture('include.ejs'), {pets: users}, {filename: file, delimiter: '@'}),
fixture('include.html'));
});
test('include ejs with absolute path and locals', function () {
var file = 'test/fixtures/include-abspath.ejs';
assert.equal(ejs.render(fixture('include-abspath.ejs'),
{dir: path.join(__dirname, 'fixtures'), pets: users, path: path},
{filename: file, delimiter: '@'}),
fixture('include.html'));
});
test('work when nested', function () {
var file = 'test/fixtures/menu.ejs';
assert.equal(ejs.render(fixture('menu.ejs'), {pets: users}, {filename: file}),
fixture('menu.html'));
});
test('work with a variable path', function () {
var file = 'test/fixtures/menu_var.ejs',
includePath = 'includes/menu-item';
assert.equal(ejs.render(fixture('menu.ejs'), {pets: users, varPath: includePath}, {filename: file}),
fixture('menu.html'));
});
test('include arbitrary files as-is', function () {
var file = 'test/fixtures/include.css.ejs';
assert.equal(ejs.render(fixture('include.css.ejs'), {pets: users}, {filename: file}),
fixture('include.css.html'));
});
test('pass compileDebug to include', function () {
var file = 'test/fixtures/include.ejs'
, fn;
fn = ejs.compile(fixture('include.ejs'), {
filename: file
, delimiter: '@'
, compileDebug: false
});
try {
// Render without a required variable reference
fn({foo: 'asdf'});
}
catch(e) {
assert.equal(e.message, 'pets is not defined');
assert.ok(!e.path);
return;
}
throw new Error('no error reported when there should be');
});
test('is dynamic', function () {
fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>Old</p>');
var file = 'test/fixtures/include_cache.ejs'
, options = {filename: file}
, out = ejs.compile(fixture('include_cache.ejs'), options);
assert.equal(out(), '<p>Old</p>\n');
fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>New</p>');
assert.equal(out(), '<p>New</p>\n');
});
test('support caching', function () {
fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>Old</p>');
var file = 'test/fixtures/include_cache.ejs'
, options = {cache: true, filename: file}
, out = ejs.render(fixture('include_cache.ejs'), {}, options)
, expected = fixture('include_cache.html');
assert.equal(out, expected);
out = ejs.render(fixture('include_cache.ejs'), {}, options);
// No change, still in cache
assert.equal(out, expected);
fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>New</p>');
out = ejs.render(fixture('include_cache.ejs'), {}, options);
assert.equal(out, expected);
});
});
suite('preprocessor include', function () {
test('work', function () {
var file = 'test/fixtures/include_preprocessor.ejs';
assert.equal(ejs.render(fixture('include_preprocessor.ejs'), {pets: users}, {filename: file, delimiter: '@'}),
fixture('include_preprocessor.html'));
});
test('no false positives', function () {
assert.equal(ejs.render('<% %> include foo <% %>'), ' include foo ');
});
test('fails without `filename`', function () {
try {
ejs.render(fixture('include_preprocessor.ejs'), {pets: users}, {delimiter: '@'});
}
catch (err) {
assert.ok(err.message.indexOf('requires the \'filename\' option') > -1);
return;
}
throw new Error('expected inclusion error');
});
test('strips BOM', function () {
assert.equal(
ejs.render('<% include fixtures/includes/bom.ejs %>',
{}, {filename: path.join(__dirname, 'f.ejs')}),
'<p>This is a file with BOM.</p>\n');
});
test('work when nested', function () {
var file = 'test/fixtures/menu_preprocessor.ejs';
assert.equal(ejs.render(fixture('menu_preprocessor.ejs'), {pets: users}, {filename: file}),
fixture('menu_preprocessor.html'));
});
test('tracks dependency correctly', function () {
var file = 'test/fixtures/menu_preprocessor.ejs'
, fn = ejs.compile(fixture('menu_preprocessor.ejs'), {filename: file});
assert(fn.dependencies.length);
});
test('include arbitrary files as-is', function () {
var file = 'test/fixtures/include_preprocessor.css.ejs';
assert.equal(ejs.render(fixture('include_preprocessor.css.ejs'), {pets: users}, {filename: file}),
fixture('include_preprocessor.css.html'));
});
test('pass compileDebug to include', function () {
var file = 'test/fixtures/include_preprocessor.ejs'
, fn;
fn = ejs.compile(fixture('include_preprocessor.ejs'), {
filename: file
, delimiter: '@'
, compileDebug: false
});
try {
// Render without a required variable reference
fn({foo: 'asdf'});
}
catch(e) {
assert.equal(e.message, 'pets is not defined');
assert.ok(!e.path);
return;
}
throw new Error('no error reported when there should be');
});
test('is static', function () {
fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>Old</p>');
var file = 'test/fixtures/include_preprocessor_cache.ejs'
, options = {filename: file}
, out = ejs.compile(fixture('include_preprocessor_cache.ejs'), options);
assert.equal(out(), '<p>Old</p>\n');
fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>New</p>');
assert.equal(out(), '<p>Old</p>\n');
});
test('support caching', function () {
fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>Old</p>');
var file = 'test/fixtures/include_preprocessor_cache.ejs'
, options = {cache: true, filename: file}
, out = ejs.render(fixture('include_preprocessor_cache.ejs'), {}, options)
, expected = fixture('include_preprocessor_cache.html');
assert.equal(out, expected);
fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>New</p>');
out = ejs.render(fixture('include_preprocessor_cache.ejs'), {}, options);
assert.equal(out, expected);
});
});
suite('comments', function () {
test('fully render with comments removed', function () {
assert.equal(ejs.render(fixture('comments.ejs')),
fixture('comments.html'));
});
});
suite('require', function () {
// Only works with inline/preprocessor includes
test('allow ejs templates to be required as node modules', function () {
var file = 'test/fixtures/include_preprocessor.ejs'
, template = require(__dirname + '/fixtures/menu_preprocessor.ejs');
if (!process.env.running_under_istanbul) {
assert.equal(template({filename: file, pets: users}),
fixture('menu_preprocessor.html'));
}
});
});
suite('examples', function () {
function noop () {}
fs.readdirSync('examples').forEach(function (f) {
if (!/\.js$/.test(f)) {
return;
}
suite(f, function () {
test('doesn\'t throw any errors', function () {
var stderr = hook_stdio(process.stderr, noop)
, stdout = hook_stdio(process.stdout, noop);
try {
require('../examples/' + f);
}
catch (ex) {
stdout();
stderr();
throw ex;
}
stdout();
stderr();
});
});
});
});

View File

@ -1 +0,0 @@
\foo

View File

@ -1 +0,0 @@
\foo

View File

@ -1,7 +0,0 @@
<li><a href="foo"><% // double-slash comment %>foo</li>
<li><a href="bar"><% /* C-style comment */ %>bar</li>
<li><a href="baz"><% // double-slash comment with newline
%>baz</li>
<li><a href="qux"><% var x = 'qux'; // double-slash comment @ end of line %><%= x %></li>
<li><a href="fee"><%# ERB style comment %>fee</li>
<li><a href="bah"><%= 'not a ' + '//' + ' comment' %></a></li>

View File

@ -1,6 +0,0 @@
<li><a href="foo">foo</li>
<li><a href="bar">bar</li>
<li><a href="baz">baz</li>
<li><a href="qux">qux</li>
<li><a href="fee">fee</li>
<li><a href="bah">not a // comment</a></li>

View File

@ -1 +0,0 @@
<% var a = 'foo' %><% var b = 'bar' %><%= a %>

View File

@ -1 +0,0 @@
foo

View File

@ -1 +0,0 @@
<p><%= "lo" + 'ki' %>'s "wheelchair"</p>

View File

@ -1 +0,0 @@
<p>loki's "wheelchair"</p>

View File

@ -1,5 +0,0 @@
<ul>
<% if (users) { %>
<p>Has users</p>
<% } %>
</ul>

View File

@ -1,8 +0,0 @@
ReferenceError: error.ejs:2
1| <ul>
>> 2| <% if (users) { %>
3| <p>Has users</p>
4| <% } %>
5| </ul>
users is not defined

View File

@ -1 +0,0 @@
<% function foo() return 'foo'; %>

View File

@ -1 +0,0 @@
<p>Hello world!</p>

View File

@ -1,5 +0,0 @@
<ul>
<@ pets.forEach(function(pet){ @>
<@- include(path.join(dir, 'pet'), {pet: pet}); @>
<@ }); @>
</ul>

View File

@ -1,3 +0,0 @@
<ul>
<%- include('hello-world'); %>
</ul>

View File

@ -1,4 +0,0 @@
<ul>
<p>Hello world!</p>
</ul>

View File

@ -1 +0,0 @@
<style><%- include('style.css', {value: 'bar'}); %></style>

View File

@ -1,4 +0,0 @@
<style>body {
foo: 'bar';
}
</style>

View File

@ -1,5 +0,0 @@
<ul>
<@ pets.forEach(function(pet){ @>
<@- include('pet', {pet: pet}); @>
<@ }); @>
</ul>

View File

@ -1,12 +0,0 @@
<ul>
<li>geddy</li>
<li>neil</li>
<li>alex</li>
</ul>

View File

@ -1 +0,0 @@
<%- include('../tmp/include') %>

View File

@ -1 +0,0 @@
<p>Old</p>

View File

@ -1 +0,0 @@
<style><% var value = 'bar' %><% include style.css %></style>

View File

@ -1,4 +0,0 @@
<style>body {
foo: 'bar';
}
</style>

View File

@ -1,5 +0,0 @@
<ul>
<@ pets.forEach(function(pet){ @>
<@ include pet @>
<@ }) @>
</ul>

View File

@ -1,12 +0,0 @@
<ul>
<li>geddy</li>
<li>neil</li>
<li>alex</li>
</ul>

View File

@ -1 +0,0 @@
<%- include ../tmp/include_preprocessor %>

View File

@ -1 +0,0 @@
<p>Old</p>

View File

@ -1 +0,0 @@
<p>This is a file with BOM.</p>

View File

@ -1 +0,0 @@
<li><% include menu/item %></li>

View File

@ -1 +0,0 @@
<a href="/<%= url %>"><%= title %></a>

View File

@ -1,3 +0,0 @@
<pre>There should be a space followed by a less-than sign and then two more
spaces in the next line:
< .</pre>

View File

@ -1,3 +0,0 @@
<pre>There should be a space followed by a less-than sign and then two more
spaces in the next line:
< .</pre>

View File

@ -1,15 +0,0 @@
<%- include('includes/menu-item', {
url: '/foo'
, title: 'Foo'
}); -%>
<%- include('includes/menu-item', {
url: '/bar'
, title: 'Bar'
}); -%>
<%- include('includes/menu-item', {
url: '/baz'
, title: 'Baz'
}); -%>

View File

@ -1,9 +0,0 @@
<li><a href="//foo">Foo</a>
</li>
<li><a href="//bar">Bar</a>
</li>
<li><a href="//baz">Baz</a>
</li>

View File

@ -1,11 +0,0 @@
<% var url = '/foo' -%>
<% var title = 'Foo' -%>
<% include includes/menu-item -%>
<% var url = '/bar' -%>
<% var title = 'Bar' -%>
<% include includes/menu-item -%>
<% var url = '/baz' -%>
<% var title = 'Baz' -%>
<% include includes/menu-item -%>

View File

@ -1,8 +0,0 @@
<li><a href="//foo">Foo</a>
</li>
<li><a href="//bar">Bar</a>
</li>
<li><a href="//baz">Baz</a>
</li>

View File

@ -1,15 +0,0 @@
<%- include(varPath, {
url: '/foo'
, title: 'Foo'
}); -%>
<%- include(varPath, {
url: '/bar'
, title: 'Bar'
}); -%>
<%- include(varPath, {
url: '/baz'
, title: 'Baz'
}); -%>

View File

@ -1 +0,0 @@
<ul><%users.forEach(function(user){%><li><%=user.name%></li><%})%></ul>

View File

@ -1 +0,0 @@
<ul><li>geddy</li><li>neil</li><li>alex</li></ul>

View File

@ -1,5 +0,0 @@
<ul>
<% users.forEach(function(user){ %>
<li><%= user.name %></li>
<% }) %>
</ul>

View File

@ -1,9 +0,0 @@
<ul>
<li>geddy</li>
<li>neil</li>
<li>alex</li>
</ul>

View File

@ -1,6 +0,0 @@
<ul>
<% var unused1 = 'blah' -%>
<% var unused2 = 'bleh' %>
<% var unused3 = 'bloh' -%>
<% var unused4 = 'bluh' %>
</ul>

View File

@ -1,4 +0,0 @@
<ul>
</ul>

View File

@ -1,5 +0,0 @@
<ul>
<% users.forEach(function(user){ -%>
<li><%= user.name %></li>
<% }) -%>
</ul>

View File

@ -1,5 +0,0 @@
AAA
<% data = "test"; -%>
BBB
<%= qdata %>
CCC

View File

@ -1,5 +0,0 @@
<ul>
<li>geddy</li>
<li>neil</li>
<li>alex</li>
</ul>

View File

@ -1,8 +0,0 @@
This document does not use semicolons in scriptlets.
<%
var a = 'b'
var b = 'c'
var c
c = b
%>
The value of c is: <%= c %>

View File

@ -1,3 +0,0 @@
This document does not use semicolons in scriptlets.
The value of c is: c

View File

@ -1 +0,0 @@
<p>hey</p>

View File

@ -1 +0,0 @@
<li><@= pet.name @></li>

View File

@ -1,14 +0,0 @@
<tag1>
<tag2>
A very long piece of text very long piece of text very long piece of
text very long piece <% var f = 'f' %>of text very long piece of
tex t very long piece of<% %>text very long
adsffadsfadsfad<%= f %>
piece of text.
<% var a = 'a' %>
Text again.
<% var b = 'b' %>
<% var c = 'c'
var d = 'd' %>
Another text. <%= c %>

View File

@ -1,8 +0,0 @@
<tag1>
<tag2>
A very long piece of text very long piece of text very long piece of
text very long piece of text very long piece of
text very long piece oftext very long
adsffadsfadsfadfpiece of text.
Text again.
Another text. c

View File

@ -1 +0,0 @@
<p><%= 'loki' %>'s wheelchair</p>

View File

@ -1 +0,0 @@
<p>loki's wheelchair</p>

View File

@ -1,3 +0,0 @@
body {
foo: '<%= value %>';
}

View File

@ -1 +0,0 @@
<h1><$= locals.name $></h1>

View File

@ -1 +0,0 @@
<h1><$= name $></h1>

View File

@ -1 +0,0 @@
<%= this.foo %>

3
node_modules/ejs/test/mocha.opts generated vendored
View File

@ -1,3 +0,0 @@
--ui tdd
--reporter spec
--check-leaks

132
node_modules/express/History.md generated vendored
View File

@ -1,3 +1,135 @@
4.16.3 / 2018-03-12
===================
* deps: accepts@~1.3.5
- deps: mime-types@~2.1.18
* deps: depd@~1.1.2
- perf: remove argument reassignment
* deps: encodeurl@~1.0.2
- Fix encoding `%` as last character
* deps: finalhandler@1.1.1
- Fix 404 output for bad / missing pathnames
- deps: encodeurl@~1.0.2
- deps: statuses@~1.4.0
* deps: proxy-addr@~2.0.3
- deps: ipaddr.js@1.6.0
* deps: send@0.16.2
- Fix incorrect end tag in default error & redirects
- deps: depd@~1.1.2
- deps: encodeurl@~1.0.2
- deps: statuses@~1.4.0
* deps: serve-static@1.13.2
- Fix incorrect end tag in redirects
- deps: encodeurl@~1.0.2
- deps: send@0.16.2
* deps: statuses@~1.4.0
* deps: type-is@~1.6.16
- deps: mime-types@~2.1.18
4.16.2 / 2017-10-09
===================
* Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
* perf: skip parsing of entire `X-Forwarded-Proto` header
4.16.1 / 2017-09-29
===================
* deps: send@0.16.1
* deps: serve-static@1.13.1
- Fix regression when `root` is incorrectly set to a file
- deps: send@0.16.1
4.16.0 / 2017-09-28
===================
* Add `"json escape"` setting for `res.json` and `res.jsonp`
* Add `express.json` and `express.urlencoded` to parse bodies
* Add `options` argument to `res.download`
* Improve error message when autoloading invalid view engine
* Improve error messages when non-function provided as middleware
* Skip `Buffer` encoding when not generating ETag for small response
* Use `safe-buffer` for improved Buffer API
* deps: accepts@~1.3.4
- deps: mime-types@~2.1.16
* deps: content-type@~1.0.4
- perf: remove argument reassignment
- perf: skip parameter parsing when no parameters
* deps: etag@~1.8.1
- perf: replace regular expression with substring
* deps: finalhandler@1.1.0
- Use `res.headersSent` when available
* deps: parseurl@~1.3.2
- perf: reduce overhead for full URLs
- perf: unroll the "fast-path" `RegExp`
* deps: proxy-addr@~2.0.2
- Fix trimming leading / trailing OWS in `X-Forwarded-For`
- deps: forwarded@~0.1.2
- deps: ipaddr.js@1.5.2
- perf: reduce overhead when no `X-Forwarded-For` header
* deps: qs@6.5.1
- Fix parsing & compacting very deep objects
* deps: send@0.16.0
- Add 70 new types for file extensions
- Add `immutable` option
- Fix missing `</html>` in default error & redirects
- Set charset as "UTF-8" for .js and .json
- Use instance methods on steam to check for listeners
- deps: mime@1.4.1
- perf: improve path validation speed
* deps: serve-static@1.13.0
- Add 70 new types for file extensions
- Add `immutable` option
- Set charset as "UTF-8" for .js and .json
- deps: send@0.16.0
* deps: setprototypeof@1.1.0
* deps: utils-merge@1.0.1
* deps: vary@~1.1.2
- perf: improve header token parsing speed
* perf: re-use options object when generating ETags
* perf: remove dead `.charset` set in `res.jsonp`
4.15.5 / 2017-09-24
===================
* deps: debug@2.6.9
* deps: finalhandler@~1.0.6
- deps: debug@2.6.9
- deps: parseurl@~1.3.2
* deps: fresh@0.5.2
- Fix handling of modified headers with invalid dates
- perf: improve ETag match loop
- perf: improve `If-None-Match` token parsing
* deps: send@0.15.6
- Fix handling of modified headers with invalid dates
- deps: debug@2.6.9
- deps: etag@~1.8.1
- deps: fresh@0.5.2
- perf: improve `If-Match` token parsing
* deps: serve-static@1.12.6
- deps: parseurl@~1.3.2
- deps: send@0.15.6
- perf: improve slash collapsing
4.15.4 / 2017-08-06
===================
* deps: debug@2.6.8
* deps: depd@~1.1.1
- Remove unnecessary `Buffer` loading
* deps: finalhandler@~1.0.4
- deps: debug@2.6.8
* deps: proxy-addr@~1.1.5
- Fix array argument being altered
- deps: ipaddr.js@1.4.0
* deps: qs@6.5.0
* deps: send@0.15.4
- deps: debug@2.6.8
- deps: depd@~1.1.1
- deps: http-errors@~1.6.2
* deps: serve-static@1.12.4
- deps: send@0.15.4
4.15.3 / 2017-05-16
===================

18
node_modules/express/Readme.md generated vendored
View File

@ -21,10 +21,22 @@ app.listen(3000)
## Installation
This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/).
Before installing, [download and install Node.js](https://nodejs.org/en/download/).
Node.js 0.10 or higher is required.
Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```bash
$ npm install express
```
Follow [our installing guide](http://expressjs.com/en/starter/installing.html)
for more information.
## Features
* Robust routing
@ -39,7 +51,7 @@ $ npm install express
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [Github Organization](https://github.com/expressjs) for Official Middleware & Modules
* [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion
* [Gitter](https://gitter.im/expressjs/express) for support and discussion
@ -115,9 +127,9 @@ $ npm test
## People
The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ's Gratipay][gratipay-image-visionmedia]][gratipay-url-visionmedia]
The original author of Express is [TJ Holowaychuk](https://github.com/tj)
The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson]
The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson)
[List of all contributors](https://github.com/expressjs/express/graphs/contributors)

View File

@ -207,7 +207,7 @@ app.use = function use(fn) {
var fns = flatten(slice.call(arguments, offset));
if (fns.length === 0) {
throw new TypeError('app.use() requires middleware functions');
throw new TypeError('app.use() requires a middleware function')
}
// setup router
@ -338,7 +338,7 @@ app.param = function param(name, fn) {
* Assign `setting` to `val`, or return `setting`'s value.
*
* app.set('foo', 'bar');
* app.get('foo');
* app.set('foo');
* // => "bar"
*
* Mounted servers inherit their parent server's settings.

View File

@ -12,6 +12,7 @@
* Module dependencies.
*/
var bodyParser = require('body-parser')
var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');
var proto = require('./application');
@ -74,16 +75,16 @@ exports.Router = Router;
* Expose middleware
*/
exports.json = bodyParser.json
exports.query = require('./middleware/query');
exports.static = require('serve-static');
exports.urlencoded = bodyParser.urlencoded
/**
* Replace removed middleware with an appropriate error message.
*/
[
'json',
'urlencoded',
;[
'bodyParser',
'compress',
'cookieSession',

View File

@ -315,8 +315,12 @@ defineGetter(req, 'protocol', function protocol(){
// Note: X-Forwarded-Proto is normally only ever a
// single value, but this is to be safe.
proto = this.get('X-Forwarded-Proto') || proto;
return proto.split(/\s*,\s*/)[0];
var header = this.get('X-Forwarded-Proto') || proto
var index = header.indexOf(',')
return index !== -1
? header.substring(0, index).trim()
: header.trim()
});
/**

99
node_modules/express/lib/response.js generated vendored
View File

@ -12,6 +12,7 @@
* @private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var deprecate = require('depd')('express');
var encodeUrl = require('encodeurl');
@ -95,7 +96,7 @@ res.links = function(links){
*
* Examples:
*
* res.send(new Buffer('wahoo'));
* res.send(Buffer.from('wahoo'));
* res.send({ some: 'json' });
* res.send('<p>some html</p>');
*
@ -106,7 +107,6 @@ res.links = function(links){
res.send = function send(body) {
var chunk = body;
var encoding;
var len;
var req = this.req;
var type;
@ -171,23 +171,33 @@ res.send = function send(body) {
}
}
// determine if ETag should be generated
var etagFn = app.get('etag fn')
var generateETag = !this.get('ETag') && typeof etagFn === 'function'
// populate Content-Length
var len
if (chunk !== undefined) {
if (!Buffer.isBuffer(chunk)) {
// convert chunk to Buffer; saves later double conversions
chunk = new Buffer(chunk, encoding);
if (Buffer.isBuffer(chunk)) {
// get length of Buffer
len = chunk.length
} else if (!generateETag && chunk.length < 1000) {
// just calculate length when no ETag + small chunk
len = Buffer.byteLength(chunk, encoding)
} else {
// convert chunk to Buffer and calculate
chunk = Buffer.from(chunk, encoding)
encoding = undefined;
len = chunk.length
}
len = chunk.length;
this.set('Content-Length', len);
}
// populate ETag
var etag;
var generateETag = len !== undefined && app.get('etag fn');
if (typeof generateETag === 'function' && !this.get('ETag')) {
if ((etag = generateETag(chunk, encoding))) {
if (generateETag && len !== undefined) {
if ((etag = etagFn(chunk, encoding))) {
this.set('ETag', etag);
}
}
@ -244,9 +254,10 @@ res.json = function json(obj) {
// settings
var app = this.app;
var escape = app.get('json escape')
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
// content-type
if (!this.get('Content-Type')) {
@ -286,9 +297,10 @@ res.jsonp = function jsonp(obj) {
// settings
var app = this.app;
var escape = app.get('json escape')
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
@ -304,7 +316,6 @@ res.jsonp = function jsonp(obj) {
// jsonp
if (typeof callback === 'string' && callback.length !== 0) {
this.charset = 'utf-8';
this.set('X-Content-Type-Options', 'nosniff');
this.set('Content-Type', 'text/javascript');
@ -506,19 +517,29 @@ res.sendfile = deprecate.function(res.sendfile,
* when the data transfer is complete, or when an error has
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
*
* This method uses `res.sendfile()`.
* Optionally providing an `options` object to use with `res.sendFile()`.
* This function will set the `Content-Disposition` header, overriding
* any `Content-Disposition` header passed as header options in order
* to set the attachment and filename.
*
* This method uses `res.sendFile()`.
*
* @public
*/
res.download = function download(path, filename, callback) {
res.download = function download (path, filename, options, callback) {
var done = callback;
var name = filename;
var opts = options || null
// support function as second arg
// support function as second or third arg
if (typeof filename === 'function') {
done = filename;
name = null;
opts = null
} else if (typeof options === 'function') {
done = options
opts = null
}
// set Content-Disposition when file is sent
@ -526,10 +547,26 @@ res.download = function download(path, filename, callback) {
'Content-Disposition': contentDisposition(name || path)
};
// merge user-provided headers
if (opts && opts.headers) {
var keys = Object.keys(opts.headers)
for (var i = 0; i < keys.length; i++) {
var key = keys[i]
if (key.toLowerCase() !== 'content-disposition') {
headers[key] = opts.headers[key]
}
}
}
// merge user-provided options
opts = Object.create(opts)
opts.headers = headers
// Resolve the full path for sendFile
var fullPath = resolve(path);
return this.sendFile(fullPath, { headers: headers }, done);
// send file
return this.sendFile(fullPath, opts, done)
};
/**
@ -1063,14 +1100,38 @@ function sendfile(res, file, options, callback) {
}
/**
* Stringify JSON, like JSON.stringify, but v8 optimized.
* Stringify JSON, like JSON.stringify, but v8 optimized, with the
* ability to escape characters that can trigger HTML sniffing.
*
* @param {*} value
* @param {function} replaces
* @param {number} spaces
* @param {boolean} escape
* @returns {string}
* @private
*/
function stringify(value, replacer, spaces) {
function stringify (value, replacer, spaces, escape) {
// v8 checks arguments.length for optimizing simple call
// https://bugs.chromium.org/p/v8/issues/detail?id=4730
return replacer || spaces
var json = replacer || spaces
? JSON.stringify(value, replacer, spaces)
: JSON.stringify(value);
if (escape) {
json = json.replace(/[<>&]/g, function (c) {
switch (c.charCodeAt(0)) {
case 0x3c:
return '\\u003c'
case 0x3e:
return '\\u003e'
case 0x26:
return '\\u0026'
default:
return c
}
})
}
return json
}

View File

@ -448,14 +448,14 @@ proto.use = function use(fn) {
var callbacks = flatten(slice.call(arguments, offset));
if (callbacks.length === 0) {
throw new TypeError('Router.use() requires middleware functions');
throw new TypeError('Router.use() requires a middleware function')
}
for (var i = 0; i < callbacks.length; i++) {
var fn = callbacks[i];
if (typeof fn !== 'function') {
throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn));
throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
}
// add the middleware

View File

@ -175,7 +175,7 @@ Route.prototype.all = function all() {
if (typeof handle !== 'function') {
var type = toString.call(handle);
var msg = 'Route.all() requires callback functions but got a ' + type;
var msg = 'Route.all() requires a callback function but got a ' + type
throw new TypeError(msg);
}
@ -198,7 +198,7 @@ methods.forEach(function(method){
if (typeof handle !== 'function') {
var type = toString.call(handle);
var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
var msg = 'Route.' + method + '() requires a callback function but got a ' + type
throw new Error(msg);
}

37
node_modules/express/lib/utils.js generated vendored
View File

@ -12,12 +12,12 @@
* @api private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var contentType = require('content-type');
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var mime = require('send').mime;
var basename = require('path').basename;
var etag = require('etag');
var proxyaddr = require('proxy-addr');
var qs = require('qs');
@ -32,13 +32,7 @@ var querystring = require('querystring');
* @api private
*/
exports.etag = function (body, encoding) {
var buf = !Buffer.isBuffer(body)
? new Buffer(body, encoding)
: body;
return etag(buf, {weak: false});
};
exports.etag = createETagGenerator({ weak: false })
/**
* Return weak ETag for `body`.
@ -49,13 +43,7 @@ exports.etag = function (body, encoding) {
* @api private
*/
exports.wetag = function wetag(body, encoding){
var buf = !Buffer.isBuffer(body)
? new Buffer(body, encoding)
: body;
return etag(buf, {weak: true});
};
exports.wetag = createETagGenerator({ weak: true })
/**
* Check if `path` looks absolute.
@ -274,6 +262,25 @@ exports.setCharset = function setCharset(type, charset) {
return contentType.format(parsed);
};
/**
* Create an ETag generator function, generating ETags with
* the given options.
*
* @param {object} options
* @return {function}
* @private
*/
function createETagGenerator (options) {
return function generateETag (body, encoding) {
var buf = !Buffer.isBuffer(body)
? Buffer.from(body, encoding)
: body
return etag(buf, options)
}
}
/**
* Parse an extended query string with qs.
*

11
node_modules/express/lib/view.js generated vendored
View File

@ -16,7 +16,6 @@
var debug = require('debug')('express:view');
var path = require('path');
var fs = require('fs');
var utils = require('./utils');
/**
* Module variables.
@ -77,7 +76,15 @@ function View(name, options) {
// load engine
var mod = this.ext.substr(1)
debug('require "%s"', mod)
opts.engines[this.ext] = require(mod).__express
// default engine export
var fn = require(mod).__express
if (typeof fn !== 'function') {
throw new Error('Module "' + mod + '" does not provide a view engine.')
}
opts.engines[this.ext] = fn
}
// store loaded engine

114
node_modules/express/package.json generated vendored
View File

@ -1,46 +1,37 @@
{
"_args": [
[
"express@4.15.3",
"/Users/martin/dev/Rinser"
]
],
"_from": "express@4.15.3",
"_id": "express@4.15.3",
"_from": "express@^4.15.3",
"_id": "express@4.16.3",
"_inBundle": false,
"_integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=",
"_integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
"_location": "/express",
"_phantomChildren": {
"debug": "2.6.7",
"depd": "1.1.0",
"destroy": "1.0.4",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"forwarded": "0.1.0",
"http-errors": "1.6.1",
"mime": "1.3.4",
"ms": "2.0.0",
"bytes": "3.0.0",
"content-type": "1.0.4",
"debug": "2.6.9",
"depd": "1.1.2",
"http-errors": "1.6.3",
"inherits": "2.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.1",
"statuses": "1.3.1",
"type-is": "1.6.16",
"unpipe": "1.0.0"
},
"_requested": {
"type": "version",
"type": "range",
"registry": true,
"raw": "express@4.15.3",
"raw": "express@^4.15.3",
"name": "express",
"escapedName": "express",
"rawSpec": "4.15.3",
"rawSpec": "^4.15.3",
"saveSpec": null,
"fetchSpec": "4.15.3"
"fetchSpec": "^4.15.3"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz",
"_spec": "4.15.3",
"_where": "/Users/martin/dev/Rinser",
"_resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
"_shasum": "6af8a502350db3246ecc4becf6b5a34d22f7ed53",
"_spec": "express@^4.15.3",
"_where": "/Users/martin/dev/test/Rinser",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
@ -48,6 +39,7 @@
"bugs": {
"url": "https://github.com/expressjs/express/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Aaron Heckmann",
@ -79,53 +71,56 @@
}
],
"dependencies": {
"accepts": "~1.3.3",
"accepts": "~1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.2",
"content-disposition": "0.5.2",
"content-type": "~1.0.2",
"content-type": "~1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.7",
"depd": "~1.1.0",
"encodeurl": "~1.0.1",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.0",
"finalhandler": "~1.0.3",
"fresh": "0.5.0",
"etag": "~1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.1",
"parseurl": "~1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "~1.1.4",
"qs": "6.4.0",
"proxy-addr": "~2.0.3",
"qs": "6.5.1",
"range-parser": "~1.2.0",
"send": "0.15.3",
"serve-static": "1.12.3",
"setprototypeof": "1.0.3",
"statuses": "~1.3.1",
"type-is": "~1.6.15",
"utils-merge": "1.0.0",
"vary": "~1.1.1"
"safe-buffer": "5.1.1",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "~1.4.0",
"type-is": "~1.6.16",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"deprecated": false,
"description": "Fast, unopinionated, minimalist web framework",
"devDependencies": {
"after": "0.8.2",
"body-parser": "1.17.1",
"connect-redis": "~2.4.1",
"cookie-parser": "~1.4.3",
"cookie-session": "~1.2.0",
"ejs": "2.5.6",
"express-session": "1.15.2",
"cookie-session": "1.3.2",
"ejs": "2.5.7",
"eslint": "2.13.1",
"express-session": "1.15.6",
"hbs": "4.0.1",
"istanbul": "0.4.5",
"marked": "0.3.6",
"method-override": "2.3.8",
"mocha": "3.4.1",
"morgan": "1.8.1",
"marked": "0.3.17",
"method-override": "2.3.10",
"mocha": "3.5.3",
"morgan": "1.9.0",
"multiparty": "4.1.3",
"pbkdf2-password": "1.2.1",
"should": "11.2.1",
"should": "13.2.1",
"supertest": "1.2.0",
"vhost": "~3.0.2"
},
@ -158,10 +153,11 @@
"url": "git+https://github.com/expressjs/express.git"
},
"scripts": {
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"
"lint": "eslint .",
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks --no-exit test/ test/acceptance/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks --no-exit test/ test/acceptance/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks --no-exit test/ test/acceptance/",
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks --no-exit test/ test/acceptance/"
},
"version": "4.15.3"
"version": "4.16.3"
}

6
node_modules/lodash/README.md generated vendored
View File

@ -1,4 +1,4 @@
# lodash v4.17.4
# lodash v4.17.10
The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules.
@ -28,12 +28,12 @@ var at = require('lodash/at');
var curryN = require('lodash/fp/curryN');
```
See the [package source](https://github.com/lodash/lodash/tree/4.17.4-npm) for more details.
See the [package source](https://github.com/lodash/lodash/tree/4.17.10-npm) for more details.
**Note:**<br>
Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL.
## Support
Tested in Chrome 54-55, Firefox 49-50, IE 11, Edge 14, Safari 9-10, Node.js 6-7, & PhantomJS 2.1.1.<br>
Tested in Chrome 63-64, Firefox 57-58, IE 11, Edge 14, Safari 10-11, Node.js 4-9, & PhantomJS 2.1.1.<br>
Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available.

34
node_modules/lodash/package.json generated vendored
View File

@ -1,25 +1,19 @@
{
"_args": [
[
"lodash@4.17.4",
"/Users/martin/dev/Rinser"
]
],
"_from": "lodash@4.17.4",
"_id": "lodash@4.17.4",
"_from": "lodash@^4.16.6",
"_id": "lodash@4.17.10",
"_inBundle": false,
"_integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
"_integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"_location": "/lodash",
"_phantomChildren": {},
"_requested": {
"type": "version",
"type": "range",
"registry": true,
"raw": "lodash@4.17.4",
"raw": "lodash@^4.16.6",
"name": "lodash",
"escapedName": "lodash",
"rawSpec": "4.17.4",
"rawSpec": "^4.16.6",
"saveSpec": null,
"fetchSpec": "4.17.4"
"fetchSpec": "^4.16.6"
},
"_requiredBy": [
"/",
@ -32,14 +26,14 @@
"/gulp-uglify",
"/hipchat-notifier",
"/inquirer",
"/mailgun-js/async",
"/requestretry",
"/rss-braider",
"/table"
],
"_resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"_spec": "4.17.4",
"_where": "/Users/martin/dev/Rinser",
"_resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"_shasum": "1b7793cf7259ea38fb3661d4d38b3260af8ae4e7",
"_spec": "lodash@^4.16.6",
"_where": "/Users/martin/dev/test/Rinser",
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
@ -48,6 +42,7 @@
"bugs": {
"url": "https://github.com/lodash/lodash/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "John-David Dalton",
@ -60,6 +55,7 @@
"url": "https://mathiasbynens.be/"
}
],
"deprecated": false,
"description": "Lodash modular utilities.",
"homepage": "https://lodash.com/",
"icon": "https://lodash.com/icon.svg",
@ -76,7 +72,7 @@
"url": "git+https://github.com/lodash/lodash.git"
},
"scripts": {
"test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\""
"test": "echo \"See https://travis-ci.org/lodash-archive/lodash-cli for testing details.\""
},
"version": "4.17.4"
"version": "4.17.10"
}

View File

@ -2,7 +2,7 @@
"_from": "git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"_id": "rss-braider@1.2.2",
"_inBundle": false,
"_integrity": "sha1-RwjGz4pf+NUkSQmupBC84F0Y2mc=",
"_integrity": "",
"_location": "/rss-braider",
"_phantomChildren": {},
"_requested": {
@ -13,14 +13,14 @@
"rawSpec": "git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"saveSpec": "git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"fetchSpec": "https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"gitCommittish": "master"
"gitCommittish": null
},
"_requiredBy": [
"/"
],
"_resolved": "git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git#607d5aa96e76887c909f090957bc13afc69d859b",
"_spec": "rss-braider@git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"_where": "/Users/martin/dev/Rinser",
"_where": "/Users/martin/dev/test/Rinser",
"author": {
"name": "Kip Gebhardt",
"email": "kgebhardt@kqed.org"

8873
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,20 @@
"name": "Rinser",
"version": "0.1.1",
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-eslint": "^8.2.3",
"cheerio": "^0.22.0",
"del": "^2.2.0",
"del": "^3.0.0",
"eslint": "^4.2.0",
"eslint-config-babel": "^7.0.1",
"eslint-config-defaults": "^9.0.0",
"eslint-plugin-flowtype": "^2.35.0",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^4.0.0",
"gulp-cache": "^0.4.6",
"gulp-autoprefixer": "^5.0.0",
"gulp-cache": "^1.0.2",
"gulp-concat": "^2.6.1",
"gulp-cssnano": "^2.1.1",
"gulp-html-replace": "^1.6.2",
"gulp-htmlmin": "^3.0.0",
"gulp-htmlmin": "^4.0.0",
"gulp-inject": "^4.2.0",
"gulp-jshint": "^2.0.4",
"gulp-livereload": "^3.8.1",
@ -35,12 +35,12 @@
"express": "^4.15.3",
"express-session": "^1.15.3",
"htmlparser": "^1.7.7",
"jsonfile": "^3.0.1",
"jsonfile": "^4.0.0",
"lodash": "^4.16.6",
"method-override": "^2.3.9",
"morgan": "^1.8.2",
"request": "^2.81.0",
"rss-braider": "git+https://gitlab.silvrtree.co.uk/martind2000/rss-braider.git",
"yargs": "^8.0.2"
"yargs": "^11.0.0"
}
}