0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-08 02:52:39 -05:00

Extracted email-content-generator into a package

refs https://github.com/TryGhost/Toolbox/issues/292

- Following the concept of having as little code in Ghost core as possible :) The email content generation is also needed to be reused in the version mismatch handling package.
This commit is contained in:
Naz 2022-05-04 17:28:09 +08:00
parent 2d7bcdf80a
commit c627779948
5 changed files with 10 additions and 158 deletions

View file

@ -1,54 +0,0 @@
const _ = require('lodash').runInContext();
const fs = require('fs-extra');
const path = require('path');
const htmlToText = require('html-to-text');
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
class EmailContentGenerator {
/**
*
* @param {Object} options
* @param {function} options.getSiteUrl
* @param {function} options.getSiteTitle
* @param {string} options.templatesDir - path to the directory containing email templates
*/
constructor({getSiteUrl, getSiteTitle, templatesDir}) {
this.getSiteUrl = getSiteUrl;
this.getSiteTitle = getSiteTitle;
this.templatesDir = templatesDir;
}
/**
*
* @param {Object} options
* @param {string} options.template - HTML template name to use for generation
* @param {Object} [options.data] - variable data to use during HTML template compilation
* @returns {Promise} resolves with an object containing html and text properties
*/
async getContent(options) {
const defaults = {
siteUrl: this.getSiteUrl(),
siteTitle: this.getSiteTitle()
};
const data = _.defaults(defaults, options.data);
// read the proper email body template
const content = await fs.readFile(path.join(this.templatesDir, options.template + '.html'), 'utf8');
// insert user-specific data into the email
const compiled = _.template(content);
const htmlContent = compiled(data);
// generate a plain-text version of the same email
const textContent = htmlToText.fromString(htmlContent);
return {
html: htmlContent,
text: textContent
};
}
}
module.exports = EmailContentGenerator;

View file

