create-email-renderer 0.1.1 → 0.2.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.
Files changed (45) hide show
  1. package/README.md +106 -2
  2. package/SKILL.md +189 -0
  3. package/dist/build.d.ts +52 -0
  4. package/dist/build.d.ts.map +1 -0
  5. package/dist/build.js +169 -0
  6. package/dist/build.js.map +1 -0
  7. package/dist/default-blocks.d.ts.map +1 -1
  8. package/dist/default-blocks.js +357 -5
  9. package/dist/default-blocks.js.map +1 -1
  10. package/dist/html-render.d.ts +4 -2
  11. package/dist/html-render.d.ts.map +1 -1
  12. package/dist/html-render.js +694 -54
  13. package/dist/html-render.js.map +1 -1
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/normalize.d.ts +3 -1
  19. package/dist/normalize.d.ts.map +1 -1
  20. package/dist/normalize.js +120 -40
  21. package/dist/normalize.js.map +1 -1
  22. package/dist/records.d.ts +8 -0
  23. package/dist/records.d.ts.map +1 -0
  24. package/dist/records.js +81 -0
  25. package/dist/records.js.map +1 -0
  26. package/dist/registry.d.ts +29 -0
  27. package/dist/registry.d.ts.map +1 -0
  28. package/dist/registry.js +31 -0
  29. package/dist/registry.js.map +1 -0
  30. package/dist/server.d.ts +4 -2
  31. package/dist/server.d.ts.map +1 -1
  32. package/dist/server.js +2 -1
  33. package/dist/server.js.map +1 -1
  34. package/dist/tracking.d.ts +12 -0
  35. package/dist/tracking.d.ts.map +1 -0
  36. package/dist/tracking.js +78 -0
  37. package/dist/tracking.js.map +1 -0
  38. package/dist/types.d.ts +354 -7
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/types.js +82 -0
  41. package/dist/types.js.map +1 -1
  42. package/docs/BLOCKS.md +467 -0
  43. package/docs/MCP.md +186 -0
  44. package/llms.txt +15 -0
  45. package/package.json +17 -4
package/README.md CHANGED
@@ -4,6 +4,18 @@ Renderiza plantillas de email por bloques a **HTML email-safe sin React**. JS pu
4
4
 
