shopify-liquid
Advanced tools
Comparing version 1.1.1 to 1.1.2
69
index.js
@@ -9,59 +9,60 @@ const scope = require('./scope'); | ||
const Filter = require('./filter.js'); | ||
const error = require('./error.js'); | ||
const Template = require('./template'); | ||
const Template = require('./parser'); | ||
const Expression = require('./expression.js'); | ||
const tagsPath = path.join(__dirname, "tags"); | ||
var _engine = { | ||
registerFilter : function(name, filter){ | ||
init: function(tag, filter) { | ||
this.tag = tag; | ||
this.filter = filter; | ||
this.parser = Template(tag, filter); | ||
this.renderer = Render(); | ||
return this; | ||
}, | ||
parse: function(html) { | ||
var tokens = tokenizer.parse(html); | ||
return this.parser.parse(tokens); | ||
}, | ||
render: function(tpl, ctx) { | ||
this.renderer.resetRegisters(); | ||
return this.renderer.renderTemplates(tpl, scope.factory(ctx)); | ||
}, | ||
parseAndRender: function(html, ctx) { | ||
var tpl = this.parse(html); | ||
return this.render(tpl, ctx); | ||
}, | ||
evalOutput: function(str, scope) { | ||
var tpl = this.parser.parseOutput(str.trim()); | ||
return this.renderer.evalOutput(tpl, scope); | ||
}, | ||
registerFilter: function(name, filter) { | ||
return this.filter.register(name, filter); | ||
}, | ||
registerTag : function(name, tag){ | ||
registerTag: function(name, tag) { | ||
return this.tag.register(name, tag); | ||
} | ||
}, | ||
}; | ||
function factory(){ | ||
function factory() { | ||
var engine = Object.create(_engine); | ||
engine.init(Tag(), Filter()); | ||
registerTagsAndFilters(engine); | ||
return engine; | ||
} | ||
engine.tag = Tag(); | ||
engine.filter = Filter(); | ||
engine.tokenize = tokenizer.parse; | ||
engine.template = Template(engine.tag, engine.filter); | ||
engine.parseStream = engine.template.parseStream; | ||
var renderer = Render(engine.filter, engine.tag); | ||
engine.renderTemplates = renderer.renderTemplates; | ||
engine.render = function(html, ctx) { | ||
var tokens = engine.tokenize(html); | ||
var templates = engine.template.parse(tokens); | ||
engine.register = {}; | ||
return engine.renderTemplates(templates, scope.factory(ctx)); | ||
}; | ||
engine.evalOutput = function(str, scope) { | ||
var template = engine.template.parseOutput(str.trim()); | ||
return renderer.evalOutput(template, scope); | ||
}; | ||
fs.readdirSync(tagsPath).map(function(f){ | ||
function registerTagsAndFilters(engine) { | ||
fs.readdirSync(tagsPath).map(f => { | ||
var match = /^(\w+)\.js$/.exec(f); | ||
if(!match) return; | ||
if (!match) return; | ||
require("./tags/" + f)(engine); | ||
}); | ||
require("./filters.js")(engine); | ||
return engine; | ||
} | ||
factory.lexical = lexical; | ||
factory.error = error; | ||
factory.isTruthy = Expression.isTruthy; | ||
factory.isFalsy = Expression.isFalsy; | ||
factory.stringify = Render.stringify; | ||
factory.evalExp = Expression.evalExp; | ||
factory.evalValue = Expression.evalValue; | ||
module.exports = factory; |
{ | ||
"name": "shopify-liquid", | ||
"version": "1.1.1", | ||
"version": "1.1.2", | ||
"description": "A Shopify Liquid Implementation in Node.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -14,2 +14,54 @@ # shopify-liquid | ||
## Usage | ||
Install: | ||
```bash | ||
npm install --save shopify-liquid | ||
``` | ||
Parse and Render: | ||
```javascript | ||
var Liquid = require('shopify-liquid'); | ||
var engine = Liquid(); | ||
engine.parseAndRender('{{name | capitalize}}', {name: 'alice'}); // Alice | ||
``` | ||
Caching templates: | ||
```javascript | ||
var tpl = engine.parse('{{name | capitalize}}'); | ||
engine.render(tpl, {name: 'alice'}); // Alice | ||
``` | ||
Register Filters: | ||
```javascript | ||
// Usage: {{ name | uppper }} | ||
engine.registerFilter('upper', function(v){ | ||
return v.toUpperCase(); | ||
}); | ||
``` | ||
> See existing filter implementations: <https://github.com/harttle/shopify-liquid/blob/master/filters.js> | ||
Register Tags: | ||
```javascript | ||
// Usage: {% upper name%} | ||
engine.registerTag('upper', { | ||
parse: function(tagToken, remainTokens) { | ||
this.str = tagToken.args; // name | ||
}, | ||
render: function(scope, hash) { | ||
var str = Liquid.evalValue(this.str, scope); // 'alice' | ||
return str.toUpperCase(); // 'Alice' | ||
} | ||
}); | ||
``` | ||
> See existing tag implementations: <https://github.com/harttle/shopify-liquid/blob/master/tags/> | ||
## Operators | ||
@@ -41,2 +93,4 @@ | ||
- [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] | ||
@@ -43,0 +97,0 @@ |
@@ -5,12 +5,8 @@ const error = require('./error.js'); | ||
function stringify(val) { | ||
if (typeof val === 'string') return val; | ||
return JSON.stringify(val); | ||
} | ||
var render = { | ||
function factory(Filter, Tag) { | ||
function renderTemplates(templates, scope) { | ||
renderTemplates: function(templates, scope) { | ||
assert(scope, 'unable to evalTemplates: scope undefined'); | ||
var html = '', partial; | ||
var html = '', | ||
partial; | ||
templates.some(template => { | ||
@@ -20,4 +16,4 @@ if (scope.get('forloop.skip')) return true; | ||
case 'tag': | ||
partial = renderTag(template, scope, this.register); | ||
if(partial === undefined) return true; | ||
partial = this.renderTag(template, scope, this.register); | ||
if (partial === undefined) return true; | ||
html += partial; | ||
@@ -29,3 +25,3 @@ break; | ||
case 'output': | ||
var val = evalOutput(template, scope); | ||
var val = this.evalOutput(template, scope); | ||
html += stringify(val); | ||
@@ -35,5 +31,5 @@ } | ||
return html; | ||
} | ||
}, | ||
function renderTag(template, scope, register) { | ||
renderTag: function(template, scope, register) { | ||
if (template.name === 'continue') { | ||
@@ -49,5 +45,5 @@ scope.set('forloop.skip', true); | ||
return template.render(scope, register); | ||
} | ||
}, | ||
function evalOutput(template, scope) { | ||
evalOutput: function(template, scope) { | ||
assert(scope, 'unable to evalOutput: scope undefined'); | ||
@@ -57,11 +53,20 @@ var val = Exp.evalExp(template.initial, scope); | ||
.reduce((v, filter) => filter.render(v, scope), val); | ||
}, | ||
resetRegisters: function(){ | ||
return this.register = {}; | ||
} | ||
}; | ||
return { | ||
renderTemplates, evalOutput, renderTag | ||
}; | ||
function factory() { | ||
var instance = Object.create(render); | ||
instance.register = {}; | ||
return instance; | ||
} | ||
factory.stringify = stringify; | ||
function stringify(val) { | ||
if (typeof val === 'string') return val; | ||
return JSON.stringify(val); | ||
} | ||
module.exports = factory; |
@@ -24,3 +24,3 @@ const lexical = require('./lexical.js'); | ||
var obj = hash(this.token.args, scope); | ||
return this.tagImpl.render(scope, obj, reg) || ''; | ||
return this.tagImpl.render && this.tagImpl.render(scope, obj, reg) || ''; | ||
}, | ||
@@ -42,5 +42,2 @@ parse: function(token, tokens){ | ||
function register(name, tag) { | ||
if (typeof tag.render !== 'function') { | ||
throw new Error(`expect ${name}.render to be a function`); | ||
} | ||
tagImpls[name] = tag; | ||
@@ -47,0 +44,0 @@ } |
@@ -15,6 +15,6 @@ var Liquid = require('..'); | ||
var stream = liquid.parseStream(remainTokens); | ||
stream.onTag('endcapture', token => stream.stop()) | ||
.onTemplate(tpl => this.templates.push(tpl)) | ||
.onEnd(x => { | ||
var stream = liquid.parser.parseStream(remainTokens); | ||
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`); | ||
@@ -25,3 +25,3 @@ }); | ||
render: function(scope, hash) { | ||
var html = liquid.renderTemplates(this.templates, scope); | ||
var html = liquid.renderer.renderTemplates(this.templates, scope); | ||
scope.set(this.variable, html); | ||
@@ -28,0 +28,0 @@ } |
@@ -13,4 +13,4 @@ var Liquid = require('..'); | ||
var p = [], | ||
stream = liquid.parseStream(remainTokens) | ||
.onTag('when', token => { | ||
stream = liquid.parser.parseStream(remainTokens) | ||
.on('tag:when', token => { | ||
if (!this.cases[token.args]) { | ||
@@ -23,6 +23,6 @@ this.cases.push({ | ||
}) | ||
.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`); | ||
@@ -40,6 +40,6 @@ }); | ||
if (val === cond) { | ||
return liquid.renderTemplates(branch.templates, scope); | ||
return liquid.renderer.renderTemplates(branch.templates, scope); | ||
} | ||
} | ||
return liquid.renderTemplates(this.elseTemplates, scope); | ||
return liquid.renderer.renderTemplates(this.elseTemplates, scope); | ||
} | ||
@@ -46,0 +46,0 @@ |
@@ -21,8 +21,8 @@ var Liquid = require('..'); | ||
var p, stream = liquid.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 => { | ||
var p, stream = liquid.parser.parseStream(remainTokens) | ||
.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`); | ||
@@ -37,3 +37,3 @@ }); | ||
if (Liquid.isFalsy(collection)) { | ||
return liquid.renderTemplates(this.elseTemplates, scope); | ||
return liquid.renderer.renderTemplates(this.elseTemplates, scope); | ||
} | ||
@@ -63,3 +63,3 @@ | ||
scope.push(ctx); | ||
html += liquid.renderTemplates(this.templates, scope); | ||
html += liquid.renderer.renderTemplates(this.templates, scope); | ||
var breakloop = scope.get('forloop.stop'); | ||
@@ -66,0 +66,0 @@ scope.pop(ctx); |
@@ -12,8 +12,8 @@ var Liquid = require('..'); | ||
var p, stream = liquid.parseStream(remainTokens) | ||
.onStart(x => this.branches.push({ | ||
var p, stream = liquid.parser.parseStream(remainTokens) | ||
.on('start', x => this.branches.push({ | ||
cond: tagToken.args, | ||
templates: p = [] | ||
})) | ||
.onTag('elsif', token => { | ||
.on('tag:elsif', token => { | ||
if (!this.branches[token.args]) { | ||
@@ -26,6 +26,6 @@ this.branches.push({ | ||
}) | ||
.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`); | ||
@@ -42,6 +42,6 @@ }); | ||
if (Liquid.isTruthy(cond)) { | ||
return liquid.renderTemplates(branch.templates, scope); | ||
return liquid.renderer.renderTemplates(branch.templates, scope); | ||
} | ||
} | ||
return liquid.renderTemplates(this.elseTemplates, scope); | ||
return liquid.renderer.renderTemplates(this.elseTemplates, scope); | ||
} | ||
@@ -48,0 +48,0 @@ |
@@ -18,7 +18,7 @@ var Liquid = require('..'); | ||
var p, stream = liquid.parseStream(remainTokens) | ||
.onStart(x => p = this.templates) | ||
.onTag('endtablerow', token => stream.stop()) | ||
.onTemplate(tpl => p.push(tpl)) | ||
.onEnd(x => { | ||
var p, stream = liquid.parser.parseStream(remainTokens) | ||
.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`); | ||
@@ -55,3 +55,3 @@ }); | ||
html += `<td class="col${col}">`; | ||
html += liquid.renderTemplates(this.templates, scope); | ||
html += liquid.renderer.renderTemplates(this.templates, scope); | ||
html += '</td>'; | ||
@@ -58,0 +58,0 @@ scope.pop(ctx); |
@@ -7,11 +7,11 @@ var Liquid = require('..'); | ||
parse: function(tagToken, remainTokens) { | ||
var p, stream = liquid.parseStream(remainTokens) | ||
.onStart(x => { | ||
var p, stream = liquid.parser.parseStream(remainTokens) | ||
.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`); | ||
@@ -26,6 +26,6 @@ }); | ||
return Liquid.isFalsy(cond) ? | ||
liquid.renderTemplates(this.templates, scope) : | ||
liquid.renderTemplates(this.elseTemplates, scope); | ||
liquid.renderer.renderTemplates(this.templates, scope) : | ||
liquid.renderer.renderTemplates(this.elseTemplates, scope); | ||
} | ||
}); | ||
}; |
@@ -20,2 +20,3 @@ const lexical = require('./lexical.js'); | ||
type: 'html', | ||
raw: htmlFragment, | ||
value: htmlFragment | ||
@@ -51,2 +52,3 @@ }); | ||
type: 'html', | ||
raw: htmlFragment, | ||
value: htmlFragment | ||
@@ -53,0 +55,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50373
29
980
165