diff --git a/.github/scripts/local-link-checker.sh b/.github/scripts/local-link-checker.sh new file mode 100755 index 000000000..fcf1f76ad --- /dev/null +++ b/.github/scripts/local-link-checker.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -e +set -u +[ -n "${DEBUG:-}" ] && set -x || true + +function gherr() { + local line="$1" + local file="${line%%:*}" + local lineno="${line#*:}" + lineno="${lineno%%:*}" + local matching="${line#*:*:}" + echo "::error file=${file#./},line=$lineno::Broken link $matching" +} + +function check() { + local line dir link target failed=0 + + while read line; do + dir="$(dirname "${line%%:*}")" + link="${line#*:*:}" + + case "$link" in + //*) + # ignore http links + ;; + /*) + fail "Not a valid local link" + ;; + ../*) + target="$(dirname "$dir")${link#..}" + if ! [ -f "$target" ]; then + failed=1 + gherr "$line" + fi + ;; + *) + # relative to current directory + target="$dir/${link#./}" + if ! [ -f "$target" ]; then + failed=1 + gherr "$line" + fi + ;; + esac + done + + exit "$failed" +} + +find . -name '*.md' -print0 | xargs -0 /usr/bin/grep -Hno '[^(): ][^():]*\.md' | check diff --git a/.github/workflows/local-link-checker.yaml b/.github/workflows/local-link-checker.yaml new file mode 100644 index 000000000..aa68e4535 --- /dev/null +++ b/.github/workflows/local-link-checker.yaml @@ -0,0 +1,21 @@ +name: Local Link Checker + +on: + push: + branches: + - "*" + pull_request: + +jobs: + local-link-checker: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: run checker + run: .github/scripts/local-link-checker.sh + + - name: info for fixing + if: ${{ failure() }} + run: echo "::error::Broken local links found, please use ./.github/scripts/local-link-checker.sh to check locally" diff --git a/.gitignore b/.gitignore index 336aeaef1..1aef5dd30 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ _book .DS_Store *.pdf *.patch -*.sh