From fd777605e1eb378b4c585a96229b676c427f2506 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sat, 5 Sep 2026 12:44:09 +0530 Subject: [PATCH] fix(email-renderer): stack columns only at compact widths --- packages/email-renderer/package.json | 2 +- packages/email-renderer/src/email.ts | 4 ++-- packages/email-renderer/test/email.test.ts | 9 +++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/email-renderer/package.json b/packages/email-renderer/package.json index f261e31f..518f31e7 100644 --- a/packages/email-renderer/package.json +++ b/packages/email-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/email-renderer", - "version": "0.1.11", + "version": "0.1.12", "type": "module", "description": "WRNexus block email renderers with HTML, text, AMP Email, and MJML interoperability.", "exports": { diff --git a/packages/email-renderer/src/email.ts b/packages/email-renderer/src/email.ts index 15abd616..4fd8dbf9 100644 --- a/packages/email-renderer/src/email.ts +++ b/packages/email-renderer/src/email.ts @@ -65,7 +65,7 @@ export const emailKind = defineDocumentKind({ rootTypes: ["layout.email-document"], blocks: emailCoreBlocks, variables: { recipientName: "string", unsubscribeUrl: "string", organizationAddress: "string" }, - breakpoints: { compact: 620 }, + breakpoints: { compact: 480 }, capabilities: ["email-html", "plain-text", "amp-email", "mjml"], targets: ["emailHtml", "plainText", "ampEmail", "mjml"], limits: { ...DEFAULT_LIMITS, maxOutputBytes: 2_000_000 }, @@ -77,7 +77,7 @@ const head = (document: BlockDocument, body: string, direction: "ltr" | "rtl") = const textColor = escapeHtml(props.textColor ?? "#111827"); const linkColor = escapeHtml(props.linkColor ?? "#2563eb"); const fontFamily = escapeHtml(props.fontFamily ?? "Arial, sans-serif"); - return `${escapeHtml(document.meta.subject)}${document.meta.preheader ? `
${escapeHtml(document.meta.preheader)}
` : ""}${body}`; + return `${escapeHtml(document.meta.subject)}${document.meta.preheader ? `
${escapeHtml(document.meta.preheader)}
` : ""}${body}`; }; const ampHead = (document: BlockDocument, body: string, direction: "ltr" | "rtl") => `${body}`; diff --git a/packages/email-renderer/test/email.test.ts b/packages/email-renderer/test/email.test.ts index 9718ecac..8c88139c 100644 --- a/packages/email-renderer/test/email.test.ts +++ b/packages/email-renderer/test/email.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { parse, type DefaultTreeAdapterMap } from "parse5"; import { emailCoreBlocks, + emailKind, renderEmail, validateAmpEmail, validateMjml, @@ -56,6 +57,14 @@ const document: BlockDocument = { }; describe("email renderer", () => { + test("responsive stacking begins below the desktop email width", async () => { + const rendered = await renderEmail(document); + expect(rendered.ok).toBe(true); + if (!rendered.ok) return; + expect(emailKind.breakpoints.compact).toBe(480); + expect(rendered.value.parts.html.content).toContain("max-width:480px"); + expect(rendered.value.parts.html.content).not.toContain("max-width:620px"); + }); test("countdown URLs are derived for HTML AMP and MJML without mutating the document", async () => { const draft = structuredClone(document); draft.root.slots.content[0]!.slots.content = [{id:"timer",type:"content.countdown",version:1,props:{label:"Offer ends",deadline:"2026-10-01T00:00:00Z",fallback:"Offer ended"},styles:{},slots:{}}];