@samva/markup 0.15.1 → 0.17.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 +42 -35
- package/CHANGELOG.md +92 -0
- package/README.md +10 -9
- package/dist/{assets-tISHaQNF.d.ts → assets-CS5Xa_mr.d.ts} +3 -3
- package/dist/{brand-nreeKWxF.js → brand-CIiEqkU7.js} +24 -31
- package/dist/{brand-plugin-CHhcei-j.d.ts → brand-plugin-Dj9SMpfS.d.ts} +3 -1
- package/dist/brand.d.ts +2 -2
- package/dist/brand.js +3 -3
- 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 +58 -225
- package/dist/compiler.js +261 -1297
- 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-UXwOO3A-.js → diagnostic-codes-DZKb0Xcg.js} +4 -0
- 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 -3
- 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-AatO_SvP.js → profile-JTvgCD6X.js} +614 -24
- 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 -1
- package/skills/sml/SKILL.md +2 -2
- package/dist/ir-DNL6H7jA.js +0 -705
- package/dist/render-BdvewoQt.d.ts +0 -564
- package/dist/render-DpYouYYG.js +0 -258
|
@@ -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,133 +1,9 @@
|
|
|
1
|
-
import { n as parseBrandSpecifier, t as BrandPlugin } from "./brand-plugin-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { caniemail } from "caniemail";
|
|
8
|
-
//#region src/email/compatibility.d.ts
|
|
9
|
-
type CaniemailClient = Parameters<typeof caniemail>[0]["clients"][number];
|
|
10
|
-
/** One client this compiler makes claims about. */
|
|
11
|
-
interface EmailClientTarget {
|
|
12
|
-
readonly id: CaniemailClient;
|
|
13
|
-
readonly label: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* The pinned matrix. Every finding is reported per client, and a client absent
|
|
17
|
-
* from this list is a client Samva makes no claim about.
|
|
18
|
-
*/
|
|
19
|
-
declare const EMAIL_CLIENT_MATRIX: readonly EmailClientTarget[];
|
|
20
|
-
interface CompatibilityProvenance {
|
|
21
|
-
/** The exact rules package a finding came from. */
|
|
22
|
-
readonly rules: string;
|
|
23
|
-
readonly apiVersion: string;
|
|
24
|
-
/** The day caniemail last changed the data this build was checked against. */
|
|
25
|
-
readonly lastUpdate: string;
|
|
26
|
-
}
|
|
27
|
-
declare const COMPATIBILITY_PROVENANCE: CompatibilityProvenance;
|
|
28
|
-
/**
|
|
29
|
-
* The constructs whose loss actually breaks a message: the recipient reads
|
|
30
|
-
* something different, in a different order, follows a link that does not work,
|
|
31
|
-
* or sees a layout that has collapsed. A target client dropping one of these
|
|
32
|
-
* blocks publication.
|
|
33
|
-
*
|
|
34
|
-
* The list is deliberately short and enumerated, because the contract is to
|
|
35
|
-
* block *known* failures. Nonessential differences require an assessment of
|
|
36
|
-
* emitted values: a concrete risk warns, expected differences and unverified
|
|
37
|
-
* behavior remain compatibility observations.
|
|
38
|
-
*/
|
|
39
|
-
declare const ESSENTIAL_CONSTRUCTS: ReadonlySet<string>;
|
|
40
|
-
interface CompatibilityInput {
|
|
41
|
-
/** The document the recipient receives. */
|
|
42
|
-
readonly html: string;
|
|
43
|
-
/** The declared fixture checked by this invocation. */
|
|
44
|
-
readonly fixture?: string | undefined;
|
|
45
|
-
/** Retained head rules, when they are not already inside the HTML. */
|
|
46
|
-
readonly css?: string | undefined;
|
|
47
|
-
/** Emitted-offset ranges with the origins of the node that produced them. */
|
|
48
|
-
readonly positions?: readonly EmittedPosition[] | undefined;
|
|
49
|
-
readonly clients?: readonly EmailClientTarget[] | undefined;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Check the emitted document against the pinned matrix.
|
|
53
|
-
*
|
|
54
|
-
* Findings are grouped by construct rather than repeated per client, so one
|
|
55
|
-
* unsupported property is one diagnostic naming every client that drops it.
|
|
56
|
-
*/
|
|
57
|
-
declare const checkEmailCompatibility: (input: CompatibilityInput) => readonly EmailDiagnostic[];
|
|
58
|
-
/**
|
|
59
|
-
* Constructs the pinned data says nothing about for a target client. These are
|
|
60
|
-
* reported so "we did not check that" is never mistaken for "that works".
|
|
61
|
-
*/
|
|
62
|
-
declare const unknownCoverage: (titles: Iterable<string>) => readonly EmailDiagnostic[];
|
|
63
|
-
/** A publication carrying one of these is refused; the message would arrive broken. */
|
|
64
|
-
declare const hasBlockingCompatibility: (findings: readonly EmailDiagnostic[]) => boolean;
|
|
65
|
-
//#endregion
|
|
66
|
-
//#region src/email/css-values.d.ts
|
|
67
|
-
/**
|
|
68
|
-
* Expand `var(--x, fallback)` against the collected custom properties.
|
|
69
|
-
* Values whose expansion exceeds the render-time budget are left as authored.
|
|
70
|
-
*/
|
|
71
|
-
declare const resolveVariables: (value: string, variables: Readonly<Record<string, string>>, depth?: number) => string;
|
|
72
|
-
/**
|
|
73
|
-
* Fold a constant `calc()` to a plain value. Tailwind writes every spacing
|
|
74
|
-
* utility as `calc(var(--spacing) * n)`, and classic Outlook does not implement
|
|
75
|
-
* `calc()` at all, so an unfolded value is a silently missing style. An
|
|
76
|
-
* expression that cannot be reduced to one term is left exactly as authored.
|
|
77
|
-
*/
|
|
78
|
-
declare const foldCalc: (value: string) => string;
|
|
79
|
-
/** Resolve custom properties, then fold what the arithmetic allows. */
|
|
80
|
-
declare const finalizeValue: (value: string, variables: Readonly<Record<string, string>>) => string;
|
|
81
|
-
/** Media Queries Level 4 range syntax down to the `min-`/`max-` prefixes clients support. */
|
|
82
|
-
declare const downlevelMediaQuery: (condition: string) => string;
|
|
83
|
-
/** Render the rules that could not be inlined as one `<style>` body. */
|
|
84
|
-
declare const renderHeadCss: (rules: readonly CssRule[], headAtRules: readonly string[], variables: Readonly<Record<string, string>>, darkVariables?: Readonly<Record<string, string>>) => string;
|
|
85
|
-
//#endregion
|
|
86
|
-
//#region src/email/css-color.d.ts
|
|
87
|
-
/** A color in extended sRGB, alpha included, before clamping and gamma. */
|
|
88
|
-
interface Rgba {
|
|
89
|
-
readonly r: number;
|
|
90
|
-
readonly g: number;
|
|
91
|
-
readonly b: number;
|
|
92
|
-
readonly a: number;
|
|
93
|
-
}
|
|
94
|
-
/** Parse any supported color notation into extended sRGB. `undefined` means "leave it alone". */
|
|
95
|
-
declare const parseColor: (value: string) => Rgba | undefined;
|
|
96
|
-
/** sRGB hex, or `rgba()` when the color is not opaque. */
|
|
97
|
-
declare const formatColor: (color: Rgba) => string;
|
|
98
|
-
/** Rewrite every modern color function in a declaration value; other text is untouched. */
|
|
99
|
-
declare const downlevelColors: (value: string) => string;
|
|
100
|
-
//#endregion
|
|
101
|
-
//#region src/email/cascade.d.ts
|
|
102
|
-
interface AppliedStyles {
|
|
103
|
-
readonly tree: EmailNode;
|
|
104
|
-
/** Rules that could not be inlined, ready for a `<style>` element in `<head>` after `darkRules`. */
|
|
105
|
-
readonly headCss: string;
|
|
106
|
-
/**
|
|
107
|
-
* A generated class for each distinct set of dark-mode declarations, mapped
|
|
108
|
-
* to those declarations. An element whose inlined styles read a color the
|
|
109
|
-
* theme's dark-mode block redefines carries the class.
|
|
110
|
-
*/
|
|
111
|
-
readonly darkRules: ReadonlyMap<string, string>;
|
|
112
|
-
/** Project `@font-face` rules, for a `<head>` style classic Outlook cannot see. */
|
|
113
|
-
readonly fontFaceCss: string;
|
|
114
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Resolve every stylesheet against the tree: inline what a client will honor on
|
|
118
|
-
* the element, and keep the rest for `<head>`. Where the sheet has a dark-mode
|
|
119
|
-
* theme, an element whose inlined styles read a color it redefines also gets a
|
|
120
|
-
* generated class whose dark-mode rule restates those styles at their dark
|
|
121
|
-
* values.
|
|
122
|
-
*/
|
|
123
|
-
declare const applyStylesheet: (root: EmailNode, sheet: Stylesheet, options?: {
|
|
124
|
-
readonly knownClasses?: ReadonlySet<string>;
|
|
125
|
-
}) => AppliedStyles;
|
|
126
|
-
//#endregion
|
|
127
|
-
//#region src/email/tailwind-stylesheets.gen.d.ts
|
|
128
|
-
/** The exact Tailwind release the compiler runs, recorded in every build manifest. */
|
|
129
|
-
declare const TAILWIND_VERSION = "4.3.3";
|
|
130
|
-
//#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";
|
|
131
7
|
//#region src/email/tailwind.d.ts
|
|
132
8
|
interface TailwindOptions {
|
|
133
9
|
/**
|
|
@@ -158,34 +34,6 @@ interface TailwindLimits {
|
|
|
158
34
|
/** Bytes of generated CSS. */
|
|
159
35
|
readonly cssBytes: number;
|
|
160
36
|
}
|
|
161
|
-
interface TailwindOutput {
|
|
162
|
-
readonly css: string;
|
|
163
|
-
readonly version: string;
|
|
164
|
-
/** Every candidate handed to the compiler, sorted, for the build manifest. */
|
|
165
|
-
readonly candidates: readonly string[];
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* What the project theme's `@import`s resolve to, already checked by
|
|
169
|
-
* `resolveThemeImports`: project stylesheets by path, and the brand theme the
|
|
170
|
-
* brand plugin's specifier stands for.
|
|
171
|
-
*/
|
|
172
|
-
interface TailwindImports {
|
|
173
|
-
readonly stylesheets: ReadonlyMap<string, string>;
|
|
174
|
-
readonly brandCss?: string | undefined;
|
|
175
|
-
/** Names the brand import; `samvaBrandPlugin` when omitted. */
|
|
176
|
-
readonly brandPlugin?: BrandPlugin | undefined;
|
|
177
|
-
}
|
|
178
|
-
/** Compile the discovered class set into CSS with the pinned Tailwind release. */
|
|
179
|
-
declare const compileTailwind: (candidates: Iterable<string>, options?: TailwindOptions, imports?: TailwindImports) => Promise<TailwindOutput>;
|
|
180
|
-
interface ClassDiscovery {
|
|
181
|
-
readonly candidates: readonly string[];
|
|
182
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Collect the class names one module states literally, and report the positions
|
|
186
|
-
* where a class is assembled from values the compiler cannot see.
|
|
187
|
-
*/
|
|
188
|
-
declare const discoverClassCandidates: (source: string, fileName: string) => ClassDiscovery;
|
|
189
37
|
//#endregion
|
|
190
38
|
//#region src/email/transform.d.ts
|
|
191
39
|
/** Where this build serves assets from, and how Tailwind is configured. */
|
|
@@ -201,70 +49,25 @@ interface TransformOptions {
|
|
|
201
49
|
/** Names the brand import and marks the footer `BrandFooter` renders; `samvaBrandPlugin` when omitted. */
|
|
202
50
|
readonly brandPlugin?: BrandPlugin | undefined;
|
|
203
51
|
}
|
|
204
|
-
interface ProjectTransform {
|
|
205
|
-
readonly assets: readonly AssetEntry[];
|
|
206
|
-
/**
|
|
207
|
-
* The compiled Tailwind sheet: the default theme, the primitives' rules, the project theme and
|
|
208
|
-
* the utilities the project uses. Without Tailwind, the default theme and the primitives' rules.
|
|
209
|
-
*/
|
|
210
|
-
readonly tailwindSheet: Stylesheet | undefined;
|
|
211
|
-
/** Every project stylesheet, parsed, by path. */
|
|
212
|
-
readonly stylesheets: ReadonlyMap<string, Stylesheet>;
|
|
213
|
-
readonly diagnostics: readonly EmailDiagnostic[];
|
|
214
|
-
}
|
|
215
52
|
/**
|
|
216
53
|
* The brand specifier a project imports — from its theme's `@import`s or its
|
|
217
54
|
* TSX — so a host can fetch that brand before it compiles. `undefined` when
|
|
218
55
|
* the project imports no brand. A project that names two brands gets the
|
|
219
56
|
* first here and a refusal from the compile.
|
|
220
57
|
*/
|
|
221
|
-
declare const projectBrandSpecifier: (files: Readonly<Record<string, string | Uint8Array>>,
|
|
222
|
-
|
|
223
|
-
declare const transformProject: (files: Readonly<Record<string, string | Uint8Array>>, options: TransformOptions) => Promise<ProjectTransform>;
|
|
224
|
-
//#endregion
|
|
225
|
-
//#region src/email/brand-footer.d.ts
|
|
226
|
-
/** A footer block for the send path to append, and its plain-text tail. */
|
|
227
|
-
interface RenderedBrandFooter {
|
|
228
|
-
readonly html: string;
|
|
229
|
-
readonly text: string;
|
|
230
|
-
/**
|
|
231
|
-
* The rules the footer needs in the message's `<head>`: its dark-mode colors and the
|
|
232
|
-
* `dark:` swap of the brand logo. Empty when it needs none.
|
|
233
|
-
*/
|
|
234
|
-
readonly headCss: string;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Render `BrandFooter` against a brand on its own, for the send path to
|
|
238
|
-
* append to a message whose template renders no footer of its own. It
|
|
239
|
-
* compiles the same component, styled by the same brand theme, a template
|
|
240
|
-
* would get from its brand import. Without `unsubscribe` the unsubscribe row is
|
|
241
|
-
* left out.
|
|
242
|
-
*/
|
|
243
|
-
declare const renderBrandFooter: (brand: EmailBrand, options: {
|
|
244
|
-
readonly unsubscribe: boolean;
|
|
58
|
+
declare const projectBrandSpecifier: (files: Readonly<Record<string, string | Uint8Array>>, options?: {
|
|
59
|
+
readonly themePath?: string | undefined;
|
|
245
60
|
readonly brandPlugin?: BrandPlugin | undefined;
|
|
246
|
-
}) =>
|
|
247
|
-
/**
|
|
248
|
-
* Render content against a brand as a project whose `theme.css` imports only
|
|
249
|
-
* the brand renders it: Tailwind compiles the brand theme for
|
|
250
|
-
* the classes the content names, `BrandLogo` and `BrandFooter` are bound to the
|
|
251
|
-
* brand, and the render inlines the result. A brand preview renders through
|
|
252
|
-
* this, so it shows what a template importing the brand compiles to.
|
|
253
|
-
*/
|
|
254
|
-
declare const renderBrandSample: (brand: EmailBrand, sample: {
|
|
255
|
-
/** Every class the content names; nothing is discovered from source here. */
|
|
256
|
-
readonly classes: readonly string[];
|
|
257
|
-
readonly render: (components: BrandComponents) => EmailContent;
|
|
258
|
-
}, brandPlugin?: BrandPlugin) => Promise<RenderedEmail>;
|
|
61
|
+
}) => string | undefined;
|
|
259
62
|
//#endregion
|
|
260
63
|
//#region src/sml/lower-project.d.ts
|
|
261
|
-
interface
|
|
262
|
-
/** The
|
|
263
|
-
readonly
|
|
64
|
+
interface CompileResult {
|
|
65
|
+
/** The compiled template, or `undefined` when a finding blocks it. */
|
|
66
|
+
readonly template: CompiledTemplate | undefined;
|
|
264
67
|
/** The fixtures read from the entry, with imported assets resolved to their URLs. */
|
|
265
68
|
readonly fixtures: Readonly<Record<string, unknown>>;
|
|
266
69
|
readonly assets: readonly AssetEntry[];
|
|
267
|
-
/** Errors block the
|
|
70
|
+
/** Errors block the template; warnings ride along. */
|
|
268
71
|
readonly diagnostics: readonly TemplateDiagnostic[];
|
|
269
72
|
}
|
|
270
73
|
//#endregion
|
|
@@ -281,18 +84,8 @@ interface CompileTemplateOptions extends TransformOptions {
|
|
|
281
84
|
*/
|
|
282
85
|
readonly schema?: Readonly<Record<string, unknown>> | undefined;
|
|
283
86
|
}
|
|
284
|
-
/** Compile a project's entry template
|
|
285
|
-
declare const compileTemplate: (options: CompileTemplateOptions) => Promise<
|
|
286
|
-
//#endregion
|
|
287
|
-
//#region src/sml/compatibility.d.ts
|
|
288
|
-
/**
|
|
289
|
-
* Check what each declared fixture delivers against the pinned client matrix. The rules run on the
|
|
290
|
-
* rendered document, because what a client drops is what the compiler produced, and every finding
|
|
291
|
-
* is located at the source of the element that produced it.
|
|
292
|
-
*/
|
|
293
|
-
declare const checkTemplateCompatibility: (ir: TemplateIr, fixtures: Readonly<Record<string, unknown>>, options?: {
|
|
294
|
-
readonly clients?: readonly EmailClientTarget[] | undefined;
|
|
295
|
-
}) => readonly EmailDiagnostic[];
|
|
87
|
+
/** Compile a project's entry template without evaluating any of it. */
|
|
88
|
+
declare const compileTemplate: (options: CompileTemplateOptions) => Promise<CompileResult>;
|
|
296
89
|
//#endregion
|
|
297
90
|
//#region src/sml/profile.d.ts
|
|
298
91
|
/**
|
|
@@ -300,11 +93,51 @@ declare const checkTemplateCompatibility: (ir: TemplateIr, fixtures: Readonly<Re
|
|
|
300
93
|
* and the entry's path. Imports of files that are absent are trusted to exist, and the brand,
|
|
301
94
|
* Tailwind and theme are not resolved, so the result holds only findings the source itself owns.
|
|
302
95
|
*/
|
|
303
|
-
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[];
|
|
304
100
|
/**
|
|
305
101
|
* The errors in `after` that `before` did not already have, compared by code and message so a
|
|
306
102
|
* finding that only moved does not count as new.
|
|
307
103
|
*/
|
|
308
|
-
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>;
|
|
309
142
|
//#endregion
|
|
310
|
-
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 };
|