fix(email-renderer): preserve multiline text across email formats
This commit is contained in:
1 parent
baee958c68
commit
612b3945ac
3 files changed
+20
-4
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/email-renderer",
|
"name": "@wrnexus/email-renderer",
|
||||||
"version": "0.1.14",
|
"version": "0.1.15",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const html = (value: unknown) =>
|
|||||||
.replaceAll('"', """)
|
.replaceAll('"', """)
|
||||||
.replaceAll("'", "'");
|
.replaceAll("'", "'");
|
||||||
const attrs = (node: BlockNode) => node.props as Record<string, unknown>;
|
const attrs = (node: BlockNode) => node.props as Record<string, unknown>;
|
||||||
|
const multilineText = (value: unknown) => html(value).replace(/\r\n?|\n/g, "<br />");
|
||||||
const imageDimension = (fallback: string): ValueSchema<string> => ({
|
const imageDimension = (fallback: string): ValueSchema<string> => ({
|
||||||
kind: "string",
|
kind: "string",
|
||||||
defaultValue: fallback,
|
defaultValue: fallback,
|
||||||
@@ -290,11 +291,11 @@ export const textBlock = leaf(
|
|||||||
{
|
{
|
||||||
emailHtml: ({ node }) =>
|
emailHtml: ({ node }) =>
|
||||||
emailCell(
|
emailCell(
|
||||||
`<p style="font-family:inherit;line-height:1.5;margin:0 0 16px;white-space:pre-line;">${html(attrs(node).text)}</p>`,
|
`<p style="font-family:inherit;line-height:1.5;margin:0 0 16px;">${multilineText(attrs(node).text)}</p>`,
|
||||||
node,
|
node,
|
||||||
),
|
),
|
||||||
ampEmail: ({ node }) => emailCell(`<p>${html(attrs(node).text)}</p>`, node),
|
ampEmail: ({ node }) => emailCell(`<p>${multilineText(attrs(node).text)}</p>`, node),
|
||||||
mjml: ({ node }) => `<mj-text>${html(attrs(node).text)}</mj-text>`,
|
mjml: ({ node }) => `<mj-text>${multilineText(attrs(node).text)}</mj-text>`,
|
||||||
},
|
},
|
||||||
({ node }) => `${String(attrs(node).text)}\n\n`,
|
({ node }) => `${String(attrs(node).text)}\n\n`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -57,6 +57,21 @@ const document: BlockDocument = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe("email renderer", () => {
|
describe("email renderer", () => {
|
||||||
|
test("text line breaks survive all formats without interpreting entered markup", async () => {
|
||||||
|
const draft = structuredClone(document);
|
||||||
|
const text = 'First line\r\nSecond line\n\n<script>alert("x")</script>\rLast line';
|
||||||
|
draft.root.slots.content[0]!.slots.content = [{id:"text",type:"content.text",version:1,props:{text},styles:{},slots:{}}];
|
||||||
|
const rendered = await renderEmail(draft,{amp:true,mjml:true});
|
||||||
|
expect(rendered.ok).toBe(true);
|
||||||
|
if (!rendered.ok) return;
|
||||||
|
for (const output of [rendered.value.parts.html.content,rendered.value.parts.amp?.content,rendered.value.exports?.mjml]) {
|
||||||
|
expect(output).toContain('First line<br />Second line<br /><br /><script>alert("x")</script><br />Last line');
|
||||||
|
expect(output).not.toContain('<script>alert');
|
||||||
|
}
|
||||||
|
expect(rendered.value.parts.text.content).toContain(text);
|
||||||
|
expect(rendered.value.parts.amp?.validation.valid).toBe(true);
|
||||||
|
expect(await validateMjml(rendered.value.exports!.mjml!)).toEqual([]);
|
||||||
|
});
|
||||||
test("AMP inherits the saved brand font, colors and body width", async () => {
|
test("AMP inherits the saved brand font, colors and body width", async () => {
|
||||||
const draft = structuredClone(document);
|
const draft = structuredClone(document);
|
||||||
Object.assign(draft.root.props, {width:"720",fontFamily:"Georgia, serif",textColor:"#112233",linkColor:"#445566",background:"#eeeeee",contentBackground:"#fafafa"});
|
Object.assign(draft.root.props, {width:"720",fontFamily:"Georgia, serif",textColor:"#112233",linkColor:"#445566",background:"#eeeeee",contentBackground:"#fafafa"});
|
||||||
|
|||||||
Reference in new issue
Block a user