From 5f45a897ef713d752030bd3741660749b1f58aaf Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 29 Jan 2021 15:30:39 -0800 Subject: [PATCH] Add templates used to render data --- layouts/partials/events/render-event.html | 93 ++++++++++++++++++ .../json-schema/resolve-additional-types.html | 92 ++++++++++++++++++ .../partials/json-schema/resolve-allof.html | 76 +++++++++++++++ .../partials/json-schema/resolve-example.html | 29 ++++++ .../partials/json-schema/resolve-refs.html | 65 +++++++++++++ layouts/partials/openapi/render-api.html | 54 +++++++++++ .../partials/openapi/render-object-table.html | 92 ++++++++++++++++++ .../partials/openapi/render-operation.html | 65 +++++++++++++ .../partials/openapi/render-parameters.html | 30 ++++++ layouts/partials/openapi/render-request.html | 67 +++++++++++++ .../partials/openapi/render-responses.html | 97 +++++++++++++++++++ layouts/shortcodes/definition.html | 59 +++++++++++ layouts/shortcodes/event-fields.html | 45 +++++++++ layouts/shortcodes/event-group.html | 32 ++++++ layouts/shortcodes/event.html | 20 ++++ layouts/shortcodes/http-api.html | 26 +++++ layouts/shortcodes/msgtypes.html | 48 +++++++++ 17 files changed, 990 insertions(+) create mode 100644 layouts/partials/events/render-event.html create mode 100644 layouts/partials/json-schema/resolve-additional-types.html create mode 100644 layouts/partials/json-schema/resolve-allof.html create mode 100644 layouts/partials/json-schema/resolve-example.html create mode 100644 layouts/partials/json-schema/resolve-refs.html create mode 100644 layouts/partials/openapi/render-api.html create mode 100644 layouts/partials/openapi/render-object-table.html create mode 100644 layouts/partials/openapi/render-operation.html create mode 100644 layouts/partials/openapi/render-parameters.html create mode 100644 layouts/partials/openapi/render-request.html create mode 100644 layouts/partials/openapi/render-responses.html create mode 100644 layouts/shortcodes/definition.html create mode 100644 layouts/shortcodes/event-fields.html create mode 100644 layouts/shortcodes/event-group.html create mode 100644 layouts/shortcodes/event.html create mode 100644 layouts/shortcodes/http-api.html create mode 100644 layouts/shortcodes/msgtypes.html diff --git a/layouts/partials/events/render-event.html b/layouts/partials/events/render-event.html new file mode 100644 index 00000000..b4bb75b4 --- /dev/null +++ b/layouts/partials/events/render-event.html @@ -0,0 +1,93 @@ +{{/* + + Renders a single event, given: + + * `event_name`: the name we want to display for the event + * `event_data`: the event specification + * `desired_example_name` (optional): the exact name of the examples to render. + If `desired_example_name` is omitted we render all examples + whose names start with the `event_name`. + +*/}} + +{{ $event_name := .event_name }} +{{ $desired_example_name := .desired_example_name }} +{{ $event_data := .event_data }} + +
+ +
+ + +

+ {{ $event_name }} +

+ +
+ +{{ $event_data.description | markdownify }} + +
+ +{{ $state_key := index $event_data.properties "state_key" }} + + + + + + +{{ if $state_key }} + + + + +{{ end }} +
Event type:{{ if $state_key }}State event{{ else }}Message event{{ end }}
State key{{ $state_key.description | markdownify }}
+ +

Content

+ +{{ $additional_types := partial "json-schema/resolve-additional-types" $event_data.properties.content }} + +{{ range $additional_types }} + {{ partial "openapi/render-object-table" (dict "caption" .title "properties" .properties "required" .required) }} +{{end}} + +

Examples

