@samva/markup 0.1.2 → 0.3.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 (93) hide show
  1. package/AGENTS.md +25 -5
  2. package/README.md +92 -26
  3. package/dist/{ast-DAhnAvQN.d.ts → ast-63I-VLQx.d.ts} +15 -2
  4. package/dist/ast.d.ts +2 -2
  5. package/dist/ast.js +14 -1
  6. package/dist/{checks-D-zFQt5R.js → checks-DXuERO4B.js} +36 -2
  7. package/dist/checks.d.ts +8 -1
  8. package/dist/checks.js +2 -2
  9. package/dist/compile-sms.d.ts +2 -2
  10. package/dist/compile-whatsapp.d.ts +2 -2
  11. package/dist/compile.d.ts +9 -84
  12. package/dist/compile.js +11 -920
  13. package/dist/compiler.d.ts +303 -0
  14. package/dist/compiler.js +1390 -0
  15. package/dist/components.d.ts +3 -3
  16. package/dist/corpus-qrUD5O6r.d.ts +254 -0
  17. package/dist/css-ar2lU3NC.d.ts +84 -0
  18. package/dist/diagnostics-Djd9ckLg.d.ts +90 -0
  19. package/dist/diagnostics.js +4 -1
  20. package/dist/elements-DtwKlFVH.d.ts +820 -0
  21. package/dist/email/components.d.ts +125 -0
  22. package/dist/email/components.js +210 -0
  23. package/dist/email/diagnostics.d.ts +2 -0
  24. package/dist/email/diagnostics.js +56 -0
  25. package/dist/email/elements.d.ts +2 -0
  26. package/dist/email/elements.js +299 -0
  27. package/dist/email/html.d.ts +42 -0
  28. package/dist/email/html.js +266 -0
  29. package/dist/email/jsx-dev-runtime.d.ts +26 -0
  30. package/dist/email/jsx-dev-runtime.js +12 -0
  31. package/dist/email/jsx-runtime.d.ts +2 -0
  32. package/dist/email/jsx-runtime.js +60 -0
  33. package/dist/email/render.d.ts +43 -0
  34. package/dist/email/render.js +6 -0
  35. package/dist/email/selection.d.ts +102 -0
  36. package/dist/email/selection.js +143 -0
  37. package/dist/email/source-edit.d.ts +67 -0
  38. package/dist/email/source-edit.js +185 -0
  39. package/dist/email/stylesheets.d.ts +15 -0
  40. package/dist/email/stylesheets.js +45 -0
  41. package/dist/email/text.d.ts +7 -0
  42. package/dist/email/text.js +100 -0
  43. package/dist/emit.d.ts +13 -12
  44. package/dist/emit.js +63 -63
  45. package/dist/input-schema-BIfzI63B.d.ts +23 -0
  46. package/dist/input-schema.d.ts +2 -0
  47. package/dist/input-schema.js +170 -0
  48. package/dist/jsx-dev-runtime.d.ts +4 -3
  49. package/dist/jsx-dev-runtime.js +9 -1
  50. package/dist/{jsx-runtime-eNIMY87F.d.ts → jsx-runtime-C5k_Zq0A.d.ts} +3 -3
  51. package/dist/jsx-runtime.d.ts +1 -1
  52. package/dist/jsx-runtime.js +20 -1
  53. package/dist/model.d.ts +1 -1
  54. package/dist/ops.d.ts +1 -1
  55. package/dist/ops.js +1 -1
  56. package/dist/{parser-DkQKIjDa.d.ts → parser-CGBS73Gz.d.ts} +2 -2
  57. package/dist/parser.d.ts +1 -1
  58. package/dist/presets/category-mapping.d.ts +1 -1
  59. package/dist/presets/corpus.d.ts +2 -0
  60. package/dist/presets/corpus.js +247 -0
  61. package/dist/presets/public-gallery.d.ts +290 -2
  62. package/dist/presets/public-gallery.js +428 -6
  63. package/dist/presets/public-handoff.d.ts +164 -2
  64. package/dist/presets/public-handoff.js +229 -61
  65. package/dist/presets/public-preview-artifacts.d.ts +2 -2
  66. package/dist/presets/public-preview-artifacts.js +25 -31
  67. package/dist/presets/public-preview.d.ts +65 -2
  68. package/dist/presets/public-preview.js +402 -1152
  69. package/dist/presets/sources.d.ts +35 -4
  70. package/dist/presets/sources.js +2328 -43
  71. package/dist/presets.d.ts +39 -5
  72. package/dist/presets.js +96 -0
  73. package/dist/printer.d.ts +1 -1
  74. package/dist/render-template.d.ts +5 -2
  75. package/dist/render-template.js +3 -1
  76. package/dist/render-ykQhtMs_.js +592 -0
  77. package/dist/source-locations-BCJQnIfU.d.ts +89 -0
  78. package/dist/source-locations.d.ts +2 -0
  79. package/dist/source-locations.js +125 -0
  80. package/dist/template-Dy5yOPyp.d.ts +60 -0
  81. package/dist/template.d.ts +2 -0
  82. package/dist/template.js +37 -0
  83. package/dist/tsx-source-instrumentation.d.ts +23 -0
  84. package/dist/tsx-source-instrumentation.js +97 -0
  85. package/dist/tsx-tracer.d.ts +116 -0
  86. package/dist/tsx-tracer.js +985 -0
  87. package/generated/sml-agent-contract.json +574 -782
  88. package/generated/sml-email-agent-contract.json +502 -677
  89. package/generated/sml-email-language-reference.md +94 -160
  90. package/generated/sml-language-reference.md +195 -220
  91. package/package.json +111 -9
  92. package/dist/public-gallery-D0Zv0pZE.d.ts +0 -611
  93. package/dist/public-preview-u1Z9aaGq.d.ts +0 -1168
