From 1124d9e4c0093207c9faf1f4402fee9de692a3bf Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Thu, 13 Feb 2014 16:15:29 +0000 Subject: [PATCH] Helper updates for Tag Pages fixes #2112 refs #1833 - modified config.urlFor to handle tag pages - modified {{#tags}} handlebars helper to autolink to tag pages. Additional autolink="false" parameter can be used to deactivate autolinking - modified url handlebars helper to handle tags - added isTag function to schema - added unit test for additional urlFor functionality - added unit test for {{#tags}} helper modifications - added unit test for url handlebards helper --- core/server/config/url.js | 2 ++ core/server/data/schema.js | 8 ++++- core/server/helpers/index.js | 29 +++++++++++++++--- core/test/unit/config_spec.js | 13 ++++++++ core/test/unit/server_helpers_index_spec.js | 34 ++++++++++++++++----- 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/core/server/config/url.js b/core/server/config/url.js index ac5b39fc4c..1cf316c1e2 100644 --- a/core/server/config/url.js +++ b/core/server/config/url.js @@ -114,6 +114,8 @@ function urlFor(context, data, absolute) { // trying to create a url for an object if (context === 'post' && data.post && data.permalinks) { urlPath = urlPathForPost(data.post, data.permalinks); + } else if (context === 'tag' && data.tag) { + urlPath = '/tag/' + data.tag.slug + '/'; } // other objects are recognised but not yet supported } else if (_.isString(context) && _.indexOf(_.keys(knownPaths), context) !== -1) { diff --git a/core/server/data/schema.js b/core/server/data/schema.js index fec7efb26a..4d31dbda87 100644 --- a/core/server/data/schema.js +++ b/core/server/data/schema.js @@ -123,7 +123,13 @@ function isPost(jsonData) { && jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug'); } +function isTag(jsonData) { + return jsonData.hasOwnProperty('name') && jsonData.hasOwnProperty('slug') + && jsonData.hasOwnProperty('description') && jsonData.hasOwnProperty('parent_id'); +} + module.exports.tables = db; module.exports.checks = { - isPost: isPost + isPost: isPost, + isTag: isTag }; \ No newline at end of file diff --git a/core/server/helpers/index.js b/core/server/helpers/index.js index 525fcc4bbc..39f6658daf 100644 --- a/core/server/helpers/index.js +++ b/core/server/helpers/index.js @@ -15,6 +15,7 @@ var downsize = require('downsize'), updateCheck = require('../update-check'), assetTemplate = _.template('<%= source %>?v=<%= version %>'), + linkTemplate = _.template('<%= text %>'), scriptTemplate = _.template(''), isProduction = process.env.NODE_ENV === 'production', @@ -111,6 +112,10 @@ coreHelpers.url = function (options) { return config.urlForPost(api.settings, this, absolute); } + if (schema.isTag(this)) { + return when(config.urlFor('tag', {tag: this}, absolute)); + } + return when(config.urlFor(this, absolute)); }; @@ -174,14 +179,28 @@ coreHelpers.author = function (context, options) { // Note that the standard {{#each tags}} implementation is unaffected by this helper // and can be used for more complex templates. coreHelpers.tags = function (options) { - var separator = _.isString(options.hash.separator) ? options.hash.separator : ', ', + var autolink = _.isString(options.hash.autolink) && options.hash.autolink === "false" ? false : true, + separator = _.isString(options.hash.separator) ? options.hash.separator : ', ', prefix = _.isString(options.hash.prefix) ? options.hash.prefix : '', suffix = _.isString(options.hash.suffix) ? options.hash.suffix : '', - output = '', - tagNames = _.pluck(this.tags, 'name'); + output = ''; - if (tagNames.length) { - output = prefix + _.escape(tagNames.join(separator)) + suffix; + function createTagList(tags) { + var tagNames = _.pluck(tags, 'name'); + + if (autolink) { + return _.map(tags, function (tag) { + return linkTemplate({ + url: config.urlFor('tag', {tag: tag}), + text: _.escape(tag.name) + }); + }).join(separator); + } + return _.escape(tagNames.join(separator)); + } + + if (this.tags && this.tags.length) { + output = prefix + createTagList(this.tags) + suffix; } return new hbs.handlebars.SafeString(output); diff --git a/core/test/unit/config_spec.js b/core/test/unit/config_spec.js index baaf063ba9..fdf9df53d2 100644 --- a/core/test/unit/config_spec.js +++ b/core/test/unit/config_spec.js @@ -235,6 +235,19 @@ describe('Config', function () { config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog' + postLink); }); + it('should return url for a tag when asked for', function () { + var testContext = 'tag', + testData = {tag: testUtils.DataGenerator.Content.tags[0]}; + + configUpdate({url: 'http://my-ghost-blog.com'}); + config.urlFor(testContext, testData).should.equal('/tag/kitchen-sink/'); + config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/tag/kitchen-sink/'); + + configUpdate({url: 'http://my-ghost-blog.com/blog'}); + config.urlFor(testContext, testData).should.equal('/blog/tag/kitchen-sink/'); + config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog/tag/kitchen-sink/'); + }); + }); describe('urlForPost', function () { diff --git a/core/test/unit/server_helpers_index_spec.js b/core/test/unit/server_helpers_index_spec.js index 12052382c5..4bcf50bfd5 100644 --- a/core/test/unit/server_helpers_index_spec.js +++ b/core/test/unit/server_helpers_index_spec.js @@ -449,7 +449,14 @@ describe('Core Helpers', function () { }); }); - it('should return empty string if not a post', function () { + it('should return the slug with a prefixed /tag/ if the context is a tag', function () { + helpers.url.call({name: 'the tag', slug: "the-tag", description: null, parent_id: null}).then(function (rendered) { + should.exist(rendered); + rendered.should.equal('/tag/the-tag/'); + }); + }); + + it('should return empty string if not a post or tag', function () { helpers.url.call({markdown: "ff", title: "title", slug: "slug"}).then(function (rendered) { rendered.should.equal(''); }); @@ -585,7 +592,7 @@ describe('Core Helpers', function () { var tags = [{name: 'foo'}, {name: 'bar'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {}} + {"hash": {autolink: 'false'}} ); should.exist(rendered); @@ -596,7 +603,7 @@ describe('Core Helpers', function () { var tags = [{name: 'haunted'}, {name: 'ghost'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {separator: '|'}} + {"hash": {separator: '|', autolink: 'false'}} ); should.exist(rendered); @@ -608,7 +615,7 @@ describe('Core Helpers', function () { var tags = [{name: 'haunted'}, {name: 'ghost'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {prefix: 'on '}} + {"hash": {prefix: 'on ', autolink: 'false'}} ); should.exist(rendered); @@ -620,7 +627,7 @@ describe('Core Helpers', function () { var tags = [{name: 'haunted'}, {name: 'ghost'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {suffix: ' forever'}} + {"hash": {suffix: ' forever', autolink: 'false'}} ); should.exist(rendered); @@ -632,7 +639,7 @@ describe('Core Helpers', function () { var tags = [{name: 'haunted'}, {name: 'ghost'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {suffix: ' forever', prefix: 'on '}} + {"hash": {suffix: ' forever', prefix: 'on ', autolink: 'false'}} ); should.exist(rendered); @@ -644,7 +651,7 @@ describe('Core Helpers', function () { var tags = [{name: 'haunted'}, {name: 'ghost'}], rendered = handlebars.helpers.tags.call( {tags: tags}, - {"hash": {suffix: ' •', prefix: '… '}} + {"hash": {suffix: ' •', prefix: '… ', autolink: 'false'}} ); should.exist(rendered); @@ -655,13 +662,24 @@ describe('Core Helpers', function () { it('does not add prefix or suffix if no tags exist', function () { var rendered = handlebars.helpers.tags.call( {}, - {"hash": {prefix: 'on ', suffix: ' forever'}} + {"hash": {prefix: 'on ', suffix: ' forever', autolink: 'false'}} ); should.exist(rendered); String(rendered).should.equal(''); }); + + it('can autolink tags to tag pages', function () { + var tags = [{name: 'foo', slug: 'foo-bar'}, {name: 'bar', slug: 'bar'}], + rendered = handlebars.helpers.tags.call( + {tags: tags}, + {"hash": {}} + ); + should.exist(rendered); + + String(rendered).should.equal('foo, bar'); + }); }); describe("meta_title helper", function () {