Skip to content
This repository has been archived by the owner on Apr 11, 2018. It is now read-only.

Commit

Permalink
Move escape functions to filters file so they can be overridden.
Browse files Browse the repository at this point in the history
closes gh-19
  • Loading branch information
paularmstrong committed Oct 4, 2011
1 parent 7fb4bf8 commit 33842c4
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 58 deletions.
6 changes: 3 additions & 3 deletions index.js
Expand Up @@ -60,7 +60,7 @@ function createTemplate(data, id) {
code = parser.compile.call(template);

// The compiled render function - this is all we need
render = new Function('__context', '__parents', '__filters', '__escape', '_', [
render = new Function('__context', '__parents', '__filters', '_', [
'__parents = __parents ? __parents.slice() : [];',
// Prevents circular includes (which will crash node without warning)
'var j = __parents.length,',
Expand All @@ -80,10 +80,10 @@ function createTemplate(data, id) {

template.render = function (context, parents) {
if (config.allowErrors) {
return render.call(this, context, parents, config.filters, helpers.escaper, _);
return render.call(this, context, parents, config.filters, _);
} else {
try {
return render.call(this, context, parents, config.filters, helpers.escaper, _);
return render.call(this, context, parents, config.filters, _);
} catch (e) {
return new TemplateError(e);
}
Expand Down
40 changes: 40 additions & 0 deletions lib/filters.js
Expand Up @@ -63,6 +63,46 @@ exports.default = function (input, def) {
return (typeof input !== 'undefined' && (input || typeof input === 'number')) ? input : def;
};

exports.escape = exports.e = function (input, type) {
type = type || 'html';
if (typeof input === 'string') {
if (type === 'js') {
var i = 0,
code,
out = '';

input = input.replace(/\\/g, '\\u005C');

for (; i < input.length; i += 1) {
code = input.charCodeAt(i);
if (code < 32) {
code = code.toString(16).toUpperCase();
code = (code.length < 2) ? '0' + code : code;
out += '\\u00' + code;
} else {
out += input[i];
}
}

return out.replace(/&/g, '\\u0026')
.replace(/</g, '\\u003C')
.replace(/>/g, '\\u003E')
.replace(/\'/g, '\\u0027')
.replace(/"/g, '\\u0022')
.replace(/\=/g, '\\u003D')
.replace(/-/g, '\\u002D')
.replace(/;/g, '\\u003B');
}
return input.replace(/&(?!amp;|lt;|gt;|quot;|#39;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
} else {
return input;
}
};

exports.first = function (input) {
if (typeof input === 'object' && !Array.isArray(input)) {
return '';
Expand Down
52 changes: 6 additions & 46 deletions lib/helpers.js
Expand Up @@ -113,10 +113,10 @@ exports.check = check;
* Returns an escaped string (safe for evaling). If context is passed
* then returns a concatenation of context and the escaped variable name.
*/
exports.escape = function (variable, context) {
exports.escapeVarName = function (variable, context) {
if (Array.isArray(variable)) {
_.each(variable, function (val, key) {
variable[key] = exports.escape(val, context);
variable[key] = exports.escapeVarName(val, context);
});
return variable;
}
Expand All @@ -137,46 +137,6 @@ exports.escape = function (variable, context) {
return chain.replace(/\n/g, '\\n').replace(/\r/g, '\\r');
};

exports.escaper = function (input, type) {
type = type || 'html';
if (typeof input === 'string') {
if (type === 'js') {
var i = 0,
code,
out = '';

input = input.replace(/\\/g, '\\u005C');

for (; i < input.length; i += 1) {
code = input.charCodeAt(i);
if (code < 32) {
code = code.toString(16).toUpperCase();
code = (code.length < 2) ? '0' + code : code;
out += '\\u00' + code;
} else {
out += input[i];
}
}

return out.replace(/&/g, '\\u0026')
.replace(/</g, '\\u003C')
.replace(/>/g, '\\u003E')
.replace(/\'/g, '\\u0027')
.replace(/"/g, '\\u0022')
.replace(/\=/g, '\\u003D')
.replace(/-/g, '\\u002D')
.replace(/;/g, '\\u003B');
}
return input.replace(/&(?!amp;|lt;|gt;|quot;|#39;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
} else {
return input;
}
};

exports.wrapFilter = function (variable, filter) {
var output = '(function () {',
args;
Expand Down Expand Up @@ -215,7 +175,7 @@ exports.wrapFilter = function (variable, filter) {
};

exports.wrapFilters = function (variable, filters, context, escape) {
var output = exports.escape(variable, context);
var output = exports.escapeVarName(variable, context);

if (filters && filters.length > 0) {
filters.forEach(function (filter) {
Expand All @@ -236,7 +196,7 @@ exports.wrapFilters = function (variable, filters, context, escape) {

output = output || '""';
if (escape) {
output = '__escape.apply(this, [' + output + ', \'' + escape + '\'])';
output = '__filters.escape.apply(this, [' + output + ', \'' + escape + '\'])';
}

return output;
Expand All @@ -245,9 +205,9 @@ exports.wrapFilters = function (variable, filters, context, escape) {
exports.setVar = function (varName, argument) {
var out = 'var ' + varName + ' = "";' +
'if (' + check(argument.name) + ') {' +
' ' + varName + ' = ' + exports.wrapFilters(exports.escape(argument.name), argument.filters, null, argument.escape) + ';' +
' ' + varName + ' = ' + exports.wrapFilters(exports.escapeVarName(argument.name), argument.filters, null, argument.escape) + ';' +
'} else if (' + check(argument.name, '__context') + ') {' +
' ' + varName + ' = ' + exports.wrapFilters(exports.escape(argument.name), argument.filters, '__context', argument.escape) + ';' +
' ' + varName + ' = ' + exports.wrapFilters(exports.escapeVarName(argument.name), argument.filters, '__context', argument.escape) + ';' +
'}';

if (argument.filters.length) {
Expand Down
6 changes: 3 additions & 3 deletions lib/tags.js
Expand Up @@ -207,7 +207,7 @@ exports['for'] = function (indent) {

return [
'(function () {',
' var ' + helpers.escape(operand1) + ',',
' var ' + helpers.escapeVarName(operand1) + ',',
' forloop = {};',
helpers.setVar('__forloopIter', operand2),
' else {',
Expand All @@ -220,7 +220,7 @@ exports['for'] = function (indent) {
' forloop.key = __forloopIndex;',
' forloop.first = (__forloopIndex === 0);',
' forloop.last = (__forloopIndex === __forloopLength - 1);',
' ' + helpers.escape(operand1) + ' = __forloopIter[__forloopIndex];',
' ' + helpers.escapeVarName(operand1) + ' = __forloopIter[__forloopIndex];',
' ' + parser.compile.call(this, indent + ' '),
' }',
' } else if (typeof __forloopIter === "object") {',
Expand All @@ -233,7 +233,7 @@ exports['for'] = function (indent) {
' forloop.key = __forloopKey;',
' forloop.first = (__forloopIndex === 0);',
' forloop.last = (__forloopIndex === __forloopLength - 1);',
' ' + helpers.escape(operand1) + ' = __forloopIter[__forloopKey];',
' ' + helpers.escapeVarName(operand1) + ' = __forloopIter[__forloopKey];',
' ' + parser.compile.call(this, indent + ' '),
' __forloopIndex += 1;',
' }',
Expand Down
6 changes: 0 additions & 6 deletions tests/helpers.test.js
Expand Up @@ -59,9 +59,3 @@ exports.isValidBlockName = function (test) {

test.done();
};

exports.escaper = function (test) {
test.strictEqual(helpers.escaper('hi<foo> & "bar" \'baz\''), 'hi&lt;foo&gt; &amp; &quot;bar&quot; &#39;baz&#39;', 'escape input');
test.strictEqual(helpers.escaper('hi&lt;foo&gt; &amp; &quot;bar&quot; &#39;baz&#39;'), 'hi&lt;foo&gt; &amp; &quot;bar&quot; &#39;baz&#39;', 'input is not double-escaped');
test.done();
};

0 comments on commit 33842c4

Please sign in to comment.