@clay-design-system/email 0.2.4 → 0.3.1
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/MIGRATION.md +31 -0
- package/README.md +7 -0
- package/dist/build/catalog.d.ts +0 -1
- package/dist/generated/email-tokens.d.ts +0 -1
- package/dist/generated/email-tokens.js +0 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/package.json +14 -5
- package/dist/build/asset-scoring.d.ts +0 -48
- package/dist/build/asset-scoring.d.ts.map +0 -1
- package/dist/build/asset-scoring.js +0 -58
- package/dist/build/asset-scoring.js.map +0 -1
- package/dist/build/braze-transform.d.ts +0 -20
- package/dist/build/braze-transform.d.ts.map +0 -1
- package/dist/build/braze-transform.js +0 -26
- package/dist/build/braze-transform.js.map +0 -1
- package/dist/build/catalog.d.ts.map +0 -1
- package/dist/build/catalog.js +0 -3
- package/dist/build/catalog.js.map +0 -1
- package/dist/build/cloudinary-env.d.ts +0 -15
- package/dist/build/cloudinary-env.d.ts.map +0 -1
- package/dist/build/cloudinary-env.js +0 -36
- package/dist/build/cloudinary-env.js.map +0 -1
- package/dist/build/cloudinary-manifest.d.ts +0 -33
- package/dist/build/cloudinary-manifest.d.ts.map +0 -1
- package/dist/build/cloudinary-manifest.js +0 -36
- package/dist/build/cloudinary-manifest.js.map +0 -1
- package/dist/build/compile.d.ts +0 -11
- package/dist/build/compile.d.ts.map +0 -1
- package/dist/build/compile.js +0 -234
- package/dist/build/compile.js.map +0 -1
- package/dist/build/email-config.d.ts +0 -26
- package/dist/build/email-config.d.ts.map +0 -1
- package/dist/build/email-config.js +0 -17
- package/dist/build/email-config.js.map +0 -1
- package/dist/build/email-list.d.ts +0 -6
- package/dist/build/email-list.d.ts.map +0 -1
- package/dist/build/email-list.js +0 -17
- package/dist/build/email-list.js.map +0 -1
- package/dist/build/email-tree.d.ts +0 -23
- package/dist/build/email-tree.d.ts.map +0 -1
- package/dist/build/email-tree.js +0 -46
- package/dist/build/email-tree.js.map +0 -1
- package/dist/build/export-braze.d.ts +0 -22
- package/dist/build/export-braze.d.ts.map +0 -1
- package/dist/build/export-braze.js +0 -92
- package/dist/build/export-braze.js.map +0 -1
- package/dist/build/generate-stock-library-map.d.ts +0 -13
- package/dist/build/generate-stock-library-map.d.ts.map +0 -1
- package/dist/build/generate-stock-library-map.js +0 -202
- package/dist/build/generate-stock-library-map.js.map +0 -1
- package/dist/build/icon-registry-map.d.ts +0 -34
- package/dist/build/icon-registry-map.d.ts.map +0 -1
- package/dist/build/icon-registry-map.js +0 -44
- package/dist/build/icon-registry-map.js.map +0 -1
- package/dist/build/import-examples.d.ts +0 -14
- package/dist/build/import-examples.d.ts.map +0 -1
- package/dist/build/import-examples.js +0 -65
- package/dist/build/import-examples.js.map +0 -1
- package/dist/build/persona-character-map.d.ts +0 -32
- package/dist/build/persona-character-map.d.ts.map +0 -1
- package/dist/build/persona-character-map.js +0 -90
- package/dist/build/persona-character-map.js.map +0 -1
- package/dist/build/placeholder.d.ts +0 -79
- package/dist/build/placeholder.d.ts.map +0 -1
- package/dist/build/placeholder.js +0 -148
- package/dist/build/placeholder.js.map +0 -1
- package/dist/build/stock-library-map.d.ts +0 -57
- package/dist/build/stock-library-map.d.ts.map +0 -1
- package/dist/build/stock-library-map.js +0 -1261
- package/dist/build/stock-library-map.js.map +0 -1
- package/dist/build/upload-assets.d.ts +0 -20
- package/dist/build/upload-assets.d.ts.map +0 -1
- package/dist/build/upload-assets.js +0 -153
- package/dist/build/upload-assets.js.map +0 -1
- package/dist/build/upload-library-assets.d.ts +0 -21
- package/dist/build/upload-library-assets.d.ts.map +0 -1
- package/dist/build/upload-library-assets.js +0 -182
- package/dist/build/upload-library-assets.js.map +0 -1
- package/dist/build/visual-resolver.d.ts +0 -87
- package/dist/build/visual-resolver.d.ts.map +0 -1
- package/dist/build/visual-resolver.js +0 -439
- package/dist/build/visual-resolver.js.map +0 -1
- package/dist/examples/manifest.d.ts +0 -21
- package/dist/examples/manifest.d.ts.map +0 -1
- package/dist/examples/manifest.js +0 -84
- package/dist/examples/manifest.js.map +0 -1
- package/dist/exports/contact-sales/Images/Contact_sales_Image_16f4175c-d08c-43f6-9d4c-a0606383271d.png +0 -0
- package/dist/exports/contact-sales/Images/Contact_sales_Image_659b3091-1da9-40c2-86b0-04250982e529.png +0 -0
- package/dist/exports/contact-sales/Images/Contact_sales_Image_79c651f4-5f0f-4a7f-8354-1f6f95ae86d9.png +0 -0
- package/dist/exports/contact-sales/index.braze.html +0 -837
- package/dist/exports/contact-sales/index.html +0 -837
- package/dist/exports/event-confirmation/Images/Confirmation_Image_11938de2-4161-4ae8-8969-90ea0d8b45cb.png +0 -0
- package/dist/exports/event-confirmation/Images/Confirmation_Image_3c52e81f-5d4f-452c-bad1-0471a27598f1.png +0 -0
- package/dist/exports/event-confirmation/Images/Confirmation_Image_3ec1fec8-bf46-4068-8835-633567a715f9.png +0 -0
- package/dist/exports/event-confirmation/Images/Confirmation_Image_c4980c01-c270-4384-a56c-0bae74814cf9.png +0 -0
- package/dist/exports/event-confirmation/Images/Confirmation_Image_cde93e8c-0f96-434d-acaf-1b86503c66f0.png +0 -0
- package/dist/exports/event-confirmation/index.braze.html +0 -1055
- package/dist/exports/event-confirmation/index.html +0 -1055
- package/dist/exports/legal-update/Images/v2_Image_07bbcc13-0ab8-46e4-ab94-98f215f85f69.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_34394d50-acdf-4375-b254-eef1f84aaacb.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_4a25f2bd-6270-439b-86c5-4a968a1b104f.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_7e8e814f-3112-4d8c-af5b-4f4616d84d9c.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_b24a04c8-4af0-42a1-be0f-cd3f66595e47.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_b709b9fb-836e-4c20-82e5-a9cb9d702392.png +0 -0
- package/dist/exports/legal-update/Images/v2_Image_ed7b924b-35e6-4536-be0c-92ddc8a34fc2.png +0 -0
- package/dist/exports/legal-update/index.braze.html +0 -1731
- package/dist/exports/legal-update/index.html +0 -1731
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_09be22f6-1f30-4c58-bf33-1df0494b8fc2.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_2dfb595e-6fe2-4e6e-a73a-942a085b38ab.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_544c971b-b4b5-4c89-a25a-8f0d92644009.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_5b6a9576-1c33-40c5-81e3-637514fb6c78.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_680c6193-793a-4a24-8288-4bb4046f4f5e.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_75818ba9-026a-45d7-91e4-f992d4ee7690.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_785f18e6-816d-44d1-8efb-ecc82510b540.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_8bf9141d-9d63-4601-9e81-5c9d726e17f8.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_9097d6e0-65d0-4237-9661-963751812786.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_a4ef2f53-2eaf-438a-bfef-61455ac0915e.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_b7748f87-a7b7-4a91-981a-16567683e4b4.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_bc9830a4-2911-4768-808a-32cbbc39215e.png +0 -0
- package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_ef0e8e92-9075-43a9-991f-09a77ef6d6d4.png +0 -0
- package/dist/exports/newsletter/index.braze.html +0 -125
- package/dist/exports/newsletter/index.html +0 -125
- package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-blocks.png +0 -0
- package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-hero-mcp.png +0 -0
- package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-magic.png +0 -0
- package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-mcp.png +0 -0
- package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-portfolio.png +0 -0
- package/dist/exports/newsletter-ai-june-july/index.braze.html +0 -1640
- package/dist/exports/newsletter-ai-june-july/index.html +0 -1640
- package/dist/exports/survey/Images/EmailLove_Image_3b6f4a6f-7f5f-418b-be71-9371b25c20ce.png +0 -0
- package/dist/exports/survey/Images/EmailLove_Image_f659c728-2401-485d-8d90-98c962d28c0c.png +0 -0
- package/dist/exports/survey/index.braze.html +0 -515
- package/dist/exports/survey/index.html +0 -515
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_115ccc58-a47f-4eca-a1f2-c0d86e1e1cf4.png +0 -0
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_aec4d0d3-6057-4b8a-8d8f-46fbd024f182.png +0 -0
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_d139966a-6051-4383-bf8f-1e5138e1b030.png +0 -0
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_080fa361-a3f2-4593-9ac0-03cf3a7972ff.png +0 -0
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_5ebade34-8f1d-4c2c-9d27-5f9e843ce502.png +0 -0
- package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_aa5e4144-9ec8-4525-b01e-077d72f0bab6.png +0 -0
- package/dist/exports/trial-01-welcome/index.braze.html +0 -941
- package/dist/exports/trial-01-welcome/index.html +0 -941
- package/dist/exports/trial-02/Images/tp2_Image_5b0d9bc4-2e38-4252-8f20-d9f27d471c21.png +0 -0
- package/dist/exports/trial-02/Images/tp2_Image_b3f77c7c-cc8e-4db8-a5d9-072f4f621e72.png +0 -0
- package/dist/exports/trial-02/Images/tp2_Image_cafd1a17-1915-47cd-80f2-1c2d0b133cfe.png +0 -0
- package/dist/exports/trial-02/index.braze.html +0 -923
- package/dist/exports/trial-02/index.html +0 -923
- package/dist/exports/trial-03/Images/tp3_Image_1b96630c-fc4d-4aec-91fb-3c1d4d8544b3.png +0 -0
- package/dist/exports/trial-03/Images/tp3_Image_58f3a342-2193-4b5c-b30a-96f7f3338dd8.png +0 -0
- package/dist/exports/trial-03/Images/tp3_Image_6c4f307a-bac2-40e7-b4f1-9aa623c9eb8e.png +0 -0
- package/dist/exports/trial-03/Images/tp3_Image_848917ce-3f89-4538-a826-558b21f5fea7.png +0 -0
- package/dist/exports/trial-03/Images/tp3_Image_aae8410f-556f-4fb9-88f9-f276d75bafd2.png +0 -0
- package/dist/exports/trial-03/Images/tp3_Image_b4d5be39-509e-4f22-9601-dd070e4c6561.png +0 -0
- package/dist/exports/trial-03/index.braze.html +0 -1129
- package/dist/exports/trial-03/index.html +0 -1129
- package/dist/exports/trial-04/Images/tp4_Image_03bd5a56-25e3-4dcc-bef5-143bf12312d5.png +0 -0
- package/dist/exports/trial-04/Images/tp4_Image_0facbfca-b735-4199-a0d9-05a59341a1e3.gif +0 -0
- package/dist/exports/trial-04/Images/tp4_Image_171cee5f-cd3d-42f0-a180-995893d3742a.png +0 -0
- package/dist/exports/trial-04/Images/tp4_Image_3509d89d-1825-4817-8c1e-130fa294d0e1.png +0 -0
- package/dist/exports/trial-04/Images/tp4_Image_763a0f40-2985-4140-859b-ddd34f20a520.png +0 -0
- package/dist/exports/trial-04/Images/tp4_Image_cc2db4f5-b41d-45d7-a798-7a79e7b8d4d8.png +0 -0
- package/dist/exports/trial-04/index.braze.html +0 -885
- package/dist/exports/trial-04/index.html +0 -885
- package/dist/exports/trial-05/Images/tp5_Image_0248a517-5c60-4e84-ad1c-449dcf4f6a64.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_4c1a2d5a-47d3-4801-bb3a-01c22decc108.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_63ae77e7-cec7-4b4a-91e0-603b5a80929f.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_7aa43530-6707-4308-ab0e-e4c38fc1b77d.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_7efe5b6d-b360-4179-bee1-72908ba569bc.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_b142bd84-c40a-4a29-b9d5-715b52fdd937.png +0 -0
- package/dist/exports/trial-05/Images/tp5_Image_c0c896ea-5b68-4f58-9e27-cdb4a1f1b438.png +0 -0
- package/dist/exports/trial-05/index.braze.html +0 -1023
- package/dist/exports/trial-05/index.html +0 -1023
- package/dist/exports/trial-06/Images/tp6_Image_2267a268-8a80-4e0d-8813-d4c75dbab6f2.png +0 -0
- package/dist/exports/trial-06/Images/tp6_Image_637a97b7-837e-478d-8ed1-6e8c2739fdc7.png +0 -0
- package/dist/exports/trial-06/Images/tp6_Image_a78df270-ad6f-41e6-8822-ba8ec38313a3.png +0 -0
- package/dist/exports/trial-06/index.braze.html +0 -773
- package/dist/exports/trial-06/index.html +0 -773
- package/dist/exports/winback/Images/_managers_Image_4587ac22-460c-487a-bc37-9dbc487e95a4.png +0 -0
- package/dist/exports/winback/Images/_managers_Image_8a77ec2c-ed49-480d-a1a1-7a38abad232a.png +0 -0
- package/dist/exports/winback/Images/_managers_Image_bb643775-8a2f-4e28-9dfb-6d1838c3561f.png +0 -0
- package/dist/exports/winback/Images/_managers_Image_f7d1bca5-0fcb-4d4c-abcd-40ce2d453b07.png +0 -0
- package/dist/exports/winback/index.braze.html +0 -605
- package/dist/exports/winback/index.html +0 -605
- package/dist/generated/email-tokens.d.ts.map +0 -1
- package/dist/generated/email-tokens.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/tokens/build-email-assets.d.ts +0 -19
- package/dist/tokens/build-email-assets.d.ts.map +0 -1
- package/dist/tokens/build-email-assets.js +0 -186
- package/dist/tokens/build-email-assets.js.map +0 -1
- package/dist/tokens/build-email-tokens.d.ts +0 -17
- package/dist/tokens/build-email-tokens.d.ts.map +0 -1
- package/dist/tokens/build-email-tokens.js +0 -229
- package/dist/tokens/build-email-tokens.js.map +0 -1
package/dist/build/compile.js
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MJML compile pipeline.
|
|
3
|
-
*
|
|
4
|
-
* Discovers the container, section previews, and full email compositions; compiles each with MJML;
|
|
5
|
-
* writes standalone HTML (+ Braze + static variants for emails) to dist/emails/, and a dist/catalog.json
|
|
6
|
-
* that Storybook and the docs read from.
|
|
7
|
-
*
|
|
8
|
-
* Run via tsx (not the emitted dist copy). Pass --watch to recompile on change.
|
|
9
|
-
*/
|
|
10
|
-
import mjml2html from 'mjml';
|
|
11
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
12
|
-
import { resolve, dirname, join } from 'node:path';
|
|
13
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
14
|
-
import { brazeTransform } from './braze-transform';
|
|
15
|
-
import { loadCloudinaryManifest, indexManifestByCampaignEmailFile } from './cloudinary-manifest';
|
|
16
|
-
import { findIconByName } from './icon-registry-map';
|
|
17
|
-
import { assetsDir, listDirs, walkEmails } from './email-tree';
|
|
18
|
-
// Shared DS asset folders and SVGs always stay base64-inlined (D20: Cloudinary hosting is
|
|
19
|
-
// raster-only) — EXCEPT icons/, which has its own hosted PNG per icon.json's cloudinaryPngUrl
|
|
20
|
-
// (see below). Campaign assets (anything else, e.g. src/assets/<campaign>/hero.png) get a
|
|
21
|
-
// hosted URL instead, once `email:upload` has run — see cloudinary-manifest.ts.
|
|
22
|
-
const SHARED_ASSET_DIRS = new Set(['icons', 'integrations', 'logos', 'placeholders']);
|
|
23
|
-
const RASTER_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp']);
|
|
24
|
-
const cloudinaryManifest = loadCloudinaryManifest();
|
|
25
|
-
const cloudinaryIndex = cloudinaryManifest ? indexManifestByCampaignEmailFile(cloudinaryManifest) : null;
|
|
26
|
-
/**
|
|
27
|
-
* Post-process compiled HTML: for each `/assets/<path>` src, prefer a hosted Cloudinary URL and
|
|
28
|
-
* otherwise fall back to inlining as a base64 data URI. MJML resolves mj-include itself before
|
|
29
|
-
* our pre-processor runs, so assets referenced in included section files survive compilation as
|
|
30
|
-
* raw paths — we resolve them here.
|
|
31
|
-
*
|
|
32
|
-
* Two independent hosted-URL sources:
|
|
33
|
-
* - `icons/<name>.svg` → the Clay icon registry's `cloudinaryPngUrl` (icons.json, populated by
|
|
34
|
-
* scripts/cloudinary/upload-icons-to-cloudinary.ts). PNG, not the icon's own SVG source: many email
|
|
35
|
-
* clients (notably Outlook) don't reliably render SVG in <img>, so hosted icon delivery
|
|
36
|
-
* follows the same raster-only rule as everything else here — only the *authoring* format is
|
|
37
|
-
* SVG. An icon not yet uploaded (brand-new, before its first `icons:upload-cloudinary` run)
|
|
38
|
-
* falls through to local base64 inlining exactly as before this existed.
|
|
39
|
-
* - Everything else under a non-shared dir (campaign raster assets) → the per-campaign
|
|
40
|
-
* Cloudinary manifest, keyed by campaign/email/filename (unchanged from before).
|
|
41
|
-
*
|
|
42
|
-
* `campaign`/`email` are only known for actual email compositions; container/section/component
|
|
43
|
-
* previews pass empty strings, which simply never match the manifest index (correct — those have
|
|
44
|
-
* no campaign context, so non-icon assets always inline in previews).
|
|
45
|
-
*/
|
|
46
|
-
function inlineAssetsInHtml(html, campaign, email) {
|
|
47
|
-
return html.replace(/src="([^"]*\/assets\/([^"?#]+))"/g, (_match, _fullPath, filename) => {
|
|
48
|
-
const firstSegment = filename.split('/')[0];
|
|
49
|
-
const ext = (filename.split('.').pop() ?? '').toLowerCase();
|
|
50
|
-
const basename = filename.split('/').pop();
|
|
51
|
-
if (firstSegment === 'icons' && basename && ext === 'svg') {
|
|
52
|
-
const iconName = basename.slice(0, -'.svg'.length);
|
|
53
|
-
const hostedIcon = findIconByName(iconName)?.cloudinaryPngUrl;
|
|
54
|
-
if (hostedIcon)
|
|
55
|
-
return `src="${hostedIcon}"`;
|
|
56
|
-
}
|
|
57
|
-
if (cloudinaryIndex && basename && !SHARED_ASSET_DIRS.has(firstSegment) && RASTER_EXTS.has(ext)) {
|
|
58
|
-
const hosted = cloudinaryIndex.get(`${campaign}/${email}/${basename}`);
|
|
59
|
-
if (hosted)
|
|
60
|
-
return `src="${hosted}"`;
|
|
61
|
-
}
|
|
62
|
-
const absPath = resolve(assetsDir, filename);
|
|
63
|
-
if (!existsSync(absPath))
|
|
64
|
-
return _match;
|
|
65
|
-
const raw = readFileSync(absPath);
|
|
66
|
-
const mime = ext === 'svg' ? 'image/svg+xml' : `image/${ext || 'png'}`;
|
|
67
|
-
return `src="data:${mime};base64,${raw.toString('base64')}"`;
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
71
|
-
const srcDir = resolve(__dirname, '..');
|
|
72
|
-
const pkgDir = resolve(srcDir, '..');
|
|
73
|
-
const distEmails = resolve(pkgDir, 'dist', 'emails');
|
|
74
|
-
const distDir = resolve(pkgDir, 'dist');
|
|
75
|
-
const titleCase = (slug) => slug.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
76
|
-
/** Compile one .mjml file to HTML, throwing with context on any validation error. */
|
|
77
|
-
function compileMjml(filePath, campaign = '', email = '') {
|
|
78
|
-
const input = readFileSync(filePath, 'utf-8');
|
|
79
|
-
// mjml2html is synchronous in v4; @types/mjml over-declares a Promise, so cast to the real shape.
|
|
80
|
-
const { html: rawHtml, errors } = mjml2html(input, {
|
|
81
|
-
filePath,
|
|
82
|
-
validationLevel: 'soft',
|
|
83
|
-
keepComments: true,
|
|
84
|
-
minify: false,
|
|
85
|
-
});
|
|
86
|
-
if (errors && errors.length) {
|
|
87
|
-
const msg = errors.map((e) => ` • ${e.formattedMessage ?? e.message}`).join('\n');
|
|
88
|
-
throw new Error(`MJML errors in ${filePath}:\n${msg}`);
|
|
89
|
-
}
|
|
90
|
-
// Inline any local asset paths that survived MJML's mj-include resolution.
|
|
91
|
-
return inlineAssetsInHtml(rawHtml, campaign, email);
|
|
92
|
-
}
|
|
93
|
-
async function loadEmailConfig(emailDir, id) {
|
|
94
|
-
const configPath = join(emailDir, `${id}.config.ts`);
|
|
95
|
-
if (!existsSync(configPath))
|
|
96
|
-
return {};
|
|
97
|
-
const mod = await import(pathToFileURL(configPath).href);
|
|
98
|
-
return (mod.default ?? {});
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Derive the inbox subject + preheader from compiled HTML. The subject is the document `<title>`
|
|
102
|
-
* (MJML `<mj-title>`); the preheader is the hidden preview div MJML emits for `<mj-preview>` — the
|
|
103
|
-
* only hidden div carrying `opacity:0` (section spacer divs use `mso-hide:all` without it).
|
|
104
|
-
*/
|
|
105
|
-
function extractInboxMeta(html) {
|
|
106
|
-
const decode = (s) => s
|
|
107
|
-
.replace(/&#x([0-9a-f]+);/gi, (_m, h) => String.fromCodePoint(parseInt(h, 16)))
|
|
108
|
-
.replace(/&#(\d+);/g, (_m, d) => String.fromCodePoint(Number(d)))
|
|
109
|
-
.replace(/"/g, '"')
|
|
110
|
-
.replace(/</g, '<')
|
|
111
|
-
.replace(/>/g, '>')
|
|
112
|
-
.replace(/&/g, '&')
|
|
113
|
-
.trim();
|
|
114
|
-
const titleMatch = html.match(/<title>([\s\S]*?)<\/title>/i);
|
|
115
|
-
const previewMatch = html.match(/<div style="[^"]*opacity:0[^"]*">([\s\S]*?)<\/div>/i);
|
|
116
|
-
const subject = titleMatch ? decode(titleMatch[1]) : undefined;
|
|
117
|
-
const preheader = previewMatch ? decode(previewMatch[1]) : undefined;
|
|
118
|
-
return {
|
|
119
|
-
subject: subject || undefined,
|
|
120
|
-
preheader: preheader || undefined,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Compile one email composition and push its catalog item. `catalogId` is the flat id used for
|
|
125
|
-
* dist/emails/ output filenames and the catalog (campaign sub-emails flatten to
|
|
126
|
-
* `<campaign>-<email-name>`); `fileBaseName` is the actual on-disk file stem inside `emailDir`
|
|
127
|
-
* (`<fileBaseName>.mjml` / `.config.ts` / `.static.html`) — the two differ for campaign sub-emails.
|
|
128
|
-
*/
|
|
129
|
-
async function compileOneEmail(catalogId, emailDir, campaign, fileBaseName, items) {
|
|
130
|
-
const mjmlPath = join(emailDir, `${fileBaseName}.mjml`);
|
|
131
|
-
const html = compileMjml(mjmlPath, campaign, fileBaseName);
|
|
132
|
-
writeFileSync(join(distEmails, `${catalogId}.html`), html);
|
|
133
|
-
const config = await loadEmailConfig(emailDir, fileBaseName);
|
|
134
|
-
// Inbox metadata: derive the truth from the compiled HTML; warn if config declares a divergent value.
|
|
135
|
-
const { subject, preheader } = extractInboxMeta(html);
|
|
136
|
-
if (config.subject && subject && config.subject !== subject) {
|
|
137
|
-
console.warn(` ⚠ ${catalogId}: config.subject "${config.subject}" ≠ <mj-title> "${subject}" — update the config to match.`);
|
|
138
|
-
}
|
|
139
|
-
if (config.preheader && preheader && config.preheader !== preheader) {
|
|
140
|
-
console.warn(` ⚠ ${catalogId}: config.preheader "${config.preheader}" ≠ <mj-preview> "${preheader}" — update the config to match.`);
|
|
141
|
-
}
|
|
142
|
-
// Braze full-template variant
|
|
143
|
-
const brazeConfig = (config.braze ?? {});
|
|
144
|
-
const brazeHtml = brazeTransform(html, brazeConfig);
|
|
145
|
-
writeFileSync(join(distEmails, `${catalogId}.braze.html`), brazeHtml);
|
|
146
|
-
// Static HTML fallback (hand-authored; passed through untouched)
|
|
147
|
-
let staticHtml;
|
|
148
|
-
const staticPath = join(emailDir, `${fileBaseName}.static.html`);
|
|
149
|
-
if (existsSync(staticPath)) {
|
|
150
|
-
staticHtml = readFileSync(staticPath, 'utf-8');
|
|
151
|
-
writeFileSync(join(distEmails, `${catalogId}.static.html`), staticHtml);
|
|
152
|
-
}
|
|
153
|
-
items.push({
|
|
154
|
-
id: catalogId,
|
|
155
|
-
title: titleCase(catalogId),
|
|
156
|
-
kind: 'email',
|
|
157
|
-
html,
|
|
158
|
-
brazeHtml,
|
|
159
|
-
staticHtml,
|
|
160
|
-
subject,
|
|
161
|
-
preheader,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
async function build() {
|
|
165
|
-
mkdirSync(distEmails, { recursive: true });
|
|
166
|
-
const items = [];
|
|
167
|
-
// 1. Container shell
|
|
168
|
-
const containerPath = resolve(srcDir, 'container', 'container.mjml');
|
|
169
|
-
if (existsSync(containerPath)) {
|
|
170
|
-
const html = compileMjml(containerPath);
|
|
171
|
-
writeFileSync(join(distEmails, 'container.html'), html);
|
|
172
|
-
items.push({ id: 'container', title: 'Container', kind: 'container', html });
|
|
173
|
-
}
|
|
174
|
-
// 2. Section previews (src/sections/<name>/<name>.preview.mjml)
|
|
175
|
-
const sectionsDir = resolve(srcDir, 'sections');
|
|
176
|
-
for (const name of listDirs(sectionsDir)) {
|
|
177
|
-
const preview = join(sectionsDir, name, `${name}.preview.mjml`);
|
|
178
|
-
if (!existsSync(preview))
|
|
179
|
-
continue;
|
|
180
|
-
const html = compileMjml(preview);
|
|
181
|
-
writeFileSync(join(distEmails, `section-${name}.html`), html);
|
|
182
|
-
items.push({ id: name, title: titleCase(name), kind: 'section', html });
|
|
183
|
-
}
|
|
184
|
-
// 2b. Component previews (src/components/<name>/<name>.preview.mjml) — atomic, reusable
|
|
185
|
-
// fragments (buttons, images) rather than full narrative sections.
|
|
186
|
-
const componentsDir = resolve(srcDir, 'components');
|
|
187
|
-
for (const name of listDirs(componentsDir)) {
|
|
188
|
-
const preview = join(componentsDir, name, `${name}.preview.mjml`);
|
|
189
|
-
if (!existsSync(preview))
|
|
190
|
-
continue;
|
|
191
|
-
const html = compileMjml(preview);
|
|
192
|
-
writeFileSync(join(distEmails, `component-${name}.html`), html);
|
|
193
|
-
items.push({ id: name, title: titleCase(name), kind: 'component', html });
|
|
194
|
-
}
|
|
195
|
-
// 3. Full email compositions — two shapes, both under src/emails/:
|
|
196
|
-
// (a) flat single email: src/emails/<name>/<name>.mjml
|
|
197
|
-
// (b) campaign sequence: src/emails/<campaign>/<email-name>/<email-name>.mjml
|
|
198
|
-
// (the output convention documented in skills/email-campaign/SKILL.md) — each
|
|
199
|
-
// sub-email compiles as `<campaign>-<email-name>` in the flat dist/emails/ output.
|
|
200
|
-
for (const { catalogId, emailDir, campaign, emailSlug } of walkEmails()) {
|
|
201
|
-
await compileOneEmail(catalogId, emailDir, campaign, emailSlug, items);
|
|
202
|
-
}
|
|
203
|
-
const catalog = {
|
|
204
|
-
generatedFrom: '@clay-design-system/email src/build/compile.ts',
|
|
205
|
-
items,
|
|
206
|
-
};
|
|
207
|
-
writeFileSync(resolve(distDir, 'catalog.json'), JSON.stringify(catalog, null, 2));
|
|
208
|
-
const counts = items.reduce((a, i) => ((a[i.kind] = (a[i.kind] ?? 0) + 1), a), {});
|
|
209
|
-
console.log(`@clay-design-system/email: compiled ${items.length} artifacts ` +
|
|
210
|
-
`(${counts.container ?? 0} container, ${counts.section ?? 0} sections, ` +
|
|
211
|
-
`${counts.component ?? 0} components, ${counts.email ?? 0} emails)`);
|
|
212
|
-
}
|
|
213
|
-
async function main() {
|
|
214
|
-
await build();
|
|
215
|
-
if (process.argv.includes('--watch')) {
|
|
216
|
-
const { default: chokidar } = await import('chokidar');
|
|
217
|
-
const watchGlobs = [
|
|
218
|
-
resolve(srcDir, 'container'),
|
|
219
|
-
resolve(srcDir, 'sections'),
|
|
220
|
-
resolve(srcDir, 'components'),
|
|
221
|
-
resolve(srcDir, 'emails'),
|
|
222
|
-
resolve(srcDir, 'generated'),
|
|
223
|
-
];
|
|
224
|
-
console.log('@clay-design-system/email: watching for changes…');
|
|
225
|
-
chokidar.watch(watchGlobs, { ignoreInitial: true }).on('all', () => {
|
|
226
|
-
build().catch((err) => console.error(err.message));
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
main().catch((err) => {
|
|
231
|
-
console.error(err.message);
|
|
232
|
-
process.exit(1);
|
|
233
|
-
});
|
|
234
|
-
//# sourceMappingURL=compile.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/build/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-email export config schema.
|
|
3
|
-
*
|
|
4
|
-
* Each `src/emails/<name>/<name>.config.ts` default-exports an object of this shape. It carries the
|
|
5
|
-
* delivery metadata that travels with the email to the ESP (Braze): the inbox `subject` line and
|
|
6
|
-
* `preheader` (preview) line, plus the CDN asset base and Braze transform settings.
|
|
7
|
-
*
|
|
8
|
-
* Source-of-truth note: the MJML head (`<mj-title>` / `<mj-preview>`) is what actually renders into
|
|
9
|
-
* the compiled HTML. `subject`/`preheader` here mirror those values so they can be read without
|
|
10
|
-
* parsing HTML (e.g. by the Braze uploader, since the delivered subject is inbox metadata, not body
|
|
11
|
-
* markup). `compile.ts` derives the real values from the compiled HTML and warns on any drift.
|
|
12
|
-
*/
|
|
13
|
-
import type { BrazeConfig } from './braze-transform';
|
|
14
|
-
export interface EmailExportConfig {
|
|
15
|
-
/** CDN base for hosted assets, e.g. `https://assets.monday.com/email/`. */
|
|
16
|
-
assetBaseUrl: string;
|
|
17
|
-
/** Inbox subject line. Mirrors the MJML `<mj-title>`. Best practice: ≤35 chars (see 11-subject-and-preheader.md). */
|
|
18
|
-
subject: string;
|
|
19
|
-
/** Inbox preview / preheader line. Mirrors the MJML `<mj-preview>`. Best practice: ≤50 chars. */
|
|
20
|
-
preheader: string;
|
|
21
|
-
/** Braze export settings (unsubscribe token, Liquid personalization, import mode). */
|
|
22
|
-
braze: BrazeConfig;
|
|
23
|
-
}
|
|
24
|
-
/** Identity helper for authoring configs with full type inference + checking. */
|
|
25
|
-
export declare function defineEmailConfig(config: EmailExportConfig): EmailExportConfig;
|
|
26
|
-
//# sourceMappingURL=email-config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-config.d.ts","sourceRoot":"","sources":["../../src/build/email-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAA;IACpB,qHAAqH;IACrH,OAAO,EAAE,MAAM,CAAA;IACf,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAA;IACjB,sFAAsF;IACtF,KAAK,EAAE,WAAW,CAAA;CACnB;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAE9E"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-email export config schema.
|
|
3
|
-
*
|
|
4
|
-
* Each `src/emails/<name>/<name>.config.ts` default-exports an object of this shape. It carries the
|
|
5
|
-
* delivery metadata that travels with the email to the ESP (Braze): the inbox `subject` line and
|
|
6
|
-
* `preheader` (preview) line, plus the CDN asset base and Braze transform settings.
|
|
7
|
-
*
|
|
8
|
-
* Source-of-truth note: the MJML head (`<mj-title>` / `<mj-preview>`) is what actually renders into
|
|
9
|
-
* the compiled HTML. `subject`/`preheader` here mirror those values so they can be read without
|
|
10
|
-
* parsing HTML (e.g. by the Braze uploader, since the delivered subject is inbox metadata, not body
|
|
11
|
-
* markup). `compile.ts` derives the real values from the compiled HTML and warns on any drift.
|
|
12
|
-
*/
|
|
13
|
-
/** Identity helper for authoring configs with full type inference + checking. */
|
|
14
|
-
export function defineEmailConfig(config) {
|
|
15
|
-
return config;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=email-config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-config.js","sourceRoot":"","sources":["../../src/build/email-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAeH,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,MAAyB;IACzD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-list.d.ts","sourceRoot":"","sources":["../../src/build/email-list.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAcvD,CAAA"}
|
package/dist/build/email-list.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/** Canonical list of EmailLove exports: slug → source folder name. */
|
|
2
|
-
export const EMAILS = [
|
|
3
|
-
{ slug: 'contact-sales', dir: 'Contact sales email' },
|
|
4
|
-
{ slug: 'event-confirmation', dir: 'Event confirmation' },
|
|
5
|
-
{ slug: 'legal-update', dir: 'Legal email' },
|
|
6
|
-
{ slug: 'newsletter', dir: 'Newsletter' },
|
|
7
|
-
{ slug: 'survey', dir: 'Survey' },
|
|
8
|
-
{ slug: 'winback', dir: 'Winback' },
|
|
9
|
-
{ slug: 'trial-01-welcome', dir: 'tp1 - welcome' },
|
|
10
|
-
{ slug: 'trial-02', dir: 'tp2' },
|
|
11
|
-
{ slug: 'trial-03', dir: 'tp3' },
|
|
12
|
-
{ slug: 'trial-04', dir: 'tp4' },
|
|
13
|
-
{ slug: 'trial-05', dir: 'tp5' },
|
|
14
|
-
{ slug: 'trial-06', dir: 'tp6' },
|
|
15
|
-
{ slug: 'newsletter-ai-june-july', dir: '' },
|
|
16
|
-
];
|
|
17
|
-
//# sourceMappingURL=email-list.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-list.js","sourceRoot":"","sources":["../../src/build/email-list.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,CAAC,MAAM,MAAM,GAAyC;IAC1D,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,qBAAqB,EAAE;IACrD,EAAE,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,oBAAoB,EAAE;IACzD,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE;IAC5C,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE;IACzC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE;IACjC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE;IACnC,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,eAAe,EAAE;IAClD,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE;IAChC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE;IAChC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE;IAChC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE;IAChC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE;IAChC,EAAE,IAAI,EAAE,yBAAyB,EAAE,GAAG,EAAE,EAAE,EAAE;CAC7C,CAAA"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared directory walk over src/emails/ — both flat single emails and campaign sequences.
|
|
3
|
-
* compile.ts and upload-assets.ts both need the same (campaign, emailSlug, mjmlPath) tuples; this
|
|
4
|
-
* is the one place that walk is defined, so the two pipelines can never disagree on it.
|
|
5
|
-
*/
|
|
6
|
-
export declare const srcDir: string;
|
|
7
|
-
export declare const emailsDir: string;
|
|
8
|
-
export declare const assetsDir: string;
|
|
9
|
-
export declare function listDirs(parent: string): string[];
|
|
10
|
-
export interface EmailEntry {
|
|
11
|
-
/** Flattened id used for dist/emails/ output + catalog (campaign sub-emails: `<campaign>-<email>`). */
|
|
12
|
-
catalogId: string;
|
|
13
|
-
/** Absolute dir containing `<emailSlug>.mjml` / `.config.ts`. */
|
|
14
|
-
emailDir: string;
|
|
15
|
-
/** Top-level dir under src/emails/. For a flat single email, equals emailSlug. */
|
|
16
|
-
campaign: string;
|
|
17
|
-
/** The on-disk file stem (`<emailSlug>.mjml` / `.config.ts`). */
|
|
18
|
-
emailSlug: string;
|
|
19
|
-
mjmlPath: string;
|
|
20
|
-
}
|
|
21
|
-
/** Every real email (flat or campaign sub-email) under src/emails/ that has an .mjml file. */
|
|
22
|
-
export declare function walkEmails(): EmailEntry[];
|
|
23
|
-
//# sourceMappingURL=email-tree.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-tree.d.ts","sourceRoot":"","sources":["../../src/build/email-tree.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,MAAM,QAA2B,CAAA;AAC9C,eAAO,MAAM,SAAS,QAA4B,CAAA;AAClD,eAAO,MAAM,SAAS,QAA4B,CAAA;AAElD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjD;AAED,MAAM,WAAW,UAAU;IACzB,uGAAuG;IACvG,SAAS,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAuBzC"}
|
package/dist/build/email-tree.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared directory walk over src/emails/ — both flat single emails and campaign sequences.
|
|
3
|
-
* compile.ts and upload-assets.ts both need the same (campaign, emailSlug, mjmlPath) tuples; this
|
|
4
|
-
* is the one place that walk is defined, so the two pipelines can never disagree on it.
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
7
|
-
import { dirname, join, resolve } from 'node:path';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
export const srcDir = resolve(__dirname, '..');
|
|
11
|
-
export const emailsDir = resolve(srcDir, 'emails');
|
|
12
|
-
export const assetsDir = resolve(srcDir, 'assets');
|
|
13
|
-
export function listDirs(parent) {
|
|
14
|
-
if (!existsSync(parent))
|
|
15
|
-
return [];
|
|
16
|
-
return readdirSync(parent, { withFileTypes: true })
|
|
17
|
-
.filter((d) => d.isDirectory())
|
|
18
|
-
.map((d) => d.name);
|
|
19
|
-
}
|
|
20
|
-
/** Every real email (flat or campaign sub-email) under src/emails/ that has an .mjml file. */
|
|
21
|
-
export function walkEmails() {
|
|
22
|
-
const entries = [];
|
|
23
|
-
for (const name of listDirs(emailsDir)) {
|
|
24
|
-
const dir = join(emailsDir, name);
|
|
25
|
-
const flatMjmlPath = join(dir, `${name}.mjml`);
|
|
26
|
-
if (existsSync(flatMjmlPath)) {
|
|
27
|
-
entries.push({ catalogId: name, emailDir: dir, campaign: name, emailSlug: name, mjmlPath: flatMjmlPath });
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
for (const subName of listDirs(dir)) {
|
|
31
|
-
const subDir = join(dir, subName);
|
|
32
|
-
const subMjmlPath = join(subDir, `${subName}.mjml`);
|
|
33
|
-
if (!existsSync(subMjmlPath))
|
|
34
|
-
continue;
|
|
35
|
-
entries.push({
|
|
36
|
-
catalogId: `${name}-${subName}`,
|
|
37
|
-
emailDir: subDir,
|
|
38
|
-
campaign: name,
|
|
39
|
-
emailSlug: subName,
|
|
40
|
-
mjmlPath: subMjmlPath,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return entries;
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=email-tree.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-tree.js","sourceRoot":"","sources":["../../src/build/email-tree.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAClD,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAElD,MAAM,UAAU,QAAQ,CAAC,MAAc;IACrC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,OAAO,WAAW,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAChD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACvB,CAAC;AAcD,8FAA8F;AAC9F,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAiB,EAAE,CAAA;IAChC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,CAAA;QAC9C,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAA;YACzG,SAAQ;QACV,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YACjC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,OAAO,CAAC,CAAA;YACnD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;gBAAE,SAAQ;YACtC,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,GAAG,IAAI,IAAI,OAAO,EAAE;gBAC/B,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,OAAO;gBAClB,QAAQ,EAAE,WAAW;aACtB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Braze export packager for EmailLove examples.
|
|
3
|
-
*
|
|
4
|
-
* Reads normalized EmailLove exports from `src/examples/<slug>/` and produces a self-contained
|
|
5
|
-
* per-email folder in `dist/exports/<slug>/`:
|
|
6
|
-
*
|
|
7
|
-
* dist/exports/<slug>/
|
|
8
|
-
* index.html ← preview HTML (relative image paths, for local review)
|
|
9
|
-
* index.braze.html ← Braze-ready HTML (unsubscribe token applied)
|
|
10
|
-
* Images/ ← all images, copied from src/examples/<slug>/Images/
|
|
11
|
-
*
|
|
12
|
-
* By default images are referenced as `Images/<file>` (relative) — matching the EmailLove
|
|
13
|
-
* reference format. Pass `--cdn-base=<url>` to rewrite image src values to absolute CDN URLs
|
|
14
|
-
* in index.braze.html, which is required for production Braze delivery.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* pnpm --filter @clay-design-system/email export:braze
|
|
18
|
-
* pnpm --filter @clay-design-system/email export:braze:cdn
|
|
19
|
-
* tsx src/build/export-braze.ts [--cdn-base=https://assets.monday.com/email/]
|
|
20
|
-
*/
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=export-braze.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export-braze.d.ts","sourceRoot":"","sources":["../../src/build/export-braze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Braze export packager for EmailLove examples.
|
|
3
|
-
*
|
|
4
|
-
* Reads normalized EmailLove exports from `src/examples/<slug>/` and produces a self-contained
|
|
5
|
-
* per-email folder in `dist/exports/<slug>/`:
|
|
6
|
-
*
|
|
7
|
-
* dist/exports/<slug>/
|
|
8
|
-
* index.html ← preview HTML (relative image paths, for local review)
|
|
9
|
-
* index.braze.html ← Braze-ready HTML (unsubscribe token applied)
|
|
10
|
-
* Images/ ← all images, copied from src/examples/<slug>/Images/
|
|
11
|
-
*
|
|
12
|
-
* By default images are referenced as `Images/<file>` (relative) — matching the EmailLove
|
|
13
|
-
* reference format. Pass `--cdn-base=<url>` to rewrite image src values to absolute CDN URLs
|
|
14
|
-
* in index.braze.html, which is required for production Braze delivery.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* pnpm --filter @clay-design-system/email export:braze
|
|
18
|
-
* pnpm --filter @clay-design-system/email export:braze:cdn
|
|
19
|
-
* tsx src/build/export-braze.ts [--cdn-base=https://assets.monday.com/email/]
|
|
20
|
-
*/
|
|
21
|
-
import { readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, existsSync, statSync, } from 'node:fs';
|
|
22
|
-
import { resolve, join, dirname, basename } from 'node:path';
|
|
23
|
-
import { fileURLToPath } from 'node:url';
|
|
24
|
-
import { brazeTransform } from './braze-transform.js';
|
|
25
|
-
import { EMAILS } from './email-list.js';
|
|
26
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
-
const examplesDir = resolve(__dirname, '..', 'examples');
|
|
28
|
-
const pkgDir = resolve(__dirname, '..', '..');
|
|
29
|
-
const exportsDir = resolve(pkgDir, 'dist', 'exports');
|
|
30
|
-
const cdnBaseArg = process.argv.find((a) => a.startsWith('--cdn-base='));
|
|
31
|
-
const cdnBase = cdnBaseArg ? cdnBaseArg.slice('--cdn-base='.length).replace(/\/?$/, '/') : null;
|
|
32
|
-
/**
|
|
33
|
-
* Rewrite `src="Images/<file>"` to `src="<cdnBase><file>"` for production Braze delivery.
|
|
34
|
-
* Only applied when --cdn-base is provided.
|
|
35
|
-
*/
|
|
36
|
-
function rewriteImageSrcs(html, base) {
|
|
37
|
-
return html.replace(/src="Images\/([^"]+)"/g, (_m, file) => `src="${base}${file}"`);
|
|
38
|
-
}
|
|
39
|
-
function exportOne(slug) {
|
|
40
|
-
const srcDir = join(examplesDir, slug);
|
|
41
|
-
if (!existsSync(srcDir)) {
|
|
42
|
-
console.warn(` ${slug.padEnd(20)} SKIP — src/examples/${slug}/ not found (run import-examples first)`);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const srcHtml = join(srcDir, 'index.html');
|
|
46
|
-
if (!existsSync(srcHtml)) {
|
|
47
|
-
console.warn(` ${slug.padEnd(20)} SKIP — no index.html in src/examples/${slug}/`);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const srcImages = join(srcDir, 'Images');
|
|
51
|
-
const destDir = join(exportsDir, slug);
|
|
52
|
-
const destImages = join(destDir, 'Images');
|
|
53
|
-
mkdirSync(destImages, { recursive: true });
|
|
54
|
-
// Copy images
|
|
55
|
-
let imageCount = 0;
|
|
56
|
-
let totalBytes = 0;
|
|
57
|
-
if (existsSync(srcImages)) {
|
|
58
|
-
for (const file of readdirSync(srcImages)) {
|
|
59
|
-
const src = join(srcImages, file);
|
|
60
|
-
if (statSync(src).isFile()) {
|
|
61
|
-
copyFileSync(src, join(destImages, basename(file)));
|
|
62
|
-
totalBytes += statSync(src).size;
|
|
63
|
-
imageCount++;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const previewHtml = readFileSync(srcHtml, 'utf-8');
|
|
68
|
-
// index.html — plain preview, relative image paths
|
|
69
|
-
writeFileSync(join(destDir, 'index.html'), previewHtml);
|
|
70
|
-
// index.braze.html — Braze transforms applied; optionally CDN-absolute image paths
|
|
71
|
-
let brazeHtml = brazeTransform(previewHtml, { unsubscribe: true });
|
|
72
|
-
if (cdnBase)
|
|
73
|
-
brazeHtml = rewriteImageSrcs(brazeHtml, cdnBase);
|
|
74
|
-
writeFileSync(join(destDir, 'index.braze.html'), brazeHtml);
|
|
75
|
-
const kbLabel = `(${(totalBytes / 1024).toFixed(0)} KB)`;
|
|
76
|
-
const cdnLabel = cdnBase ? ` → ${cdnBase}` : '';
|
|
77
|
-
console.log(` ${slug.padEnd(20)} ${String(imageCount).padStart(2)} images ${kbLabel.padEnd(12)}${cdnLabel}`);
|
|
78
|
-
}
|
|
79
|
-
function main() {
|
|
80
|
-
const mode = cdnBase ? `CDN mode (${cdnBase})` : 'relative-path mode';
|
|
81
|
-
console.log(`\nExporting ${EMAILS.length} emails to dist/exports/ [${mode}]\n`);
|
|
82
|
-
mkdirSync(exportsDir, { recursive: true });
|
|
83
|
-
for (const { slug } of EMAILS)
|
|
84
|
-
exportOne(slug);
|
|
85
|
-
console.log(`\nDone → ${exportsDir}`);
|
|
86
|
-
if (!cdnBase) {
|
|
87
|
-
console.log('\nTip: run with --cdn-base=https://assets.monday.com/email/ to get absolute image\n' +
|
|
88
|
-
'URLs in index.braze.html for production Braze delivery.');
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
main();
|
|
92
|
-
//# sourceMappingURL=export-braze.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export-braze.js","sourceRoot":"","sources":["../../src/build/export-braze.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates stock-library-map.ts from stock-library-source.csv (D5.5, board item Clay Lifecycle D5).
|
|
3
|
-
*
|
|
4
|
-
* stock-library-source.csv is the authored source — same "CSV is authored, other artifacts are
|
|
5
|
-
* generated from it, never hand-edit the generated file" convention as the Asset Catalog's own
|
|
6
|
-
* CatalogTest.csv → chips_seed.sql (see .../Assets/Asset Catalog/Table/SCHEMA.md). This script is
|
|
7
|
-
* the equivalent of that repo's `build_seed.py`.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* pnpm --filter @clay-design-system/email library:generate-map
|
|
11
|
-
*/
|
|
12
|
-
export {};
|
|
13
|
-
//# sourceMappingURL=generate-stock-library-map.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generate-stock-library-map.d.ts","sourceRoot":"","sources":["../../src/build/generate-stock-library-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|