Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

shopify-liquid

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shopify-liquid - npm Package Compare versions

Comparing version 1.1.1 to 1.1.2

parser.js

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 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc