feat(api): Add section index and All endpoints nav item

- Add api/section-children.html partial for API section index pages
- Update api/list.html to detect section index vs tag pages
- Add "All endpoints" nav item listing all operations sorted by method+path
- Remove {{< children >}} shortcode from API index pages (use data-driven list)
claude/api-code-samples-plan-MEkQO
Jason Stirnaman 2025-12-12 11:25:37 -06:00
parent 76b58732f9
commit beb8088417
4 changed files with 166 additions and 57 deletions

View File

@ -263,6 +263,14 @@
align-items: center;
gap: 0.4rem;
}
// Path-based operation display (All endpoints list)
&--path .api-path {
font-family: $proxima;
font-size: 0.55rem;
color: inherit;
word-break: break-all;
}
}
.api-method {

View File

@ -1,70 +1,38 @@
{{/*
API Documentation Tag/List Layout
API Documentation Layout
Displays tag-based API documentation pages with:
1. Title
2. Summary (brief description)
3. Operations list (links to nested operation pages)
4. Description (detailed content)
Handles two cases:
1. Section index (no 'tag' param) - shows list of tag pages from article data
2. Tag pages (has 'tag' param) - shows operations list and description
For conceptual pages (isConceptual: true), shows content without operations list.
Required frontmatter:
- title: Page title
- description or summary: Brief description
- operations: Array of operation objects (for non-conceptual pages)
*/}}
{{ partial "header.html" . }}
{{ partial "topnav.html" . }}
<div class="page-wrapper">
{{/* Left: Existing Hugo sidebar (includes API nav via sidebar.html) */}}
{{ partial "sidebar.html" . }}
{{/* Center + Right: Content and TOC */}}
<div class="content-wrapper api-content">
<div class="api-main">
<article class="article article--content api-reference" role="main">
<header class="article--header">
<div class="article--header-row">
<div class="article--header-text">
<h1 class="article--title">{{ .Title }}</h1>
{{/* Summary - first sentence only at top */}}
{{ with .Params.summary }}
<p class="article--summary">{{ . | markdownify }}</p>
{{ else }}
{{/* Extract first sentence from description (or full text if no sentence ending) */}}
{{ with .Description }}
{{ $matches := findRE `^[^.!?]*[.!?]` . 1 }}
{{ if gt (len $matches) 0 }}
{{ $firstSentence := index $matches 0 }}
<p class="article--summary">{{ $firstSentence | markdownify }}</p>
{{ else }}
{{/* No sentence ending found - use first line or full description */}}
{{ $firstLine := index (split . "\n") 0 }}
<p class="article--summary">{{ $firstLine | markdownify }}</p>
{{ end }}
{{ end }}
{{ end }}
</div>
{{/* Download OpenAPI spec button */}}
{{ with .Params.staticFilePath }}
<div class="api-spec-actions">
<a href="{{ . }}" class="btn api-spec-download" download>
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
<path d="M8 12L3 7h3V2h4v5h3L8 12z"/>
<path d="M1 14h14v2H1v-2z"/>
</svg>
Download OpenAPI Spec
</a>
</div>
{{ end }}
</div>
<h1 class="article--title">{{ .Title }}</h1>
{{ with .Description }}
<p class="article--description">{{ . }}</p>
{{ end }}
</header>
{{/* Check if this is a section index (no tag param) or a tag page */}}
{{ $hasTag := isset .Params "tag" }}
{{ if not $hasTag }}
{{/* SECTION INDEX - Show tag pages from article data */}}
{{ partial "api/section-children.html" . }}
{{ else }}
{{/* TAG PAGE - Show operations or conceptual content */}}
{{ $isConceptual := .Params.isConceptual | default false }}
{{ if $isConceptual }}
@ -78,17 +46,15 @@
{{ end }}
{{ end }}
</section>
{{ else }}
{{/* Operational Page - Show operations list then description */}}
{{/* Operations List */}}
{{ $operations := .Params.operations }}
{{ if $operations }}
<section class="api-operations-list">
<h2 id="endpoints">Endpoints</h2>
<div class="api-operations-grid">
{{ range $operations }}
{{/* Build URL: parent section (e.g., /influxdb3/core/api/) + operation path + method */}}
{{ $apiBase := $.Parent.RelPermalink }}
{{ $operationURL := printf "%s%s/%s/" $apiBase .path (lower .method) }}
<a href="{{ $operationURL }}" class="api-operation-card">
@ -117,18 +83,14 @@
</section>
{{ end }}
{{/* RapiDoc renderer - only for pages with additional content beyond description */}}
{{/* Don't show RapiDoc on list pages since operations are already shown as cards above */}}
{{ end }}
{{ end }}
{{/* Related documentation links */}}
{{ partial "article/related.html" . }}
</article>
</div>
{{/* Right: Page TOC - "ON THIS PAGE" */}}
<aside class="api-toc" data-component="api-toc">
<h4 class="api-toc-header">ON THIS PAGE</h4>
<nav class="api-toc-nav"></nav>

View File

@ -0,0 +1,87 @@
{{/*
API Section Children
Renders tag pages from article data as a children list.
Sort order: conceptual tags (traitTags) first, then other tags alphabetically.
Uses data from:
- data/article_data/influxdb/{product}/articles.yml
*/}}
{{ $currentPage := . }}
{{/* Extract product and version from URL */}}
{{ $productPathData := findRE "[^/]+.*?" .RelPermalink }}
{{ $product := index $productPathData 0 }}
{{ $version := index $productPathData 1 }}
{{/* Build data key for article data lookup */}}
{{ $dataKey := "" }}
{{ if eq $product "influxdb3" }}
{{ $dataKey = print "influxdb3_" $version }}
{{ else if eq $product "influxdb" }}
{{ $dataKey = print $version }}
{{ else }}
{{ $dataKey = $product }}
{{ end }}
{{/* Get article data for this product */}}
{{ $articles := slice }}
{{ with site.Data.article_data }}
{{ with index . "influxdb" }}
{{ with index . $dataKey }}
{{ with index . "articles" }}
{{ with .articles }}
{{ $articles = . }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ if gt (len $articles) 0 }}
{{/* Separate conceptual (traitTag) and non-conceptual articles */}}
{{ $conceptualArticles := slice }}
{{ $operationArticles := slice }}
{{ range $articles }}
{{ if and (reflect.IsMap .) (isset . "fields") }}
{{ $fields := index . "fields" }}
{{ if reflect.IsMap $fields }}
{{ $isConceptual := false }}
{{ if isset $fields "isConceptual" }}
{{ $isConceptual = index $fields "isConceptual" }}
{{ end }}
{{ if $isConceptual }}
{{ $conceptualArticles = $conceptualArticles | append . }}
{{ else }}
{{ $operationArticles = $operationArticles | append . }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{/* Sort each group alphabetically by tag name */}}
{{ $conceptualArticles = sort $conceptualArticles "fields.tag" }}
{{ $operationArticles = sort $operationArticles "fields.tag" }}
{{/* Combine: conceptual first, then operations */}}
{{ $sortedArticles := $conceptualArticles | append $operationArticles }}
<section class="api-children children">
{{ range $sortedArticles }}
{{ $path := index . "path" }}
{{ $fields := index . "fields" }}
{{ $tag := index $fields "tag" }}
{{ $description := index $fields "description" | default "" }}
{{ $tagPageUrl := print "/" $product "/" $version "/" $path "/" | relURL }}
<div class="child-item">
<h3 id="{{ $tag | urlize }}"><a href="{{ $tagPageUrl }}">{{ $tag }}</a></h3>
{{ with $description }}
<p>{{ . }}</p>
{{ end }}
</div>
{{ end }}
</section>
{{ end }}

