@samva/markup 0.9.0 → 0.11.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 (92) hide show
  1. package/AGENTS.md +53 -41
  2. package/CHANGELOG.md +379 -0
  3. package/README.md +6 -6
  4. package/dist/assets-B0yseju_.d.ts +115 -0
  5. package/dist/brand-DTctcDmf.js +202 -0
  6. package/dist/brand-plugin-CHhcei-j.d.ts +32 -0
  7. package/dist/{theme-css.d.ts → brand.d.ts} +15 -4
  8. package/dist/brand.js +4 -0
  9. package/dist/compiler.d.ts +236 -18
  10. package/dist/compiler.js +1315 -13
  11. package/dist/{email/components.js → components-Bl6DT21n.js} +4 -4
  12. package/dist/diagnostic-model-DJtqbETd.js +38 -0
  13. package/dist/diagnostic-model-DxthUZBT.d.ts +31 -0
  14. package/dist/{email/diagnostics.js → diagnostics-CnKFefKz.js} +2 -2
  15. package/dist/diagnostics.d.ts +406 -27
  16. package/dist/diagnostics.js +402 -34
  17. package/dist/edit.d.ts +234 -0
  18. package/dist/{channel-edit.js → edit.js} +341 -3
  19. package/dist/email/jsx-dev-runtime.d.ts +1 -1
  20. package/dist/email/jsx-dev-runtime.js +1 -2
  21. package/dist/email/jsx-runtime.d.ts +1 -1
  22. package/dist/email/jsx-runtime.js +1 -85
  23. package/dist/{email/components.d.ts → email.d.ts} +2 -2
  24. package/dist/email.js +2 -0
  25. package/dist/html-DjPxwjLi.js +1637 -0
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/{cascade-t6kxlgEI.js → ir-De6pTH51.js} +8 -4
  29. package/dist/jsx-runtime-CBlexoeR.js +98 -0
  30. package/dist/{elements-cqldpaJt.d.ts → jsx-runtime-ylIOnaSf.d.ts} +74 -74
  31. package/dist/{profile-BH-OtdDA.js → profile-PUfi3GPH.js} +166 -32
  32. package/dist/{email/render.js → render-D2ht57ZZ.js} +103 -8
  33. package/dist/render-DQKz4Aco.d.ts +548 -0
  34. package/dist/render.d.ts +35 -0
  35. package/dist/render.js +49 -0
  36. package/dist/sms.d.ts +1 -1
  37. package/dist/sms.js +1 -1
  38. package/dist/{template-_QE_rQND.d.ts → template-DMPwxMSq.d.ts} +2 -2
  39. package/dist/{template.js → template-zLUjcwfF.js} +2 -2
  40. package/dist/{theme-css-hFqcPSar.js → theme-css-CEUrDpqq.js} +3 -3
  41. package/dist/whatsapp.d.ts +1 -1
  42. package/dist/whatsapp.js +1 -1
  43. package/generated/contract.json +18 -12
  44. package/generated/reference.md +19 -12
  45. package/package.json +39 -122
  46. package/samva-brand.d.ts +4 -4
  47. package/skills/sml/SKILL.md +2 -2
  48. package/dist/assets-C5duwTya.d.ts +0 -40
  49. package/dist/brand-B-0bN_Ir.d.ts +0 -88
  50. package/dist/channel-edit.d.ts +0 -121
  51. package/dist/channel-specs-B6M_HlaV.js +0 -29
  52. package/dist/compatibility-DbISoFIq.js +0 -589
  53. package/dist/css-BVQKICKC.d.ts +0 -109
  54. package/dist/diagnostic-codes.d.ts +0 -403
  55. package/dist/diagnostic-codes.js +0 -399
  56. package/dist/email/assets.d.ts +0 -2
  57. package/dist/email/assets.js +0 -63
  58. package/dist/email/brand-footer.d.ts +0 -34
  59. package/dist/email/brand-footer.js +0 -63
  60. package/dist/email/brand.d.ts +0 -2
  61. package/dist/email/brand.js +0 -148
  62. package/dist/email/diagnostics.d.ts +0 -2
  63. package/dist/email/elements.d.ts +0 -2
  64. package/dist/email/elements.js +0 -299
  65. package/dist/email/html.d.ts +0 -2
  66. package/dist/email/html.js +0 -321
  67. package/dist/email/render.d.ts +0 -40
  68. package/dist/email/text.d.ts +0 -7
  69. package/dist/email/text.js +0 -100
  70. package/dist/html-BJepOwZ4.d.ts +0 -56
  71. package/dist/ir-aaqNE987.d.ts +0 -252
  72. package/dist/ir.d.ts +0 -2
  73. package/dist/ir.js +0 -7
  74. package/dist/preview-Ekdg1dXG.d.ts +0 -100
  75. package/dist/preview.d.ts +0 -2
  76. package/dist/preview.js +0 -160
  77. package/dist/render-ir.d.ts +0 -19
  78. package/dist/render-ir.js +0 -826
  79. package/dist/sms-segments.d.ts +0 -13
  80. package/dist/sms-segments.js +0 -46
  81. package/dist/source-edit.d.ts +0 -116
  82. package/dist/source-edit.js +0 -343
  83. package/dist/source-locations.d.ts +0 -2
  84. package/dist/source-locations.js +0 -16
  85. package/dist/static.d.ts +0 -57
  86. package/dist/static.js +0 -69
  87. package/dist/tailwind-CMYpZf1v.js +0 -614
  88. package/dist/template.d.ts +0 -2
  89. package/dist/theme-css.js +0 -2
  90. package/dist/theme-imports-lvBw3AD1.js +0 -109
  91. package/dist/transform-Ct2OMkFN.d.ts +0 -153
  92. package/dist/unsubscribe-link-CoesnQDU.js +0 -26
