@samva/markup 0.8.0 → 0.10.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 (172) hide show
  1. package/AGENTS.md +107 -46
  2. package/CHANGELOG.md +345 -0
  3. package/README.md +188 -52
  4. package/dist/{brand-DcoVkh_S.d.ts → assets-BIsyMQ92.d.ts} +41 -11
  5. package/dist/{email/brand.js → brand-C0MKTwmX.js} +64 -4
  6. package/dist/{theme-css.d.ts → brand.d.ts} +12 -3
  7. package/dist/brand.js +4 -0
  8. package/dist/channel-specs-C2feJwuP.d.ts +13 -0
  9. package/dist/compiler.d.ts +88 -115
  10. package/dist/compiler.js +750 -171
  11. package/dist/components-BZCqegS8.js +1864 -0
  12. package/dist/diagnostic-model-DJtqbETd.js +38 -0
  13. package/dist/{diagnostics-OcQKQYSY.d.ts → diagnostic-model-DxthUZBT.d.ts} +3 -21
  14. package/dist/{diagnostics-BMYtBCQk.d.ts → diagnostics-B-Gym34R.d.ts} +8 -4
  15. package/dist/{email/diagnostics.js → diagnostics-CnKFefKz.js} +4 -3
  16. package/dist/diagnostics.d.ts +410 -2
  17. package/dist/diagnostics.js +402 -52
  18. package/dist/edit.d.ts +234 -0
  19. package/dist/edit.js +947 -0
  20. package/dist/email/jsx-dev-runtime.d.ts +2 -2
  21. package/dist/email/jsx-dev-runtime.js +1 -2
  22. package/dist/email/jsx-runtime.d.ts +1 -1
  23. package/dist/email/jsx-runtime.js +1 -85
  24. package/dist/{email/components.d.ts → email.d.ts} +22 -11
  25. package/dist/email.js +2 -0
  26. package/dist/fmt.d.ts +32 -0
  27. package/dist/fmt.js +174 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +2 -0
  30. package/dist/{render-vAv_4r9v.js → ir-CLhlklKV.js} +96 -279
  31. package/dist/jsx-runtime-CBlexoeR.js +98 -0
  32. package/dist/{elements-BzjjnoCS.d.ts → jsx-runtime-ylIOnaSf.d.ts} +76 -76
  33. package/dist/profile-pWGtWZXF.js +3803 -0
  34. package/dist/render-BPonDpCl.d.ts +539 -0
  35. package/dist/render-BQmfh94k.js +257 -0
  36. package/dist/render.d.ts +35 -0
  37. package/dist/render.js +49 -0
  38. package/dist/sms.d.ts +16 -0
  39. package/dist/sms.js +12 -0
  40. package/dist/source-locations-C8wCsiAy.d.ts +23 -0
  41. package/dist/template-DMPwxMSq.d.ts +65 -0
  42. package/dist/template-zLUjcwfF.js +42 -0
  43. package/dist/{theme-css-hFqcPSar.js → theme-css-JtRCm1fb.js} +2 -2
  44. package/dist/whatsapp.d.ts +57 -0
  45. package/dist/whatsapp.js +22 -0
  46. package/generated/contract.json +1788 -0
  47. package/generated/reference.md +360 -0
  48. package/package.json +46 -239
  49. package/samva-brand.d.ts +4 -4
  50. package/skills/sml/SKILL.md +123 -0
  51. package/dist/ast-BrDtApwS.d.ts +0 -107
  52. package/dist/ast.d.ts +0 -2
  53. package/dist/ast.js +0 -124
  54. package/dist/candidate.d.ts +0 -29
  55. package/dist/candidate.js +0 -88
  56. package/dist/catalog-CKuOooB8.d.ts +0 -354
  57. package/dist/checks-D73Xizbw.js +0 -59366
  58. package/dist/checks.d.ts +0 -33
  59. package/dist/checks.js +0 -2
  60. package/dist/classes.d.ts +0 -26
  61. package/dist/classes.js +0 -184
  62. package/dist/compile-sms.d.ts +0 -28
  63. package/dist/compile-sms.js +0 -44
  64. package/dist/compile-whatsapp.d.ts +0 -56
  65. package/dist/compile-whatsapp.js +0 -186
  66. package/dist/compile.d.ts +0 -18
  67. package/dist/compile.js +0 -29
  68. package/dist/components.d.ts +0 -289
  69. package/dist/components.js +0 -106
  70. package/dist/conditionals.d.ts +0 -10
  71. package/dist/conditionals.js +0 -74
  72. package/dist/corpus-CPPfgAHN.d.ts +0 -106
  73. package/dist/css-CS2jLID6.d.ts +0 -109
  74. package/dist/email/assets.d.ts +0 -40
  75. package/dist/email/assets.js +0 -63
  76. package/dist/email/brand-footer.d.ts +0 -34
  77. package/dist/email/brand-footer.js +0 -62
  78. package/dist/email/brand.d.ts +0 -2
  79. package/dist/email/components.js +0 -240
  80. package/dist/email/diagnostics.d.ts +0 -2
  81. package/dist/email/elements.d.ts +0 -2
  82. package/dist/email/elements.js +0 -299
  83. package/dist/email/html.d.ts +0 -2
  84. package/dist/email/html.js +0 -278
  85. package/dist/email/render.d.ts +0 -50
  86. package/dist/email/render.js +0 -3
  87. package/dist/email/selection.d.ts +0 -2
  88. package/dist/email/selection.js +0 -91
  89. package/dist/email/source-edit.d.ts +0 -67
  90. package/dist/email/source-edit.js +0 -185
  91. package/dist/email/stylesheets.d.ts +0 -15
  92. package/dist/email/stylesheets.js +0 -48
  93. package/dist/email/text.d.ts +0 -7
  94. package/dist/email/text.js +0 -100
  95. package/dist/emit.d.ts +0 -51
  96. package/dist/emit.js +0 -151
  97. package/dist/html-Bl9BAdqc.d.ts +0 -42
  98. package/dist/interpolate.d.ts +0 -24
  99. package/dist/interpolate.js +0 -43
  100. package/dist/jsx-dev-runtime.d.ts +0 -11
  101. package/dist/jsx-dev-runtime.js +0 -15
  102. package/dist/jsx-runtime-I-1nCtl2.d.ts +0 -57
  103. package/dist/jsx-runtime.d.ts +0 -2
  104. package/dist/jsx-runtime.js +0 -121
  105. package/dist/lexer.d.ts +0 -60
  106. package/dist/lexer.js +0 -281
  107. package/dist/model.d.ts +0 -24
  108. package/dist/model.js +0 -77
  109. package/dist/ops-BvwqHl7V.js +0 -630
  110. package/dist/ops.d.ts +0 -114
  111. package/dist/ops.js +0 -2
  112. package/dist/parser-t29cHLVL.d.ts +0 -396
  113. package/dist/parser.d.ts +0 -2
  114. package/dist/parser.js +0 -859
  115. package/dist/predicate-BI6uRRM-.js +0 -549
  116. package/dist/predicate-M-05Nd7R.d.ts +0 -56
  117. package/dist/predicate.d.ts +0 -2
  118. package/dist/predicate.js +0 -2
  119. package/dist/printer.d.ts +0 -6
  120. package/dist/printer.js +0 -122
  121. package/dist/registry-Dcp6QEK_.d.ts +0 -73
  122. package/dist/registry.d.ts +0 -2
  123. package/dist/registry.js +0 -646
  124. package/dist/render-template.d.ts +0 -45
  125. package/dist/render-template.js +0 -76
  126. package/dist/selection-CCArx9lU.d.ts +0 -91
  127. package/dist/showcase-egkusQBf.d.ts +0 -415
  128. package/dist/sms-segments-y4FpPilJ.d.ts +0 -13
  129. package/dist/sms-segments.d.ts +0 -2
  130. package/dist/sms-segments.js +0 -46
  131. package/dist/source-locations-DrCM82Ym.d.ts +0 -67
  132. package/dist/source-locations.d.ts +0 -2
  133. package/dist/source-locations.js +0 -102
  134. package/dist/starters/category-mapping.d.ts +0 -13
  135. package/dist/starters/category-mapping.js +0 -49
  136. package/dist/starters/corpus.d.ts +0 -2
  137. package/dist/starters/corpus.js +0 -194
  138. package/dist/starters/library.d.ts +0 -18
  139. package/dist/starters/library.js +0 -692
  140. package/dist/starters/public-gallery.d.ts +0 -266
  141. package/dist/starters/public-gallery.js +0 -916
  142. package/dist/starters/public-handoff.d.ts +0 -164
  143. package/dist/starters/public-handoff.js +0 -361
  144. package/dist/starters/public-preview-artifacts.d.ts +0 -43
  145. package/dist/starters/public-preview-artifacts.js +0 -104
  146. package/dist/starters/public-preview.d.ts +0 -61
  147. package/dist/starters/public-preview.js +0 -83
  148. package/dist/starters/showcase.d.ts +0 -2
  149. package/dist/starters/showcase.js +0 -335
  150. package/dist/starters/sources.d.ts +0 -45
  151. package/dist/starters/sources.js +0 -7762
  152. package/dist/starters/theme.d.ts +0 -45
  153. package/dist/starters/theme.js +0 -77
  154. package/dist/starters.d.ts +0 -2
  155. package/dist/starters.js +0 -874
  156. package/dist/tailwind-BYq7Lo6u.js +0 -727
  157. package/dist/template-DWftqh4x.d.ts +0 -60
  158. package/dist/template.d.ts +0 -2
  159. package/dist/template.js +0 -37
  160. package/dist/theme-css.js +0 -2
  161. package/dist/tsx-source-instrumentation.d.ts +0 -30
  162. package/dist/tsx-source-instrumentation.js +0 -115
  163. package/dist/tsx-tracer.d.ts +0 -112
  164. package/dist/tsx-tracer.js +0 -985
  165. package/dist/variables-J_L3qxRa.d.ts +0 -77
  166. package/dist/variables.d.ts +0 -2
  167. package/dist/variables.js +0 -141
  168. package/dist/version-BITr58kk.js +0 -96
  169. package/generated/sml-agent-contract.json +0 -709
  170. package/generated/sml-email-agent-contract.json +0 -615
  171. package/generated/sml-email-language-reference.md +0 -94
  172. package/generated/sml-language-reference.md +0 -195
