@samva/markup 0.16.0 → 0.17.1
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 +42 -40
- package/CHANGELOG.md +72 -0
- package/README.md +10 -9
- package/dist/{brand-jFV6YtSV.d.ts → assets-CS5Xa_mr.d.ts} +41 -3
- package/dist/{brand-Ci05p37c.js → brand-CIiEqkU7.js} +64 -3
- package/dist/{brand-plugin-CHhcei-j.d.ts → brand-plugin-Dj9SMpfS.d.ts} +3 -1
- package/dist/brand.d.ts +2 -3
- package/dist/brand.js +3 -4
- package/dist/compatibility.d.ts +76 -0
- package/dist/compatibility.js +807 -0
- package/dist/compiled-template-Bc4Dq9zy.d.ts +268 -0
- package/dist/compiler.d.ts +59 -193
- package/dist/compiler.js +473 -775
- package/dist/{components-3XHjYD3i.js → components-C5850-Qg.js} +37 -29
- package/dist/css-B_aVKrDo.js +436 -0
- package/dist/css-color-DLM12Osu.js +315 -0
- package/dist/{diagnostic-codes-8XDLR9ef.js → diagnostic-codes-DZKb0Xcg.js} +40 -1
- package/dist/{diagnostics-CUYlQ_6x.d.ts → diagnostics-D4vSLQrO.d.ts} +1 -10
- package/dist/diagnostics.d.ts +6 -2
- package/dist/diagnostics.js +3 -4
- package/dist/edit.d.ts +10 -9
- package/dist/edit.js +12 -11
- package/dist/email/jsx-dev-runtime.d.ts +1 -1
- package/dist/email/jsx-dev-runtime.js +1 -1
- package/dist/email/jsx-runtime.d.ts +2 -2
- package/dist/email/jsx-runtime.js +2 -2
- package/dist/email.d.ts +1 -1
- package/dist/email.js +1 -1
- package/dist/html-DJUK2YJF.js +483 -0
- package/dist/index.d.ts +1 -1
- package/dist/{jsx-runtime-DC7xG0aA.d.ts → jsx-runtime-DL8NVF1f.d.ts} +12 -6
- package/dist/{jsx-runtime-CBlexoeR.js → jsx-runtime-qL19u3Fy.js} +17 -10
- package/dist/preview-rNoJBEIY.d.ts +104 -0
- package/dist/{profile-BsY4dkan.js → profile-JTvgCD6X.js} +714 -29
- package/dist/{html-BvRFepeO.js → render-template-DwPDm3Hq.js} +155 -572
- package/dist/render.d.ts +40 -28
- package/dist/render.js +3 -47
- package/dist/selectors-CYWCoxZr.js +157 -0
- package/dist/sms.d.ts +1 -1
- package/dist/sms.js +1 -1
- package/dist/{template-B-UDXK8a.d.ts → template-DmNcoH4Q.d.ts} +2 -9
- package/dist/{theme-css-s9QwD5Ko.js → theme-css-P9F5S7Ic.js} +3 -316
- package/dist/whatsapp.d.ts +1 -1
- package/dist/whatsapp.js +1 -1
- package/generated/contract.json +7 -2
- package/generated/reference.md +3 -2
- package/package.json +5 -5
- package/skills/sml/SKILL.md +2 -2
- package/dist/assets-BSpgZOSR.js +0 -61
- package/dist/assets-BSuNT9gr.d.ts +0 -39
- package/dist/brand-footer-ClRtWnIc.d.ts +0 -40
- package/dist/brand-footer-DXVGsKE5.js +0 -746
- package/dist/brand-sample.d.ts +0 -4
- package/dist/brand-sample.js +0 -2
- package/dist/cascade-DoLWZ66g.js +0 -701
- package/dist/diagnostic-model-DJtqbETd.js +0 -36
- package/dist/ir-KJLFW08u.js +0 -5
- package/dist/render-CVnXZMyK.js +0 -258
- package/dist/render-CuZej25A.d.ts +0 -564
- package/dist/theme-imports-u_P0ygvQ.js +0 -102
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
//#region src/sms-segments.d.ts
|
|
2
|
+
/** The encoding a message needs: GSM-7 when every character fits, UCS-2 otherwise. */
|
|
3
|
+
type SmsEncoding = "gsm7" | "ucs2";
|
|
4
|
+
interface SmsSegmentInfo {
|
|
5
|
+
readonly encoding: SmsEncoding;
|
|
6
|
+
readonly characterCount: number;
|
|
7
|
+
readonly segmentCount: number;
|
|
8
|
+
}
|
|
9
|
+
declare const smsSegmentInfo: (text: string) => SmsSegmentInfo;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/compiled-template.d.ts
|
|
12
|
+
/** The version this package writes. A publication pins the version it was built with. */
|
|
13
|
+
declare const COMPILED_TEMPLATE_VERSION = 1;
|
|
14
|
+
/**
|
|
15
|
+
* Where a node came from: `[line, column]` in the entry file, or `[line, column, file]` with an
|
|
16
|
+
* index into `CompiledTemplate.sources` when the node came from an imported project file. Published
|
|
17
|
+
* sends strip these.
|
|
18
|
+
*/
|
|
19
|
+
type CompiledSource = readonly [line: number, column: number, file?: number];
|
|
20
|
+
/**
|
|
21
|
+
* A value read at render time.
|
|
22
|
+
*
|
|
23
|
+
* - a string, number, boolean or `null` is a literal;
|
|
24
|
+
* - `bind` reads the input: `"order.id"` is a path from the input root, `"$item.title"` a path
|
|
25
|
+
* from the enclosing `each` variable named `item` (the `$` prefix keeps loop variables from
|
|
26
|
+
* colliding with input fields);
|
|
27
|
+
* - `lit` is a literal object or array, for formatter options;
|
|
28
|
+
* - `concat` joins the text of its parts (a template string);
|
|
29
|
+
* - `format` calls one formatter from `@samva/markup/fmt`;
|
|
30
|
+
* - `if` selects between two values (a conditional attribute or class);
|
|
31
|
+
* - `op` is arithmetic, allowed inside formatter arguments and conditions;
|
|
32
|
+
* - `length` is `.length` of a bound array or string;
|
|
33
|
+
* - `count` is `.filter(...).length`: the items of an array that satisfy a condition.
|
|
34
|
+
*/
|
|
35
|
+
type CompiledValue = string | number | boolean | null | {
|
|
36
|
+
readonly bind: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly lit: unknown;
|
|
39
|
+
} | {
|
|
40
|
+
readonly concat: readonly CompiledValue[];
|
|
41
|
+
} | {
|
|
42
|
+
readonly format: CompiledFormatter;
|
|
43
|
+
readonly args: readonly CompiledValue[];
|
|
44
|
+
} | {
|
|
45
|
+
readonly if: CompiledPredicate;
|
|
46
|
+
readonly then: CompiledValue;
|
|
47
|
+
readonly else: CompiledValue;
|
|
48
|
+
} | {
|
|
49
|
+
readonly op: CompiledArithmetic;
|
|
50
|
+
readonly args: readonly [CompiledValue, CompiledValue];
|
|
51
|
+
} | {
|
|
52
|
+
readonly length: CompiledValue;
|
|
53
|
+
} |
|
|
54
|
+
/** How many items of a bound array satisfy `where`, with each item bound as `$as` while it runs. */
|
|
55
|
+
{
|
|
56
|
+
readonly count: CompiledValue;
|
|
57
|
+
readonly as: string;
|
|
58
|
+
readonly where: CompiledPredicate;
|
|
59
|
+
};
|
|
60
|
+
type CompiledFormatter = "money" | "number" | "date" | "time" | "plural" | "list";
|
|
61
|
+
type CompiledArithmetic = "+" | "-" | "*" | "/" | "%";
|
|
62
|
+
type CompiledComparison = "eq" | "ne" | "lt" | "gt" | "le" | "ge";
|
|
63
|
+
/** A condition over the input. Truthiness follows JavaScript: `""`, `0`, `null` and absent are false. */
|
|
64
|
+
type CompiledPredicate =
|
|
65
|
+
/** The bound value at this path is truthy. */
|
|
66
|
+
{
|
|
67
|
+
readonly present: string;
|
|
68
|
+
} |
|
|
69
|
+
/** Any value is truthy. */
|
|
70
|
+
{
|
|
71
|
+
readonly truthy: CompiledValue;
|
|
72
|
+
} | {
|
|
73
|
+
readonly not: CompiledPredicate;
|
|
74
|
+
} | {
|
|
75
|
+
readonly and: readonly CompiledPredicate[];
|
|
76
|
+
} | {
|
|
77
|
+
readonly or: readonly CompiledPredicate[];
|
|
78
|
+
} | {
|
|
79
|
+
readonly cmp: CompiledComparison;
|
|
80
|
+
readonly args: readonly [CompiledValue, CompiledValue];
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* An element's inline style. A string is fully static and was checked at compile time; a list
|
|
84
|
+
* carries declarations whose values are read at render time; `if` selects between two styles.
|
|
85
|
+
*/
|
|
86
|
+
type CompiledStyle = string | readonly (readonly [property: string, value: CompiledValue])[] | {
|
|
87
|
+
readonly if: CompiledPredicate;
|
|
88
|
+
readonly then: CompiledStyle;
|
|
89
|
+
readonly else: CompiledStyle;
|
|
90
|
+
};
|
|
91
|
+
/** A part of compatibility markup the primitives emit verbatim. */
|
|
92
|
+
type CompiledRawPart = string | {
|
|
93
|
+
readonly attr: CompiledValue;
|
|
94
|
+
} | {
|
|
95
|
+
readonly text: CompiledValue;
|
|
96
|
+
};
|
|
97
|
+
interface CompiledElement {
|
|
98
|
+
readonly el: string;
|
|
99
|
+
readonly attrs?: Readonly<Record<string, CompiledValue>>;
|
|
100
|
+
readonly style?: CompiledStyle;
|
|
101
|
+
readonly children?: readonly CompiledNode[];
|
|
102
|
+
/**
|
|
103
|
+
* Set by the compiler on the elements `BrandFooter` writes: only they may carry the reserved
|
|
104
|
+
* footer markers, so an element the author wrote cannot claim a footer the send path would
|
|
105
|
+
* then not append.
|
|
106
|
+
*/
|
|
107
|
+
readonly reserved?: true;
|
|
108
|
+
readonly src?: CompiledSource;
|
|
109
|
+
}
|
|
110
|
+
/** Content that appears when the predicate holds, or else `else`. */
|
|
111
|
+
interface CompiledIf {
|
|
112
|
+
readonly if: CompiledPredicate;
|
|
113
|
+
readonly then: readonly CompiledNode[];
|
|
114
|
+
readonly else?: readonly CompiledNode[];
|
|
115
|
+
readonly src?: CompiledSource;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Repeat `children` for each item of a bound array.
|
|
119
|
+
*
|
|
120
|
+
* `where` skips the items that fail a condition (`.filter(...)`), with the item bound as `$as`.
|
|
121
|
+
* `chunk` groups the items into consecutive slices of that size instead: the loop variable `$as`
|
|
122
|
+
* then holds one slice, an array, and the last slice may be shorter. Filtering applies first.
|
|
123
|
+
*/
|
|
124
|
+
interface CompiledEach {
|
|
125
|
+
readonly each: CompiledValue;
|
|
126
|
+
/** The loop variable, referenced as `$as.field`. */
|
|
127
|
+
readonly as: string;
|
|
128
|
+
/** The zero-based index variable, referenced as `$index`. */
|
|
129
|
+
readonly index?: string;
|
|
130
|
+
readonly where?: CompiledPredicate;
|
|
131
|
+
readonly chunk?: number;
|
|
132
|
+
readonly children: readonly CompiledNode[];
|
|
133
|
+
readonly src?: CompiledSource;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Compatibility markup the email primitives emit verbatim (conditional comments, VML). Bound
|
|
137
|
+
* parts are escaped for the context they sit in. `text` is what the plain-text part reads.
|
|
138
|
+
*/
|
|
139
|
+
interface CompiledRaw {
|
|
140
|
+
readonly raw: readonly CompiledRawPart[];
|
|
141
|
+
readonly text?: CompiledValue;
|
|
142
|
+
readonly src?: CompiledSource;
|
|
143
|
+
}
|
|
144
|
+
/** Where the hidden inbox-preview block goes; it renders the channel's `preheader`. */
|
|
145
|
+
interface CompiledPreheader {
|
|
146
|
+
readonly preheader: true;
|
|
147
|
+
}
|
|
148
|
+
/** A node in an email body. A bare value in child position is rendered as escaped text. */
|
|
149
|
+
type CompiledNode = CompiledValue | CompiledElement | CompiledIf | CompiledEach | CompiledRaw | CompiledPreheader;
|
|
150
|
+
interface CompiledEmail {
|
|
151
|
+
readonly subject: CompiledValue;
|
|
152
|
+
readonly preheader?: CompiledValue;
|
|
153
|
+
readonly body: CompiledNode;
|
|
154
|
+
}
|
|
155
|
+
/** A plain-text channel body: text pieces, conditionals and loops. */
|
|
156
|
+
interface CompiledSms {
|
|
157
|
+
readonly category?: string;
|
|
158
|
+
readonly body: readonly CompiledNode[];
|
|
159
|
+
}
|
|
160
|
+
type CompiledWhatsAppButton = {
|
|
161
|
+
readonly type: "quick-reply";
|
|
162
|
+
readonly text: CompiledValue;
|
|
163
|
+
} | {
|
|
164
|
+
readonly type: "url";
|
|
165
|
+
readonly text: CompiledValue;
|
|
166
|
+
readonly url: CompiledValue;
|
|
167
|
+
} | {
|
|
168
|
+
readonly type: "phone";
|
|
169
|
+
readonly text: CompiledValue;
|
|
170
|
+
readonly phone: CompiledValue;
|
|
171
|
+
} | {
|
|
172
|
+
readonly type: "copy-code";
|
|
173
|
+
readonly code: CompiledValue;
|
|
174
|
+
} | {
|
|
175
|
+
readonly type: "flow";
|
|
176
|
+
readonly text: CompiledValue;
|
|
177
|
+
/** The Samva flow handle, resolved to Meta's flow id when the template is registered. */
|
|
178
|
+
readonly flow: string;
|
|
179
|
+
readonly action: "navigate" | "data_exchange";
|
|
180
|
+
/** Meta's `navigate_screen`; absent opens the flow's first entry screen. */
|
|
181
|
+
readonly screen?: string;
|
|
182
|
+
};
|
|
183
|
+
/** A button, or buttons that appear when a condition over the input holds. */
|
|
184
|
+
type CompiledWhatsAppButtonNode = CompiledWhatsAppButton | {
|
|
185
|
+
readonly if: CompiledPredicate;
|
|
186
|
+
readonly then: readonly CompiledWhatsAppButtonNode[];
|
|
187
|
+
readonly else?: readonly CompiledWhatsAppButtonNode[];
|
|
188
|
+
readonly src?: CompiledSource;
|
|
189
|
+
};
|
|
190
|
+
interface CompiledWhatsApp {
|
|
191
|
+
readonly category: string;
|
|
192
|
+
readonly language: string;
|
|
193
|
+
/** For a media header, `content` is the media URL. */
|
|
194
|
+
readonly header?: {
|
|
195
|
+
readonly type: "text" | "image" | "video" | "document";
|
|
196
|
+
readonly content: readonly CompiledNode[];
|
|
197
|
+
};
|
|
198
|
+
readonly body: readonly CompiledNode[];
|
|
199
|
+
readonly footer?: readonly CompiledNode[];
|
|
200
|
+
readonly buttons?: readonly CompiledWhatsAppButtonNode[];
|
|
201
|
+
}
|
|
202
|
+
interface CompiledTemplate {
|
|
203
|
+
readonly sml: typeof COMPILED_TEMPLATE_VERSION;
|
|
204
|
+
readonly template: string;
|
|
205
|
+
readonly locale?: string;
|
|
206
|
+
/** Project paths that `CompiledSource` file indexes name; index 0 is the entry. */
|
|
207
|
+
readonly sources?: readonly string[];
|
|
208
|
+
readonly email?: CompiledEmail;
|
|
209
|
+
readonly sms?: CompiledSms;
|
|
210
|
+
readonly whatsapp?: CompiledWhatsApp;
|
|
211
|
+
/** The portable JSON Schema every send's input is validated against. */
|
|
212
|
+
readonly schema: Readonly<Record<string, unknown>>;
|
|
213
|
+
}
|
|
214
|
+
/** The channels a template can declare and `render` can render. */
|
|
215
|
+
type Channel = "email" | "sms" | "whatsapp";
|
|
216
|
+
interface RenderedEmail {
|
|
217
|
+
readonly subject: string;
|
|
218
|
+
readonly preheader: string | undefined;
|
|
219
|
+
readonly html: string;
|
|
220
|
+
readonly text: string;
|
|
221
|
+
}
|
|
222
|
+
/** An SMS message: its text and what it costs in segments. */
|
|
223
|
+
interface RenderedSms {
|
|
224
|
+
readonly text: string;
|
|
225
|
+
readonly segments: SmsSegmentInfo;
|
|
226
|
+
}
|
|
227
|
+
type RenderedWhatsAppButton = {
|
|
228
|
+
readonly type: "quick-reply";
|
|
229
|
+
readonly text: string;
|
|
230
|
+
} | {
|
|
231
|
+
readonly type: "url";
|
|
232
|
+
readonly text: string;
|
|
233
|
+
readonly url: string;
|
|
234
|
+
} | {
|
|
235
|
+
readonly type: "phone";
|
|
236
|
+
readonly text: string;
|
|
237
|
+
readonly phone: string;
|
|
238
|
+
} | {
|
|
239
|
+
readonly type: "copy-code";
|
|
240
|
+
readonly code: string;
|
|
241
|
+
} | {
|
|
242
|
+
readonly type: "flow";
|
|
243
|
+
readonly text: string;
|
|
244
|
+
readonly flow: string;
|
|
245
|
+
readonly action: "navigate" | "data_exchange";
|
|
246
|
+
readonly screen?: string;
|
|
247
|
+
};
|
|
248
|
+
/** A WhatsApp message with every text rendered and every conditional button resolved. */
|
|
249
|
+
interface RenderedWhatsApp {
|
|
250
|
+
readonly language: string;
|
|
251
|
+
readonly category: string;
|
|
252
|
+
/** For a media header, `text` is the media URL. */
|
|
253
|
+
readonly header?: {
|
|
254
|
+
readonly type: "text" | "image" | "video" | "document";
|
|
255
|
+
readonly text: string;
|
|
256
|
+
};
|
|
257
|
+
readonly body: string;
|
|
258
|
+
readonly footer?: string;
|
|
259
|
+
readonly buttons: readonly RenderedWhatsAppButton[];
|
|
260
|
+
}
|
|
261
|
+
/** What `render` returns for each channel. */
|
|
262
|
+
interface RenderedMessage {
|
|
263
|
+
readonly email: RenderedEmail;
|
|
264
|
+
readonly sms: RenderedSms;
|
|
265
|
+
readonly whatsapp: RenderedWhatsApp;
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
268
|
+
export { smsSegmentInfo as A, RenderedEmail as C, RenderedWhatsAppButton as D, RenderedWhatsApp as E, SmsEncoding as O, CompiledWhatsAppButtonNode as S, RenderedSms as T, CompiledStyle as _, CompiledEach as a, CompiledWhatsApp as b, CompiledFormatter as c, CompiledPredicate as d, CompiledPreheader as f, CompiledSource as g, CompiledSms as h, CompiledComparison as i, SmsSegmentInfo as k, CompiledIf as l, CompiledRawPart as m, Channel as n, CompiledElement as o, CompiledRaw as p, CompiledArithmetic as r, CompiledEmail as s, COMPILED_TEMPLATE_VERSION as t, CompiledNode as u, CompiledTemplate as v, RenderedMessage as w, CompiledWhatsAppButton as x, CompiledValue as y };
|
package/dist/compiler.d.ts
CHANGED
|
@@ -1,135 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { n as renderBrandFooter, r as renderBrandSample, t as RenderedBrandFooter } from "./brand-footer-ClRtWnIc.js";
|
|
8
|
-
import { n as AssetEntry } from "./assets-BSuNT9gr.js";
|
|
9
|
-
import { caniemail } from "caniemail";
|
|
10
|
-
//#region src/email/compatibility.d.ts
|
|
11
|
-
type CaniemailClient = Parameters<typeof caniemail>[0]["clients"][number];
|
|
12
|
-
/** One client this compiler makes claims about. */
|
|
13
|
-
interface EmailClientTarget {
|
|
14
|
-
readonly id: CaniemailClient;
|
|
15
|
-
readonly label: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* The pinned matrix. Every finding is reported per client, and a client absent
|
|
19
|
-
* from this list is a client Samva makes no claim about.
|
|
20
|
-
*/
|
|
21
|
-
declare const EMAIL_CLIENT_MATRIX: readonly EmailClientTarget[];
|
|
22
|
-
interface CompatibilityProvenance {
|
|
23
|
-
/** The exact rules package a finding came from. */
|
|
24
|
-
readonly rules: string;
|
|
25
|
-
readonly apiVersion: string;
|
|
26
|
-
/** The day caniemail last changed the data this build was checked against. */
|
|
27
|
-
readonly lastUpdate: string;
|
|
28
|
-
}
|
|
29
|
-
declare const COMPATIBILITY_PROVENANCE: CompatibilityProvenance;
|
|
30
|
-
/**
|
|
31
|
-
* The constructs whose loss actually breaks a message: the recipient reads
|
|
32
|
-
* something different, in a different order, follows a link that does not work,
|
|
33
|
-
* or sees a layout that has collapsed. A target client dropping one of these
|
|
34
|
-
* blocks publication.
|
|
35
|
-
*
|
|
36
|
-
* The list is deliberately short and enumerated, because the contract is to
|
|
37
|
-
* block *known* failures. Nonessential differences require an assessment of
|
|
38
|
-
* emitted values: a concrete risk warns, expected differences and unverified
|
|
39
|
-
* behavior remain compatibility observations.
|
|
40
|
-
*/
|
|
41
|
-
declare const ESSENTIAL_CONSTRUCTS: ReadonlySet<string>;
|
|
42
|
-
interface CompatibilityInput {
|
|
43
|
-
/** The document the recipient receives. */
|
|
44
|
-
readonly html: string;
|
|
45
|
-
/** The declared fixture checked by this invocation. */
|
|
46
|
-
readonly fixture?: string | undefined;
|
|
47
|
-
/** Retained head rules, when they are not already inside the HTML. */
|
|
48
|
-
readonly css?: string | undefined;
|
|
49
|
-
/** Emitted-offset ranges with the origins of the node that produced them. */
|
|
50
|
-
readonly positions?: readonly EmittedPosition[] | undefined;
|
|
51
|
-
readonly clients?: readonly EmailClientTarget[] | undefined;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Check the emitted document against the pinned matrix.
|
|
55
|
-
*
|
|
56
|
-
* Findings are grouped by construct rather than repeated per client, so one
|
|
57
|
-
* unsupported property is one diagnostic naming every client that drops it.
|
|
58
|
-
*/
|
|
59
|
-
declare const checkEmailCompatibility: (input: CompatibilityInput) => readonly EmailDiagnostic[];
|
|
60
|
-
/**
|
|
61
|
-
* Constructs the pinned data says nothing about for a target client. These are
|
|
62
|
-
* reported so "we did not check that" is never mistaken for "that works".
|
|
63
|
-
*/
|
|
64
|
-
declare const unknownCoverage: (titles: Iterable<string>) => readonly EmailDiagnostic[];
|
|
65
|
-
/** A publication carrying one of these is refused; the message would arrive broken. */
|
|
66
|
-
declare const hasBlockingCompatibility: (findings: readonly EmailDiagnostic[]) => boolean;
|
|
67
|
-
//#endregion
|
|
68
|
-
//#region src/email/css-values.d.ts
|
|
69
|
-
/**
|
|
70
|
-
* Expand `var(--x, fallback)` against the collected custom properties.
|
|
71
|
-
* Values whose expansion exceeds the render-time budget are left as authored.
|
|
72
|
-
*/
|
|
73
|
-
declare const resolveVariables: (value: string, variables: Readonly<Record<string, string>>, depth?: number) => string;
|
|
74
|
-
/**
|
|
75
|
-
* Fold a constant `calc()` to a plain value. Tailwind writes every spacing
|
|
76
|
-
* utility as `calc(var(--spacing) * n)`, and classic Outlook does not implement
|
|
77
|
-
* `calc()` at all, so an unfolded value is a silently missing style. An
|
|
78
|
-
* expression that cannot be reduced to one term is left exactly as authored.
|
|
79
|
-
*/
|
|
80
|
-
declare const foldCalc: (value: string) => string;
|
|
81
|
-
/** Resolve custom properties, then fold what the arithmetic allows. */
|
|
82
|
-
declare const finalizeValue: (value: string, variables: Readonly<Record<string, string>>) => string;
|
|
83
|
-
/** Media Queries Level 4 range syntax down to the `min-`/`max-` prefixes clients support. */
|
|
84
|
-
declare const downlevelMediaQuery: (condition: string) => string;
|
|
85
|
-
/** Render the rules that could not be inlined as one `<style>` body. */
|
|
86
|
-
declare const renderHeadCss: (rules: readonly CssRule[], headAtRules: readonly string[], variables: Readonly<Record<string, string>>, darkVariables?: Readonly<Record<string, string>>) => string;
|
|
87
|
-
//#endregion
|
|
88
|
-
//#region src/email/css-color.d.ts
|
|
89
|
-
/** A color in extended sRGB, alpha included, before clamping and gamma. */
|
|
90
|
-
interface Rgba {
|
|
91
|
-
readonly r: number;
|
|
92
|
-
readonly g: number;
|
|
93
|
-
readonly b: number;
|
|
94
|
-
readonly a: number;
|
|
95
|
-
}
|
|
96
|
-
/** Parse any supported color notation into extended sRGB. `undefined` means "leave it alone". */
|
|
97
|
-
declare const parseColor: (value: string) => Rgba | undefined;
|
|
98
|
-
/** sRGB hex, or `rgba()` when the color is not opaque. */
|
|
99
|
-
declare const formatColor: (color: Rgba) => string;
|
|
100
|
-
/** Rewrite every modern color function in a declaration value; other text is untouched. */
|
|
101
|
-
declare const downlevelColors: (value: string) => string;
|
|
102
|
-
//#endregion
|
|
103
|
-
//#region src/email/cascade.d.ts
|
|
104
|
-
interface AppliedStyles {
|
|
105
|
-
readonly tree: EmailNode;
|
|
106
|
-
/** Rules that could not be inlined, ready for a `<style>` element in `<head>` after `darkRules`. */
|
|
107
|
-
readonly headCss: string;
|
|
108
|
-
/**
|
|
109
|
-
* A generated class for each distinct set of dark-mode declarations, mapped
|
|
110
|
-
* to those declarations. An element whose inlined styles read a color the
|
|
111
|
-
* theme's dark-mode block redefines carries the class.
|
|
112
|
-
*/
|
|
113
|
-
readonly darkRules: ReadonlyMap<string, string>;
|
|
114
|
-
/** Project `@font-face` rules, for a `<head>` style classic Outlook cannot see. */
|
|
115
|
-
readonly fontFaceCss: string;
|
|
116
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Resolve every stylesheet against the tree: inline what a client will honor on
|
|
120
|
-
* the element, and keep the rest for `<head>`. Where the sheet has a dark-mode
|
|
121
|
-
* theme, an element whose inlined styles read a color it redefines also gets a
|
|
122
|
-
* generated class whose dark-mode rule restates those styles at their dark
|
|
123
|
-
* values.
|
|
124
|
-
*/
|
|
125
|
-
declare const applyStylesheet: (root: EmailNode, sheet: Stylesheet, options?: {
|
|
126
|
-
readonly knownClasses?: ReadonlySet<string>;
|
|
127
|
-
}) => AppliedStyles;
|
|
128
|
-
//#endregion
|
|
129
|
-
//#region src/email/tailwind-stylesheets.gen.d.ts
|
|
130
|
-
/** The exact Tailwind release the compiler runs, recorded in every build manifest. */
|
|
131
|
-
declare const TAILWIND_VERSION = "4.3.3";
|
|
132
|
-
//#endregion
|
|
1
|
+
import { n as parseBrandSpecifier, t as BrandPlugin } from "./brand-plugin-Dj9SMpfS.js";
|
|
2
|
+
import { i as TemplateDiagnostic, n as EmailDiagnostic } from "./diagnostics-D4vSLQrO.js";
|
|
3
|
+
import { n as AssetEntry, p as EmailBrand } from "./assets-CS5Xa_mr.js";
|
|
4
|
+
import { v as CompiledTemplate } from "./compiled-template-Bc4Dq9zy.js";
|
|
5
|
+
import { i as TEMPLATE_NAME_PATTERN } from "./template-DmNcoH4Q.js";
|
|
6
|
+
import "css-tree";
|
|
133
7
|
//#region src/email/tailwind.d.ts
|
|
134
8
|
interface TailwindOptions {
|
|
135
9
|
/**
|
|
@@ -160,34 +34,6 @@ interface TailwindLimits {
|
|
|
160
34
|
/** Bytes of generated CSS. */
|
|
161
35
|
readonly cssBytes: number;
|
|
162
36
|
}
|
|
163
|
-
interface TailwindOutput {
|
|
164
|
-
readonly css: string;
|
|
165
|
-
readonly version: string;
|
|
166
|
-
/** Every candidate handed to the compiler, sorted, for the build manifest. */
|
|
167
|
-
readonly candidates: readonly string[];
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* What the project theme's `@import`s resolve to, already checked by
|
|
171
|
-
* `resolveThemeImports`: project stylesheets by path, and the brand theme the
|
|
172
|
-
* brand plugin's specifier stands for.
|
|
173
|
-
*/
|
|
174
|
-
interface TailwindImports {
|
|
175
|
-
readonly stylesheets: ReadonlyMap<string, string>;
|
|
176
|
-
readonly brandCss?: string | undefined;
|
|
177
|
-
/** Names the brand import; `samvaBrandPlugin` when omitted. */
|
|
178
|
-
readonly brandPlugin?: BrandPlugin | undefined;
|
|
179
|
-
}
|
|
180
|
-
/** Compile the discovered class set into CSS with the pinned Tailwind release. */
|
|
181
|
-
declare const compileTailwind: (candidates: Iterable<string>, options?: TailwindOptions, imports?: TailwindImports) => Promise<TailwindOutput>;
|
|
182
|
-
interface ClassDiscovery {
|
|
183
|
-
readonly candidates: readonly string[];
|
|
184
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Collect the class names one module states literally, and report the positions
|
|
188
|
-
* where a class is assembled from values the compiler cannot see.
|
|
189
|
-
*/
|
|
190
|
-
declare const discoverClassCandidates: (source: string, fileName: string) => ClassDiscovery;
|
|
191
37
|
//#endregion
|
|
192
38
|
//#region src/email/transform.d.ts
|
|
193
39
|
/** Where this build serves assets from, and how Tailwind is configured. */
|
|
@@ -203,35 +49,25 @@ interface TransformOptions {
|
|
|
203
49
|
/** Names the brand import and marks the footer `BrandFooter` renders; `samvaBrandPlugin` when omitted. */
|
|
204
50
|
readonly brandPlugin?: BrandPlugin | undefined;
|
|
205
51
|
}
|
|
206
|
-
interface ProjectTransform {
|
|
207
|
-
readonly assets: readonly AssetEntry[];
|
|
208
|
-
/**
|
|
209
|
-
* The compiled Tailwind sheet: the default theme, the primitives' rules, the project theme and
|
|
210
|
-
* the utilities the project uses. Without Tailwind, the default theme and the primitives' rules.
|
|
211
|
-
*/
|
|
212
|
-
readonly tailwindSheet: Stylesheet | undefined;
|
|
213
|
-
/** Every project stylesheet, parsed, by path. */
|
|
214
|
-
readonly stylesheets: ReadonlyMap<string, Stylesheet>;
|
|
215
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
216
|
-
}
|
|
217
52
|
/**
|
|
218
53
|
* The brand specifier a project imports — from its theme's `@import`s or its
|
|
219
54
|
* TSX — so a host can fetch that brand before it compiles. `undefined` when
|
|
220
55
|
* the project imports no brand. A project that names two brands gets the
|
|
221
56
|
* first here and a refusal from the compile.
|
|
222
57
|
*/
|
|
223
|
-
declare const projectBrandSpecifier: (files: Readonly<Record<string, string | Uint8Array>>,
|
|
224
|
-
|
|
225
|
-
|
|
58
|
+
declare const projectBrandSpecifier: (files: Readonly<Record<string, string | Uint8Array>>, options?: {
|
|
59
|
+
readonly themePath?: string | undefined;
|
|
60
|
+
readonly brandPlugin?: BrandPlugin | undefined;
|
|
61
|
+
}) => string | undefined;
|
|
226
62
|
//#endregion
|
|
227
63
|
//#region src/sml/lower-project.d.ts
|
|
228
|
-
interface
|
|
229
|
-
/** The
|
|
230
|
-
readonly
|
|
64
|
+
interface CompileResult {
|
|
65
|
+
/** The compiled template, or `undefined` when a finding blocks it. */
|
|
66
|
+
readonly template: CompiledTemplate | undefined;
|
|
231
67
|
/** The fixtures read from the entry, with imported assets resolved to their URLs. */
|
|
232
68
|
readonly fixtures: Readonly<Record<string, unknown>>;
|
|
233
69
|
readonly assets: readonly AssetEntry[];
|
|
234
|
-
/** Errors block the
|
|
70
|
+
/** Errors block the template; warnings ride along. */
|
|
235
71
|
readonly diagnostics: readonly TemplateDiagnostic[];
|
|
236
72
|
}
|
|
237
73
|
//#endregion
|
|
@@ -248,18 +84,8 @@ interface CompileTemplateOptions extends TransformOptions {
|
|
|
248
84
|
*/
|
|
249
85
|
readonly schema?: Readonly<Record<string, unknown>> | undefined;
|
|
250
86
|
}
|
|
251
|
-
/** Compile a project's entry template
|
|
252
|
-
declare const compileTemplate: (options: CompileTemplateOptions) => Promise<
|
|
253
|
-
//#endregion
|
|
254
|
-
//#region src/sml/compatibility.d.ts
|
|
255
|
-
/**
|
|
256
|
-
* Check what each declared fixture delivers against the pinned client matrix. The rules run on the
|
|
257
|
-
* rendered document, because what a client drops is what the compiler produced, and every finding
|
|
258
|
-
* is located at the source of the element that produced it.
|
|
259
|
-
*/
|
|
260
|
-
declare const checkTemplateCompatibility: (ir: TemplateIr, fixtures: Readonly<Record<string, unknown>>, options?: {
|
|
261
|
-
readonly clients?: readonly EmailClientTarget[] | undefined;
|
|
262
|
-
}) => readonly EmailDiagnostic[];
|
|
87
|
+
/** Compile a project's entry template without evaluating any of it. */
|
|
88
|
+
declare const compileTemplate: (options: CompileTemplateOptions) => Promise<CompileResult>;
|
|
263
89
|
//#endregion
|
|
264
90
|
//#region src/sml/profile.d.ts
|
|
265
91
|
/**
|
|
@@ -267,11 +93,51 @@ declare const checkTemplateCompatibility: (ir: TemplateIr, fixtures: Readonly<Re
|
|
|
267
93
|
* and the entry's path. Imports of files that are absent are trusted to exist, and the brand,
|
|
268
94
|
* Tailwind and theme are not resolved, so the result holds only findings the source itself owns.
|
|
269
95
|
*/
|
|
270
|
-
declare const
|
|
96
|
+
declare const checkTemplate: (files: string | Readonly<Record<string, string | Uint8Array>>, options?: {
|
|
97
|
+
readonly entry?: string | undefined;
|
|
98
|
+
readonly brandPlugin?: BrandPlugin | undefined;
|
|
99
|
+
}) => readonly TemplateDiagnostic[];
|
|
271
100
|
/**
|
|
272
101
|
* The errors in `after` that `before` did not already have, compared by code and message so a
|
|
273
102
|
* finding that only moved does not count as new.
|
|
274
103
|
*/
|
|
275
|
-
declare const
|
|
104
|
+
declare const introducedErrors: (before: readonly TemplateDiagnostic[], after: readonly TemplateDiagnostic[]) => readonly TemplateDiagnostic[];
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/email/footer.d.ts
|
|
107
|
+
/** A footer block for the send path to append, and its plain-text tail. */
|
|
108
|
+
interface CompiledFooter {
|
|
109
|
+
readonly html: string;
|
|
110
|
+
readonly text: string;
|
|
111
|
+
/**
|
|
112
|
+
* The rules the footer needs in the message's `<head>`: its dark-mode colors and the
|
|
113
|
+
* `dark:` swap of the brand logo. Empty when it needs none.
|
|
114
|
+
*/
|
|
115
|
+
readonly headCss: string;
|
|
116
|
+
}
|
|
117
|
+
interface FooterCompile {
|
|
118
|
+
/** The footer, or `undefined` when a finding blocks it. */
|
|
119
|
+
readonly footer: CompiledFooter | undefined;
|
|
120
|
+
readonly diagnostics: readonly EmailDiagnostic[];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Compile `BrandFooter` against a brand on its own, for the send path to append to a message
|
|
124
|
+
* whose template renders no footer of its own. It compiles the same component, styled by the same
|
|
125
|
+
* brand theme, a template would get from its brand import. The footer always carries the
|
|
126
|
+
* unsubscribe row; the send drops it with `withoutUnsubscribeRow` from `./brand` where the message
|
|
127
|
+
* has none. A brand theme outside the grammar leaves no footer and comes back as diagnostics.
|
|
128
|
+
*/
|
|
129
|
+
declare const compileFooter: (brand: EmailBrand, options?: {
|
|
130
|
+
readonly brandPlugin?: BrandPlugin | undefined;
|
|
131
|
+
}) => Promise<FooterCompile>;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/email/brand-preview.d.ts
|
|
134
|
+
/** The preview's HTML, or `undefined` when a finding blocks it. */
|
|
135
|
+
interface BrandPreview {
|
|
136
|
+
readonly html: string | undefined;
|
|
137
|
+
readonly diagnostics: readonly TemplateDiagnostic[];
|
|
138
|
+
}
|
|
139
|
+
declare const previewBrand: (brand: EmailBrand, options?: {
|
|
140
|
+
readonly brandPlugin?: BrandPlugin | undefined;
|
|
141
|
+
}) => Promise<BrandPreview>;
|
|
276
142
|
//#endregion
|
|
277
|
-
export { type
|
|
143
|
+
export { type BrandPreview, type CompileResult, type CompileTemplateOptions, type CompiledFooter, type FooterCompile, TEMPLATE_NAME_PATTERN, type TailwindOptions, checkTemplate, compileFooter, compileTemplate, introducedErrors, parseBrandSpecifier, previewBrand, projectBrandSpecifier };
|