@lupinum/nuxt-email 1.0.0-beta.3 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +49 -17
- package/THIRD_PARTY_NOTICES +4 -4
- package/dist/agent/AGENTS.md +43 -0
- package/dist/agent/pages/docs/components/code.md +68 -0
- package/dist/agent/pages/docs/components/content.md +111 -0
- package/dist/agent/pages/docs/components/layout.md +89 -0
- package/dist/agent/pages/docs/components/markdown.md +49 -0
- package/dist/agent/pages/docs/components/structure.md +122 -0
- package/dist/agent/pages/docs/components/tailwind.md +41 -0
- package/dist/agent/pages/docs/components.md +56 -0
- package/dist/agent/pages/docs/getting-started/choose-a-tool.md +38 -0
- package/dist/agent/pages/docs/getting-started/first-email.md +99 -0
- package/dist/agent/pages/docs/getting-started/installation.md +85 -0
- package/dist/agent/pages/docs/getting-started/render-from-nitro.md +59 -0
- package/dist/agent/pages/docs/getting-started.md +64 -0
- package/dist/agent/pages/docs/guides/client-compatibility.md +65 -0
- package/dist/agent/pages/docs/guides/plain-text.md +42 -0
- package/dist/agent/pages/docs/guides/preview-workflow.md +83 -0
- package/dist/agent/pages/docs/guides/sending-email.md +132 -0
- package/dist/agent/pages/docs/guides/standalone-rendering.md +118 -0
- package/dist/agent/pages/docs/guides/subject-lines.md +95 -0
- package/dist/agent/pages/docs/guides/tailwind.md +128 -0
- package/dist/agent/pages/docs/guides/testing-your-emails.md +118 -0
- package/dist/agent/pages/docs/guides.md +32 -0
- package/dist/agent/pages/docs/reference/conformance.md +55 -0
- package/dist/agent/pages/docs/reference/define-email.md +69 -0
- package/dist/agent/pages/docs/reference/errors.md +72 -0
- package/dist/agent/pages/docs/reference/migration.md +144 -0
- package/dist/agent/pages/docs/reference/module.md +90 -0
- package/dist/agent/pages/docs/reference/render-email.md +107 -0
- package/dist/agent/pages/docs/reference.md +30 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/EButton.d.ts +1 -1
- package/dist/runtime/tailwind/engine/css/constants.d.ts +1 -0
- package/dist/runtime/tailwind/engine/css/constants.js +1 -0
- package/dist/runtime/tailwind/engine/css/downlevel-for-email-clients.js +2 -1
- package/dist/runtime/tailwind/engine/css/extract-rules-per-class.js +91 -33
- package/dist/runtime/tailwind/engine/css/sanitize-non-inlinable-rules.js +7 -2
- package/dist/runtime/tailwind/engine/stylesheets.d.ts +3 -3
- package/dist/runtime/tailwind/engine/stylesheets.js +141 -34
- package/package.json +23 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#63](https://github.com/lupinum-dev/nuxt-email/pull/63) [`8ceae4a`](https://github.com/lupinum-dev/nuxt-email/commit/8ceae4a7cf9439962e03f01ceb50bffa0b8fdd0f) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix conditional and child utility styles with the current Tailwind compiler, and fail instead of dropping unsupported conditions.
|
|
8
|
+
|
|
9
|
+
`ETailwind` keeps media-query, pseudo-class, child (`*:`, `**:`) and arbitrary selector variants such as `[:where(&)]:` with their conditions. Supported wrappers around a utility are `@media` and `@supports` (`@layer` is ignored). A utility inside any other at-rule now throws, for example `@container` variants (`@sm:`) or custom CSS in the `ETailwind` `utility` prop that wraps a class in `@scope` or `@container`. It throws `Unable to render Tailwind CSS: @<name> rules are not supported.` Before, the condition was dropped silently and the style applied everywhere.
|
|
10
|
+
|
|
11
|
+
Migration: remove `@container` variants (`@sm:`, `@md:` and so on) from email templates, and move custom CSS in the `ETailwind` `utility` prop out of `@container`, `@scope` and other unsupported at-rules, or rewrite the condition with `@media` or `@supports`.
|
|
12
|
+
|
|
13
|
+
## v1.0.0-beta.4
|
|
14
|
+
|
|
15
|
+
[compare changes](https://github.com/lupinum-dev/nuxt-email/compare/v1.0.0-beta.3...v1.0.0-beta.4)
|
|
16
|
+
|
|
17
|
+
### 🚀 Enhancements
|
|
18
|
+
|
|
19
|
+
- **docs:** Ship versioned package guidance ([#55](https://github.com/lupinum-dev/nuxt-email/pull/55))
|
|
20
|
+
|
|
21
|
+
### 🩹 Fixes
|
|
22
|
+
|
|
23
|
+
- **deps:** Clear workspace advisories and update Vitest ([#54](https://github.com/lupinum-dev/nuxt-email/pull/54))
|
|
24
|
+
|
|
25
|
+
### ❤️ Contributors
|
|
26
|
+
|
|
27
|
+
- Matthias Amon
|
|
28
|
+
|
|
3
29
|
## v1.0.0-beta.3
|
|
4
30
|
|
|
5
31
|
[compare changes](https://github.com/lupinum-dev/nuxt-email/compare/v1.0.0-beta.2...v1.0.0-beta.3)
|
package/README.md
CHANGED
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
<a href="https://www.npmjs.com/package/@lupinum/nuxt-email"><img src="https://img.shields.io/npm/v/@lupinum/nuxt-email?color=00DC82" alt="npm version"></a>
|
|
21
21
|
<a href="https://github.com/lupinum-dev/nuxt-email/actions/workflows/ci.yml"><img src="https://github.com/lupinum-dev/nuxt-email/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
|
|
22
22
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-00DC82" alt="MIT license"></a>
|
|
23
|
-
<a href="https://discord.
|
|
23
|
+
<a href="https://discord.lupinum.com"><img src="https://img.shields.io/badge/Discord-18181B?logo=discord" alt="Discord"></a>
|
|
24
24
|
<a href="https://deepwiki.com/lupinum-dev/nuxt-email"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
27
|
> [!WARNING]
|
|
28
|
-
>
|
|
28
|
+
> The 1.0.0 beta is published on npm's [`next` tag](https://www.npmjs.com/package/@lupinum/nuxt-email?activeTab=versions). The [three-client beta smoke test](https://github.com/lupinum-dev/nuxt-email/blob/main/docs/release/client-qa-checklist.md#100-beta1-smoke-test) passed against beta.1; the full eight-client checklist and an external transactional beta still block stable `1.0.0`. The unscoped `nuxt-email` package on npm is unrelated to this project.
|
|
29
29
|
|
|
30
30
|
## Why use Nuxt Email?
|
|
31
31
|
|
|
@@ -113,20 +113,52 @@ export default defineEventHandler(async () => {
|
|
|
113
113
|
|
|
114
114
|
The template name and props are generated from the Vue file. Invalid names and props fail during type checking. Use a sibling fixture to inspect it in `/__email`, then [pass the rendered result to your provider](https://nuxt-email.lupinum.com/docs/guides/sending-email).
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
Questions? Ask in the [Lupinum OSS Discord](https://discord.lupinum.com).
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
what you build.
|
|
118
|
+
## Agent setup
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
`@lupinum/nuxt-email` ships its documentation inside the package for coding
|
|
121
|
+
agents such as Claude Code, Codex and Cursor. The pages match the installed
|
|
122
|
+
version, so an agent does not follow the website for a different version.
|
|
123
|
+
|
|
124
|
+
To set it up, give your coding agent this task:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
Set up @lupinum/nuxt-email for coding agents as described under "Agent setup" in its README.
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Steps for the agent
|
|
131
|
+
|
|
132
|
+
1. Find `node_modules/@lupinum/nuxt-email/dist/agent/AGENTS.md`. Look in the
|
|
133
|
+
directory of the project that depends on `@lupinum/nuxt-email` first, then
|
|
134
|
+
in its parent directories up to the repository root (workspaces can hoist
|
|
135
|
+
packages). Read it; it lists the documentation pages.
|
|
136
|
+
2. Add the section below to the project's agent instructions: `AGENTS.md`, or
|
|
137
|
+
`CLAUDE.md` if the project has only that file. If it has neither, create
|
|
138
|
+
`AGENTS.md`. Write the path relative to the repository root, through
|
|
139
|
+
`node_modules/@lupinum/nuxt-email` (for example
|
|
140
|
+
`apps/web/node_modules/@lupinum/nuxt-email/...` in a workspace). Never write
|
|
141
|
+
a resolved path such as `node_modules/.pnpm/...`: it contains the version and
|
|
142
|
+
breaks after an upgrade. If a section for `@lupinum/nuxt-email` already
|
|
143
|
+
exists, leave it as it is.
|
|
144
|
+
|
|
145
|
+
Use the path you found in place of the sample path:
|
|
146
|
+
|
|
147
|
+
```md
|
|
148
|
+
## @lupinum/nuxt-email
|
|
149
|
+
|
|
150
|
+
Before you change code that uses @lupinum/nuxt-email, read
|
|
151
|
+
`node_modules/@lupinum/nuxt-email/dist/agent/AGENTS.md` and the pages it
|
|
152
|
+
lists. They document the installed version. Prefer them over what you
|
|
153
|
+
remember about this package and over the website.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
3. Do not copy the documentation into the project and do not install a skill.
|
|
157
|
+
The section points into the installed package, so it stays correct after
|
|
158
|
+
every upgrade or downgrade.
|
|
159
|
+
|
|
160
|
+
If the file does not exist, the installed version has no packaged
|
|
161
|
+
documentation. Read the package README and its TypeScript types instead.
|
|
130
162
|
|
|
131
163
|
## Email components
|
|
132
164
|
|
|
@@ -196,7 +228,7 @@ See the [changelog](CHANGELOG.md) for released changes.
|
|
|
196
228
|
|
|
197
229
|
## Contributing and development
|
|
198
230
|
|
|
199
|
-
Read the [contribution guide](https://github.com/lupinum-dev/nuxt-email/blob/main/CONTRIBUTING.md) before you open a pull request. Run the normal handoff gate before you submit a change:
|
|
231
|
+
Read the [contribution guide](https://github.com/lupinum-dev/nuxt-email/blob/main/.github/CONTRIBUTING.md) before you open a pull request. Run the normal handoff gate before you submit a change:
|
|
200
232
|
|
|
201
233
|
```bash
|
|
202
234
|
corepack enable
|
|
@@ -204,11 +236,11 @@ pnpm install --frozen-lockfile
|
|
|
204
236
|
pnpm verify
|
|
205
237
|
```
|
|
206
238
|
|
|
207
|
-
Maintainers use the protected workflow in [
|
|
239
|
+
Maintainers use the protected workflow in [Lupinum OSS](https://oss.lupinum.com/docs/releasing) for releases.
|
|
208
240
|
|
|
209
241
|
## Support and security
|
|
210
242
|
|
|
211
|
-
Open a [GitHub issue](https://github.com/lupinum-dev/nuxt-email/issues) for bugs and focused proposals. Join the [Lupinum OSS Discord](https://discord.
|
|
243
|
+
Open a [GitHub issue](https://github.com/lupinum-dev/nuxt-email/issues) for bugs and focused proposals. Join the [Lupinum OSS Discord](https://discord.lupinum.com) for project discussion.
|
|
212
244
|
|
|
213
245
|
Use the [private security process](https://github.com/lupinum-dev/nuxt-email/security/policy) to report a vulnerability. Do not report a vulnerability in a public issue.
|
|
214
246
|
|
package/THIRD_PARTY_NOTICES
CHANGED
|
@@ -2,12 +2,12 @@ React Email
|
|
|
2
2
|
===========
|
|
3
3
|
|
|
4
4
|
Nuxt Email contains Vue adaptations of selected compatibility algorithms and
|
|
5
|
-
markup strategies from React Email 6.
|
|
6
|
-
|
|
5
|
+
markup strategies from React Email 6.11.0, pinned at source commit
|
|
6
|
+
15419ff1f4cd0e32ed2c15a4a9182cc47a200a60. The adapted surface covers button
|
|
7
7
|
padding and Outlook spacing, text margin expansion, table padding placement,
|
|
8
8
|
hidden preview text, the font-face declaration, inline code rendering, Markdown
|
|
9
9
|
rendering, and Tailwind class inlining. The pinned upstream source is available at
|
|
10
|
-
https://github.com/resend/react-email/tree/
|
|
10
|
+
https://github.com/resend/react-email/tree/15419ff1f4cd0e32ed2c15a4a9182cc47a200a60.
|
|
11
11
|
|
|
12
12
|
Copyright 2024 Plus Five Five, Inc
|
|
13
13
|
|
|
@@ -44,7 +44,7 @@ whose text is reproduced once below.
|
|
|
44
44
|
- css-tree 3.2.1 — CSS parsing and generation in the Tailwind inlining engine.
|
|
45
45
|
Copyright (C) 2016-2026 by Roman Dvornov
|
|
46
46
|
|
|
47
|
-
- tailwindcss 4.
|
|
47
|
+
- tailwindcss 4.3.3 — utility compilation used by ETailwind; its stylesheet CSS
|
|
48
48
|
is also vendored byte-for-byte into the engine.
|
|
49
49
|
Copyright (c) Tailwind Labs, Inc.
|
|
50
50
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @lupinum/nuxt-email 1.0.0-beta.5 documentation
|
|
2
|
+
|
|
3
|
+
These pages document the installed version 1.0.0-beta.5. Prefer them over what you
|
|
4
|
+
remember about this package and over the website, which may describe another version.
|
|
5
|
+
Read the pages that match the task before you write code. If they do not answer a question,
|
|
6
|
+
the user can ask in the Lupinum OSS Discord: https://discord.lupinum.com
|
|
7
|
+
|
|
8
|
+
> Typed transactional email for Nuxt, with email-safe Tailwind v4.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Use this site to author and render transactional email with Nuxt Email.
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
- [Introduction](./pages/docs/getting-started.md): What Nuxt Email is, why its output is trustworthy, and how it is compared with a fixed React Email version.
|
|
17
|
+
- [Choose the right tool](./pages/docs/getting-started/choose-a-tool.md): Compare Nuxt Email with the closest Vue, Nuxt, standalone, and React email workflows.
|
|
18
|
+
- [Installation](./pages/docs/getting-started/installation.md): Add @lupinum/nuxt-email to a supported Nuxt application and optionally configure syntax highlighting.
|
|
19
|
+
- [Your first email](./pages/docs/getting-started/first-email.md): Write a Vue email template under app/emails/, add a typed preview fixture, and understand template naming.
|
|
20
|
+
- [Render from Nitro](./pages/docs/getting-started/render-from-nitro.md): Call the typed, server-only renderEmail auto-import and pass its html and text to your provider SDK.
|
|
21
|
+
- [Overview](./pages/docs/components.md): The built-in E-prefixed components, optional ECodeBlock, and their shared safety rules.
|
|
22
|
+
- [Structure](./pages/docs/components/structure.md): EHtml, EHead, EBody, EPreview, and EFont — the document shell, head, body, inbox preview text, and font declarations.
|
|
23
|
+
- [Layout](./pages/docs/components/layout.md): EContainer, ESection, ERow, and EColumn — presentation-table primitives for stable email layouts.
|
|
24
|
+
- [Content](./pages/docs/components/content.md): EText, EHeading, ELink, EImg, EHr, and EButton for visible email content.
|
|
25
|
+
- [Code](./pages/docs/components/code.md): Compatibility-safe inline code and opt-in syntax-highlighted blocks.
|
|
26
|
+
- [Markdown](./pages/docs/components/markdown.md): EMarkdown renders Markdown to email-safe HTML with inline styles and per-element overrides.
|
|
27
|
+
- [Tailwind](./pages/docs/components/tailwind.md): ETailwind compiles Tailwind v4 utilities into email-safe inline styles and head rules during server rendering.
|
|
28
|
+
- [Guides](./pages/docs/guides.md): Task-focused guides for authoring, previewing, testing, and sending transactional email.
|
|
29
|
+
- [Preview workflow](./pages/docs/guides/preview-workflow.md): Use the development-only /__email preview, add fixtures, and monitor exact rendered size without treating it as a client guarantee.
|
|
30
|
+
- [Sending email](./pages/docs/guides/sending-email.md): Hand Nuxt Email output to a provider SDK or a local Mailpit SMTP server.
|
|
31
|
+
- [Using Tailwind](./pages/docs/guides/tailwind.md): How ETailwind inlines utilities, how nested-component classes are reached, and the exact documented limitations.
|
|
32
|
+
- [Subject lines](./pages/docs/guides/subject-lines.md): Compute a subject line from the same typed props with defineEmail, and read it back from the render result.
|
|
33
|
+
- [Plain text](./pages/docs/guides/plain-text.md): How the plain-text fallback is produced from the rendered HTML, what it excludes, and how to control table output.
|
|
34
|
+
- [Testing your emails](./pages/docs/guides/testing-your-emails.md): Render templates and assert on their output in unit tests with the @lupinum/nuxt-email/testing utilities.
|
|
35
|
+
- [Client compatibility and proofs](./pages/docs/guides/client-compatibility.md): What is automatically proven, and the manual email-client QA checklist that closes the remaining gap.
|
|
36
|
+
- [Render outside Nitro](./pages/docs/guides/standalone-rendering.md): Compile the same Vue templates for a Node backend without booting Nuxt.
|
|
37
|
+
- [Reference](./pages/docs/reference.md): The precise contracts — renderEmail, module behavior, error types, conformance, and migration.
|
|
38
|
+
- [renderEmail](./pages/docs/reference/render-email.md): The one public render API — its signature, deterministic result shape, plain-text contract, and security boundary.
|
|
39
|
+
- [defineEmail](./pages/docs/reference/define-email.md): Declare a template subject or authored plain-text alternative from script setup.
|
|
40
|
+
- [Module behavior](./pages/docs/reference/module.md): What the module registers, its fixed conventions, and the opt-in codeBlock configuration.
|
|
41
|
+
- [Error types](./pages/docs/reference/errors.md): Public error classes, their stable fields, common symptoms, and recovery steps.
|
|
42
|
+
- [Conformance and divergences](./pages/docs/reference/conformance.md): How compatibility is measured against React Email, the current pass numbers, and every intentional divergence.
|
|
43
|
+
- [Migration from React Email](./pages/docs/reference/migration.md): Translate JSX templates, props, and rendering calls to Nuxt Email's Vue single-file components and generated server API.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Code"
|
|
3
|
+
description: "Compatibility-safe inline code and opt-in syntax-highlighted blocks."
|
|
4
|
+
url: "https://nuxt-email.lupinum.com/docs/components/code"
|
|
5
|
+
route: "/docs/components/code"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Code
|
|
13
|
+
|
|
14
|
+
> Compatibility-safe inline code and opt-in syntax-highlighted blocks.
|
|
15
|
+
|
|
16
|
+
## ECodeInline
|
|
17
|
+
|
|
18
|
+
`ECodeInline` renders inline code inside a text flow. Place it inside `EText` (or another text element). It accepts safe HTML attributes and forwards them, plus `style`, to both emitted elements.
|
|
19
|
+
|
|
20
|
+
| Prop | Type | Default | Required |
|
|
21
|
+
| --- | --- | --- | --- |
|
|
22
|
+
| — | No component-specific props; accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). | — | — |
|
|
23
|
+
|
|
24
|
+
It renders three siblings: a `<style>` with the `Orange.fr` webmail compatibility rule, a visible `<code>` element, and a hidden copy `<span>` (`display:none`). The hidden compatibility copy is excluded from plain-text conversion, so recipients receive the code once.
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<EText>
|
|
28
|
+
Run <ECodeInline class="inline-code">pnpm install</ECodeInline> to begin.
|
|
29
|
+
</EText>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## ECodeBlock
|
|
33
|
+
|
|
34
|
+
`ECodeBlock` is available only when `codeBlock` is configured on the Nuxt module. It uses the Shiki syntax highlighter and renders escaped tokens with inline theme colors. The language list is a closed build-time allowlist. Only configured languages and the grammars they import are bundled. A different runtime `language` value throws and lists the enabled languages.
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Default | Required |
|
|
37
|
+
| --- | --- | --- | --- |
|
|
38
|
+
| `code` | `string` | — | Yes |
|
|
39
|
+
| `language` | Configured language union | — | Yes |
|
|
40
|
+
| `lineNumbers` | `boolean` | `false` | No |
|
|
41
|
+
| `fontFamily` | `string` | `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace` | No |
|
|
42
|
+
|
|
43
|
+
Code is escaped before rendering. The language is typed from the configured allowlist and checked again at runtime. Line numbers are decorative and excluded from plain text.
|
|
44
|
+
|
|
45
|
+
```ts [nuxt.config.ts]
|
|
46
|
+
export default defineNuxtConfig({
|
|
47
|
+
modules: ['@lupinum/nuxt-email'],
|
|
48
|
+
nuxtEmail: {
|
|
49
|
+
codeBlock: {
|
|
50
|
+
languages: ['typescript', 'bash'],
|
|
51
|
+
theme: 'github-dark',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<ECodeBlock
|
|
59
|
+
:code="source"
|
|
60
|
+
language="typescript"
|
|
61
|
+
line-numbers
|
|
62
|
+
style="border-radius:8px;padding:16px"
|
|
63
|
+
/>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The configured theme produces concrete inline colors; there is no stylesheet or browser runtime. Author styles are also inline for email-client compatibility. Theme selection is build-time because email clients do not reliably support the CSS-variable approach used for responsive light/dark Shiki themes.
|
|
67
|
+
|
|
68
|
+
Without `codeBlock`, the component is unregistered and Shiki performs no module-setup or production-bundle work. Use the generated `#nuxt-email/testing` binding when testing templates that contain `ECodeBlock`.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Content"
|
|
3
|
+
description: "EText, EHeading, ELink, EImg, EHr, and EButton for visible email content."
|
|
4
|
+
url: "https://nuxt-email.lupinum.com/docs/components/content"
|
|
5
|
+
route: "/docs/components/content"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Content
|
|
13
|
+
|
|
14
|
+
> EText, EHeading, ELink, EImg, EHr, and EButton for visible email content.
|
|
15
|
+
|
|
16
|
+
These components carry the visible content of an email. Layout-sensitive components provide email-safe defaults. `ELink` is visually neutral.
|
|
17
|
+
|
|
18
|
+
## EText
|
|
19
|
+
|
|
20
|
+
`EText` renders a `<p>` with `font-size: 14px`, `line-height: 24px`, and `16px` top and bottom margins. Author styles override these defaults.
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Required |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| — | No component-specific props; accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). | — | — |
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<EText :style="{ color: '#334155' }">Your workspace is ready.</EText>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## EHeading
|
|
31
|
+
|
|
32
|
+
`EHeading` renders a heading element. An unsupported tag fails during rendering.
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Required |
|
|
35
|
+
| --- | --- | --- | --- |
|
|
36
|
+
| `as` | `'h1' \| 'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6'` | `h1` | No |
|
|
37
|
+
|
|
38
|
+
It also accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares).
|
|
39
|
+
|
|
40
|
+
```vue
|
|
41
|
+
<EHeading as="h2">Account ready</EHeading>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## ELink
|
|
45
|
+
|
|
46
|
+
`ELink` renders a visually neutral anchor. It adds no color or text decoration.
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Default | Required |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| `href` | `string` | — | Yes |
|
|
51
|
+
| `target` | Safe native anchor target | `_blank` | No |
|
|
52
|
+
|
|
53
|
+
`href` must be non-empty. The value is escaped, but its URL scheme is not validated. Set visual styles explicitly and validate application-controlled URLs.
|
|
54
|
+
|
|
55
|
+
```vue
|
|
56
|
+
<ELink href="https://example.com/account" style="color:#2563eb">Open account</ELink>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## EImg
|
|
60
|
+
|
|
61
|
+
`EImg` renders an image with block display and no border, outline, or text decoration.
|
|
62
|
+
|
|
63
|
+
| Prop | Type | Default | Required |
|
|
64
|
+
| --- | --- | --- | --- |
|
|
65
|
+
| `src` | `string` | — | Yes |
|
|
66
|
+
| `alt` | `string` | — | Yes |
|
|
67
|
+
|
|
68
|
+
`src` must be non-empty. Use `alt=""` for a decorative image. The URL is serialized but never fetched. Safe image attributes such as `width` and `height` are accepted.
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<EImg src="https://example.com/logo.png" alt="Example" width="120" height="32" />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## EHr
|
|
75
|
+
|
|
76
|
+
`EHr` renders a full-width horizontal rule with a transparent border and a `1px solid #eaeaea` top border. Author styles override individual defaults.
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Required |
|
|
79
|
+
| --- | --- | --- | --- |
|
|
80
|
+
| — | No component-specific props; accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). | — | — |
|
|
81
|
+
|
|
82
|
+
```vue
|
|
83
|
+
<EHr :style="{ borderTopColor: '#cbd5e1' }" />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## EButton
|
|
87
|
+
|
|
88
|
+
`EButton` renders an anchor with conditional Outlook spacer markup. The spacer keeps its padding usable in Outlook for Windows.
|
|
89
|
+
|
|
90
|
+
| Prop | Type | Default | Required |
|
|
91
|
+
| --- | --- | --- | --- |
|
|
92
|
+
| `href` | `string` | — | Yes |
|
|
93
|
+
| `target` | Safe native anchor target | `_blank` | No |
|
|
94
|
+
| `style` | Vue style value | Email-safe anchor defaults | No |
|
|
95
|
+
|
|
96
|
+
The default style uses `line-height: 100%`, no text decoration, inline-block display, and `max-width: 100%`. It also sets the Outlook-specific `mso-padding-alt` property to `0px`. Author styles override these values.
|
|
97
|
+
|
|
98
|
+
Padding accepts finite non-negative numbers or `px`, `em`, `rem`, and `%` values. Shorthand accepts one to four values. Invalid units, negative or non-finite values, and output large enough to inflate the message fail during rendering.
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<EButton
|
|
102
|
+
href="https://example.com/activate"
|
|
103
|
+
:style="{ backgroundColor: '#0f5132', color: '#fff', padding: '12px 20px' }"
|
|
104
|
+
>
|
|
105
|
+
Activate account
|
|
106
|
+
</EButton>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
<card title="Client notes" icon="lucide:mail">
|
|
110
|
+
Remote images are often blocked, so always provide useful alternative text. Outlook for Windows ignores CSS padding on inline anchors; `EButton` supplies conditional spacer markup for that client. Verify both behaviors during [manual QA](/raw/docs/guides/client-compatibility.md).
|
|
111
|
+
</card>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Layout"
|
|
3
|
+
description: "EContainer, ESection, ERow, and EColumn — presentation-table primitives for stable email layouts."
|
|
4
|
+
url: "https://nuxt-email.lupinum.com/docs/components/layout"
|
|
5
|
+
route: "/docs/components/layout"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Layout
|
|
13
|
+
|
|
14
|
+
> EContainer, ESection, ERow, and EColumn — presentation-table primitives for stable email layouts.
|
|
15
|
+
|
|
16
|
+
These components use presentation tables for email-client compatibility.
|
|
17
|
+
|
|
18
|
+
## EContainer
|
|
19
|
+
|
|
20
|
+
`EContainer` renders a centered presentation table for bounded content. It defaults to `align="center"`, `width="100%"`, and a maximum width of `37.5em`. Its fixed attributes are `border="0"`, `cellpadding="0"`, `cellspacing="0"`, and `role="presentation"`.
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Required |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| — | No component-specific props; accepts safe table attributes except the fixed attributes above. | — | — |
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<EContainer :style="{ maxWidth: '600px' }">Content</EContainer>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## ESection
|
|
31
|
+
|
|
32
|
+
`ESection` renders a full-width presentation table with one inner cell.
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Required |
|
|
35
|
+
| --- | --- | --- | --- |
|
|
36
|
+
| — | No component-specific props; accepts safe table attributes except `border`, `cellpadding`, `cellspacing`, and `role`. | — | — |
|
|
37
|
+
|
|
38
|
+
```vue
|
|
39
|
+
<ESection :style="{ padding: '16px' }">Content</ESection>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## ERow
|
|
43
|
+
|
|
44
|
+
`ERow` renders a full-width presentation table whose row receives its default slot. Put `EColumn` components directly in the slot.
|
|
45
|
+
|
|
46
|
+
| Prop | Type | Default | Required |
|
|
47
|
+
| --- | --- | --- | --- |
|
|
48
|
+
| — | No component-specific props; accepts safe table attributes except `border`, `cellpadding`, `cellspacing`, and `role`. | — | — |
|
|
49
|
+
|
|
50
|
+
```vue
|
|
51
|
+
<ERow><EColumn>Content</EColumn></ERow>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## EColumn
|
|
55
|
+
|
|
56
|
+
`EColumn` renders a `<td>` cell. It has no default width and adds no synthetic React marker.
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Required |
|
|
59
|
+
| --- | --- | --- | --- |
|
|
60
|
+
| — | No component-specific props; accepts safe cell attributes such as `width`, `colspan`, alignment, and `style`. | — | — |
|
|
61
|
+
|
|
62
|
+
```vue
|
|
63
|
+
<EColumn width="50%">Left</EColumn>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Padding placement
|
|
67
|
+
|
|
68
|
+
`EContainer`, `ESection`, and `ERow` move physical padding known at render time to a `<td>`. This includes author styles and non-variant Tailwind utilities. Responsive and pseudo-class utilities remain CSS rules because they have no single inline value. Put responsive padding on an inner `EColumn` and verify the target clients.
|
|
69
|
+
|
|
70
|
+
`ERow` adds its padding wrapper only when physical padding exists. Logical padding properties remain on the table.
|
|
71
|
+
|
|
72
|
+
## Fixed presentation attributes
|
|
73
|
+
|
|
74
|
+
`EContainer`, `ESection`, and `ERow` reject overrides for `border`, `cellpadding`, `cellspacing`, and `role`, including alternate casing. Use `style` when you need a visual border. This deliberate [divergence](/raw/docs/reference/conformance.md) prevents silently broken layout semantics.
|
|
75
|
+
|
|
76
|
+
```vue
|
|
77
|
+
<EContainer :style="{ maxWidth: '600px', padding: '24px' }">
|
|
78
|
+
<ESection :style="{ padding: '16px 20px' }">
|
|
79
|
+
<ERow>
|
|
80
|
+
<EColumn width="50%">Left</EColumn>
|
|
81
|
+
<EColumn width="50%">Right</EColumn>
|
|
82
|
+
</ERow>
|
|
83
|
+
</ESection>
|
|
84
|
+
</EContainer>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<card title="Client note: Outlook columns" icon="lucide:columns-3">
|
|
88
|
+
Columns remain table cells in Outlook for Windows. Give them explicit widths and verify narrow layouts in your [client QA](/raw/docs/guides/client-compatibility.md).
|
|
89
|
+
</card>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Markdown"
|
|
3
|
+
description: "EMarkdown renders Markdown to email-safe HTML with inline styles and per-element overrides."
|
|
4
|
+
url: "https://nuxt-email.lupinum.com/docs/components/markdown"
|
|
5
|
+
route: "/docs/components/markdown"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Markdown
|
|
13
|
+
|
|
14
|
+
> EMarkdown renders Markdown to email-safe HTML with inline styles and per-element overrides.
|
|
15
|
+
|
|
16
|
+
## EMarkdown
|
|
17
|
+
|
|
18
|
+
`EMarkdown` renders Markdown to email-safe HTML with inline styles. It is useful when content comes from a content management system (CMS) rather than Vue markup.
|
|
19
|
+
|
|
20
|
+
| Prop | Type | Default | Required |
|
|
21
|
+
| --- | --- | --- | --- |
|
|
22
|
+
| `source` | `string` | Text-only default slot | No |
|
|
23
|
+
| `markdownCustomStyles` | Per-element style map | Built-in email-safe styles | No |
|
|
24
|
+
|
|
25
|
+
When `source` is a string, it takes precedence over the default slot. Custom styles merge over the defaults.
|
|
26
|
+
|
|
27
|
+
Raw HTML is rejected, including HTML comments. Links and images accept relative URLs plus `http`, `https`, `mailto`, `tel`, and `cid`; other schemes are rejected after HTML-entity and control-character normalization. HTML-looking text inside code spans and fences is escaped. This keeps Markdown from becoming an implicit raw-HTML escape hatch.
|
|
28
|
+
|
|
29
|
+
The rendered container accepts Vue's normal `class`, `style`, and safe HTML attributes. Use ordinary string, object, or array `style` values; include CSS units explicitly for dimensional values such as padding.
|
|
30
|
+
|
|
31
|
+
The default slot must contain **text only**; an element child throws a `TypeError` rather than being silently stringified. Links render with `target="_blank"`, and tables render with `role="presentation"`.
|
|
32
|
+
|
|
33
|
+
```vue
|
|
34
|
+
<EMarkdown source="# Title\n\nA paragraph with a [link](https://example.com)." />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
With overrides:
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<EMarkdown
|
|
41
|
+
:source="body"
|
|
42
|
+
:markdown-custom-styles="{ h1: { color: '#0f172a' }, a: { color: '#2563eb' } }"
|
|
43
|
+
:style="{ padding: '0 24px' }"
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
<card title="Divergence: no data-id marker" icon="lucide:git-compare">
|
|
48
|
+
Unlike React Email, the container omits the `data-id="react-email-markdown"` marker (the same no-data-id divergence as `EColumn`). No Vue behavior consumes the marker. See the [conformance report](/raw/docs/reference/conformance.md).
|
|
49
|
+
</card>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Structure"
|
|
3
|
+
description: "EHtml, EHead, EBody, EPreview, and EFont — the document shell, head, body, inbox preview text, and font declarations."
|
|
4
|
+
url: "https://nuxt-email.lupinum.com/docs/components/structure"
|
|
5
|
+
route: "/docs/components/structure"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Structure
|
|
13
|
+
|
|
14
|
+
> EHtml, EHead, EBody, EPreview, and EFont — the document shell, head, body, inbox preview text, and font declarations.
|
|
15
|
+
|
|
16
|
+
These components form the email document shell. Every render must contain exactly one `<html>` root and one `<body>`.
|
|
17
|
+
|
|
18
|
+
## EHtml
|
|
19
|
+
|
|
20
|
+
`EHtml` renders the required document root.
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Required |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| `lang` | `string` | — | Yes |
|
|
25
|
+
| `dir` | Safe native `dir` value | `ltr` | No |
|
|
26
|
+
|
|
27
|
+
`lang` must be a non-empty string. `EHtml` also accepts the [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares).
|
|
28
|
+
|
|
29
|
+
```vue
|
|
30
|
+
<EHtml lang="en"><EBody>Content</EBody></EHtml>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## EHead
|
|
34
|
+
|
|
35
|
+
`EHead` renders `<head>`. It inserts the UTF-8 content-type and Apple message-reformatting meta tags before its default slot. Put `<title>`, `EFont`, and other email head content in that slot.
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Default | Required |
|
|
38
|
+
| --- | --- | --- | --- |
|
|
39
|
+
| — | No component-specific props; accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). | — | — |
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<EHead><title>Order confirmed</title></EHead>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## EBody
|
|
46
|
+
|
|
47
|
+
`EBody` renders `<body>` and a full-width presentation table. Author styles apply to the inner cell. Background values mirror to `<body>`, where supplied margin and padding reset properties become zero.
|
|
48
|
+
|
|
49
|
+
| Prop | Type | Default | Required |
|
|
50
|
+
| --- | --- | --- | --- |
|
|
51
|
+
| `lang` | Safe native `lang` value | `en` | No |
|
|
52
|
+
| `dir` | Safe native `dir` value | `ltr` | No |
|
|
53
|
+
|
|
54
|
+
`EBody` accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). Its language and direction do not inherit from `EHtml`; set both wrappers when the email uses another language or right-to-left text.
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<EBody :style="{ backgroundColor: '#f5f5f5' }">Content</EBody>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```vue
|
|
61
|
+
<EHtml lang="ar" dir="rtl">
|
|
62
|
+
<EHead>
|
|
63
|
+
<title>تم تأكيد الطلب</title>
|
|
64
|
+
</EHead>
|
|
65
|
+
<EBody lang="ar" dir="rtl">
|
|
66
|
+
<EText>تم تأكيد طلبك.</EText>
|
|
67
|
+
</EBody>
|
|
68
|
+
</EHtml>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Localization and right-to-left text
|
|
72
|
+
|
|
73
|
+
Keep localization in application code. Either create one literal template per locale, such as `welcome/en` and `welcome/ar`, or pass already-resolved strings through typed props. Do not call application-context internationalization composables inside an email template. Email templates render in an isolated server application.
|
|
74
|
+
|
|
75
|
+
Set matching `lang` and `dir` values on both `EHtml` and `EBody`, as shown above. The wrappers do not inherit these values from one another.
|
|
76
|
+
|
|
77
|
+
## EPreview
|
|
78
|
+
|
|
79
|
+
`EPreview` renders hidden inbox-preview text from a text-only default slot.
|
|
80
|
+
|
|
81
|
+
| Prop | Type | Default | Required |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| — | No component-specific props; accepts [shared safe native attributes](/raw/docs/components.md#rules-every-component-shares). | — | — |
|
|
84
|
+
|
|
85
|
+
Preview text is safely truncated at 200 UTF-16 code units. Compatibility filler is added when the text is shorter. Author styles cannot make the preview visible, and the preview is excluded from derived plain text.
|
|
86
|
+
|
|
87
|
+
```vue
|
|
88
|
+
<EPreview>Your order is confirmed.</EPreview>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use an explicit `<title>` inside `EHead`. `EPreview` does not generate or move a title into the head. This is an [intentional divergence](/raw/docs/reference/conformance.md).
|
|
92
|
+
|
|
93
|
+
## EFont
|
|
94
|
+
|
|
95
|
+
`EFont` declares an `@font-face` and a document-wide default font. Place it inside `EHead`.
|
|
96
|
+
|
|
97
|
+
| Prop | Type | Default | Required |
|
|
98
|
+
| --- | --- | --- | --- |
|
|
99
|
+
| `fontFamily` | `string` | — | Yes |
|
|
100
|
+
| `fallbackFontFamily` | `FontFallback \| readonly [FontFallback, ...FontFallback[]]` | — | Yes |
|
|
101
|
+
| `webFont` | `{ url: string, format: FontFormat }` | — | No |
|
|
102
|
+
| `fontStyle` | `'normal' \| 'italic' \| 'oblique'` | `normal` | No |
|
|
103
|
+
| `fontWeight` | `number \| 'normal' \| 'bold' \| 'bolder' \| 'lighter'` | `400` | No |
|
|
104
|
+
|
|
105
|
+
Supported fallbacks are `Arial`, `Helvetica`, `Verdana`, `Georgia`, `Times New Roman`, `serif`, `sans-serif`, `monospace`, `cursive`, and `fantasy`. Numeric weights must be from 1 through 1000. Web-font formats are `woff`, `woff2`, `truetype`, `opentype`, `embedded-opentype`, and `svg`.
|
|
106
|
+
|
|
107
|
+
`EFont` emits one `<style>` with the font-face rule and a global font stack. Outlook uses the first fallback through its specific `mso-font-alt` property. Invalid or empty values fail during rendering.
|
|
108
|
+
|
|
109
|
+
```vue
|
|
110
|
+
<EHead>
|
|
111
|
+
<EFont
|
|
112
|
+
font-family="Roboto"
|
|
113
|
+
:fallback-font-family="['Verdana', 'sans-serif']"
|
|
114
|
+
:web-font="{ url: 'https://fonts.example.com/roboto.woff2', format: 'woff2' }"
|
|
115
|
+
:font-weight="700"
|
|
116
|
+
/>
|
|
117
|
+
</EHead>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
<card title="Client note" icon="lucide:mail">
|
|
121
|
+
Only some clients honor web fonts. Choose a fallback stack that resembles the primary font and verify it in the clients you support.
|
|
122
|
+
</card>
|