@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
package/AGENTS.md CHANGED
@@ -1,57 +1,118 @@
1
1
  # @samva/markup agent guide
2
2
 
3
- `@samva/markup` is the authoring language and compiler for Samva templates. Email templates are
4
- TSX modules that default-export a `defineEmail` definition and render through a JSX runtime that
5
- lowers to email-safe HTML and plain text. SMS and WhatsApp templates use the structured SML runtime.
6
- The package is plain TypeScript with no application runtime; the local editor, project builds, and
7
- exports live in `@samva/vite`.
3
+ `@samva/markup` is the authoring language and compiler for Samva templates. A template is one TSX
4
+ file in a static profile that default-exports `defineTemplate`: ordinary JSX, HTML and Tailwind that
5
+ a compiler reads without running. The compiler produces a versioned JSON IR, and a pure renderer
6
+ turns the IR and an input into subject, preheader, HTML and text, so nothing executes at send time.
7
+ A body that would compute over its input is a diagnostic, not a second mode: compute the value in
8
+ the caller and send it in the payload. The package is plain TypeScript with no application runtime;
9
+ the local editor, project builds, and exports live in `@samva/vite`.
8
10
 
9
11
  ## Entry points
10
12
 
11
- - `@samva/markup/template` — `defineEmail`, `TemplateDefinition`, `TemplateInput`, and
12
- `TEMPLATE_NAME_PATTERN`.
13
- - `@samva/markup/email` — the JSX runtime. Set `jsxImportSource: "@samva/markup/email"` for email
14
- entries.
15
- - `@samva/markup/email/components` — email primitives (`Email`, `Section`, `Columns`, `Button`,
16
- and the rest of its exports). They generate table layout and classic-Outlook fallbacks.
17
- - `@samva/markup/email/render` — `renderEmail(template, data)`, which validates input and returns
18
- subject, preheader, HTML, text, and the derived tree.
19
- - `@samva/markup/email/diagnostics` — `EmailDiagnostic` and `EmailCompileError`.
20
- - `@samva/markup/email/assets` — `isAssetPath` and `ASSET_CONTENT_TYPES`: which imported files
21
- become content-addressed assets, without loading the compiler.
13
+ Authoring entries are what a template file imports:
14
+
15
+ - `@samva/markup` — `defineTemplate({ id, schema, fixtures, locale?, email?, sms?, whatsapp? })`,
16
+ `SmlTemplate`, `TemplateInput`, and `TEMPLATE_ID_PATTERN` (lowercase kebab-case, the rule the CLI
17
+ and API slugs share). `email` is `{ subject, preheader?, body }`; each is a function of the
18
+ validated input.
19
+ - `@samva/markup/email` — email primitives (`Email`, `Section`, `Columns`, `Button`, and the rest of
20
+ its exports). They generate table layout and classic-Outlook fallbacks. Set
21
+ `jsxImportSource: "@samva/markup/email"`; the runtime is `@samva/markup/email/jsx-runtime`.
22
+ - `@samva/markup/fmt` — `fmt.money`, `number`, `date`, `time`, `plural` and `list`: the only
23
+ functions a body may call.
24
+ - `@samva/markup/sms` and `@samva/markup/whatsapp` — the channel components (`Sms`; `WhatsApp` with
25
+ `WhatsApp.Header`, `Body`, `Footer`, `Buttons`, `UrlButton`, `QuickReplyButton`, `PhoneButton`,
26
+ `CopyCodeButton`). `whatsappTemplate` derives Meta's positional `{{n}}` text.
22
27
  - `@samva/markup/input-schema` — `inputSchema`, which turns any Standard JSON Schema into the
23
28
  portable JSON Schema and validator a template's input is checked against.
24
- - `@samva/markup/compiler` — `compileEmailProject`, the bundler-agnostic compile step. It imports no
25
- Vite, esbuild, or Node builtins, so it runs in any JavaScript host.
26
29
  - `samva:brand` — `BrandLogo` (light logo, swapped for the dark one where the client honors dark
27
30
  mode) and `BrandFooter` (company, postal address, social links and the unsubscribe row the send
28
31
  path fills). The compiler binds them to the brand the build resolves; add
29
32
  `"types": ["@samva/markup/samva-brand"]` to the project's tsconfig for `tsc`. In `theme.css`,
30
33
  `@import "samva:brand";` layers the brand theme; `samva:brand/<slug>` names one brand.
31
- - `jsxImportSource: "@samva/markup"` and `@samva/markup/components` — the structured SMS and
32
- WhatsApp runtime and components. `parseSml` (`@samva/markup/parser`) and `compileSml` /
33
- `compileSource` (`@samva/markup/compile`) work on SML source.
34
34
 