+ +{{ $all_examples := index site.Data "event-schemas" "examples" }} + +{{ range $example_name, $example := $all_examples }} + + {{/* + This is to allow the msgtype template to work. + It lets callers specify exactly the name of the example they want + */}} + {{ if $desired_example_name }} + {{ if eq $example_name $desired_example_name }} + {{ $example_content := partial "json-schema/resolve-refs" (dict "schema" $example "path" "event-schemas/examples") }} +```json +{{ jsonify (dict "indent" " ") $example_content }} +``` + {{ end }} + {{/* + If `$desired_example_name` is not given, we will include any + examples whose first part (before "$") matches the event name + */}} + {{ else }} + + {{ $pieces := split $example_name "$" }} + {{ $example_base_name := index $pieces 0 }} + {{ if eq $event_name $example_base_name }} + {{ $example_content := partial "json-schema/resolve-refs" (dict "schema" $example "path" "event-schemas/examples") }} + {{ $example_json := jsonify (dict "indent" " ") $example_content }} + {{ $example_json = replace $example_json "\\u003c" "<" }} + {{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} + +```json +{{ $example_json }} +``` + {{ end }} + {{ end }} +{{ end }} + +
diff --git a/layouts/partials/json-schema/resolve-additional-types.html b/layouts/partials/json-schema/resolve-additional-types.html new file mode 100644 index 00000000..a4f95445 --- /dev/null +++ b/layouts/partials/json-schema/resolve-additional-types.html @@ -0,0 +1,92 @@ +{{/* + + Finds and returns all nested objects, given: + + * `this_object`: a JSON schema object + + Given a schema object, this template finds all nested objects under that + schema. + + It "cleans" each object by copying only the parts of the objects that + the renderer needs, and adds the result to an array, `additional_objects`. + + Finally it returns the array of all the objects it found. + + Note that the returned array may contain duplicate objects. + +*/}} + +{{ $this_object := partial "json-schema/resolve-allof" . }} +{{ $additional_objects := slice }} + +{{ if eq $this_object.type "object" }} + + {{/* + Add the object we were passed into the $additional_objects array + */}} + {{ $additional_objects = $additional_objects | append (partial "clean-object" $this_object) }} + + {{/* + Add any nested objects referenced in this object's `additionalProperties` + */}} + {{ if $this_object.additionalProperties }} + {{ if reflect.IsMap $this_object.additionalProperties }} + {{ $additional_objects = $additional_objects | append (partial "clean-object" $this_object.additionalProperties) }} + + {{ range $key, $property := $this_object.additionalProperties.properties }} + {{ $additional_objects = partial "get-additional-objects" (dict "this_object" $property "additional_objects" $additional_objects) }} + {{ end }} + + {{ 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 "this_object" $property "additional_objects" $additional_objects) }} + {{ end }} + +{{ end }} + +{{ if eq $this_object.type "array" }} + {{/* + Add any nested objects referenced in this object's `items` + */}} + {{ if reflect.IsSlice $this_object.items}} + {{ range $this_object.items }} + {{ $additional_objects = partial "get-additional-objects" (dict "this_object" . "additional_objects" $additional_objects) }} + {{ end }} + {{ else }} + {{ $additional_objects = partial "get-additional-objects" (dict "this_object" $this_object.items "additional_objects" $additional_objects) }} + {{ end }} +{{ end }} + +{{ return $additional_objects }} + + +{{/* + This actually makes the recursive call and adds the returned objects to the array +*/}} +{{ define "partials/get-additional-objects" }} + {{ $additional_objects := .additional_objects }} + + {{ $this_object := partial "json-schema/resolve-allof" .this_object }} + {{ $more_objects := partial "json-schema/resolve-additional-types" $this_object }} + {{/* + 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" .) }} + {{ end }} + {{ return $additional_objects }} +{{ end }} + +{{/* + Only copy the bits of the object that we actually care about. + This is needed for uniqify to work - otherwise objects that are the same + but with (for example) different examples will be considered differen. +*/}} +{{ define "partials/clean-object" }} + {{ return (dict "title" .title "properties" .properties "required" .required "enum" .enum) }} +{{ end }} diff --git a/layouts/partials/json-schema/resolve-allof.html b/layouts/partials/json-schema/resolve-allof.html new file mode 100644 index 00000000..0150cfde --- /dev/null +++ b/layouts/partials/json-schema/resolve-allof.html @@ -0,0 +1,76 @@ +{{/* + + Resolves the `allOf` keyword (https://swagger.io/specification/v2/#composition-and-inheritance-polymorphism), + given a JSON schema object. + + `allOf` is used to support a kind of inheritance for JSON schema objects. + + An object can reference a "parent" object using `allOf`, and it then inherits + its parent's properties. If the same property is present in the child, then + we use the child's version (the child overrides the parent). + + Of course the parent can itself inherit from *its* parent, so we recurse to + handle that. + +*/}} + +{{ $ret := . }} +{{ $original := . }} + +{{ $required := .required }} +{{ if not $required }} + {{ $required := slice }} +{{ end }} + +{{ with $ret.allOf }} + + {{ $all_of_values := dict }} + + {{/* + allOf is always an array + */}} + {{ range . }} + + {{ with .required }} + {{ $required = union $required . }} + {{ end }} + + {{/* + With merge, values from the second argument override those from the first argument. + So this order will accumulate values from allOf items, allowing later ones to override earlier + */}} + {{ $all_of_values = merge $all_of_values . }} + + {{ end }} + + {{/* + Then apply allOf values to the original, but allow the original to override allOf. + */}} + {{ $ret = merge $all_of_values $ret }} + + {{/* + Except that if allOf *itself* contains allOf, we do want to override the original for that field only. + */}} + {{ with $all_of_values.allOf }} + {{ $ret = merge $ret (dict "allOf" . ) }} + {{ end }} + + {{ with $ret.required }} + {{ $required = union $required $ret.required }} + {{ end }} + + {{ $ret = merge $ret (dict "required" $required) }} + +{{ end }} + +{{/* + Recurse while we are finding new allOf entries to resolve +*/}} +{{ if ne $ret.allOf $original.allOf }} + + {{ $resolved := partial "json-schema/resolve-allof" $ret }} + {{ $ret = merge $ret $resolved }} + +{{ end }} + +{{ return $ret }} diff --git a/layouts/partials/json-schema/resolve-example.html b/layouts/partials/json-schema/resolve-example.html new file mode 100644 index 00000000..51ce6d53 --- /dev/null +++ b/layouts/partials/json-schema/resolve-example.html @@ -0,0 +1,29 @@ +{{/* + + 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 := partial "json-schema/resolve-allof" . }} + +{{ if eq $this_object.type "object" }} + + {{ if not $this_object.example }} + {{ $this_object := merge (dict "example" dict ) $this_object }} + {{ end }} + + {{ range $key, $property := $this_object.properties}} + {{ $this_property_example := partial "json-schema/resolve-example" $property }} + {{ if $this_property_example }} + {{ $this_object = merge (dict "example" (dict $key $this_property_example)) $this_object }} + {{ end }} + {{ end }} + +{{ end }} + +{{ return $this_object.example }} diff --git a/layouts/partials/json-schema/resolve-refs.html b/layouts/partials/json-schema/resolve-refs.html new file mode 100644 index 00000000..1d99201d --- /dev/null +++ b/layouts/partials/json-schema/resolve-refs.html @@ -0,0 +1,65 @@ +{{/* + + Resolves the `$ref` JSON schema keyword, by recursively replacing + it with the object it points to. + + This template uses [`Scratch`](https://gohugo.io/functions/scratch/) + rather than a normal `dict` because with `dict` you can't replace key values: + https://discourse.gohugo.io/t/how-can-i-add-set-and-delete-keys-in-a-dictionary/29661 + +*/}} + +{{ $schema := .schema }} +{{ $path := .path}} + +{{ $ret := $schema }} + +{{ if reflect.IsMap $schema }} + + {{ $scratch := newScratch }} + {{ $scratch.Set "result_map" dict }} + + {{ $ref_value := index $schema "$ref"}} + {{ if $ref_value}} + {{ $full_path := path.Join $path $ref_value }} + {{/* + Apparently Hugo doesn't give us a nice way to split the extension off a filename. + */}} + {{ $without_ext := replaceRE "\\.[^\\.]*$" "" $full_path }} + {{ $pieces := split $without_ext "/" }} + + {{ $ref := index site.Data $pieces }} + + {{ $new_path := (path.Split $full_path).Dir}} + {{ $result_map := partial "json-schema/resolve-refs" (dict "schema" $ref "path" $new_path)}} + {{ if $result_map}} + {{ $scratch.Set "result_map" $result_map }} + {{end }} + {{ end }} + + + {{ range $key, $value := $schema }} + {{ if ne $key "$ref" }} + {{ $resolved := partial "json-schema/resolve-refs" (dict "schema" $value "path" $path) }} + {{ $scratch.SetInMap "result_map" $key $resolved }} + {{ end }} + {{ end }} + + {{ $ret = $scratch.Get "result_map" }} + +{{ end }} + +{{ if reflect.IsSlice $schema }} + + {{ $result_slice := slice }} + + {{ range $schema }} + {{ $resolved := partial "json-schema/resolve-refs" (dict "schema" . "path" $path) }} + {{ $result_slice = $result_slice | append $resolved }} + {{ end }} + + {{ $ret = $result_slice }} + +{{ end }} + +{{ return $ret }} diff --git a/layouts/partials/openapi/render-api.html b/layouts/partials/openapi/render-api.html new file mode 100644 index 00000000..db10b98c --- /dev/null +++ b/layouts/partials/openapi/render-api.html @@ -0,0 +1,54 @@ +{{/* + + Render an HTTP API, given: + + * `api_data`: the OpenAPI/Swagger data + * `base_url`: the base URL: that is, the part we glue onto the front + of each value in `paths` to get a complete URL. + * `path`: the directory under /data where we found this API definition. + We use this to resolve "$ref" values, since they are relative to the schema's + location. + +*/}} + +{{ $api_data := index .api_data }} +{{ $base_url := .base_url }} +{{ $path := .path }} + +{{ range $path_name, $path_data := $api_data.paths }} + + {{ $endpoint := delimit (slice $base_url $path_name ) "" }} + + {{/* note that a `paths` entry can be a $ref */}} + + {{ $params := dict "endpoint" $endpoint "path" $path }} + + {{ with $path_data.get }} + + {{ $operation_params := merge $params (dict "method" "GET" "operation_data" . ) }} + {{ partial "openapi/render-operation" $operation_params }} + + {{ end }} + + {{ with $path_data.post }} + + {{ $operation_params := merge $params (dict "method" "POST" "operation_data" . ) }} + {{ partial "openapi/render-operation" $operation_params }} + + {{ end }} + + {{ with $path_data.put }} + + {{ $operation_params := merge $params (dict "method" "PUT" "operation_data" . ) }} + {{ partial "openapi/render-operation" $operation_params }} + + {{ end }} + + {{ with $path_data.delete }} + + {{ $operation_params := merge $params (dict "method" "DELETE" "operation_data" . ) }} + {{ partial "openapi/render-operation" $operation_params }} + + {{ end }} + +{{ end }} diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html new file mode 100644 index 00000000..0f4b3a77 --- /dev/null +++ b/layouts/partials/openapi/render-object-table.html @@ -0,0 +1,92 @@ +{{/* + + Render a table listing the properties of an object, given: + + * `caption`: optional caption for the table + * `properties`: dictionary of the properties to list, each given as: + `property_name` : `property_data` + * `required`: 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. + +*/}} + +{{ $caption := .caption }} +{{ $properties := .properties}} +{{ $required := .required}} + +{{ if $properties }} + + + {{ with $caption }} + + {{ end }} + + + + + + + {{ range $property_name, $property := $properties }} + + {{ $property := partial "json-schema/resolve-allof" $property }} + + {{/* + If the property has a `title`, use that rather than `type`. + This means we can write things like `EventFilter` rather than `object`. + */}} + {{ $type := $property.type}} + {{ if $property.title }} + {{ $type = $property.title }} + {{ end }} + + {{/* + If the property is an array, indicate this with square brackets, + like`[type]`. + */}} + {{ if eq $type "array"}} + {{ $items := $property.items }} + {{ if $property.items }} + {{ $items = partial "json-schema/resolve-allof" $property.items }} + {{ end }} + {{ $inner_type := $items.type }} + {{ if $items.title }} + {{ $inner_type = $items.title }} + {{ end }} + {{ $type = delimit (slice "[" $inner_type "]") "" }} + {{ end }} + + {{/* + If the property is an enum, indicate this. + */}} + {{ if (and (eq $type "string") ($property.enum)) }} + {{ $type = "enum" }} + {{ end }} + + {{/* + If the property uses `additionalProperties` to describe its + internal structure, handle this. + */}} + {{ if reflect.IsMap $property.additionalProperties }} + {{ if $property.additionalProperties.title }} + {{ $type = delimit (slice "{ string: " $property.additionalProperties.title "}" ) "" }} + {{ end }} + {{ end }} + + {{/* + 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 }} + + + + + + + + {{ end }} + +
{{ . }}
NameTypeDescription
{{ $property_name }}{{ $type }}{{ if $required }}Required: {{end}}{{ $property.description | markdownify }}{{ if eq $type "enum"}}

One of: {{ $property.enum }}.

{{ end }}
+ +{{ end }} diff --git a/layouts/partials/openapi/render-operation.html b/layouts/partials/openapi/render-operation.html new file mode 100644 index 00000000..430c571a --- /dev/null +++ b/layouts/partials/openapi/render-operation.html @@ -0,0 +1,65 @@ +{{/* + + Render a single HTTP API operation: that is, a method+endpoint combination, given: + + * `method`: the method, e.g. GET, PUT + * `endpoint`: the endpoint + * `operation_data`: the OpenAPI/Swagger data for the operation + * `path`: the path where this definition was found, to enable us to resolve "$ref" + + This template renders the operation as a `
` containing: + + * an `

` heading containing the method and endpoint + * a `
` element containing the details, including: + * operation description + * basic info about the operation + * request details + * response details + +*/}} + +{{ $method := .method }} +{{ $endpoint := .endpoint }} +{{ $operation_data := .operation_data }} +{{ $path := .path }} + +
+ +
+ + +