package/dist/emit.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { sameTemplateSourceLocations } from "./source-locations.js";
1
2
  import { isRootTag } from "./ast.js";
2
3
  import { createVariablesProxy } from "./variables.js";
3
4
  import { renderTemplate } from "./render-template.js";
@@ -5,55 +6,40 @@ import { Result } from "effect";
5
6
  //#region src/emit.ts
6
7
  /**
7
8
  * emitModule — the module-level emit boundary for the TSX authoring layer
8
- * (design brief §7b). The vite plugin (M12) does the importing: TSX runs at the
9
+ * (design brief §7b). The vite plugin does the importing: TSX runs at the
9
10
  * USER's build time and this receives the already-evaluated module object (a
10
11
  * record of its exports). emitModule stays bundler-agnostic — it never touches
11
- * the filesystem, esbuild, or vite. It discovers the named template functions,
12
- * runs each through renderTemplate (print → parse validation), and additionally
13
- * renders each one TWICE to guard emission determinism (a build-time clock or
14
- * RNG produces a different second emission and is reported as unstable).
12
+ * the filesystem, esbuild, or vite. It reads only `moduleExports.default`,
13
+ * runs that function through renderTemplate (print → parse validation), and
14
+ * additionally renders it TWICE to guard emission determinism (a build-time
15
+ * clock or RNG produces a different second emission and is reported as
16
+ * unstable).
15
17
  *
16
- * Non-function and helper exports are ignored silently; a module with zero
17
- * templates is a distinct diagnostic (the common "forgot to export the function"
18
- * / "imported the wrong file" mistake).
18
+ * Named exports are ordinary helpers and are never inspected or invoked. A
19
+ * missing or invalid default is a module-level diagnostic (the common "forgot
20
+ * to default-export the function" / "imported the wrong file" mistake).
19
21
  *
20
- * Template discovery
22
+ * Default-export classification
21
23
  *
22
- * Discovery is by PROBING, not by an explicit `isTemplate` marker. A module
23
- * export is a template iff it is a function that, when invoked with a fresh
24
- * recording proxy, returns a channel root element (JsxResult with
25
- * `kind: "element"` and an <Email>/<Sms>/<WhatsApp> tag). Rationale for
26
- * probing over a marker:
24
+ * This recorder recognizes function exports returning a channel root element.
25
+ * SMS and WhatsApp use the recorded AST; legacy Email roots remain recognizable
26
+ * so the compiler can report the executable defineEmail requirement. Executable
27
+ * email definitions are discovered by their definition marker before this path.
28
+ * Structured function exports have no marker and are classified by probing.
27
29
  *
28
- * • The canonical template shape (brief §7b) is a plain named exported
29
- * function of `Variables<T>` — requiring a `Foo.isTemplate = true` tag or a
30
- * `defineTemplate()` wrapper would add ceremony the brief explicitly avoids
31
- * ("named exported function is the canonical template shape").
32
- * • The proxy makes the probe cheap and side-effect-free for well-formed
33
- * templates: property accesses record variables and return refs; no network,
34
- * no I/O. Composition helpers that assemble sub-trees also just build AST.
30
+ * The proxy makes the probe cheap and side-effect-free for well-formed
31
+ * templates: property accesses record variables and return refs; no network,
32
+ * no I/O. A default export that throws when called with a proxy, or that
33
+ * returns a non-root node, is `invalid-default-export` rather than a crash.
35
34
  *
36
- * Soundness boundary (documented tradeoff): probing invokes the function, so a
37
- * helper export with arbitrary arity or side effects is executed once during
38
- * discovery. We contain the two failure shapes:
39
- *
40
- * • A helper that THROWS when called with a proxy (wrong argument shape, a
41
- * coercion-guard trip, an invalid-child assembly) is classified as a
42
- * non-template and skipped — the throw is swallowed only for the probe. This
43
- * is the one place we catch, and it is confined to classification.
44
- * • A helper that RETURNS a non-<Email> node (a bare <Container>, a Fragment,
45
- * a string) is likewise skipped.
46
- *
47
- * The corollary: a genuine template whose body throws (a real authoring bug —
48
- * coercing a variable, a malformed child) is misclassified as a helper and
49
- * silently skipped rather than surfacing its error. That is acceptable because
50
- * the same bug breaks the template's real emit regardless, and the zero-template
51
- * diagnostic fires when it was the module's only template. The probe re-runs the
52
- * function; renderTemplate runs it again on the confirmed templates, so a
53
- * template function must be a pure builder of its AST (no external side effects)
54
- * — which the recording-proxy model already requires.
35
+ * A genuine template whose body throws (a real authoring bug — coercing a
36
+ * variable, a malformed child) is therefore classified as an invalid default.
37
+ * That is acceptable because the same bug breaks the template's real emit
38
+ * regardless. Confirmed templates are rendered by renderTemplate, so a
39
+ * template function must be a pure builder of its AST — which the
40
+ * recording-proxy model already requires.
55
41
  */
