@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
@@ -0,0 +1,35 @@
1
+ import { C as isUrlAttribute, S as emailElement, _ as EmailGlobalProps, b as EmailStyle, g as EmailElementSpec, h as EmailAttributeSpec, m as EMAIL_GLOBAL_ATTRIBUTES, p as EMAIL_ELEMENTS, r as EmailNode, v as EmailIntrinsicElements, x as EmailTag, y as EmailLayout } from "./jsx-runtime-ylIOnaSf.js";
2
+ import { $ as IrWhatsApp, A as emailAuthoringTarget, B as IrElement, D as EmittedPosition, E as EmailElementSelection, F as emailSelections, G as IrPredicate, H as IrFormatter, I as renderIrPreview, J as IrRawPart, K as IrPreheader, L as IrArithmetic, M as emailSelectionAncestry, N as emailSelectionIndex, O as INSTANCE_PATH_ATTRIBUTE, P as emailSelectionSiblings, Q as IrValue, R as IrComparison, U as IrIf, V as IrEmail, W as IrNode, X as IrSource, Y as IrSms, Z as IrStyle, a as renderEmailContent, at as RenderedPosition, c as checkAttribute, ct as TemplateIr, d as escapeText, et as IrWhatsAppButton, f as kebab, i as compileEmail, it as RenderedIrWhatsApp, j as emailDefinitionInstances, k as IrPreview, l as declarationValue, m as serializeStyle, n as EmailCompileOutput, nt as RenderOptions, o as EmailHtmlOutput, ot as RenderedWhatsAppButton, p as serializeEmailHtml, q as IrRaw, r as RenderedEmail, rt as RenderedIrEmail, s as SerializeEmailOptions, st as SML_IR_VERSION, t as EMAIL_DOCTYPE, tt as IrWhatsAppButtonNode, u as escapeAttribute, z as IrEach } from "./render-DQKz4Aco.js";
3
+ //#region src/render-ir.d.ts
4
+ interface IrRenderDiagnostic {
5
+ readonly code: string;
6
+ readonly message: string;
7
+ }
8
+ declare class IrRenderError extends Error {
9
+ readonly diagnostics: readonly IrRenderDiagnostic[];
10
+ constructor(diagnostics: readonly IrRenderDiagnostic[]);
11
+ }
12
+ /** Render the email channel of a compiled template against one validated input. */
13
+ declare const renderIr: (ir: TemplateIr, input: unknown, options?: RenderOptions) => RenderedIrEmail;
14
+ /** Render the SMS channel of a compiled template to plain text. */
15
+ declare const renderIrSms: (ir: TemplateIr, input: unknown, options?: RenderOptions) => string;
16
+ /** Render the WhatsApp channel of a compiled template: every text rendered, conditional buttons resolved. */
17
+ declare const renderIrWhatsApp: (ir: TemplateIr, input: unknown, options?: RenderOptions) => RenderedIrWhatsApp;
18
+ //#endregion
19
+ //#region src/email/text.d.ts
20
+ /** Derive the plain-text alternative from the semantic tree in reading order. */
21
+ declare const deriveEmailText: (node: EmailNode) => string;
22
+ //#endregion
23
+ //#region src/sms-segments.d.ts
24
+ /** The encoding a message needs: GSM-7 when every character fits, UCS-2 otherwise. */
25
+ type SmsEncoding = "gsm7" | "ucs2";
26
+ interface SmsSegmentInfo {
27
+ readonly encoding: SmsEncoding;
28
+ readonly characterCount: number;
29
+ readonly segmentCount: number;
30
+ }
31
+ declare const smsSegmentInfo: (text: string) => SmsSegmentInfo;
32
+ declare const hasSmsOptOut: (text: string) => boolean;
33
+ //#endregion
34
+ export { EMAIL_DOCTYPE, EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, EmailAttributeSpec, EmailCompileOutput, EmailElementSelection, EmailElementSpec, EmailGlobalProps, EmailHtmlOutput, EmailIntrinsicElements, EmailLayout, EmailStyle, EmailTag, EmittedPosition, INSTANCE_PATH_ATTRIBUTE, IrArithmetic, IrComparison, IrEach, IrElement, IrEmail, IrFormatter, IrIf, IrNode, IrPredicate, IrPreheader, IrPreview, IrRaw, IrRawPart, IrRenderDiagnostic, IrRenderError, IrSms, IrSource, IrStyle, IrValue, IrWhatsApp, IrWhatsAppButton, IrWhatsAppButtonNode, RenderOptions, RenderedEmail, RenderedIrEmail, RenderedIrWhatsApp, RenderedPosition, RenderedWhatsAppButton, SML_IR_VERSION, SerializeEmailOptions, SmsEncoding, SmsSegmentInfo, TemplateIr, checkAttribute, compileEmail, declarationValue, deriveEmailText, emailAuthoringTarget, emailDefinitionInstances, emailElement, emailSelectionAncestry, emailSelectionIndex, emailSelectionSiblings, emailSelections, escapeAttribute, escapeText, hasSmsOptOut, isUrlAttribute, kebab, renderEmailContent, renderIr, renderIrPreview, renderIrSms, renderIrWhatsApp, serializeEmailHtml, serializeStyle, smsSegmentInfo };
35
+ //# sourceMappingURL=render.d.ts.map
package/dist/render.js ADDED
@@ -0,0 +1,49 @@
1
+ import { C as isUrlAttribute, S as emailElement, _ as renderIr, a as kebab, b as EMAIL_ELEMENTS, c as INSTANCE_PATH_ATTRIBUTE, d as emailSelectionAncestry, f as emailSelectionIndex, g as IrRenderError, h as renderIrPreview, i as escapeText, l as emailAuthoringTarget, m as emailSelections, n as declarationValue, o as serializeEmailHtml, p as emailSelectionSiblings, r as escapeAttribute, s as serializeStyle, t as checkAttribute, u as emailDefinitionInstances, v as renderIrSms, x as EMAIL_GLOBAL_ATTRIBUTES, y as renderIrWhatsApp } from "./html-DjPxwjLi.js";
2
+ import { t as SML_IR_VERSION } from "./ir-De6pTH51.js";
3
+ import { i as deriveEmailText, n as compileEmail, r as renderEmailContent, t as EMAIL_DOCTYPE } from "./render-D2ht57ZZ.js";
4
+ //#region src/sms-segments.ts
5
+ const GSM7_EXTENDED = /* @__PURE__ */ new Set([
6
+ "[",
7
+ "]",
8
+ "{",
9
+ "}",
10
+ "\\",
11
+ "~",
12
+ "|",
13
+ "€",
14
+ "^",
15
+ "\f"
16
+ ]);
17
+ const GSM7_BASIC_PATTERN = /^[@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&'()*+,\-./:;<=>?¡0-9ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà]*$/;
18
+ const containsNonGsmCharacters = (text) => {
19
+ for (const char of text) {
20
+ if (GSM7_EXTENDED.has(char)) continue;
21
+ if (!GSM7_BASIC_PATTERN.test(char)) return true;
22
+ }
23
+ return false;
24
+ };
25
+ const smsSegmentInfo = (text) => {
26
+ if (containsNonGsmCharacters(text)) {
27
+ const codePoints = [...text].length;
28
+ const segmentCount = codePoints <= 70 ? 1 : Math.ceil(codePoints / 67);
29
+ return {
30
+ encoding: "ucs2",
31
+ characterCount: text.length,
32
+ segmentCount
33
+ };
34
+ }
35
+ let encodedLength = 0;
36
+ for (const char of text) encodedLength += GSM7_EXTENDED.has(char) ? 2 : 1;
37
+ const segmentCount = encodedLength <= 160 ? 1 : Math.ceil(encodedLength / 153);
38
+ return {
39
+ encoding: "gsm7",
40
+ characterCount: text.length,
41
+ segmentCount
42
+ };
43
+ };
44
+ const SMS_OPT_OUT_PATTERN = /\b(stop|unsubscribe|opt[\s-]?out|cancel|quit)\b/i;
45
+ const hasSmsOptOut = (text) => SMS_OPT_OUT_PATTERN.test(text);
46
+ //#endregion
47
+ export { EMAIL_DOCTYPE, EMAIL_ELEMENTS, EMAIL_GLOBAL_ATTRIBUTES, INSTANCE_PATH_ATTRIBUTE, IrRenderError, SML_IR_VERSION, checkAttribute, compileEmail, declarationValue, deriveEmailText, emailAuthoringTarget, emailDefinitionInstances, emailElement, emailSelectionAncestry, emailSelectionIndex, emailSelectionSiblings, emailSelections, escapeAttribute, escapeText, hasSmsOptOut, isUrlAttribute, kebab, renderEmailContent, renderIr, renderIrPreview, renderIrSms, renderIrWhatsApp, serializeEmailHtml, serializeStyle, smsSegmentInfo };
48
+
49
+ //# sourceMappingURL=render.js.map
package/dist/sms.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { r as EmailNode, t as EmailChild } from "./jsx-runtime-ylIOnaSf.js";
1
2
  import { t as SmsCategory } from "./channel-specs-C2feJwuP.js";
2
- import { f as EmailChild, m as EmailNode } from "./elements-cqldpaJt.js";
3
3
  //#region src/sms.d.ts
4
4
  interface SmsProps {
5
5
  readonly category?: SmsCategory | undefined;
package/dist/sms.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Fragment, jsx } from "./email/jsx-runtime.js";
1
+ import { a as jsx, n as Fragment } from "./jsx-runtime-CBlexoeR.js";
2
2
  //#region src/sms.ts
3
3
  /**
4
4
  * The root of an SMS body: plain text with bindings, conditionals and formatters. The compiler
@@ -1,4 +1,4 @@
1
- import { m as EmailNode } from "./elements-cqldpaJt.js";
1
+ import { r as EmailNode } from "./jsx-runtime-ylIOnaSf.js";
2
2
  import { r as InputSchema } from "./input-schema-7dPFVvNE.js";
3
3
  import { StandardJSONSchemaV1 } from "@standard-schema/spec";
4
4
  //#region src/template.d.ts
@@ -62,4 +62,4 @@ declare const defineTemplate: <S extends StandardJSONSchemaV1>(definition: {
62
62
  }) => SmlTemplate<StandardJSONSchemaV1.InferInput<S>>;
63
63
  //#endregion
64
64
  export { TEMPLATE_NAME_PATTERN as a, TEMPLATE_ID_PATTERN as i, EmailContent as n, TemplateInput as o, SmlTemplate as r, defineTemplate as s, EmailChannel as t };
65
- //# sourceMappingURL=template-_QE_rQND.d.ts.map
65
+ //# sourceMappingURL=template-DMPwxMSq.d.ts.map
@@ -37,6 +37,6 @@ const defineTemplate = (definition) => {
37
37
  };
38
38
  };
39
39
  //#endregion
40
- export { TEMPLATE_ID_PATTERN, TEMPLATE_NAME_PATTERN, defineTemplate };
40
+ export { TEMPLATE_NAME_PATTERN as n, defineTemplate as r, TEMPLATE_ID_PATTERN as t };
41
41
 
42
- //# sourceMappingURL=template.js.map
42
+ //# sourceMappingURL=template-zLUjcwfF.js.map
@@ -1,5 +1,5 @@
1
- import { Result } from "better-result";
2
1
  import { generate, parse, walk } from "css-tree";
2
+ import { Result } from "better-result";
3
3
  //#region src/email/css-color.ts
4
4
  const clamp = (value, low = 0, high = 1) => value < low ? low : value > high ? high : value;
5
5
  const toGamma = (channel) => channel <= .0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - .055;
@@ -575,7 +575,7 @@ const brandThemeVariables = (brand) => {
575
575
  ...defaults.dark === void 0 ? {} : { [darkVariableName(BRAND_FOREGROUND_VARIABLE)]: defaults.dark }
576
576
  };
577
577
  };
578
- /** The stylesheet Tailwind compiles for `@import "samva:brand"`: `brandThemeVariables` and the font faces. */
578
+ /** The stylesheet Tailwind compiles for the theme's brand import: `brandThemeVariables` and the font faces. */
579
579
  const brandTailwindCss = (brand) => printBrandCss({
580
580
  fontFaces: brand.fontFaces,
581
581
  variables: brandThemeVariables(brand),
@@ -584,4 +584,4 @@ const brandTailwindCss = (brand) => printBrandCss({
584
584
  //#endregion
585
585
  export { brandThemeVariables as a, parseBrandCss as c, formatColor as d, parseColor as f, brandTailwindCss as i, printBrandCss as l, BRAND_FOREGROUND_VARIABLE as n, contrastForeground as o, brandForegroundDefaults as r, darkVariableName as s, BRAND_COLOR_VARIABLE as t, downlevelColors as u };
586
586
 
587
- //# sourceMappingURL=theme-css-hFqcPSar.js.map
587
+ //# sourceMappingURL=theme-css-CEUrDpqq.js.map
@@ -1,5 +1,5 @@
1
+ import { r as EmailNode, t as EmailChild } from "./jsx-runtime-ylIOnaSf.js";
1
2
  import { n as WhatsAppCategory, r as WhatsAppHeaderType } from "./channel-specs-C2feJwuP.js";
2
- import { f as EmailChild, m as EmailNode } from "./elements-cqldpaJt.js";
3
3
  //#region src/whatsapp.d.ts
4
4
  interface WhatsAppProps {
5
5
  readonly name?: string | undefined;
package/dist/whatsapp.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Fragment, jsx } from "./email/jsx-runtime.js";
1
+ import { a as jsx, n as Fragment } from "./jsx-runtime-CBlexoeR.js";
2
2
  //#region src/whatsapp.ts
3
3
  const fragment = (children) => jsx(Fragment, { children });
4
4
  /**
@@ -137,7 +137,7 @@
137
137
  "components": [
138
138
  {
139
139
  "name": "Email",
140
- "import": "@samva/markup/email/components",
140
+ "import": "@samva/markup/email",
141
141
  "props": [
142
142
  {
143
143
  "name": "className",
@@ -181,7 +181,7 @@
181
181
  },
182
182
  {
183
183
  "name": "Section",
184
- "import": "@samva/markup/email/components",
184
+ "import": "@samva/markup/email",
185
185
  "props": [
186
186
  {
187
187
  "name": "className",
@@ -224,7 +224,7 @@
224
224
  },
225
225
  {
226
226
  "name": "Columns",
227
- "import": "@samva/markup/email/components",
227
+ "import": "@samva/markup/email",
228
228
  "props": [
229
229
  {
230
230
  "name": "className",
@@ -269,7 +269,7 @@
269
269
  },
270
270
  {
271
271
  "name": "Column",
272
- "import": "@samva/markup/email/components",
272
+ "import": "@samva/markup/email",
273
273
  "props": [
274
274
  {
275
275
  "name": "className",
@@ -306,7 +306,7 @@
306
306
  },
307
307
  {
308
308
  "name": "Button",
309
- "import": "@samva/markup/email/components",
309
+ "import": "@samva/markup/email",
310
310
  "props": [
311
311
  {
312
312
  "name": "className",
@@ -392,7 +392,7 @@
392
392
  },
393
393
  {
394
394
  "name": "Spacer",
395
- "import": "@samva/markup/email/components",
395
+ "import": "@samva/markup/email",
396
396
  "props": [
397
397
  {
398
398
  "name": "height",
@@ -403,7 +403,7 @@
403
403
  },
404
404
  {
405
405
  "name": "Divider",
406
- "import": "@samva/markup/email/components",
406
+ "import": "@samva/markup/email",
407
407
  "props": [
408
408
  {
409
409
  "name": "className",
@@ -430,7 +430,7 @@
430
430
  },
431
431
  {
432
432
  "name": "Image",
433
- "import": "@samva/markup/email/components",
433
+ "import": "@samva/markup/email",
434
434
  "props": [
435
435
  {
436
436
  "name": "className",
@@ -473,7 +473,7 @@
473
473
  },
474
474
  {
475
475
  "name": "Link",
476
- "import": "@samva/markup/email/components",
476
+ "import": "@samva/markup/email",
477
477
  "props": [
478
478
  {
479
479
  "name": "className",
@@ -1304,7 +1304,7 @@
1304
1304
  },
1305
1305
  {
1306
1306
  "code": "brand-unavailable",
1307
- "summary": "The build has no brand to resolve a samva:brand import.",
1307
+ "summary": "The build has no brand to resolve a brand import.",
1308
1308
  "fix": "Create or select the brand the import names."
1309
1309
  },
1310
1310
  {
@@ -1549,6 +1549,12 @@
1549
1549
  "summary": "The email channel has no subject.",
1550
1550
  "fix": "Add subject: (input) => ...."
1551
1551
  },
1552
+ {
1553
+ "code": "moved-import",
1554
+ "summary": "The file imports an @samva/markup entry that moved.",
1555
+ "fix": "Import email components from \"@samva/markup/email\".",
1556
+ "upgrade": "Replace every import from \"@samva/markup/email/components\" with \"@samva/markup/email\" in every project file, templates and partials alike. The imported names are unchanged; change only the specifier.\n\nCompile each entry and render every declared fixture to confirm the output is unchanged. Resolve errors before requesting one saved version for the whole project, approved by the user; do not publish."
1557
+ },
1552
1558
  {
1553
1559
  "code": "multiple-roots",
1554
1560
  "summary": "The body renders nothing or more than one root.",
@@ -1592,7 +1598,7 @@
1592
1598
  {
1593
1599
  "code": "reserved-attribute",
1594
1600
  "summary": "An attribute is written only by a brand component.",
1595
- "fix": "Render BrandFooter from samva:brand instead of marking an element as the footer."
1601
+ "fix": "Render BrandFooter from the brand import instead of marking an element as the footer."
1596
1602
  },
1597
1603
  {
1598
1604
  "code": "reserved-character",
@@ -1649,7 +1655,7 @@
1649
1655
  {
1650
1656
  "code": "unknown-component",
1651
1657
  "summary": "A component the profile cannot read.",
1652
- "fix": "Import components from @samva/markup/email/components, samva:brand, or the project."
1658
+ "fix": "Import components from @samva/markup/email, the brand import, or the project."
1653
1659
  },
1654
1660
  {
1655
1661
  "code": "unknown-field",
@@ -50,7 +50,7 @@ There is no escape hatch: compute the value where the message is sent and add it
50
50
 
51
51
  ### Email
52
52
 
53
- Import from `@samva/markup/email/components`.
53
+ Import from `@samva/markup/email`.
54
54
 
55
55
  | Prop | Type | Notes |
56
56
  | ------------------ | ---------------- | -------------------------------------------------------------------- |
@@ -64,7 +64,7 @@ Import from `@samva/markup/email/components`.
64
64
 
65
65
  ### Section
66
66
 
67
- Import from `@samva/markup/email/components`.
67
+ Import from `@samva/markup/email`.
68
68
 
69
69
  | Prop | Type | Notes |
70
70
  | ------------- | ------------------------------- | -------------------------------------------------------------------- |
@@ -78,7 +78,7 @@ Import from `@samva/markup/email/components`.
78
78
 
79
79
  ### Columns
80
80
 
81
- Import from `@samva/markup/email/components`.
81
+ Import from `@samva/markup/email`.
82
82
 
83
83
  | Prop | Type | Notes |
84
84
  | ------------ | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -92,7 +92,7 @@ Import from `@samva/markup/email/components`.
92
92
 
93
93
  ### Column
94
94
 
95
- Import from `@samva/markup/email/components`.
95
+ Import from `@samva/markup/email`.
96
96
 
97
97
  | Prop | Type | Notes |
98
98
  | ------------ | ------------------------------- | ------------------------------------------------------- |
@@ -105,7 +105,7 @@ Import from `@samva/markup/email/components`.
105
105
 
106
106
  ### Button
107
107
 
108
- Import from `@samva/markup/email/components`.
108
+ Import from `@samva/markup/email`.
109
109
 
110
110
  | Prop | Type | Notes |
111
111
  | ------------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -127,7 +127,7 @@ Import from `@samva/markup/email/components`.
127
127
 
128
128
  ### Spacer
129
129
 
130
- Import from `@samva/markup/email/components`.
130
+ Import from `@samva/markup/email`.
131
131
 
132
132
  | Prop | Type | Notes |
133
133
  | -------- | -------- | ----- |
@@ -135,7 +135,7 @@ Import from `@samva/markup/email/components`.
135
135
 
136
136
  ### Divider
137
137
 
138
- Import from `@samva/markup/email/components`.
138
+ Import from `@samva/markup/email`.
139
139
 
140
140
  | Prop | Type | Notes |
141
141
  | ------------ | ------------ | ------------------------------------------------------- |
@@ -146,7 +146,7 @@ Import from `@samva/markup/email/components`.
146
146
 
147
147
  ### Image
148
148
 
149
- Import from `@samva/markup/email/components`.
149
+ Import from `@samva/markup/email`.
150
150
 
151
151
  | Prop | Type | Notes |
152
152
  | ------------ | ------------------------------- | -------------------------------------------------------------------- |
@@ -160,7 +160,7 @@ Import from `@samva/markup/email/components`.
160
160
 
161
161
  ### Link
162
162
 
163
- Import from `@samva/markup/email/components`.
163
+ Import from `@samva/markup/email`.
164
164
 
165
165
  | Prop | Type | Notes |
166
166
  | ------------ | ------------ | ------------------------------------------------------- |
@@ -249,7 +249,7 @@ Global attributes: `id`, `title`, `lang`, `dir`, `role`.
249
249
  | Code | Meaning | Fix |
250
250
  | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
251
251
  | `brand-import-conflict` | The project imports two different brands. | Import one brand specifier everywhere. |
252
- | `brand-unavailable` | The build has no brand to resolve a samva:brand import. | Create or select the brand the import names. |
252
+ | `brand-unavailable` | The build has no brand to resolve a brand import. | Create or select the brand the import names. |
253
253
  | `button-dynamic-label` | A Button label is read at render time, so classic Outlook cannot size it. | Give the button a width: <Button width={200}>. |
254
254
  | `button-outlook-fallback` | Classic Outlook needs a height and a plain string label to draw the button. | Give <Button> a height and a string label. |
255
255
  | `caniemail/unknown-coverage` | A feature has no client-support data. | Verify it in the target clients. |
@@ -297,6 +297,7 @@ Global attributes: `id`, `title`, `lang`, `dir`, `role`.
297
297
  | `missing-head` | Styles that cannot be inlined need a <head> to live in. | Wrap the message in <Email>, or write those declarations inline. |
298
298
  | `missing-schema` | The template declares no input schema. | Add schema: jsonSchema<Input>({ ... }). |
299
299
  | `missing-subject` | The email channel has no subject. | Add subject: (input) => .... |
300
+ | `moved-import` | The file imports an @samva/markup entry that moved. | Import email components from "@samva/markup/email". |
300
301
  | `multiple-roots` | The body renders nothing or more than one root. | Wrap the body in a single element such as <Email>. |
301
302
  | `nesting-limit` | The template nests deeper than the compiler reads. | Flatten the structure. |
302
303
  | `no-channel` | The template declares no channel body. | Add an email body. |
@@ -305,7 +306,7 @@ Global attributes: `id`, `title`, `lang`, `dir`, `role`.
305
306
  | `not-a-function` | A channel field is not a function of the input. | Write (input) => ... in place or declare the function in the project. |
306
307
  | `preheader-without-shell` | A preheader is set but the body has no <Email> shell to hold it. | Wrap the body in <Email>. |
307
308
  | `recursive-partial` | A partial renders itself; partials are inlined at compile time. | Flatten the recursion, or repeat the structure with .map. |
308
- | `reserved-attribute` | An attribute is written only by a brand component. | Render BrandFooter from samva:brand instead of marking an element as the footer. |
309
+ | `reserved-attribute` | An attribute is written only by a brand component. | Render BrandFooter from the brand import instead of marking an element as the footer. |
309
310
  | `reserved-character` | Text contains a private-use character the compiler reserves. | Remove the characters U+E000 to U+E003. |
310
311
  | `reserved-url` | A URL is the unsubscribe placeholder only BrandFooter can write. | Render <BrandFooter /> instead. |
311
312
  | `schema-not-static` | The schema cannot be read without running code. | Write the schema as a literal jsonSchema<Input>({ type: 'object', ... }). |
@@ -314,7 +315,7 @@ Global attributes: `id`, `title`, `lang`, `dir`, `role`.
314
315
  | `tailwind-dynamic-class` | A class list is assembled at run time. | Write the classes literally. |
315
316
  | `too-many-class-variants` | A class list chooses between more literal lists than the compiler resolves. | Split the choice into fewer conditions, or move part of it to a partial. |
316
317
  | `unguarded-optional` | An optional field is read outside a guard, so a send without it would render a blank. | Guard it with {input.field && ...}, or make the field required. |
317
- | `unknown-component` | A component the profile cannot read. | Import components from @samva/markup/email/components, samva:brand, or the project. |
318
+ | `unknown-component` | A component the profile cannot read. | Import components from @samva/markup/email, the brand import, or the project. |
318
319
  | `unknown-field` | A binding names a field the schema does not declare. | Add the field to the schema, or bind a field it declares (the message suggests the nearest). |
319
320
  | `unknown-formatter` | fmt.<name> is not a formatter. | Use fmt.money, number, date, time, plural or list. |
320
321
  | `unmatched-class` | A class produced no styles. | Use a class the theme or Tailwind defines, or write the style inline. |
@@ -345,6 +346,12 @@ Explicit text has no email-channel field: plain text is derived from the body. I
345
346
 
346
347
  Convert every affected entry in the project at its existing path, including emails/ entries. Compile each entry, render every declared fixture and inspect the affected output. Resolve errors before requesting one saved version for the whole project, approved by the user; do not publish.
347
348
 
349
+ ### `moved-import`
350
+
351
+ Replace every import from "@samva/markup/email/components" with "@samva/markup/email" in every project file, templates and partials alike. The imported names are unchanged; change only the specifier.
352
+
353
+ Compile each entry and render every declared fixture to confirm the output is unchanged. Resolve errors before requesting one saved version for the whole project, approved by the user; do not publish.
354
+
348
355
  ## Quality bar
349
356
 
350
357
  - Run the check until it reports no errors, then render every fixture.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samva/markup",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Type-safe authoring and compilation primitives for Samva templates",
5
5
  "keywords": [
6
6
  "email",
@@ -31,6 +31,7 @@
31
31
  "skills",
32
32
  "package.json",
33
33
  "README.md",
34
+ "CHANGELOG.md",
34
35
  "AGENTS.md",
35
36
  "LICENSE"
36
37
  ],
@@ -41,18 +42,21 @@
41
42
  "types": "./dist/index.d.ts",
42
43
  "import": "./dist/index.js"
43
44
  },
44
- "./package.json": "./package.json",
45
- "./static": {
46
- "types": "./dist/static.d.ts",
47
- "import": "./dist/static.js"
45
+ "./email": {
46
+ "types": "./dist/email.d.ts",
47
+ "import": "./dist/email.js"
48
48
  },
49
- "./ir": {
50
- "types": "./dist/ir.d.ts",
51
- "import": "./dist/ir.js"
49
+ "./email/jsx-runtime": {
50
+ "types": "./dist/email/jsx-runtime.d.ts",
51
+ "import": "./dist/email/jsx-runtime.js"
52
52
  },
53
- "./render-ir": {
54
- "types": "./dist/render-ir.d.ts",
55
- "import": "./dist/render-ir.js"
53
+ "./email/jsx-dev-runtime": {
54
+ "types": "./dist/email/jsx-dev-runtime.d.ts",
55
+ "import": "./dist/email/jsx-dev-runtime.js"
56
+ },
57
+ "./fmt": {
58
+ "types": "./dist/fmt.d.ts",
59
+ "import": "./dist/fmt.js"
56
60
  },
57
61
  "./sms": {
58
62
  "types": "./dist/sms.d.ts",
@@ -62,103 +66,36 @@
62
66
  "types": "./dist/whatsapp.d.ts",
63
67
  "import": "./dist/whatsapp.js"
64
68
  },
65
- "./fmt": {
66
- "types": "./dist/fmt.d.ts",
67
- "import": "./dist/fmt.js"
69
+ "./input-schema": {
70
+ "types": "./dist/input-schema.d.ts",
71
+ "import": "./dist/input-schema.js"
68
72
  },
69
73
  "./compiler": {
70
74
  "types": "./dist/compiler.d.ts",
71
75
  "import": "./dist/compiler.js"
72
76
  },
73
- "./sms-segments": {
74
- "types": "./dist/sms-segments.d.ts",
75
- "import": "./dist/sms-segments.js"
76
- },
77
- "./diagnostic-codes": {
78
- "types": "./dist/diagnostic-codes.d.ts",
79
- "import": "./dist/diagnostic-codes.js"
80
- },
81
77
  "./diagnostics": {
82
78
  "types": "./dist/diagnostics.d.ts",
83
79
  "import": "./dist/diagnostics.js"
84
80
  },
85
- "./source-locations": {
86
- "types": "./dist/source-locations.d.ts",
87
- "import": "./dist/source-locations.js"
88
- },
89
- "./theme-css": {
90
- "types": "./dist/theme-css.d.ts",
91
- "import": "./dist/theme-css.js"
81
+ "./render": {
82
+ "types": "./dist/render.d.ts",
83
+ "import": "./dist/render.js"
92
84
  },
93
- "./contract.json": "./generated/contract.json",
94
- "./generated/*": "./generated/*",
95
- "./input-schema": {
96
- "types": "./dist/input-schema.d.ts",
97
- "import": "./dist/input-schema.js"
85
+ "./edit": {
86
+ "types": "./dist/edit.d.ts",
87
+ "import": "./dist/edit.js"
98
88
  },
99
- "./template": {
100
- "types": "./dist/template.d.ts",
101
- "import": "./dist/template.js"
102
- },
103
- "./email/jsx-runtime": {
104
- "types": "./dist/email/jsx-runtime.d.ts",
105
- "import": "./dist/email/jsx-runtime.js"
106
- },
107
- "./email/jsx-dev-runtime": {
108
- "types": "./dist/email/jsx-dev-runtime.d.ts",
109
- "import": "./dist/email/jsx-dev-runtime.js"
110
- },
111
- "./email/render": {
112
- "types": "./dist/email/render.d.ts",
113
- "import": "./dist/email/render.js"
114
- },
115
- "./email/elements": {
116
- "types": "./dist/email/elements.d.ts",
117
- "import": "./dist/email/elements.js"
118
- },
119
- "./email/components": {
120
- "types": "./dist/email/components.d.ts",
121
- "import": "./dist/email/components.js"
122
- },
123
- "./email/diagnostics": {
124
- "types": "./dist/email/diagnostics.d.ts",
125
- "import": "./dist/email/diagnostics.js"
126
- },
127
- "./email/assets": {
128
- "types": "./dist/email/assets.d.ts",
129
- "import": "./dist/email/assets.js"
130
- },
131
- "./channel-edit": {
132
- "types": "./dist/channel-edit.d.ts",
133
- "import": "./dist/channel-edit.js"
134
- },
135
- "./source-edit": {
136
- "types": "./dist/source-edit.d.ts",
137
- "import": "./dist/source-edit.js"
138
- },
139
- "./preview": {
140
- "types": "./dist/preview.d.ts",
141
- "import": "./dist/preview.js"
142
- },
143
- "./email/html": {
144
- "types": "./dist/email/html.d.ts",
145
- "import": "./dist/email/html.js"
146
- },
147
- "./email/text": {
148
- "types": "./dist/email/text.d.ts",
149
- "import": "./dist/email/text.js"
89
+ "./brand": {
90
+ "types": "./dist/brand.d.ts",
91
+ "import": "./dist/brand.js"
150
92
  },
151
93
  "./samva-brand": {
152
94
  "types": "./samva-brand.d.ts"
153
95
  },
154
- "./email/brand-footer": {
155
- "types": "./dist/email/brand-footer.d.ts",
156
- "import": "./dist/email/brand-footer.js"
157
- },
158
- "./email/brand": {
159
- "types": "./dist/email/brand.d.ts",
160
- "import": "./dist/email/brand.js"
161
- }
96
+ "./contract.json": "./generated/contract.json",
97
+ "./reference.md": "./generated/reference.md",
98
+ "./package.json": "./package.json"
162
99
  },
163
100
  "publishConfig": {
164
101
  "access": "public"
@@ -170,46 +107,26 @@
170
107
  "codegen:tailwind": "bun run scripts/codegen-tailwind.ts && oxfmt src/email/tailwind-stylesheets.gen.ts",
171
108
  "codegen:contract": "bun run scripts/generate-contract.ts",
172
109
  "codegen:docs": "bun run scripts/codegen-docs.ts",
173
- "test": "vitest run --root ../.. --project packages packages/markup/tests",
110
+ "test": "vitest run",
174
111
  "typecheck": "tsc --noEmit && tsc --noEmit -p tests/consumer/tsconfig.json"
175
112
  },
176
113
  "dependencies": {
114
+ "@babel/parser": "^8.0.4",
177
115
  "@cfworker/json-schema": "4.1.1",
178
116
  "@standard-schema/spec": "1.1.0",
179
- "better-result": "3.0.1"
117
+ "better-result": "3.0.1",
118
+ "caniemail": "2.0.2",
119
+ "css-tree": "3.2.1",
120
+ "tailwindcss": "^4.3.3"
180
121
  },
181
122
  "devDependencies": {
182
- "@babel/parser": "^8.0.4",
183
123
  "@css-inline/css-inline-wasm": "0.15.0",
184
- "@effect/vitest": "4.0.0-rc.117",
124
+ "@effect/vitest": "4.0.0",
185
125
  "@types/css-tree": "3.2.0",
186
- "caniemail": "2.0.2",
187
- "css-tree": "3.2.1",
188
- "effect": "4.0.0-rc.117",
189
- "tailwindcss": "^4.3.3",
126
+ "effect": "4.0.0",
190
127
  "tsdown": "^0.22.13",
191
128
  "typescript": "^7.0.2",
192
- "vitest": "^4.1.11",
129
+ "vitest": "^5.0.3",
193
130
  "zod": "4.6.5"
194
- },
195
- "peerDependencies": {
196
- "@babel/parser": "^8.0.4",
197
- "caniemail": "2.0.2",
198
- "css-tree": "3.2.1",
199
- "tailwindcss": "^4.3.3"
200
- },
201
- "peerDependenciesMeta": {
202
- "@babel/parser": {
203
- "optional": true
204
- },
205
- "caniemail": {
206
- "optional": true
207
- },
208
- "css-tree": {
209
- "optional": true
210
- },
211
- "tailwindcss": {
212
- "optional": true
213
- }
214
131
  }
215
132
  }