{{/* Render a table listing the properties of an object, given: * `title`: optional caption for the table * `anchor`: optional HTML element id for the table * `properties`: optional dictionary of the properties to list, each given as: `property_name` : `property_data` * `additionalProperties`: optional dictionary for properties with undefined names, in the same format as `property_data` * `patternProperties`: optional dictionary for properties with names adhering to a regex pattern, in the same format as `property_data` * `required`: optional array containing the names of required properties. In some cases (such as response body specifications) this isn't used, and instead properties have a `required` boolean attribute. We support this too. */}} {{ $title := .title }} {{ $properties := .properties}} {{ $required := .required}} {{ if $properties }} {{ with $title }} {{ . }} {{ end }} Name Type Description {{ range $property_name, $property := $properties }} {{/* Handle two ways of indicating "required", one for simple parameters, the other for request and response body objects. */}} {{ $required := cond (or (in $required $property_name) ( eq $property.required true )) true false }} {{ $property_name }} {{ partial "partials/property-type" $property | safeHTML }} {{ partial "partials/property-description" (dict "property" $property "required" $required) }} {{ end }} {{ else if (or .additionalProperties .patternProperties) }} {{ with $title }} {{ . }} {{ end }} Type Description {{ $property := . }} {{ partial "partials/property-type" $property | safeHTML }} {{ partial "partials/property-description" (dict "property" $property) }} {{ end }} {{/* Computes the type to display for a property's schema, given: * `type`: optional 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 that the property can have * `additionalProperties`: if the type is an object, optional dictionary for properties with undefined names * `patternProperties`: if the type is an object, optional dictionary for properties with names adhering to a regex pattern * `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 := "" }} {{ if eq .type "object" }} {{/* Resolve the type or title of the object */}} {{ $type = partial "object-type-or-title" . }} {{ else if eq .type "array"}} {{/* If the property is an array, indicate this with square brackets, like `[type]`. */}} {{ $items := .items }} {{ $inner_type := partial "property-type" $items }} {{ $type = delimit (slice "[" $inner_type "]") "" }} {{ else if or (reflect.IsSlice .type) .oneOf }} {{/* It's legal to specify an array of types. There are two ways to do that: - Use an array of strings. - Use oneOf, with items having a schema. Join them together in that case, like `type|other_type`. */}} {{ $types := slice }} {{ if .oneOf }} {{ range .oneOf }} {{ $types = $types | append (partial "property-type" .) }} {{ end }} {{ else }} {{ range .type }} {{ $types = $types | append (htmlEscape .) }} {{ end }} {{ end }} {{ $type = delimit $types "|" }} {{ else }} {{/* A simple type like string or boolean */}} {{ $type = (htmlEscape .type) }} {{ end }} {{ return $type }} {{ end }} {{/* Computes the type to display for an object property's schema, given: * `type`: string equal to "object" * `title`: optional string for the title of the object property * `additionalProperties`: optional dictionary for properties with undefined names * `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/object-type-or-title" }} {{ $type := "object" }} {{ if .title }} {{/* If the property has a `title`, use that rather than `type`. This means we can write things like `EventFilter` rather than `object`. */}} {{ $type = .title | htmlEscape }} {{ if .anchor }} {{ $type = printf "%s" (htmlEscape .anchor) $type }} {{ end }} {{ else if reflect.IsMap .additionalProperties }} {{/* If the property uses `additionalProperties` to describe its internal structure, handle this with a bit of recursion */}} {{ $type = delimit (slice "{string: " (partial "property-type" .additionalProperties) "}" ) "" }} {{ else if reflect.IsMap .patternProperties }} {{/* If the property uses `patternProperties` to describe its internal structure, handle this with a bit of recursion. Types are grouped by pattern format. Note that we ignore patterns without a format as the current definitions always have a single pattern, but we might need to handle them later to differentiate schemas according to patterns. */}} {{/* Construct a map from format ID to the type string of the format. */}} {{ $formatMap := newScratch }} {{ range $pattern, $schema := .patternProperties }} {{ $formatId := or (index $schema "x-pattern-format") "string" }} {{ if $formatMap.Get $formatId }} {{ errorf "'%s' pattern format is defined more than once for the same property" $formatId }} {{ end }} {{ $formatMap.Set $formatId (partial "property-type" $schema) }} {{ end }} {{/* First generate the type string for each format. */}} {{ $types := slice }} {{ range $formatId, $formatType := $formatMap.Values }} {{ $formatKey := "string" }} {{ if ne $formatId "string" }} {{ with index site.Data "custom-formats" $formatId }} {{ $formatKey = printf "%s" (htmlEscape .url) (htmlEscape .title) }} {{ else }} {{ errorf "Unsupported value for `x-pattern-format`: %s" $formatId }} {{ end }} {{ end }} {{ $formatString := printf "{%s: %s}" $formatKey $formatType }} {{ $types = $types | append $formatString }} {{ end }} {{/* Then join all the formats. */}} {{ $type = delimit $types "|" }} {{ end }} {{ return $type }} {{ end }} {{/* Computes the description to display for a property, given: * `required`: boolean indicating whether this property is required. * `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. * `x-changedInMatrixVersion`: optional string indicating in which Matrix spec version this property was last changed. */}} {{ define "partials/property-description" }} {{ if .required }}Required: {{end -}} {{ .property.description | markdownify -}} {{ 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 }}