mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
refactor filters and corresponding tests
This commit is contained in:
+78
-74
@@ -1,93 +1,82 @@
|
||||
const strftime = require('./src/strftime.js');
|
||||
const _ = require('./src/util/underscore.js');
|
||||
|
||||
module.exports = function(liquid) {
|
||||
liquid.registerFilter('abs', v => Math.abs(v));
|
||||
liquid.registerFilter('append', (v, arg) => v + arg);
|
||||
liquid.registerFilter('capitalize', str =>
|
||||
stringify(str).charAt(0).toUpperCase() + str.slice(1));
|
||||
liquid.registerFilter('ceil', v => Math.ceil(v));
|
||||
var escapeMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
};
|
||||
var unescapeMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
''': "'",
|
||||
};
|
||||
|
||||
liquid.registerFilter('date', (v, arg) => {
|
||||
var filters = {
|
||||
'abs': v => Math.abs(v),
|
||||
'append': (v, arg) => v + arg,
|
||||
'capitalize': str => stringify(str).charAt(0).toUpperCase() + str.slice(1),
|
||||
'ceil': v => Math.ceil(v),
|
||||
'date': (v, arg) => {
|
||||
if (v === 'now') v = new Date();
|
||||
return strftime(v, arg);
|
||||
});
|
||||
},
|
||||
'default': (v, arg) => arg || v,
|
||||
'divided_by': (v, arg) => Math.floor(v / arg),
|
||||
'downcase': v => v.toLowerCase(),
|
||||
'escape': escape,
|
||||
|
||||
liquid.registerFilter('default', (v, arg) => arg || v);
|
||||
liquid.registerFilter('divided_by', (v, arg) => Math.floor(v / arg));
|
||||
liquid.registerFilter('downcase', v => v.toLowerCase());
|
||||
|
||||
var escapeMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
};
|
||||
|
||||
function escape(str) {
|
||||
return stringify(str).replace(/&|<|>|"|'/g, m => escapeMap[m]);
|
||||
}
|
||||
liquid.registerFilter('escape', escape);
|
||||
|
||||
var unescapeMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
''': "'",
|
||||
};
|
||||
|
||||
function unescape(str) {
|
||||
return stringify(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m]);
|
||||
}
|
||||
liquid.registerFilter('escape_once', str => escape(unescape(str)));
|
||||
liquid.registerFilter('first', v => v[0]);
|
||||
liquid.registerFilter('floor', v => Math.floor(v));
|
||||
liquid.registerFilter('join', (v, arg) => v.join(arg));
|
||||
liquid.registerFilter('last', v => v[v.length - 1]);
|
||||
liquid.registerFilter('lstrip', v => stringify(v).replace(/^\s+/, ''));
|
||||
liquid.registerFilter('map', (arr, arg) => arr.map(v => v[arg]));
|
||||
liquid.registerFilter('minus', bindFixed((v, arg) => v - arg));
|
||||
liquid.registerFilter('modulo', bindFixed((v, arg) => v % arg));
|
||||
liquid.registerFilter('newline_to_br', v => v.replace(/\n/g, '<br />'));
|
||||
liquid.registerFilter('plus', bindFixed((v, arg) => v + arg));
|
||||
liquid.registerFilter('prepend', (v, arg) => arg + v);
|
||||
liquid.registerFilter('remove', (v, arg) => v.split(arg).join(''));
|
||||
liquid.registerFilter('remove_first', (v, l) => v.replace(l, ''));
|
||||
liquid.registerFilter('replace', (v, pattern, replacement) =>
|
||||
stringify(v).split(pattern).join(replacement));
|
||||
liquid.registerFilter('replace_first', (v, arg1, arg2) => stringify(v).replace(arg1, arg2));
|
||||
liquid.registerFilter('reverse', v => v.reverse());
|
||||
liquid.registerFilter('round', (v, arg) => {
|
||||
'escape_once': str => escape(unescape(str)),
|
||||
'first': v => v[0],
|
||||
'floor': v => Math.floor(v),
|
||||
'join': (v, arg) => v.join(arg),
|
||||
'last': v => v[v.length - 1],
|
||||
'lstrip': v => stringify(v).replace(/^\s+/, ''),
|
||||
'map': (arr, arg) => arr.map(v => v[arg]),
|
||||
'minus': bindFixed((v, arg) => v - arg),
|
||||
'modulo': bindFixed((v, arg) => v % arg),
|
||||
'newline_to_br': v => v.replace(/\n/g, '<br />'),
|
||||
'plus': bindFixed((v, arg) => v + arg),
|
||||
'prepend': (v, arg) => arg + v,
|
||||
'remove': (v, arg) => v.split(arg).join(''),
|
||||
'remove_first': (v, l) => v.replace(l, ''),
|
||||
'replace': (v, pattern, replacement) =>
|
||||
stringify(v).split(pattern).join(replacement),
|
||||
'replace_first': (v, arg1, arg2) => stringify(v).replace(arg1, arg2),
|
||||
'reverse': v => v.reverse(),
|
||||
'round': (v, arg) => {
|
||||
var amp = Math.pow(10, arg || 0);
|
||||
return Math.round(v * amp, arg) / amp;
|
||||
});
|
||||
liquid.registerFilter('rstrip', str => stringify(str).replace(/\s+$/, ''));
|
||||
liquid.registerFilter('size', v => v.length);
|
||||
liquid.registerFilter('slice', (v, begin, length) =>
|
||||
v.substr(begin, length === undefined ? 1 : length));
|
||||
liquid.registerFilter('sort', (v, arg) => v.sort(arg));
|
||||
liquid.registerFilter('split', (v, arg) => stringify(v).split(arg));
|
||||
liquid.registerFilter('strip', (v) => stringify(v).trim());
|
||||
liquid.registerFilter('strip_html', v => stringify(v).replace(/<\/?\s*\w+\s*\/?>/g, ''));
|
||||
liquid.registerFilter('strip_newlines', v => stringify(v).replace(/\n/g, ''));
|
||||
liquid.registerFilter('times', (v, arg) => v * arg);
|
||||
liquid.registerFilter('truncate', (v, l, o) => {
|
||||
},
|
||||
'rstrip': str => stringify(str).replace(/\s+$/, ''),
|
||||
'size': v => v.length,
|
||||
'slice': (v, begin, length) =>
|
||||
v.substr(begin, length === undefined ? 1 : length),
|
||||
'sort': (v, arg) => v.sort(arg),
|
||||
'split': (v, arg) => stringify(v).split(arg),
|
||||
'strip': (v) => stringify(v).trim(),
|
||||
'strip_html': v => stringify(v).replace(/<\/?\s*\w+\s*\/?>/g, ''),
|
||||
'strip_newlines': v => stringify(v).replace(/\n/g, ''),
|
||||
'times': (v, arg) => v * arg,
|
||||
'truncate': (v, l, o) => {
|
||||
v = stringify(v);
|
||||
o = (o === undefined) ? '...' : o;
|
||||
l = l || 16;
|
||||
if (v.length <= l) return v;
|
||||
return v.substr(0, l - o.length) + o;
|
||||
});
|
||||
liquid.registerFilter('truncatewords', (v, l, o) => {
|
||||
},
|
||||
'truncatewords': (v, l, o) => {
|
||||
if (o === undefined) o = '...';
|
||||
var arr = v.split(' ');
|
||||
var ret = arr.slice(0, l).join(' ');
|
||||
if (arr.length > l) ret += o;
|
||||
return ret;
|
||||
});
|
||||
liquid.registerFilter('uniq', function(arr) {
|
||||
},
|
||||
'uniq': function(arr) {
|
||||
var u = {};
|
||||
return (arr || []).filter(val => {
|
||||
if (u.hasOwnProperty(val)) {
|
||||
@@ -96,11 +85,19 @@ module.exports = function(liquid) {
|
||||
u[val] = true;
|
||||
return true;
|
||||
});
|
||||
});
|
||||
liquid.registerFilter('upcase', str => stringify(str).toUpperCase());
|
||||
liquid.registerFilter('url_encode', encodeURIComponent);
|
||||
},
|
||||
'upcase': str => stringify(str).toUpperCase(),
|
||||
'url_encode': encodeURIComponent
|
||||
};
|
||||
|
||||
function escape(str) {
|
||||
return stringify(str).replace(/&|<|>|"|'/g, m => escapeMap[m]);
|
||||
}
|
||||
|
||||
function unescape(str) {
|
||||
return stringify(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m]);
|
||||
}
|
||||
|
||||
function getFixed(v) {
|
||||
var p = (v + "").split(".");
|
||||
return (p.length > 1) ? p[1].length : 0;
|
||||
@@ -121,3 +118,10 @@ function bindFixed(cb) {
|
||||
return cb(l, r).toFixed(f);
|
||||
};
|
||||
}
|
||||
|
||||
function registerAll(liquid) {
|
||||
return _.forOwn(filters, (func, name) => liquid.registerFilter(name, func));
|
||||
}
|
||||
|
||||
registerAll.filters = filters;
|
||||
module.exports = registerAll;
|
||||
|
||||
+8
-6
@@ -1,14 +1,16 @@
|
||||
// quote related
|
||||
var singleQuoted = /'[^']*'/;
|
||||
var doubleQuoted = /"[^"]*"/;
|
||||
var quoteBalanced = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source}|[^'"])*`);
|
||||
var quoted = new RegExp(`${singleQuoted.source}|${doubleQuoted.source}`);
|
||||
var quoteBalanced = new RegExp(`(?:${quoted.source}|[^'"])*`);
|
||||
|
||||
var number = /(?:-?\d+\.?\d*|\.?\d+)/;
|
||||
// values
|
||||
var integer = /-?\d+/;
|
||||
var number = /-?\d+\.?\d*|\.?\d+/;
|
||||
var bool = /true|false/;
|
||||
var identifier = /[a-zA-Z_$][a-zA-Z_$0-9]*/;
|
||||
var subscript = /\[\d+\]/;
|
||||
var identifier = /[\w-]+/;
|
||||
var subscript = new RegExp(`\\[(?:${quoted.source}|[\\w-\\.]+)\\]`);
|
||||
|
||||
var quoted = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source})`);
|
||||
var literal = new RegExp(`(?:${quoted.source}|${bool.source}|${number.source})`);
|
||||
var variable = new RegExp(`${identifier.source}(?:\\.${identifier.source}|${subscript.source})*`);
|
||||
|
||||
@@ -69,7 +71,7 @@ function parseLiteral(str) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
quoted, number, bool, literal, filter,
|
||||
quoted, number, bool, literal, filter, integer,
|
||||
hash, hashCapture,
|
||||
range, rangeCapture,
|
||||
identifier, value, quoteBalanced, operators,
|
||||
|
||||
+25
-1
@@ -1,5 +1,29 @@
|
||||
function isString(value){
|
||||
/*
|
||||
* Checks if value is classified as a String primitive or object.
|
||||
* @param {any} value The value to check.
|
||||
* @return {Boolean} Returns true if value is a string, else false.
|
||||
*/
|
||||
function isString(value) {
|
||||
return value instanceof String || typeof value === 'string';
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterates over own enumerable string keyed properties of an object and invokes iteratee for each property.
|
||||
* The iteratee is invoked with three arguments: (value, key, object).
|
||||
* Iteratee functions may exit iteration early by explicitly returning false.
|
||||
* @param {Object} object The object to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @return {Object} Returs object.
|
||||
*/
|
||||
function forOwn(object, iteratee) {
|
||||
object = object || {};
|
||||
for (var k in object) {
|
||||
if (object.hasOwnProperty(k)) {
|
||||
if (iteratee(object[k], k, object) === false) break;
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
exports.isString = isString;
|
||||
exports.forOwn = forOwn;
|
||||
|
||||
+3
-3
@@ -16,10 +16,10 @@ function test(promise, cb){
|
||||
describe('error', function() {
|
||||
|
||||
it('should throw TokenizationError when tag illegal', function() {
|
||||
return test(engine.parseAndRender('{% -a %}', {}), function(err){
|
||||
return test(engine.parseAndRender('{% . a %}', {}), function(err){
|
||||
expect(err.name).to.equal('TokenizationError');
|
||||
expect(err.message).to.equal('illegal tag: {% -a %}');
|
||||
expect(err.input).to.equal('{% -a %}');
|
||||
expect(err.message).to.equal('illegal tag: {% . a %}');
|
||||
expect(err.input).to.equal('{% . a %}');
|
||||
expect(err.line).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
+150
-102
@@ -1,9 +1,8 @@
|
||||
const chai = require("chai");
|
||||
const expect = chai.expect;
|
||||
chai.use(require("chai-as-promised"));
|
||||
|
||||
const chaiAsPromised = require("chai-as-promised");
|
||||
var liquid = require('..')(),
|
||||
ctx;
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
function test(src, dst) {
|
||||
ctx = {
|
||||
@@ -20,57 +19,74 @@ function test(src, dst) {
|
||||
category: 'bar'
|
||||
}]
|
||||
};
|
||||
return expect(liquid.parseAndRender(src, ctx)).to.eventually.equal(dst);
|
||||
return liquid.parseAndRender(src, ctx).should.eventually.equal(dst);
|
||||
}
|
||||
|
||||
describe('filters', function() {
|
||||
it('should support abs 1', () => test('{{ -3 | abs }}', '3'));
|
||||
it('should support abs 2', () => test('{{ arr[0] | abs }}', '2'));
|
||||
describe('abs', function() {
|
||||
it('should return 3 for -3', () => test('{{ -3 | abs }}', '3'));
|
||||
it('should return 2 for arr[0]', () => test('{{ arr[0] | abs }}', '2'));
|
||||
});
|
||||
|
||||
it('should support append 1', () => test('{{ -3 | append: "abc" }}', '-3abc'));
|
||||
it('should support append 2', () => test('{{ "a" | append: foo }}', 'abar'));
|
||||
describe('append', function() {
|
||||
it('should return "-3abc" for -3, "abc"',
|
||||
() => test('{{ -3 | append: "abc" }}', '-3abc'));
|
||||
it('should return "abar" for "a",foo', () => test('{{ "a" | append: foo }}', 'abar'));
|
||||
});
|
||||
|
||||
it('should support capitalize', () => test('{{ "i am good" | capitalize }}', 'I am good'));
|
||||
|
||||
it('should support ceil 1', () => test('{{ 1.2 | ceil }}', '2'));
|
||||
it('should support ceil 2', () => test('{{ 2.0 | ceil }}', '2'));
|
||||
it('should support ceil 3', () => test('{{ "3.5" | ceil }}', '4'));
|
||||
it('should support ceil 4', () => test('{{ 183.357 | ceil }}', '184'));
|
||||
describe('ceil', function() {
|
||||
it('should return "2" for 1.2', () => test('{{ 1.2 | ceil }}', '2'));
|
||||
it('should return "2" for 2.0', () => test('{{ 2.0 | ceil }}', '2'));
|
||||
it('should return "4" for 3.5', () => test('{{ "3.5" | ceil }}', '4'));
|
||||
it('should return "184" for 183.357', () => test('{{ 183.357 | ceil }}', '184'));
|
||||
});
|
||||
|
||||
describe('date', function(){
|
||||
it('should support %a %b %d %Y', function() {
|
||||
describe('date', function() {
|
||||
it('should support date: %a %b %d %Y', function() {
|
||||
var str = ctx.date.toDateString();
|
||||
return test('{{ date | date:"%a %b %d %Y"}}', str);
|
||||
});
|
||||
it('should support "now"', function() {
|
||||
var year = (new Date()).getFullYear();
|
||||
var src = '{{ "now" | date: "%Y"}}';
|
||||
return expect(liquid.parseAndRender(src)).to.eventually.match(/\d{4}/);
|
||||
it('should create a new Date when given "now"', function() {
|
||||
return test('{{ "now" | date: "%Y"}}', (new Date).getFullYear().toString());
|
||||
});
|
||||
});
|
||||
|
||||
it('should support default', () => test('{{false |default: "a"}}', 'a'));
|
||||
|
||||
it('should support divided_by 1', () => test('{{4 | divided_by: 2}}', '2'));
|
||||
it('should support divided_by 2', () => test('{{16 | divided_by: 4}}', '4'));
|
||||
it('should support divided_by 3', () => test('{{5 | divided_by: 3}}', '1'));
|
||||
|
||||
it('should support downcase 1', () => test('{{ "Parker Moore" | downcase }}', 'parker moore'));
|
||||
it('should support downcase 2', () => test('{{ "apple" | downcase }}', 'apple'));
|
||||
|
||||
it('should support escape 1', function() {
|
||||
return test('{{ "Have you read \'James & the Giant Peach\'?" | escape }}',
|
||||
'Have you read 'James & the Giant Peach'?');
|
||||
});
|
||||
it('should support escape 2', function() {
|
||||
return test('{{ "Tetsuro Takara" | escape }}', 'Tetsuro Takara');
|
||||
});
|
||||
it('should support excape function', function() {
|
||||
return test('{{ func | escape }}', 'function () {}');
|
||||
describe('divided_by', function() {
|
||||
it('should return 2 for 4,2', () => test('{{4 | divided_by: 2}}', '2'));
|
||||
it('should return 4 for 16,4', () => test('{{16 | divided_by: 4}}', '4'));
|
||||
it('should return 1 for 5,3', () => test('{{5 | divided_by: 3}}', '1'));
|
||||
});
|
||||
|
||||
it('should support escape_once 1', () => test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'));
|
||||
it('should support escape_once 2', () => test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'));
|
||||
describe('downcase', function() {
|
||||
it('should return "parker moore" for "Parker Moore"',
|
||||
() => test('{{ "Parker Moore" | downcase }}', 'parker moore'));
|
||||
it('should return "apple" for "apple"',
|
||||
() => test('{{ "apple" | downcase }}', 'apple'));
|
||||
});
|
||||
|
||||
describe('escape', function() {
|
||||
it('should escape \' and &', function() {
|
||||
return test('{{ "Have you read \'James & the Giant Peach\'?" | escape }}',
|
||||
'Have you read 'James & the Giant Peach'?');
|
||||
});
|
||||
it('should escape normal string', function() {
|
||||
return test('{{ "Tetsuro Takara" | escape }}', 'Tetsuro Takara');
|
||||
});
|
||||
it('should escape function', function() {
|
||||
return test('{{ func | escape }}', 'function () {}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('escape_once', function() {
|
||||
it('should do escape', () =>
|
||||
test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'));
|
||||
it('should not escape twice',
|
||||
() => test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'));
|
||||
});
|
||||
|
||||
it('should support split/first', function() {
|
||||
var src = '{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}' +
|
||||
@@ -78,10 +94,12 @@ describe('filters', function() {
|
||||
return test(src, 'apples');
|
||||
});
|
||||
|
||||
it('should support floor 1', () => test('{{ 1.2 | floor }}', '1'));
|
||||
it('should support floor 2', () => test('{{ 2.0 | floor }}', '2'));
|
||||
it('should support floor 3', () => test('{{ 183.357 | floor }}', '183'));
|
||||
it('should support floor 4', () => test('{{ "3.5" | floor }}', '3'));
|
||||
describe('floor', function() {
|
||||
it('should return "1" for 1.2', () => test('{{ 1.2 | floor }}', '1'));
|
||||
it('should return "2" for 2.0', () => test('{{ 2.0 | floor }}', '2'));
|
||||
it('should return "183" for 183.357', () => test('{{ 183.357 | floor }}', '183'));
|
||||
it('should return "3" for 3.5', () => test('{{ "3.5" | floor }}', '3'));
|
||||
});
|
||||
|
||||
it('should support join', function() {
|
||||
var src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
@@ -104,13 +122,19 @@ describe('filters', function() {
|
||||
return test('{{posts | map: "category"}}', '["foo","bar"]');
|
||||
});
|
||||
|
||||
it('should support minus 1', () => test('{{ 4 | minus: 2 }}', '2'));
|
||||
it('should support minus 2', () => test('{{ 16 | minus: 4 }}', '12'));
|
||||
it('should support minus 3', () => test('{{ 183.357 | minus: 12 }}', '171.357'));
|
||||
describe('minus', function() {
|
||||
it('should return "2" for 4,2', () => test('{{ 4 | minus: 2 }}', '2'));
|
||||
it('should return "12" for 16,4', () => test('{{ 16 | minus: 4 }}', '12'));
|
||||
it('should return "171.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | minus: 12 }}', '171.357'));
|
||||
});
|
||||
|
||||
it('should support modulo 1', () => test('{{ 3 | modulo: 2 }}', '1'));
|
||||
it('should support modulo 2', () => test('{{ 24 | modulo: 7 }}', '3'));
|
||||
it('should support modulo 3', () => test('{{ 183.357 | modulo: 12 }}', '3.357'));
|
||||
describe('modulo', function() {
|
||||
it('should return "1" for 3,2', () => test('{{ 3 | modulo: 2 }}', '1'));
|
||||
it('should return "3" for 24,7', () => test('{{ 24 | modulo: 7 }}', '3'));
|
||||
it('should return "3.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | modulo: 12 }}', '3.357'));
|
||||
});
|
||||
|
||||
it('should support string_with_newlines', function() {
|
||||
var src = '{% capture string_with_newlines %}\n' +
|
||||
@@ -124,9 +148,12 @@ describe('filters', function() {
|
||||
return test(src, dst);
|
||||
});
|
||||
|
||||
it('should support plus 1', () => test('{{ 4 | plus: 2 }}', '6'));
|
||||
it('should support plus 2', () => test('{{ 16 | plus: 4 }}', '20'));
|
||||
it('should support plus 3', () => test('{{ 183.357 | plus: 12 }}', '195.357'));
|
||||
describe('plus', function() {
|
||||
it('should return "6" for 4,2', () => test('{{ 4 | plus: 2 }}', '6'));
|
||||
it('should return "20" for 16,4', () => test('{{ 16 | plus: 4 }}', '20'));
|
||||
it('should return "195.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | plus: 12 }}', '195.357'));
|
||||
});
|
||||
|
||||
it('should support prepend', function() {
|
||||
return test('{% assign url = "liquidmarkup.com" %}' +
|
||||
@@ -160,26 +187,34 @@ describe('filters', function() {
|
||||
'.moT rojaM ot lortnoc dnuorG');
|
||||
});
|
||||
|
||||
it('should support round 1', () => test('{{1.2|round}}', '1'));
|
||||
it('should support round 2', () => test('{{2.7|round}}', '3'));
|
||||
it('should support round 3', () => test('{{183.357|round: 2}}', '183.36'));
|
||||
describe('round', function() {
|
||||
it('should return "1" for 1.2', () => test('{{1.2|round}}', '1'));
|
||||
it('should return "3" for 2.7', () => test('{{2.7|round}}', '3'));
|
||||
it('should return "183.36" for 183.357,2',
|
||||
() => test('{{183.357|round: 2}}', '183.36'));
|
||||
});
|
||||
|
||||
it('should support rstrip', function() {
|
||||
return test('{{ " So much room for activities! " | rstrip }}',
|
||||
' So much room for activities!');
|
||||
});
|
||||
|
||||
it('should support size 1', () => test('{{ "Ground control to Major Tom." | size }}', '28'));
|
||||
it('should support size 2', function() {
|
||||
return test('{% assign my_array = "apples, oranges, peaches, plums"' +
|
||||
' | split: ", " %}{{ my_array | size }}',
|
||||
'4');
|
||||
describe('size', function() {
|
||||
it('should return string length',
|
||||
() => test('{{ "Ground control to Major Tom." | size }}', '28'));
|
||||
it('should return array size', function() {
|
||||
return test('{% assign my_array = "apples, oranges, peaches, plums"' +
|
||||
' | split: ", " %}{{ my_array | size }}',
|
||||
'4');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support slice 1', () => test('{{ "Liquid" | slice: 0 }}', 'L'));
|
||||
it('should support slice 2', () => test('{{ "Liquid" | slice: 2 }}', 'q'));
|
||||
it('should support slice 3', () => test('{{ "Liquid" | slice: 2, 5 }}', 'quid'));
|
||||
it('should support slice 4', () => test('{{ "Liquid" | slice: -3, 2 }}', 'ui'));
|
||||
describe('slice', function() {
|
||||
it('should slice first char by 0', () => test('{{ "Liquid" | slice: 0 }}', 'L'));
|
||||
it('should slice third char by 2', () => test('{{ "Liquid" | slice: 2 }}', 'q'));
|
||||
it('should slice substr by 2,5', () => test('{{ "Liquid" | slice: 2, 5 }}', 'quid'));
|
||||
it('should slice substr by -3,2', () => test('{{ "Liquid" | slice: -3, 2 }}', 'ui'));
|
||||
});
|
||||
|
||||
it('should support sort', function() {
|
||||
return test('{% assign my_array = "zebra, octopus, giraffe, Sally Snake"' +
|
||||
@@ -201,12 +236,14 @@ describe('filters', function() {
|
||||
'So much room for activities!');
|
||||
});
|
||||
|
||||
it('should support strip_tml 1', function() {
|
||||
return test('{{ "Have <em>you</em> read <strong>Ulysses</strong>?" | strip_html }}',
|
||||
'Have you read Ulysses?');
|
||||
});
|
||||
it('should support strip_tml 2', function() {
|
||||
return test('{{"<br/><br />< p ></p></ p >" | strip_html }}', '');
|
||||
describe('strip_html', function() {
|
||||
it('should strip all tags', function() {
|
||||
return test('{{ "Have <em>you</em> read <strong>Ulysses</strong>?" | strip_html }}',
|
||||
'Have you read Ulysses?');
|
||||
});
|
||||
it('should strip until empty', function() {
|
||||
return test('{{"<br/><br />< p ></p></ p >" | strip_html }}', '');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support strip_newlines', function() {
|
||||
@@ -216,42 +253,49 @@ describe('filters', function() {
|
||||
'Hellothere');
|
||||
});
|
||||
|
||||
it('should support times 1', () => test('{{ 3 | times: 2 }}', '6'));
|
||||
it('should support times 2', () => test('{{ 24 | times: 7 }}', '168'));
|
||||
it('should support times 3', () => test('{{ 183.357 | times: 12 }}', '2200.284'));
|
||||
|
||||
it('should support truncate 1', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
|
||||
'Ground control to...');
|
||||
});
|
||||
it('should support truncate 2', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 80 }}',
|
||||
'Ground control to Major Tom.');
|
||||
});
|
||||
it('should support truncate 3', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 25,", and so on" }}',
|
||||
'Ground control, and so on');
|
||||
});
|
||||
it('should support truncate 4', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20, "" }}',
|
||||
'Ground control to Ma');
|
||||
describe('times', function() {
|
||||
it('should return "6" for 3,2', () => test('{{ 3 | times: 2 }}', '6'));
|
||||
it('should return "168" for 24,7', () => test('{{ 24 | times: 7 }}', '168'));
|
||||
it('should return "2200.284" for 183.357,12',
|
||||
() => test('{{ 183.357 | times: 12 }}', '2200.284'));
|
||||
});
|
||||
|
||||
it('should support truncatewords 1', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3 }}',
|
||||
'Ground control to...');
|
||||
describe('truncate', function() {
|
||||
it('should truncate when string too long', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
|
||||
'Ground control to...');
|
||||
});
|
||||
it('should not truncate when string not long enough', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 80 }}',
|
||||
'Ground control to Major Tom.');
|
||||
});
|
||||
it('should truncate with custom ellipsis', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 25,", and so on" }}',
|
||||
'Ground control, and so on');
|
||||
});
|
||||
it('should truncate with empty custom ellipsis', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20, "" }}',
|
||||
'Ground control to Ma');
|
||||
});
|
||||
});
|
||||
it('should support truncatewords 2', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 8 }}',
|
||||
'Ground control to Major Tom.');
|
||||
});
|
||||
it('should support truncatewords 3', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "--" }}',
|
||||
'Ground control to--');
|
||||
});
|
||||
it('should support truncatewords 4', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "" }}',
|
||||
'Ground control to');
|
||||
|
||||
describe('truncatewords', function() {
|
||||
it('should truncate when too many words', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3 }}',
|
||||
'Ground control to...');
|
||||
});
|
||||
it('should not truncate when not enough words', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 8 }}',
|
||||
'Ground control to Major Tom.');
|
||||
});
|
||||
it('should truncate with custom ellipsis', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "--" }}',
|
||||
'Ground control to--');
|
||||
});
|
||||
it('should truncate with empty custom ellipsis', function() {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "" }}',
|
||||
'Ground control to');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support uniq', function() {
|
||||
@@ -262,6 +306,10 @@ describe('filters', function() {
|
||||
|
||||
it('should support upcase', () => test('{{ "Parker Moore" | upcase }}', 'PARKER MOORE'));
|
||||
|
||||
it('should support url_encode 1', () => test('{{ "[email protected]" | url_encode }}', 'john%40liquid.com'));
|
||||
it('should support url_encode 2', () => test('{{ "Tetsuro Takara" | url_encode }}', 'Tetsuro%20Takara'));
|
||||
describe('url_encode', function() {
|
||||
it('should encode @',
|
||||
() => test('{{ "[email protected]" | url_encode }}', 'john%40liquid.com'));
|
||||
it('should encode <space>',
|
||||
() => test('{{ "Tetsuro Takara" | url_encode }}', 'Tetsuro%20Takara'));
|
||||
});
|
||||
});
|
||||
|
||||
+19
-5
@@ -39,10 +39,25 @@ describe('lexical', function() {
|
||||
lexical.isLiteral("'a bcd'").should.equal(true);
|
||||
});
|
||||
|
||||
it("should test variable", function() {
|
||||
lexical.isVariable("foo").should.equal(true);
|
||||
lexical.isVariable("foo.bar.foo").should.equal(true);
|
||||
lexical.isVariable("foo[0].b").should.equal(true);
|
||||
describe('.isVariable()', function() {
|
||||
it('should return true for foo', function(){
|
||||
lexical.isVariable("foo").should.equal(true);
|
||||
});
|
||||
it('should return true for.bar.foo', function(){
|
||||
lexical.isVariable("foo.bar.foo").should.equal(true);
|
||||
});
|
||||
it('should return true for foo[0].b', function(){
|
||||
lexical.isVariable("foo[0].b").should.equal(true);
|
||||
});
|
||||
it('should return true for 0a', function(){
|
||||
lexical.isVariable("0a").should.equal(true);
|
||||
});
|
||||
it('should return true for foo[a.b]', function(){
|
||||
lexical.isVariable("foo[a.b]").should.equal(true);
|
||||
});
|
||||
it('should return true for foo[a.b]', function(){
|
||||
lexical.isVariable("foo['a[0]']").should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should test none literal', function() {
|
||||
@@ -55,7 +70,6 @@ describe('lexical', function() {
|
||||
lexical.isVariable("a.").should.equal(false);
|
||||
lexical.isVariable(".b").should.equal(false);
|
||||
lexical.isVariable(".").should.equal(false);
|
||||
lexical.isVariable("0a").should.equal(false);
|
||||
lexical.isVariable("[0][12].bar[0]").should.equal(false);
|
||||
});
|
||||
|
||||
|
||||
+8
-3
@@ -70,6 +70,11 @@ describe('liquid', function() {
|
||||
var template = engine.parse('<p>{{arr | join: "_"}}</p>');
|
||||
return engine.render(template, ctx).should.eventually.equal('<p>-2_a</p>');
|
||||
});
|
||||
it('should render accessive filters', function() {
|
||||
var src = '{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}' +
|
||||
'{{ my_array | first }}';
|
||||
return expect(engine.parseAndRender(src)).to.eventually.equal('apples');
|
||||
});
|
||||
describe('#renderFile()', function() {
|
||||
it('should render file', function() {
|
||||
return engine.renderFile('/root/files/foo.html', ctx).should.eventually.equal('foo');
|
||||
@@ -83,17 +88,17 @@ describe('liquid', function() {
|
||||
it('should use default extname', function() {
|
||||
return engine.renderFile('files/name', ctx).should.eventually.equal('My name is harttle.');
|
||||
});
|
||||
it('should accept root with no trailing slash', function(){
|
||||
it('should accept root with no trailing slash', function() {
|
||||
engine = Liquid({
|
||||
root: '/root',
|
||||
extname: '.html'
|
||||
});
|
||||
return expect(engine.renderFile('files/foo.html')).to.eventually.equal('foo');
|
||||
});
|
||||
it('should accept dot path', function(){
|
||||
it('should accept dot path', function() {
|
||||
return expect(engine.renderFile('./files/foo.html')).to.eventually.equal('foo');
|
||||
});
|
||||
it('should accept double-dot path', function(){
|
||||
it('should accept double-dot path', function() {
|
||||
return expect(engine.renderFile('files/foo/../foo.html')).to.eventually.equal('foo');
|
||||
});
|
||||
});
|
||||
|
||||
+35
-38
@@ -1,27 +1,25 @@
|
||||
var chai = require("chai");
|
||||
var should = chai.should();
|
||||
var expect = chai.expect;
|
||||
const chai = require("chai");
|
||||
const expect = chai.expect;
|
||||
|
||||
var Scope = require('../src/scope.js');
|
||||
|
||||
describe('scope', function() {
|
||||
var scope, ctx;
|
||||
beforeEach(function(){
|
||||
beforeEach(function() {
|
||||
ctx = {
|
||||
foo: 'bar',
|
||||
bar: ['a', {b: [1, 2]}]
|
||||
foo: 'bar'
|
||||
};
|
||||
scope = Scope.factory(ctx);
|
||||
});
|
||||
|
||||
it('should get property', function() {
|
||||
scope.get('foo').should.equal('bar');
|
||||
it('should get direct property', function() {
|
||||
expect(scope.get('foo')).equal('bar');
|
||||
});
|
||||
|
||||
it('should get undefined property', function() {
|
||||
function fn(){
|
||||
scope.get('notdefined');
|
||||
}
|
||||
function fn() {
|
||||
scope.get('notdefined');
|
||||
}
|
||||
expect(fn).to.not.throw();
|
||||
expect(scope.get('notdefined')).to.equal(undefined);
|
||||
expect(scope.get('')).to.equal(undefined);
|
||||
@@ -29,47 +27,46 @@ describe('scope', function() {
|
||||
});
|
||||
|
||||
it('should throw undefined in strict mode', function() {
|
||||
scope = Scope.factory(ctx, {
|
||||
strict: true
|
||||
});
|
||||
function fn(){
|
||||
scope.get('notdefined');
|
||||
}
|
||||
expect(fn).to.throw(/undefined variable: notdefined/);
|
||||
scope = Scope.factory(ctx, {
|
||||
strict: true
|
||||
});
|
||||
|
||||
function fn() {
|
||||
scope.get('notdefined');
|
||||
}
|
||||
expect(fn).to.throw(/undefined variable: notdefined/);
|
||||
});
|
||||
|
||||
it('should get all property', function() {
|
||||
scope.get().should.deep.equal(ctx);
|
||||
it('should get all properties when arguments empty', function() {
|
||||
expect(scope.get()).deep.equal(ctx);
|
||||
});
|
||||
|
||||
it('should set property', function() {
|
||||
scope.set('foo', 'FOO');
|
||||
scope.get('foo').should.equal('FOO');
|
||||
});
|
||||
|
||||
it('should set child property', function() {
|
||||
it('should access child property via dot syntax', function() {
|
||||
scope.set('oo.bar', 'FOO');
|
||||
scope.get('oo.bar').should.equal('FOO');
|
||||
expect(scope.get('oo.bar')).to.equal('FOO');
|
||||
});
|
||||
|
||||
it('should get desendent property', function() {
|
||||
scope.get('bar[0]').should.equal('a');
|
||||
scope.get('bar[1].b').should.deep.equal([1, 2]);
|
||||
scope.get('bar[1].b[1]').should.equal(2);
|
||||
it('should access child property via [<Number>] syntax', function() {
|
||||
scope.set('bar', ['a', {'b': [1,2]}]);
|
||||
expect(scope.get('bar[0]')).to.equal('a');
|
||||
expect(scope.get('bar[1].b')).to.deep.equal([1, 2]);
|
||||
expect(scope.get('bar[1].b[1]')).to.equal(2);
|
||||
});
|
||||
|
||||
it('should push scope', function() {
|
||||
scope.push({foo: 'foo', foo1: 'foo1'});
|
||||
scope.get('foo').should.equal('foo');
|
||||
scope.get('foo1').should.equal('foo1');
|
||||
scope.get('bar[1].b[1]').should.equal(2);
|
||||
scope.set('bar', 'bar');
|
||||
scope.push({
|
||||
foo: 'foo'
|
||||
});
|
||||
expect(scope.get('foo')).to.equal('foo');
|
||||
expect(scope.get('bar')).to.equal('bar');
|
||||
});
|
||||
|
||||
it('should pop scope', function() {
|
||||
scope.push({foo: 'foo', foo1: 'foo1'});
|
||||
scope.push({
|
||||
foo: 'foo'
|
||||
});
|
||||
scope.pop();
|
||||
expect(scope.get('foo')).to.equal('bar');
|
||||
expect(scope.get('foo1')).to.equal(undefined);
|
||||
expect(scope.get('bar[1].b[1]')).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
+4
-5
@@ -1,8 +1,7 @@
|
||||
var chai = require("chai");
|
||||
var sinonChai = require("sinon-chai");
|
||||
var sinon = require("sinon");
|
||||
var expect = chai.expect;
|
||||
chai.use(sinonChai);
|
||||
const chai = require("chai");
|
||||
const sinon = require("sinon");
|
||||
const expect = chai.expect;
|
||||
chai.use(require("sinon-chai"));
|
||||
|
||||
var tag = require('../src/tag.js')();
|
||||
var Scope = require('../src/scope.js');
|
||||
|
||||
+28
-5
@@ -1,17 +1,40 @@
|
||||
const chai = require("chai");
|
||||
const sinon = require('sinon');
|
||||
const expect = chai.expect;
|
||||
const _ = require('../../src/util/underscore.js');
|
||||
chai.use(require("sinon-chai"));
|
||||
|
||||
var _ = require('../../src/util/underscore.js');
|
||||
|
||||
describe('util/underscore', function() {
|
||||
describe('.isString()', function(){
|
||||
it('should return true for literal string', function(){
|
||||
describe('.isString()', function() {
|
||||
it('should return true for literal string', function() {
|
||||
expect(_.isString('foo')).to.be.true;
|
||||
});
|
||||
it('should return true String instance', function(){
|
||||
it('should return true String instance', function() {
|
||||
expect(_.isString(new String('foo'))).to.be.true;
|
||||
});
|
||||
it('should return false for 123 ', function(){
|
||||
it('should return false for 123 ', function() {
|
||||
expect(_.isString(123)).to.be.false;
|
||||
});
|
||||
});
|
||||
describe('.forOwn()', function() {
|
||||
it('should iterate all properties', function() {
|
||||
var spy = sinon.spy();
|
||||
var obj = {
|
||||
foo: "bar"
|
||||
};
|
||||
_.forOwn(obj, spy);
|
||||
expect(spy).to.have.been.calledWith('bar', 'foo', obj);
|
||||
});
|
||||
it('should not iterate over properties on prototype', function() {
|
||||
var spy = sinon.spy();
|
||||
var obj = Object.create({
|
||||
bar: 'foo'
|
||||
});
|
||||
obj.foo = 'bar';
|
||||
_.forOwn(obj, spy);
|
||||
expect(spy).to.have.been.calledOnce;
|
||||
expect(spy).to.have.been.calledWith('bar', 'foo', obj);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user