From e29a4670bf7dc7184135d3c8aa6447a89ed31a66 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 18:22:44 +0000 Subject: [PATCH 1/9] Clean up comment markers There is no need for full `{{/* ... */}}` comment markers here: simple `/* ... */` ones work fine. --- .../json-schema/resolve-additional-types.html | 46 ++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index c5d420b68..54e3366ec 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -1,5 +1,4 @@ -{{/* - +/* Finds and returns all objects, including nested ones, given a dict containing: * `schema`: a JSON schema object * `anchor_base`: a prefix to add to the HTML anchors generated for each object. If nil, no anchors are generated. @@ -19,8 +18,7 @@ * anchor: a string suitable for using as an html anchor for this object (if `anchor_base` was set, and the object has a title) Note that the returned array contains only unique objects. - -*/}} +*/ {{ $this_object := .schema }} {{ $anchor_base := .anchor_base }} @@ -28,19 +26,15 @@ {{ $name := .name | default $this_object.title | default "" }} {{ if eq $this_object.type "object" }} - {{/* give this object an anchor, if it has a name */}} + /* Give this object an anchor, if it has a name */ {{ if (and $anchor_base $this_object.title) }} {{ $this_object = merge $this_object (dict "anchor" (printf "%s_%s" $anchor_base (anchorize $this_object.title))) }} {{ end }} - {{/* - Add the object we were passed into the $all_objects array - */}} + /* Add the object we were passed into the $all_objects array */ {{ $all_objects = $all_objects | append $this_object }} - {{/* - Add any nested objects referenced in this object's `additionalProperties` - */}} + /* Add any nested objects referenced in this object's `additionalProperties` */ {{ if $this_object.additionalProperties }} {{ if reflect.IsMap $this_object.additionalProperties }} {{ $all_objects = partial "get-additional-objects" (dict @@ -52,9 +46,7 @@ {{ end }} {{ end }} - {{/* - Add any nested objects referenced in this object's `patternProperties` - */}} + /* Add any nested objects referenced in this object's `patternProperties` */ {{ if $this_object.patternProperties }} {{ range $pattern, $object := $this_object.patternProperties}} {{ $all_objects = partial "get-additional-objects" (dict @@ -66,9 +58,7 @@ {{ end }} {{ end }} - {{/* - Add any nested objects referenced in this object's `properties` - */}} + /* Add any nested objects referenced in this object's `properties` */ {{ range $key, $property := $this_object.properties}} {{ $all_objects = partial "get-additional-objects" (dict "this_object" $property @@ -77,13 +67,10 @@ "name" (printf "%s.%s" $name $key) ) }} {{ end }} - {{ end }} {{ if eq $this_object.type "array" }} - {{/* - Add any nested objects referenced in this object's `items` - */}} + /* Add any nested objects referenced in this object's `items` */ {{ if $this_object.items.anyOf }} {{ range $idx, $item := $this_object.items.anyOf }} {{ $all_objects = partial "get-additional-objects" (dict @@ -105,10 +92,10 @@ {{ end }} {{ end }} -{{/* +/* Handle object schemas using the `oneOf` keyword (https://json-schema.org/understanding-json-schema/reference/combining.html#oneof) -*/}} +*/ {{ if $this_object.oneOf }} {{ range $idx, $item := $this_object.oneOf }} {{ $all_objects = partial "get-additional-objects" (dict @@ -123,11 +110,11 @@ {{ return uniq $all_objects }} -{{/* +/* This actually makes the recursive call and adds the returned objects to the array -*/}} +*/ {{ define "partials/get-additional-objects" }} - {{/* .name is the name of the object for logging purposes */}} + /* .name is the name of the object for logging purposes */ {{ $name := .name }} {{ $all_objects := .all_objects }} @@ -142,20 +129,17 @@ {{ $this_object := partial "json-schema/resolve-allof" .this_object }} {{ $more_objects := partial "json-schema/resolve-additional-types" (dict "schema" $this_object "anchor_base" .anchor_base "name" $name) }} - {{/* - As far as I know we don't have something like Array.concat(), so add them one at a time - */}} {{ range $more_objects}} {{ $all_objects = $all_objects | append (partial "clean-object" .) }} {{ end }} {{ return $all_objects }} {{ end }} -{{/* +/* Only copy the bits of the object that we actually care about. This is needed for uniqify to work - otherwise objects that are the same but with (for example) different examples will be considered different. -*/}} +*/ {{ define "partials/clean-object" }} {{ return (dict "title" .title "properties" .properties "required" .required "enum" .enum "anchor" .anchor) }} {{ end }} From 3fee99616beb1a4724511a1f654d3a82e144c5d7 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 18:16:47 +0000 Subject: [PATCH 2/9] resolve-additional-types: improve documentation --- .../json-schema/resolve-additional-types.html | 100 ++++++++++++------ 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index 54e3366ec..f6ca1e6e8 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -1,24 +1,48 @@ -/* - Finds and returns all objects, including nested ones, given a dict containing: - * `schema`: a JSON schema object - * `anchor_base`: a prefix to add to the HTML anchors generated for each object. If nil, no anchors are generated. - * `name`: optionally, a name to use for this object in error/warning messages. If left unset, - the object's `title` property is used (if present). - - This template finds all nested objects inside `schema`. - - Assumes that "resolve-refs" and "resolve-allof" has already been called on the - input schema. - - Returns an array of all the objects found. The first object keeps all its properties. For all other objects, the following properties are returned: - * title - * properties - * required - * enum - * anchor: a string suitable for using as an html anchor for this object (if `anchor_base` was set, and the object has a title) - - Note that the returned array contains only unique objects. -*/ +/* Finds and returns all schema definitions for objects, including subschemas, + * in a JSON schema. + * + * The input should be a dict containing: + * + * * `schema`: a dict containing a JSON schema. + * * `anchor_base`: a prefix to add to the HTML anchors generated for each + * object. If nil, no anchors are generated. + * * `name`: optionally, a name to use for this schema in error/warning + * messages. If left unset, the schema's `title` property is used (if + * present). + * + * Assumes that "resolve-refs" and "resolve-allof" has already been called on + * the input schema. + * + * Returns an array of all the JSON schema definitions with `type: object` found + * by recursing through `schema` and inspecting any subschemas, and including + * `schema` itself. + * + * The returned entries are based on the JSON schema definitions found by + * recursing through the input `schema`, with the following differences: + * + * * `allOf` references are expanded. (Although this partial requires that + * `resolve-allof` is called on the top-level `schema` beforehand, + * `resolve-allof` doesn't recurse down to subschemas). + * + * * If `anchor_base` is set, each object with a `title` is given an `anchor`, + * which is a string suitable for using as an html anchor for that object schema. + * + * * With the *exception* of the top-level `schema` (if it is an object), + * properties outside the following list are removed: + * + * * title + * * properties + * * required + * * enum + * * anchor + * + * In particular, this means that examples are removed (typically examples + * are not helpful for subschemas), which means that duplicate schemas can + * be successfully eliminated. + * + * The returned array contains only unique objects (ie, if the same object is + * referenced twice within `schema`, it will only be returned once). + */ {{ $this_object := .schema }} {{ $anchor_base := .anchor_base }} @@ -92,10 +116,9 @@ {{ end }} {{ end }} -/* - Handle object schemas using the `oneOf` keyword - (https://json-schema.org/understanding-json-schema/reference/combining.html#oneof) -*/ +/* Handle object schemas using the `oneOf` keyword + * (https://json-schema.org/understanding-json-schema/reference/combining.html#oneof) + */ {{ if $this_object.oneOf }} {{ range $idx, $item := $this_object.oneOf }} {{ $all_objects = partial "get-additional-objects" (dict @@ -110,9 +133,17 @@ {{ return uniq $all_objects }} -/* - This actually makes the recursive call and adds the returned objects to the array -*/ +/* This actually makes the recursive call and adds the returned object schema definitions to the array. + * + * Input is a dict containing: + * * `this_object`: a JSON schema object. + * * `name`: a name to use for this object in error/warning messages. + * * `anchor_base`: a prefix to add to the HTML anchors generated for each + * object. If nil, no anchors are generated. + * * `all_objects`: the array of object schema definitions so far. + * + * Returns the array of object definitions. + */ {{ define "partials/get-additional-objects" }} /* .name is the name of the object for logging purposes */ {{ $name := .name }} @@ -123,8 +154,8 @@ {{ errorf "Invalid call to partials/get-additional-objects: %s is not a map" $name .this_object }} {{ end }} - /* although we expect resolve-allof to be called on the input, resolve-allof does not recurse into - * nested objects, so we have to call it again. + /* Although we expect resolve-allof to be called on the input, resolve-allof does not recurse into + * nested schemas, so we have to call it again. */ {{ $this_object := partial "json-schema/resolve-allof" .this_object }} @@ -135,11 +166,10 @@ {{ return $all_objects }} {{ end }} -/* - Only copy the bits of the object that we actually care about. - This is needed for uniqify to work - otherwise objects that are the same - but with (for example) different examples will be considered different. -*/ +/* Only copy the bits of the object that we actually care about. + * This is needed for uniqify to work - otherwise objects that are the same + * but with (for example) different examples will be considered different. + */ {{ define "partials/clean-object" }} {{ return (dict "title" .title "properties" .properties "required" .required "enum" .enum "anchor" .anchor) }} {{ end }} From 4043c1fc5885858a5f2c218b4254e258eac05bba Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 18:05:27 +0000 Subject: [PATCH 3/9] Extract an inner helper for `resolve-additional-types` --- .../json-schema/resolve-additional-types.html | 146 ++++++++++-------- 1 file changed, 80 insertions(+), 66 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index f6ca1e6e8..166915c56 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -44,95 +44,109 @@ * referenced twice within `schema`, it will only be returned once). */ -{{ $this_object := .schema }} -{{ $anchor_base := .anchor_base }} -{{ $all_objects := slice }} -{{ $name := .name | default $this_object.title | default "" }} - -{{ if eq $this_object.type "object" }} - /* Give this object an anchor, if it has a name */ - {{ if (and $anchor_base $this_object.title) }} - {{ $this_object = merge $this_object (dict "anchor" (printf "%s_%s" $anchor_base (anchorize $this_object.title))) }} - {{ end }} +{{ return partial "resolve-additional-types-inner" (dict + "schema" .schema + "anchor_base" .anchor_base + "name" (.name | default .schema.title | default "") +) }} + +/* + * A helper for the resolve-additional-types partial. + * + * Takes the same inputs as resolve-additional-types itself, except that `name` is mandatory. + * + * Returns the array of object schema definitions. + */ +{{ define "partials/resolve-additional-types-inner" }} + {{ $this_object := .schema }} + {{ $anchor_base := .anchor_base }} + {{ $name := .name }} + {{ $all_objects := slice }} - /* Add the object we were passed into the $all_objects array */ - {{ $all_objects = $all_objects | append $this_object }} + {{ if eq $this_object.type "object" }} + /* Give this object an anchor, if it has a name */ + {{ if (and $anchor_base $this_object.title) }} + {{ $this_object = merge $this_object (dict "anchor" (printf "%s_%s" $anchor_base (anchorize $this_object.title))) }} + {{ end }} - /* Add any nested objects referenced in this object's `additionalProperties` */ - {{ if $this_object.additionalProperties }} - {{ if reflect.IsMap $this_object.additionalProperties }} + /* Add the object we were passed into the $all_objects array */ + {{ $all_objects = $all_objects | append $this_object }} + + /* Add any nested objects referenced in this object's `additionalProperties` */ + {{ if $this_object.additionalProperties }} + {{ if reflect.IsMap $this_object.additionalProperties }} + {{ $all_objects = partial "get-additional-objects" (dict + "this_object" $this_object.additionalProperties + "all_objects" $all_objects + "anchor_base" $anchor_base + "name" (printf "%s.additional" $name) + ) }} + {{ end }} + {{ end }} + + /* Add any nested objects referenced in this object's `patternProperties` */ + {{ if $this_object.patternProperties }} + {{ range $pattern, $object := $this_object.patternProperties}} + {{ $all_objects = partial "get-additional-objects" (dict + "this_object" $object + "all_objects" $all_objects + "anchor_base" $anchor_base + "name" (printf "%s.pattern.%s" $name $pattern) + ) }} + {{ end }} + {{ end }} + + /* Add any nested objects referenced in this object's `properties` */ + {{ range $key, $property := $this_object.properties}} {{ $all_objects = partial "get-additional-objects" (dict - "this_object" $this_object.additionalProperties + "this_object" $property "all_objects" $all_objects "anchor_base" $anchor_base - "name" (printf "%s.additional" $name) + "name" (printf "%s.%s" $name $key) ) }} {{ end }} {{ end }} - /* Add any nested objects referenced in this object's `patternProperties` */ - {{ if $this_object.patternProperties }} - {{ range $pattern, $object := $this_object.patternProperties}} + {{ if eq $this_object.type "array" }} + /* Add any nested objects referenced in this object's `items` */ + {{ if $this_object.items.anyOf }} + {{ range $idx, $item := $this_object.items.anyOf }} + {{ $all_objects = partial "get-additional-objects" (dict + "this_object" $item + "all_objects" $all_objects + "anchor_base" $anchor_base + "name" (printf "%s.items[%d]" $name $idx) + ) }} + {{ end }} + {{ else if reflect.IsMap $this_object.items}} {{ $all_objects = partial "get-additional-objects" (dict - "this_object" $object - "all_objects" $all_objects - "anchor_base" $anchor_base - "name" (printf "%s.pattern.%s" $name $pattern) + "this_object" $this_object.items + "all_objects" $all_objects + "anchor_base" $anchor_base + "name" (printf "%s.items" $name) ) }} + {{ else }} + {{ errorf "%s is defined as an 'array' but lacks a valid 'items'" $name }} {{ end }} {{ end }} - /* Add any nested objects referenced in this object's `properties` */ - {{ range $key, $property := $this_object.properties}} - {{ $all_objects = partial "get-additional-objects" (dict - "this_object" $property - "all_objects" $all_objects - "anchor_base" $anchor_base - "name" (printf "%s.%s" $name $key) - ) }} - {{ end }} -{{ end }} - -{{ if eq $this_object.type "array" }} - /* Add any nested objects referenced in this object's `items` */ - {{ if $this_object.items.anyOf }} - {{ range $idx, $item := $this_object.items.anyOf }} + /* Handle object schemas using the `oneOf` keyword + * (https://json-schema.org/understanding-json-schema/reference/combining.html#oneof) + */ + {{ if $this_object.oneOf }} + {{ range $idx, $item := $this_object.oneOf }} {{ $all_objects = partial "get-additional-objects" (dict "this_object" $item "all_objects" $all_objects "anchor_base" $anchor_base - "name" (printf "%s.items[%d]" $name $idx) + "name" (printf "%s.oneOf[%d]" $name $idx) ) }} {{ end }} - {{ else if reflect.IsMap $this_object.items}} - {{ $all_objects = partial "get-additional-objects" (dict - "this_object" $this_object.items - "all_objects" $all_objects - "anchor_base" $anchor_base - "name" (printf "%s.items" $name) - ) }} - {{ else }} - {{ errorf "%s is defined as an 'array' but lacks a valid 'items'" $name }} {{ end }} -{{ end }} -/* Handle object schemas using the `oneOf` keyword - * (https://json-schema.org/understanding-json-schema/reference/combining.html#oneof) - */ -{{ if $this_object.oneOf }} - {{ range $idx, $item := $this_object.oneOf }} - {{ $all_objects = partial "get-additional-objects" (dict - "this_object" $item - "all_objects" $all_objects - "anchor_base" $anchor_base - "name" (printf "%s.oneOf[%d]" $name $idx) - ) }} - {{ end }} + {{ return uniq $all_objects }} {{ end }} -{{ return uniq $all_objects }} - - /* This actually makes the recursive call and adds the returned object schema definitions to the array. * * Input is a dict containing: @@ -159,7 +173,7 @@ */ {{ $this_object := partial "json-schema/resolve-allof" .this_object }} - {{ $more_objects := partial "json-schema/resolve-additional-types" (dict "schema" $this_object "anchor_base" .anchor_base "name" $name) }} + {{ $more_objects := partial "resolve-additional-types-inner" (dict "schema" $this_object "anchor_base" .anchor_base "name" $name) }} {{ range $more_objects}} {{ $all_objects = $all_objects | append (partial "clean-object" .) }} {{ end }} From 83bbc23e3091ed758f5a1e299a6cbba718762253 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 14 Feb 2024 09:58:49 +0000 Subject: [PATCH 4/9] Do not generate anchors for objects which will not have a table --- .../partials/json-schema/resolve-additional-types.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index 166915c56..232080877 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -24,8 +24,9 @@ * `resolve-allof` is called on the top-level `schema` beforehand, * `resolve-allof` doesn't recurse down to subschemas). * - * * If `anchor_base` is set, each object with a `title` is given an `anchor`, - * which is a string suitable for using as an html anchor for that object schema. + * * If `anchor_base` is set, each object with a `title` and `properties` + * is given an `anchor`, which is a string suitable for using as an html + * anchor for that object schema. * * * With the *exception* of the top-level `schema` (if it is an object), * properties outside the following list are removed: @@ -64,8 +65,8 @@ {{ $all_objects := slice }} {{ if eq $this_object.type "object" }} - /* Give this object an anchor, if it has a name */ - {{ if (and $anchor_base $this_object.title) }} + /* Give this object an anchor, if it has a name and properties */ + {{ if (and $anchor_base $this_object.title $this_object.properties) }} {{ $this_object = merge $this_object (dict "anchor" (printf "%s_%s" $anchor_base (anchorize $this_object.title))) }} {{ end }} From 8e004b1d3157cdaab1c6049444894032f23fc4ff Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 18:33:02 +0000 Subject: [PATCH 5/9] Delay addition of $this_object to result array ... so that we have a chance to modify it first. --- .../partials/json-schema/resolve-additional-types.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index 232080877..258128214 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -70,9 +70,6 @@ {{ $this_object = merge $this_object (dict "anchor" (printf "%s_%s" $anchor_base (anchorize $this_object.title))) }} {{ end }} - /* Add the object we were passed into the $all_objects array */ - {{ $all_objects = $all_objects | append $this_object }} - /* Add any nested objects referenced in this object's `additionalProperties` */ {{ if $this_object.additionalProperties }} {{ if reflect.IsMap $this_object.additionalProperties }} @@ -106,6 +103,13 @@ "name" (printf "%s.%s" $name $key) ) }} {{ end }} + + /* Finally, prepend the object we were passed onto the $all_objects array */ + {{ $tmp := slice $this_object }} + {{ if $all_objects }} + {{ $tmp = $tmp | append $all_objects }} + {{ end }} + {{ $all_objects = $tmp }} {{ end }} {{ if eq $this_object.type "array" }} From a6ae391c9895c613343babf1f0ec67b0dbdfc488 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 18:58:53 +0000 Subject: [PATCH 6/9] `resolve-additional-types`: update innards to return updated schema --- .../json-schema/resolve-additional-types.html | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index 258128214..a7c9484ac 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -45,18 +45,26 @@ * referenced twice within `schema`, it will only be returned once). */ -{{ return partial "resolve-additional-types-inner" (dict +{{ $res := partial "resolve-additional-types-inner" (dict "schema" .schema "anchor_base" .anchor_base "name" (.name | default .schema.title | default "") ) }} +{{ return $res.objects }} /* * A helper for the resolve-additional-types partial. * * Takes the same inputs as resolve-additional-types itself, except that `name` is mandatory. * - * Returns the array of object schema definitions. + * Returns a dict containing: + * + * * `objects`: The array of object schema definitions. + * + * * `schema`: An updated copy of the `schema` input (eg, nested `allOf` + * entries are expanded, and an `anchor` may be added). If the input + * `schema` was itself an object, this will be the same as the first entry + * in `objects`. */ {{ define "partials/resolve-additional-types-inner" }} {{ $this_object := .schema }} @@ -73,35 +81,38 @@ /* Add any nested objects referenced in this object's `additionalProperties` */ {{ if $this_object.additionalProperties }} {{ if reflect.IsMap $this_object.additionalProperties }} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $this_object.additionalProperties "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.additional" $name) ) }} + {{ $all_objects = $res.objects }} {{ end }} {{ end }} /* Add any nested objects referenced in this object's `patternProperties` */ {{ if $this_object.patternProperties }} {{ range $pattern, $object := $this_object.patternProperties}} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $object "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.pattern.%s" $name $pattern) ) }} + {{ $all_objects = $res.objects }} {{ end }} {{ end }} /* Add any nested objects referenced in this object's `properties` */ {{ range $key, $property := $this_object.properties}} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $property "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.%s" $name $key) ) }} + {{ $all_objects = $res.objects }} {{ end }} /* Finally, prepend the object we were passed onto the $all_objects array */ @@ -116,20 +127,22 @@ /* Add any nested objects referenced in this object's `items` */ {{ if $this_object.items.anyOf }} {{ range $idx, $item := $this_object.items.anyOf }} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $item "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.items[%d]" $name $idx) ) }} + {{ $all_objects = $res.objects }} {{ end }} {{ else if reflect.IsMap $this_object.items}} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $this_object.items "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.items" $name) ) }} + {{ $all_objects = $res.objects }} {{ else }} {{ errorf "%s is defined as an 'array' but lacks a valid 'items'" $name }} {{ end }} @@ -140,16 +153,20 @@ */ {{ if $this_object.oneOf }} {{ range $idx, $item := $this_object.oneOf }} - {{ $all_objects = partial "get-additional-objects" (dict + {{ $res := partial "get-additional-objects" (dict "this_object" $item "all_objects" $all_objects "anchor_base" $anchor_base "name" (printf "%s.oneOf[%d]" $name $idx) ) }} + {{ $all_objects = $res.objects }} {{ end }} {{ end }} - {{ return uniq $all_objects }} + {{ return (dict + "objects" (uniq $all_objects) + "schema" $this_object + ) }} {{ end }} /* This actually makes the recursive call and adds the returned object schema definitions to the array. @@ -161,7 +178,10 @@ * object. If nil, no anchors are generated. * * `all_objects`: the array of object schema definitions so far. * - * Returns the array of object definitions. + * Returns a dict containing: + * * `objects`: The array of object schema definitions. + * * `schema`: An updated copy of the `schema` input (eg, nested `allOf` + * entries are expanded, and an `anchor` may be added). */ {{ define "partials/get-additional-objects" }} /* .name is the name of the object for logging purposes */ @@ -178,11 +198,14 @@ */ {{ $this_object := partial "json-schema/resolve-allof" .this_object }} - {{ $more_objects := partial "resolve-additional-types-inner" (dict "schema" $this_object "anchor_base" .anchor_base "name" $name) }} - {{ range $more_objects}} + {{ $res := partial "resolve-additional-types-inner" (dict "schema" $this_object "anchor_base" .anchor_base "name" $name) }} + {{ range $res.objects }} {{ $all_objects = $all_objects | append (partial "clean-object" .) }} {{ end }} - {{ return $all_objects }} + {{ return (dict + "objects" $all_objects + "schema" $res.schema + ) }} {{ end }} /* Only copy the bits of the object that we actually care about. From 3736461cd1fce21c073506ecd86b09fa856611be Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 13 Feb 2024 22:40:24 +0000 Subject: [PATCH 7/9] Propagate schema updates into parent objects while recursing --- .../json-schema/resolve-additional-types.html | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html index a7c9484ac..a24eddf45 100644 --- a/layouts/partials/json-schema/resolve-additional-types.html +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -88,11 +88,15 @@ "name" (printf "%s.additional" $name) ) }} {{ $all_objects = $res.objects }} + + /* Update the top-level schema with the updated subschemas for the additionalProperties */ + {{ $this_object = merge $this_object (dict "additionalProperties" $res.schema) }} {{ end }} {{ end }} /* Add any nested objects referenced in this object's `patternProperties` */ {{ if $this_object.patternProperties }} + {{ $updated_pattern_properties := dict }} {{ range $pattern, $object := $this_object.patternProperties}} {{ $res := partial "get-additional-objects" (dict "this_object" $object @@ -101,21 +105,32 @@ "name" (printf "%s.pattern.%s" $name $pattern) ) }} {{ $all_objects = $res.objects }} + {{ $updated_pattern_properties = merge $updated_pattern_properties (dict $pattern $res.schema) }} {{ end }} + + /* Update the top-level schema with the updated subschemas for the patternProperties */ + {{ $this_object = merge $this_object (dict "patternProperties" $updated_pattern_properties) }} {{ end }} /* Add any nested objects referenced in this object's `properties` */ - {{ range $key, $property := $this_object.properties}} - {{ $res := partial "get-additional-objects" (dict - "this_object" $property - "all_objects" $all_objects - "anchor_base" $anchor_base - "name" (printf "%s.%s" $name $key) - ) }} - {{ $all_objects = $res.objects }} + {{ if $this_object.properties }} + {{ $updated_properties := dict }} + {{ range $key, $property := $this_object.properties}} + {{ $res := partial "get-additional-objects" (dict + "this_object" $property + "all_objects" $all_objects + "anchor_base" $anchor_base + "name" (printf "%s.%s" $name $key) + ) }} + {{ $all_objects = $res.objects }} + {{ $updated_properties = merge $updated_properties (dict $key $res.schema) }} + {{ end }} + + /* Update the top-level schema with the updated subschemas for the regular properties */ + {{ $this_object = merge $this_object (dict "properties" $updated_properties) }} {{ end }} - /* Finally, prepend the object we were passed onto the $all_objects array */ + /* Finally, prepend the updated schema for the top-level object onto the $all_objects array */ {{ $tmp := slice $this_object }} {{ if $all_objects }} {{ $tmp = $tmp | append $all_objects }} @@ -143,6 +158,8 @@ "name" (printf "%s.items" $name) ) }} {{ $all_objects = $res.objects }} + /* Update the top-level schema with the updated subschema for the items */ + {{ $this_object = merge $this_object (dict "items" $res.schema) }} {{ else }} {{ errorf "%s is defined as an 'array' but lacks a valid 'items'" $name }} {{ end }} From 3c52648c50d65881ee79f16029d6697c3f2f976a Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 6 Apr 2023 02:07:03 +0100 Subject: [PATCH 8/9] Link to HTML anchors, where they exist --- .../partials/openapi/render-object-table.html | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html index 3d3cfbaa5..47be51ec7 100644 --- a/layouts/partials/openapi/render-object-table.html +++ b/layouts/partials/openapi/render-object-table.html @@ -81,7 +81,7 @@ Computes the type to display for a property, given: * `type`: string or array of strings for the type(s) of the property - + * `title`: optional string for the title of the property * `oneOf`: optional array of dictionaries describing the different formats @@ -95,6 +95,9 @@ * `items`: if the type is an array, array of dictionaries describing the format of the array's items + + * `anchor`: optional HTML element id for the target type, which will be used to link to it. + */}} {{ define "partials/property-type" }} {{ $type := .type }} @@ -123,7 +126,7 @@ Computes the type to display for a property's schema, given: * `type`: string or array of strings for the type(s) of the property - + * `title`: optional string for the title of the property * `oneOf`: optional array of dictionaries describing the different formats @@ -134,7 +137,9 @@ * `patternProperties`: optional dictionary for properties with names adhering to a regex pattern - + + * `anchor`: optional HTML element id for the target type, which will be used to link to it. + The title has a higher priority than anything else. */}} {{ define "partials/type-or-title" }} @@ -145,6 +150,9 @@ This means we can write things like `EventFilter` rather than `object`. */}} {{ $type = .title }} + {{ if .anchor }} + {{ $type = printf "%s" (htmlEscape .anchor) (htmlEscape $type) | safeHTML }} + {{ end }} {{ else if reflect.IsMap .additionalProperties }} {{/* If the property uses `additionalProperties` to describe its @@ -205,9 +213,9 @@ * `property`: dictionary describing the property's data, with these fields: * `description`: string describing the property - + * `enum`: optional array indicating the accepted values for the property - + * `x-addedInMatrixVersion`: optional string indicating in which Matrix spec version this property was added. @@ -220,4 +228,4 @@ {{ if .property.enum }}

One of: [{{ delimit .property.enum ", " }}].

{{ end -}} {{ if (index .property "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index .property "x-addedInMatrixVersion")) }}{{ end -}} {{ if (index .property "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index .property "x-changedInMatrixVersion")) }}{{ end -}} -{{ end }} \ No newline at end of file +{{ end }} From 03f932ba101b71c8a07e236d37db30641397ee71 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 14 Feb 2024 09:42:51 +0000 Subject: [PATCH 9/9] changelog --- changelogs/internal/newsfragments/1724.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/internal/newsfragments/1724.clarification diff --git a/changelogs/internal/newsfragments/1724.clarification b/changelogs/internal/newsfragments/1724.clarification new file mode 100644 index 000000000..12be0c5ac --- /dev/null +++ b/changelogs/internal/newsfragments/1724.clarification @@ -0,0 +1 @@ +Update HTML templates to include links to object schema definitions.