raw and comment

This commit is contained in:
harttle
2016-06-20 01:10:43 +08:00
parent 54bc206d36
commit 8053d7021f
16 changed files with 105 additions and 51 deletions
+2
View File
@@ -89,6 +89,8 @@ Documentation: <https://shopify.github.io/liquid/basics/introduction/#tags>
- [x] capture [Document](https://shopify.github.io/liquid/tags/variable/) [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/capture.js) [Test][tt]
- [x] increment [Document](https://shopify.github.io/liquid/tags/variable/) [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/increment.js) [Test][tt]
- [x] decrement [Document](https://shopify.github.io/liquid/tags/variable/) [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/decrement.js) [Test][tt]
- [x] raw [Document](https://help.shopify.com/themes/liquid/tags/theme-tags#raw) [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/raw.js) [Test][tt]
- [x] comment [Document](https://help.shopify.com/themes/liquid/tags/theme-tags#comment) [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/comment.js) [Test][tt]
## Filters
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "shopify-liquid",
"version": "1.1.1",
"version": "1.1.2",
"description": "A Shopify Liquid Implementation in Node.js",
"main": "index.js",
"scripts": {
+1 -12
View File
@@ -24,6 +24,7 @@ module.exports = function(Tag, Filter) {
start: function() {
this.trigger('start');
while (!this.stopRequested && (token = this.tokens.shift())) {
if (this.trigger('token', token)) continue;
if (token.type == 'tag' &&
this.trigger(`tag:${token.name}`, token)) {
continue;
@@ -37,18 +38,6 @@ module.exports = function(Tag, Filter) {
stop: function() {
this.stopRequested = true;
return this;
},
onStart: function(cb) {
return this.on('start', cb);
},
onEnd: function(cb) {
return this.on('end', cb);
},
onTag: function(name, cb) {
return this.on(`tag:${name}`, cb);
},
onTemplate: function(cb) {
return this.on('template', cb);
}
};
+1 -4
View File
@@ -21,7 +21,7 @@ module.exports = function() {
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) || '';
return this.tagImpl.render && this.tagImpl.render(scope, obj, reg) || '';
},
parse: function(token, tokens){
this.type = 'tag';
@@ -38,9 +38,6 @@ module.exports = function() {
};
function register(name, tag) {
if (typeof tag.render !== 'function') {
throw new Error(`expect ${name}.render to be a function`);
}
tagImpls[name] = tag;
}
+3 -3
View File
@@ -13,9 +13,9 @@ module.exports = function(liquid) {
this.templates = [];
var stream = liquid.parser.parseStream(remainTokens);
stream.onTag('endcapture', token => stream.stop())
.onTemplate(tpl => this.templates.push(tpl))
.onEnd(x => {
stream.on('tag:endcapture', token => stream.stop())
.on('template', tpl => this.templates.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
stream.start();
+5 -5
View File
@@ -11,7 +11,7 @@ module.exports = function(liquid) {
var p = [],
stream = liquid.parser.parseStream(remainTokens)
.onTag('when', token => {
.on('tag:when', token => {
if (!this.cases[token.args]) {
this.cases.push({
val: token.args,
@@ -19,10 +19,10 @@ module.exports = function(liquid) {
});
}
})
.onTag('else', token => p = this.elseTemplates)
.onTag('endcase', token => stream.stop())
.onTemplate(tpl => p.push(tpl))
.onEnd(x => {
.on('tag:else', token => p = this.elseTemplates)
.on('tag:endcase', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
+21
View File
@@ -0,0 +1,21 @@
var Liquid = require('..');
var lexical = Liquid.lexical;
var re = new RegExp(`(${lexical.identifier.source})`);
module.exports = function(liquid) {
liquid.registerTag('comment', {
parse: function(tagToken, remainTokens) {
var stream = liquid.parser.parseStream(remainTokens);
stream
.on('token', token => {
if(token.name === 'endcomment') stream.stop();
})
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
stream.start();
}
});
};
+5 -5
View File
@@ -19,11 +19,11 @@ module.exports = function(liquid) {
this.elseTemplates = [];
var p, stream = liquid.parser.parseStream(remainTokens)
.onStart(x => p = this.templates)
.onTag('else', token => p = this.elseTemplates)
.onTag('endfor', token => stream.stop())
.onTemplate(tpl => p.push(tpl))
.onEnd(x => {
.on('start', x => p = this.templates)
.on('tag:else', token => p = this.elseTemplates)
.on('tag:endfor', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
+6 -6
View File
@@ -10,11 +10,11 @@ module.exports = function(liquid) {
this.elseTemplates = [];
var p, stream = liquid.parser.parseStream(remainTokens)
.onStart(x => this.branches.push({
.on('start', x => this.branches.push({
cond: tagToken.args,
templates: p = []
}))
.onTag('elsif', token => {
.on('tag:elsif', token => {
if (!this.branches[token.args]) {
this.branches.push({
cond: token.args,
@@ -22,10 +22,10 @@ module.exports = function(liquid) {
});
}
})
.onTag('else', token => p = this.elseTemplates)
.onTag('endif', token => stream.stop())
.onTemplate(tpl => p.push(tpl))
.onEnd(x => {
.on('tag:else', token => p = this.elseTemplates)
.on('tag:endif', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
+27
View File
@@ -0,0 +1,27 @@
var Liquid = require('..');
var lexical = Liquid.lexical;
var re = new RegExp(`(${lexical.identifier.source})`);
module.exports = function(liquid) {
liquid.registerTag('raw', {
parse: function(tagToken, remainTokens) {
this.tokens = [];
var stream = liquid.parser.parseStream(remainTokens);
stream
.on('token', token => {
if(token.name === 'endraw') stream.stop();
else this.tokens.push(token);
})
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
stream.start();
},
render: function(scope, hash) {
return this.tokens.map(token => token.raw).join('');
}
});
};
+4 -4
View File
@@ -16,10 +16,10 @@ module.exports = function(liquid) {
this.templates = [];
var p, stream = liquid.parser.parseStream(remainTokens)
.onStart(x => p = this.templates)
.onTag('endtablerow', token => stream.stop())
.onTemplate(tpl => p.push(tpl))
.onEnd(x => {
.on('start', x => p = this.templates)
.on('tag:endtablerow', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
+5 -5
View File
@@ -5,14 +5,14 @@ module.exports = function(liquid) {
liquid.registerTag('unless', {
parse: function(tagToken, remainTokens) {
var p, stream = liquid.parser.parseStream(remainTokens)
.onStart(x => {
.on('start', x => {
p = this.templates = [];
this.cond = tagToken.args;
})
.onTag('else', token => this.elseTemplates = p = [])
.onTag('endunless', token => stream.stop())
.onTemplate(tpl => p.push(tpl))
.onEnd(x => {
.on('tag:else', token => this.elseTemplates = p = [])
.on('tag:endunless', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`);
});
-6
View File
@@ -27,12 +27,6 @@ describe('tag', function() {
}).to.throw(/tag foo not found/);
});
it('should throw when render method not defined', function() {
expect(function() {
tag.register('foo', {});
}).to.throw(/expect foo.render to be a function/);
});
it('should register simple tag', function() {
expect(
function() {
+12
View File
@@ -34,6 +34,18 @@ describe('tags', function() {
test('{% assign foo="a b" | capitalize | split: " " | first %}{{foo}}', 'A');
});
it('should support raw', function() {
testThrow('{% raw%}', /{% raw%} not closed/);
test('{% raw %}{{ 5 | plus: 6 }}{% endraw %} is equal to 11.', '{{ 5 | plus: 6 }} is equal to 11.');
test('{% raw %}\n{{ foo}} \n{% endraw %}', '\n{{ foo}} \n');
});
it('should support comment', function() {
testThrow('{% comment %}{% raw%}', /{% comment %} not closed/);
test('My name is {% comment %}super{% endcomment %} Shopify.', 'My name is Shopify.');
test('{% comment %}\n{{ foo}} \n{% endcomment %}', '');
});
it('should support case', function() {
testThrow('{% case "foo"%}', /{% case "foo"%} not closed/);
test('{% case "foo"%}' +
+10
View File
@@ -1,5 +1,6 @@
var chai = require("chai");
var should = chai.should();
var expect = chai.expect;
var tokenizer = require('../tokenizer.js');
@@ -39,4 +40,13 @@ describe('tokenizer', function() {
tokens[1].value.should.equal('bar');
tokens[2].value.should.equal('foo');
});
it('should keep white spaces and newlines', function(){
var html = '{{foo}}\n{%bar %} \n {{alice}}';
var tokens = tokenizer.parse(html);
expect(tokens.length).to.equal(5);
expect(tokens[1].type).to.equal('html');
expect(tokens[1].raw).to.equal('\n');
expect(tokens[3].type).to.equal('html');
expect(tokens[3].raw).to.equal(' \n ');
});
});
+2
View File
@@ -17,6 +17,7 @@ function parse(html) {
htmlFragment = html.slice(idx, result.index);
tokens.push({
type: 'html',
raw: htmlFragment,
value: htmlFragment
});
}
@@ -47,6 +48,7 @@ function parse(html) {
htmlFragment = html.slice(idx, html.length);
tokens.push({
type: 'html',
raw: htmlFragment,
value: htmlFragment
});
}