@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.
Files changed (60) hide show
  1. package/AGENTS.md +42 -40
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +10 -9
  4. package/dist/{brand-jFV6YtSV.d.ts → assets-CS5Xa_mr.d.ts} +41 -3
  5. package/dist/{brand-Ci05p37c.js → brand-CIiEqkU7.js} +64 -3
  6. package/dist/{brand-plugin-CHhcei-j.d.ts → brand-plugin-Dj9SMpfS.d.ts} +3 -1
  7. package/dist/brand.d.ts +2 -3
  8. package/dist/brand.js +3 -4
  9. package/dist/compatibility.d.ts +76 -0
  10. package/dist/compatibility.js +807 -0
  11. package/dist/compiled-template-Bc4Dq9zy.d.ts +268 -0
  12. package/dist/compiler.d.ts +59 -193
  13. package/dist/compiler.js +473 -775
  14. package/dist/{components-3XHjYD3i.js → components-C5850-Qg.js} +37 -29
  15. package/dist/css-B_aVKrDo.js +436 -0
  16. package/dist/css-color-DLM12Osu.js +315 -0
  17. package/dist/{diagnostic-codes-8XDLR9ef.js → diagnostic-codes-DZKb0Xcg.js} +40 -1
  18. package/dist/{diagnostics-CUYlQ_6x.d.ts → diagnostics-D4vSLQrO.d.ts} +1 -10
  19. package/dist/diagnostics.d.ts +6 -2
  20. package/dist/diagnostics.js +3 -4
  21. package/dist/edit.d.ts +10 -9
  22. package/dist/edit.js +12 -11
  23. package/dist/email/jsx-dev-runtime.d.ts +1 -1
  24. package/dist/email/jsx-dev-runtime.js +1 -1
  25. package/dist/email/jsx-runtime.d.ts +2 -2
  26. package/dist/email/jsx-runtime.js +2 -2
  27. package/dist/email.d.ts +1 -1
  28. package/dist/email.js +1 -1
  29. package/dist/html-DJUK2YJF.js +483 -0
  30. package/dist/index.d.ts +1 -1
  31. package/dist/{jsx-runtime-DC7xG0aA.d.ts → jsx-runtime-DL8NVF1f.d.ts} +12 -6
  32. package/dist/{jsx-runtime-CBlexoeR.js → jsx-runtime-qL19u3Fy.js} +17 -10
  33. package/dist/preview-rNoJBEIY.d.ts +104 -0
  34. package/dist/{profile-BsY4dkan.js → profile-JTvgCD6X.js} +714 -29
  35. package/dist/{html-BvRFepeO.js → render-template-DwPDm3Hq.js} +155 -572
  36. package/dist/render.d.ts +40 -28
  37. package/dist/render.js +3 -47
  38. package/dist/selectors-CYWCoxZr.js +157 -0
  39. package/dist/sms.d.ts +1 -1
  40. package/dist/sms.js +1 -1
  41. package/dist/{template-B-UDXK8a.d.ts → template-DmNcoH4Q.d.ts} +2 -9
  42. package/dist/{theme-css-s9QwD5Ko.js → theme-css-P9F5S7Ic.js} +3 -316
  43. package/dist/whatsapp.d.ts +1 -1
  44. package/dist/whatsapp.js +1 -1
  45. package/generated/contract.json +7 -2
  46. package/generated/reference.md +3 -2
  47. package/package.json +5 -5
  48. package/skills/sml/SKILL.md +2 -2
  49. package/dist/assets-BSpgZOSR.js +0 -61
  50. package/dist/assets-BSuNT9gr.d.ts +0 -39
  51. package/dist/brand-footer-ClRtWnIc.d.ts +0 -40
  52. package/dist/brand-footer-DXVGsKE5.js +0 -746
  53. package/dist/brand-sample.d.ts +0 -4
  54. package/dist/brand-sample.js +0 -2
  55. package/dist/cascade-DoLWZ66g.js +0 -701
  56. package/dist/diagnostic-model-DJtqbETd.js +0 -36
  57. package/dist/ir-KJLFW08u.js +0 -5
  58. package/dist/render-CVnXZMyK.js +0 -258
  59. package/dist/render-CuZej25A.d.ts +0 -564
  60. 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 };
