@cosmicdrift/kumiko-renderer-mail-html 0.377.0 → 0.379.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/render.js +25 -11
- package/package.json +7 -7
- package/src/changes.json +6 -0
package/dist/render.js
CHANGED
|
@@ -22,6 +22,8 @@ import { buildMailBandLinksHtml, buildMailFooterHtml, layoutLinksToPlaceholder,
|
|
|
22
22
|
import { mailChromeText } from "./mail-strings.js";
|
|
23
23
|
import { MAIL_IMAGE_MAX_WIDTH_PX, renderStructuredLayoutMjml } from "./structured-layout.js";
|
|
24
24
|
const LINE_BREAKS = /[\r\n]+/g;
|
|
25
|
+
const PLAIN_REFERENCE = /\{\{\s*([\w.]+)\s*\}\}/g;
|
|
26
|
+
const FORMATTED_VARIABLE_TYPES = new Set(["money", "date", "percent"]);
|
|
25
27
|
function describe(e) {
|
|
26
28
|
return e instanceof Error ? e.message : String(e);
|
|
27
29
|
}
|
|
@@ -211,24 +213,35 @@ async function renderMailBody(tplApi, ctx, template, hbs, context, buttonInlineS
|
|
|
211
213
|
throw new RendererError(`renderer-mail-html: rendering the body of "${template.slug}" failed — ${describe(e)}`, "other");
|
|
212
214
|
}
|
|
213
215
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
// Meta lines only hold plain {{name}} references (checked on save); typed values
|
|
217
|
+
// need the same format helpers the body compiler adds, or money renders as "[object Object]".
|
|
218
|
+
function withFormatHelpers(source, variables) {
|
|
219
|
+
return source.replace(PLAIN_REFERENCE, (reference, name) => {
|
|
220
|
+
const type = variables[name]?.type;
|
|
221
|
+
return type !== undefined && FORMATTED_VARIABLE_TYPES.has(type)
|
|
222
|
+
? `{{${type} ${name}}}`
|
|
223
|
+
: reference;
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function renderSubjectLine(hbs, source, context, variables) {
|
|
227
|
+
return compileDocumentSource(hbs, withFormatHelpers(source, variables), { noEscape: true })(context).replace(LINE_BREAKS, "");
|
|
216
228
|
}
|
|
217
229
|
function renderFileNamePattern(hbs, pattern, slug, context) {
|
|
218
230
|
try {
|
|
219
|
-
|
|
231
|
+
// File names keep raw values: a formatted date or amount would put spaces into the name.
|
|
232
|
+
return renderSubjectLine(hbs, pattern, context, {});
|
|
220
233
|
}
|
|
221
234
|
catch (e) {
|
|
222
235
|
throw new RendererError(`renderer-mail-html: rendering the attachment file name "${pattern}" of "${slug}" failed — ${describe(e)}`, "other");
|
|
223
236
|
}
|
|
224
237
|
}
|
|
225
|
-
function renderSubjectLines(hbs, meta, slug, context) {
|
|
238
|
+
function renderSubjectLines(hbs, meta, slug, context, variables) {
|
|
226
239
|
try {
|
|
227
240
|
return {
|
|
228
|
-
subject: renderSubjectLine(hbs, meta.subject, context),
|
|
241
|
+
subject: renderSubjectLine(hbs, meta.subject, context, variables),
|
|
229
242
|
previewText: meta.previewText === undefined
|
|
230
243
|
? undefined
|
|
231
|
-
: renderSubjectLine(hbs, meta.previewText, context),
|
|
244
|
+
: renderSubjectLine(hbs, meta.previewText, context, variables),
|
|
232
245
|
};
|
|
233
246
|
}
|
|
234
247
|
catch (e) {
|
|
@@ -236,8 +249,8 @@ function renderSubjectLines(hbs, meta, slug, context) {
|
|
|
236
249
|
}
|
|
237
250
|
}
|
|
238
251
|
// Chip and tone are author-chosen per mail; a chip without a known tone takes the accent tone.
|
|
239
|
-
function renderMailChrome(hbs, meta, slug, context, brandColor) {
|
|
240
|
-
const render = (source) => source === undefined ? "" : renderSubjectLine(hbs, source, context).trim();
|
|
252
|
+
function renderMailChrome(hbs, meta, slug, context, variables, brandColor) {
|
|
253
|
+
const render = (source) => source === undefined ? "" : renderSubjectLine(hbs, source, context, variables).trim();
|
|
241
254
|
try {
|
|
242
255
|
const headerChip = render(meta.headerChip);
|
|
243
256
|
const tone = readMailTone(render(meta.tone));
|
|
@@ -464,7 +477,7 @@ export async function mailHtmlRender(req, ctx, options = {}) {
|
|
|
464
477
|
throw new RendererError(`renderer-mail-html supports only kind="mail", got "${req.kind}"`, "invalid_payload");
|
|
465
478
|
}
|
|
466
479
|
const { slug, locale, variables, unsubscribeUrl, draft } = req.payload;
|
|
467
|
-
const tplApi = createTemplateResolverApi(ctx.db);
|
|
480
|
+
const tplApi = createTemplateResolverApi(ctx.db, ctx.registry);
|
|
468
481
|
const { template, meta } = await resolveMailTemplate(tplApi, ctx, slug, locale, draft);
|
|
469
482
|
const [format, tenantName, footer, siteUrl, brandSuffix, brandingLogoUrl] = await Promise.all([
|
|
470
483
|
readDocumentFormat(ctx, locale),
|
|
@@ -483,8 +496,9 @@ export async function mailHtmlRender(req, ctx, options = {}) {
|
|
|
483
496
|
unsubscribeUrl: unsubscribeUrl ?? "",
|
|
484
497
|
};
|
|
485
498
|
const context = { ...variables, ...systemPlaceholders };
|
|
499
|
+
const variableDefs = resolveTemplateVariables(ctx.registry, template.slug, template.variableSchema);
|
|
486
500
|
const { appearance, accentColor, brandColor } = await resolveMailBranding(ctx, layout);
|
|
487
|
-
const chrome = renderMailChrome(hbs, meta, slug, context, brandColor);
|
|
501
|
+
const chrome = renderMailChrome(hbs, meta, slug, context, variableDefs, brandColor);
|
|
488
502
|
const body = await renderMailBody(tplApi, ctx, template, hbs, context, appearance?.buttonStyle, chrome.tone?.bar ?? brandColor ?? DEFAULT_ACCENT_COLOR, brandingLogoUrl);
|
|
489
503
|
const { contentHtml } = body;
|
|
490
504
|
const layoutFileRefs = await resolveLayoutFileRefs(tplApi, ctx, layout);
|
|
@@ -498,7 +512,7 @@ export async function mailHtmlRender(req, ctx, options = {}) {
|
|
|
498
512
|
locale,
|
|
499
513
|
renderFileName: (pattern) => renderFileNamePattern(hbs, pattern, slug, context),
|
|
500
514
|
});
|
|
501
|
-
const { subject, previewText } = renderSubjectLines(hbs, meta, slug, context);
|
|
515
|
+
const { subject, previewText } = renderSubjectLines(hbs, meta, slug, context, variableDefs);
|
|
502
516
|
const mjmlSource = compileLayoutMjml({
|
|
503
517
|
layout,
|
|
504
518
|
hbs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-renderer-mail-html",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.379.0",
|
|
4
4
|
"description": "Renderer-Foundation plugin for branded HTML emails: mail-kind templates (document HTML + subject meta) rendered with isolated Handlebars into an MJML layout, plus plain text via html-to-text. Templates resolved from template-resolver.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
23
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
24
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
25
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
22
|
+
"@cosmicdrift/kumiko-bundled-features": "0.379.0",
|
|
23
|
+
"@cosmicdrift/kumiko-framework": "0.379.0",
|
|
24
|
+
"@cosmicdrift/kumiko-renderer": "0.379.0",
|
|
25
|
+
"@cosmicdrift/kumiko-types": "0.379.0",
|
|
26
26
|
"handlebars": "^4.7.8",
|
|
27
27
|
"html-to-text": "^9.0.5",
|
|
28
28
|
"mjml": "^5.2.2"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
32
|
-
"@cosmicdrift/kumiko-testing": "0.
|
|
31
|
+
"@cosmicdrift/kumiko-locale-de": "0.379.0",
|
|
32
|
+
"@cosmicdrift/kumiko-testing": "0.379.0",
|
|
33
33
|
"@types/html-to-text": "^9.0.4",
|
|
34
34
|
"@types/mjml": "^5.0.0"
|
|
35
35
|
},
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.378.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Typed placeholders in mail subject lines are formatted",
|
|
6
|
+
"detail": "A money placeholder in the subject or preview text rendered as \"[object Object]\" and a date as its raw ISO string, because only the body compiler added the format helpers. Subject, preview text, header chip, tone and footer note now use the same money, date and percent formatting as the body. Attachment file names keep the raw values."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.377.0",
|
|
4
10
|
"type": "improvement",
|