@samva/markup 0.1.1 → 0.2.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.
Files changed (97) hide show
  1. package/AGENTS.md +25 -5
  2. package/README.md +92 -26
  3. package/dist/{ast-DAhnAvQN.d.ts → ast-63I-VLQx.d.ts} +15 -2
  4. package/dist/ast.d.ts +2 -2
  5. package/dist/ast.js +15 -2
  6. package/dist/{checks-CW0nFj5n.js → checks-DXuERO4B.js} +37 -3
  7. package/dist/checks.d.ts +8 -1
  8. package/dist/checks.js +2 -2
  9. package/dist/compile-sms.d.ts +2 -2
  10. package/dist/compile-whatsapp.d.ts +2 -2
  11. package/dist/compile.d.ts +9 -84
  12. package/dist/compile.js +11 -920
  13. package/dist/compiler.d.ts +301 -0
  14. package/dist/compiler.js +1389 -0
  15. package/dist/components.d.ts +4 -4
  16. package/dist/conditionals.js +1 -1
  17. package/dist/corpus-Dz5irJ9x.d.ts +161 -0
  18. package/dist/diagnostics-Djd9ckLg.d.ts +90 -0
  19. package/dist/diagnostics.js +6 -3
  20. package/dist/elements-DtwKlFVH.d.ts +820 -0
  21. package/dist/email/components.d.ts +119 -0
  22. package/dist/email/components.js +207 -0
  23. package/dist/email/diagnostics.d.ts +2 -0
  24. package/dist/email/diagnostics.js +56 -0
  25. package/dist/email/elements.d.ts +2 -0
  26. package/dist/email/elements.js +299 -0
  27. package/dist/email/html.d.ts +42 -0
  28. package/dist/email/html.js +266 -0
  29. package/dist/email/jsx-dev-runtime.d.ts +26 -0
  30. package/dist/email/jsx-dev-runtime.js +12 -0
  31. package/dist/email/jsx-runtime.d.ts +2 -0
  32. package/dist/email/jsx-runtime.js +60 -0
  33. package/dist/email/render.d.ts +36 -0
  34. package/dist/email/render.js +6 -0
  35. package/dist/email/selection.d.ts +102 -0
  36. package/dist/email/selection.js +143 -0
  37. package/dist/email/source-edit.d.ts +67 -0
  38. package/dist/email/source-edit.js +185 -0
  39. package/dist/email/stylesheets.d.ts +2 -0
  40. package/dist/email/stylesheets.js +43 -0
  41. package/dist/email/text.d.ts +7 -0
  42. package/dist/email/text.js +92 -0
  43. package/dist/emit.d.ts +13 -12
  44. package/dist/emit.js +63 -63
  45. package/dist/input-schema-BIfzI63B.d.ts +23 -0
  46. package/dist/input-schema.d.ts +2 -0
  47. package/dist/input-schema.js +170 -0
  48. package/dist/jsx-dev-runtime.d.ts +4 -3
  49. package/dist/jsx-dev-runtime.js +9 -1
  50. package/dist/{jsx-runtime-fSxcvlx4.d.ts → jsx-runtime-C5k_Zq0A.d.ts} +4 -4
  51. package/dist/jsx-runtime.d.ts +1 -1
  52. package/dist/jsx-runtime.js +20 -1
  53. package/dist/model.d.ts +1 -1
  54. package/dist/ops.d.ts +1 -1
  55. package/dist/ops.js +2 -2
  56. package/dist/{parser-yzjUOGhc.d.ts → parser-CGBS73Gz.d.ts} +12 -3
  57. package/dist/parser.d.ts +2 -2
  58. package/dist/parser.js +48 -9
  59. package/dist/predicate-CvkzT-a2.js +539 -0
  60. package/dist/{predicate-DTtVtLK7.d.ts → predicate-G2SeSvoN.d.ts} +9 -2
  61. package/dist/predicate.d.ts +2 -2
  62. package/dist/predicate.js +2 -417
  63. package/dist/presets/corpus.d.ts +2 -0
  64. package/dist/presets/corpus.js +186 -0
  65. package/dist/presets/public-gallery.d.ts +241 -459
  66. package/dist/presets/public-gallery.js +305 -5
  67. package/dist/presets/public-handoff.d.ts +75 -3
  68. package/dist/presets/public-handoff.js +220 -37
  69. package/dist/presets/public-preview-artifacts.js +20 -26
  70. package/dist/presets/public-preview.d.ts +40 -1152
  71. package/dist/presets/public-preview.js +388 -1152
  72. package/dist/presets/sources.d.ts +17 -4
  73. package/dist/presets/sources.js +1212 -43
  74. package/dist/presets.d.ts +2 -2
  75. package/dist/printer.d.ts +1 -1
  76. package/dist/render-Cddsy_XF.js +585 -0
  77. package/dist/render-template.d.ts +6 -3
  78. package/dist/render-template.js +4 -2
  79. package/dist/source-locations-BCJQnIfU.d.ts +89 -0
  80. package/dist/source-locations.d.ts +2 -0
  81. package/dist/source-locations.js +125 -0
  82. package/dist/stylesheets-oDRAnYA3.d.ts +94 -0
  83. package/dist/template-Dy5yOPyp.d.ts +60 -0
  84. package/dist/template.d.ts +2 -0
  85. package/dist/template.js +37 -0
  86. package/dist/tsx-source-instrumentation.d.ts +23 -0
  87. package/dist/tsx-source-instrumentation.js +97 -0
  88. package/dist/tsx-tracer.d.ts +116 -0
  89. package/dist/tsx-tracer.js +985 -0
  90. package/dist/{variables-3NGLpNTB.d.ts → variables-if1VrV34.d.ts} +2 -2
  91. package/dist/variables.d.ts +1 -1
  92. package/dist/variables.js +1 -1
  93. package/generated/sml-agent-contract.json +574 -782
  94. package/generated/sml-email-agent-contract.json +502 -677
  95. package/generated/sml-email-language-reference.md +94 -160
  96. package/generated/sml-language-reference.md +195 -220
  97. package/package.json +111 -8