35
- The package's `generated/` directory ships the SML and email language references and agent
36
- contracts; read those before authoring. Import only subpaths declared in `package.json` `exports`.
35
+ Tooling entries are what a host (Vite, the CLI, the editor, the API, the template agent) imports:
36
+
37
+ - `@samva/markup/compiler` — `compileTemplate`, which reads a project's files and returns the IR,
38
+ the fixtures, the assets and the diagnostics; `checkTemplateCompatibility` checks each fixture
39
+ against the client matrix and locates findings at source. `checkStaticProfile(source | files,
40
+ entry?)` is the synchronous structural check: it runs the compiler's lowering without Tailwind, a
41
+ brand or the files an import names, and returns only findings the source itself owns.
42
+ `introducedProfileErrors(before, after)` is what a visual edit is refused on. It also holds the
43
+ compiler's building blocks (`transformProject`, Tailwind, the cascade, CSS), the brand footer and
44
+ sample renders (`renderBrandFooter`, `renderBrandSample`), and `TEMPLATE_NAME_PATTERN`. It imports no Vite, esbuild, or Node builtins, so it runs in any
45
+ JavaScript host.
46
+ - `@samva/markup/diagnostics` — source spans and line maps, the `DIAGNOSTIC_CODES` registry with
47
+ each code's fix and upgrade recipe, and `EmailDiagnostic`/`EmailCompileError`. It does not load
48
+ the compiler, so a host that only reports imports it.
49
+ - `@samva/markup/render` — `renderIr(ir, input, { locale, timeZone })`, `renderIrSms` and
50
+ `renderIrWhatsApp`; the IR types and `SML_IR_VERSION`; `renderIrPreview(ir, input)`, the render an
51
+ editor shows, with an instance path (`INSTANCE_PATH_ATTRIBUTE`) on every element and the
52
+ `selections` that map each one to its TSX span; `compileEmail`, the HTML serializer and text
53
+ derivation; the email element table; SMS segment counts. Its import closure excludes the
54
+ compiler's libraries (`tests/entry-closure.test.ts`): it is the send-time security boundary and
55
+ what the API bundles.
56
+ - `@samva/markup/edit` — the code transforms behind visual edits (`inspectSourceElement`,
57
+ `literalReplacement`, `expressionReplacement`, `classNameEdit`, `structuralReplacements`,
58
+ `applySourceReplacements` with a `ProfileGuard`); form reads and exact edits for the `sms` and
59
+ `whatsapp` channel bodies (`readSmsChannel`, `editSmsChannel`, `readWhatsAppChannel`,
60
+ `editWhatsAppChannel`), where text between expressions is editable and every expression,
61
+ conditional or element is a locked segment; and JSX source locations. Browser-safe: Babel parser
62
+ only.
63
+ - `@samva/markup/brand` — brand records and their CSS model (`parseBrandCss`, `printBrandCss`), the
64
+ footer markers a send reads (`renderedFooterMarkers`, `withoutUnsubscribeRow`), and project
65
+ assets (`isAssetPath`, `ASSET_CONTENT_TYPES`, `assetUrl`): which imported files become
66
+ content-addressed assets. The send path imports it, so its closure holds only the css-tree parser
67
+ `theme.css` needs; rendering a footer compiles Tailwind and lives in `./compiler`.
68
+
69
+ `tests/published-dependencies.test.ts` pins this list. The compiler's libraries (Babel, Tailwind,
70
+ css-tree, caniemail) are dependencies, because a template project depends on this package alone and
71
+ `samva templates check` runs its installed compiler.
72
+
73
+ The package ships what an agent needs to author without this repository:
74
+
75
+ - `@samva/markup/contract.json` (`generated/contract.json`) — components with their props, the
76
+ static-profile forms and the forms it refuses, formatters, HTML elements, channel specs and every
77
+ diagnostic code with its fix. `@samva/markup/reference.md` renders the same contract for reading.
78
+ `bun run codegen:contract` writes both from the modules that own each fact (component and `Fmt`
79
+ interfaces, `PROFILE_FORMS`, `DIAGNOSTIC_CODES`, the element table), and a test fails when they
80
+ drift.
81
+ - `skills/sml/SKILL.md` — the `sml` skill: the write, check, render, look, repair loop, the static
82
+ profile and the data rules, for an agent that edits a template project.
83
+
84
+ Read the contract before authoring. Import only subpaths declared in `package.json` `exports`.
37
85
 
38
86
  ## How you hurt yourself here
39
87
 
88
+ - **Computing in a body.** A body is read, not run. A call other than `fmt.*` and `.map`, a
89
+ statement (`const`, `if`, a loop), an import outside `@samva/markup` and the project, a hook, an
90
+ event handler and `dangerouslySetInnerHTML` are each a diagnostic with a code, a location and a
91
+ fix. Compute the value in the caller and send it in the payload. There is no escape hatch.
92
+ - **Chunking or counting in a body.** `items.reduce`, index arithmetic and `filter` helpers are
93
+ calls the profile refuses. Use `<Columns each={list} per={n}>{(item) => <Column … />}</Columns>`
94
+ for a grid and `.filter(condition)` before `.map` or `.length`; the condition is a `&&` / `?:`
95
+ condition over the item.
96
+ - **Building a class name at run time.** Tailwind reads literal classes. `className={`text-${size}`}`
97
+ is `dynamic-class`; choose between literal lists instead: `input.vip ? "bg-amber-100" : "bg-white"`.
98
+ - **Reading an optional field unguarded.** Binding `input.trackingUrl` outside
99
+ `input.trackingUrl && …` is `unguarded-optional`; a misspelled field is `unknown-field` with the
100
+ nearest match; a fixture that stopped matching the schema is `fixture-invalid`.
101
+ - **Reporting a finding without a registry entry.** `Findings.add` and the lowerer accept only
102
+ codes in `DIAGNOSTIC_CODES` (`src/diagnostic-codes.ts`), which holds each code's meaning and fix.
103
+ Add the entry with the code; the contract and the docs read it.
104
+ - **Putting the subject or preheader on `<Email>`.** They belong to the channel (`email.subject`,
105
+ `email.preheader`); `<Email>` has no `preheader` prop.
40
106
  - **Passing a string where you want markup.** Nothing an author passes as a string becomes markup;