package/samva-brand.d.ts CHANGED
@@ -4,11 +4,11 @@
4
4
  // `"types": ["@samva/markup/samva-brand"]` to the project's tsconfig.
5
5
 
6
6
  declare module "samva:brand" {
7
- export const BrandLogo: import("@samva/markup/email/brand").BrandComponents["BrandLogo"];
8
- export const BrandFooter: import("@samva/markup/email/brand").BrandComponents["BrandFooter"];
7
+ export const BrandLogo: import("@samva/markup/brand").BrandComponents["BrandLogo"];
8
+ export const BrandFooter: import("@samva/markup/brand").BrandComponents["BrandFooter"];
9
9
  }
10
10
 
11
11
  declare module "samva:brand/*" {
12
- export const BrandLogo: import("@samva/markup/email/brand").BrandComponents["BrandLogo"];
13
- export const BrandFooter: import("@samva/markup/email/brand").BrandComponents["BrandFooter"];
12
+ export const BrandLogo: import("@samva/markup/brand").BrandComponents["BrandLogo"];
13
+ export const BrandFooter: import("@samva/markup/brand").BrandComponents["BrandFooter"];
14
14
  }
@@ -23,7 +23,7 @@ samva templates dev # local editor with every fixture re
23
23
 
24
24
  Add `--json` for diagnostics as data: each has a `code`, a location, a severity and a `fix`. Apply
25
25
  the fix the diagnostic names rather than rewriting around it. Without the CLI, call
26
- `compileTemplate` from `@samva/markup/static` and `renderIr` from `@samva/markup/render-ir`.
26
+ `compileTemplate` from `@samva/markup/compiler` and `renderIr` from `@samva/markup/render`.
27
27
 
28
28
  ## Upgrades
29
29
 
@@ -36,7 +36,7 @@ fixtures before saving the project.
36
36
 
