mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-20 06:50:47 -07:00
coverage
This commit is contained in:
+4
-4
@@ -6,12 +6,12 @@ var doubleQuoted = /"[^"]*"/;
|
|||||||
var quoteBalanced = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source}|[^'"])*`);
|
var quoteBalanced = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source}|[^'"])*`);
|
||||||
|
|
||||||
var number = /(?:-?\d+\.?\d*|\.?\d+)/;
|
var number = /(?:-?\d+\.?\d*|\.?\d+)/;
|
||||||
var bool = /true|false/i;
|
var bool = /true|false/;
|
||||||
var identifier = /[a-zA-Z_$][a-zA-Z_$0-9]*/;
|
var identifier = /[a-zA-Z_$][a-zA-Z_$0-9]*/;
|
||||||
var subscript = /\[\d+\]/;
|
var subscript = /\[\d+\]/;
|
||||||
|
|
||||||
var quoted = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source})`);
|
var quoted = new RegExp(`(?:${singleQuoted.source}|${doubleQuoted.source})`);
|
||||||
var literal = new RegExp(`(?:${quoted.source}|${bool.source}|${number.source})`, 'i');
|
var literal = new RegExp(`(?:${quoted.source}|${bool.source}|${number.source})`);
|
||||||
var variable = new RegExp(`${identifier.source}(?:\\.${identifier.source}|${subscript.source})*`);
|
var variable = new RegExp(`${identifier.source}(?:\\.${identifier.source}|${subscript.source})*`);
|
||||||
|
|
||||||
// range related
|
// range related
|
||||||
@@ -19,10 +19,10 @@ var rangeLimit = new RegExp(`(?:${variable.source}|${number.source})`);
|
|||||||
var range = new RegExp(`\\(${rangeLimit.source}\\.\\.${rangeLimit.source}\\)`);
|
var range = new RegExp(`\\(${rangeLimit.source}\\.\\.${rangeLimit.source}\\)`);
|
||||||
var rangeCapture = new RegExp(`\\((${rangeLimit.source})\\.\\.(${rangeLimit.source})\\)`);
|
var rangeCapture = new RegExp(`\\((${rangeLimit.source})\\.\\.(${rangeLimit.source})\\)`);
|
||||||
|
|
||||||
var value = new RegExp(`(?:${literal.source}|${variable.source}|${range.source})`, 'i');
|
var value = new RegExp(`(?:${literal.source}|${variable.source}|${range.source})`);
|
||||||
|
|
||||||
// hash related
|
// hash related
|
||||||
var hash = new RegExp(`(?:${identifier.source})\\s*:\\s*(?:${value.source})`, 'g');
|
var hash = new RegExp(`(?:${identifier.source})\\s*:\\s*(?:${value.source})`);
|
||||||
var hashCapture = new RegExp(`(${identifier.source})\\s*:\\s*(${value.source})`, 'g');
|
var hashCapture = new RegExp(`(${identifier.source})\\s*:\\s*(${value.source})`, 'g');
|
||||||
|
|
||||||
var tagLine = new RegExp(`^\\s*(${identifier.source})\\s*(.*)\\s*$`);
|
var tagLine = new RegExp(`^\\s*(${identifier.source})\\s*(.*)\\s*$`);
|
||||||
|
|||||||
@@ -2,21 +2,6 @@ const lexical = require('./lexical.js');
|
|||||||
const Exp = require('./expression.js');
|
const Exp = require('./expression.js');
|
||||||
const TokenizationError = require('./error.js').TokenizationError;
|
const TokenizationError = require('./error.js').TokenizationError;
|
||||||
|
|
||||||
var _tagInstance = {
|
|
||||||
render: function(scope, register) {
|
|
||||||
var reg = register[this.name];
|
|
||||||
if(!reg) reg = register[this.name] = {};
|
|
||||||
var obj = hash(this.token.args, scope);
|
|
||||||
return this.tagImpl.render(scope, obj, reg) || '';
|
|
||||||
},
|
|
||||||
parse: function(tokens){
|
|
||||||
if(this.tagImpl.parse){
|
|
||||||
this.tagImpl.parse(this.token, tokens);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function hash(markup, scope) {
|
function hash(markup, scope) {
|
||||||
var obj = {};
|
var obj = {};
|
||||||
lexical.hashCapture.lastIndex = 0;
|
lexical.hashCapture.lastIndex = 0;
|
||||||
@@ -31,6 +16,27 @@ function hash(markup, scope) {
|
|||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
var tagImpls = {};
|
var tagImpls = {};
|
||||||
|
|
||||||
|
var _tagInstance = {
|
||||||
|
render: function(scope, register) {
|
||||||
|
var reg = register[this.name];
|
||||||
|
if(!reg) reg = register[this.name] = {};
|
||||||
|
var obj = hash(this.token.args, scope);
|
||||||
|
return this.tagImpl.render(scope, obj, reg) || '';
|
||||||
|
},
|
||||||
|
parse: function(token, tokens){
|
||||||
|
this.type = 'tag';
|
||||||
|
this.token = token;
|
||||||
|
this.name = token.name;
|
||||||
|
|
||||||
|
var tagImpl = tagImpls[this.name];
|
||||||
|
if (!tagImpl) throw new Error(`tag ${this.name} not found`);
|
||||||
|
this.tagImpl = Object.create(tagImpl);
|
||||||
|
if(this.tagImpl.parse){
|
||||||
|
this.tagImpl.parse(token, tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function register(name, tag) {
|
function register(name, tag) {
|
||||||
if (typeof tag.render !== 'function') {
|
if (typeof tag.render !== 'function') {
|
||||||
throw new Error(`expect ${name}.render to be a function`);
|
throw new Error(`expect ${name}.render to be a function`);
|
||||||
@@ -38,15 +44,9 @@ module.exports = function() {
|
|||||||
tagImpls[name] = tag;
|
tagImpls[name] = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
function construct(token) {
|
function construct(token, tokens) {
|
||||||
var tagImpl = tagImpls[token.name];
|
|
||||||
if (!tagImpl) throw new Error(`tag ${token.name} not found`);
|
|
||||||
|
|
||||||
var instance = Object.create(_tagInstance);
|
var instance = Object.create(_tagInstance);
|
||||||
instance.token = token;
|
instance.parse(token, tokens);
|
||||||
instance.type = 'tag';
|
|
||||||
instance.name = token.name;
|
|
||||||
instance.tagImpl = Object.create(tagImpl);
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ module.exports = function(liquid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.candidates.length){
|
if (!this.candidates.length){
|
||||||
throw new Error(`illegal tag: ${tagToken.raw}`);
|
throw new Error(`empty candidates: ${tagToken.raw}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+7
-26
@@ -3,23 +3,11 @@ var lexical = Liquid.lexical;
|
|||||||
|
|
||||||
module.exports = function(liquid) {
|
module.exports = function(liquid) {
|
||||||
liquid.registerTag('unless', {
|
liquid.registerTag('unless', {
|
||||||
|
|
||||||
parse: function(tagToken, remainTokens) {
|
parse: function(tagToken, remainTokens) {
|
||||||
this.branches = [];
|
|
||||||
this.elseTemplates = [];
|
|
||||||
|
|
||||||
var p, stream = liquid.parseStream(remainTokens)
|
var p, stream = liquid.parseStream(remainTokens)
|
||||||
.onStart(x => this.branches.push({
|
.onStart(x => {
|
||||||
cond: tagToken.args,
|
p = this.templates = [];
|
||||||
templates: p = []
|
this.cond = tagToken.args;
|
||||||
}))
|
|
||||||
.onTag('elsif', token => {
|
|
||||||
if (!this.branches[token.args]) {
|
|
||||||
this.branches.push({
|
|
||||||
cond: token.args,
|
|
||||||
templates: p = []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.onTag('else', token => this.elseTemplates = p = [])
|
.onTag('else', token => this.elseTemplates = p = [])
|
||||||
.onTag('endunless', token => stream.stop())
|
.onTag('endunless', token => stream.stop())
|
||||||
@@ -32,17 +20,10 @@ module.exports = function(liquid) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
render: function(scope, hash) {
|
render: function(scope, hash) {
|
||||||
for (var i = 0; i < this.branches.length; i++) {
|
var cond = Liquid.evalExp(this.cond, scope);
|
||||||
var branch = this.branches[i];
|
return Liquid.isFalsy(cond) ?
|
||||||
var cond = Liquid.evalExp(branch.cond, scope);
|
liquid.renderTemplates(this.templates, scope) :
|
||||||
cond = Liquid.isTruthy(cond);
|
liquid.renderTemplates(this.elseTemplates, scope);
|
||||||
if (i === 0) cond = !cond;
|
|
||||||
if (cond) {
|
|
||||||
return liquid.renderTemplates(branch.templates, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return liquid.renderTemplates(this.elseTemplates, scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ module.exports = function(Tag, Filter) {
|
|||||||
|
|
||||||
function parseTag(token, tokens) {
|
function parseTag(token, tokens) {
|
||||||
if (token.name === 'continue' || token.name === 'break') return token;
|
if (token.name === 'continue' || token.name === 'break') return token;
|
||||||
return Tag.construct(token).parse(tokens);
|
return Tag.construct(token, tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseOutput(str) {
|
function parseOutput(str) {
|
||||||
|
|||||||
+3
-3
@@ -23,7 +23,7 @@ describe('tag', function() {
|
|||||||
type: 'tag',
|
type: 'tag',
|
||||||
value: 'foo',
|
value: 'foo',
|
||||||
name: 'foo'
|
name: 'foo'
|
||||||
});
|
}, []);
|
||||||
}).to.throw(/tag foo not found/);
|
}).to.throw(/tag foo not found/);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ describe('tag', function() {
|
|||||||
type: 'tag',
|
type: 'tag',
|
||||||
value: 'foo',
|
value: 'foo',
|
||||||
name: 'foo'
|
name: 'foo'
|
||||||
}).render(scope, {});
|
}, []).render(scope, {});
|
||||||
expect(spy).to.have.been.called;
|
expect(spy).to.have.been.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ describe('tag', function() {
|
|||||||
name: 'foo',
|
name: 'foo',
|
||||||
args: 'aa:foo bb: arr[0] cc: 2.3'
|
args: 'aa:foo bb: arr[0] cc: 2.3'
|
||||||
};
|
};
|
||||||
tag.construct(token).render(scope, {});
|
tag.construct(token, []).render(scope, {});
|
||||||
expect(spy).to.have.been.calledWithMatch(scope, {
|
expect(spy).to.have.been.calledWithMatch(scope, {
|
||||||
aa: 'bar',
|
aa: 'bar',
|
||||||
bb: 2,
|
bb: 2,
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ describe('tags', function() {
|
|||||||
emptyArray: []
|
emptyArray: []
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support assign', function() {
|
it('should support assign', function() {
|
||||||
test('{% assign foo="bar" %}{{foo}}', 'bar');
|
test('{% assign foo="bar" %}{{foo}}', 'bar');
|
||||||
test('{% assign foo=(1..3) %}{{foo}}', '[1,2,3]');
|
test('{% assign foo=(1..3) %}{{foo}}', '[1,2,3]');
|
||||||
test('{% assign foo="a b" | capitalize | split: " " | first %}{{foo}}', 'A');
|
test('{% assign foo="a b" | capitalize | split: " " | first %}{{foo}}', 'A');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support case', function() {
|
it('should support case', function() {
|
||||||
testThrow('{% case "foo"%}', /{% case "foo"%} not closed/);
|
testThrow('{% case "foo"%}', /{% case "foo"%} not closed/);
|
||||||
test('{% case "foo"%}' +
|
test('{% case "foo"%}' +
|
||||||
@@ -69,10 +71,22 @@ describe('tags', function() {
|
|||||||
testThrow('{% capture = %}{%endcapture%}', /= not valid identifier/);
|
testThrow('{% capture = %}{%endcapture%}', /= not valid identifier/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw when for capture closed', function() {
|
||||||
|
testThrow('{%capture c%}{{c}}', /tag .* not closed/);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support for', function() {
|
it('should support for', function() {
|
||||||
test('{%for c in alpha%}{{c}}{%endfor%}', 'abc');
|
test('{%for c in alpha%}{{c}}{%endfor%}', 'abc');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw when for not closed', function() {
|
||||||
|
testThrow('{%for c in alpha%}{{c}}', /tag .* not closed/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support for else', function() {
|
||||||
|
test('{%for c in ""%}a{%else%}b{%endfor%}', 'b');
|
||||||
|
});
|
||||||
|
|
||||||
it('should support for with forloop', function() {
|
it('should support for with forloop', function() {
|
||||||
src = '{%for c in alpha%}' +
|
src = '{%for c in alpha%}' +
|
||||||
'{{forloop.first}}.{{forloop.index}}.{{forloop.index0}}.' +
|
'{{forloop.first}}.{{forloop.index}}.{{forloop.index0}}.' +
|
||||||
@@ -117,6 +131,10 @@ describe('tags', function() {
|
|||||||
test(src + src + src + src, '1231');
|
test(src + src + src + src, '1231');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw when cycle candidates empty', function() {
|
||||||
|
testThrow('{%cycle%}', /empty candidates/);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support cycle in for block', function() {
|
it('should support cycle in for block', function() {
|
||||||
src = '{% for i in (1..5) %}{% cycle one, "e"%}{% endfor %}';
|
src = '{% for i in (1..5) %}{% cycle one, "e"%}{% endfor %}';
|
||||||
test(src, '1e1e1');
|
test(src, '1e1e1');
|
||||||
|
|||||||
Reference in New Issue
Block a user