41
107
  strings render as escaped text. There is no raw-HTML escape hatch: compatibility markup comes only
42
108
  from the email primitives.
43
- - **Using an element or attribute the serializer does not allow.** `@samva/markup/email/elements` is
109
+ - **Using an element or attribute the serializer does not allow.** `@samva/markup/render` is
44
110
  the one table behind both the JSX intrinsic prop types and the serializer's allowlist, so an
45
111
  unsupported element or attribute fails at typecheck and again at compile with a source location.
46
112
  - **Naming a template or fixture like a path.** A template id and a fixture key are both written
47
113
  into file paths, so each must match `TEMPLATE_NAME_PATTERN`, one plain path segment.
48
- `defineEmail` throws a `TypeError` where the name is declared. Code that builds a path from these
114
+ `defineTemplate` throws a `TypeError` where the name is declared. Code that builds a path from these
49
115
  names imports the pattern instead of restating it.
50
- - **Reading the clock or randomness in a template.** Samva's hosted render has no ambient clock and
51
- no entropy source: reading the current instant or a random value there throws unless the
52
- definition declares the fixed value in its `runtime` (`TemplateRuntime`). A local render does not
53
- enforce this, so a template that reads `Date.now()` can pass locally and fail once published. Take
54
- times from validated input, or declare them.
55
116
  - **Declaring a webfont as if every client loads it.** A project font is an ordinary `@font-face`
56
117
  in the project's CSS (usually `theme.css`) whose `src` is a `.woff2` file in the project, named
57
118
  by a path relative to that stylesheet; the compiler serves it as a content-addressed asset and
@@ -59,8 +120,6 @@ contracts; read those before authoring. Import only subpaths declared in `packag
59
120
  that names a project font must end in a generic (`sans-serif`, `serif`, `monospace`) or the
60
121
  render fails with `email-font-fallback`. Only WOFF2 is accepted; an `https:` `src` stays an
61
122
  external reference.
62
- - **Treating `renderEmail` as a sandbox.** It executes the template's TypeScript in the calling
63
- process. Run untrusted template source in an isolated host.
64
123
  - **Expecting the schema library to do the validation.** A template's input schema is converted to
65
124
  a portable JSON Schema and validated by that document, not by the library that produced it. A
66
125
  refinement that the converter cannot export is refused, and defaults are never inserted or values
@@ -68,27 +127,29 @@ contracts; read those before authoring. Import only subpaths declared in `packag
68
127
 
69
128
  ## Rules
70
129
 
71
- - **Email entries default-export a `defineEmail` definition** from a `.tsx` file. The definition
72
- owns a stable, project-unique `id`, an input schema, named fixtures, and a synchronous `render`
73
- that receives the validated JSON input unchanged. Helper modules are ordinary imports, not
74
- catalog entries.
75
- - **Email templates have no textual SML form.** The derived semantic tree lowers directly to HTML
76
- and text through `@samva/markup/email/render`; SML is the SMS and WhatsApp language.
77
- - **Structured SML is a closed grammar.** `parseSml` and `compileSml` reject anything outside it
78
- rather than passing it through.
79
- - **Failures are typed.** The SML surface returns a better-result `Result`; branch with
80
- `Result.isOk` / `Result.isErr` and discriminate the `TaggedError` (`SmlParseError`,
81
- `SmlCompileError`) by `_tag`. Email compilation reports `EmailDiagnostic` values: errors throw
82
- `EmailCompileError`, warnings ride back on the render result. A declaration the compiler cannot
130
+ - **Email entries default-export `defineTemplate`** from a `.tsx` file. The definition owns a
131
+ stable, project-unique kebab-case `id`, an input schema, at least one fixture, and one body per
132
+ channel. Helper modules are ordinary imports, not catalog entries; a partial is a function from
133
+ props (and `children`) to JSX that the compiler inlines. A fixture is data: literals, constants
134
+ and imported assets.
135
+ - **The IR is the artifact.** Rendering is a pure function of the IR and the input. The renderer
136
+ escapes per context, applies the serializer's URL and style rules to every bound value, and
137
+ rejects unsafe input rather than sanitizing it.
138
+ - **Failures are typed.** Compilation reports diagnostic values with a code, a location and a fix:
139
+ `compileTemplate` returns them beside the IR, and an error finding leaves no IR. A declaration the compiler cannot
83
140
  accept at all, such as an invalid name or a nonportable input schema, throws a `TypeError`.
