-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jsx-email): import css in templates (#244)
- Loading branch information
1 parent
d731f47
commit 3981f3e
Showing
27 changed files
with
461 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
.moon/cache | ||
.eslintcache | ||
.compiled | ||
.rendered | ||
.test | ||
node_modules | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--- | ||
title: 'Compile' | ||
description: 'Compile jsx-email templates into a bundle' | ||
params: -D | ||
slug: render | ||
type: package | ||
--- | ||
|
||
<!--@include: @/include/header.md--> | ||
|
||
<!--@include: @/include/install.md--> | ||
|
||
## Usage | ||
|
||
```jsx | ||
import { readFile } from 'node:fs/promises;'; | ||
import { resolve } from 'node:path'; | ||
|
||
import { compile } from 'jsx-email'; | ||
|
||
const templatePath = resolve(__dirname, './emails/Batman'); | ||
const outputDir = resolve(__dirname, '.compiled'); | ||
|
||
const compiledFiles = await compile({ files: [templatePath], hashFiles: false, outDir }); | ||
``` | ||
|
||
::: tip | ||
Once compiled into a bundle, the file can be imported and passed to render such like: | ||
|
||
```jsx | ||
import { Template } from './.compiled/batman.js'; | ||
|
||
import { render } from 'jsx-email'; | ||
|
||
const html = render(<Template />); | ||
``` | ||
|
||
Note that whether or not to use a file extension in the import depends on your project's settings. When using TypeScript you may have to adjust types to avoid errors, using this method. | ||
::: | ||
|
||
## Method Options | ||
|
||
```ts | ||
export interface Options { | ||
disableDefaultStyle?: boolean; | ||
inlineCss?: boolean; | ||
minify?: boolean; | ||
plainText?: boolean | PlainTextOptions; | ||
pretty?: boolean; | ||
} | ||
``` | ||
|
||
### Options | ||
|
||
```ts | ||
files: string[]; | ||
``` | ||
|
||
An array of absolute paths for JSX/TSX template files to compile | ||
|
||
```ts | ||
hashFiles?: boolean; | ||
``` | ||
|
||
Default: true. If `true`, adds the build hash to compiled file names. Set this to `false` if hashing and unique output filenames aren't needed. | ||
|
||
```ts | ||
outDir: string; | ||
``` | ||
|
||
An absolute path to output the compiled file(s) | ||
|
||
```ts | ||
writeMeta?: boolean; | ||
``` | ||
|
||
If `true`, writes the ESBuild metadata for the compiled file(s) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
--- | ||
title: 'Recipes' | ||
description: 'Recipes for jsx-email' | ||
--- | ||
|
||
## 🧁 jsx-email Recipes | ||
|
||
Recipes are actual, working examples of jsx-email features and techniques that can be copied and pasted. They help users to understand how a thing works outside of the documentation. | ||
|
||
### Available recipes: | ||
|
||
<table border="0" cellspacing="0" cellpadding="0" class="recipes"> | ||
<tr> | ||
<td>🧁</td> | ||
<td>Importing CSS</td> | ||
<td width="100%"><a href="https://github.com/shellscape/jsx-email/tree/main/recipes/import-css">/recipes/import-css</a></td> | ||
</tr> | ||
</table> | ||
|
||
### External Recipes | ||
|
||
<table border="0" cellspacing="0" cellpadding="0" class="recipes"> | ||
<tr> | ||
<td>🧁</td> | ||
<td>Integration with Keycloak(ify)</td> | ||
<td width="100%"><a href="https://github.com/timofei-iatsenko/keycloakify-jsx-emails">github.com/timofei-iatsenko/keycloakify-jsx-emails</a></td> | ||
</tr> | ||
</table> | ||
|
||
<br/><br/><br/><br/><br/><br/><br/> | ||
Don't see a recipe that you'd like to? [Open an Issue!](https://github.com/shellscape/jsx-email/issues/new?assignees=&labels=&projects=&template=DOCS.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Note: after server start we change the root directory to trick vite | ||
export const originalCwd = process.cwd(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { readFile, writeFile } from 'node:fs/promises'; | ||
import { dirname, basename, extname, join, resolve } from 'path'; | ||
|
||
import esbuild from 'esbuild'; | ||
|
||
import { loadConfig } from '../config.js'; | ||
import { log } from '../log.js'; | ||
|
||
interface CompileOptions { | ||
/** | ||
* @desc an array of absolute paths for JSX/TSX template files to compile | ||
*/ | ||
files: string[]; | ||
/** | ||
* @desc Default: true. If true, adds the build hash to compiled file names. | ||
*/ | ||
hashFiles?: boolean; | ||
/** | ||
* @desc the path to output the compiled file(s) | ||
*/ | ||
outDir: string; | ||
/** | ||
* @desc If true, writes the ESBuild metadata for the compiled file(s) | ||
*/ | ||
writeMeta?: boolean; | ||
} | ||
|
||
// Note: after server start we change the root directory to trick vite | ||
const originalCwd = process.cwd(); | ||
|
||
const cssPlugin: esbuild.Plugin = { | ||
name: 'jsx-email/css-plugin', | ||
setup(builder) { | ||
builder.onLoad({ filter: /\.css$/ }, async (args) => { | ||
const buffer = await readFile(args.path); | ||
const css = await esbuild.transform(buffer, { loader: 'css', minify: false }); | ||
return { contents: css.code, loader: 'text' }; | ||
}); | ||
} | ||
}; | ||
|
||
/** | ||
* @desc Compiles a JSX/TSX template file using esbuild | ||
* @param options CompileOptions | ||
* @returns string[] An array of files affected by the compilation | ||
*/ | ||
export const compile = async (options: CompileOptions) => { | ||
const config = await loadConfig(); | ||
|
||
const { files, hashFiles = true, outDir, writeMeta = false } = options; | ||
const { metafile } = await esbuild.build({ | ||
bundle: true, | ||
define: { | ||
'import.meta.isJsxEmailPreview': JSON.stringify(globalThis.isJsxEmailPreview || false) | ||
}, | ||
entryNames: hashFiles ? '[dir]/[name]-[hash]' : '[dir]/[name]', | ||
entryPoints: files, | ||
jsx: 'automatic', | ||
logLevel: 'error', | ||
metafile: true, | ||
outdir: outDir, | ||
platform: 'node', | ||
plugins: [cssPlugin], | ||
write: true, | ||
...config.esbuild | ||
}); | ||
|
||
const affectedFiles = Object.keys(metafile.outputs); | ||
const affectedPaths = affectedFiles.map((file) => resolve('/', file)); | ||
|
||
if (metafile && writeMeta) { | ||
const { outputs } = metafile; | ||
const ops = Object.entries(outputs).map(async ([path]) => { | ||
const fileName = basename(path, extname(path)); | ||
const metaPath = join(dirname(path), `${fileName}.meta.json`); | ||
const writePath = resolve(originalCwd, metaPath); | ||
const json = JSON.stringify(metafile); | ||
|
||
log.debug('meta writePath:', writePath); | ||
await writeFile(writePath, json, 'utf8'); | ||
}); | ||
await Promise.all(ops); | ||
} | ||
|
||
return affectedPaths; | ||
}; |
Oops, something went wrong.