mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
tag: layout, block
This commit is contained in:
@@ -49,7 +49,9 @@ var html = engine.renderFile("hello.html", {name: 'alice'});
|
||||
|
||||
`cache` default to `false`, `extname` default to `.liquid`, `root` default to `""`.
|
||||
|
||||
## Include
|
||||
## Includes and Layouts
|
||||
|
||||
### Includes
|
||||
|
||||
```
|
||||
// file: color.liquid
|
||||
@@ -70,6 +72,30 @@ color: 'red' shape: 'circle'
|
||||
color: 'yellow' shape: 'square'
|
||||
```
|
||||
|
||||
### Layouts
|
||||
|
||||
```
|
||||
// file: default-layout.html
|
||||
Header
|
||||
{% block content %}My default content{% endblock %}
|
||||
Footer
|
||||
|
||||
// file: page.html
|
||||
{% layout "default-layout" %}
|
||||
{% block content %}My page content{% endblock %}
|
||||
```
|
||||
|
||||
The output of `page.html`:
|
||||
|
||||
```
|
||||
Header
|
||||
My page content
|
||||
Footer
|
||||
```
|
||||
|
||||
* It's possible to define multiple blocks.
|
||||
* block name is optional when there's only one block.
|
||||
|
||||
## Extension
|
||||
|
||||
Register Filters:
|
||||
@@ -131,6 +157,7 @@ Tag | Document | Source | Test
|
||||
`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]
|
||||
`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]
|
||||
`include` | [Document](https://help.shopify.com/themes/liquid/tags/theme-tags#include) | [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/include.js) | [Test][tt]
|
||||
`layout, block` | [Document](http://docs.mixture.io/templates/) | [Source](https://github.com/harttle/shopify-liquid/blob/master/tags/layout.js) | [Test][tt]
|
||||
|
||||
|
||||
## Filters
|
||||
|
||||
@@ -58,7 +58,7 @@ var _engine = {
|
||||
filepath += this.options.extname;
|
||||
}
|
||||
var tpl = this.options.cache && this.cache[filepath] ||
|
||||
this.parse(fs.readFileSync(filepath));
|
||||
this.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
return this.options.cache ? (this.cache[filepath] = tpl) : tpl;
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "shopify-liquid",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.5",
|
||||
"description": "A Shopify Liquid Implementation in Node.js",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -8,7 +8,6 @@ var scope = {
|
||||
var v = _.get(this.scopes[i], str);
|
||||
if (v !== undefined) return v;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
set: function(k, v) {
|
||||
_.set(this.scopes[this.scopes.length - 1], k, v);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
var Liquid = require('..');
|
||||
var lexical = Liquid.lexical;
|
||||
var withRE = new RegExp(`with\\s+(${lexical.value.source})`);
|
||||
|
||||
module.exports = function(liquid) {
|
||||
|
||||
liquid.registerTag('layout', {
|
||||
parse: function(token, remainTokens){
|
||||
var match = lexical.value.exec(token.args);
|
||||
if(!match) error(`illegal token ${token.raw}`, token);
|
||||
|
||||
this.layout = match[0];
|
||||
this.tpls = liquid.parser.parse(remainTokens);
|
||||
},
|
||||
render: function(scope, hash) {
|
||||
var layout = Liquid.evalValue(this.layout, scope);
|
||||
var tpl = liquid.handleCache(layout);
|
||||
|
||||
scope.push({});
|
||||
liquid.renderer.renderTemplates(this.tpls, scope);
|
||||
var html = liquid.renderer.renderTemplates(tpl, scope);
|
||||
scope.pop();
|
||||
return html;
|
||||
}
|
||||
});
|
||||
|
||||
liquid.registerTag('block', {
|
||||
parse: function(token, remainTokens){
|
||||
var match = /\w+/.exec(token.args);
|
||||
this.block = match ? match[0] : '';
|
||||
|
||||
this.tpls = [];
|
||||
var p, stream = liquid.parser.parseStream(remainTokens)
|
||||
.on('tag:endblock', token => stream.stop())
|
||||
.on('template', tpl => this.tpls.push(tpl))
|
||||
.on('end', x => {
|
||||
throw new Error(`tag ${token.raw} not closed`);
|
||||
});
|
||||
stream.start();
|
||||
},
|
||||
render: function(scope, hash){
|
||||
var html = scope.get(`_liquid.blocks.${this.block}`);
|
||||
if(html === undefined){
|
||||
html = liquid.renderer.renderTemplates(this.tpls, scope);
|
||||
}
|
||||
scope.set(`_liquid.blocks.${this.block}`, html);
|
||||
return html;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
+1
-1
@@ -40,7 +40,7 @@ describe('expression', function() {
|
||||
expect(evalExp('one<=two', scope)).to.equal(true);
|
||||
expect(evalExp('x contains "x"', scope)).to.equal(false);
|
||||
expect(evalExp('x contains "X"', scope)).to.equal(true);
|
||||
expect(evalExp('x contains z', scope)).to.equal(true);
|
||||
expect(evalExp('x contains z', scope)).to.equal(false);
|
||||
expect(evalExp('"<=" == "<="', scope)).to.equal(true);
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ describe('scope', function() {
|
||||
scope.push({foo: 'foo', foo1: 'foo1'});
|
||||
scope.pop();
|
||||
expect(scope.get('foo')).to.equal('bar');
|
||||
expect(scope.get('foo1')).to.equal('');
|
||||
expect(scope.get('foo1')).to.equal(undefined);
|
||||
expect(scope.get('bar[1].b[1]')).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
+28
-1
@@ -31,6 +31,9 @@ describe('tags', function() {
|
||||
emptyArray: []
|
||||
};
|
||||
mock({
|
||||
'/default-layout.html': 'foo{% block %}Default{% endblock %}foo',
|
||||
'/multi-blocks-layout.html': 'foo{% block "a"%}{% endblock %}{% block b%}{%endblock%}foo',
|
||||
'/multi-blocks.html': '{% layout "multi-blocks-layout" %}{%block a%}aaa{%endblock%},{%block b%};{%block c%}ccc{%endblock%};{%endblock%}',
|
||||
'/files/foo.html': 'foo',
|
||||
'/current.html': 'bar{% include "foo.html" %}bar',
|
||||
'/relative.html': 'bar{% include "../files/foo.html" %}bar',
|
||||
@@ -202,6 +205,11 @@ describe('tags', function() {
|
||||
test(src, dst);
|
||||
});
|
||||
|
||||
it('should throw when tablerow not closed', function() {
|
||||
src = '{% tablerow i in (1..0) cols:2 %}{{ i }}';
|
||||
testThrow(src, /tag .* not closed/);
|
||||
});
|
||||
|
||||
it('should support tablerow with range', function() {
|
||||
src = '{% tablerow i in (1..5) cols:2 %}{{ i }}{% endtablerow %}';
|
||||
dst = '<table>' +
|
||||
@@ -257,5 +265,24 @@ describe('tags', function() {
|
||||
var dst = 'color:red, shape:rect';
|
||||
expect(liquid.renderFile(filepath, ctx)).to.equal(dst);
|
||||
});
|
||||
|
||||
it('should throw when block not closed', function() {
|
||||
src = '{% layout "default-layout" %}{%block%}bar';
|
||||
testThrow(src, /tag {%block%} not closed/);
|
||||
});
|
||||
it('should support layout', function() {
|
||||
src = '{% layout "default-layout" %}{%block%}bar{%endblock%}';
|
||||
test(src, 'foobarfoo');
|
||||
});
|
||||
it('should support layout: multiple blocks', function() {
|
||||
src = '{% layout "multi-blocks-layout" %}' +
|
||||
'{%block a%}bara{%endblock%}' +
|
||||
'{%block b%}barb{%endblock%}';
|
||||
test(src, 'foobarabarbfoo');
|
||||
});
|
||||
it('should support layout: nested', function() {
|
||||
src = '{% layout "multi-blocks" %}{% block a%}A{%endblock%}{%block c%}C{%endblock%}';
|
||||
test(src, 'fooA;C;foo');
|
||||
src = '{% layout "multi-blocks" %}{%block c%}C{%endblock%}';
|
||||
test(src, 'fooaaa;C;foo');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user