check-links.sh
1 #!/bin/bash 2 3 # Link Checker Script for Planar Documentation 4 # Validates all internal and external links in documentation (can return false positives) 5 6 set -e 7 8 DOCS_DIR="docs/src" 9 REPORT_FILE="docs/maintenance/link-check-report.md" 10 TEMP_FILE="/tmp/link-check.tmp" 11 12 echo "# Link Check Report - $(date)" > "$REPORT_FILE" 13 echo "" >> "$REPORT_FILE" 14 15 # Function to check internal links 16 check_internal_links() { 17 echo "## Internal Links" >> "$REPORT_FILE" 18 echo "" >> "$REPORT_FILE" 19 20 find "$DOCS_DIR" -name "*.md" -exec grep -l "\[.*\](.*\.md)" {} \; | while read -r file; do 21 echo "Checking internal links in: $file" 22 23 # Extract markdown links 24 grep -o '\[.*\](.*\.md[^)]*)' "$file" | while read -r link; do 25 # Extract the file path from the link 26 link_path=$(echo "$link" | sed 's/.*](\([^)]*\)).*/\1/' | sed 's/#.*//') 27 28 # Convert relative path to absolute 29 if [[ "$link_path" == /* ]]; then 30 full_path="$DOCS_DIR$link_path" 31 else 32 dir=$(dirname "$file") 33 full_path="$dir/$link_path" 34 fi 35 36 # Check if file exists 37 if [[ ! -f "$full_path" ]]; then 38 echo "- ❌ **$file**: Broken link to \`$link_path\`" >> "$REPORT_FILE" 39 fi 40 done 41 done 42 43 echo "" >> "$REPORT_FILE" 44 } 45 46 # Function to check external links 47 check_external_links() { 48 echo "## External Links" >> "$REPORT_FILE" 49 echo "" >> "$REPORT_FILE" 50 51 find "$DOCS_DIR" -name "*.md" -exec grep -l "http" {} \; | while read -r file; do 52 echo "Checking external links in: $file" 53 54 # Extract HTTP/HTTPS links 55 grep -o 'https\?://[^)]*' "$file" | sort -u | while read -r url; do 56 # Clean up URL (remove trailing punctuation) 57 clean_url=$(echo "$url" | sed 's/[.,;)]$//') 58 59 # Check if URL is accessible 60 if ! curl -s --head --fail "$clean_url" > /dev/null 2>&1; then 61 echo "- ❌ **$file**: Broken external link to \`$clean_url\`" >> "$REPORT_FILE" 62 fi 63 done 64 done 65 66 echo "" >> "$REPORT_FILE" 67 } 68 69 # Function to check anchor links 70 check_anchor_links() { 71 echo "## Anchor Links" >> "$REPORT_FILE" 72 echo "" >> "$REPORT_FILE" 73 74 find "$DOCS_DIR" -name "*.md" -exec grep -l "#.*)" {} \; | while read -r file; do 75 echo "Checking anchor links in: $file" 76 77 # Extract anchor links within the same file 78 grep -o '\[.*\](#[^)]*' "$file" | while read -r link; do 79 anchor=$(echo "$link" | sed 's/.*](#\([^)]*\)).*/\1/') 80 81 # Convert anchor to expected heading format 82 expected_heading=$(echo "$anchor" | sed 's/-/ /g' | tr '[:upper:]' '[:lower:]') 83 84 # Check if heading exists in the file 85 if ! grep -qi "^#.*$expected_heading" "$file"; then 86 echo "- ❌ **$file**: Broken anchor link to \`#$anchor\`" >> "$REPORT_FILE" 87 fi 88 done 89 done 90 91 echo "" >> "$REPORT_FILE" 92 } 93 94 # Main execution 95 echo "Starting link validation..." 96 97 # Create maintenance directory if it doesn't exist 98 mkdir -p "$(dirname "$REPORT_FILE")" 99 100 # Run checks 101 check_internal_links 102 check_external_links 103 check_anchor_links 104 105 # Summary 106 echo "## Summary" >> "$REPORT_FILE" 107 echo "" >> "$REPORT_FILE" 108 109 broken_count=$(grep -c "❌" "$REPORT_FILE" || echo "0") 110 if [[ "$broken_count" -eq 0 ]]; then 111 echo "✅ All links are working correctly!" >> "$REPORT_FILE" 112 echo "Link check completed successfully - no broken links found." 113 exit 0 114 else 115 echo "❌ Found $broken_count broken links that need attention." >> "$REPORT_FILE" 116 echo "Link check completed - found $broken_count broken links. See $REPORT_FILE for details." 117 exit 1 118 fi