New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

jqtpl

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jqtpl - npm Package Compare versions

Comparing version 1.1.0 to 2.0.0rc1

.npmignore

2

index.js
module.exports = require('./lib/jqtpl');
module.exports.express = require('./lib/jqtpl.express');
module.exports.__express = require('./lib/express').render;

@@ -1,4 +0,7 @@

/*jslint evil: true*/
(function(exports) {
/**
* Port of jQuery's Template Engine to Nodejs.
* A template engine for nodejs, browser and any other javascript environment.
*
* Originally started as a port of jQuery's Template Engine to Nodejs.
* http://github.com/jquery/jquery-tmpl

@@ -11,2 +14,3 @@ *

var isArray = Array.isArray;

@@ -21,95 +25,13 @@ /**

*/
var isArray = Array.isArray || function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
if (!isArray) {
isArray = function(obj) {
return {}.toString.call(obj) === '[object Array]';
};
}
/**
* Iterate over array or object ala jquery.
* @param {Object|Array} obj object or array to iterate over.
* @param {Function} callback function.
* @api public
*/
exports.each = function(obj, callback) {
var key;
if (isArray(obj)) {
for (key = 0; key < obj.length; ++key) {
callback.call(obj[key], key, obj[key]);
}
} else {
for (key in obj) {
callback.call(obj[key], key, obj[key]);
}
}
};
/**
* Escape html chars.
* @param {String} str html string.
* @return {String} str escaped html string.
* @api public
*/
exports.encode = function(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;');
};
/**
* Tags supported by the engine.
* @type {Object}
* @api public
*/
exports.tag = {
'tmpl': {
_default: { $2: 'null' },
open: 'if($notnull_1){_=_.concat($item.nest($1,$2));}'
// tmpl target parameter can be of type function, so use $1,
// not $1a (so not auto detection of functions) This means that
// {{tmpl foo}} treats foo as a template (which IS a function).
// Explicit parens can be used if foo is a function that returns
// a template: {{tmpl foo()}}.
},
'wrap': {
_default: { $2: 'null' },
open: '$item.calls(_,$1,$2);_=[];',
close: 'call=$item.calls();_=call._.concat($item.wrap(call,_));'
},
'each': {
_default: { $2: '$index, $value' },
open: 'if($notnull_1){$.each($1a,function($2){with(this){',
close: '}});}'
},
'if': {
open: 'if(($notnull_1) && $1a){',
close: '}'
},
'else': {
_default: { $1: 'true' },
open: '}else if(($notnull_1) && $1a){'
},
'html': {
// Unecoded expression evaluation.
open: 'if($notnull_1){_.push($1a);}'
},
'=': {
// Encoded expression evaluation. Abbreviated form is ${}.
_default: { $1: '$data' },
open: 'if($notnull_1){_.push($.encode($1a));}'
},
'!': {
// Comment tag. Skipped by parser
open: ''
},
'verbatim': {}
};
/**
* Escape template.
* @param {String} args template.
* @return {String} args
*
* @param {String} template.
* @return {String}
* @api private

@@ -126,4 +48,5 @@ */

* Unescape template.
* @param {String} args template.
* @return {String} args
*
* @param {String} template.
* @return {String}
* @api private

@@ -135,2 +58,7 @@ */

var rVerbatim = /\{\{verbatim\}\}((.|\n)*?)\{\{\/verbatim\}\}/g,
rTags = /\$\{([^\}]*)\}/g,
rParser = /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
rEscapedWhite = /\\n|\\t|\\r/g;
/**

@@ -143,32 +71,30 @@ * Build reusable function for template generation

*/
function buildTmplFn(markup) {
function build(markup) {
var verbatims = [],
rverbatim = /\{\{verbatim\}\}((.|\n)*?)\{\{\/verbatim\}\}/g;
body;
// save all the data inside the verbatim tags
markup = markup.replace(rverbatim, function(all, content) {
verbatims.push(content);
body =
'var __body="";' +
// replace the {{verbatim}}data{{/verbatim}} with just {{verbatim}}
// this tag will let the parser know where to inject the corresponding data
return "{{verbatim}}";
});
// Introduce the data as local variables using with(){}.
'with(__data){' +
'__body+="' +
// Convert the template into pure JavaScript.
escape(markup)
.trim()
// Save all the data inside the verbatim tags.
.replace(rVerbatim, function(all, content) {
verbatims.push(content);
return new Function('$', '$item',
'var call,_=[],$data=$item.data;' +
// Replace the {{verbatim}}data{{/verbatim}} with just {{verbatim}}
// this tag will let the parser know where to inject the corresponding data.
return "{{verbatim}}";
})
.replace(rTags, '{{= $1}}')
.replace(rParser, function(all, slash, type, fnargs, target, parens, args) {
var tag = exports.tag[type], def, expr, exprAutoFnDetect;
// Introduce the data as local variables using with(){}
'with($data){_.push("' +
// Convert the template into pure JavaScript
escape(markup.trim())
.replace(/\$\{([^\}]*)\}/g, '{{= $1}}')
.replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
function(all, slash, type, fnargs, target, parens, args) {
var tag = exports.tag[type], def, expr, exprAutoFnDetect,
rEscapedWhite = /\\n|\\t|\\r/g;
if (!tag) {
throw new Error('Template command not found: ' + type);
throw new Error('Unknown template tag: ' + type);
}

@@ -178,7 +104,7 @@

// inject the corresponding verbatim data
// Inject the corresponding verbatim data.
return escape(verbatims.shift());
}
def = tag._default || [];
def = tag.default || [];

@@ -202,88 +128,204 @@ if (parens && !/\w$/.test(target)) {

// In that case don't call with template item as 'this' pointer. Just evaluate...
expr = parens ? (target.indexOf('.') > -1 ? target + unescape(parens) : ('(' + target + ').call($item' + args)) : target;
exprAutoFnDetect = parens ? expr : '(typeof(' + target + ')==="function"?(' + target + ').call($item):(' + target + '))';
expr = parens ? (target.indexOf('.') > -1 ? target + unescape(parens) : ('(' + target + ').call(__data' + args)) : target;
exprAutoFnDetect = parens ? expr : '(typeof(' + target + ')==="function"?(' + target + ').call(__data):(' + target + '))';
} else {
exprAutoFnDetect = expr = def.$1 || 'null';
exprAutoFnDetect = expr = def.__1 || 'null';
}
fnargs = unescape(fnargs);
return '");' +
return '";' +
tag[slash ? 'close' : 'open']
.split('$notnull_1').join(target ? 'typeof(' + target + ')!=="undefined" && (' + target + ')!=null' : 'true')
.split('$1a').join(exprAutoFnDetect)
.split('$1').join(expr)
.split('$2').join(fnargs || def.$2 || '') +
'_.push("';
}
) +
'");}return _.join("");'
);
.split('__notnull_1').join(target ? 'typeof(' + target + ')!=="undefined" && (' + target + ')!=null' : 'true')
.split('__1a').join(exprAutoFnDetect)
.split('__1').join(expr)
.split('__2').join(fnargs || def.__2 || '') +
'__body += "';
}) +
'"' +
'}' +
'return __body;';
return new Function('$', '__data', body);
}
/**
* Generate reusable function and cache it using name or markup as a key
* Render a template.
*
* @param {String} name of the template.
* @param {String} markup html string - optional.
* @return {Function|undefined} reusable template generator function.
* @param {String} cached tempalte name.
* @param {Object?} data used as template vars.
* @return {String} rendered markup string.
* @api private
*/
function render(name, data) {
var fn = exports.cache[name],
ret, i;
if (data && isArray(data)) {
ret = '';
for (i = 0; i < data.length; ++i) {
ret += fn.call({}, $, data[i]);
}
} else {
ret = fn.call({}, $, data || {});
}
return ret;
}
/**
* Tags supported by the engine.
*
* @type {Object}
* @api public
*/
exports.template = function template(name, markup) {
name = name || markup;
exports.tag = {
partial: {
default: {__2: 'null'},
var fn = template[name];
// Partal target parameter can be of type function, so use __1,
// not __1a (so not auto detection of functions) This means that
// {{partial foo}} treats foo as a template (which IS a function).
// Explicit parens can be used if foo is a function that returns
// a template: {{partial foo()}}.
open: 'if(__notnull_1){__body+=$.partial(__1,__2,__data)}'
},
each: {
default: {__2: '$value, $index'},
open: 'if(__notnull_1){$.each(__1a,function(__2){',
close: '});}'
},
verbatim: {},
if (markup != null && !fn) {
// Uncoded expression evaluation.
html: {
open: 'if(__notnull_1){__body+=__1a}'
},
'if': {
open: 'if((__notnull_1) && __1a){',
close: '}'
},
'else': {
default: {__1: 'true'},
open: '}else if((__notnull_1) && __1a){'
},
// Encoded expression evaluation. Abbreviated form is ${}.
'=': {
default: {__1: '__data'},
open: 'if(__notnull_1){__body+=$.escapeHtml(__1a)}'
},
// Comment tag. Skipped by parser.
'!': {
open: ''
}
};
/**
* Cached template generator functions.
*
* - `key` - template name or markup string.
* - `value` - compiled template function.
*
* @type {Object}
* @api public
*/
exports.cache = {};
/**
* Build a reusable function and cache it using name or markup as a key.
*
* @param {String} markup html string.
* @param {String?} optional name of the template.
* @return {Function} reusable template generator function.
* @api public
*/
exports.compile = function(markup, name) {
if (markup == null) {
throw new Error('Param `markup` is required.');
}
name || (name = markup);
if (!exports.cache[name]) {
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
try {
fn = template[name] = buildTmplFn(markup);
exports.cache[name] = build(markup);
} catch(err) {
throw new Error('CompilationError: ' + err + '\nTemplate: ' + name);
err.message += ': ' + name;
err.markup = markup;
throw err;
}
}
return fn;
return function(data) {
return render(name, data);
};
};
/**
* Compile and render a template.
*
* @param {String} markup or cached name.
* @param {Object?} data used as template vars.
* @return {String} rendered markup string.
* @api public
*/
exports.render = function(markup, data) {
return exports.compile(markup)(data);
};
/**
* Global helpers namespace - make functions available in every template.
* Use this namespace in custom tags.
*
* @type {Object}
* @api public
*/
var $ = exports.$ = {};
/**
* Render nested template
* @param {String} tmpl path to the view
* @param {Object} data object optional.
* @param {Object} options optional.
* @return {String} rendered template.
* @api private
* Can be overridden to provide platform specific functionality like
* loading files by name.
*/
function nest(tmpl, data, options) {
return exports.tmpl(exports.template(tmpl), data, options);
}
$.partial = exports.render;
/**
* Render template
* @param {String|Function} markup html markup or precompiled markup name.
* @param {Object} data can be used in template as template vars.
* @param {Object} options additional options.
* @return {String} ret rendered markup string.
* @api public
* Iterate over array or object.
*
* @param {Object|Array} obj object or array to iterate over.
* @param {Function} callback function.
* @api private
*/
exports.tmpl = function(markup, data, options) {
var fn = typeof markup === 'function' ? markup : exports.template(null, markup),
ret = '', i;
$.each = function(obj, callback) {
var key;
data = data || {};
options = options || {};
options.data = data;
options.nest = nest;
if (isArray(data)) {
for (i = 0; i < data.length; ++i) {
options.data = data[i];
ret += fn.call(options.scope, exports, options);
if (isArray(obj)) {
for (key = 0; key < obj.length; ++key) {
callback.call(obj[key], obj[key], key);
}
} else {
ret = fn.call(options.scope, exports, options);
for (key in obj) {
callback.call(obj[key], obj[key], key);
}
}
};
return ret;
/**
* Escape html chars.
*
* @param {String} str html string.
* @return {String} str escaped html string.
* @api private
*/
$.escapeHtml = function(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;');
};
}(typeof exports == 'object' ? exports : (this.jqtpl = {})));

@@ -1,21 +0,18 @@

{
{
"name": "jqtpl",
"description": "A port of jQuery's template engine",
"version": "1.1.0",
"description": "A template engine for nodejs, browser and any other javascript environment",
"version": "2.0.0rc1",
"author": "Oleg Slobodskoi <oleg008@gmail.com>",
"contributors": [
{ "name": "John Resig", "email": "jeresig@gmail.com" },
{ "name": "Boris Moore", "email": "borismoore@gmail.com"}
],
"repository": {
"type": "git",
"url": "http://github.com/kof/node-jqtpl.git"
"url": "http://github.com/kof/jqtpl.git"
},
"keywords": ["template", "engine", "jquery", "jquery-tmpl", "django", "logicless", "express"],
"directories": { "lib": "./lib" },
"engines": { "node": ">= 0.3.7" },
"keywords": ["template", "engine", "jquery", "jquery-tmpl", "logic-less"],
"engines": {"node": "*"},
"dependencies": {
"underscore": "1.4.x"
},
"devDependencies": {
"express": ">= 2.2.1 < 3.0.0",
"qunit": "0.2.x",
"underscore": "1.3.x",
"express": "3.0.x",
"qunit": "0.5.x",
"request": "2.9.x"

@@ -22,0 +19,0 @@ },

@@ -1,125 +0,54 @@

## This is a port of jQuery's Template Engine to nodejs
## A template engine for nodejs, browser and any other javascript environment.
- Logic-less.
- Extendable - implement your own tags.
- Html escaped per default.
### Originally started as a port of jquery templates.
http://github.com/jquery/jquery-tmpl
## Full API documentation of the original plugin
http://api.jquery.com/category/plugins/templates/
Note: currently not implemented: wrap tag and tmplItem method.
**Now compatibility to the original engine is dropped as jquery-tmpl is not any more developed.**
## Philosophy is similar to django
http://docs.djangoproject.com/en/dev/topics/templates/
* no program logic in templates
* no embeded script language like in ejs
1. this is evil because it enables program logic in templates
1. bad usability
1. because of the "var" problem in javascript
## Features
* jquery tmpl plugin conform
* extendable - you can implement new statements
* html escaping per default
* simple syntax
* tiny and fast
## Installation via npm
npm install jqtpl
## Run tests
### Installation
$ npm i jqtpl
$ make test
## Template API
## Usage
### ${}, {{=}} print variable, array or function (escaped)
### require the module
var jqtpl = require("jqtpl");
- Print variable
### jqtpl.tmpl(markup, data, options);
// tpl
<div>${a}</div>
// code
jqtpl.render(tpl, {a:123});
// output
<div>123</div>
Compile and render a template. It uses `jqtpl.template` method.
- Print array
- `markup` html code string
- `data` object or array of data
- `options` optional options object
//tpl
<div>${a}</div>
// code
jqtpl.render(tpl, [{a:1},{a:2},{a:3}]);
// output
<div>1</div><div>2</div><div>3</div>
### jqtpl.template(name, tpl)
- Print automatically detected function
Named templates - there is a way to precompile the template using a string, so you can render this template later using its name.
**Template is cached after this fn call.**
// tpl
<div>${a}</div>
// code
jqtpl.render(tpl, {
a: function() {
return 1 + 5;
}
});
//output
<div>6</div>
// tpl
<div>${a}</div>
// code
// precompile an cache it
jqtpl.template( "templateName", tpl );
// render
jqtpl.tmpl( "templateName", {a:1} );
// you can also delete the template from cache
delete jqtpl.template["templateName"];
// output
<div>1</div>
### Local variables
- `$data` - data object passed to render method
- `$item` - contains $data via $item.data as well as user options - an optional map of user-defined key-value pairs.
Examples:
// tpl
<div>${ $item.someMethod() }</div>
// code
jqtpl.tmpl( tpl, {a:1}, {
someMethod: function(){ return 1; }
});
//output
<div>1</div>
## Tags
### ${} - simple output (escaped per default)
// tpl
<div>${a}</div>
// code
jqtpl.tmpl( tpl, {a:123});
// output
<div>123</div>
### ${} - simple output but with array as data argument (escaped per default)
//tpl
<div>${a}</div>
// code
jqtpl.tmpl( tpl, [{a:1},{a:2},{a:3}]);
// output
<div>1</div><div>2</div><div>3</div>
### ${} - if property is a function - it will be called automatically (escaped per default)
// tpl
<div>${a}</div>
// code
jqtpl.tmpl( tpl, {
a:function() {
return 1 + 5;
}
});
//output
<div>6</div>
### {{if}} and {{else}}

@@ -137,3 +66,3 @@

// code
jqtpl.tmpl( tpl, {a:6});
jqtpl.render(tpl, {a:6});

@@ -144,3 +73,3 @@ // output

// code
jqtpl.tmpl( tpl, {a:5});
jqtpl.render(tpl, {a:5});

@@ -153,3 +82,3 @@ // output

// tpl
{{each(i, name) names}}
{{each(name, i) names}}
<div>${i}.${name}</div>

@@ -159,3 +88,2 @@ {{/each}}

// alternative syntax
{{each names}}

@@ -166,3 +94,3 @@ <div>${$index}.${$value}</div>

// code
jqtpl.tmpl( tpl, {names: ["A", "B"]});
jqtpl.render(tpl, {names: ['A', 'B']});

@@ -172,3 +100,3 @@ // output

### {{html}} - there is a way to avoid escaping if you know what you do :)
### {{html}} - print unescaped html.

@@ -179,3 +107,3 @@ // tpl

// code
jqtpl.tmpl( tpl, {a:'<div id="123">2</div>'});
jqtpl.render(tpl, {a:'<div id="123">2</div>'});

@@ -192,3 +120,3 @@ // output

// code
jqtpl.tmpl( tpl );
jqtpl.render(tpl);

@@ -198,11 +126,15 @@ // output

### {{tmpl}} - subtemplates.
### {{partial}} - subtemplates.
Note: passing json object with 2 curly brackets without any separation will break the engine: {{tmpl({a: {b: 1}}) "mypartial"}}
Render subtemplates by passing a template string, template name or file name (serverside).
**Note: passing json object with 2 curly brackets without any separation will break the engine: {{partial({a: {b: 1}}) 'mypartial'}}**
// tpl
<div>{{tmpl({name: "Test"}) '${name}'}}</div>
<div>{{partial({name: 'Test'}) '${name}'}}</div>
<div>{{partial 'myTemplate'}}</div>
<div>{{partial 'myTemplate.html'}}</div>
// code
jqtpl.tmpl(tpl);
jqtpl.render(tpl);

@@ -212,14 +144,15 @@ // output

# Not jquery-tmpl compatible stuff
## Specific tags
### {{verbatim}} tag
If you want to skip a part of your template, which should be rendered on the client, you can use now verbatim tag.
Skip a part of your template - leave it in original on the same place but without "verbatim" tag. If you render the result as a template again - it will be rendered.
The use case is to be able to render the same template partially on the server and on the client. F.e. a layout template can contain variables which needs to be rendered on the server and templates which need to be rendered on the client.
// mytemplate.html
<div>my name is ${name}</div>
{{verbatim}}
<script id="my-template">
<div>your name is ${userName}</div>
</script>
{{/verbatim}}

@@ -232,72 +165,68 @@

<div>my name is Kof</div>
<div>your name is ${userName}</div>
<script id="my-template">
<div>your name is ${userName}</div>
</script>
## Express specific stuff
## Engine API
**Note: express is caching all templates in production!**
### require the module
var jqtpl = require('jqtpl');
### Usage
### jqtpl.render(markup, [data]);
app.set("view engine", "html");
app.register(".html", require("jqtpl").express);
Compile and render a template. It uses `jqtpl.template` method. Returns a rendered html string.
### {{partial}} tag
- `markup` html code or precompiled template name.
- `data` optional object or array of data.
Read express documentation here http://expressjs.com/guide.html#res.partial()
### jqtpl.compile(markup, [name])
// tpl
Compile and cache a template string. Returns a `render` function which can be called to render the template, see `jtpl.render`.
// myaction.html
<div>{{partial(test) "mypartial"}}</div>
- `markup` html string.
- `name` optional template name, if no name is passed - markup string will be used as a name.
// mypartial.html
${name}
// tpl
<div>${a}</div>
// code
app.get('/myaction', function(req, res) {
res.render('myaction', {test: {name: 'Test'}});
})
// code
// output
<div>Test</div>
// precompile an cache it
jqtpl.compile(tpl, 'myTemplate');
Using array of data:
// render user a name
jqtpl.render('myTemplate', {a:1});
// tpl
// delete the template from cache
delete jqtpl.cache['myTemplate'];
// myaction.html
<div id="main">
{{partial(test) "mypartial"}}
</div>
// output
<div>1</div>
// mypartial.html
<div class="partial">
${name}
</div>
### jqtpl.cache
// code
app.get('/myaction', function(req, res) {
res.render('myaction', {
as: global,
test: [
{name: "Test1"},
{name: "Test2"}
]
});
})
A map of compiled templates.
// output
<div id="main">
<div class="partial">Test1</div>
<div class="partial">Test2</div>
</div>
- `key` - template name or markup string.
- `value` - compiled template function.
### jqtpl.$
A namespace for global helper functions, which can be used in every template.
## Express specific stuff
**Note: express will cache all templates in production!**
### Usage
app.set('views', '/path/to/the/views/dir');
app.set('view engine', 'html');
app.engine('html', require('jqtpl').__express);
### {{layout}} tag
Using layout tag in a view it is possible to define a layout within this view.
Note: it is possible since express@2.2.1.
// tpl
// mylayout.html

@@ -309,8 +238,16 @@ <html>

// myview.html
{{layout "mylayout"}}
<div>myview</div>
{{layout 'mylayout'}}
<div>myview</div>
// myview1.html
{{layout({a: 1}) 'mylayout'}}
<div>myview1</div>
// output
<html>
<div>myview</div>
<div>myview</div>
</html>
## Licence
See package.json
var express = require('express'),
_ = require('underscore'),
request = require('request');
request = require('request'),
fs = require('fs');
var server,
options;
var options;

@@ -15,10 +15,19 @@ options = {

options.express = {
views: options.root + '/1',
'view engine': 'html',
'view options': {layout: false}
};
var views = options.root + '/1';
server = createServer();
function create() {
var app = express();
app.engine('html', render);
app.set('views', views);
app.set('view engine', 'html');
app.use(express.bodyParser());
app.post('/*', function(req, res){
res.render(req.url.substr(1), req.body);
});
app.listen(options.port);
return app;
}
function post(path, data, callback) {

@@ -29,2 +38,3 @@ if (!callback) {

}
request({

@@ -36,3 +46,4 @@ method: 'post',

if (err) {
throw new Error(err);
console.error(err);
equal(err, null, 'Request errored.');
}

@@ -44,24 +55,4 @@

function createServer(opts) {
var server = express.createServer(express.bodyParser()),
eo = _.defaults(opts || {}, options.express);
var app = create();
_.each(eo, function(val, name) {
server.set(name, val);
});
// qunit copies jqtpl.express exports to global
server.register('.html', global);
server.post('/*', function(req, res){
if (req.body) {
req.body.as = global;
}
res.render(req.url.substr(1), req.body);
});
server.listen(options.port);
return server;
}
test("locals", function() {

@@ -76,26 +67,3 @@ expect(1);

test("scope option", function() {
var fn = compile( "<div>${this.test}</div>", {scope: {test: 123}} );
same(fn({a:1}), '<div>123</div>', "scope is correct");
});
test("debug option", function() {
var printed,
util = require( "util" ),
debug = util.debug;
// mock print method
util.debug = function( str ) {
printed = true;
};
compile( 'test', {debug: true} )();
// restore orig. print function
util.debug = debug;
ok( printed, "debug option works" );
});
test("partials using `partial`", function() {
test("partials", function() {
expect(1);

@@ -109,3 +77,3 @@ stop();

test("partials using `partial`", function() {
test("partials 2", function() {
expect(1);

@@ -126,56 +94,58 @@ stop();

test("layout tag", function() {
var html = 'mylayout requested view mylayout';
expect(2);
test('render template with a layout', function() {
expect(1);
stop();
post('/layouttest', function(data) {
equal(data, html, 'served html is correct');
post('/layouttest', function(data) {
ok(data, html, 'if caching is turned, second call should work too #46');
start();
});
app.set('view options', {layout: true});
app.set('views', options.root + '/2');
post('/views/test', {mylocal: "mylocal"}, function(data) {
equal(data, 'abc mylocal', 'template and layout rendered correctly');
app.disable('view options');
app.set('views', views);
start();
});
});
test("rendering multiple times of the same template #29", function() {
var template = 'Just example ${example}'
var je = require('../').express
var render = je.compile(template, {filename: 'example.html'})
test("render multiple times the same template #29", function() {
var data;
equal(render({example: 'Hello'}), 'Just example Hello', 'template rendered correctly');
equal(render({example: 'Hello'}), 'Just example Hello', 'template rendered correctly');
data = {
a: 'Hello',
settings: {
'view options': {}
}
};
equal(render(views + '/view.html', data), '<div>Hello</div>', 'template rendered correctly');
equal(render(views + '/view.html', data), '<div>Hello</div>', 'template rendered correctly 2');
equal(render(views + '/view.html', data), '<div>Hello</div>', 'template rendered correctly 3');
});
test("clean cache if template have to be recompiled", function() {
var je = require('../').express
test("template recompiled if cache disabled", function() {
var data,
view = views + '/view.html';
var template = 'my template 1';
var render = je.compile(template, {filename: 'template.html'});
equal(render(), 'my template 1', 'template 1 rendered correctly');
// now template has been changed
template = 'my template 2';
render = je.compile(template, {filename: 'template.html'})
equal(render(), 'my template 2', 'template 2 rendered correctly after recompile');
data = {
a: 'Hello',
settings: {
'view options': {}
}
};
equal(render(view, data), '<div>Hello</div>', 'template rendered correctly');
fs.writeFileSync(view, 'new template ${a}');
equal(render(view, data), 'new template Hello', 'template was recompiled');
fs.writeFileSync(view, '<div>${a}</div>');
});
test("rendering template with a layout turned on", function() {
expect(1);
test("layout tag", function() {
var html = 'mylayout requested view mylayout';
expect(2);
stop();
server.close();
server = createServer({
'view options': {layout: true},
views: options.root + '/2'
post('/layouttest', function(data) {
equal(data, html, 'layout rendered correctly');
post('/layouttest', function(data) {
equal(data, html, 'if caching is turned on, second call should work too #46');
start();
});
});
post('/views/test', {mylocal: "mylocal"}, function(data) {
equal(data, 'abc mylocal', 'template and layout rendered correctly');
server.close();
server = createServer();
start();
});
});

@@ -1,78 +0,194 @@

QUnit.module('jqtpl');
test('Variables ${}, {{=}}', function() {
equal(render('lorem ipsum'), 'lorem ipsum', 'plain text passes through untouched');
equal(render('${ a }', {a: 1}), '1', 'simple variable output');
equal(render(''), '', 'empty template string rendered without errors');
equal(render('{{}}'), '{{}}', 'empty tag');
equal(render('{{\t\t}}'), '{{\t\t}}', 'empty tag with tabs whitespace');
equal(render('<div>${a}/${a}</div>', {a:1}), '<div>1/1</div>', 'many variables');
equal(render('<div>{{= a}}</div>', {a:1}), '<div>1</div>', 'use simple data object, using {{= }} in the template ');
equal(render('<div>${a}</div>', [{a:1}]), '<div>1</div>', 'use an array with one object element');
equal(render('<div>{{= a}}</div>', [{a:1}]), '<div>1</div>', 'use an array with one object element, using {{= }} in the template');
equal(render('<div>${a}</div>', [{a:1},{a:2}]), '<div>1</div><div>2</div>', 'use an array with 2 objects');
equal(render('<div>${a}</div>', {a: function(){return 1}}), '<div>1</div>', 'use function as a value');
equal(render('${ "string" }'), 'string', 'basic string output (double)');
equal(render("${ 'string' }"), 'string', 'basic string output (single)');
equal(render('${ isUndefined }'), '', 'variable lookup error suppression');
var tpl1 = "<div>${a}</div>",
tpl2 = "<div>{{= a}}</div>",
tpl3 = "<div>${$data.a}</div>",
tpl4 = "<div>${$item.data.a}</div>",
tpl5 = "<div>${$item.someFunction()}</div>",
tpl6 = "{{html a}}",
tpl9 = "{{if a == 1}}<div>${a}</div>{{/if}}",
tpl11 = "{{if a == 1}}<div>${a}</div>{{else}}2{{/if}}",
tpl12 = "{{if a == 1}}<div>${a}</div>{{else a==2 }}2{{else}}3{{/if}}";
equal(render('A${ a }', {a: 1}), 'A1', 'variable and text (1)');
equal(render('${ a }B', {a: 1}), '1B', 'variable and text (2)');
equal(render('A${ a }B', {a: 1}), 'A1B', 'variable and text (3)');
test('method "template"', function() {
equal( typeof template("test", tpl1), "function", "precompile template and cache using template name" );
equal( tmpl("test", {a:1}), "<div>1</div>", "render using template name" );
ok( delete template["test"], "remove cache item" );
equal(render('${ a.b.c }', {a:{b:{c:'abc'}}}), 'abc', 'lookups work for submembers');
equal(render('<div>${a()}</div>', {a: function(){return 1}}), '<div>1</div>', 'function can be called within tag');
equal(render('<div>${a("aaa")}</div>', {a: function(arg){return arg}}), '<div>aaa</div>', 'functions pass strings correctly');
equal(render('<div>${a(aaa)}</div>', {a: function(arg){return arg}, aaa: 123}), '<div>123</div>', 'functions pass arguments correctly');
equal(
render('${ foo }', {
foo: {
toString: function () {return 'S';},
toValue:function () {return 'V';}
}
}),
'S',
'variables use toString, not toValue'
);
equal(render('${ dot,dot,comma,dash }', {dot:'.','comma':',','dash':'-'}), '-', 'Comma passes variables correctly.');
equal(render('${ fun }', {fun: function() {return 123;}}), 123, 'variable gets called if it is callable');
equal(render('${ obj.fun }', {obj: {fun: function() {return 123;}}}), 123, 'last variable in sequence gets called if it is callable');
equal(
render('${ foo.bar }', {
foo: function() {
return { bar: function () {return 'BAZ'; } };
}
}),
'',
'member functions in a sequence do not get called'
);
// FIXME
// equal(render('${ "str\\"i\\"ng" }'), 'str"i"ng', 'string quote escapes (double)');
// equal(render("${ 'str\\'i\\'ng' }"), "str'i'ng", 'string quote escapes (single)');
// equal(render('{{ }}'), '{{ }}', 'empty tag with whitespace');
// equal(render('${ isUndefined.member }'), '', 'variable lookup error suppression (with member)');
});
test('escaping', function() {
equal(tmpl("${ 'foo<div>bar</div>baz' }"), 'foo&lt;div&gt;bar&lt;/div&gt;baz', 'echoing escapes html');
equal(tmpl("${ r }", {r:'foo<div>bar</div>baz'}), 'foo&lt;div&gt;bar&lt;/div&gt;baz', 'echoing escapes html (lookup)');
equal(tmpl("${ '&' }"), '&amp;', 'echoing escapes ampersands 1');
equal(tmpl("${ '&amp;' }"), '&amp;amp;', 'echoing escapes ampersands 2');
equal(tmpl("${ '-<&>-<&>-' }"), '-&lt;&amp;&gt;-&lt;&amp;&gt;-', 'echoing escapes & < >');
test("Falsy values", function() {
equal(render('${ 0 }'), '0', '0');
equal(render('${ false }'), 'false', 'false');
equal(render('${ null }'), '', 'null');
equal(render('${ undefined }'), '', 'undefined');
equal(render("${ '' }"), '', 'empty string');
equal(render('${ "" }'), '', 'empty string 2');
});
test('${}', function() {
equal( tmpl(tpl1, {a:1}), "<div>1</div>", "use simple data object" );
equal( tmpl(tpl1,{a:'<div id="123">2</div>'}), "<div>&lt;div id=&quot;123&quot;&gt;2&lt;/div&gt;</div>", "escaping per default" );
equal( tmpl(tpl2, {a:1}), "<div>1</div>", "use simple data object, using {{= }} in the template " );
equal( tmpl(tpl1, [{a:1}]), "<div>1</div>", "use an array with one object element" );
equal( tmpl(tpl2, [{a:1}]), "<div>1</div>", "use an array with one object element, using {{= }} in the template" );
equal( tmpl(tpl1, [{a:1},{a:2}]), "<div>1</div><div>2</div>", "use an array with 2 objects" );
equal( tmpl(tpl1, {a: function(){return 1}}), "<div>1</div>", "use function as a value" );
})
test("Falsy lookups", function() {
equal(render('${ zero }', {zero: 0}), '0', '0');
equal(render('${ zero }', {zero: false}), 'false', 'false');
equal(render('${ zero }', {zero: null}), '', 'null');
equal(render('${ zero }', {zero: undefined}), '', 'undefined');
equal(render("${ zero }", {zero: ''}), '', 'empty string');
});
test('local variables', function() {
equal( tmpl(tpl3, {a:1}), "<div>1</div>", "test access to $data" );
equal( tmpl(tpl4, {a:1}), "<div>1</div>", "test access to $item" );
equal( tmpl(tpl5, null, {someFunction: function() {return 1}}), "<div>1</div>", "test access to $item" );
test("Javascript operations", function() {
equal(render('${ one + "foo" }', {one: 'first'}), 'firstfoo', 'string concatination');
equal(render('${ 1 + 5 }'), '6', 'adding');
equal(render('${ 9 - 5 }'), '4', 'subtracting');
equal(render('${ 5 % 2 }'), '1', 'modulo');
equal(render('${ -n }', {n:10}), '-10', 'unary minus');
equal(render('${ +n }', {n:"10"}), '10', 'unary plus');
equal(render('${ "bar" in foo }', {foo:{bar:'baz'}}), 'true', 'in operator');
equal(render('${ foo instanceof Date }', {foo:new Date()}), 'true', 'instanceof operator');
equal(render('${ typeof "str" }'), 'string', 'typeof operator');
equal(render('${ n & 1 }', {n:5}), '1', 'bitwise AND');
equal(render('${ n | 1 }', {n:4}), '5', 'bitwise OR');
equal(render('${ n ^ 1 }', {n:5}), '4', 'bitwise XOR');
equal(render('${ ~n }', {n:5}), '-6', 'bitwise NOT');
equal(render('${ n << 1 }', {n:5}), '10', 'left shift');
equal(render('${ n >> 1 }', {n:5}), '2', 'right shift');
equal(render('${ n >>> 1 }', {n:5}), '2', 'zero-fill right shift');
equal(render('${ 1 == 5 }'), 'false', 'comparing ==');
equal(render('${ 1 != 5 }'), 'true', 'comparing !=');
equal(render('${ 5 === 5 }'), 'true', 'comparing ===');
equal(render('${ 5 !== 5 }'), 'false', 'comparing !==');
equal(render('${ 1 >= 5 }'), 'false', 'comparing >=');
equal(render('${ 1 > 5 }'), 'false', 'comparing >');
equal(render('${ 1 <= 5 }'), 'true', 'comparing <=');
equal(render('${ 1 < 5 }'), 'true', 'comparing <');
equal(render('${ zero || "FALSY" }', {zero: 0}), 'FALSY', 'Logical OR');
equal(render('${ zero && "TRUEY" }', {zero: 1}), 'TRUEY', 'Logical AND');
equal(render('${ zero ? "zero" : "other" }', {zero: 1}), 'zero', 'Conditional Operator');
equal(render('${ !zero }', {zero: 1}), 'false', 'Unary logical NOT');
equal(render("${ 'test' }"), 'test', 'Single-Quoted Strings');
equal(render("${ 'test' == testvar }", { testvar: 'test' }), 'true', 'Single-Quoted Comparison');
});
var testData = {},
out;
function R(a, b) {
out = "equal(render('" + a + "'), ";
}
function test_handler(msg, actual, expected) {
out += "'" + expected + "', '" + msg + "');";
console.log(out);
}
/*
FIXME
test("Disallowed / illegal", function() {
equal(render('${ a += 1 }', {a: 1}), SyntaxError, 'Disallow incremental assignment');
equal(render('${ a -= 1 }', {a: 1}), SyntaxError, 'Disallow decremental assignment');
equal(render('${ a *= 1 }', {a: 1}), SyntaxError, 'Disallow multiply assignment');
equal(render('${ a /= 1 }', {a: 1}), SyntaxError, 'Disallow division assignment');
equal(render('${ a <<= 1 }', {a: 1}), SyntaxError, 'Disallow left shift assignment');
equal(render('${ a >>= 1 }', {a: 1}), SyntaxError, 'Disallow right shift assignment');
equal(render('${ a >>>= 1 }', {a: 1}), SyntaxError, 'Disallow zero-fill right shift assignment');
equal(render('${ a &= 1 }', {a: 1}), SyntaxError, 'Disallow bitwise AND assignment');
equal(render('${ a |= 1 }', {a: 1}), SyntaxError, 'Disallow bitwise OR assignment');
equal(render('${ a ^= 1 }', {a: 1}), SyntaxError, 'Disallow bitwise XOR assignment');
equal(render('${ { a:"a"} }', {a: 1}), SyntaxError, 'Disallow literal object creation');
equal(render('${ [1,2,3] }', {a: 1}), SyntaxError, 'Disallow literal array creation');
equal(render('${ --a }', {a: 1}), SyntaxError, 'Disallow decrement');
equal(render('${ (a = 2) }', {a: 1}), SyntaxError, 'Disallow assignments');
});
*/
test("Bracketed accessors", function() {
equal(render('${ foo["bar"] }',{foo:{bar:'baz'}}), 'baz', 'foo["bar"]');
equal(render("${ foo['bar'] }",{foo:{bar:'baz'}}), 'baz', "foo['bar']");
});
test('${html}', function() {
equal( tmpl(tpl6,{a:'<div id="123">2</div>'}), '<div id="123">2</div>', 'output html without escaping');
equal(
render('{{html a}}', {a:'<div id="123">2</div>'}),
'<div id="123">2</div>',
'output html without escaping'
);
});
test('${if}', function() {
equal( tmpl(tpl9,{a:1}), "<div>1</div>", "test 'if' when true" );
equal( tmpl(tpl9,{a:2}), "", "test 'if' when false" );
test('{{if}} {{else}}', function() {
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: true}), 'TRUE', 'if:true');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: false}), 'FALSE', 'if:false');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: null}), 'FALSE', 'if:null');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: undefined}), 'FALSE', 'if:undefined');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: {}}), 'TRUE', 'if:[]');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: []}), 'TRUE', 'if:{}');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: ''}), 'FALSE', 'if:""');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: 'A'}), 'TRUE', 'if:A');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: 0}), 'FALSE', 'if:0');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if}}', {a: 1}), 'TRUE', 'if:1');
equal(render('{{if a}}TRUE{{else}}FALSE{{/if a}}', {a: 1}), 'TRUE', '/if ignores following text');
});
test('{else}', function() {
equal( tmpl(tpl11,{a:1}), "<div>1</div>", "test else when true" );
equal( tmpl(tpl11,{a:2}), "2", "test else when false" );
equal( tmpl(tpl12,{a:2}), "2", "test else =2" );
equal( tmpl(tpl12,{a:3}), "3", "test else =3" );
test("Incorrect nesting", function() {
throws(function() { render('{{if 1}}{{if 1}}{{/if}}') }, SyntaxError, 'defaut');
throws(function() { render('{{if 1}}{{/if}}{{/if}}') }, SyntaxError, 'extra /if');
throws(function() { render('{{if 1}}{{each arr}}{{/if}}{{/each}}', {arr: []}) }, SyntaxError, 'but terminated');
});
test('{{each}}', function() {
equal(
tmpl(
"{{each(index, value) names}}<div>${index}.${value}</div>{{/each}}",
{names: ["A", "B"]}
),
"<div>0.A</div><div>1.B</div>", "test 'each', use index and value, explizitely mapping them "
);
render(
'{{each(value, index) names}}<div>${index}.${value}</div>{{/each}}',
{names: ['A', 'B']}
),
'<div>0.A</div><div>1.B</div>', 'test "each", use index and value, explizitely mapping them '
);
equal(
tmpl(
"{{each names}}<div>${$index}.${$value}</div>{{/each}}",
{names: ["A", "B"]}
),
"<div>0.A</div><div>1.B</div>", "test 'each', use index and name with auto mapping"
);
render(
'{{each names}}<div>${$index}.${$value}</div>{{/each}}',
{names: ['A', 'B']}
),
'<div>0.A</div><div>1.B</div>', 'test "each", use index and name with auto mapping'
);
equal(
tmpl(
"{{each $item.getData()}}<div>${$value}</div>{{/each}}",
null,
render(
'{{each getData()}}<div>${$value}</div>{{/each}}',
{

@@ -83,105 +199,141 @@ getData: function(){

}
),
"<div>1</div><div>2</div><div>3</div>", "test 'each', using templates variables"
);
),
'<div>1</div><div>2</div><div>3</div>', 'test "each", using template variables'
);
equal(
tmpl(
"{{each data }}<div>${$value}</div>{{/each}}",
render(
'{{each data }}<div>${$value}</div>{{/each}}',
{
data: {1:1, 2:2, 3:3}
}
),
"<div>1</div><div>2</div><div>3</div>",
"iterate over json in each loop"
);
),
'<div>1</div><div>2</div><div>3</div>',
'iterate over json in each loop'
);
});
test('{{partial}}', function() {
compile('${ "test text" }', 'test');
equal(render('{{partial "test"}}'), 'test text', 'rendered partial from cache');
test('{{tmpl}}', function() {
compile('{{partial "test" }', 'nested');
equal(render('{{partial "nested"}}'), 'nested test text', 'rendered nested partial from cache');
equal(
tmpl(
"{{tmpl(data) extTpl}}",
render(
'{{partial(data) extTpl}}',
{
extTpl: "<div>${a}</div>",
extTpl: '<div>${a}</div>',
data: {a:123456}
}
),
"<div>123456</div>",
"include template {{tmpl}} and pass data object"
);
),
'<div>123456</div>',
'include template {{tmpl}} and pass data object'
);
equal(
tmpl(
"{{tmpl(data) extTpl}}",
render(
'{{partial(data) extTpl}}',
{
extTpl: "<div>${a}</div>",
extTpl: '<div>${a}</div>',
data: [{a:1}, {a:2}]
}
),
"<div>1</div><div>2</div>",
"include template {{tmpl}} and pass data array"
);
),
'<div>1</div><div>2</div>',
'include template {{tmpl}} and pass data array'
);
});
test('{{!}}', function() {
equal( tmpl("<div>{{! its a comment}}</div>", {a:1}), "<div></div>", "comments work" );
});
equal(render('A{{! its a comment}}B'), 'AB', 'comments are removed');
equal(render('{{! inky }}foo{{! blinky }}'), 'foo', 'comments are removed 2');
test('empty template', function() {
try {
equal(tmpl(''), '', 'empty template string rendered without errors');
} catch(e) {
ok(false, 'empty template shouldn\'t throw errors');
}
// FIXME
// equal(render('A{{! comments "}}" test }}B'), 'AB', 'comments may include string of comments');
// equal(render('A{# C{# E #}D #}B'), 'AD #}B', 'comments cannot nest other comments');
// test_handler( "comments may include strings with escapes (double)", R('A{# comments "str\"ing" test #}B', testData), "AB" );
// test_handler( "comments may include strings with escapes (single)", R("A{# comments 'str\'ing' test #}B", testData), "AB" );
// test_handler( "comments may include tags", R("A{# {{= v }} #}B", testData), "AB" );
// test_handler( "comments may span lines", R("A{# \ncomments test\n #}B", testData), "AB" );
// test_handler( "comments may contain invalid content (invalid tag)", R('1{{! {{ INVALID_TAG }} }}2', testData), '12' );
// test_handler( "comments may contain invalid content (stray end tag)", R('1{{! {{/if}} }}2', testData), '12' );
// test_handler( "comments may contain invalid content (stray else)", R('1{{! {{else}} }}2', testData), '12' );
// test_handler( "comments may contain invalid content (invalid javascript)", R('1{{! {{if ...}} }}2', testData), '12' );
});
test('preserve whitespaces', function() {
var html;
var html = render("<div>\n{{= [{\tkey: \n'value'\r}] }}\n</div>", {});
try {
html = tmpl(
'<div>\n{{= [{\tkey: \n"value"\r}] }}\n</div>',
{}
);
ok(true, 'no compilation errors');
} catch(err) {
ok(false, err.message);
}
equal(
html,
'<div>\n[object Object]\n</div>',
'whitespaces preserved'
);
"<div>\n[object Object]\n</div>",
"whitespaces preserved"
);
try {
html = tmpl(
'<div>\n{{= someFunction({\tkey: \n"value"\r}) }}\n</div>',
{
someFunction: function(data) {
return 'some text ' + data.key;
}
html = render(
"<div>\n{{= someFunction({\tkey: \n'value'\r}) }}\n</div>",
{
someFunction: function(data) {
return "some text " + data.key;
}
);
ok(true, 'no compilation errors');
} catch(err) {
ok(false, err.message);
}
}
);
equal(
html,
'<div>\nsome text value\n</div>',
'whitespaces preserved'
);
"<div>\nsome text value\n</div>",
"whitespaces preserved"
);
});
test('{{verbatim}}', function() {
test("{{verbatim}}", function() {
equal(
tmpl(
"<div>{{= a}}{{verbatim}}${a}12345{{/verbatim}{{/verbatim}}{{verbatim}}}{{= a}}{{/verbatim}}${a}</div>",
render(
'<div>{{= a}}{{verbatim}}${a}12345{{/verbatim}{{/verbatim}}{{verbatim}}}{{= a}}{{/verbatim}}${a}</div>',
{a:1}
),
"<div>1${a}12345{{/verbatim}}{{= a}}1</div>",
"verbatim"
);
),
'<div>1${a}12345{{/verbatim}}{{= a}}1</div>',
'verbatim'
);
});
test('Error reporting', function() {
throws(function() { render('${ a b c }}'); }, SyntaxError, 'syntax error');
throws(function() { render('${a.b}'); }, ReferenceError, 'reference error');
throws(function() { render('${[]()}'); }, TypeError, 'type error');
});
test('Escaping', function() {
equal(render('${ "foo<div>bar</div>baz" }'), "foo&lt;div&gt;bar&lt;/div&gt;baz", "echoing escapes html");
equal(render('${ r }', {r:"foo<div>bar</div>baz"}), "foo&lt;div&gt;bar&lt;/div&gt;baz", "echoing escapes html (lookup)");
equal(render('${ "&" }'), "&amp;", "echoing escapes ampersands 1");
equal(render('${ "&amp;" }'), "&amp;amp;", "echoing escapes ampersands 2");
equal(render('${ "-<&>-<&>-" }'), "-&lt;&amp;&gt;-&lt;&amp;&gt;-", "echoing escapes & < >");
equal(render('${\n \na\n }', {a: 1}), '1', 'newlines do not kill tags');
equal(render('${ "on\ne" }'), 'one', 'newlines in strings do not kill tags');
equal(render('${\r \r\na\r\n }', {a: 1}), '1', 'returns do not kill tags');
equal(render('${ "on\re" }'), 'one', 'returns in strings do not kill tags');
equal(render('${ "on\\e" }'), 'one', 'slashes in strings do not kill tags');
equal(render('a\nb\nc${ 8 }.'), 'a\nb\nc8.', 'newlines do not kill parsing');
});
test("Ignore malformed tags", function() {
equal(render('a {{one } b'), 'a {{one } b', 'a {{one } b');
equal(render('${ a }} {{b }', {a: '1', b: '1'}), '1} {{b }', '1} {{b }');
equal(render('{{one }'), '{{one }', '{{one }');
});
test("Reserved words", function() {
// FIXME
// throws(function() { render('${ new Object() }'); }, SyntaxError, 'Disallow new operator');
// throws(function() { render('${ delete a }'); }, SyntaxError, 'Disallow delete operator');
throws(function() { render('${ function(){} }'); }, SyntaxError, 'Disallow function operator');
throws(function() { render('${ return a }'); }, SyntaxError, 'Disallow return');
throws(function() { render('${ for a }'); }, SyntaxError, 'Disallow for');
throws(function() { render('${ do{ a }while(a) }'); }, SyntaxError, 'Disallow do/while');
throws(function() { render('${ if a }'); }, SyntaxError, 'Disallow if');
throws(function() { render('${ try{b.s}catch(e){} }'); }, SyntaxError, 'Disallow try/catch');
throws(function() { render('${ with (s) }'); }, SyntaxError, 'Disallow with keyword');
throws(function() { render('${ throw "foo" }'); }, SyntaxError, 'Disallow throw keyword');
});

Sorry, the diff of this file is not supported yet

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