From 4e132ca1c5cf71d276ae25323e5d21516617ebc7 Mon Sep 17 00:00:00 2001 From: harttle Date: Sat, 4 Nov 2017 10:46:15 +0800 Subject: [PATCH] tags: use scope.opts insteadof scope.get('liquid') --- demo/express/app.js | 6 ++-- demo/express/index.js | 7 ++--- src/scope.js | 16 +++++----- src/util/error.js | 14 +++++---- tags/cycle.js | 68 +++++++++++++++++++++---------------------- tags/include.js | 9 +++--- tags/layout.js | 10 +++---- test/tags/layout.js | 22 ++++++++++---- 8 files changed, 79 insertions(+), 73 deletions(-) diff --git a/demo/express/app.js b/demo/express/app.js index 84bae0b06..9ec2dc1cd 100644 --- a/demo/express/app.js +++ b/demo/express/app.js @@ -3,13 +3,13 @@ var app = express() var Liquid = require('../..') var engine = Liquid({ - root: __dirname, // for layouts and partials + root: __dirname, // for layouts and partials extname: '.liquid' }) app.engine('liquid', engine.express()) // register liquid engine -app.set('views', ['./partials', './views']) // specify the views directory -app.set('view engine', 'liquid') // set to default +app.set('views', ['./partials', './views']) // specify the views directory +app.set('view engine', 'liquid') // set to default app.get('/', function (req, res) { var todos = ['fork and clone', 'make it better', 'make a pull request'] diff --git a/demo/express/index.js b/demo/express/index.js index 29778f6e3..5485b772d 100644 --- a/demo/express/index.js +++ b/demo/express/index.js @@ -1,6 +1,5 @@ -const app = require('./app.js'); +const app = require('./app.js') app.listen(3000, function () { - console.log('Example app listening on port 3000!'); -}); - + console.log('Example app listening on port 3000!') +}) diff --git a/src/scope.js b/src/scope.js index ce4c1fcbb..caf9a77ba 100644 --- a/src/scope.js +++ b/src/scope.js @@ -11,6 +11,9 @@ var Scope = { return ctx }, get: function (str) { + if (str === 'liquid') { + throw new Error('NO LONGER SUPPORTED: use scope.opts instread of scope.get("liquid")') + } try { return this.getPropertyByPath(this.scopes, str) } catch (e) { @@ -168,19 +171,14 @@ function matchRightBracket (str, begin) { } exports.factory = function (ctx, opts) { - opts = _.assign({ + var defaultOptions = { strict_variables: false, strict_filters: false, blocks: {}, root: [] - }, opts) - - ctx = _.assign(ctx, { - liquid: opts - }) - + } var scope = Object.create(Scope) - scope.opts = opts - scope.scopes = [ctx] + scope.opts = _.assign(defaultOptions, opts) + scope.scopes = [ctx || {}] return scope } diff --git a/src/util/error.js b/src/util/error.js index 3b8cc23cb..f919bcb08 100644 --- a/src/util/error.js +++ b/src/util/error.js @@ -7,7 +7,7 @@ function initError () { } } -function initLiquidError (message, token) { +function initLiquidError (err, token) { initError.call(this) this.input = token.input @@ -15,12 +15,14 @@ function initLiquidError (message, token) { this.file = token.file var context = mkContext(token.input, token.line) - this.message = mkMessage(message, token) - this.stack = context + '\n' + (this.stack || this.message) + this.message = mkMessage(err.message, token) + this.stack = context + + '\n' + (this.stack || this.message) + + (err.stack ? '\nFrom ' + err.stack : '') } function TokenizationError (message, token) { - initLiquidError.call(this, message, token) + initLiquidError.call(this, {message: message}, token) } TokenizationError.prototype = Object.create(Error.prototype) TokenizationError.prototype.constructor = TokenizationError @@ -29,7 +31,7 @@ function ParseError (e, token) { _.assign(this, e) this.originalError = e - initLiquidError.call(this, e.message, token) + initLiquidError.call(this, e, token) } ParseError.prototype = Object.create(Error.prototype) ParseError.prototype.constructor = ParseError @@ -42,7 +44,7 @@ function RenderError (e, tpl) { _.assign(this, e) this.originalError = e - initLiquidError.call(this, e.message, tpl.token) + initLiquidError.call(this, e, tpl.token) } RenderError.prototype = Object.create(Error.prototype) RenderError.prototype.constructor = RenderError diff --git a/tags/cycle.js b/tags/cycle.js index 07e779a9e..0cb79a0c9 100644 --- a/tags/cycle.js +++ b/tags/cycle.js @@ -1,44 +1,44 @@ -const Liquid = require('..'); -const Promise = require('any-promise'); -const lexical = Liquid.lexical; -const groupRE = new RegExp(`^(?:(${lexical.value.source})\\s*:\\s*)?(.*)$`); -const candidatesRE = new RegExp(lexical.value.source, 'g'); -const assert = require('../src/util/assert.js'); +const Liquid = require('..') +const Promise = require('any-promise') +const lexical = Liquid.lexical +const groupRE = new RegExp(`^(?:(${lexical.value.source})\\s*:\\s*)?(.*)$`) +const candidatesRE = new RegExp(lexical.value.source, 'g') +const assert = require('../src/util/assert.js') -module.exports = function(liquid) { - liquid.registerTag('cycle', { +module.exports = function (liquid) { + liquid.registerTag('cycle', { - parse: function(tagToken, remainTokens) { - var match = groupRE.exec(tagToken.args); - assert(match, `illegal tag: ${tagToken.raw}`); + parse: function (tagToken, remainTokens) { + var match = groupRE.exec(tagToken.args) + assert(match, `illegal tag: ${tagToken.raw}`) - this.group = match[1] || ''; - var candidates = match[2]; + this.group = match[1] || '' + var candidates = match[2] - this.candidates = []; + this.candidates = [] - while(match = candidatesRE.exec(candidates)){ - this.candidates.push(match[0]); - } + while ((match = candidatesRE.exec(candidates))) { + this.candidates.push(match[0]) + } + assert(this.candidates.length, `empty candidates: ${tagToken.raw}`) + }, - assert(this.candidates.length, `empty candidates: ${tagToken.raw}`); - }, + render: function (scope, hash) { + var group = Liquid.evalValue(this.group, scope) + var fingerprint = `cycle:${group}:` + this.candidates.join(',') - render: function(scope, hash) { - var group = Liquid.evalValue(this.group, scope); - var fingerprint = `cycle:${group}:` + this.candidates.join(','); - var register = scope.get('liquid'); - var idx = register[fingerprint]; + var groups = scope.opts.groups = scope.opts.groups || {} + var idx = groups[fingerprint] - if(idx === undefined){ - idx = register[fingerprint] = 0; - } + if (idx === undefined) { + idx = groups[fingerprint] = 0 + } - var candidate = this.candidates[idx]; - idx = (idx + 1) % this.candidates.length; - register[fingerprint] = idx; + var candidate = this.candidates[idx] + idx = (idx + 1) % this.candidates.length + groups[fingerprint] = idx - return Promise.resolve(Liquid.evalValue(candidate, scope)); - } - }); -}; + return Promise.resolve(Liquid.evalValue(candidate, scope)) + } + }) +} diff --git a/tags/include.js b/tags/include.js index e9e2c58cc..260b18639 100644 --- a/tags/include.js +++ b/tags/include.js @@ -18,21 +18,20 @@ module.exports = function (liquid) { render: function (scope, hash) { var filepath = Liquid.evalValue(this.value, scope) - var register = scope.get('liquid') - var originBlocks = register.blocks - register.blocks = {} + var originBlocks = scope.opts.blocks + scope.opts.blocks = {} if (this.with) { hash[filepath] = Liquid.evalValue(this.with, scope) } - return liquid.getTemplate(filepath, register.root) + return liquid.getTemplate(filepath, scope.opts.root) .then((templates) => { scope.push(hash) return liquid.renderer.renderTemplates(templates, scope) }) .then((html) => { scope.pop() - register.blocks = originBlocks + scope.opts.blocks = originBlocks return html }) } diff --git a/tags/layout.js b/tags/layout.js index f53e424e2..4ba84b64b 100644 --- a/tags/layout.js +++ b/tags/layout.js @@ -14,12 +14,11 @@ module.exports = function (liquid) { }, render: function (scope, hash) { var layout = Liquid.evalValue(this.layout, scope) - var register = scope.get('liquid') // render the remaining tokens immediately return liquid.renderer.renderTemplates(this.tpls, scope) // now register.blocks contains rendered blocks - .then(() => liquid.getTemplate(layout, register.root)) + .then(() => liquid.getTemplate(layout, scope.opts.root)) .then(templates => { // push the hash scope.push(hash) @@ -49,18 +48,17 @@ module.exports = function (liquid) { stream.start() }, render: function (scope) { - var register = scope.get('liquid') - var html = register.blocks[this.block] + var html = scope.opts.blocks[this.block] // if not defined yet if (html === undefined) { return liquid.renderer.renderTemplates(this.tpls, scope) .then((partial) => { - register.blocks[this.block] = partial + scope.opts.blocks[this.block] = partial return partial }) } else { // if already defined by desendents - register.blocks[this.block] = html + scope.opts.blocks[this.block] = html return Promise.resolve(html) } } diff --git a/test/tags/layout.js b/test/tags/layout.js index b5b47e458..c5444826a 100644 --- a/test/tags/layout.js +++ b/test/tags/layout.js @@ -24,13 +24,23 @@ describe('tags/layout', function () { return expect(liquid.parseAndRender(src)).to .be.rejectedWith(/tag {%block%} not closed/) }) - it('should handle anonymous block', function () { - mock({ - '/parent.html': 'X{%block%}{%endblock%}Y' + describe('anonymous block', function () { + it('should handle anonymous block', function () { + mock({ + '/parent.html': 'X{%block%}{%endblock%}Y' + }) + var src = '{% layout "parent.html" %}{%block%}A{%endblock%}' + return expect(liquid.parseAndRender(src)).to + .eventually.equal('XAY') + }) + it('should handle top level contents as anonymous block', function () { + mock({ + '/parent.html': 'X{%block%}{%endblock%}Y' + }) + var src = '{% layout "parent.html" %}A' + return expect(liquid.parseAndRender(src)).to + .eventually.equal('XAY') }) - var src = '{% layout "parent.html" %}{%block%}A{%endblock%}' - return expect(liquid.parseAndRender(src)).to - .eventually.equal('XAY') }) it('should handle named blocks', function () { mock({