+ {{ $method }} + {{ $endpoint }} +

+ +
+ +{{ if $operation_data.deprecated }} + {{ partial "alert" (dict "type" "warning" "omit_title" "true" "content" "This API is deprecated and will be removed from a future release.") }} +{{ end }} + +

{{ $operation_data.description | markdownify }}

+ +
+ + + + + {{ $rate_limited := index $operation_data.responses "429" }} + + + + + + +
Rate-limited:{{ if $rate_limited }}Yes{{ else }}No{{ end }}
Requires authentication:{{ if $operation_data.security }}Yes{{ else }}No{{ end }}
+ +
+{{ partial "openapi/render-request" (dict "parameters" $operation_data.parameters "path" $path) }} +
+{{ partial "openapi/render-responses" (dict "responses" $operation_data.responses "path" $path) }} + +
+ +
diff --git a/layouts/partials/openapi/render-parameters.html b/layouts/partials/openapi/render-parameters.html new file mode 100644 index 00000000..2b4fb09d --- /dev/null +++ b/layouts/partials/openapi/render-parameters.html @@ -0,0 +1,30 @@ +{{/* + + Render the parameters of a given type, given: + + * `parameters`: OpenAPI/Swagger data specifying the parameters + * `type`: the type of parameters to render: "header, ""path", "query" + * `caption`: caption to use for the table + + This template renders a single table containing parameters of the given type. + +*/}} + +{{ $parameters := .parameters }} +{{ $type := .type }} +{{ $caption := .caption }} + +{{ $parameters_of_type := where $parameters "in" $type }} + +{{ with $parameters_of_type }} + + {{/* convert parameters into the format that render-object-table expects to see */}} + {{ $param_dict := dict }} + {{ range $parameter := . }} + {{ $param_dict = merge $param_dict (dict $parameter.name (dict "type" $parameter.type "description" $parameter.description "required" $parameter.required "enum" $parameter.enum) )}} + {{ end }} + + {{/* and render the parameters */}} + {{ partial "openapi/render-object-table" (dict "caption" $caption "properties" $param_dict) }} + +{{ end }} diff --git a/layouts/partials/openapi/render-request.html b/layouts/partials/openapi/render-request.html new file mode 100644 index 00000000..1695c2f8 --- /dev/null +++ b/layouts/partials/openapi/render-request.html @@ -0,0 +1,67 @@ +{{/* + + Render the request part of a single HTTP API operation, given: + + * `parameters`: OpenAPI/Swagger data specifying the parameters + * `path`: the path where this definition was found, to enable us to resolve "$ref" + + This template renders: + * the "simple parameters" (header, path, query parameters) + * body parameters, which may be more complex, containing nested objects + * response body examples + +*/}} + +{{ $parameters := .parameters }} +{{ $path := .path }} + +

