Added newsletter design customisation data to template

refs https://github.com/TryGhost/Team/issues/2845

Ideally the calculation of these values would be handled by a Newsletter entity
but we don't have one yet, we can look to fix this if we have time. For now
we're calculating them in separate methods to make it easier to extract in
future.
This commit is contained in:
Fabien "egg" O'Carroll 2023-03-29 11:03:49 +07:00 committed by Fabien 'egg' O'Carroll
parent ac1b013c80
commit f23b869499
2 changed files with 197 additions and 1 deletions

View File

@ -740,6 +740,65 @@ class EmailRenderer {
}
}
#getBackgroundColor(newsletter) {
/** @type {'light' | 'dark' | string | null} */
const value = newsletter.get('background_color');
const validHex = /#([0-9a-f]{3}){1,2}$/i;
if (validHex.test(value)) {
return value;
}
if (value === 'dark') {
return '#15212a';
}
// value === dark, value === null, value is not valid hex
return '#ffffff';
}
#getBorderColor(newsletter, accentColor) {
/** @type {'transparent' | 'accent' | 'dark' | string | null} */
const value = newsletter.get('border_color');
const validHex = /#([0-9a-f]{3}){1,2}$/i;
if (validHex.test(value)) {
return value;
}
if (value === 'dark') {
return '#15212a';
}
if (value === 'accent') {
return accentColor;
}
// value === 'transparent', value === null, value is not valid hex
return null;
}
#getTitleColor(newsletter, accentColor) {
/** @type {'accent' | 'auto' | string | null} */
const value = newsletter.get('title_color');
const validHex = /#([0-9a-f]{3}){1,2}$/i;
if (validHex.test(value)) {
return value;
}
if (value === 'accent') {
return accentColor;
}
// value === 'auto', value === null, value is not valid hex
const backgroundColor = this.#getBackgroundColor(newsletter);
return textColorForBackgroundColor(backgroundColor).hex();
}
/**
* @private
*/
@ -755,6 +814,15 @@ class EmailRenderer {
accentColor = '#15212A';
}
const backgroundColor = this.#getBackgroundColor(newsletter);
const backgroundIsDark = textColorForBackgroundColor(backgroundColor).hex().toLowerCase() === '#ffffff';
const borderColor = this.#getBorderColor(newsletter, accentColor);
const secondaryBorderColor = textColorForBackgroundColor(backgroundColor).alpha(0.12).toString();
const titleColor = this.#getTitleColor(newsletter, accentColor);
const textColor = textColorForBackgroundColor(backgroundColor).hex();
const secondaryTextColor = textColorForBackgroundColor(backgroundColor).alpha(0.45).toString();
const linkColor = backgroundIsDark ? '#ffffff' : accentColor;
const {href: headerImage, width: headerImageWidth} = await this.limitImageWidth(newsletter.get('header_image'));
const {href: postFeatureImage, width: postFeatureImageWidth, height: postFeatureImageHeight} = await this.limitImageWidth(post.get('feature_image'));
@ -874,6 +942,14 @@ class EmailRenderer {
adjustedAccentColor: adjustedAccentColor || '#3498db', // default to #3498db
adjustedAccentContrastColor: adjustedAccentContrastColor || '#ffffff', // default to #ffffff
showBadge: newsletter.get('show_badge'),
backgroundColor: backgroundColor,
backgroundIsDark: backgroundIsDark,
borderColor: borderColor,
secondaryBorderColor: secondaryBorderColor,
titleColor: titleColor,
textColor: textColor,
secondaryTextColor: secondaryTextColor,
linkColor: linkColor,
headerImage,
headerImageWidth,

View File

@ -861,8 +861,10 @@ describe('Email renderer', function () {
let emailRenderer;
let basePost;
let addTrackingToUrlStub;
let labsEnabled;
beforeEach(function () {
labsEnabled = true;
basePost = {
lexical: '{}',
visibility: 'public',
@ -956,11 +958,32 @@ describe('Email renderer', function () {
}
},
labs: {
isSet: () => true
isSet: () => labsEnabled
}
});
});
it('Renders with labs disabled', async function () {
labsEnabled = false;
const post = createModel(basePost);
const newsletter = createModel({
header_image: null,
name: 'Test Newsletter',
show_badge: false,
feedback_enabled: true,
show_post_title_section: true
});
const segment = null;
const options = {};
await emailRenderer.renderBody(
post,
newsletter,
segment,
options
);
});
it('returns feedback buttons and unsubcribe links', async function () {
const post = createModel(basePost);
const newsletter = createModel({
@ -1508,6 +1531,103 @@ describe('Email renderer', function () {
});
});
async function templateDataWithSettings(settingsObj) {
const html = '';
const post = createModel({
posts_meta: createModel({}),
loaded: ['posts_meta']
});
const newsletter = createModel({
...settingsObj
});
const data = await emailRenderer.getTemplateData({post, newsletter, html, addPaywall: false});
return data;
}
it('Uses the correct background colors based on settings', async function () {
const tests = [
{input: 'Invalid Color', expected: '#ffffff'},
{input: '#BADA55', expected: '#BADA55'},
{input: 'dark', expected: '#15212a'},
{input: 'light', expected: '#ffffff'},
{input: null, expected: '#ffffff'}
];
for (const test of tests) {
const data = await templateDataWithSettings({
background_color: test.input
});
assert.equal(data.backgroundColor, test.expected);
}
});
it('Uses the correct border colors based on settings', async function () {
settings.accent_color = '#ABC123';
const tests = [
{input: 'Invalid Color', expected: null},
{input: '#BADA55', expected: '#BADA55'},
{input: 'dark', expected: '#15212a'},
{input: 'light', expected: null},
{input: 'accent', expected: settings.accent_color},
{input: 'transparent', expected: null}
];
for (const test of tests) {
const data = await templateDataWithSettings({
border_color: test.input
});
assert.equal(data.borderColor, test.expected);
}
});
it('Uses the correct title colors based on settings and background color', async function () {
settings.accent_color = '#DEF456';
const tests = [
{input: '#BADA55', expected: '#BADA55'},
{input: 'accent', expected: settings.accent_color},
{input: 'Invalid Color', expected: '#FFFFFF', background_color: '#15212A'},
{input: null, expected: '#000000', background_color: '#ffffff'}
];
for (const test of tests) {
const data = await templateDataWithSettings({
title_color: test.input,
background_color: test.background_color
});
assert.equal(data.titleColor, test.expected);
}
});
it('Sets the backgroundIsDark correctly', async function () {
const tests = [
{background_color: '#15212A', expected: true},
{background_color: '#ffffff', expected: false}
];
for (const test of tests) {
const data = await templateDataWithSettings({
background_color: test.background_color
});
assert.equal(data.backgroundIsDark, test.expected);
}
});
it('Sets the linkColor correctly', async function () {
settings.accent_color = '#A1B2C3';
const tests = [
{background_color: '#15212A', expected: '#ffffff'},
{background_color: '#ffffff', expected: settings.accent_color}
];
for (const test of tests) {
const data = await templateDataWithSettings({
background_color: test.background_color
});
assert.equal(data.linkColor, test.expected);
}
});
it('uses default accent color', async function () {
const html = '';
const post = createModel({