diff --git a/changelogs/internal/newsfragments/1637.clarification b/changelogs/internal/newsfragments/1637.clarification
new file mode 100644
index 00000000..018cd98f
--- /dev/null
+++ b/changelogs/internal/newsfragments/1637.clarification
@@ -0,0 +1 @@
+Fix rendering of `m.receipt` event in Client-Server API.
diff --git a/data/api/application-service/definitions/protocol.yaml b/data/api/application-service/definitions/protocol.yaml
index f29d72e8..801faed1 100644
--- a/data/api/application-service/definitions/protocol.yaml
+++ b/data/api/application-service/definitions/protocol.yaml
@@ -41,7 +41,6 @@ properties:
type: string
example: "mxc://example.org/aBcDeFgH"
field_types:
- title: Field Types
description: |-
The type definitions for the fields defined in the `user_fields` and
`location_fields`. Each entry in those arrays MUST have an entry here. The
diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml
index 2f038e80..15d093c2 100644
--- a/data/api/client-server/cross_signing.yaml
+++ b/data/api/client-server/cross_signing.yaml
@@ -150,7 +150,6 @@ paths:
description: |-
Publishes cross-signing signatures for the user.
- The request body is a map from user ID to key ID to signed JSON object.
The signed JSON object must match the key previously uploaded or
retrieved for the given key ID, with the exception of the `signatures`
property, which contains the new signature(s) to add.
@@ -162,7 +161,8 @@ paths:
application/json:
schema:
type: object
- title: Signatures
+ description: |-
+ A map of user ID to a map of key ID to signed JSON object.
additionalProperties:
type: object
additionalProperties:
diff --git a/data/event-schemas/schema/m.direct.yaml b/data/event-schemas/schema/m.direct.yaml
index f00b83bc..3256b574 100644
--- a/data/event-schemas/schema/m.direct.yaml
+++ b/data/event-schemas/schema/m.direct.yaml
@@ -11,10 +11,12 @@ properties:
content:
additionalProperties:
type: array
- title: User ID
items:
type: string
type: object
+ description: |-
+ The mapping of user ID to a list of room IDs of the 'direct' rooms for
+ that user ID.
type:
enum:
- m.direct
diff --git a/data/event-schemas/schema/m.ignored_user_list.yaml b/data/event-schemas/schema/m.ignored_user_list.yaml
index 0f0b2f85..32cc6a46 100644
--- a/data/event-schemas/schema/m.ignored_user_list.yaml
+++ b/data/event-schemas/schema/m.ignored_user_list.yaml
@@ -10,12 +10,12 @@ properties:
properties:
ignored_users:
type: object
- title: "Ignored users"
- description: "The map of users to ignore"
+ description: |-
+ The map of users to ignore. This is a mapping of user ID to empty
+ object.
patternProperties:
"^@":
type: "object"
- title: "Ignored User"
description: "An empty object for future enhancement"
x-pattern: "$USER_ID"
required:
diff --git a/data/event-schemas/schema/m.receipt.yaml b/data/event-schemas/schema/m.receipt.yaml
index 6062d31f..702191d1 100644
--- a/data/event-schemas/schema/m.receipt.yaml
+++ b/data/event-schemas/schema/m.receipt.yaml
@@ -9,22 +9,24 @@ allOf:
properties:
content:
type: object
+ description: |-
+ The mapping of event ID to a collection of receipts for this
+ event ID. The event ID is the ID of the event being acknowledged
+ and *not* an ID for the receipt itself.
patternProperties:
"^\\$":
type: object
x-pattern: "$EVENT_ID"
- title: Receipts
+ title: Event Receipts
description: |-
- The mapping of event ID to a collection of receipts for this
- event ID. The event ID is the ID of the event being acknowledged
- and *not* an ID for the receipt itself.
+ The collection of receipts for this event ID.
properties:
"m.read":
type: object
- title: Users
description: |-
A collection of users who have sent `m.read` receipts for
- this event.
+ this event. The string key is the user ID the receipt
+ belongs to.
patternProperties:
"^@": &receiptUserMap
type: object
@@ -48,7 +50,6 @@ properties:
(default).
"m.read.private":
type: object
- title: Own User
description: |-
Similar to `m.read`, the users who have sent `m.read.private`
receipts for this event. Due to the nature of private read
diff --git a/layouts/partials/events/render-event.html b/layouts/partials/events/render-event.html
index 0f4d543d..70752721 100644
--- a/layouts/partials/events/render-event.html
+++ b/layouts/partials/events/render-event.html
@@ -56,7 +56,10 @@
Content
{{ $anchor_base := anchorize $event_name }}
-{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $event_data.properties.content "anchor_base" $anchor_base) }}
+{{ $additional_types := partial "json-schema/resolve-additional-types" (dict
+ "schema" $event_data.properties.content
+ "anchor_base" $anchor_base
+) }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html
index 449b4222..c5d420b6 100644
--- a/layouts/partials/json-schema/resolve-additional-types.html
+++ b/layouts/partials/json-schema/resolve-additional-types.html
@@ -1,6 +1,6 @@
{{/*
- Finds and returns all nested objects, given a dict containing:
+ 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,
@@ -11,20 +11,20 @@
Assumes that "resolve-refs" and "resolve-allof" has already been called on the
input schema.
- Returns an array of all the objects found. For each object, the following properties are returned:
+ 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 may contain duplicate objects.
+ Note that the returned array contains only unique objects.
*/}}
{{ $this_object := .schema }}
{{ $anchor_base := .anchor_base }}
-{{ $additional_objects := slice }}
+{{ $all_objects := slice }}
{{ $name := .name | default $this_object.title | default "" }}
{{ if eq $this_object.type "object" }}
@@ -34,31 +34,45 @@
{{ end }}
{{/*
- Add the object we were passed into the $additional_objects array
+ Add the object we were passed into the $all_objects array
*/}}
- {{ $additional_objects = $additional_objects | append (partial "clean-object" $this_object) }}
+ {{ $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 }}
- {{ $additional_objects = partial "get-additional-objects" (dict
+ {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $this_object.additionalProperties
- "additional_objects" $additional_objects
+ "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}}
- {{ $additional_objects = partial "get-additional-objects" (dict
+ {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $property
- "additional_objects" $additional_objects
+ "all_objects" $all_objects
"anchor_base" $anchor_base
"name" (printf "%s.%s" $name $key)
) }}
@@ -72,17 +86,17 @@
*/}}
{{ if $this_object.items.anyOf }}
{{ range $idx, $item := $this_object.items.anyOf }}
- {{ $additional_objects = partial "get-additional-objects" (dict
+ {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $item
- "additional_objects" $additional_objects
+ "all_objects" $all_objects
"anchor_base" $anchor_base
"name" (printf "%s.items[%d]" $name $idx)
) }}
{{ end }}
{{ else if reflect.IsMap $this_object.items}}
- {{ $additional_objects = partial "get-additional-objects" (dict
+ {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $this_object.items
- "additional_objects" $additional_objects
+ "all_objects" $all_objects
"anchor_base" $anchor_base
"name" (printf "%s.items" $name)
) }}
@@ -97,16 +111,16 @@
*/}}
{{ if $this_object.oneOf }}
{{ range $idx, $item := $this_object.oneOf }}
- {{ $additional_objects = partial "get-additional-objects" (dict
+ {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $item
- "additional_objects" $additional_objects
+ "all_objects" $all_objects
"anchor_base" $anchor_base
"name" (printf "%s.oneOf[%d]" $name $idx)
) }}
{{ end }}
{{ end }}
-{{ return $additional_objects }}
+{{ return uniq $all_objects }}
{{/*
@@ -116,7 +130,7 @@
{{/* .name is the name of the object for logging purposes */}}
{{ $name := .name }}
- {{ $additional_objects := .additional_objects }}
+ {{ $all_objects := .all_objects }}
{{ if not (reflect.IsMap .this_object) }}
{{ errorf "Invalid call to partials/get-additional-objects: %s is not a map" $name .this_object }}
@@ -132,9 +146,9 @@
As far as I know we don't have something like Array.concat(), so add them one at a time
*/}}
{{ range $more_objects}}
- {{ $additional_objects = $additional_objects | append (partial "clean-object" .) }}
+ {{ $all_objects = $all_objects | append (partial "clean-object" .) }}
{{ end }}
- {{ return $additional_objects }}
+ {{ return $all_objects }}
{{ end }}
{{/*
diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html
index 0de9d2d1..3d3cfbaa 100644
--- a/layouts/partials/openapi/render-object-table.html
+++ b/layouts/partials/openapi/render-object-table.html
@@ -6,10 +6,16 @@
* `anchor`: optional HTML element id for the table
- * `properties`: dictionary of the properties to list, each given as:
+ * `properties`: optional dictionary of the properties to list, each given as:
`property_name` : `property_data`
- * `required`: array containing the names of required properties.
+ * `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.
@@ -34,24 +40,6 @@
{{ range $property_name, $property := $properties }}
{{ $property := partial "json-schema/resolve-allof" $property }}
- {{ $type := $property.type }}
-
- {{ if or (eq $property.type "object") (and $property.oneOf (reflect.IsSlice .oneOf)) }}
- {{ $type = partial "type-or-title" $property }}
- {{ end }}
-
- {{/*
- If the property is an array, indicate this with square brackets,
- like `[type]`.
- */}}
- {{ if eq $property.type "array"}}
- {{ $items := $property.items }}
- {{ if $property.items }}
- {{ $items = partial "json-schema/resolve-allof" $property.items }}
- {{ end }}
- {{ $inner_type := partial "type-or-title" $items }}
- {{ $type = delimit (slice "[" $inner_type "]") "" }}
- {{ end }}
{{/*
Handle two ways of indicating "required", one for simple parameters,
@@ -61,25 +49,93 @@
{{ $property_name }} |
- {{ $type }} |
-
- {{ 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 -}}
- |
+ {{ partial "partials/property-type" $property }} |
+ {{ partial "partials/property-description" (dict "property" $property "required" $required) }} |
{{ end }}
+{{ else if (or .additionalProperties .patternProperties) }}
+
+ {{ with $title }}
+ {{ . }}
+ {{ end }}
+
+ Type |
+ Description |
+
+
+ {{ $property := partial "json-schema/resolve-allof" . }}
+
+
+ {{ partial "partials/property-type" $property }} |
+ {{ partial "partials/property-description" (dict "property" $property) }} |
+
+
+
{{ end }}
{{/*
- Picks either the `title` of a property, or the `type`, to turn into the rendered type field.
- Also handles `additionalProperties`, if no `title` is present.
+ 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
+ that the property can have
+
+ * `additionalProperties`: optional dictionary for properties with undefined
+ names
+
+ * `patternProperties`: 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
+*/}}
+{{ define "partials/property-type" }}
+ {{ $type := .type }}
+
+ {{ if or (eq .type "object") (and .oneOf (reflect.IsSlice .oneOf)) }}
+ {{ $type = partial "type-or-title" . }}
+ {{ end }}
+
+ {{/*
+ If the property is an array, indicate this with square brackets,
+ like `[type]`.
+ */}}
+ {{ if eq .type "array"}}
+ {{ $items := .items }}
+ {{ if .items }}
+ {{ $items = partial "json-schema/resolve-allof" .items }}
+ {{ end }}
+ {{ $inner_type := partial "type-or-title" $items }}
+ {{ $type = delimit (slice "[" $inner_type "]") "" }}
+ {{ end }}
+
+ {{ return $type }}
+{{ end }}
+
+{{/*
+ 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
+ that the property can have
+
+ * `additionalProperties`: optional dictionary for properties with undefined
+ names
+
+ * `patternProperties`: optional dictionary for properties with names
+ adhering to a regex pattern
+
+ The title has a higher priority than anything else.
*/}}
{{ define "partials/type-or-title" }}
{{ $type := "" }}
@@ -94,7 +150,24 @@
If the property uses `additionalProperties` to describe its
internal structure, handle this with a bit of recursion
*/}}
- {{ $type = delimit (slice "{string: " (partial "type-or-title" .additionalProperties) "}" ) "" }}
+ {{ $additionalProperties := partial "json-schema/resolve-allof" .additionalProperties }}
+ {{ $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.
+ Note that we ignore the pattern as the current definitions
+ always have a single pattern, but we might need to handle
+ them later to differentiate schemas according to patterns.
+ */}}
+ {{ $types := slice }}
+
+ {{ range $pattern, $schema := .patternProperties}}
+ {{ $schema = partial "json-schema/resolve-allof" $schema }}
+ {{ $types = $types | append (partial "property-type" $schema) }}
+ {{ end }}
+
+ {{ $type = delimit (slice "{string: " (delimit $types "|") "}" ) "" }}
{{ else if reflect.IsSlice .type }}
{{/* It's legal to specify an array of types. Join them together in that case */}}
@@ -123,3 +196,28 @@
{{ 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 }}
\ No newline at end of file
diff --git a/layouts/partials/openapi/render-request.html b/layouts/partials/openapi/render-request.html
index 0771204b..3d4b0381 100644
--- a/layouts/partials/openapi/render-request.html
+++ b/layouts/partials/openapi/render-request.html
@@ -46,7 +46,6 @@
{{ $schema := partial "json-schema/resolve-allof" $schema }}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }}
- {{ $additional_types = uniq $additional_types }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
{{ end }}
diff --git a/layouts/partials/openapi/render-responses.html b/layouts/partials/openapi/render-responses.html
index c0ee5279..99662ad0 100644
--- a/layouts/partials/openapi/render-responses.html
+++ b/layouts/partials/openapi/render-responses.html
@@ -81,7 +81,6 @@
objects or arrays.)
*/}}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }}
- {{ $additional_types = uniq $additional_types }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
{{ end }}
diff --git a/layouts/shortcodes/definition.html b/layouts/shortcodes/definition.html
index 67cd63c0..0699ff7b 100644
--- a/layouts/shortcodes/definition.html
+++ b/layouts/shortcodes/definition.html
@@ -51,7 +51,6 @@
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $definition "name" (printf "\"%s\"" $path)) }}
-{{ $additional_types = uniq $additional_types }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}