56
- /** Probe one export: is it a function that yields a channel root document? */
42
+ /** Probe the default export: is it a function that yields a channel root document? */
57
43
  const isTemplateFunction = (value) => {
58
44
  if (typeof value !== "function") return false;
59
45
  const { proxy } = createVariablesProxy();
@@ -65,9 +51,17 @@ const isTemplateFunction = (value) => {
65
51
  }
66
52
  return result !== null && typeof result === "object" && result.kind === "element" && isRootTag(result.tag);
67
53
  };
68
- const ZERO_TEMPLATES = {
69
- code: "no-templates",
70
- message: "no template exports found — a template is a named exported function returning a channel root element (e.g. `export function WelcomeEmail(v: Variables<{…}>) { return <Email>…</Email>; }`; <Sms> and <WhatsApp> roots work the same way)",
54
+ const MISSING_DEFAULT = {
55
+ code: "missing-default-export",
56
+ message: "no default export — a structured template must default-export a function returning <Sms> or <WhatsApp>. Email templates must default-export defineEmail with an input schema and fixtures. Named exports are ignored.",
57
+ span: {
58
+ start: 0,
59
+ end: 0
60
+ }
61
+ };
62
+ const INVALID_DEFAULT = {
63
+ code: "invalid-default-export",
64
+ message: "the default export is not a structured Samva template returning <Sms> or <WhatsApp>. Email templates must default-export defineEmail with an input schema and fixtures.",
71
65
  span: {
72
66
  start: 0,
73
67
  end: 0
@@ -82,31 +76,31 @@ const unstableDiagnostic = (name) => ({
82
76
  }
83
77
  });
84
78
  /**
85
- * Discovers template functions in an already-evaluated module object, renders
86
- * each to canonical SML with a determinism guard, and returns per-template
87
- * results plus an aggregate ok/fail. `moduleExports` is a plain record of the
88
- * module's exports (the vite plugin imports the TSX; this stays bundler-agnostic
89
- * and pure).
79
+ * Emits the one supported template from an already-evaluated module object:
80
+ * `moduleExports.default`. Named exports are never probed. `moduleExports` is
81
+ * a plain record of the module's exports (the vite plugin imports the TSX;
82
+ * this stays bundler-agnostic and pure).
90
83
  *
91
- * Discovery is exhaustive and order-preserving over `Object.entries`: every
92
- * function export is probed, non-templates (helpers, constants, types-erased
93
- * exports) are ignored silently, and a module with zero templates yields a
94
- * single `no-templates` diagnostic with `ok: false`.
84
+ * A missing default yields `missing-default-export`. A present default that
85
+ * is not a template function yields `invalid-default-export`. Both fail the
86
+ * aggregate with an empty `templates` array.
95
87
  */
96
88
  const emitModule = (moduleExports) => {
97
- const templates = [];
98
- for (const [name, value] of Object.entries(moduleExports)) {
99
- if (!isTemplateFunction(value)) continue;
100
- templates.push(emitOne(name, value));
101
- }
102
- if (templates.length === 0) return {
89
+ if (!Object.hasOwn(moduleExports, "default")) return {
90
+ ok: false,
91
+ templates: [],
92
+ diagnostics: [MISSING_DEFAULT]
93
+ };
94
+ const value = moduleExports.default;
95
+ if (!isTemplateFunction(value)) return {
103
96
  ok: false,
104
97
  templates: [],
105
- diagnostics: [ZERO_TEMPLATES]
98
+ diagnostics: [INVALID_DEFAULT]
106
99
  };
100
+ const template = emitOne("default", value);
107
101
  return {
108
- ok: templates.every((template) => template.ok),
109
- templates,
102
+ ok: template.ok,
103
+ templates: [template],
110
104
  diagnostics: []
111
105
  };
112
106
  };
@@ -126,15 +120,20 @@ const emitOne = (name, template) => {
126
120
  ok: false,
127
121
  source: void 0,
128
122
  variables: [],
123
+ sourceLocations: {
124
+ kind: "unavailable",
125
+ reason: "render-failed"
126
+ },
129
127
  diagnostics: first.failure.diagnostics
130
128
  };
131
129
  const rendered = first.success;
132
130
  const second = renderTemplate(template);
133
- if (Result.isSuccess(second) && second.success.source === rendered.source) return {
131
+ if (Result.isSuccess(second) && second.success.source === rendered.source && sameTemplateSourceLocations(second.success.sourceLocations, rendered.sourceLocations)) return {
134
132
  name,
135
133
  ok: true,
136
134
  source: rendered.source,
137
135
  variables: rendered.variables,
136
+ sourceLocations: rendered.sourceLocations,
138
137
  diagnostics: []
139
138
  };
140
139
  return {
@@ -142,6 +141,7 @@ const emitOne = (name, template) => {
142
141
  ok: false,
143
142
  source: rendered.source,
144
143
  variables: rendered.variables,
144
+ sourceLocations: rendered.sourceLocations,
145
145
  diagnostics: [unstableDiagnostic(name)]
146
146
  };
147
147
  };
@@ -0,0 +1,23 @@
1
+ import { OutputUnit } from "@cfworker/json-schema";
2
+ import { StandardJSONSchemaV1 } from "effect/StandardSchema";
3
+ //#region src/input-schema.d.ts
4
+ /** JSON Schema dialect accepted by template publications. */
5
+ declare const INPUT_SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
6
+ /** A compiled non-mutating validator and its complete published schema. */
7
+ interface InputSchema<Input> {
8
+ readonly schema: Record<string, unknown>;
9
+ /** Canonical validation document; annotations are retained only in schema. */
10
+ readonly validationIdentity: string;
11
+ readonly validate: ((value: unknown) => value is Input) & {
12
+ errors?: readonly OutputUnit[];
13
+ };
14
+ }
15
+ /** Direct portable JSON Schema authoring; the caller declares its JSON input type. */
16
+ declare const jsonSchema: <Input>(schema: Record<string, unknown>) => StandardJSONSchemaV1<Input>;
17
+ /** Convert caller input, never validator output. Both conversion directions must be portable. */
18
+ declare const inputSchema: <S extends StandardJSONSchemaV1>(source: S) => InputSchema<StandardJSONSchemaV1.InferInput<S>>;
19
+ /** Serializable validation errors suitable for build and request diagnostics. */
20
+ type InputIssue = OutputUnit;
21
+ //#endregion
22
+ export { jsonSchema as a, inputSchema as i, InputIssue as n, InputSchema as r, INPUT_SCHEMA_DIALECT as t };
23
+ //# sourceMappingURL=input-schema-BIfzI63B.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { a as jsonSchema, i as inputSchema, n as InputIssue, r as InputSchema, t as INPUT_SCHEMA_DIALECT } from "./input-schema-BIfzI63B.js";
2
+ export { INPUT_SCHEMA_DIALECT, InputIssue, InputSchema, inputSchema, jsonSchema };
@@ -0,0 +1,170 @@
1
+ import { Validator } from "@cfworker/json-schema";
2
+ import applicator from "ajv/dist/refs/json-schema-2020-12/meta/applicator.json" with { type: "json" };
3
+ import content from "ajv/dist/refs/json-schema-2020-12/meta/content.json" with { type: "json" };
4
+ import core from "ajv/dist/refs/json-schema-2020-12/meta/core.json" with { type: "json" };
5
+ import format_annotation from "ajv/dist/refs/json-schema-2020-12/meta/format-annotation.json" with { type: "json" };
6
+ import meta_data from "ajv/dist/refs/json-schema-2020-12/meta/meta-data.json" with { type: "json" };
7
+ import unevaluated from "ajv/dist/refs/json-schema-2020-12/meta/unevaluated.json" with { type: "json" };
8
+ import validation from "ajv/dist/refs/json-schema-2020-12/meta/validation.json" with { type: "json" };
9
+ import metaSchema from "ajv/dist/refs/json-schema-2020-12/schema.json" with { type: "json" };
10
+ import { Predicate } from "effect";
11
+ //#region src/input-schema.ts
12
+ const meta = new Validator(metaSchema, "2020-12", false);
13
+ for (const part of [
14
+ applicator,
15
+ content,
16
+ core,
17
+ format_annotation,
18
+ meta_data,
19
+ unevaluated,
20
+ validation
21
+ ]) meta.addSchema(part);
22
+ /** JSON Schema dialect accepted by template publications. */
23
+ const INPUT_SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
24
+ const canonicalJson = (value) => {
25
+ if (Array.isArray(value)) return value.map(canonicalJson);
26
+ if (Predicate.isObject(value)) return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => [key, canonicalJson(item)]));
27
+ return value;
28
+ };
29
+ const annotations = /* @__PURE__ */ new Set([
30
+ "title",
31
+ "description",
32
+ "default",
33
+ "examples",
34
+ "deprecated",
35
+ "readOnly",
36
+ "writeOnly",
37
+ "$comment"
38
+ ]);
39
+ const scalarKeywords = /* @__PURE__ */ new Set([
40
+ "$schema",
41
+ "$ref",
42
+ "type",
43
+ "enum",
44
+ "const",
45
+ "required",
46
+ "minProperties",
47
+ "maxProperties",
48
+ "minItems",
49
+ "maxItems",
50
+ "uniqueItems",
51
+ "minLength",
52
+ "maxLength",
53
+ "pattern",
54
+ "minimum",
55
+ "maximum",
56
+ "exclusiveMinimum",
57
+ "exclusiveMaximum",
58
+ "multipleOf"
59
+ ]);
60
+ const schemaMaps = /* @__PURE__ */ new Set([
61
+ "properties",
62
+ "$defs",
63
+ "patternProperties",
64
+ "dependentSchemas"
65
+ ]);
66
+ const schemaValues = /* @__PURE__ */ new Set([
67
+ "additionalProperties",
68
+ "items",
69
+ "contains",
70
+ "not",
71
+ "if",
72
+ "then",
73
+ "else",
74
+ "propertyNames"
75
+ ]);
76
+ const schemaArrays = /* @__PURE__ */ new Set([
77
+ "allOf",
78
+ "anyOf",
79
+ "oneOf",
80
+ "prefixItems"
81
+ ]);
82
+ /** Check every schema position before deriving identity; unknown keywords never disappear. */
83
+ const canonicalSchema = (schema, path = "#") => {
84
+ if (typeof schema === "boolean") return schema;
85
+ if (!Predicate.isObject(schema)) throw new TypeError(`Invalid schema at ${path}`);
86
+ const shape = meta.validate(schema);
87
+ if (!shape.valid) throw new TypeError(`Invalid JSON Schema at ${path}: ${JSON.stringify(shape.errors)}`);
88
+ const result = {};
89
+ for (const [key, value] of Object.entries(schema).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
90
+ if (annotations.has(key)) continue;
91
+ if (schemaMaps.has(key)) {
92
+ if (!Predicate.isObject(value)) throw new TypeError(`Invalid ${path}/${key}`);
93
+ result[key] = Object.fromEntries(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, child]) => [name, canonicalSchema(child, `${path}/${key}/${name}`)]));
94
+ } else if (schemaValues.has(key)) result[key] = canonicalSchema(value, `${path}/${key}`);
95
+ else if (schemaArrays.has(key)) {
96
+ if (!Array.isArray(value)) throw new TypeError(`Invalid ${path}/${key}`);
97
+ result[key] = value.map((child, index) => canonicalSchema(child, `${path}/${key}/${index}`));
98
+ } else if (scalarKeywords.has(key)) {
99
+ if (key === "$ref" && (typeof value !== "string" || !(value === "#" || value.startsWith("#/")))) throw new TypeError(`Only local JSON Pointer references are supported at ${path}/$ref`);
100
+ if (key === "$schema" && value !== "https://json-schema.org/draft/2020-12/schema") throw new TypeError(`Expected JSON Schema 2020-12 at ${path}`);
101
+ result[key] = canonicalJson(value);
102
+ } else throw new TypeError(`Unsupported input schema keyword ${path}/${key}`);
103
+ }
104
+ return result;
105
+ };
106
+ /** Direct portable JSON Schema authoring; the caller declares its JSON input type. */
107
+ const jsonSchema = (schema) => ({ "~standard": {
108
+ version: 1,
109
+ vendor: "samva-json-schema",
110
+ jsonSchema: {
111
+ input: () => schema,
112
+ output: () => schema
113
+ }
114
+ } });
115
+ /** Pinned Effect/Zod converters omit arbitrary refinements, so inspect those vendors' check metadata. */
116
+ const rejectNonportableChecks = (source) => {
117
+ const vendor = source["~standard"].vendor;
118
+ if (vendor !== "effect" && vendor !== "zod") return;
119
+ const seen = /* @__PURE__ */ new WeakSet();
120
+ const visit = (value) => {
121
+ if (Array.isArray(value)) {
122
+ for (const child of value) visit(child);
123
+ return;
124
+ }
125
+ if (!Predicate.isObject(value) || seen.has(value)) return;
126
+ seen.add(value);
127
+ if (vendor === "zod" && Predicate.isObject(value._zod)) {
128
+ visit(value._zod.def);
129
+ return;
130
+ }
131
+ if (vendor === "effect" && value.encoding !== void 0) throw new TypeError("Nonportable Effect transform; use a JSON input schema without decoding transforms");
132
+ if (vendor === "effect" && value._tag === "Suspend") throw new TypeError("Unsupported suspended Effect converter; use local JSON Schema references");
133
+ if (vendor === "zod" && value.type === "lazy") throw new TypeError("Unsupported lazy Zod converter; author recursive input with local JSON Schema references");
134
+ if (vendor === "zod" && (value.check === "custom" || value.check === "overwrite" || [
135
+ "transform",
136
+ "default",
137
+ "prefault",
138
+ "catch"
139
+ ].includes(String(value.type)))) throw new TypeError("Nonportable Zod refinement/transform; express constraints in JSON Schema");
140
+ if (vendor === "effect" && value._tag === "Filter" && (!Predicate.isObject(value.annotations) || typeof value.annotations.toJsonSchema !== "function")) throw new TypeError("Nonportable Effect refinement; provide a JSON Schema constraint");
141
+ for (const [key, child] of Object.entries(value)) if (key !== "~standard" && key !== "annotations") visit(child);
142
+ };
143
+ if (vendor === "effect" && Predicate.hasProperty(source, "ast")) visit(source.ast);
144
+ else visit(source);
145
+ };
146
+ /** Convert caller input, never validator output. Both conversion directions must be portable. */
147
+ const inputSchema = (source) => {
148
+ rejectNonportableChecks(source);
149
+ const converter = source["~standard"].jsonSchema;
150
+ const schema = structuredClone(converter.input({ target: "draft-2020-12" }));
151
+ const canonical = canonicalSchema(schema);
152
+ const output = canonicalSchema(converter.output({ target: "draft-2020-12" }));
153
+ if (JSON.stringify(canonical) !== JSON.stringify(output)) throw new TypeError("Template schemas must preserve JSON input; input/output conversion differs");
154
+ const validator = new Validator(schema, "2020-12", false);
155
+ const validate = (value) => {
156
+ const result = validator.validate(value);
157
+ validate.errors = result.errors;
158
+ return result.valid;
159
+ };
160
+ validate.errors = [];
161
+ return {
162
+ schema,
163
+ validationIdentity: JSON.stringify(canonical),
164
+ validate
165
+ };
166
+ };
167
+ //#endregion
168
+ export { INPUT_SCHEMA_DIALECT, inputSchema, jsonSchema };
169
+
170
+ //# sourceMappingURL=input-schema.js.map
@@ -1,10 +1,11 @@
1
- import { a as JsxResult, i as JSX, n as Fragment, t as Component } from "./jsx-runtime-eNIMY87F.js";
1
+ import { r as JsxSource } from "./source-locations-BCJQnIfU.js";
2
+ import { a as JsxResult, i as JSX, n as Fragment, t as Component } from "./jsx-runtime-C5k_Zq0A.js";
2
3
  //#region src/jsx-dev-runtime.d.ts
