@samva/markup 0.8.0 → 0.10.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/AGENTS.md +107 -46
- package/CHANGELOG.md +345 -0
- package/README.md +188 -52
- package/dist/{brand-DcoVkh_S.d.ts → assets-BIsyMQ92.d.ts} +41 -11
- package/dist/{email/brand.js → brand-C0MKTwmX.js} +64 -4
- package/dist/{theme-css.d.ts → brand.d.ts} +12 -3
- package/dist/brand.js +4 -0
- package/dist/channel-specs-C2feJwuP.d.ts +13 -0
- package/dist/compiler.d.ts +88 -115
- package/dist/compiler.js +750 -171
- package/dist/components-BZCqegS8.js +1864 -0
- package/dist/diagnostic-model-DJtqbETd.js +38 -0
- package/dist/{diagnostics-OcQKQYSY.d.ts → diagnostic-model-DxthUZBT.d.ts} +3 -21
- package/dist/{diagnostics-BMYtBCQk.d.ts → diagnostics-B-Gym34R.d.ts} +8 -4
- package/dist/{email/diagnostics.js → diagnostics-CnKFefKz.js} +4 -3
- package/dist/diagnostics.d.ts +410 -2
- package/dist/diagnostics.js +402 -52
- package/dist/edit.d.ts +234 -0
- package/dist/edit.js +947 -0
- package/dist/email/jsx-dev-runtime.d.ts +2 -2
- package/dist/email/jsx-dev-runtime.js +1 -2
- package/dist/email/jsx-runtime.d.ts +1 -1
- package/dist/email/jsx-runtime.js +1 -85
- package/dist/{email/components.d.ts → email.d.ts} +22 -11
- package/dist/email.js +2 -0
- package/dist/fmt.d.ts +32 -0
- package/dist/fmt.js +174 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/{render-vAv_4r9v.js → ir-CLhlklKV.js} +96 -279
- package/dist/jsx-runtime-CBlexoeR.js +98 -0
- package/dist/{elements-BzjjnoCS.d.ts → jsx-runtime-ylIOnaSf.d.ts} +76 -76
- package/dist/profile-pWGtWZXF.js +3803 -0
- package/dist/render-BPonDpCl.d.ts +539 -0
- package/dist/render-BQmfh94k.js +257 -0
- package/dist/render.d.ts +35 -0
- package/dist/render.js +49 -0
- package/dist/sms.d.ts +16 -0
- package/dist/sms.js +12 -0
- package/dist/source-locations-C8wCsiAy.d.ts +23 -0
- package/dist/template-DMPwxMSq.d.ts +65 -0
- package/dist/template-zLUjcwfF.js +42 -0
- package/dist/{theme-css-hFqcPSar.js → theme-css-JtRCm1fb.js} +2 -2
- package/dist/whatsapp.d.ts +57 -0
- package/dist/whatsapp.js +22 -0
- package/generated/contract.json +1788 -0
- package/generated/reference.md +360 -0
- package/package.json +46 -239
- package/samva-brand.d.ts +4 -4
- package/skills/sml/SKILL.md +123 -0
- package/dist/ast-BrDtApwS.d.ts +0 -107
- package/dist/ast.d.ts +0 -2
- package/dist/ast.js +0 -124
- package/dist/candidate.d.ts +0 -29
- package/dist/candidate.js +0 -88
- package/dist/catalog-CKuOooB8.d.ts +0 -354
- package/dist/checks-D73Xizbw.js +0 -59366
- package/dist/checks.d.ts +0 -33
- package/dist/checks.js +0 -2
- package/dist/classes.d.ts +0 -26
- package/dist/classes.js +0 -184
- package/dist/compile-sms.d.ts +0 -28
- package/dist/compile-sms.js +0 -44
- package/dist/compile-whatsapp.d.ts +0 -56
- package/dist/compile-whatsapp.js +0 -186
- package/dist/compile.d.ts +0 -18
- package/dist/compile.js +0 -29
- package/dist/components.d.ts +0 -289
- package/dist/components.js +0 -106
- package/dist/conditionals.d.ts +0 -10
- package/dist/conditionals.js +0 -74
- package/dist/corpus-CPPfgAHN.d.ts +0 -106
- package/dist/css-CS2jLID6.d.ts +0 -109
- package/dist/email/assets.d.ts +0 -40
- package/dist/email/assets.js +0 -63
- package/dist/email/brand-footer.d.ts +0 -34
- package/dist/email/brand-footer.js +0 -62
- package/dist/email/brand.d.ts +0 -2
- package/dist/email/components.js +0 -240
- package/dist/email/diagnostics.d.ts +0 -2
- package/dist/email/elements.d.ts +0 -2
- package/dist/email/elements.js +0 -299
- package/dist/email/html.d.ts +0 -2
- package/dist/email/html.js +0 -278
- package/dist/email/render.d.ts +0 -50
- package/dist/email/render.js +0 -3
- package/dist/email/selection.d.ts +0 -2
- package/dist/email/selection.js +0 -91
- package/dist/email/source-edit.d.ts +0 -67
- package/dist/email/source-edit.js +0 -185
- package/dist/email/stylesheets.d.ts +0 -15
- package/dist/email/stylesheets.js +0 -48
- package/dist/email/text.d.ts +0 -7
- package/dist/email/text.js +0 -100
- package/dist/emit.d.ts +0 -51
- package/dist/emit.js +0 -151
- package/dist/html-Bl9BAdqc.d.ts +0 -42
- package/dist/interpolate.d.ts +0 -24
- package/dist/interpolate.js +0 -43
- package/dist/jsx-dev-runtime.d.ts +0 -11
- package/dist/jsx-dev-runtime.js +0 -15
- package/dist/jsx-runtime-I-1nCtl2.d.ts +0 -57
- package/dist/jsx-runtime.d.ts +0 -2
- package/dist/jsx-runtime.js +0 -121
- package/dist/lexer.d.ts +0 -60
- package/dist/lexer.js +0 -281
- package/dist/model.d.ts +0 -24
- package/dist/model.js +0 -77
- package/dist/ops-BvwqHl7V.js +0 -630
- package/dist/ops.d.ts +0 -114
- package/dist/ops.js +0 -2
- package/dist/parser-t29cHLVL.d.ts +0 -396
- package/dist/parser.d.ts +0 -2
- package/dist/parser.js +0 -859
- package/dist/predicate-BI6uRRM-.js +0 -549
- package/dist/predicate-M-05Nd7R.d.ts +0 -56
- package/dist/predicate.d.ts +0 -2
- package/dist/predicate.js +0 -2
- package/dist/printer.d.ts +0 -6
- package/dist/printer.js +0 -122
- package/dist/registry-Dcp6QEK_.d.ts +0 -73
- package/dist/registry.d.ts +0 -2
- package/dist/registry.js +0 -646
- package/dist/render-template.d.ts +0 -45
- package/dist/render-template.js +0 -76
- package/dist/selection-CCArx9lU.d.ts +0 -91
- package/dist/showcase-egkusQBf.d.ts +0 -415
- package/dist/sms-segments-y4FpPilJ.d.ts +0 -13
- package/dist/sms-segments.d.ts +0 -2
- package/dist/sms-segments.js +0 -46
- package/dist/source-locations-DrCM82Ym.d.ts +0 -67
- package/dist/source-locations.d.ts +0 -2
- package/dist/source-locations.js +0 -102
- package/dist/starters/category-mapping.d.ts +0 -13
- package/dist/starters/category-mapping.js +0 -49
- package/dist/starters/corpus.d.ts +0 -2
- package/dist/starters/corpus.js +0 -194
- package/dist/starters/library.d.ts +0 -18
- package/dist/starters/library.js +0 -692
- package/dist/starters/public-gallery.d.ts +0 -266
- package/dist/starters/public-gallery.js +0 -916
- package/dist/starters/public-handoff.d.ts +0 -164
- package/dist/starters/public-handoff.js +0 -361
- package/dist/starters/public-preview-artifacts.d.ts +0 -43
- package/dist/starters/public-preview-artifacts.js +0 -104
- package/dist/starters/public-preview.d.ts +0 -61
- package/dist/starters/public-preview.js +0 -83
- package/dist/starters/showcase.d.ts +0 -2
- package/dist/starters/showcase.js +0 -335
- package/dist/starters/sources.d.ts +0 -45
- package/dist/starters/sources.js +0 -7762
- package/dist/starters/theme.d.ts +0 -45
- package/dist/starters/theme.js +0 -77
- package/dist/starters.d.ts +0 -2
- package/dist/starters.js +0 -874
- package/dist/tailwind-BYq7Lo6u.js +0 -727
- package/dist/template-DWftqh4x.d.ts +0 -60
- package/dist/template.d.ts +0 -2
- package/dist/template.js +0 -37
- package/dist/theme-css.js +0 -2
- package/dist/tsx-source-instrumentation.d.ts +0 -30
- package/dist/tsx-source-instrumentation.js +0 -115
- package/dist/tsx-tracer.d.ts +0 -112
- package/dist/tsx-tracer.js +0 -985
- package/dist/variables-J_L3qxRa.d.ts +0 -77
- package/dist/variables.d.ts +0 -2
- package/dist/variables.js +0 -141
- package/dist/version-BITr58kk.js +0 -96
- package/generated/sml-agent-contract.json +0 -709
- package/generated/sml-email-agent-contract.json +0 -615
- package/generated/sml-email-language-reference.md +0 -94
- package/generated/sml-language-reference.md +0 -195
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { P as emailElement, f as preheaderNode, v as serializeEmailHtml } from "./components-BZCqegS8.js";
|
|
2
|
+
import { i as drainEmailDiagnostics, t as EmailNode } from "./jsx-runtime-CBlexoeR.js";
|
|
3
|
+
import { n as applyStylesheet } from "./ir-CLhlklKV.js";
|
|
4
|
+
import { r as hasBlockingDiagnostic, t as EmailCompileError } from "./diagnostics-CnKFefKz.js";
|
|
5
|
+
//#region src/email/text.ts
|
|
6
|
+
const PARAGRAPH = "\n\n";
|
|
7
|
+
const LINE = "\n";
|
|
8
|
+
const INVISIBLE = /\u200b|\u200c|\u200d|\u200e|\u200f|\u2060|\ufeff/g;
|
|
9
|
+
const isLayoutTable = (props) => props.role === "presentation" || props.role === "none";
|
|
10
|
+
/**
|
|
11
|
+
* A data-table cell that reads as nothing and holds only imagery with empty alt text carries no
|
|
12
|
+
* column of its own; an empty cell without such an image is a positional placeholder.
|
|
13
|
+
*/
|
|
14
|
+
const isDecorativeCell = (cell, context) => {
|
|
15
|
+
const images = collect(cell.children, (tag) => tag === "img", () => true);
|
|
16
|
+
return images.length > 0 && images.every((image) => image.props.alt === "") && childText(cell, context).trim() === "";
|
|
17
|
+
};
|
|
18
|
+
/** Wrap a block's content in separators; empty blocks contribute nothing. */
|
|
19
|
+
const block = (inner, separator) => {
|
|
20
|
+
const trimmed = inner.replace(/^\s+/, "").replace(/\s+$/, "");
|
|
21
|
+
return trimmed === "" ? "" : `${separator}${trimmed}${separator}`;
|
|
22
|
+
};
|
|
23
|
+
const collect = (nodes, keep, descend) => nodes.flatMap((child) => {
|
|
24
|
+
if (child.type === "Fragment") return collect(child.children, keep, descend);
|
|
25
|
+
if (child.type !== "Element") return [];
|
|
26
|
+
if (keep(child.tag)) return [child];
|
|
27
|
+
return descend(child.tag) ? collect(child.children, keep, descend) : [];
|
|
28
|
+
});
|
|
29
|
+
const TABLE_SECTIONS = /* @__PURE__ */ new Set([
|
|
30
|
+
"thead",
|
|
31
|
+
"tbody",
|
|
32
|
+
"tfoot"
|
|
33
|
+
]);
|
|
34
|
+
const childText = (node, context) => node.children.map((child) => derive(child, context)).join("");
|
|
35
|
+
const derive = (node, context) => {
|
|
36
|
+
switch (node.type) {
|
|
37
|
+
case "Text": return context.preformatted ? node.value : node.value.replace(INVISIBLE, "").replace(/[^\S\n]+/g, " ");
|
|
38
|
+
case "Raw": return node.text;
|
|
39
|
+
case "Fragment": return node.children.map((child) => derive(child, context)).join("");
|
|
40
|
+
case "Element": {
|
|
41
|
+
const spec = emailElement(node.tag);
|
|
42
|
+
if (spec === void 0) return childText(node, context);
|
|
43
|
+
switch (spec.layout) {
|
|
44
|
+
case "metadata": return "";
|
|
45
|
+
case "document":
|
|
46
|
+
case "inline":
|
|
47
|
+
case "list-item": return childText(node, context);
|
|
48
|
+
case "break": return LINE;
|
|
49
|
+
case "rule": return `${PARAGRAPH}---${PARAGRAPH}`;
|
|
50
|
+
case "image": {
|
|
51
|
+
const alt = typeof node.props.alt === "string" ? node.props.alt.trim() : "";
|
|
52
|
+
return alt === "" ? "" : `[${alt}]`;
|
|
53
|
+
}
|
|
54
|
+
case "link": {
|
|
55
|
+
const label = childText(node, context).replace(/\s+/g, " ").trim();
|
|
56
|
+
const href = typeof node.props.href === "string" ? node.props.href : "";
|
|
57
|
+
if (href === "" || href === label) return label;
|
|
58
|
+
return label === "" ? href : `${label} (${href})`;
|
|
59
|
+
}
|
|
60
|
+
case "list": {
|
|
61
|
+
const indent = " ".repeat(context.listDepth);
|
|
62
|
+
const start = Number(node.props.start ?? 1);
|
|
63
|
+
const first = Number.isFinite(start) ? start : 1;
|
|
64
|
+
const nested = {
|
|
65
|
+
...context,
|
|
66
|
+
listDepth: context.listDepth + 1
|
|
67
|
+
};
|
|
68
|
+
const lines = collect(node.children, (tag) => tag === "li", () => false).map((item, index) => {
|
|
69
|
+
const marker = node.tag === "ol" ? `${first + index}.` : "-";
|
|
70
|
+
const continuation = `${indent}${" ".repeat(marker.length + 1)}`;
|
|
71
|
+
const [head = "", ...rest] = derive(item, nested).replace(/^\s+/, "").replace(/\s+$/, "").replace(/\n{2,}/g, LINE).split("\n");
|
|
72
|
+
return [`${indent}${marker} ${head}`, ...rest.map((line) => line.trim() === "" ? "" : /^\s/.test(line) ? line : `${continuation}${line}`)].join(LINE);
|
|
73
|
+
});
|
|
74
|
+
return block(lines.join(LINE), PARAGRAPH);
|
|
75
|
+
}
|
|
76
|
+
case "table": {
|
|
77
|
+
if (isLayoutTable(node.props)) return childText(node, context);
|
|
78
|
+
const rows = collect(node.children, (tag) => tag === "tr", (tag) => TABLE_SECTIONS.has(tag)).map((row) => collect(row.children, (tag) => tag === "td" || tag === "th", () => false).filter((cell) => !isDecorativeCell(cell, context)).map((cell) => childText(cell, context).replace(/\s+/g, " ").trim()).join(" | "));
|
|
79
|
+
return block(rows.join(LINE), PARAGRAPH);
|
|
80
|
+
}
|
|
81
|
+
case "row": return block(collect(node.children, (tag) => tag === "td" || tag === "th", () => false).map((cell) => childText(cell, context).replace(/^\s+|\s+$/g, "")).filter((cell) => cell !== "").join(LINE), LINE);
|
|
82
|
+
case "table-section":
|
|
83
|
+
case "cell": return block(childText(node, context), LINE);
|
|
84
|
+
case "preformatted": return block(childText(node, {
|
|
85
|
+
...context,
|
|
86
|
+
preformatted: true
|
|
87
|
+
}), PARAGRAPH);
|
|
88
|
+
case "block": return block(childText(node, context), PARAGRAPH);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
/** Collapse the separators the walk emits into readable plain text. */
|
|
94
|
+
const normalize = (value) => value.replace(/\r\n?/g, "\n").split("\n").map((line) => line.replace(/[^\S\n]+$/, "")).join("\n").replace(/\n{3,}/g, PARAGRAPH).trim();
|
|
95
|
+
/** Derive the plain-text alternative from the semantic tree in reading order. */
|
|
96
|
+
const deriveEmailText = (node) => normalize(derive(node, {
|
|
97
|
+
preformatted: false,
|
|
98
|
+
listDepth: 0
|
|
99
|
+
}));
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/email/render.ts
|
|
102
|
+
/** Classic Outlook lays a document out correctly only under a transitional doctype. */
|
|
103
|
+
const EMAIL_DOCTYPE = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
|
|
104
|
+
const settle = (diagnostics) => {
|
|
105
|
+
if (hasBlockingDiagnostic(diagnostics)) throw new EmailCompileError({ diagnostics });
|
|
106
|
+
return diagnostics;
|
|
107
|
+
};
|
|
108
|
+
/** Lower the derived tree to HTML and its plain-text alternative. */
|
|
109
|
+
const compileEmail = (node, options = {}) => {
|
|
110
|
+
const serialized = serializeEmailHtml(node, options);
|
|
111
|
+
const diagnostics = settle([...drainEmailDiagnostics(), ...serialized.diagnostics]);
|
|
112
|
+
return {
|
|
113
|
+
html: serialized.html,
|
|
114
|
+
text: deriveEmailText(node),
|
|
115
|
+
diagnostics,
|
|
116
|
+
positions: serialized.positions
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
/** Put the hidden preview block first inside `<body>`, or first overall when there is no shell. */
|
|
120
|
+
const withPreheader = (node, text) => {
|
|
121
|
+
const insert = (current) => {
|
|
122
|
+
if (current.type === "Fragment") {
|
|
123
|
+
for (const [index, child] of current.children.entries()) {
|
|
124
|
+
const replaced = insert(child);
|
|
125
|
+
if (replaced !== void 0) return EmailNode.Fragment({ children: current.children.with(index, replaced) });
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (current.type !== "Element") return void 0;
|
|
130
|
+
if (current.tag === "body") return EmailNode.Element({
|
|
131
|
+
...current,
|
|
132
|
+
children: [preheaderNode(text), ...current.children]
|
|
133
|
+
});
|
|
134
|
+
for (const [index, child] of current.children.entries()) {
|
|
135
|
+
const replaced = insert(child);
|
|
136
|
+
if (replaced !== void 0) return EmailNode.Element({
|
|
137
|
+
...current,
|
|
138
|
+
children: current.children.with(index, replaced)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
return insert(node) ?? EmailNode.Fragment({ children: [preheaderNode(text), node] });
|
|
143
|
+
};
|
|
144
|
+
const headStyle = (css, origins) => EmailNode.Element({
|
|
145
|
+
tag: "style",
|
|
146
|
+
props: {},
|
|
147
|
+
children: [EmailNode.Text({ value: css })],
|
|
148
|
+
origins,
|
|
149
|
+
authored: false
|
|
150
|
+
});
|
|
151
|
+
/**
|
|
152
|
+
* Put the retained rules in a `<style>` at the end of `<head>`, and project
|
|
153
|
+
* `@font-face` rules in a sibling classic Outlook cannot see. Outlook for
|
|
154
|
+
* Windows registers a face it cannot load and then renders the family in Times
|
|
155
|
+
* New Roman, ignoring the stack; hidden, the family is merely missing and the
|
|
156
|
+
* stack's fallback applies.
|
|
157
|
+
*/
|
|
158
|
+
const withHeadCss = (node, css, fontFaceCss) => {
|
|
159
|
+
const insert = (current) => {
|
|
160
|
+
if (current.type === "Fragment") {
|
|
161
|
+
for (const [index, child] of current.children.entries()) {
|
|
162
|
+
const replaced = insert(child);
|
|
163
|
+
if (replaced !== void 0) return EmailNode.Fragment({ children: current.children.with(index, replaced) });
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (current.type !== "Element") return void 0;
|
|
168
|
+
if (current.tag === "head") return EmailNode.Element({
|
|
169
|
+
...current,
|
|
170
|
+
children: [
|
|
171
|
+
...current.children,
|
|
172
|
+
...css === "" ? [] : [headStyle(css, current.origins)],
|
|
173
|
+
...fontFaceCss === "" ? [] : [
|
|
174
|
+
EmailNode.Raw({
|
|
175
|
+
html: "<!--[if !mso]><!-->",
|
|
176
|
+
text: "",
|
|
177
|
+
origins: []
|
|
178
|
+
}),
|
|
179
|
+
headStyle(fontFaceCss, current.origins),
|
|
180
|
+
EmailNode.Raw({
|
|
181
|
+
html: "<!--<![endif]-->",
|
|
182
|
+
text: "",
|
|
183
|
+
origins: []
|
|
184
|
+
})
|
|
185
|
+
]
|
|
186
|
+
]
|
|
187
|
+
});
|
|
188
|
+
for (const [index, child] of current.children.entries()) {
|
|
189
|
+
const replaced = insert(child);
|
|
190
|
+
if (replaced !== void 0) return EmailNode.Element({
|
|
191
|
+
...current,
|
|
192
|
+
children: current.children.with(index, replaced)
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
return insert(node);
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Render authored content against a stylesheet: inline what a client honors,
|
|
200
|
+
* keep the rest for `<head>`, and lower to HTML and text.
|
|
201
|
+
*/
|
|
202
|
+
const renderEmailContent = (stylesheet, render, options = {}) => {
|
|
203
|
+
drainEmailDiagnostics();
|
|
204
|
+
const content = render();
|
|
205
|
+
const invalid = [];
|
|
206
|
+
const fail = (code, message) => invalid.push({
|
|
207
|
+
code,
|
|
208
|
+
severity: "error",
|
|
209
|
+
message,
|
|
210
|
+
origins: []
|
|
211
|
+
});
|
|
212
|
+
if (typeof content.subject !== "string" || /[\r\n\u0000]/.test(content.subject)) fail("invalid-subject", "Invalid email subject: it must be one line of text.");
|
|
213
|
+
if (content.preheader !== void 0 && typeof content.preheader !== "string") fail("invalid-preheader", "Invalid email preheader: it must be a string.");
|
|
214
|
+
if (content.text !== void 0 && typeof content.text !== "string") fail("invalid-text", "Invalid plain text: it must be a string.");
|
|
215
|
+
settle(invalid);
|
|
216
|
+
const base = content.preheader === void 0 ? content.body : withPreheader(content.body, content.preheader);
|
|
217
|
+
const styled = stylesheet === void 0 ? {
|
|
218
|
+
tree: base,
|
|
219
|
+
headCss: "",
|
|
220
|
+
fontFaceCss: "",
|
|
221
|
+
diagnostics: []
|
|
222
|
+
} : applyStylesheet(base, stylesheet);
|
|
223
|
+
const style = [...styled.diagnostics];
|
|
224
|
+
let tree = styled.tree;
|
|
225
|
+
if (styled.headCss !== "" || styled.fontFaceCss !== "") {
|
|
226
|
+
const placed = withHeadCss(tree, styled.headCss, styled.fontFaceCss);
|
|
227
|
+
if (placed === void 0) style.push({
|
|
228
|
+
code: "missing-head",
|
|
229
|
+
severity: "error",
|
|
230
|
+
message: "Styles that cannot be inlined — media queries, dark-scheme rules and pseudo-selectors — need a <head> to live in. Wrap the message in <Email>, or write those declarations as inline styles.",
|
|
231
|
+
origins: []
|
|
232
|
+
});
|
|
233
|
+
else tree = placed;
|
|
234
|
+
}
|
|
235
|
+
settle(style);
|
|
236
|
+
const compiled = compileEmail(tree, options);
|
|
237
|
+
const prefix = compiled.html.startsWith("<html") ? EMAIL_DOCTYPE : "";
|
|
238
|
+
const html = `${prefix}${compiled.html}`;
|
|
239
|
+
const positions = prefix === "" ? compiled.positions : compiled.positions.map((position) => ({
|
|
240
|
+
...position,
|
|
241
|
+
start: position.start + prefix.length,
|
|
242
|
+
end: position.end + prefix.length
|
|
243
|
+
}));
|
|
244
|
+
return {
|
|
245
|
+
subject: content.subject,
|
|
246
|
+
preheader: content.preheader,
|
|
247
|
+
html,
|
|
248
|
+
text: content.text ?? compiled.text,
|
|
249
|
+
tree,
|
|
250
|
+
diagnostics: [...style, ...compiled.diagnostics],
|
|
251
|
+
positions
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
//#endregion
|
|
255
|
+
export { deriveEmailText as i, compileEmail as n, renderEmailContent as r, EMAIL_DOCTYPE as t };
|
|
256
|
+
|
|
257
|
+
//# sourceMappingURL=render-BQmfh94k.js.map
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { C as isUrlAttribute, S as emailElement, _ as EmailGlobalProps, b as EmailStyle, g as EmailElementSpec, h as EmailAttributeSpec, m as EMAIL_GLOBAL_ATTRIBUTES, p as EMAIL_ELEMENTS, r as EmailNode, v as EmailIntrinsicElements, x as EmailTag, y as EmailLayout } from "./jsx-runtime-ylIOnaSf.js";
|
|
2
|
+
import { $ as IrWhatsApp, A as emailAuthoringTarget, B as IrElement, D as EmittedPosition, E as EmailElementSelection, F as emailSelections, G as IrPredicate, H as IrFormatter, I as renderIrPreview, J as IrRawPart, K as IrPreheader, L as IrArithmetic, M as emailSelectionAncestry, N as emailSelectionIndex, O as INSTANCE_PATH_ATTRIBUTE, P as emailSelectionSiblings, Q as IrValue, R as IrComparison, U as IrIf, V as IrEmail, W as IrNode, X as IrSource, Y as IrSms, Z as IrStyle, a as renderEmailContent, at as RenderedPosition, c as checkAttribute, ct as TemplateIr, d as escapeText, et as IrWhatsAppButton, f as kebab, i as compileEmail, it as RenderedIrWhatsApp, j as emailDefinitionInstances, k as IrPreview, l as declarationValue, m as serializeStyle, n as EmailCompileOutput, nt as RenderOptions, o as EmailHtmlOutput, ot as RenderedWhatsAppButton, p as serializeEmailHtml, q as IrRaw, r as RenderedEmail, rt as RenderedIrEmail, s as SerializeEmailOptions, st as SML_IR_VERSION, t as EMAIL_DOCTYPE, tt as IrWhatsAppButtonNode, u as escapeAttribute, z as IrEach } from "./render-BPonDpCl.js";
|
|
3
|
+
//#region src/render-ir.d.ts
|
|
4
|
+
interface IrRenderDiagnostic {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly message: string;
|
|
7
|
+
}
|
|
8
|
+
declare class IrRenderError extends Error {
|
|
9
|
+
readonly diagnostics: readonly IrRenderDiagnostic[];
|
|
10
|
+
constructor(diagnostics: readonly IrRenderDiagnostic[]);
|
|
11
|
+
}
|
|
12
|
+
/** Render the email channel of a compiled template against one validated input. */
|
|
13
|
+
declare const renderIr: (ir: TemplateIr, input: unknown, options?: RenderOptions) => RenderedIrEmail;
|
|
14
|
+
/** Render the SMS channel of a compiled template to plain text. */
|
|
15
|
+
declare const renderIrSms: (ir: TemplateIr, input: unknown, options?: RenderOptions) => string;
|
|
16
|
+
/** Render the WhatsApp channel of a compiled template: every text rendered, conditional buttons resolved. */
|
|
17
|
+
declare const renderIrWhatsApp: (ir: TemplateIr, input: unknown, options?: RenderOptions) => RenderedIrWhatsApp;
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/email/text.d.ts
|
|
20
|
+
/** Derive the plain-text alternative from the semantic tree in reading order. */
|
|
21
|
+
declare const deriveEmailText: (node: EmailNode) => string;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/sms-segments.d.ts
|
|
24
|
+
/** The encoding a message needs: GSM-7 when every character fits, UCS-2 otherwise. */
|
|
25
|
+
type SmsEncoding = "gsm7" | "ucs2";
|
|
26
|
+
interface SmsSegmentInfo {
|
|
27
|
+
readonly encoding: SmsEncoding;
|
|
28
|
+
readonly characterCount: number;
|
|
29
|
+
readonly segmentCount: number;
|
|
30
|
+
}
|
|
31
|
+
declare const smsSegmentInfo: (text: string) => SmsSegmentInfo;
|
|
32
|
+
declare const hasSmsOptOut: (text: string) => boolean;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { EMAIL_DOCTYPE, EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, EmailAttributeSpec, EmailCompileOutput, EmailElementSelection, EmailElementSpec, EmailGlobalProps, EmailHtmlOutput, EmailIntrinsicElements, EmailLayout, EmailStyle, EmailTag, EmittedPosition, INSTANCE_PATH_ATTRIBUTE, IrArithmetic, IrComparison, IrEach, IrElement, IrEmail, IrFormatter, IrIf, IrNode, IrPredicate, IrPreheader, IrPreview, IrRaw, IrRawPart, IrRenderDiagnostic, IrRenderError, IrSms, IrSource, IrStyle, IrValue, IrWhatsApp, IrWhatsAppButton, IrWhatsAppButtonNode, RenderOptions, RenderedEmail, RenderedIrEmail, RenderedIrWhatsApp, RenderedPosition, RenderedWhatsAppButton, SML_IR_VERSION, SerializeEmailOptions, SmsEncoding, SmsSegmentInfo, TemplateIr, checkAttribute, compileEmail, declarationValue, deriveEmailText, emailAuthoringTarget, emailDefinitionInstances, emailElement, emailSelectionAncestry, emailSelectionIndex, emailSelectionSiblings, emailSelections, escapeAttribute, escapeText, hasSmsOptOut, isUrlAttribute, kebab, renderEmailContent, renderIr, renderIrPreview, renderIrSms, renderIrWhatsApp, serializeEmailHtml, serializeStyle, smsSegmentInfo };
|
|
35
|
+
//# sourceMappingURL=render.d.ts.map
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { A as renderIrSms, C as emailSelectionAncestry, D as renderIrPreview, E as emailSelections, F as isUrlAttribute, M as EMAIL_ELEMENTS, N as EMAIL_GLOBAL_ATTRIBUTES, O as IrRenderError, P as emailElement, S as emailDefinitionInstances, T as emailSelectionSiblings, _ as kebab, b as INSTANCE_PATH_ATTRIBUTE, g as escapeText, h as escapeAttribute, j as renderIrWhatsApp, k as renderIr, m as declarationValue, p as checkAttribute, v as serializeEmailHtml, w as emailSelectionIndex, x as emailAuthoringTarget, y as serializeStyle } from "./components-BZCqegS8.js";
|
|
2
|
+
import { t as SML_IR_VERSION } from "./ir-CLhlklKV.js";
|
|
3
|
+
import { i as deriveEmailText, n as compileEmail, r as renderEmailContent, t as EMAIL_DOCTYPE } from "./render-BQmfh94k.js";
|
|
4
|
+
//#region src/sms-segments.ts
|
|
5
|
+
const GSM7_EXTENDED = /* @__PURE__ */ new Set([
|
|
6
|
+
"[",
|
|
7
|
+
"]",
|
|
8
|
+
"{",
|
|
9
|
+
"}",
|
|
10
|
+
"\\",
|
|
11
|
+
"~",
|
|
12
|
+
"|",
|
|
13
|
+
"€",
|
|
14
|
+
"^",
|
|
15
|
+
"\f"
|
|
16
|
+
]);
|
|
17
|
+
const GSM7_BASIC_PATTERN = /^[@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&'()*+,\-./:;<=>?¡0-9ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà]*$/;
|
|
18
|
+
const containsNonGsmCharacters = (text) => {
|
|
19
|
+
for (const char of text) {
|
|
20
|
+
if (GSM7_EXTENDED.has(char)) continue;
|
|
21
|
+
if (!GSM7_BASIC_PATTERN.test(char)) return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
const smsSegmentInfo = (text) => {
|
|
26
|
+
if (containsNonGsmCharacters(text)) {
|
|
27
|
+
const codePoints = [...text].length;
|
|
28
|
+
const segmentCount = codePoints <= 70 ? 1 : Math.ceil(codePoints / 67);
|
|
29
|
+
return {
|
|
30
|
+
encoding: "ucs2",
|
|
31
|
+
characterCount: text.length,
|
|
32
|
+
segmentCount
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
let encodedLength = 0;
|
|
36
|
+
for (const char of text) encodedLength += GSM7_EXTENDED.has(char) ? 2 : 1;
|
|
37
|
+
const segmentCount = encodedLength <= 160 ? 1 : Math.ceil(encodedLength / 153);
|
|
38
|
+
return {
|
|
39
|
+
encoding: "gsm7",
|
|
40
|
+
characterCount: text.length,
|
|
41
|
+
segmentCount
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const SMS_OPT_OUT_PATTERN = /\b(stop|unsubscribe|opt[\s-]?out|cancel|quit)\b/i;
|
|
45
|
+
const hasSmsOptOut = (text) => SMS_OPT_OUT_PATTERN.test(text);
|
|
46
|
+
//#endregion
|
|
47
|
+
export { EMAIL_DOCTYPE, EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, INSTANCE_PATH_ATTRIBUTE, IrRenderError, SML_IR_VERSION, checkAttribute, compileEmail, declarationValue, deriveEmailText, emailAuthoringTarget, emailDefinitionInstances, emailElement, emailSelectionAncestry, emailSelectionIndex, emailSelectionSiblings, emailSelections, escapeAttribute, escapeText, hasSmsOptOut, isUrlAttribute, kebab, renderEmailContent, renderIr, renderIrPreview, renderIrSms, renderIrWhatsApp, serializeEmailHtml, serializeStyle, smsSegmentInfo };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=render.js.map
|
package/dist/sms.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { r as EmailNode, t as EmailChild } from "./jsx-runtime-ylIOnaSf.js";
|
|
2
|
+
import { t as SmsCategory } from "./channel-specs-C2feJwuP.js";
|
|
3
|
+
//#region src/sms.d.ts
|
|
4
|
+
interface SmsProps {
|
|
5
|
+
readonly category?: SmsCategory | undefined;
|
|
6
|
+
readonly children?: EmailChild;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The root of an SMS body: plain text with bindings, conditionals and formatters. The compiler
|
|
10
|
+
* reads it from source; executed, it is a fragment of its children so a template file that also
|
|
11
|
+
* declares an email body still evaluates.
|
|
12
|
+
*/
|
|
13
|
+
declare const Sms: (props: SmsProps) => EmailNode;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Sms, type SmsCategory, SmsProps };
|
|
16
|
+
//# sourceMappingURL=sms.d.ts.map
|
package/dist/sms.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { a as jsx, n as Fragment } from "./jsx-runtime-CBlexoeR.js";
|
|
2
|
+
//#region src/sms.ts
|
|
3
|
+
/**
|
|
4
|
+
* The root of an SMS body: plain text with bindings, conditionals and formatters. The compiler
|
|
5
|
+
* reads it from source; executed, it is a fragment of its children so a template file that also
|
|
6
|
+
* declares an email body still evaluates.
|
|
7
|
+
*/
|
|
8
|
+
const Sms = (props) => jsx(Fragment, { children: props.children });
|
|
9
|
+
//#endregion
|
|
10
|
+
export { Sms };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=sms.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/source-locations.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The source payload a JSX transform may attach to an element. The transform may omit any field
|
|
4
|
+
* for synthetic calls; only a complete payload can identify a source origin safely.
|
|
5
|
+
*/
|
|
6
|
+
interface JsxSource {
|
|
7
|
+
readonly fileName?: string | undefined;
|
|
8
|
+
readonly lineNumber?: number | undefined;
|
|
9
|
+
readonly columnNumber?: number | undefined;
|
|
10
|
+
}
|
|
11
|
+
/** A complete, normalized source origin for a JSX element. */
|
|
12
|
+
interface JsxSourceLocation {
|
|
13
|
+
readonly fileName: string;
|
|
14
|
+
readonly lineNumber: number;
|
|
15
|
+
readonly columnNumber: number;
|
|
16
|
+
}
|
|
17
|
+
/** The JSX prop that carries a {@link JsxSource} to the email JSX runtime. */
|
|
18
|
+
declare const JSX_SOURCE_LOCATION_PROP: "__samva_source_location";
|
|
19
|
+
/** Normalize the optional payload a JSX transform attaches. */
|
|
20
|
+
declare const completeJsxSourceLocation: (source: JsxSource | null | undefined) => JsxSourceLocation | undefined;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { completeJsxSourceLocation as i, JsxSource as n, JsxSourceLocation as r, JSX_SOURCE_LOCATION_PROP as t };
|
|
23
|
+
//# sourceMappingURL=source-locations-C8wCsiAy.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { r as EmailNode } from "./jsx-runtime-ylIOnaSf.js";
|
|
2
|
+
import { r as InputSchema } from "./input-schema-7dPFVvNE.js";
|
|
3
|
+
import { StandardJSONSchemaV1 } from "@standard-schema/spec";
|
|
4
|
+
//#region src/template.d.ts
|
|
5
|
+
/** One actual-input render owns all of a message's authored content. */
|
|
6
|
+
interface EmailContent {
|
|
7
|
+
readonly subject: string;
|
|
8
|
+
readonly preheader?: string;
|
|
9
|
+
readonly body: EmailNode;
|
|
10
|
+
readonly text?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The one naming contract for a template id and a fixture key: a letter, a digit or `_` first,
|
|
14
|
+
* then those plus `.`, `_` and `-`.
|
|
15
|
+
*
|
|
16
|
+
* Both names are written into file paths — a local export writes one page at
|
|
17
|
+
* `templates/<id>/<fixture>.html` — so each has to be a single plain path segment. The rule lives
|
|
18
|
+
* at the declaration, so a project that could not be exported is refused where the name is
|
|
19
|
+
* written rather than at the end of a build. Consumers that resolve a path from these names
|
|
20
|
+
* import this pattern; they do not restate it.
|
|
21
|
+
*/
|
|
22
|
+
declare const TEMPLATE_NAME_PATTERN: RegExp;
|
|
23
|
+
/** Caller input for generated references and separate authoring consumers. */
|
|
24
|
+
type TemplateInput<T extends {
|
|
25
|
+
readonly schema: unknown;
|
|
26
|
+
}> = T["schema"] extends InputSchema<infer Input> ? Input : never;
|
|
27
|
+
/**
|
|
28
|
+
* The one naming contract for a template `id`: lowercase kebab-case, the same rule as the CLI and
|
|
29
|
+
* API slug, so the id a definition declares is the handle a caller sends by.
|
|
30
|
+
*/
|
|
31
|
+
declare const TEMPLATE_ID_PATTERN: RegExp;
|
|
32
|
+
/** The email channel of a template: an envelope and a body, each a function of the input. */
|
|
33
|
+
interface EmailChannel<Input> {
|
|
34
|
+
readonly subject: (input: Input) => string;
|
|
35
|
+
readonly preheader?: ((input: Input) => string | undefined) | undefined;
|
|
36
|
+
readonly body: (input: Input) => EmailNode;
|
|
37
|
+
}
|
|
38
|
+
/** A template as `defineTemplate` returns it: its identity, input contract and each channel it declares. */
|
|
39
|
+
interface SmlTemplate<Input> {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly schema: InputSchema<Input>;
|
|
42
|
+
readonly fixtures: Readonly<Record<string, Input>>;
|
|
43
|
+
readonly locale?: string | undefined;
|
|
44
|
+
readonly email?: EmailChannel<Input> | undefined;
|
|
45
|
+
readonly sms?: ((input: Input) => EmailNode) | undefined;
|
|
46
|
+
readonly whatsapp?: ((input: Input) => EmailNode) | undefined;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Define a template: one id, one input schema, named fixtures and one body per channel. Every
|
|
50
|
+
* function in it receives the validated input and returns JSX or a string; a compiler reads them
|
|
51
|
+
* without running them, so nothing here executes at send time. Types are inferred from the
|
|
52
|
+
* Standard JSON Schema input.
|
|
53
|
+
*/
|
|
54
|
+
declare const defineTemplate: <S extends StandardJSONSchemaV1>(definition: {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly schema: S;
|
|
57
|
+
readonly fixtures: Readonly<Record<string, NoInfer<StandardJSONSchemaV1.InferInput<S>>>>;
|
|
58
|
+
readonly locale?: string | undefined;
|
|
59
|
+
readonly email?: EmailChannel<NoInfer<StandardJSONSchemaV1.InferInput<S>>> | undefined;
|
|
60
|
+
readonly sms?: ((input: NoInfer<StandardJSONSchemaV1.InferInput<S>>) => EmailNode) | undefined;
|
|
61
|
+
readonly whatsapp?: ((input: NoInfer<StandardJSONSchemaV1.InferInput<S>>) => EmailNode) | undefined;
|
|
62
|
+
}) => SmlTemplate<StandardJSONSchemaV1.InferInput<S>>;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { TEMPLATE_NAME_PATTERN as a, TEMPLATE_ID_PATTERN as i, EmailContent as n, TemplateInput as o, SmlTemplate as r, defineTemplate as s, EmailChannel as t };
|
|
65
|
+
//# sourceMappingURL=template-DMPwxMSq.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { n as inputSchema } from "./input-schema-zjkgrXn2.js";
|
|
2
|
+
//#region src/template.ts
|
|
3
|
+
/**
|
|
4
|
+
* The one naming contract for a template id and a fixture key: a letter, a digit or `_` first,
|
|
5
|
+
* then those plus `.`, `_` and `-`.
|
|
6
|
+
*
|
|
7
|
+
* Both names are written into file paths — a local export writes one page at
|
|
8
|
+
* `templates/<id>/<fixture>.html` — so each has to be a single plain path segment. The rule lives
|
|
9
|
+
* at the declaration, so a project that could not be exported is refused where the name is
|
|
10
|
+
* written rather than at the end of a build. Consumers that resolve a path from these names
|
|
11
|
+
* import this pattern; they do not restate it.
|
|
12
|
+
*/
|
|
13
|
+
const TEMPLATE_NAME_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
|
|
14
|
+
const checkTemplateName = (kind, value) => {
|
|
15
|
+
if (TEMPLATE_NAME_PATTERN.test(value)) return;
|
|
16
|
+
throw new TypeError(`${kind} ${JSON.stringify(value)} is not one path segment. A template id and a fixture key are written into file paths, so each must start with a letter, a digit or "_" and continue with letters, digits, ".", "_" or "-".`);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The one naming contract for a template `id`: lowercase kebab-case, the same rule as the CLI and
|
|
20
|
+
* API slug, so the id a definition declares is the handle a caller sends by.
|
|
21
|
+
*/
|
|
22
|
+
const TEMPLATE_ID_PATTERN = /^(?=.{1,100}$)[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
23
|
+
/**
|
|
24
|
+
* Define a template: one id, one input schema, named fixtures and one body per channel. Every
|
|
25
|
+
* function in it receives the validated input and returns JSX or a string; a compiler reads them
|
|
26
|
+
* without running them, so nothing here executes at send time. Types are inferred from the
|
|
27
|
+
* Standard JSON Schema input.
|
|
28
|
+
*/
|
|
29
|
+
const defineTemplate = (definition) => {
|
|
30
|
+
if (!TEMPLATE_ID_PATTERN.test(definition.id)) throw new TypeError(`Template id ${JSON.stringify(definition.id)} is not lowercase kebab-case. The id is the handle a send names, so write lowercase letters and digits joined by single hyphens, for example "order-shipped".`);
|
|
31
|
+
const fixtureNames = Object.keys(definition.fixtures);
|
|
32
|
+
if (fixtureNames.length === 0) throw new TypeError(`Template ${definition.id} declares no fixtures. Fixtures are the preview, the agent's render targets and the publish check; declare at least one.`);
|
|
33
|
+
for (const fixture of fixtureNames) checkTemplateName("Fixture key", fixture);
|
|
34
|
+
return {
|
|
35
|
+
...definition,
|
|
36
|
+
schema: inputSchema(definition.schema)
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { TEMPLATE_NAME_PATTERN as n, defineTemplate as r, TEMPLATE_ID_PATTERN as t };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=template-zLUjcwfF.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Result } from "better-result";
|
|
2
1
|
import { generate, parse, walk } from "css-tree";
|
|
2
|
+
import { Result } from "better-result";
|
|
3
3
|
//#region src/email/css-color.ts
|
|
4
4
|
const clamp = (value, low = 0, high = 1) => value < low ? low : value > high ? high : value;
|
|
5
5
|
const toGamma = (channel) => channel <= .0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - .055;
|
|
@@ -584,4 +584,4 @@ const brandTailwindCss = (brand) => printBrandCss({
|
|
|
584
584
|
//#endregion
|
|
585
585
|
export { brandThemeVariables as a, parseBrandCss as c, formatColor as d, parseColor as f, brandTailwindCss as i, printBrandCss as l, BRAND_FOREGROUND_VARIABLE as n, contrastForeground as o, brandForegroundDefaults as r, darkVariableName as s, BRAND_COLOR_VARIABLE as t, downlevelColors as u };
|
|
586
586
|
|
|
587
|
-
//# sourceMappingURL=theme-css-
|
|
587
|
+
//# sourceMappingURL=theme-css-JtRCm1fb.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { r as EmailNode, t as EmailChild } from "./jsx-runtime-ylIOnaSf.js";
|
|
2
|
+
import { n as WhatsAppCategory, r as WhatsAppHeaderType } from "./channel-specs-C2feJwuP.js";
|
|
3
|
+
//#region src/whatsapp.d.ts
|
|
4
|
+
interface WhatsAppProps {
|
|
5
|
+
readonly name?: string | undefined;
|
|
6
|
+
/** The Meta language code, for example `en_US`. */
|
|
7
|
+
readonly language: string;
|
|
8
|
+
readonly category: WhatsAppCategory;
|
|
9
|
+
readonly children?: EmailChild;
|
|
10
|
+
}
|
|
11
|
+
interface WhatsAppHeaderProps {
|
|
12
|
+
/** `text` by default; for `image`, `video` and `document` the child is the media URL. */
|
|
13
|
+
readonly type?: WhatsAppHeaderType | undefined;
|
|
14
|
+
readonly children?: EmailChild;
|
|
15
|
+
}
|
|
16
|
+
interface WhatsAppTextProps {
|
|
17
|
+
readonly children?: EmailChild;
|
|
18
|
+
}
|
|
19
|
+
interface WhatsAppButtonsProps {
|
|
20
|
+
readonly children?: EmailChild;
|
|
21
|
+
}
|
|
22
|
+
interface WhatsAppUrlButtonProps {
|
|
23
|
+
readonly url: string;
|
|
24
|
+
/** The button label. */
|
|
25
|
+
readonly children?: EmailChild;
|
|
26
|
+
}
|
|
27
|
+
interface WhatsAppPhoneButtonProps {
|
|
28
|
+
readonly phone: string;
|
|
29
|
+
/** The button label. */
|
|
30
|
+
readonly children?: EmailChild;
|
|
31
|
+
}
|
|
32
|
+
interface WhatsAppQuickReplyButtonProps {
|
|
33
|
+
/** The button label. */
|
|
34
|
+
readonly children?: EmailChild;
|
|
35
|
+
}
|
|
36
|
+
interface WhatsAppCopyCodeButtonProps {
|
|
37
|
+
/** The code the button copies. */
|
|
38
|
+
readonly children?: EmailChild;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The root of a WhatsApp body. Meta's template anatomy is the vocabulary: `WhatsApp.Header`,
|
|
42
|
+
* `WhatsApp.Body`, `WhatsApp.Footer` and `WhatsApp.Buttons`, whose children are the four button
|
|
43
|
+
* kinds.
|
|
44
|
+
*/
|
|
45
|
+
declare const WhatsApp: ((props: WhatsAppProps) => EmailNode) & {
|
|
46
|
+
Header: (props: WhatsAppHeaderProps) => EmailNode;
|
|
47
|
+
Body: (props: WhatsAppTextProps) => EmailNode;
|
|
48
|
+
Footer: (props: WhatsAppTextProps) => EmailNode;
|
|
49
|
+
Buttons: (props: WhatsAppButtonsProps) => EmailNode;
|
|
50
|
+
UrlButton: (props: WhatsAppUrlButtonProps) => EmailNode;
|
|
51
|
+
QuickReplyButton: (props: WhatsAppQuickReplyButtonProps) => EmailNode;
|
|
52
|
+
PhoneButton: (props: WhatsAppPhoneButtonProps) => EmailNode;
|
|
53
|
+
CopyCodeButton: (props: WhatsAppCopyCodeButtonProps) => EmailNode;
|
|
54
|
+
};
|
|
55
|
+
//#endregion
|
|
56
|
+
export { WhatsApp, WhatsAppButtonsProps, type WhatsAppCategory, WhatsAppCopyCodeButtonProps, WhatsAppHeaderProps, type WhatsAppHeaderType, WhatsAppPhoneButtonProps, WhatsAppProps, WhatsAppQuickReplyButtonProps, WhatsAppTextProps, WhatsAppUrlButtonProps };
|
|
57
|
+
//# sourceMappingURL=whatsapp.d.ts.map
|
package/dist/whatsapp.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { a as jsx, n as Fragment } from "./jsx-runtime-CBlexoeR.js";
|
|
2
|
+
//#region src/whatsapp.ts
|
|
3
|
+
const fragment = (children) => jsx(Fragment, { children });
|
|
4
|
+
/**
|
|
5
|
+
* The root of a WhatsApp body. Meta's template anatomy is the vocabulary: `WhatsApp.Header`,
|
|
6
|
+
* `WhatsApp.Body`, `WhatsApp.Footer` and `WhatsApp.Buttons`, whose children are the four button
|
|
7
|
+
* kinds.
|
|
8
|
+
*/
|
|
9
|
+
const WhatsApp = Object.assign((props) => fragment(props.children), {
|
|
10
|
+
Header: (props) => fragment(props.children),
|
|
11
|
+
Body: (props) => fragment(props.children),
|
|
12
|
+
Footer: (props) => fragment(props.children),
|
|
13
|
+
Buttons: (props) => fragment(props.children),
|
|
14
|
+
UrlButton: (props) => fragment(props.children),
|
|
15
|
+
QuickReplyButton: (props) => fragment(props.children),
|
|
16
|
+
PhoneButton: (props) => fragment(props.children),
|
|
17
|
+
CopyCodeButton: (props) => fragment(props.children)
|
|
18
|
+
});
|
|
19
|
+
//#endregion
|
|
20
|
+
export { WhatsApp };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=whatsapp.js.map
|