Skip to content

Commit dd7bde3

Browse files
committed
Revert "wip"
This reverts commit 007f66b.
1 parent 42d4c5b commit dd7bde3

File tree

7 files changed

+89
-61
lines changed

7 files changed

+89
-61
lines changed

AGENTS.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# React Email - Agent Guidelines
2+
3+
## Build/Test Commands
4+
- `pnpm build` - Build all packages using Turbo
5+
- `pnpm test` - Run all tests using Vitest
6+
- `pnpm test:watch` - Run tests in watch mode
7+
- `pnpm lint` - Check code with Biome linter
8+
- `pnpm lint:fix` - Fix linting issues automatically
9+
- Run single test: `cd packages/[package-name] && pnpm test [test-file]`
10+
11+
## Code Style (Biome Config)
12+
- **Formatting**: 2 spaces, 80 char line width, single quotes, use `pnpm lint` for checking formatting and linting, and use `pnpm lint:fix` to lint and format all files
13+
- **Imports**: Use `import type` for types, organize imports automatically
14+
- **Components**: Use `React.forwardRef` for all package components in `packages` if they support React 18 with proper displayName
15+
- **Functions**: Always prefer `const ... = () => {...}` rather than `function`
16+
- **Exports**: Use named exports, avoid default exports because they are hard to refactor
17+
- **Error Handling**: Use proper TypeScript types, avoid `any`, and only if necessary, use `unknown`
18+
19+
## Project Structure
20+
- Monorepo with packages in `packages/*`, `apps/*`
21+
- Each package has `src/index.ts`, component file, and `.spec.tsx` test
22+
- Tests use Vitest with `@react-email/render` for HTML output testing
23+
- Use `turbo run` commands for cross-package operations
24+
- Documentation is written using Mintlify
25+
- There are apps in `apps` that we publish
26+
- `apps/demo`: https://demo.react.email
27+
- `apps/docs`: https://react.email/docs
28+
- `apps/web`: https://react.email
29+

apps/web/components/ensure-matching-variants.spec.tsx

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,57 @@
11
import { existsSync } from 'node:fs';
22
import path from 'node:path';
33
import { pretty, render } from '@react-email/components';
4+
import { parse, stringify } from 'html-to-ast';
5+
import type { Attr, IDoc as Doc } from 'html-to-ast/dist/types';
6+
import postcss from 'postcss';
47
import { getComponentElement } from '../src/app/components/get-imported-components-for';
58
import { Layout } from './_components/layout';
69
import { componentsStructure, getComponentPathFromSlug } from './structure';
710

