mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 13:54:35 +03:00
Add structured data to static pages
refs #6534 - adds structured data on static pages - selects post context object for static pages - updates tests
This commit is contained in:
parent
48b846b13d
commit
5102637b8e
@ -1,11 +1,11 @@
|
|||||||
var config = require('../../config');
|
var config = require('../../config'),
|
||||||
|
getContextObject = require('./context_object.js');
|
||||||
|
|
||||||
function getAuthorImage(data, absolute) {
|
function getAuthorImage(data, absolute) {
|
||||||
var context = data.context ? data.context[0] : null,
|
var context = data.context ? data.context[0] : null,
|
||||||
blog = config.theme,
|
contextObject = getContextObject(data, context);
|
||||||
contextObject = data[context] || blog;
|
|
||||||
|
|
||||||
if (context === 'post' && contextObject.author && contextObject.author.image) {
|
if ((context === 'post' || context === 'page') && contextObject.author && contextObject.author.image) {
|
||||||
return config.urlFor('image', {image: contextObject.author.image}, absolute);
|
return config.urlFor('image', {image: contextObject.author.image}, absolute);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
13
core/server/data/meta/context_object.js
Normal file
13
core/server/data/meta/context_object.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var config = require('../../config');
|
||||||
|
|
||||||
|
function getContextObject(data, context) {
|
||||||
|
var blog = config.theme,
|
||||||
|
contextObject;
|
||||||
|
|
||||||
|
context = context === 'page' ? 'post' : context;
|
||||||
|
contextObject = data[context] || blog;
|
||||||
|
|
||||||
|
return contextObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getContextObject;
|
@ -1,9 +1,9 @@
|
|||||||
var config = require('../../config');
|
var config = require('../../config'),
|
||||||
|
getContextObject = require('./context_object.js');
|
||||||
|
|
||||||
function getCoverImage(data) {
|
function getCoverImage(data) {
|
||||||
var context = data.context ? data.context[0] : null,
|
var context = data.context ? data.context[0] : null,
|
||||||
blog = config.theme,
|
contextObject = getContextObject(data, context);
|
||||||
contextObject = data[context] || blog;
|
|
||||||
|
|
||||||
if (context === 'home' || context === 'author') {
|
if (context === 'home' || context === 'author') {
|
||||||
if (contextObject.cover) {
|
if (contextObject.cover) {
|
||||||
|
@ -97,7 +97,7 @@ function getAuthorSchema(metaData, data) {
|
|||||||
function getSchema(metaData, data) {
|
function getSchema(metaData, data) {
|
||||||
if (!config.isPrivacyDisabled('useStructuredData')) {
|
if (!config.isPrivacyDisabled('useStructuredData')) {
|
||||||
var context = data.context ? data.context[0] : null;
|
var context = data.context ? data.context[0] : null;
|
||||||
if (context === 'post') {
|
if (context === 'post' || context === 'page') {
|
||||||
return getPostSchema(metaData, data);
|
return getPostSchema(metaData, data);
|
||||||
} else if (context === 'home') {
|
} else if (context === 'home') {
|
||||||
return getHomeSchema(metaData);
|
return getHomeSchema(metaData);
|
||||||
|
@ -98,7 +98,7 @@ function ghost_head(options) {
|
|||||||
escapeExpression(metaData.nextUrl) + '" />');
|
escapeExpression(metaData.nextUrl) + '" />');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context !== 'paged' && context !== 'page' && useStructuredData) {
|
if (context !== 'paged' && useStructuredData) {
|
||||||
head.push('');
|
head.push('');
|
||||||
head.push.apply(head, finaliseStructuredData(metaData));
|
head.push.apply(head, finaliseStructuredData(metaData));
|
||||||
head.push('');
|
head.push('');
|
||||||
|
49
core/test/unit/metadata/context_object_spec.js
Normal file
49
core/test/unit/metadata/context_object_spec.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*globals describe, it, before, after */
|
||||||
|
var should = require('should'),
|
||||||
|
getContextObject = require('../../../server/data/meta/context_object.js'),
|
||||||
|
configUtils = require('../../utils/configUtils');
|
||||||
|
|
||||||
|
describe('getContextObject', function () {
|
||||||
|
var data, context, contextObject;
|
||||||
|
|
||||||
|
it('should be a function', function () {
|
||||||
|
should.exist(getContextObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return post context object for a post', function () {
|
||||||
|
data = {post: {id: 2}};
|
||||||
|
context = 'post';
|
||||||
|
contextObject = getContextObject(data, context);
|
||||||
|
|
||||||
|
should.exist(contextObject);
|
||||||
|
contextObject.should.eql(data.post);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return post context object for a static page', function () {
|
||||||
|
data = {post: {id: 2}};
|
||||||
|
context = 'page';
|
||||||
|
contextObject = getContextObject(data, context);
|
||||||
|
|
||||||
|
should.exist(contextObject);
|
||||||
|
contextObject.should.eql(data.post);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('override blog', function () {
|
||||||
|
before(function () {
|
||||||
|
configUtils.set({theme: {foo: 'bar'}});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function () {
|
||||||
|
configUtils.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return blog context object for unknown context', function () {
|
||||||
|
data = {post: {id: 2}};
|
||||||
|
context = 'unknown';
|
||||||
|
contextObject = getContextObject(data, context);
|
||||||
|
|
||||||
|
should.exist(contextObject);
|
||||||
|
contextObject.should.have.property('foo', 'bar');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -110,6 +110,57 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns structured data on static page', function (done) {
|
||||||
|
var post = {
|
||||||
|
meta_description: 'all about our blog',
|
||||||
|
title: 'About',
|
||||||
|
image: '/content/images/test-image-about.png',
|
||||||
|
published_at: moment('2008-05-31T19:18:15').toISOString(),
|
||||||
|
updated_at: moment('2014-10-06T15:23:54').toISOString(),
|
||||||
|
page: true,
|
||||||
|
author: {
|
||||||
|
name: 'Author name',
|
||||||
|
url: 'http://testauthorurl.com',
|
||||||
|
slug: 'Author',
|
||||||
|
image: '/content/images/test-author-image.png',
|
||||||
|
website: 'http://authorwebsite.com',
|
||||||
|
bio: 'Author bio'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
helpers.ghost_head.call(
|
||||||
|
{safeVersion: '0.3', relativeUrl: '/about/', context: ['page'], post: post},
|
||||||
|
{data: {root: {context: ['page']}}}
|
||||||
|
).then(function (rendered) {
|
||||||
|
should.exist(rendered);
|
||||||
|
rendered.string.should.match(/<link rel="canonical" href="http:\/\/testurl.com\/about\/" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="referrer" content="origin" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:site_name" content="Ghost" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:type" content="website" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:title" content="About" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:description" content="all about our blog" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:url" content="http:\/\/testurl.com\/about\/" \/>/);
|
||||||
|
rendered.string.should.match(/<meta property="og:image" content="http:\/\/testurl.com\/content\/images\/test-image-about.png" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="twitter:card" content="summary_large_image" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="twitter:title" content="About" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="twitter:description" content="all about our blog" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="twitter:url" content="http:\/\/testurl.com\/about\/" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="twitter:image:src" content="http:\/\/testurl.com\/content\/images\/test-image-about.png" \/>/);
|
||||||
|
rendered.string.should.match(/<meta name="generator" content="Ghost 0.3" \/>/);
|
||||||
|
rendered.string.should.match(/<link rel="alternate" type="application\/rss\+xml" title="Ghost" href="http:\/\/testurl.com\/rss\/" \/>/);
|
||||||
|
rendered.string.should.match(/<script type=\"application\/ld\+json\">/);
|
||||||
|
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
|
||||||
|
rendered.string.should.match(/"@type": "Article"/);
|
||||||
|
rendered.string.should.match(/"publisher": "Ghost"/);
|
||||||
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/about\/"/);
|
||||||
|
rendered.string.should.match(/"image": "http:\/\/testurl.com\/content\/images\/test-image-about.png"/);
|
||||||
|
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
||||||
|
rendered.string.should.match(/"description": "all about our blog"/);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
it('returns structured data and schema first tag page with meta description and meta title', function (done) {
|
it('returns structured data and schema first tag page with meta description and meta title', function (done) {
|
||||||
var tag = {
|
var tag = {
|
||||||
meta_description: 'tag meta description',
|
meta_description: 'tag meta description',
|
||||||
@ -327,7 +378,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
tags: [{name: 'tag1'}, {name: 'tag2'}, {name: 'tag3'}],
|
tags: [{name: 'tag1'}, {name: 'tag2'}, {name: 'tag3'}],
|
||||||
author: {
|
author: {
|
||||||
name: 'Author name',
|
name: 'Author name',
|
||||||
url: 'http//:testauthorurl.com',
|
url: 'http://testauthorurl.com',
|
||||||
slug: 'Author',
|
slug: 'Author',
|
||||||
image: '/content/images/test-author-image.png',
|
image: '/content/images/test-author-image.png',
|
||||||
website: 'http://authorwebsite.com',
|
website: 'http://authorwebsite.com',
|
||||||
@ -637,16 +688,22 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns canonical URL', function (done) {
|
it('returns canonical URL', function (done) {
|
||||||
|
var post = {
|
||||||
|
title: 'Welcome to Ghost',
|
||||||
|
html: '<p>This is a short post</p>',
|
||||||
|
author: {
|
||||||
|
name: 'Author name'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
helpers.ghost_head.call(
|
helpers.ghost_head.call(
|
||||||
{safeVersion: '0.3', relativeUrl: '/about/', context: ['page']},
|
{safeVersion: '0.3', relativeUrl: '/about/', context: ['page'], post: post},
|
||||||
{data: {root: {context: ['page']}}}
|
{data: {root: {context: ['page']}}}
|
||||||
).then(function (rendered) {
|
).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.match(/<link rel="canonical" href="http:\/\/testurl.com\/about\/" \/>/);
|
rendered.string.should.match(/<link rel="canonical" href="http:\/\/testurl.com\/about\/" \/>/);
|
||||||
rendered.string.should.match(/<meta name="generator" content="Ghost 0.3" \/>/);
|
rendered.string.should.match(/<meta name="generator" content="Ghost 0.3" \/>/);
|
||||||
rendered.string.should.match(/<link rel="alternate" type="application\/rss\+xml" title="Ghost" href="http:\/\/testurl.com\/rss\/" \/>/);
|
rendered.string.should.match(/<link rel="alternate" type="application\/rss\+xml" title="Ghost" href="http:\/\/testurl.com\/rss\/" \/>/);
|
||||||
rendered.string.should.not.match(/<meta property="og/);
|
|
||||||
rendered.string.should.not.match(/<script type=\"application\/ld\+json\">/);
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
|
Loading…
Reference in New Issue
Block a user