3
4
  interface JsxDevProps {
4
5
  readonly children?: unknown;
5
6
  readonly [key: string]: unknown;
6
7
  }
7
- declare const jsxDEV: (type: Component<JsxDevProps> | typeof Fragment, props: JsxDevProps) => JsxResult;
8
+ declare const jsxDEV: <P>(type: Component<P> | typeof Fragment, props: P, _key?: string | number | null, _isStaticChildren?: boolean, source?: JsxSource | null, _self?: unknown) => JsxResult;
8
9
  //#endregion
9
- export { Fragment, type JSX, jsxDEV };
10
+ export { Fragment, type JSX, JsxDevProps, jsxDEV };
10
11
  //# sourceMappingURL=jsx-dev-runtime.d.ts.map
@@ -1,6 +1,14 @@
1
+ import { attachJsxSourceLocation, completeJsxSourceLocation } from "./source-locations.js";
1
2
  import { Fragment, jsx } from "./jsx-runtime.js";
2
3
  //#region src/jsx-dev-runtime.ts
3
- const jsxDEV = (type, props) => jsx(type, props);
4
+ const jsxDEV = (type, props, _key, _isStaticChildren, source, _self) => {
5
+ const result = jsx(type, props);
6
+ if (type !== Fragment && result.kind === "element") {
7
+ const location = completeJsxSourceLocation(source);
8
+ if (location !== void 0) attachJsxSourceLocation(result, location);
9
+ }
10
+ return result;
11
+ };
4
12
  //#endregion
