/ scripts / validation / check-links.sh
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