@@ -1,135 +1,9 @@
1
- import { a as TemplateDiagnostic, r as EmailDiagnostic } from "./diagnostics-CUYlQ_6x.js";
2
- import { r as EmailNode } from "./jsx-runtime-DC7xG0aA.js";
3
- import { a as TEMPLATE_NAME_PATTERN, n as EmailContent } from "./template-B-UDXK8a.js";
4
- import { n as parseBrandSpecifier, t as BrandPlugin } from "./brand-plugin-CHhcei-j.js";
5
- import { a as EmailBrand } from "./brand-jFV6YtSV.js";
6
- import { C as Compound, D as EmittedPosition, S as CompiledSelector, T as matchesSelector, _ as Specificity, b as parseStylesheet, ct as TemplateIr, g as CssRule, h as CssDeclaration, v as Stylesheet, w as classListOf, x as Ancestry, y as compileSelector } from "./render-CuZej25A.js";
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>>, themePath?: string, brandPlugin?: BrandPlugin) => string | undefined;
224
- /** Read a whole project, then compile the classes its scripts used. */
225
- declare const transformProject: (files: Readonly<Record<string, string | Uint8Array>>, options: TransformOptions) => Promise<ProjectTransform>;
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 CompiledTemplate {
229
- /** The IR, or `undefined` when a finding blocks it. */
230
- readonly ir: TemplateIr | undefined;
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 IR; warnings ride along. */
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 to IR without evaluating any of it. */
252
- declare const compileTemplate: (options: CompileTemplateOptions) => Promise<CompiledTemplate>;
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 checkStaticProfile: (files: string | Readonly<Record<string, string | Uint8Array>>, entry?: string, brandPlugin?: BrandPlugin) => readonly TemplateDiagnostic[];
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 introducedProfileErrors: (before: readonly TemplateDiagnostic[], after: readonly TemplateDiagnostic[]) => readonly TemplateDiagnostic[];
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 Ancestry, type AppliedStyles, COMPATIBILITY_PROVENANCE, type ClassDiscovery, type CompatibilityInput, type CompatibilityProvenance, type CompileTemplateOptions, type CompiledSelector, type CompiledTemplate, type Compound, type CssDeclaration, type CssRule, EMAIL_CLIENT_MATRIX, ESSENTIAL_CONSTRUCTS, type EmailClientTarget, type EmailContent, type ProjectTransform, type RenderedBrandFooter, type Specificity, type Stylesheet, TAILWIND_VERSION, TEMPLATE_NAME_PATTERN, type TailwindLimits, type TailwindOptions, type TailwindOutput, type TransformOptions, applyStylesheet, checkEmailCompatibility, checkStaticProfile, checkTemplateCompatibility, classListOf, compileSelector, compileTailwind, compileTemplate, discoverClassCandidates, downlevelColors, downlevelMediaQuery, finalizeValue, foldCalc, formatColor, hasBlockingCompatibility, introducedProfileErrors, matchesSelector, parseBrandSpecifier, parseColor, parseStylesheet, projectBrandSpecifier, renderBrandFooter, renderBrandSample, renderHeadCss, resolveVariables, transformProject, unknownCoverage };
143
+ export { type BrandPreview, type CompileResult, type CompileTemplateOptions, type CompiledFooter, type FooterCompile, TEMPLATE_NAME_PATTERN, type TailwindOptions, checkTemplate, compileFooter, compileTemplate, introducedErrors, parseBrandSpecifier, previewBrand, projectBrandSpecifier };