| 
									
										
										
										
											2025-09-13 19:14:45 +00:00
										 |  |  | #!/usr/bin/env node | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Post-process HTML files generated by MkDocs to remove .md extensions from links | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import * as fs from 'fs'; | 
					
						
							|  |  |  | import * as path from 'path'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Process HTML content to remove .md extensions from links | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function fixHtmlLinks(content: string): string { | 
					
						
							|  |  |  |     // Replace .md extensions in href attributes
 | 
					
						
							| 
									
										
										
										
											2025-09-13 19:42:32 +00:00
										 |  |  |     // Handle both quoted and unquoted href attributes
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // First, handle quoted hrefs: href="...something.md" or href="...something.md#anchor"
 | 
					
						
							|  |  |  |     content = content.replace(/href="([^"]*?)\.md(#[^"]*)?"/g, 'href="$1$2"'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Then, handle unquoted hrefs: href=...something.md or href=...something.md#anchor
 | 
					
						
							|  |  |  |     // This matches href= followed by a non-whitespace URL ending in .md
 | 
					
						
							|  |  |  |     content = content.replace(/href=([^\s>]*?)\.md(#[^\s>]*)?(?=[\s>])/g, 'href=$1$2'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return content; | 
					
						
							| 
									
										
										
										
											2025-09-13 19:14:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Recursively process all HTML files in a directory | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function processDirectory(dir: string): number { | 
					
						
							|  |  |  |     let filesProcessed = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const entries = fs.readdirSync(dir, { withFileTypes: true }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const entry of entries) { | 
					
						
							|  |  |  |         const fullPath = path.join(dir, entry.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (entry.isDirectory()) { | 
					
						
							|  |  |  |             // Recursively process subdirectories
 | 
					
						
							|  |  |  |             filesProcessed += processDirectory(fullPath); | 
					
						
							|  |  |  |         } else if (entry.isFile() && entry.name.endsWith('.html')) { | 
					
						
							|  |  |  |             // Process HTML files
 | 
					
						
							|  |  |  |             const content = fs.readFileSync(fullPath, 'utf-8'); | 
					
						
							|  |  |  |             const fixedContent = fixHtmlLinks(content); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (content !== fixedContent) { | 
					
						
							|  |  |  |                 fs.writeFileSync(fullPath, fixedContent, 'utf-8'); | 
					
						
							|  |  |  |                 console.log(`Fixed: ${path.relative(process.cwd(), fullPath)}`); | 
					
						
							|  |  |  |                 filesProcessed++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return filesProcessed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function main(): number { | 
					
						
							|  |  |  |     const args = process.argv.slice(2); | 
					
						
							|  |  |  |     const siteDir = args[0] || 'site'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const fullPath = path.resolve(siteDir); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!fs.existsSync(fullPath)) { | 
					
						
							|  |  |  |         console.error(`Error: Directory '${fullPath}' does not exist`); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     console.log(`Processing HTML files in: ${fullPath}`); | 
					
						
							|  |  |  |     console.log('-'.repeat(50)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const filesProcessed = processDirectory(fullPath); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     console.log('-'.repeat(50)); | 
					
						
							|  |  |  |     console.log(`Processed ${filesProcessed} HTML files`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Run the main function
 | 
					
						
							|  |  |  | process.exit(main()); |