const _ = require('lodash');
const oneLineTrim = require('common-tags/lib/oneLineTrim');
const previousSpec = require('./v1');
const ghostVersions = require('../utils').versions;
const docsBaseUrl = `https://ghost.org/docs/themes/`;
// TODO: we don't use versioned docs anymore and the previous rules should only contain
// correct links. The usage of replacing the previousBaseUrl can probably be removed
const prevDocsBaseUrl = `https://themes.ghost.org/v${ghostVersions.v1.docs}/docs/`;
const prevDocsBaseUrlRegEx = new RegExp(prevDocsBaseUrl, 'g');
const previousKnownHelpers = previousSpec.knownHelpers;
const previousTemplates = previousSpec.templates;
const previousRules = previousSpec.rules;
function requiredClassRule(strings) {
return `The .${strings[0]}
CSS class is required to appear styled in your theme`;
}
function requiredClassDetails(strings) {
return oneLineTrim`The .${strings[0]}
CSS class is required otherwise wide images will appear unstyled.
Find out more about required theme changes for the Koenig editor here.`;
}
// assign new or overwrite existing knownHelpers, templates, or rules here:
let knownHelpers = ['link', 'link_class', 'concat'];
let templates = [];
let rules = {
// New rules
'GS001-DEPR-USER-GET': {
level: 'error',
rule: `Replace {{#get "users"}}
with {{#get "authors"}}
`,
details: oneLineTrim`The usage of {{#get "users"}}
is deprecated and will not return any data. It should be replaced with {{#get "authors"}}
.
Find more information about the {{get}}
helper here.`,
regex: /{{\s*?#get ("|')\s*users("|')\s*/g,
helper: '{{#get "users"}}'
},
'GS001-DEPR-AUTH-INCL': {
level: 'error',
rule: `Replace include="author"
with include="authors"
`,
details: oneLineTrim`The usage of {{#get "posts" include="author"}}
is deprecated and should be replaced with {{#get "posts" include="authors"}}
.
Find more information about the {{get}}
helper here.`,
// This regex seems only to work properly with the escaped characters. Removing them resulted
// in not detecting the wrong usage.
regex: /{{\s*?#get.+include=("|')\s*?([\w\[\]]+,{1}\s*?)*?(\s*?author\s*?)(\s*,{1}\s?[\w\[\]]+)*?\s*?("|')(.*)}}/g, // eslint-disable-line no-useless-escape
helper: 'include="author"'
},
'GS001-DEPR-AUTH-FIELD': {
level: 'error',
rule: `Replace fields="author"
with fields="authors"
`,
details: oneLineTrim`The usage of {{#get "posts" fields="author"}}
is deprecated and should be replaced with
{{#get "posts" fields="primary_author"}}
or {{#get "posts" fields="authors.[#]"}}
.
Find more information about the {{get}}
helper here.`,
// This regex seems only to work properly with the escaped characters. Removing them resulted
// in not detecting the wrong usage.
regex: /{{\s*?#get.+fields=("|')\s*?([\w\[\]]+,{1}\s*?)*?(\s*?author\s*?)(\s*,{1}\s?[\w\[\]]+)*?\s*?("|')(.*)}}/g, // eslint-disable-line no-useless-escape
helper: 'fields="author"'
},
'GS001-DEPR-AUTH-FILT': {
level: 'error',
rule: `Replace filter="author:[...]"
with filter="authors:[...]"
`,
details: oneLineTrim`The usage of {{#get "posts" filter="author:[...]"}}
is deprecated and should be replaced with {{#get "posts" filter="authors:[...]"}}
.
Find more information about the {{get}}
helper here.`,
// This regex seems only to work properly with the escaped characters. Removing them resulted
// in not detecting the wrong usage.
regex: /{{\s*?#get.+filter=("|')\s*?([\w\[\]]+,{1}\s*?)*?(\s*?author:).*("|')(.*)}}/g, // eslint-disable-line no-useless-escape
helper: 'filter="author:[...]"'
},
'GS001-DEPR-AUTHBL': {
level: 'error',
rule: 'Replace {{#author}}
with {{#primary_author}}
or {{#foreach authors}}...{{/foreach}}
',
details: oneLineTrim`The usage of {{#author}}
block helper outside of author.hbs
is deprecated and
should be replaced with {{#primary_author}}
or {{#foreach authors}}...{{/foreach}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?#author\s*?}}/g,
notValidIn: 'author.hbs',
helper: '{{#author}}'
},
'GS001-DEPR-CON-AUTH': {
level: 'error',
rule: `Replace {{#if author.*}}
with {{#if primary_author.*}}
or {{#if authors.[#].*}}
`,
details: oneLineTrim`The usage of {{#if author.*}}
is deprecated and should be replaced with {{#if primary_author.*}}
or {{#if authors.[#].*}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?#if\s*?(author)(?:\.\w+)*?\s*?}}/g,
helper: '{{#if author.*}}'
},
'GS001-DEPR-CON-PAUTH': {
level: 'error',
rule: `Replace {{#if post.author.*}}
with {{#if post.primary_author.*}}
or {{#if post.authors.[#].*}}
`,
details: oneLineTrim`The usage of {{#if post.author.*}}
is deprecated and should be replaced with {{#if post.primary_author.*}}
or {{#if post.authors.[#].*}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?#if\s*?(?:post\.)(author)(?:\.\w+)*?\s*?}}/g,
helper: '{{#if post.author.*}}'
},
'GS001-DEPR-AUTH': {
level: 'error',
rule: 'Replace {{author}}
with {{authors}}
',
details: oneLineTrim`The usage of {{author}}
is deprecated and should be replaced with {{authors}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\s*?}}/g,
helper: '{{author}}'
},
'GS001-DEPR-AUTH-ID': {
level: 'error',
rule: 'Replace {{author.id}}
with {{primary_author.id}}
or {{authors.[#].id}}
',
details: oneLineTrim`The usage of {{author.id}}
is deprecated and should be replaced with either {{primary_author.id}}
or {{authors.[#].id}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.id\s*?}}/g,
helper: '{{author.id}}'
},
'GS001-DEPR-AUTH-SLUG': {
level: 'error',
rule: 'Replace {{author.slug}}
with {{primary_author.slug}}
or {{authors.[#].slug}}
',
details: oneLineTrim`The usage of {{author.slug}}
is deprecated and should be replaced with either {{primary_author.slug}}
or {{authors.[#].slug}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.slug\s*?}}/g,
helper: '{{author.slug}}'
},
'GS001-DEPR-AUTH-MAIL': {
level: 'error',
rule: 'Replace {{author.email}}
with {{primary_author.email}}
or {{authors.[#].email}}
',
details: oneLineTrim`The usage of {{author.email}}
is deprecated and should be replaced with either {{primary_author.email}}
or {{authors.[#].email}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.email\s*?}}/g,
helper: '{{author.email}}'
},
'GS001-DEPR-AUTH-MT': {
level: 'error',
rule: 'Replace {{author.meta_title}}
with {{primary_author.meta_title}}
or {{authors.[#].meta_title}}
',
details: oneLineTrim`The usage of {{author.meta_title}}
is deprecated and should be replaced with either {{primary_author.meta_title}}
or {{authors.[#].meta_title}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.meta_title\s*?}}/g,
helper: '{{author.meta_title}}'
},
'GS001-DEPR-AUTH-MD': {
level: 'error',
rule: 'Replace {{author.meta_description}}
with {{primary_author.meta_description}}
or {{authors.[#].meta_description}}
',
details: oneLineTrim`The usage of {{author.meta_description}}
is deprecated and should be replaced with either {{primary_author.meta_description}}
or {{authors.[#].meta_description}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.meta_description\s*?}}/g,
helper: '{{author.meta_description}}'
},
'GS001-DEPR-AUTH-NAME': {
level: 'error',
rule: 'Replace {{author.name}}
with {{primary_author.name}}
or {{authors.[#].name}}
',
details: oneLineTrim`The usage of {{author.name}}
is deprecated and should be replaced with either {{primary_author.name}}
or {{authors.[#].name}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.name\s*?}}/g,
helper: '{{author.name}}'
},
'GS001-DEPR-AUTH-BIO': {
level: 'error',
rule: 'Replace {{author.bio}}
with {{primary_author.bio}}
or {{authors.[#].bio}}
',
details: oneLineTrim`The usage of {{author.bio}}
is deprecated and should be replaced with either {{primary_author.bio}}
or {{authors.[#].bio}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.bio\s*?}}/g,
helper: '{{author.bio}}'
},
'GS001-DEPR-AUTH-LOC': {
level: 'error',
rule: 'Replace {{author.location}}
with {{primary_author.location}}
or {{authors.[#].location}}
',
details: oneLineTrim`The usage of {{author.location}}
is deprecated and should be replaced with either {{primary_author.location}}
or {{authors.[#].location}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.location\s*?}}/g,
helper: '{{author.location}}'
},
'GS001-DEPR-AUTH-WEB': {
level: 'error',
rule: 'Replace {{author.website}}
with {{primary_author.website}}
or {{authors.[#].website}}
',
details: oneLineTrim`The usage of {{author.website}}
is deprecated and should be replaced with either {{primary_author.website}}
or {{authors.[#].website}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.website\s*?}}/g,
helper: '{{author.website}}'
},
'GS001-DEPR-AUTH-TW': {
level: 'error',
rule: 'Replace {{author.twitter}}
with {{primary_author.twitter}}
or {{authors.[#].twitter}}
',
details: oneLineTrim`The usage of {{author.twitter}}
is deprecated and should be replaced with either {{primary_author.twitter}}
or {{authors.[#].twitter}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.twitter\s*?}}/g,
helper: '{{author.twitter}}'
},
'GS001-DEPR-AUTH-FB': {
level: 'error',
rule: 'Replace {{author.facebook}}
with {{primary_author.facebook}}
or {{authors.[#].facebook}}
',
details: oneLineTrim`The usage of {{author.facebook}}
is deprecated and should be replaced with either {{primary_author.facebook}}
or {{authors.[#].facebook}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.facebook\s*?}}/g,
helper: '{{author.facebook}}'
},
'GS001-DEPR-AUTH-PIMG': {
level: 'error',
rule: 'Replace {{author.profile_image}}
with {{primary_author.profile_image}}
or {{authors.[#].profile_image}}
',
details: oneLineTrim`The usage of {{author.profile_image}}
is deprecated and should be replaced with either {{primary_author.profile_image}}
or {{authors.[#].profile_image}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.profile_image\s*?}}/g,
helper: '{{author.profile_image}}'
},
'GS001-DEPR-AUTH-CIMG': {
level: 'error',
rule: 'Replace {{author.cover_image}}
with {{primary_author.cover_image}}
or {{authors.[#].cover_image}}
',
details: oneLineTrim`The usage of {{author.cover_image}}
is deprecated and should be replaced with either {{primary_author.cover_image}}
or {{authors.[#].cover_image}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.cover_image\s*?}}/g,
helper: '{{author.cover_image}}'
},
'GS001-DEPR-AUTH-URL': {
level: 'error',
rule: 'Replace {{author.url}}
with {{primary_author.url}}
or {{authors.[#].url}}
',
details: oneLineTrim`The usage of {{author.url}}
is deprecated and should be replaced with either {{primary_author.url}}
or {{authors.[#].url}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?author\.url\s*?}}/g,
helper: '{{author.url}}'
},
'GS001-DEPR-PAUTH': {
level: 'error',
rule: 'Replace {{post.author}}
with {{post.primary_author}}
or {{authors.[#]}}
',
details: oneLineTrim`The usage of {{post.author}}
is deprecated and should be replaced with either {{post.primary_author}}
or {{post.authors.[#]}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\s*?}}/g,
helper: '{{post.author}}'
},
'GS001-DEPR-PAUTH-ID': {
level: 'error',
rule: 'Replace {{post.author.id}}
with {{post.primary_author.id}}
or {{authors.[#].id}}
',
details: oneLineTrim`The usage of {{post.author.id}}
is deprecated and should be replaced with either {{post.primary_author.id}}
or {{post.authors.[#].id}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.id\s*?}}/g,
helper: '{{post.author.id}}'
},
'GS001-DEPR-PAUTH-SLUG': {
level: 'error',
rule: 'Replace {{post.author.slug}}
with {{post.primary_author.slug}}
or {{post.authors.[#].slug}}
',
details: oneLineTrim`The usage of {{post.author.slug}}
is deprecated and should be replaced with either {{post.primary_author.slug}}
or {{post.authors.[#].slug}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.slug\s*?}}/g,
helper: '{{post.author.slug}}'
},
'GS001-DEPR-PAUTH-MAIL': {
level: 'error',
rule: 'Replace {{post.author.email}}
with {{post.primary_author.email}}
or {{post.authors.[#].email}}
',
details: oneLineTrim`The usage of {{post.author.email}}
is deprecated and should be replaced with either {{post.primary_author.email}}
or {{post.authors.[#].email}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.email\s*?}}/g,
helper: '{{post.author.email}}'
},
'GS001-DEPR-PAUTH-MT': {
level: 'error',
rule: 'Replace {{post.author.meta_title}}
with {{post.primary_author.meta_title}}
or {{post.authors.[#].meta_title}}
',
details: oneLineTrim`The usage of {{post.author.meta_title}}
is deprecated and should be replaced with either {{post.primary_author.meta_title}}
or {{post.authors.[#].meta_title}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.meta_title\s*?}}/g,
helper: '{{post.author.meta_title}}'
},
'GS001-DEPR-PAUTH-MD': {
level: 'error',
rule: 'Replace {{post.author.meta_description}}
with {{post.primary_author.meta_description}}
or {{post.authors.[#].meta_description}}
',
details: oneLineTrim`The usage of {{post.author.meta_description}}
is deprecated and should be replaced with either {{post.primary_author.meta_description}}
or {{post.authors.[#].meta_description}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.meta_description\s*?}}/g,
helper: '{{post.author.meta_description}}'
},
'GS001-DEPR-PAUTH-NAME': {
level: 'error',
rule: 'Replace {{post.author.name}}
with {{post.primary_author.name}}
or {{post.authors.[#].name}}
',
details: oneLineTrim`The usage of {{post.author.name}}
is deprecated and should be replaced with either {{post.primary_author.name}}
or {{post.authors.[#].name}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.name\s*?}}/g,
helper: '{{post.author.name}}'
},
'GS001-DEPR-PAUTH-BIO': {
level: 'error',
rule: 'Replace {{post.author.bio}}
with {{post.primary_author.bio}}
or {{post.authors.[#].bio}}
',
details: oneLineTrim`The usage of {{post.author.bio}}
is deprecated and should be replaced with either {{post.primary_author.bio}}
or {{post.authors.[#].bio}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.bio\s*?}}/g,
helper: '{{post.author.bio}}'
},
'GS001-DEPR-PAUTH-LOC': {
level: 'error',
rule: 'Replace {{post.author.location}}
with {{post.primary_author.location}}
or {{post.authors.[#].location}}
',
details: oneLineTrim`The usage of {{post.author.location}}
is deprecated and should be replaced with either {{post.primary_author.location}}
or {{post.authors.[#].location}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.location\s*?}}/g,
helper: '{{post.author.location}}'
},
'GS001-DEPR-PAUTH-WEB': {
level: 'error',
rule: 'Replace {{post.author.website}}
with {{post.primary_author.website}}
or {{post.authors.[#].website}}
',
details: oneLineTrim`The usage of {{post.author.website}}
is deprecated and should be replaced with either {{post.primary_author.website}}
or {{post.authors.[#].website}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.website\s*?}}/g,
helper: '{{post.author.website}}'
},
'GS001-DEPR-PAUTH-TW': {
level: 'error',
rule: 'Replace {{post.author.twitter}}
with {{post.primary_author.twitter}}
or {{post.authors.[#].twitter}}
',
details: oneLineTrim`The usage of {{post.author.twitter}}
is deprecated and should be replaced with either {{post.primary_author.twitter}}
or {{post.authors.[#].twitter}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.twitter\s*?}}/g,
helper: '{{post.author.twitter}}'
},
'GS001-DEPR-PAUTH-FB': {
level: 'error',
rule: 'Replace {{post.author.facebook}}
with {{post.primary_author.facebook}}
or {{post.authors.[#].facebook}}
',
details: oneLineTrim`The usage of {{post.author.facebook}}
is deprecated and should be replaced with either {{post.primary_author.facebook}}
or {{post.authors.[#].facebook}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.facebook\s*?}}/g,
helper: '{{post.author.facebook}}'
},
'GS001-DEPR-PAUTH-PIMG': {
level: 'error',
rule: 'Replace {{post.author.profile_image}}
with {{post.primary_author.profile_image}}
or {{post.authors.[#].profile_image}}
',
details: oneLineTrim`The usage of {{post.author.profile_image}}
is deprecated and should be replaced with either {{post.primary_author.profile_image}}
or {{post.authors.[#].profile_image}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.profile_image\s*?}}/g,
helper: '{{post.author.profile_image}}'
},
'GS001-DEPR-PAUTH-CIMG': {
level: 'error',
rule: 'Replace {{post.author.cover_image}}
with {{post.primary_author.cover_image}}
or {{post.authors.[#].cover_image}}
',
details: oneLineTrim`The usage of {{post.author.cover_image}}
is deprecated and should be replaced with either {{post.primary_author.cover_image}}
or {{post.authors.[#].cover_image}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.cover_image\s*?}}/g,
helper: '{{post.author.cover_image}}'
},
'GS001-DEPR-PAUTH-URL': {
level: 'error',
rule: 'Replace {{post.author.url}}
with {{post.primary_author.url}}
or {{post.authors.[#].url}}
',
details: oneLineTrim`The usage of {{post.author.url}}
is deprecated and should be replaced with either {{post.primary_author.url}}
or {{post.authors.[#].url}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?post\.author\.url\s*?}}/g,
helper: '{{post.author.url}}'
},
'GS001-DEPR-PAID': {
level: 'error',
rule: 'Replace {{post.author_id}}
code with {{post.primary_author.id}}
',
details: oneLineTrim`The {{post.author_id}}
attribute in post context was removed
Instead of {{post.author_id}}
you need to use {{post.primary_author.id}}
.
See the object attributes of post
here.`,
regex: /{{\s*?post\.author_id\s*?}}/g,
helper: '{{post.author_id}}'
},
'GS001-DEPR-NAUTH': {
level: 'error',
rule: 'Replace ../author
with ../primary_author
or ../authors.[#]
',
details: oneLineTrim`The usage of ../author
is deprecated and should be replaced with either ../primary_author
or ../authors.[#]
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?(?:#|#if)?\s*?\.\.\/author(?:\.\S*?)?\s*?}}/g,
helper: '{{../author}}'
},
'GS001-DEPR-IUA': {
level: 'error',
rule: 'Replace {{img_url author.*}}
with {{img_url primary_author.*}}
or .{img_url author.[#].*}}
',
details: oneLineTrim`The usage of {{img_url author.*}}
is deprecated and should be replaced with either {{img_url primary_author.*}}
or {{img_url author.[#].*}}
.
Find more information about the {{authors}}
helper here.`,
regex: /{{\s*?img_url\s*?(author.).*}}/g,
helper: '{{img_url author.*}}'
},
'GS001-DEPR-BLOG': {
level: 'error',
rule: 'The {{@blog}}
helper should be replaced with {{@site}}
',
details: oneLineTrim`With the introduction of the Content API {{@blog}}
became deprecated in favour of {{@site}}
.
The {{@blog}}
helper will be removed in next version of Ghost and should not be used.
Find more information about the @site
property here.`,
regex: /{{\s*?@blog\.[a-zA-Z0-9_]+\s*?}}/g,
helper: '{{@blog}}'
},
'GS001-DEPR-BPL': {
level: 'error',
rule: '{{@blog.permalinks}}
was removed',
details: oneLineTrim`With the introduction of Dynamic Routing, you can define multiple permalinks.
The {{@blog.permalinks}}
property will therefore no longer be used and should be removed from the theme.
Find more information about Ghost data helpers here.`,
regex: /{{\s*?@blog\.permalinks\s*?}}/g,
helper: '{{@blog.permalinks}}'
},
'GS001-DEPR-SPL': {
level: 'error',
rule: '{{@site.permalinks}}
was removed',
details: oneLineTrim`With the introduction of Dynamic Routing, you can define multiple permalinks.
The {{@site.permalinks}}
property will therefore no longer be used and should be removed from the theme.
Find more information about the @site
property here.`,
regex: /{{\s*?@site\.permalinks\s*?}}/g,
helper: '{{@site.permalinks}}'
},
'GS001-DEPR-SGH': {
level: 'error',
rule: 'Replace {{@site.ghost_head}}
with {{ghost_head}}
',
details: oneLineTrim`The usage of {{@site.ghost_head}}
is deprecated and should be replaced with {{ghost_head}}
.
The {{@site.ghost_head}}
property will therefore no longer be used and should be removed from the theme.
Find more information about the {{ghost_head}}
property here.`,
regex: /{{\s*?@site\.ghost_head\s*?}}/g,
helper: '{{@site.ghost_head}}'
},
'GS001-DEPR-SGF': {
level: 'error',
rule: 'Replace {{@site.ghost_foot}}
with {{ghost_foot}}
',
details: oneLineTrim`The usage of {{@site.ghost_foot}}
is deprecated and should be replaced with {{ghost_foot}}
.
The {{@site.ghost_foot}}
property will therefore no longer be used and should be removed from the theme.
Find more information about the {{ghost_foot}}
property here.`,
regex: /{{\s*?@site\.ghost_foot\s*?}}/g,
helper: '{{@site.ghost_foot}}'
},
'GS001-DEPR-LANG': {
level: 'error',
rule: 'The {{lang}}
helper should be replaced with {{@site.lang}}
',
details: oneLineTrim`The {{lang}}
helper is a duplicate of {{@site.lang}}
. Using {{@site.lang}}
is preferred.
The {{lang}}
helper will be removed in next version of Ghost and should not be used.
Find more information about the @site.lang
property here.`,
regex: /{{\s*?lang\s*?}}/g,
helper: '{{lang}}'
},
'GS001-DEPR-CSS-KGMD': {
level: 'warning',
rule: `.kg-card-markdown
doesn't exist in current version of Ghost, ensure your theme works without it`,
details: oneLineTrim`The .kg-card-markdown
CSS class is deprecated and will no longer be used in Ghost.
It's recommended to add your own wrapper around the {{content}}
helper and target that instead if needed.
Find out more about required theme changes for the Koenig editor here.`,
regex: /\.kg-card-markdown/g,
className: '.kg-card-markdown',
css: true
},
'GS050-CSS-KGWW': {
level: 'error',
rule: requiredClassRule`kg-width-wide`,
details: requiredClassDetails`kg-width-wide`,
regex: /\.kg-width-wide/g,
className: '.kg-width-wide',
css: true
},
'GS050-CSS-KGWF': {
level: 'error',
rule: requiredClassRule`kg-width-full`,
details: requiredClassDetails`kg-width-full`,
regex: /\.kg-width-full/g,
className: '.kg-width-full',
css: true
},
'GS050-CSS-KGGC': {
level: 'error',
rule: requiredClassRule`kg-gallery-container`,
details: requiredClassDetails``,
regex: /\.kg-gallery-container/g,
className: '.kg-gallery-container',
css: true,
cardAsset: 'gallery'
},
'GS050-CSS-KGGR': {
level: 'error',
rule: requiredClassRule`kg-gallery-row`,
details: requiredClassDetails`kg-gallery-row`,
regex: /\.kg-gallery-row/g,
className: '.kg-gallery-row',
css: true,
cardAsset: 'gallery'
},
'GS050-CSS-KGGI': {
level: 'error',
rule: requiredClassRule`kg-gallery-image`,
details: requiredClassDetails`kg-gallery-image`,
regex: /\.kg-gallery-image/g,
className: '.kg-gallery-image',
css: true,
cardAsset: 'gallery'
},
'GS050-CSS-KGBM': {
level: 'error',
rule: requiredClassRule`kg-bookmark-card`,
details: requiredClassDetails`kg-bookmark-card`,
regex: /\.kg-bookmark-card/g,
className: '.kg-bookmark-card',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMCO': {
level: 'error',
rule: requiredClassRule`kg-bookmark-container`,
details: requiredClassDetails`kg-bookmark-container`,
regex: /\.kg-bookmark-container/g,
className: '.kg-bookmark-container',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMCON': {
level: 'error',
rule: requiredClassRule`kg-bookmark-content`,
details: requiredClassDetails`kg-bookmark-content`,
regex: /\.kg-bookmark-content/g,
className: '.kg-bookmark-content',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMTI': {
level: 'error',
rule: requiredClassRule`kg-bookmark-title`,
details: requiredClassDetails`kg-bookmark-title`,
regex: /\.kg-bookmark-title/g,
className: '.kg-bookmark-title',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMDE': {
level: 'error',
rule: requiredClassRule`kg-bookmark-description`,
details: requiredClassDetails`kg-bookmark-description`,
regex: /\.kg-bookmark-description/g,
className: '.kg-bookmark-description',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMME': {
level: 'error',
rule: requiredClassRule`kg-bookmark-metadata`,
details: requiredClassDetails`kg-bookmark-metadata`,
regex: /\.kg-bookmark-metadata/g,
className: '.kg-bookmark-metadata',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMIC': {
level: 'error',
rule: requiredClassRule`kg-bookmark-icon`,
details: requiredClassDetails`kg-bookmark-icon`,
regex: /\.kg-bookmark-icon/g,
className: '.kg-bookmark-icon',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMAU': {
level: 'error',
rule: requiredClassRule`kg-bookmark-author`,
details: requiredClassDetails`kg-bookmark-author`,
regex: /\.kg-bookmark-author/g,
className: '.kg-bookmark-author',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMPU': {
level: 'error',
rule: requiredClassRule`kg-bookmark-publisher`,
details: requiredClassDetails``,
regex: /\.kg-bookmark-publisher/g,
className: '.kg-bookmark-publisher',
css: true,
cardAsset: 'bookmark'
},
'GS050-CSS-KGBMTH': {
level: 'error',
rule: requiredClassRule`kg-bookmark-thumbnail`,
details: requiredClassDetails``,
regex: /\.kg-bookmark-thumbnail/g,
className: '.kg-bookmark-thumbnail',
css: true,
cardAsset: 'bookmark'
},
// Updated v1 rules
'GS001-DEPR-AC': {
level: 'error',
rule: 'Replace {{author.cover}}
with {{primary_author.cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{author.cover}}
you need to use
{{primary_author.cover_image}}
or {{authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?author\.cover\s*?}}/g,
helper: '{{author.cover}}'
},
'GS001-DEPR-AC-2': {
level: 'error',
rule: 'Replace {{primary_author.cover}}
with {{primary_author.cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{primary_author.cover}}
you need to use
{{primary_author.cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?primary_author\.cover\s*?}}/g,
helper: '{{primary_author.cover}}'
},
'GS001-DEPR-AC-3': {
level: 'error',
rule: 'Replace {{authors.[#].cover}}
with {{authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{authors.[#].cover}}
you need to use
{{authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?authors\.\[[0-9]+\]\.(cover)\s*?}}/g,
helper: '{{authors.[#].cover}}'
},
'GS001-DEPR-AIMG': {
level: 'error',
rule: 'Replace {{author.image}}
with {{primary_author.profile_image}}
or {{authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{author.image}}
, you need to use
{{primary_author.profile_image}}
or {{authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?author\.image\s*?}}/g,
helper: '{{author.image}}'
},
'GS001-DEPR-AIMG-2': {
level: 'error',
rule: 'Replace {{primary_author.image}}
with {{primary_author.profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{primary_author.image}}
, you need to use
{{primary_author.profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?primary_author\.(image)\s*?}}/g,
helper: '{{primary_author.image}}'
},
'GS001-DEPR-AIMG-3': {
level: 'error',
rule: 'Replace {{authors.[#].image}}
with {{authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{authors.[#].image}}
, you need to use
{{authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?authors\.\[[0-9]+\]\.(cover)\s*?}}/g,
helper: '{{authors.[#].image}}'
},
'GS001-DEPR-PAC': {
level: 'error',
rule: 'Replace {{post.author.cover}}
with {{post.primary_author.cover_image}}
or {{post.authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{post.author.cover}}
, you need to use
{{post.primary_author.cover_image}}
or {{post.authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.author\.cover\s*?}}/g,
helper: '{{post.author.cover}}'
},
'GS001-DEPR-PAC-2': {
level: 'error',
rule: 'Replace {{post.primary_author.cover}}
with {{post.primary_author.cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{post.primary_author.cover}}
, you need to use
{{post.primary_author.cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.primary_author\.cover\s*?}}/g,
helper: '{{post.primary_author.cover}}'
},
'GS001-DEPR-PAC-3': {
level: 'error',
rule: 'Replace {{post.authors.[#].cover}}
with {{post.authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{post.authors.[#].cover}}
, you need to use
{{post.authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.authors\.\[[0-9]+\]\.(cover)\s*?}}/g,
helper: '{{post.authors.[#].cover}}'
},
'GS001-DEPR-PAIMG': {
level: 'error',
rule: 'Replace {{post.author.image}}
with {{post.primary_author.profile_image}}
or {{post.authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{post.author.image}}
, you need to use
{{post.primary_author.profile_image}}
or {{post.authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.author\.image\s*?}}/g,
helper: '{{post.author.image}}'
},
'GS001-DEPR-PAIMG-2': {
level: 'error',
rule: 'Replace {{post.primary_author.image}}
with {{post.primary_author.profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{post.primary_author.image}}
, you need to use
{{post.primary_author.profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.primary_author\.image\s*?}}/g,
helper: '{{post.primary_author.image}}'
},
'GS001-DEPR-PAIMG-3': {
level: 'error',
rule: 'Replace {{post.authors.[#].image}}
with {{post.authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{post.authors.[#].image}}
, you need to use
{{post.authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?post\.authors\.\[[0-9]+\]\.(image)\s*?}}/g,
helper: '{{post.authors.[#].image}}'
},
'GS001-DEPR-CON-AC': {
level: 'error',
rule: 'Replace {{#if author.cover}}
with {{#if primary_author.cover_image}}
or {{#if authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if author.cover}}
, you need to use
{{#if primary_author.cover_image}}
or {{#if authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?author\.cover\s*?}}/g,
helper: '{{#if author.cover}}'
},
'GS001-DEPR-CON-AC-2': {
level: 'error',
rule: 'Replace {{#if primary_author.cover}}
with {{#if primary_author.cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if primary_author.cover}}
, you need to use
{{#if primary_author.cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?primary_author\.cover\s*?}}/g,
helper: '{{#if primary_author.cover}}'
},
'GS001-DEPR-CON-AC-3': {
level: 'error',
rule: 'Replace {{#if authors.[#].cover}}
with {{#if authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if authors.[#].cover}}
, you need to use
{{#if authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?authors\.\[[0-9]+\]\.cover\s*?}}/g,
helper: '{{#if authors.[#].cover}}'
},
'GS001-DEPR-CON-AIMG': {
level: 'error',
rule: 'Replace {{#if author.image}}
with {{#if primary_author.profile_image}}
or {{#if authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if author.image}}
, you need to use
{{#if primary_author.profile_image}}
or {{#if authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?author\.image\s*?}}/g,
helper: '{{#if author.image}}'
},
'GS001-DEPR-CON-AIMG-2': {
level: 'error',
rule: 'Replace {{#if primary_author.image}}
with {{#if primary_author.profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if primary_author.image}}
, you need to use
{{#if primary_author.profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?primary_author\.image\s*?}}/g,
helper: '{{#if primary_author.image}}'
},
'GS001-DEPR-CON-AIMG-3': {
level: 'error',
rule: 'Replace {{#if authors.[#].image}}
with {{#if authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if authors.[#].image}}
, you need to use
{{#if authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?authors\.\[[0-9]+\]\.image\s*?}}/g,
helper: '{{#if authors.[#].image}}'
},
'GS001-DEPR-CON-PAC': {
level: 'error',
rule: 'Replace {{#if post.author.cover}}
with {{#if post.primary_author.cover_image}}
or {{#if post.authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if post.author.cover}}
, you need to use
{{#if post.primary_author.cover_image}}
or {{#if post.authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.author\.cover\s*?}}/g,
helper: '{{#if post.author.cover}}'
},
'GS001-DEPR-CON-PAC-2': {
level: 'error',
rule: 'Replace {{#if post.primary_author.cover}}
with {{#if post.primary_author.cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if post.primary_author.cover}}
, you need to use
{{#if post.primary_author.cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.primary_author\.cover\s*?}}/g,
helper: '{{#if post.primary_author.cover}}'
},
'GS001-DEPR-CON-PAC-3': {
level: 'error',
rule: 'Replace {{#if post.authors.[#].cover}}
with {{#if post.authors.[#].cover_image}}
',
details: oneLineTrim`The cover
attribute was replaced with cover_image
.
Instead of {{#if post.authors.[#].cover}}
, you need to use
{{#if post.authors.[#].cover_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.authors\.\[[0-9]+\]\.cover\s*?}}/g,
helper: '{{#if post.authors.[#].cover}}'
},
'GS001-DEPR-CON-PAIMG': {
level: 'error',
rule: 'Replace {{#if post.author.image}}
with {{#if post.primary_author.profile_image}}
or {{#if post.authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if post.author.image}}
, you need to use
{{#if post.primary_author.profile_image}}
or {{#if post.authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.author\.image\s*?}}/g,
helper: '{{#if post.author.image}}'
},
'GS001-DEPR-CON-PAIMG-2': {
level: 'error',
rule: 'Replace {{#if post.primary_author.image}}
with {{#if post.primary_author.profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if post.primary_author.image}}
, you need to use
{{#if post.primary_author.profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.primary_author\.image\s*?}}/g,
helper: '{{#if post.primary_author.image}}'
},
'GS001-DEPR-CON-PAIMG-3': {
level: 'error',
rule: 'Replace {{#if post.authors.[#].image}}
with {{#if post.authors.[#].profile_image}}
',
details: oneLineTrim`The image
attribute was replaced with profile_image
.
Instead of {{#if post.authors.[#].image}}
, you need to use
{{#if post.authors.[#].profile_image}}
.
See the object attributes of author
here.`,
regex: /{{\s*?#if\s*?post\.authors\.\[[0-9]+\]\.image\s*?}}/g,
helper: '{{#if post.authors.[#].image}}'
},
'GS010-PJ-KEYWORDS': {
level: 'warning',
rule: 'package.json
property keywords
should contain ghost-theme
',
details: oneLineTrim`The property keywords
in your package.json
file must contain ghost-theme
. E.g. {"keywords": ["ghost-theme"]}
.
Check the package.json
documentation for further information.`
}
};
knownHelpers = _.union(previousKnownHelpers, knownHelpers);
templates = _.union(previousTemplates, templates);
// Merge the previous rules into the new rules, but overwrite any specified property,
// as well as adding any new rule to the spec.
// Furthermore, replace the usage of the old doc URLs that we're linking to, with the
// new version.
rules = _.each(_.merge({}, previousRules, rules), function replaceDocsUrl(value) {
value.details = value.details.replace(prevDocsBaseUrlRegEx, docsBaseUrl);
});
module.exports = {
knownHelpers: knownHelpers,
templates: templates,
rules: rules,
/**
* Copy of Ghost defaults for https://github.com/TryGhost/Ghost/blob/e25f1df0ae551c447da0d319bae06eadf9665444/core/frontend/services/theme-engine/config/defaults.json
*/
defaultPackageJSON: {
posts_per_page: 5,
card_assets: {
exclude: ['bookmark', 'gallery']
}
}
};