Skip to content

Commit

Permalink
feat(web): Make HTML a separate copy-paste code variant (#1697)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielmfern committed Sep 20, 2024
1 parent 6c9d108 commit 87e0cf7
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 141 deletions.
26 changes: 2 additions & 24 deletions apps/web/src/app/components/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { renderAsync } from "@react-email/components";
import { notFound } from "next/navigation";
import Link from "next/link";
import { slugify } from "../../../utils/slugify";
import { Layout } from "../../../../components/_components/layout";
import { componentsStructure } from "../../../../components/structure";
import type { ImportedComponent } from "../get-components";
import { getImportedComponentsFor } from "../get-components";
import PageTransition from "../../../components/page-transition";
import type { RenderedComponent } from "../../../components/components-view";
import { ComponentsView } from "../../../components/components-view";
import { IconArrowLeft } from "../../../components/icons/icon-arrow-left";

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

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

const renderedComponents: RenderedComponent[] = await Promise.all(
(await getImportedComponentsFor(foundCategory)).map(async (component) => {
const componentWithoutElement: Omit<ImportedComponent, "element"> = {
...component,
};
delete (
componentWithoutElement as Omit<ImportedComponent, "element"> & {
element?: React.ReactElement;
}
).element;
return {
...componentWithoutElement,
html: await renderAsync(
<Layout withTailwind={false}>{component.element}</Layout>,
),
} as RenderedComponent;
}),
);

const importedComponents = await getImportedComponentsFor(foundCategory);
return (
<>
<div className="pointer-events-none absolute inset-0 flex justify-center">
Expand All @@ -108,7 +86,7 @@ const ComponentPage: React.FC<ComponentPageParams> = async ({ params }) => {
</h1>
</div>
<div className="relative flex w-full flex-col gap-4 border-y border-slate-4 pt-3">
<ComponentsView components={renderedComponents} />
<ComponentsView components={importedComponents} />
</div>
</PageTransition>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ import path from "node:path";
import { traverse } from "@babel/core";
import { parse } from "@babel/parser";
import { z } from "zod";
import { render } from "@react-email/components";
import type { Category, Component } from "../../../components/structure";
import {
getComponentPathFromSlug,
pathToComponents,
} from "../../../components/structure";
import { Layout } from "../../../components/_components/layout";

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

export interface ImportedComponent extends Component {
element: React.ReactElement;
code: Partial<Record<CodeVariant, string>> | string;
code: Partial<Record<CodeVariant, string>> & { html: string };
}

const ComponentModule = z.object({
Expand Down Expand Up @@ -77,16 +83,22 @@ export const getImportedComponent = async (

if (variantFilenames.length === 1 && variantFilenames[0] === "index.tsx") {
const filePath = path.join(dirpath, "index.tsx");
const element = <Layout>{await getComponentElement(filePath)}</Layout>;
const html = await render(element, {
pretty: true,
});
const fileContent = await fs.readFile(filePath, "utf8");
const code = getComponentCodeFrom(fileContent);
return {
...component,
element: await getComponentElement(filePath),
code,
code: {
react: code,
html,
},
};
}

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

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

const element = <Layout>{elements[0]}</Layout>;

codePerVariant.html = await render(element, {
pretty: true,
});

return {
...component,
element: elements[0],
code: codePerVariant,
};
};
Expand Down
Loading

1 comment on commit 87e0cf7

@vercel
Copy link

@vercel vercel bot commented on 87e0cf7 Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-email-demo – ./apps/demo

react-email-demo.vercel.app
react-email-demo-resend.vercel.app
react-email-demo-git-main-resend.vercel.app
demo.react.email

Please sign in to comment.