5
5
  Es el compañero de [`create-email-template`](https://www.npmjs.com/package/create-email-template) (editor visual). Comparten el mismo core: los tipos, los defaults y la normalización son idénticos en ambos lados, por lo que el preview del editor y el HTML final nunca divergen.
6
6
 
7
+ ## ¿Programas con una IA o vas a integrarlo?
8
+
9
+ La documentación para agentes viaja dentro del paquete:
10
+
11
+ - **[`SKILL.md`](./SKILL.md)** — orientación: modelo mental del payload, los 3 flujos, recetas
12
+ (tarea → API) y reglas de oro.
13
+ - **[`docs/BLOCKS.md`](./docs/BLOCKS.md)** — catálogo de los **25 bloques** con props, defaults,
14
+ variantes y ejemplos `blockJson` copiables.
15
+ - **[`docs/MCP.md`](./docs/MCP.md)** — cómo exponer el renderer como **servidor MCP** (tools
16
+ `list_blocks`, `build_block`, `render_email`, `validate_template`…).
17
+ - **[`llms.txt`](./llms.txt)** — índice corto para herramientas que lo buscan por convención.
18
+
7
19
  ## Instalación
8
20
 
9
21
  ```sh
@@ -39,8 +51,9 @@ await emailClient.send({ to: user.email, subject, html });
39
51
  | `subject` | `string` | — (obligatorio) | Asunto del correo. **Resuelve variables**: `"Hola {firstName}"` → `"Hola Danny"`. También queda en `<title>` y en el preview oculto del email. |
40
52
  | `payload` | `string \| object \| null` | — | El JSON del editor. Tolera `null`/`undefined`/string inválido (devuelve vacío). |
41
53
  | `context` | `EmailContext` | `SAMPLE_CONTEXT` | Valores para las variables `{key}`. Se mezcla sobre `SAMPLE_CONTEXT`, así que los correos de prueba siempre se ven completos aunque falten claves. |
42
- | `settings` | `Partial<EmailSettings>` | settings del payload | Sobrescribe `{ pageBackground, cardBorderWidth, cardBorderRadius }` guardados. |
54
+ | `settings` | `Partial<EmailSettings>` | settings del payload | Sobrescribe `{ pageBackground, cardBorderWidth, cardBorderRadius, fontFamily }` guardados. |
43
55
  | `palette` | `EmailPalette` | `DEFAULT_PALETTE` | Sobrescribe los colores: `{ INK, DARK, GOLD, CREAM_DIM }`. |
56
+ | `tracking` | `EmailTracking` | — | Trackeo **por envío**: pixel de apertura y reescritura de enlaces. Ver [Trackeo](#trackeo-aperturas-y-clics). |
44
57
 
45
58
  **Comportamiento**: lanza `Template payload has no blocks` si tras normalizar no queda ningún bloque. En cualquier otro caso de datos sucios, normaliza sin quejarse (ver [Normalización](#normalización-de-payloads)).
46
59
 
@@ -97,9 +110,99 @@ Esto significa que **añadir props nuevas a un bloque no rompe las plantillas ya
97
110
  | `extractVariables(text)` / `validateVariables(text, knownKeys)` | Inspección de variables usadas/no reconocidas. |
98
111
  | `renderRichText(html)` | Sanitiza y aplica estilos inline al rich text del editor. |
99
112
  | `sanitizeRichText` / `escapeHtml` / `normalizeBlockHtml` / `isRichText` | Piezas del pipeline por separado. |
100
- | `createBlock(type, library)` | Crea un bloque nuevo con defaultProps (útil para generar plantillas por código). |
113
+ | `blockJson(type, props?)` | Constructor **tipado** de un bloque: defaults del esquema, coerción de tipos e ids automáticos. Tipo desconocido → `null`. |
114
+ | `templateJson(blocks, settings?)` | Arma el payload completo (`{ content, settings }`) para `renderTemplateEmail`. |
115
+ | `createBlock(type, library)` | Crea un bloque nuevo con defaultProps (helper de bajo nivel del editor). |
101
116
  | Defaults | `DEFAULT_BLOCK_LIBRARY`, `DEFAULT_PALETTE`, `DEFAULT_SETTINGS`, `DEFAULT_VARIABLES`, `SAMPLE_CONTEXT`. |
102
117
 
118
+ ## Construir bloques desde el back-end (`blockJson`)
119
+
120
+ Para inyectar contenido que no vive en la plantilla (un producto, un carrito, una imagen) no
121
+ hace falta escribir el JSON a mano: `blockJson` parte de los **defaults del esquema vivo**,
122
+ coacciona tipos, genera los ids y completa los arrays de registros.
123
+
124
+ ```ts
125
+ import { blockJson, templateJson } from "create-email-renderer";
126
+
127
+ // Un bloque suelto: lo que no pases queda con su default.
128
+ const promo = blockJson("image", { src: "https://…/promo.jpg", alt: "Promo" });
129
+
130
+ // Carrito real: los registros se completan solos (id, imageUrl, quantity…).
131
+ const carrito = blockJson("checkout", {
132
+ heading: "Tu pedido está listo",
133
+ lines: cart.items.map((i) => ({ name: i.name, price: i.price, quantity: String(i.qty) })),
134
+ });
135
+
136
+ // Correo completo listo para enviar.
137
+ const { html, subject } = await renderTemplateEmail({
138
+ subject: "Tu pedido {orderId}",
139
+ payload: templateJson([promo, carrito], { cardBorderWidth: 0 }),
140
+ context: { orderId: "A-123" },
141
+ });
142
+ ```
143
+
144
+ - **Posicional**: `blockJson(type, props?)` y `templateJson(blocks, settings?)`.
145
+ - **Tipado**: el editor autocompleta solo las props del tipo elegido; una prop inexistente es error de compilación.
146
+ - **Tolerante**: un tipo desconocido devuelve `null` (y `templateJson` lo descarta).
147
+ - **Anidamiento**: `columns` / `blocks` aceptan `blockJson(...)`, el atajo `[type, props]` o `{ type, props }`; se respeta la profundidad máxima (`MAX_BLOCK_DEPTH`).
148
+ - **Ids**: nunca los administras, se generan con `newId()`.
149
+
150
+ ## Trackeo (aperturas y clics)
151
+
152
+ Opcional y **por envío** (no se guarda en la plantilla, así que el preview del editor nunca
153
+ lleva pixel). Con `tracking` apagado la salida es idéntica a no usarlo.
154
+
155
+ ```ts
156
+ await renderTemplateEmail({
157
+ subject: "Tu carrito te espera",
158
+ payload,
159
+ context: { email: "ana@ejemplo.com" },
160
+ tracking: {
161
+ pixelUrl: "https://track.mi-app.com/o?cid=cart-123&e={email}", // apertura (1×1)
162
+ clickUrl: "https://track.mi-app.com/c?cid=cart-123&u={url}", // clics
163
+ utm: { source: "email", medium: "email", campaign: "carrito" },
164
+ exclude: ["/baja"], // extra opcional
165
+ // transformLink: (href) => `https://mi-redirect/?to=${encodeURIComponent(href)}`,
166
+ },
167
+ });
168
+ ```
169
+
170
+ | Campo | Qué hace |
171
+ |---|---|
172
+ | `pixelUrl` | Inyecta un `<img width="1" height="1">` antes de `</body>`. Acepta `{variables}`. |
173
+ | `clickUrl` | Reescribe cada `<a href>`: el destino va en `{url}` (codificado) y el tracker recibe las mismas `{variables}`. |
174
+ | `utm` | Añade `utm_*` al destino **antes** de pasarlo por el tracker (respeta los parámetros que ya existían). |
175
+ | `exclude` | Substrings de href que no se reescriben; se suman a los de por defecto (`mailto:`, `tel:`, `sms:`, `#`, `unsubscribe`, `/baja`, `optout`…). |
176
+ | `transformLink` | Control total: devuelve el href final tú mismo. |
177
+
178
+ **Caveats honestos**
179
+
180
+ - Las **aperturas** ya no son fiables: Apple Mail precarga las imágenes (MPP) y Gmail las sirve
181
+ por proxy. Úsalo como tendencia, no como verdad.
182
+ - El **click tracking** cambia la URL visible al pasar el ratón y la vista previa del enlace en
183
+ algunos clientes; y **nunca** debe pasar por el tracker el enlace de baja.
184
+ - Si tu ESP (Mailflare, Resend, SES…) ya trackea, no lo dupliques: aquí tienes `transformLink`
185
+ como salida de emergencia.
186
+
187
+ ## Tipografía
188
+
189
+ El correo lleva un **stack de fuentes de sistema** (lista ordenada: el cliente usa la primera que
190
+ tenga instalada) para no depender de la fuente por defecto del cliente —que en Gmail/Outlook suele
191
+ ser Times New Roman—:
192
+
193
+ ```ts
194
+ await renderTemplateEmail({
195
+ subject: "Hola",
196
+ payload,
197
+ settings: { fontFamily: "Georgia, 'Times New Roman', serif" }, // o "" para no emitir nada
198
+ });
199
+ ```
200
+
201
+ `FONT_STACKS` trae 7 grupos listos (Sistema, Arial/Helvetica, Verdana/Tahoma, Trebuchet MS,
202
+ Georgia, Times New Roman y Monoespaciada) y `DEFAULT_SETTINGS.fontFamily` es el stack de sistema.
203
+ Las **webfonts** (`@font-face`) no son fiables: Gmail las elimina y Outlook escritorio las ignora,
204
+ así que conviene dejar siempre un fallback de sistema al final del stack.
205
+
103
206
  ## Subpaths
104
207
 
105
208
  Todo está disponible desde la raíz. Si prefieres imports granulares (menos bundle en serverless):
@@ -112,6 +215,7 @@ create-email-renderer/types → todos los tipos + createBlock
112
215
  create-email-renderer/variables → variables, contextos y resolve
113
216
  create-email-renderer/richtext → helpers de rich text
114
217
  create-email-renderer/default-blocks → defaults de bloques, paleta y settings
218
+ create-email-renderer/build → blockJson, templateJson
115
219
  ```
116
220
 
117
221
  ## Licencia
package/SKILL.md ADDED
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: create-email-renderer
3
+ description: Render and build email templates as JSON blocks into email-safe HTML without React (Node, Workers, edge)
4
+ licence: MIT
5
+ metadata:
6
+ author: asmel2020
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Skill: `create-email-renderer`
11
+
12
+ Renderiza plantillas de email **por bloques** (JSON → HTML email-safe) **sin React**. JS puro:
13
+ corre en Node, Cloudflare Workers, Vercel Edge, Deno y Bun. Es el compañero sin UI de
14
+ `create-email-template` (el editor visual): comparten el mismo core, así que el preview del
15
+ editor y el HTML final nunca divergen.
16
+
17
+ - 📖 Catálogo de los **25 bloques** (props, defaults, variantes, ejemplos): [`docs/BLOCKS.md`](./docs/BLOCKS.md)
18
+ - 🔌 Cómo exponerlo como **MCP**: [`docs/MCP.md`](./docs/MCP.md)
19
+
20
+ ---
21
+
22
+ ## Cuándo usar esto
23
+
24
+ | Quieres… | Usa |
25
+ |---|---|
26
+ | Mandar un correo desde el back-end a partir de una plantilla guardada | `renderTemplateEmail` |
27
+ | Construir el correo por código (sin editor) | `blockJson` + `templateJson` |
28
+ | Inyectar datos reales (carrito, pedido, productos) en una plantilla guardada | mutar `content` del payload y renderizar |
29
+ | Leer/limpiar un payload viejo o sucio | `parseTemplatePayload` / `normalizeBlocks` |
30
+ | Píxel de apertura y tracking de clics | opción `tracking` |
31
+
32
+ ## Instalación
33
+
34
+ ```sh
35
+ npm install create-email-renderer
36
+ ```
37
+
38
+ Sin React, sin DOM, sin peer deps. Única dependencia: `sanitize-html`.
39
+
40
+ ## Modelo mental (30 segundos)
41
+
42
+ ```
43
+ payload = { content: EmailBlock[], settings } ← lo que guarda el editor
44
+ └── block = { id, type, props } ← uno de los 25 tipos
45
+ ```
46
+
47
+ 1. **`content`** es una lista ordenada de bloques. Cada bloque tiene un `type` y sus `props`.
48
+ 2. Lo que no venga en `props` se completa con el **default del esquema**, y lo desconocido se
49
+ descarta (`normalizeBlocks`) → **añadir props nuevas no rompe plantillas viejas**.
50
+ 3. Las variables `{clave}` se resuelven con el `context` en tiempo de render.
51
+ 4. El HTML final es tablas con estilos inline (`<table role="presentation">`), email-safe.
52
+
53
+ ## Los 3 flujos
54
+
55
+ ```
56
+ ① Editor (create-email-template) ──getPayload()──▶ { content, settings } ──PUT──▶ tu backend
57
+ ② Tu backend ──renderTemplateEmail({ subject, payload, context })──▶ { html, subject } ──▶ ESP
58
+ ③ Tu backend ──blockJson()/templateJson()──▶ payload ──▶ mismo render (sin editor de por medio)
59
+ ```
60
+
61
+ ## Recetas (tarea → API)
62
+
63
+ ### Renderizar una plantilla guardada
64
+
65
+ ```ts
66
+ import { renderTemplateEmail } from "create-email-renderer/server";
67
+
68
+ const { html, subject } = await renderTemplateEmail({
69
+ subject: "Hola {firstName}", // resuelve variables
70
+ payload: template.payload, // string JSON u objeto {content, settings}
71
+ context: { firstName: user.name },
72
+ settings: { cardBorderWidth: 0 }, // sobrescribe los settings guardados
73
+ palette: { INK: "#111", DARK: "#000", GOLD: "#d7b227", CREAM_DIM: "#aaa" },
74
+ });
75
+ ```
76
+
77
+ - `payload` tolera `null`/string inválido (devuelve vacío) pero **lanza** `Template payload has no blocks` si tras normalizar no queda ningún bloque.
78
+ - No re-exporta `renderEmailHtml` (el paquete UI tiene su versión React con el mismo nombre). Para el HTML puro: `create-email-renderer/html-render`.
79
+
80
+ ### Construir un bloque (tipado, con defaults e ids)
81
+
82
+ ```ts
83
+ import { blockJson, templateJson } from "create-email-renderer";
84
+
85
+ blockJson("image", { src: "https://…/foto.jpg", alt: "Foto" });
86
+ blockJson("checkout", { lines: [{ name: "Camiseta", price: "$20" }] }); // id/quantity se rellenan
87
+ blockJson("columns", { columns: [{ blocks: [["text", { text: "Hola" }]] }] });
88
+
89
+ templateJson([/* bloques */], { fontFamily: "" }); // → { content, settings } listo para render
90
+ ```
91
+
92
+ - Posicional y **tipado** (`blockJson("image", {` autocompleta solo las props de `image`).
93
+ - Tipo desconocido → `null` (y `templateJson` lo descarta).
94
+ - **Nunca administras ids**: se generan para el bloque y para cada registro.
95
+ - Hijos: acepta `blockJson(...)`, `[type, props]` o `{ type, props }`; respeta `MAX_BLOCK_DEPTH = 1`.
96
+
97
+ ### Inyectar el carrito / datos del pedido
98
+
99
+ ```ts
100
+ import { parseTemplatePayload } from "create-email-renderer";
101
+
102
+ const { content, settings } = parseTemplatePayload(template.payload);
103
+ const blocks = content.map((b) =>
104
+ b.type === "checkout"
105
+ ? { ...b, props: { ...b.props, heading: "Tu pedido está listo",
106
+ lines: cart.items.map((i) => ({ name: i.name, price: i.price, quantity: String(i.qty) })) } }
107
+ : b,
108
+ );
109
+ const html = await renderEmailHtml({ blocks, subject, context, settings });
110
+ ```
111
+
112
+ `normalize` repara ids/tipos de los registros, así que puedes construir el array "flojo".
113
+ Ver [`docs/BLOCKS.md`](./docs/BLOCKS.md) para las props de cada bloque y
114
+ [`docs/MCP.md`](./docs/MCP.md) para exponer esto como tool.
115
+
116
+ ### Tracking (opt-in, por envío)
117
+
118
+ ```ts
119
+ await renderTemplateEmail({
120
+ subject, payload, context,
121
+ tracking: {
122
+ pixelUrl: "https://track.mi-app.com/o?cid=123&e={email}", // apertura 1×1
123
+ clickUrl: "https://track.mi-app.com/c?cid=123&u={url}", // clics
124
+ utm: { source: "email", medium: "email", campaign: "carrito" },
125
+ // exclude: ["/baja"], transformLink: (href) => …
126
+ },
127
+ });
128
+ ```
129
+
130
+ Nunca se guarda en la plantilla (no contamina el preview) y con `tracking` apagado la salida es
131
+ idéntica. La baja (`/baja`, `unsubscribe`, `mailto:`…) **no** se reescribe ni con `exclude` por
132
+ defecto.
133
+
134
+ ### Otros helpers
135
+
136
+ | Export | Para qué |
137
+ |---|---|
138
+ | `parseTemplatePayload(raw)` | `{ content, settings }` normalizado, nunca lanza. |
139
+ | `normalizeBlocks(input, library?)` / `normalizeSettings(input)` | Limpiar payloads legacy. |
140
+ | `resolveVariables(text, ctx)` / `extractVariables` / `validateVariables` | Variables `{key}`. |
141
+ | `buildTemplateContext(base, extra?)` | Contexto limpio (quita `null`/`""`) sobre `SAMPLE_CONTEXT`. |
142
+ | `renderRichText` / `sanitizeRichText` / `escapeHtml` | Pipeline de rich text. |
143
+ | `DEFAULT_BLOCK_LIBRARY` / `DEFAULT_PALETTE` / `DEFAULT_SETTINGS` / `SAMPLE_CONTEXT` | Defaults. |
144
+ | `listBlockDefinitions()` / `registerBlock()` | Registry vivo: catálogo y plugins. |
145
+
146
+ ## Subpaths
147
+
148
+ ```
149
+ create-email-renderer → todo
150
+ create-email-renderer/server → parseTemplatePayload, renderTemplateEmail, buildTemplateContext
151
+ create-email-renderer/html-render → renderEmailHtml
152
+ create-email-renderer/build → blockJson, templateJson
153
+ create-email-renderer/normalize → normalizeBlocks, normalizeSettings
154
+ create-email-renderer/types → tipos (EmailBlock, EmailBlockType, EmailSettings…)
155
+ create-email-renderer/variables → variables + contextos
156
+ create-email-renderer/richtext → helpers de rich text
157
+ create-email-renderer/default-blocks → defaults de bloques, paleta y settings
158
+ create-email-renderer/registry → registerBlock, listBlockDefinitions
159
+ ```
160
+
161
+ ## Reglas de oro (no las rompas)
162
+
163
+ 1. **Este paquete nunca depende de React** ni de nada que lo arrastre. Si algo necesita DOM/JSX,
164
+ pertenece a `create-email-template`.
165
+ 2. **El core vive aquí**: tipos, defaults, normalización y preset de bloques. El paquete UI los
166
+ reexporta con shims de una línea. No dupliques esa lógica.
167
+ 3. **Todo helper nuevo debe ser puro y no-lanzador** con datos corruptos (salvo `blockJson` con
168
+ tipo desconocido → `null`, y `renderTemplateEmail` sin bloques → throw).
169
+ 4. **Es aditivo por diseño**: no cambies defaults ni el HTML existente sin querer; hay un snapshot
170
+ de paridad por tipo de bloque para vigilarlo.
171
+
172
+ ## Errores comunes
173
+
174
+ | Síntoma | Causa |
175
+ |---|---|
176
+ | `Template payload has no blocks` | Todo el `content` se descartó al normalizar (tipos desconocidos). |
177
+ | `{firstName}` sale literal en el correo | La clave no está en el `context` (las desconocidas se dejan tal cual). |
178
+ | El correo se ve con otra tipografía | `settings.fontFamily` vacío ⇒ hereda la del cliente; pon un stack. |
179
+ | Las imágenes se estiran | `imageHeight` con `object-fit` en Outlook escritorio; usa `0`. |
180
+ | Las imágenes no cargan en Gmail | Son `data:` (SVG inline); Gmail las descarta. Usa URLs `https:`. |
181
+ | Un array de registros queda vacío | Usaste `items` para registros: los registros van en `lines`/`products`/… |
182
+ | El bloque anidado desaparece | `MAX_BLOCK_DEPTH = 1`: los hijos no pueden contener bloques. |
183
+
184
+ ## Verificación antes de dar algo por hecho
185
+
186
+ ```sh
187
+ pnpm --filter create-email-renderer test # snapshots de paridad + unitarios
188
+ pnpm lint && pnpm check-types && pnpm build
189
+ ```
@@ -0,0 +1,52 @@
1
+ import type { BlockPropsMap, EmailBlock, EmailBlockType, EmailSettings } from "./types.js";
2
+ /**
3
+ * Registro de un array de registros en la entrada: sin `id` y con todos los
4
+ * campos opcionales (el constructor rellena ids y defaults).
5
+ */
6
+ export type RecordInput<T> = Partial<Omit<T, "id">>;
7
+ /**
8
+ * Props de entrada de un bloque: todo opcional (los defaults completan) y los
9
+ * arrays de registros aceptan entradas sin `id`.
10
+ */
11
+ export type BlockInputProps<T extends EmailBlockType> = Omit<{
12
+ [K in keyof BlockPropsMap[T]]?: BlockPropsMap[T][K] extends Array<infer I> ? I extends {
13
+ id: string;
14
+ } ? RecordInput<I>[] : BlockPropsMap[T][K] : BlockPropsMap[T][K];
15
+ }, never>;
16
+ /** Celda de un contenedor: ancho + hijos (bloques o atajos). */
17
+ export interface ColumnInput {
18
+ id?: string;
19
+ width?: number;
20
+ blocks?: BlockInput[];
21
+ }
22
+ /** Bloque ya construido o el atajo `[type, props]` / `{ type, props }`. */
23
+ export type BlockShorthand<T extends EmailBlockType = EmailBlockType> = {
24
+ [K in T]: [K, BlockInputProps<K>?] | {
25
+ type: K;
26
+ props?: BlockInputProps<K>;
27
+ };
28
+ }[T];
29
+ export type BlockInput = EmailBlock | BlockShorthand | (BlockInputProps<EmailBlockType> & {
30
+ type: EmailBlockType;
31
+ });
32
+ /**
33
+ * Construye un bloque a partir de su tipo y (opcionalmente) props parciales.
34
+ * Lo que no pases queda con el default del esquema; los ids se generan solos.
35
+ * Devuelve `null` si el tipo no existe en la librería viva.
36
+ *
37
+ * ```ts
38
+ * blockJson("image", { src: "https://…/foto.jpg", alt: "Foto" })
39
+ * blockJson("checkout", { lines: [{ name: "Camiseta", price: "$20" }] })
40
+ * ```
41
+ */
42
+ export declare function blockJson<T extends EmailBlockType>(type: T, props?: BlockInputProps<T>): EmailBlock;
43
+ export declare function blockJson(type: string, props?: Record<string, unknown>): EmailBlock | null;
44
+ /**
45
+ * Construye el payload completo (`{ content, settings }`) listo para
46
+ * `renderTemplateEmail({ payload })`. Descarta los bloques inválidos (`null`).
47
+ */
48
+ export declare const templateJson: (blocks: Array<EmailBlock | null | undefined>, settings?: Partial<EmailSettings>) => {
49
+ content: EmailBlock[];
50
+ settings: Partial<EmailSettings>;
51
+ };
52
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAEV,aAAa,EAEb,UAAU,EAEV,cAAc,EACd,aAAa,EACd,MAAM,YAAY,CAAC;AAapB;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,cAAc,IAAI,IAAI,CAC1D;KACG,CAAC,IAAI,MAAM,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GACtE,CAAC,SAAS;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GACtB,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACrB,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACxB,EACD,KAAK,CACN,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,2EAA2E;AAC3E,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI;KACrE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;KAAE;CAC7E,CAAC,CAAC,CAAC,CAAC;AAEL,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,cAAc,GACd,CAAC,eAAe,CAAC,cAAc,CAAC,GAAG;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC,CAAC;AAyIjE;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,cAAc,EAChD,IAAI,EAAE,CAAC,EACP,KAAK,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GACzB,UAAU,CAAC;AACd,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,UAAU,GAAG,IAAI,CAAC;AAerB;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,KAAK,CAAC,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC,EAC5C,WAAW,OAAO,CAAC,aAAa,CAAC,KAChC;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;CAO1D,CAAC"}
package/dist/build.js ADDED
@@ -0,0 +1,169 @@
1
+ // Constructor de bloques para consumidores sin editor (back-end, Workers,
2
+ // scripts): arma un `EmailBlock` válido partiendo de los defaults del esquema
3
+ // vivo, coacciona tipos, genera ids y completa los arrays de registros.
4
+ // Es puramente aditivo: no altera `normalize`, el render ni los defaults.
5
+ import { DEFAULT_BLOCK_LIBRARY, DEFAULT_SETTINGS, } from "./default-blocks.js";
6
+ import { newId } from "./id.js";
7
+ import { coerceNumber, normalizeRecordArray, RECORD_ARRAY_FIELDS, } from "./records.js";
8
+ import { listBlockDefinitions } from "./registry.js";
9
+ import { normalizeSettings } from "./normalize.js";
10
+ import { isContainerType } from "./types.js";
11
+ /** Props de layout opcionales (mismo conjunto que normaliza `normalize.ts`). */
12
+ const LAYOUT_KEYS = [
13
+ "paddingTop",
14
+ "paddingRight",
15
+ "paddingBottom",
16
+ "paddingLeft",
17
+ "marginTop",
18
+ "marginBottom",
19
+ "gap",
20
+ ];
21
+ const isEmailBlock = (value) => {
22
+ const block = value;
23
+ return (!!block &&
24
+ typeof block === "object" &&
25
+ typeof block.id === "string" &&
26
+ typeof block.type === "string" &&
27
+ !!block.props &&
28
+ typeof block.props === "object");
29
+ };
30
+ /** Normaliza las formas aceptadas de un hijo a `[type, props]`. */
31
+ const asShorthand = (value) => {
32
+ if (Array.isArray(value)) {
33
+ const [type, props] = value;
34
+ return typeof type === "string" ? { type, props } : null;
35
+ }
36
+ if (value && typeof value === "object") {
37
+ const raw = value;
38
+ return typeof raw.type === "string"
39
+ ? { type: raw.type, props: raw.props ?? {} }
40
+ : null;
41
+ }
42
+ return null;
43
+ };
44
+ const resolveDefinition = (type) => {
45
+ const live = listBlockDefinitions();
46
+ const library = live.length > 0 ? live : DEFAULT_BLOCK_LIBRARY;
47
+ return library.find((def) => def.type === type);
48
+ };
49
+ /**
50
+ * Construye las props de un bloque: defaults del esquema + lo que pases,
51
+ * coaccionando tipos y completando registros e hijos.
52
+ */
53
+ const buildProps = (definition, input, depth) => {
54
+ const props = structuredClone(definition.defaultProps);
55
+ const def = definition.type;
56
+ for (const key of Object.keys(props)) {
57
+ const value = input[key];
58
+ if (value === undefined || value === null)
59
+ continue;
60
+ const fallback = props[key];
61
+ if (key === "columns" && Array.isArray(fallback)) {
62
+ props[key] = buildColumns(value, depth);
63
+ }
64
+ else if (key === "blocks" && def === "container") {
65
+ props[key] = buildBlockList(value, depth + 1);
66
+ }
67
+ else if (key === "columns" && def === "gallery") {
68
+ props[key] = coerceNumber(value, fallback);
69
+ }
70
+ else if (RECORD_ARRAY_FIELDS[key]) {
71
+ props[key] = normalizeRecordArray(value, fallback, RECORD_ARRAY_FIELDS[key]);
72
+ }
73
+ else if (typeof fallback === "number") {
74
+ props[key] = coerceNumber(value, fallback);
75
+ }
76
+ else if (typeof fallback === "boolean") {
77
+ props[key] = value === true || value === "true";
78
+ }
79
+ else if (Array.isArray(fallback)) {
80
+ props[key] = Array.isArray(value) ? value.map((v) => String(v)) : fallback;
81
+ }
82
+ else if (typeof fallback === "string") {
83
+ props[key] = String(value);
84
+ }
85
+ else {
86
+ props[key] = value;
87
+ }
88
+ }
89
+ // Overrides de layout opcionales que no viven en los defaults.
90
+ for (const key of LAYOUT_KEYS) {
91
+ const value = input[key];
92
+ if (value === undefined || value === null)
93
+ continue;
94
+ if (typeof value === "number" && Number.isFinite(value)) {
95
+ props[key] = value;
96
+ }
97
+ else if (typeof value === "string" && value.trim() !== "") {
98
+ const parsed = parseFloat(value);
99
+ if (Number.isFinite(parsed))
100
+ props[key] = parsed;
101
+ }
102
+ }
103
+ return props;
104
+ };
105
+ /** Construye una lista de bloques (hijos de contenedores/columnas). */
106
+ const buildBlockList = (input, depth) => {
107
+ if (!Array.isArray(input))
108
+ return [];
109
+ const blocks = [];
110
+ for (const entry of input) {
111
+ if (isEmailBlock(entry)) {
112
+ // Ya es un bloque (p. ej. salido de `blockJson`): se respeta tal cual,
113
+ // salvo que sea un contenedor demasiado profundo.
114
+ if (depth > 0 && isContainerType(entry.type))
115
+ continue;
116
+ blocks.push(entry);
117
+ continue;
118
+ }
119
+ const shorthand = asShorthand(entry);
120
+ if (!shorthand)
121
+ continue;
122
+ if (depth > 0 && isContainerType(shorthand.type))
123
+ continue;
124
+ const definition = resolveDefinition(shorthand.type);
125
+ if (!definition)
126
+ continue;
127
+ blocks.push({
128
+ id: newId(),
129
+ type: definition.type,
130
+ props: buildProps(definition, shorthand.props ?? {}, depth),
131
+ });
132
+ }
133
+ return blocks;
134
+ };
135
+ /** Construye las celdas de `columns` / `grid` / `footer`. */
136
+ const buildColumns = (input, depth) => {
137
+ if (!Array.isArray(input))
138
+ return [];
139
+ return input.map((raw) => {
140
+ const col = (raw ?? {});
141
+ const id = typeof col.id === "string" && col.id ? col.id : newId();
142
+ const blocks = buildBlockList(col.blocks, depth + 1);
143
+ const width = coerceNumber(col.width, 0);
144
+ return width > 0 ? { id, blocks, width } : { id, blocks };
145
+ });
146
+ };
147
+ export function blockJson(type, props) {
148
+ if (typeof type !== "string" || !type)
149
+ return null;
150
+ const definition = resolveDefinition(type);
151
+ if (!definition)
152
+ return null;
153
+ return {
154
+ id: newId(),
155
+ type: definition.type,
156
+ props: buildProps(definition, props ?? {}, 0),
157
+ };
158
+ }
159
+ /**
160
+ * Construye el payload completo (`{ content, settings }`) listo para
161
+ * `renderTemplateEmail({ payload })`. Descarta los bloques inválidos (`null`).
162
+ */
163
+ export const templateJson = (blocks, settings) => ({
164
+ content: blocks.filter((block) => !!block && !!block.props),
165
+ settings: settings
166
+ ? normalizeSettings({ ...DEFAULT_SETTINGS, ...settings })
167
+ : {},
168
+ });
169
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"default-blocks.d.ts","sourceRoot":"","sources":["../src/default-blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE9E,eAAO,MAAM,eAAe,EAAE,YAK7B,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,aAI9B,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,eAAe,EAiJlD,CAAA"}
1
+ {"version":3,"file":"default-blocks.d.ts","sourceRoot":"","sources":["../src/default-blocks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE9E,eAAO,MAAM,eAAe,EAAE,YAK7B,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,aAK9B,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,eAAe,EAwelD,CAAA"}