a9050f68ea
no issue - Removed deprecated 'blog' reference from frontend data. The alias (site->blog) stays till next version (v4) as it's not leaving much of technical debt but would ease the migration process for anybody still using it. - The follow up to this is substitute of all references to `options.data.blog` with `options.data.site` in "frontend" - Fixed test utils helper to use `site` instead of `blog` - Removed 0.1 flag checks in {{get}} helper - Removed user aliasing from {{get}} helper - Removed unused translation for {{get}} helper - Added a note to excerpt changes in metadata for future reference - Removed page alias used in description helper. The mix of page context with post object in the metadata was only possible in v0.1 - Changed mock in ghost_head helper to use v2 - Removed unneeded test for body class helper
192 lines
6.1 KiB
JavaScript
192 lines
6.1 KiB
JavaScript
var config = require('../../server/config'),
|
|
escapeExpression = require('../services/themes/engine').escapeExpression,
|
|
socialUrls = require('@tryghost/social-urls'),
|
|
_ = require('lodash');
|
|
|
|
function schemaImageObject(metaDataVal) {
|
|
var imageObject;
|
|
if (!metaDataVal) {
|
|
return null;
|
|
}
|
|
if (!metaDataVal.dimensions) {
|
|
return metaDataVal.url;
|
|
}
|
|
|
|
imageObject = {
|
|
'@type': 'ImageObject',
|
|
url: metaDataVal.url,
|
|
width: metaDataVal.dimensions.width,
|
|
height: metaDataVal.dimensions.height
|
|
};
|
|
|
|
return imageObject;
|
|
}
|
|
|
|
// 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' || context === 'page') {
|
|
if (data[context].primary_author.website) {
|
|
sameAs.push(escapeExpression(data[context].primary_author.website));
|
|
}
|
|
if (data[context].primary_author.facebook) {
|
|
sameAs.push(socialUrls.facebook(data[context].primary_author.facebook));
|
|
}
|
|
if (data[context].primary_author.twitter) {
|
|
sameAs.push(socialUrls.twitter(data[context].primary_author.twitter));
|
|
}
|
|
} else if (context === 'author') {
|
|
if (data.author.website) {
|
|
sameAs.push(escapeExpression(data.author.website));
|
|
}
|
|
if (data.author.facebook) {
|
|
sameAs.push(socialUrls.facebook(data.author.facebook));
|
|
}
|
|
if (data.author.twitter) {
|
|
sameAs.push(socialUrls.twitter(data.author.twitter));
|
|
}
|
|
}
|
|
|
|
return sameAs;
|
|
}
|
|
|
|
function getPostSchema(metaData, data) {
|
|
// CASE: metaData.excerpt for post context is populated by either the custom excerpt, the meta description,
|
|
// or the automated excerpt of 50 words. It is empty for any other context.
|
|
var description = metaData.excerpt ? escapeExpression(metaData.excerpt) : null,
|
|
schema;
|
|
|
|
const context = data.page ? 'page' : 'post';
|
|
|
|
schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Article',
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: escapeExpression(metaData.site.title),
|
|
logo: schemaImageObject(metaData.site.logo) || null
|
|
},
|
|
author: {
|
|
'@type': 'Person',
|
|
name: escapeExpression(data[context].primary_author.name),
|
|
image: schemaImageObject(metaData.authorImage),
|
|
url: metaData.authorUrl,
|
|
sameAs: trimSameAs(data, context),
|
|
description: data[context].primary_author.metaDescription ?
|
|
escapeExpression(data[context].primary_author.metaDescription) :
|
|
null
|
|
},
|
|
headline: escapeExpression(metaData.metaTitle),
|
|
url: metaData.url,
|
|
datePublished: metaData.publishedDate,
|
|
dateModified: metaData.modifiedDate,
|
|
image: schemaImageObject(metaData.coverImage),
|
|
keywords: metaData.keywords && metaData.keywords.length > 0 ?
|
|
metaData.keywords.join(', ') : null,
|
|
description: description,
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': metaData.site.url || null
|
|
}
|
|
};
|
|
schema.author = trimSchema(schema.author);
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getHomeSchema(metaData) {
|
|
var schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebSite',
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: escapeExpression(metaData.site.title),
|
|
logo: schemaImageObject(metaData.site.logo) || null
|
|
},
|
|
url: metaData.url,
|
|
image: schemaImageObject(metaData.coverImage),
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': metaData.site.url || null
|
|
},
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getTagSchema(metaData, data) {
|
|
var schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Series',
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: escapeExpression(metaData.site.title),
|
|
logo: schemaImageObject(metaData.site.logo) || null
|
|
},
|
|
url: metaData.url,
|
|
image: schemaImageObject(metaData.coverImage),
|
|
name: data.tag.name,
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': metaData.site.url || null
|
|
},
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getAuthorSchema(metaData, data) {
|
|
var schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Person',
|
|
sameAs: trimSameAs(data, 'author'),
|
|
name: escapeExpression(data.author.name),
|
|
url: metaData.authorUrl,
|
|
image: schemaImageObject(metaData.coverImage),
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': metaData.site.url || null
|
|
},
|
|
description: metaData.metaDescription ?
|
|
escapeExpression(metaData.metaDescription) :
|
|
null
|
|
};
|
|
|
|
return trimSchema(schema);
|
|
}
|
|
|
|
function getSchema(metaData, data) {
|
|
if (!config.isPrivacyDisabled('useStructuredData')) {
|
|
var context = data.context ? data.context : null;
|
|
if (_.includes(context, 'post') || _.includes(context, 'page') || _.includes(context, 'amp')) {
|
|
return getPostSchema(metaData, data);
|
|
} else if (_.includes(context, 'home')) {
|
|
return getHomeSchema(metaData);
|
|
} else if (_.includes(context, 'tag')) {
|
|
return getTagSchema(metaData, data);
|
|
} else if (_.includes(context, 'author')) {
|
|
return getAuthorSchema(metaData, data);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
module.exports = getSchema;
|