diff --git a/core/server/helpers/has.js b/core/server/helpers/has.js index bd2830ae56..669ea86b3e 100644 --- a/core/server/helpers/has.js +++ b/core/server/helpers/has.js @@ -40,6 +40,14 @@ function evaluateIntegerMatch(expr, integer) { }, false); } +function evaluateStringMatch(expr, str, ci) { + if (ci) { + return expr && str && expr.toLocaleLowerCase() === str.toLocaleLowerCase(); + } + + return expr === str; +} + module.exports = function has(options) { options = options || {}; options.hash = options.hash || {}; @@ -48,16 +56,22 @@ module.exports = function has(options) { author = this.author ? this.author.name : null, number = options.data.number, index = options.data.index, + slug = this.slug, + id = this.id, tagList = options.hash.tag || false, authorList = options.hash.author || false, numberList = options.hash.number || false, indexList = options.hash.index || false, + slugParam = options.hash.slug || false, + idParam = options.hash.id || false, tagsOk, authorOk, numberOk, - indexOk; + indexOk, + slugOk, + idOk; - if (!tagList && !authorList && !numberList && !indexList) { + if (!tagList && !authorList && !numberList && !indexList && !slugParam && !idParam) { logging.warn(i18n.t('warnings.helpers.has.invalidAttribute')); return; } @@ -66,8 +80,10 @@ module.exports = function has(options) { authorOk = authorList && evaluateAuthorList(authorList, author) || false; numberOk = numberList && evaluateIntegerMatch(numberList, number) || false; indexOk = indexList && evaluateIntegerMatch(indexList, index) || false; + slugOk = slugParam && evaluateStringMatch(slugParam, slug, true) || false; + idOk = idParam && evaluateStringMatch(idParam, id, true) || false; - if (tagsOk || authorOk || numberOk || indexOk) { + if (tagsOk || authorOk || numberOk || indexOk || slugOk || idOk) { return options.fn(this); } return options.inverse(this); diff --git a/core/test/unit/server_helpers/has_spec.js b/core/test/unit/server_helpers/has_spec.js index 3d7c912599..88e056e5f0 100644 --- a/core/test/unit/server_helpers/has_spec.js +++ b/core/test/unit/server_helpers/has_spec.js @@ -344,4 +344,68 @@ describe('{{#has}} helper', function () { inverse.callCount.should.eql(5); }); }); + + describe('slug match', function () { + it('matches on an exact slug (pass)', function () { + thisCtx = {slug: 'welcome'}; + + // {{#has slug="welcome"}} + callHasHelper(thisCtx, {slug: 'welcome'}); + + fn.called.should.be.true(); + inverse.called.should.be.false(); + }); + + it('matches on an exact slug (fail)', function () { + thisCtx = {slug: 'welcome'}; + + // {{#has slug="welcome-to-ghost"}} + callHasHelper(thisCtx, {slug: 'welcome-to-ghost'}); + + fn.called.should.be.false(); + inverse.called.should.be.true(); + }); + + it('fails gracefully if there is no slug (fail)', function () { + thisCtx = {}; + + // {{#has slug="welcome-to-ghost"}} + callHasHelper(thisCtx, {slug: 'welcome-to-ghost'}); + + fn.called.should.be.false(); + inverse.called.should.be.true(); + }); + }); + + describe('id match', function () { + it('matches on an exact id (pass)', function () { + thisCtx = {id: '5981fbed98141579627e9a5a'}; + + // {{#has id="5981fbed98141579627e9a5a"}} + callHasHelper(thisCtx, {id: '5981fbed98141579627e9a5a'}); + + fn.called.should.be.true(); + inverse.called.should.be.false(); + }); + + it('matches on an exact id (fail)', function () { + thisCtx = {id: '5981fbed98141579627e9a5a'}; + + // {{#has id="5981fbed98141579627e9a5a"}} + callHasHelper(thisCtx, {id: '5981fbed98141579627e9abc'}); + + fn.called.should.be.false(); + inverse.called.should.be.true(); + }); + + it('fails gracefully if there is no id (fail)', function () { + thisCtx = {}; + + // {{#has id="5981fbed98141579627e9a5a"}} + callHasHelper(thisCtx, {id: '5981fbed98141579627e9abc'}); + + fn.called.should.be.false(); + inverse.called.should.be.true(); + }); + }); });