From d1bbc3cbe165519af2fdc7791386ccd09836cb03 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Tue, 27 Feb 2024 16:24:38 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20extra=20whitespace=20in?= =?UTF-8?q?=20plaintext=20transactional=20member=20emails=20(#19736)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes ENG-660 - added tagged template function to strip leading whitespace from our plaintext email strings without making the source file harder to read --- .../core/core/server/services/members/api.js | 28 +++++++++++++++---- .../admin/__snapshots__/members.test.js.snap | 18 ++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/ghost/core/core/server/services/members/api.js b/ghost/core/core/server/services/members/api.js index 21d6318a536d..5b5757455f06 100644 --- a/ghost/core/core/server/services/members/api.js +++ b/ghost/core/core/server/services/members/api.js @@ -27,6 +27,24 @@ const ghostMailer = new mail.GhostMailer(); module.exports = createApiInstance; +function trimLeadingWhitespace(strings, ...values) { + // Interweave the strings with the + // substitution vars first. + let output = ''; + for (let i = 0; i < values.length; i++) { + output += strings[i] + values[i]; + } + output += strings[values.length]; + + // Split on newlines. + const lines = output.split(/(?:\r\n|\n|\r)/); + + // Rip out the leading whitespace on each line. + return lines.map((line) => { + return line.trimStart(); + }).join('\n').trim(); +} + function createApiInstance(config) { const membersApiInstance = MembersApi({ tokenConfig: config.getTokenConfig(), @@ -75,7 +93,7 @@ function createApiInstance(config) { const siteTitle = settingsCache.get('title'); switch (type) { case 'subscribe': - return ` + return trimLeadingWhitespace` ${t(`Hey there,`)} ${t('You\'re one tap away from subscribing to {{siteTitle}} — please confirm your email address with this link:', {siteTitle, interpolation: {escapeValue: false}})} @@ -92,7 +110,7 @@ function createApiInstance(config) { ${t('If you did not make this request, you can simply delete this message.')} ${t('You will not be subscribed.')} `; case 'signup': - return ` + return trimLeadingWhitespace` ${t(`Hey there,`)} ${t('Tap the link below to complete the signup process for {{siteTitle}}, and be automatically signed in:', {siteTitle, interpolation: {escapeValue: false}})} @@ -109,7 +127,7 @@ function createApiInstance(config) { ${t('If you did not make this request, you can simply delete this message.')} ${t('You will not be signed up, and no account will be created for you.')} `; case 'signup-paid': - return ` + return trimLeadingWhitespace` ${t(`Hey there,`)} ${t('Thank you for subscribing to {{siteTitle}}. Tap the link below to be automatically signed in:', {siteTitle, interpolation: {escapeValue: false}})} @@ -126,7 +144,7 @@ function createApiInstance(config) { ${t('Thank you for subscribing to {{siteTitle}}!', {siteTitle, interpolation: {escapeValue: false}})} `; case 'updateEmail': - return ` + return trimLeadingWhitespace` ${t(`Hey there,`)} ${t('Please confirm your email address with this link:')} @@ -142,7 +160,7 @@ function createApiInstance(config) { `; case 'signin': default: - return ` + return trimLeadingWhitespace` ${t(`Hey there,`)} ${t('Welcome back! Use this link to securely sign in to your {{siteTitle}} account:', {siteTitle, interpolation: {escapeValue: false}})} diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap index 65d5c69733f7..7f19d6eb5ada 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/members.test.js.snap @@ -1790,22 +1790,20 @@ exports[`Members API Can add and send a signup confirmation email 3: [html 1] 1` `; exports[`Members API Can add and send a signup confirmation email 4: [text 1] 1`] = ` -" - Hey there, +"Hey there, - Tap the link below to complete the signup process for Ghost's Test Site, and be automatically signed in: +Tap the link below to complete the signup process for Ghost's Test Site, and be automatically signed in: - http://127.0.0.1:2369/members/?token=REPLACED_TOKEN&action=signup +http://127.0.0.1:2369/members/?token=REPLACED_TOKEN&action=signup - For your security, the link will expire in 24 hours time. +For your security, the link will expire in 24 hours time. - See you soon! +See you soon! - --- +--- - Sent to member_getting_confirmation@test.com - If you did not make this request, you can simply delete this message. You will not be signed up, and no account will be created for you. - " +Sent to member_getting_confirmation@test.com +If you did not make this request, you can simply delete this message. You will not be signed up, and no account will be created for you." `; exports[`Members API Can add and send a signup confirmation email 5: [metadata 1] 1`] = `