Request

+ +{{ if $parameters }} + + {{ $simple_parameters := where $parameters "in" "!=" "body"}} + {{ if $simple_parameters }} +

Request parameters

+ + {{ partial "openapi/render-parameters" (dict "parameters" $simple_parameters "type" "header" "caption" "header parameters") }} + {{ partial "openapi/render-parameters" (dict "parameters" $simple_parameters "type" "path" "caption" "path parameters") }} + {{ partial "openapi/render-parameters" (dict "parameters" $simple_parameters "type" "query" "caption" "query parameters") }} + + {{ end }} + + {{ $body_parameters := where $parameters "in" "body"}} + {{ if $body_parameters }} +

Request body

+ + {{/* at most one body param is allowed by the spec */}} + {{ $body_parameter := index $body_parameters 0 }} + {{ $schema := partial "json-schema/resolve-refs" (dict "schema" $body_parameter.schema "path" $path) }} + {{ $schema := partial "json-schema/resolve-allof" $schema }} + + {{ $additional_types := partial "json-schema/resolve-additional-types" $schema }} + {{ $additional_types = uniq $additional_types }} + {{ range $additional_types }} + {{ partial "openapi/render-object-table" (dict "caption" .title "properties" .properties "required" .required) }} + {{ end }} + +

Request body example

