Skip to content

Commit 50b1914

Browse files
committed
Merge branch 'main' into feat/vs-code-preview-ext
2 parents 6c0a6e5 + c73dcb0 commit 50b1914

File tree

10 files changed

+138
-427
lines changed

10 files changed

+138
-427
lines changed

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@react-email/render": "0.0.7",
2525
"classnames": "2.3.2",
2626
"framer-motion": "8.5.5",
27-
"next": "13.4.10",
27+
"next": "13.5.0",
2828
"prism-react-renderer": "1.3.5",
2929
"react": "18.2.0",
3030
"react-dom": "18.2.0"

docs/changelog.mdx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,19 @@ title: "Changelog"
33
sidebarTitle: "Changelog"
44
description: "New features, bug fixes, and improvements made to each package."
55
"og:image": "https://react.email/static/covers/react-email.png"
6-
icon: 'list-check'
6+
icon: "list-check"
77
---
88

9+
## Nov 01, 2023
10+
11+
**Components `0.0.11`**
12+
13+
- Upgrade `@react-email/render` to `v0.0.9`
14+
15+
**Render `0.0.9`**
16+
17+
- Fix `renderAsync` function to support Next.js 14
18+
919
## April 05. 2023
1020

1121
**Button `0.0.8`**

examples/resend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"start": "next start"
1111
},
1212
"dependencies": {
13-
"next": "13.4.4",
13+
"next": "13.5.0",
1414
"react": "18.2.0",
1515
"react-dom": "18.2.0",
1616
"resend": "0.15.1"

examples/scaleway/next/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@react-email/components": "0.0.4",
1414
"@react-email/render": "0.0.6",
1515
"@scaleway/sdk": "1.5.0",
16-
"next": "13.2.3",
16+
"next": "13.5.0",
1717
"react": "18.2.0",
1818
"react-dom": "18.2.0"
1919
},

