Compare commits

...

8 commits

Author SHA1 Message Date
Andrew Morgan 63474ab991
Merge 72b34b863f into e283c35dbd 2025-03-13 11:30:06 -06:00
Johannes Marbach e283c35dbd
Remove extra trailing quotes from sync API specs (#2091)
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2025-03-05 09:12:15 -05:00
Kévin Commaille 1916e53f8c
Deduplicate Invite3pid (#2074)
* Deduplicate Invite3pid

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-03-05 09:56:49 +00:00
Kévin Commaille 02a1aeefbc
Deduplicate RoomKeysUpdateResponse (#2073)
And add a link to the endpoint that is mentionned while we're at it.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-03-05 09:52:40 +00:00
Kévin Commaille 3adbfa30da
Look for examples in all possible locations (#2076)
We used to only look for examples in a few (sometimes arbitrary) places, and we didn't support showing several examples in most cases. This is intended to fix this. In the process we try to deduplicate code to make sure that we use the same logic everywhere.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-03-05 09:44:59 +00:00
Kévin Commaille 4ff9a851e6
Add link to git commit for unstable changelog too (#2078)
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-03-05 09:43:27 +00:00
Andrew Morgan 72b34b863f newsfile 2025-01-28 19:03:28 +00:00
Andrew Morgan 4d84d75bb6 Add a note to the federation invite endpoints that invites can be sent twice
As this may be non-obvious when implementing behaviour that is triggered by an incoming invite
event.

See https://github.com/matrix-org/matrix-spec/issues/2062 for more context.
2025-01-28 19:02:09 +00:00
27 changed files with 337 additions and 380 deletions

View file

@ -0,0 +1 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
Deduplicate the definition of `RoomKeysUpdateResponse`.

View file

@ -0,0 +1 @@
Deduplicate the definitions of `Invite3pid`.

View file

@ -0,0 +1 @@
Support more locations for examples in OpenAPI definitions and JSON schemas.

View file

@ -0,0 +1 @@
Add link to the git commit for the unstable changelog.

View file

@ -0,0 +1 @@
Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room.

View file

@ -0,0 +1 @@
Remove an erroneous `room_id` field in a few examples.

View file

@ -131,32 +131,7 @@ paths:
A list of objects representing third-party IDs to invite into
the room.
items:
type: object
title: Invite3pid
properties:
id_server:
type: string
description: The hostname+port of the identity server which should be used for
third-party identifier lookups.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
medium:
type: string
description: |-
The kind of address being passed in the address field, for example `email`
(see [the list of recognised values](/appendices/#3pid-types)).
address:
type: string
description: The invitee's third-party identifier.
required:
- id_server
- id_access_token
- medium
- address
$ref: definitions/invite_3pid.yaml
room_version:
type: string
description: |-

View file

@ -0,0 +1,45 @@
# Copyright 2025 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
type: object
title: Invite3pid
properties:
id_server:
type: string
description: The hostname+port of the identity server which should be used for
third-party identifier lookups.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
medium:
type: string
description: |-
The kind of address being passed in the address field, for example `email`
(see [the list of recognised values](/appendices/#3pid-types)).
address:
type: string
description: The invitee's third-party identifier.
required:
- id_server
- id_access_token
- medium
- address
example: {
"id_server": "matrix.org",
"id_access_token": "abc123_OpaqueString",
"medium": "email",
"address": "cheeky@monkey.com"
}

View file

@ -438,22 +438,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"403":
description: |-
The version specified does not match the current backup version.
@ -571,22 +556,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"404":
description: The backup was not found.
content:
@ -644,22 +614,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"403":
description: |-
The version specified does not match the current backup version.
@ -778,22 +733,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"404":
description: The backup was not found.
content:
@ -866,22 +806,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"403":
description: |-
The version specified does not match the current backup version.
@ -1007,22 +932,7 @@ paths:
content:
application/json:
schema:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See `GET /room_keys/version/{version}` for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
$ref: "#/components/schemas/RoomKeysUpdateResponse"
"404":
description: The backup was not found.
content:
@ -1056,6 +966,26 @@ servers:
basePath:
default: /_matrix/client/v3
components:
schemas:
RoomKeysUpdateResponse:
type: object
title: RoomKeysUpdateResponse
properties:
etag:
description: |-
The new etag value representing stored keys in the backup.
See [`GET /room_keys/version/{version}`](client-server-api/#get_matrixclientv3room_keysversionversion)
for more details.
type: string
example: abcdefg
count:
description: The number of keys stored in the backup
type: integer
example: 10
required:
- etag
- count
securitySchemes:
accessTokenQuery:
$ref: definitions/security.yaml#/accessTokenQuery

View file

@ -214,7 +214,7 @@ paths:
- public
description: |-
Whether this room is visible to the `/publicRooms` API
or not."
or not.
account_data:
type: array
description: |-

View file

@ -96,7 +96,7 @@ paths:
- public
description: |-
Whether this room is visible to the `/publicRooms` API
or not."
or not.
account_data:
type: array
description: The private data that this user has attached to this room.

View file

@ -76,37 +76,7 @@ paths:
content:
application/json:
schema:
type: object
example: {
"id_server": "matrix.org",
"id_access_token": "abc123_OpaqueString",
"medium": "email",
"address": "cheeky@monkey.com"
}
properties:
id_server:
type: string
description: The hostname+port of the identity server which should be used for
third-party identifier lookups.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
medium:
type: string
description: |-
The kind of address being passed in the address field, for example
`email` (see [the list of recognised values](/appendices/#3pid-types)).
address:
type: string
description: The invitee's third-party identifier.
required:
- id_server
- id_access_token
- medium
- address
$ref: definitions/invite_3pid.yaml
required: true
responses:
"200":

View file

@ -20,7 +20,7 @@ paths:
put:
summary: Invites a remote user to a room
description: |-
Invites a remote user to a room. Once the event has been signed by both the inviting
Invites a remote user to a room. Once the event has been signed by both the inviting
homeserver and the invited homeserver, it can be sent to all of the servers in the
room by the inviting homeserver.
@ -32,6 +32,10 @@ paths:
[room version specification](/rooms) for precise event formats. **The request and response
bodies here describe the common event fields in more detail and may be missing other
required fields for a PDU.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](https://spec.matrix.org/v1.13/server-server-api/#transactions).
operationId: sendInviteV1
security:
- signedRequest: []
@ -75,22 +79,6 @@ paths:
example:
$ref: ../../event-schemas/examples/invite_room_state.json
type: object
example: {
"room_id": "!somewhere:example.org",
"type": "m.room.member",
"state_key": "@joe:elsewhere.com",
"origin": "example.org",
"origin_server_ts": 1549041175876,
"sender": "@someone:example.org",
"content": {
"membership": "invite"
},
"signatures": {
"example.com": {
"ed25519:key_version": "SomeSignatureHere"
},
}
}
required: true
responses:
"200":

View file

@ -24,7 +24,7 @@ paths:
This API is nearly identical to the v1 API with the exception of the request
body being different, and the response format fixed.
Invites a remote user to a room. Once the event has been signed by both the inviting
Invites a remote user to a room. Once the event has been signed by both the inviting
homeserver and the invited homeserver, it can be sent to all of the servers in the
room by the inviting homeserver.
@ -36,6 +36,10 @@ paths:
[room version specification](/rooms) for precise event formats. **The request and response
bodies here describe the common event fields in more detail and may be missing other
required fields for a PDU.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](https://spec.matrix.org/v1.13/server-server-api/#transactions).
operationId: sendInviteV2
security:
- signedRequest: []
@ -78,25 +82,6 @@ paths:
required:
- room_version
- event
example: {
"room_version": "2",
"event": {
"room_id": "!somewhere:example.org",
"type": "m.room.member",
"state_key": "@joe:elsewhere.com",
"origin": "example.org",
"origin_server_ts": 1549041175876,
"sender": "@someone:example.org",
"content": {
"membership": "invite"
},
"signatures": {
"example.com": {
"ed25519:key_version": "SomeSignatureHere"
},
}
}
}
required: true
responses:
"200":

View file

@ -140,7 +140,6 @@ paths:
- type
- content
example: {
"room_id": "!somewhere:example.org",
"type": "m.room.member",
"state_key": "@someone:example.org",
"origin": "example.org",

View file

@ -270,7 +270,6 @@ paths:
- type
- content
example: {
"room_id": "!somewhere:example.org",
"type": "m.room.member",
"state_key": "@someone:example.org",
"origin": "example.org",

View file

@ -31,9 +31,17 @@
<h1>{{ .Title }}</h1>
<table class="release-info">
{{ if ne $version "unstable" -}}
{{ $commitLink := printf "https://github.com/matrix-org/matrix-spec/tree/%s" $version -}}
{{ $rev := $version }}
{{ if eq $version "unstable" -}}
{{- /*
Extract the git SHA from the frontmatter of the changelog, where
it was stashed by `generate-changelog.sh`.
*/ -}}
{{ $rev = .Params.commit -}}
{{ end -}}
{{ $commitLink := printf "https://github.com/matrix-org/matrix-spec/tree/%s" $rev -}}
<tr><th>Git commit</th><td><a href="{{ $commitLink }}">{{ $commitLink }}</a></td>
{{ if ne $version "unstable" }}
<tr><th>Release date</th><td>{{ .Date | time.Format ":date_long" }}</td>
{{ end -}}
{{ $checklist := .OutputFormats.Get "checklist" -}}

View file

@ -13,10 +13,4 @@
{{ $path := delimit (slice "event-schemas/examples" .name) "/" }}
{{ $example_content := partial "json-schema/resolve-refs" (dict "schema" .schema "path" $path) }}
{{ $example_json := jsonify (dict "indent" " ") $example_content }}
{{ $example_json = replace $example_json "\\u003c" "<" }}
{{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }}
```json
{{ $example_json }}
```
{{ partial "render-example" (dict "example" $example_content) }}

View file

@ -1,46 +0,0 @@
{{/*
For complex objects, example content is sometimes attached to the
object's individual properties (and subproperties...), so to get
a complete example for the whole object we need to iterate through
its properties (and subproperties...) and assemble them.
That's what this template does.
*/}}
{{ $this_object := . }}
{{ $example := $this_object.example }}
{{ if not $example }}
{{ if eq $this_object.type "object" }}
{{ $example = dict }}
{{ range $key, $property := $this_object.properties}}
{{ $this_property_example := partial "json-schema/resolve-example" $property }}
{{ if $this_property_example }}
{{ $example = merge (dict $key $this_property_example) $example }}
{{ end }}
{{ end }}
{{ else if eq $this_object.type "array" }}
{{/* the "items" within an array can either be an object (where we have a
list of items which match the schema), or a list (for tuple
validation, where each item has a different schema).
TODO: support tuple validation here.
*/}}
{{ if reflect.IsMap $this_object.items }}
{{ $items_example := partial "json-schema/resolve-example" $this_object.items }}
{{ if $items_example }}
{{ $example = slice $items_example }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ return $example }}

View file

@ -0,0 +1,71 @@
{{/*
Find examples in the given JSON schema.
Tries to find examples in the `examples` and `example` keys of the schema
first.
If it doesn't succeed, iterates through the properties and subproperties to
collect their examples, to merge them into a complete example for the whole
object.
Parameter: the JSON schema to extract the examples from.
*/}}
{{ $this_object := . }}
{{ $examples := slice }}
{{ if $this_object.examples }}
{{/* This is an array of examples, we can just use it */}}
{{ $examples = $this_object.examples }}
{{ else if $this_object.example }}
{{ $examples = slice $this_object.example }}
{{ else }}
{{/* Resolve the nested examples */}}
{{ if eq $this_object.type "object" }}
{{ $example := dict }}
{{ range $key, $property := $this_object.properties}}
{{ $this_property_examples := partial "json-schema/resolve-examples" $property }}
{{/*
It would be too complex to handle several nested examples,
just use the first one.
*/}}
{{ with index $this_property_examples 0 }}
{{ $example = merge (dict $key .) $example }}
{{ end }}
{{ end }}
{{/*
Add the assembled example to the list if either (a) the example is
non-empty, or (b) the object itself is meant to be empty (so an
empty example is correct).
*/}}
{{ if (or $example (not $this_object.properties)) }}
{{ $examples = slice $example }}
{{ end }}
{{ else if eq $this_object.type "array" }}
{{/* the "items" within an array can either be an object (where we have a
list of items which match the schema), or a list (for tuple
validation, where each item has a different schema).
TODO: support tuple validation here.
*/}}
{{ if reflect.IsMap $this_object.items }}
{{ $items_examples := partial "json-schema/resolve-examples" $this_object.items }}
{{/*
It would be too complex to handle several nested examples,
just use the first one.
*/}}
{{ with index $items_examples 0 }}
{{ $examples = slice (slice .) }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ return $examples }}

View file

@ -0,0 +1,104 @@
{{/*
Render a map of [Media Type Objects](https://spec.openapis.org/oas/v3.1.1#media-type-object).
This map can be found as the `content` field of requests and responses.
Parameters:
* `content`: A map of MIME type to Media Type Object
* `kind`: the kind of object that is rendered, either `request` or `response`.
* `anchor_base`: a prefix to add to the HTML anchors generated for each object
This template renders:
* Object tables if the map contains an `application/json` MIME type, or a
table with the MIME types and the corresponding description of the object.
* The examples of the Media Type Objects.
*/}}
{{/*
Request and response bodies can have several content types. If there is a
JSON type, we display that; otherwise we just show the content types and
descriptions.
*/}}
{{ $json_body := index .content "application/json" }}
{{ if $json_body }}
{{/*
Display the JSON schemas
*/}}
{{ $schema := $json_body.schema }}
{{/*
All this is to work out how to express the content of the response
in the case where it is an array.
*/}}
{{ if eq $schema.type "array" }}
{{ $type_of := "" }}
{{ if $schema.items.anyOf }}
{{ $types := slice }}
{{ range $schema.items.anyOf }}
{{ if .title }}
{{ $types = $types | append .title}}
{{ else }}
{{ $types = $types | append .type }}
{{ end }}
{{ end }}
{{ $type_of = delimit $types ", "}}
{{ else }}
{{ $type_of = $schema.items.title }}
{{ end }}
<p>Array of <code>{{ $type_of }}</code>.</p>
{{ end }}
{{/*
Render object tables for any objects referenced in the request/response.
This will be a no-op for request/response body types which aren't
objects or arrays.
*/}}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" .anchor_base) }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
{{ end }}
{{ else }}
{{/*
Show the content types and description.
*/}}
{{ partial "openapi/render-content-type" (dict "content_types" .content) }}
{{ end }}
{{/*
Show all the examples.
*/}}
{{ if eq .kind "request" }}
<h3>Request body example</h3>
{{ end }}
{{ range $mime, $body := .content }}
{{ $examples := slice }}
{{/*
Find the examples to display, with the following priority:
1. The `examples` field
2. The `example` field
3. The examples in the `schema` field
*/}}
{{ if $body.examples }}
{{/* This is a map of string to Example Object */}}
{{ range $key, $example := $body.examples }}
{{/* The example is in the `value` field of the object */}}
{{ $examples = $examples | append (slice $example.value) }}
{{ end }}
{{ else if $body.example }}
{{ $examples = slice $body.example }}
{{ else if $body.schema }}
{{ $examples = partial "json-schema/resolve-examples" $body.schema }}
{{ end }}
{{ range $examples }}
{{ partial "render-example" (dict "example" . "mime" $mime) }}
{{ end }}
{{ end }}

View file

@ -33,65 +33,8 @@
{{ if $request_body }}
<h3>Request body</h3>
{{/*
A request can have several content types.
*/}}
{{ $json_body := index $request_body.content "application/json" }}
{{ if $json_body }}
{{/*
Display the JSON schemas
*/}}
{{ $schema := $json_body.schema }}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor) }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
{{ end }}
{{ else }}
{{/*
Show the content types and description.
*/}}
{{ partial "openapi/render-content-type" (dict "content_types" $request_body.content) }}
{{ end }}
<h3>Request body example</h3>
{{/*
Show all the examples.
*/}}
{{ range $mime, $body := $request_body.content }}
{{ $example := dict }}
{{ if $body.schema }}
{{ $example = partial "json-schema/resolve-example" $body.schema }}
{{ end }}
{{ if and (eq ($example | len) 0) $body.example }}
{{/*
If no example was generated from the schema, fallback to the
main example.
*/}}
{{ $example = $body.example }}
{{ end }}
{{ if eq $mime "application/json" }}
{{ $example_json := jsonify (dict "indent" " ") $example }}
{{ $example_json = replace $example_json "\\u003c" "<" }}
{{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }}
```json
{{ $example_json }}
```
{{ else }}
{{ $example = $example | safeHTML }}
{{/*
We need to set a language for the code otherwise the styling
is different than other examples.
*/}}
```json
{{ $example }}
```
{{ end }}
{{ end }}
{{ partial "openapi/render-media-type-objects" (dict "content" $request_body.content "kind" "request" "anchor_base" $anchor) }}
{{ end }}
{{ else }}

View file

@ -59,72 +59,6 @@
{{ partial "openapi/render-object-table" (dict "title" "Headers" "properties" $headers_dict) }}
{{ end }}
{{/*
A response can have several content types.
*/}}
{{ $json_body := index $response.content "application/json" }}
{{ if $json_body }}
{{/*
Display the JSON schemas
*/}}
{{ $schema := $json_body.schema }}
{{/*
All this is to work out how to express the content of the response
in the case where it is an array.
*/}}
{{ if eq $schema.type "array" }}
{{ $type_of := "" }}
{{ if $schema.items.anyOf }}
{{ $types := slice }}
{{ range $schema.items.anyOf }}
{{ if .title }}
{{ $types = $types | append .title}}
{{ else }}
{{ $types = $types | append .type }}
{{ end }}
{{ end }}
{{ $type_of = delimit $types ", "}}
{{ else }}
{{ $type_of = $schema.items.title }}
{{ end }}
<p>Array of <code>{{ $type_of }}</code>.</p>
{{ end }}
{{/*
render object tables for any objects referenced in the
response. (This will be a no-op for response types which aren't
objects or arrays.)
*/}}
{{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor) }}
{{ range $additional_types }}
{{ partial "openapi/render-object-table" . }}
{{ end }}
{{/*
render an example. currently this is only supported for arrays and objects.
*/}}
{{ if or (eq $schema.type "object") (eq $schema.type "array") }}
{{ $example := partial "json-schema/resolve-example" $schema }}
{{ if $json_body.examples }}
{{ $example = $json_body.examples.response.value }}
{{ end }}
{{ $example_json := jsonify (dict "indent" " ") $example }}
{{ $example_json = replace $example_json "\\u003c" "<" }}
{{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }}
```json
{{ $example_json }}
```
{{ end }}
{{ else }}
{{/*
Show the content types and description.
*/}}
{{ partial "openapi/render-content-type" (dict "content_types" $response.content) }}
{{ end }}
{{ partial "openapi/render-media-type-objects" (dict "content" $response.content "kind" "response" "anchor_base" $anchor) }}
{{ end }}
{{ end }}

View file

@ -0,0 +1,40 @@
{{/*
Renders an example to be included in HTML, with support for pretty-printing
JSON.
Parameters:
* `example`: the example
* `mime`: the mime type of the example. Used to pretty-print JSON and for
syntax highlighting. If it is not provided, it is assumed to be
`application/json`.
*/}}
{{ $example := .example }}
{{/*
We need to convert the mime type to a recognized language.
For simplicity we only support JSON, which is also the default. Other mime
types are not highlighted.
*/}}
{{ $language := "json" }}
{{ if (and .mime (ne .mime "application/json")) }}
{{/*
`no-highlight` treats the value as plain text, but still styles the code
block like the ones with proper syntax highlighting.
*/}}
{{ $language = "no-highlight" }}
{{ end }}
{{ if eq $language "json" }}
{{ $example = jsonify (dict "indent" " ") $example }}
{{ $example = replace $example "\\u003c" "<" }}
{{ $example = replace $example "\\u003e" ">" }}
{{ end }}
```{{ $language }}
{{ $example | safeHTML }}
```

View file

@ -58,13 +58,14 @@
{{ partial "openapi/render-object-table" . }}
{{end}}
{{ $examples := partial "json-schema/resolve-examples" $definition }}
{{ if $examples }}
<h2>Examples</h2>
{{ $example := partial "json-schema/resolve-example" $definition }}
```json
{{ jsonify (dict "indent" " ") $example }}
```
{{ range $examples }}
{{ partial "render-example" (dict "example" .) }}
{{ end }}
{{ end }}
</details>

View file

@ -44,8 +44,18 @@ outputs:
- html
- checklist
date: $(date -Idate)
---
EOF
# Add the commit hash for the unstable versions. It is used to generate a
# link to the commit on the repository.
if [ "$VERSION" == "vUNSTABLE" ]; then
echo "params:"
echo " commit: $(git rev-parse --short HEAD)"
fi
# Close the frontmatter.
echo "---"
# Remove trailing whitespace (such as our intentionally blank RST headings)
sed -e "s/[ ]*$//" rendered.md
} > ../content/changelog/$FILENAME