View File

@ -148,4 +148,56 @@
{{ end }}
</li>
{{ end }}
{{/* ALL ENDPOINTS - Collect all operations and sort by method+path */}}
{{ $allOperations := slice }}
{{ range $operationArticles }}
{{ $fields := index . "fields" }}
{{ if isset $fields "operations" }}
{{ range index $fields "operations" }}
{{ $allOperations = $allOperations | append . }}
{{ end }}
{{ end }}
{{ end }}
{{ if gt (len $allOperations) 0 }}
{{/* Sort operations alphabetically by path, then method */}}
{{ $sortedOps := slice }}
{{ range $allOperations }}
{{ $sortKey := printf "%s %s" .path (upper .method) }}
{{ $sortedOps = $sortedOps | append (dict "sortKey" $sortKey "op" .) }}
{{ end }}
{{ $sortedOps = sort $sortedOps "sortKey" }}
{{/* Check if any operation is active */}}
{{ $anyOpActive := false }}
{{ range $sortedOps }}
{{ $op := .op }}
{{ $opPathSlug := $op.path | replaceRE "^/" "" }}
{{ $opUrl := printf "/%s/%s/api/%s/%s/" $product $version $opPathSlug (lower $op.method) }}
{{ if eq $currentPage.RelPermalink $opUrl }}
{{ $anyOpActive = true }}
{{ end }}
{{ end }}
<li class="nav-item">
<a href="#" class="children-toggle{{ if $anyOpActive }} open{{ end }}"></a>
<span class="nav-group-label">All endpoints</span>
<ul class="children{{ if $anyOpActive }} open{{ end }}">
{{ range $sortedOps }}
{{ $op := .op }}
{{ $apiPath := $op.path }}
{{ $opPathSlug := $apiPath | replaceRE "^/" "" }}
{{ $operationUrl := printf "/%s/%s/api/%s/%s/" $product $version $opPathSlug (lower $op.method) | relURL }}
{{ $opIsActive := eq $currentPage.RelPermalink (printf "/%s/%s/api/%s/%s/" $product $version $opPathSlug (lower $op.method)) }}
<li class="nav-item api-operation api-operation--path{{ if $opIsActive }} active{{ end }}">
<a href="{{ $operationUrl | safeURL }}">
<span class="api-method api-method--{{ lower $op.method }}">{{ upper $op.method }}</span>
<span class="api-path">{{ $apiPath }}</span>
</a>
</li>
{{ end }}
</ul>
</li>
{{ end }}
{{ end }}