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
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

@ -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:

@ -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

@ -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:

@ -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

@ -56,7 +56,10 @@
<h2>Content</h2>
{{ $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" . }}

@ -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 "<untitled object>" }}
{{ 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 }}
{{/*

@ -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 @@
<tr>
<td><code>{{ $property_name }}</code></td>
<td><code>{{ $type }}</code></td>
<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>
<td><code>{{ partial "partials/property-type" $property }}</code></td>
<td>{{ partial "partials/property-description" (dict "property" $property "required" $required) }}</td>
</tr>
{{ end }}
</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 }}
{{/*
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 }}
{{/*
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'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 }}<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 }}
{{ $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 }}

@ -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 }}

@ -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" . }}

Loading…
Cancel
Save