Skip to content

Commit 87e0cf7

Browse files
authored
feat(web): Make HTML a separate copy-paste code variant (#1697)
1 parent 6c9d108 commit 87e0cf7

File tree

4 files changed

+174
-141
lines changed

4 files changed

+174
-141
lines changed

apps/web/src/app/components/[slug]/page.tsx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { renderAsync } from "@react-email/components";
21
import { notFound } from "next/navigation";
32
import Link from "next/link";
43
import { slugify } from "../../../utils/slugify";
5-
import { Layout } from "../../../../components/_components/layout";
64
import { componentsStructure } from "../../../../components/structure";
7-
import type { ImportedComponent } from "../get-components";
85
import { getImportedComponentsFor } from "../get-components";
96
import PageTransition from "../../../components/page-transition";
10-
import type { RenderedComponent } from "../../../components/components-view";
117
import { ComponentsView } from "../../../components/components-view";
128
import { IconArrowLeft } from "../../../components/icons/icon-arrow-left";
139

@@ -65,25 +61,7 @@ const ComponentPage: React.FC<ComponentPageParams> = async ({ params }) => {
6561

6662
if (!foundCategory) return <p>Component category not found.</p>;
6763

68-
const renderedComponents: RenderedComponent[] = await Promise.all(
69-
(await getImportedComponentsFor(foundCategory)).map(async (component) => {
70-
const componentWithoutElement: Omit<ImportedComponent, "element"> = {
71-
...component,
72-
};
73-
delete (
74-
componentWithoutElement as Omit<ImportedComponent, "element"> & {
75-
element?: React.ReactElement;
76-
}
77-
).element;
78-
return {
79-
...componentWithoutElement,
80-
html: await renderAsync(
81-
<Layout withTailwind={false}>{component.element}</Layout>,
82-
),
83-
} as RenderedComponent;
84-
}),
85-
);
86-
64+
const importedComponents = await getImportedComponentsFor(foundCategory);
8765
return (
8866
<>
8967
<div className="pointer-events-none absolute inset-0 flex justify-center">
@@ -108,7 +86,7 @@ const ComponentPage: React.FC<ComponentPageParams> = async ({ params }) => {
10886
</h1>
10987
</div>
11088
<div className="relative flex w-full flex-col gap-4 border-y border-slate-4 pt-3">
111-
<ComponentsView components={renderedComponents} />
89+
<ComponentsView components={importedComponents} />
11290
</div>
11391
</PageTransition>
11492
</>

apps/web/src/app/components/get-components.ts renamed to apps/web/src/app/components/get-components.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ import path from "node:path";
33
import { traverse } from "@babel/core";
44
import { parse } from "@babel/parser";
55
import { z } from "zod";
6+
import { render } from "@react-email/components";
67
import type { Category, Component } from "../../../components/structure";
78
import {
89
getComponentPathFromSlug,
910
pathToComponents,
1011
} from "../../../components/structure";
12+
import { Layout } from "../../../components/_components/layout";
1113

12-
export type CodeVariant = "tailwind" | "inline-styles";
14+
/**
15+
* Tailwind and Inline Styles are both with React, but the React
16+
* option is meant for where Tailwind nor Inline Styles are used
17+
* at all in the markup.
18+
*/
19+
export type CodeVariant = "tailwind" | "inline-styles" | "react" | "html";
1320

1421
export interface ImportedComponent extends Component {
15-
element: React.ReactElement;
16-
code: Partial<Record<CodeVariant, string>> | string;
22+
code: Partial<Record<CodeVariant, string>> & { html: string };
1723
}
1824

1925
const ComponentModule = z.object({
@@ -77,16 +83,22 @@ export const getImportedComponent = async (
7783

7884
if (variantFilenames.length === 1 && variantFilenames[0] === "index.tsx") {
7985
const filePath = path.join(dirpath, "index.tsx");
86+
const element = <Layout>{await getComponentElement(filePath)}</Layout>;
87+
const html = await render(element, {
88+
pretty: true,
89+
});
8090
const fileContent = await fs.readFile(filePath, "utf8");
8191
const code = getComponentCodeFrom(fileContent);
8292
return {
8393
...component,
84-
element: await getComponentElement(filePath),
85-
code,
94+
code: {
95+
react: code,
96+
html,
97+
},
8698
};
8799
}
88100

89-
const codePerVariant: Partial<Record<CodeVariant, string>> = {};
101+
const codePerVariant: ImportedComponent["code"] = { html: "" };
90102

91103
const elements = await Promise.all(
92104
variantFilenames.map(async (variantFilename) => {
@@ -107,9 +119,14 @@ export const getImportedComponent = async (
107119
codePerVariant[variantKey] = getComponentCodeFrom(fileContents[index]);
108120
});
109121

122+
const element = <Layout>{elements[0]}</Layout>;
123+
124+
codePerVariant.html = await render(element, {
125+
pretty: true,
126+
});
127+
110128
return {
111129
...component,
112-
element: elements[0],
113130
code: codePerVariant,
114131
};
115132
};

0 commit comments

Comments
 (0)