Skip to content

Commit 40eabaf

Browse files
authored
add support for aep-openapi-linter documentation (#87)
1 parent 4bcf3cf commit 40eabaf

File tree

2 files changed

+166
-7
lines changed

2 files changed

+166
-7
lines changed

scripts/generate.ts

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import * as fs from "fs";
22
import * as path from "path";
33

44
import loadConfigFiles from "./src/config";
5-
import { buildSidebar, buildLinterSidebar, addToSidebar } from "./src/sidebar";
5+
import {
6+
buildSidebar,
7+
buildLinterSidebar,
8+
buildOpenAPILinterSidebar,
9+
addToSidebar,
10+
} from "./src/sidebar";
611
import {
712
type AEP,
813
type ConsolidatedLinterRule,
@@ -15,6 +20,7 @@ import { load, dump } from "js-yaml";
1520

1621
const AEP_LOC = process.env.AEP_LOCATION || "";
1722
const AEP_LINTER_LOC = process.env.AEP_LINTER_LOC || "";
23+
const AEP_OPENAPI_LINTER_LOC = process.env.AEP_OPENAPI_LINTER_LOC || "";
1824
const AEP_COMPONENTS = process.env.AEP_COMPONENTS_LOC || "";
1925

2026
// Logging functions
@@ -47,6 +53,19 @@ function logFolderDetection() {
4753
);
4854
}
4955

56+
if (AEP_OPENAPI_LINTER_LOC) {
57+
console.log(`✓ OpenAPI Linter folder found: ${AEP_OPENAPI_LINTER_LOC}`);
58+
if (fs.existsSync(AEP_OPENAPI_LINTER_LOC)) {
59+
console.log(` - Path exists and is accessible`);
60+
} else {
61+
console.log(` - ⚠️ Path does not exist`);
62+
}
63+
} else {
64+
console.log(
65+
`✗ OpenAPI Linter folder not configured (AEP_OPENAPI_LINTER_LOC environment variable)`,
66+
);
67+
}
68+
5069
if (AEP_COMPONENTS) {
5170
console.log(`✓ Components folder found: ${AEP_COMPONENTS}`);
5271
if (fs.existsSync(AEP_COMPONENTS)) {
@@ -277,6 +296,64 @@ async function assembleLinterRules(): Promise<LinterRule[]> {
277296
return linterRules;
278297
}
279298

299+
/**
300+
* Assembles OpenAPI linter rules from the aep-openapi-linter repository.
301+
*
302+
* Structure difference from api-linter:
303+
* - api-linter: docs/rules/XXXX/*.md (multiple files per AEP)
304+
* - openapi-linter: docs/XXXX.md (one file per AEP)
305+
*
306+
* @returns Promise<LinterRule[]> Array of linter rules, empty if repo not found
307+
*/
308+
async function assembleOpenAPILinterRules(): Promise<LinterRule[]> {
309+
// Defensive check: Verify repository exists
310+
if (!fs.existsSync(AEP_OPENAPI_LINTER_LOC)) {
311+
console.log("ℹ️ OpenAPI linter repository not found, skipping...");
312+
console.log(` Expected location: ${AEP_OPENAPI_LINTER_LOC}`);
313+
return [];
314+
}
315+
316+
const docsPath = path.join(AEP_OPENAPI_LINTER_LOC, "docs");
317+
318+
// Defensive check: Verify docs directory exists
319+
if (!fs.existsSync(docsPath)) {
320+
console.warn("⚠️ OpenAPI linter docs directory not found");
321+
console.warn(` Expected: ${docsPath}`);
322+
return [];
323+
}
324+
325+
let linterRules: LinterRule[] = [];
326+
327+
try {
328+
const files = await fs.promises.readdir(docsPath);
329+
330+
for (const file of files) {
331+
// Process only numbered AEP files (e.g., 0131.md, 0132.md)
332+
// Skip index files like rules.md
333+
if (file.match(/^\d{4}\.md$/)) {
334+
const filePath = path.join(docsPath, file);
335+
const aepNumber = file.split(".")[0]; // Extract "0131" from "0131.md"
336+
337+
try {
338+
const rule = buildLinterRule(filePath, aepNumber);
339+
linterRules.push(rule);
340+
console.log(`✓ Processed OpenAPI linter rule: AEP-${aepNumber}`);
341+
} catch (error) {
342+
console.error(`❌ Failed to process ${file}:`, error);
343+
// Continue processing other files
344+
}
345+
}
346+
}
347+
348+
console.log(`✓ Assembled ${linterRules.length} OpenAPI linter rules`);
349+
} catch (error) {
350+
console.error("❌ Error reading OpenAPI linter docs directory:", error);
351+
return [];
352+
}
353+
354+
return linterRules;
355+
}
356+
280357
function buildLinterRule(rulePath: string, aep: string): LinterRule {
281358
logFileRead(rulePath, "Linter rule");
282359
let contents = fs.readFileSync(rulePath, "utf-8");
@@ -326,11 +403,10 @@ ${rules_contents.join("\n")}
326403
return consolidated_rules;
327404
}
328405

329-
function writeRule(rule: ConsolidatedLinterRule) {
330-
const filePath = path.join(
331-
`src/content/docs/tooling/linter/rules/`,
332-
`${rule.aep}.md`,
333-
);
406+
function writeRule(rule: ConsolidatedLinterRule, outputPath?: string) {
407+
const filePath =
408+
outputPath ||
409+
path.join(`src/content/docs/tooling/linter/rules/`, `${rule.aep}.md`);
334410
writeFile(filePath, rule.contents);
335411
}
336412

@@ -506,6 +582,44 @@ if (AEP_LINTER_LOC != "") {
506582
console.warn("Proto linter repo is not found.");
507583
}
508584

585+
if (AEP_OPENAPI_LINTER_LOC != "") {
586+
console.log("=== Processing OpenAPI Linter Repository ===");
587+
588+
// Process OpenAPI linter rules
589+
const openapiLinterRules = await assembleOpenAPILinterRules();
590+
591+
if (openapiLinterRules.length > 0) {
592+
// Write OpenAPI linter overview page
593+
await writePage(
594+
AEP_OPENAPI_LINTER_LOC,
595+
"README.md",
596+
"src/content/docs/tooling/openapi-linter/index.md",
597+
"OpenAPI Linter",
598+
);
599+
600+
// Consolidate rules (groups by AEP number)
601+
const consolidatedOpenAPIRules = consolidateLinterRule(openapiLinterRules);
602+
603+
// Write rule markdown files
604+
for (const rule of consolidatedOpenAPIRules) {
605+
const outputPath = path.join(
606+
"src/content/docs/tooling/openapi-linter/rules",
607+
`${rule.aep}.md`,
608+
);
609+
writeRule(rule, outputPath);
610+
}
611+
612+
// Update sidebar navigation
613+
sidebar = buildOpenAPILinterSidebar(consolidatedOpenAPIRules, sidebar);
614+
615+
console.log("✅ OpenAPI linter integration complete\n");
616+
} else {
617+
console.log("ℹ️ No OpenAPI linter rules found, skipping integration\n");
618+
}
619+
} else {
620+
console.log("ℹ️ OpenAPI linter repo not configured, skipping...\n");
621+
}
622+
509623
if (AEP_COMPONENTS != "") {
510624
console.log("=== Processing Components Repository ===");
511625
// Read all YAML component files.

scripts/src/sidebar.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ function buildLinterSidebar(
2020
return addToSidebar(sidebar, "Tooling", contents);
2121
}
2222

23+
/**
24+
* Builds sidebar entries for OpenAPI linter rules.
25+
*
26+
* @param rules Consolidated linter rules by AEP number
27+
* @param sidebar Existing sidebar structure
28+
* @returns Updated sidebar with OpenAPI linter entries
29+
*/
30+
function buildOpenAPILinterSidebar(
31+
rules: ConsolidatedLinterRule[],
32+
sidebar: Sidebar[],
33+
): Sidebar[] {
34+
// Guard: Only add if we have rules to display
35+
if (rules.length === 0) {
36+
console.log("ℹ️ No OpenAPI linter rules to add to sidebar");
37+
return sidebar;
38+
}
39+
40+
// Create rule items sorted by AEP number
41+
const ruleItems = rules
42+
.sort((a, b) => a.aep.localeCompare(b.aep))
43+
.map((rule) => `tooling/openapi-linter/rules/${rule.aep}`);
44+
45+
let contents = [
46+
{
47+
label: "OpenAPI Linter",
48+
items: [
49+
"tooling/openapi-linter",
50+
{
51+
label: "Rules",
52+
collapsed: true, // Start collapsed for cleaner UI
53+
items: ruleItems,
54+
},
55+
],
56+
},
57+
];
58+
59+
console.log(`✓ Added ${ruleItems.length} OpenAPI linter rules to sidebar`);
60+
return addToSidebar(sidebar, "Tooling", contents);
61+
}
62+
2363
function buildSidebar(aeps: AEP[], groups: any, sidebar: Sidebar[]): Sidebar[] {
2464
let response = [];
2565
for (var group of groups.categories) {
@@ -52,4 +92,9 @@ function addToSidebar(sidebar: Sidebar[], label: string, items): Sidebar[] {
5292
return sidebar;
5393
}
5494

55-
export { buildSidebar, buildLinterSidebar, addToSidebar };
95+
export {
96+
buildSidebar,
97+
buildLinterSidebar,
98+
buildOpenAPILinterSidebar,
99+
addToSidebar,
100+
};

0 commit comments

Comments
 (0)