From 33e350a66a57c03488c4e26587b0d7df4163d30d Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sat, 5 Sep 2026 18:24:38 +0530 Subject: [PATCH] Preserve configured brand logo dimensions across email targets --- packages/email-renderer/package.json | 2 +- packages/email-renderer/src/blocks.ts | 10 ++++++---- packages/email-renderer/test/email.test.ts | 10 ++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/email-renderer/package.json b/packages/email-renderer/package.json index 50d8da30..da895d5c 100644 --- a/packages/email-renderer/package.json +++ b/packages/email-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/email-renderer", - "version": "0.1.36", + "version": "0.1.37", "type": "module", "description": "WRNexus block email renderers with HTML, text, AMP Email, and MJML interoperability.", "exports": { diff --git a/packages/email-renderer/src/blocks.ts b/packages/email-renderer/src/blocks.ts index 872822ca..a6385078 100644 --- a/packages/email-renderer/src/blocks.ts +++ b/packages/email-renderer/src/blocks.ts @@ -145,6 +145,8 @@ export const emailDocumentBlock = defineBlock({ linkColor: brandColor("#2563eb"), logoUrl: safeUrl({ schemes: ["https"], optional: true }), logoAlt: string({ max: 300, default: "" }), + logoWidth: imageDimension("200"), + logoHeight: imageDimension("64"), }) as never, styles, slots: { content: contentSlot }, @@ -153,17 +155,17 @@ export const emailDocumentBlock = defineBlock({ id: id(), type: "layout.email-document", version: 1, - props: { width: "600", background: "#f3f4f6", contentBackground: "#ffffff", fontFamily: "Arial, sans-serif", textColor: "#111827", linkColor: "#2563eb", logoUrl: "", logoAlt: "" }, + props: { width: "600", background: "#f3f4f6", contentBackground: "#ffffff", fontFamily: "Arial, sans-serif", textColor: "#111827", linkColor: "#2563eb", logoUrl: "", logoAlt: "", logoWidth: "200", logoHeight: "64" }, styles: {}, slots: { content: [] }, }), renderers: { emailHtml: ({ node, slots }) => - `
${attrs(node).logoUrl ? `${html(attrs(node).logoAlt)}` : ""}${slots.content}
`, + `
${attrs(node).logoUrl ? `${html(attrs(node).logoAlt)}` : ""}${slots.content}
`, ampEmail: ({ node, slots }) => - ``, + ``, mjml: ({ node, slots, context }) => - `${mjmlDocumentHead(node, context)}${attrs(node).logoUrl ? `` : ""}${slots.content}`, + `${mjmlDocumentHead(node, context)}${attrs(node).logoUrl ? `` : ""}${slots.content}`, }, textRenderer: ({ slots }) => slots.content, } satisfies BlockDefinition); diff --git a/packages/email-renderer/test/email.test.ts b/packages/email-renderer/test/email.test.ts index 988ee5b8..c3554fbe 100644 --- a/packages/email-renderer/test/email.test.ts +++ b/packages/email-renderer/test/email.test.ts @@ -111,6 +111,8 @@ describe("email renderer", () => { const draft = structuredClone(document); draft.root.props.logoUrl = "https://example.com/logo.png"; draft.root.props.logoAlt = 'Brand & "Company"'; + draft.root.props.logoWidth = "180"; + draft.root.props.logoHeight = "90"; const result = await renderEmail(draft,{amp:true,mjml:true}); expect(result.ok).toBe(true); if (!result.ok) return; @@ -120,6 +122,14 @@ describe("email renderer", () => { } expect(result.value.parts.amp?.validation.valid).toBe(true); expect(await validateMjml(result.value.exports!.mjml!)).toEqual([]); + 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.exports?.mjml).toContain('width="180px" height="90px"'); + for (const value of ["0", "4001", "180px", "1;display:none"]) { + const invalid = structuredClone(draft); + invalid.root.props.logoWidth = value; + expect((await renderEmail(invalid)).ok).toBe(false); + } draft.root.props.logoUrl = ""; const empty = await renderEmail(draft,{amp:true,mjml:true}); expect(empty.ok).toBe(true);