@samva/markup 0.1.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 +8 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/dist/ast-DAhnAvQN.d.ts +120 -0
- package/dist/ast.d.ts +2 -0
- package/dist/ast.js +159 -0
- package/dist/ast.js.map +1 -0
- package/dist/candidate.d.ts +29 -0
- package/dist/candidate.js +88 -0
- package/dist/candidate.js.map +1 -0
- package/dist/checks-CW0nFj5n.js +58922 -0
- package/dist/checks-CW0nFj5n.js.map +1 -0
- package/dist/checks.d.ts +26 -0
- package/dist/checks.js +2 -0
- package/dist/classes.d.ts +27 -0
- package/dist/classes.js +184 -0
- package/dist/classes.js.map +1 -0
- package/dist/compile-sms.d.ts +28 -0
- package/dist/compile-sms.js +44 -0
- package/dist/compile-sms.js.map +1 -0
- package/dist/compile-whatsapp.d.ts +56 -0
- package/dist/compile-whatsapp.js +186 -0
- package/dist/compile-whatsapp.js.map +1 -0
- package/dist/compile.d.ts +93 -0
- package/dist/compile.js +938 -0
- package/dist/compile.js.map +1 -0
- package/dist/components.d.ts +289 -0
- package/dist/components.js +106 -0
- package/dist/components.js.map +1 -0
- package/dist/conditionals.d.ts +10 -0
- package/dist/conditionals.js +42 -0
- package/dist/conditionals.js.map +1 -0
- package/dist/diagnostics-oveE-laV.d.ts +79 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +62 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emit.d.ts +50 -0
- package/dist/emit.js +151 -0
- package/dist/emit.js.map +1 -0
- package/dist/footer.d.ts +66 -0
- package/dist/footer.js +90 -0
- package/dist/footer.js.map +1 -0
- package/dist/interpolate.d.ts +27 -0
- package/dist/interpolate.js +61 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +10 -0
- package/dist/jsx-dev-runtime.js +7 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime-fSxcvlx4.d.ts +57 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +102 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/lexer.d.ts +60 -0
- package/dist/lexer.js +269 -0
- package/dist/lexer.js.map +1 -0
- package/dist/model.d.ts +39 -0
- package/dist/model.js +90 -0
- package/dist/model.js.map +1 -0
- package/dist/ops.d.ts +208 -0
- package/dist/ops.js +546 -0
- package/dist/ops.js.map +1 -0
- package/dist/parser-yzjUOGhc.d.ts +387 -0
- package/dist/parser.d.ts +2 -0
- package/dist/parser.js +821 -0
- package/dist/parser.js.map +1 -0
- package/dist/predicate-DTtVtLK7.d.ts +49 -0
- package/dist/predicate.d.ts +2 -0
- package/dist/predicate.js +417 -0
- package/dist/predicate.js.map +1 -0
- package/dist/presets/category-mapping.d.ts +13 -0
- package/dist/presets/category-mapping.js +49 -0
- package/dist/presets/category-mapping.js.map +1 -0
- package/dist/presets/public-gallery.d.ts +490 -0
- package/dist/presets/public-gallery.js +563 -0
- package/dist/presets/public-gallery.js.map +1 -0
- package/dist/presets/public-handoff.d.ts +68 -0
- package/dist/presets/public-handoff.js +105 -0
- package/dist/presets/public-handoff.js.map +1 -0
- package/dist/presets/public-preview-artifacts.d.ts +41 -0
- package/dist/presets/public-preview-artifacts.js +109 -0
- package/dist/presets/public-preview-artifacts.js.map +1 -0
- package/dist/presets/public-preview.d.ts +1168 -0
- package/dist/presets/public-preview.js +1158 -0
- package/dist/presets/public-preview.js.map +1 -0
- package/dist/presets/sources.d.ts +7 -0
- package/dist/presets/sources.js +54 -0
- package/dist/presets/sources.js.map +1 -0
- package/dist/presets.d.ts +350 -0
- package/dist/presets.js +1251 -0
- package/dist/presets.js.map +1 -0
- package/dist/printer.d.ts +6 -0
- package/dist/printer.js +122 -0
- package/dist/printer.js.map +1 -0
- package/dist/registry.d.ts +42 -0
- package/dist/registry.js +646 -0
- package/dist/registry.js.map +1 -0
- package/dist/render-template.d.ts +42 -0
- package/dist/render-template.js +74 -0
- package/dist/render-template.js.map +1 -0
- package/dist/sms-segments-y4FpPilJ.d.ts +13 -0
- package/dist/sms-segments.d.ts +2 -0
- package/dist/sms-segments.js +46 -0
- package/dist/sms-segments.js.map +1 -0
- package/dist/theme-6ApjjiBo.d.ts +116 -0
- package/dist/theme-css.d.ts +24 -0
- package/dist/theme-css.js +509 -0
- package/dist/theme-css.js.map +1 -0
- package/dist/theme.d.ts +2 -0
- package/dist/theme.js +95 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.d.ts +6 -0
- package/dist/tokens.js +417 -0
- package/dist/tokens.js.map +1 -0
- package/dist/variables-3NGLpNTB.d.ts +77 -0
- package/dist/variables.d.ts +2 -0
- package/dist/variables.js +141 -0
- package/dist/variables.js.map +1 -0
- package/dist/version-BITr58kk.js +96 -0
- package/dist/version-BITr58kk.js.map +1 -0
- package/generated/sml-agent-contract.json +917 -0
- package/generated/sml-email-agent-contract.json +790 -0
- package/generated/sml-email-language-reference.md +160 -0
- package/generated/sml-language-reference.md +220 -0
- package/package.json +203 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<!-- GENERATED by apps/api/scripts/generate-sml-reference.ts — do not edit by hand. -->
|
|
2
|
+
|
|
3
|
+
# SML email language reference
|
|
4
|
+
|
|
5
|
+
SML is JSX-strict markup: every tag is closed, every attribute is quoted (or
|
|
6
|
+
`{numeric}`), and the vocabulary is closed. One email document has one
|
|
7
|
+
`<Email>` root and compiles to email-safe table HTML.
|
|
8
|
+
|
|
9
|
+
## Email primitives
|
|
10
|
+
|
|
11
|
+
Styling is an email-safe subset of Tailwind utility classes on the `class`
|
|
12
|
+
attribute. The compiler lowers this to table-based HTML with Outlook/Gmail
|
|
13
|
+
fallbacks — you never write raw HTML.
|
|
14
|
+
|
|
15
|
+
| Tag | Attributes | Children | Notes |
|
|
16
|
+
| ------------- | ------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `<Email>` | lang, dir, width (1-10000), class | Subject?, Preview?, blocks | Email document root. Exactly one root per template; wraps the whole message. |
|
|
18
|
+
| `<Subject>` | — | text, {{vars}} | Email subject line. Text and interpolations only; must appear before body blocks. |
|
|
19
|
+
| `<Preview>` | — | text, {{vars}} | Inbox preview text (hidden in the body). Text and interpolations only. |
|
|
20
|
+
| `<Container>` | class, backgroundImage, backgroundPosition, backgroundSize | blocks | Centered 600px max-width wrapper. Compiles to a table on the outlook-safe base. |
|
|
21
|
+
| `<Section>` | class, backgroundImage, backgroundPosition, backgroundSize | blocks | Full-width band. Padding splits onto the inner cell for Outlook/Klaviyo. |
|
|
22
|
+
| `<Row>` | class | Column+ | Horizontal layout. Children must be <Column>. Use instead of flex/grid. |
|
|
23
|
+
| `<Column>` | class, width, valign | blocks | A cell inside a <Row>. `width` is an HTML width (e.g. "50%", "300"). |
|
|
24
|
+
| `<Heading>` | level (1-6), class | text, {{vars}}, strong, em, a | Renders <h1>-<h6> by `level` (default 1). |
|
|
25
|
+
| `<Text>` | class | text, {{vars}}, strong, em, a | Paragraph. Ships sane font-size/line-height/margin defaults. |
|
|
26
|
+
| `<Button>` | href (required), class | text, {{vars}}, strong, em | Link styled as a button. Set padding via classes; the compiler injects the Outlook mso hack. |
|
|
27
|
+
| `<Image>` | src (required), alt, width (0-10000), height (0-10000), class | Source? | Responsive image. Always set `alt` for accessibility. Add a <Source scheme="dark"> child to swap the asset in dark mode. |
|
|
28
|
+
| `<Source>` | scheme (required), src (required) | void | Image source variant. Inside <Image>, `scheme="dark"` swaps the asset when dark-mode media queries are honored. |
|
|
29
|
+
| `<Divider>` | class | void | Horizontal rule (border-top). |
|
|
30
|
+
| `<Spacer>` | height (required, 1-2000) | void | Vertical gap of `height` px. |
|
|
31
|
+
| `<List>` | type, class | ListItem+ | Bulleted or numbered list. `type` is "unordered" (default) or "ordered". Children must be <ListItem>. |
|
|
32
|
+
| `<ListItem>` | class | text, {{vars}}, strong, em, a | A single list row. Inline content only (text, {{vars}}, strong/em/a). |
|
|
33
|
+
| `<If>` | test (required) | blocks, Else? | Send-time conditional block. `test` is a predicate over declared variables (see "Send-time conditionals" below). Content: blocks, then an optional trailing <Else>. |
|
|
34
|
+
| `<Else>` | — | blocks | The false branch of an <If>. Valid only as the last direct child of <If>. |
|
|
35
|
+
| `<a>` | href (required), class | text, {{vars}}, strong, em | Inline link. It has deterministic theme-brand color and underline defaults; use safe classes to override either. |
|
|
36
|
+
| `<strong>` | — | text, {{vars}}, strong, em | Bold inline text. |
|
|
37
|
+
| `<em>` | — | text, {{vars}}, strong, em | Italic inline text. |
|
|
38
|
+
|
|
39
|
+
- Interpolate variables with `{{name}}` (or `${name}`) inside text content.
|
|
40
|
+
- Only `sm:` (min-width 640px, progressive enhancement) and `dark:` (color
|
|
41
|
+
families only) class variants are supported. `hover:`/`focus:`/`md:`/`lg:`/etc.
|
|
42
|
+
are rejected.
|
|
43
|
+
|
|
44
|
+
## Send-time conditionals
|
|
45
|
+
|
|
46
|
+
`<If test="...">...<Else>...</Else></If>` renders one branch per recipient at
|
|
47
|
+
send time. Both branches compile into the email artifact behind hidden markers;
|
|
48
|
+
the send-time interpolation step selects one branch and strips the markers before
|
|
49
|
+
`{{}}` substitution.
|
|
50
|
+
|
|
51
|
+
- `<Else>` is optional and, when present, must be the last direct child of
|
|
52
|
+
`<If>`. There is no `<ElseIf>` — nest another `<If>` inside `<Else>` instead.
|
|
53
|
+
Both elements accept the same email blocks as any other conditional section.
|
|
54
|
+
- `test` is a closed predicate grammar over flat variable names and literals:
|
|
55
|
+
- Comparison operators: `==`, `!=`, `>`, `>=`, `<`, `<=`.
|
|
56
|
+
- Boolean keywords: `and`, `or`, `not`, plus
|
|
57
|
+
`( )` grouping.
|
|
58
|
+
- Literals: `'single-quoted strings'` or bare numbers. No arithmetic, function
|
|
59
|
+
calls, method calls, or dotted paths.
|
|
60
|
+
- A bare variable name means "present and non-empty"; a missing variable makes
|
|
61
|
+
every comparison false, including `!=`.
|
|
62
|
+
|
|
63
|
+
## Utility classes
|
|
64
|
+
|
|
65
|
+
Email styling uses this Tailwind subset. Arbitrary values (`w-[600px]`,
|
|
66
|
+
`text-[#374151]`, `bg-[#0088cc]`) are allowed where noted.
|
|
67
|
+
|
|
68
|
+
| Class | What it sets |
|
|
69
|
+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `p-*` | Padding on all sides (p-4 = 16px). Compiles onto table cells for Outlook. |
|
|
71
|
+
| `px-*` | Horizontal padding. |
|
|
72
|
+
| `py-*` | Vertical padding. |
|
|
73
|
+
| `pt-*` | Top padding. |
|
|
74
|
+
| `pr-*` | Right padding. |
|
|
75
|
+
| `pb-*` | Bottom padding. |
|
|
76
|
+
| `pl-*` | Left padding. |
|
|
77
|
+
| `m-*` | Margin on all sides. Warn tier — some clients strip margins. (warn: some clients strip it) |
|
|
78
|
+
| `mx-*` | Horizontal margin; mx-auto centers block elements. (warn: some clients strip it) |
|
|
79
|
+
| `my-*` | Vertical margin. (warn: some clients strip it) |
|
|
80
|
+
| `mt-*` | Top margin. (warn: some clients strip it) |
|
|
81
|
+
| `mr-*` | Right margin. (warn: some clients strip it) |
|
|
82
|
+
| `mb-*` | Bottom margin. (warn: some clients strip it) |
|
|
83
|
+
| `ml-*` | Left margin. (warn: some clients strip it) |
|
|
84
|
+
| `w-*` | Width from the spacing scale (w-32 = 128px), w-full, or w-[600px]/w-[50%]. |
|
|
85
|
+
| `max-w-*` | Max width from the container scale (max-w-lg = 512px) or max-w-[600px]. |
|
|
86
|
+
| `h-*` | Height from the spacing scale (h-12 = 48px) or h-[80px]. |
|
|
87
|
+
| `text-*` | Font size with paired line-height (text-sm = 14px/20px) or bounded px value (text-[15px] = 15px/22.5px). Put an explicit leading-* after it to override line-height. Text alignment: text-left, text-center, text-right, text-justify. Text color from the palette (text-gray-700) or text-[#374151]. |
|
|
88
|
+
| `leading-*` | Line height: named ratios (leading-relaxed) or spacing steps (leading-6 = 24px). |
|
|
89
|
+
| `font-*` | Font weight: font-normal, font-medium, font-semibold, font-bold, ... Font stack: font-sans, font-serif, font-mono. |
|
|
90
|
+
| `tracking-*` | Letter spacing: tracking-tighter … tracking-widest (em-based; inlines fine in Outlook). Pair tracking-wide/wider with uppercase for eyebrows. |
|
|
91
|
+
| `uppercase` | Uppercase text transform. |
|
|
92
|
+
| `underline` | Underlined text. |
|
|
93
|
+
| `no-underline` | Removes the underline (links render underlined by default in most clients). |
|
|
94
|
+
| `bg-*` | Background color from the palette (bg-white, bg-blue-600) or bg-[#0088cc]. |
|
|
95
|
+
| `bg-gradient-*` | Linear gradient background for hero sections: bg-gradient-to-b/t/l/r with from-{color} and to-{color}. Modern base compiles a CSS linear-gradient (plus a solid from-color fallback); the outlook-safe base degrades to the solid from-color — Outlook for Windows never renders the gradient. |
|
|
96
|
+
| `from-*` | Gradient start color (from-indigo-600). Doubles as the solid fallback color on clients without gradient support (Outlook for Windows). |
|
|
97
|
+
| `to-*` | Gradient end color (to-purple-600). |
|
|
98
|
+
| `border-*` | Solid border width: border (1px), border-2, border-0. Border color from the palette (border-gray-200). |
|
|
99
|
+
| `rounded-*` | Border radius (rounded-md = 6px). Ignored by Outlook for Windows — buttons degrade to square corners. |
|
|
100
|
+
| `rounded-t-*` | Top border radius for card/header blocks (rounded-t-lg). Degrades to square corners in Outlook for Windows. |
|
|
101
|
+
| `rounded-r-*` | Right-side border radius (rounded-r-lg). Degrades to square corners in Outlook for Windows. |
|
|
102
|
+
| `rounded-b-*` | Bottom border radius for card/footer blocks (rounded-b-lg). Degrades to square corners in Outlook for Windows. |
|
|
103
|
+
| `rounded-l-*` | Left-side border radius (rounded-l-lg). Degrades to square corners in Outlook for Windows. |
|
|
104
|
+
| `block` | display: block. |
|
|
105
|
+
| `inline-block` | display: inline-block. |
|
|
106
|
+
| `hidden` | display: none. Pair with sm:block for mobile-only content. |
|
|
107
|
+
|
|
108
|
+
Palette color families (each with the usual `50`-`950` steps, plus `white`,
|
|
109
|
+
`black`, `transparent`): `amber`, `black`, `blue`, `brand`, `brand-foreground`, `cyan`, `emerald`, `fuchsia`, `gray`, `green`, `indigo`, `lime`, `mauve`, `mist`, `neutral`, `olive`, `orange`, `pink`, `purple`, `red`, `rose`, `sky`, `slate`, `stone`, `taupe`, `teal`, `violet`, `white`, `yellow`, `zinc`.
|
|
110
|
+
|
|
111
|
+
## Rejected utilities
|
|
112
|
+
|
|
113
|
+
These compile to hard errors — the message names the failing client and the
|
|
114
|
+
supported alternative. Drop the feature rather than break a client.
|
|
115
|
+
|
|
116
|
+
| Class / prefix | Why it is rejected |
|
|
117
|
+
| -------------- | -------------------------------------------------------------------------------------------- |
|
|
118
|
+
| `flex` | display:flex is unsupported in Outlook for Windows (Word engine) — use <Row>/<Column> |
|
|
119
|
+
| `inline-flex` | display:inline-flex is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
120
|
+
| `grid` | display:grid is unsupported in Outlook for Windows and Gmail — use <Row>/<Column> |
|
|
121
|
+
| `inline-grid` | display:inline-grid is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
122
|
+
| `gap-` | gap requires flex/grid, unsupported in Outlook for Windows — use padding on <Column> |
|
|
123
|
+
| `space-` | space-* margins require selectors Gmail strips — use padding or <Spacer> |
|
|
124
|
+
| `items-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
125
|
+
| `justify-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> and text-center |
|
|
126
|
+
| `self-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
127
|
+
| `content-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
128
|
+
| `order-` | flex order is unsupported in Outlook for Windows — reorder the source instead |
|
|
129
|
+
| `absolute` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
130
|
+
| `relative` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
131
|
+
| `fixed` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
132
|
+
| `sticky` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
133
|
+
| `static` | CSS position is ignored by Gmail and Outlook — remove it |
|
|
134
|
+
| `inset-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
135
|
+
| `top-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
136
|
+
| `right-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
137
|
+
| `bottom-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
138
|
+
| `left-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
139
|
+
| `z-` | z-index is ignored by Gmail and Outlook — remove it |
|
|
140
|
+
| `float-` | float is unreliable across email clients — use <Row>/<Column> |
|
|
141
|
+
| `shadow` | box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead |
|
|
142
|
+
| `shadow-` | box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead |
|
|
143
|
+
| `opacity-` | opacity is unsupported in Outlook for Windows — bake the tint into the color |
|
|
144
|
+
| `transform` | CSS transforms are unsupported in email clients — remove them |
|
|
145
|
+
| `rotate-` | CSS transforms are unsupported in email clients — remove them |
|
|
146
|
+
| `scale-` | CSS transforms are unsupported in email clients — remove them |
|
|
147
|
+
| `translate-` | CSS transforms are unsupported in email clients — remove them |
|
|
148
|
+
| `skew-` | CSS transforms are unsupported in email clients — remove them |
|
|
149
|
+
| `transition` | transitions don't run in email — remove them |
|
|
150
|
+
| `transition-` | transitions don't run in email — remove them |
|
|
151
|
+
| `duration-` | transitions don't run in email — remove them |
|
|
152
|
+
| `animate-` | animations don't run in email — remove them |
|
|
153
|
+
| `blur-` | CSS filters are unsupported in most email clients — remove them |
|
|
154
|
+
| `brightness-` | CSS filters are unsupported in most email clients — remove them |
|
|
155
|
+
| `grayscale` | CSS filters are unsupported in most email clients — remove them |
|
|
156
|
+
| `grayscale-` | CSS filters are unsupported in most email clients — remove them |
|
|
157
|
+
| `truncate` | text truncation is unsupported in Outlook for Windows — shorten the copy |
|
|
158
|
+
| `line-clamp-` | line clamping is unsupported in email clients — shorten the copy |
|
|
159
|
+
| `aspect-` | aspect-ratio is unsupported in Outlook and Gmail — set width/height on <Image> |
|
|
160
|
+
| `overflow-` | overflow is unreliable across email clients — restructure the layout |
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
<!-- GENERATED by apps/api/scripts/generate-sml-reference.ts — do not edit by hand. -->
|
|
2
|
+
|
|
3
|
+
# SML language reference
|
|
4
|
+
|
|
5
|
+
SML is JSX-strict markup: every tag is closed, every attribute is quoted (or
|
|
6
|
+
`{numeric}`), and the vocabulary is closed. One document targets exactly one
|
|
7
|
+
channel, declared by the root tag: `<Email>` compiles to email-safe table
|
|
8
|
+
HTML, `<Sms>` to a plain-text message body, `<WhatsApp>` to a Meta template
|
|
9
|
+
payload. Cross-channel compilation does not exist — one `.samva` file is one
|
|
10
|
+
channel's template.
|
|
11
|
+
|
|
12
|
+
## Email primitives
|
|
13
|
+
|
|
14
|
+
Styling is an email-safe subset of Tailwind utility classes on the `class`
|
|
15
|
+
attribute (email only). The compiler lowers this to table-based HTML with
|
|
16
|
+
Outlook/Gmail fallbacks — you never write raw HTML.
|
|
17
|
+
|
|
18
|
+
| Tag | Attributes | Children | Notes |
|
|
19
|
+
| ------------- | ------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `<Email>` | lang, dir, width (1-10000), class | Subject?, Preview?, blocks | Email document root. Exactly one root per template; wraps the whole message. |
|
|
21
|
+
| `<Subject>` | — | text, {{vars}} | Email subject line. Text and interpolations only; must appear before body blocks. |
|
|
22
|
+
| `<Preview>` | — | text, {{vars}} | Inbox preview text (hidden in the body). Text and interpolations only. |
|
|
23
|
+
| `<Container>` | class, backgroundImage, backgroundPosition, backgroundSize | blocks | Centered 600px max-width wrapper. Compiles to a table on the outlook-safe base. |
|
|
24
|
+
| `<Section>` | class, backgroundImage, backgroundPosition, backgroundSize | blocks | Full-width band. Padding splits onto the inner cell for Outlook/Klaviyo. |
|
|
25
|
+
| `<Row>` | class | Column+ | Horizontal layout. Children must be <Column>. Use instead of flex/grid. |
|
|
26
|
+
| `<Column>` | class, width, valign | blocks | A cell inside a <Row>. `width` is an HTML width (e.g. "50%", "300"). |
|
|
27
|
+
| `<Heading>` | level (1-6), class | text, {{vars}}, strong, em, a | Renders <h1>-<h6> by `level` (default 1). |
|
|
28
|
+
| `<Text>` | class | text, {{vars}}, strong, em, a | Paragraph. Ships sane font-size/line-height/margin defaults. |
|
|
29
|
+
| `<Button>` | href (required), class | text, {{vars}}, strong, em | Link styled as a button. Set padding via classes; the compiler injects the Outlook mso hack. |
|
|
30
|
+
| `<Image>` | src (required), alt, width (0-10000), height (0-10000), class | Source? | Responsive image. Always set `alt` for accessibility. Add a <Source scheme="dark"> child to swap the asset in dark mode. |
|
|
31
|
+
| `<Source>` | scheme (required), src (required) | void | Image source variant. Inside <Image>, `scheme="dark"` swaps the asset when dark-mode media queries are honored. |
|
|
32
|
+
| `<Divider>` | class | void | Horizontal rule (border-top). |
|
|
33
|
+
| `<Spacer>` | height (required, 1-2000) | void | Vertical gap of `height` px. |
|
|
34
|
+
| `<List>` | type, class | ListItem+ | Bulleted or numbered list. `type` is "unordered" (default) or "ordered". Children must be <ListItem>. |
|
|
35
|
+
| `<ListItem>` | class | text, {{vars}}, strong, em, a | A single list row. Inline content only (text, {{vars}}, strong/em/a). |
|
|
36
|
+
| `<If>` | test (required) | blocks, Else? | Send-time conditional block. `test` is a predicate over declared variables (see "Send-time conditionals" below). Content: blocks, then an optional trailing <Else>. |
|
|
37
|
+
| `<Else>` | — | blocks | The false branch of an <If>. Valid only as the last direct child of <If>. |
|
|
38
|
+
| `<a>` | href (required), class | text, {{vars}}, strong, em | Inline link. It has deterministic theme-brand color and underline defaults; use safe classes to override either. |
|
|
39
|
+
| `<strong>` | — | text, {{vars}}, strong, em | Bold inline text. |
|
|
40
|
+
| `<em>` | — | text, {{vars}}, strong, em | Italic inline text. |
|
|
41
|
+
|
|
42
|
+
- Interpolate variables with `{{name}}` (or `${name}`) inside text content.
|
|
43
|
+
- Only `sm:` (min-width 640px, progressive enhancement) and `dark:` (color
|
|
44
|
+
families only) class variants are supported. `hover:`/`focus:`/`md:`/`lg:`/etc.
|
|
45
|
+
are rejected.
|
|
46
|
+
|
|
47
|
+
## SMS documents
|
|
48
|
+
|
|
49
|
+
| Tag | Attributes | Children | Notes |
|
|
50
|
+
| -------- | --------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `<Sms>` | category | verbatim text, {{vars}}, If | SMS document root. The body is VERBATIM text — newlines and space runs are content. No layout tags, no classes. |
|
|
52
|
+
| `<If>` | test (required) | verbatim text, {{vars}}, If, Else? | Send-time conditional inline in the body. Content is verbatim text/{{vars}}, then an optional trailing <Else>. |
|
|
53
|
+
| `<Else>` | — | verbatim text, {{vars}}, If | The false branch of an <If>; must be its last child. Nothing may follow it, whitespace included. |
|
|
54
|
+
|
|
55
|
+
- The body is VERBATIM: newlines and runs of spaces are content and are
|
|
56
|
+
preserved exactly. There is no whitespace collapsing and no `class`
|
|
57
|
+
attribute anywhere — SMS has no styling.
|
|
58
|
+
- `category` is optional authoring intent: `transactional`, `promotional`,
|
|
59
|
+
or `service_implicit`.
|
|
60
|
+
- The compiler reports GSM-7/UCS-2 encoding and segment estimates (variables
|
|
61
|
+
count at a 16-character worst case) and warns on multi-segment bodies and
|
|
62
|
+
missing opt-out language (e.g. "Reply STOP to unsubscribe").
|
|
63
|
+
- Example: `<Sms category="transactional">{{workspace}}: {{code}} is your
|
|
64
|
+
code. Reply STOP to opt out.</Sms>`
|
|
65
|
+
|
|
66
|
+
## WhatsApp documents
|
|
67
|
+
|
|
68
|
+
| Tag | Attributes | Children | Notes |
|
|
69
|
+
| ------------ | ----------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `<WhatsApp>` | name, language, category (required) | Header?, Body, Footer?, Buttons? (in order) | WhatsApp template root. Children are Meta's template anatomy in order: Header?, Body, Footer?, Buttons?. `name`/`language` default from the template slug/locale at the API layer. |
|
|
71
|
+
| `<Header>` | type | verbatim text, {{vars}}, If | Optional template header. `type` is "text" (default, ≤60 chars) or "image"/"video"/"document" (content is the media URL/handle). |
|
|
72
|
+
| `<Body>` | — | verbatim text, {{vars}}, If | Required template body (≤1024 chars). Verbatim text, {{vars}}, and <If> conditionals. |
|
|
73
|
+
| `<Footer>` | — | verbatim text, {{vars}}, If | Optional template footer (≤60 chars). |
|
|
74
|
+
| `<Buttons>` | — | Button+ | Interactive buttons container. Meta limits: ≤10 total, ≤2 url, ≤1 phone. |
|
|
75
|
+
| `<Button>` | type (required), url, phone | verbatim text, {{vars}}, If | `type` is "quick-reply" (label only), "url" (requires `url`, ≤2), "phone" (requires `phone`, ≤1), or "copy-code" (content is the code to copy). Label text ≤25 chars. |
|
|
76
|
+
| `<If>` | test (required) | verbatim text, {{vars}}, If, Else? | Send-time conditional inline in a text slot. Content is verbatim text/{{vars}}, then an optional trailing <Else>. |
|
|
77
|
+
| `<Else>` | — | verbatim text, {{vars}}, If | The false branch of an <If>; must be its last child. Nothing may follow it, whitespace included. |
|
|
78
|
+
|
|
79
|
+
- Components follow Meta's template anatomy in order — `Header?`, `Body`
|
|
80
|
+
(required), `Footer?`, `Buttons?` — each at most once. Text slots are
|
|
81
|
+
verbatim like SMS; no `class` attributes.
|
|
82
|
+
- `category` is required: `marketing`, `utility`, `authentication`, or
|
|
83
|
+
`service`. `name`/`language` are optional (defaulted from the template
|
|
84
|
+
slug and variant locale).
|
|
85
|
+
- Meta limits compile as diagnostics: header/footer ≤60 chars, body ≤1024,
|
|
86
|
+
button labels ≤25 (warnings); button counts and missing `url`/`phone`
|
|
87
|
+
attributes are errors. Don't mix positional `{{1}}` and named `{{var}}`
|
|
88
|
+
placeholders.
|
|
89
|
+
|
|
90
|
+
## Send-time conditionals
|
|
91
|
+
|
|
92
|
+
`<If test="...">...<Else>...</Else></If>` renders one branch per recipient at
|
|
93
|
+
send time, selected by the per-recipient variables. It works on every channel:
|
|
94
|
+
both branches compile into the artifact (email HTML/text, sms body, whatsapp
|
|
95
|
+
component text) behind hidden markers; the send-time interpolation step picks
|
|
96
|
+
a branch and strips the markers before `{{}}` substitution — sent messages
|
|
97
|
+
never contain markers or the untaken branch.
|
|
98
|
+
|
|
99
|
+
- `<Else>` is optional and, when present, must be the last direct child of
|
|
100
|
+
`<If>`. There is no `<ElseIf>` — nest another `<If>` inside `<Else>` instead.
|
|
101
|
+
In email, both `<If>` and `<Else>` accept the same children as any other
|
|
102
|
+
block (Container, Section, Row, Heading, Text, Button, Image, Divider,
|
|
103
|
+
Spacer, and nested If). In sms/whatsapp text slots they carry verbatim text,
|
|
104
|
+
`{{vars}}`, and nested `<If>` inline.
|
|
105
|
+
- `test` is a closed predicate grammar — comparisons and boolean combinators
|
|
106
|
+
over flat variable names and literals, nothing else:
|
|
107
|
+
- Comparison operators: `==`, `!=`, `>`, `>=`, `<`, `<=`.
|
|
108
|
+
- Boolean keywords: `and`, `or`, `not`, plus
|
|
109
|
+
`( )` grouping.
|
|
110
|
+
- Literals: `'single-quoted strings'` or bare numbers. No arithmetic, no
|
|
111
|
+
function calls, no method calls, no dotted paths — variable names are flat
|
|
112
|
+
(`plan`, not `user.plan`).
|
|
113
|
+
- A bare variable name (`seats`) means "present and non-empty"; a missing
|
|
114
|
+
variable makes every comparison false, including `!=`.
|
|
115
|
+
- Examples: `test="plan == 'pro'"`, `test="seats > 5 and plan != 'free'"`,
|
|
116
|
+
`test="not (region == 'eu' or region == 'uk')"`.
|
|
117
|
+
- Full grammar and evaluation semantics live in `packages/markup/src/predicate.ts`
|
|
118
|
+
(parse / evaluate / print / collectPredicateVariables) — the same module the
|
|
119
|
+
compiler, checks, send-time evaluator, and canvas all share, so predicate
|
|
120
|
+
semantics cannot fork between them.
|
|
121
|
+
|
|
122
|
+
## Utility classes (email only)
|
|
123
|
+
|
|
124
|
+
Email styling uses this Tailwind subset. Arbitrary values (`w-[600px]`, `text-[#374151]`,
|
|
125
|
+
`bg-[#0088cc]`) are allowed where noted in each family's description. Sms and
|
|
126
|
+
whatsapp documents have no `class` attribute anywhere.
|
|
127
|
+
|
|
128
|
+
| Class | What it sets |
|
|
129
|
+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
130
|
+
| `p-*` | Padding on all sides (p-4 = 16px). Compiles onto table cells for Outlook. |
|
|
131
|
+
| `px-*` | Horizontal padding. |
|
|
132
|
+
| `py-*` | Vertical padding. |
|
|
133
|
+
| `pt-*` | Top padding. |
|
|
134
|
+
| `pr-*` | Right padding. |
|
|
135
|
+
| `pb-*` | Bottom padding. |
|
|
136
|
+
| `pl-*` | Left padding. |
|
|
137
|
+
| `m-*` | Margin on all sides. Warn tier — some clients strip margins. (warn: some clients strip it) |
|
|
138
|
+
| `mx-*` | Horizontal margin; mx-auto centers block elements. (warn: some clients strip it) |
|
|
139
|
+
| `my-*` | Vertical margin. (warn: some clients strip it) |
|
|
140
|
+
| `mt-*` | Top margin. (warn: some clients strip it) |
|
|
141
|
+
| `mr-*` | Right margin. (warn: some clients strip it) |
|
|
142
|
+
| `mb-*` | Bottom margin. (warn: some clients strip it) |
|
|
143
|
+
| `ml-*` | Left margin. (warn: some clients strip it) |
|
|
144
|
+
| `w-*` | Width from the spacing scale (w-32 = 128px), w-full, or w-[600px]/w-[50%]. |
|
|
145
|
+
| `max-w-*` | Max width from the container scale (max-w-lg = 512px) or max-w-[600px]. |
|
|
146
|
+
| `h-*` | Height from the spacing scale (h-12 = 48px) or h-[80px]. |
|
|
147
|
+
| `text-*` | Font size with paired line-height (text-sm = 14px/20px) or bounded px value (text-[15px] = 15px/22.5px). Put an explicit leading-* after it to override line-height. Text alignment: text-left, text-center, text-right, text-justify. Text color from the palette (text-gray-700) or text-[#374151]. |
|
|
148
|
+
| `leading-*` | Line height: named ratios (leading-relaxed) or spacing steps (leading-6 = 24px). |
|
|
149
|
+
| `font-*` | Font weight: font-normal, font-medium, font-semibold, font-bold, ... Font stack: font-sans, font-serif, font-mono. |
|
|
150
|
+
| `tracking-*` | Letter spacing: tracking-tighter … tracking-widest (em-based; inlines fine in Outlook). Pair tracking-wide/wider with uppercase for eyebrows. |
|
|
151
|
+
| `uppercase` | Uppercase text transform. |
|
|
152
|
+
| `underline` | Underlined text. |
|
|
153
|
+
| `no-underline` | Removes the underline (links render underlined by default in most clients). |
|
|
154
|
+
| `bg-*` | Background color from the palette (bg-white, bg-blue-600) or bg-[#0088cc]. |
|
|
155
|
+
| `bg-gradient-*` | Linear gradient background for hero sections: bg-gradient-to-b/t/l/r with from-{color} and to-{color}. Modern base compiles a CSS linear-gradient (plus a solid from-color fallback); the outlook-safe base degrades to the solid from-color — Outlook for Windows never renders the gradient. |
|
|
156
|
+
| `from-*` | Gradient start color (from-indigo-600). Doubles as the solid fallback color on clients without gradient support (Outlook for Windows). |
|
|
157
|
+
| `to-*` | Gradient end color (to-purple-600). |
|
|
158
|
+
| `border-*` | Solid border width: border (1px), border-2, border-0. Border color from the palette (border-gray-200). |
|
|
159
|
+
| `rounded-*` | Border radius (rounded-md = 6px). Ignored by Outlook for Windows — buttons degrade to square corners. |
|
|
160
|
+
| `rounded-t-*` | Top border radius for card/header blocks (rounded-t-lg). Degrades to square corners in Outlook for Windows. |
|
|
161
|
+
| `rounded-r-*` | Right-side border radius (rounded-r-lg). Degrades to square corners in Outlook for Windows. |
|
|
162
|
+
| `rounded-b-*` | Bottom border radius for card/footer blocks (rounded-b-lg). Degrades to square corners in Outlook for Windows. |
|
|
163
|
+
| `rounded-l-*` | Left-side border radius (rounded-l-lg). Degrades to square corners in Outlook for Windows. |
|
|
164
|
+
| `block` | display: block. |
|
|
165
|
+
| `inline-block` | display: inline-block. |
|
|
166
|
+
| `hidden` | display: none. Pair with sm:block for mobile-only content. |
|
|
167
|
+
|
|
168
|
+
Palette color families (each with the usual `50`-`950` steps, plus `white`,
|
|
169
|
+
`black`, `transparent`): `amber`, `black`, `blue`, `brand`, `brand-foreground`, `cyan`, `emerald`, `fuchsia`, `gray`, `green`, `indigo`, `lime`, `mauve`, `mist`, `neutral`, `olive`, `orange`, `pink`, `purple`, `red`, `rose`, `sky`, `slate`, `stone`, `taupe`, `teal`, `violet`, `white`, `yellow`, `zinc`.
|
|
170
|
+
|
|
171
|
+
## Rejected utilities
|
|
172
|
+
|
|
173
|
+
These compile to hard errors — the message names the failing client and the
|
|
174
|
+
supported alternative. Drop the feature rather than break a client.
|
|
175
|
+
|
|
176
|
+
| Class / prefix | Why it is rejected |
|
|
177
|
+
| -------------- | -------------------------------------------------------------------------------------------- |
|
|
178
|
+
| `flex` | display:flex is unsupported in Outlook for Windows (Word engine) — use <Row>/<Column> |
|
|
179
|
+
| `inline-flex` | display:inline-flex is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
180
|
+
| `grid` | display:grid is unsupported in Outlook for Windows and Gmail — use <Row>/<Column> |
|
|
181
|
+
| `inline-grid` | display:inline-grid is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
182
|
+
| `gap-` | gap requires flex/grid, unsupported in Outlook for Windows — use padding on <Column> |
|
|
183
|
+
| `space-` | space-* margins require selectors Gmail strips — use padding or <Spacer> |
|
|
184
|
+
| `items-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
185
|
+
| `justify-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> and text-center |
|
|
186
|
+
| `self-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
187
|
+
| `content-` | flexbox alignment is unsupported in Outlook for Windows — use <Row>/<Column> |
|
|
188
|
+
| `order-` | flex order is unsupported in Outlook for Windows — reorder the source instead |
|
|
189
|
+
| `absolute` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
190
|
+
| `relative` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
191
|
+
| `fixed` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
192
|
+
| `sticky` | CSS position is ignored by Gmail and Outlook — use nested <Section>s |
|
|
193
|
+
| `static` | CSS position is ignored by Gmail and Outlook — remove it |
|
|
194
|
+
| `inset-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
195
|
+
| `top-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
196
|
+
| `right-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
197
|
+
| `bottom-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
198
|
+
| `left-` | position offsets are ignored by Gmail and Outlook — use padding |
|
|
199
|
+
| `z-` | z-index is ignored by Gmail and Outlook — remove it |
|
|
200
|
+
| `float-` | float is unreliable across email clients — use <Row>/<Column> |
|
|
201
|
+
| `shadow` | box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead |
|
|
202
|
+
| `shadow-` | box-shadow is unsupported in Outlook for Windows and Gmail — use a border instead |
|
|
203
|
+
| `opacity-` | opacity is unsupported in Outlook for Windows — bake the tint into the color |
|
|
204
|
+
| `transform` | CSS transforms are unsupported in email clients — remove them |
|
|
205
|
+
| `rotate-` | CSS transforms are unsupported in email clients — remove them |
|
|
206
|
+
| `scale-` | CSS transforms are unsupported in email clients — remove them |
|
|
207
|
+
| `translate-` | CSS transforms are unsupported in email clients — remove them |
|
|
208
|
+
| `skew-` | CSS transforms are unsupported in email clients — remove them |
|
|
209
|
+
| `transition` | transitions don't run in email — remove them |
|
|
210
|
+
| `transition-` | transitions don't run in email — remove them |
|
|
211
|
+
| `duration-` | transitions don't run in email — remove them |
|
|
212
|
+
| `animate-` | animations don't run in email — remove them |
|
|
213
|
+
| `blur-` | CSS filters are unsupported in most email clients — remove them |
|
|
214
|
+
| `brightness-` | CSS filters are unsupported in most email clients — remove them |
|
|
215
|
+
| `grayscale` | CSS filters are unsupported in most email clients — remove them |
|
|
216
|
+
| `grayscale-` | CSS filters are unsupported in most email clients — remove them |
|
|
217
|
+
| `truncate` | text truncation is unsupported in Outlook for Windows — shorten the copy |
|
|
218
|
+
| `line-clamp-` | line clamping is unsupported in email clients — shorten the copy |
|
|
219
|
+
| `aspect-` | aspect-ratio is unsupported in Outlook and Gmail — set width/height on <Image> |
|
|
220
|
+
| `overflow-` | overflow is unreliable across email clients — restructure the layout |
|