mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
c4d3bd7cd2
refs #6534 - don't output publisher for the 'People' type on the author page - change publisher to a full 'Organisation' for the 'Article' type on posts Note: Google's structured data validator also wants image & publisher.logo inside of Article to be full 'ImageObject's. Currently, it output's an error for them: 'The attribute itemtype has an invalid value.' However, the spec on Schema.org says a url is valid: https://schema.org/Article, which is slightly different to Google's spec here: https://developers.google.com/structured-data/rich-snippets/articles#article_markup_properties Ideally, we would output a full 'ImageObject', however we don't currently have the width & height info required. Therefore, I think what we have is valid strictly speaking, but we should aim to fix this when we have better image tools.
144 lines
4.3 KiB
JavaScript
144 lines
4.3 KiB
JavaScript
var config = require('../../config'),
|
|
hbs = require('express-hbs'),
|
|
escapeExpression = hbs.handlebars.Utils.escapeExpression,
|
|
_ = require('lodash');
|
|
|
|
// Creates the final schema object with values that are not null
|
|
function trimSchema(schema) {
|
|
var schemaObject = {};
|
|
|
|
_.each(schema, function (value, key) {
|
|
if (value !== null && typeof value !== 'undefined') {
|
|
schemaObject[key] = value;
|
|
}
|
|
});
|
|
return schemaObject;
|
|
}
|
|
|
|
function trimSameAs(data, context) {
|
|
var sameAs = [];
|
|
|
|
if (context === 'post') {
|
|
if (data.post.author.website) {
|
|
sameAs.push(data.post.author.website);
|
|
}
|
|
if (data.post.author.facebook) {
|
|
sameAs.push(data.post.author.facebook);
|
|
}
|
|
if (data.post.author.twitter) {
|
|
sameAs.push(data.post.author.twitter);
|
|
}
|
|
} else if (context === 'author') {
|
|
if (data.author.website) {
|
|
sameAs.push(data.author.website);
|
|
}
|
|
if (data.author.facebook) {
|
|
sameAs.push(data.author.facebook);
|
|
}
|
|
if (data.author.twitter) {
|
|
sameAs.push(data.author.twitter);
|
|
}
|
|
}
|
|
|
|
return sameAs;
|
|
}
|
|
|
|
function getPostSchema(metaData, data) {
|
|
var description = metaData.metaDescription ? escapeExpression(metaData.metaDescription) :
|
|
(metaData.excerpt ? escapeExpression(metaData.excerpt) : null),
|
|
schema;
|
|
|
|
schema = {
|
|
'@context': 'http://schema.org',
|
|
'@type': 'Article',
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: escapeExpression(metaData.blog.title),
|
|
logo: metaData.blog.logo || null
|
|
},
|
|
author: {
|
|
'@type': 'Person',
|
|
name: escapeExpression(data.post.author.name),
|
|
image: metaData.authorImage,
|
|
url: metaData.authorUrl,
|
|
sameAs: trimSameAs(data, 'post'),
|
|
description: data.post.author.bio ?
|
|
escapeExpression(data.post.author.bio) :
|
|
null
|
|
},
|
|
headline: escapeExpression(metaData.metaTitle),
|
|
url: metaData.url,
|
|
datePublished: metaData.publishedDate,
|
|
dateModified: metaData.modifiedDate,
|
|
image: metaData.coverImage,
|
|
keywords: metaData.keywords && metaData.keywords.length > 0 ?
|
|
metaData.keywords.join(', ') : null,
|
|
description: description
|
|
};
|
|
schema.author = trimSchema(schema.author);
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getHomeSchema(metaData) {
|
|
var schema = {
|
|
'@context': 'http://schema.org',
|
|
'@type': 'Website',
|
|
publisher: escapeExpression(metaData.blog.title),
|
|
url: metaData.url,
|
|
image: metaData.coverImage,
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getTagSchema(metaData, data) {
|
|
var schema = {
|
|
'@context': 'http://schema.org',
|
|
'@type': 'Series',
|
|
publisher: escapeExpression(metaData.blog.title),
|
|
url: metaData.url,
|
|
image: metaData.coverImage,
|
|
name: data.tag.name,
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getAuthorSchema(metaData, data) {
|
|
var schema = {
|
|
'@context': 'http://schema.org',
|
|
'@type': 'Person',
|
|
sameAs: trimSameAs(data, 'author'),
|
|
name: escapeExpression(data.author.name),
|
|
url: metaData.authorUrl,
|
|
image: metaData.coverImage,
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getSchema(metaData, data) {
|
|
if (!config.isPrivacyDisabled('useStructuredData')) {
|
|
var context = data.context ? data.context[0] : null;
|
|
if (context === 'post' || context === 'page') {
|
|
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);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
module.exports = getSchema;
|