@clink/emails 1.0.3 → 1.0.5

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const path_1 = __importDefault(require("path"));
8
+ const mjml_1 = __importDefault(require("mjml"));
9
+ const repoRoot = path_1.default.join(__dirname, '..');
10
+ const templatesSrcRoot = path_1.default.join(repoRoot, 'src', 'templates');
11
+ const templatesRoot = path_1.default.join(__dirname, 'templates');
12
+ const htmlRoot = path_1.default.join(__dirname, 'html');
13
+ function ensureDir(dir) {
14
+ if (!fs_1.default.existsSync(dir)) {
15
+ fs_1.default.mkdirSync(dir, { recursive: true });
16
+ }
17
+ }
18
+ function copyDir(src, dest) {
19
+ if (!fs_1.default.existsSync(src))
20
+ return;
21
+ ensureDir(dest);
22
+ const entries = fs_1.default.readdirSync(src, { withFileTypes: true });
23
+ for (const entry of entries) {
24
+ const srcPath = path_1.default.join(src, entry.name);
25
+ const destPath = path_1.default.join(dest, entry.name);
26
+ if (entry.isDirectory()) {
27
+ copyDir(srcPath, destPath);
28
+ }
29
+ else {
30
+ fs_1.default.copyFileSync(srcPath, destPath);
31
+ }
32
+ }
33
+ }
34
+ function read(file) {
35
+ return fs_1.default.readFileSync(file, 'utf8');
36
+ }
37
+ function write(file, content) {
38
+ fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true });
39
+ fs_1.default.writeFileSync(file, content);
40
+ }
41
+ function replaceLocaleTokens(mjml, dict) {
42
+ let output = mjml;
43
+ for (const [key, value] of Object.entries(dict)) {
44
+ output = output.split(`[[${key}]]`).join(value);
45
+ }
46
+ return output;
47
+ }
48
+ function getDirectories(root) {
49
+ if (!fs_1.default.existsSync(root))
50
+ return [];
51
+ return fs_1.default
52
+ .readdirSync(root, { withFileTypes: true })
53
+ .filter(d => d.isDirectory())
54
+ .map(d => d.name);
55
+ }
56
+ function getLocaleFiles(templateDir) {
57
+ if (!fs_1.default.existsSync(templateDir))
58
+ return [];
59
+ return fs_1.default
60
+ .readdirSync(templateDir, { withFileTypes: true })
61
+ .filter(f => f.isFile() && f.name.endsWith('.json'))
62
+ .map(f => f.name);
63
+ }
64
+ function buildTemplate(audience, templateName, localeFile) {
65
+ const locale = localeFile.replace(/\.json$/, '');
66
+ const templateDir = path_1.default.join(templatesRoot, audience, templateName);
67
+ const contentPath = path_1.default.join(templateDir, 'template.mjml');
68
+ const translationsPath = path_1.default.join(templateDir, localeFile);
69
+ if (!fs_1.default.existsSync(contentPath))
70
+ return;
71
+ const baseTemplatePath = path_1.default.join(__dirname, 'layouts', 'base.mjml');
72
+ const baseTemplate = read(baseTemplatePath);
73
+ const content = read(contentPath);
74
+ const translations = JSON.parse(read(translationsPath));
75
+ const localizedContent = replaceLocaleTokens(content, translations);
76
+ let mjmlSource = baseTemplate;
77
+ mjmlSource = mjmlSource.replace('%CONTENT%', localizedContent);
78
+ mjmlSource = replaceLocaleTokens(mjmlSource, translations);
79
+ const { html } = (0, mjml_1.default)(mjmlSource, { minify: true });
80
+ const outPath = path_1.default.join(htmlRoot, audience, templateName, `${locale}.html`);
81
+ write(outPath, html);
82
+ }
83
+ function buildAll() {
84
+ copyDir(templatesSrcRoot, templatesRoot);
85
+ const layoutsSrcRoot = path_1.default.join(repoRoot, 'src', 'layouts');
86
+ const layoutsRoot = path_1.default.join(__dirname, 'layouts');
87
+ copyDir(layoutsSrcRoot, layoutsRoot);
88
+ const audiences = getDirectories(templatesRoot);
89
+ for (const audience of audiences) {
90
+ const audienceDir = path_1.default.join(templatesRoot, audience);
91
+ const templateNames = getDirectories(audienceDir);
92
+ for (const templateName of templateNames) {
93
+ const templateDir = path_1.default.join(audienceDir, templateName);
94
+ const localeFiles = getLocaleFiles(templateDir);
95
+ for (const localeFile of localeFiles) {
96
+ buildTemplate(audience, templateName, localeFile);
97
+ }
98
+ }
99
+ }
100
+ }
101
+ buildAll();
@@ -0,0 +1,39 @@
1
+ <!doctype html><html lang="und" dir="auto" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"><head><title></title><!--[if !mso]><!--><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]--><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style type="text/css">#outlook a { padding:0; }
2
+ body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }
3
+ table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }
4
+ img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }
5
+ p { display:block;margin:13px 0; }</style><!--[if mso]>
6
+ <noscript>
7
+ <xml>
8
+ <o:OfficeDocumentSettings>
9
+ <o:AllowPNG/>
10
+ <o:PixelsPerInch>96</o:PixelsPerInch>
11
+ </o:OfficeDocumentSettings>
12
+ </xml>
13
+ </noscript>
14
+ <![endif]--><!--[if lte mso 11]>
15
+ <style type="text/css">
16
+ .mj-outlook-group-fix { width:100% !important; }
17
+ </style>
18
+ <![endif]--><!--[if !mso]><!--><link href="undefined" rel="stylesheet" type="text/css"><style type="text/css">@import url(undefined);</style><!--<![endif]--><style type="text/css">@media only screen and (min-width:480px) {
19
+ .mj-column-per-100 { width:100% !important; max-width: 100%; }
20
+ }</style><style media="screen and (min-width:480px)">.moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }</style><style type="text/css">@media only screen and (max-width:479px) {
21
+ table.mj-full-width-mobile { width: 100% !important; }
22
+ td.mj-full-width-mobile { width: auto !important; }
23
+ }</style><style type="text/css">.body-bordered { border-radius: 24px; max-width: 600px; margin: 0 auto;
24
+ outline: none; /* Ensure the border is visible */ } @media (min-width:
25
+ 600px) { .body-bordered { border-radius: 24px; max-width: 600px; margin: 0
26
+ auto; margin-top: 40px; outline: 1px solid #D6D6D6 !important; } }
27
+ .discountBox div { border-width: 1px; border-style: dashed; border-color:
28
+ #FCBC42; }</style></head><body style="word-spacing:normal;"><div aria-roledescription="email" class="body-bordered" role="article" lang="und" dir="auto"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:12px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:24px 0px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px 8px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:40px;"><img alt="Nuento" src="https://ik.imagekit.io/nuento/logo/Logomark_Uj47FzOvV.png" style="border:0;display:block;outline:none;text-decoration:none;height:40px;width:100%;font-size:16px;" width="40" height="40"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
29
+ 0px;">Hej {{ catering.contact.name }},</p><p style="line-height: 24px; margin: 16px
30
+ 0px;">Du har modtaget en ny bestilling via Nuento med ordrenr. {{ catering_order.id8digit }}.</p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" class="btn-link" style="font-size:0px;padding:10px 25px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:separate;line-height:100%;"><tbody><tr><td align="center" bgcolor="#11141A" role="presentation" style="border:none;border-radius:999px;cursor:auto;mso-padding-alt:10px 25px;background:#11141A;" valign="middle"><a href="{{{ catering_order.approvalUrl }}}" style="background-color: #FA3232; align: left; display: inline-block; background: #11141A; color: #ffffff; font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; line-height: 24px; margin: 0; text-decoration: none; text-transform: none; padding: 10px 25px; mso-padding-alt: 0px; border-radius: 999px;" target="_blank">Svar på ordre</a></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><![endif]--> {{#if catering_order.paymentLinkName}}<!--[if mso | IE]><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
31
+ 0px;">Ordren er blevet gennemført på baggrund af et bestillingslink med følgende betegnelse:</p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-left:16px;padding-right:16px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:568px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="background-color:#E6F7FF;border-radius:8px;vertical-align:top;border-collapse:separate;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:center;color:#222730;"><p style="line-height: 24px; margin: 16px
32
+ 0px;"><i style="line-height: 24px;">{{{catering_order.paymentLinkName}}}</i></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><![endif]--> {{/if}}<!--[if mso | IE]><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
33
+ 0px;"><font size="4">Levering {{ catering_order.selectedDate }} til spisetid kl. {{ catering_order.selectedTime }}</font></p><p style="line-height: 24px; margin: 16px
34
+ 0px;"><font size="4">Samlet ordrestørrelse</font><br><font size="4"><b style="line-height: 24px;">{{ invoice.price.total }}</b></font></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:16px 0px 8px 0px;word-break:break-word;"><p style="line-height: 24px; border-top: solid 1px #dadada; font-size: 1px; margin: 0px auto; width: 100%;"></p><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 1px #dadada;font-size:1px;margin:0px auto;width:600px;" role="presentation" width="600px" ><tr><td style="height:0;line-height:0;"> &nbsp;
35
+ </td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
36
+ 0px;"><font size="4"><b style="line-height: 24px;">Har du brug for hjælp?</b></font></p><p style="line-height: 24px; margin: 16px
37
+ 0px;">Så tøv ikke med at kontakte os.</p><p style="line-height: 24px; margin: 16px
38
+ 0px;">{{ support.email }}<br><a href="tel:{{ support.phone }}" style="line-height: 24px; text-decoration: underline;">{{ support.phone }}</a></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:16px 0px 8px 0px;word-break:break-word;"><p style="line-height: 24px; border-top: solid 1px #dadada; font-size: 1px; margin: 0px auto; width: 100%;"></p><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 1px #dadada;font-size:1px;margin:0px auto;width:600px;" role="presentation" width="600px" ><tr><td style="height:0;line-height:0;"> &nbsp;
39
+ </td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:24px 24px 0px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><b style="line-height: 24px;">Sendt fra</b><br>Nuento Denmark ApS, CVR 39000725<br>Lundeborgvej 4, 9220 Aalborg</div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:32px 0px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px 24px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:118px;"><img alt="Nuento" src="https://ik.imagekit.io/nuento/logo/logo-40_5iYF6s3Jp.png" style="border:0;display:block;outline:none;text-decoration:none;height:40px;width:100%;font-size:16px;" width="118" height="40"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div></body></html>
@@ -0,0 +1,39 @@
1
+ <!doctype html><html lang="und" dir="auto" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"><head><title></title><!--[if !mso]><!--><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]--><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style type="text/css">#outlook a { padding:0; }
2
+ body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }
3
+ table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }
4
+ img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }
5
+ p { display:block;margin:13px 0; }</style><!--[if mso]>
6
+ <noscript>
7
+ <xml>
8
+ <o:OfficeDocumentSettings>
9
+ <o:AllowPNG/>
10
+ <o:PixelsPerInch>96</o:PixelsPerInch>
11
+ </o:OfficeDocumentSettings>
12
+ </xml>
13
+ </noscript>
14
+ <![endif]--><!--[if lte mso 11]>
15
+ <style type="text/css">
16
+ .mj-outlook-group-fix { width:100% !important; }
17
+ </style>
18
+ <![endif]--><!--[if !mso]><!--><link href="undefined" rel="stylesheet" type="text/css"><style type="text/css">@import url(undefined);</style><!--<![endif]--><style type="text/css">@media only screen and (min-width:480px) {
19
+ .mj-column-per-100 { width:100% !important; max-width: 100%; }
20
+ }</style><style media="screen and (min-width:480px)">.moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }</style><style type="text/css">@media only screen and (max-width:479px) {
21
+ table.mj-full-width-mobile { width: 100% !important; }
22
+ td.mj-full-width-mobile { width: auto !important; }
23
+ }</style><style type="text/css">.body-bordered { border-radius: 24px; max-width: 600px; margin: 0 auto;
24
+ outline: none; /* Ensure the border is visible */ } @media (min-width:
25
+ 600px) { .body-bordered { border-radius: 24px; max-width: 600px; margin: 0
26
+ auto; margin-top: 40px; outline: 1px solid #D6D6D6 !important; } }
27
+ .discountBox div { border-width: 1px; border-style: dashed; border-color:
28
+ #FCBC42; }</style></head><body style="word-spacing:normal;"><div aria-roledescription="email" class="body-bordered" role="article" lang="und" dir="auto"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:12px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:24px 0px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px 8px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:40px;"><img alt="Nuento" src="https://ik.imagekit.io/nuento/logo/Logomark_Uj47FzOvV.png" style="border:0;display:block;outline:none;text-decoration:none;height:40px;width:100%;font-size:16px;" width="40" height="40"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
29
+ 0px;">Hi {{ catering.contact.name }},</p><p style="line-height: 24px; margin: 16px
30
+ 0px;">You have received a new order via Nuento with order no. {{ catering_order.id8digit }}.</p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" class="btn-link" style="font-size:0px;padding:10px 25px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:separate;line-height:100%;"><tbody><tr><td align="center" bgcolor="#11141A" role="presentation" style="border:none;border-radius:999px;cursor:auto;mso-padding-alt:10px 25px;background:#11141A;" valign="middle"><a href="{{{ catering_order.approvalUrl }}}" style="background-color: #FA3232; align: left; display: inline-block; background: #11141A; color: #ffffff; font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; line-height: 24px; margin: 0; text-decoration: none; text-transform: none; padding: 10px 25px; mso-padding-alt: 0px; border-radius: 999px;" target="_blank">Respond to order</a></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><![endif]--> {{#if catering_order.paymentLinkName}}<!--[if mso | IE]><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
31
+ 0px;">The order was placed using an order link with the following label:</p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-left:16px;padding-right:16px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:568px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="background-color:#E6F7FF;border-radius:8px;vertical-align:top;border-collapse:separate;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:center;color:#222730;"><p style="line-height: 24px; margin: 16px
32
+ 0px;"><i style="line-height: 24px;">{{{catering_order.paymentLinkName}}}</i></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><![endif]--> {{/if}}<!--[if mso | IE]><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
33
+ 0px;"><font size="4">Delivery on {{ catering_order.selectedDate }} at {{ catering_order.selectedTime }}</font></p><p style="line-height: 24px; margin: 16px
34
+ 0px;"><font size="4">Total order amount</font><br><font size="4"><b style="line-height: 24px;">{{ invoice.price.total }}</b></font></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:16px 0px 8px 0px;word-break:break-word;"><p style="line-height: 24px; border-top: solid 1px #dadada; font-size: 1px; margin: 0px auto; width: 100%;"></p><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 1px #dadada;font-size:1px;margin:0px auto;width:600px;" role="presentation" width="600px" ><tr><td style="height:0;line-height:0;"> &nbsp;
35
+ </td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;padding-bottom:10px;padding-top:10px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><p style="line-height: 24px; margin: 16px
36
+ 0px;"><font size="4"><b style="line-height: 24px;">Need help?</b></font></p><p style="line-height: 24px; margin: 16px
37
+ 0px;">Don't hesitate to contact us.</p><p style="line-height: 24px; margin: 16px
38
+ 0px;">{{ support.email }}<br><a href="tel:{{ support.phone }}" style="line-height: 24px; text-decoration: underline;">{{ support.phone }}</a></p></div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="center" style="font-size:0px;padding:16px 0px 8px 0px;word-break:break-word;"><p style="line-height: 24px; border-top: solid 1px #dadada; font-size: 1px; margin: 0px auto; width: 100%;"></p><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 1px #dadada;font-size:1px;margin:0px auto;width:600px;" role="presentation" width="600px" ><tr><td style="height:0;line-height:0;"> &nbsp;
39
+ </td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:24px 24px 0px;word-break:break-word;"><div style="font-family:Arial, sans-serif;font-size:16px;line-height:24px;text-align:left;color:#222730;"><b style="line-height: 24px;">Sendt fra</b><br>Nuento Denmark ApS, CVR 39000725<br>Lundeborgvej 4, 9220 Aalborg</div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="600px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" role="presentation" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:32px 0px 0px;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0px 24px 24px;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:118px;"><img alt="Nuento" src="https://ik.imagekit.io/nuento/logo/logo-40_5iYF6s3Jp.png" style="border:0;display:block;outline:none;text-decoration:none;height:40px;width:100%;font-size:16px;" width="118" height="40"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div></body></html>
@@ -0,0 +1,13 @@
1
+ export type Locale = 'da' | 'en';
2
+ export type Audience = 'buyer' | 'supplier';
3
+ export type EmailTemplate = {
4
+ subject: string;
5
+ html: string;
6
+ };
7
+ export type TemplateDefinition = {
8
+ audience: string;
9
+ template: string;
10
+ locales: string[];
11
+ };
12
+ export declare function listTemplates(): TemplateDefinition[];
13
+ export declare function getEmailTemplate(audience: Audience, template: string, locale: Locale): EmailTemplate;
@@ -1,4 +1,5 @@
1
1
  {
2
+ "subject": "Ny ordre modtaget - Ordre #{{ catering_order.id8digit }}",
2
3
  "intro_greeting": "Hej {{ catering.contact.name }},",
3
4
  "intro_body": "Du har modtaget en ny bestilling via Nuento med ordrenr. {{ catering_order.id8digit }}.",
4
5
  "button_reply": "Svar på ordre",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "subject": "New order received - Order #{{ catering_order.id8digit }}",
2
3
  "intro_greeting": "Hi {{ catering.contact.name }},",
3
4
  "intro_body": "You have received a new order via Nuento with order no. {{ catering_order.id8digit }}.",
4
5
  "button_reply": "Respond to order",
@@ -6,5 +7,5 @@
6
7
  "delivery_line": "Delivery on {{ catering_order.selectedDate }} at {{ catering_order.selectedTime }}",
7
8
  "total_label": "Total order amount",
8
9
  "support_heading": "Need help?",
9
- "support_body": "Dont hesitate to contact us."
10
+ "support_body": "Don't hesitate to contact us."
10
11
  }
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@clink/emails",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
+ "files": [
7
+ "dist/**/*"
8
+ ],
6
9
  "scripts": {
7
10
  "build": "tsc && node dist/build-emails.js",
8
11
  "prepublishOnly": "yarn build"
@@ -1,114 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
- import mjml2html from 'mjml'
4
-
5
- const repoRoot = path.join(__dirname, '..')
6
- const templatesSrcRoot = path.join(repoRoot, 'src', 'templates')
7
- const templatesRoot = path.join(__dirname, 'templates')
8
- const htmlRoot = path.join(__dirname, 'html')
9
-
10
- function ensureDir(dir: string) {
11
- if (!fs.existsSync(dir)) {
12
- fs.mkdirSync(dir, {recursive: true})
13
- }
14
- }
15
-
16
- function copyDir(src: string, dest: string) {
17
- if (!fs.existsSync(src)) return
18
- ensureDir(dest)
19
- const entries = fs.readdirSync(src, {withFileTypes: true})
20
- for (const entry of entries) {
21
- const srcPath = path.join(src, entry.name)
22
- const destPath = path.join(dest, entry.name)
23
- if (entry.isDirectory()) {
24
- copyDir(srcPath, destPath)
25
- } else {
26
- fs.copyFileSync(srcPath, destPath)
27
- }
28
- }
29
- }
30
-
31
- function read(file: string) {
32
- return fs.readFileSync(file, 'utf8')
33
- }
34
-
35
- function write(file: string, content: string) {
36
- fs.mkdirSync(path.dirname(file), {recursive: true})
37
- fs.writeFileSync(file, content)
38
- }
39
-
40
- function replaceLocaleTokens(mjml: string, dict: Record<string, string>) {
41
- let output = mjml
42
- for (const [key, value] of Object.entries(dict)) {
43
- output = output.split(`[[${key}]]`).join(value)
44
- }
45
- return output
46
- }
47
-
48
- function getDirectories(root: string) {
49
- if (!fs.existsSync(root)) return []
50
- return fs
51
- .readdirSync(root, {withFileTypes: true})
52
- .filter(d => d.isDirectory())
53
- .map(d => d.name)
54
- }
55
-
56
- function getLocaleFiles(templateDir: string) {
57
- if (!fs.existsSync(templateDir)) return []
58
- return fs
59
- .readdirSync(templateDir, {withFileTypes: true})
60
- .filter(f => f.isFile() && f.name.endsWith('.json'))
61
- .map(f => f.name)
62
- }
63
-
64
- function buildTemplate(
65
- audience: string,
66
- templateName: string,
67
- localeFile: string,
68
- ) {
69
- const locale = localeFile.replace(/\.json$/, '')
70
- const templateDir = path.join(templatesRoot, audience, templateName)
71
- const contentPath = path.join(templateDir, 'template.mjml')
72
- const translationsPath = path.join(templateDir, localeFile)
73
- if (!fs.existsSync(contentPath)) return
74
-
75
- const baseTemplatePath = path.join(__dirname, 'layouts', 'base.mjml')
76
- const baseTemplate = read(baseTemplatePath)
77
- const content = read(contentPath)
78
- const translations = JSON.parse(read(translationsPath)) as Record<
79
- string,
80
- string
81
- >
82
-
83
- const localizedContent = replaceLocaleTokens(content, translations)
84
-
85
- let mjmlSource = baseTemplate
86
- mjmlSource = mjmlSource.replace('%CONTENT%', localizedContent)
87
- mjmlSource = replaceLocaleTokens(mjmlSource, translations)
88
-
89
- const {html} = mjml2html(mjmlSource, {minify: true})
90
- const outPath = path.join(htmlRoot, audience, templateName, `${locale}.html`)
91
- write(outPath, html)
92
- }
93
-
94
- function buildAll() {
95
- copyDir(templatesSrcRoot, templatesRoot)
96
- const layoutsSrcRoot = path.join(repoRoot, 'src', 'layouts')
97
- const layoutsRoot = path.join(__dirname, 'layouts')
98
- copyDir(layoutsSrcRoot, layoutsRoot)
99
-
100
- const audiences = getDirectories(templatesRoot)
101
- for (const audience of audiences) {
102
- const audienceDir = path.join(templatesRoot, audience)
103
- const templateNames = getDirectories(audienceDir)
104
- for (const templateName of templateNames) {
105
- const templateDir = path.join(audienceDir, templateName)
106
- const localeFiles = getLocaleFiles(templateDir)
107
- for (const localeFile of localeFiles) {
108
- buildTemplate(audience, templateName, localeFile)
109
- }
110
- }
111
- }
112
- }
113
-
114
- buildAll()
package/src/index.ts DELETED
@@ -1,92 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
-
4
- export type Locale = 'da' | 'en'
5
- export type Audience = 'buyer' | 'supplier'
6
-
7
- export type EmailTemplate = {
8
- subject: string
9
- html: string
10
- }
11
-
12
- export type TemplateDefinition = {
13
- audience: string
14
- template: string
15
- locales: string[]
16
- }
17
-
18
- const templatesRoot = path.join(__dirname, 'templates')
19
- const htmlRoot = path.join(__dirname, 'html')
20
-
21
- function getDirectories(root: string) {
22
- if (!fs.existsSync(root)) return []
23
- return fs
24
- .readdirSync(root, {withFileTypes: true})
25
- .filter(d => d.isDirectory())
26
- .map(d => d.name)
27
- }
28
-
29
- function getLocalesForTemplate(audience: string, template: string) {
30
- const dir = path.join(templatesRoot, audience, template)
31
- if (!fs.existsSync(dir)) return []
32
- return fs
33
- .readdirSync(dir, {withFileTypes: true})
34
- .filter(f => f.isFile() && f.name.endsWith('.json'))
35
- .map(f => f.name.replace(/\.json$/, ''))
36
- }
37
-
38
- export function listTemplates(): TemplateDefinition[] {
39
- const result: TemplateDefinition[] = []
40
- const audiences = getDirectories(templatesRoot)
41
- for (const audience of audiences) {
42
- const audienceDir = path.join(templatesRoot, audience)
43
- const templates = getDirectories(audienceDir)
44
- for (const template of templates) {
45
- const locales = getLocalesForTemplate(audience, template)
46
- result.push({audience, template, locales})
47
- }
48
- }
49
- return result
50
- }
51
-
52
- export function getEmailTemplate(
53
- audience: Audience,
54
- template: string,
55
- locale: Locale,
56
- ): EmailTemplate {
57
- const translationsPath = path.join(
58
- templatesRoot,
59
- audience,
60
- template,
61
- `${locale}.json`,
62
- )
63
- const htmlPath = path.join(htmlRoot, audience, template, `${locale}.html`)
64
-
65
- if (!fs.existsSync(translationsPath)) {
66
- throw new Error(
67
- `Missing translations for audience="${audience}" template="${template}" locale="${locale}"`,
68
- )
69
- }
70
-
71
- if (!fs.existsSync(htmlPath)) {
72
- throw new Error(
73
- `Missing HTML for audience="${audience}" template="${template}" locale="${locale}". Did you run the build step?`,
74
- )
75
- }
76
-
77
- const translations = JSON.parse(
78
- fs.readFileSync(translationsPath, 'utf8'),
79
- ) as Record<string, string>
80
- const html = fs.readFileSync(htmlPath, 'utf8')
81
-
82
- if (typeof translations.subject !== 'string') {
83
- throw new Error(
84
- `Translations for audience="${audience}" template="${template}" locale="${locale}" do not contain a "subject" key`,
85
- )
86
- }
87
-
88
- return {
89
- subject: translations.subject,
90
- html,
91
- }
92
- }
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2020",
4
- "module": "commonjs",
5
- "rootDir": "src",
6
- "outDir": "dist",
7
- "declaration": true,
8
- "declarationMap": false,
9
- "emitDeclarationOnly": false,
10
- "strict": true,
11
- "esModuleInterop": true,
12
- "resolveJsonModule": true
13
- },
14
- "include": ["src"]
15
- }
File without changes