11#! /bin/bash
22
33# Script to generate HTML documentation from all API specs using Redocly
4- # This will convert all .yaml and .yml files in the specs directory to HTML
4+ # Preserves folder structure under docs/api-docs and generates index.html with correct links
55
66set -ex
77set -o pipefail
@@ -27,8 +27,8 @@ rm -rf "$OUTPUT_DIR"
2727mkdir -p " $OUTPUT_DIR "
2828
2929# Check if redocly is installed
30- if ! command -v redocly & > /dev/null; then
31- echo -e " ${RED} ❌ Redocly is not installed. Please install it first :${NC} "
30+ if ! command -v redocly & > /dev/null; then
31+ echo -e " ${RED} ❌ Redocly CLI not found. Install it with :${NC} "
3232 echo " npm install -g @redocly/cli"
3333 exit 1
3434fi
@@ -45,8 +45,6 @@ error_count=0
4545convert_spec_to_html () {
4646 local spec_file=" $1 "
4747 local relative_path=" ${spec_file# $SPECS_DIR / } "
48- local filename=$( basename " $spec_file " )
49- local name_without_ext=" ${filename% .* } "
5048 local output_file=" $OUTPUT_DIR /${relative_path% .* } .html"
5149
5250 # Create output directory if it doesn't exist
@@ -86,19 +84,32 @@ cat > "$INDEX_FILE" << 'EOF'
8684<meta name="viewport" content="width=device-width, initial-scale=1.0">
8785<title>Devtron API Documentation</title>
8886<style>
89- body { font-family: Arial, sans-serif; margin: 20px; }
90- h1 { color: #333 ; }
91- h3 { margin-top: 20px; }
87+ body { font-family: Arial, sans-serif; margin: 20px; background: #f8f9fa; color: #333; }
88+ h1 { color: #2c3e50 ; }
89+ h3 { margin-top: 20px; border-bottom: 1px solid #ccc; padding-bottom: 5px; color: #34495e; }
9290ul { list-style: none; padding-left: 0; }
9391li { margin: 5px 0; }
94- a { text-decoration: none; color: #0366d6 ; }
92+ a { text-decoration: none; color: #1a73e8 ; }
9593a:hover { text-decoration: underline; }
94+ .container { max-width: 900px; margin: auto; }
95+ .description { margin-bottom: 20px; font-size: 1rem; color: #555; }
96+ .category { margin-bottom: 20px; padding: 10px; background: #fff; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
97+ .api-list li { padding: 3px 0; }
98+ .footer { margin-top: 40px; font-size: 0.9rem; color: #666; }
99+ .footer a { color: #1a73e8; text-decoration: none; }
100+ .footer a:hover { text-decoration: underline; }
101+ .timestamp { font-style: italic; }
96102</style>
97103</head>
98104<body>
99105<div class="container">
100106<h1>🚀 Devtron API Documentation</h1>
107+ <div class="description">
108+ Comprehensive API documentation for Devtron - Kubernetes-native software delivery platform
109+ </div>
110+
101111<div class="categories" id="categories"></div>
112+
102113<div class="footer">
103114<p><a href="https://devtron.ai/" target="_blank">Devtron</a></p>
104115<p class="timestamp">Last updated: <span id="timestamp"></span></p>
@@ -108,14 +119,14 @@ a:hover { text-decoration: underline; }
108119const apiData = {
109120EOF
110121
111- # Populate apiData
122+ # Populate apiData preserving folder structure
112123for spec_file in " ${spec_files[@]} " ; do
113124 relative_path=" ${spec_file# $SPECS_DIR / } "
114125 html_file=" ${relative_path% .* } .html"
115126 category=$( dirname " $relative_path " )
116- [[ " $category " == " ." ]] && category=" root "
127+ [[ " $category " == " ." ]] && category=" Root "
117128
118- # Capitalise each word and split camelCase
129+ # Capitalize words and split camelCase
119130 display_category=$( echo " $category " | sed ' s/[-_]/ /g' | sed ' s/\([a-z]\)\([A-Z]\)/\1 \2/g' | sed ' s/\b\w/\U&/g' )
120131
121132 # Get title or fallback
@@ -143,6 +154,7 @@ function populatePage() {
143154
144155 Object.keys(categories).sort().forEach(cat => {
145156 const section = document.createElement('div');
157+ section.className = "category";
146158 const h3 = document.createElement('h3');
147159 h3.textContent = cat;
148160 section.appendChild(h3);
@@ -151,7 +163,7 @@ function populatePage() {
151163 categories[cat].sort((a,b)=>a.title.localeCompare(b.title)).forEach(api => {
152164 const li = document.createElement('li');
153165 const a = document.createElement('a');
154- a.href = api.filename;
166+ a.href = api.filename; // links preserve folder structure
155167 a.textContent = api.title;
156168 li.appendChild(a);
157169 ul.appendChild(li);
@@ -174,10 +186,9 @@ echo -e "${GREEN}✅ Index page generated: $INDEX_FILE${NC}"
174186
175187# === FINAL SUMMARY ===
176188echo -e " ${BLUE} 📊 Final Summary:${NC} "
177- echo -e " ${GREEN} ✅ Successfully converted: $success_count files${NC} "
178- if [ $error_count -gt 0 ]; then
179- echo -e " ${RED} ❌ Failed to convert: $error_count files${NC} "
180- echo -e " ${YELLOW} 📝 Check $ERROR_LOG for details${NC} "
189+ echo -e " ${GREEN} ✅ Successfully converted: $success_count specs${NC} "
190+ if (( error_count > 0 )) ; then
191+ echo -e " ${RED} ❌ Failed to convert: $error_count (see $ERROR_LOG )${NC} "
181192fi
182193echo -e " ${BLUE} 📁 Output directory: $OUTPUT_DIR ${NC} "
183194echo -e " ${BLUE} 🌐 Main index: $INDEX_FILE ${NC} "
0 commit comments