37
37
  ```tsx
38
38
  import { defineTemplate } from "@samva/markup";
39
- import { Email } from "@samva/markup/email/components";
39
+ import { Email } from "@samva/markup/email";
40
40
  import { fmt } from "@samva/markup/fmt";
41
41
  import { jsonSchema } from "@samva/markup/input-schema";
42
42
 
@@ -1,40 +0,0 @@
1
- import { r as EmailDiagnostic } from "./diagnostics-B-Gym34R.js";
2
- //#region src/email/assets.d.ts
3
- /** Files a template may import, and what they are served as. */
4
- declare const ASSET_CONTENT_TYPES: Readonly<Record<string, string>>;
5
- interface AssetEntry {
6
- /** Project-relative path the template imported. */
7
- readonly path: string;
8
- /** SHA-256 of the exact bytes, lowercase hex. */
9
- readonly digest: string;
10
- readonly bytes: number;
11
- readonly contentType: string;
12
- /** `<digest><ext>` — the name the asset has under any base. */
13
- readonly fileName: string;
14
- }
15
- interface AssetManifest {
16
- /** Where these assets are served from in this build. */
17
- readonly base: string;
18
- readonly assets: readonly AssetEntry[];
19
- }
20
- /** True when the compiler turns this import into a content-addressed asset. */
21
- declare const isAssetPath: (path: string) => boolean;
22
- /** Address one file by its content. */
23
- declare const assetEntry: (path: string, bytes: Uint8Array) => Promise<AssetEntry>;
24
- /**
25
- * The URL an asset has under a base. The base is a build input: publication
26
- * passes its hosted origin, and a local export passes whatever it will serve
27
- * the exported files from.
28
- */
29
- declare const assetUrl: (entry: AssetEntry, base: string) => string;
30
- /** Record, but never fetch, a URL the template points at. */
31
- declare const isExternalAsset: (reference: string) => boolean;
32
- /**
33
- * Reject an asset base that would produce URLs a client will not load. The
34
- * relative forms are the ones a page on disk resolves against its own
35
- * directory, which is what a local export writes.
36
- */
37
- declare const checkAssetBase: (base: string) => readonly EmailDiagnostic[];
38
- //#endregion
39
- export { assetUrl as a, isExternalAsset as c, assetEntry as i, AssetEntry as n, checkAssetBase as o, AssetManifest as r, isAssetPath as s, ASSET_CONTENT_TYPES as t };
40
- //# sourceMappingURL=assets-C5duwTya.d.ts.map
@@ -1,88 +0,0 @@
1
- import { m as EmailNode } from "./elements-cqldpaJt.js";
2
- //#region src/internal/unsubscribe-link.d.ts
3
- /**
4
- * The per-recipient unsubscribe URL is not known at render: the send path
5
- * substitutes each delivery's link for this placeholder, or removes the
6
- * unsubscribe row when the send resolved no unsubscribe group.
7
- */
8
- declare const UNSUBSCRIBE_URL_PLACEHOLDER = "%samva:unsubscribe-url%";
9
- //#endregion
10
- //#region src/email/brand.d.ts
11
- interface EmailBrandAddress {
12
- readonly street1: string;
13
- readonly street2?: string | undefined;
14
- readonly city: string;
15
- readonly region: string;
16
- readonly postalCode: string;
17
- readonly country: string;
18
- }
19
- interface EmailBrandSocialLink {
20
- readonly label: string;
21
- readonly url: string;
22
- }
23
- interface EmailBrandAssets {
24
- readonly logoUrl?: string | undefined;
25
- readonly logoDarkUrl?: string | undefined;
26
- readonly iconUrl?: string | undefined;
27
- }
28
- interface EmailBrandFooter {
29
- readonly companyName?: string | undefined;
30
- readonly address?: EmailBrandAddress | undefined;
31
- readonly socialLinks?: readonly EmailBrandSocialLink[] | undefined;
32
- }
33
- interface EmailBrand {
34
- /** The brand's slug; `samva:brand/<slug>` must name it. */
35
- readonly slug: string;
36
- /** Brand theme CSS in the closed grammar `parseBrandCss` accepts. */
37
- readonly css: string;
38
- readonly assets?: EmailBrandAssets | undefined;
39
- readonly footer?: EmailBrandFooter | undefined;
40
- }
41
- /** Marks the block the send path recognizes as the template's own footer. */
42
- declare const FOOTER_ATTRIBUTE = "data-samva-footer";
43
- /** Marks the footer row that carries the unsubscribe link. */
44
- declare const UNSUBSCRIBE_ROW_ATTRIBUTE = "data-samva-unsubscribe";
45
- /** Every class the brand components use, compiled for any project that imports them. */
46
- declare const BRAND_COMPONENT_CLASSES: readonly ["dark:hidden!", "hidden", "dark:block!", "text-xs", "text-gray-500", "text-center", "font-semibold", "underline"];
47
- interface BrandLogoProps {
48
- /** Rendered width in pixels; the height follows the image. */
49
- readonly width?: number | undefined;
50
- /** Defaults to the brand footer's company name. */
51
- readonly alt?: string | undefined;
52
- readonly align?: "left" | "center" | "right" | undefined;
53
- readonly className?: string | undefined;
54
- }
55
- interface BrandFooterProps {
56
- /** Text of the unsubscribe link. */
57
- readonly unsubscribeLabel?: string | undefined;
58
- readonly className?: string | undefined;
59
- }
60
- interface BrandComponents {
61
- readonly BrandLogo: (props: BrandLogoProps) => EmailNode | null;
62
- readonly BrandFooter: (props: BrandFooterProps) => EmailNode | null;
63
- }
64
- /** Bind `BrandLogo` and `BrandFooter` to one brand. */
65
- declare const brandComponents: (brand: EmailBrand) => BrandComponents;
66
- /** What a rendered message says about the footer it carries. */
67
- interface RenderedFooterMarkers {
68
- /** The message renders `BrandFooter` (or claims to, with the marker). */
69
- readonly footer: boolean;
70
- /** The message carries the unsubscribe placeholder link only `BrandFooter` can write. */
71
- readonly unsubscribeLink: boolean;
72
- }
73
- /** Read the footer markers from rendered HTML. */
74
- declare const renderedFooterMarkers: (html: string) => RenderedFooterMarkers;
75
- /**
76
- * Drop the unsubscribe row from a rendered message, for a send that resolved
77
- * no unsubscribe group: there is no link to put there, so the row goes.
78
- */
79
- declare const withoutUnsubscribeRow: (rendered: {
80
- readonly html?: string | undefined;
81
- readonly text?: string | undefined;
82
- }) => {
83
- readonly html: string | undefined;
84
- readonly text: string | undefined;
85
- };
86
- //#endregion
87
- export { EmailBrand as a, EmailBrandFooter as c, RenderedFooterMarkers as d, UNSUBSCRIBE_ROW_ATTRIBUTE as f, UNSUBSCRIBE_URL_PLACEHOLDER as g, withoutUnsubscribeRow as h, BrandLogoProps as i, EmailBrandSocialLink as l, renderedFooterMarkers as m, BrandComponents as n, EmailBrandAddress as o, brandComponents as p, BrandFooterProps as r, EmailBrandAssets as s, BRAND_COMPONENT_CLASSES as t, FOOTER_ATTRIBUTE as u };
88
- //# sourceMappingURL=brand-B-0bN_Ir.d.ts.map
@@ -1,121 +0,0 @@
1
- import { n as WhatsAppCategory, r as WhatsAppHeaderType, t as SmsCategory } from "./channel-specs-C2feJwuP.js";
2
- import { SourceReplacement } from "./source-edit.js";
3
- //#region src/channel-edit.d.ts
4
- /** A run of body text between two locked segments. It is empty when nothing sits between them. */
5
- interface TextSegment {
6
- readonly kind: "text";
7
- readonly text: string;
8
- /** The source range the text is written back over. */
9
- readonly start: number;
10
- readonly end: number;
11
- }
12
- /** An expression, conditional or element the form does not edit, kept as authored. */
13
- interface LockedSegment {
14
- readonly kind: "locked";
15
- /** The authored source, shortened for display. */
16
- readonly summary: string;
17
- readonly start: number;
18
- readonly end: number;
19
- }
20
- type ChannelSegment = TextSegment | LockedSegment;
21
- /** How an attribute appears on an element. Only a literal is editable. */
22
- type AttributeState = {
23
- readonly kind: "absent";
24
- } | {
25
- readonly kind: "literal";
26
- readonly value: string;
27
- } | {
28
- readonly kind: "expression";
29
- readonly source: string;
30
- };
31
- interface SmsChannelForm {
32
- readonly category: AttributeState;
33
- readonly segments: readonly ChannelSegment[];
34
- /** The input fields the body reads, as dotted paths. */
35
- readonly variables: readonly string[];
36
- }
37
- type WhatsAppButtonKind = "quick-reply" | "url" | "phone" | "copy-code";
38
- type WhatsAppButtonRow = {
39
- readonly kind: "editable";
40
- readonly type: WhatsAppButtonKind;
41
- /** The label, or the copied code for a copy-code button. */
42
- readonly text: string;
43
- readonly url: AttributeState;
44
- readonly phone: AttributeState;
45
- } | {
46
- /** A conditional, or a button whose label reads the input. */
47
- readonly kind: "locked";
48
- readonly summary: string;
49
- };
50
- interface WhatsAppChannelForm {
51
- readonly name: AttributeState;
52
- readonly language: AttributeState;
53
- readonly category: AttributeState;
54
- /** Null when the template has no header. */
55
- readonly header: readonly ChannelSegment[] | null;
56
- readonly headerType: AttributeState;
57
- readonly body: readonly ChannelSegment[];
58
- /** Null when the template has no footer. */
59
- readonly footer: readonly ChannelSegment[] | null;
60
- readonly buttons: readonly WhatsAppButtonRow[];
61
- readonly variables: readonly string[];
62
- }
63
- type ChannelEditResult = {
64
- readonly ok: true;
65
- readonly edits: readonly SourceReplacement[];
66
- } | {
67
- readonly ok: false;
68
- readonly reason: string;
69
- };
70
- type SmsEdit = {
71
- readonly kind: "category";
72
- readonly value: SmsCategory | undefined;
73
- } | {
74
- readonly kind: "text";
75
- readonly segment: number;
76
- readonly text: string;
77
- };
78
- type WhatsAppPart = "header" | "body" | "footer";
79
- type WhatsAppEdit = {
80
- readonly kind: "attribute";
81
- readonly name: "name" | "language" | "category";
82
- readonly value: string | undefined;
83
- } | {
84
- readonly kind: "headerType";
85
- readonly value: WhatsAppHeaderType;
86
- } | {
87
- readonly kind: "text";
88
- readonly part: WhatsAppPart;
89
- readonly segment: number;
90
- readonly text: string;
91
- } | {
92
- readonly kind: "buttonText";
93
- readonly button: number;
94
- readonly text: string;
95
- } | {
96
- readonly kind: "buttonAttribute";
97
- readonly button: number;
98
- readonly name: "url" | "phone";
99
- readonly value: string;
100
- } | {
101
- readonly kind: "buttonType";
102
- readonly button: number;
103
- readonly type: WhatsAppButtonKind;
104
- } | {
105
- readonly kind: "buttonAdd";
106
- readonly type: WhatsAppButtonKind;
107
- } | {
108
- readonly kind: "buttonRemove";
109
- readonly button: number;
110
- };
111
- /** The form model of the template's SMS body, or null when it is not a `<Sms>` written in place. */
112
- declare const readSmsChannel: (source: string) => SmsChannelForm | null;
113
- /** The source replacements that apply one form change to the SMS body. */
114
- declare const editSmsChannel: (source: string, edit: SmsEdit) => ChannelEditResult;
115
- /** The form model of the template's WhatsApp body, or null when it is not a `<WhatsApp>` written in place. */
116
- declare const readWhatsAppChannel: (source: string) => WhatsAppChannelForm | null;
117
- /** The source replacements that apply one form change to the WhatsApp body. */
118
- declare const editWhatsAppChannel: (source: string, edit: WhatsAppEdit) => ChannelEditResult;
119
- //#endregion
120
- export { AttributeState, ChannelEditResult, ChannelSegment, LockedSegment, type SmsCategory, SmsChannelForm, SmsEdit, TextSegment, WhatsAppButtonKind, WhatsAppButtonRow, type WhatsAppCategory, WhatsAppChannelForm, WhatsAppEdit, type WhatsAppHeaderType, WhatsAppPart, editSmsChannel, editWhatsAppChannel, readSmsChannel, readWhatsAppChannel };
121
- //# sourceMappingURL=channel-edit.d.ts.map
@@ -1,29 +0,0 @@
1
- //#region src/channel-specs.ts
2
- const SMS_CATEGORIES = [
3
- "transactional",
4
- "promotional",
5
- "service_implicit"
6
- ];
7
- const WHATSAPP_CATEGORIES = [
8
- "marketing",
9
- "utility",
10
- "authentication"
11
- ];
12
- const WHATSAPP_HEADER_TYPES = [
13
- "text",
14
- "image",
15
- "video",
16
- "document"
17
- ];
18
- /** The attributes `<Sms>` accepts. */
19
- const SMS_ATTRIBUTES = ["category"];
20
- /** The attributes `<WhatsApp>` accepts. */
21
- const WHATSAPP_ATTRIBUTES = [
22
- "name",
23
- "language",
24
- "category"
25
- ];
26
- //#endregion
27
- export { WHATSAPP_HEADER_TYPES as a, WHATSAPP_CATEGORIES as i, SMS_CATEGORIES as n, WHATSAPP_ATTRIBUTES as r, SMS_ATTRIBUTES as t };
28
-
29
- //# sourceMappingURL=channel-specs-B6M_HlaV.js.map