@@ -1,5 +1,5 @@
1
- import { r as JsxSource } from "../source-locations-DrCM82Ym.js";
2
- import { g as JSX, h as Fragment, m as EmailNode, p as EmailComponent } from "../elements-BzjjnoCS.js";
1
+ import { n as JsxSource } from "../source-locations-C8wCsiAy.js";
2
+ import { a as JSX, i as Fragment, n as EmailComponent, r as EmailNode } from "../jsx-runtime-ylIOnaSf.js";
3
3
  //#region src/email/jsx-dev-runtime.d.ts
4
4
  /** Development JSX retains compiler-provided origins directly on the semantic tree. */
5
5
  declare const jsxDEV: (type: string | EmailComponent<Record<string, unknown>> | typeof Fragment, props: Record<string, unknown> | null, _key?: unknown, _staticChildren?: boolean, source?: JsxSource) => EmailNode;
@@ -1,5 +1,4 @@
1
- import { JSX_SOURCE_LOCATION_PROP } from "../source-locations.js";
2
- import { Fragment, jsx } from "./jsx-runtime.js";
1
+ import { a as jsx, n as Fragment, u as JSX_SOURCE_LOCATION_PROP } from "../jsx-runtime-CBlexoeR.js";
3
2
  //#region src/email/jsx-dev-runtime.ts
