Make AMP brand logos responsive within configured width
Quality / quality (ubuntu-latest) (push) Failing after 1s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
Clintchiz committed 2026-09-05 18:28:25 +05:30
1 parent 33e350a66a
commit df382ed550
4 files changed
+5 -3

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@wrnexus/email-renderer", "name": "@wrnexus/email-renderer",
"version": "0.1.37", "version": "0.1.38",
"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": {
+1 -1
View File
@@ -163,7 +163,7 @@ export const emailDocumentBlock = defineBlock({
emailHtml: ({ node, slots }) => emailHtml: ({ node, slots }) =>
`<table data-block-id="${html(node.id)}" role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;table-layout:fixed;background:${html(attrs(node).background ?? "#f3f4f6")};color:${html(attrs(node).textColor ?? "#111827")};font-family:${html(attrs(node).fontFamily ?? "Arial, sans-serif")};"><tr><td align="center">${attrs(node).logoUrl ? `<img src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}" height="${html(attrs(node).logoHeight ?? "64")}" style="display:block;height:auto;max-width:100%;width:${html(attrs(node).logoWidth ?? "200")}px;margin:20px auto;" />` : ""}<table role="presentation" class="wrn-email" width="${html(attrs(node).width)}" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;table-layout:fixed;max-width:100%;width:${html(attrs(node).width)}px;background:${html(attrs(node).contentBackground ?? "#ffffff")};color:${html(attrs(node).textColor ?? "#111827")};font-family:${html(attrs(node).fontFamily ?? "Arial, sans-serif")};">${slots.content}</table></td></tr></table>`, `<table data-block-id="${html(node.id)}" role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;table-layout:fixed;background:${html(attrs(node).background ?? "#f3f4f6")};color:${html(attrs(node).textColor ?? "#111827")};font-family:${html(attrs(node).fontFamily ?? "Arial, sans-serif")};"><tr><td align="center">${attrs(node).logoUrl ? `<img src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}" height="${html(attrs(node).logoHeight ?? "64")}" style="display:block;height:auto;max-width:100%;width:${html(attrs(node).logoWidth ?? "200")}px;margin:20px auto;" />` : ""}<table role="presentation" class="wrn-email" width="${html(attrs(node).width)}" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;table-layout:fixed;max-width:100%;width:${html(attrs(node).width)}px;background:${html(attrs(node).contentBackground ?? "#ffffff")};color:${html(attrs(node).textColor ?? "#111827")};font-family:${html(attrs(node).fontFamily ?? "Arial, sans-serif")};">${slots.content}</table></td></tr></table>`,
ampEmail: ({ node, slots }) => ampEmail: ({ node, slots }) =>
`<table role="presentation" width="100%" class="email-bg"><tr><td align="center">${attrs(node).logoUrl ? `<amp-img class="marketing-image" src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}" height="${html(attrs(node).logoHeight ?? "64")}" layout="fixed"></amp-img>` : ""}<table role="presentation" width="${html(attrs(node).width)}" class="email-body">${slots.content}</table></td></tr></table>`, `<table role="presentation" width="100%" class="email-bg"><tr><td align="center">${attrs(node).logoUrl ? `<div class="brand-logo"><amp-img class="marketing-image" src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}" height="${html(attrs(node).logoHeight ?? "64")}" layout="responsive"></amp-img></div>` : ""}<table role="presentation" width="${html(attrs(node).width)}" class="email-body">${slots.content}</table></td></tr></table>`,
mjml: ({ node, slots, context }) => mjml: ({ node, slots, context }) =>
`<mjml>${mjmlDocumentHead(node, context)}<mj-body width="${html(attrs(node).width ?? "600")}px" background-color="${html(attrs(node).background ?? "#f3f4f6")}">${attrs(node).logoUrl ? `<mj-section padding="20px"><mj-column><mj-image src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}px" height="${html(attrs(node).logoHeight ?? "64")}px" padding="0" /></mj-column></mj-section>` : ""}${slots.content}</mj-body></mjml>`, `<mjml>${mjmlDocumentHead(node, context)}<mj-body width="${html(attrs(node).width ?? "600")}px" background-color="${html(attrs(node).background ?? "#f3f4f6")}">${attrs(node).logoUrl ? `<mj-section padding="20px"><mj-column><mj-image src="${html(attrs(node).logoUrl)}" alt="${html(attrs(node).logoAlt)}" width="${html(attrs(node).logoWidth ?? "200")}px" height="${html(attrs(node).logoHeight ?? "64")}px" padding="0" /></mj-column></mj-section>` : ""}${slots.content}</mj-body></mjml>`,
}, },
+1 -1
View File
@@ -83,7 +83,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 layoutCss = (node: BlockDocument["root"]): string => ampLayoutCss(node, String(document.root.props.linkColor ?? "#2563eb")) + Object.values(node.slots).flat().map(layoutCss).join(""); const layoutCss = (node: BlockDocument["root"]): string => ampLayoutCss(node, String(document.root.props.linkColor ?? "#2563eb")) + Object.values(node.slots).flat().map(layoutCss).join("");
const props = document.root.props as Record<string, unknown>; const props = document.root.props as Record<string, unknown>;
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"}}`; 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"}}.brand-logo{max-width:${props.logoWidth ?? "200"}px;width:100%;margin:20px auto}.email-bg{table-layout:fixed;width:100%;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}${layoutCss(document.root)}.button{background:#2563eb;border-radius:6px;color:#fff;display:inline-block;font-weight:700;padding:12px 20px;text-decoration:none}</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}${layoutCss(document.root)}.button{background:#2563eb;border-radius:6px;color:#fff;display:inline-block;font-weight:700;padding:12px 20px;text-decoration:none}</style></head><body>${body}</body></html>`;
}; };
@@ -124,6 +124,8 @@ describe("email renderer", () => {
expect(await validateMjml(result.value.exports!.mjml!)).toEqual([]); expect(await validateMjml(result.value.exports!.mjml!)).toEqual([]);
expect(result.value.parts.html.content).toContain('width="180" height="90"'); expect(result.value.parts.html.content).toContain('width="180" height="90"');
expect(result.value.parts.amp?.content).toContain('width="180" height="90"'); expect(result.value.parts.amp?.content).toContain('width="180" height="90"');
expect(result.value.parts.amp?.content).toContain('width="180" height="90" layout="responsive"');
expect(result.value.parts.amp?.content).toContain('.brand-logo{max-width:180px;width:100%;margin:20px auto}');
expect(result.value.exports?.mjml).toContain('width="180px" height="90px"'); expect(result.value.exports?.mjml).toContain('width="180px" height="90px"');
for (const value of ["0", "4001", "180px", "1;display:none"]) { for (const value of ["0", "4001", "180px", "1;display:none"]) {
const invalid = structuredClone(draft); const invalid = structuredClone(draft);