@react-email/render 2.0.7-canary.0 → 2.0.8
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/dist/browser/index.cjs +9 -19
- package/dist/browser/index.d.cts.map +1 -1
- package/dist/browser/index.d.mts.map +1 -1
- package/dist/browser/index.mjs +6 -11
- package/dist/browser/index.mjs.map +1 -1
- package/dist/edge/index.cjs +9 -20
- package/dist/edge/index.d.cts.map +1 -1
- package/dist/edge/index.d.mts.map +1 -1
- package/dist/edge/index.mjs +6 -12
- package/dist/edge/index.mjs.map +1 -1
- package/dist/node/index.cjs +12 -20
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.mts.map +1 -1
- package/dist/node/index.mjs +10 -13
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -6,16 +7,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
9
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
19
16
|
}
|
|
20
17
|
return to;
|
|
21
18
|
};
|
|
@@ -23,7 +20,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
20
|
value: mod,
|
|
24
21
|
enumerable: true
|
|
25
22
|
}) : target, mod));
|
|
26
|
-
|
|
27
23
|
//#endregion
|
|
28
24
|
let prettier_plugins_html = require("prettier/plugins/html");
|
|
29
25
|
prettier_plugins_html = __toESM(prettier_plugins_html);
|
|
@@ -32,7 +28,6 @@ let html_to_text = require("html-to-text");
|
|
|
32
28
|
let react = require("react");
|
|
33
29
|
react = __toESM(react);
|
|
34
30
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
-
|
|
36
31
|
//#region src/shared/utils/pretty.ts
|
|
37
32
|
function getHtmlNode(path) {
|
|
38
33
|
const topNode = path.node;
|
|
@@ -93,7 +88,6 @@ const pretty = (str, options = {}) => {
|
|
|
93
88
|
...options
|
|
94
89
|
});
|
|
95
90
|
};
|
|
96
|
-
|
|
97
91
|
//#endregion
|
|
98
92
|
//#region src/shared/utils/to-plain-text.ts
|
|
99
93
|
const plainTextSelectors = [
|
|
@@ -120,7 +114,6 @@ function toPlainText(html, options) {
|
|
|
120
114
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
121
115
|
});
|
|
122
116
|
}
|
|
123
|
-
|
|
124
117
|
//#endregion
|
|
125
118
|
//#region src/shared/error-boundary.tsx
|
|
126
119
|
function createErrorBoundary(reject) {
|
|
@@ -134,7 +127,6 @@ function createErrorBoundary(reject) {
|
|
|
134
127
|
}
|
|
135
128
|
};
|
|
136
129
|
}
|
|
137
|
-
|
|
138
130
|
//#endregion
|
|
139
131
|
//#region src/shared/read-stream.browser.ts
|
|
140
132
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -161,7 +153,6 @@ const readStream = async (stream) => {
|
|
|
161
153
|
});
|
|
162
154
|
return decoder.decode(mergedChunks);
|
|
163
155
|
};
|
|
164
|
-
|
|
165
156
|
//#endregion
|
|
166
157
|
//#region src/browser/render.tsx
|
|
167
158
|
const render = async (node, options) => {
|
|
@@ -186,9 +177,8 @@ const render = async (node, options) => {
|
|
|
186
177
|
if (options?.pretty) return pretty(document);
|
|
187
178
|
return document;
|
|
188
179
|
};
|
|
189
|
-
|
|
190
180
|
//#endregion
|
|
191
181
|
exports.plainTextSelectors = plainTextSelectors;
|
|
192
182
|
exports.pretty = pretty;
|
|
193
183
|
exports.render = render;
|
|
194
|
-
exports.toPlainText = toPlainText;
|
|
184
|
+
exports.toPlainText = toPlainText;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/browser/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/browser/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCTvC,MAAA,GAAgB,IAAA,EAAM,KAAA,CAAM,SAAA,EAAW,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/browser/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/browser/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCTvC,MAAA,GAAgB,IAAA,EAAM,KAAA,CAAM,SAAA,EAAW,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
package/dist/browser/index.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { format } from "prettier/standalone";
|
|
|
3
3
|
import { convert } from "html-to-text";
|
|
4
4
|
import React, { Suspense } from "react";
|
|
5
5
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
6
|
-
|
|
7
6
|
//#region src/shared/utils/pretty.ts
|
|
8
7
|
function getHtmlNode(path) {
|
|
9
8
|
const topNode = path.node;
|
|
@@ -64,7 +63,6 @@ const pretty = (str, options = {}) => {
|
|
|
64
63
|
...options
|
|
65
64
|
});
|
|
66
65
|
};
|
|
67
|
-
|
|
68
66
|
//#endregion
|
|
69
67
|
//#region src/shared/utils/to-plain-text.ts
|
|
70
68
|
const plainTextSelectors = [
|
|
@@ -84,14 +82,13 @@ const plainTextSelectors = [
|
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
];
|
|
87
|
-
function toPlainText(html
|
|
88
|
-
return convert(html
|
|
85
|
+
function toPlainText(html, options) {
|
|
86
|
+
return convert(html, {
|
|
89
87
|
wordwrap: false,
|
|
90
88
|
...options,
|
|
91
89
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
92
90
|
});
|
|
93
91
|
}
|
|
94
|
-
|
|
95
92
|
//#endregion
|
|
96
93
|
//#region src/shared/error-boundary.tsx
|
|
97
94
|
function createErrorBoundary(reject) {
|
|
@@ -105,7 +102,6 @@ function createErrorBoundary(reject) {
|
|
|
105
102
|
}
|
|
106
103
|
};
|
|
107
104
|
}
|
|
108
|
-
|
|
109
105
|
//#endregion
|
|
110
106
|
//#region src/shared/read-stream.browser.ts
|
|
111
107
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -132,7 +128,6 @@ const readStream = async (stream) => {
|
|
|
132
128
|
});
|
|
133
129
|
return decoder.decode(mergedChunks);
|
|
134
130
|
};
|
|
135
|
-
|
|
136
131
|
//#endregion
|
|
137
132
|
//#region src/browser/render.tsx
|
|
138
133
|
const render = async (node, options) => {
|
|
@@ -140,7 +135,7 @@ const render = async (node, options) => {
|
|
|
140
135
|
if ("default" in m) return m.default;
|
|
141
136
|
return m;
|
|
142
137
|
});
|
|
143
|
-
const html
|
|
138
|
+
const html = await new Promise((resolve, reject) => {
|
|
144
139
|
const ErrorBoundary = createErrorBoundary(reject);
|
|
145
140
|
reactDOMServer.renderToReadableStream(/* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(ErrorBoundary, { children: node }) }), {
|
|
146
141
|
onError(error) {
|
|
@@ -152,12 +147,12 @@ const render = async (node, options) => {
|
|
|
152
147
|
return readStream(stream);
|
|
153
148
|
}).then(resolve).catch(reject);
|
|
154
149
|
});
|
|
155
|
-
if (options?.plainText) return toPlainText(html
|
|
156
|
-
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html
|
|
150
|
+
if (options?.plainText) return toPlainText(html, options.htmlToTextOptions);
|
|
151
|
+
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html.replace(/<!DOCTYPE.*?>/, "")}`;
|
|
157
152
|
if (options?.pretty) return pretty(document);
|
|
158
153
|
return document;
|
|
159
154
|
};
|
|
160
|
-
|
|
161
155
|
//#endregion
|
|
162
156
|
export { plainTextSelectors, pretty, render, toPlainText };
|
|
157
|
+
|
|
163
158
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["html","html"],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/shared/read-stream.browser.ts","../../src/browser/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import type { ReactDOMServerReadableStream } from 'react-dom/server.browser';\n\nconst decoder = new TextDecoder('utf-8');\n\nexport const readStream = async (stream: ReactDOMServerReadableStream) => {\n const chunks: Uint8Array[] = [];\n\n const writableStream = new WritableStream({\n write(chunk: Uint8Array) {\n chunks.push(chunk);\n },\n abort(reason) {\n throw new Error('Stream aborted', {\n cause: {\n reason,\n },\n });\n },\n });\n await stream.pipeTo(writableStream);\n\n let length = 0;\n chunks.forEach((item) => {\n length += item.length;\n });\n const mergedChunks = new Uint8Array(length);\n let offset = 0;\n chunks.forEach((item) => {\n mergedChunks.set(item, offset);\n offset += item.length;\n });\n\n return decoder.decode(mergedChunks);\n};\n","import { Suspense } from 'react';\nimport { pretty, toPlainText } from '../node';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { readStream } from '../shared/read-stream.browser';\n\nexport const render = async (node: React.ReactNode, options?: Options) => {\n const reactDOMServer = await import('react-dom/server').then((m) => {\n if ('default' in m) {\n return m.default;\n }\n return m;\n });\n\n const html = await new Promise<string>((resolve, reject) => {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <Suspense>\n <ErrorBoundary>{node}</ErrorBoundary>\n </Suspense>,\n {\n onError(error: unknown) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then(resolve)\n .catch(reject);\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/shared/read-stream.browser.ts","../../src/browser/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import type { ReactDOMServerReadableStream } from 'react-dom/server.browser';\n\nconst decoder = new TextDecoder('utf-8');\n\nexport const readStream = async (stream: ReactDOMServerReadableStream) => {\n const chunks: Uint8Array[] = [];\n\n const writableStream = new WritableStream({\n write(chunk: Uint8Array) {\n chunks.push(chunk);\n },\n abort(reason) {\n throw new Error('Stream aborted', {\n cause: {\n reason,\n },\n });\n },\n });\n await stream.pipeTo(writableStream);\n\n let length = 0;\n chunks.forEach((item) => {\n length += item.length;\n });\n const mergedChunks = new Uint8Array(length);\n let offset = 0;\n chunks.forEach((item) => {\n mergedChunks.set(item, offset);\n offset += item.length;\n });\n\n return decoder.decode(mergedChunks);\n};\n","import { Suspense } from 'react';\nimport { pretty, toPlainText } from '../node';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { readStream } from '../shared/read-stream.browser';\n\nexport const render = async (node: React.ReactNode, options?: Options) => {\n const reactDOMServer = await import('react-dom/server').then((m) => {\n if ('default' in m) {\n return m.default;\n }\n return m;\n });\n\n const html = await new Promise<string>((resolve, reject) => {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <Suspense>\n <ErrorBoundary>{node}</ErrorBoundary>\n </Suspense>,\n {\n onError(error: unknown) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then(resolve)\n .catch(reject);\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|
package/dist/edge/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -6,16 +7,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
9
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
19
16
|
}
|
|
20
17
|
return to;
|
|
21
18
|
};
|
|
@@ -23,7 +20,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
20
|
value: mod,
|
|
24
21
|
enumerable: true
|
|
25
22
|
}) : target, mod));
|
|
26
|
-
|
|
27
23
|
//#endregion
|
|
28
24
|
let prettier_plugins_html = require("prettier/plugins/html");
|
|
29
25
|
prettier_plugins_html = __toESM(prettier_plugins_html);
|
|
@@ -32,7 +28,6 @@ let html_to_text = require("html-to-text");
|
|
|
32
28
|
let react = require("react");
|
|
33
29
|
react = __toESM(react);
|
|
34
30
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
-
|
|
36
31
|
//#region src/shared/utils/pretty.ts
|
|
37
32
|
function getHtmlNode(path) {
|
|
38
33
|
const topNode = path.node;
|
|
@@ -93,7 +88,6 @@ const pretty = (str, options = {}) => {
|
|
|
93
88
|
...options
|
|
94
89
|
});
|
|
95
90
|
};
|
|
96
|
-
|
|
97
91
|
//#endregion
|
|
98
92
|
//#region src/shared/utils/to-plain-text.ts
|
|
99
93
|
const plainTextSelectors = [
|
|
@@ -120,7 +114,6 @@ function toPlainText(html, options) {
|
|
|
120
114
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
121
115
|
});
|
|
122
116
|
}
|
|
123
|
-
|
|
124
117
|
//#endregion
|
|
125
118
|
//#region src/shared/error-boundary.tsx
|
|
126
119
|
function createErrorBoundary(reject) {
|
|
@@ -134,7 +127,6 @@ function createErrorBoundary(reject) {
|
|
|
134
127
|
}
|
|
135
128
|
};
|
|
136
129
|
}
|
|
137
|
-
|
|
138
130
|
//#endregion
|
|
139
131
|
//#region src/shared/read-stream.browser.ts
|
|
140
132
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -161,13 +153,11 @@ const readStream = async (stream) => {
|
|
|
161
153
|
});
|
|
162
154
|
return decoder.decode(mergedChunks);
|
|
163
155
|
};
|
|
164
|
-
|
|
165
156
|
//#endregion
|
|
166
157
|
//#region src/edge/import-react-dom.tsx
|
|
167
158
|
const importReactDom = () => {
|
|
168
159
|
return import("react-dom/server.edge").catch(() => import("react-dom/server"));
|
|
169
160
|
};
|
|
170
|
-
|
|
171
161
|
//#endregion
|
|
172
162
|
//#region src/edge/render.tsx
|
|
173
163
|
const render = async (element, options) => {
|
|
@@ -192,9 +182,8 @@ const render = async (element, options) => {
|
|
|
192
182
|
if (options?.pretty) return pretty(document);
|
|
193
183
|
return document;
|
|
194
184
|
};
|
|
195
|
-
|
|
196
185
|
//#endregion
|
|
197
186
|
exports.plainTextSelectors = plainTextSelectors;
|
|
198
187
|
exports.pretty = pretty;
|
|
199
188
|
exports.render = render;
|
|
200
|
-
exports.toPlainText = toPlainText;
|
|
189
|
+
exports.toPlainText = toPlainText;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/edge/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/edge/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCPvC,MAAA,GACX,OAAA,EAAS,KAAA,CAAM,YAAA,EACf,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/edge/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/edge/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCPvC,MAAA,GACX,OAAA,EAAS,KAAA,CAAM,YAAA,EACf,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
package/dist/edge/index.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { format } from "prettier/standalone";
|
|
|
3
3
|
import { convert } from "html-to-text";
|
|
4
4
|
import React, { Suspense } from "react";
|
|
5
5
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
6
|
-
|
|
7
6
|
//#region src/shared/utils/pretty.ts
|
|
8
7
|
function getHtmlNode(path) {
|
|
9
8
|
const topNode = path.node;
|
|
@@ -64,7 +63,6 @@ const pretty = (str, options = {}) => {
|
|
|
64
63
|
...options
|
|
65
64
|
});
|
|
66
65
|
};
|
|
67
|
-
|
|
68
66
|
//#endregion
|
|
69
67
|
//#region src/shared/utils/to-plain-text.ts
|
|
70
68
|
const plainTextSelectors = [
|
|
@@ -84,14 +82,13 @@ const plainTextSelectors = [
|
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
];
|
|
87
|
-
function toPlainText(html
|
|
88
|
-
return convert(html
|
|
85
|
+
function toPlainText(html, options) {
|
|
86
|
+
return convert(html, {
|
|
89
87
|
wordwrap: false,
|
|
90
88
|
...options,
|
|
91
89
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
92
90
|
});
|
|
93
91
|
}
|
|
94
|
-
|
|
95
92
|
//#endregion
|
|
96
93
|
//#region src/shared/error-boundary.tsx
|
|
97
94
|
function createErrorBoundary(reject) {
|
|
@@ -105,7 +102,6 @@ function createErrorBoundary(reject) {
|
|
|
105
102
|
}
|
|
106
103
|
};
|
|
107
104
|
}
|
|
108
|
-
|
|
109
105
|
//#endregion
|
|
110
106
|
//#region src/shared/read-stream.browser.ts
|
|
111
107
|
const decoder = new TextDecoder("utf-8");
|
|
@@ -132,13 +128,11 @@ const readStream = async (stream) => {
|
|
|
132
128
|
});
|
|
133
129
|
return decoder.decode(mergedChunks);
|
|
134
130
|
};
|
|
135
|
-
|
|
136
131
|
//#endregion
|
|
137
132
|
//#region src/edge/import-react-dom.tsx
|
|
138
133
|
const importReactDom = () => {
|
|
139
134
|
return import("react-dom/server.edge").catch(() => import("react-dom/server"));
|
|
140
135
|
};
|
|
141
|
-
|
|
142
136
|
//#endregion
|
|
143
137
|
//#region src/edge/render.tsx
|
|
144
138
|
const render = async (element, options) => {
|
|
@@ -146,7 +140,7 @@ const render = async (element, options) => {
|
|
|
146
140
|
if ("default" in m) return m.default;
|
|
147
141
|
return m;
|
|
148
142
|
});
|
|
149
|
-
const html
|
|
143
|
+
const html = await new Promise((resolve, reject) => {
|
|
150
144
|
const ErrorBoundary = createErrorBoundary(reject);
|
|
151
145
|
reactDOMServer.renderToReadableStream(/* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(Suspense, { children: element }) }), {
|
|
152
146
|
onError(error) {
|
|
@@ -158,12 +152,12 @@ const render = async (element, options) => {
|
|
|
158
152
|
return readStream(stream);
|
|
159
153
|
}).then(resolve).catch(reject);
|
|
160
154
|
});
|
|
161
|
-
if (options?.plainText) return toPlainText(html
|
|
162
|
-
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html
|
|
155
|
+
if (options?.plainText) return toPlainText(html, options.htmlToTextOptions);
|
|
156
|
+
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html.replace(/<!DOCTYPE.*?>/, "")}`;
|
|
163
157
|
if (options?.pretty) return pretty(document);
|
|
164
158
|
return document;
|
|
165
159
|
};
|
|
166
|
-
|
|
167
160
|
//#endregion
|
|
168
161
|
export { plainTextSelectors, pretty, render, toPlainText };
|
|
162
|
+
|
|
169
163
|
//# sourceMappingURL=index.mjs.map
|
package/dist/edge/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["html","html"],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/shared/read-stream.browser.ts","../../src/edge/import-react-dom.tsx","../../src/edge/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import type { ReactDOMServerReadableStream } from 'react-dom/server.browser';\n\nconst decoder = new TextDecoder('utf-8');\n\nexport const readStream = async (stream: ReactDOMServerReadableStream) => {\n const chunks: Uint8Array[] = [];\n\n const writableStream = new WritableStream({\n write(chunk: Uint8Array) {\n chunks.push(chunk);\n },\n abort(reason) {\n throw new Error('Stream aborted', {\n cause: {\n reason,\n },\n });\n },\n });\n await stream.pipeTo(writableStream);\n\n let length = 0;\n chunks.forEach((item) => {\n length += item.length;\n });\n const mergedChunks = new Uint8Array(length);\n let offset = 0;\n chunks.forEach((item) => {\n mergedChunks.set(item, offset);\n offset += item.length;\n });\n\n return decoder.decode(mergedChunks);\n};\n","export const importReactDom = () => {\n // We don't use async here because tsup converts it to a generator syntax\n // that esbuild doesn't understand as dealing with the import failing during\n // bundling: https://github.com/evanw/esbuild/issues/3216#issuecomment-1628913722\n return import('react-dom/server.edge').catch(\n () =>\n // This ensures that we still have compatibility with React 18,\n // which doesn't have the `.edge` export.\n import('react-dom/server'),\n );\n};\n","import { Suspense } from 'react';\nimport { pretty } from '../node';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { readStream } from '../shared/read-stream.browser';\nimport { toPlainText } from '../shared/utils/to-plain-text';\nimport { importReactDom } from './import-react-dom';\n\nexport const render = async (\n element: React.ReactElement,\n options?: Options,\n) => {\n const reactDOMServer = await importReactDom().then((m) => {\n if ('default' in m) {\n return m.default;\n }\n\n return m;\n });\n\n const html = await new Promise<string>((resolve, reject) => {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <ErrorBoundary>\n <Suspense>{element}</Suspense>\n </ErrorBoundary>,\n {\n onError(error: unknown) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then(resolve)\n .catch(reject);\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/shared/read-stream.browser.ts","../../src/edge/import-react-dom.tsx","../../src/edge/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import type { ReactDOMServerReadableStream } from 'react-dom/server.browser';\n\nconst decoder = new TextDecoder('utf-8');\n\nexport const readStream = async (stream: ReactDOMServerReadableStream) => {\n const chunks: Uint8Array[] = [];\n\n const writableStream = new WritableStream({\n write(chunk: Uint8Array) {\n chunks.push(chunk);\n },\n abort(reason) {\n throw new Error('Stream aborted', {\n cause: {\n reason,\n },\n });\n },\n });\n await stream.pipeTo(writableStream);\n\n let length = 0;\n chunks.forEach((item) => {\n length += item.length;\n });\n const mergedChunks = new Uint8Array(length);\n let offset = 0;\n chunks.forEach((item) => {\n mergedChunks.set(item, offset);\n offset += item.length;\n });\n\n return decoder.decode(mergedChunks);\n};\n","export const importReactDom = () => {\n // We don't use async here because tsup converts it to a generator syntax\n // that esbuild doesn't understand as dealing with the import failing during\n // bundling: https://github.com/evanw/esbuild/issues/3216#issuecomment-1628913722\n return import('react-dom/server.edge').catch(\n () =>\n // This ensures that we still have compatibility with React 18,\n // which doesn't have the `.edge` export.\n import('react-dom/server'),\n );\n};\n","import { Suspense } from 'react';\nimport { pretty } from '../node';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { readStream } from '../shared/read-stream.browser';\nimport { toPlainText } from '../shared/utils/to-plain-text';\nimport { importReactDom } from './import-react-dom';\n\nexport const render = async (\n element: React.ReactElement,\n options?: Options,\n) => {\n const reactDOMServer = await importReactDom().then((m) => {\n if ('default' in m) {\n return m.default;\n }\n\n return m;\n });\n\n const html = await new Promise<string>((resolve, reject) => {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <ErrorBoundary>\n <Suspense>{element}</Suspense>\n </ErrorBoundary>,\n {\n onError(error: unknown) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then(resolve)\n .catch(reject);\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|
package/dist/node/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -6,16 +7,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
9
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
19
16
|
}
|
|
20
17
|
return to;
|
|
21
18
|
};
|
|
@@ -23,7 +20,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
20
|
value: mod,
|
|
24
21
|
enumerable: true
|
|
25
22
|
}) : target, mod));
|
|
26
|
-
|
|
27
23
|
//#endregion
|
|
28
24
|
let prettier_plugins_html = require("prettier/plugins/html");
|
|
29
25
|
prettier_plugins_html = __toESM(prettier_plugins_html);
|
|
@@ -33,7 +29,6 @@ let react = require("react");
|
|
|
33
29
|
react = __toESM(react);
|
|
34
30
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
35
31
|
let node_stream = require("node:stream");
|
|
36
|
-
|
|
37
32
|
//#region src/shared/utils/pretty.ts
|
|
38
33
|
function getHtmlNode(path) {
|
|
39
34
|
const topNode = path.node;
|
|
@@ -94,7 +89,6 @@ const pretty = (str, options = {}) => {
|
|
|
94
89
|
...options
|
|
95
90
|
});
|
|
96
91
|
};
|
|
97
|
-
|
|
98
92
|
//#endregion
|
|
99
93
|
//#region src/shared/utils/to-plain-text.ts
|
|
100
94
|
const plainTextSelectors = [
|
|
@@ -121,7 +115,6 @@ function toPlainText(html, options) {
|
|
|
121
115
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
122
116
|
});
|
|
123
117
|
}
|
|
124
|
-
|
|
125
118
|
//#endregion
|
|
126
119
|
//#region src/shared/error-boundary.tsx
|
|
127
120
|
function createErrorBoundary(reject) {
|
|
@@ -135,7 +128,6 @@ function createErrorBoundary(reject) {
|
|
|
135
128
|
}
|
|
136
129
|
};
|
|
137
130
|
}
|
|
138
|
-
|
|
139
131
|
//#endregion
|
|
140
132
|
//#region src/node/read-stream.ts
|
|
141
133
|
const readStream = async (stream) => {
|
|
@@ -177,7 +169,6 @@ const readStream = async (stream) => {
|
|
|
177
169
|
}
|
|
178
170
|
return result;
|
|
179
171
|
};
|
|
180
|
-
|
|
181
172
|
//#endregion
|
|
182
173
|
//#region src/node/render.tsx
|
|
183
174
|
const render = async (node, options) => {
|
|
@@ -205,7 +196,9 @@ const render = async (node, options) => {
|
|
|
205
196
|
const ErrorBoundary = createErrorBoundary(reject);
|
|
206
197
|
const stream = reactDOMServer.renderToPipeableStream(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, { children: node }) }), {
|
|
207
198
|
async onAllReady() {
|
|
208
|
-
html = await readStream(stream)
|
|
199
|
+
html = await readStream(stream).then((s) => {
|
|
200
|
+
return s.replaceAll("\0", "");
|
|
201
|
+
});
|
|
209
202
|
resolve();
|
|
210
203
|
},
|
|
211
204
|
onError(error) {
|
|
@@ -220,9 +213,8 @@ const render = async (node, options) => {
|
|
|
220
213
|
if (options?.pretty) return pretty(document);
|
|
221
214
|
return document;
|
|
222
215
|
};
|
|
223
|
-
|
|
224
216
|
//#endregion
|
|
225
217
|
exports.plainTextSelectors = plainTextSelectors;
|
|
226
218
|
exports.pretty = pretty;
|
|
227
219
|
exports.render = render;
|
|
228
|
-
exports.toPlainText = toPlainText;
|
|
220
|
+
exports.toPlainText = toPlainText;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/node/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/node/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCRvC,MAAA,GAAgB,IAAA,EAAM,KAAA,CAAM,SAAA,EAAW,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/node/render.tsx"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/shared/options.ts","../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/node/render.tsx"],"mappings":";;;;KAIY,OAAA;;;AAAZ;EAIE,MAAA;AAAA;EAmByC;;;EAbrC,SAAA;AAAA;EAaoB;;;EAPpB,SAAA;;;ACyGN;;;;EDlGM,iBAAA,GAAoB,iBAAA;AAAA;;;cCkGb,MAAA,GAAU,GAAA,UAAa,OAAA,GAAS,SAAA,KAAY,OAAA;;;cCvH5C,kBAAA,EAAoB,kBAAA;AAAA,iBASjB,WAAA,CAAY,IAAA,UAAc,OAAA,GAAU,iBAAA;;;cCRvC,MAAA,GAAgB,IAAA,EAAM,KAAA,CAAM,SAAA,EAAW,OAAA,GAAU,OAAA,KAAO,OAAA"}
|
package/dist/node/index.mjs
CHANGED
|
@@ -4,7 +4,6 @@ import { convert } from "html-to-text";
|
|
|
4
4
|
import React, { Suspense } from "react";
|
|
5
5
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
6
6
|
import { Writable } from "node:stream";
|
|
7
|
-
|
|
8
7
|
//#region src/shared/utils/pretty.ts
|
|
9
8
|
function getHtmlNode(path) {
|
|
10
9
|
const topNode = path.node;
|
|
@@ -65,7 +64,6 @@ const pretty = (str, options = {}) => {
|
|
|
65
64
|
...options
|
|
66
65
|
});
|
|
67
66
|
};
|
|
68
|
-
|
|
69
67
|
//#endregion
|
|
70
68
|
//#region src/shared/utils/to-plain-text.ts
|
|
71
69
|
const plainTextSelectors = [
|
|
@@ -85,14 +83,13 @@ const plainTextSelectors = [
|
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
];
|
|
88
|
-
function toPlainText(html
|
|
89
|
-
return convert(html
|
|
86
|
+
function toPlainText(html, options) {
|
|
87
|
+
return convert(html, {
|
|
90
88
|
wordwrap: false,
|
|
91
89
|
...options,
|
|
92
90
|
selectors: [...plainTextSelectors, ...options?.selectors ?? []]
|
|
93
91
|
});
|
|
94
92
|
}
|
|
95
|
-
|
|
96
93
|
//#endregion
|
|
97
94
|
//#region src/shared/error-boundary.tsx
|
|
98
95
|
function createErrorBoundary(reject) {
|
|
@@ -106,7 +103,6 @@ function createErrorBoundary(reject) {
|
|
|
106
103
|
}
|
|
107
104
|
};
|
|
108
105
|
}
|
|
109
|
-
|
|
110
106
|
//#endregion
|
|
111
107
|
//#region src/node/read-stream.ts
|
|
112
108
|
const readStream = async (stream) => {
|
|
@@ -148,7 +144,6 @@ const readStream = async (stream) => {
|
|
|
148
144
|
}
|
|
149
145
|
return result;
|
|
150
146
|
};
|
|
151
|
-
|
|
152
147
|
//#endregion
|
|
153
148
|
//#region src/node/render.tsx
|
|
154
149
|
const render = async (node, options) => {
|
|
@@ -156,7 +151,7 @@ const render = async (node, options) => {
|
|
|
156
151
|
if ("default" in m) return m.default;
|
|
157
152
|
return m;
|
|
158
153
|
});
|
|
159
|
-
let html
|
|
154
|
+
let html;
|
|
160
155
|
await new Promise((resolve, reject) => {
|
|
161
156
|
if (Object.hasOwn(reactDOMServer, "renderToReadableStream") && typeof WritableStream !== "undefined") {
|
|
162
157
|
const ErrorBoundary = createErrorBoundary(reject);
|
|
@@ -169,14 +164,16 @@ const render = async (node, options) => {
|
|
|
169
164
|
await stream.allReady;
|
|
170
165
|
return readStream(stream);
|
|
171
166
|
}).then((result) => {
|
|
172
|
-
html
|
|
167
|
+
html = result;
|
|
173
168
|
resolve();
|
|
174
169
|
}).catch(reject);
|
|
175
170
|
} else {
|
|
176
171
|
const ErrorBoundary = createErrorBoundary(reject);
|
|
177
172
|
const stream = reactDOMServer.renderToPipeableStream(/* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(Suspense, { children: node }) }), {
|
|
178
173
|
async onAllReady() {
|
|
179
|
-
html
|
|
174
|
+
html = await readStream(stream).then((s) => {
|
|
175
|
+
return s.replaceAll("\0", "");
|
|
176
|
+
});
|
|
180
177
|
resolve();
|
|
181
178
|
},
|
|
182
179
|
onError(error) {
|
|
@@ -186,12 +183,12 @@ const render = async (node, options) => {
|
|
|
186
183
|
});
|
|
187
184
|
}
|
|
188
185
|
});
|
|
189
|
-
if (options?.plainText) return toPlainText(html
|
|
190
|
-
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html
|
|
186
|
+
if (options?.plainText) return toPlainText(html, options.htmlToTextOptions);
|
|
187
|
+
const document = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">${html.replace(/<!DOCTYPE.*?>/, "")}`;
|
|
191
188
|
if (options?.pretty) return pretty(document);
|
|
192
189
|
return document;
|
|
193
190
|
};
|
|
194
|
-
|
|
195
191
|
//#endregion
|
|
196
192
|
export { plainTextSelectors, pretty, render, toPlainText };
|
|
193
|
+
|
|
197
194
|
//# sourceMappingURL=index.mjs.map
|
package/dist/node/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["html","html"],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/node/read-stream.ts","../../src/node/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import { Writable } from 'node:stream';\nimport type {\n PipeableStream,\n ReactDOMServerReadableStream,\n} from 'react-dom/server.browser';\n\nexport const readStream = async (\n stream: PipeableStream | ReactDOMServerReadableStream,\n) => {\n let result = '';\n // Create a single TextDecoder instance to handle streaming properly\n // This fixes issues with multi-byte characters (e.g., CJK) being split across chunks\n const decoder = new TextDecoder('utf-8');\n\n if ('pipeTo' in stream) {\n // means it's a readable stream\n const writableStream = new WritableStream({\n write(chunk: BufferSource) {\n // Use stream: true to handle multi-byte characters split across chunks\n result += decoder.decode(chunk, { stream: true });\n },\n close() {\n // Flush any remaining bytes\n result += decoder.decode();\n },\n });\n await stream.pipeTo(writableStream);\n } else {\n const writable = new Writable({\n write(chunk: BufferSource, _encoding, callback) {\n // Use stream: true to handle multi-byte characters split across chunks\n result += decoder.decode(chunk, { stream: true });\n\n callback();\n },\n final(callback) {\n // Flush any remaining bytes\n result += decoder.decode();\n callback();\n },\n });\n await new Promise<void>((resolve, reject) => {\n writable.on('pipe', (source) => {\n source.on('error', (err: Error) => {\n writable.destroy(err);\n });\n });\n writable.on('error', reject);\n writable.on('close', () => {\n resolve();\n });\n\n stream.pipe(writable);\n });\n }\n\n return result;\n};\n","import { Suspense } from 'react';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { pretty } from '../shared/utils/pretty';\nimport { toPlainText } from '../shared/utils/to-plain-text';\nimport { readStream } from './read-stream';\n\nexport const render = async (node: React.ReactNode, options?: Options) => {\n const reactDOMServer = await import('react-dom/server').then((m) => {\n if ('default' in m) {\n return m.default;\n }\n return m;\n });\n\n let html!: string;\n await new Promise<void>((resolve, reject) => {\n if (\n Object.hasOwn(reactDOMServer, 'renderToReadableStream') &&\n typeof WritableStream !== 'undefined'\n ) {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <ErrorBoundary>\n <Suspense>{node}</Suspense>\n </ErrorBoundary>,\n {\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n onError(error) {\n // Throw immediately when an error occurs to prevent CSR fallback\n reject(error);\n },\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then((result) => {\n html = result;\n resolve();\n })\n .catch(reject);\n } else {\n const ErrorBoundary = createErrorBoundary(reject);\n const stream = reactDOMServer.renderToPipeableStream(\n <ErrorBoundary>\n <Suspense>{node}</Suspense>\n </ErrorBoundary>,\n {\n async onAllReady() {\n html = await readStream(stream);\n resolve();\n },\n onError(error) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n );\n }\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/shared/utils/pretty.ts","../../src/shared/utils/to-plain-text.ts","../../src/shared/error-boundary.tsx","../../src/node/read-stream.ts","../../src/node/render.tsx"],"sourcesContent":["import type { Options, Plugin } from 'prettier';\nimport type { builders } from 'prettier/doc';\nimport * as html from 'prettier/plugins/html';\nimport { format } from 'prettier/standalone';\n\ninterface HtmlNode {\n type?: 'element' | 'text' | 'ieConditionalComment';\n kind?: 'element' | 'text' | 'ieConditionalComment' | 'root';\n name?: string;\n sourceSpan: {\n start: { file: unknown[]; offset: number; line: number; col: number };\n end: { file: unknown[]; offset: number; line: number; col: number };\n details: null;\n };\n parent?: HtmlNode;\n}\n\nfunction getHtmlNode(path: {\n node?: HtmlNode;\n stack?: Array<Record<string, unknown>>;\n}) {\n const topNode = path.node;\n if (topNode) {\n return topNode;\n }\n\n return path.stack?.[path.stack.length - 1] as HtmlNode;\n}\n\nfunction recursivelyMapDoc(\n doc: builders.Doc,\n callback: (innerDoc: string | builders.DocCommand) => builders.Doc,\n): builders.Doc {\n if (Array.isArray(doc)) {\n return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));\n }\n\n if (typeof doc === 'object') {\n if (doc.type === 'line') {\n return callback(doc.soft ? '' : ' ');\n }\n\n if (doc.type === 'group') {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n expandedStates: recursivelyMapDoc(\n doc.expandedStates,\n callback,\n ) as builders.Doc[],\n };\n }\n\n if ('contents' in doc) {\n return {\n ...doc,\n contents: recursivelyMapDoc(doc.contents, callback),\n };\n }\n\n if ('parts' in doc) {\n return {\n ...doc,\n parts: recursivelyMapDoc(doc.parts, callback) as builders.Doc[],\n };\n }\n\n if (doc.type === 'if-break') {\n return {\n ...doc,\n breakContents: recursivelyMapDoc(doc.breakContents, callback),\n flatContents: recursivelyMapDoc(doc.flatContents, callback),\n };\n }\n\n const nextDoc = { ...doc } as Record<string, unknown>;\n for (const [key, value] of Object.entries(nextDoc)) {\n if (value && typeof value === 'object') {\n nextDoc[key] = recursivelyMapDoc(value as builders.Doc, callback);\n }\n }\n\n return nextDoc as builders.Doc;\n }\n\n return callback(doc);\n}\n\nconst modifiedHtml = { ...html } as Plugin;\nif (modifiedHtml.printers) {\n const previousPrint = modifiedHtml.printers.html.print;\n modifiedHtml.printers.html.print = (path, options, print, args) => {\n const node = getHtmlNode(\n path as Parameters<Plugin['printers']['html']['print']>[0],\n );\n\n const rawPrintingResult = previousPrint(path, options, print, args);\n\n if (\n node?.type === 'ieConditionalComment' ||\n node?.kind === 'ieConditionalComment'\n ) {\n const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {\n if (typeof doc === 'object' && doc.type === 'line') {\n return doc.soft ? '' : ' ';\n }\n\n return doc;\n });\n\n return printingResult;\n }\n\n return rawPrintingResult;\n };\n}\n\nconst defaults: Options = {\n endOfLine: 'lf',\n tabWidth: 2,\n plugins: [modifiedHtml],\n bracketSameLine: true,\n parser: 'html',\n};\n\nexport const pretty = (str: string, options: Options = {}) => {\n return format(str.replaceAll('\\0', ''), {\n ...defaults,\n ...options,\n });\n};\n","import {\n convert,\n type HtmlToTextOptions,\n type SelectorDefinition,\n} from 'html-to-text';\n\nexport const plainTextSelectors: SelectorDefinition[] = [\n { selector: 'img', format: 'skip' },\n { selector: '[data-skip-in-text=true]', format: 'skip' },\n {\n selector: 'a',\n options: { linkBrackets: false, hideLinkHrefIfSameAsText: true },\n },\n];\n\nexport function toPlainText(html: string, options?: HtmlToTextOptions) {\n return convert(html, {\n wordwrap: false,\n ...options,\n selectors: [...plainTextSelectors, ...(options?.selectors ?? [])],\n });\n}\n","import React from 'react';\n\nexport function createErrorBoundary(reject: (error: unknown) => void) {\n // React Server Components don't support React.Component, so it's just not defined here\n if (!React.Component) {\n return (props: { children?: React.ReactNode }) => <>{props.children}</>;\n }\n\n return class ErrorBoundary extends React.Component<{\n children: React.ReactNode;\n }> {\n componentDidCatch(error: unknown) {\n reject(error);\n }\n render() {\n return this.props.children;\n }\n };\n}\n","import { Writable } from 'node:stream';\nimport type {\n PipeableStream,\n ReactDOMServerReadableStream,\n} from 'react-dom/server.browser';\n\nexport const readStream = async (\n stream: PipeableStream | ReactDOMServerReadableStream,\n) => {\n let result = '';\n // Create a single TextDecoder instance to handle streaming properly\n // This fixes issues with multi-byte characters (e.g., CJK) being split across chunks\n const decoder = new TextDecoder('utf-8');\n\n if ('pipeTo' in stream) {\n // means it's a readable stream\n const writableStream = new WritableStream({\n write(chunk: BufferSource) {\n // Use stream: true to handle multi-byte characters split across chunks\n result += decoder.decode(chunk, { stream: true });\n },\n close() {\n // Flush any remaining bytes\n result += decoder.decode();\n },\n });\n await stream.pipeTo(writableStream);\n } else {\n const writable = new Writable({\n write(chunk: BufferSource, _encoding, callback) {\n // Use stream: true to handle multi-byte characters split across chunks\n result += decoder.decode(chunk, { stream: true });\n\n callback();\n },\n final(callback) {\n // Flush any remaining bytes\n result += decoder.decode();\n callback();\n },\n });\n await new Promise<void>((resolve, reject) => {\n writable.on('pipe', (source) => {\n source.on('error', (err: Error) => {\n writable.destroy(err);\n });\n });\n writable.on('error', reject);\n writable.on('close', () => {\n resolve();\n });\n\n stream.pipe(writable);\n });\n }\n\n return result;\n};\n","import { Suspense } from 'react';\nimport { createErrorBoundary } from '../shared/error-boundary';\nimport type { Options } from '../shared/options';\nimport { pretty } from '../shared/utils/pretty';\nimport { toPlainText } from '../shared/utils/to-plain-text';\nimport { readStream } from './read-stream';\n\nexport const render = async (node: React.ReactNode, options?: Options) => {\n const reactDOMServer = await import('react-dom/server').then((m) => {\n if ('default' in m) {\n return m.default;\n }\n return m;\n });\n\n let html!: string;\n await new Promise<void>((resolve, reject) => {\n if (\n Object.hasOwn(reactDOMServer, 'renderToReadableStream') &&\n typeof WritableStream !== 'undefined'\n ) {\n const ErrorBoundary = createErrorBoundary(reject);\n reactDOMServer\n .renderToReadableStream(\n <ErrorBoundary>\n <Suspense>{node}</Suspense>\n </ErrorBoundary>,\n {\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n onError(error) {\n // Throw immediately when an error occurs to prevent CSR fallback\n reject(error);\n },\n },\n )\n .then(async (stream) => {\n await stream.allReady;\n return readStream(stream);\n })\n .then((result) => {\n html = result;\n resolve();\n })\n .catch(reject);\n } else {\n const ErrorBoundary = createErrorBoundary(reject);\n const stream = reactDOMServer.renderToPipeableStream(\n <ErrorBoundary>\n <Suspense>{node}</Suspense>\n </ErrorBoundary>,\n {\n async onAllReady() {\n html = await readStream(stream).then((s: string) => {\n // Workaround for https://github.com/facebook/react/pull/26228\n // (fixed in React 19, not backported to 18)\n return s.replaceAll('\\0', '');\n });\n resolve();\n },\n onError(error) {\n reject(error);\n },\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n },\n );\n }\n });\n\n if (options?.plainText) {\n return toPlainText(html, options.htmlToTextOptions);\n }\n\n const doctype =\n '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">';\n\n const document = `${doctype}${html.replace(/<!DOCTYPE.*?>/, '')}`;\n\n if (options?.pretty) {\n return pretty(document);\n }\n\n return document;\n};\n"],"mappings":"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"}
|