11#! /bin/bash
2+ set -e
23
3- # 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
5-
6- set -ex
7-
8- # Colors for output
9- RED=' \033[0;31m'
10- GREEN=' \033[0;32m'
11- YELLOW=' \033[1;33m'
12- BLUE=' \033[0;34m'
13- NC=' \033[0m' # No Color
14-
15- # Directories
16- SPECS_DIR=" specs"
174OUTPUT_DIR=" docs/api-docs"
185INDEX_FILE=" $OUTPUT_DIR /index.html"
19- ERROR_LOG=" $OUTPUT_DIR /errors.log"
206
21- echo -e " ${BLUE} π Starting API documentation generation...${NC} "
22-
23- # Create output directory
7+ # 1. Clean output dir
8+ rm -rf " $OUTPUT_DIR "
249mkdir -p " $OUTPUT_DIR "
2510
26- # Check if redocly is installed
27- if ! command -v redocly & > /dev/null; then
28- echo -e " ${RED} β Redocly is not installed. Please install it first:${NC} "
29- echo " npm install -g @redocly/cli"
30- exit 1
31- fi
32-
33- echo -e " ${GREEN} β
Redocly found: $( redocly --version) ${NC} "
34-
35- # Counter for successful conversions
36- success_count=0
37- error_count=0
38-
39- # Clear error log
40- > " $ERROR_LOG "
41-
42- # Function to convert a spec file to HTML
43- convert_spec_to_html () {
44- local spec_file=" $1 "
45- local relative_path=" ${spec_file# $SPECS_DIR / } "
46- local filename=$( basename " $spec_file " )
47- local name_without_ext=" ${filename% .* } "
48-
49- # Create output filename
50- local output_file=" $OUTPUT_DIR /${relative_path% .* } .html"
51-
52- # Create output directory if it doesn't exist
53- local output_dir
54- output_dir=$( dirname " $output_file " )
55- mkdir -p " $output_dir "
56-
57- echo -e " ${BLUE} π Converting: $spec_file ${NC} "
58-
59- # Capture both stdout and stderr to check for errors
60- if redocly build-docs " $spec_file " -o " $output_file " 2>&1 ; then
61- echo -e " ${GREEN} β
Success: $output_file ${NC} "
62- (( success_count++ ))
63- return 0
64- else
65- echo -e " ${RED} β Failed: $spec_file ${NC} "
66- echo " Failed: $spec_file " >> " $ERROR_LOG "
67- (( error_count++ ))
68- return 1
69- fi
70- }
71-
72- # Find all spec files and convert them
73- echo -e " ${YELLOW} π Finding all spec files...${NC} "
74- spec_files=$( find " $SPECS_DIR " -name " *.yaml" -o -name " *.yml" | sort)
75-
76- echo -e " ${BLUE} π Found $( echo " $spec_files " | wc -l | tr -d ' ' ) spec files${NC} "
77-
78- # Convert each spec file
79- for spec_file in $spec_files ; do
80- convert_spec_to_html " $spec_file " || true
81- done
82-
83- # Generate index page
84- echo -e " ${YELLOW} π Generating index page...${NC} "
85-
11+ # 2. Prepare index.html
8612cat > " $INDEX_FILE " << 'EOF '
8713<!DOCTYPE html>
8814<html lang="en">
8915<head>
9016 <meta charset="UTF-8">
91- <meta name="viewport" content="width=device-width, initial-scale=1.0">
92- <title>Devtron API Documentation</title>
17+ <title>API Documentation</title>
9318 <style>
94- /* styles omitted for brevity β keep your existing CSS here */
19+ body { font-family: Arial, sans-serif; margin: 20px; }
20+ h1 { border-bottom: 2px solid #ccc; padding-bottom: 10px; }
21+ .category { margin-bottom: 20px; }
22+ .category h3 { margin-top: 0; color: #2c3e50; }
23+ .api-list { list-style: none; padding-left: 0; }
24+ .api-list li { margin: 5px 0; }
25+ .timestamp { margin-top: 40px; font-size: 0.9em; color: #888; }
9526 </style>
9627</head>
9728<body>
98- <div class="container">
99- <h1>π Devtron API Documentation</h1>
100- <div class="description">
101- Comprehensive API documentation for Devtron - Kubernetes-native software delivery platform
102- </div>
103-
104- <div class="categories" id="categories">
105- <!-- Categories will be populated by JavaScript -->
106- </div>
107-
108- <div class="footer">
109- <p><a href="/https://devtron.ai/" target="_blank">Devtron</a></p>
110- <p class="timestamp">Last updated: <span id="timestamp"></span></p>
111- </div>
112- </div>
113-
29+ <h1>API Documentation</h1>
30+ <div id="categories"></div>
31+ <div class="timestamp">Last updated: <span id="timestamp"></span></div>
11432 <script>
11533 const apiData = {
11634EOF
11735
118- # Generate the JavaScript data for the index page
119- echo " Generating JavaScript data for index page... "
120-
121- total_apis=0
122- categories_count=0
36+ # 3. Loop over all specs
37+ find specs -type f -name " *.yaml " | while read -r spec ; do
38+ title= $( grep -m1 " ^title: " " $spec " | sed ' s/^[[:space:]]*title:[[:space:]]*// ' | tr -d ' " ' )
39+ filename= $( basename " $spec " .yaml ) .html
40+ category= $( basename " $( dirname " $spec " ) " )
12341
124- for spec_file in $spec_files ; do
125- relative_path=" ${spec_file# $SPECS_DIR / } "
126- filename=$( basename " $spec_file " )
127- name_without_ext=" ${filename% .* } "
128- category=$( dirname " $relative_path " )
42+ # Run redocly to generate HTML
43+ npx @redocly/cli build-docs " $spec " -o " $OUTPUT_DIR /$filename "
12944
130- if [ " $category " = " ." ]; then
131- category=" root"
132- fi
133-
134- display_category=$( echo " $category " | sed ' s/-/ /g' | sed ' s/_/ /g' | sed ' s/\b\w/\U&/g' )
135-
136- title=$( grep -m 1 ' ^[[:space:]]*title:' " $spec_file " \
137- | sed ' s/^[[:space:]]*title:[[:space:]]*//' \
138- | tr -d ' "' \
139- || echo " $name_without_ext " )
140-
141- output_file=" ${relative_path% .* } .html"
142-
143- if [ -f " $OUTPUT_DIR /$output_file " ]; then
144- cat >> " $INDEX_FILE " << EOF
145- "${category} _${name_without_ext} ": {
146- "category": "${display_category} ",
45+ # Add entry to index.html
46+ cat >> " $INDEX_FILE " << EOF
47+ "${filename} ": {
14748 "title": "${title} ",
148- "filename ": "${output_file } ",
149- "original_file ": "${relative_path } "
49+ "category ": "${category } ",
50+ "filename ": "${filename } "
15051 },
15152EOF
152- fi
15353done
15454
155- # Log what find returns for index.html
156- echo -e " ${YELLOW} π Searching for index.html in $OUTPUT_DIR ...${NC} "
157- find . -name " index.html" -path " */docs/api-docs/*"
158-
159- # Remove trailing comma only if file exists
160- if [[ -f " $INDEX_FILE " ]]; then
161- sed -i ' $ s/,$//' " $INDEX_FILE "
162- else
163- echo -e " ${RED} β οΈ $INDEX_FILE not found, skipping trailing comma fix${NC} "
164- fi
55+ # 4. Remove last comma in apiData
56+ sed -i ' $ s/,$//' " $INDEX_FILE "
16557
58+ # 5. Append JS for rendering categories & APIs
16659cat >> " $INDEX_FILE " << 'EOF '
16760 };
16861
@@ -182,21 +75,31 @@ cat >> "$INDEX_FILE" << 'EOF'
18275 categoryDiv.className = 'category';
18376
18477 const categoryTitle = document.createElement('h3');
185- categoryTitle.textContent = category;
78+ categoryTitle.textContent = category
79+ .replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase -> space
80+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') // ABCThing -> ABC Thing
81+ .split(/[\s-_]+/) // split on space, dash, underscore
82+ .map(word => {
83+ if (word === word.toUpperCase()) return word; // keep acronyms uppercase
84+ return word.charAt(0).toUpperCase() + word.slice(1);
85+ })
86+ .join(' ');
87+
18688 categoryDiv.appendChild(categoryTitle);
18789
18890 const apiList = document.createElement('ul');
18991 apiList.className = 'api-list';
19092
191- categories[category].sort((a, b) => a.title.localeCompare(b.title)).forEach(api => {
192- const listItem = document.createElement('li');
193- const link = document.createElement('a');
194- link.href = api.filename;
195- link.textContent = api.title;
196- link.target = '_blank';
197- listItem.appendChild(link);
198- apiList.appendChild(listItem);
199- });
93+ categories[category]
94+ .sort((a, b) => a.title.localeCompare(b.title))
95+ .forEach(api => {
96+ const listItem = document.createElement('li');
97+ const link = document.createElement('a');
98+ link.href = api.filename; // removed target="_blank"
99+ link.textContent = api.title;
100+ listItem.appendChild(link);
101+ apiList.appendChild(listItem);
102+ });
200103
201104 categoryDiv.appendChild(apiList);
202105 categoriesContainer.appendChild(categoryDiv);
@@ -211,24 +114,4 @@ cat >> "$INDEX_FILE" << 'EOF'
211114</html>
212115EOF
213116
214- echo -e " ${GREEN} β
Index page generated: $INDEX_FILE ${NC} "
215-
216- # Final summary
217- echo -e " ${BLUE} π Final Summary:${NC} "
218- echo -e " ${GREEN} β
Successfully converted: $success_count files${NC} "
219- if [ $error_count -gt 0 ]; then
220- echo -e " ${RED} β Failed to convert: $error_count files${NC} "
221- echo -e " ${YELLOW} π Check $ERROR_LOG for details on failed conversions${NC} "
222- fi
223- echo -e " ${BLUE} π Output directory: $OUTPUT_DIR ${NC} "
224- echo -e " ${BLUE} π Main index: $INDEX_FILE ${NC} "
225-
226- # Create README
227- cat > " $OUTPUT_DIR /README.md" << 'EOF '
228- # Devtron API Documentation
229- ... (keep your existing README text here)
230- EOF
231-
232- echo -e " ${GREEN} β
README created: $OUTPUT_DIR /README.md${NC} "
233- echo -e " ${GREEN} π API documentation generation complete!${NC} "
234- echo -e " ${BLUE} π‘ Open $INDEX_FILE in your browser to view the documentation${NC} "
117+ echo " β
API documentation generated at $OUTPUT_DIR "
0 commit comments