Permalink
Browse files

Cleaned + Implemented half of default filters.

  • Loading branch information...
1 parent 4900633 commit 177519a09e5995ba22e8adc109f2140639f2d10b Anders Hellerup Madsen committed Dec 12, 2009
File renamed without changes.
@@ -1,10 +1,9 @@
/*jslint laxbreak: true, eqeqeq: true, undef: true, regexp: false */
/*global require, process, exports */
-
var sys = require('sys');
+var utils = require('../utils/utils');
var template_defaults = require('./template_defaults');
-
/***************** TOKENIZER ******************************/
function tokenize(input) {
@@ -297,23 +296,15 @@ exports.parse = function (input) {
// TODO: Make this a property on a token class
function split_token(input) {
- var re = /([^\s"]*"(?:[^"\\]*(?:\\.[^"\\]*)*)"\S*|[^\s']*'(?:[^'\\]*(?:\\.[^'\\]*)*)'\S*|\S+)/g,
- out = [],
- m = false;
-
- while (m = re.exec(input)) {
- out.push(m[0]);
- }
- return out;
+ return utils.string.smart_split(input);
}
-
exports.split_token = split_token;
+// TODO: Node lists are always created by the Parser class, so it could extend the list with this method.
function evaluate_node_list (node_list, context) {
return node_list.reduce( function (p, c) { return p + c(context); }, '');
}
-
exports.evaluate_node_list = evaluate_node_list;
View
@@ -0,0 +1,112 @@
+var sys = require('sys');
+process.mixin(GLOBAL, require('../utils/test').dsl);
+process.mixin(GLOBAL, require('./template'));
+
+testcase('Test tokenizer');
+ test('sanity test', function () {
+ var tokens = tokenize('Hest');
+ assertEquals([{'type': 'text', 'contents': 'Hest'}], tokens);
+ });
+ test('no empty tokens between tags', function () {
+ var tokens = tokenize('{{tag}}');
+ assertEquals( [{type:'variable', contents: 'tag'}], tokens );
+ });
+ test('split token contents', function () {
+ assertEquals(
+ ['virker', 'det', 'her'],
+ split_token(' virker det her ')
+ );
+ assertEquals(
+ ['her', 'er', '"noget der er i qoutes"', 'og', 'noget', 'der', 'ikke', 'er'],
+ split_token('her er "noget der er i qoutes" og noget der ikke er')
+ );
+
+ assertEquals( ['date:"F j, Y"'], split_token('date:"F j, Y"'));
+ assertEquals( ['date:', '"F j, Y"'], split_token('date: "F j, Y"'));
+ });
+
+testcase('Filter Expression tests');
+ test('should parse valid syntax', function () {
+ assertEquals(
+ { variable: 'item', filter_list: [ { name: 'add' } ] },
+ new FilterExpression("item|add")
+ );
+ assertEquals(
+ { variable: 'item.subitem', filter_list: [ { name: 'add' }, { name: 'sub' } ] },
+ new FilterExpression("item.subitem|add|sub")
+ );
+ assertEquals(
+ { variable: 'item', filter_list: [ { name: 'add', arg: 5 }, { name: 'sub', arg: 2 } ] },
+ new FilterExpression('item|add:"5"|sub:"2"')
+ );
+ assertEquals(
+ { variable: 'item', filter_list: [ { name: 'concat', arg: 'heste er naijs' } ] },
+ new FilterExpression('item|concat:"heste er naijs"')
+ );
+ assertEquals(
+ { variable: 'person_name', filter_list: [ ] },
+ new FilterExpression('person_name')
+ );
+ assertEquals(
+ { constant: 335, filter_list: [{name: 'test'}] },
+ new FilterExpression('335|test')
+ );
+ assertEquals(
+ { constant: "hest", filter_list: [{name: 'test'}] },
+ new FilterExpression('"hest"|test')
+ );
+ });
+
+ test('should fail on invalid syntax', function () {
+ function attempt(s) { return new FilterExpression(s); }
+
+ shouldThrow(attempt, 'item |add:"2"');
+ shouldThrow(attempt, 'item| add:"2"');
+ shouldThrow(attempt, 'item|add :"2"');
+ shouldThrow(attempt, 'item|add: "2"');
+ shouldThrow(attempt, 'item|add|:"2"|sub');
+ });
+
+testcase('Context test');
+ setup( function () {
+ var tc = {
+ plain: {
+ a: 5,
+ b: 'hest',
+ c: true,
+ d: [ 1, 2, 3, 4 ]
+ }
+ };
+
+ var clone = JSON.parse( JSON.stringify(tc.plain) );
+ tc.context = new Context(clone);
+
+ return tc;
+ });
+
+ test('test get from first level', function (tc) {
+ for (x in tc.plain) {
+ assertEquals(tc.plain[x], tc.context.get(x));
+ }
+ });
+
+ test('test get string literal', function (tc) {
+ assertEquals(5, tc.context.get('a'));
+ assertEquals('a', tc.context.get("'a'"));
+ assertEquals('a', tc.context.get('"a"'));
+ });
+
+ test('test set', function (tc) {
+ tc.context.set('a', tc.plain.a + 100);
+ assertEquals(tc.plain.a + 100, tc.context.get('a'));
+ });
+
+ test('test push and pop', function (tc) {
+ tc.context.push();
+ assertEquals(tc.plain.a, tc.context.get('a'));
+ tc.context.pop();
+ assertEquals(tc.plain.a, tc.context.get('a'));
+ });
+
+run();
+
@@ -2,11 +2,79 @@
/*global require, process, exports */
var sys = require('sys');
-var template = require('./template_system');
+var template = require('./template');
+var utils = require('../utils/utils');
var filters = exports.filters = {
add: function (value, arg) { return value + arg; },
+ addslashes: function (value, arg) { return utils.string.add_slashes(value.toString()); },
+ capfirst: function (value, arg) { return utils.string.cap_first(value.toString()); },
+ center: function (value, arg) { return utils.string.center(value.toString(), arg); },
+ cut: function (value, arg) { return value.toString().replace(arg, ""); },
+ date: function (value, arg) { return utils.date.date(arg, new Date(value)); },
+ 'default': function (value, arg) { return value ? value : arg; },
+ default_if_none: function (value, arg) { return (value === null || value === undefined) ? arg : value; },
+
+ dictsort: function (value, arg) {
+ var clone = value.slice(0);
+ clone.sort(function (a, b) { return a[arg] < b[arg] ? -1 : a[arg] > b[arg] ? 1 : 0 });
+ return clone;
+ },
+
+ dictsortreversed: function (value, arg) {
+ var tmp = filters.dictsort(value, arg);
+ tmp.reverse();
+ return tmp;
+ },
+ divisibleby: function (value, arg) { return value % arg === 0; },
+
+ escape: function (value, arg) {
+ // TODO: Implement escaping/autoescaping correctly
+ throw "escape() filter is not implemented";
+ },
+ escapejs: function (value, arg) { return escape(value); },
+ filesizeformat: function (value, arg) {
+ var bytes = Number(value);
+ if (isNaN(bytes)) { return "0 bytes"; }
+ if (bytes <= 1) { return '1 byte'; }
+ if (bytes < 1024) { return bytes.toFixed(0) + ' bytes'; }
+ if (bytes < 1024 * 1024) { return (bytes / 1024).toFixed(1) + 'KB'; }
+ if (bytes < 1024 * 1024 * 1024) { return (bytes / (1024 * 1024)).toFixed(1) + 'MB'; }
+ return (bytes / (1024 * 1024 * 1024)).toFixed(1) + 'GB';
+ },
+ first: function (value, arg) { return (value instanceof Array) ? value[0] : ""; },
+ fix_ampersands: function (value, arg) { return value.toString().replace('&', '&amp;'); },
+
+ floatformat: function (value, arg) {
+ var num = Number(value),
+ arg = arg || -1,
+ show_zeores = arg > 0,
+ fix = Math.abs(arg);
+ if (isNaN(num)) {
+ return '';
+ }
+ var s = num.toFixed(fix);
+ if (!show_zeores && Number(s) % 1 === 0) {
+ return num.toFixed(0);
+ }
+ return s;
+ },
+ force_escape: function (value, arg) { return utils.string.html_escape(value.toString()); },
+ get_digit: function (value, arg) {
+ if (typeof value !== 'number' || typeof arg !== 'number' || typeof arg < 1) { return value; }
+ var s = value.toString();
+ return Number(s[s.length - arg]);
+ },
+ iriencode: function (value, arg) {
+ // TODO: implement iriencode filter
+ throw "iri encoding is not implemented";
+ },
+ join: function (value, arg) { return (value instanceof Array) ? value.join(arg) : '' },
+ last: function (value, arg) { return (value instanceof Array && value.length) ? value[value.length - 1] : ''; },
+ length: function (value, arg) { return value.hasOwnProperty('length') ? value.length : 0; },
+ length_is: function (value, arg) { return value.hasOwnProperty('length') && value.length === arg; },
+
sub: function (value, arg) { return value - arg; }
};
@@ -153,3 +221,4 @@ var callbacks = exports.callbacks = {
return nodes.IfNode(item_names, not_item_names, operator, node_list, else_list);
}
};
+
@@ -0,0 +1,107 @@
+var sys = require('sys');
+process.mixin(GLOBAL, require('../utils/test').dsl);
+process.mixin(GLOBAL, require('./template_defaults'));
+
+testcase('Test dictsort filter');
+ test('should sort correctly', function () {
+ var list = [
+ {'name': 'zed', 'age': 19},
+ {'name': 'amy', 'age': 22},
+ {'name': 'joe', 'age': 31}
+ ];
+ var before = list.slice(0);
+ assertEquals([ list[1], list[2], list[0] ], filters.dictsort(list, 'name') );
+ assertEquals(before, list);
+ });
+
+ test('should sort correctly with dictsortreversed', function () {
+ var list = [
+ {'name': 'zed', 'age': 19},
+ {'name': 'amy', 'age': 22},
+ {'name': 'joe', 'age': 31}
+ ];
+ var before = list.slice(0);
+ assertEquals([ list[0], list[2], list[1] ], filters.dictsortreversed(list, 'name') );
+ assertEquals(before, list);
+ });
+
+testcase('filesizeformat filter');
+ test('should return correct readable filesizes', function () {
+ assertEquals('117.7MB', filters.filesizeformat(123456789));
+ });
+
+testcase('first filter');
+ test('should return first in list', function () {
+ assertEquals('', filters.first('hest'));
+ assertEquals('hest', filters.first(['hest', 'abe', 39]));
+ });
+
+testcase('fix_ampersands');
+ test('should fix ampersands', function () {
+ assertEquals('Tom &amp; Jerry', filters.fix_ampersands('Tom & Jerry'));
+ });
+
+testcase('floatformat filter');
+ test('should format floats', function () {
+ assertEquals('', filters.floatformat('hest'));
+
+ assertEquals('34.2', filters.floatformat(34.23234));
+ assertEquals('34', filters.floatformat(34.00000));
+ assertEquals('34.3', filters.floatformat(34.26000));
+
+ assertEquals('34.232', filters.floatformat(34.23234, 3));
+ assertEquals('34.000', filters.floatformat(34.00000, 3));
+ assertEquals('34.260', filters.floatformat(34.26000, 3));
+
+ assertEquals('34.232', filters.floatformat(34.23234, -3));
+ assertEquals('34', filters.floatformat(34.00000, -3));
+ assertEquals('34.260', filters.floatformat(34.26000, -3));
+ });
+testcase('force_escape filter');
+ test('should escape string', function () {
+ assertEquals(
+ '&lt;script=&qout;alert(&#39;din mor&#39;)&qout;&gt;&lt;/script&gt;',
+ filters.force_escape('<script="alert(\'din mor\')"></script>')
+ );
+ });
+
+testcase('get_digit');
+ test('should get correct digit', function () {
+ assertEquals(2, filters.get_digit(987654321, 2));
+ assertEquals('987654321', filters.get_digit('987654321', 2));
+ assertEquals('hest', filters.get_digit('hest'), 2);
+ assertEquals(123, filters.get_digit(123), 5);
+ assertEquals(123, filters.get_digit(123), 0);
+ });
+
+testcase('join filter')
+ test('should join list', function () {
+ assertEquals('1, 2, 3, 4', filters.join([1,2,3,4], ', '));
+ assertEquals('', filters.join('1,2,3,4', ', '));
+ });
+testcase('last filter')
+ test('should return last', function () {
+ assertEquals('d', filters.last(['a', 'b', 'c', 'd']));
+ assertEquals('', filters.last([]));
+ assertEquals('', filters.last('hest'));
+ });
+testcase('length filter')
+ test('should return correct length', function () {
+ assertEquals(5, filters.length([1,2,3,4,5]));
+ assertEquals(4, filters.length('hest'));
+ assertEquals(0, filters.length(16));
+ });
+testcase('length_is filter')
+ test('should return true on correct length', function () {
+ assertEquals(true, filters.length_is([1,2,3,4,5], 5));
+ assertEquals(true, filters.length_is('hest', 4));
+ });
+ test('should fail on incorrect length or bad arguments', function () {
+ assertEquals(false, filters.length_is([1,2,3,4,5], 2));
+ assertEquals(false, filters.length_is('hest', 16));
+ assertEquals(false, filters.length_is(16, 4));
+ assertEquals(false, filters.length_is('hest'));
+ });
+
+
+run();
Oops, something went wrong.

0 comments on commit 177519a

Please sign in to comment.