4
3
  /** Development JSX retains compiler-provided origins directly on the semantic tree. */
5
4
  const jsxDEV = (type, props, _key, _staticChildren, source) => jsx(type, {
@@ -1,2 +1,2 @@
1
- import { C as reportEmailDiagnostic, S as rawMarkup, _ as currentEmailOrigins, b as jsxs, f as EmailChild, g as JSX, h as Fragment, m as EmailNode, p as EmailComponent, v as drainEmailDiagnostics, x as normalizeChildren, y as jsx } from "../elements-BzjjnoCS.js";
1
+ import { a as JSX, c as jsx, d as rawMarkup, f as reportEmailDiagnostic, i as Fragment, l as jsxs, n as EmailComponent, o as currentEmailOrigins, r as EmailNode, s as drainEmailDiagnostics, t as EmailChild, u as normalizeChildren } from "../jsx-runtime-ylIOnaSf.js";
2
2
  export { EmailChild, EmailComponent, EmailNode, Fragment, JSX, currentEmailOrigins, drainEmailDiagnostics, jsx, jsxs, normalizeChildren, rawMarkup, reportEmailDiagnostic };
@@ -1,86 +1,2 @@
1
- import { t as hasProperty } from "../guards-eV1qLbf2.js";
2
- import { JSX_SOURCE_LOCATION_PROP, completeJsxSourceLocation } from "../source-locations.js";
3
- //#region src/email/jsx-runtime.ts
4
- /** Constructors for the authoring tree. The tree is data; nothing here validates it. */
5
- const EmailNode = {
6
- Text: (fields) => ({
7
- type: "Text",
8
- ...fields
9
- }),
10
- Element: (fields) => ({
11
- type: "Element",
12
- ...fields
13
- }),
14
- Fragment: (fields) => ({
15
- type: "Fragment",
16
- ...fields
17
- }),
18
- Raw: (fields) => ({
19
- type: "Raw",
20
- ...fields
21
- })
22
- };
23
- const EMAIL_NODE_TYPES = /* @__PURE__ */ new Set([
24
- "Text",
25
- "Element",
26
- "Fragment",
27
- "Raw"
28
- ]);
29
- /** True for a node this runtime built; anything else is not a child it can place. */
30
- const isEmailNode = (input) => hasProperty(input, "type") && typeof input.type === "string" && EMAIL_NODE_TYPES.has(input.type);
31
- const Fragment = Symbol.for("@samva/markup/email/Fragment");
32
- const callSites = [];
33
- /** Call sites enclosing the element being built, innermost first. */
34
- const currentEmailOrigins = () => [...callSites].reverse();
35
- const reported = [];
36
- /** Record a finding from inside a compiler primitive, located at the authoring call site. */
37
- const reportEmailDiagnostic = (diagnostic) => {
38
- reported.push({
39
- ...diagnostic,
40
- origins: currentEmailOrigins()
41
- });
42
- };
43
- /** Take and clear the findings primitives reported during a render. */
44
- const drainEmailDiagnostics = () => reported.splice(0);
45
- /** Normalize actual values without interpolation or recording proxies. */
46
- const normalizeChildren = (input) => {
47
- if (input === null || input === void 0 || typeof input === "boolean") return [];
48
- if (typeof input === "string") return [EmailNode.Text({ value: input })];
49
- if (typeof input === "number" && Number.isFinite(input)) return [EmailNode.Text({ value: String(input) })];
50
- if (Array.isArray(input)) return input.flatMap(normalizeChildren);
51
- if (isEmailNode(input)) return [input];
52
- throw new TypeError("Email children must be synchronous text, finite numbers, elements, or arrays");
53
- };
54
- /** Compatibility markup emitted by a compiler primitive, with the text it stands for. */
55
- const rawMarkup = (html, text = "") => EmailNode.Raw({
56
- html,
57
- text,
58
- origins: currentEmailOrigins()
59
- });
60
- /** Automatic JSX factory for ordinary HTML and synchronous imported components. */
61
- const jsx = (type, props) => {
62
- const { children, [JSX_SOURCE_LOCATION_PROP]: source, ...attributes } = props ?? {};
63
- const origin = completeJsxSourceLocation(source);
64
- if (type === Fragment) return EmailNode.Fragment({ children: normalizeChildren(children) });
65
- if (typeof type === "string") return EmailNode.Element({
66
- tag: type,
67
- props: attributes,
68
- children: normalizeChildren(children),
69
- origins: origin === void 0 ? currentEmailOrigins() : [origin, ...currentEmailOrigins()],
70
- authored: origin !== void 0
71
- });
72
- if (origin !== void 0) callSites.push(origin);
73
- try {
74
- return EmailNode.Fragment({ children: normalizeChildren(type({
75
- ...attributes,
76
- children
77
- })) });
78
- } finally {
79
- if (origin !== void 0) callSites.pop();
80
- }
81
- };
82
- const jsxs = jsx;
83
- //#endregion
1
+ import { a as jsx, c as rawMarkup, i as drainEmailDiagnostics, l as reportEmailDiagnostic, n as Fragment, o as jsxs, r as currentEmailOrigins, s as normalizeChildren, t as EmailNode } from "../jsx-runtime-CBlexoeR.js";
84
2
  export { EmailNode, Fragment, currentEmailOrigins, drainEmailDiagnostics, jsx, jsxs, normalizeChildren, rawMarkup, reportEmailDiagnostic };
85
-
86
- //# sourceMappingURL=jsx-runtime.js.map
@@ -1,4 +1,4 @@
1
- import { c as EmailStyle, f as EmailChild, m as EmailNode } from "../elements-BzjjnoCS.js";
1
+ import { b as EmailStyle, r as EmailNode, t as EmailChild } from "./jsx-runtime-ylIOnaSf.js";
2
2
  //#region src/email/components.d.ts
3
3
  /** Marks the hidden preview block so the renderer can read it back and the text lane can keep it. */
4
4
  declare const PREHEADER_ATTRIBUTE = "data-samva-preheader";
@@ -9,8 +9,6 @@ interface EmailProps {
9
9
  readonly dir?: "ltr" | "rtl" | undefined;
10
10
  /** Document title; several clients use it as the fallback preview line. */
11
11
  readonly title?: string | undefined;
12
- /** Hidden preview text shown in the inbox list next to the subject. */
13
- readonly preheader?: string | undefined;
14
12
  readonly backgroundColor?: string | undefined;
15
13
  /** Applied to the content cell, where Yahoo and AOL keep body styling. */
16
14
  readonly style?: EmailStyle | undefined;
@@ -19,7 +17,7 @@ interface EmailProps {
19
17
  /** The hidden inbox preview block. Padding characters stop the client borrowing body copy. */
20
18
  declare const preheaderNode: (text: string) => EmailNode;
21
19
  /** 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;
20
+ declare const Email: ({ className, lang, dir, title, backgroundColor, style, children }: EmailProps) => EmailNode;
23
21
  interface SectionProps {
24
22
  /** CSS classes applied to the primitive's content element. */
25
23
  readonly className?: string | undefined;
@@ -33,17 +31,30 @@ interface SectionProps {
33
31
  }
34
32
  /** A full-width band of content, as the single-cell table every client agrees on. */
35
33
  declare const Section: ({ className, align, width, bgcolor, style, tableStyle, children }: SectionProps) => EmailNode;
36
- interface ColumnsProps {
34
+ interface ColumnsProps<Item = never> {
37
35
  /** CSS classes applied to the primitive's content element. */
38
36
  readonly className?: string | undefined;
39
37
  readonly align?: "left" | "center" | "right" | undefined;
40
38
  readonly width?: number | string | undefined;
41
39
  readonly style?: EmailStyle | undefined;
42
- /** `Column` elements; anything else is a content-model error. */
43
- readonly children?: EmailChild;
40
+ /**
41
+ * Repeat the cells for each item: `children` is then a function from an item (and its index in
42
+ * the row) to a `Column`. Without `per` all items share one row.
43
+ */
44
+ readonly each?: readonly Item[] | undefined;
45
+ /** With `each`, the cells in a row; each chunk of items is its own `Columns` table. */
46
+ readonly per?: number | undefined;
47
+ /** `Column` elements, or with `each` a function that returns one. */
48
+ readonly children?: EmailChild | ((item: Item, index: number) => EmailChild);
44
49
  }
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;
50
+ /** The equal share of a row that each of `count` cells takes, whole percent rounded down. */
51
+ declare const equalColumnWidth: (count: number) => string;
52
+ /**
53
+ * A row of side-by-side `Column`s. No flex or grid conversion happens here. With `each` it repeats
54
+ * its cells over a list, `per` to a row, and splits the row equally between cells that state no
55
+ * width.
56
+ */
57
+ declare const Columns: <Item = never>({ className, align, width, style, each, per, children }: ColumnsProps<Item>) => EmailNode;
47
58
  interface ColumnProps {
48
59
  /** CSS classes applied to the primitive's content element. */
49
60
  readonly className?: string | undefined;
@@ -121,5 +132,5 @@ interface LinkProps {
121
132
  /** A text link that opens outside the client and cannot reach back at the opener. */
122
133
  declare const Link: ({ className, href, target, rel, style, children }: LinkProps) => EmailNode;
123
134
  //#endregion
124
- export { Button, ButtonProps, Column, ColumnProps, Columns, ColumnsProps, Divider, DividerProps, Email, EmailProps, Image, ImageProps, Link, LinkProps, PREHEADER_ATTRIBUTE, Section, SectionProps, Spacer, SpacerProps, preheaderNode };
125
- //# sourceMappingURL=components.d.ts.map
135
+ export { Button, ButtonProps, Column, ColumnProps, Columns, ColumnsProps, Divider, DividerProps, Email, EmailProps, Image, ImageProps, Link, LinkProps, PREHEADER_ATTRIBUTE, Section, SectionProps, Spacer, SpacerProps, equalColumnWidth, preheaderNode };
136
+ //# sourceMappingURL=email.d.ts.map
package/dist/email.js ADDED
@@ -0,0 +1,2 @@
1
+ import { a as Email, c as PREHEADER_ATTRIBUTE, d as equalColumnWidth, f as preheaderNode, i as Divider, l as Section, n as Column, o as Image, r as Columns, s as Link, t as Button, u as Spacer } from "./components-BZCqegS8.js";
2
+ export { Button, Column, Columns, Divider, Email, Image, Link, PREHEADER_ATTRIBUTE, Section, Spacer, equalColumnWidth, preheaderNode };
package/dist/fmt.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ //#region src/fmt.d.ts
2
+ declare const DEFAULT_LOCALE = "en-US";
3
+ declare const DEFAULT_TIME_ZONE = "UTC";
4
+ interface FormatContext {
5
+ readonly locale?: string | undefined;
6
+ readonly timeZone?: string | undefined;
7
+ }
8
+ type DateStyle = "short" | "medium" | "long" | "full";
9
+ interface PluralForms {
10
+ readonly zero?: string;
11
+ readonly one?: string;
12
+ readonly two?: string;
13
+ readonly few?: string;
14
+ readonly many?: string;
15
+ readonly other: string;
16
+ }
17
+ interface Fmt {
18
+ money(amount: number, currency: string, locale?: string): string;
19
+ number(value: number, options?: Intl.NumberFormatOptions, locale?: string): string;
20
+ date(iso: string, style?: DateStyle, locale?: string): string;
21
+ time(iso: string, style?: DateStyle, locale?: string): string;
22
+ plural(count: number, forms: PluralForms, locale?: string): string;
23
+ list(values: readonly string[], locale?: string): string;
24
+ }
25
+ declare const FORMATTER_NAMES: readonly ["money", "number", "date", "time", "plural", "list"];
26
+ declare const createFmt: (context?: FormatContext) => Fmt;
27
+ declare const withFormatContext: <T>(context: FormatContext, run: () => T) => T;
28
+ declare const fmt: Fmt;
29
+ declare const callFormatter: (formatter: Fmt, name: string, args: readonly unknown[]) => string;
30
+ //#endregion
31
+ export { DEFAULT_LOCALE, DEFAULT_TIME_ZONE, DateStyle, FORMATTER_NAMES, Fmt, FormatContext, PluralForms, callFormatter, createFmt, fmt, withFormatContext };
32
+ //# sourceMappingURL=fmt.d.ts.map
package/dist/fmt.js ADDED
@@ -0,0 +1,174 @@
1
+ //#region src/fmt.ts
2
+ const DEFAULT_LOCALE = "en-US";
3
+ const DEFAULT_TIME_ZONE = "UTC";
4
+ const FORMATTER_NAMES = [
5
+ "money",
6
+ "number",
7
+ "date",
8
+ "time",
9
+ "plural",
10
+ "list"
11
+ ];
12
+ const CACHE_LIMIT = 200;
13
+ const cache = /* @__PURE__ */ new Map();
14
+ const cached = (kind, locale, options, make) => {
15
+ const key = `${kind}\u0000${locale}\u0000${options === void 0 ? "" : JSON.stringify(options)}`;
16
+ const hit = cache.get(key);
17
+ if (hit !== void 0) return hit;
18
+ const value = make();
19
+ if (cache.size >= CACHE_LIMIT) cache.clear();
20
+ cache.set(key, value);
21
+ return value;
22
+ };
23
+ const assertFinite = (value, what) => {
24
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(`${what} must be a finite number.`);
25
+ };
26
+ const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
27
+ const parseIso = (iso) => {
28
+ if (typeof iso !== "string") throw new TypeError("ISO date must be a string.");
29
+ const date = new Date(DATE_ONLY.test(iso) ? `${iso}T00:00:00Z` : iso);
30
+ if (Number.isNaN(date.getTime())) throw new RangeError(`Cannot parse "${iso}" as an ISO 8601 date.`);
31
+ return date;
32
+ };
33
+ const createFmt = (context = {}) => {
34
+ const defaultLocale = context.locale ?? "en-US";
35
+ const timeZone = context.timeZone ?? "UTC";
36
+ const pick = (locale) => locale ?? defaultLocale;
37
+ return {
38
+ money: (amount, currency, locale) => {
39
+ assertFinite(amount, "money amount");
40
+ const l = pick(locale);
41
+ return cached("money", l, currency, () => new Intl.NumberFormat(l, {
42
+ style: "currency",
43
+ currency
44
+ })).format(amount);
45
+ },
46
+ number: (value, options, locale) => {
47
+ assertFinite(value, "number value");
48
+ const l = pick(locale);
49
+ return cached("number", l, options, () => new Intl.NumberFormat(l, options)).format(value);
50
+ },
51
+ date: (iso, style = "medium", locale) => {
52
+ const d = parseIso(iso);
53
+ const l = pick(locale);
54
+ return cached("date", l, {
55
+ style,
56
+ timeZone
57
+ }, () => new Intl.DateTimeFormat(l, {
58
+ dateStyle: style,
59
+ timeZone
60
+ })).format(d);
61
+ },
62
+ time: (iso, style = "short", locale) => {
63
+ const d = parseIso(iso);
64
+ const l = pick(locale);
65
+ return cached("time", l, {
66
+ style,
67
+ timeZone
68
+ }, () => new Intl.DateTimeFormat(l, {
69
+ timeStyle: style,
70
+ timeZone
71
+ })).format(d);
72
+ },
73
+ plural: (count, forms, locale) => {
74
+ assertFinite(count, "plural count");
75
+ const l = pick(locale);
76
+ return forms[cached("plural", l, void 0, () => new Intl.PluralRules(l)).select(count)] ?? forms.other;
77
+ },
78
+ list: (values, locale) => {
79
+ const l = pick(locale);
80
+ return cached("list", l, void 0, () => new Intl.ListFormat(l, {
81
+ type: "conjunction",
82
+ style: "long"
83
+ })).format(values);
84
+ }
85
+ };
86
+ };
87
+ let ambient = {};
88
+ const withFormatContext = (context, run) => {
89
+ const previous = ambient;
90
+ ambient = context;
91
+ try {
92
+ return run();
93
+ } finally {
94
+ ambient = previous;
95
+ }
96
+ };
97
+ const fmt = {
98
+ money: (a, c, l) => createFmt(ambient).money(a, c, l),
99
+ number: (v, o, l) => createFmt(ambient).number(v, o, l),
100
+ date: (i, s, l) => createFmt(ambient).date(i, s, l),
101
+ time: (i, s, l) => createFmt(ambient).time(i, s, l),
102
+ plural: (c, f, l) => createFmt(ambient).plural(c, f, l),
103
+ list: (v, l) => createFmt(ambient).list(v, l)
104
+ };
105
+ const STYLES = [
106
+ "short",
107
+ "medium",
108
+ "long",
109
+ "full"
110
+ ];
111
+ const PLURAL_KEYS = [
112
+ "zero",
113
+ "one",
114
+ "two",
115
+ "few",
116
+ "many",
117
+ "other"
118
+ ];
119
+ const arity = (name, args, min, max) => {
120
+ if (args.length < min || args.length > max) {
121
+ const expected = min === max ? `${min}` : `${min} to ${max}`;
122
+ throw new TypeError(`${name} takes ${expected} arguments but received ${args.length}.`);
123
+ }
124
+ };
125
+ const str = (name, index, value, optional = false) => {
126
+ if (value === void 0 && optional) return void 0;
127
+ if (typeof value !== "string") throw new TypeError(`${name} argument ${index + 1} must be a string.`);
128
+ return value;
129
+ };
130
+ const num = (name, index, value) => {
131
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(`${name} argument ${index + 1} must be a finite number.`);
132
+ return value;
133
+ };
134
+ const style = (name, index, value) => {
135
+ if (value === void 0) return void 0;
136
+ if (typeof value !== "string" || !STYLES.includes(value)) throw new TypeError(`${name} argument ${index + 1} must be one of ${STYLES.join(", ")}.`);
137
+ return value;
138
+ };
139
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
140
+ const callFormatter = (formatter, name, args) => {
141
+ switch (name) {
142
+ case "money":
143
+ arity(name, args, 2, 3);
144
+ return formatter.money(num(name, 0, args[0]), str(name, 1, args[1]), str(name, 2, args[2], true));
145
+ case "number": {
146
+ arity(name, args, 1, 3);
147
+ const options = args[1];
148
+ if (options !== void 0 && !isRecord(options)) throw new TypeError("number argument 2 must be an options object.");
149
+ return formatter.number(num(name, 0, args[0]), options, str(name, 2, args[2], true));
150
+ }
151
+ case "date":
152
+ case "time":
153
+ arity(name, args, 1, 3);
154
+ return formatter[name](str(name, 0, args[0]), style(name, 1, args[1]), str(name, 2, args[2], true));
155
+ case "plural": {
156
+ arity(name, args, 2, 3);
157
+ const forms = args[1];
158
+ if (!isRecord(forms) || typeof forms.other !== "string") throw new TypeError("plural argument 2 must be an object with a string `other` form.");
159
+ for (const key of PLURAL_KEYS) if (forms[key] !== void 0 && typeof forms[key] !== "string") throw new TypeError(`plural argument 2 form \`${key}\` must be a string.`);
160
+ return formatter.plural(num(name, 0, args[0]), forms, str(name, 2, args[2], true));
161
+ }
162
+ case "list": {
163
+ arity(name, args, 1, 2);
164
+ const values = args[0];
165
+ if (!Array.isArray(values) || values.some((v) => typeof v !== "string")) throw new TypeError("list argument 1 must be an array of strings.");
166
+ return formatter.list(values, str(name, 1, args[1], true));
167
+ }
168
+ default: throw new TypeError(`Unknown formatter "${name}".`);
169
+ }
170
+ };
171
+ //#endregion
172
+ export { DEFAULT_LOCALE, DEFAULT_TIME_ZONE, FORMATTER_NAMES, callFormatter, createFmt, fmt, withFormatContext };
173
+
174
+ //# sourceMappingURL=fmt.js.map
@@ -0,0 +1,2 @@
1
+ import { i as TEMPLATE_ID_PATTERN, o as TemplateInput, r as SmlTemplate, s as defineTemplate, t as EmailChannel } from "./template-DMPwxMSq.js";
2
+ export { type EmailChannel, type SmlTemplate, TEMPLATE_ID_PATTERN, type TemplateInput, defineTemplate };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { r as defineTemplate, t as TEMPLATE_ID_PATTERN } from "./template-zLUjcwfF.js";
2
+ export { TEMPLATE_ID_PATTERN, defineTemplate };