5
13
  export { Fragment, jsxDEV };
6
14
 
@@ -1,4 +1,4 @@
1
- import { T as SmlNode, m as ElementNode, n as Attribute } from "./ast-DAhnAvQN.js";
1
+ import { E as SmlNode, m as ElementNode, n as Attribute } from "./ast-63I-VLQx.js";
2
2
  import { s as VariableRef } from "./variables-if1VrV34.js";
3
3
  //#region src/jsx-runtime.d.ts
4
4
  /** A component is a plain function of its props that returns a draft node. */
@@ -41,7 +41,7 @@ interface JsxProps {
41
41
  * children), so `jsxs` re-exports this.
42
42
  */
43
43
  declare const jsx: (type: Component<JsxProps> | typeof Fragment, props: JsxProps) => JsxResult;
44
- declare const jsxs: (type: Component<JsxProps> | typeof Fragment, props: JsxProps) => JsxResult;
44
+ declare const jsxs: typeof jsx;
45
45
  /** Groups children without an element wrapper. Its children splice into the parent. */
46
46
  declare const Fragment: unique symbol;
47
47
  declare namespace JSX {
@@ -54,4 +54,4 @@ declare namespace JSX {
54
54
  }
55
55
  //#endregion
56
56
  export { JsxResult as a, elementDraft as c, normalizeChildren as d, JSX as i, jsx as l, Fragment as n, SmlChild as o, FragmentDraft as r, SmlChildren as s, Component as t, jsxs as u };
57
- //# sourceMappingURL=jsx-runtime-eNIMY87F.d.ts.map
57
+ //# sourceMappingURL=jsx-runtime-C5k_Zq0A.d.ts.map
@@ -1,2 +1,2 @@
1
- import { a as JsxResult, c as elementDraft, d as normalizeChildren, i as JSX, l as jsx, n as Fragment, o as SmlChild, r as FragmentDraft, s as SmlChildren, t as Component, u as jsxs } from "./jsx-runtime-eNIMY87F.js";
1
+ import { a as JsxResult, c as elementDraft, d as normalizeChildren, i as JSX, l as jsx, n as Fragment, o as SmlChild, r as FragmentDraft, s as SmlChildren, t as Component, u as jsxs } from "./jsx-runtime-C5k_Zq0A.js";
2
2
  export { Component, Fragment, FragmentDraft, JSX, JsxResult, SmlChild, SmlChildren, elementDraft, jsx, jsxs, normalizeChildren };
@@ -1,3 +1,4 @@
1
+ import { JSX_SOURCE_LOCATION_PROP, attachJsxSourceLocation, completeJsxSourceLocation } from "./source-locations.js";
1
2
  import { VARIABLE_REF, isVariableRef } from "./variables.js";
2
3
  import { Predicate } from "effect";
3
4
  //#region src/jsx-runtime.ts
@@ -79,6 +80,18 @@ const elementDraft = (tag, attributes, children) => ({
79
80
  children,
80
81
  span: PLACEHOLDER_SPAN
81
82
  });
83
+ const stripSourceLocation = (props) => {
84
+ const source = props[JSX_SOURCE_LOCATION_PROP];
85
+ if (source === void 0) return {
86
+ props,
87
+ source: void 0
88
+ };
89
+ const { [JSX_SOURCE_LOCATION_PROP]: _source, ...rest } = props;
90
+ return {
91
+ props: rest,
92
+ source
93
+ };
94
+ };
82
95
  /**
83
96
  * The automatic-runtime entry point. `type` is always one of our typed
84
97
  * component functions (or `Fragment`); we invoke it with its props. The JSX
@@ -91,7 +104,13 @@ const jsx = (type, props) => {
91
104
  kind: "fragment",
92
105
  children: normalizeChildren(props.children)
93
106
  };
94
- return type(props);
107
+ const { props: cleanProps, source } = stripSourceLocation(props);
108
+ const result = type(cleanProps);
109
+ if (source !== void 0 && result.kind === "element") {
110
+ const location = completeJsxSourceLocation(source);
111
+ if (location !== void 0) attachJsxSourceLocation(result, location);
112
+ }
113
+ return result;
95
114
  };
96
115
  const jsxs = jsx;
97
116
  /** Groups children without an element wrapper. Its children splice into the parent. */
package/dist/model.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as SmlDocument, D as SmlTag } from "./ast-DAhnAvQN.js";
1
+ import { O as SmlTag, w as SmlDocument } from "./ast-63I-VLQx.js";
2
2
  import { Result, Schema } from "effect";
