From 2cd8f8ea143e28199e70f97b6a0b19dc21cfc301 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sat, 5 Sep 2026 12:06:48 +0530 Subject: [PATCH] fix(email-renderer): preserve section ancestry in parsed HTML --- bun.lock | 7 ++++--- packages/email-renderer/package.json | 3 ++- packages/email-renderer/src/blocks.ts | 4 ++-- packages/email-renderer/test/email.test.ts | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/bun.lock b/bun.lock index 54f28eb1..78e2507e 100644 --- a/bun.lock +++ b/bun.lock @@ -270,7 +270,7 @@ }, "packages/block-editor": { "name": "@wrnexus/block-editor", - "version": "0.1.0", + "version": "0.1.1", "dependencies": { "@wrnexus/blocks": "workspace:*", "@wrnexus/dnd": "workspace:*", @@ -284,7 +284,7 @@ }, "packages/blocks": { "name": "@wrnexus/blocks", - "version": "0.1.0", + "version": "0.1.2", "devDependencies": { "@types/bun": "^1.4.0", "typescript": "^6.0.3", @@ -428,7 +428,7 @@ }, "packages/email-renderer": { "name": "@wrnexus/email-renderer", - "version": "0.1.0", + "version": "0.1.8", "dependencies": { "@wrnexus/blocks": "workspace:*", "amphtml-validator": "1.0.38", @@ -437,6 +437,7 @@ }, "devDependencies": { "@types/bun": "^1.4.0", + "parse5": "7.3.0", "typescript": "^6.0.3", }, }, diff --git a/packages/email-renderer/package.json b/packages/email-renderer/package.json index af5ad6ab..cf90c958 100644 --- a/packages/email-renderer/package.json +++ b/packages/email-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/email-renderer", - "version": "0.1.7", + "version": "0.1.8", "type": "module", "description": "WRNexus block email renderers with HTML, text, AMP Email, and MJML interoperability.", "exports": { @@ -21,6 +21,7 @@ "mjml-parser-xml": "5.4.0" }, "devDependencies": { + "parse5": "7.3.0", "@types/bun": "^1.4.0", "typescript": "^6.0.3" } diff --git a/packages/email-renderer/src/blocks.ts b/packages/email-renderer/src/blocks.ts index 2f88c65d..448c7db2 100644 --- a/packages/email-renderer/src/blocks.ts +++ b/packages/email-renderer/src/blocks.ts @@ -129,12 +129,12 @@ export const sectionBlock = defineBlock({ renderers: { emailHtml: ({ node, slots }) => emailCell( - `
${slots.content}
`, + `
${slots.content}
`, node, ), ampEmail: ({ node, slots }) => emailCell( - `
${slots.content}
`, + `
${slots.content}
`, node, ), mjml: ({ node, slots }) => diff --git a/packages/email-renderer/test/email.test.ts b/packages/email-renderer/test/email.test.ts index 0d742385..e0ac094e 100644 --- a/packages/email-renderer/test/email.test.ts +++ b/packages/email-renderer/test/email.test.ts @@ -1,4 +1,5 @@ import { describe, expect, test } from "bun:test"; +import { parse, type DefaultTreeAdapterMap } from "parse5"; import { emailCoreBlocks, renderEmail, @@ -55,6 +56,21 @@ const document: BlockDocument = { }; describe("email renderer", () => { + test("browser HTML parsing preserves every block inside its section", async () => { + const rendered = await renderEmail(document); + expect(rendered.ok).toBe(true); + if (!rendered.ok) return; + const tree = parse(rendered.value.parts.html.content); + const ancestry = new Map(); + const walk = (node: DefaultTreeAdapterMap["node"], parents: string[]) => { + const id = "attrs" in node ? node.attrs.find(attr => attr.name === "data-block-id")?.value : undefined; + if (id) ancestry.set(id, parents); + if ("childNodes" in node) for (const child of node.childNodes) walk(child, id ? [...parents, id] : parents); + }; + walk(tree, []); + expect(ancestry.get("heading")).toEqual(["root", "section"]); + expect(ancestry.get("button")).toEqual(["root", "section"]); + }); test("renders deterministic HTML, text, AMP, and MJML", async () => { const first = await renderEmail(document, { amp: true, mjml: true }); const second = await renderEmail(document, { amp: true, mjml: true });