11+
type MaybeDoc = ReturnType<typeof parse>[number];
12+
13+
const walkAst = <T extends MaybeDoc>(ast: T[], callback: (doc: T) => void) => {
14+
for (const doc of ast) {
15+
callback(doc);
16+
if (doc.children) {
17+
walkAst(doc.children as T[], callback);
18+
}
19+
}
20+
};
21+
22+
const getStyleObjectFromString = (style: string): Record<string, string> => {
23+
const obj: Record<string, string> = {};
24+
const root = postcss.parse(style);
25+
root.walkDecls((decl) => {
26+
obj[decl.prop] = decl.value;
27+
});
28+
return obj;
29+
};
30+
31+
const sortStyle = (style: string): string => {
32+
const object = getStyleObjectFromString(style);
33+
const styleProperties = Object.keys(object).sort();
34+
return styleProperties.map((prop) => `${prop}:${object[prop]}`).join(';');
35+
};
36+
37+
const getComparableHtml = (html: string): string => {
38+
const ast = parse(html);
39+
walkAst(ast, (doc) => {
40+
const orderedAttributes: Attr = {};
41+
if (doc.attrs) {
42+
for (const key of Object.keys(doc.attrs).sort()) {
43+
orderedAttributes[key] = doc.attrs[key];
44+
}
45+
doc.attrs = orderedAttributes;
46+
if ('style' in doc.attrs) {
47+
const style = doc.attrs.style as string;
48+
doc.attrs.style = sortStyle(style);
49+
}
50+
}
51+
});
52+
return stringify(ast as Doc[]);
53+
};
54+
855
describe('copy-paste components', () => {
956
const components = componentsStructure.flatMap(
1057
(category) => category.components,
@@ -31,14 +78,16 @@ describe('copy-paste components', () => {
3178
) {
3279
const tailwindElement = await getComponentElement(tailwindVariantPath);
3380
const inlineStylesElement = await getComponentElement(
34-
inlineStylesVariantPath
81+
inlineStylesVariantPath,
3582
);
36-
const tailwindHtml = pretty(
37-
await render(<Layout>{tailwindElement}</Layout>),
83+
const tailwindHtml = getComparableHtml(
84+
await pretty(await render(<Layout>{tailwindElement}</Layout>)),
3885
);
39-
const inlineStylesHtml = pretty(
40-
await render(
41-
<Layout withTailwind={false}>{inlineStylesElement}</Layout>,
86+
const inlineStylesHtml = getComparableHtml(
87+
await pretty(
88+
await render(
89+
<Layout withTailwind={false}>{inlineStylesElement}</Layout>,
90+
),
4291
),
4392
);
4493
expect(tailwindHtml).toBe(inlineStylesHtml);

apps/web/components/four-images-in-a-grid/inline-styles.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ export const component = (
77
<Row>
88
<Text
99
style={{
10+
margin: '0px',
1011
fontSize: 16,
1112
lineHeight: '24px',
12-
margin: '0px',
1313
fontWeight: 600,
1414
color: 'rgb(79,70,229)',
1515
}}

apps/web/tsconfig.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
{
22
"extends": "tsconfig/nextjs.json",
33
"compilerOptions": {
4-
"esModuleInterop": true,
5-
"paths": { "@/*": ["./src/*"] },
6-
"plugins": [{ "name": "next" }],
74
"target": "ES2018",
5+
"plugins": [{ "name": "next" }],
6+
"paths": { "@/*": ["./src/*"] },
87
"types": ["vitest/globals"]
98
},
109
"include": [

packages/render/src/shared/utils/__snapshots__/pretty.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ exports[`pretty > should prettify base doucment correctly 1`] = `
11351135
"
11361136
`;
11371137

1138-
exports[`pretty > style attribute formatting > should print properties per-line once they get too wide 1`] = `
1138+
exports[`pretty > should print style properties per-line once they get too wide 1`] = `
11391139
"<div
11401140
style="
11411141
width:100%;

packages/render/src/shared/utils/pretty.spec.tsx renamed to packages/render/src/shared/utils/pretty.spec.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import fs from 'node:fs';
22
import path from 'node:path';
3-
import { render } from '../../node';
43
import { pretty, wrapText } from './pretty';
5-
import { component } from '../../../../../apps/web/components/four-images-in-a-grid/inline-styles';
6-
import { Layout } from '../../../../../apps/web/components/_components/layout';
74

85
const stripeHtml = fs.readFileSync(
96
path.resolve(__dirname, './tests/stripe-email.html'),
@@ -21,15 +18,6 @@ describe('pretty', () => {
2118
expect(pretty(document, { lineBreak: '\n' })).toMatchSnapshot();
2219
});
2320

24-
test.only('testing', async () => {
25-
const html = await render(<Layout>{component}</Layout>);
26-
await fs.promises.writeFile(
27-
'tailwind copy-paste component.html',
28-
html,
29-
'utf8',
30-
);
31-
32-
console.log(pretty(html));
3321
it('should not wrap text inside of <style> and <script> tags', () => {
3422
const document = `<!DOCTYPE html><html><head><style>body { color: red; }</style></head><body><script>console.log('Hello, world!');</script></body></html>`;
3523
expect(pretty(document, { lineBreak: '\n' })).toMatchSnapshot();
@@ -42,7 +30,7 @@ describe('pretty', () => {
4230
expect(pretty(document, { lineBreak: '\n' })).toMatchSnapshot();
4331
});
4432

45-
it('should work with an img element', () => {
33+
it.only('should work with an img element', () => {
4634
const document =
4735
'<img alt="Stagg Electric Kettle" style="border-radius:12px;border:none;display:block;object-fit:cover;outline:none;text-decoration:none;width:100%;" height="288" src="/static/stagg-eletric-kettle.jpg" />';
4836
expect(pretty(document, { lineBreak: '\n' })).toMatchSnapshot();

packages/render/tailwind copy-paste component.html

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)