Files
doos/scripts/check-docs.sh
T

36 lines
1.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Checks the documentation set: every markdown file links to every other one, and every relative link resolves.
# Usage: scripts/check-docs.sh (exit 1 on any problem, lists them all)
set -u
cd "$(dirname "$0")/.."
DOCS=(README.md SPEC.md COMPARISON.md AGENTS.md CHANGELOG.md docs/ARCHITECTURE.md docs/RESEARCH.md)
bad=0
fail() { echo "docs: $*"; bad=$((bad+1)); }
# no markdown file may exist outside the checked set (so a new doc cannot dodge the rule)
while IFS= read -r f; do
f=${f#./}
printf '%s\n' "${DOCS[@]}" | grep -qxF "$f" || fail "$f is not in the DOCS list of scripts/check-docs.sh"
done < <(find . -name '*.md' -not -path './build/*' -not -path './.git/*' -not -path './prompt.md') # prompt.md: the original task statement, not documentation
for f in "${DOCS[@]}"; do
[ -f "$f" ] || { fail "$f is missing"; continue; }
dir=$(dirname "$f")
# every other document must be linked
for g in "${DOCS[@]}"; do
[ "$f" = "$g" ] && continue
rel=$(realpath --relative-to="$dir" "$g")
grep -qE "\]\(${rel//./\\.}(#[^)]*)?\)" "$f" || fail "$f does not link to $g (expected ]($rel))"
done
# every relative link must point at something that exists
while IFS= read -r target; do
case "$target" in http://*|https://*|mailto:*|\#*) continue ;; esac
path=${target%%#*}
[ -z "$path" ] && continue
[ -e "$dir/$path" ] || fail "$f links to missing $target"
done < <(grep -oE '\]\([^)]+\)' "$f" | sed -E 's/^\]\(//; s/\)$//')
done
[ "$bad" -eq 0 ] && echo "docs: ${#DOCS[@]} documents, all cross-linked, all links resolve" || { echo "docs: $bad problem(s)"; exit 1; }