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:{}}];