+ + {{ $example := partial "json-schema/resolve-example" $schema }} + {{ if $example }} + {{ $example_json := jsonify (dict "indent" " ") $example }} + {{ $example_json = replace $example_json "\\u003c" "<" }} + {{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} + +```json +{{ $example_json }} +``` + + {{ else }} + {{ partial "alert" (dict "type" "warning" "omit_title" "true" "color" "warning" "content" "Specification error: Example invalid or not present") }} + {{ end }} + + {{ end }} + +{{ else }} +

No request parameters or request body.

+{{ end }} diff --git a/layouts/partials/openapi/render-responses.html b/layouts/partials/openapi/render-responses.html new file mode 100644 index 00000000..c92aba8e --- /dev/null +++ b/layouts/partials/openapi/render-responses.html @@ -0,0 +1,97 @@ +{{/* + + Render the response part of a single HTTP API operation, given: + + * `responses`: OpenAPI/Swagger data specifying the responses + * `path`: the path where this definition was found, to enable us to resolve "$ref" + + This template renders: + * a summary of all the different responses + * details of the body for each response code + * body parameters, which may be more complex, containing nested objects + * response body examples + +*/}} + +{{ $responses := .responses }} +{{ $path := .path }} + +

Responses

+ + + + + + + +{{ range $code, $response := $responses }} + + + + + + +{{ end }} + +
StatusDescription
{{ $code }}{{ $response.description | markdownify }}
+ +{{ range $code, $response := $responses }} + + {{ if $response.schema }} + + {{ $schema := partial "json-schema/resolve-refs" (dict "schema" $response.schema "path" $path) }} + {{ $schema := partial "json-schema/resolve-allof" $schema }} + + {{ if or $schema.properties (eq $schema.type "array") }} +

{{ $code}} response

+ + {{/* + 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 reflect.IsSlice $schema.items }} + {{ $types := slice }} + {{ range $schema.items }} + {{ if .title }} + {{ $types = $types | append .title}} + {{ else }} + {{ $types = $types | append .type }} + {{ end }} + {{ end }} + {{ $type_of = delimit $types ", "}} + {{ else }} + {{ $type_of = $schema.items.title }} + {{ end }} +

Array of {{ $type_of }}.

+ {{ end }} + + {{ $additional_types := partial "json-schema/resolve-additional-types" $schema }} + {{ $additional_types = uniq $additional_types }} + {{ range $additional_types }} + {{ partial "openapi/render-object-table" (dict "caption" .title "properties" .properties "required" .required) }} + {{ end }} + + {{ $example := partial "json-schema/resolve-example" $schema }} + {{ if $response.examples }} + {{ $example = partial "json-schema/resolve-refs" (dict "schema" $response.examples "path" $path) }} + {{ $example = index $example "application/json" }} + {{ end }} + + {{ if $example }} + {{ $example_json := jsonify (dict "indent" " ") $example }} + {{ $example_json = replace $example_json "\\u003c" "<" }} + {{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} + +```json +{{ $example_json }} +``` + + {{ else }} + {{ partial "alert" (dict "type" "warning" "omit_title" "true" "color" "warning" "content" "Specification error: Example invalid or not present") }} + {{ end }} + + {{ end }} + {{ end }} +{{ end }} diff --git a/layouts/shortcodes/definition.html b/layouts/shortcodes/definition.html new file mode 100644 index 00000000..151e0606 --- /dev/null +++ b/layouts/shortcodes/definition.html @@ -0,0 +1,59 @@ +{{/* + + This template is used to render EDUs and PDUs in the server-server and room versions specs. + + It expects to be passed a `path` parameter, which is a path, relative to /data, + pointing to a schema file. The file extension is omitted. For example: + + {{% definition path="api/server-server/definitions/edu" %}} + + This template replaces the old {{definition_*}} template. + +*/}} + +{{ $path := .Params.path }} +{{ $compact := .Params.compact }} +{{ $pieces := split $path "/" }} + +{{/* The definition is referenced by the .path parameter */}} +{{ $definition := index .Site.Data $pieces }} + +{{/* The base path, which we use to resolve $ref, omits the last component */}} +{{ $pieces = first (sub (len $pieces) 1) $pieces}} +{{ $path = delimit $pieces "/" }} + +{{/* Resolve $ref and allOf */}} +{{ $definition = partial "json-schema/resolve-refs" (dict "schema" $definition "path" $path) }} +{{ $definition = partial "json-schema/resolve-allof" $definition }} + +
+ +
+ + +

+ {{ $definition.title }} +

+ +
+ +{{ $definition.description | markdownify }} + +
+ +{{ $additional_types := partial "json-schema/resolve-additional-types" $definition }} +{{ $additional_types = uniq $additional_types }} + +{{ range $additional_types }} + {{ partial "openapi/render-object-table" (dict "caption" .title "properties" .properties "required" .required) }} +{{end}} + +

Examples

+ +{{ $example := partial "json-schema/resolve-example" $definition }} + +```json +{{ jsonify (dict "indent" " ") $example }} +``` + +
diff --git a/layouts/shortcodes/event-fields.html b/layouts/shortcodes/event-fields.html new file mode 100644 index 00000000..83651c21 --- /dev/null +++ b/layouts/shortcodes/event-fields.html @@ -0,0 +1,45 @@ +{{/* + + This template is used to render the fields that all basic events and room events + must or may contain. + + It expects to be passed an `event_type` parameter, is the name of a file under + /data/event-schemas/core-event-schema. The file extension is omitted. For example: + + {{% event-fields event_type="room_event" %}} + + This template replaces the old {{common_event_fields}} and {{common_room_event_fields}} templates. + +*/}} + +{{ $event := index .Site.Data "event-schemas" "schema" "core-event-schema" .Params.event_type }} +{{ $path := "event-schemas/schema/core-event-schema" }} + +{{ $event = partial "json-schema/resolve-refs" (dict "schema" $event "path" $path) }} +{{ $event := partial "json-schema/resolve-allof" $event }} + +
+ +
+ + +

+ {{ humanize $event.title }} +

+ +
+ +{{ $event.description | markdownify }} + +
+ +{{ $event = merge $event (dict "title" "") }} + +{{ $additional_types := partial "json-schema/resolve-additional-types" $event }} +{{ range $additional_types }} + {{ partial "openapi/render-object-table" (dict "caption" .title "properties" .properties "required" .required) }} +{{end}} + +
+ +
diff --git a/layouts/shortcodes/event-group.html b/layouts/shortcodes/event-group.html new file mode 100644 index 00000000..5e2900f0 --- /dev/null +++ b/layouts/shortcodes/event-group.html @@ -0,0 +1,32 @@ +{{/* + + This template is used to render a group of events starting with a given prefix. + + It expects to be passed a `group_name` parameter. For example: + + {{% event-group group_name="m.call" %}} + + The template will then render all events whose schema starts with the given name. + + This template replaces the old {{*_events}} template. + +*/}} + +{{ $path := "event-schemas/schema" }} + +{{ $events := index .Site.Data "event-schemas" "schema" }} +{{ $group_name := .Params.group_name }} + +{{ range $event_name, $event_data := $events }} + + {{ $prefix := substr $event_name 0 (len $group_name) }} + {{ if eq $prefix $group_name }} + + {{ $event_data = partial "json-schema/resolve-refs" (dict "schema" $event_data "path" $path) }} + {{ $event_data := partial "json-schema/resolve-allof" $event_data }} + + {{ partial "events/render-event" (dict "event_name" $event_name "event_data" $event_data)}} + + {{ end }} + +{{ end }} diff --git a/layouts/shortcodes/event.html b/layouts/shortcodes/event.html new file mode 100644 index 00000000..71c9c534 --- /dev/null +++ b/layouts/shortcodes/event.html @@ -0,0 +1,20 @@ +{{/* + + This template is used to render an event. + + It expects to be passed an `event` parameter, which is the name of a schema file under + "data/event-schemas/schema". The file extension is omitted. For example: + + {{% event event="m.accepted_terms" %}} + + This template replaces the old {{*_event}} template. + +*/}} + +{{ $event_data := index .Site.Data "event-schemas" "schema" .Params.event }} +{{ $path := "event-schemas/schema" }} + +{{ $event_data = partial "json-schema/resolve-refs" (dict "schema" $event_data "path" $path) }} +{{ $event_data := partial "json-schema/resolve-allof" $event_data }} + +{{ partial "events/render-event" (dict "event_name" .Params.event "event_data" $event_data)}} diff --git a/layouts/shortcodes/http-api.html b/layouts/shortcodes/http-api.html new file mode 100644 index 00000000..b4bc6d0d --- /dev/null +++ b/layouts/shortcodes/http-api.html @@ -0,0 +1,26 @@ +{{/* + + This template is used to render an HTTP API, given an OpenAPI/Swagger definition. + + It expects to be passed two parameters: + + * a `spec` parameter identifying the spec, which must be the name of + a directory under /data/api + * an `api` parameter, identifying an OpenAPI/Swagger definition, + which is the name of a schema file under "data/api/$spec". + The file extension is omitted. For example: + + {{% http-api spec="server-server" api="public_rooms" %}} + + This template replaces the old {{*_http_api}} template. + +*/}} + +{{ $spec := .Params.spec}} +{{ $api := .Params.api}} + +{{ $api_data := index .Site.Data.api .Params.spec .Params.api }} +{{ $base_url := replace $api_data.basePath "%CLIENT_MAJOR_VERSION%" "r0" }} +{{ $path := delimit (slice "api" $spec) "/" }} + +{{ partial "openapi/render-api" (dict "api_data" $api_data "base_url" $base_url "path" $path) }} diff --git a/layouts/shortcodes/msgtypes.html b/layouts/shortcodes/msgtypes.html new file mode 100644 index 00000000..695e9bb7 --- /dev/null +++ b/layouts/shortcodes/msgtypes.html @@ -0,0 +1,48 @@ +{{/* + + This template is used to render the `m.room.message` events. + + It replaces the old {{msgtype_events}} template. + +*/}} + +{{ $path := "event-schemas/schema" }} +{{ $compact := false }} + +{{/* + The old template starts with an explicit list of events, presumably + to define the order in which they are rendered. +*/}} +{{ $msgtypes := (slice "m.room.message$m.text" "m.room.message$m.emote" "m.room.message$m.notice" "m.room.message$m.image" "m.room.message$m.file") }} + +{{/* + It excludes `m.room.message$m.server_notice` +*/}} +{{ $excluded := slice "m.room.message$m.server_notice" }} + +{{/* + It then adds any other events that start `m.room.message`. +*/}} +{{ $events := index .Site.Data "event-schemas" "schema" }} +{{ $expected_prefix := "m.room.message$"}} +{{ range $object_name, $event_data := $events }} + + {{ $prefix := substr $object_name 0 (len $expected_prefix) }} + {{ if and (eq $prefix $expected_prefix) (not (in $excluded $object_name)) (not (in $msgtypes $object_name)) }} + {{ $msgtypes = $msgtypes | append $object_name }} + {{ end }} + +{{ end }} + +{{ $site_data := .Site.Data }} + +{{ range $msgtypes }} + + {{ $event_data := index $site_data "event-schemas" "schema" . }} + {{ $event_data = partial "json-schema/resolve-refs" (dict "schema" $event_data "path" $path) }} + {{ $event_data := partial "json-schema/resolve-allof" $event_data }} + + {{ $event_name := index (split . "$") 1 }} + {{ partial "events/render-event" (dict "event_name" $event_name "desired_example_name" . "event_data" $event_data)}} + +{{ end }}