react-email 6.3.0 → 6.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cli/index.mjs +1 -1
- package/dist/index.cjs +31 -7
- package/dist/index.mjs +31 -7
- package/package.json +1 -1
- package/src/components/container/container.tsx +31 -3
- package/src/components/preview/preview.spec.tsx +6 -6
- package/src/components/preview/preview.tsx +1 -1
- package/src/components/section/section.tsx +31 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# react-email
|
|
2
2
|
|
|
3
|
+
## 6.3.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fbda5c8: increase whitespace padding to 200 characters for better Gmail preview text rendering
|
|
8
|
+
|
|
9
|
+
## 6.3.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- c610dc0: fix: padding in Container/Section failing on Klaviyo and Outlook desktop
|
|
14
|
+
|
|
3
15
|
## 6.3.0
|
|
4
16
|
|
|
5
17
|
## 6.2.0
|
package/dist/cli/index.mjs
CHANGED
|
@@ -6523,7 +6523,7 @@ const getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFil
|
|
|
6523
6523
|
//#region package.json
|
|
6524
6524
|
var package_default = {
|
|
6525
6525
|
name: "react-email",
|
|
6526
|
-
version: "6.3.
|
|
6526
|
+
version: "6.3.2",
|
|
6527
6527
|
description: "A live preview of your emails right in your browser.",
|
|
6528
6528
|
bin: { "email": "./dist/cli/index.mjs" },
|
|
6529
6529
|
type: "module",
|
package/dist/index.cjs
CHANGED
|
@@ -17461,7 +17461,16 @@ const Column = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17461
17461
|
Column.displayName = "Column";
|
|
17462
17462
|
//#endregion
|
|
17463
17463
|
//#region src/components/container/container.tsx
|
|
17464
|
-
const Container = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
17464
|
+
const Container = react.forwardRef(({ children, style = {}, ...props }, ref) => {
|
|
17465
|
+
const tdStyle = {};
|
|
17466
|
+
const tableStyle = {};
|
|
17467
|
+
const styleRecord = style;
|
|
17468
|
+
for (const key in styleRecord) {
|
|
17469
|
+
if (!Object.hasOwn(styleRecord, key)) continue;
|
|
17470
|
+
const value = styleRecord[key];
|
|
17471
|
+
if (key === "padding" || key === "paddingTop" || key === "paddingRight" || key === "paddingBottom" || key === "paddingLeft") tdStyle[key] = value;
|
|
17472
|
+
else tableStyle[key] = value;
|
|
17473
|
+
}
|
|
17465
17474
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
|
|
17466
17475
|
align: "center",
|
|
17467
17476
|
width: "100%",
|
|
@@ -17473,11 +17482,14 @@ const Container = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17473
17482
|
role: "presentation",
|
|
17474
17483
|
style: {
|
|
17475
17484
|
maxWidth: "37.5em",
|
|
17476
|
-
...
|
|
17485
|
+
...tableStyle
|
|
17477
17486
|
},
|
|
17478
17487
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
17479
17488
|
style: { width: "100%" },
|
|
17480
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
17489
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
17490
|
+
style: tdStyle,
|
|
17491
|
+
children
|
|
17492
|
+
})
|
|
17481
17493
|
}) })
|
|
17482
17494
|
});
|
|
17483
17495
|
});
|
|
@@ -17862,7 +17874,7 @@ const Markdown = react.forwardRef(({ children, markdownContainerStyles, markdown
|
|
|
17862
17874
|
Markdown.displayName = "Markdown";
|
|
17863
17875
|
//#endregion
|
|
17864
17876
|
//#region src/components/preview/preview.tsx
|
|
17865
|
-
const PREVIEW_MAX_LENGTH =
|
|
17877
|
+
const PREVIEW_MAX_LENGTH = 200;
|
|
17866
17878
|
const Preview = react.forwardRef(({ children = "", ...props }, ref) => {
|
|
17867
17879
|
const text = (Array.isArray(children) ? children.join("") : children).substring(0, PREVIEW_MAX_LENGTH);
|
|
17868
17880
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -17911,7 +17923,16 @@ const Row = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17911
17923
|
Row.displayName = "Row";
|
|
17912
17924
|
//#endregion
|
|
17913
17925
|
//#region src/components/section/section.tsx
|
|
17914
|
-
const Section = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
17926
|
+
const Section = react.forwardRef(({ children, style = {}, ...props }, ref) => {
|
|
17927
|
+
const tdStyle = {};
|
|
17928
|
+
const tableStyle = {};
|
|
17929
|
+
const styleRecord = style;
|
|
17930
|
+
for (const key in styleRecord) {
|
|
17931
|
+
if (!Object.hasOwn(styleRecord, key)) continue;
|
|
17932
|
+
const value = styleRecord[key];
|
|
17933
|
+
if (key === "padding" || key === "paddingTop" || key === "paddingRight" || key === "paddingBottom" || key === "paddingLeft") tdStyle[key] = value;
|
|
17934
|
+
else tableStyle[key] = value;
|
|
17935
|
+
}
|
|
17915
17936
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
|
|
17916
17937
|
align: "center",
|
|
17917
17938
|
width: "100%",
|
|
@@ -17921,8 +17942,11 @@ const Section = react.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17921
17942
|
role: "presentation",
|
|
17922
17943
|
...props,
|
|
17923
17944
|
ref,
|
|
17924
|
-
style,
|
|
17925
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
17945
|
+
style: tableStyle,
|
|
17946
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
17947
|
+
style: tdStyle,
|
|
17948
|
+
children
|
|
17949
|
+
}) }) })
|
|
17926
17950
|
});
|
|
17927
17951
|
});
|
|
17928
17952
|
Section.displayName = "Section";
|
package/dist/index.mjs
CHANGED
|
@@ -17440,7 +17440,16 @@ const Column = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17440
17440
|
Column.displayName = "Column";
|
|
17441
17441
|
//#endregion
|
|
17442
17442
|
//#region src/components/container/container.tsx
|
|
17443
|
-
const Container = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
17443
|
+
const Container = React$1.forwardRef(({ children, style = {}, ...props }, ref) => {
|
|
17444
|
+
const tdStyle = {};
|
|
17445
|
+
const tableStyle = {};
|
|
17446
|
+
const styleRecord = style;
|
|
17447
|
+
for (const key in styleRecord) {
|
|
17448
|
+
if (!Object.hasOwn(styleRecord, key)) continue;
|
|
17449
|
+
const value = styleRecord[key];
|
|
17450
|
+
if (key === "padding" || key === "paddingTop" || key === "paddingRight" || key === "paddingBottom" || key === "paddingLeft") tdStyle[key] = value;
|
|
17451
|
+
else tableStyle[key] = value;
|
|
17452
|
+
}
|
|
17444
17453
|
return /* @__PURE__ */ jsx("table", {
|
|
17445
17454
|
align: "center",
|
|
17446
17455
|
width: "100%",
|
|
@@ -17452,11 +17461,14 @@ const Container = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17452
17461
|
role: "presentation",
|
|
17453
17462
|
style: {
|
|
17454
17463
|
maxWidth: "37.5em",
|
|
17455
|
-
...
|
|
17464
|
+
...tableStyle
|
|
17456
17465
|
},
|
|
17457
17466
|
children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", {
|
|
17458
17467
|
style: { width: "100%" },
|
|
17459
|
-
children: /* @__PURE__ */ jsx("td", {
|
|
17468
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
17469
|
+
style: tdStyle,
|
|
17470
|
+
children
|
|
17471
|
+
})
|
|
17460
17472
|
}) })
|
|
17461
17473
|
});
|
|
17462
17474
|
});
|
|
@@ -17841,7 +17853,7 @@ const Markdown = React$1.forwardRef(({ children, markdownContainerStyles, markdo
|
|
|
17841
17853
|
Markdown.displayName = "Markdown";
|
|
17842
17854
|
//#endregion
|
|
17843
17855
|
//#region src/components/preview/preview.tsx
|
|
17844
|
-
const PREVIEW_MAX_LENGTH =
|
|
17856
|
+
const PREVIEW_MAX_LENGTH = 200;
|
|
17845
17857
|
const Preview = React$1.forwardRef(({ children = "", ...props }, ref) => {
|
|
17846
17858
|
const text = (Array.isArray(children) ? children.join("") : children).substring(0, PREVIEW_MAX_LENGTH);
|
|
17847
17859
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -17890,7 +17902,16 @@ const Row = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17890
17902
|
Row.displayName = "Row";
|
|
17891
17903
|
//#endregion
|
|
17892
17904
|
//#region src/components/section/section.tsx
|
|
17893
|
-
const Section = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
17905
|
+
const Section = React$1.forwardRef(({ children, style = {}, ...props }, ref) => {
|
|
17906
|
+
const tdStyle = {};
|
|
17907
|
+
const tableStyle = {};
|
|
17908
|
+
const styleRecord = style;
|
|
17909
|
+
for (const key in styleRecord) {
|
|
17910
|
+
if (!Object.hasOwn(styleRecord, key)) continue;
|
|
17911
|
+
const value = styleRecord[key];
|
|
17912
|
+
if (key === "padding" || key === "paddingTop" || key === "paddingRight" || key === "paddingBottom" || key === "paddingLeft") tdStyle[key] = value;
|
|
17913
|
+
else tableStyle[key] = value;
|
|
17914
|
+
}
|
|
17894
17915
|
return /* @__PURE__ */ jsx("table", {
|
|
17895
17916
|
align: "center",
|
|
17896
17917
|
width: "100%",
|
|
@@ -17900,8 +17921,11 @@ const Section = React$1.forwardRef(({ children, style, ...props }, ref) => {
|
|
|
17900
17921
|
role: "presentation",
|
|
17901
17922
|
...props,
|
|
17902
17923
|
ref,
|
|
17903
|
-
style,
|
|
17904
|
-
children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
17924
|
+
style: tableStyle,
|
|
17925
|
+
children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
17926
|
+
style: tdStyle,
|
|
17927
|
+
children
|
|
17928
|
+
}) }) })
|
|
17905
17929
|
});
|
|
17906
17930
|
});
|
|
17907
17931
|
Section.displayName = "Section";
|
package/package.json
CHANGED
|
@@ -3,7 +3,35 @@ import * as React from 'react';
|
|
|
3
3
|
export type ContainerProps = Readonly<React.ComponentPropsWithoutRef<'table'>>;
|
|
4
4
|
|
|
5
5
|
export const Container = React.forwardRef<HTMLTableElement, ContainerProps>(
|
|
6
|
-
({ children, style, ...props }, ref) => {
|
|
6
|
+
({ children, style = {}, ...props }, ref) => {
|
|
7
|
+
// Split padding styles to improve compatibility with Klaviyo and Outlook,
|
|
8
|
+
// while preserving user-provided style property order without allocating
|
|
9
|
+
// entry arrays on each render.
|
|
10
|
+
const tdStyle: React.CSSProperties = {};
|
|
11
|
+
const tableStyle: React.CSSProperties = {};
|
|
12
|
+
|
|
13
|
+
const styleRecord = style as Record<string, unknown>;
|
|
14
|
+
|
|
15
|
+
for (const key in styleRecord) {
|
|
16
|
+
if (!Object.hasOwn(styleRecord, key)) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const value = styleRecord[key];
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
key === 'padding' ||
|
|
24
|
+
key === 'paddingTop' ||
|
|
25
|
+
key === 'paddingRight' ||
|
|
26
|
+
key === 'paddingBottom' ||
|
|
27
|
+
key === 'paddingLeft'
|
|
28
|
+
) {
|
|
29
|
+
(tdStyle as Record<string, unknown>)[key] = value;
|
|
30
|
+
} else {
|
|
31
|
+
(tableStyle as Record<string, unknown>)[key] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
7
35
|
return (
|
|
8
36
|
<table
|
|
9
37
|
align="center"
|
|
@@ -14,11 +42,11 @@ export const Container = React.forwardRef<HTMLTableElement, ContainerProps>(
|
|
|
14
42
|
cellSpacing="0"
|
|
15
43
|
ref={ref}
|
|
16
44
|
role="presentation"
|
|
17
|
-
style={{ maxWidth: '37.5em', ...
|
|
45
|
+
style={{ maxWidth: '37.5em', ...tableStyle }}
|
|
18
46
|
>
|
|
19
47
|
<tbody>
|
|
20
48
|
<tr style={{ width: '100%' }}>
|
|
21
|
-
<td>{children}</td>
|
|
49
|
+
<td style={tdStyle}>{children}</td>
|
|
22
50
|
</tr>
|
|
23
51
|
</tbody>
|
|
24
52
|
</table>
|
|
@@ -5,7 +5,7 @@ describe('<Preview> component', () => {
|
|
|
5
5
|
it('renders correctly', async () => {
|
|
6
6
|
const actualOutput = await render(<Preview>Email preview text</Preview>);
|
|
7
7
|
expect(actualOutput).toMatchInlineSnapshot(
|
|
8
|
-
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">Email preview text<div> </div></div><!--/$-->"`,
|
|
8
|
+
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">Email preview text<div> </div></div><!--/$-->"`,
|
|
9
9
|
);
|
|
10
10
|
});
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ describe('<Preview> component', () => {
|
|
|
14
14
|
<Preview>Email preview text</Preview>,
|
|
15
15
|
);
|
|
16
16
|
expect(actualOutputArray).toMatchInlineSnapshot(
|
|
17
|
-
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">Email preview text<div> </div></div><!--/$-->"`,
|
|
17
|
+
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">Email preview text<div> </div></div><!--/$-->"`,
|
|
18
18
|
);
|
|
19
19
|
});
|
|
20
20
|
|
|
@@ -22,15 +22,15 @@ describe('<Preview> component', () => {
|
|
|
22
22
|
const longText = 'really long'.repeat(100);
|
|
23
23
|
const actualOutputLong = await render(<Preview>{longText}</Preview>);
|
|
24
24
|
expect(actualOutputLong).toMatchInlineSnapshot(
|
|
25
|
-
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">really longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally </div><!--/$-->"`,
|
|
25
|
+
`"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">really longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longreally longre</div><!--/$-->"`,
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
describe('renderWhiteSpace', () => {
|
|
31
|
-
it('renders null when text length is greater than or equal to PREVIEW_MAX_LENGTH (
|
|
31
|
+
it('renders null when text length is greater than or equal to PREVIEW_MAX_LENGTH (200)', () => {
|
|
32
32
|
const text =
|
|
33
|
-
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Tenetur dolore mollitia dignissimos itaque. At excepturi reiciendis iure molestias incidunt. Ab saepe, nostrum dicta dolor maiores tenetur eveniet odio amet ipsum?';
|
|
33
|
+
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Tenetur dolore mollitia dignissimos itaque. At excepturi reiciendis iure molestias incidunt. Ab saepe, nostrum dicta dolor maiores tenetur eveniet odio amet ipsum? Lorem ipsum extra.';
|
|
34
34
|
const html = renderWhiteSpace(text);
|
|
35
35
|
expect(html).toBeNull();
|
|
36
36
|
});
|
|
@@ -43,7 +43,7 @@ describe('renderWhiteSpace', () => {
|
|
|
43
43
|
expect(html).not.toBeNull();
|
|
44
44
|
|
|
45
45
|
const actualTextContent = html?.props.children;
|
|
46
|
-
const expectedTextContent = whiteSpaceCharacters.repeat(
|
|
46
|
+
const expectedTextContent = whiteSpaceCharacters.repeat(200 - text.length);
|
|
47
47
|
expect(actualTextContent).toBe(expectedTextContent);
|
|
48
48
|
});
|
|
49
49
|
});
|
|
@@ -3,7 +3,35 @@ import * as React from 'react';
|
|
|
3
3
|
export type SectionProps = Readonly<React.ComponentPropsWithoutRef<'table'>>;
|
|
4
4
|
|
|
5
5
|
export const Section = React.forwardRef<HTMLTableElement, SectionProps>(
|
|
6
|
-
({ children, style, ...props }, ref) => {
|
|
6
|
+
({ children, style = {}, ...props }, ref) => {
|
|
7
|
+
// Split padding styles to improve compatibility with Klaviyo and Outlook,
|
|
8
|
+
// while preserving user-provided style property order without allocating
|
|
9
|
+
// entry arrays on each render.
|
|
10
|
+
const tdStyle: React.CSSProperties = {};
|
|
11
|
+
const tableStyle: React.CSSProperties = {};
|
|
12
|
+
|
|
13
|
+
const styleRecord = style as Record<string, unknown>;
|
|
14
|
+
|
|
15
|
+
for (const key in styleRecord) {
|
|
16
|
+
if (!Object.hasOwn(styleRecord, key)) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const value = styleRecord[key];
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
key === 'padding' ||
|
|
24
|
+
key === 'paddingTop' ||
|
|
25
|
+
key === 'paddingRight' ||
|
|
26
|
+
key === 'paddingBottom' ||
|
|
27
|
+
key === 'paddingLeft'
|
|
28
|
+
) {
|
|
29
|
+
(tdStyle as Record<string, unknown>)[key] = value;
|
|
30
|
+
} else {
|
|
31
|
+
(tableStyle as Record<string, unknown>)[key] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
7
35
|
return (
|
|
8
36
|
<table
|
|
9
37
|
align="center"
|
|
@@ -14,11 +42,11 @@ export const Section = React.forwardRef<HTMLTableElement, SectionProps>(
|
|
|
14
42
|
role="presentation"
|
|
15
43
|
{...props}
|
|
16
44
|
ref={ref}
|
|
17
|
-
style={
|
|
45
|
+
style={tableStyle}
|
|
18
46
|
>
|
|
19
47
|
<tbody>
|
|
20
48
|
<tr>
|
|
21
|
-
<td>{children}</td>
|
|
49
|
+
<td style={tdStyle}>{children}</td>
|
|
22
50
|
</tr>
|
|
23
51
|
</tbody>
|
|
24
52
|
</table>
|