Fix rendering of `m.receipt` event in Client-Server API (#1637)

... and other improvements

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
pull/1650/head
Kévin Commaille 1 year ago committed by GitHub
parent 5672bdbab7
commit e40d9ca186
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1 @@
Fix rendering of `m.receipt` event in Client-Server API.

@ -41,7 +41,6 @@ properties:
type: string type: string
example: "mxc://example.org/aBcDeFgH" example: "mxc://example.org/aBcDeFgH"
field_types: field_types:
title: Field Types
description: |- description: |-
The type definitions for the fields defined in the `user_fields` and 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 `location_fields`. Each entry in those arrays MUST have an entry here. The

@ -150,7 +150,6 @@ paths:
description: |- description: |-
Publishes cross-signing signatures for the user. 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 The signed JSON object must match the key previously uploaded or
retrieved for the given key ID, with the exception of the `signatures` retrieved for the given key ID, with the exception of the `signatures`
property, which contains the new signature(s) to add. property, which contains the new signature(s) to add.
@ -162,7 +161,8 @@ paths:
application/json: application/json:
schema: schema:
type: object type: object
title: Signatures description: |-
A map of user ID to a map of key ID to signed JSON object.
additionalProperties: additionalProperties:
type: object type: object
additionalProperties: additionalProperties:

@ -11,10 +11,12 @@ properties:
content: content:
additionalProperties: additionalProperties:
type: array type: array
title: User ID
items: items:
type: string type: string
type: object type: object
description: |-
The mapping of user ID to a list of room IDs of the 'direct' rooms for
that user ID.
type: type:
enum: enum:
- m.direct - m.direct

@ -10,12 +10,12 @@ properties:
properties: properties:
ignored_users: ignored_users:
type: object type: object
title: "Ignored users" description: |-
description: "The map of users to ignore" The map of users to ignore. This is a mapping of user ID to empty
object.
patternProperties: patternProperties:
"^@": "^@":
type: "object" type: "object"
title: "Ignored User"
description: "An empty object for future enhancement" description: "An empty object for future enhancement"
x-pattern: "$USER_ID" x-pattern: "$USER_ID"
required: required:

@ -9,22 +9,24 @@ allOf:
properties: properties:
content: content:
type: object 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: patternProperties:
"^\\$": "^\\$":
type: object type: object
x-pattern: "$EVENT_ID" x-pattern: "$EVENT_ID"
title: Receipts title: Event Receipts
description: |- description: |-
The mapping of event ID to a collection of receipts for this The collection of receipts for this event ID.
event ID. The event ID is the ID of the event being acknowledged
and *not* an ID for the receipt itself.
properties: properties:
"m.read": "m.read":
type: object type: object
title: Users
description: |- description: |-
A collection of users who have sent `m.read` receipts for 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: patternProperties:
"^@": &receiptUserMap "^@": &receiptUserMap
type: object type: object
@ -48,7 +50,6 @@ properties:
(default). (default).
"m.read.private": "m.read.private":
type: object type: object
title: Own User
description: |- description: |-
Similar to `m.read`, the users who have sent `m.read.private` Similar to `m.read`, the users who have sent `m.read.private`
receipts for this event. Due to the nature of private read receipts for this event. Due to the nature of private read

@ -56,7 +56,10 @@
<h2>Content</h2> <h2>Content</h2>
{{ $anchor_base := anchorize $event_name }} {{ $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 }} {{ range $additional_types }}
{{ partial "openapi/render-object-table" . }} {{ partial "openapi/render-object-table" . }}

@ -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 * `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. * `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, * `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 Assumes that "resolve-refs" and "resolve-allof" has already been called on the
input schema. 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 * title
* properties * properties
* required * required
* enum * 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) * 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 }} {{ $this_object := .schema }}
{{ $anchor_base := .anchor_base }} {{ $anchor_base := .anchor_base }}
{{ $additional_objects := slice }} {{ $all_objects := slice }}
{{ $name := .name | default $this_object.title | default "<untitled object>" }} {{ $name := .name | default $this_object.title | default "<untitled object>" }}
{{ if eq $this_object.type "object" }} {{ if eq $this_object.type "object" }}
@ -34,31 +34,45 @@
{{ end }} {{ 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` Add any nested objects referenced in this object's `additionalProperties`
*/}} */}}
{{ if $this_object.additionalProperties }} {{ if $this_object.additionalProperties }}
{{ if reflect.IsMap $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 "this_object" $this_object.additionalProperties
"additional_objects" $additional_objects "all_objects" $all_objects
"anchor_base" $anchor_base "anchor_base" $anchor_base
"name" (printf "%s.additional" $name) "name" (printf "%s.additional" $name)
) }} ) }}
{{ end }} {{ end }}
{{ 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` Add any nested objects referenced in this object's `properties`
*/}} */}}
{{ range $key, $property := $this_object.properties}} {{ range $key, $property := $this_object.properties}}
{{ $additional_objects = partial "get-additional-objects" (dict {{ $all_objects = partial "get-additional-objects" (dict
"this_object" $property "this_object" $property
"additional_objects" $additional_objects "all_objects" $all_objects
"anchor_base" $anchor_base "anchor_base" $anchor_base
"name" (printf "%s.%s" $name $key) "name" (printf "%s.%s" $name $key)
) }} ) }}
@ -72,17 +86,17 @@
*/}} */}}
{{ if $this_object.items.anyOf }} {{ if $this_object.items.anyOf }}
{{ range $idx, $item := $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 "this_object" $item
"additional_objects" $additional_objects "all_objects" $all_objects
"anchor_base" $anchor_base "anchor_base" $anchor_base
"name" (printf "%s.items[%d]" $name $idx) "name" (printf "%s.items[%d]" $name $idx)
) }} ) }}
{{ end }} {{ end }}
{{ else if reflect.IsMap $this_object.items}} {{ 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 "this_object" $this_object.items
"additional_objects" $additional_objects "all_objects" $all_objects
"anchor_base" $anchor_base "anchor_base" $anchor_base
"name" (printf "%s.items" $name) "name" (printf "%s.items" $name)
) }} ) }}
@ -97,16 +111,16 @@
*/}} */}}
{{ if $this_object.oneOf }} {{ if $this_object.oneOf }}
{{ range $idx, $item := $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 "this_object" $item
"additional_objects" $additional_objects "all_objects" $all_objects
"anchor_base" $anchor_base "anchor_base" $anchor_base
"name" (printf "%s.oneOf[%d]" $name $idx) "name" (printf "%s.oneOf[%d]" $name $idx)
) }} ) }}
{{ end }} {{ end }}
{{ end }} {{ end }}
{{ return $additional_objects }} {{ return uniq $all_objects }}
{{/* {{/*
@ -116,7 +130,7 @@
{{/* .name is the name of the object for logging purposes */}} {{/* .name is the name of the object for logging purposes */}}
{{ $name := .name }} {{ $name := .name }}
{{ $additional_objects := .additional_objects }} {{ $all_objects := .all_objects }}
{{ if not (reflect.IsMap .this_object) }} {{ if not (reflect.IsMap .this_object) }}
{{ errorf "Invalid call to partials/get-additional-objects: %s is not a map" $name .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 As far as I know we don't have something like Array.concat(), so add them one at a time
*/}} */}}
{{ range $more_objects}} {{ range $more_objects}}
{{ $additional_objects = $additional_objects | append (partial "clean-object" .) }} {{ $all_objects = $all_objects | append (partial "clean-object" .) }}
{{ end }} {{ end }}
{{ return $additional_objects }} {{ return $all_objects }}
{{ end }} {{ end }}
{{/* {{/*

@ -6,10 +6,16 @@
* `anchor`: optional HTML element id for the table * `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` `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 In some cases (such as response body specifications) this isn't used, and
instead properties have a `required` boolean attribute. We support this too. instead properties have a `required` boolean attribute. We support this too.
@ -34,24 +40,6 @@
{{ range $property_name, $property := $properties }} {{ range $property_name, $property := $properties }}
{{ $property := partial "json-schema/resolve-allof" $property }} {{ $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, Handle two ways of indicating "required", one for simple parameters,
@ -61,25 +49,93 @@
<tr> <tr>
<td><code>{{ $property_name }}</code></td> <td><code>{{ $property_name }}</code></td>
<td><code>{{ $type }}</code></td> <td><code>{{ partial "partials/property-type" $property }}</code></td>
<td> <td>{{ partial "partials/property-description" (dict "property" $property "required" $required) }}</td>
{{ if $required }}<strong>Required: </strong>{{end -}}
{{ $property.description | markdownify -}}
{{ if $property.enum }}<p>One of: <code>[{{ delimit $property.enum ", " }}]</code>.</p>{{ 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 -}}
</td>
</tr> </tr>
{{ end }} {{ end }}
</table> </table>
{{ else if (or .additionalProperties .patternProperties) }}
<table{{ if .anchor }} id="{{ .anchor }}"{{ end }} class="object-table">
{{ with $title }}
<caption>{{ . }}</caption>
{{ end }}
<thead>
<th class="col-type">Type</th>
<th class="col-description">Description</th>
</thead>
{{ $property := partial "json-schema/resolve-allof" . }}
<tr>
<td><code>{{ partial "partials/property-type" $property }}</code></td>
<td>{{ partial "partials/property-description" (dict "property" $property) }}</td>
</tr>
</table>
{{ end }} {{ end }}
{{/* {{/*
Picks either the `title` of a property, or the `type`, to turn into the rendered type field. Computes the type to display for a property, given:
Also handles `additionalProperties`, if no `title` is present.
* `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" }} {{ define "partials/type-or-title" }}
{{ $type := "" }} {{ $type := "" }}
@ -94,7 +150,24 @@
If the property uses `additionalProperties` to describe its If the property uses `additionalProperties` to describe its
internal structure, handle this with a bit of recursion 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 }} {{ else if reflect.IsSlice .type }}
{{/* It's legal to specify an array of types. Join them together in that case */}} {{/* It's legal to specify an array of types. Join them together in that case */}}
@ -123,3 +196,28 @@
{{ end }} {{ end }}
{{ return $type }} {{ return $type }}
{{ end }} {{ 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 }}<strong>Required: </strong>{{end -}}
{{ .property.description | markdownify -}}
{{ if .property.enum }}<p>One of: <code>[{{ delimit .property.enum ", " }}]</code>.</p>{{ 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 }}

@ -46,7 +46,6 @@
{{ $schema := partial "json-schema/resolve-allof" $schema }} {{ $schema := partial "json-schema/resolve-allof" $schema }}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }} {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }}
{{ $additional_types = uniq $additional_types }}
{{ range $additional_types }} {{ range $additional_types }}
{{ partial "openapi/render-object-table" . }} {{ partial "openapi/render-object-table" . }}
{{ end }} {{ end }}

@ -81,7 +81,6 @@
objects or arrays.) objects or arrays.)
*/}} */}}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }} {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor_base) }}
{{ $additional_types = uniq $additional_types }}
{{ range $additional_types }} {{ range $additional_types }}
{{ partial "openapi/render-object-table" . }} {{ partial "openapi/render-object-table" . }}
{{ end }} {{ end }}

@ -51,7 +51,6 @@
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $definition "name" (printf "\"%s\"" $path)) }} {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $definition "name" (printf "\"%s\"" $path)) }}
{{ $additional_types = uniq $additional_types }}
{{ range $additional_types }} {{ range $additional_types }}
{{ partial "openapi/render-object-table" . }} {{ partial "openapi/render-object-table" . }}

Loading…
Cancel
Save