@@ -0,0 +1,119 @@
1
+ import { c as EmailStyle, f as EmailChild, m as EmailNode } from "../elements-DtwKlFVH.js";
2
+ //#region src/email/components.d.ts
3
+ /** Marks the hidden preview block so the renderer can read it back and the text lane can keep it. */
4
+ declare const PREHEADER_ATTRIBUTE = "data-samva-preheader";
5
+ interface EmailProps {
6
+ /** CSS classes applied to the primitive's content element. */
7
+ readonly className?: string | undefined;
8
+ readonly lang?: string | undefined;
9
+ readonly dir?: "ltr" | "rtl" | undefined;
10
+ /** Document title; several clients use it as the fallback preview line. */
11
+ readonly title?: string | undefined;
12
+ /** Hidden preview text shown in the inbox list next to the subject. */
13
+ readonly preheader?: string | undefined;
14
+ readonly backgroundColor?: string | undefined;
15
+ /** Applied to the content cell, where Yahoo and AOL keep body styling. */
16
+ readonly style?: EmailStyle | undefined;
17
+ readonly children?: EmailChild;
18
+ }
19
+ /** The hidden inbox preview block. Padding characters stop the client borrowing body copy. */
20
+ declare const preheaderNode: (text: string) => EmailNode;
21
+ /** Document shell: the head every target client needs, plus the body content cell. */
22
+ declare const Email: ({ className, lang, dir, title, preheader, backgroundColor, style, children }: EmailProps) => EmailNode;
23
+ interface SectionProps {
24
+ /** CSS classes applied to the primitive's content element. */
25
+ readonly className?: string | undefined;
26
+ readonly align?: "left" | "center" | "right" | undefined;
27
+ readonly width?: number | string | undefined;
28
+ readonly bgcolor?: string | undefined;
29
+ /** Applied to the content cell so padding survives Outlook and Klaviyo. */
30
+ readonly style?: EmailStyle | undefined;
31
+ readonly tableStyle?: EmailStyle | undefined;
32
+ readonly children?: EmailChild;
33
+ }
34
+ /** A full-width band of content, as the single-cell table every client agrees on. */
35
+ declare const Section: ({ className, align, width, bgcolor, style, tableStyle, children }: SectionProps) => EmailNode;
36
+ interface ColumnsProps {
37
+ /** CSS classes applied to the primitive's content element. */
38
+ readonly className?: string | undefined;
39
+ readonly align?: "left" | "center" | "right" | undefined;
40
+ readonly width?: number | string | undefined;
41
+ readonly style?: EmailStyle | undefined;
42
+ /** `Column` elements; anything else is a content-model error. */
43
+ readonly children?: EmailChild;
44
+ }
45
+ /** A row of side-by-side `Column`s. No flex or grid conversion happens here. */
46
+ declare const Columns: ({ className, align, width, style, children }: ColumnsProps) => EmailNode;
47
+ interface ColumnProps {
48
+ /** CSS classes applied to the primitive's content element. */
49
+ readonly className?: string | undefined;
50
+ readonly align?: "left" | "center" | "right" | undefined;
51
+ readonly valign?: "top" | "middle" | "bottom" | undefined;
52
+ readonly width?: number | string | undefined;
53
+ readonly style?: EmailStyle | undefined;
54
+ readonly children?: EmailChild;
55
+ }
56
+ /** One cell of a `Columns` row. */
57
+ declare const Column: ({ className, align, valign, width, style, children }: ColumnProps) => EmailNode;
58
+ interface ButtonProps {
59
+ /** CSS classes applied to the primitive's content element. */
60
+ readonly className?: string | undefined;
61
+ readonly href: string;
62
+ /** Pixel width and height; classic Outlook's VML fallback needs both. */
63
+ readonly width?: number | undefined;
64
+ readonly height?: number | undefined;
65
+ readonly backgroundColor?: string | undefined;
66
+ readonly color?: string | undefined;
67
+ readonly borderRadius?: number | undefined;
68
+ readonly borderColor?: string | undefined;
69
+ readonly borderWidth?: number | undefined;
70
+ readonly fontSize?: number | undefined;
71
+ readonly fontFamily?: string | undefined;
72
+ readonly align?: "left" | "center" | "right" | undefined;
73
+ readonly style?: EmailStyle | undefined;
74
+ /** The label. A string label is required for the classic Outlook fallback. */
75
+ readonly children?: EmailChild;
76
+ }
77
+ /** A link styled as a button, with a VML fallback so classic Outlook draws the shape. */
78
+ declare const Button: ({ className, href, width, height, backgroundColor, color, borderRadius, borderColor, borderWidth, fontSize, fontFamily, align, style, children }: ButtonProps) => EmailNode;
79
+ interface SpacerProps {
80
+ readonly height: number;
81
+ }
82
+ /** Vertical space that survives clients which collapse margins. */
83
+ declare const Spacer: ({ height }: SpacerProps) => EmailNode;
84
+ interface DividerProps {
85
+ /** CSS classes applied to the primitive's content element. */
86
+ readonly className?: string | undefined;
87
+ readonly color?: string | undefined;
88
+ readonly thickness?: number | undefined;
89
+ readonly style?: EmailStyle | undefined;
90
+ }
91
+ /** A horizontal rule drawn as a cell border, which every target client renders. */
92
+ declare const Divider: ({ className, color, thickness, style }: DividerProps) => EmailNode;
93
+ interface ImageProps {
94
+ /** CSS classes applied to the primitive's content element. */
95
+ readonly className?: string | undefined;
96
+ readonly src: string;
97
+ /** Required. Use an empty string only for images that carry no meaning. */
98
+ readonly alt: string;
99
+ readonly width?: number | string | undefined;
100
+ readonly height?: number | string | undefined;
101
+ readonly align?: "left" | "center" | "right" | undefined;
102
+ readonly style?: EmailStyle | undefined;
103
+ }
104
+ /** An image with the width/height attributes Outlook sizes from before CSS applies. */
105
+ declare const Image: ({ className, src, alt, width, height, align, style }: ImageProps) => EmailNode;
106
+ interface LinkProps {
107
+ /** CSS classes applied to the primitive's content element. */
108
+ readonly className?: string | undefined;
109
+ readonly href: string;
110
+ readonly target?: string | undefined;
111
+ readonly rel?: string | undefined;
112
+ readonly style?: EmailStyle | undefined;
113
+ readonly children?: EmailChild;
114
+ }
115
+ /** A text link that opens outside the client and cannot reach back at the opener. */
116
+ declare const Link: ({ className, href, target, rel, style, children }: LinkProps) => EmailNode;
117
+ //#endregion
118
+ export { Button, ButtonProps, Column, ColumnProps, Columns, ColumnsProps, Divider, DividerProps, Email, EmailProps, Image, ImageProps, Link, LinkProps, PREHEADER_ATTRIBUTE, Section, SectionProps, Spacer, SpacerProps, preheaderNode };
119
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1,207 @@
1
+ import { jsx, rawMarkup, reportEmailDiagnostic } from "./jsx-runtime.js";
2
+ import { escapeAttribute, escapeText } from "./html.js";
3
+ //#region src/email/components.ts
4
+ /** Marks the hidden preview block so the renderer can read it back and the text lane can keep it. */
5
+ const PREHEADER_ATTRIBUTE = "data-samva-preheader";
6
+ const PREHEADER_PADDING_ATTRIBUTE = "data-samva-preheader-padding";
7
+ const PREHEADER_TARGET_LENGTH = 200;
8
+ const PREHEADER_PADDING = "\xA0‌​‍‎‏";
9
+ const presentation = (table, row, rowProps = {}) => jsx("table", {
10
+ role: "presentation",
11
+ border: 0,
12
+ cellpadding: 0,
13
+ cellspacing: 0,
14
+ ...table,
15
+ children: jsx("tbody", { children: jsx("tr", {
16
+ ...rowProps,
17
+ children: row
18
+ }) })
19
+ });
20
+ /** The hidden inbox preview block. Padding characters stop the client borrowing body copy. */
21
+ const preheaderNode = (text) => jsx("div", {
22
+ [PREHEADER_ATTRIBUTE]: text,
23
+ style: {
24
+ display: "none",
25
+ overflow: "hidden",
26
+ lineHeight: "1px",
27
+ opacity: 0,
28
+ maxHeight: 0,
29
+ maxWidth: 0
30
+ },
31
+ children: [text, text.length >= PREHEADER_TARGET_LENGTH ? null : jsx("div", {
32
+ [PREHEADER_PADDING_ATTRIBUTE]: true,
33
+ children: PREHEADER_PADDING.repeat(Math.ceil((PREHEADER_TARGET_LENGTH - text.length) / 7))
34
+ })]
35
+ });
36
+ /** Document shell: the head every target client needs, plus the body content cell. */
37
+ const Email = ({ className, lang = "en", dir = "ltr", title, preheader, backgroundColor, style, children }) => jsx("html", {
38
+ lang,
39
+ dir,
40
+ xmlns: "http://www.w3.org/1999/xhtml",
41
+ "xmlns:o": "urn:schemas-microsoft-com:office:office",
42
+ children: [jsx("head", { children: [
43
+ jsx("meta", { charset: "utf-8" }),
44
+ jsx("meta", {
45
+ "http-equiv": "Content-Type",
46
+ content: "text/html; charset=UTF-8"
47
+ }),
48
+ jsx("meta", {
49
+ name: "viewport",
50
+ content: "width=device-width, initial-scale=1"
51
+ }),
52
+ jsx("meta", { name: "x-apple-disable-message-reformatting" }),
53
+ jsx("meta", {
54
+ name: "color-scheme",
55
+ content: "light dark"
56
+ }),
57
+ jsx("meta", {
58
+ name: "supported-color-schemes",
59
+ content: "light dark"
60
+ }),
61
+ title === void 0 ? null : jsx("title", { children: title }),
62
+ rawMarkup("<!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->")
63
+ ] }), jsx("body", {
64
+ style: {
65
+ margin: 0,
66
+ padding: 0,
67
+ ...backgroundColor === void 0 ? {} : { backgroundColor }
68
+ },
69
+ children: [preheader === void 0 ? null : preheaderNode(preheader), presentation({
70
+ align: "center",
71
+ width: "100%",
72
+ ...backgroundColor === void 0 ? {} : { bgcolor: backgroundColor }
73
+ }, jsx("td", {
74
+ className,
75
+ ...style === void 0 ? {} : { style },
76
+ children
77
+ }))]
78
+ })]
79
+ });
80
+ /** A full-width band of content, as the single-cell table every client agrees on. */
81
+ const Section = ({ className, align = "center", width = "100%", bgcolor, style, tableStyle, children }) => presentation({
82
+ align,
83
+ width,
84
+ ...bgcolor === void 0 ? {} : { bgcolor },
85
+ ...tableStyle === void 0 ? {} : { style: tableStyle }
86
+ }, jsx("td", {
87
+ className,
88
+ ...style === void 0 ? {} : { style },
89
+ children
90
+ }));
91
+ /** A row of side-by-side `Column`s. No flex or grid conversion happens here. */
92
+ const Columns = ({ className, align = "center", width = "100%", style, children }) => presentation({
93
+ className,
94
+ align,
95
+ width,
96
+ ...style === void 0 ? {} : { style }
97
+ }, children, { style: { width: "100%" } });
98
+ /** One cell of a `Columns` row. */
99
+ const Column = ({ className, align, valign, width, style, children }) => jsx("td", {
100
+ className,
101
+ ...align === void 0 ? {} : { align },
102
+ ...valign === void 0 ? {} : { valign },
103
+ ...width === void 0 ? {} : { width },
104
+ ...style === void 0 ? {} : { style },
105
+ children
106
+ });
107
+ const DEFAULT_BUTTON_FONT = "Helvetica, Arial, sans-serif";
108
+ /** A link styled as a button, with a VML fallback so classic Outlook draws the shape. */
109
+ const Button = ({ className, href, width, height, backgroundColor = "#000000", color = "#ffffff", borderRadius = 0, borderColor, borderWidth = 0, fontSize = 16, fontFamily = DEFAULT_BUTTON_FONT, align = "left", style, children }) => {
110
+ const label = typeof children === "string" ? children : void 0;
111
+ const fallback = width !== void 0 && height !== void 0 && label !== void 0;
112
+ if (!fallback) reportEmailDiagnostic({
113
+ code: "button-outlook-fallback",
114
+ severity: "warning",
115
+ message: "<Button> draws its classic Outlook shape from VML, which needs width, height and a plain string label. Without all three, classic Windows Outlook shows an unstyled link.",
116
+ clients: ["outlook-windows"]
117
+ });
118
+ const arcsize = height === void 0 ? 0 : Math.round(borderRadius / height * 100);
119
+ return presentation({
120
+ width: "100%",
121
+ style: { borderCollapse: "collapse" }
122
+ }, jsx("td", {
123
+ align,
124
+ children: [fallback ? rawMarkup(`<!--[if mso]><v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${escapeAttribute(href)}" style="height:${height}px;v-text-anchor:middle;width:${width}px;" arcsize="${arcsize}%" ${borderColor === void 0 ? "stroke=\"false\"" : `strokecolor="${escapeAttribute(borderColor)}" strokeweight="${borderWidth}px"`} fillcolor="${escapeAttribute(backgroundColor)}"><w:anchorlock/><center style="color:${escapeAttribute(color)};font-family:${escapeAttribute(fontFamily)};font-size:${fontSize}px;font-weight:bold;">${escapeText(label)}</center></v:roundrect><![endif]-->`) : null, jsx("a", {
125
+ className,
126
+ href,
127
+ target: "_blank",
128
+ rel: "noopener noreferrer",
129
+ style: {
130
+ backgroundColor,
131
+ color,
132
+ borderRadius: `${borderRadius}px`,
133
+ display: "inline-block",
134
+ fontFamily,
135
+ fontSize: `${fontSize}px`,
136
+ fontWeight: "bold",
137
+ lineHeight: height === void 0 ? "120%" : `${height - 2 * borderWidth}px`,
138
+ textAlign: "center",
139
+ textDecoration: "none",
140
+ ...width === void 0 ? {} : {
141
+ width: `${width}px`,
142
+ maxWidth: "100%"
143
+ },
144
+ ...borderColor === void 0 ? {} : { border: `${borderWidth}px solid ${borderColor}` },
145
+ ...fallback ? { msoHide: "all" } : {},
146
+ ...style
147
+ },
148
+ children
149
+ })]
150
+ }));
151
+ };
152
+ /** Vertical space that survives clients which collapse margins. */
153
+ const Spacer = ({ height }) => presentation({ width: "100%" }, jsx("td", {
154
+ height,
155
+ style: {
156
+ height: `${height}px`,
157
+ lineHeight: `${height}px`,
158
+ fontSize: "1px"
159
+ },
160
+ children: "​"
161
+ }));
162
+ /** A horizontal rule drawn as a cell border, which every target client renders. */
163
+ const Divider = ({ className, color = "#e5e7eb", thickness = 1, style }) => presentation({ width: "100%" }, jsx("td", {
164
+ className,
165
+ style: {
166
+ borderTop: `${thickness}px solid ${color}`,
167
+ fontSize: "1px",
168
+ lineHeight: "1px",
169
+ ...style
170
+ },
171
+ children: "​"
172
+ }));
173
+ /** An image with the width/height attributes Outlook sizes from before CSS applies. */
174
+ const Image = ({ className, src, alt, width, height, align, style }) => jsx("img", {
175
+ className,
176
+ src,
177
+ alt,
178
+ border: 0,
179
+ ...width === void 0 ? {} : { width },
180
+ ...height === void 0 ? {} : { height },
181
+ ...align === void 0 ? {} : { align },
182
+ style: {
183
+ display: "block",
184
+ outline: "none",
185
+ border: "none",
186
+ textDecoration: "none",
187
+ maxWidth: "100%",
188
+ ...style
189
+ }
190
+ });
191
+ /** A text link that opens outside the client and cannot reach back at the opener. */
192
+ const Link = ({ className, href, target = "_blank", rel = "noopener noreferrer", style, children }) => jsx("a", {
193
+ className,
194
+ href,
195
+ target,
196
+ rel,
197
+ style: {
198
+ color: "#067df7",
199
+ textDecoration: "none",
200
+ ...style
201
+ },
202
+ children
203
+ });
204
+ //#endregion
205
+ export { Button, Column, Columns, Divider, Email, Image, Link, PREHEADER_ATTRIBUTE, Section, Spacer, preheaderNode };
206
+
207
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1,2 @@
1
+ import { a as formatEmailDiagnostic, i as EmailDiagnosticSeverity, n as EmailCompileError, o as hasBlockingDiagnostic, r as EmailDiagnostic, t as EmailCompatibilityAssessment } from "../diagnostics-Djd9ckLg.js";
2
+ export { EmailCompatibilityAssessment, EmailCompileError, EmailDiagnostic, EmailDiagnosticSeverity, formatEmailDiagnostic, hasBlockingDiagnostic };
@@ -0,0 +1,56 @@
1
+ import { JsxSourceLocation } from "../source-locations.js";
2
+ import { Schema } from "effect";
3
+ //#region src/email/diagnostics.ts
4
+ const EmailDiagnosticSeverity = Schema.Literals([
5
+ "error",
6
+ "warning",
7
+ "info"
8
+ ]);
9
+ /** What the emitted document establishes beyond the client feature matrix. */
10
+ const EmailCompatibilityAssessment = Schema.Struct({
11
+ assessment: Schema.Literals([
12
+ "risk",
13
+ "degradation",
14
+ "unverified",
15
+ "not-applicable"
16
+ ]),
17
+ /** A short description of the consequence or the remaining verification. */
18
+ title: Schema.String
19
+ });
20
+ const EmailDiagnostic = Schema.Struct({
21
+ /** Stable identifier, e.g. `unsupported-element` or `caniemail/css-border-radius`. */
22
+ code: Schema.String,
23
+ severity: EmailDiagnosticSeverity,
24
+ /** States what is wrong and what to write instead. */
25
+ message: Schema.String,
26
+ /** Innermost authoring element first, then each enclosing component call site. */
27
+ origins: Schema.Array(JsxSourceLocation),
28
+ /** Target clients a compatibility finding applies to. */
29
+ clients: Schema.optional(Schema.Array(Schema.String)),
30
+ /** Partial-support notes and other caveats a client matrix carries. */
31
+ notes: Schema.optional(Schema.String),
32
+ /** Which pinned rule data produced the finding. */
33
+ provenance: Schema.optional(Schema.String),
34
+ /** Declared fixtures whose rendered output produced this finding. */
35
+ fixtures: Schema.optional(Schema.Array(Schema.String)),
36
+ /** Source chains for every located emitted occurrence; origins identifies the first. */
37
+ occurrences: Schema.optional(Schema.Array(Schema.Array(JsxSourceLocation))),
38
+ /** Compatibility observations are not automatically defects or proof of client rendering. */
39
+ compatibility: Schema.optional(EmailCompatibilityAssessment)
40
+ });
41
+ var EmailCompileError = class extends Schema.TaggedError()("EmailCompileError", { diagnostics: Schema.Array(EmailDiagnostic) }) {
42
+ get message() {
43
+ return this.diagnostics.map(formatEmailDiagnostic).join("\n");
44
+ }
45
+ };
46
+ /** `emails/welcome.tsx:12:3 unsupported-element: …` — the shape agents iterate on. */
47
+ const formatEmailDiagnostic = (diagnostic) => {
48
+ const origin = diagnostic.origins[0];
49
+ return `${origin === void 0 ? "<unknown source>" : `${origin.fileName}:${origin.lineNumber}:${origin.columnNumber}`} ${diagnostic.code}: ${diagnostic.message}`;
50
+ };
51
+ /** True when a set of findings must stop the compile or refuse a publication. */
52
+ const hasBlockingDiagnostic = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.severity === "error");
53
+ //#endregion
54
+ export { EmailCompatibilityAssessment, EmailCompileError, EmailDiagnostic, EmailDiagnosticSeverity, formatEmailDiagnostic, hasBlockingDiagnostic };
55
+
56
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1,2 @@
1
+ import { a as EmailGlobalProps, c as EmailStyle, d as isUrlAttribute, i as EmailElementSpec, l as EmailTag, n as EMAIL_GLOBAL_ATTRIBUTES, o as EmailIntrinsicElements, r as EmailAttributeSpec, s as EmailLayout, t as EMAIL_ELEMENTS, u as emailElement } from "../elements-DtwKlFVH.js";
2
+ export { EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, EmailAttributeSpec, EmailElementSpec, EmailGlobalProps, EmailIntrinsicElements, EmailLayout, EmailStyle, EmailTag, emailElement, isUrlAttribute };
@@ -0,0 +1,299 @@
1
+ //#region src/email/elements.ts
2
+ /** Attributes every supported element accepts. `class`/`className`/`style` are handled separately. */
3
+ const EMAIL_GLOBAL_ATTRIBUTES = {
4
+ id: { type: "string" },
5
+ title: { type: "string" },
6
+ lang: { type: "string" },
7
+ dir: {
8
+ type: "string",
9
+ values: [
10
+ "ltr",
11
+ "rtl",
12
+ "auto"
13
+ ]
14
+ },
15
+ role: { type: "string" }
16
+ };
17
+ const alignment = {
18
+ type: "string",
19
+ values: [
20
+ "left",
21
+ "center",
22
+ "right"
23
+ ]
24
+ };
25
+ const verticalAlignment = {
26
+ type: "string",
27
+ values: [
28
+ "top",
29
+ "middle",
30
+ "bottom"
31
+ ]
32
+ };
33
+ const flowAttributes = { align: alignment };
34
+ const cellAttributes = {
35
+ align: alignment,
36
+ valign: verticalAlignment,
37
+ width: { type: "measure" },
38
+ height: { type: "measure" },
39
+ bgcolor: { type: "string" },
40
+ colspan: { type: "number" },
41
+ rowspan: { type: "number" }
42
+ };
43
+ const block = (attributes) => ({
44
+ content: "flow",
45
+ layout: "block",
46
+ attributes
47
+ });
48
+ const inline = () => ({
49
+ content: "flow",
50
+ layout: "inline",
51
+ attributes: {}
52
+ });
53
+ /** The complete supported vocabulary. Anything outside it is a compile error with a source location. */
54
+ const EMAIL_ELEMENTS = {
55
+ html: {
56
+ content: "flow",
57
+ layout: "document",
58
+ attributes: {
59
+ xmlns: { type: "string" },
60
+ "xmlns:o": { type: "string" },
61
+ "xmlns:v": { type: "string" },
62
+ "xmlns:w": { type: "string" }
63
+ },
64
+ childElements: ["head", "body"]
65
+ },
66
+ head: {
67
+ content: "flow",
68
+ layout: "metadata",
69
+ attributes: {},
70
+ childElements: [
71
+ "title",
72
+ "meta",
73
+ "style"
74
+ ]
75
+ },
76
+ title: {
77
+ content: "text",
78
+ layout: "metadata",
79
+ attributes: {}
80
+ },
81
+ style: {
82
+ content: "raw",
83
+ layout: "metadata",
84
+ attributes: { type: { type: "string" } }
85
+ },
86
+ meta: {
87
+ content: "void",
88
+ layout: "metadata",
89
+ attributes: {
90
+ name: { type: "string" },
91
+ content: { type: "string" },
92
+ charset: { type: "string" },
93
+ "http-equiv": { type: "string" }
94
+ }
95
+ },
96
+ body: {
97
+ content: "flow",
98
+ layout: "block",
99
+ attributes: { bgcolor: { type: "string" } }
100
+ },
101
+ div: block(flowAttributes),
102
+ section: block(flowAttributes),
103
+ article: block(flowAttributes),
104
+ header: block(flowAttributes),
105
+ footer: block(flowAttributes),
106
+ main: block(flowAttributes),
107
+ center: block({}),
108
+ p: block(flowAttributes),
109
+ blockquote: block(flowAttributes),
110
+ pre: {
111
+ content: "flow",
112
+ layout: "preformatted",
113
+ attributes: {}
114
+ },
115
+ h1: block(flowAttributes),
116
+ h2: block(flowAttributes),
117
+ h3: block(flowAttributes),
118
+ h4: block(flowAttributes),
119
+ h5: block(flowAttributes),
120
+ h6: block(flowAttributes),
121
+ span: inline(),
122
+ strong: inline(),
123
+ b: inline(),
124
+ em: inline(),
125
+ i: inline(),
126
+ u: inline(),
127
+ s: inline(),
128
+ small: inline(),
129
+ code: inline(),
130
+ a: {
131
+ content: "flow",
132
+ layout: "link",
133
+ attributes: {
134
+ href: {
135
+ type: "url",
136
+ required: true
137
+ },
138
+ target: { type: "string" },
139
+ rel: { type: "string" },
140
+ name: { type: "string" }
141
+ }
142
+ },
143
+ img: {
144
+ content: "void",
145
+ layout: "image",
146
+ attributes: {
147
+ src: {
148
+ type: "url",
149
+ required: true
150
+ },
151
+ alt: {
152
+ type: "string",
153
+ required: true
154
+ },
155
+ width: { type: "measure" },
156
+ height: { type: "measure" },
157
+ border: { type: "measure" },
158
+ align: alignment
159
+ }
160
+ },
161
+ table: {
162
+ content: "flow",
163
+ layout: "table",
164
+ attributes: {
165
+ width: { type: "measure" },
166
+ height: { type: "measure" },
167
+ border: { type: "measure" },
168
+ cellpadding: { type: "measure" },
169
+ cellspacing: { type: "measure" },
170
+ align: alignment,
171
+ bgcolor: { type: "string" }
172
+ },
173
+ childElements: [
174
+ "caption",
175
+ "colgroup",
176
+ "thead",
177
+ "tbody",
178
+ "tfoot",
179
+ "tr"
180
+ ]
181
+ },
182
+ caption: {
183
+ content: "flow",
184
+ layout: "block",
185
+ attributes: flowAttributes
186
+ },
187
+ colgroup: {
188
+ content: "flow",
189
+ layout: "table-section",
190
+ attributes: {
191
+ span: { type: "number" },
192
+ width: { type: "measure" }
193
+ },
194
+ childElements: ["col"]
195
+ },
196
+ col: {
197
+ content: "void",
198
+ layout: "table-section",
199
+ attributes: {
200
+ span: { type: "number" },
201
+ width: { type: "measure" }
202
+ }
203
+ },
204
+ thead: {
205
+ content: "flow",
206
+ layout: "table-section",
207
+ attributes: {
208
+ align: alignment,
209
+ valign: verticalAlignment,
210
+ bgcolor: { type: "string" }
211
+ },
212
+ childElements: ["tr"]
213
+ },
214
+ tbody: {
215
+ content: "flow",
216
+ layout: "table-section",
217
+ attributes: {
218
+ align: alignment,
219
+ valign: verticalAlignment,
220
+ bgcolor: { type: "string" }
221
+ },
222
+ childElements: ["tr"]
223
+ },
224
+ tfoot: {
225
+ content: "flow",
226
+ layout: "table-section",
227
+ attributes: {
228
+ align: alignment,
229
+ valign: verticalAlignment,
230
+ bgcolor: { type: "string" }
231
+ },
232
+ childElements: ["tr"]
233
+ },
234
+ tr: {
235
+ content: "flow",
236
+ layout: "row",
237
+ attributes: {
238
+ align: alignment,
239
+ valign: verticalAlignment,
240
+ bgcolor: { type: "string" },
241
+ height: { type: "measure" }
242
+ },
243
+ childElements: ["td", "th"]
244
+ },
245
+ td: {
246
+ content: "flow",
247
+ layout: "cell",
248
+ attributes: cellAttributes
249
+ },
250
+ th: {
251
+ content: "flow",
252
+ layout: "cell",
253
+ attributes: cellAttributes
254
+ },
255
+ ul: {
256
+ content: "flow",
257
+ layout: "list",
258
+ attributes: {},
259
+ childElements: ["li"]
260
+ },
261
+ ol: {
262
+ content: "flow",
263
+ layout: "list",
264
+ attributes: {
265
+ start: { type: "number" },
266
+ type: { type: "string" }
267
+ },
268
+ childElements: ["li"]
269
+ },
270
+ li: {
271
+ content: "flow",
272
+ layout: "list-item",
273
+ attributes: {}
274
+ },
275
+ br: {
276
+ content: "void",
277
+ layout: "break",
278
+ attributes: {}
279
+ },
280
+ hr: {
281
+ content: "void",
282
+ layout: "rule",
283
+ attributes: {
284
+ width: { type: "measure" },
285
+ size: { type: "number" },
286
+ align: alignment
287
+ }
288
+ }
289
+ };
290
+ /** Attributes that must carry a URL; these are checked against the safe-scheme rule. */
291
+ const isUrlAttribute = (tag, attribute) => {
292
+ return EMAIL_ELEMENTS[tag]?.attributes[attribute]?.type === "url";
293
+ };
294
+ /** Look up one supported element, or `undefined` when the tag is outside the vocabulary. */
295
+ const emailElement = (tag) => Object.hasOwn(EMAIL_ELEMENTS, tag) ? EMAIL_ELEMENTS[tag] : void 0;
296
+ //#endregion
297
+ export { EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, emailElement, isUrlAttribute };
298
+
299
+ //# sourceMappingURL=elements.js.map