Removed fallback Ghost icon in staff notifications (#20731)

ref https://linear.app/tryghost/issue/PLG-150

- if the publication has no custom icon, staff notifications do not
render the Ghost icon as fallback anymore
This commit is contained in:
Sag 2024-08-08 17:47:51 +02:00 committed by GitHub
parent e0a07c6813
commit 0d9955538d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 35 additions and 17 deletions

View File

@ -11,7 +11,7 @@ function getBlogLogo() {
// CASE: no publication logo is updated. We can try to use either an uploaded publication icon // CASE: no publication logo is updated. We can try to use either an uploaded publication icon
// or use the default one to make // or use the default one to make
// Google happy with it. See https://github.com/TryGhost/Ghost/issues/7558 // Google happy with it. See https://github.com/TryGhost/Ghost/issues/7558
logo.url = blogIcon.getIconUrl(true); logo.url = blogIcon.getIconUrl({absolute: true});
} }
return logo; return logo;

View File

@ -98,13 +98,17 @@ class BlogIcon {
} }
/** /**
* Return URL for Blog icon: [subdirectory or not]favicon.[ico, jpeg, or png] * Return URL for blog icon, if available: [subdirectory or not]favicon.[ico, jpeg, or png]
* Always returns {string} getIconUrl * Otherwise, fallbacks to the default Ghost favicon.ico file, if requested
* @returns {string} [subdirectory or not]favicon.[ico, jpeg, or png] * Otherwise, returns null
* @param {Object} [options]
* @param {boolean} [options.absolute] - if true, return absolute URL. Default: false
* @param {boolean} [options.fallbackToDefault] - if true, fallbacks to Ghost's default favicon.ico when no blog icon is found. Default: true
* @returns {string|null} [subdirectory or not]favicon.[ico, jpeg, or png] or null
* @description Checks if we have a custom uploaded icon and the extension of it. If no custom uploaded icon * @description Checks if we have a custom uploaded icon and the extension of it. If no custom uploaded icon
* exists, we're returning the default `favicon.ico` * exists, we're returning the default `favicon.ico`
*/ */
getIconUrl(absolute) { getIconUrl({absolute = false, fallbackToDefault = true} = {}) {
const blogIcon = this.settingsCache.get('icon'); const blogIcon = this.settingsCache.get('icon');
if (blogIcon) { if (blogIcon) {
@ -124,9 +128,13 @@ class BlogIcon {
const sizedIcon = blogIcon.replace(/\/content\/images\//, '/content/images/size/w256h256/'); const sizedIcon = blogIcon.replace(/\/content\/images\//, '/content/images/size/w256h256/');
return this.urlUtils.urlFor({relativeUrl: sizedIcon}, absolute ? true : undefined); return this.urlUtils.urlFor({relativeUrl: sizedIcon}, absolute ? true : undefined);
} else { }
if (fallbackToDefault) {
return this.urlUtils.urlFor({relativeUrl: '/favicon.ico'}, absolute ? true : undefined); return this.urlUtils.urlFor({relativeUrl: '/favicon.ico'}, absolute ? true : undefined);
} }
return null;
} }
/** /**

View File

@ -110,7 +110,7 @@ function ping(post) {
// if it is a post or a test message to check webhook working. // if it is a post or a test message to check webhook working.
text: `Notification from *${blogTitle}* :ghost:`, text: `Notification from *${blogTitle}* :ghost:`,
unfurl_links: true, unfurl_links: true,
icon_url: blogIcon.getIconUrl(true), icon_url: blogIcon.getIconUrl({absolute: true}),
username: slackSettings.username, username: slackSettings.username,
// We don't want to send attachment if it is a test notification. // We don't want to send attachment if it is a test notification.
attachments: [ attachments: [
@ -141,7 +141,7 @@ function ping(post) {
} }
], ],
footer: blogTitle, footer: blogTitle,
footer_icon: blogIcon.getIconUrl(true), footer_icon: blogIcon.getIconUrl({absolute: true}),
ts: moment().unix() ts: moment().unix()
} }
] ]
@ -150,7 +150,7 @@ function ping(post) {
slackData = { slackData = {
text: message, text: message,
unfurl_links: true, unfurl_links: true,
icon_url: blogIcon.getIconUrl(true), icon_url: blogIcon.getIconUrl({absolute: true}),
username: slackSettings.username username: slackSettings.username
}; };
} }

View File

@ -51,7 +51,7 @@ describe('lib/image: blog icon', function () {
} }
} }
}}); }});
blogIcon.getIconUrl(true).should.deepEqual([{relativeUrl: '/content/images/2017/04/my-icon.ico'}, true]); blogIcon.getIconUrl({absolute: true}).should.deepEqual([{relativeUrl: '/content/images/2017/04/my-icon.ico'}, true]);
}); });
it('custom uploaded png blog icon', function () { it('custom uploaded png blog icon', function () {
@ -64,7 +64,7 @@ describe('lib/image: blog icon', function () {
} }
} }
}}); }});
blogIcon.getIconUrl(true).should.deepEqual([{relativeUrl: '/content/images/size/w256h256/2017/04/my-icon.png'}, true]); blogIcon.getIconUrl({absolute: true}).should.deepEqual([{relativeUrl: '/content/images/size/w256h256/2017/04/my-icon.png'}, true]);
}); });
it('default ico blog icon', function () { it('default ico blog icon', function () {
@ -73,7 +73,17 @@ describe('lib/image: blog icon', function () {
}, settingsCache: { }, settingsCache: {
get: () => {} get: () => {}
}}); }});
blogIcon.getIconUrl(true).should.deepEqual([{relativeUrl: '/favicon.ico'}, true]); blogIcon.getIconUrl({absolute: true}).should.deepEqual([{relativeUrl: '/favicon.ico'}, true]);
});
it('returns null if no fallback is requested', function () {
const blogIcon = new BlogIcon({config: {}, storageUtils: {}, urlUtils: {
urlFor: (key, boolean) => [key, boolean]
}, settingsCache: {
get: () => {}
}});
should.equal(blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}), null);
}); });
}); });
}); });

View File

@ -45,7 +45,7 @@ class StaffServiceEmails {
attributionUrl: attribution?.url || '', attributionUrl: attribution?.url || '',
referrerSource: attribution?.referrerSource, referrerSource: attribution?.referrerSource,
siteTitle: this.settingsCache.get('title'), siteTitle: this.settingsCache.get('title'),
siteIconUrl: this.blogIcon.getIconUrl(true), siteIconUrl: this.blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}),
siteUrl: this.urlUtils.getSiteUrl(), siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain, siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'), accentColor: this.settingsCache.get('accent_color'),
@ -105,7 +105,7 @@ class StaffServiceEmails {
offerData, offerData,
subscriptionData, subscriptionData,
siteTitle: this.settingsCache.get('title'), siteTitle: this.settingsCache.get('title'),
siteIconUrl: this.blogIcon.getIconUrl(true), siteIconUrl: this.blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}),
siteUrl: this.urlUtils.getSiteUrl(), siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain, siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'), accentColor: this.settingsCache.get('accent_color'),
@ -156,7 +156,7 @@ class StaffServiceEmails {
tierData, tierData,
subscriptionData, subscriptionData,
siteTitle: this.settingsCache.get('title'), siteTitle: this.settingsCache.get('title'),
siteIconUrl: this.blogIcon.getIconUrl(true), siteIconUrl: this.blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}),
siteUrl: this.urlUtils.getSiteUrl(), siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain, siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'), accentColor: this.settingsCache.get('accent_color'),
@ -186,7 +186,7 @@ class StaffServiceEmails {
return { return {
siteTitle: this.settingsCache.get('title'), siteTitle: this.settingsCache.get('title'),
siteIconUrl: this.blogIcon.getIconUrl(true), siteIconUrl: this.blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}),
siteUrl: this.urlUtils.getSiteUrl(), siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain, siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'), accentColor: this.settingsCache.get('accent_color'),
@ -287,7 +287,7 @@ class StaffServiceEmails {
const templateData = { const templateData = {
siteTitle: this.settingsCache.get('title'), siteTitle: this.settingsCache.get('title'),
siteUrl: this.urlUtils.getSiteUrl(), siteUrl: this.urlUtils.getSiteUrl(),
siteIconUrl: this.blogIcon.getIconUrl(true), siteIconUrl: this.blogIcon.getIconUrl({absolute: true, fallbackToDefault: false}),
siteDomain: this.siteDomain, siteDomain: this.siteDomain,
fromEmail: this.fromEmailAddress, fromEmail: this.fromEmailAddress,
toEmail: to, toEmail: to,