84
141
  - **Data models are plain types.** Markup's data models are TypeScript types, not schema
85
142
  declarations, so there is no schema library to adopt to consume them. Unions discriminate on
86
- `type` (an `EmailNode`, an `SmlOp`); only error classes carry `_tag`. The input schema is the one
143
+ `type`; only error classes carry `_tag`. The input schema is the one
87
144
  place a Standard Schema is accepted, and which library produces it is yours to choose.
88
145
 
89
146
  ## Proving your setup
90
147
 
91
148
  - `tsc --noEmit` over the template project catches unsupported elements, attributes, and props.
149
+ - `compileTemplate` reports every static-profile, binding and fixture finding with a source
150
+ location, and `renderIr(compiled.ir, fixture)` proves one fixture's output without executing the
151
+ template.
92
152
  - `samva templates check` (from `@samva/cli`) compiles every entry and renders every fixture,
93
153
  reporting findings with source locations.
94
- - `renderEmail(template, fixture)` in a unit test proves one template's output without a build.
154
+ - `renderIrPreview(compiled.ir, fixture)` returns the same document with the source spans an editor
155
+ selects by.
package/CHANGELOG.md ADDED
@@ -0,0 +1,345 @@
1
+ ## @samva/markup@0.10.0
2
+
3
+ ### Breaking: `@samva/markup` publishes 17 entries in two tiers
4
+
5
+ Template files import `@samva/markup`, `@samva/markup/email`, `@samva/markup/fmt`,
6
+ `@samva/markup/sms`, `@samva/markup/whatsapp` and `@samva/markup/input-schema`. Email components
7
+ move from `@samva/markup/email/components` to `@samva/markup/email`, the entry `jsxImportSource`
8
+ already names. A template that still imports the old path fails with `moved-import`, which names
9
+ the replacement.
10
+
11
+ Hosts import five tooling entries:
12
+
13
+ | Entry | Replaces |
14
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
15
+ | `@samva/markup/compiler` | `./compiler`, `./static`, `./template` (`TEMPLATE_NAME_PATTERN`), `./email/brand-footer` |
16
+ | `@samva/markup/diagnostics` | `./diagnostics`, `./diagnostic-codes`, `./email/diagnostics` |
17
+ | `@samva/markup/render` | `./ir`, `./render-ir`, `./preview`, `./email/render`, `./email/html`, `./email/text`, `./email/elements`, `./sms-segments` |
18
+ | `@samva/markup/edit` | `./source-edit`, `./channel-edit`, `./source-locations` |
19
+ | `@samva/markup/brand` | `./email/brand`, `./email/assets`, `./theme-css` |
20
+
21
+ `@samva/markup/reference.md` replaces `@samva/markup/generated/*`. `tailwindcss`, `css-tree`,
22
+ `caniemail` and `@babel/parser` are dependencies instead of optional peers, so a project that
23
+ depends on `@samva/markup` alone can run `samva templates check`.
24
+
25
+ ## @samva/markup@0.9.0
26
+
27
+ ### Breaking: remove textual email SML APIs
28
+
29
+ `@samva/markup` removes textual email SML components and grammar types, plus the
30
+ `@samva/markup/candidate`, `/classes`, `/checks`, `/model`, `/ops`, `/registry`, and `/tsx-tracer`
31
+ subpaths. Email templates use TSX `defineEmail` modules and lower directly to subject, HTML, and text
32
+ through the email semantic tree. The structured SML language and compiler remain for SMS and
33
+ WhatsApp.
34
+
35
+ `@samva/vite` removes `darkClassCount` from the public `AuthoringValidationSummary` returned by its
36
+ emit API. Email validation no longer reports a count derived from textual email SML classes.
37
+
38
+ ### Breaking: the executing template runtime and the textual SML grammar are removed
39
+
40
+ A template is `defineTemplate` in the static profile, compiled to IR; nothing in `@samva/markup`
41
+ runs a template any more.
42
+
43
+ - **Removed.** `defineEmail`, `isTemplateDefinition`, `TemplateDefinition`, `TemplateRuntime`,
44
+ `renderEmail` and `bindStylesheets`; `compileEmailProject` and the generated entry, reset and
45
+ stylesheet-registry modules (`@samva/markup/email/stylesheets`); the TSX source instrumentation and
46
+ runtime tracing (`@samva/markup/tsx-source-instrumentation`, `@samva/markup/email/selection`); and
47
+ the textual structured SML grammar with its JSX runtime and components
48
+ (`@samva/markup/{ast,components,compile,compile-sms,compile-whatsapp,conditionals,emit,
49
+ interpolate,jsx-runtime,jsx-dev-runtime,lexer,parser,predicate,printer,render-template,variables}`).
50
+ SMS and WhatsApp bodies are the `sms` and `whatsapp` fields of `defineTemplate`, written with
51
+ `Sms` from `@samva/markup/sms` and `WhatsApp` from `@samva/markup/whatsapp`.
52
+ - **`@samva/markup/preview`** adds `renderIrPreview`, which renders a fixture from the IR with an
53
+ instance path on every element and the selection each path resolves to, taken from the source
54
+ spans the compiler recorded. The selection helpers that lived in `email/selection` move here.
55
+ - **`@samva/markup/source-edit`** (moved from `email/source-edit`) is the set of code transforms behind
56
+ visual edits: text, attributes, `className`, and inserting, duplicating, moving and deleting
57
+ elements. `checkStaticProfile` in `@samva/markup/static` refuses an edit that would leave the
58
+ static profile. `@samva/markup/channel-edit` does the same for `sms` and `whatsapp` bodies.
59
+ - **`TemplateInput`** reads the caller input from a template's `schema`.
60
+
61
+ ### Breaking: templates are `defineTemplate` in a static profile
62
+
63
+ `@samva/markup` adds `defineTemplate({ id, schema, fixtures, locale?, email, sms?, whatsapp? })` at
64
+ its root. A template is one TSX file in a static profile that the new compiler reads without running:
65
+ text and attribute bindings, template strings, `&&`, `?:`, comparisons, `||`, `.length`, `.map`,
66
+ `fmt.*` calls, arithmetic inside formatter arguments and conditions, partials with props and
67
+ children, conditional class names, `.filter(condition)` before `.map` or `.length`, and
68
+ `<Columns each per>` for grids (a `Column` without a `width` takes an equal share of its row). Everything else is a compile error with a stable code, a
69
+ `file:line:column` location and a fix.
70
+
71
+ - `@samva/markup/static` compiles a project to a versioned JSON IR (`"sml": 1`) and checks every
72
+ binding against the input schema: `unknown-field` with a did-you-mean, `unguarded-optional`, and
73
+ `fixture-invalid` per fixture. Tailwind, project CSS, brand themes, fonts and assets resolve at
74
+ compile time, and `checkTemplateCompatibility` locates client findings at source.
75
+ - `@samva/markup/render-ir` renders the IR against an input as a pure, dependency-free function.
76
+ It escapes for text, attribute and URL contexts and rejects unsafe bound values.
77
+ - `@samva/markup/fmt` adds the deterministic formatters `money`, `number`, `date`, `time`, `plural`
78
+ and `list`, which take their locale and time zone from the render.
79
+ - `@samva/markup/sms` and `@samva/markup/whatsapp` add channel components with distinct names per
80
+ channel; WhatsApp bindings become Meta's positional `{{n}}` placeholders.
81
+ - `id` is lowercase kebab-case, the rule the CLI and API slugs share. `subject` and `preheader`
82
+ belong to the channel; the `Email` component no longer takes a `preheader` prop.
83
+
84
+ `defineEmail` remains for templates that compute over their input, and it stays outside the static
85
+ profile.
86
+
87
+ ### Agents get a contract, a skill and a `templates/` root
88
+
89
+ - **`@samva/markup`.** Ships `@samva/markup/contract.json` and `generated/reference.md`, generated
90
+ from the compiler: component props, the static-profile forms and the forms it refuses, formatters,
91
+ HTML elements and every diagnostic code with its fix. The `sml` skill ships in the package under
92
+ `skills/sml`. Every compiler finding now comes from one registry of codes
93
+ (`DIAGNOSTIC_CODES`). The generated `sml-*-contract.json` and `sml-*-reference.md` files are
94
+ replaced by these two.
95
+ - **Entry root.** New hosted projects, the starter and the gallery use `templates/` as the entry
96
+ root. `emails/` is still accepted for entry paths in the API, the SDK types and the CLI
97
+ (`samva templates add`, `move`, `publish`).
98
+
99
+ ## @samva/markup@0.8.0
100
+
101
+ ### Breaking: `@samva/markup/presets` is `@samva/markup/starters`
102
+
103
+ Every `@samva/markup/presets*` subpath is renamed to `@samva/markup/starters*`, and its exports
104
+ follow: `presetCatalog` is `starterCatalog`, `presetProject` is `starterProject`,
105
+ `presetEmailFixtures` is `starterEmailFixtures`, and every other `preset*` / `Preset*` name reads
106
+ `starter*` / `Starter*`. A public gallery entry's `presetId` is `starterId`, and the corpus
107
+ record types are `OwnedEditableStarter` and `BrandRecreationStarter`. `RECOMMENDED_THEME` and
108
+ `showcaseProjectPaths` are removed.
109
+
110
+ ### Starters on theme variables
111
+
112
+ Every starter styles each color and font through a theme variable, and keeps its look in its own
113
+ `starter.css`. `@samva/markup/starters/theme` names the variables every starter defines and a
114
+ brand sets to restyle one (`STARTER_THEME_VARIABLES`: `--color-brand`, `--color-surface`,
115
+ `--font-body` and the rest; `starterThemeVariableNames` adds each color's `-dark` pair) and writes
116
+ the `theme.css` a project starts with (`starterThemeCss({ brand })`), which imports `samva:brand`
117
+ only when `brand` is true:
118
+
119
+ ```css
120
+ @import "./starter.css";
121
+ @import "samva:brand";
122
+ @theme {
123
+ }
124
+ ```
125
+
126
+ `var()` now resolves in a `Button`'s classic Outlook shape and in a `bgcolor`, so
127
+ `<Button backgroundColor="var(--color-brand)">` paints the theme color everywhere. Every `@theme`
128
+ in project and brand CSS compiles as `static`, so a variable a project stylesheet reads reaches
129
+ the inliner even when no utility class reads it.
130
+
131
+ ### Theme imports and brand themes
132
+
133
+ A project `theme.css` layers with `@import`: another project stylesheet by relative path, then the
134
+ organization's brand, then the project's own `@theme` overrides.
135
+
136
+ ```css
137
+ @import "./starter.css";
138
+ @import "samva:brand";
139
+
140
+ @theme {
141
+ --color-accent: #0f766e;
142
+ }
143
+ ```
144
+
145
+ `samva:brand` names the organization's default brand and `samva:brand/<slug>` names one brand; the
146
+ build supplies it through `compileEmailProject`'s `brand` option. `parseBrandCss` and
147
+ `printBrandCss` (`@samva/markup/theme-css`) read and write the brand theme grammar: `@theme`
148
+ variables in the color, font, text, leading, tracking, radius, spacing, container and shadow
149
+ namespaces, `--color-*` variables in a `@media (prefers-color-scheme: dark)` block, and
150
+ `@font-face` rules with https WOFF2 sources. A dark-mode color compiles to its `--color-*-dark`
151
+ theme variable, read by `dark:` utilities.
152
+
153
+ A project compiles against one brand: importing two fails with `brand-import-conflict`, and a
154
+ `samva:brand` import the build has no brand for, or whose slug names another brand, fails with
155
+ `brand-unavailable`. A brand theme outside the grammar fails with its `brand-css-*` finding.
156
+ `@samva/markup/compiler` exports `parseBrandSpecifier`, `projectBrandSpecifier` and the
157
+ `EmailBrand` types.
158
+
159
+ Breaking: any other `@import` in the theme — including `@import "tailwindcss"` — now refuses the
160
+ compile with `css-import-unresolved` instead of resolving to nothing. An `@import` with layer,
161
+ supports or media conditions, one that imports itself, or a `.css` path outside the project is
162
+ refused the same way. A theme with no utility class in use still compiles its `@font-face` rules.
163
+
164
+ ### `BrandLogo` and `BrandFooter`
165
+
166
+ ```tsx
167
+ import { BrandFooter, BrandLogo } from "samva:brand";
168
+ ```
169
+
170
+ `BrandLogo` renders the brand's logo and swaps to its dark logo where the client honors dark mode.
171
+ It takes `width` (default 120), `alt`, `align` and `className`, and renders nothing when the brand
172
+ has no logo. `BrandFooter` takes `unsubscribeLabel` and `className`.
173
+ `BrandFooter` renders the company name, postal address, social links and an unsubscribe row; the
174
+ send path fills the unsubscribe link per delivery and never click-tracks it, and a template that
175
+ renders `BrandFooter` gets no appended footer. Add `"types": ["@samva/markup/samva-brand"]` to the
176
+ project's tsconfig so `tsc` knows the module.
177
+
178
+ ### Breaking: token-table exports removed
179
+
180
+ `@samva/markup/footer`, `@samva/markup/theme`, and `@samva/markup/tokens` are removed; a brand's
181
+ footer renders through `BrandFooter`. `parseThemeCss` and `printThemeCss` are replaced by
182
+ `parseBrandCss` and `printBrandCss` in `@samva/markup/theme-css`.
183
+
184
+ ### Local builds resolve `samva:brand`
185
+
186
+ `samvaEditor()`, `buildTemplates()` and `exportEmailProject()` compile a project that imports
187
+ `samva:brand` or `samva:brand/<slug>` against its organization's brand, resolved in this order:
188
+
189
+ 1. Live. With `SAMVA_API_KEY` in the environment or the project's `.env` (and `SAMVA_API_URL` for
190
+ another API), the brand is fetched from `/v1/brands`. Without one, the `samva` CLI on `PATH`
191
+ answers `samva brands get --json` with its `samva login` session; `@samva/vite` stores no
192
+ credential.
193
+ 2. Snapshot. `.samva/brands/<slug>.json`, written by `samva brands pull [slug]`, with a
194
+ `brand-offline` warning. The default brand reads the most recent snapshot pulled while it was
195
+ the default.
196
+ 3. Neither. The build fails with `brand-unavailable`, naming both fixes.
197
+
198
+ When the live brand's digest differs from the snapshot's, the build warns with
199
+ `brand-snapshot-stale`; run `samva brands pull` again. Warnings are build diagnostics and editor log
200
+ lines and never fail a build. The editor and `check --watch` reuse a resolution for up to 30
201
+ seconds. Keep `.samva` in `.gitignore`; a project that imports no brand needs no credentials.
202
+
203
+ `@samva/vite/project` exports `resolveProjectBrand`, `loadBrandEnv`, `BRAND_SNAPSHOT_DIR` and the
204
+ `BrandResolution`, `BrandSnapshot`, `BrandWarning` and `ResolvedBrand` types. The editor recompiles
205
+ the theme when any stylesheet it imports changes.
206
+
207
+ ### Breaking: `exportEmailProject` themes the export
208
+
209
+ `exportEmailProject` drops `tailwind` and takes `root` and `theme`. `dir` holds the templates and
210
+ `root` (default `dir`) is the project: its `theme.css` themes the export as in `buildTemplates()`,
211
+ `theme` names another file or `false` disables it, and only `.tsx` files under `dir` are entries.
212
+
213
+ ```ts
214
+ const receipt = await exportEmailProject({ dir: "emails", root: ".", out: "dist/email" });
215
+ ```
216
+
217
+ ### Project fonts in `@font-face`
218
+
219
+ A template project declares a webfont with ordinary CSS: an `@font-face` in `theme.css` (or any
220
+ imported stylesheet) whose `src` names a `.woff2` file in the project, plus a `--font-*` token in
221
+ `@theme`.
222
+
223
+ ```css
224
+ @font-face {
225
+ font-family: "Brand Sans";
226
+ src: url("./fonts/brand-sans.woff2") format("woff2");
227
+ font-weight: 400;
228
+ }
229
+ @theme {
230
+ --font-brand: "Brand Sans", Helvetica, Arial, sans-serif;
231
+ }
232
+ ```
233
+
234
+ The compiler serves the file as a content-addressed asset, so local previews, exports and
235
+ publications all load the same bytes, and it puts the rule in a `<style>` classic Outlook does not
236
+ read, so Outlook uses the rest of the stack instead of Times New Roman.
237
+
238
+ Breaking for projects that already declared fonts: a relative `src` that names no project file, a
239
+ source that is not WOFF2, and an `http:` or `data:` source are compile errors, and a `font-family`
240
+ stack that names a project font without ending in a generic family fails with
241
+ `email-font-fallback`. `Stylesheet` gains `fontFaces`, and `@font-face` no longer appears in
242
+ `headAtRules`.
243
+
244
+ ## @samva/markup@0.7.0
245
+
246
+ ### Breaking: WhatsApp `category="service"` removed
247
+
248
+ `<WhatsApp category>` accepts `marketing`, `utility`, or `authentication`, the categories Meta
249
+ approves templates under.
250
+
251
+ ## @samva/markup@0.6.0
252
+
253
+ ### Improve markup compilation safety
254
+
255
+ Invalid or unsafe markup is now rejected earlier, preventing malformed email output. Complex styles
256
+ and conditions also compile more reliably.
257
+
258
+ ### Carry the plain-text alternative on a public preview artifact
259
+
260
+ `buildPublicTemplatePreviewArtifact` returns `text` alongside `html`, `subject` and `preheader`, so
261
+ a surface that mounts a preset's published preview has the whole executed fixture rather than its
262
+ HTML half. It is the same value `renderEmail` derived when the artifact was built; nothing is
263
+ recomputed.
264
+
265
+ ## @samva/markup@0.5.0
266
+
267
+ ### Breaking: a template project no longer installs Effect
268
+
269
+ - **A much smaller install:** `@samva/markup` has no Effect dependency and no `ajv` dependency, so a template project's lockfile and `node_modules` drop both graphs. The JSON Schema 2020-12 dialect the input validator checks against ships inside the package. Writing templates is unchanged: JSX, `defineEmail`, components, fixtures, and the input schema all work exactly as before, and you can still declare template input with an Effect, Zod, or plain JSON schema.
270
+ - **`@samva/vite` drops Effect too:** The Vite plugin carries no Effect dependency either, so `samva email templates build`, the editor dev server, and a template project that installs both packages resolve neither graph.
271
+ - **Breaking: compile and render results:** Everything the compiler returns is now a [better-result](https://better-result.dev) `Result`. Read a success with `Result.isOk(result)` and `result.value`, a failure with `Result.isError(result)` and `result.error`. Errors keep their names and tags — `SmlParseError`, `SmlCompileError`, `SmlOpError`, `EmailCompileError` — so code that matches on `_tag` or catches `EmailCompileError` still works.
272
+ - **Breaking: data unions discriminate on `type`:** `EmailNode` and the editor-op, corpus and gallery unions name their variant with `type` instead of `_tag` — `node.type === "Element"`, `op.type === "setProp"`. Compiler errors are unaffected: `SmlParseError`, `SmlCompileError`, `SmlOpError` and `EmailCompileError` keep `_tag`, which is their error library's own field.
273
+ - **Breaking: schema values are gone:** The package declares its data models as TypeScript types only. Runtime schema values such as `EmailDiagnostic`, `EmailElementSelection`, `SmlOpSchema`, and `SmlDocumentSchema` no longer exist; the types of the same name do, and the shapes are identical. If you decoded one of these at a boundary, declare the schema in your own project against the exported type.
274
+
275
+ ## @samva/markup@0.4.0
276
+
277
+ ### Faster, reliable saves in large projects
278
+
279
+ - **Saves in large projects are quick again:** Saving a template no longer re-evaluates every template in the project, so previews come back in about the time one template takes to build.
280
+ - **No false "Document changed elsewhere" banner:** Your own edits and fixture switches are recognized as yours, so the editor no longer locks the source panel and undo after a save. Edits made outside the editor are still detected.
281
+
282
+ ### Breaking: every email template is a complete, editable project
283
+
284
+ - **28 templates rebuilt:** The 28 remaining single-file presets are rebuilt as showcase projects with their own stylesheet, drawn artwork, and `default` and `long-content` sample data. Marketing, digest, lifecycle, commerce, and notification templates are covered, authored for five fictional senders: Northwick, Kestrel, Northloop, Fernhollow, and Meridian. Template ids and their gallery pages are unchanged.
285
+ - **Breaking: simpler template inputs:** Repeating content such as stories, deals, agenda items, checklist steps, and order lines is a list instead of numbered fields. Images are bundled with the project instead of passed as URLs, and headline and body copy is edited in the template source rather than supplied as input. Optional sections such as sponsors, gift cards, and reminders appear only when you send them. Dates, days remaining, and step numbers come from your input, so scheduled sends never depend on the clock. If you render one of these templates with your own data, move to the new input shape; each template's sample data shows it.
286
+ - **Breaking: four presets retired:** `receipt`, `newsletter`, `promo`, and `order-delivered` are removed from the catalog, the public gallery, and the `PresetId` types. Use `order-receipt`, `product-newsletter`, and `product-launch-promo` instead.
287
+ - **Stock photography removed:** The onboarding tour and setup checklist templates now use drawn artwork, so no template depends on third-party images.
288
+
289
+ ## @samva/markup@0.3.0
290
+
291
+ - **Reliable project styling:** Switching between projects or preview fixtures preserves each template's styles and avoids unexpected revision changes.
292
+ - **Better Outlook buttons:** `<Button>` sizes to its label without requiring a fixed width. Explicit widths remain supported.
293
+ - **New editable templates:** Product newsletter, order receipt, product launch promotion, and an attributed Vercel invitation, including styles, images, and sample data.
294
+ - **Richer template inputs:** Use lists and objects for repeating content such as newsletter stories and receipt items.
295
+ - **Cleaner plain-text emails:** Empty table cells no longer leave unnecessary separators.
296
+ - **For custom render integrations:** `bindStylesheets` from `@samva/markup/email/render` binds a renderer to one project's styles.
297
+
298
+ ## @samva/markup@0.2.0
299
+
300
+ ### Breaking: author email templates with typed input and executable TSX
301
+
302
+ Email entries now default-export `defineEmail({ id, schema, fixtures, render })` from
303
+ `@samva/markup/template`. Replace function-based email entries and `Variables<T>` placeholders
304
+ with a schema and a `render(input)` function. Set `jsxImportSource` to `@samva/markup/email`,
305
+ import email components from `@samva/markup/email/components`, and upgrade `@samva/markup` and
306
+ `@samva/vite` together to 0.2.0. Regenerate the project's dependency lockfile before publishing.
307
+
308
+ The input contract supports Standard JSON Schema, including Effect and Zod schema adapters.
309
+ `TemplateInput<typeof template>` extracts the inferred input type. Named fixtures supply preview
310
+ and validation inputs; rendering evaluates ordinary TSX, imported components, conditionals and
311
+ mapped arrays against actual input. Time and randomness must come from input or fixed `runtime`
312
+ configuration.
313
+
314
+ The shared local and hosted compiler resolves CSS, Tailwind and imported assets, validates fixture
315
+ inputs, and produces HTML, text and email-client diagnostics. Diagnostics identify known support
316
+ constraints; they do not certify rendering in every email client.
317
+
318
+ The Vite editor maps rendered instances to canonical TSX source. Literal edits preserve the
319
+ source expression; computed or structural changes use reviewed source edits. Fixture switching,
320
+ undo/redo, save/reopen and revision-conflict handling keep source edits tied to the preview.
321
+
322
+ Published email templates pin an executable, input contract, dependency graph and runtime
323
+ configuration. Existing email source must adopt the new contract and be republished; previously
324
+ published HTML snapshots are not executable publications.
325
+
326
+ ## @samva/markup@0.1.2
327
+
328
+ ### Reject oversized SML templates before compilation
329
+
330
+ Templates that exceed supported size, nesting, or node limits now return a validation error before
331
+ compilation.
332
+
333
+ ## @samva/markup@0.1.1
334
+
335
+ ### Release the 0.1.1 package family
336
+
337
+ `@samva/markup` publishes with the rest of the 0.1.1 family.
338
+
339
+ ## @samva/markup@0.1.0
340
+
341
+ ### Publish the Samva template authoring toolchain
342
+
343
+ `@samva/markup` and `@samva/vite` are published on npm. They provide typed TSX authoring, local
344
+ visual editing, and deterministic template builds. `samva templates push` uploads the compiled
345
+ templates.