3
3
  //#region src/model.d.ts
4
4
  declare const SmlNodeKeyAttrsSchema: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Finite]>>;
package/dist/ops.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { o as SmlParseError } from "./diagnostics-oveE-laV.js";
2
- import { T as SmlNode } from "./ast-DAhnAvQN.js";
2
+ import { E as SmlNode } from "./ast-63I-VLQx.js";
3
3
  import { Result, Schema } from "effect";
4
4
  //#region src/ops.d.ts
5
5
  /**
package/dist/ops.js CHANGED
@@ -2,7 +2,7 @@ import { DiagnosticSchema } from "./diagnostics.js";
2
2
  import { AttributeValueSchema, SML_TAGS, SmlNodeSchema, documentChannel } from "./ast.js";
3
3
  import { CHANNEL_TAG_SPECS, allowedChildren, parseSml } from "./parser.js";
4
4
  import { compileSml } from "./compile.js";
5
- import { i as isBreakingCompatibilityCheck, n as checkSmlCompatibility } from "./checks-D-zFQt5R.js";
5
+ import { a as isBreakingCompatibilityCheck, r as checkSmlCompatibility } from "./checks-DXuERO4B.js";
6
6
  import { printSml } from "./printer.js";
7
7
  import { Result, Schema } from "effect";
8
8
  //#region src/ops.ts
@@ -1,5 +1,5 @@
1
1
  import { o as SmlParseError } from "./diagnostics-oveE-laV.js";
2
- import { C as SmlDocument, D as SmlTag, d as Channel } from "./ast-DAhnAvQN.js";
2
+ import { O as SmlTag, d as Channel, w as SmlDocument } from "./ast-63I-VLQx.js";
3
3
  import { Result } from "effect";
4
4
  //#region src/limits.d.ts
5
5
  /** Hard ceilings shared by SML documents and standalone predicate parsing. */
