fix(api-docs): fix Hugo spec path, sidebar data, and test selectors
- Move Hugo spec (relative links) to _build/ instead of static/ with -hugo- suffix, preserving original basenames for tag spec filenames - Add articleDataKey, articleSection, and specDownloadPath to generated section and tag page frontmatter for sidebar nav and download button - Fix sidebar link test to use #nav-tree instead of .sidebar (avoids matching the hamburger toggle link)api-docs-uplift
parent
1c9d1a839a
commit
11e4913a58
|
|
@ -380,6 +380,16 @@ function generateTagPagesFromArticleData(options) {
|
|||
if (!fs.existsSync(apiParentDir)) {
|
||||
fs.mkdirSync(apiParentDir, { recursive: true });
|
||||
}
|
||||
// Derive articleDataKey from staticDirName or articlesPath
|
||||
const articleDataKey = options.staticDirName || path.basename(articlesPath);
|
||||
// Derive articleSection from contentPath — the section is the last segment of the API URL
|
||||
// e.g., "content/influxdb3/core" → generates pages in "api/", so section = "api"
|
||||
// For management APIs: generates pages in "management-api/", so section = "management-api"
|
||||
const articleSection = apiParentDir.includes('management-api')
|
||||
? 'management-api'
|
||||
: 'api';
|
||||
// Derive specDownloadPath: /openapi/{staticDirName}.yml
|
||||
const specDownloadPath = `/openapi/${articleDataKey}.yml`;
|
||||
if (!fs.existsSync(parentIndexFile)) {
|
||||
// Build description - use product description or generate from product name
|
||||
const apiDescription = productDescription ||
|
||||
|
|
@ -389,6 +399,9 @@ function generateTagPagesFromArticleData(options) {
|
|||
description: apiDescription,
|
||||
weight: 104,
|
||||
type: 'api',
|
||||
articleDataKey,
|
||||
articleSection,
|
||||
specDownloadPath,
|
||||
};
|
||||
// Add menu entry for parent page (unless skipParentMenu is true)
|
||||
if (menuKey && !skipParentMenu) {
|
||||
|
|
@ -476,7 +489,11 @@ All {{% product-name %}} API endpoints, sorted by path.
|
|||
type: 'api',
|
||||
layout: isConceptual ? 'single' : 'list',
|
||||
staticFilePath: article.fields.staticFilePath,
|
||||
specDownloadPath,
|
||||
weight,
|
||||
// Sidebar data lookup fields
|
||||
articleDataKey,
|
||||
articleSection,
|
||||
// Tag-based fields
|
||||
tag: article.fields.tag,
|
||||
isConceptual,
|
||||
|
|
@ -842,15 +859,11 @@ function absolutifyLinks(spec, baseUrl) {
|
|||
if (key && MARKDOWN_FIELDS.has(key)) {
|
||||
return value.replace(INTERNAL_LINK_RE, `$1${baseUrl}$2`);
|
||||
}
|
||||
if (key === 'href' &&
|
||||
parent?.title &&
|
||||
value.startsWith('/')) {
|
||||
if (key === 'href' && parent?.title && value.startsWith('/')) {
|
||||
return `${baseUrl}${value}`;
|
||||
}
|
||||
// externalDocs.url — standard OpenAPI field
|
||||
if (key === 'url' &&
|
||||
parent?.description &&
|
||||
value.startsWith('/')) {
|
||||
if (key === 'url' && parent?.description && value.startsWith('/')) {
|
||||
return `${baseUrl}${value}`;
|
||||
}
|
||||
return value;
|
||||
|
|
@ -988,8 +1001,11 @@ function processSpecFile(specConfig, staticPath, staticDirName, productKey) {
|
|||
linkErrors.forEach((err) => console.warn(` ${err}`));
|
||||
}
|
||||
}
|
||||
// Write Hugo spec (relative links) for article generation and templates
|
||||
const hugoSpecPath = staticSpecPath.replace(/\.yml$/, '-hugo.yml');
|
||||
// Write Hugo spec (relative links) to _build/ for article generation.
|
||||
// Tag specs and frontmatter staticFilePath derive names from this path,
|
||||
// so it must match the final staticSpecPath basename.
|
||||
const hugoSpecPath = path.join(API_DOCS_ROOT, '_build', path.relative(path.join(DOCS_ROOT, 'static'), staticSpecPath));
|
||||
fs.mkdirSync(path.dirname(hugoSpecPath), { recursive: true });
|
||||
fs.writeFileSync(hugoSpecPath, yaml.dump(transformedSpec));
|
||||
// Absolutify links for downloadable specs (relative paths → full URLs)
|
||||
const downloadSpec = absolutifyLinks(transformedSpec, DOCS_BASE_URL);
|
||||
|
|
@ -1111,6 +1127,7 @@ function processProduct(productKey, config) {
|
|||
menuParent: 'InfluxDB HTTP API',
|
||||
skipParentMenu: config.skipParentMenu,
|
||||
pathSpecFiles: allPathSpecFiles,
|
||||
staticDirName,
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -492,6 +492,8 @@ interface GenerateTagPagesOptions {
|
|||
skipParentMenu?: boolean;
|
||||
/** Map of API path to path-specific spec file (for single-operation rendering) */
|
||||
pathSpecFiles?: Map<string, string>;
|
||||
/** Static directory name for download path derivation (e.g., 'influxdb3-core') */
|
||||
staticDirName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -563,6 +565,19 @@ function generateTagPagesFromArticleData(
|
|||
fs.mkdirSync(apiParentDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Derive articleDataKey from staticDirName or articlesPath
|
||||
const articleDataKey = options.staticDirName || path.basename(articlesPath);
|
||||
|
||||
// Derive articleSection from contentPath — the section is the last segment of the API URL
|
||||
// e.g., "content/influxdb3/core" → generates pages in "api/", so section = "api"
|
||||
// For management APIs: generates pages in "management-api/", so section = "management-api"
|
||||
const articleSection = apiParentDir.includes('management-api')
|
||||
? 'management-api'
|
||||
: 'api';
|
||||
|
||||
// Derive specDownloadPath: /openapi/{staticDirName}.yml
|
||||
const specDownloadPath = `/openapi/${articleDataKey}.yml`;
|
||||
|
||||
if (!fs.existsSync(parentIndexFile)) {
|
||||
// Build description - use product description or generate from product name
|
||||
const apiDescription =
|
||||
|
|
@ -574,6 +589,9 @@ function generateTagPagesFromArticleData(
|
|||
description: apiDescription,
|
||||
weight: 104,
|
||||
type: 'api',
|
||||
articleDataKey,
|
||||
articleSection,
|
||||
specDownloadPath,
|
||||
};
|
||||
|
||||
// Add menu entry for parent page (unless skipParentMenu is true)
|
||||
|
|
@ -680,7 +698,11 @@ All {{% product-name %}} API endpoints, sorted by path.
|
|||
type: 'api',
|
||||
layout: isConceptual ? 'single' : 'list',
|
||||
staticFilePath: article.fields.staticFilePath,
|
||||
specDownloadPath,
|
||||
weight,
|
||||
// Sidebar data lookup fields
|
||||
articleDataKey,
|
||||
articleSection,
|
||||
// Tag-based fields
|
||||
tag: article.fields.tag,
|
||||
isConceptual,
|
||||
|
|
@ -1162,19 +1184,11 @@ function absolutifyLinks(
|
|||
if (key && MARKDOWN_FIELDS.has(key)) {
|
||||
return value.replace(INTERNAL_LINK_RE, `$1${baseUrl}$2`);
|
||||
}
|
||||
if (
|
||||
key === 'href' &&
|
||||
parent?.title &&
|
||||
value.startsWith('/')
|
||||
) {
|
||||
if (key === 'href' && parent?.title && value.startsWith('/')) {
|
||||
return `${baseUrl}${value}`;
|
||||
}
|
||||
// externalDocs.url — standard OpenAPI field
|
||||
if (
|
||||
key === 'url' &&
|
||||
parent?.description &&
|
||||
value.startsWith('/')
|
||||
) {
|
||||
if (key === 'url' && parent?.description && value.startsWith('/')) {
|
||||
return `${baseUrl}${value}`;
|
||||
}
|
||||
return value;
|
||||
|
|
@ -1357,8 +1371,15 @@ function processSpecFile(
|
|||
}
|
||||
}
|
||||
|
||||
// Write Hugo spec (relative links) for article generation and templates
|
||||
const hugoSpecPath = staticSpecPath.replace(/\.yml$/, '-hugo.yml');
|
||||
// Write Hugo spec (relative links) to _build/ for article generation.
|
||||
// Tag specs and frontmatter staticFilePath derive names from this path,
|
||||
// so it must match the final staticSpecPath basename.
|
||||
const hugoSpecPath = path.join(
|
||||
API_DOCS_ROOT,
|
||||
'_build',
|
||||
path.relative(path.join(DOCS_ROOT, 'static'), staticSpecPath)
|
||||
);
|
||||
fs.mkdirSync(path.dirname(hugoSpecPath), { recursive: true });
|
||||
fs.writeFileSync(hugoSpecPath, yaml.dump(transformedSpec));
|
||||
|
||||
// Absolutify links for downloadable specs (relative paths → full URLs)
|
||||
|
|
@ -1368,10 +1389,7 @@ function processSpecFile(
|
|||
fs.writeFileSync(staticSpecPath, yaml.dump(downloadSpec));
|
||||
console.log(`✓ Wrote downloadable spec to ${staticSpecPath}`);
|
||||
|
||||
fs.writeFileSync(
|
||||
staticJsonSpecPath,
|
||||
JSON.stringify(downloadSpec, null, 2)
|
||||
);
|
||||
fs.writeFileSync(staticJsonSpecPath, JSON.stringify(downloadSpec, null, 2));
|
||||
console.log(`✓ Generated JSON spec at ${staticJsonSpecPath}`);
|
||||
|
||||
return { staticSpecPath, staticJsonSpecPath, hugoSpecPath, articlesPath };
|
||||
|
|
@ -1541,6 +1559,7 @@ function processProduct(productKey: string, config: ProductConfig): void {
|
|||
menuParent: 'InfluxDB HTTP API',
|
||||
skipParentMenu: config.skipParentMenu,
|
||||
pathSpecFiles: allPathSpecFiles,
|
||||
staticDirName,
|
||||
});
|
||||
} else {
|
||||
generatePagesFromArticleData({
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ describe('API reference content', () => {
|
|||
);
|
||||
});
|
||||
it('has a sidebar link to the product home', function () {
|
||||
// The sidebar contains a link to the product root page
|
||||
cy.get('.sidebar a')
|
||||
// The nav tree contains a link to the product root page
|
||||
cy.get('#nav-tree a')
|
||||
.first()
|
||||
.should('have.attr', 'href')
|
||||
.and('match', /^\/[^/]+\/[^/]+\/$/);
|
||||
|
|
|
|||
Loading…
Reference in New Issue