@ -1,7 +1,7 @@
const path = require('path');
const urlUtils = require('../../../shared/url-utils');
const settingsCache = require('../../../shared/settings-cache');
const EmailContentGenerator = require('./EmailContentGenerator');
const EmailContentGenerator = require('@tryghost/email-content-generator');
const emailContentGenerator = new EmailContentGenerator({
getSiteUrl: () => urlUtils.urlFor('home', true),

View file

@ -70,6 +70,7 @@
"@tryghost/domain-events": "0.1.10",
"@tryghost/email-analytics-provider-mailgun": "1.0.8",
"@tryghost/email-analytics-service": "1.0.6",
"@tryghost/email-content-generator": "0.1.0",
"@tryghost/errors": "1.2.12",
"@tryghost/express-dynamic-redirects": "0.2.9",
"@tryghost/helpers": "1.1.64",

View file

@ -1,102 +0,0 @@
const assert = require('assert');
const path = require('path');
const EmailContentGenerator = require('../../../../../core/server/services/mail/EmailContentGenerator');
describe('Mail: EmailContentGenerator', function () {
it('generate welcome', async function () {
const emailContentGenerator = new EmailContentGenerator({
getSiteTitle: () => 'The Ghost Blog',
getSiteUrl: () => 'http://myblog.com',
templatesDir: path.resolve(__dirname, '../../../../../core/server/services/mail/templates/')
});
const content = await emailContentGenerator.getContent({
template: 'welcome',
data: {
ownerEmail: 'test@example.com'
}
});
assert.match(content.html, /<title>Welcome to Ghost<\/title>/);
assert.match(content.html, /This email was sent from <a href="http:\/\/myblog.com" style="color: #738A94;">http:\/\/myblog.com<\/a> to <a href="mailto:test@example.com" style="color: #738A94;">test@example.com<\/a><\/p>/);
assert.match(content.text, /Email Address: test@example.com \[test@example.com\]/);
assert.match(content.text, /This email was sent from http:\/\/myblog.com/);
});
it('generates newsletter template', async function () {
const emailContentGenerator = new EmailContentGenerator({
getSiteTitle: () => 'The Ghost Blog',
getSiteUrl: () => 'http://myblog.com',
templatesDir: path.resolve(__dirname, '../../../../../core/server/services/mail/templates/')
});
const content = await emailContentGenerator.getContent({
template: 'newsletter',
data: {
blog: {
logo: 'http://myblog.com/content/images/blog-logo.jpg',
title: 'The Ghost Blog',
url: 'http://myblog.com',
twitter: 'http://twitter.com/ghost',
facebook: 'https://www.facebook.com/ghost',
unsubscribe: 'http://myblog.com/unsubscribe',
post: [
{
picture: 'http://myblog.com/content/images/post-1-image.jpg',
title: 'Featured blog post',
text: 'This is a featured blog post. It&#x2019;s awesome&#x2026;',
url: 'http://myblog.com/featured-blog-post',
tag: 'featured',
author: 'harry potter'
},
{
picture: 'http://myblog.com/content/images/post-2-image.jpg',
title: 'Second blog post',
text: 'This is the second blog post. It&#x2019;s also awesome&#x2026;',
url: 'http://myblog.com/second-blog-post',
tag: 'second',
author: 'lord voldemord'
},
{
picture: 'http://myblog.com/content/images/post-3-image.jpg',
title: 'Third blog post',
text: 'This is the third blog post. It&#x2019;s also awesome&#x2026;',
url: 'http://myblog.com/third-blog-post',
tag: 'third',
author: 'marry poppins'
},
{
picture: 'http://myblog.com/content/images/post-4-image.jpg',
title: 'Fourth blog post',
text: 'This is the fourth blog post. It&#x2019;s also awesome&#x2026;',
url: 'http://myblog.com/fourth-blog-post',
tag: 'fourth',
author: 'donald duck'
},
{
picture: 'http://myblog.com/content/images/post-5-image.jpg',
title: 'Fifth blog post',
text: 'This is the fifth blog post. It&#x2019;s also awesome&#x2026;',
url: 'http://myblog.com/fifth-blog-post',
tag: 'fifth',
author: 'casper the ghost'
}
]
},
newsletter: {
interval: 'monthly',
date: 'june, 9th 2016'
}
}
});
assert.match(content.html, /<title>The Ghost Blog<\/title>/);
assert.match(content.html, /<span style="text-transform:capitalize">monthly<\/span> digest/);
assert.match(content.html, /<span style="text-transform:capitalize">june, 9th 2016<\/span><\/h3>/);
assert.match(content.text, /MONTHLY DIGEST — JUNE, 9TH 2016/);
assert.match(content.text, /SECOND BLOG POST \[HTTP:\/\/MYBLOG.COM\/SECOND-BLOG-POST\]/);
});
});

View file

@ -1930,6 +1930,13 @@
"@tryghost/debug" "^0.1.9"
lodash "^4.17.20"
"@tryghost/email-content-generator@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@tryghost/email-content-generator/-/email-content-generator-0.1.0.tgz#cb8233ce70f416cce5f91964e953889580ea815a"
integrity sha512-/WXpNA4HgmCA+TEnWg4jwQS9KJOt4cGQNNFuANtt8z//mdbV1IKRK9IamLT/zWGlzYCaw/lLWy/j/UjghPaqtQ==
dependencies:
html-to-text "^5.1.1"
"@tryghost/errors@1.2.10":
version "1.2.10"
resolved "https://registry.yarnpkg.com/@tryghost/errors/-/errors-1.2.10.tgz#b01b16744986005784ffd6916eec48a3e93976a9"
@ -6709,7 +6716,7 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
html-to-text@5.1.1:
html-to-text@5.1.1, html-to-text@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-5.1.1.tgz#2d89db7bf34bc7bcb7d546b1b228991a16926e87"
integrity sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==