@@ -393,4 +393,4 @@ declare const allowedChildren: (model: ContentModel) => ReadonlyArray<SmlTag>;
393
393
  declare const parseSml: (source: string) => Result.Result<SmlDocument, SmlParseError>;
394
394
  //#endregion
395
395
  export { SMS_TAG_SPECS as a, UNIVERSAL_ATTRIBUTE_TAGS as c, parseSml as d, SML_PARSER_LIMITS as f, EMAIL_TAG_SPECS as i, WHATSAPP_TAG_SPECS as l, CHANNEL_TAG_SPECS as n, TagSpec as o, ContentModel as r, UNIVERSAL_ATTRIBUTES as s, AttributeSpec as t, allowedChildren as u };
396
- //# sourceMappingURL=parser-DkQKIjDa.d.ts.map
396
+ //# sourceMappingURL=parser-CGBS73Gz.d.ts.map
package/dist/parser.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as SMS_TAG_SPECS, c as UNIVERSAL_ATTRIBUTE_TAGS, d as parseSml, f as SML_PARSER_LIMITS, i as EMAIL_TAG_SPECS, l as WHATSAPP_TAG_SPECS, n as CHANNEL_TAG_SPECS, o as TagSpec, r as ContentModel, s as UNIVERSAL_ATTRIBUTES, t as AttributeSpec, u as allowedChildren } from "./parser-DkQKIjDa.js";
1
+ import { a as SMS_TAG_SPECS, c as UNIVERSAL_ATTRIBUTE_TAGS, d as parseSml, f as SML_PARSER_LIMITS, i as EMAIL_TAG_SPECS, l as WHATSAPP_TAG_SPECS, n as CHANNEL_TAG_SPECS, o as TagSpec, r as ContentModel, s as UNIVERSAL_ATTRIBUTES, t as AttributeSpec, u as allowedChildren } from "./parser-CGBS73Gz.js";
2
2
  export { AttributeSpec, CHANNEL_TAG_SPECS, ContentModel, EMAIL_TAG_SPECS, SML_PARSER_LIMITS, SMS_TAG_SPECS, TagSpec, UNIVERSAL_ATTRIBUTES, UNIVERSAL_ATTRIBUTE_TAGS, WHATSAPP_TAG_SPECS, allowedChildren, parseSml };
