diff --git a/src/scope.js b/src/scope.js index 8899165e4..09795f630 100644 --- a/src/scope.js +++ b/src/scope.js @@ -58,12 +58,17 @@ var Scope = { }, readProperty: function (obj, key) { let val - if (key === 'size' && (_.isArray(obj) || _.isString(obj))) { - val = obj.length - } else if (_.isNil(obj)) { + if (_.isNil(obj)) { val = undefined } else { - val = obj[key] + if (typeof obj.to_liquid === 'function') { + obj = obj.to_liquid() + } + if (key === 'size' && (_.isArray(obj) || _.isString(obj))) { + val = obj.length + } else { + val = obj[key] + } } if (_.isNil(val) && this.opts.strict_variables) { throw new TypeError(`undefined variable: ${key}`) diff --git a/src/util/underscore.js b/src/util/underscore.js index 8441f26fa..32b0b75fc 100644 --- a/src/util/underscore.js +++ b/src/util/underscore.js @@ -1,3 +1,4 @@ +'use strict' const toStr = Object.prototype.toString /* @@ -10,12 +11,12 @@ function isString (value) { } function stringify (value) { + if (value && typeof value.to_liquid === 'function') { + return stringify(value.to_liquid()) + } if (isString(value)) { return value } - if (value && typeof value.to_liquid === 'function') { - return value.to_liquid() - } let cache = [] return JSON.stringify(value, (key, value) => { diff --git a/test/render.js b/test/render.js index db1efef87..f0c78ed9a 100644 --- a/test/render.js +++ b/test/render.js @@ -1,3 +1,4 @@ +'use strict' const chai = require('chai') const chaiAsPromised = require('chai-as-promised') const expect = chai.expect @@ -42,7 +43,6 @@ describe('render', function () { let tpl = Template.parseValue('bar') return expect(render.renderValue(tpl, scope)).to.eventually.equal('custom') }) - it('should stringify objects', function () { let scope = Scope.factory({ foo: { obj: { arr: ['a', 2] } } @@ -65,20 +65,6 @@ describe('render', function () { }) }) - it('should eval filter with correct arguments', function () { - let date = sinon.stub().returns('y') - let time = sinon.spy() - filter.register('date', date) - filter.register('time', time) - let tpl = Template.parseValue('foo.bar | date: "b" | time:2') - let scope = Scope.factory({ - foo: {bar: 'bar'} - }) - render.evalValue(tpl, scope) - expect(date).to.have.been.calledWith('bar', 'b') - expect(time).to.have.been.calledWith('y', 2) - }) - describe('.evalValue()', function () { it('should throw when scope undefined', function () { expect(function () { @@ -99,5 +85,18 @@ describe('render', function () { let tpl = Template.parseValue('"x" | arr') expect(render.evalValue(tpl, Scope.factory())).to.deep.equal([1]) }) + it('should eval filter with correct arguments', function () { + let date = sinon.stub().returns('y') + let time = sinon.spy() + filter.register('date', date) + filter.register('time', time) + let tpl = Template.parseValue('foo.bar | date: "b" | time:2') + let scope = Scope.factory({ + foo: {bar: 'bar'} + }) + render.evalValue(tpl, scope) + expect(date).to.have.been.calledWith('bar', 'b') + expect(time).to.have.been.calledWith('y', 2) + }) }) }) diff --git a/test/scope.js b/test/scope.js index 889d61d93..7bce0783e 100644 --- a/test/scope.js +++ b/test/scope.js @@ -88,6 +88,14 @@ describe('scope', function () { }).to.throw(/unbalanced '/) }) + it('should respect to to_liquid', function () { + let scope = Scope.factory({foo: { + to_liquid: () => ({bar: 'BAR'}), + bar: 'bar' + }}) + expect(scope.get('foo.bar')).to.equal('BAR') + }) + it('should access child property via dot syntax', function () { expect(scope.get('bar.zoo')).to.equal('coo') expect(scope.get('bar.arr')).to.deep.equal(['a', 'b'])