feat(api): add All endpoints page and fix v2 menu warnings
- Add "All endpoints" page showing all operations grouped by API version
- Generate all-endpoints page automatically via TypeScript generation script
- Make "All endpoints" nav item a clickable link instead of just a toggle
- Fix duplicate menu entry warnings for cloud-v2 and oss-v2 products
by adding skipParentMenu: true to their configs
- Fix 404 errors for paths with curly braces (e.g., {request_path})
by removing braces in normalize-path.html partial
- Add Cypress tests for API section structure and all-endpoints page
- Update v2 product article data with tag-based generation
claude/api-code-samples-plan-MEkQO
parent
eb6feb75d2
commit
138e9e4f6e
|
|
@ -313,6 +313,36 @@ ${introText}
|
|||
fs.writeFileSync(parentIndexFile, parentContent);
|
||||
console.log(`✓ Generated parent index at ${parentIndexFile}`);
|
||||
}
|
||||
// Generate "All endpoints" page
|
||||
const allEndpointsDir = path.join(apiParentDir, 'all-endpoints');
|
||||
const allEndpointsFile = path.join(allEndpointsDir, '_index.md');
|
||||
if (!fs.existsSync(allEndpointsDir)) {
|
||||
fs.mkdirSync(allEndpointsDir, { recursive: true });
|
||||
}
|
||||
const allEndpointsFrontmatter = {
|
||||
title: 'All endpoints',
|
||||
description: `View all API endpoints sorted by path.`,
|
||||
type: 'api',
|
||||
layout: 'all-endpoints',
|
||||
weight: 999,
|
||||
isAllEndpoints: true,
|
||||
};
|
||||
// Add menu entry for all-endpoints page
|
||||
if (menuKey) {
|
||||
allEndpointsFrontmatter.menu = {
|
||||
[menuKey]: {
|
||||
name: 'All endpoints',
|
||||
parent: menuParent || 'InfluxDB HTTP API',
|
||||
},
|
||||
};
|
||||
}
|
||||
const allEndpointsContent = `---
|
||||
${yaml.dump(allEndpointsFrontmatter)}---
|
||||
|
||||
All {{% product-name %}} API endpoints, sorted by path.
|
||||
`;
|
||||
fs.writeFileSync(allEndpointsFile, allEndpointsContent);
|
||||
console.log(`✓ Generated all-endpoints page at ${allEndpointsFile}`);
|
||||
// Generate a page for each article (tag)
|
||||
for (const article of data.articles) {
|
||||
const pagePath = path.join(contentPath, article.path);
|
||||
|
|
@ -506,21 +536,25 @@ ${yaml.dump(frontmatter)}---
|
|||
* Maps product identifiers to their OpenAPI specs and content directories
|
||||
*/
|
||||
const productConfigs = {
|
||||
// TODO: v2 products (cloud-v2, oss-v2) are disabled for now because they
|
||||
// have existing Redoc-based API reference at /reference/api/
|
||||
// Uncomment when ready to migrate v2 products to RapiDoc
|
||||
// 'cloud-v2': {
|
||||
// specFile: path.join(API_DOCS_ROOT, 'influxdb/cloud/v2/ref.yml'),
|
||||
// pagesDir: path.join(DOCS_ROOT, 'content/influxdb/cloud/api'),
|
||||
// description: 'InfluxDB Cloud (v2 API)',
|
||||
// menuKey: 'influxdb_cloud',
|
||||
// },
|
||||
// 'oss-v2': {
|
||||
// specFile: path.join(API_DOCS_ROOT, 'influxdb/v2/v2/ref.yml'),
|
||||
// pagesDir: path.join(DOCS_ROOT, 'content/influxdb/v2/api'),
|
||||
// description: 'InfluxDB OSS v2',
|
||||
// menuKey: 'influxdb_v2',
|
||||
// },
|
||||
// InfluxDB v2 products - use tag-based generation for consistency
|
||||
// These have existing /reference/api/ pages with menu entries,
|
||||
// so we skip adding menu entries to the generated parent pages.
|
||||
'cloud-v2': {
|
||||
specFile: path.join(API_DOCS_ROOT, 'influxdb/cloud/v2/ref.yml'),
|
||||
pagesDir: path.join(DOCS_ROOT, 'content/influxdb/cloud'),
|
||||
description: 'InfluxDB Cloud (v2 API)',
|
||||
menuKey: 'influxdb_cloud',
|
||||
skipParentMenu: true,
|
||||
useTagBasedGeneration: true,
|
||||
},
|
||||
'oss-v2': {
|
||||
specFile: path.join(API_DOCS_ROOT, 'influxdb/v2/v2/ref.yml'),
|
||||
pagesDir: path.join(DOCS_ROOT, 'content/influxdb/v2'),
|
||||
description: 'InfluxDB OSS v2',
|
||||
menuKey: 'influxdb_v2',
|
||||
skipParentMenu: true,
|
||||
useTagBasedGeneration: true,
|
||||
},
|
||||
// InfluxDB 3 products use tag-based generation for better UX
|
||||
// Keys use underscores to match Hugo data directory structure
|
||||
influxdb3_core: {
|
||||
|
|
|
|||
|
|
@ -449,6 +449,42 @@ ${introText}
|
|||
console.log(`✓ Generated parent index at ${parentIndexFile}`);
|
||||
}
|
||||
|
||||
// Generate "All endpoints" page
|
||||
const allEndpointsDir = path.join(apiParentDir, 'all-endpoints');
|
||||
const allEndpointsFile = path.join(allEndpointsDir, '_index.md');
|
||||
|
||||
if (!fs.existsSync(allEndpointsDir)) {
|
||||
fs.mkdirSync(allEndpointsDir, { recursive: true });
|
||||
}
|
||||
|
||||
const allEndpointsFrontmatter: Record<string, unknown> = {
|
||||
title: 'All endpoints',
|
||||
description: `View all API endpoints sorted by path.`,
|
||||
type: 'api',
|
||||
layout: 'all-endpoints',
|
||||
weight: 999,
|
||||
isAllEndpoints: true,
|
||||
};
|
||||
|
||||
// Add menu entry for all-endpoints page
|
||||
if (menuKey) {
|
||||
allEndpointsFrontmatter.menu = {
|
||||
[menuKey]: {
|
||||
name: 'All endpoints',
|
||||
parent: menuParent || 'InfluxDB HTTP API',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const allEndpointsContent = `---
|
||||
${yaml.dump(allEndpointsFrontmatter)}---
|
||||
|
||||
All {{% product-name %}} API endpoints, sorted by path.
|
||||
`;
|
||||
|
||||
fs.writeFileSync(allEndpointsFile, allEndpointsContent);
|
||||
console.log(`✓ Generated all-endpoints page at ${allEndpointsFile}`);
|
||||
|
||||
// Generate a page for each article (tag)
|
||||
for (const article of data.articles) {
|
||||
const pagePath = path.join(contentPath, article.path);
|
||||
|
|
@ -710,21 +746,25 @@ ${yaml.dump(frontmatter)}---
|
|||
* Maps product identifiers to their OpenAPI specs and content directories
|
||||
*/
|
||||
const productConfigs: ProductConfigMap = {
|
||||
// TODO: v2 products (cloud-v2, oss-v2) are disabled for now because they
|
||||
// have existing Redoc-based API reference at /reference/api/
|
||||
// Uncomment when ready to migrate v2 products to RapiDoc
|
||||
// 'cloud-v2': {
|
||||
// specFile: path.join(API_DOCS_ROOT, 'influxdb/cloud/v2/ref.yml'),
|
||||
// pagesDir: path.join(DOCS_ROOT, 'content/influxdb/cloud/api'),
|
||||
// description: 'InfluxDB Cloud (v2 API)',
|
||||
// menuKey: 'influxdb_cloud',
|
||||
// },
|
||||
// 'oss-v2': {
|
||||
// specFile: path.join(API_DOCS_ROOT, 'influxdb/v2/v2/ref.yml'),
|
||||
// pagesDir: path.join(DOCS_ROOT, 'content/influxdb/v2/api'),
|
||||
// description: 'InfluxDB OSS v2',
|
||||
// menuKey: 'influxdb_v2',
|
||||
// },
|
||||
// InfluxDB v2 products - use tag-based generation for consistency
|
||||
// These have existing /reference/api/ pages with menu entries,
|
||||
// so we skip adding menu entries to the generated parent pages.
|
||||
'cloud-v2': {
|
||||
specFile: path.join(API_DOCS_ROOT, 'influxdb/cloud/v2/ref.yml'),
|
||||
pagesDir: path.join(DOCS_ROOT, 'content/influxdb/cloud'),
|
||||
description: 'InfluxDB Cloud (v2 API)',
|
||||
menuKey: 'influxdb_cloud',
|
||||
skipParentMenu: true,
|
||||
useTagBasedGeneration: true,
|
||||
},
|
||||
'oss-v2': {
|
||||
specFile: path.join(API_DOCS_ROOT, 'influxdb/v2/v2/ref.yml'),
|
||||
pagesDir: path.join(DOCS_ROOT, 'content/influxdb/v2'),
|
||||
description: 'InfluxDB OSS v2',
|
||||
menuKey: 'influxdb_v2',
|
||||
skipParentMenu: true,
|
||||
useTagBasedGeneration: true,
|
||||
},
|
||||
// InfluxDB 3 products use tag-based generation for better UX
|
||||
// Keys use underscores to match Hugo data directory structure
|
||||
influxdb3_core: {
|
||||
|
|
|
|||
|
|
@ -331,3 +331,110 @@ describe('RapiDoc Mini component', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* API Section Page Structure Tests
|
||||
* Tests that API section pages show only tags (immediate children)
|
||||
*/
|
||||
describe('API section page structure', () => {
|
||||
const sectionPages = [
|
||||
'/influxdb3/core/api/',
|
||||
'/influxdb3/enterprise/api/',
|
||||
];
|
||||
|
||||
sectionPages.forEach((page) => {
|
||||
describe(`Section page ${page}`, () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('GET', '**', (req) => {
|
||||
req.continue((res) => {
|
||||
if (res.headers['content-type']?.includes('text/html')) {
|
||||
res.body = res.body.replace(
|
||||
/data-user-analytics-fingerprint-enabled="true"/,
|
||||
'data-user-analytics-fingerprint-enabled="false"'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
cy.visit(page);
|
||||
});
|
||||
|
||||
it('displays page title', () => {
|
||||
cy.get('h1').should('contain', 'InfluxDB HTTP API');
|
||||
});
|
||||
|
||||
it('shows tag pages as children', () => {
|
||||
cy.get('.children-links h3 a').should('have.length.at.least', 5);
|
||||
});
|
||||
|
||||
it('does not show individual operations in content area', () => {
|
||||
// Operations cards should not appear in the main content
|
||||
cy.get('.article--content .api-operation-card').should('not.exist');
|
||||
});
|
||||
|
||||
it('has All endpoints link in navigation', () => {
|
||||
cy.get('.sidebar a').contains('All endpoints').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* All Endpoints Page Tests
|
||||
* Tests the "All endpoints" page shows all operations
|
||||
*/
|
||||
describe('All endpoints page', () => {
|
||||
const allEndpointsPages = [
|
||||
'/influxdb3/core/api/all-endpoints/',
|
||||
'/influxdb3/enterprise/api/all-endpoints/',
|
||||
];
|
||||
|
||||
allEndpointsPages.forEach((page) => {
|
||||
describe(`All endpoints ${page}`, () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('GET', '**', (req) => {
|
||||
req.continue((res) => {
|
||||
if (res.headers['content-type']?.includes('text/html')) {
|
||||
res.body = res.body.replace(
|
||||
/data-user-analytics-fingerprint-enabled="true"/,
|
||||
'data-user-analytics-fingerprint-enabled="false"'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
cy.visit(page);
|
||||
});
|
||||
|
||||
it('displays page title "All endpoints"', () => {
|
||||
cy.get('h1').should('contain', 'All endpoints');
|
||||
});
|
||||
|
||||
it('shows v3 API section', () => {
|
||||
cy.get('#v3-api').should('exist');
|
||||
});
|
||||
|
||||
it('displays operation cards', () => {
|
||||
cy.get('.api-operation-card').should('have.length.at.least', 10);
|
||||
});
|
||||
|
||||
it('operation cards have method badges', () => {
|
||||
cy.get('.api-operation-card .api-method').should('have.length.at.least', 10);
|
||||
});
|
||||
|
||||
it('operation cards have path codes', () => {
|
||||
cy.get('.api-operation-card .api-path').should('have.length.at.least', 10);
|
||||
});
|
||||
|
||||
it('operation cards link to operation pages', () => {
|
||||
cy.get('.api-operation-card').first().should('have.attr', 'href').and('match', /\/api\//);
|
||||
});
|
||||
|
||||
it('is accessible from navigation', () => {
|
||||
// Navigate back to section page
|
||||
cy.get('.sidebar a').contains('InfluxDB HTTP API').click();
|
||||
// Then navigate to All endpoints
|
||||
cy.get('.sidebar a').contains('All endpoints').click();
|
||||
cy.url().should('include', '/all-endpoints/');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,48 @@
|
|||
{{/*
|
||||
All Endpoints Layout
|
||||
|
||||
Shows all API operations on a single page, grouped by version and sorted by path.
|
||||
Used for /api/all-endpoints/ pages.
|
||||
|
||||
Uses data from:
|
||||
- data/article_data/influxdb/{product}/articles.yml
|
||||
*/}}
|
||||
|
||||
{{ partial "header.html" . }}
|
||||
{{ partial "topnav.html" . }}
|
||||
|
||||
<div class="page-wrapper">
|
||||
{{ partial "sidebar.html" . }}
|
||||
|
||||
<div class="content-wrapper api-content">
|
||||
<div class="api-main">
|
||||
<article class="article article--content api-reference" role="main">
|
||||
<header class="article--header">
|
||||
<h1 class="article--title">{{ .Title }}</h1>
|
||||
{{ with .Description }}
|
||||
<p class="article--description">{{ . }}</p>
|
||||
{{ end }}
|
||||
</header>
|
||||
|
||||
{{ with .Content }}
|
||||
<section class="api-section-content">
|
||||
{{ . }}
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{/* Get all operations from article data */}}
|
||||
{{ partial "api/all-endpoints-list.html" . }}
|
||||
|
||||
{{ partial "article/related.html" . }}
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<aside class="api-toc" data-component="api-toc">
|
||||
<h4 class="api-toc-header">ON THIS PAGE</h4>
|
||||
<nav class="api-toc-nav"></nav>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ partial "footer.html" . }}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
{{/*
|
||||
All Endpoints List
|
||||
|
||||
Renders all API operations grouped by version (v3, v2, v1) and sorted by path.
|
||||
Excludes conceptual/trait tag operations.
|
||||
|
||||
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 }}
|
||||
|
||||
{{/* Collect all operations from non-conceptual articles */}}
|
||||
{{ $allOperations := 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 not $isConceptual }}
|
||||
{{ if isset $fields "operations" }}
|
||||
{{ $tag := index $fields "tag" }}
|
||||
{{ range index $fields "operations" }}
|
||||
{{ $allOperations = $allOperations | append (dict "op" . "tag" $tag) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if gt (len $allOperations) 0 }}
|
||||
{{/* Group operations by API version prefix */}}
|
||||
{{ $v3Ops := slice }}
|
||||
{{ $v2Ops := slice }}
|
||||
{{ $v1Ops := slice }}
|
||||
{{ $otherOps := slice }}
|
||||
|
||||
{{ range $allOperations }}
|
||||
{{ $path := .op.path }}
|
||||
{{ if hasPrefix $path "/api/v3" }}
|
||||
{{ $v3Ops = $v3Ops | append . }}
|
||||
{{ else if hasPrefix $path "/api/v2" }}
|
||||
{{ $v2Ops = $v2Ops | append . }}
|
||||
{{ else if or (hasPrefix $path "/api/v1") (hasPrefix $path "/health") (hasPrefix $path "/ping") (hasPrefix $path "/metrics") (hasPrefix $path "/query") (hasPrefix $path "/write") }}
|
||||
{{ $v1Ops = $v1Ops | append . }}
|
||||
{{ else }}
|
||||
{{ $otherOps = $otherOps | append . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Sort each group by path then method */}}
|
||||
{{ $sortV3 := slice }}
|
||||
{{ range $v3Ops }}
|
||||
{{ $sortKey := printf "%s %s" .op.path (upper .op.method) }}
|
||||
{{ $sortV3 = $sortV3 | append (dict "sortKey" $sortKey "data" .) }}
|
||||
{{ end }}
|
||||
{{ $sortV3 = sort $sortV3 "sortKey" }}
|
||||
|
||||
{{ $sortV2 := slice }}
|
||||
{{ range $v2Ops }}
|
||||
{{ $sortKey := printf "%s %s" .op.path (upper .op.method) }}
|
||||
{{ $sortV2 = $sortV2 | append (dict "sortKey" $sortKey "data" .) }}
|
||||
{{ end }}
|
||||
{{ $sortV2 = sort $sortV2 "sortKey" }}
|
||||
|
||||
{{ $sortV1 := slice }}
|
||||
{{ range $v1Ops }}
|
||||
{{ $sortKey := printf "%s %s" .op.path (upper .op.method) }}
|
||||
{{ $sortV1 = $sortV1 | append (dict "sortKey" $sortKey "data" .) }}
|
||||
{{ end }}
|
||||
{{ $sortV1 = sort $sortV1 "sortKey" }}
|
||||
|
||||
{{/* Render v3 API endpoints */}}
|
||||
{{ if gt (len $sortV3) 0 }}
|
||||
<section class="api-operations-list api-version-group">
|
||||
<h2 id="v3-api">v3 API</h2>
|
||||
<div class="api-operations-grid">
|
||||
{{ range $sortV3 }}
|
||||
{{ $op := .data.op }}
|
||||
{{ $tag := .data.tag }}
|
||||
{{ $apiBase := $currentPage.Parent.RelPermalink }}
|
||||
{{ $pathWithoutApiPrefix := $op.path | strings.TrimPrefix "/api" }}
|
||||
{{ $normalizedPath := $pathWithoutApiPrefix | strings.TrimPrefix "/" }}
|
||||
{{ $operationURL := printf "%s%s/%s/" $apiBase $normalizedPath (lower $op.method) }}
|
||||
<a href="{{ $operationURL }}" class="api-operation-card">
|
||||
<span class="api-method api-method--{{ lower $op.method }}">{{ upper $op.method }}</span>
|
||||
<code class="api-path">{{ $op.path }}</code>
|
||||
<span class="api-operation-summary">{{ $op.summary }}</span>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{/* Render v2-compatible endpoints */}}
|
||||
{{ if gt (len $sortV2) 0 }}
|
||||
<section class="api-operations-list api-version-group">
|
||||
<h2 id="v2-compatible">v2-compatible API</h2>
|
||||
<div class="api-operations-grid">
|
||||
{{ range $sortV2 }}
|
||||
{{ $op := .data.op }}
|
||||
{{ $tag := .data.tag }}
|
||||
{{ $apiBase := $currentPage.Parent.RelPermalink }}
|
||||
{{ $pathWithoutApiPrefix := $op.path | strings.TrimPrefix "/api" }}
|
||||
{{ $normalizedPath := $pathWithoutApiPrefix | strings.TrimPrefix "/" }}
|
||||
{{ $operationURL := printf "%s%s/%s/" $apiBase $normalizedPath (lower $op.method) }}
|
||||
<a href="{{ $operationURL }}" class="api-operation-card">
|
||||
<span class="api-method api-method--{{ lower $op.method }}">{{ upper $op.method }}</span>
|
||||
<code class="api-path">{{ $op.path }}</code>
|
||||
<span class="api-operation-summary">{{ $op.summary }}</span>
|
||||
{{ with $op.compatVersion }}<span class="api-compat-badge api-compat-badge--{{ . }}">{{ . }}</span>{{ end }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{/* Render v1-compatible endpoints */}}
|
||||
{{ if gt (len $sortV1) 0 }}
|
||||
<section class="api-operations-list api-version-group">
|
||||
<h2 id="v1-compatible">v1-compatible API</h2>
|
||||
<div class="api-operations-grid">
|
||||
{{ range $sortV1 }}
|
||||
{{ $op := .data.op }}
|
||||
{{ $tag := .data.tag }}
|
||||
{{ $apiBase := $currentPage.Parent.RelPermalink }}
|
||||
{{ $pathWithoutApiPrefix := $op.path | strings.TrimPrefix "/api" }}
|
||||
{{ $normalizedPath := $pathWithoutApiPrefix }}
|
||||
{{/* v1 paths may not have /api prefix - normalize */}}
|
||||
{{ if not (findRE `^/v\d+/` $pathWithoutApiPrefix) }}
|
||||
{{ $normalizedPath = printf "/v1%s" $pathWithoutApiPrefix }}
|
||||
{{ end }}
|
||||
{{ $normalizedPath = $normalizedPath | strings.TrimPrefix "/" }}
|
||||
{{ $operationURL := printf "%s%s/%s/" $apiBase $normalizedPath (lower $op.method) }}
|
||||
<a href="{{ $operationURL }}" class="api-operation-card">
|
||||
<span class="api-method api-method--{{ lower $op.method }}">{{ upper $op.method }}</span>
|
||||
<code class="api-path">{{ $op.path }}</code>
|
||||
<span class="api-operation-summary">{{ $op.summary }}</span>
|
||||
{{ with $op.compatVersion }}<span class="api-compat-badge api-compat-badge--{{ . }}">{{ . }}</span>{{ end }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<p>No endpoints available.</p>
|
||||
{{ end }}
|
||||
|
|
@ -5,15 +5,18 @@
|
|||
1. Strips leading "/api" prefix (parent directory provides /api/)
|
||||
2. Adds v1/ prefix for paths without a version (e.g., /write → v1/write)
|
||||
3. Strips leading "/" to avoid double slashes
|
||||
4. Removes curly braces from path parameters (e.g., {db} → db)
|
||||
|
||||
Parameters:
|
||||
- path: The API path (e.g., "/write", "/api/v3/configure/database")
|
||||
- path: The API path (e.g., "/write", "/api/v3/engine/{request_path}")
|
||||
|
||||
Returns: URL-safe path slug (e.g., "v1/write", "v3/configure/database")
|
||||
Returns: URL-safe path slug (e.g., "v1/write", "v3/engine/request_path")
|
||||
*/}}
|
||||
{{ $path := . | strings.TrimPrefix "/api" }}
|
||||
{{ if not (findRE `^/v\d+/` $path) }}
|
||||
{{ $path = printf "/v1%s" $path }}
|
||||
{{ end }}
|
||||
{{ $path = $path | strings.TrimPrefix "/" }}
|
||||
{{/* Remove curly braces from path parameters */}}
|
||||
{{ $path = replaceRE `[{}]` "" $path }}
|
||||
{{ return $path }}
|
||||
|
|
|
|||
|
|
@ -180,10 +180,13 @@
|
|||
{{ 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 }}">
|
||||
{{/* Build URL for all-endpoints page */}}
|
||||
{{ $allEndpointsUrl := printf "/%s/%s/api/all-endpoints/" $product $version | relURL }}
|
||||
{{ $allEndpointsActive := eq $currentPage.RelPermalink (printf "/%s/%s/api/all-endpoints/" $product $version) }}
|
||||
<li class="nav-item{{ if $allEndpointsActive }} active{{ end }}">
|
||||
<a href="#" class="children-toggle{{ if or $anyOpActive $allEndpointsActive }} open{{ end }}"></a>
|
||||
<a href="{{ $allEndpointsUrl }}">All endpoints</a>
|
||||
<ul class="children{{ if or $anyOpActive $allEndpointsActive }} open{{ end }}">
|
||||
{{ range $sortedOps }}
|
||||
{{ $op := .op }}
|
||||
{{ $apiPath := $op.path }}
|
||||
|
|
|
|||
Loading…
Reference in New Issue