@@ -1,5 +1,5 @@
1
1
  import { PresetCategory } from "../presets.js";
2
- import { i as TemplateCollectionId } from "../public-gallery-D0Zv0pZE.js";
2
+ import { TemplateCollectionId } from "./public-gallery.js";
3
3
  //#region presets/category-mapping.d.ts
4
4
  declare const LAB_DIMENSIONS: readonly ["newsletter", "receipt", "security", "product-update", "onboarding", "promotion", "shipping", "social-notification"];
5
5
  type LabDimension = (typeof LAB_DIMENSIONS)[number];
@@ -0,0 +1,2 @@
1
+ import { a as PublicCorpusRegistrationIssue, c as TemplateFacetQuery, d as matchesTemplateFacets, f as ownedPresetSourcePath, h as templateFacetOptions, i as PublicCorpusRegistration, l as TemplateFacetSet, m as registerPublicCorpusEntry, n as InspirationReference, o as TemplateCorpusKind, p as ownedShowcasePresetSources, r as OwnedEditablePreset, s as TemplateCorpusRecord, t as BrandRecreationPreset, u as brandRecreationProvenance } from "../corpus-qrUD5O6r.js";
2
+ export { BrandRecreationPreset, InspirationReference, OwnedEditablePreset, PublicCorpusRegistration, PublicCorpusRegistrationIssue, TemplateCorpusKind, TemplateCorpusRecord, TemplateFacetQuery, TemplateFacetSet, brandRecreationProvenance, matchesTemplateFacets, ownedPresetSourcePath, ownedShowcasePresetSources, registerPublicCorpusEntry, templateFacetOptions };