Skip to content

Commit

Permalink
Created image helper with absolute url option
Browse files Browse the repository at this point in the history
closes #4231

- Adds {{image}} helper
- Adds image_spec test unit
- Updated {{ghost_head}} to use image helper
  • Loading branch information
cobbspur committed Oct 28, 2014
1 parent f6eccf4 commit 4a56d10
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 33 deletions.
9 changes: 7 additions & 2 deletions core/server/config/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ function urlPathForPost(post, permalinks) {
// This is probably not the right place for this, but it's the best place for now
function urlFor(context, data, absolute) {
var urlPath = '/',
secure,
knownObjects = ['post', 'tag', 'author'],
secure, imagePathRe,
knownObjects = ['post', 'tag', 'author', 'image'],

// this will become really big
knownPaths = {
Expand Down Expand Up @@ -133,6 +133,11 @@ function urlFor(context, data, absolute) {
} else if (context === 'author' && data.author) {
urlPath = '/author/' + data.author.slug + '/';
secure = data.author.secure;
} else if (context === 'image' && data.image) {
urlPath = data.image;
imagePathRe = new RegExp('^' + ghostConfig.paths.subdir + '/' + ghostConfig.paths.imagesRelPath);
absolute = imagePathRe.test(data.image) ? absolute : false;
secure = data.image.secure;
}
// other objects are recognised but not yet supported
} else if (_.isString(context) && _.indexOf(_.keys(knownPaths), context) !== -1) {
Expand Down
21 changes: 11 additions & 10 deletions core/server/helpers/ghost_head.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var hbs = require('express-hbs'),
meta_title = require('./meta_title'),
excerpt = require('./excerpt'),
tagsHelper = require('./tags'),
imageHelper = require('./image'),
ghost_head;

ghost_head = function (options) {
Expand All @@ -42,12 +43,21 @@ ghost_head = function (options) {
ops.push(urlHelper.call(self, {hash: {absolute: true}}));
ops.push(meta_description.call(self));
ops.push(meta_title.call(self));
if (self.post) {
ops.push(imageHelper.call(self.post, {hash: {absolute:true}}));

if (self.post.author) {
ops.push(imageHelper.call(self.post.author, {hash: {absolute:true}}));
}
}

// Resolves promises then push pushes meta data into ghost_head
return Promise.settle(ops).then(function (results) {
var url = results[0].value(),
metaDescription = results[1].value(),
metaTitle = results[2].value(),
coverImage = results.length > 3 ? results[3].value() : null,
authorImage = results.length > 4 ? results[4].value() : null,
publishedDate, modifiedDate,
tags = tagsHelper.call(self.post, {hash: {autolink: 'false'}}).string.split(','),
card = 'summary',
Expand Down Expand Up @@ -80,19 +90,10 @@ ghost_head = function (options) {
publishedDate = moment(self.post.published_at).toISOString();
modifiedDate = moment(self.post.updated_at).toISOString();

if (self.post.image) {
coverImage = self.post.image;
// Test to see if image was linked by url or uploaded
coverImage = coverImage.substring(0, 4) === 'http' ? coverImage : hbs.handlebars.Utils.escapeExpression(blog.url + coverImage);
if (coverImage) {
card = 'summary_large_image';
}

if (self.post.author.image) {
authorImage = self.post.author.image;
// Test to see if image was linked by url or uploaded
authorImage = authorImage.substring(0, 4) === 'http' ? authorImage : hbs.handlebars.Utils.escapeExpression(blog.url + authorImage);
}

// escaped data
metaTitle = hbs.handlebars.Utils.escapeExpression(metaTitle);
metaDescription = hbs.handlebars.Utils.escapeExpression(metaDescription + '...');
Expand Down
20 changes: 20 additions & 0 deletions core/server/helpers/image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

// Usage: `{{image}}`, `{{image absolute="true"}}`
//
// Returns the URL for the current object scope i.e. If inside a post scope will return image permalink
// `absolute` flag outputs absolute URL, else URL is relative.

var Promise = require('bluebird'),
config = require('../config'),
image;

image = function (options) {
var absolute = options && options.hash.absolute;
if (this.image) {
return Promise.resolve(config.urlFor('image', {image: this.image}, absolute));
} else {
return Promise.resolve();
}
};

module.exports = image;
2 changes: 2 additions & 0 deletions core/server/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ coreHelpers.post_class = require('./post_class');
coreHelpers.tags = require('./tags');
coreHelpers.title = require('./title');
coreHelpers.url = require('./url');
coreHelpers.image = require('./image');

coreHelpers.ghost_script_tags = require('./ghost_script_tags');

Expand Down Expand Up @@ -146,6 +147,7 @@ registerHelpers = function (adminHbs) {
registerAsyncThemeHelper('meta_title', coreHelpers.meta_title);
registerAsyncThemeHelper('post_class', coreHelpers.post_class);
registerAsyncThemeHelper('url', coreHelpers.url);
registerAsyncThemeHelper('image', coreHelpers.image);

// Register admin helpers
registerAdminHelper('ghost_script_tags', coreHelpers.ghost_script_tags);
Expand Down
42 changes: 21 additions & 21 deletions core/test/unit/server_helpers/ghost_head_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ describe('{{ghost_head}} helper', function () {
var post = {
meta_description: 'blog description',
title: 'Welcome to Ghost',
image: '/test-image.png',
image: '/content/images/test-image.png',
published_at: moment('2008-05-31T19:18:15').toISOString(),
updated_at: moment('2014-10-06T15:23:54').toISOString(),
tags: [{name: 'tag1'}, {name: 'tag2'}, {name: 'tag3'}],
author: {
name: 'Author name',
url: 'http//:testauthorurl.com',
slug: 'Author',
image: '/test-author-image.png',
image: '/content/images/test-author-image.png',
website: 'http://authorwebsite.com'
}
};
Expand All @@ -75,7 +75,7 @@ describe('{{ghost_head}} helper', function () {
' <meta property="og:title" content="Welcome to Ghost" />\n' +
' <meta property="og:description" content="blog description..." />\n' +
' <meta property="og:url" content="http://testurl.com/post/" />\n' +
' <meta property="og:image" content="http://testurl.com/test-image.png" />\n' +
' <meta property="og:image" content="http://testurl.com/content/images/test-image.png" />\n' +
' <meta property="article:published_time" content="' + post.published_at + '" />\n' +
' <meta property="article:modified_time" content="' + post.updated_at + '" />\n' +
' <meta property="article:tag" content="tag1" />\n' +
Expand All @@ -85,15 +85,15 @@ describe('{{ghost_head}} helper', function () {
' <meta name="twitter:title" content="Welcome to Ghost" />\n' +
' <meta name="twitter:description" content="blog description..." />\n' +
' <meta name="twitter:url" content="http://testurl.com/post/" />\n' +
' <meta name="twitter:image:src" content="http://testurl.com/test-image.png" />\n \n' +
' <meta name="twitter:image:src" content="http://testurl.com/content/images/test-image.png" />\n \n' +
' <script type=\"application/ld+json\">\n{\n' +
' "@context": "http://schema.org",\n "@type": "Article",\n "publisher": "Ghost",\n' +
' "author": {\n "@type": "Person",\n "name": "Author name",\n ' +
' \"image\": \"http://testurl.com/test-author-image.png\",\n ' +
' \"image\": \"http://testurl.com/content/images/test-author-image.png\",\n ' +
' "url": "http://testurl.com/author/Author",\n "sameAs": "http://authorwebsite.com"\n ' +
'},\n "headline": "Welcome to Ghost",\n "url": "http://testurl.com/post/",\n' +
' "datePublished": "' + post.published_at + '",\n "dateModified": "' + post.updated_at + '",\n' +
' "image": "http://testurl.com/test-image.png",\n "keywords": "tag1, tag2, tag3",\n' +
' "image": "http://testurl.com/content/images/test-image.png",\n "keywords": "tag1, tag2, tag3",\n' +
' "description": "blog description..."\n}\n </script>\n\n' +
' <meta name="generator" content="Ghost 0.3" />\n' +
' <link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/" />');
Expand All @@ -107,15 +107,15 @@ describe('{{ghost_head}} helper', function () {
meta_description: 'blog "test" description',
title: 'title',
meta_title: 'Welcome to Ghost "test"',
image: '/test-image.png',
image: '/content/images/test-image.png',
published_at: moment('2008-05-31T19:18:15').toISOString(),
updated_at: moment('2014-10-06T15:23:54').toISOString(),
tags: [{name: 'tag1'}, {name: 'tag2'}, {name: 'tag3'}],
author: {
name: 'Author name',
url: 'http//:testauthorurl.com',
slug: 'Author',
image: '/test-author-image.png',
image: '/content/images/test-author-image.png',
website: 'http://authorwebsite.com'
}
};
Expand All @@ -128,7 +128,7 @@ describe('{{ghost_head}} helper', function () {
' <meta property="og:title" content="Welcome to Ghost &quot;test&quot;" />\n' +
' <meta property="og:description" content="blog &quot;test&quot; description..." />\n' +
' <meta property="og:url" content="http://testurl.com/post/" />\n' +
' <meta property="og:image" content="http://testurl.com/test-image.png" />\n' +
' <meta property="og:image" content="http://testurl.com/content/images/test-image.png" />\n' +
' <meta property="article:published_time" content="' + post.published_at + '" />\n' +
' <meta property="article:modified_time" content="' + post.updated_at + '" />\n' +
' <meta property="article:tag" content="tag1" />\n' +
Expand All @@ -138,15 +138,15 @@ describe('{{ghost_head}} helper', function () {
' <meta name="twitter:title" content="Welcome to Ghost &quot;test&quot;" />\n' +
' <meta name="twitter:description" content="blog &quot;test&quot; description..." />\n' +
' <meta name="twitter:url" content="http://testurl.com/post/" />\n' +
' <meta name="twitter:image:src" content="http://testurl.com/test-image.png" />\n \n' +
' <meta name="twitter:image:src" content="http://testurl.com/content/images/test-image.png" />\n \n' +
' <script type=\"application/ld+json\">\n{\n' +
' "@context": "http://schema.org",\n "@type": "Article",\n "publisher": "Ghost",\n' +
' "author": {\n "@type": "Person",\n "name": "Author name",\n ' +
' \"image\": \"http://testurl.com/test-author-image.png\",\n ' +
' \"image\": \"http://testurl.com/content/images/test-author-image.png\",\n ' +
' "url": "http://testurl.com/author/Author",\n "sameAs": "http://authorwebsite.com"\n ' +
'},\n "headline": "Welcome to Ghost &quot;test&quot;",\n "url": "http://testurl.com/post/",\n' +
' "datePublished": "' + post.published_at + '",\n "dateModified": "' + post.updated_at + '",\n' +
' "image": "http://testurl.com/test-image.png",\n "keywords": "tag1, tag2, tag3",\n' +
' "image": "http://testurl.com/content/images/test-image.png",\n "keywords": "tag1, tag2, tag3",\n' +
' "description": "blog &quot;test&quot; description..."\n}\n </script>\n\n' +
' <meta name="generator" content="Ghost 0.3" />\n' +
' <link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/" />');
Expand All @@ -159,15 +159,15 @@ describe('{{ghost_head}} helper', function () {
var post = {
meta_description: 'blog description',
title: 'Welcome to Ghost',
image: '/test-image.png',
image: '/content/images/test-image.png',
published_at: moment('2008-05-31T19:18:15').toISOString(),
updated_at: moment('2014-10-06T15:23:54').toISOString(),
tags: [],
author: {
name: 'Author name',
url: 'http//:testauthorurl.com',
slug: 'Author',
image: '/test-author-image.png',
image: '/content/images/test-author-image.png',
website: 'http://authorwebsite.com'
}
};
Expand All @@ -180,22 +180,22 @@ describe('{{ghost_head}} helper', function () {
' <meta property="og:title" content="Welcome to Ghost" />\n' +
' <meta property="og:description" content="blog description..." />\n' +
' <meta property="og:url" content="http://testurl.com/post/" />\n' +
' <meta property="og:image" content="http://testurl.com/test-image.png" />\n' +
' <meta property="og:image" content="http://testurl.com/content/images/test-image.png" />\n' +
' <meta property="article:published_time" content="' + post.published_at + '" />\n' +
' <meta property="article:modified_time" content="' + post.updated_at + '" />\n \n' +
' <meta name="twitter:card" content="summary_large_image" />\n' +
' <meta name="twitter:title" content="Welcome to Ghost" />\n' +
' <meta name="twitter:description" content="blog description..." />\n' +
' <meta name="twitter:url" content="http://testurl.com/post/" />\n' +
' <meta name="twitter:image:src" content="http://testurl.com/test-image.png" />\n \n' +
' <meta name="twitter:image:src" content="http://testurl.com/content/images/test-image.png" />\n \n' +
' <script type=\"application/ld+json\">\n{\n' +
' "@context": "http://schema.org",\n "@type": "Article",\n "publisher": "Ghost",\n' +
' "author": {\n "@type": "Person",\n "name": "Author name",\n ' +
' \"image\": \"http://testurl.com/test-author-image.png\",\n ' +
' \"image\": \"http://testurl.com/content/images/test-author-image.png\",\n ' +
' "url": "http://testurl.com/author/Author",\n "sameAs": "http://authorwebsite.com"\n ' +
'},\n "headline": "Welcome to Ghost",\n "url": "http://testurl.com/post/",\n' +
' "datePublished": "' + post.published_at + '",\n "dateModified": "' + post.updated_at + '",\n' +
' "image": "http://testurl.com/test-image.png",\n' +
' "image": "http://testurl.com/content/images/test-image.png",\n' +
' "description": "blog description..."\n}\n </script>\n\n' +
' <meta name="generator" content="Ghost 0.3" />\n' +
' <link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/" />');
Expand All @@ -204,7 +204,7 @@ describe('{{ghost_head}} helper', function () {
}).catch(done);
});

it('returns structured data on post page without author image and post cover image', function (done) {
it('returns structured data on post page with null author image and post cover image', function (done) {
var post = {
meta_description: 'blog description',
title: 'Welcome to Ghost',
Expand Down Expand Up @@ -262,15 +262,15 @@ describe('{{ghost_head}} helper', function () {
var post = {
meta_description: 'blog description',
title: 'Welcome to Ghost',
image: '/test-image.png',
image: 'content/images/test-image.png',
published_at: moment('2008-05-31T19:18:15').toISOString(),
updated_at: moment('2014-10-06T15:23:54').toISOString(),
tags: [{name: 'tag1'}, {name: 'tag2'}, {name: 'tag3'}],
author: {
name: 'Author name',
url: 'http//:testauthorurl.com',
slug: 'Author',
image: '/test-author-image.png',
image: 'content/images/test-author-image.png',
website: 'http://authorwebsite.com'
}
};
Expand Down
69 changes: 69 additions & 0 deletions core/test/unit/server_helpers/image_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*globals describe, before, afterEach, after, it*/
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
hbs = require('express-hbs'),
utils = require('./utils'),

// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers');

describe('{{image}} helper', function () {
var sandbox;

before(function () {
sandbox = sinon.sandbox.create();
utils.overrideConfig({url: 'http://testurl.com/'});
utils.loadHelpers();
});

afterEach(function () {
sandbox.restore();
});

after(function () {
utils.restoreConfig();
});

it('has loaded image helper', function () {
should.exist(handlebars.helpers.image);
});

it('should output relative url of image', function (done) {
helpers.image.call({
image: '/content/images/image-relative-url.png',
author: {
image: '/content/images/author-image-relatve-url.png'
}
}).then(function (rendered) {
should.exist(rendered);
rendered.should.equal('/content/images/image-relative-url.png');
done();
}).catch(done);
});

it('should output absolute url of image if the option is present ', function (done) {
helpers.image.call({image: '/content/images/image-relative-url.png',
author: {image: '/content/images/author-image-relatve-url.png'}},
{hash: {absolute: 'true'}}).then(function (rendered) {
should.exist(rendered);
rendered.should.equal('http://testurl.com/content/images/image-relative-url.png');
done();
}).catch(done);
});

it('should have no output if there is no image ', function (done) {
helpers.image.call({image: null}, {hash: {absolute: 'true'}}).then(function (rendered) {
should.not.exist(rendered);
done();
}).catch(done);
});

it('should have no output if there is no image property ', function (done) {
helpers.image.call({}, {hash: {absolute: 'true'}}).then(function (rendered) {
should.not.exist(rendered);
done();
}).catch(done);
});
});

0 comments on commit 4a56d10

Please sign in to comment.