@samva/markup 0.13.0 → 0.14.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 +11 -1
- package/CHANGELOG.md +50 -0
- package/dist/{assets-DCULM6QD.d.ts → assets-tISHaQNF.d.ts} +1 -1
- package/dist/{brand-C45QBKX9.js → brand-B-t62NJB.js} +4 -4
- package/dist/brand.d.ts +48 -25
- package/dist/brand.js +3 -3
- package/dist/compiler.d.ts +23 -6
- package/dist/compiler.js +657 -199
- package/dist/components-CwWSoG5N.js +401 -0
- package/dist/dark-scheme-CbCwGDWH.js +12 -0
- package/dist/{diagnostic-codes-DdZ4tka5.js → diagnostic-codes-UXwOO3A-.js} +22 -0
- package/dist/diagnostics.d.ts +17 -0
- package/dist/diagnostics.js +1 -1
- package/dist/edit.js +2 -2
- package/dist/email.d.ts +52 -9
- package/dist/email.js +1 -1
- package/dist/{ir-C-ubz6N3.js → ir-D-gTGquU.js} +202 -78
- package/dist/{profile-CXnkfEMi.js → profile-Cc8VxOKA.js} +72 -11
- package/dist/{render-Cja448i0.js → render-6gLei61p.js} +7 -5
- package/dist/{render-C6OTH8BQ.d.ts → render-C1X3S5or.d.ts} +5 -0
- package/dist/render.d.ts +1 -1
- package/dist/render.js +2 -2
- package/dist/{theme-css-CEUrDpqq.js → theme-css-s9QwD5Ko.js} +108 -46
- package/generated/contract.json +176 -2
- package/generated/reference.md +165 -118
- package/package.json +1 -1
- package/skills/sml/SKILL.md +63 -5
- package/dist/components-DycSEKva.js +0 -273
package/AGENTS.md
CHANGED
|
@@ -30,7 +30,7 @@ Authoring entries are what a template file imports:
|
|
|
30
30
|
mode) and `BrandFooter` (company, postal address, social links and the unsubscribe row the send
|
|
31
31
|
path fills). The compiler binds them to the brand the build resolves; add
|
|
32
32
|
`"types": ["@samva/markup/samva-brand"]` to the project's tsconfig for `tsc`. In `theme.css`,
|
|
33
|
-
`@import "samva:brand";` layers the brand theme; `samva:brand/<slug>` names one brand. These are
|
|
33
|
+
`@import "samva:brand";` layers the brand theme over the default theme (`DEFAULT_THEME`); `samva:brand/<slug>` names one brand. These are
|
|
34
34
|
Samva's brand plugin (`samvaBrandPlugin` from `@samva/markup/brand`), the default; a host that
|
|
35
35
|
delivers mail itself passes its own `BrandPlugin` as `brandPlugin` to `compileTemplate`,
|
|
36
36
|
`renderIr` and `renderBrandFooter` to rename the brand import, the footer markers, the
|
|
@@ -65,6 +65,7 @@ entry?)` is the synchronous structural check: it runs the compiler's lowering wi
|
|
|
65
65
|
conditional or element is a locked segment; and JSX source locations. Browser-safe: Babel parser
|
|
66
66
|
only.
|
|
67
67
|
- `@samva/markup/brand` — brand records and their CSS model (`parseBrandCss`, `printBrandCss`), the
|
|
68
|
+
theme vocabulary (`THEME_COLOR_ROLES`, `THEME_TOKENS`, `DEFAULT_THEME`, `foregroundDefaults`), the
|
|
68
69
|
footer markers a send reads (`renderedFooterMarkers`, `withoutUnsubscribeRow`), and project
|
|
69
70
|
assets (`isAssetPath`, `ASSET_CONTENT_TYPES`, `assetUrl`): which imported files become
|
|
70
71
|
content-addressed assets. The send path imports it, so its closure holds only the css-tree parser
|
|
@@ -117,6 +118,15 @@ Read the contract before authoring. Import only subpaths declared in `package.js
|
|
|
117
118
|
into file paths, so each must match `TEMPLATE_NAME_PATTERN`, one plain path segment.
|
|
118
119
|
`defineTemplate` throws a `TypeError` where the name is declared. Code that builds a path from these
|
|
119
120
|
names imports the pattern instead of restating it.
|
|
121
|
+
- **Naming a second set of tokens for dark mode.** A theme states dark mode once, in
|
|
122
|
+
`@media (prefers-color-scheme: dark) { @theme { --color-card: … } }`, with the same names as its
|
|
123
|
+
light `@theme`. The cascade gives every element whose inlined styles read one of those colors a
|
|
124
|
+
generated `sml-dark-*` class, so `bg-card` switches by itself. A `--color-card-dark` token is just
|
|
125
|
+
another color, and `dark:` only picks a different token. A block styled with palette colors
|
|
126
|
+
(`bg-indigo-600`) or raw hex ignores the theme; style with the vocabulary in `THEME_COLOR_ROLES`.
|
|
127
|
+
- **Reading contrast off the light render.** `checkEmailCompatibility` includes `email-contrast`,
|
|
128
|
+
which judges each fixture in light and dark mode (`CONTRAST_THRESHOLDS`); a color a dark block
|
|
129
|
+
leaves unpaired is an error there, not a visual nit.
|
|
120
130
|
- **Declaring a webfont as if every client loads it.** A project font is an ordinary `@font-face`
|
|
121
131
|
in the project's CSS (usually `theme.css`) whose `src` is a `.woff2` file in the project, named
|
|
122
132
|
by a path relative to that stylesheet; the compiler serves it as a content-addressed asset and
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
+
## @samva/markup@0.14.0
|
|
2
|
+
|
|
3
|
+
### A semantic theme vocabulary, one dark-mode mechanism and a contrast check
|
|
4
|
+
|
|
5
|
+
Every project compiles over a default theme in a shadcn-style vocabulary: `background`,
|
|
6
|
+
`foreground`, `card`, `primary`, `secondary`, `muted`, `accent` (each with its `-foreground`),
|
|
7
|
+
`border`, `--radius` (with `rounded-sm` to `rounded-xl` derived from it), `--font-sans` and
|
|
8
|
+
`--font-heading`. `starter.css`, a brand and the project's own `@theme` set the same names, so
|
|
9
|
+
`bg-card` or `text-primary-foreground` resolve in any project and a theme restyles every block that
|
|
10
|
+
reads them. `reference.md` and `contract.json` list the tokens, their roles and their defaults;
|
|
11
|
+
`@samva/markup/brand` exports `THEME_COLOR_ROLES`, `THEME_TOKENS` and `DEFAULT_THEME`.
|
|
12
|
+
|
|
13
|
+
Dark mode is one mechanism: the theme's `@media (prefers-color-scheme: dark) { @theme { … } }`
|
|
14
|
+
block, in project CSS and brand CSS alike. The compiler gives each element whose inlined styles
|
|
15
|
+
read a color that block redefines a generated `sml-dark-*` class with a dark-mode rule, so a block
|
|
16
|
+
writes `bg-card` once. Explicit `dark:` utilities still apply after it and resolve theme colors at
|
|
17
|
+
their dark values. A layer that sets a color in light mode only keeps it in dark mode, and a layer
|
|
18
|
+
that sets `--color-primary`, `--color-secondary` or `--color-accent` without its `-foreground` gets
|
|
19
|
+
black or white by contrast.
|
|
20
|
+
|
|
21
|
+
Breaking: the `-dark` suffix convention is gone. Nothing lowers a dark color to
|
|
22
|
+
`--color-<name>-dark` any more; move those values into the dark-mode block and drop the matching
|
|
23
|
+
`dark:…-dark` classes. `brandTailwindCss`, `brandThemeVariables`, `darkVariableName`,
|
|
24
|
+
`BRAND_COLOR_VARIABLE`, `BRAND_FOREGROUND_VARIABLE` and the `brand-css-dark-conflict` finding are
|
|
25
|
+
removed; `brandForegroundDefaults(brand)` is `foregroundDefaults(light, dark)` over the fills.
|
|
26
|
+
The brand footer and logo use `text-muted-foreground`.
|
|
27
|
+
|
|
28
|
+
The primitives read the theme. `Email` paints the page color (`--color-background` by default) on
|
|
29
|
+
the body and, as `bgcolor`, on the wrapper table, and pads its content 16px each side (`gutter`).
|
|
30
|
+
`Section` treats a pixel width as a maximum, so it fits a phone. `Columns` stacks its cells below
|
|
31
|
+
600px (`stack={false}` keeps a row) and spaces them with `gap` in both layouts. `Button`, `Link`
|
|
32
|
+
and `Divider` default to the primary fill, the primary color and the border color through classes
|
|
33
|
+
a utility on them overrides; their explicit props are inline styles as before. These change the
|
|
34
|
+
compiled output of every template, so the email-parity golden digests change.
|
|
35
|
+
|
|
36
|
+
`checkEmailCompatibility` adds `email-contrast`: each fixture is judged in light and dark mode,
|
|
37
|
+
and text below 3:1 or a button below 1.5:1 against its surroundings is an error located at the
|
|
38
|
+
element; normal-size text below 4.5:1 and a button below 3:1 are warnings. New diagnostic codes:
|
|
39
|
+
`email-contrast`, `invalid-columns-stack`, `invalid-columns-gap` and `invalid-number-prop`.
|
|
40
|
+
|
|
41
|
+
The email starter is redesigned on the vocabulary from copyable blocks in `templates/blocks/`.
|
|
42
|
+
|
|
43
|
+
## @samva/markup@0.13.1
|
|
44
|
+
|
|
45
|
+
### The authoring reference omits channel-only upgrade recipes
|
|
46
|
+
|
|
47
|
+
`generated/reference.md` lists upgrade recipes only for diagnostics that apply to every template,
|
|
48
|
+
matching its diagnostics table and `contract.json`. The `whatsapp-template-name` recipe stays in the
|
|
49
|
+
diagnostic codes, where an agent migrating a WhatsApp template reads it.
|
|
50
|
+
|
|
1
51
|
## @samva/markup@0.13.0
|
|
2
52
|
|
|
3
53
|
### Meta's WhatsApp template name comes from the template's handle
|
|
@@ -33,7 +33,7 @@ interface EmailBrand {
|
|
|
33
33
|
readonly footer?: EmailBrandFooter | undefined;
|
|
34
34
|
}
|
|
35
35
|
/** Every class the brand components use, compiled for any project that imports them. */
|
|
36
|
-
declare const BRAND_COMPONENT_CLASSES: readonly ["dark:hidden!", "hidden", "dark:block!", "text-xs", "text-
|
|
36
|
+
declare const BRAND_COMPONENT_CLASSES: readonly ["dark:hidden!", "hidden", "dark:block!", "text-xs", "text-muted-foreground", "text-center", "font-semibold", "underline"];
|
|
37
37
|
interface BrandLogoProps {
|
|
38
38
|
/** Rendered width in pixels; the height follows the image. */
|
|
39
39
|
readonly width?: number | undefined;
|
|
@@ -67,7 +67,7 @@ const BRAND_COMPONENT_CLASSES = [
|
|
|
67
67
|
"hidden",
|
|
68
68
|
"dark:block!",
|
|
69
69
|
"text-xs",
|
|
70
|
-
"text-
|
|
70
|
+
"text-muted-foreground",
|
|
71
71
|
"text-center",
|
|
72
72
|
"font-semibold",
|
|
73
73
|
"underline"
|
|
@@ -138,7 +138,7 @@ const brandComponents = (brand, plugin = samvaBrandPlugin) => {
|
|
|
138
138
|
const links = footer.socialLinks ?? [];
|
|
139
139
|
if (links.length > 0) rows.push(row(links.flatMap((link, index) => [...index === 0 ? [] : [" · "], jsx("a", {
|
|
140
140
|
href: link.url,
|
|
141
|
-
className: "text-
|
|
141
|
+
className: "text-muted-foreground underline",
|
|
142
142
|
children: link.label
|
|
143
143
|
})])));
|
|
144
144
|
rows.push(row(unsubscribeLink(unsubscribeLabel, plugin), {
|
|
@@ -155,7 +155,7 @@ const brandComponents = (brand, plugin = samvaBrandPlugin) => {
|
|
|
155
155
|
[BRAND_FOOTER_MARKER]: true,
|
|
156
156
|
children: jsx("tbody", { children: jsx("tr", { children: jsx("td", {
|
|
157
157
|
align: "center",
|
|
158
|
-
className: classes("text-xs text-
|
|
158
|
+
className: classes("text-xs text-muted-foreground text-center", className),
|
|
159
159
|
style: { padding: "32px 16px" },
|
|
160
160
|
children: jsx("table", {
|
|
161
161
|
role: "presentation",
|
|
@@ -179,7 +179,7 @@ const brandComponents = (brand, plugin = samvaBrandPlugin) => {
|
|
|
179
179
|
*/
|
|
180
180
|
const unsubscribeLink = (label, plugin) => jsx("a", {
|
|
181
181
|
href: plugin.unsubscribeUrlPlaceholder,
|
|
182
|
-
className: "text-
|
|
182
|
+
className: "text-muted-foreground underline",
|
|
183
183
|
[UNSUBSCRIBE_LINK]: true,
|
|
184
184
|
children: label
|
|
185
185
|
});
|
package/dist/brand.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as BrandPlugin } from "./brand-plugin-CHhcei-j.js";
|
|
2
|
-
import { _ as EmailBrandSocialLink, a as assetUrl, b as renderedFooterMarkers, c as isExternalAsset, d as BrandFooterProps, f as BrandLogoProps, g as EmailBrandFooter, h as EmailBrandAssets, i as assetEntry, l as BRAND_COMPONENT_CLASSES, m as EmailBrandAddress, n as AssetEntry, o as checkAssetBase, p as EmailBrand, r as AssetManifest, s as isAssetPath, t as ASSET_CONTENT_TYPES, u as BrandComponents, v as RenderedFooterMarkers, x as withoutUnsubscribeRow, y as brandComponents } from "./assets-
|
|
2
|
+
import { _ as EmailBrandSocialLink, a as assetUrl, b as renderedFooterMarkers, c as isExternalAsset, d as BrandFooterProps, f as BrandLogoProps, g as EmailBrandFooter, h as EmailBrandAssets, i as assetEntry, l as BRAND_COMPONENT_CLASSES, m as EmailBrandAddress, n as AssetEntry, o as checkAssetBase, p as EmailBrand, r as AssetManifest, s as isAssetPath, t as ASSET_CONTENT_TYPES, u as BrandComponents, v as RenderedFooterMarkers, x as withoutUnsubscribeRow, y as brandComponents } from "./assets-tISHaQNF.js";
|
|
3
3
|
import { t as Diagnostic } from "./diagnostic-model-DxthUZBT.js";
|
|
4
4
|
import { Result } from "better-result";
|
|
5
5
|
//#region src/email/samva-brand-plugin.d.ts
|
|
@@ -29,8 +29,6 @@ interface BrandCss {
|
|
|
29
29
|
readonly dark: Readonly<Record<string, string>>;
|
|
30
30
|
readonly fontFaces: readonly BrandFontFace[];
|
|
31
31
|
}
|
|
32
|
-
/** The theme variable a dark-mode color lowers to: `--color-brand` → `--color-brand-dark`. */
|
|
33
|
-
declare const darkVariableName: (property: string) => string;
|
|
34
32
|
/** Parse brand theme CSS against the closed grammar above. */
|
|
35
33
|
declare const parseBrandCss: (css: string) => Result<BrandCss, ReadonlyArray<Diagnostic>>;
|
|
36
34
|
/**
|
|
@@ -39,9 +37,43 @@ declare const parseBrandCss: (css: string) => Result<BrandCss, ReadonlyArray<Dia
|
|
|
39
37
|
* output always parses back to the same value.
|
|
40
38
|
*/
|
|
41
39
|
declare const printBrandCss: (brand: BrandCss) => string;
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The semantic color tokens, as Tailwind color names (`bg-card`,
|
|
42
|
+
* `text-primary-foreground`, `border-border`), each with the role a block uses
|
|
43
|
+
* it for. A block reads only these, so swapping the theme reskins it.
|
|
44
|
+
*/
|
|
45
|
+
declare const THEME_COLOR_ROLES: {
|
|
46
|
+
readonly background: "The page, behind everything.";
|
|
47
|
+
readonly foreground: "Text on the page.";
|
|
48
|
+
readonly card: "A surface that groups the message's content.";
|
|
49
|
+
readonly "card-foreground": "Text on a card.";
|
|
50
|
+
readonly primary: "The main action's fill (a button), and links.";
|
|
51
|
+
readonly "primary-foreground": "Text on a primary fill.";
|
|
52
|
+
readonly secondary: "A quieter action's fill.";
|
|
53
|
+
readonly "secondary-foreground": "Text on a secondary fill.";
|
|
54
|
+
readonly muted: "A subdued surface: a code block, a table header.";
|
|
55
|
+
readonly "muted-foreground": "Secondary text on the page, a card or a muted surface: labels, captions, the footer.";
|
|
56
|
+
readonly accent: "A highlighted surface: a callout, a selected row.";
|
|
57
|
+
readonly "accent-foreground": "Text on an accent surface.";
|
|
58
|
+
readonly border: "Rules, dividers and outlines.";
|
|
59
|
+
};
|
|
60
|
+
declare const THEME_COLORS: readonly (keyof typeof THEME_COLOR_ROLES)[];
|
|
61
|
+
type ThemeColor = (typeof THEME_COLORS)[number];
|
|
62
|
+
/**
|
|
63
|
+
* The non-color tokens: the corner radius (`rounded`; `rounded-sm` to `rounded-xl` follow it) and
|
|
64
|
+
* the body and heading families (`font-sans`, `font-heading`).
|
|
65
|
+
*/
|
|
66
|
+
declare const THEME_TOKENS: readonly ["--radius", "--font-sans", "--font-heading"];
|
|
67
|
+
/**
|
|
68
|
+
* The theme every project compiles with, beneath its own: a neutral light and
|
|
69
|
+
* dark palette, an 8px radius and the system sans-serif stack. A project's
|
|
70
|
+
* `theme.css`, its imported stylesheets and its brand layer over it.
|
|
71
|
+
*/
|
|
72
|
+
declare const DEFAULT_THEME: BrandCss;
|
|
73
|
+
/** `DEFAULT_THEME` as theme CSS. */
|
|
74
|
+
declare const DEFAULT_THEME_CSS: string;
|
|
75
|
+
/** The fills whose text color a brand may leave out: `--color-primary` and `--color-primary-foreground`, and so on. */
|
|
76
|
+
declare const FILL_COLORS: readonly ["primary", "secondary", "accent"];
|
|
45
77
|
/**
|
|
46
78
|
* Black or white, whichever has the higher WCAG contrast ratio against
|
|
47
79
|
* `color`. A translucent color is judged over white, the page an email sits on.
|
|
@@ -51,25 +83,16 @@ declare const BRAND_FOREGROUND_VARIABLE = "--color-brand-foreground";
|
|
|
51
83
|
*/
|
|
52
84
|
declare const contrastForeground: (color: string) => "#000000" | "#ffffff" | undefined;
|
|
53
85
|
/**
|
|
54
|
-
* The text
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* the foreground, or whose
|
|
86
|
+
* The text colors a theme layer gets for the fills it sets without one: for
|
|
87
|
+
* each of `FILL_COLORS`, the `contrastForeground` of the fill, in light mode
|
|
88
|
+
* and, where the layer's dark-mode block sets the fill, in dark mode. A layer
|
|
89
|
+
* that sets the foreground, or whose fill does not evaluate, gets no default.
|
|
90
|
+
* Every build lowers each theme layer with these, so stored theme CSS never
|
|
91
|
+
* carries them.
|
|
58
92
|
*/
|
|
59
|
-
declare const
|
|
60
|
-
readonly light
|
|
61
|
-
readonly dark
|
|
93
|
+
declare const foregroundDefaults: (light: Readonly<Record<string, string>>, dark: Readonly<Record<string, string>>) => {
|
|
94
|
+
readonly light: Readonly<Record<string, string>>;
|
|
95
|
+
readonly dark: Readonly<Record<string, string>>;
|
|
62
96
|
};
|
|
63
|
-
/**
|
|
64
|
-
* A brand theme as flat theme variables, the way a build compiles it. Email
|
|
65
|
-
* inlining resolves `var()` once, so a dark-mode `@theme` cannot switch a
|
|
66
|
-
* value at run time; each dark color lowers to its `-dark` theme variable,
|
|
67
|
-
* which `dark:` utilities read (`dark:bg-brand-dark`). A text-on-brand color
|
|
68
|
-
* the brand leaves out is filled in by `brandForegroundDefaults`, so every
|
|
69
|
-
* build compiles the same default and the stored CSS never carries it.
|
|
70
|
-
*/
|
|
71
|
-
declare const brandThemeVariables: (brand: BrandCss) => Readonly<Record<string, string>>;
|
|
72
|
-
/** The stylesheet Tailwind compiles for the theme's brand import: `brandThemeVariables` and the font faces. */
|
|
73
|
-
declare const brandTailwindCss: (brand: BrandCss) => string;
|
|
74
97
|
//#endregion
|
|
75
|
-
export { ASSET_CONTENT_TYPES, AssetEntry, AssetManifest,
|
|
98
|
+
export { ASSET_CONTENT_TYPES, AssetEntry, AssetManifest, BRAND_COMPONENT_CLASSES, BrandComponents, BrandCss, BrandFontFace, BrandFooterProps, BrandLogoProps, type BrandPlugin, DEFAULT_THEME, DEFAULT_THEME_CSS, EmailBrand, EmailBrandAddress, EmailBrandAssets, EmailBrandFooter, EmailBrandSocialLink, FILL_COLORS, RenderedFooterMarkers, THEME_COLORS, THEME_COLOR_ROLES, THEME_TOKENS, ThemeColor, assetEntry, assetUrl, brandComponents, checkAssetBase, contrastForeground, foregroundDefaults, isAssetPath, isExternalAsset, parseBrandCss, printBrandCss, renderedFooterMarkers, samvaBrandPlugin, withoutUnsubscribeRow };
|
package/dist/brand.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { D as samvaBrandPlugin } from "./html-eOZfDwVf.js";
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as ASSET_CONTENT_TYPES, c as checkAssetBase, i as withoutUnsubscribeRow, l as isAssetPath, n as brandComponents, o as assetEntry, r as renderedFooterMarkers, s as assetUrl, t as BRAND_COMPONENT_CLASSES, u as isExternalAsset } from "./brand-
|
|
4
|
-
export { ASSET_CONTENT_TYPES,
|
|
2
|
+
import { a as THEME_COLOR_ROLES, c as foregroundDefaults, i as THEME_COLORS, l as parseBrandCss, n as DEFAULT_THEME_CSS, o as THEME_TOKENS, r as FILL_COLORS, s as contrastForeground, t as DEFAULT_THEME, u as printBrandCss } from "./theme-css-s9QwD5Ko.js";
|
|
3
|
+
import { a as ASSET_CONTENT_TYPES, c as checkAssetBase, i as withoutUnsubscribeRow, l as isAssetPath, n as brandComponents, o as assetEntry, r as renderedFooterMarkers, s as assetUrl, t as BRAND_COMPONENT_CLASSES, u as isExternalAsset } from "./brand-B-t62NJB.js";
|
|
4
|
+
export { ASSET_CONTENT_TYPES, BRAND_COMPONENT_CLASSES, DEFAULT_THEME, DEFAULT_THEME_CSS, FILL_COLORS, THEME_COLORS, THEME_COLOR_ROLES, THEME_TOKENS, assetEntry, assetUrl, brandComponents, checkAssetBase, contrastForeground, foregroundDefaults, isAssetPath, isExternalAsset, parseBrandCss, printBrandCss, renderedFooterMarkers, samvaBrandPlugin, withoutUnsubscribeRow };
|
package/dist/compiler.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as parseBrandSpecifier, t as BrandPlugin } from "./brand-plugin-CHhcei-j.js";
|
|
2
2
|
import { a as TemplateDiagnostic, r as EmailDiagnostic } from "./diagnostics-CUYlQ_6x.js";
|
|
3
3
|
import { r as EmailNode } from "./jsx-runtime-DC7xG0aA.js";
|
|
4
|
-
import { n as AssetEntry, p as EmailBrand, u as BrandComponents } from "./assets-
|
|
5
|
-
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, r as RenderedEmail, v as Stylesheet, w as classListOf, x as Ancestry, y as compileSelector } from "./render-
|
|
4
|
+
import { n as AssetEntry, p as EmailBrand, u as BrandComponents } from "./assets-tISHaQNF.js";
|
|
5
|
+
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, r as RenderedEmail, v as Stylesheet, w as classListOf, x as Ancestry, y as compileSelector } from "./render-C1X3S5or.js";
|
|
6
6
|
import { a as TEMPLATE_NAME_PATTERN, n as EmailContent } from "./template-B-UDXK8a.js";
|
|
7
7
|
import { caniemail } from "caniemail";
|
|
8
8
|
//#region src/email/compatibility.d.ts
|
|
@@ -81,7 +81,7 @@ declare const finalizeValue: (value: string, variables: Readonly<Record<string,
|
|
|
81
81
|
/** Media Queries Level 4 range syntax down to the `min-`/`max-` prefixes clients support. */
|
|
82
82
|
declare const downlevelMediaQuery: (condition: string) => string;
|
|
83
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>>) => string;
|
|
84
|
+
declare const renderHeadCss: (rules: readonly CssRule[], headAtRules: readonly string[], variables: Readonly<Record<string, string>>, darkVariables?: Readonly<Record<string, string>>) => string;
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/email/css-color.d.ts
|
|
87
87
|
/** A color in extended sRGB, alpha included, before clamping and gamma. */
|
|
@@ -101,15 +101,24 @@ declare const downlevelColors: (value: string) => string;
|
|
|
101
101
|
//#region src/email/cascade.d.ts
|
|
102
102
|
interface AppliedStyles {
|
|
103
103
|
readonly tree: EmailNode;
|
|
104
|
-
/** Rules that could not be inlined, ready for a `<style>` element in `<head
|
|
104
|
+
/** Rules that could not be inlined, ready for a `<style>` element in `<head>` after `darkRules`. */
|
|
105
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>;
|
|
106
112
|
/** Project `@font-face` rules, for a `<head>` style classic Outlook cannot see. */
|
|
107
113
|
readonly fontFaceCss: string;
|
|
108
114
|
readonly diagnostics: readonly EmailDiagnostic[];
|
|
109
115
|
}
|
|
110
116
|
/**
|
|
111
117
|
* Resolve every stylesheet against the tree: inline what a client will honor on
|
|
112
|
-
* the element, and keep the rest for `<head>`.
|
|
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.
|
|
113
122
|
*/
|
|
114
123
|
declare const applyStylesheet: (root: EmailNode, sheet: Stylesheet, options?: {
|
|
115
124
|
readonly knownClasses?: ReadonlySet<string>;
|
|
@@ -194,7 +203,10 @@ interface TransformOptions {
|
|
|
194
203
|
}
|
|
195
204
|
interface ProjectTransform {
|
|
196
205
|
readonly assets: readonly AssetEntry[];
|
|
197
|
-
/**
|
|
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
|
+
*/
|
|
198
210
|
readonly tailwindSheet: Stylesheet | undefined;
|
|
199
211
|
/** Every project stylesheet, parsed, by path. */
|
|
200
212
|
readonly stylesheets: ReadonlyMap<string, Stylesheet>;
|
|
@@ -215,6 +227,11 @@ declare const transformProject: (files: Readonly<Record<string, string | Uint8Ar
|
|
|
215
227
|
interface RenderedBrandFooter {
|
|
216
228
|
readonly html: string;
|
|
217
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;
|
|
218
235
|
}
|
|
219
236
|
/**
|
|
220
237
|
* Render `BrandFooter` against a brand on its own, for the send path to
|