Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

wash

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wash - npm Package Compare versions

Comparing version 0.1.1 to 1.0.4

.jshintrc

181

lib/builtins.js

@@ -1,161 +0,82 @@

var _ = require('underscore');
'use strict';
function builtins() {
};
var utils = require('./utils'),
_ = require('lodash');
builtins.prototype.__isDefined = function(name) {
return _.isFunction(this[name]);
};
exports.range = _.bind(_.range, _);
builtins.prototype.range = function(start, stop, step) {
if(arguments.length <= 1) {
stop = start || 0;
start = 0;
}
step = arguments[2] || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0;
var arr = new Array(length);
while(idx < length) {
arr[idx++] = start;
start += step;
}
return arr;
exports.lower = function(s) {
console.assert(_.isString(s));
return s.toLowerCase();
};
builtins.prototype.lower = function(str) {
if(_.isString(str)) {
return str.toLowerCase();
} else {
throw new Error('InvalidTypeError - unsupported string type: ' + typeof str);
}
};
builtins.prototype.upper = function(str) {
if(_.isString(str)) {
return str.toUpperCase();
} else {
throw new Error('InvalidTypeError - unsupported string type: ' + typeof str);
}
exports.upper = function(s) {
console.assert(_.isString(s));
return s.toUpperCase();
};
builtins.prototype.join = function(x, delim) {
if(!_.isString(delim)) {
throw new Error('InvalidTypeError - unsupported delimiter type: ' + typeof delim);
}
exports.join = function(x, delim) {
console.assert(_.isString(delim));
console.assert(_.isString(x) || _.isArray(x));
if(_.isArray(x)) {
return x.join(delim);
} else if(_.isString(x)) {
return x.split('').join(delim);
} else {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
}
return _.isString(x) ?
x.split('').join(delim) :
x.join(delim);
};
builtins.prototype.len = function(x) {
try {
return x.length;
} catch(err) {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
}
};
exports.len = _.bind(_.size, _);
builtins.prototype.reverse = function(x) {
if(_.isArray(x)) {
var len = x.length;
var rev = new Array(len);
for(var i=len-1; i>=0; --i) { rev[i] = x[len-i-1]; }
return rev;
} else if(_.isString(x)) {
exports.reverse = function(x) {
console.assert(_.isString(x) || _.isArray(x));
if(_.isString(x)) {
return x.split('').reverse().join('');
} else {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
return _.clone(x).reverse();
}
};
builtins.prototype.sort = function(x, reverse) {
if(_.isArray(x)) {
var clone = x.slice();
clone.sort();
if(!!reverse) { clone.reverse(); }
return clone;
} else if(_.isString(x)) {
var clone = x.split('');
clone.sort();
if(!!reverse) { clone.reverse(); }
return clone.join('');
} else {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
}
exports.sort = function(x) {
console.assert(_.isString(x) || _.isArray(x));
return _.isString(x) ?
_.sortBy(x).join('') :
_.sortBy(x);
};
builtins.prototype.isArray = function(x) {
return _.isArray(x);
};
exports.isArray = _.bind(_.isArray, _);
exports.isObject = _.bind(_.isPlainObject, _);
exports.isBoolean = _.bind(_.isBoolean, _);
exports.isString = _.bind(_.isString, _);
builtins.prototype.isObject = function(x) {
return _.isObject(x);
exports.slice = function(x, start, stop) {
console.assert(_.isString(x) || _.isArray(x));
return x.slice(start, stop);
};
builtins.prototype.slice = function(x, start, stop) {
if(_.isArray(x) || _.isString(x)) {
return x.slice(start, stop);
} else {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
}
};
exports.get = function(x, p) {
console.assert(_.isString(x) || _.isArray(x) || _.isPlainObject(x));
builtins.prototype.getAt = function(x, idx) {
if(!_.isNumber(idx)) {
throw new Error('InvalidTypeError - index must be a number: ' + typeof idx);
}
if(_.isArray(x) || _.isString(x)) {
return x[idx];
if(_.isString(x) || _.isArray(x)) {
console.assert(_.isNumber(p) && !_.isNaN(p) && (p >= 0) && (p < x.length));
return x[p];
} else {
throw new Error('InvalidTypeError - unsupported collection type: ' + typeof x);
var v = utils.getValueByPath(x, p);
console.assert(!_.isUndefined(v));
return v;
}
};
builtins.prototype.split = function(str, delim) {
if(!_.isString(delim)) {
throw new Error('InvalidTypeError - delim must be a string: ' + typeof delim);
}
if(_.isString(str)) {
return str.split(delim);
} else {
throw new Error('InvalidTypeError - unsupported string type: ' + typeof str);
}
exports.split = function(s, delim) {
console.assert(_.isString(s));
console.assert(_.isString(delim));
return s.split(delim);
};
builtins.prototype.int = function(str) {
if(_.isString(str)) {
return parseInt(str);
} else {
throw new Error('InvalidTypeError - unsupported string type: ' + typeof str);
}
};
exports.int = _.bind(parseInt, null);
exports.float = _.bind(parseFloat, null);
builtins.prototype.float = function(str) {
if(_.isString(str)) {
return parseFloat(str);
} else {
throw new Error('InvalidTypeError - unsupported string type: ' + typeof str);
}
exports.str = function(x) {
return _.isString(x) ? x : JSON.stringify(x);
};
builtins.prototype.str = function(x) {
if(_.isString(x) || _.isArray(x) || _.isNumber(x)) {
return x.toString();
} else {
throw new Error('InvalidTypeError - unsupported type: ' + typeof x);
}
};
exports = module.exports = new builtins();
exports.math = Math;

@@ -1,13 +0,7 @@

var assert = require('assert'),
builtins = require('./builtins'),
_ = require('underscore');
'use strict';
function escapeStr(str) {
return str.replace(/\\/gm, '\\\\').replace(/\r?\n/gm, '\\n').replace(/\"/gm, '\\"').replace(/\t/gm, '\\t');
}
var builtins = require('./builtins'),
utils = require('./utils'),
_ = require('lodash');
function escapeRegex(str){
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
}
var evalOpenTag = '{{';

@@ -71,95 +65,57 @@ var evalCloseTag = '}}';

var evalTagRegex = new RegExp(escapeRegex(evalOpenTag) + '([^]*?)' + escapeRegex(evalCloseTag));
var actionTagRegex = new RegExp(escapeRegex(actionOpenTag) + '(\\s*(\\w+)([^]*)?)' + escapeRegex(actionCloseTag));
var actionTagNameRegex = new RegExp('\\s*(\\w+)[^]*');
var tagCaptureRegex = new RegExp('('+escapeRegex(evalOpenTag) + '[^]*?' + escapeRegex(evalCloseTag)
+'|'+escapeRegex(actionOpenTag) + '[^]*?' + escapeRegex(actionCloseTag)+')', 'gm');
var evalTagRegex = new RegExp(utils.escapeRegex(evalOpenTag) + '([^]*?)' + utils.escapeRegex(evalCloseTag));
var actionTagRegex = new RegExp(utils.escapeRegex(actionOpenTag) + '(\\s*(\\w+)([^]*)?)' + utils.escapeRegex(actionCloseTag));
//var actionTagNameRegex = new RegExp('\\s*(\\w+)[^]*');
var tagCaptureRegex = new RegExp('('+utils.escapeRegex(evalOpenTag) + '[^]*?' + utils.escapeRegex(evalCloseTag) +
'|'+utils.escapeRegex(actionOpenTag) + '[^]*?' + utils.escapeRegex(actionCloseTag)+')', 'gm');
var operators = ['+', '-', '*', '/', '==', '!=', '>=', '<=', '>', '<', '||', '&&', '!'];
// operators + "string" + comman, parenthesis
// operators + "string" + comman, parenthesis, brackets
// if, elif, else, endif
// for, in, endfor
var tokenSplitRegex = /(\+(?!\=)|\-(?!\=)|\*(?!\=)|\/(?!\=)|\=\=(?!\=)|\!\=(?!\=)|\>\=(?!\=)|\<\=(?!\=)|\>(?!\=|\>|\<)|\<(?!\=|\<|\>)|\|\||\&\&|\!(?!\=)|\".+?\"|\(|\)|,|\bif\b|\belse\b|\belif\b|\bendif\b|\bfor\b|\bin\b|\bendfor\b)/g;
var tokenSplitRegex = /(\+(?!=)|\-(?!=)|\*(?!=)|\/(?!=)|==(?!=)|!=(?!=)|>=(?!=)|<=(?!=)|>(?!=|>|<)|<(?!=|<|>)|\|\||&&|!(?!=)|".+?"|\(|\)|\[|]|,|\bif\b|\belse\b|\belif\b|\bendif\b|\bfor\b|\bin\b|\bendfor\b)/g;
var defaultOptions = {
throwsOnErrors: false,
outputCompiledCode: false,
throwOnError: false,
outputPrecompiledSourceToConsole: false,
outputErrorToConsole: false,
maximumIterations: -1
};
var options = {};
for(var d in defaultOptions) {
options[d] = defaultOptions[d];
}
// tokenize and remove empty ones
function _tokenize(expr) {
console.assert(_.isString(expr));
function Precompiled(code) {
this.code = code;
return _.filter(_.map(expr.split(tokenSplitRegex), function(t) { return t.trim(); }));
}
Precompiled.prototype.render = function(context) {
context = context || {};
function _safeEval(expr, shouldThrow) {
console.assert(_.isString(expr));
try {
var _func = new Function('__ctx', '__builtin', this.code);
if(expr.length === 0) { return ''; }
try {
return _func(context, builtins);
} catch(e) {
//console.log('runtime', e);
if(options.throwsOnErrors) { throw e; }
else { return ''; }
}
} catch(e) {
//console.log('compile-time', e);
if(options.throwsOnErrors) { throw e; }
else { return ''; }
}
};
var tokens = expr.split('.');
function Wash(source) {
this.source = source;
this._code = '';
this._localVars = [];
this._loop_counter = 0;
}
var safetyTest = '(';
_.each(tokens, function(e, i) {
var p = tokens.slice(0, i + 1);
safetyTest += '__ctx.' + p.join('.') + ' !== undefined';
if(i < tokens.length - 1) { safetyTest += ' && '; }
});
safetyTest += ')';
Wash.prototype._tokenize = function(expr) {
// tokenize and remove empty tokens
var tokens = expr.split(tokenSplitRegex);
var reduced = [];
for(var i=0, len=tokens.length; i<len; ++i) {
var trimmed = tokens[i].trim();
if(trimmed.length) { reduced.push(trimmed); }
if(shouldThrow) {
return '((' + safetyTest + ')?(__ctx.' + expr + '):assert(false))';
} else {
return '((' + safetyTest + ')?(__ctx.' + expr + '):"")';
}
return reduced;
};
}
Wash.prototype._evalTokenSafe = function(expr) {
if(expr.length === 0) {
//console.log('_evalTokenSafe() "" -> ""');
return '';
}
function _findSub(tokens, openIdx, openChar, closeChar) {
console.assert(tokens[openIdx] === openChar);
var tokens = expr.split('.');
var tokenTest = '(';
_.each(tokens, function(e, i) {
var p = tokens.slice(0, i+1);
tokenTest += '__ctx.' + p.join('.') + ' !== undefined';
if(i < tokens.length - 1) { tokenTest += ' && '; }
});
tokenTest += ')';
var output = '((' + tokenTest + ')?(__ctx.' + expr + '):"")';
//console.log('_evalTokenSafe() "%s" -> "%s"', expr, output);
return output;
};
Wash.prototype._findSub = function(tokens, openIdx, openChar, closeChar) {
assert(tokens[openIdx] === openChar, 'tokens[openIdx] != openChar?');
var level = 1;
for(var j=openIdx+1, len=tokens.length; j<len; ++j) {
for(var j = openIdx+1, len = tokens.length; j < len; ++j) {
if(tokens[j] === openChar) {

@@ -174,38 +130,99 @@ level += 1;

return -1;
}
function _isLiteral(token) {
// operators, string literal, true, false, number literals, commas
return _.contains(operators, token) ||
/^".*"$|^true$|^false$|^-?\d*\.?\d+$|^,$/.test(token);
}
function Precompiled(code, options) {
var self = this;
self.code = code;
self.options = options || {};
utils.deepDefaults(self.options, defaultOptions);
}
Precompiled.prototype.render = function(context) {
var self = this;
context = context || {};
var fn = null;
try {
/* jshint -W054 */
fn = new Function('__ctx', '__builtins', self.code);
} catch(e) {
if(self.options.outputErrorToConsole) {
console.error('Precompiled.render() compile error: ');
console.error(e.stack || e);
}
if(self.options.throwOnError) { throw e; }
else { return ''; }
}
try {
return fn(context, builtins);
} catch(e) {
if(self.options.outputErrorToConsole) {
console.error('Precompiled.render() rendering error: ');
console.error(e.stack || e);
}
if(self.options.throwOnError) { throw e; }
else { return ''; }
}
};
function Wash(source, options) {
var self = this;
self.source = source;
self.options = options || {};
_.each(_.keys(self.options), function(k) {
console.assert(!_.isUndefined(defaultOptions[k]), 'Unknown option: ' + k);
});
utils.deepDefaults(self.options, defaultOptions);
self._code = '';
self._localVars = [];
self._loop_counter = 0;
}
Wash.prototype._evalTokens = function(tokens) {
var self = this;
var outs = '';
for(var i=0,len=tokens.length; i<len; ++i) {
for(var i = 0, len = tokens.length; i < len; ++i) {
var token = tokens[i];
// operators, string literal, true, false, number literals, comman
if(_.contains(operators, token) || /^\".*\"$|^true$|^false$|^-?\d*\.?\d+$|^\,$/.test(token)) {
console.assert((token !== '[') && (token !== ']'));
if(_isLiteral(token)) {
outs += token;
} else if(token === '(') {
var closeIdx = this._findSub(tokens, i, '(', ')');
if(closeIdx > i) {
outs += '(' + this._evalTokens(tokens.slice(i+1, closeIdx)) + ')';
i = closeIdx;
var closeParen = _findSub(tokens, i, '(', ')');
if(closeParen > i) {
outs += '(' + self._evalTokens(tokens.slice(i + 1, closeParen)) + ')';
i = closeParen;
} else {
outs += token;
}
} else if(builtins.__isDefined(token)) {
outs += '__builtin.' + token;
} else {
var first;
var dot = token.indexOf('.');
if(dot < 0) {
first = token;
var builtin = utils.getValueByPath(builtins, '.' + token);
if(builtin) {
outs += '__builtins.' + token;
} else {
first = token.slice(0, dot);
var dot = token.indexOf('.');
var first = (dot < 0) ? token : token.slice(0, dot);
if(_.contains(self._localVars, first)) {
outs += token;
} else {
outs += _safeEval(token, self.options.throwOnError);
}
}
if(_.contains(this._localVars, first)) {
outs += token;
} else {
outs += this._evalTokenSafe(token);
}
}

@@ -218,45 +235,48 @@ }

Wash.prototype._parseForTag = function(params) {
var loopId = ++this._loop_counter;
var self = this;
var loopId = ++self._loop_counter;
var it = params[0];
var iterable = this._evalTokens(params.slice(2));
this._localVars.push(it);
self._localVars.push(it);
this._code += 'var __cnt_' + loopId + '=0;\n'
+ 'var __iterable_' + loopId + '=(' + iterable + ');\n'
+ 'for(var __key_' + loopId + ' in __iterable_' + loopId + '){\n';
self._code += 'var __cnt_' + loopId + '=0;\n' +
'var __iterable_' + loopId + '=(' + iterable + ');\n' +
'for(var __key_' + loopId + ' in __iterable_' + loopId + '){\n';
if(options.maximumIterations >= 0) {
this._code += 'if(__cnt_' + loopId + '>=' + options.maximumIterations+') { break; };\n';
if(self.options.maximumIterations >= 0) {
self._code += 'if(__cnt_' + loopId + '>=' + self.options.maximumIterations + ') { break; };\n';
}
this._code += 'var ' + it + '={\n'
+ 'key:__key_' + loopId + ',\n'
+ 'value:__iterable_' + loopId + '[__key_' + loopId + '],\n'
+ 'index:(__cnt_' + loopId + '++) };\n';
self._code += 'var ' + it + '={\n' + 'key:__key_' + loopId + ',\n' +
'value:__iterable_' + loopId + '[__key_' + loopId + '],\n' +
'index:(__cnt_' + loopId + '++) };\n';
};
Wash.prototype._parseTag = function(name, params) {
var self = this;
switch(name) {
case 'if':
var predExpr = this._evalTokens(params);
this._code += 'if('+predExpr+'){\n';
var predIf = self._evalTokens(params);
self._code += 'if(' + predIf + '){\n';
break;
case 'elif':
var predExpr = this._evalTokens(params);
this._code += '}else if('+predExpr+'){\n';
var predElif= self._evalTokens(params);
self._code += '}else if(' + predElif + '){\n';
break;
case 'else':
this._code += '}else{\n';
self._code += '}else{\n';
break;
case 'endif':
this._code += '}\n';
self._code += '}\n';
break;
case 'for':
this._parseForTag(params);
self._parseForTag(params);
break;
case 'endfor':
this._localVars.pop();
this._code += '}\n';
self._localVars.pop();
self._code += '}\n';
break;

@@ -267,46 +287,42 @@ }

Wash.prototype.precompile = function() {
this._code += '"use strict";\nvar __out="";\n';
var self = this;
self._code += '"use strict";\nvar __out="";\n';
var tokens = this.source.split(tagCaptureRegex);
//console.log(tokens);
var tagLevels = {};
for(var t in tags) {
tagLevels[tags[t].openTag] = 0;
}
_.each(tags, function(tag) {
tagLevels[tag.openTag] = 0;
});
for(var i=0,len=tokens.length; i<len; ++i) {
_.each(tokens, function(token) {
if(token.length === 0) { return; }
try {
var token = tokens[i];
if(token.length === 0) { continue; }
var match, expr;
var match;
if((match = evalTagRegex.exec(token)) && (tagLevels['raw'] <= 0)) {
var expr = match[1].trim();
if(expr.length) {
var output = this._evalTokens(this._tokenize(expr));
if(output.length) {
this._code += '__out+=(' + output + ');\n';
if((match = evalTagRegex.exec(token)) && (tagLevels.raw <= 0)) {
expr = match[1].trim();
if(expr) {
var output = self._evalTokens(_tokenize(expr));
if(output) {
self._code += '__out+=(' + output + ');\n';
}
}
} else if((match = actionTagRegex.exec(token))) {
var expr = match[1].trim();
if(expr.length) {
expr = match[1].trim();
if(expr) {
var tagName = match[2];
var tagParams = this._tokenize(match[3] || '');
console.assert(tags[tagName], 'Unknown tag: ' + tagName);
if(!tags[tagName]) {
throw new Error('Template syntax error - unknown tag: ' + tagName);
}
var tagParams = _tokenize(match[3] || '');
var tagInfo = tags[tagName];
console.assert(tagInfo.requireParams || (tagParams.length === 0),
'Redundant tag params: ' + tagName + ' ' + tagParams);
if(!tagInfo.requireParams && (tagParams.length > 0)) {
throw new Error('Template syntax error - redundant tag params: ' + tagName + ' ' + tagParams);
}
if(tagLevels['raw'] <= 0) {
this._parseTag(tagName, tagParams);
if(tagLevels.raw <= 0) {
self._parseTag(tagName, tagParams);
} else if(tagInfo.openTag !== 'raw') {
this._code += '__out+="' + escapeStr(token) + '";\n';
self._code += '__out+="' + utils.escapeStr(token) + '";\n';
}

@@ -317,37 +333,53 @@

} else {
this._code += '__out+="' + escapeStr(token) + '";\n';
self._code += '__out+="' + utils.escapeStr(token) + '";\n';
}
} catch(err) {
if(options.throwsOnErrors) { throw err; }
if(self.options.outputErrorToConsole) {
console.error('Wash.precompile() eval error: ');
console.error(err.stack || err);
}
if(self.options.throwOnError) { throw err; }
}
}
});
for(var tagName in tagLevels) {
var l = tagLevels[tagName];
if(l > 0) {
if(options.throwsOnErrors) {
throw new Error('Template syntax error - no closing tag: ' + tagName);
} else {
this._code = 'var __out = ""';
_.each(tagLevels, function(level, tagName) {
if(level > 0) {
if(self.options.outputErrorToConsole) {
console.error('Wash.precompile() no closing tag: ' + tagName);
}
} else if(l < 0) {
if(options.throwsOnErrors) {
throw new Error('Template syntax error - redundant closing tag: ' + tagName);
} else {
this._code = 'var __out = ""';
console.assert(!self.options.throwOnError, 'No closing tag: ' + tagName);
self._code = 'var __out = "";';
} else if(level < 0) {
if(self.options.outputErrorToConsole) {
console.error('Wash.precompile() redundant closing tag: ' + tagName);
}
console.assert(!self.options.throwOnError, 'Redundant closing tag: ' + tagName);
self._code = 'var __out = "";';
}
}
});
this._code += 'return __out;\n';
self._code += 'return __out;\n';
if(options.outputCompiledCode) {
console.log(this._code);
if(self.options.outputPrecompiledSourceToConsole) {
console.log('Wash.precompile() compiled source: ');
console.log(self._code);
}
return new Precompiled(this._code);
return new Precompiled(self._code, self.options);
};
Wash.prototype.render = function(context) {
var self = this;
var precompiled = self.precompile();
return precompiled.render(context);
};
exports = module.exports = Wash;
exports.precompile = function(source) {
var wash = new Wash(source);
var wash = new Wash(source, defaultOptions);
return wash.precompile();

@@ -358,3 +390,3 @@ };

if(!(source instanceof Precompiled)) {
var wash = new Wash(source);
var wash = new Wash(source, defaultOptions);
source = wash.precompile(source);

@@ -364,34 +396,2 @@ }

return source.render(context);
};
exports.save = function(precompiled) {
assert(precompiled instanceof Precompiled, 'input parameter is not a "Precompiled" object.');
return precompiled.code;
};
exports.load = function(saved) {
return new Precompiled(saved, [], []);
};
exports.resetOptions = function() {
for(var d in defaultOptions) {
options[d] = defaultOptions[d];
}
};
exports.setOption = function(name, value) {
if(!options.hasOwnProperty(name)) {
throw new Error('invalid option name: ' + name);
}
options[name] = value;
};
exports.getOption = function(name) {
if(!options.hasOwnProperty(name)) {
throw new Error('invalid option name: ' + name);
}
return options[name];
};
{
"name": "wash",
"description": "a safe template rendering engine",
"version": "0.1.1",
"version": "1.0.4",
"main": "index",
"author": {
"author": {
"name" : "Daniel Kang",

@@ -12,3 +12,3 @@ "email" : "me@daniel.gs",

"licenses" : [
{
{
"type" : "MIT",

@@ -19,7 +19,7 @@ "url" : "https://raw.github.com/d5/wash/master/LICENSE"

"dependencies": {
"underscore": "1.5.0"
"lodash": "2.4.1"
},
"devDependencies": {
"mocha": "1.12.0",
"expect.js": "0.2.0"
"jshint": "2.5.2",
"mocha": "1.20.x"
},

@@ -35,4 +35,4 @@ "repository": {

"scripts": {
"test": "node_modules/.bin/mocha --reporter spec"
"test": "node_modules/.bin/jshint lib && node_modules/.bin/jshint test && node_modules/.bin/mocha test"
}
}
}

@@ -64,8 +64,4 @@ # Wash

## Wash in Production
- [gist.sh](http://gist.sh): _(currently in beta phase)_
## License
[MIT license](https://raw.github.com/d5/wash/master/LICENSE)

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('eval', function() {
beforeEach(function() {
reset();
});
describe('empty', function() {

@@ -9,0 +5,0 @@ expect('', '');

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('eval', function() {
beforeEach(function() {
reset();
});
describe('built-ins', function() {

@@ -37,4 +33,3 @@ describe('len', function() {

expect('{{ join(range(3)) }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ join(range(3)) }}', function() { opt('throwsOnErrors', true) });
expectError('{{ join(range(3)) }}', '');
});

@@ -47,8 +42,5 @@

expect('{{ reverse() }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ reverse() }}', function() { opt('throwsOnErrors', true) });
expectError('{{ reverse() }}', '');
expectError('{{ reverse(ten) }}', '');
expect('{{ reverse(ten) }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ reverse(ten) }}', function() { opt('throwsOnErrors', true) });
expect('{{ reverse(foo) + foo }}', 'ooffoo');

@@ -63,15 +55,6 @@ });

expect('{{ sort(range(3), true) }}', '2,1,0');
expect('{{ sort(arr, true) }}', '4,3,2,1,0');
expect('{{ sort(rarr, true) }}', '9,8,4,3,2');
expect('{{ sort(hello, true) }}', 'roollledWH, ');
expectError('{{ sort() }}', '');
expectError('{{ sort(ten) }}', '');
expect('{{ sort() }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ sort() }}', function() { opt('throwsOnErrors', true) });
expect('{{ sort(ten) }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ sort(ten) }}', function() { opt('throwsOnErrors', true) });
expect('{{ sort(hello) + hello }}', ' ,HWdellloorHello, World');
expect('{{ sort(hello,true) + hello }}', 'roollledWH, Hello, World');
});

@@ -90,7 +73,4 @@

expect('{{ slice(5) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ slice(5) }}', function() { opt('throwsOnErrors', true); });
expect('{{ slice() }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ slice() }}', function() { opt('throwsOnErrors', true); });
expectError('{{ slice(5) }}', '');
expectError('{{ slice() }}', '');
});

@@ -107,3 +87,3 @@

describe('isObject', function() {
expect('{{ isObject(arr) }}', 'true');
expect('{{ isObject(arr) }}', 'false');
expect('{{ isObject(foo) }}', 'false');

@@ -115,12 +95,13 @@ expect('{{ isObject(a) }}', 'true');

describe('getAt', function() {
expect('{{ getAt(arr, 2) }}', '2');
expect('{{ getAt("abcde", 3) }}', 'd');
expect('{{ getAt(a.b.c, 1) }}', 'b');
describe('get', function() {
expect('{{ get(arr, 2) }}', '2');
expect('{{ get("abcde", 3) }}', 'd');
expect('{{ get(a.b.c, 1) }}', 'b');
expect('{{ getAt(arr, "2") }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ getAt(arr, "2") }}', function() { opt('throwsOnErrors', true); });
expectError('{{ get(arr, "2") }}', '');
expectError('{{ get(a, 0) }}', '');
expect('{{ getAt(a, 0) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ getAt(a, 0) }}', function() { opt('throwsOnErrors', true); });
expect('{{ get(a, ".b.c") }}', 'abc');
expect('{{ get(a.b, ".c") }}', 'abc');
expect('{{ get(a.b.c, 1) }}', 'b');
});

@@ -135,10 +116,5 @@

expect('{{ split("1,2,3", 1) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ split("1,2,3", 1) }}', function() { opt('throwsOnErrors', true); });
expect('{{ split(arr, ",") }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ split(arr, ",") }}', function() { opt('throwsOnErrors', true); });
expect('{{ split(func1, ",") }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ split(func1, ",") }}', function() { opt('throwsOnErrors', true); });
expectError('{{ split("1,2,3", 1) }}', '');
expectError('{{ split(arr, ",") }}', '');
expectError('{{ split(func1, ",") }}', '');
});

@@ -151,5 +127,2 @@

expect('{{ int("0.34") }}', '0');
expect('{{ int(arr) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ int(arr) }}', function() { opt('throwsOnErrors', true); });
});

@@ -162,5 +135,2 @@

expect('{{ float("0.34") }}', '0.34');
expect('{{ float(arr) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ float(arr) }}', function() { opt('throwsOnErrors', true); });
});

@@ -172,9 +142,7 @@

expect('{{ str(ten) }}', '10');
expect('{{ str(arr) }}', '0,1,2,3,4');
expect('{{ str(arr) }}', '[0,1,2,3,4]');
expect('{{ str(func1) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ str(func1)) }}', function() { opt('throwsOnErrors', true); });
expect('{{ str(func1) }}', 'undefined');
expect('{{ str(a) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ str(a)) }}', function() { opt('throwsOnErrors', true); });
expect('{{ str(a) }}', '{\"b\":{\"c\":\"abc\"}}');
});

@@ -188,6 +156,10 @@

describe('not builtins', function() {
expect('{{ len2(foo) }}', '', function() { opt('throwsOnErrors', false); });
expectException('{{ len2(foo) }}', function() { opt('throwsOnErrors', true); });
expectError('{{ len2(foo) }}', '');
});
describe('some math functions', function() {
expect('{{ math.min(4, 5) }}', '4');
expect('{{ math.max(4, 5) }}', '5');
});
});
});

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('eval', function() {
beforeEach(function() {
reset();
});
describe('function', function() {

@@ -18,12 +14,8 @@ describe('call', function() {

describe('global functions', function() {
expect('{{ Math.abs(-123) }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ Math.abs(-123) }}', function() { opt('throwsOnErrors', true) });
expect('{{ process.memoryUsage() }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ process.memoryUsage() }}', function() { opt('throwsOnErrors', true) });
expect('{{ JSON.parse("{}") }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ JSON.parse("{}") }}', function() { opt('throwsOnErrors', true) });
expect('{{ parseInt("123") }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ parseInt("123") }}', function() { opt('throwsOnErrors', true) });
expectError('{{ Math.abs(-123) }}', '');
expectError('{{ process.memoryUsage() }}', '');
expectError('{{ JSON.parse("{}") }}', '');
expectError('{{ parseInt("123") }}', '');
});
});
});

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('eval', function() {
beforeEach(function() {
reset();
});
describe('empty', function() {

@@ -51,13 +47,9 @@ expect('{{}}', '');

expect('{{ \'foo\' }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ \'foo\' }}', function() { opt('throwsOnErrors', true) });
expectError('{{ \'foo\' }}', '');
});
describe('syntax error', function() {
expect('{{ () }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ () }}', function() { opt('throwsOnErrors', true) });
expect('{{ true false }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ true false }}', function() { opt('throwsOnErrors', true) });
expect('{{ "foo" "bar" }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ "foo" "bar" }}', function() { opt('throwsOnErrors', true) });
expectError('{{ () }}', '');
expectError('{{ true false }}', '');
expectError('{{ "foo" "bar" }}', '');
});

@@ -108,4 +100,3 @@ });

expect('{{ "foo" == "bar" }}', 'false');
expect('{{ 1 === 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 === 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 === 2 }}', '');
});

@@ -119,4 +110,3 @@

expect('{{ "foo" != "bar" }}', 'true');
expect('{{ 1 !== 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 !== 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 !== 2 }}', '');
});

@@ -128,4 +118,3 @@

expect('{{ 3 > 2 }}', 'true');
expect('{{ 1 >> 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 >> 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 >> 2 }}', '');
});

@@ -137,4 +126,3 @@

expect('{{ 3 >= 2 }}', 'true');
expect('{{ 1 >>= 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 >>= 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 >>= 2 }}', '');
});

@@ -146,4 +134,3 @@

expect('{{ 3 < 2 }}', 'false');
expect('{{ 1 << 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 << 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 << 2 }}', '');
});

@@ -155,4 +142,3 @@

expect('{{ 3 <= 2 }}', 'false');
expect('{{ 1 <== 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 <== 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 <== 2 }}', '');
});

@@ -164,4 +150,3 @@

expect('{{ false && false }}', 'false');
expect('{{ true &&& true }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ true &&& true }}', function() { opt('throwsOnErrors', true) });
expectError('{{ true &&& true }}', '');
});

@@ -173,4 +158,3 @@

expect('{{ false || false }}', 'false');
expect('{{ true ||| true }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ true ||| true }}', function() { opt('throwsOnErrors', true) });
expectError('{{ true ||| true }}', '');
});

@@ -182,15 +166,11 @@

expect('{{ !!true }}', 'true');
expect('{{ true ! true }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ true ! true }}', function() { opt('throwsOnErrors', true) });
expect('{{ true !! true }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ true !! true }}', function() { opt('throwsOnErrors', true) });
expectError('{{ true ! true }}', '');
expectError('{{ true !! true }}', '');
});
describe('other no-supports', function() {
expect('{{ 1 <> 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 <> 2 }}', function() { opt('throwsOnErrors', true) });
expect('{{ 1 !! 2 }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ 1 !! 2 }}', function() { opt('throwsOnErrors', true) });
expectError('{{ 1 <> 2 }}', '');
expectError('{{ 1 !! 2 }}', '');
});
});
});

@@ -1,9 +0,5 @@

require('./util');
'use strict';
describe('eval', function() {
beforeEach(function() {
reset();
});
describe('variables', function() {
describe('variables', function() {
expect('{{ foo }}', 'foo');

@@ -29,22 +25,18 @@ expect('{{ bar }}', 'Bar');

expect('{{ a. b .c }}', 'abc');
expect('{{ a..b }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ a..b }}', function() { opt('throwsOnErrors', true) });
expect('{{ a.b..c }}', '', function() { opt('throwsOnErrors', false) });
expectException('{{ a.b..c }}', function() { opt('throwsOnErrors', true) });
expectError('{{ a..b }}', '');
expectError('{{ a.b..c }}', '');
});
describe('global variables', function() {
expect('{{ Math.E }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ Math.E }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ process.version }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ process.version }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ __ctx }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ __ctx }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ __builtin }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ __builtin }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ NaN }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ NaN }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ undefined }}', '', function() { opt('throwsOnErrors', false) });
expect('{{ undefined }}', '', function() { opt('throwsOnErrors', true) });
expect('{{ Math.E }}', '');
expect('{{ process.version }}', '');
expect('{{ __ctx }}', '');
expect('{{ __builtin }}', '');
expect('{{ NaN }}', '');
expect('{{ undefined }}', '');
});
describe('partial error', function() {
expectError('{{ notDefined }} still {{ foo }}', ' still foo');
});
});

@@ -1,14 +0,11 @@

var t = require('../lib/wash'),
expect = require('expect.js');
'use strict';
var wash = require('../lib/wash');
describe('precompile', function() {
beforeEach(function() {
reset();
});
it('simplest', function() {
it('simplest', function() {
var source = '{{ foo }}';
var ctx = { foo: 'bar' };
var precompiled = t.precompile(source);
expect(t.render(source, ctx)).to.equal(t.render(precompiled, ctx));
var precompiled = wash.precompile(source);
assert.strictEqual(wash.render(source, ctx), wash.render(precompiled, ctx));
});

@@ -19,14 +16,5 @@

var ctx = { foo: 5 };
var precompiled = t.precompile(source);
expect(t.render(source, ctx)).to.equal(t.render(precompiled, ctx));
var precompiled = wash.precompile(source);
assert.strictEqual(wash.render(source, ctx), wash.render(precompiled, ctx));
});
it('save and load', function() {
var source = '{% for i in range(foo) %}{{ i }}{% endfor %}';
var ctx = { foo: 5 };
var precompiled = t.precompile(source);
var saved = t.save(precompiled);
var loaded = t.load(saved);
expect(t.render(precompiled, ctx)).to.equal(t.render(loaded, ctx));
});
});

@@ -1,24 +0,15 @@

require('./util');
'use strict';
describe('safety', function() {
beforeEach(function() {
reset();
});
describe('call', function() {
expectException('{{ arr.join.call(arr, ",") }}');
expectError('{{ arr.join.call(arr, ",") }}', '');
});
describe('apply', function() {
expectException('{{ arr.concat.apply(arr, rarr) }}');
expectError('{{ arr.concat.apply(arr, rarr) }}', '');
});
describe('String', function() {
//expect('');
});
describe('Array', function() {
// arr.prototype ==> ""
expect('{{ arr.prototype }}', '');
expectException('{{ arr.prototype.join(",") }}');
expectError('{{ arr.prototype.join(",") }}', '');
expect('{% for i in arr.prototype %}{{ i.value }}{% endfor %}', '');

@@ -30,3 +21,3 @@ });

expect('{{ __builtin }}', '');
expectException('{{ __builtin.len("123") }}');
expectError('{{ __builtin.len("123") }}', '');
});

@@ -38,7 +29,7 @@

expect('{{ __ctx.foo }}', '');
expectException('{{ __ctx.func1() }}');
expectError('{{ __ctx.func1() }}', '');
});
describe('while', function() {
expectException('{{ while(true) {} }}');
expectError('{{ while(true) {} }}', '');
});

@@ -45,0 +36,0 @@

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('for', function() {
beforeEach(function() {
reset();
});
describe('array', function() {

@@ -40,36 +36,28 @@ expect('{% for i in arr %}{{ i.value }}{% endfor %}', '01234');

describe('max iterations', function () {
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '0123456789', function() { opt('maximumIterations', -1); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '0123456789', function() { opt('maximumIterations', 10); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '01234', function() { opt('maximumIterations', 5); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '01', function() { opt('maximumIterations', 2); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '', function() { opt('maximumIterations', 0); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', '0123456789', function() { opt('maximumIterations', -1); });
expect('{% for i in "abcde" %}{{ i.value }}{% endfor %}', 'ab', function() { opt('maximumIterations', 2); });
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: -1 }, '0123456789');
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: 10 }, '0123456789');
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: 5 }, '01234');
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: 2 }, '01');
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: 0 }, '');
expect('{% for i in range(10) %}{{ i.value }}{% endfor %}', { maximumIterations: -1 }, '0123456789');
expect('{% for i in "abcde" %}{{ i.value }}{% endfor %}', { maximumIterations: 2 }, 'ab');
});
describe('errors', function() {
expect('{% for i in %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for i in %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for i in %}{{ i.value }}{% endfor %}', '');
expect('{% for in range(4) %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for in range(4) %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for in range(4) %}{{ i.value }}{% endfor %}', '');
expect('{% for in %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for in %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for in %}{{ i.value }}{% endfor %}', '');
expect('{% for i range(4) %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for i range(4) %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for i range(4) %}{{ i.value }}{% endfor %}', '');
expect('{% for(i in range(4)) %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for(i in range(4)) %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for(i in range(4)) %}{{ i.value }}{% endfor %}', '');
expect('{% for (i) in range(4) %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for (i) in range(4) %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for (i) in range(4) %}{{ i.value }}{% endfor %}', '');
expect('{% for range(3) in range(4) %}{{ i.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for range(3) in range(4) %}{{ i.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for range(3) in range(4) %}{{ i.value }}{% endfor %}', '');
expect('{% for i in range(4) %}{% for j in range(3) %}{{ "" + i.value + j.value }}{% endfor %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% for i in range(4) %}{% for j in range(3) %}{{ "" + i.value + j.value }}{% endfor %}', function() { opt('throwsOnErrors', true); });
expectError('{% for i in range(4) %}{% for j in range(3) %}{{ "" + i.value + j.value }}{% endfor %}', '');
});
});

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('if', function() {
beforeEach(function() {
reset();
});
describe('basic', function() {

@@ -59,11 +55,8 @@ expect('{% if true %}1{% endif %}', '1');

describe('errors', function() {
expect('{% if true %}{% if true %}1{% endif %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% if true %}{% if true %}1{% endif %}', function() { opt('throwsOnErrors', true); });
expectError('{% if true %}{% if true %}1{% endif %}', '');
expect('{% if %}1{% endif %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% if %}1{% endif %}', function() { opt('throwsOnErrors', true); });
expectError('{% if %}1{% endif %}', '');
expect('{% if true %}1{% endif what %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% if true %}1{% endif what %}', function() { opt('throwsOnErrors', true); });
expectError('{% if true %}1{% endif what %}', '');
});
});

@@ -1,8 +0,4 @@

require('./util');
'use strict';
describe('raw', function() {
beforeEach(function() {
reset();
});
describe('basic', function() {

@@ -26,8 +22,6 @@ expect('{% raw %}foo{% endraw %}', 'foo');

describe('errors', function() {
expect('{% raw %}foo', '', function() { opt('throwsOnErrors', false); });
expectException('{% raw %}foo', function() { opt('throwsOnErrors', true); });
expectError('{% raw %}foo', '');
expect('{% raw %}{% raw %}foo{% endraw %}', '', function() { opt('throwsOnErrors', false); });
expectException('{% raw %}{% raw %}foo{% endraw %}', function() { opt('throwsOnErrors', true); });
})
expectError('{% raw %}{% raw %}foo{% endraw %}', '');
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc