matrix-spec/layouts/_partials/openapi/render-operation.html
Andrew Morgan f30e850bf1 Fix duplicate modules endpoints
I was seeing duplicate endpoints appearing under each module (typically
2 of each). This turned out to be due to the `render-operation` partial
being called multiple times (once when rendering the page, and another
when rendering the left-hand-side TOC).

We now check whether the endpoint has already been added to the list
before insertion, via a "seen" map (for quick lookup).
2025-12-10 20:34:16 +00:00

119 lines
4.1 KiB
HTML

{{/*
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 data for the operation
* `anchor_base`: an optional prefix for the HTML IDs generated by
this template.
This template renders the operation as a `<section>` containing:
* an `<h1>` heading containing the method and endpoint
* a `<details>` element containing the details, including:
* operation description
* basic info about the operation
* request details
* response details
*/}}
{{ $method := .method }}
{{ $endpoint := .endpoint }}
{{ $operation_data := .operation_data }}
{{ $page := .page }}
{{ $module := .module }}
{{ $anchor := "" }}
{{ if .anchor_base }}
{{ $anchor = printf "%s_" .anchor_base }}
{{ end }}
{{ $anchor = printf "%s%s%s" $anchor (lower $method) (anchorize $endpoint) }}
{{/* Collect endpoints for the on-page endpoints TOC */}}
{{ if $page }}
{{/* Store each endpoint's metadata in a scratch variable */}}
{{ $entry := dict "anchor" $anchor "method" $method "endpoint" $endpoint "summary" $operation_data.summary "deprecated" $operation_data.deprecated "module" $module }}
{{ if not ($page.Scratch.Get "api_endpoints_seen") }}
{{ $page.Scratch.Set "api_endpoints_seen" dict }}
{{ end }}
{{/* Keep a map of seen endpoints. This is necessary as this partial may be
rendered multiple times for the same endpoint (e.g. in the TOC and
in the main content), leading to duplicates. */}}
{{ $seen := $page.Scratch.Get "api_endpoints_seen" }}
{{ $key := printf "%s|%s" $method $endpoint }}
{{ if not (index $seen $key) }}
{{ if not (reflect.IsSlice ($page.Scratch.Get "api_endpoints")) }}
{{ $page.Scratch.Set "api_endpoints" (slice) }}
{{ end }}
{{ $page.Scratch.Add "api_endpoints" (slice $entry) }}
{{ $page.Scratch.SetInMap "api_endpoints_seen" $key true }}
{{ end }}
{{ end }}
<section class="rendered-data">
<details {{ if not site.Params.ui.rendered_data_collapsed }}open{{ end }}>
<summary>
<h1 id="{{ $anchor }}">
<span class="http-api-method">{{ $method }}</span>
<span class="endpoint{{ if $operation_data.deprecated }} deprecated-inline{{ end }}">{{ $endpoint }}</span>
{{ partial "td/heading-self-link.html" (dict "Anchor" $anchor) }}
</h1>
</summary>
<hr>
{{ 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 }}
{{ if (index $operation_data "x-addedInMatrixVersion") }}
{{ partial "added-in" (dict "v" (index $operation_data "x-addedInMatrixVersion")) }}
{{ end }}
{{ if (index $operation_data "x-changedInMatrixVersion") }}
{{ partial "changed-in" (dict "changes_dict" (index $operation_data "x-changedInMatrixVersion")) }}
{{ end -}}
{{ $operation_data.description | page.RenderString (dict "display" "block") }}
<table class="basic-info">
<tr>
<th>Rate-limited:</th>
{{ $rate_limited := index $operation_data.responses "429" }}
<td>{{ if $rate_limited }}Yes{{ else }}No{{ end }}</td>
</tr>
<tr>
<th>Requires authentication:</th>
{{/*
Authentication is defined with the `security` key. We assume that the
key is not set if no authentication is necessary. If the key is set,
authentication is required unless it contains an item that is an empty
object.
*/}}
{{ $requires_authentication := "Yes" }}
{{ if $operation_data.security }}
{{ range $operation_data.security }}
{{ if eq (len (index $operation_data.security 0)) 0 }}
{{ $requires_authentication = "Optional" }}
{{ end }}
{{ end }}
{{ else }}
{{ $requires_authentication = "No" }}
{{ end }}
<td>{{ $requires_authentication }}</td>
</tr>
</table>
<hr>
{{ partial "openapi/render-request" (dict "parameters" $operation_data.parameters "request_body" $operation_data.requestBody "anchor_base" $anchor ) }}
<hr>
{{ partial "openapi/render-responses" (dict "responses" $operation_data.responses "anchor_base" $anchor ) }}
</details>
</section>