Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cute-taxes-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/mail-react": minor
---

The new `@comet/mail-react` package provides utilities for building HTML emails with React
8 changes: 8 additions & 0 deletions .changeset/mighty-pants-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@comet/mail-react": minor
---

Add the `css` helper function

Similar to the `css` function provided by styled-components or @mui/material.
It simply returns the string passed into it but provides CSS syntax highlighting and auto-formatting when using certain IDE plugins, e.g. the "styled-components" plugin in VSCode.
1 change: 1 addition & 0 deletions demo/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@apollo/server": "^5.1.0",
"@as-integrations/express5": "^1.1.2",
"@comet/cms-api": "workspace:*",
"@comet/mail-react": "workspace:*",
"@faker-js/faker": "^10.1.0",
"@kubernetes/client-node": "^1.3.0",
"@mikro-orm/cli": "^6.4.16",
Expand Down
11 changes: 9 additions & 2 deletions demo/api/src/products/product-published.mail.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { MailTemplate, MailTemplateInterface } from "@comet/cms-api";
import { css } from "@comet/mail-react";
import { TranslationService } from "@src/translation/translation.service";

type MailProps = {
recipient: { name: string; email: string; language: string };
countProductPublished: "all" | number;
};

const mailStyles = css`
body {
font-family: Arial, sans-serif;
}
`;

@MailTemplate()
export class ProductPublishedMail implements MailTemplateInterface<MailProps> {
constructor(private readonly translationService: TranslationService) {}
Expand Down Expand Up @@ -34,7 +41,7 @@ export class ProductPublishedMail implements MailTemplateInterface<MailProps> {
countProductPublished: props.countProductPublished,
},
),
html: intl.formatMessage(
html: `<head><style>${mailStyles}</style></head>${intl.formatMessage(
{
id: "product-published-mail.html-message",
defaultMessage:
Expand All @@ -51,7 +58,7 @@ export class ProductPublishedMail implements MailTemplateInterface<MailProps> {
countProductPublished: props.countProductPublished,
p: (...chunks) => `<p>${chunks.join("")}</p>`,
},
),
)}`,
};
}

Expand Down
7 changes: 7 additions & 0 deletions dev-pm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ export default defineConfig({
group: ["site-react", "site-nextjs", "cms"],
},

//group mail-react
{
name: "mail-react",
script: "pnpm --filter @comet/mail-react run dev",
group: ["mail-react"],
},

//group demo admin
{
name: "demo-admin",
Expand Down
3 changes: 3 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
"project": ["./src/**/*.{ts,tsx}"],
"ignore": ["./src/**/*.generated.ts"]
},
"packages/mail-react": {
"project": ["./src/**/*.{ts,tsx}"]
},
"demo/admin": {
"entry": ["./src/loader.ts", "./src/**/*.cometGen.{ts,tsx}"],
"project": ["./src/**/*.{ts,tsx}"],
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
"build:docs": "pnpm build:storybook && pnpm --recursive --filter '@comet/eslint-plugin' --filter '@comet/admin*' --filter '!@comet/admin-generator' --filter 'comet-docs' run build",
"clean": "pnpm --recursive run clean",
"copy-project-files": "node copy-project-files.js",
"dev": "pnpm dev:admin && pnpm dev:cms && pnpm dev:demo",
"dev": "pnpm dev:admin && pnpm dev:cms && pnpm dev:mail-react && pnpm dev:demo",
"dev:admin": "dev-pm start @comet-admin",
"dev:cms": "dev-pm start @cms",
"dev:cms:admin": "dev-pm start @cms-admin",
"dev:cms:api": "dev-pm start @cms-api",
"dev:cms:site-nextjs": "dev-pm start @site-nextjs",
"dev:cms:site-react": "dev-pm start @site-react",
"dev:mail-react": "dev-pm start @mail-react",
"dev:demo": "dev-pm start @demo",
"dev:demo:admin": "dev-pm start @demo-admin",
"dev:demo:api": "dev-pm start @demo-api",
Expand Down
1 change: 1 addition & 0 deletions packages/mail-react/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib/
16 changes: 16 additions & 0 deletions packages/mail-react/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import eslintConfigReact from "@comet/eslint-config/future/react.js";

/** @type {import('eslint')} */
const config = [
{
ignores: ["lib/**"],
},
...eslintConfigReact,
{
rules: {
"@comet/no-other-module-relative-import": "off",
},
},
];

export default config;
9 changes: 9 additions & 0 deletions packages/mail-react/lint-staged.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @filename: lint-staged.config.mjs
* @type {import('lint-staged').Configuration}
*/
export default {
"src/**/*.{ts,tsx,js,jsx,json,css,scss,md}": () => "pnpm lint:eslint",
"src/**/*.{ts,tsx}": () => "pnpm lint:tsc",
"*.{js,json,md,yml,yaml}": () => "pnpm lint:prettier",
};
36 changes: 36 additions & 0 deletions packages/mail-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@comet/mail-react",
"version": "8.10.0",
"description": "Utilities for building HTML emails with React",
"type": "commonjs",
"main": "lib/index.js",
Copy link
Collaborator

Choose a reason for hiding this comment

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

The package.json should include a types and files field as well, see:

"types": "lib/index.d.ts",
"files": [
"bin/**/*.js",
"lib/*"
],
.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added those, but without bin/**/*.js, as there is no bin directory created during build.
Is that correct? (I have no idea what this is used for 😅)

"scripts": {
"build": "pnpm run clean && tsc",
"clean": "rimraf lib",
Copy link
Collaborator

Choose a reason for hiding this comment

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

The rimraf dependency appears to be missing.

"dev": "tsc --watch",
"lint": "run-p lint:prettier lint:eslint lint:tsc",
"lint:ci": "pnpm run lint",
"lint:eslint": "eslint --max-warnings 0 src/ **/*.json --no-warn-ignored",
"lint:prettier": "pnpm exec prettier --check './**/*.{js,json,md,yml,yaml}'",
"lint:tsc": "tsc"
},
"devDependencies": {
"@comet/eslint-config": "workspace:*",
"@types/jest": "^29.5.14",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please remove this package.

"eslint": "^9.30.1",
"npm-run-all2": "^8.0.0",
"prettier": "^3.6.2",
"typescript": "5.9.3"
},
"peerDependencies": {
"eslint": ">=9",
"prettier": ">=3"
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

This aren't peer dependencies. Which package did you choose as basis?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, should have noticed that, they are included in devDependencies anyway 😅

Which package did you choose as basis?

Mostly from site-react but partially from eslint-config because I thought that would be the smallest/simplest.

"engines": {
"node": ">=22.0.0"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
}
}
1 change: 1 addition & 0 deletions packages/mail-react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { css } from "./utils/css";
4 changes: 4 additions & 0 deletions packages/mail-react/src/utils/css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* Helper function to enable syntax highlighting & auto-formatting for CSS strings when using certain IDE plugins, e.g. the "styled-components" plugin in VSCode.
*/
export const css = (strings: TemplateStringsArray, ...rest: unknown[]): string => String.raw({ raw: strings }, ...rest);
9 changes: 9 additions & 0 deletions packages/mail-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"exclude": ["node_modules", "lib"],
"extends": "../../tsconfig.core.json",
"include": ["./src"]
}
24 changes: 24 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.