@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 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"]}
@@ -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 };
@@ -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":[]}