fix(email-renderer): stack AMP columns at mobile widths
This commit is contained in:
1 parent
8e51b28583
commit
2f735b267b
4 files changed
+10
-5
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/email-renderer",
|
"name": "@wrnexus/email-renderer",
|
||||||
"version": "0.1.17",
|
"version": "0.1.18",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "WRNexus block email renderers with HTML, text, AMP Email, and MJML interoperability.",
|
"description": "WRNexus block email renderers with HTML, text, AMP Email, and MJML interoperability.",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ export const columnsBlock = defineBlock({
|
|||||||
node,
|
node,
|
||||||
),
|
),
|
||||||
ampEmail: ({ node, slots }) =>
|
ampEmail: ({ node, slots }) =>
|
||||||
emailCell(`<table role="presentation" width="100%"><tr>${slots.columns}</tr></table>`, node),
|
emailCell(`<table role="presentation" width="100%"><tr class="wrn-columns">${slots.columns}</tr></table>`, node),
|
||||||
mjml: ({ slots }) => slots.columns,
|
mjml: ({ slots }) => slots.columns,
|
||||||
},
|
},
|
||||||
textRenderer: ({ slots }) => slots.columns,
|
textRenderer: ({ slots }) => slots.columns,
|
||||||
@@ -234,7 +234,7 @@ export const columnBlock = defineBlock({
|
|||||||
emailHtml: ({ node, slots }) =>
|
emailHtml: ({ node, slots }) =>
|
||||||
`<td data-block-id="${html(node.id)}" class="wrn-column" width="${html(attrs(node).width)}" valign="top"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">${slots.content}</table></td>`,
|
`<td data-block-id="${html(node.id)}" class="wrn-column" width="${html(attrs(node).width)}" valign="top"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">${slots.content}</table></td>`,
|
||||||
ampEmail: ({ node, slots }) =>
|
ampEmail: ({ node, slots }) =>
|
||||||
`<td width="${html(attrs(node).width)}" valign="top"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">${slots.content}</table></td>`,
|
`<td class="wrn-column" width="${html(attrs(node).width)}" valign="top"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">${slots.content}</table></td>`,
|
||||||
mjml: ({ node, slots }) =>
|
mjml: ({ node, slots }) =>
|
||||||
`<mj-column width="${html(attrs(node).width)}">${slots.content}</mj-column>`,
|
`<mj-column width="${html(attrs(node).width)}">${slots.content}</mj-column>`,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ const head = (document: BlockDocument, body: string, direction: "ltr" | "rtl") =
|
|||||||
};
|
};
|
||||||
const ampHead = (document: BlockDocument, body: string, direction: "ltr" | "rtl") => {
|
const ampHead = (document: BlockDocument, body: string, direction: "ltr" | "rtl") => {
|
||||||
const props = document.root.props as Record<string, unknown>;
|
const props = document.root.props as Record<string, unknown>;
|
||||||
const css = `.marketing-image img{object-fit:contain}body{margin:0;color:${props.textColor ?? "#111827"};font-family:${props.fontFamily ?? "Arial, sans-serif"}}a{color:${props.linkColor ?? "#2563eb"}}.email-bg{background:${props.background ?? "#f3f4f6"}}.email-body{max-width:${props.width ?? "600"}px;width:100%;background:${props.contentBackground ?? "#ffffff"}}`;
|
const css = `@media only screen and (max-width:480px){.email-body .wrn-columns{display:block}.email-body .wrn-column{display:block;width:100%}}.marketing-image img{object-fit:contain}body{margin:0;color:${props.textColor ?? "#111827"};font-family:${props.fontFamily ?? "Arial, sans-serif"}}a{color:${props.linkColor ?? "#2563eb"}}.email-bg{background:${props.background ?? "#f3f4f6"}}.email-body{max-width:${props.width ?? "600"}px;width:100%;background:${props.contentBackground ?? "#ffffff"}}`;
|
||||||
return `<!doctype html><html amp4email data-css-strict lang="${escapeHtml(document.meta.lang)}" dir="${direction}"><head><meta charset="utf-8"><script async src="https://cdn.ampproject.org/v0.js"></script><style amp4email-boilerplate>body{visibility:hidden}</style><style amp-custom>${css}.section{padding:24px}.button{background:#2563eb;border-radius:6px;color:#fff;display:inline-block;font-weight:700;padding:12px 20px;text-decoration:none}.spacer{height:24px}</style></head><body>${body}</body></html>`;
|
return `<!doctype html><html amp4email data-css-strict lang="${escapeHtml(document.meta.lang)}" dir="${direction}"><head><meta charset="utf-8"><script async src="https://cdn.ampproject.org/v0.js"></script><style amp4email-boilerplate>body{visibility:hidden}</style><style amp-custom>${css}.section{padding:24px}.button{background:#2563eb;border-radius:6px;color:#fff;display:inline-block;font-weight:700;padding:12px 20px;text-decoration:none}.spacer{height:24px}</style></head><body>${body}</body></html>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,13 +62,18 @@ describe("email renderer", () => {
|
|||||||
const draft=structuredClone(document);
|
const draft=structuredClone(document);
|
||||||
const content=draft.root.slots.content[0]!.slots.content;
|
const content=draft.root.slots.content[0]!.slots.content;
|
||||||
draft.root.slots.content[0]!.slots.content=[{id:"columns",type:"layout.columns",version:1,props:{},styles:{},slots:{columns:Array.from({length:count},(_,index)=>({id:`column-${index}`,type:"layout.column",version:1,props:{width:`${100/count}%`},styles:{},slots:{content:index===0?content:[]}}))}}];
|
draft.root.slots.content[0]!.slots.content=[{id:"columns",type:"layout.columns",version:1,props:{},styles:{},slots:{columns:Array.from({length:count},(_,index)=>({id:`column-${index}`,type:"layout.column",version:1,props:{width:`${100/count}%`},styles:{},slots:{content:index===0?content:[]}}))}}];
|
||||||
const result=await renderEmail(draft,{mjml:true});
|
const result=await renderEmail(draft,{mjml:true,amp:true});
|
||||||
expect(result.ok).toBe(true);
|
expect(result.ok).toBe(true);
|
||||||
if(!result.ok)continue;
|
if(!result.ok)continue;
|
||||||
const mjml=result.value.exports!.mjml!;
|
const mjml=result.value.exports!.mjml!;
|
||||||
expect(mjml.match(/<mj-column\b/g)).toHaveLength(count);
|
expect(mjml.match(/<mj-column\b/g)).toHaveLength(count);
|
||||||
expect(await validateMjml(mjml)).toEqual([]);
|
expect(await validateMjml(mjml)).toEqual([]);
|
||||||
expect(mjml).toContain("Hello <world>");
|
expect(mjml).toContain("Hello <world>");
|
||||||
|
const amp=result.value.parts.amp;
|
||||||
|
expect(amp?.validation.valid).toBe(true);
|
||||||
|
expect(amp?.content.match(/class="wrn-column"/g)).toHaveLength(count);
|
||||||
|
expect(amp?.content).toContain('class="wrn-columns"');
|
||||||
|
expect(amp?.content).toContain('@media only screen and (max-width:480px){.email-body .wrn-columns{display:block}.email-body .wrn-column{display:block;width:100%}}');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
test("global brand logo survives HTML, AMP, and strict MJML export", async () => {
|
test("global brand logo survives HTML, AMP, and strict MJML export", async () => {
|
||||||
|
|||||||
Reference in new issue
Block a user