schema-components 1.21.0 → 1.22.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/README.md +1 -1
- package/dist/core/adapter.d.mts +20 -3
- package/dist/core/adapter.mjs +209 -28
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +22 -1
- package/dist/core/formats.mjs +21 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +1 -1
- package/dist/core/normalise.d.mts +29 -3
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.mjs +1 -1
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/ref.mjs +1 -0
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +0 -2
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +2 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/version.d.mts +1 -1
- package/dist/core/walkBuilders.d.mts +3 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +79 -2
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-D0QCYGv0.d.mts} +1 -1
- package/dist/{errors-QEwOtQAA.d.mts → errors-DpFwqs5C.d.mts} +1 -1
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/a11y.mjs +10 -3
- package/dist/html/renderToHtml.d.mts +10 -3
- package/dist/html/renderToHtml.mjs +13 -3
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +0 -5
- package/dist/html/streamRenderers.d.mts +5 -4
- package/dist/html/streamRenderers.mjs +91 -30
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-DaSrnr8g.mjs → normalise-DVEJQmF7.mjs} +468 -115
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/ApiSecurity.mjs +16 -2
- package/dist/openapi/components.d.mts +150 -18
- package/dist/openapi/components.mjs +129 -15
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +35 -3
- package/dist/openapi/resolve.d.mts +12 -5
- package/dist/openapi/resolve.mjs +183 -23
- package/dist/react/SchemaComponent.d.mts +100 -35
- package/dist/react/SchemaComponent.mjs +59 -45
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/SchemaView.mjs +2 -2
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headless.mjs +1 -2
- package/dist/react/headlessRenderers.d.mts +3 -4
- package/dist/react/headlessRenderers.mjs +10 -30
- package/dist/{ref-si8ViYun.d.mts → ref-D-_JBZkF.d.mts} +1 -1
- package/dist/{renderer-DI6ZYf7a.d.mts → renderer-BaRlQIuN.d.mts} +2 -2
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/typeInference-DkcUHfaM.d.mts +982 -0
- package/dist/{types-BnxPEElk.d.mts → types-BrRMV0en.d.mts} +3 -10
- package/package.json +1 -3
- package/dist/typeInference-Bxw3NOG1.d.mts +0 -647
- /package/dist/{version-D-u7aMfy.d.mts → version-D2jfdX6E.d.mts} +0 -0
package/dist/core/swagger2.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { s as normaliseSwagger2Document } from "../normalise-DVEJQmF7.mjs";
|
|
2
2
|
export { normaliseSwagger2Document };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { DEFAULT_MAX_DEPTH, FromJSONSchema, InferParameterOverrides, InferRequestBodyFields, InferResponseFields, OpenAPIRequestBodyType, OpenAPIResponseType, PathOfType, RejectUnrepresentableZod, ResolveOpenAPIRef, TypeAtPath, UnrepresentableZodSchemaError, UnrepresentableZodType, UnsafeFields, __SchemaInferenceFellBack };
|
|
1
|
+
import { _ as __SchemaInferenceFellBack, a as InferParameterOverrides, c as OpenAPIRequestBodyType, d as RejectUnrepresentableZod, f as ResolveOpenAPIRef, g as UnsafeFields, h as UnrepresentableZodType, i as FromJSONSchemaMode, l as OpenAPIResponseType, m as UnrepresentableZodSchemaError, n as DEFAULT_OPENAPI_CONTENT_TYPE, o as InferRequestBodyFields, p as TypeAtPath, r as FromJSONSchema, s as InferResponseFields, t as DEFAULT_MAX_DEPTH, u as PathOfType } from "../typeInference-DkcUHfaM.mjs";
|
|
2
|
+
export { DEFAULT_MAX_DEPTH, DEFAULT_OPENAPI_CONTENT_TYPE, FromJSONSchema, FromJSONSchemaMode, InferParameterOverrides, InferRequestBodyFields, InferResponseFields, OpenAPIRequestBodyType, OpenAPIResponseType, PathOfType, RejectUnrepresentableZod, ResolveOpenAPIRef, TypeAtPath, UnrepresentableZodSchemaError, UnrepresentableZodType, UnsafeFields, __SchemaInferenceFellBack };
|
package/dist/core/types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { ArrayConstraints, ArrayField, BooleanField, ConditionalField, DiscriminatedUnionField, Editability, EnumField, FieldBase, FieldConstraints, FieldOverride, FieldOverrides, FileConstraints, FileField, JsonObject, LiteralField, NegationField, NeverField, NullField, NumberConstraints, NumberField, ObjectConstraints, ObjectField, RecordField,
|
|
1
|
+
import { A as UnknownField, B as isNeverField, C as RecordField, D as StringField, E as StringConstraints, F as isDiscriminatedUnionField, G as isStringField, H as isNumberField, I as isEnumField, J as isUnknownField, K as isTupleField, L as isFileField, M as isArrayField, N as isBooleanField, O as TupleField, P as isConditionalField, R as isLiteralField, S as ObjectField, T as SchemaType, U as isObjectField, V as isNullField, W as isRecordField, Y as resolveEditability, _ as NeverField, a as DiscriminatedUnionField, b as NumberField, c as FieldBase, d as FieldOverrides, f as FileConstraints, g as NegationField, h as LiteralField, i as ConditionalField, j as WalkedField, k as UnionField, l as FieldConstraints, m as JsonObject, n as ArrayField, o as Editability, p as FileField, q as isUnionField, r as BooleanField, s as EnumField, t as ArrayConstraints, u as FieldOverride, v as NullField, w as SchemaMeta, x as ObjectConstraints, y as NumberConstraints, z as isNegationField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
export { ArrayConstraints, ArrayField, BooleanField, ConditionalField, DiscriminatedUnionField, Editability, EnumField, FieldBase, FieldConstraints, FieldOverride, FieldOverrides, FileConstraints, FileField, JsonObject, LiteralField, NegationField, NeverField, NullField, NumberConstraints, NumberField, ObjectConstraints, ObjectField, RecordField, SchemaMeta, SchemaType, StringConstraints, StringField, TupleField, UnionField, UnknownField, WalkedField, isArrayField, isBooleanField, isConditionalField, isDiscriminatedUnionField, isEnumField, isFileField, isLiteralField, isNegationField, isNeverField, isNullField, isNumberField, isObjectField, isRecordField, isStringField, isTupleField, isUnionField, isUnknownField, resolveEditability };
|
package/dist/core/types.mjs
CHANGED
|
@@ -83,9 +83,6 @@ function isNegationField(field) {
|
|
|
83
83
|
function isFileField(field) {
|
|
84
84
|
return isField(field, "file");
|
|
85
85
|
}
|
|
86
|
-
function isRecursiveField(field) {
|
|
87
|
-
return isField(field, "recursive");
|
|
88
|
-
}
|
|
89
86
|
function isNeverField(field) {
|
|
90
87
|
return isField(field, "never");
|
|
91
88
|
}
|
|
@@ -93,4 +90,4 @@ function isUnknownField(field) {
|
|
|
93
90
|
return isField(field, "unknown");
|
|
94
91
|
}
|
|
95
92
|
//#endregion
|
|
96
|
-
export { isArrayField, isBooleanField, isConditionalField, isDiscriminatedUnionField, isEnumField, isFileField, isLiteralField, isNegationField, isNeverField, isNullField, isNumberField, isObjectField, isRecordField,
|
|
93
|
+
export { isArrayField, isBooleanField, isConditionalField, isDiscriminatedUnionField, isEnumField, isFileField, isLiteralField, isNegationField, isNeverField, isNullField, isNumberField, isObjectField, isRecordField, isStringField, isTupleField, isUnionField, isUnknownField, resolveEditability };
|
package/dist/core/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as detectJsonSchemaDraft, c as inferJsonSchemaDraftWithReason, d as isSwagger2, f as matchJsonSchemaDraftUri, i as OpenApiVersionInfo, l as isOpenApi30, n as JsonSchemaDialectInfo, o as detectOpenApiVersion, p as readJsonSchemaDialect, r as JsonSchemaDraft, s as inferJsonSchemaDraft, t as InferredDraft, u as isOpenApi31 } from "../version-
|
|
1
|
+
import { a as detectJsonSchemaDraft, c as inferJsonSchemaDraftWithReason, d as isSwagger2, f as matchJsonSchemaDraftUri, i as OpenApiVersionInfo, l as isOpenApi30, n as JsonSchemaDialectInfo, o as detectOpenApiVersion, p as readJsonSchemaDialect, r as JsonSchemaDraft, s as inferJsonSchemaDraft, t as InferredDraft, u as isOpenApi31 } from "../version-D2jfdX6E.mjs";
|
|
2
2
|
export { InferredDraft, JsonSchemaDialectInfo, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri, readJsonSchemaDialect };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as DiagnosticsOptions } from "../diagnostics-
|
|
3
|
-
import { t as ExternalResolver } from "../ref-
|
|
1
|
+
import { A as UnknownField, D as StringField, b as NumberField, c as FieldBase, j as WalkedField, o as Editability, p as FileField, r as BooleanField, v as NullField, w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
|
|
3
|
+
import { t as ExternalResolver } from "../ref-D-_JBZkF.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/core/walkBuilders.d.ts
|
|
6
6
|
declare function getString(obj: Record<string, unknown>, key: string): string | undefined;
|
package/dist/core/walker.d.mts
CHANGED
package/dist/core/walker.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { isObject } from "./guards.mjs";
|
|
|
2
2
|
import { appendPointer, emitDiagnostic } from "./diagnostics.mjs";
|
|
3
3
|
import { isPrototypePollutingKey } from "./uri.mjs";
|
|
4
4
|
import { countDistinctRefs, resolveRef } from "./ref.mjs";
|
|
5
|
+
import { matchJsonSchemaDraftUri } from "./version.mjs";
|
|
5
6
|
import { extractArrayConstraints, extractObjectConstraints, stripInapplicableConstraints } from "./constraints.mjs";
|
|
6
7
|
import { ANNOTATION_SIBLINGS, detectDiscriminated, mergeAllOf, mergeRefSiblings, normaliseAnyOf } from "./merge.mjs";
|
|
7
8
|
import { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys } from "./walkBuilders.mjs";
|
|
@@ -40,6 +41,55 @@ function walkSubSchema(value, ctx) {
|
|
|
40
41
|
constraints: {}
|
|
41
42
|
};
|
|
42
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Rank an `unevaluatedProperties`/`unevaluatedItems` value by how
|
|
46
|
+
* restrictive it is. Higher is stricter. The ordering reflects
|
|
47
|
+
* JSON Schema 2020-12 §11.2/§11.3 semantics:
|
|
48
|
+
*
|
|
49
|
+
* false (forbid all extras)
|
|
50
|
+
* > schema-object (extras must match the schema)
|
|
51
|
+
* > true (extras explicitly permitted)
|
|
52
|
+
* > absent (extras implicitly permitted)
|
|
53
|
+
*
|
|
54
|
+
* Unknown shapes (numbers, arrays, strings) sort below absent — we
|
|
55
|
+
* cannot reason about them, so do not let them override anything.
|
|
56
|
+
*/
|
|
57
|
+
function unevaluatedRank(value) {
|
|
58
|
+
if (value === false) return 3;
|
|
59
|
+
if (isObject(value)) return 2;
|
|
60
|
+
if (value === true) return 1;
|
|
61
|
+
if (value === void 0) return 0;
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Pick the strictest `unevaluatedProperties` / `unevaluatedItems` across
|
|
66
|
+
* a set of `allOf` branches (including the parent prepended as a
|
|
67
|
+
* branch) and apply it to the merged node. `mergeAllOf` already collects
|
|
68
|
+
* properties from every branch into the merged result; surfacing the
|
|
69
|
+
* strictest unevaluated keyword closes the loop so the walker's object
|
|
70
|
+
* builder sees the spec-correct value.
|
|
71
|
+
*
|
|
72
|
+
* The merged node is mutated in place — that is consistent with the
|
|
73
|
+
* surrounding walker code, which treats the merge output as a fresh
|
|
74
|
+
* working node.
|
|
75
|
+
*/
|
|
76
|
+
function applyStrictestUnevaluated(merged, branches) {
|
|
77
|
+
let strictestProps = merged.unevaluatedProperties;
|
|
78
|
+
let strictestItems = merged.unevaluatedItems;
|
|
79
|
+
for (const branch of branches) {
|
|
80
|
+
if (!isObject(branch)) continue;
|
|
81
|
+
if ("unevaluatedProperties" in branch) {
|
|
82
|
+
const candidate = branch.unevaluatedProperties;
|
|
83
|
+
if (unevaluatedRank(candidate) > unevaluatedRank(strictestProps)) strictestProps = candidate;
|
|
84
|
+
}
|
|
85
|
+
if ("unevaluatedItems" in branch) {
|
|
86
|
+
const candidate = branch.unevaluatedItems;
|
|
87
|
+
if (unevaluatedRank(candidate) > unevaluatedRank(strictestItems)) strictestItems = candidate;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (strictestProps !== void 0) merged.unevaluatedProperties = strictestProps;
|
|
91
|
+
if (strictestItems !== void 0) merged.unevaluatedItems = strictestItems;
|
|
92
|
+
}
|
|
43
93
|
function walk(schema, options = {}) {
|
|
44
94
|
const { componentMeta, rootMeta, fieldOverrides, rootDocument, diagnostics, externalResolver } = options;
|
|
45
95
|
if (typeof schema === "boolean") return walkBooleanSchema(schema);
|
|
@@ -76,8 +126,10 @@ function walk(schema, options = {}) {
|
|
|
76
126
|
function walkNode(schema, ctx) {
|
|
77
127
|
const allOf = getArray(schema, "allOf");
|
|
78
128
|
if (allOf !== void 0 && allOf.length > 0) {
|
|
79
|
-
const
|
|
129
|
+
const branches = [withoutKeys(schema, ["allOf"]), ...allOf];
|
|
130
|
+
const merged = mergeAllOf(branches, ctx.diagnostics, ctx.pointer);
|
|
80
131
|
if (merged === false) return walkBooleanSchema(false);
|
|
132
|
+
applyStrictestUnevaluated(merged, branches);
|
|
81
133
|
return walkNode(merged, ctx);
|
|
82
134
|
}
|
|
83
135
|
const anyOf = getArray(schema, "anyOf");
|
|
@@ -227,11 +279,36 @@ function walkNode(schema, ctx) {
|
|
|
227
279
|
});
|
|
228
280
|
return buildUnknownField(schema, ctx);
|
|
229
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Drafts that pre-date the `contentSchema` keyword (added in Draft
|
|
284
|
+
* 2019-09). Used to emit `keyword-out-of-draft` when a document
|
|
285
|
+
* declaring one of these drafts uses `contentSchema` anyway.
|
|
286
|
+
*/
|
|
287
|
+
const PRE_CONTENT_SCHEMA_DRAFTS = new Set([
|
|
288
|
+
"draft-04",
|
|
289
|
+
"draft-06",
|
|
290
|
+
"draft-07"
|
|
291
|
+
]);
|
|
230
292
|
function walkString(schema, ctx) {
|
|
231
293
|
if (getString(schema, "format") === "binary") return buildFileField(schema, ctx);
|
|
232
294
|
const field = buildStringField(schema, ctx);
|
|
233
295
|
const contentSchema = getObject(schema, "contentSchema");
|
|
234
|
-
if (contentSchema !== void 0)
|
|
296
|
+
if (contentSchema !== void 0) {
|
|
297
|
+
const rootSchema = getString(ctx.rootDocument, "$schema");
|
|
298
|
+
if (rootSchema !== void 0) {
|
|
299
|
+
const draft = matchJsonSchemaDraftUri(rootSchema);
|
|
300
|
+
if (draft !== void 0 && PRE_CONTENT_SCHEMA_DRAFTS.has(draft)) emitDiagnostic(ctx.diagnostics, {
|
|
301
|
+
code: "keyword-out-of-draft",
|
|
302
|
+
message: `\`contentSchema\` is a Draft 2019-09+ keyword; the document declares ${draft}`,
|
|
303
|
+
pointer: appendPointer(ctx.pointer, "contentSchema"),
|
|
304
|
+
detail: {
|
|
305
|
+
keyword: "contentSchema",
|
|
306
|
+
declaredDraft: draft
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
field.meta.decodedSchema = walkNode(contentSchema, ctx);
|
|
311
|
+
}
|
|
235
312
|
return field;
|
|
236
313
|
}
|
|
237
314
|
function walkNumber(schema, ctx) {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Machine-readable codes identifying each class of diagnostic.
|
|
17
17
|
* Stable across releases — consumers can pattern-match on these.
|
|
18
18
|
*/
|
|
19
|
-
type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "unsupported-type" | "dropped-swagger-feature" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "legacy-dependencies-split" | "dependent-required-invalid" | "unknown-json-schema-dialect" | "relative-ref-resolved" | "bare-exclusive-bound" | "enum-value-filtered" | "required-non-string" | "pattern-invalid" | "duplicate-body-parameter" | "prototype-polluting-property";
|
|
19
|
+
type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "invalid-id-fragment" | "unsupported-type" | "dropped-swagger-feature" | "dynamic-ref-degraded" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "keyword-out-of-draft" | "legacy-dependencies-split" | "dependent-required-invalid" | "unknown-json-schema-dialect" | "unknown-openapi-version" | "relative-ref-resolved" | "bare-exclusive-bound" | "enum-value-filtered" | "required-non-string" | "pattern-invalid" | "duplicate-body-parameter" | "prototype-polluting-property" | "cross-schema-relative-ref-unsupported" | "cyclic-path-item-ref" | "doc-not-object" | "path-item-ref-too-deep" | "swagger-cyclic-parameter-ref" | "swagger-invalid-file-parameter" | "swagger-missing-consumes" | "swagger-missing-host" | "type-mismatch" | "unknown-security-scheme-type" | "zod-codec-output-only";
|
|
20
20
|
/**
|
|
21
21
|
* A single diagnostic emitted during schema processing.
|
|
22
22
|
*/
|
|
@@ -32,7 +32,7 @@ declare class SchemaError extends Error {
|
|
|
32
32
|
* JSON Schema, missing OpenAPI ref, unsupported ref format.
|
|
33
33
|
*/
|
|
34
34
|
declare class SchemaNormalisationError extends SchemaError {
|
|
35
|
-
readonly kind: "invalid-zod" | "zod3-unsupported" | "zod-transform-unsupported" | "zod-type-unrepresentable" | "zod-conversion-failed" | "zod-conversion-bug" | "zod-cycle-detected" | "zod-duplicate-id" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
|
|
35
|
+
readonly kind: "invalid-zod" | "unsupported-schema" | "zod3-unsupported" | "zod-transform-unsupported" | "zod-type-unrepresentable" | "zod-conversion-failed" | "zod-conversion-bug" | "zod-cycle-detected" | "zod-duplicate-id" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
|
|
36
36
|
/**
|
|
37
37
|
* For `zod-type-unrepresentable`, the offending Zod type name
|
|
38
38
|
* (e.g. "bigint", "date", "map", "set"). `undefined` for other kinds.
|
package/dist/html/a11y.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as AllConstraints } from "../renderer-
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { t as AllConstraints } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
import { HtmlAttributes, HtmlNode } from "./html.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/html/a11y.d.ts
|
package/dist/html/a11y.mjs
CHANGED
|
@@ -18,11 +18,18 @@ function joinPath(parent, suffix) {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Normalise a path into the id segment used after the `sc-` prefix.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
*
|
|
22
|
+
* Whitelist-based: every character outside `[A-Za-z0-9_-]` collapses to
|
|
23
|
+
* a single hyphen. A blacklist that only stripped `.[]` would still leak
|
|
24
|
+
* spaces, slashes, and other punctuation through into ids when a path
|
|
25
|
+
* is sourced from a free-text field like `meta.description` — producing
|
|
26
|
+
* structurally invalid CSS selectors and `aria-labelledby` references.
|
|
27
|
+
*
|
|
28
|
+
* Trailing hyphens are trimmed so e.g. `tags[0]` → `tags-0` (not
|
|
29
|
+
* `tags-0-`).
|
|
23
30
|
*/
|
|
24
31
|
function normaliseIdSegment(value) {
|
|
25
|
-
return value.replace(/[
|
|
32
|
+
return value.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/-+$/g, "");
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
35
|
* Build the input ID for a field at a given path.
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtml.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build the recursion-cap sentinel element. The label is interpolated
|
|
7
|
+
* via `h()` + `serialize` so any HTML in `meta.description` (which is
|
|
8
|
+
* schema-author content but can equally be sourced from user-supplied
|
|
9
|
+
* JSON Schema input) is escaped — never interpolated into raw markup.
|
|
10
|
+
*/
|
|
11
|
+
declare function recursionSentinelHtml(label: string): string;
|
|
5
12
|
interface RenderToHtmlOptions {
|
|
6
13
|
/** The data value to render. */
|
|
7
14
|
value?: unknown;
|
|
@@ -29,4 +36,4 @@ interface RenderToHtmlOptions {
|
|
|
29
36
|
*/
|
|
30
37
|
declare function renderToHtml(schema: unknown, options?: RenderToHtmlOptions): string;
|
|
31
38
|
//#endregion
|
|
32
|
-
export { RenderToHtmlOptions, renderToHtml };
|
|
39
|
+
export { RenderToHtmlOptions, recursionSentinelHtml, renderToHtml };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import "../core/limits.mjs";
|
|
1
2
|
import { normaliseSchema } from "../core/adapter.mjs";
|
|
2
3
|
import { getHtmlRenderFn, mergeHtmlResolvers } from "../core/renderer.mjs";
|
|
3
4
|
import { walk } from "../core/walker.mjs";
|
|
5
|
+
import { h, serialize } from "./html.mjs";
|
|
4
6
|
import { joinPath } from "./a11y.mjs";
|
|
5
7
|
import { defaultHtmlResolver } from "./renderers.mjs";
|
|
6
8
|
//#region src/html/renderToHtml.ts
|
|
@@ -25,6 +27,15 @@ import { defaultHtmlResolver } from "./renderers.mjs";
|
|
|
25
27
|
* });
|
|
26
28
|
*/
|
|
27
29
|
/**
|
|
30
|
+
* Build the recursion-cap sentinel element. The label is interpolated
|
|
31
|
+
* via `h()` + `serialize` so any HTML in `meta.description` (which is
|
|
32
|
+
* schema-author content but can equally be sourced from user-supplied
|
|
33
|
+
* JSON Schema input) is escaped — never interpolated into raw markup.
|
|
34
|
+
*/
|
|
35
|
+
function recursionSentinelHtml(label) {
|
|
36
|
+
return serialize(h("fieldset", { class: "sc-recursive" }, h("em", {}, `↻ ${label} (recursive)`)));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
28
39
|
* Render a schema to an HTML string.
|
|
29
40
|
*
|
|
30
41
|
* @param schema - Zod schema, JSON Schema, or OpenAPI document
|
|
@@ -44,9 +55,8 @@ function renderToHtml(schema, options = {}) {
|
|
|
44
55
|
rootDocument
|
|
45
56
|
});
|
|
46
57
|
const resolver = options.resolver ?? defaultHtmlResolver;
|
|
47
|
-
const MAX_HTML_DEPTH = 10;
|
|
48
58
|
const makeRenderChild = (currentDepth, parentPath) => (childTree, childValue, pathSuffix) => {
|
|
49
|
-
if (currentDepth >=
|
|
59
|
+
if (currentDepth >= 10) return recursionSentinelHtml(typeof childTree.meta.description === "string" ? childTree.meta.description : "schema");
|
|
50
60
|
const childPath = joinPath(parentPath, pathSuffix);
|
|
51
61
|
return renderFieldHtml(childTree, childValue, resolver, childPath, makeRenderChild(currentDepth + 1, childPath));
|
|
52
62
|
};
|
|
@@ -73,4 +83,4 @@ function renderFieldHtml(tree, value, resolver, path, renderChild) {
|
|
|
73
83
|
return renderFn(props);
|
|
74
84
|
}
|
|
75
85
|
//#endregion
|
|
76
|
-
export { renderToHtml };
|
|
86
|
+
export { recursionSentinelHtml, renderToHtml };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtmlStream.d.ts
|
|
5
5
|
interface StreamRenderOptions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderers.d.ts
|
|
5
5
|
declare function dateInputType(format: string | undefined): string | undefined;
|
package/dist/html/renderers.mjs
CHANGED
|
@@ -334,10 +334,6 @@ function renderFileHtml(props) {
|
|
|
334
334
|
if (typeof props.meta.description === "string") Object.assign(attrs, ariaLabelAttrs(props.meta.description));
|
|
335
335
|
return serialize(h("input", attrs));
|
|
336
336
|
}
|
|
337
|
-
function renderRecursiveHtml(props) {
|
|
338
|
-
const refTarget = props.tree.type === "recursive" ? props.tree.refTarget : "";
|
|
339
|
-
return serialize(h("fieldset", { class: "sc-recursive" }, `↻ ${typeof props.meta.description === "string" ? props.meta.description : refTarget} (recursive)`));
|
|
340
|
-
}
|
|
341
337
|
function renderUnknownHtml(props) {
|
|
342
338
|
if (props.readOnly) {
|
|
343
339
|
if (props.value === void 0 || props.value === null) return serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
@@ -433,7 +429,6 @@ const defaultHtmlResolver = {
|
|
|
433
429
|
discriminatedUnion: renderDiscriminatedUnionHtml,
|
|
434
430
|
conditional: renderConditionalHtml,
|
|
435
431
|
negation: renderNegationHtml,
|
|
436
|
-
recursive: renderRecursiveHtml,
|
|
437
432
|
file: renderFileHtml,
|
|
438
433
|
never: renderNeverHtml,
|
|
439
434
|
unknown: renderUnknownHtml
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
|
|
3
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
4
|
import { HtmlElement } from "./html.mjs";
|
|
4
5
|
|
|
5
6
|
//#region src/html/streamRenderers.d.ts
|
|
6
7
|
declare function yieldOpen(el: HtmlElement): string;
|
|
7
8
|
declare function yieldClose(el: HtmlElement): string;
|
|
8
9
|
declare function renderLeaf(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string): string;
|
|
9
|
-
declare function renderFieldSync(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver): string;
|
|
10
|
+
declare function renderFieldSync(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver, currentDepth: number, diagnostics: DiagnosticsOptions | undefined): string;
|
|
10
11
|
declare function matchUnionOption(options: WalkedField[], value: unknown): WalkedField | undefined;
|
|
11
|
-
declare function streamField(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver): Iterable<string, void, undefined>;
|
|
12
|
+
declare function streamField(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver, currentDepth?: number, diagnostics?: DiagnosticsOptions): Iterable<string, void, undefined>;
|
|
12
13
|
//#endregion
|
|
13
14
|
export { matchUnionOption, renderFieldSync, renderLeaf, streamField, yieldClose, yieldOpen };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
+
import "../core/limits.mjs";
|
|
3
|
+
import { emitDiagnostic } from "../core/diagnostics.mjs";
|
|
2
4
|
import { getHtmlRenderFn } from "../core/renderer.mjs";
|
|
3
5
|
import { VOID_ELEMENTS, h, raw, serialize, serializeAttributes } from "./html.mjs";
|
|
4
|
-
import { ariaLabelAttrs, buildHintElement, buildInputId, requiredIndicator } from "./a11y.mjs";
|
|
6
|
+
import { ariaLabelAttrs, buildHintElement, buildInputId, joinPath, requiredIndicator } from "./a11y.mjs";
|
|
7
|
+
import { recursionSentinelHtml } from "./renderToHtml.mjs";
|
|
5
8
|
//#region src/html/streamRenderers.ts
|
|
6
9
|
function yieldOpen(el) {
|
|
7
10
|
const attrStr = serializeAttributes(el.attributes);
|
|
@@ -27,8 +30,8 @@ function renderLeaf(tree, value, mergedResolver, path) {
|
|
|
27
30
|
if (value === void 0 || value === null) return serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
28
31
|
return serialize(h("span", { class: "sc-value" }, typeof value === "string" ? value : JSON.stringify(value)));
|
|
29
32
|
}
|
|
30
|
-
function renderFieldSync(tree, value, mergedResolver, path, rawResolver) {
|
|
31
|
-
return [...streamField(tree, value, mergedResolver, path, rawResolver)].join("");
|
|
33
|
+
function renderFieldSync(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
34
|
+
return [...streamField(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics)].join("");
|
|
32
35
|
}
|
|
33
36
|
function matchUnionOption(options, value) {
|
|
34
37
|
if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
|
|
@@ -37,7 +40,26 @@ function matchUnionOption(options, value) {
|
|
|
37
40
|
if (Array.isArray(value)) return options.find((o) => o.type === "array");
|
|
38
41
|
if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
|
|
39
42
|
}
|
|
40
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Build a visible placeholder element used when a value does not match
|
|
45
|
+
* the shape implied by its field type. The expected-shape label is
|
|
46
|
+
* passed verbatim into `h()` so the serialiser escapes it.
|
|
47
|
+
*
|
|
48
|
+
* Streaming must keep producing output, so we never throw here — the
|
|
49
|
+
* diagnostic surfaces the problem to the caller (when a sink is wired)
|
|
50
|
+
* while the rendered output remains structurally valid.
|
|
51
|
+
*/
|
|
52
|
+
function typeMismatchPlaceholder(expectedShape) {
|
|
53
|
+
return serialize(h("span", {
|
|
54
|
+
class: "sc-value sc-value--invalid",
|
|
55
|
+
role: "alert"
|
|
56
|
+
}, `invalid value (expected ${expectedShape})`));
|
|
57
|
+
}
|
|
58
|
+
function* streamField(tree, value, mergedResolver, path, rawResolver, currentDepth = 0, diagnostics) {
|
|
59
|
+
if (currentDepth >= 10) {
|
|
60
|
+
yield recursionSentinelHtml(typeof tree.meta.description === "string" ? tree.meta.description : "schema");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
41
63
|
const effectiveValue = value ?? tree.defaultValue;
|
|
42
64
|
const type = tree.type;
|
|
43
65
|
if (type === "string" || type === "number" || type === "boolean" || type === "enum" || type === "literal" || type === "file" || type === "unknown") {
|
|
@@ -45,30 +67,44 @@ function* streamField(tree, value, mergedResolver, path, rawResolver) {
|
|
|
45
67
|
return;
|
|
46
68
|
}
|
|
47
69
|
if (type === "union") {
|
|
48
|
-
yield* streamUnion(tree, effectiveValue, mergedResolver, path, rawResolver);
|
|
70
|
+
yield* streamUnion(tree, effectiveValue, mergedResolver, path, rawResolver, currentDepth, diagnostics);
|
|
49
71
|
return;
|
|
50
72
|
}
|
|
51
73
|
if (type === "discriminatedUnion") {
|
|
52
|
-
yield* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolver);
|
|
74
|
+
yield* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics);
|
|
53
75
|
return;
|
|
54
76
|
}
|
|
55
77
|
if (type === "object") {
|
|
56
|
-
yield* streamObject(tree, value, mergedResolver, path, rawResolver);
|
|
78
|
+
yield* streamObject(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics);
|
|
57
79
|
return;
|
|
58
80
|
}
|
|
59
81
|
if (type === "array") {
|
|
60
|
-
yield* streamArray(tree, value, mergedResolver, path, rawResolver);
|
|
82
|
+
yield* streamArray(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics);
|
|
61
83
|
return;
|
|
62
84
|
}
|
|
63
85
|
if (type === "record") {
|
|
64
|
-
yield* streamRecord(tree, value, mergedResolver, path, rawResolver);
|
|
86
|
+
yield* streamRecord(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics);
|
|
65
87
|
return;
|
|
66
88
|
}
|
|
67
89
|
yield renderLeaf(tree, value, mergedResolver, path);
|
|
68
90
|
}
|
|
69
|
-
function* streamObject(tree, value, mergedResolver, path, rawResolver) {
|
|
91
|
+
function* streamObject(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
70
92
|
if (tree.type !== "object") return;
|
|
71
93
|
const fields = tree.fields;
|
|
94
|
+
if (value !== void 0 && value !== null && !isObject(value)) {
|
|
95
|
+
emitDiagnostic(diagnostics, {
|
|
96
|
+
code: "type-mismatch",
|
|
97
|
+
message: "Object schema received non-object value during streaming render",
|
|
98
|
+
pointer: path === "" ? "/" : `/${path}`,
|
|
99
|
+
detail: {
|
|
100
|
+
expected: "object",
|
|
101
|
+
actualType: typeof value,
|
|
102
|
+
path
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
yield typeMismatchPlaceholder("object");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
72
108
|
const obj = isObject(value) ? value : {};
|
|
73
109
|
const readOnly = tree.editability === "presentation";
|
|
74
110
|
const descriptionText = typeof tree.meta.description === "string" ? tree.meta.description : void 0;
|
|
@@ -82,7 +118,7 @@ function* streamObject(tree, value, mergedResolver, path, rawResolver) {
|
|
|
82
118
|
for (const [key, field] of Object.entries(fields)) {
|
|
83
119
|
const label = typeof field.meta.description === "string" ? field.meta.description : key;
|
|
84
120
|
const childValue = obj[key];
|
|
85
|
-
const childHtml = renderFieldSync(field, childValue, mergedResolver, key, rawResolver);
|
|
121
|
+
const childHtml = renderFieldSync(field, childValue, mergedResolver, joinPath(path, key), rawResolver, currentDepth + 1, diagnostics);
|
|
86
122
|
yield `${serialize(h("dt", { class: "sc-label" }, label))}${serialize(h("dd", { class: "sc-value" }, raw(childHtml)))}`;
|
|
87
123
|
}
|
|
88
124
|
yield yieldClose(dl);
|
|
@@ -96,7 +132,7 @@ function* streamObject(tree, value, mergedResolver, path, rawResolver) {
|
|
|
96
132
|
const label = typeof field.meta.description === "string" ? field.meta.description : key;
|
|
97
133
|
const fieldId = buildInputId(path, key);
|
|
98
134
|
const childValue = obj[key];
|
|
99
|
-
const childChunks = [...streamField(field, childValue, mergedResolver, key, rawResolver)].join("");
|
|
135
|
+
const childChunks = [...streamField(field, childValue, mergedResolver, joinPath(path, key), rawResolver, currentDepth + 1, diagnostics)].join("");
|
|
100
136
|
const required = requiredIndicator(field);
|
|
101
137
|
const labelContent = [label];
|
|
102
138
|
if (required !== void 0) labelContent.push(required);
|
|
@@ -111,29 +147,55 @@ function* streamObject(tree, value, mergedResolver, path, rawResolver) {
|
|
|
111
147
|
yield yieldClose(fieldset);
|
|
112
148
|
}
|
|
113
149
|
}
|
|
114
|
-
function* streamArray(tree, value, mergedResolver, path, rawResolver) {
|
|
115
|
-
const arr = Array.isArray(value) ? value : [];
|
|
150
|
+
function* streamArray(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
116
151
|
if (tree.type !== "array") return;
|
|
117
152
|
const element = tree.element;
|
|
118
153
|
if (element === void 0) return;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
if (value !== void 0 && value !== null && !Array.isArray(value)) {
|
|
155
|
+
emitDiagnostic(diagnostics, {
|
|
156
|
+
code: "type-mismatch",
|
|
157
|
+
message: "Array schema received non-array value during streaming render",
|
|
158
|
+
pointer: path === "" ? "/" : `/${path}`,
|
|
159
|
+
detail: {
|
|
160
|
+
expected: "array",
|
|
161
|
+
actualType: typeof value,
|
|
162
|
+
path
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
yield typeMismatchPlaceholder("array");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const arr = Array.isArray(value) ? value : [];
|
|
169
|
+
if (tree.editability === "presentation") {
|
|
122
170
|
const ul = h("ul", { class: "sc-array" });
|
|
123
171
|
yield yieldOpen(ul);
|
|
124
|
-
for (const item of arr) yield serialize(h("li", { class: "sc-item" }, raw(renderFieldSync(element, item, mergedResolver,
|
|
172
|
+
for (const [i, item] of arr.entries()) yield serialize(h("li", { class: "sc-item" }, raw(renderFieldSync(element, item, mergedResolver, joinPath(path, `[${String(i)}]`), rawResolver, currentDepth + 1, diagnostics))));
|
|
125
173
|
yield yieldClose(ul);
|
|
126
174
|
} else {
|
|
127
175
|
const div = h("div", { class: "sc-array" });
|
|
128
176
|
yield yieldOpen(div);
|
|
129
|
-
for (const item of arr) yield serialize(h("div", {}, raw(renderFieldSync(element, item, mergedResolver,
|
|
177
|
+
for (const [i, item] of arr.entries()) yield serialize(h("div", {}, raw(renderFieldSync(element, item, mergedResolver, joinPath(path, `[${String(i)}]`), rawResolver, currentDepth + 1, diagnostics))));
|
|
130
178
|
yield yieldClose(div);
|
|
131
179
|
}
|
|
132
180
|
}
|
|
133
|
-
function* streamRecord(tree, value, mergedResolver, path, rawResolver) {
|
|
134
|
-
const obj = isObject(value) ? value : {};
|
|
181
|
+
function* streamRecord(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
135
182
|
if (tree.type !== "record") return;
|
|
136
183
|
const valueType = tree.valueType;
|
|
184
|
+
if (value !== void 0 && value !== null && !isObject(value)) {
|
|
185
|
+
emitDiagnostic(diagnostics, {
|
|
186
|
+
code: "type-mismatch",
|
|
187
|
+
message: "Record schema received non-object value during streaming render",
|
|
188
|
+
pointer: path === "" ? "/" : `/${path}`,
|
|
189
|
+
detail: {
|
|
190
|
+
expected: "object",
|
|
191
|
+
actualType: typeof value,
|
|
192
|
+
path
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
yield typeMismatchPlaceholder("object");
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const obj = isObject(value) ? value : {};
|
|
137
199
|
const readOnly = tree.editability === "presentation";
|
|
138
200
|
const attrs = {
|
|
139
201
|
class: "sc-record",
|
|
@@ -143,7 +205,7 @@ function* streamRecord(tree, value, mergedResolver, path, rawResolver) {
|
|
|
143
205
|
const dl = h("dl", attrs);
|
|
144
206
|
yield yieldOpen(dl);
|
|
145
207
|
for (const [key, val] of Object.entries(obj)) {
|
|
146
|
-
const childHtml = renderFieldSync(valueType, val, mergedResolver, key, rawResolver);
|
|
208
|
+
const childHtml = renderFieldSync(valueType, val, mergedResolver, joinPath(path, key), rawResolver, currentDepth + 1, diagnostics);
|
|
147
209
|
yield `${serialize(h("dt", { class: "sc-label" }, key))}${serialize(h("dd", { class: "sc-value" }, raw(childHtml)))}`;
|
|
148
210
|
}
|
|
149
211
|
yield yieldClose(dl);
|
|
@@ -151,13 +213,13 @@ function* streamRecord(tree, value, mergedResolver, path, rawResolver) {
|
|
|
151
213
|
const container = h("div", attrs);
|
|
152
214
|
yield yieldOpen(container);
|
|
153
215
|
for (const [key, val] of Object.entries(obj)) {
|
|
154
|
-
const childHtml = renderFieldSync(valueType, val, mergedResolver, key, rawResolver);
|
|
216
|
+
const childHtml = renderFieldSync(valueType, val, mergedResolver, joinPath(path, key), rawResolver, currentDepth + 1, diagnostics);
|
|
155
217
|
yield serialize(h("div", { class: "sc-field" }, h("label", { class: "sc-label" }, key), raw(childHtml)));
|
|
156
218
|
}
|
|
157
219
|
yield yieldClose(container);
|
|
158
220
|
}
|
|
159
221
|
}
|
|
160
|
-
function* streamUnion(tree, value, mergedResolver, path, rawResolver) {
|
|
222
|
+
function* streamUnion(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
161
223
|
const options = tree.type === "union" ? tree.options : void 0;
|
|
162
224
|
if (options === void 0 || options.length === 0) {
|
|
163
225
|
if (value === void 0 || value === null) yield serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
@@ -165,10 +227,10 @@ function* streamUnion(tree, value, mergedResolver, path, rawResolver) {
|
|
|
165
227
|
return;
|
|
166
228
|
}
|
|
167
229
|
const target = matchUnionOption(options, value) ?? options[0];
|
|
168
|
-
if (target !== void 0) yield* streamField(target, value, mergedResolver,
|
|
230
|
+
if (target !== void 0) yield* streamField(target, value, mergedResolver, path, rawResolver, currentDepth + 1, diagnostics);
|
|
169
231
|
else yield serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
170
232
|
}
|
|
171
|
-
function* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolver) {
|
|
233
|
+
function* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolver, currentDepth, diagnostics) {
|
|
172
234
|
const options = tree.type === "discriminatedUnion" ? tree.options : void 0;
|
|
173
235
|
const discriminator = tree.type === "discriminatedUnion" ? tree.discriminator : void 0;
|
|
174
236
|
if (options === void 0 || options.length === 0) {
|
|
@@ -176,8 +238,7 @@ function* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolve
|
|
|
176
238
|
else yield serialize(h("span", { class: "sc-value" }, JSON.stringify(value)));
|
|
177
239
|
return;
|
|
178
240
|
}
|
|
179
|
-
const
|
|
180
|
-
const obj = isRecord(value) ? value : {};
|
|
241
|
+
const obj = isObject(value) ? value : {};
|
|
181
242
|
const discKey = discriminator ?? "";
|
|
182
243
|
const currentDiscriminatorValue = typeof obj[discKey] === "string" ? obj[discKey] : void 0;
|
|
183
244
|
const optionLabels = options.map((opt) => {
|
|
@@ -197,7 +258,7 @@ function* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolve
|
|
|
197
258
|
}
|
|
198
259
|
const activeOption = options[activeIndex];
|
|
199
260
|
if (tree.editability === "presentation") {
|
|
200
|
-
if (activeOption !== void 0) yield* streamField(activeOption, value, mergedResolver,
|
|
261
|
+
if (activeOption !== void 0) yield* streamField(activeOption, value, mergedResolver, path, rawResolver, currentDepth + 1, diagnostics);
|
|
201
262
|
return;
|
|
202
263
|
}
|
|
203
264
|
const panelId = `sc-${path}-panel`;
|
|
@@ -224,7 +285,7 @@ function* streamDiscriminatedUnion(tree, value, mergedResolver, path, rawResolve
|
|
|
224
285
|
"aria-labelledby": `sc-${path}-tab-${String(activeIndex)}`
|
|
225
286
|
});
|
|
226
287
|
yield yieldOpen(panelOpen);
|
|
227
|
-
if (activeOption !== void 0) yield* streamField(activeOption, value, mergedResolver,
|
|
288
|
+
if (activeOption !== void 0) yield* streamField(activeOption, value, mergedResolver, path, rawResolver, currentDepth + 1, diagnostics);
|
|
228
289
|
yield yieldClose(panelOpen);
|
|
229
290
|
yield yieldClose(wrapper);
|
|
230
291
|
}
|