@mjmx/core 1.0.0
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/LICENSE +21 -0
- package/README.md +191 -0
- package/dist/chunk-SUL5BGGO.js +44 -0
- package/dist/chunk-SUL5BGGO.js.map +1 -0
- package/dist/index.cjs +147 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime-Dg-2Ex6t.d.cts +435 -0
- package/dist/jsx-dev-runtime-Dg-2Ex6t.d.ts +435 -0
- package/dist/jsx-dev-runtime.cjs +70 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.cts +1 -0
- package/dist/jsx-dev-runtime.d.ts +1 -0
- package/dist/jsx-dev-runtime.js +12 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +68 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.d.cts +1 -0
- package/dist/jsx-runtime.d.ts +1 -0
- package/dist/jsx-runtime.js +11 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/package.json +99 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dmitry Kudryavtsev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# mjmx
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<code>mjmx</code> is a JSX runtime to generate <a href="https://mjml.io/" target="_blank">mjml</a> strings.
|
|
5
|
+
<br/><br/>
|
|
6
|
+
<b>No dependency on react</b>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
> This project was developed with the help of [Claude Code](https://claude.ai/).
|
|
10
|
+
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Usage](#usage)
|
|
15
|
+
- [API](#api)
|
|
16
|
+
- [`render(mjml, options?)`](#rendermjml-options)
|
|
17
|
+
- [`serialize(node)`](#serializenode)
|
|
18
|
+
- [Render Options](#render-options)
|
|
19
|
+
- [Note on `mj-include`](#note-on-mj-include)
|
|
20
|
+
- [Strict Types](#strict-types)
|
|
21
|
+
- [Motivation](#motivation)
|
|
22
|
+
- [Why there is no preview server?](#why-there-is-no-preview-server)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @mjmx/core
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
Configure your `tsconfig.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"compilerOptions": {
|
|
38
|
+
"jsx": "react-jsx",
|
|
39
|
+
"jsxImportSource": "@mjmx/core"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or use the pragma comment:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
/** @jsxImportSource @mjmx/core */
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Example
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { render } from '@mjmx/core';
|
|
54
|
+
|
|
55
|
+
const Email = ({ name }: { name: string }) => (
|
|
56
|
+
<mjml>
|
|
57
|
+
<mj-body>
|
|
58
|
+
<mj-section>
|
|
59
|
+
<mj-column>
|
|
60
|
+
<mj-text font-size="20px" color="#333">
|
|
61
|
+
Hello {name}!
|
|
62
|
+
</mj-text>
|
|
63
|
+
<mj-button href="https://example.com">Click me</mj-button>
|
|
64
|
+
</mj-column>
|
|
65
|
+
</mj-section>
|
|
66
|
+
</mj-body>
|
|
67
|
+
</mjml>
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const { html, errors } = render(<Email name="World" />);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### `render(mjml, options?)`
|
|
76
|
+
|
|
77
|
+
Renders an MJML node or string to HTML.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
const { html, errors } = render(<mjml>...</mjml>);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### `serialize(node)`
|
|
84
|
+
|
|
85
|
+
Converts an MJML AST node to an MJML XML string.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const mjmlString = serialize(<mjml>...</mjml>);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Render Options
|
|
92
|
+
|
|
93
|
+
Options are passed directly to `mjml2html`:
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
render(email, {
|
|
97
|
+
validationLevel: 'strict' | 'soft' | 'skip',
|
|
98
|
+
// ...
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Note on `mj-include`
|
|
103
|
+
|
|
104
|
+
The `mj-include` tag is supported, but is often redundant when using JSX since you can compose components directly:
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
// Instead of mj-include, just use JSX composition
|
|
108
|
+
const Header = () => <mj-section>...</mj-section>;
|
|
109
|
+
const Email = () => (
|
|
110
|
+
<mjml>
|
|
111
|
+
<mj-body>
|
|
112
|
+
<Header />
|
|
113
|
+
</mj-body>
|
|
114
|
+
</mjml>
|
|
115
|
+
);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
If you do use `mj-include`, ensure the `path` attribute points to a valid file path that will be resolvable when `mjml2html` processes the output. Paths are relative to the working directory where the MJML renderer is invoked, not relative to your source files.
|
|
119
|
+
|
|
120
|
+
## Strict Types
|
|
121
|
+
|
|
122
|
+
Attributes use template literal types for better autocomplete:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
// CSS units
|
|
126
|
+
<mj-text font-size="16px" padding="10px 20px">
|
|
127
|
+
|
|
128
|
+
// Colors
|
|
129
|
+
<mj-section background-color="#f4f4f4">
|
|
130
|
+
|
|
131
|
+
// Percentages for widths
|
|
132
|
+
<mj-column width="50%">
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Motivation
|
|
136
|
+
|
|
137
|
+
There is [react.email](https://react.email/) and [mjml-react](https://github.com/Faire/mjml-react).
|
|
138
|
+
The first one, reimplement email HTML logic from scratch, rather than relying on a battle tested `mjml` library.
|
|
139
|
+
But more importantly, both `react.email` and `mjml-react` depend on `react` and `react-dom` for no obvious reason.
|
|
140
|
+
|
|
141
|
+
`mjmx` takes a different approach, no dependency on React at all, instead implementing its own AST and JSX Runtime.
|
|
142
|
+
It's a perfect companion library for someone who uses server rendered templates with something like [@kitajs/html](https://github.com/kitajs/html).
|
|
143
|
+
And in fact, `mjmx` was inspired by `@kitajs/html`.
|
|
144
|
+
|
|
145
|
+
Under the hood, it's pure string manipulation.
|
|
146
|
+
So a code like this:
|
|
147
|
+
|
|
148
|
+
```jsx
|
|
149
|
+
const node = <mj-text font-size="16px">Hello</mj-text>;
|
|
150
|
+
console.log(serialize(node));
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Will simply output
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
<mj-text font-size="16px">Hello</mj-text>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The alternative is to use `mjml` directly, with something like `handlebars` for light templating.
|
|
160
|
+
With the `mjml` CLI you will be able to compile `.hbs.mjml` MJML files into `.hbs` HTML files during CI/CD, hence saving the runtime evaluation and parsing of MJML.
|
|
161
|
+
Then, you will load the compiled HTML + handlebars template, and compile it into a JS function.
|
|
162
|
+
Handlebars templates are pretty fast.
|
|
163
|
+
This setup will eliminate the need to depend on mjml, or evaluating mjml template in runtime.
|
|
164
|
+
However, you will lose:
|
|
165
|
+
|
|
166
|
+
1. Fast iteration - you will have to compile templates ahead of time, or setup a watch process to make sure your backend is reloaded when templates change
|
|
167
|
+
2. Type safety - while `mjml` is able to compile and validate templates, there is no way to generate type-safe handlebars calls, so if you mistype a variable, handlebars will either throw an error if running in strict mode, or will simply render an empty string
|
|
168
|
+
3. Complex logic - writing complex handlebars logic inside mjml files is... cumbersome
|
|
169
|
+
|
|
170
|
+
It's up to you to decide what trade-offs you want.
|
|
171
|
+
|
|
172
|
+
I used to roll with mjml+handlebars for years, but as I value type-safety and faster iteration, I decided to build this library to complement my usage of `@kitajs/html` with a similar tool, without pulling react dependencies.
|
|
173
|
+
|
|
174
|
+
## Why there is no preview server?
|
|
175
|
+
|
|
176
|
+
Being able to preview your emails is a must.
|
|
177
|
+
We all hate the `Hello {{valuedCustomer}}` type of emails.
|
|
178
|
+
However, making a dev server with preview endpoint that will satisfy everyone, is a complicated task.
|
|
179
|
+
For starters, you need to deal with things like subject or what props to pass.
|
|
180
|
+
Sure, you could hard-code some preview props, like Ruby on Rails does, but everyone probably have a different setup for that.
|
|
181
|
+
And then, you get into territory like `i18n`.
|
|
182
|
+
|
|
183
|
+
It's impossible to get this right for every use-case, so I think it's better you implement one yourself.
|
|
184
|
+
My preview server is about 300 lines of code, and with LLMs, you can generate it with one comprehensive prompt.
|
|
185
|
+
So I prefer to keep this library lean, and focus only on generating mjml from JSX, without all other nonsense.
|
|
186
|
+
|
|
187
|
+
I am, however, open to PRs, and might consider it.
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/ast.ts
|
|
2
|
+
var MJML_NODE_TYPE = /* @__PURE__ */ Symbol.for("mjmx.node");
|
|
3
|
+
var Fragment = /* @__PURE__ */ Symbol.for("mjmx.fragment");
|
|
4
|
+
function isMjmlNode(value) {
|
|
5
|
+
return typeof value === "object" && value !== null && "$$typeof" in value && value.$$typeof === MJML_NODE_TYPE;
|
|
6
|
+
}
|
|
7
|
+
function createNode(tag, attributes, children) {
|
|
8
|
+
const stringAttributes = {};
|
|
9
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
10
|
+
if (value === void 0 || value === null) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (value instanceof URL) {
|
|
14
|
+
stringAttributes[key] = value.toString();
|
|
15
|
+
} else {
|
|
16
|
+
stringAttributes[key] = String(value);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
$$typeof: MJML_NODE_TYPE,
|
|
21
|
+
tag,
|
|
22
|
+
attributes: stringAttributes,
|
|
23
|
+
children
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/jsx-runtime.ts
|
|
28
|
+
function jsx(tag, props, _key) {
|
|
29
|
+
if (typeof tag === "function") {
|
|
30
|
+
return tag(props);
|
|
31
|
+
}
|
|
32
|
+
const { children, ...attributes } = props;
|
|
33
|
+
const childArray = children === void 0 ? [] : Array.isArray(children) ? children : [children];
|
|
34
|
+
return createNode(tag, attributes, childArray);
|
|
35
|
+
}
|
|
36
|
+
var jsxs = jsx;
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
Fragment,
|
|
40
|
+
isMjmlNode,
|
|
41
|
+
jsx,
|
|
42
|
+
jsxs
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=chunk-SUL5BGGO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ast.ts","../src/jsx-runtime.ts"],"sourcesContent":["export const MJML_NODE_TYPE = Symbol.for('mjmx.node');\n\nexport const Fragment = Symbol.for('mjmx.fragment');\n\nexport interface MjmlNode {\n readonly $$typeof: typeof MJML_NODE_TYPE;\n readonly tag: string | typeof Fragment;\n readonly attributes: Record<string, string | undefined>;\n readonly children: MjmlChild[];\n}\n\nexport type MjmlChild =\n | MjmlNode\n | string\n | number\n | boolean\n | null\n | undefined\n | MjmlChild[];\n\nexport function isMjmlNode(value: unknown): value is MjmlNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value &&\n value.$$typeof === MJML_NODE_TYPE\n );\n}\n\nexport function createNode(\n tag: string | typeof Fragment,\n attributes: Record<string, unknown>,\n children: MjmlChild[]\n): MjmlNode {\n const stringAttributes: Record<string, string | undefined> = {};\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n if (value instanceof URL) {\n stringAttributes[key] = value.toString();\n } else {\n stringAttributes[key] = String(value);\n }\n }\n\n return {\n $$typeof: MJML_NODE_TYPE,\n tag,\n attributes: stringAttributes,\n children,\n };\n}\n","import { createNode, Fragment, type MjmlChild, type MjmlNode } from './ast';\nimport type {\n MjAccordionAttributes,\n MjAccordionElementAttributes,\n MjAccordionTextAttributes,\n MjAccordionTitleAttributes,\n MjAllAttributes,\n MjAttributesAttributes,\n MjBodyAttributes,\n MjBreakpointAttributes,\n MjButtonAttributes,\n MjCarouselAttributes,\n MjCarouselImageAttributes,\n MjClassAttributes,\n MjColumnAttributes,\n MjDividerAttributes,\n MjFontAttributes,\n MjGroupAttributes,\n MjHeadAttributes,\n MjHeroAttributes,\n MjHtmlAttributeAttributes,\n MjHtmlAttributesAttributes,\n MjImageAttributes,\n MjIncludeAttributes,\n MjmlAttributes,\n MjNavbarAttributes,\n MjNavbarLinkAttributes,\n MjPreviewAttributes,\n MjRawAttributes,\n MjSectionAttributes,\n MjSelectorAttributes,\n MjSocialAttributes,\n MjSocialElementAttributes,\n MjSpacerAttributes,\n MjStyleAttributes,\n MjTableAttributes,\n MjTextAttributes,\n MjTitleAttributes,\n MjWrapperAttributes,\n} from './types';\n\nexport { Fragment };\n\ntype PropsWithChildren<T = object> = T & { children?: MjmlChild };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Component = (props: any) => MjmlNode;\n\nexport function jsx(\n tag: string | typeof Fragment | Component,\n props: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _key?: string\n): MjmlNode {\n if (typeof tag === 'function') {\n return tag(props);\n }\n\n const { children, ...attributes } = props;\n\n const childArray: MjmlChild[] =\n children === undefined\n ? []\n : Array.isArray(children)\n ? children\n : [children as MjmlChild];\n\n return createNode(tag, attributes, childArray);\n}\n\nexport const jsxs = jsx;\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace JSX {\n export type Element = MjmlNode;\n export type ElementType = string | typeof Fragment | Component;\n\n export interface ElementChildrenAttribute {\n children: MjmlChild;\n }\n\n export interface IntrinsicElements {\n mjml: PropsWithChildren<MjmlAttributes>;\n 'mj-head': PropsWithChildren<MjHeadAttributes>;\n 'mj-body': PropsWithChildren<MjBodyAttributes>;\n 'mj-attributes': PropsWithChildren<MjAttributesAttributes>;\n 'mj-breakpoint': MjBreakpointAttributes;\n 'mj-font': MjFontAttributes;\n 'mj-html-attributes': PropsWithChildren<MjHtmlAttributesAttributes>;\n 'mj-preview': PropsWithChildren<MjPreviewAttributes>;\n 'mj-style': PropsWithChildren<MjStyleAttributes>;\n 'mj-title': PropsWithChildren<MjTitleAttributes>;\n 'mj-all': MjAllAttributes;\n 'mj-class': MjClassAttributes;\n 'mj-section': PropsWithChildren<MjSectionAttributes>;\n 'mj-column': PropsWithChildren<MjColumnAttributes>;\n 'mj-group': PropsWithChildren<MjGroupAttributes>;\n 'mj-wrapper': PropsWithChildren<MjWrapperAttributes>;\n 'mj-text': PropsWithChildren<MjTextAttributes>;\n 'mj-button': PropsWithChildren<MjButtonAttributes>;\n 'mj-image': MjImageAttributes;\n 'mj-divider': MjDividerAttributes;\n 'mj-spacer': MjSpacerAttributes;\n 'mj-table': PropsWithChildren<MjTableAttributes>;\n 'mj-raw': PropsWithChildren<MjRawAttributes>;\n 'mj-hero': PropsWithChildren<MjHeroAttributes>;\n 'mj-accordion': PropsWithChildren<MjAccordionAttributes>;\n 'mj-accordion-element': PropsWithChildren<MjAccordionElementAttributes>;\n 'mj-accordion-title': PropsWithChildren<MjAccordionTitleAttributes>;\n 'mj-accordion-text': PropsWithChildren<MjAccordionTextAttributes>;\n 'mj-carousel': PropsWithChildren<MjCarouselAttributes>;\n 'mj-carousel-image': MjCarouselImageAttributes;\n 'mj-navbar': PropsWithChildren<MjNavbarAttributes>;\n 'mj-navbar-link': PropsWithChildren<MjNavbarLinkAttributes>;\n 'mj-social': PropsWithChildren<MjSocialAttributes>;\n 'mj-social-element': PropsWithChildren<MjSocialElementAttributes>;\n 'mj-include': MjIncludeAttributes;\n 'mj-selector': PropsWithChildren<MjSelectorAttributes>;\n 'mj-html-attribute': PropsWithChildren<MjHtmlAttributeAttributes>;\n }\n}\n"],"mappings":";AAAO,IAAM,iBAAiB,uBAAO,IAAI,WAAW;AAE7C,IAAM,WAAW,uBAAO,IAAI,eAAe;AAkB3C,SAAS,WAAW,OAAmC;AAC5D,SACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,MAAM,aAAa;AAEvB;AAEO,SAAS,WACd,KACA,YACA,UACU;AACV,QAAM,mBAAuD,CAAC;AAE9D,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AACA,QAAI,iBAAiB,KAAK;AACxB,uBAAiB,GAAG,IAAI,MAAM,SAAS;AAAA,IACzC,OAAO;AACL,uBAAiB,GAAG,IAAI,OAAO,KAAK;AAAA,IACtC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,EACF;AACF;;;ACLO,SAAS,IACd,KACA,OAEA,MACU;AACV,MAAI,OAAO,QAAQ,YAAY;AAC7B,WAAO,IAAI,KAAK;AAAA,EAClB;AAEA,QAAM,EAAE,UAAU,GAAG,WAAW,IAAI;AAEpC,QAAM,aACJ,aAAa,SACT,CAAC,IACD,MAAM,QAAQ,QAAQ,IACpB,WACA,CAAC,QAAqB;AAE9B,SAAO,WAAW,KAAK,YAAY,UAAU;AAC/C;AAEO,IAAM,OAAO;","names":[]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Fragment: () => Fragment,
|
|
34
|
+
jsx: () => jsx,
|
|
35
|
+
jsxs: () => jsxs,
|
|
36
|
+
render: () => render,
|
|
37
|
+
serialize: () => serialize
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
|
|
41
|
+
// src/ast.ts
|
|
42
|
+
var MJML_NODE_TYPE = /* @__PURE__ */ Symbol.for("mjmx.node");
|
|
43
|
+
var Fragment = /* @__PURE__ */ Symbol.for("mjmx.fragment");
|
|
44
|
+
function isMjmlNode(value) {
|
|
45
|
+
return typeof value === "object" && value !== null && "$$typeof" in value && value.$$typeof === MJML_NODE_TYPE;
|
|
46
|
+
}
|
|
47
|
+
function createNode(tag, attributes, children) {
|
|
48
|
+
const stringAttributes = {};
|
|
49
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
50
|
+
if (value === void 0 || value === null) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (value instanceof URL) {
|
|
54
|
+
stringAttributes[key] = value.toString();
|
|
55
|
+
} else {
|
|
56
|
+
stringAttributes[key] = String(value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
$$typeof: MJML_NODE_TYPE,
|
|
61
|
+
tag,
|
|
62
|
+
attributes: stringAttributes,
|
|
63
|
+
children
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/jsx-runtime.ts
|
|
68
|
+
function jsx(tag, props, _key) {
|
|
69
|
+
if (typeof tag === "function") {
|
|
70
|
+
return tag(props);
|
|
71
|
+
}
|
|
72
|
+
const { children, ...attributes } = props;
|
|
73
|
+
const childArray = children === void 0 ? [] : Array.isArray(children) ? children : [children];
|
|
74
|
+
return createNode(tag, attributes, childArray);
|
|
75
|
+
}
|
|
76
|
+
var jsxs = jsx;
|
|
77
|
+
|
|
78
|
+
// src/render.ts
|
|
79
|
+
var import_mjml = __toESM(require("mjml"), 1);
|
|
80
|
+
|
|
81
|
+
// src/serialize.ts
|
|
82
|
+
var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
|
|
83
|
+
"mj-all",
|
|
84
|
+
"mj-breakpoint",
|
|
85
|
+
"mj-carousel-image",
|
|
86
|
+
"mj-class",
|
|
87
|
+
"mj-divider",
|
|
88
|
+
"mj-font",
|
|
89
|
+
"mj-image",
|
|
90
|
+
"mj-include",
|
|
91
|
+
"mj-spacer"
|
|
92
|
+
]);
|
|
93
|
+
function serializeAttributes(attributes) {
|
|
94
|
+
const parts = [];
|
|
95
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
96
|
+
if (value !== void 0) {
|
|
97
|
+
parts.push(`${key}="${value}"`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
101
|
+
}
|
|
102
|
+
function serializeChildren(children) {
|
|
103
|
+
const parts = [];
|
|
104
|
+
for (const child of children) {
|
|
105
|
+
if (child === null || child === void 0 || child === true || child === false) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (Array.isArray(child)) {
|
|
109
|
+
parts.push(serializeChildren(child));
|
|
110
|
+
} else if (isMjmlNode(child)) {
|
|
111
|
+
parts.push(serializeNode(child));
|
|
112
|
+
} else {
|
|
113
|
+
parts.push(String(child));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return parts.join("");
|
|
117
|
+
}
|
|
118
|
+
function serializeNode(node) {
|
|
119
|
+
if (node.tag === Fragment) {
|
|
120
|
+
return serializeChildren(node.children);
|
|
121
|
+
}
|
|
122
|
+
const tag = node.tag;
|
|
123
|
+
const attrs = serializeAttributes(node.attributes);
|
|
124
|
+
if (SELF_CLOSING_TAGS.has(tag)) {
|
|
125
|
+
return `<${tag}${attrs} />`;
|
|
126
|
+
}
|
|
127
|
+
const content = serializeChildren(node.children);
|
|
128
|
+
return `<${tag}${attrs}>${content}</${tag}>`;
|
|
129
|
+
}
|
|
130
|
+
function serialize(node) {
|
|
131
|
+
return serializeNode(node);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/render.ts
|
|
135
|
+
function render(mjml, options) {
|
|
136
|
+
const str = isMjmlNode(mjml) ? serialize(mjml) : mjml;
|
|
137
|
+
return (0, import_mjml.default)(str, options);
|
|
138
|
+
}
|
|
139
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
140
|
+
0 && (module.exports = {
|
|
141
|
+
Fragment,
|
|
142
|
+
jsx,
|
|
143
|
+
jsxs,
|
|
144
|
+
render,
|
|
145
|
+
serialize
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ast.ts","../src/jsx-runtime.ts","../src/render.ts","../src/serialize.ts"],"sourcesContent":["export { Fragment, type MjmlChild, type MjmlNode } from './ast';\nexport { jsx, jsxs, type JSX } from './jsx-runtime';\nexport { render, type RenderOptions, type RenderResult } from './render';\nexport { serialize } from './serialize';\n\nexport type {\n Align,\n CSSPixel,\n CSSSpacing,\n CSSUnit,\n CSSWidth,\n Color,\n Direction,\n HexColor,\n MjAccordionAttributes,\n MjAccordionElementAttributes,\n MjAccordionTextAttributes,\n MjAccordionTitleAttributes,\n MjAllAttributes,\n MjAttributesAttributes,\n MjBodyAttributes,\n MjBreakpointAttributes,\n MjButtonAttributes,\n MjCarouselAttributes,\n MjCarouselImageAttributes,\n MjClassAttributes,\n MjColumnAttributes,\n MjDividerAttributes,\n MjFontAttributes,\n MjGroupAttributes,\n MjHeadAttributes,\n MjHeroAttributes,\n MjHtmlAttributeAttributes,\n MjHtmlAttributesAttributes,\n MjImageAttributes,\n MjIncludeAttributes,\n MjNavbarAttributes,\n MjNavbarLinkAttributes,\n MjPreviewAttributes,\n MjRawAttributes,\n MjSectionAttributes,\n MjSelectorAttributes,\n MjSocialAttributes,\n MjSocialElementAttributes,\n MjSpacerAttributes,\n MjStyleAttributes,\n MjTableAttributes,\n MjTextAttributes,\n MjTitleAttributes,\n MjWrapperAttributes,\n MjmlAttributes,\n URLString,\n VerticalAlign,\n} from './types';\n","export const MJML_NODE_TYPE = Symbol.for('mjmx.node');\n\nexport const Fragment = Symbol.for('mjmx.fragment');\n\nexport interface MjmlNode {\n readonly $$typeof: typeof MJML_NODE_TYPE;\n readonly tag: string | typeof Fragment;\n readonly attributes: Record<string, string | undefined>;\n readonly children: MjmlChild[];\n}\n\nexport type MjmlChild =\n | MjmlNode\n | string\n | number\n | boolean\n | null\n | undefined\n | MjmlChild[];\n\nexport function isMjmlNode(value: unknown): value is MjmlNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value &&\n value.$$typeof === MJML_NODE_TYPE\n );\n}\n\nexport function createNode(\n tag: string | typeof Fragment,\n attributes: Record<string, unknown>,\n children: MjmlChild[]\n): MjmlNode {\n const stringAttributes: Record<string, string | undefined> = {};\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value === undefined || value === null) {\n continue;\n }\n if (value instanceof URL) {\n stringAttributes[key] = value.toString();\n } else {\n stringAttributes[key] = String(value);\n }\n }\n\n return {\n $$typeof: MJML_NODE_TYPE,\n tag,\n attributes: stringAttributes,\n children,\n };\n}\n","import { createNode, Fragment, type MjmlChild, type MjmlNode } from './ast';\nimport type {\n MjAccordionAttributes,\n MjAccordionElementAttributes,\n MjAccordionTextAttributes,\n MjAccordionTitleAttributes,\n MjAllAttributes,\n MjAttributesAttributes,\n MjBodyAttributes,\n MjBreakpointAttributes,\n MjButtonAttributes,\n MjCarouselAttributes,\n MjCarouselImageAttributes,\n MjClassAttributes,\n MjColumnAttributes,\n MjDividerAttributes,\n MjFontAttributes,\n MjGroupAttributes,\n MjHeadAttributes,\n MjHeroAttributes,\n MjHtmlAttributeAttributes,\n MjHtmlAttributesAttributes,\n MjImageAttributes,\n MjIncludeAttributes,\n MjmlAttributes,\n MjNavbarAttributes,\n MjNavbarLinkAttributes,\n MjPreviewAttributes,\n MjRawAttributes,\n MjSectionAttributes,\n MjSelectorAttributes,\n MjSocialAttributes,\n MjSocialElementAttributes,\n MjSpacerAttributes,\n MjStyleAttributes,\n MjTableAttributes,\n MjTextAttributes,\n MjTitleAttributes,\n MjWrapperAttributes,\n} from './types';\n\nexport { Fragment };\n\ntype PropsWithChildren<T = object> = T & { children?: MjmlChild };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Component = (props: any) => MjmlNode;\n\nexport function jsx(\n tag: string | typeof Fragment | Component,\n props: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _key?: string\n): MjmlNode {\n if (typeof tag === 'function') {\n return tag(props);\n }\n\n const { children, ...attributes } = props;\n\n const childArray: MjmlChild[] =\n children === undefined\n ? []\n : Array.isArray(children)\n ? children\n : [children as MjmlChild];\n\n return createNode(tag, attributes, childArray);\n}\n\nexport const jsxs = jsx;\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace JSX {\n export type Element = MjmlNode;\n export type ElementType = string | typeof Fragment | Component;\n\n export interface ElementChildrenAttribute {\n children: MjmlChild;\n }\n\n export interface IntrinsicElements {\n mjml: PropsWithChildren<MjmlAttributes>;\n 'mj-head': PropsWithChildren<MjHeadAttributes>;\n 'mj-body': PropsWithChildren<MjBodyAttributes>;\n 'mj-attributes': PropsWithChildren<MjAttributesAttributes>;\n 'mj-breakpoint': MjBreakpointAttributes;\n 'mj-font': MjFontAttributes;\n 'mj-html-attributes': PropsWithChildren<MjHtmlAttributesAttributes>;\n 'mj-preview': PropsWithChildren<MjPreviewAttributes>;\n 'mj-style': PropsWithChildren<MjStyleAttributes>;\n 'mj-title': PropsWithChildren<MjTitleAttributes>;\n 'mj-all': MjAllAttributes;\n 'mj-class': MjClassAttributes;\n 'mj-section': PropsWithChildren<MjSectionAttributes>;\n 'mj-column': PropsWithChildren<MjColumnAttributes>;\n 'mj-group': PropsWithChildren<MjGroupAttributes>;\n 'mj-wrapper': PropsWithChildren<MjWrapperAttributes>;\n 'mj-text': PropsWithChildren<MjTextAttributes>;\n 'mj-button': PropsWithChildren<MjButtonAttributes>;\n 'mj-image': MjImageAttributes;\n 'mj-divider': MjDividerAttributes;\n 'mj-spacer': MjSpacerAttributes;\n 'mj-table': PropsWithChildren<MjTableAttributes>;\n 'mj-raw': PropsWithChildren<MjRawAttributes>;\n 'mj-hero': PropsWithChildren<MjHeroAttributes>;\n 'mj-accordion': PropsWithChildren<MjAccordionAttributes>;\n 'mj-accordion-element': PropsWithChildren<MjAccordionElementAttributes>;\n 'mj-accordion-title': PropsWithChildren<MjAccordionTitleAttributes>;\n 'mj-accordion-text': PropsWithChildren<MjAccordionTextAttributes>;\n 'mj-carousel': PropsWithChildren<MjCarouselAttributes>;\n 'mj-carousel-image': MjCarouselImageAttributes;\n 'mj-navbar': PropsWithChildren<MjNavbarAttributes>;\n 'mj-navbar-link': PropsWithChildren<MjNavbarLinkAttributes>;\n 'mj-social': PropsWithChildren<MjSocialAttributes>;\n 'mj-social-element': PropsWithChildren<MjSocialElementAttributes>;\n 'mj-include': MjIncludeAttributes;\n 'mj-selector': PropsWithChildren<MjSelectorAttributes>;\n 'mj-html-attribute': PropsWithChildren<MjHtmlAttributeAttributes>;\n }\n}\n","import mjml2html from 'mjml';\nimport type { MjmlNode } from './ast';\nimport { isMjmlNode } from './ast';\nimport { serialize } from './serialize';\n\nexport type RenderOptions = Parameters<typeof mjml2html>[1];\nexport type RenderResult = ReturnType<typeof mjml2html>;\n\nexport function render(\n mjml: MjmlNode | string,\n options?: RenderOptions\n): RenderResult {\n const str = isMjmlNode(mjml) ? serialize(mjml) : mjml;\n return mjml2html(str, options);\n}\n","import { Fragment, isMjmlNode, type MjmlChild, type MjmlNode } from './ast';\n\nconst SELF_CLOSING_TAGS = new Set([\n 'mj-all',\n 'mj-breakpoint',\n 'mj-carousel-image',\n 'mj-class',\n 'mj-divider',\n 'mj-font',\n 'mj-image',\n 'mj-include',\n 'mj-spacer',\n]);\n\nfunction serializeAttributes(\n attributes: Record<string, string | undefined>\n): string {\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value !== undefined) {\n parts.push(`${key}=\"${value}\"`);\n }\n }\n\n return parts.length > 0 ? ' ' + parts.join(' ') : '';\n}\n\nfunction serializeChildren(children: MjmlChild[]): string {\n const parts: string[] = [];\n\n for (const child of children) {\n if (\n child === null ||\n child === undefined ||\n child === true ||\n child === false\n ) {\n continue;\n }\n\n if (Array.isArray(child)) {\n parts.push(serializeChildren(child));\n } else if (isMjmlNode(child)) {\n parts.push(serializeNode(child));\n } else {\n parts.push(String(child));\n }\n }\n\n return parts.join('');\n}\n\nfunction serializeNode(node: MjmlNode): string {\n if (node.tag === Fragment) {\n return serializeChildren(node.children);\n }\n\n const tag = node.tag as string;\n const attrs = serializeAttributes(node.attributes);\n\n if (SELF_CLOSING_TAGS.has(tag)) {\n return `<${tag}${attrs} />`;\n }\n\n const content = serializeChildren(node.children);\n return `<${tag}${attrs}>${content}</${tag}>`;\n}\n\nexport function serialize(node: MjmlNode): string {\n return serializeNode(node);\n}\n\nexport const toMjmlString = serialize;\n"],"mappings":"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","names":["mjml2html"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { M as MjmlNode } from './jsx-dev-runtime-Dg-2Ex6t.cjs';
|
|
2
|
+
export { A as Align, C as CSSPixel, a as CSSSpacing, b as CSSUnit, c as CSSWidth, d as Color, D as Direction, F as Fragment, H as HexColor, J as JSX, e as MjAccordionAttributes, f as MjAccordionElementAttributes, g as MjAccordionTextAttributes, h as MjAccordionTitleAttributes, i as MjAllAttributes, j as MjAttributesAttributes, k as MjBodyAttributes, l as MjBreakpointAttributes, m as MjButtonAttributes, n as MjCarouselAttributes, o as MjCarouselImageAttributes, p as MjClassAttributes, q as MjColumnAttributes, r as MjDividerAttributes, s as MjFontAttributes, t as MjGroupAttributes, u as MjHeadAttributes, v as MjHeroAttributes, w as MjHtmlAttributeAttributes, x as MjHtmlAttributesAttributes, y as MjImageAttributes, z as MjIncludeAttributes, B as MjNavbarAttributes, E as MjNavbarLinkAttributes, G as MjPreviewAttributes, I as MjRawAttributes, K as MjSectionAttributes, L as MjSelectorAttributes, N as MjSocialAttributes, O as MjSocialElementAttributes, P as MjSpacerAttributes, Q as MjStyleAttributes, R as MjTableAttributes, S as MjTextAttributes, T as MjTitleAttributes, U as MjWrapperAttributes, V as MjmlAttributes, W as MjmlChild, X as URLString, Y as VerticalAlign, Z as jsx, _ as jsxs } from './jsx-dev-runtime-Dg-2Ex6t.cjs';
|
|
3
|
+
import mjml2html from 'mjml';
|
|
4
|
+
|
|
5
|
+
type RenderOptions = Parameters<typeof mjml2html>[1];
|
|
6
|
+
type RenderResult = ReturnType<typeof mjml2html>;
|
|
7
|
+
declare function render(mjml: MjmlNode | string, options?: RenderOptions): RenderResult;
|
|
8
|
+
|
|
9
|
+
declare function serialize(node: MjmlNode): string;
|
|
10
|
+
|
|
11
|
+
export { MjmlNode, type RenderOptions, type RenderResult, render, serialize };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { M as MjmlNode } from './jsx-dev-runtime-Dg-2Ex6t.js';
|
|
2
|
+
export { A as Align, C as CSSPixel, a as CSSSpacing, b as CSSUnit, c as CSSWidth, d as Color, D as Direction, F as Fragment, H as HexColor, J as JSX, e as MjAccordionAttributes, f as MjAccordionElementAttributes, g as MjAccordionTextAttributes, h as MjAccordionTitleAttributes, i as MjAllAttributes, j as MjAttributesAttributes, k as MjBodyAttributes, l as MjBreakpointAttributes, m as MjButtonAttributes, n as MjCarouselAttributes, o as MjCarouselImageAttributes, p as MjClassAttributes, q as MjColumnAttributes, r as MjDividerAttributes, s as MjFontAttributes, t as MjGroupAttributes, u as MjHeadAttributes, v as MjHeroAttributes, w as MjHtmlAttributeAttributes, x as MjHtmlAttributesAttributes, y as MjImageAttributes, z as MjIncludeAttributes, B as MjNavbarAttributes, E as MjNavbarLinkAttributes, G as MjPreviewAttributes, I as MjRawAttributes, K as MjSectionAttributes, L as MjSelectorAttributes, N as MjSocialAttributes, O as MjSocialElementAttributes, P as MjSpacerAttributes, Q as MjStyleAttributes, R as MjTableAttributes, S as MjTextAttributes, T as MjTitleAttributes, U as MjWrapperAttributes, V as MjmlAttributes, W as MjmlChild, X as URLString, Y as VerticalAlign, Z as jsx, _ as jsxs } from './jsx-dev-runtime-Dg-2Ex6t.js';
|
|
3
|
+
import mjml2html from 'mjml';
|
|
4
|
+
|
|
5
|
+
type RenderOptions = Parameters<typeof mjml2html>[1];
|
|
6
|
+
type RenderResult = ReturnType<typeof mjml2html>;
|
|
7
|
+
declare function render(mjml: MjmlNode | string, options?: RenderOptions): RenderResult;
|
|
8
|
+
|
|
9
|
+
declare function serialize(node: MjmlNode): string;
|
|
10
|
+
|
|
11
|
+
export { MjmlNode, type RenderOptions, type RenderResult, render, serialize };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Fragment,
|
|
3
|
+
isMjmlNode,
|
|
4
|
+
jsx,
|
|
5
|
+
jsxs
|
|
6
|
+
} from "./chunk-SUL5BGGO.js";
|
|
7
|
+
|
|
8
|
+
// src/render.ts
|
|
9
|
+
import mjml2html from "mjml";
|
|
10
|
+
|
|
11
|
+
// src/serialize.ts
|
|
12
|
+
var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
|
|
13
|
+
"mj-all",
|
|
14
|
+
"mj-breakpoint",
|
|
15
|
+
"mj-carousel-image",
|
|
16
|
+
"mj-class",
|
|
17
|
+
"mj-divider",
|
|
18
|
+
"mj-font",
|
|
19
|
+
"mj-image",
|
|
20
|
+
"mj-include",
|
|
21
|
+
"mj-spacer"
|
|
22
|
+
]);
|
|
23
|
+
function serializeAttributes(attributes) {
|
|
24
|
+
const parts = [];
|
|
25
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
26
|
+
if (value !== void 0) {
|
|
27
|
+
parts.push(`${key}="${value}"`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
31
|
+
}
|
|
32
|
+
function serializeChildren(children) {
|
|
33
|
+
const parts = [];
|
|
34
|
+
for (const child of children) {
|
|
35
|
+
if (child === null || child === void 0 || child === true || child === false) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (Array.isArray(child)) {
|
|
39
|
+
parts.push(serializeChildren(child));
|
|
40
|
+
} else if (isMjmlNode(child)) {
|
|
41
|
+
parts.push(serializeNode(child));
|
|
42
|
+
} else {
|
|
43
|
+
parts.push(String(child));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return parts.join("");
|
|
47
|
+
}
|
|
48
|
+
function serializeNode(node) {
|
|
49
|
+
if (node.tag === Fragment) {
|
|
50
|
+
return serializeChildren(node.children);
|
|
51
|
+
}
|
|
52
|
+
const tag = node.tag;
|
|
53
|
+
const attrs = serializeAttributes(node.attributes);
|
|
54
|
+
if (SELF_CLOSING_TAGS.has(tag)) {
|
|
55
|
+
return `<${tag}${attrs} />`;
|
|
56
|
+
}
|
|
57
|
+
const content = serializeChildren(node.children);
|
|
58
|
+
return `<${tag}${attrs}>${content}</${tag}>`;
|
|
59
|
+
}
|
|
60
|
+
function serialize(node) {
|
|
61
|
+
return serializeNode(node);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/render.ts
|
|
65
|
+
function render(mjml, options) {
|
|
66
|
+
const str = isMjmlNode(mjml) ? serialize(mjml) : mjml;
|
|
67
|
+
return mjml2html(str, options);
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
Fragment,
|
|
71
|
+
jsx,
|
|
72
|
+
jsxs,
|
|
73
|
+
render,
|
|
74
|
+
serialize
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render.ts","../src/serialize.ts"],"sourcesContent":["import mjml2html from 'mjml';\nimport type { MjmlNode } from './ast';\nimport { isMjmlNode } from './ast';\nimport { serialize } from './serialize';\n\nexport type RenderOptions = Parameters<typeof mjml2html>[1];\nexport type RenderResult = ReturnType<typeof mjml2html>;\n\nexport function render(\n mjml: MjmlNode | string,\n options?: RenderOptions\n): RenderResult {\n const str = isMjmlNode(mjml) ? serialize(mjml) : mjml;\n return mjml2html(str, options);\n}\n","import { Fragment, isMjmlNode, type MjmlChild, type MjmlNode } from './ast';\n\nconst SELF_CLOSING_TAGS = new Set([\n 'mj-all',\n 'mj-breakpoint',\n 'mj-carousel-image',\n 'mj-class',\n 'mj-divider',\n 'mj-font',\n 'mj-image',\n 'mj-include',\n 'mj-spacer',\n]);\n\nfunction serializeAttributes(\n attributes: Record<string, string | undefined>\n): string {\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(attributes)) {\n if (value !== undefined) {\n parts.push(`${key}=\"${value}\"`);\n }\n }\n\n return parts.length > 0 ? ' ' + parts.join(' ') : '';\n}\n\nfunction serializeChildren(children: MjmlChild[]): string {\n const parts: string[] = [];\n\n for (const child of children) {\n if (\n child === null ||\n child === undefined ||\n child === true ||\n child === false\n ) {\n continue;\n }\n\n if (Array.isArray(child)) {\n parts.push(serializeChildren(child));\n } else if (isMjmlNode(child)) {\n parts.push(serializeNode(child));\n } else {\n parts.push(String(child));\n }\n }\n\n return parts.join('');\n}\n\nfunction serializeNode(node: MjmlNode): string {\n if (node.tag === Fragment) {\n return serializeChildren(node.children);\n }\n\n const tag = node.tag as string;\n const attrs = serializeAttributes(node.attributes);\n\n if (SELF_CLOSING_TAGS.has(tag)) {\n return `<${tag}${attrs} />`;\n }\n\n const content = serializeChildren(node.children);\n return `<${tag}${attrs}>${content}</${tag}>`;\n}\n\nexport function serialize(node: MjmlNode): string {\n return serializeNode(node);\n}\n\nexport const toMjmlString = serialize;\n"],"mappings":";;;;;;;;AAAA,OAAO,eAAe;;;ACEtB,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,oBACP,YACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,QAAI,UAAU,QAAW;AACvB,YAAM,KAAK,GAAG,GAAG,KAAK,KAAK,GAAG;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,MAAM,KAAK,GAAG,IAAI;AACpD;AAEA,SAAS,kBAAkB,UAA+B;AACxD,QAAM,QAAkB,CAAC;AAEzB,aAAW,SAAS,UAAU;AAC5B,QACE,UAAU,QACV,UAAU,UACV,UAAU,QACV,UAAU,OACV;AACA;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,KAAK,kBAAkB,KAAK,CAAC;AAAA,IACrC,WAAW,WAAW,KAAK,GAAG;AAC5B,YAAM,KAAK,cAAc,KAAK,CAAC;AAAA,IACjC,OAAO;AACL,YAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,EAAE;AACtB;AAEA,SAAS,cAAc,MAAwB;AAC7C,MAAI,KAAK,QAAQ,UAAU;AACzB,WAAO,kBAAkB,KAAK,QAAQ;AAAA,EACxC;AAEA,QAAM,MAAM,KAAK;AACjB,QAAM,QAAQ,oBAAoB,KAAK,UAAU;AAEjD,MAAI,kBAAkB,IAAI,GAAG,GAAG;AAC9B,WAAO,IAAI,GAAG,GAAG,KAAK;AAAA,EACxB;AAEA,QAAM,UAAU,kBAAkB,KAAK,QAAQ;AAC/C,SAAO,IAAI,GAAG,GAAG,KAAK,IAAI,OAAO,KAAK,GAAG;AAC3C;AAEO,SAAS,UAAU,MAAwB;AAChD,SAAO,cAAc,IAAI;AAC3B;;;AD/DO,SAAS,OACd,MACA,SACc;AACd,QAAM,MAAM,WAAW,IAAI,IAAI,UAAU,IAAI,IAAI;AACjD,SAAO,UAAU,KAAK,OAAO;AAC/B;","names":[]}
|