40 lines
2.0 KiB
Bash
Executable File
40 lines
2.0 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 docs/CI.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' -not -path './audit/*' -not -path './review.md' -not -path './review2.md' -not -path './valgrind/*')
|
|
# prompt.md: the original task statement, not documentation.
|
|
# audit/*, valgrind/*: separate, self-contained doc sets (one README per CVE check, one for the
|
|
# valgrind setup); linked from the main docs but not forced into their full cross-link mesh.
|
|
# review.md, review2.md: standalone one-off reviews, not part of the maintained doc set.
|
|
|
|
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; }
|