@momentumcms/auth 0.5.9 → 0.5.10
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/CHANGELOG.md +11 -0
- package/index.cjs +179 -155
- package/index.js +178 -154
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## 0.5.10 (2026-03-13)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- E2E stability, shadow token wiring, and email template access control ([d4bc2068](https://github.com/DonaldMurillo/momentum-cms/commit/d4bc2068))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Claude Opus 4.6
|
|
10
|
+
- Donald Murillo @DonaldMurillo
|
|
11
|
+
|
|
1
12
|
## 0.5.9 (2026-03-10)
|
|
2
13
|
|
|
3
14
|
This was a version bump only for auth to align it with other projects, there were no code changes.
|
package/index.cjs
CHANGED
|
@@ -39,6 +39,16 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
39
39
|
return result;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
// libs/email/src/lib/utils/escape-html.ts
|
|
43
|
+
function escapeHtml(unsafe) {
|
|
44
|
+
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
45
|
+
}
|
|
46
|
+
var init_escape_html = __esm({
|
|
47
|
+
"libs/email/src/lib/utils/escape-html.ts"() {
|
|
48
|
+
"use strict";
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
42
52
|
// libs/email/src/lib/utils/css-inliner.ts
|
|
43
53
|
function inlineCss(html) {
|
|
44
54
|
return (0, import_juice.default)(html, {
|
|
@@ -56,83 +66,6 @@ var init_css_inliner = __esm({
|
|
|
56
66
|
}
|
|
57
67
|
});
|
|
58
68
|
|
|
59
|
-
// libs/email/src/lib/utils/strip-artifacts.ts
|
|
60
|
-
function stripAngularArtifacts(html) {
|
|
61
|
-
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*ng-reflect-[\w-]+="[^"]*"/g, "").replace(/\s*_ng(?:host|content)-[\w-]+(?:="")?/g, "").replace(/\s*ng-version="[^"]*"/g, "").replace(/\s*ng-server-context="[^"]*"/g, "").replace(/\s*ngh="[^"]*"/g, "").replace(/\n\s*\n/g, "\n");
|
|
62
|
-
}
|
|
63
|
-
var init_strip_artifacts = __esm({
|
|
64
|
-
"libs/email/src/lib/utils/strip-artifacts.ts"() {
|
|
65
|
-
"use strict";
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// libs/email/src/lib/render/render-types.ts
|
|
70
|
-
function injectEmailData() {
|
|
71
|
-
return (0, import_core.inject)(EMAIL_DATA);
|
|
72
|
-
}
|
|
73
|
-
var import_core, EMAIL_DATA;
|
|
74
|
-
var init_render_types = __esm({
|
|
75
|
-
"libs/email/src/lib/render/render-types.ts"() {
|
|
76
|
-
"use strict";
|
|
77
|
-
import_core = require("@angular/core");
|
|
78
|
-
EMAIL_DATA = new import_core.InjectionToken("EMAIL_DATA");
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// libs/email/src/lib/render/render-email.ts
|
|
83
|
-
function buildDocument(selector) {
|
|
84
|
-
return `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><${selector}></${selector}></body></html>`;
|
|
85
|
-
}
|
|
86
|
-
async function renderEmail(component, data, options) {
|
|
87
|
-
const shouldInlineCss = options?.inlineCss ?? true;
|
|
88
|
-
const shouldStripArtifacts = options?.stripArtifacts ?? true;
|
|
89
|
-
const extraProviders = options?.providers ?? [];
|
|
90
|
-
const mirror = (0, import_core2.reflectComponentType)(component);
|
|
91
|
-
if (!mirror) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
`Cannot reflect component type: ${component.name}. Ensure it has a @Component decorator.`
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
const providers = [...extraProviders, { provide: EMAIL_DATA, useValue: data ?? {} }];
|
|
97
|
-
let html = await (0, import_platform_server.renderApplication)(
|
|
98
|
-
(context) => (0, import_platform_browser.bootstrapApplication)(component, { providers }, context),
|
|
99
|
-
{
|
|
100
|
-
document: buildDocument(mirror.selector),
|
|
101
|
-
url: "/"
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
if (shouldStripArtifacts) {
|
|
105
|
-
html = stripAngularArtifacts(html);
|
|
106
|
-
}
|
|
107
|
-
if (shouldInlineCss) {
|
|
108
|
-
html = inlineCss(html);
|
|
109
|
-
}
|
|
110
|
-
return html;
|
|
111
|
-
}
|
|
112
|
-
var import_compiler, import_core2, import_platform_server, import_platform_browser;
|
|
113
|
-
var init_render_email = __esm({
|
|
114
|
-
"libs/email/src/lib/render/render-email.ts"() {
|
|
115
|
-
"use strict";
|
|
116
|
-
import_compiler = require("@angular/compiler");
|
|
117
|
-
import_core2 = require("@angular/core");
|
|
118
|
-
import_platform_server = require("@angular/platform-server");
|
|
119
|
-
import_platform_browser = require("@angular/platform-browser");
|
|
120
|
-
init_css_inliner();
|
|
121
|
-
init_strip_artifacts();
|
|
122
|
-
init_render_types();
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// libs/email/src/lib/utils/escape-html.ts
|
|
127
|
-
function escapeHtml(unsafe) {
|
|
128
|
-
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
129
|
-
}
|
|
130
|
-
var init_escape_html = __esm({
|
|
131
|
-
"libs/email/src/lib/utils/escape-html.ts"() {
|
|
132
|
-
"use strict";
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
|
|
136
69
|
// libs/email/src/lib/utils/replace-variables.ts
|
|
137
70
|
function replaceVariables(text2, variables) {
|
|
138
71
|
return text2.replace(/\{\{(\w+)\}\}/g, (_, key) => variables[key] ?? "");
|
|
@@ -382,6 +315,174 @@ var init_render_blocks = __esm({
|
|
|
382
315
|
}
|
|
383
316
|
});
|
|
384
317
|
|
|
318
|
+
// libs/email/src/lib/utils/blocks-to-plain-text.ts
|
|
319
|
+
function blocksToPlainText(blocks2, depth = 0) {
|
|
320
|
+
const lines = [];
|
|
321
|
+
for (const block of blocks2) {
|
|
322
|
+
const text2 = blockToText(block, depth);
|
|
323
|
+
if (text2) {
|
|
324
|
+
lines.push(text2);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return lines.join("\n\n");
|
|
328
|
+
}
|
|
329
|
+
function blockToText(block, depth) {
|
|
330
|
+
switch (block.type) {
|
|
331
|
+
case "header":
|
|
332
|
+
return headerToText(block.data);
|
|
333
|
+
case "text":
|
|
334
|
+
return String(block.data["content"] ?? "");
|
|
335
|
+
case "button":
|
|
336
|
+
return buttonToText(block.data);
|
|
337
|
+
case "footer":
|
|
338
|
+
return String(block.data["text"] ?? "");
|
|
339
|
+
case "columns":
|
|
340
|
+
if (depth >= MAX_BLOCK_DEPTH2) {
|
|
341
|
+
console.warn("[momentum:email] Max nesting depth reached, skipping columns block");
|
|
342
|
+
return "";
|
|
343
|
+
}
|
|
344
|
+
return columnsToText(block.data, depth);
|
|
345
|
+
case "divider":
|
|
346
|
+
case "spacer":
|
|
347
|
+
case "image":
|
|
348
|
+
return "";
|
|
349
|
+
default:
|
|
350
|
+
return "";
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function headerToText(data) {
|
|
354
|
+
const title = String(data["title"] ?? "");
|
|
355
|
+
const subtitle = data["subtitle"] ? String(data["subtitle"]) : "";
|
|
356
|
+
if (!title && !subtitle)
|
|
357
|
+
return "";
|
|
358
|
+
if (!subtitle)
|
|
359
|
+
return title;
|
|
360
|
+
return `${title}
|
|
361
|
+
${subtitle}`;
|
|
362
|
+
}
|
|
363
|
+
function buttonToText(data) {
|
|
364
|
+
const label = String(data["label"] ?? "");
|
|
365
|
+
const href = data["href"] ? String(data["href"]) : "";
|
|
366
|
+
if (!label)
|
|
367
|
+
return "";
|
|
368
|
+
if (!href)
|
|
369
|
+
return label;
|
|
370
|
+
return `${label}: ${href}`;
|
|
371
|
+
}
|
|
372
|
+
function columnsToText(data, depth) {
|
|
373
|
+
const columns = data["columns"];
|
|
374
|
+
if (!Array.isArray(columns))
|
|
375
|
+
return "";
|
|
376
|
+
const parts = [];
|
|
377
|
+
for (const col of columns) {
|
|
378
|
+
if (col && typeof col === "object" && Array.isArray(col.blocks)) {
|
|
379
|
+
const colText = blocksToPlainText(col.blocks, depth + 1);
|
|
380
|
+
if (colText) {
|
|
381
|
+
parts.push(colText);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return parts.join("\n\n");
|
|
386
|
+
}
|
|
387
|
+
var MAX_BLOCK_DEPTH2;
|
|
388
|
+
var init_blocks_to_plain_text = __esm({
|
|
389
|
+
"libs/email/src/lib/utils/blocks-to-plain-text.ts"() {
|
|
390
|
+
"use strict";
|
|
391
|
+
MAX_BLOCK_DEPTH2 = 5;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// libs/email/src/server.ts
|
|
396
|
+
var server_exports = {};
|
|
397
|
+
__export(server_exports, {
|
|
398
|
+
DEFAULT_EMAIL_THEME: () => DEFAULT_EMAIL_THEME,
|
|
399
|
+
blocksToPlainText: () => blocksToPlainText,
|
|
400
|
+
escapeHtml: () => escapeHtml,
|
|
401
|
+
inlineCss: () => inlineCss,
|
|
402
|
+
isValidBlock: () => isValidBlock,
|
|
403
|
+
renderEmailFromBlocks: () => renderEmailFromBlocks,
|
|
404
|
+
replaceBlockVariables: () => replaceBlockVariables,
|
|
405
|
+
replaceVariables: () => replaceVariables
|
|
406
|
+
});
|
|
407
|
+
var init_server = __esm({
|
|
408
|
+
"libs/email/src/server.ts"() {
|
|
409
|
+
"use strict";
|
|
410
|
+
init_render_blocks();
|
|
411
|
+
init_replace_variables();
|
|
412
|
+
init_blocks_to_plain_text();
|
|
413
|
+
init_css_inliner();
|
|
414
|
+
init_escape_html();
|
|
415
|
+
init_types();
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// libs/email/src/lib/utils/strip-artifacts.ts
|
|
420
|
+
function stripAngularArtifacts(html) {
|
|
421
|
+
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*ng-reflect-[\w-]+="[^"]*"/g, "").replace(/\s*_ng(?:host|content)-[\w-]+(?:="")?/g, "").replace(/\s*ng-version="[^"]*"/g, "").replace(/\s*ng-server-context="[^"]*"/g, "").replace(/\s*ngh="[^"]*"/g, "").replace(/\n\s*\n/g, "\n");
|
|
422
|
+
}
|
|
423
|
+
var init_strip_artifacts = __esm({
|
|
424
|
+
"libs/email/src/lib/utils/strip-artifacts.ts"() {
|
|
425
|
+
"use strict";
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// libs/email/src/lib/render/render-types.ts
|
|
430
|
+
function injectEmailData() {
|
|
431
|
+
return (0, import_core.inject)(EMAIL_DATA);
|
|
432
|
+
}
|
|
433
|
+
var import_core, EMAIL_DATA;
|
|
434
|
+
var init_render_types = __esm({
|
|
435
|
+
"libs/email/src/lib/render/render-types.ts"() {
|
|
436
|
+
"use strict";
|
|
437
|
+
import_core = require("@angular/core");
|
|
438
|
+
EMAIL_DATA = new import_core.InjectionToken("EMAIL_DATA");
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// libs/email/src/lib/render/render-email.ts
|
|
443
|
+
function buildDocument(selector) {
|
|
444
|
+
return `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><${selector}></${selector}></body></html>`;
|
|
445
|
+
}
|
|
446
|
+
async function renderEmail(component, data, options) {
|
|
447
|
+
const shouldInlineCss = options?.inlineCss ?? true;
|
|
448
|
+
const shouldStripArtifacts = options?.stripArtifacts ?? true;
|
|
449
|
+
const extraProviders = options?.providers ?? [];
|
|
450
|
+
const mirror = (0, import_core2.reflectComponentType)(component);
|
|
451
|
+
if (!mirror) {
|
|
452
|
+
throw new Error(
|
|
453
|
+
`Cannot reflect component type: ${component.name}. Ensure it has a @Component decorator.`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
const providers = [...extraProviders, { provide: EMAIL_DATA, useValue: data ?? {} }];
|
|
457
|
+
let html = await (0, import_platform_server.renderApplication)(
|
|
458
|
+
(context) => (0, import_platform_browser.bootstrapApplication)(component, { providers }, context),
|
|
459
|
+
{
|
|
460
|
+
document: buildDocument(mirror.selector),
|
|
461
|
+
url: "/"
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
if (shouldStripArtifacts) {
|
|
465
|
+
html = stripAngularArtifacts(html);
|
|
466
|
+
}
|
|
467
|
+
if (shouldInlineCss) {
|
|
468
|
+
html = inlineCss(html);
|
|
469
|
+
}
|
|
470
|
+
return html;
|
|
471
|
+
}
|
|
472
|
+
var import_compiler, import_core2, import_platform_server, import_platform_browser;
|
|
473
|
+
var init_render_email = __esm({
|
|
474
|
+
"libs/email/src/lib/render/render-email.ts"() {
|
|
475
|
+
"use strict";
|
|
476
|
+
import_compiler = require("@angular/compiler");
|
|
477
|
+
import_core2 = require("@angular/core");
|
|
478
|
+
import_platform_server = require("@angular/platform-server");
|
|
479
|
+
import_platform_browser = require("@angular/platform-browser");
|
|
480
|
+
init_css_inliner();
|
|
481
|
+
init_strip_artifacts();
|
|
482
|
+
init_render_types();
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
385
486
|
// libs/email/src/lib/templates/default-templates.ts
|
|
386
487
|
var DEFAULT_PASSWORD_RESET_BLOCKS, DEFAULT_VERIFICATION_BLOCKS;
|
|
387
488
|
var init_default_templates = __esm({
|
|
@@ -1002,83 +1103,6 @@ var init_eml_footer_component = __esm({
|
|
|
1002
1103
|
}
|
|
1003
1104
|
});
|
|
1004
1105
|
|
|
1005
|
-
// libs/email/src/lib/utils/blocks-to-plain-text.ts
|
|
1006
|
-
function blocksToPlainText(blocks2, depth = 0) {
|
|
1007
|
-
const lines = [];
|
|
1008
|
-
for (const block of blocks2) {
|
|
1009
|
-
const text2 = blockToText(block, depth);
|
|
1010
|
-
if (text2) {
|
|
1011
|
-
lines.push(text2);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
return lines.join("\n\n");
|
|
1015
|
-
}
|
|
1016
|
-
function blockToText(block, depth) {
|
|
1017
|
-
switch (block.type) {
|
|
1018
|
-
case "header":
|
|
1019
|
-
return headerToText(block.data);
|
|
1020
|
-
case "text":
|
|
1021
|
-
return String(block.data["content"] ?? "");
|
|
1022
|
-
case "button":
|
|
1023
|
-
return buttonToText(block.data);
|
|
1024
|
-
case "footer":
|
|
1025
|
-
return String(block.data["text"] ?? "");
|
|
1026
|
-
case "columns":
|
|
1027
|
-
if (depth >= MAX_BLOCK_DEPTH2) {
|
|
1028
|
-
console.warn("[momentum:email] Max nesting depth reached, skipping columns block");
|
|
1029
|
-
return "";
|
|
1030
|
-
}
|
|
1031
|
-
return columnsToText(block.data, depth);
|
|
1032
|
-
case "divider":
|
|
1033
|
-
case "spacer":
|
|
1034
|
-
case "image":
|
|
1035
|
-
return "";
|
|
1036
|
-
default:
|
|
1037
|
-
return "";
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
function headerToText(data) {
|
|
1041
|
-
const title = String(data["title"] ?? "");
|
|
1042
|
-
const subtitle = data["subtitle"] ? String(data["subtitle"]) : "";
|
|
1043
|
-
if (!title && !subtitle)
|
|
1044
|
-
return "";
|
|
1045
|
-
if (!subtitle)
|
|
1046
|
-
return title;
|
|
1047
|
-
return `${title}
|
|
1048
|
-
${subtitle}`;
|
|
1049
|
-
}
|
|
1050
|
-
function buttonToText(data) {
|
|
1051
|
-
const label = String(data["label"] ?? "");
|
|
1052
|
-
const href = data["href"] ? String(data["href"]) : "";
|
|
1053
|
-
if (!label)
|
|
1054
|
-
return "";
|
|
1055
|
-
if (!href)
|
|
1056
|
-
return label;
|
|
1057
|
-
return `${label}: ${href}`;
|
|
1058
|
-
}
|
|
1059
|
-
function columnsToText(data, depth) {
|
|
1060
|
-
const columns = data["columns"];
|
|
1061
|
-
if (!Array.isArray(columns))
|
|
1062
|
-
return "";
|
|
1063
|
-
const parts = [];
|
|
1064
|
-
for (const col of columns) {
|
|
1065
|
-
if (col && typeof col === "object" && Array.isArray(col.blocks)) {
|
|
1066
|
-
const colText = blocksToPlainText(col.blocks, depth + 1);
|
|
1067
|
-
if (colText) {
|
|
1068
|
-
parts.push(colText);
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
return parts.join("\n\n");
|
|
1073
|
-
}
|
|
1074
|
-
var MAX_BLOCK_DEPTH2;
|
|
1075
|
-
var init_blocks_to_plain_text = __esm({
|
|
1076
|
-
"libs/email/src/lib/utils/blocks-to-plain-text.ts"() {
|
|
1077
|
-
"use strict";
|
|
1078
|
-
MAX_BLOCK_DEPTH2 = 5;
|
|
1079
|
-
}
|
|
1080
|
-
});
|
|
1081
|
-
|
|
1082
1106
|
// libs/email/src/index.ts
|
|
1083
1107
|
var src_exports = {};
|
|
1084
1108
|
__export(src_exports, {
|
|
@@ -1351,7 +1375,7 @@ async function renderFromDbTemplate(template, variables, defaultSubject, default
|
|
|
1351
1375
|
if (!template.emailBlocks || !Array.isArray(template.emailBlocks) || template.emailBlocks.length === 0) {
|
|
1352
1376
|
return null;
|
|
1353
1377
|
}
|
|
1354
|
-
const { renderEmailFromBlocks: renderEmailFromBlocks2, replaceVariables: replaceVariables2, blocksToPlainText: blocksToPlainText2 } = await Promise.resolve().then(() => (
|
|
1378
|
+
const { renderEmailFromBlocks: renderEmailFromBlocks2, replaceVariables: replaceVariables2, blocksToPlainText: blocksToPlainText2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
1355
1379
|
const subject = template.subject ? replaceVariables2(template.subject, variables) : defaultSubject;
|
|
1356
1380
|
const blocks2 = template.emailBlocks;
|
|
1357
1381
|
const html = renderEmailFromBlocks2(
|
package/index.js
CHANGED
|
@@ -18,6 +18,16 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
18
18
|
return result;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
// libs/email/src/lib/utils/escape-html.ts
|
|
22
|
+
function escapeHtml(unsafe) {
|
|
23
|
+
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
24
|
+
}
|
|
25
|
+
var init_escape_html = __esm({
|
|
26
|
+
"libs/email/src/lib/utils/escape-html.ts"() {
|
|
27
|
+
"use strict";
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
21
31
|
// libs/email/src/lib/utils/css-inliner.ts
|
|
22
32
|
import juice from "juice";
|
|
23
33
|
function inlineCss(html) {
|
|
@@ -34,82 +44,6 @@ var init_css_inliner = __esm({
|
|
|
34
44
|
}
|
|
35
45
|
});
|
|
36
46
|
|
|
37
|
-
// libs/email/src/lib/utils/strip-artifacts.ts
|
|
38
|
-
function stripAngularArtifacts(html) {
|
|
39
|
-
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*ng-reflect-[\w-]+="[^"]*"/g, "").replace(/\s*_ng(?:host|content)-[\w-]+(?:="")?/g, "").replace(/\s*ng-version="[^"]*"/g, "").replace(/\s*ng-server-context="[^"]*"/g, "").replace(/\s*ngh="[^"]*"/g, "").replace(/\n\s*\n/g, "\n");
|
|
40
|
-
}
|
|
41
|
-
var init_strip_artifacts = __esm({
|
|
42
|
-
"libs/email/src/lib/utils/strip-artifacts.ts"() {
|
|
43
|
-
"use strict";
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// libs/email/src/lib/render/render-types.ts
|
|
48
|
-
import { InjectionToken, inject } from "@angular/core";
|
|
49
|
-
function injectEmailData() {
|
|
50
|
-
return inject(EMAIL_DATA);
|
|
51
|
-
}
|
|
52
|
-
var EMAIL_DATA;
|
|
53
|
-
var init_render_types = __esm({
|
|
54
|
-
"libs/email/src/lib/render/render-types.ts"() {
|
|
55
|
-
"use strict";
|
|
56
|
-
EMAIL_DATA = new InjectionToken("EMAIL_DATA");
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// libs/email/src/lib/render/render-email.ts
|
|
61
|
-
import "@angular/compiler";
|
|
62
|
-
import { reflectComponentType } from "@angular/core";
|
|
63
|
-
import { renderApplication } from "@angular/platform-server";
|
|
64
|
-
import { bootstrapApplication } from "@angular/platform-browser";
|
|
65
|
-
function buildDocument(selector) {
|
|
66
|
-
return `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><${selector}></${selector}></body></html>`;
|
|
67
|
-
}
|
|
68
|
-
async function renderEmail(component, data, options) {
|
|
69
|
-
const shouldInlineCss = options?.inlineCss ?? true;
|
|
70
|
-
const shouldStripArtifacts = options?.stripArtifacts ?? true;
|
|
71
|
-
const extraProviders = options?.providers ?? [];
|
|
72
|
-
const mirror = reflectComponentType(component);
|
|
73
|
-
if (!mirror) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
`Cannot reflect component type: ${component.name}. Ensure it has a @Component decorator.`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
const providers = [...extraProviders, { provide: EMAIL_DATA, useValue: data ?? {} }];
|
|
79
|
-
let html = await renderApplication(
|
|
80
|
-
(context) => bootstrapApplication(component, { providers }, context),
|
|
81
|
-
{
|
|
82
|
-
document: buildDocument(mirror.selector),
|
|
83
|
-
url: "/"
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
if (shouldStripArtifacts) {
|
|
87
|
-
html = stripAngularArtifacts(html);
|
|
88
|
-
}
|
|
89
|
-
if (shouldInlineCss) {
|
|
90
|
-
html = inlineCss(html);
|
|
91
|
-
}
|
|
92
|
-
return html;
|
|
93
|
-
}
|
|
94
|
-
var init_render_email = __esm({
|
|
95
|
-
"libs/email/src/lib/render/render-email.ts"() {
|
|
96
|
-
"use strict";
|
|
97
|
-
init_css_inliner();
|
|
98
|
-
init_strip_artifacts();
|
|
99
|
-
init_render_types();
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// libs/email/src/lib/utils/escape-html.ts
|
|
104
|
-
function escapeHtml(unsafe) {
|
|
105
|
-
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
106
|
-
}
|
|
107
|
-
var init_escape_html = __esm({
|
|
108
|
-
"libs/email/src/lib/utils/escape-html.ts"() {
|
|
109
|
-
"use strict";
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
47
|
// libs/email/src/lib/utils/replace-variables.ts
|
|
114
48
|
function replaceVariables(text2, variables) {
|
|
115
49
|
return text2.replace(/\{\{(\w+)\}\}/g, (_, key) => variables[key] ?? "");
|
|
@@ -359,6 +293,173 @@ var init_render_blocks = __esm({
|
|
|
359
293
|
}
|
|
360
294
|
});
|
|
361
295
|
|
|
296
|
+
// libs/email/src/lib/utils/blocks-to-plain-text.ts
|
|
297
|
+
function blocksToPlainText(blocks2, depth = 0) {
|
|
298
|
+
const lines = [];
|
|
299
|
+
for (const block of blocks2) {
|
|
300
|
+
const text2 = blockToText(block, depth);
|
|
301
|
+
if (text2) {
|
|
302
|
+
lines.push(text2);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return lines.join("\n\n");
|
|
306
|
+
}
|
|
307
|
+
function blockToText(block, depth) {
|
|
308
|
+
switch (block.type) {
|
|
309
|
+
case "header":
|
|
310
|
+
return headerToText(block.data);
|
|
311
|
+
case "text":
|
|
312
|
+
return String(block.data["content"] ?? "");
|
|
313
|
+
case "button":
|
|
314
|
+
return buttonToText(block.data);
|
|
315
|
+
case "footer":
|
|
316
|
+
return String(block.data["text"] ?? "");
|
|
317
|
+
case "columns":
|
|
318
|
+
if (depth >= MAX_BLOCK_DEPTH2) {
|
|
319
|
+
console.warn("[momentum:email] Max nesting depth reached, skipping columns block");
|
|
320
|
+
return "";
|
|
321
|
+
}
|
|
322
|
+
return columnsToText(block.data, depth);
|
|
323
|
+
case "divider":
|
|
324
|
+
case "spacer":
|
|
325
|
+
case "image":
|
|
326
|
+
return "";
|
|
327
|
+
default:
|
|
328
|
+
return "";
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function headerToText(data) {
|
|
332
|
+
const title = String(data["title"] ?? "");
|
|
333
|
+
const subtitle = data["subtitle"] ? String(data["subtitle"]) : "";
|
|
334
|
+
if (!title && !subtitle)
|
|
335
|
+
return "";
|
|
336
|
+
if (!subtitle)
|
|
337
|
+
return title;
|
|
338
|
+
return `${title}
|
|
339
|
+
${subtitle}`;
|
|
340
|
+
}
|
|
341
|
+
function buttonToText(data) {
|
|
342
|
+
const label = String(data["label"] ?? "");
|
|
343
|
+
const href = data["href"] ? String(data["href"]) : "";
|
|
344
|
+
if (!label)
|
|
345
|
+
return "";
|
|
346
|
+
if (!href)
|
|
347
|
+
return label;
|
|
348
|
+
return `${label}: ${href}`;
|
|
349
|
+
}
|
|
350
|
+
function columnsToText(data, depth) {
|
|
351
|
+
const columns = data["columns"];
|
|
352
|
+
if (!Array.isArray(columns))
|
|
353
|
+
return "";
|
|
354
|
+
const parts = [];
|
|
355
|
+
for (const col of columns) {
|
|
356
|
+
if (col && typeof col === "object" && Array.isArray(col.blocks)) {
|
|
357
|
+
const colText = blocksToPlainText(col.blocks, depth + 1);
|
|
358
|
+
if (colText) {
|
|
359
|
+
parts.push(colText);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return parts.join("\n\n");
|
|
364
|
+
}
|
|
365
|
+
var MAX_BLOCK_DEPTH2;
|
|
366
|
+
var init_blocks_to_plain_text = __esm({
|
|
367
|
+
"libs/email/src/lib/utils/blocks-to-plain-text.ts"() {
|
|
368
|
+
"use strict";
|
|
369
|
+
MAX_BLOCK_DEPTH2 = 5;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// libs/email/src/server.ts
|
|
374
|
+
var server_exports = {};
|
|
375
|
+
__export(server_exports, {
|
|
376
|
+
DEFAULT_EMAIL_THEME: () => DEFAULT_EMAIL_THEME,
|
|
377
|
+
blocksToPlainText: () => blocksToPlainText,
|
|
378
|
+
escapeHtml: () => escapeHtml,
|
|
379
|
+
inlineCss: () => inlineCss,
|
|
380
|
+
isValidBlock: () => isValidBlock,
|
|
381
|
+
renderEmailFromBlocks: () => renderEmailFromBlocks,
|
|
382
|
+
replaceBlockVariables: () => replaceBlockVariables,
|
|
383
|
+
replaceVariables: () => replaceVariables
|
|
384
|
+
});
|
|
385
|
+
var init_server = __esm({
|
|
386
|
+
"libs/email/src/server.ts"() {
|
|
387
|
+
"use strict";
|
|
388
|
+
init_render_blocks();
|
|
389
|
+
init_replace_variables();
|
|
390
|
+
init_blocks_to_plain_text();
|
|
391
|
+
init_css_inliner();
|
|
392
|
+
init_escape_html();
|
|
393
|
+
init_types();
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// libs/email/src/lib/utils/strip-artifacts.ts
|
|
398
|
+
function stripAngularArtifacts(html) {
|
|
399
|
+
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*ng-reflect-[\w-]+="[^"]*"/g, "").replace(/\s*_ng(?:host|content)-[\w-]+(?:="")?/g, "").replace(/\s*ng-version="[^"]*"/g, "").replace(/\s*ng-server-context="[^"]*"/g, "").replace(/\s*ngh="[^"]*"/g, "").replace(/\n\s*\n/g, "\n");
|
|
400
|
+
}
|
|
401
|
+
var init_strip_artifacts = __esm({
|
|
402
|
+
"libs/email/src/lib/utils/strip-artifacts.ts"() {
|
|
403
|
+
"use strict";
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// libs/email/src/lib/render/render-types.ts
|
|
408
|
+
import { InjectionToken, inject } from "@angular/core";
|
|
409
|
+
function injectEmailData() {
|
|
410
|
+
return inject(EMAIL_DATA);
|
|
411
|
+
}
|
|
412
|
+
var EMAIL_DATA;
|
|
413
|
+
var init_render_types = __esm({
|
|
414
|
+
"libs/email/src/lib/render/render-types.ts"() {
|
|
415
|
+
"use strict";
|
|
416
|
+
EMAIL_DATA = new InjectionToken("EMAIL_DATA");
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// libs/email/src/lib/render/render-email.ts
|
|
421
|
+
import "@angular/compiler";
|
|
422
|
+
import { reflectComponentType } from "@angular/core";
|
|
423
|
+
import { renderApplication } from "@angular/platform-server";
|
|
424
|
+
import { bootstrapApplication } from "@angular/platform-browser";
|
|
425
|
+
function buildDocument(selector) {
|
|
426
|
+
return `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><${selector}></${selector}></body></html>`;
|
|
427
|
+
}
|
|
428
|
+
async function renderEmail(component, data, options) {
|
|
429
|
+
const shouldInlineCss = options?.inlineCss ?? true;
|
|
430
|
+
const shouldStripArtifacts = options?.stripArtifacts ?? true;
|
|
431
|
+
const extraProviders = options?.providers ?? [];
|
|
432
|
+
const mirror = reflectComponentType(component);
|
|
433
|
+
if (!mirror) {
|
|
434
|
+
throw new Error(
|
|
435
|
+
`Cannot reflect component type: ${component.name}. Ensure it has a @Component decorator.`
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
const providers = [...extraProviders, { provide: EMAIL_DATA, useValue: data ?? {} }];
|
|
439
|
+
let html = await renderApplication(
|
|
440
|
+
(context) => bootstrapApplication(component, { providers }, context),
|
|
441
|
+
{
|
|
442
|
+
document: buildDocument(mirror.selector),
|
|
443
|
+
url: "/"
|
|
444
|
+
}
|
|
445
|
+
);
|
|
446
|
+
if (shouldStripArtifacts) {
|
|
447
|
+
html = stripAngularArtifacts(html);
|
|
448
|
+
}
|
|
449
|
+
if (shouldInlineCss) {
|
|
450
|
+
html = inlineCss(html);
|
|
451
|
+
}
|
|
452
|
+
return html;
|
|
453
|
+
}
|
|
454
|
+
var init_render_email = __esm({
|
|
455
|
+
"libs/email/src/lib/render/render-email.ts"() {
|
|
456
|
+
"use strict";
|
|
457
|
+
init_css_inliner();
|
|
458
|
+
init_strip_artifacts();
|
|
459
|
+
init_render_types();
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
362
463
|
// libs/email/src/lib/templates/default-templates.ts
|
|
363
464
|
var DEFAULT_PASSWORD_RESET_BLOCKS, DEFAULT_VERIFICATION_BLOCKS;
|
|
364
465
|
var init_default_templates = __esm({
|
|
@@ -979,83 +1080,6 @@ var init_eml_footer_component = __esm({
|
|
|
979
1080
|
}
|
|
980
1081
|
});
|
|
981
1082
|
|
|
982
|
-
// libs/email/src/lib/utils/blocks-to-plain-text.ts
|
|
983
|
-
function blocksToPlainText(blocks2, depth = 0) {
|
|
984
|
-
const lines = [];
|
|
985
|
-
for (const block of blocks2) {
|
|
986
|
-
const text2 = blockToText(block, depth);
|
|
987
|
-
if (text2) {
|
|
988
|
-
lines.push(text2);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
return lines.join("\n\n");
|
|
992
|
-
}
|
|
993
|
-
function blockToText(block, depth) {
|
|
994
|
-
switch (block.type) {
|
|
995
|
-
case "header":
|
|
996
|
-
return headerToText(block.data);
|
|
997
|
-
case "text":
|
|
998
|
-
return String(block.data["content"] ?? "");
|
|
999
|
-
case "button":
|
|
1000
|
-
return buttonToText(block.data);
|
|
1001
|
-
case "footer":
|
|
1002
|
-
return String(block.data["text"] ?? "");
|
|
1003
|
-
case "columns":
|
|
1004
|
-
if (depth >= MAX_BLOCK_DEPTH2) {
|
|
1005
|
-
console.warn("[momentum:email] Max nesting depth reached, skipping columns block");
|
|
1006
|
-
return "";
|
|
1007
|
-
}
|
|
1008
|
-
return columnsToText(block.data, depth);
|
|
1009
|
-
case "divider":
|
|
1010
|
-
case "spacer":
|
|
1011
|
-
case "image":
|
|
1012
|
-
return "";
|
|
1013
|
-
default:
|
|
1014
|
-
return "";
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
function headerToText(data) {
|
|
1018
|
-
const title = String(data["title"] ?? "");
|
|
1019
|
-
const subtitle = data["subtitle"] ? String(data["subtitle"]) : "";
|
|
1020
|
-
if (!title && !subtitle)
|
|
1021
|
-
return "";
|
|
1022
|
-
if (!subtitle)
|
|
1023
|
-
return title;
|
|
1024
|
-
return `${title}
|
|
1025
|
-
${subtitle}`;
|
|
1026
|
-
}
|
|
1027
|
-
function buttonToText(data) {
|
|
1028
|
-
const label = String(data["label"] ?? "");
|
|
1029
|
-
const href = data["href"] ? String(data["href"]) : "";
|
|
1030
|
-
if (!label)
|
|
1031
|
-
return "";
|
|
1032
|
-
if (!href)
|
|
1033
|
-
return label;
|
|
1034
|
-
return `${label}: ${href}`;
|
|
1035
|
-
}
|
|
1036
|
-
function columnsToText(data, depth) {
|
|
1037
|
-
const columns = data["columns"];
|
|
1038
|
-
if (!Array.isArray(columns))
|
|
1039
|
-
return "";
|
|
1040
|
-
const parts = [];
|
|
1041
|
-
for (const col of columns) {
|
|
1042
|
-
if (col && typeof col === "object" && Array.isArray(col.blocks)) {
|
|
1043
|
-
const colText = blocksToPlainText(col.blocks, depth + 1);
|
|
1044
|
-
if (colText) {
|
|
1045
|
-
parts.push(colText);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
return parts.join("\n\n");
|
|
1050
|
-
}
|
|
1051
|
-
var MAX_BLOCK_DEPTH2;
|
|
1052
|
-
var init_blocks_to_plain_text = __esm({
|
|
1053
|
-
"libs/email/src/lib/utils/blocks-to-plain-text.ts"() {
|
|
1054
|
-
"use strict";
|
|
1055
|
-
MAX_BLOCK_DEPTH2 = 5;
|
|
1056
|
-
}
|
|
1057
|
-
});
|
|
1058
|
-
|
|
1059
1083
|
// libs/email/src/index.ts
|
|
1060
1084
|
var src_exports = {};
|
|
1061
1085
|
__export(src_exports, {
|
|
@@ -1306,7 +1330,7 @@ async function renderFromDbTemplate(template, variables, defaultSubject, default
|
|
|
1306
1330
|
if (!template.emailBlocks || !Array.isArray(template.emailBlocks) || template.emailBlocks.length === 0) {
|
|
1307
1331
|
return null;
|
|
1308
1332
|
}
|
|
1309
|
-
const { renderEmailFromBlocks: renderEmailFromBlocks2, replaceVariables: replaceVariables2, blocksToPlainText: blocksToPlainText2 } = await Promise.resolve().then(() => (
|
|
1333
|
+
const { renderEmailFromBlocks: renderEmailFromBlocks2, replaceVariables: replaceVariables2, blocksToPlainText: blocksToPlainText2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
1310
1334
|
const subject = template.subject ? replaceVariables2(template.subject, variables) : defaultSubject;
|
|
1311
1335
|
const blocks2 = template.emailBlocks;
|
|
1312
1336
|
const html = renderEmailFromBlocks2(
|