packages/components/package.json

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@react-email/components",
3-
"version": "0.0.7",
3+
"version": "0.0.11",
44
"description": "All react-email components",
55
"sideEffects": false,
66
"main": "./dist/index.js",
@@ -41,23 +41,23 @@
4141
"node": ">=18.0.0"
4242
},
4343
"dependencies": {
44-
"@react-email/body": "0.0.2",
45-
"@react-email/button": "0.0.9",
46-
"@react-email/column": "0.0.7",
47-
"@react-email/container": "0.0.8",
48-
"@react-email/font": "0.0.2",
49-
"@react-email/head": "0.0.5",
50-
"@react-email/heading": "0.0.8",
51-
"@react-email/hr": "0.0.5",
52-
"@react-email/html": "0.0.4",
53-
"@react-email/img": "0.0.5",
54-
"@react-email/link": "0.0.5",
55-
"@react-email/preview": "0.0.6",
56-
"@react-email/render": "0.0.7",
57-
"@react-email/row": "0.0.5",
58-
"@react-email/section": "0.0.9",
59-
"@react-email/tailwind": "0.0.8",
60-
"@react-email/text": "0.0.5"
44+
"@react-email/body": "0.0.4",
45+
"@react-email/button": "0.0.11",
46+
"@react-email/column": "0.0.8",
47+
"@react-email/container": "0.0.10",
48+
"@react-email/font": "0.0.4",
49+
"@react-email/head": "0.0.6",
50+
"@react-email/heading": "0.0.9",
51+
"@react-email/hr": "0.0.6",
52+
"@react-email/html": "0.0.6",
53+
"@react-email/img": "0.0.6",
54+
"@react-email/link": "0.0.6",
55+
"@react-email/preview": "0.0.7",
56+
"@react-email/render": "0.0.9",
57+
"@react-email/row": "0.0.6",
58+
"@react-email/section": "0.0.10",
59+
"@react-email/tailwind": "0.0.12",
60+
"@react-email/text": "0.0.6"
6161
},
6262
"peerDependencies": {
6363
"react": "18.2.0"

packages/render/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@react-email/render",
3-
"version": "0.0.8",
3+
"version": "0.0.9",
44
"description": "Transform React components into HTML email templates",
55
"sideEffects": false,
66
"main": "./dist/index.js",

packages/render/src/render-async.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe("renderAsync using renderToStaticMarkup", () => {
77
const actualOutput = await renderAsync(<Template firstName="Jim" />);
88

99
expect(actualOutput).toMatchInlineSnapshot(
10-
'"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><h1>Welcome, Jim!</h1><img alt=\\"test\\" src=\\"img/test.png\\"/><p>Thanks for trying our product. We&#x27;re thrilled to have you on board!</p>"',
10+
'"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><h1>Welcome, <!-- -->Jim<!-- -->!</h1><img alt=\\"test\\" src=\\"img/test.png\\"/><p>Thanks for trying our product. We&#x27;re thrilled to have you on board!</p>"',
1111
);
1212
});
1313

@@ -39,7 +39,7 @@ describe("renderAsync using renderToReadableStream", () => {
3939
const actualOutput = await renderAsync(<Template firstName="Jim" />);
4040

4141
expect(actualOutput).toMatchInlineSnapshot(
42-
'"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><h1>Welcome, Jim!</h1><img alt=\\"test\\" src=\\"img/test.png\\"/><p>Thanks for trying our product. We&#x27;re thrilled to have you on board!</p>"',
42+
'"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><h1>Welcome, <!-- -->Jim<!-- -->!</h1><img alt=\\"test\\" src=\\"img/test.png\\"/><p>Thanks for trying our product. We&#x27;re thrilled to have you on board!</p>"',
4343
);
4444
});
4545

packages/render/src/render-async.ts

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,26 @@
1-
import { type ReadableStream } from "node:stream/web";
1+
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
22
import { convert } from "html-to-text";
33
import pretty from "pretty";
4-
import { type ReactNode } from "react";
5-
import react from "react-dom/server";
6-
7-
const { renderToStaticMarkup } = react;
8-
9-
// Note: only available in platforms that support WebStreams
10-
// https://react.dev/reference/react-dom/server/renderToString#alternatives
11-
const renderToStream =
12-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
13-
react.renderToReadableStream || react.renderToPipeableStream;
14-
15-
export default async function renderToString(children: ReactNode) {
16-
const stream = await renderToStream(children);
17-
18-
const html = await readableStreamToString(
19-
// ReactDOMServerReadableStream behaves like ReadableStream
20-
// in modern edge runtimes but the types are not compatible
21-
stream as unknown as ReadableStream<Uint8Array>,
22-
);
23-
24-
return (
25-
html
26-
// Remove leading doctype becuase we add it manually
27-
.replace(/^<!DOCTYPE html>/, "")
28-
// Remove empty comments to match the output of renderToStaticMarkup
29-
.replace(/<!-- -->/g, "")
30-
);
31-
}
32-
33-
async function readableStreamToString(
34-
readableStream: ReadableStream<Uint8Array>,
35-
) {
36-
let result = "";
37-
38-
const decoder = new TextDecoder();
39-
40-
for await (const chunk of readableStream) {
41-
result += decoder.decode(chunk);
4+
import type { ReactDOMServerReadableStream } from "react-dom/server";
5+
6+
const readStream = async (readableStream: ReactDOMServerReadableStream) => {
7+
const reader = readableStream.getReader();
8+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9+
const chunks: any[] = [];
10+
11+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, no-constant-condition
12+
while (true) {
13+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, no-await-in-loop
14+
const { value, done } = await reader.read();
15+
if (done) {
16+
break;
17+
}
18+
chunks.push(value);
4219
}
4320

44-
return result;
45-
}
21+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
22+
return chunks.map((chunk) => new TextDecoder("utf-8").decode(chunk)).join("");
23+
};
4624

4725
export const renderAsync = async (
4826
component: React.ReactElement,
@@ -51,24 +29,31 @@ export const renderAsync = async (
5129
plainText?: boolean;
5230
},
5331
) => {
54-
const markup =
55-
typeof renderToStaticMarkup === "undefined"
56-
? await renderToString(component)
57-
: renderToStaticMarkup(component);
32+
const reactDOMServer = (await import("react-dom/server")).default;
33+
const renderToStream =
34+
reactDOMServer.renderToReadableStream ||
35+
reactDOMServer.renderToString ||
36+
reactDOMServer.renderToPipeableStream;
37+
38+
const doctype =
39+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
40+
41+
const readableStream = await renderToStream(component);
42+
const html =
43+
typeof readableStream === "string"
44+
? readableStream
45+
: await readStream(readableStream);
5846

5947
if (options?.plainText) {
60-
return convert(markup, {
48+
return convert(html, {
6149
selectors: [
6250
{ selector: "img", format: "skip" },
6351
{ selector: "#__react-email-preview", format: "skip" },
6452
],
6553
});
6654
}
6755

68-
const doctype =
69-
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
70-
71-
const document = `${doctype}${markup}`;
56+
const document = `${doctype}${html}`;
7257

7358
if (options?.pretty) {
7459
return pretty(document);

packages/tailwind/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@react-email/tailwind",
3-
"version": "0.0.11",
3+
"version": "0.0.12",
44
"description": "A React component to wrap emails with Tailwind CSS",
55
"sideEffects": false,
66
"main": "./dist/index.js",
@@ -46,7 +46,7 @@
4646
"dependencies": {
4747
"react": "18.2.0",
4848
"react-dom": "18.2.0",
49-
"tw-to-css": "0.0.11"
49+
"tw-to-css": "0.0.12"
5050
},
5151
"peerDependencies": {
5252
"react": "18.2.0"

0 commit comments

Comments
 (0)