@samva/markup 0.1.1 → 0.2.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.
- package/AGENTS.md +25 -5
- package/README.md +92 -26
- package/dist/{ast-DAhnAvQN.d.ts → ast-63I-VLQx.d.ts} +15 -2
- package/dist/ast.d.ts +2 -2
- package/dist/ast.js +15 -2
- package/dist/{checks-CW0nFj5n.js → checks-DXuERO4B.js} +37 -3
- package/dist/checks.d.ts +8 -1
- package/dist/checks.js +2 -2
- package/dist/compile-sms.d.ts +2 -2
- package/dist/compile-whatsapp.d.ts +2 -2
- package/dist/compile.d.ts +9 -84
- package/dist/compile.js +11 -920
- package/dist/compiler.d.ts +301 -0
- package/dist/compiler.js +1389 -0
- package/dist/components.d.ts +4 -4
- package/dist/conditionals.js +1 -1
- package/dist/corpus-Dz5irJ9x.d.ts +161 -0
- package/dist/diagnostics-Djd9ckLg.d.ts +90 -0
- package/dist/diagnostics.js +6 -3
- package/dist/elements-DtwKlFVH.d.ts +820 -0
- package/dist/email/components.d.ts +119 -0
- package/dist/email/components.js +207 -0
- package/dist/email/diagnostics.d.ts +2 -0
- package/dist/email/diagnostics.js +56 -0
- package/dist/email/elements.d.ts +2 -0
- package/dist/email/elements.js +299 -0
- package/dist/email/html.d.ts +42 -0
- package/dist/email/html.js +266 -0
- package/dist/email/jsx-dev-runtime.d.ts +26 -0
- package/dist/email/jsx-dev-runtime.js +12 -0
- package/dist/email/jsx-runtime.d.ts +2 -0
- package/dist/email/jsx-runtime.js +60 -0
- package/dist/email/render.d.ts +36 -0
- package/dist/email/render.js +6 -0
- package/dist/email/selection.d.ts +102 -0
- package/dist/email/selection.js +143 -0
- package/dist/email/source-edit.d.ts +67 -0
- package/dist/email/source-edit.js +185 -0
- package/dist/email/stylesheets.d.ts +2 -0
- package/dist/email/stylesheets.js +43 -0
- package/dist/email/text.d.ts +7 -0
- package/dist/email/text.js +92 -0
- package/dist/emit.d.ts +13 -12
- package/dist/emit.js +63 -63
- package/dist/input-schema-BIfzI63B.d.ts +23 -0
- package/dist/input-schema.d.ts +2 -0
- package/dist/input-schema.js +170 -0
- package/dist/jsx-dev-runtime.d.ts +4 -3
- package/dist/jsx-dev-runtime.js +9 -1
- package/dist/{jsx-runtime-fSxcvlx4.d.ts → jsx-runtime-C5k_Zq0A.d.ts} +4 -4
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +20 -1
- package/dist/model.d.ts +1 -1
- package/dist/ops.d.ts +1 -1
- package/dist/ops.js +2 -2
- package/dist/{parser-yzjUOGhc.d.ts → parser-CGBS73Gz.d.ts} +12 -3
- package/dist/parser.d.ts +2 -2
- package/dist/parser.js +48 -9
- package/dist/predicate-CvkzT-a2.js +539 -0
- package/dist/{predicate-DTtVtLK7.d.ts → predicate-G2SeSvoN.d.ts} +9 -2
- package/dist/predicate.d.ts +2 -2
- package/dist/predicate.js +2 -417
- package/dist/presets/corpus.d.ts +2 -0
- package/dist/presets/corpus.js +186 -0
- package/dist/presets/public-gallery.d.ts +241 -459
- package/dist/presets/public-gallery.js +305 -5
- package/dist/presets/public-handoff.d.ts +75 -3
- package/dist/presets/public-handoff.js +220 -37
- package/dist/presets/public-preview-artifacts.js +20 -26
- package/dist/presets/public-preview.d.ts +40 -1152
- package/dist/presets/public-preview.js +388 -1152
- package/dist/presets/sources.d.ts +17 -4
- package/dist/presets/sources.js +1212 -43
- package/dist/presets.d.ts +2 -2
- package/dist/printer.d.ts +1 -1
- package/dist/render-Cddsy_XF.js +585 -0
- package/dist/render-template.d.ts +6 -3
- package/dist/render-template.js +4 -2
- package/dist/source-locations-BCJQnIfU.d.ts +89 -0
- package/dist/source-locations.d.ts +2 -0
- package/dist/source-locations.js +125 -0
- package/dist/stylesheets-oDRAnYA3.d.ts +94 -0
- package/dist/template-Dy5yOPyp.d.ts +60 -0
- package/dist/template.d.ts +2 -0
- package/dist/template.js +37 -0
- package/dist/tsx-source-instrumentation.d.ts +23 -0
- package/dist/tsx-source-instrumentation.js +97 -0
- package/dist/tsx-tracer.d.ts +116 -0
- package/dist/tsx-tracer.js +985 -0
- package/dist/{variables-3NGLpNTB.d.ts → variables-if1VrV34.d.ts} +2 -2
- package/dist/variables.d.ts +1 -1
- package/dist/variables.js +1 -1
- package/generated/sml-agent-contract.json +574 -782
- package/generated/sml-email-agent-contract.json +502 -677
- package/generated/sml-email-language-reference.md +94 -160
- package/generated/sml-language-reference.md +195 -220
- package/package.json +111 -8
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
|
|
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
|
|
12
|
-
* runs
|
|
13
|
-
* renders
|
|
14
|
-
* RNG produces a different second emission and is reported as
|
|
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
|
-
*
|
|
17
|
-
*
|
|
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
|
-
*
|
|
22
|
+
* Default-export classification
|
|
21
23
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
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
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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
|
|
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
|
|
69
|
-
code: "
|
|
70
|
-
message: "no
|
|
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
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
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
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
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: [
|
|
98
|
+
diagnostics: [INVALID_DEFAULT]
|
|
106
99
|
};
|
|
100
|
+
const template = emitOne("default", value);
|
|
107
101
|
return {
|
|
108
|
-
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,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 {
|
|
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<
|
|
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
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -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
|
|
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,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { s as VariableRef } from "./variables-
|
|
1
|
+
import { E as SmlNode, m as ElementNode, n as Attribute } from "./ast-63I-VLQx.js";
|
|
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. */
|
|
5
5
|
type Component<P> = (props: P) => SmlNode;
|
|
@@ -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:
|
|
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-
|
|
57
|
+
//# sourceMappingURL=jsx-runtime-C5k_Zq0A.d.ts.map
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -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-
|
|
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 };
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -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
|
-
|
|
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 {
|
|
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
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 {
|
|
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
|
|
@@ -74,7 +74,7 @@ const ApplyOpsResultSchema = Schema.Struct({
|
|
|
74
74
|
diagnostics: Schema.Array(DiagnosticSchema),
|
|
75
75
|
results: Schema.Array(SmlOpResultSchema)
|
|
76
76
|
});
|
|
77
|
-
var SmlOpError = class extends Schema.
|
|
77
|
+
var SmlOpError = class extends Schema.TaggedError()("SmlOpError", { diagnostics: Schema.Array(DiagnosticSchema) }) {
|
|
78
78
|
get message() {
|
|
79
79
|
return this.diagnostics.map((diagnostic) => diagnostic.message).join("\n");
|
|
80
80
|
}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { o as SmlParseError } from "./diagnostics-oveE-laV.js";
|
|
2
|
-
import {
|
|
2
|
+
import { O as SmlTag, d as Channel, w as SmlDocument } from "./ast-63I-VLQx.js";
|
|
3
3
|
import { Result } from "effect";
|
|
4
|
+
//#region src/limits.d.ts
|
|
5
|
+
/** Hard ceilings shared by SML documents and standalone predicate parsing. */
|
|
6
|
+
declare const SML_PARSER_LIMITS: {
|
|
7
|
+
readonly maxCharacters: 500000;
|
|
8
|
+
readonly maxUtf8Bytes: number;
|
|
9
|
+
readonly maxDepth: 64;
|
|
10
|
+
readonly maxNodes: 25000;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
4
13
|
//#region src/parser.d.ts
|
|
5
14
|
type ContentModel = "email" | "block" | "columns" | "list" | "image" | "if" | "inline" | "inline-nolink" | "preview" | "whatsapp" | "buttons" | "verbatim" | "verbatim-if" | "void";
|
|
6
15
|
interface AttributeSpec {
|
|
@@ -383,5 +392,5 @@ declare const UNIVERSAL_ATTRIBUTE_TAGS: ReadonlySet<SmlTag>;
|
|
|
383
392
|
declare const allowedChildren: (model: ContentModel) => ReadonlyArray<SmlTag>;
|
|
384
393
|
declare const parseSml: (source: string) => Result.Result<SmlDocument, SmlParseError>;
|
|
385
394
|
//#endregion
|
|
386
|
-
export { SMS_TAG_SPECS as a, UNIVERSAL_ATTRIBUTE_TAGS as c, parseSml as d, 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 };
|
|
387
|
-
//# sourceMappingURL=parser-
|
|
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-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, 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-
|
|
2
|
-
export { AttributeSpec, CHANNEL_TAG_SPECS, ContentModel, EMAIL_TAG_SPECS, SMS_TAG_SPECS, TagSpec, UNIVERSAL_ATTRIBUTES, UNIVERSAL_ATTRIBUTE_TAGS, WHATSAPP_TAG_SPECS, allowedChildren, parseSml };
|
|
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
|
+
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 };
|