#!/usr/bin/env bash # Check internal doc links in docs/ (relative paths). Report broken file links. # Usage: ./scripts/check-doc-links.sh # Run from repo root. set -e REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" DOCS="$REPO_ROOT/docs" FAIL=0 check_file() { local f="$1" local from_dir="${f#$REPO_ROOT/}" from_dir="$(dirname "$from_dir")" while IFS= read -r url; do [[ -z "$url" ]] && continue path_only="${url%%#*}" [[ -z "$path_only" ]] && continue [[ "$path_only" == https://* ]] && continue [[ "$path_only" == http://* ]] && continue [[ "$path_only" == mailto:* ]] && continue # Resolve relative to source file dir if [[ "$path_only" == /* ]]; then resolved="${path_only#/}" elif [[ -z "$from_dir" || "$from_dir" == "." ]]; then resolved="$path_only" else resolved="$from_dir/$path_only" resolved="$(echo "$resolved" | sed 's|/\./|/|g')" while [[ "$resolved" == *"/../"* ]] || [[ "$resolved" == *"/.." ]]; do resolved="$(echo "$resolved" | sed 's|/[^/]*/\.\./|/|;s|/[^/]*/\.\.$||')" done fi target="$REPO_ROOT/$resolved" if [[ -d "$target" ]]; then continue; fi if [[ ! -f "$target" ]]; then echo "BROKEN: $f -> $resolved (target missing)" FAIL=1 fi done < <(grep -ohE '\]\([^)]+\)' "$f" 2>/dev/null | sed 's/^](//;s/)$//') } echo "=== Checking internal doc links under docs/ ===" while IFS= read -r -d '' f; do check_file "$f" done < <(find "$DOCS" -name "*.md" -print0 2>/dev/null) if [[ "$FAIL" -eq 0 ]]; then echo "No broken internal links found." fi exit "$FAIL"