mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 13:54:35 +03:00
Merge pull request #6405 from jtwebman/ghost_head_refactor
Refactored ghost head helper
This commit is contained in:
commit
8b5ea4691a
@ -12,9 +12,9 @@ function getDescription(data, root) {
|
|||||||
} else if (_.contains(context, 'home')) {
|
} else if (_.contains(context, 'home')) {
|
||||||
description = config.theme.description;
|
description = config.theme.description;
|
||||||
} else if (_.contains(context, 'author') && data.author) {
|
} else if (_.contains(context, 'author') && data.author) {
|
||||||
description = data.author.bio;
|
description = data.author.meta_description || data.author.bio;
|
||||||
} else if (_.contains(context, 'tag') && data.tag) {
|
} else if (_.contains(context, 'tag') && data.tag) {
|
||||||
description = data.tag.meta_description;
|
description = data.tag.meta_description || data.tag.description;
|
||||||
} else if ((_.contains(context, 'post') || _.contains(context, 'page')) && data.post) {
|
} else if ((_.contains(context, 'post') || _.contains(context, 'page')) && data.post) {
|
||||||
description = data.post.meta_description;
|
description = data.post.meta_description;
|
||||||
}
|
}
|
||||||
|
@ -6,26 +6,18 @@
|
|||||||
// We use the name ghost_head to match the helper for consistency:
|
// We use the name ghost_head to match the helper for consistency:
|
||||||
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
|
||||||
var hbs = require('express-hbs'),
|
var getMetaData = require('../data/meta'),
|
||||||
moment = require('moment'),
|
hbs = require('express-hbs'),
|
||||||
_ = require('lodash'),
|
escapeExpression = hbs.handlebars.Utils.escapeExpression,
|
||||||
Promise = require('bluebird'),
|
SafeString = hbs.handlebars.SafeString,
|
||||||
|
_ = require('lodash'),
|
||||||
config = require('../config'),
|
api = require('../api'),
|
||||||
filters = require('../filters'),
|
filters = require('../filters'),
|
||||||
|
assetHelper = require('./asset'),
|
||||||
api = require('../api'),
|
config = require('../config'),
|
||||||
assetHelper = require('./asset'),
|
Promise = require('bluebird'),
|
||||||
urlHelper = require('./url'),
|
labs = require('../utils/labs'),
|
||||||
meta_description = require('./meta_description'),
|
api = require('../api');
|
||||||
meta_title = require('./meta_title'),
|
|
||||||
excerpt = require('./excerpt'),
|
|
||||||
tagsHelper = require('./tags'),
|
|
||||||
imageHelper = require('./image'),
|
|
||||||
labs = require('../utils/labs'),
|
|
||||||
|
|
||||||
blog,
|
|
||||||
ghost_head;
|
|
||||||
|
|
||||||
function getClient() {
|
function getClient() {
|
||||||
if (labs.isSet('publicAPI') === true) {
|
if (labs.isSet('publicAPI') === true) {
|
||||||
@ -37,12 +29,10 @@ function getClient() {
|
|||||||
secret: client.secret
|
secret: client.secret
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return Promise.resolve({});
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeMetaTag(property, content, type) {
|
function writeMetaTag(property, content, type) {
|
||||||
@ -50,234 +40,26 @@ function writeMetaTag(property, content, type) {
|
|||||||
return '<meta ' + type + '="' + property + '" content="' + content + '" />';
|
return '<meta ' + type + '="' + property + '" content="' + content + '" />';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImage(props, context, contextObject) {
|
function finaliseStructuredData(metaData) {
|
||||||
if (context === 'home' || context === 'author') {
|
var head = [];
|
||||||
contextObject.image = contextObject.cover;
|
_.each(metaData.structuredData, function (content, property) {
|
||||||
}
|
|
||||||
|
|
||||||
props.image = imageHelper.call(contextObject, {hash: {absolute: true}});
|
|
||||||
|
|
||||||
if (context === 'post' && contextObject.author) {
|
|
||||||
props.author_image = imageHelper.call(contextObject.author, {hash: {absolute: true}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPaginationUrls(pagination, relativeUrl, secure, head) {
|
|
||||||
var trimmedUrl, next, prev,
|
|
||||||
trimmedUrlpattern = /.+(?=\/page\/\d*\/)/,
|
|
||||||
tagOrAuthorPattern = /\/(tag)|(author)\//;
|
|
||||||
|
|
||||||
trimmedUrl = relativeUrl.match(trimmedUrlpattern);
|
|
||||||
if (pagination.prev) {
|
|
||||||
prev = (pagination.prev > 1 ? '/page/' + pagination.prev + '/' : '/');
|
|
||||||
prev = (trimmedUrl) ? trimmedUrl + prev : prev;
|
|
||||||
head.push('<link rel="prev" href="' +
|
|
||||||
config.urlFor({relativeUrl: prev, secure: secure}, true) + '" />'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (pagination.next) {
|
|
||||||
next = '/page/' + pagination.next + '/';
|
|
||||||
if (trimmedUrl) {
|
|
||||||
next = trimmedUrl + next;
|
|
||||||
} else if (tagOrAuthorPattern.test(relativeUrl)) {
|
|
||||||
next = relativeUrl.slice(0, -1) + next;
|
|
||||||
}
|
|
||||||
head.push('<link rel="next" href="' +
|
|
||||||
config.urlFor({relativeUrl: next, secure: secure}, true) + '" />'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addContextMetaData(context, data, metaData) {
|
|
||||||
// escaped data
|
|
||||||
metaData.metaTitle = hbs.handlebars.Utils.escapeExpression(metaData.metaTitle);
|
|
||||||
metaData.metaDescription = metaData.metaDescription ? hbs.handlebars.Utils.escapeExpression(metaData.metaDescription) : null;
|
|
||||||
|
|
||||||
if (context === 'author') {
|
|
||||||
metaData.authorUrl = hbs.handlebars.Utils.escapeExpression(blog.url + '/author/' + data.author.slug);
|
|
||||||
metaData.ogType = 'profile';
|
|
||||||
} else if (context === 'post') {
|
|
||||||
metaData.publishedDate = moment(data.post.published_at).toISOString();
|
|
||||||
metaData.modifiedDate = moment(data.post.updated_at).toISOString();
|
|
||||||
metaData.authorUrl = hbs.handlebars.Utils.escapeExpression(blog.url + '/author/' + data.post.author.slug);
|
|
||||||
metaData.ogType = 'article';
|
|
||||||
}
|
|
||||||
return metaData;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initMetaData(context, data, results) {
|
|
||||||
var metaData = {
|
|
||||||
url: results.url,
|
|
||||||
canonicalUrl: results.canonicalUrl,
|
|
||||||
metaDescription: results.meta_description || null,
|
|
||||||
metaTitle: results.meta_title,
|
|
||||||
coverImage: results.image,
|
|
||||||
authorImage: results.author_image,
|
|
||||||
publishedDate: null,
|
|
||||||
modifiedDate: null,
|
|
||||||
tags: null,
|
|
||||||
card: 'summary',
|
|
||||||
authorUrl: null,
|
|
||||||
ogType: 'website',
|
|
||||||
keywords: null,
|
|
||||||
blog: blog,
|
|
||||||
title: blog.title,
|
|
||||||
clientId: results.client.id,
|
|
||||||
clientSecret: results.client.secret
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!metaData.metaDescription) {
|
|
||||||
if (context === 'post') {
|
|
||||||
metaData.metaDescription = excerpt.call(data.post, {hash: {words: '40'}}).string + '...';
|
|
||||||
} else if (context === 'tag') {
|
|
||||||
metaData.metaDescription = data.tag.description ? data.tag.description : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addContextMetaData(context, data, metaData);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStructuredData(metaData) {
|
|
||||||
var structuredData;
|
|
||||||
|
|
||||||
if (metaData.coverImage) {
|
|
||||||
metaData.card = 'summary_large_image';
|
|
||||||
}
|
|
||||||
|
|
||||||
structuredData = {
|
|
||||||
'og:site_name': metaData.title,
|
|
||||||
'og:type': metaData.ogType,
|
|
||||||
'og:title': metaData.metaTitle,
|
|
||||||
'og:description': metaData.metaDescription,
|
|
||||||
'og:url': metaData.canonicalUrl,
|
|
||||||
'og:image': metaData.coverImage,
|
|
||||||
'article:published_time': metaData.publishedDate,
|
|
||||||
'article:modified_time': metaData.modifiedDate,
|
|
||||||
'article:tag': metaData.tags,
|
|
||||||
'twitter:card': metaData.card,
|
|
||||||
'twitter:title': metaData.metaTitle,
|
|
||||||
'twitter:description': metaData.metaDescription,
|
|
||||||
'twitter:url': metaData.canonicalUrl,
|
|
||||||
'twitter:image:src': metaData.coverImage
|
|
||||||
};
|
|
||||||
|
|
||||||
return structuredData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the final schema object with values that are not null
|
|
||||||
function trimSchema(schema) {
|
|
||||||
var schemaObject = {};
|
|
||||||
|
|
||||||
_.each(schema, function (value, key) {
|
|
||||||
if (value !== null && value !== undefined) {
|
|
||||||
schemaObject[key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return schemaObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPostSchema(metaData, data) {
|
|
||||||
var schema = {
|
|
||||||
'@context': 'http://schema.org',
|
|
||||||
'@type': 'Article',
|
|
||||||
publisher: metaData.title,
|
|
||||||
author: {
|
|
||||||
'@type': 'Person',
|
|
||||||
name: data.post.author.name,
|
|
||||||
image: metaData.authorImage,
|
|
||||||
url: metaData.authorUrl,
|
|
||||||
sameAs: data.post.author.website || null,
|
|
||||||
description: data.post.author.bio || null
|
|
||||||
},
|
|
||||||
headline: metaData.metaTitle,
|
|
||||||
url: metaData.url,
|
|
||||||
datePublished: metaData.publishedDate,
|
|
||||||
dateModified: metaData.modifiedDate,
|
|
||||||
image: metaData.coverImage,
|
|
||||||
keywords: metaData.keywords,
|
|
||||||
description: metaData.metaDescription
|
|
||||||
};
|
|
||||||
return trimSchema(schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTagSchema(metaData, data) {
|
|
||||||
var schema = {
|
|
||||||
'@context': 'http://schema.org',
|
|
||||||
'@type': 'Series',
|
|
||||||
publisher: metaData.title,
|
|
||||||
url: metaData.url,
|
|
||||||
image: metaData.coverImage,
|
|
||||||
name: data.tag.name,
|
|
||||||
description: metaData.metaDescription
|
|
||||||
};
|
|
||||||
|
|
||||||
return trimSchema(schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAuthorSchema(metaData, data) {
|
|
||||||
var schema = {
|
|
||||||
'@context': 'http://schema.org',
|
|
||||||
'@type': 'Person',
|
|
||||||
sameAs: data.author.website || null,
|
|
||||||
publisher: metaData.title,
|
|
||||||
name: data.author.name,
|
|
||||||
url: metaData.authorUrl,
|
|
||||||
image: metaData.coverImage,
|
|
||||||
description: metaData.metaDescription
|
|
||||||
};
|
|
||||||
|
|
||||||
return trimSchema(schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHomeSchema(metaData) {
|
|
||||||
var schema = {
|
|
||||||
'@context': 'http://schema.org',
|
|
||||||
'@type': 'Website',
|
|
||||||
publisher: metaData.title,
|
|
||||||
url: metaData.url,
|
|
||||||
image: metaData.coverImage,
|
|
||||||
description: metaData.metaDescription
|
|
||||||
};
|
|
||||||
|
|
||||||
return trimSchema(schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
function chooseSchema(metaData, context, data) {
|
|
||||||
if (context === 'post') {
|
|
||||||
return getPostSchema(metaData, data);
|
|
||||||
} else if (context === 'home') {
|
|
||||||
return getHomeSchema(metaData);
|
|
||||||
} else if (context === 'tag') {
|
|
||||||
return getTagSchema(metaData, data);
|
|
||||||
} else if (context === 'author') {
|
|
||||||
return getAuthorSchema(metaData, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function finaliseStructuredData(structuredData, tags, head) {
|
|
||||||
_.each(structuredData, function (content, property) {
|
|
||||||
if (property === 'article:tag') {
|
if (property === 'article:tag') {
|
||||||
_.each(tags, function (tag) {
|
_.each(metaData.keywords, function (keyword) {
|
||||||
if (tag !== '') {
|
if (keyword !== '') {
|
||||||
tag = hbs.handlebars.Utils.escapeExpression(tag.trim());
|
keyword = escapeExpression(keyword);
|
||||||
head.push(writeMetaTag(property, tag));
|
head.push(writeMetaTag(property,
|
||||||
|
escapeExpression(keyword)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
head.push('');
|
head.push('');
|
||||||
} else if (content !== null && content !== undefined) {
|
} else if (content !== null && content !== undefined) {
|
||||||
head.push(writeMetaTag(property, content));
|
head.push(writeMetaTag(property,
|
||||||
|
escapeExpression(content)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
function finaliseSchema(schema, head) {
|
|
||||||
head.push('<script type="application/ld+json">\n' + JSON.stringify(schema, null, ' ') +
|
|
||||||
'\n </script>\n'
|
|
||||||
);
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAjaxHelper(clientId, clientSecret) {
|
function getAjaxHelper(clientId, clientSecret) {
|
||||||
return '<script type="text/javascript" src="' +
|
return '<script type="text/javascript" src="' +
|
||||||
assetHelper('shared/ghost-url.js', {hash: {minifyInProduction: true}}) + '"></script>\n' +
|
assetHelper('shared/ghost-url.js', {hash: {minifyInProduction: true}}) + '"></script>\n' +
|
||||||
@ -289,90 +71,62 @@ function getAjaxHelper(clientId, clientSecret) {
|
|||||||
'</script>';
|
'</script>';
|
||||||
}
|
}
|
||||||
|
|
||||||
ghost_head = function (options) {
|
function ghost_head(options) {
|
||||||
// if error page do nothing
|
// if error page do nothing
|
||||||
if (this.code >= 400) {
|
if (this.code >= 400) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var metaData = getMetaData(this, options.data.root),
|
||||||
// create a shortcut for theme config
|
|
||||||
blog = config.theme;
|
|
||||||
|
|
||||||
/*jshint unused:false*/
|
|
||||||
var self = this,
|
|
||||||
useStructuredData = !config.isPrivacyDisabled('useStructuredData'),
|
|
||||||
head = [],
|
head = [],
|
||||||
safeVersion = this.safeVersion,
|
context = this.context ? this.context[0] : null,
|
||||||
props = {},
|
useStructuredData = !config.isPrivacyDisabled('useStructuredData'),
|
||||||
structuredData,
|
safeVersion = this.safeVersion;
|
||||||
schema,
|
|
||||||
title = hbs.handlebars.Utils.escapeExpression(blog.title),
|
|
||||||
context = self.context ? self.context[0] : null,
|
|
||||||
contextObject = _.cloneDeep(self[context] || blog);
|
|
||||||
|
|
||||||
// Store Async calls in an object of named promises
|
return getClient().then(function (client) {
|
||||||
props.url = urlHelper.call(self, {hash: {absolute: true}});
|
|
||||||
props.canonicalUrl = config.urlJoin(config.getBaseUrl(false),
|
|
||||||
urlHelper.call(self, {hash: {absolute: false}}));
|
|
||||||
props.meta_description = meta_description.call(self, options);
|
|
||||||
props.meta_title = meta_title.call(self, options);
|
|
||||||
props.client = getClient();
|
|
||||||
getImage(props, context, contextObject);
|
|
||||||
|
|
||||||
// Resolves promises then push pushes meta data into ghost_head
|
|
||||||
return Promise.props(props).then(function (results) {
|
|
||||||
if (context) {
|
if (context) {
|
||||||
var metaData = initMetaData(context, self, results),
|
|
||||||
tags = tagsHelper.call(self.post, {hash: {autolink: 'false'}}).string.split(',');
|
|
||||||
|
|
||||||
// If there are tags - build the keywords metaData string
|
|
||||||
if (tags[0] !== '') {
|
|
||||||
metaData.keywords = hbs.handlebars.Utils.escapeExpression(tagsHelper.call(self.post,
|
|
||||||
{hash: {autolink: 'false', separator: ', '}}
|
|
||||||
).string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// head is our main array that holds our meta data
|
// head is our main array that holds our meta data
|
||||||
head.push('<link rel="canonical" href="' + metaData.canonicalUrl + '" />');
|
head.push('<link rel="canonical" href="' +
|
||||||
|
escapeExpression(metaData.canonicalUrl) + '" />');
|
||||||
head.push('<meta name="referrer" content="origin" />');
|
head.push('<meta name="referrer" content="origin" />');
|
||||||
|
|
||||||
// Generate context driven pagination urls
|
if (metaData.previousUrl) {
|
||||||
if (self.pagination) {
|
head.push('<link rel="prev" href="' +
|
||||||
getPaginationUrls(self.pagination, self.relativeUrl, self.secure, head);
|
escapeExpression(metaData.previousUrl) + '" />');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaData.nextUrl) {
|
||||||
|
head.push('<link rel="next" href="' +
|
||||||
|
escapeExpression(metaData.nextUrl) + '" />');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test to see if we are on a post page and that Structured data has not been disabled in config.js
|
|
||||||
if (context !== 'paged' && context !== 'page' && useStructuredData) {
|
if (context !== 'paged' && context !== 'page' && useStructuredData) {
|
||||||
// Create context driven OpenGraph and Twitter meta data
|
|
||||||
structuredData = getStructuredData(metaData);
|
|
||||||
// Create context driven JSONLD object
|
|
||||||
schema = chooseSchema(metaData, context, self);
|
|
||||||
head.push('');
|
head.push('');
|
||||||
// Formats structured data and pushes to head array
|
head.push.apply(head, finaliseStructuredData(metaData));
|
||||||
finaliseStructuredData(structuredData, tags, head);
|
|
||||||
head.push('');
|
head.push('');
|
||||||
// Formats schema script/JSONLD data and pushes to head array
|
|
||||||
finaliseSchema(schema, head);
|
head.push('<script type="application/ld+json">\n' +
|
||||||
|
JSON.stringify(metaData.schema, null, ' ') +
|
||||||
|
'\n </script>\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metaData.clientId && metaData.clientSecret) {
|
if (client && client.id && client.secret) {
|
||||||
head.push(getAjaxHelper(metaData.clientId, metaData.clientSecret));
|
head.push(getAjaxHelper(client.id, client.secret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
head.push('<meta name="generator" content="Ghost ' + safeVersion + '" />');
|
head.push('<meta name="generator" content="Ghost ' +
|
||||||
|
escapeExpression(safeVersion) + '" />');
|
||||||
head.push('<link rel="alternate" type="application/rss+xml" title="' +
|
head.push('<link rel="alternate" type="application/rss+xml" title="' +
|
||||||
title + '" href="' + config.urlFor('rss', {secure: self.secure},
|
escapeExpression(metaData.blog.title) + '" href="' +
|
||||||
true) + '" />');
|
escapeExpression(metaData.rssUrl) + '" />');
|
||||||
}).then(function () {
|
|
||||||
return api.settings.read({key: 'ghost_head'});
|
return api.settings.read({key: 'ghost_head'});
|
||||||
}).then(function (response) {
|
}).then(function (response) {
|
||||||
head.push(response.settings[0].value);
|
head.push(response.settings[0].value);
|
||||||
return filters.doFilter('ghost_head', head);
|
return filters.doFilter('ghost_head', head);
|
||||||
}).then(function (head) {
|
}).then(function (head) {
|
||||||
var headString = _.reduce(head, function (memo, item) { return memo + '\n ' + item; }, '');
|
return new SafeString(head.join('\n ').trim());
|
||||||
return new hbs.handlebars.SafeString(headString.trim());
|
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = ghost_head;
|
module.exports = ghost_head;
|
||||||
|
@ -38,6 +38,18 @@ describe('getMetaDescription', function () {
|
|||||||
description.should.equal('Best tag ever!');
|
description.should.equal('Best tag ever!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return data tag description if no meta description for tag', function () {
|
||||||
|
var description = getMetaDescription({
|
||||||
|
tag: {
|
||||||
|
meta_description: '',
|
||||||
|
description: 'The normal description'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
context: ['tag']
|
||||||
|
});
|
||||||
|
description.should.equal('The normal description');
|
||||||
|
});
|
||||||
|
|
||||||
it('should return data post meta description if on root context contains post', function () {
|
it('should return data post meta description if on root context contains post', function () {
|
||||||
var description = getMetaDescription({
|
var description = getMetaDescription({
|
||||||
post: {
|
post: {
|
||||||
|
@ -269,7 +269,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
rendered.string.should.match(/"@type": "Person"/);
|
rendered.string.should.match(/"@type": "Person"/);
|
||||||
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
||||||
rendered.string.should.match(/"publisher": "Ghost"/);
|
rendered.string.should.match(/"publisher": "Ghost"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/AuthorName"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/AuthorName\/"/);
|
||||||
rendered.string.should.match(/"image": "http:\/\/testurl.com\/content\/images\/author-cover-image.png"/);
|
rendered.string.should.match(/"image": "http:\/\/testurl.com\/content\/images\/author-cover-image.png"/);
|
||||||
rendered.string.should.match(/"name": "Author name"/);
|
rendered.string.should.match(/"name": "Author name"/);
|
||||||
rendered.string.should.match(/"description": "Author bio"/);
|
rendered.string.should.match(/"description": "Author bio"/);
|
||||||
@ -371,7 +371,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
rendered.string.should.match(/"@type": "Person"/);
|
rendered.string.should.match(/"@type": "Person"/);
|
||||||
rendered.string.should.match(/"name": "Author name"/);
|
rendered.string.should.match(/"name": "Author name"/);
|
||||||
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author\/"/);
|
||||||
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
||||||
rendered.string.should.match(/"description": "Author bio"/);
|
rendered.string.should.match(/"description": "Author bio"/);
|
||||||
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
||||||
@ -444,7 +444,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
rendered.string.should.match(/"@type": "Person"/);
|
rendered.string.should.match(/"@type": "Person"/);
|
||||||
rendered.string.should.match(/"name": "Author name"/);
|
rendered.string.should.match(/"name": "Author name"/);
|
||||||
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author\/"/);
|
||||||
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
||||||
rendered.string.should.match(/"headline": "Welcome to Ghost "test""/);
|
rendered.string.should.match(/"headline": "Welcome to Ghost "test""/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
||||||
@ -511,7 +511,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
rendered.string.should.match(/"@type": "Person"/);
|
rendered.string.should.match(/"@type": "Person"/);
|
||||||
rendered.string.should.match(/"name": "Author name"/);
|
rendered.string.should.match(/"name": "Author name"/);
|
||||||
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
rendered.string.should.match(/"image\": \"http:\/\/testurl.com\/content\/images\/test-author-image.png\"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author\/"/);
|
||||||
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
||||||
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
||||||
@ -581,7 +581,7 @@ describe('{{ghost_head}} helper', function () {
|
|||||||
rendered.string.should.match(/"@type": "Person"/);
|
rendered.string.should.match(/"@type": "Person"/);
|
||||||
rendered.string.should.match(/"name": "Author name"/);
|
rendered.string.should.match(/"name": "Author name"/);
|
||||||
rendered.string.should.not.match(/"image\"/);
|
rendered.string.should.not.match(/"image\"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/Author\/"/);
|
||||||
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
rendered.string.should.match(/"sameAs": "http:\/\/authorwebsite.com"/);
|
||||||
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
rendered.string.should.match(/"headline": "Welcome to Ghost"/);
|
||||||
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
rendered.string.should.match(/"url": "http:\/\/testurl.com\/post\/"/);
|
||||||
|
Loading…
Reference in New Issue
Block a user