-
Notifications
You must be signed in to change notification settings - Fork 2
fix(docs): repair 4 links broken by #18, add a doc-link gate #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,51 @@ | ||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # check-doc-links.sh — every relative Markdown link must resolve. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Why this exists: collapsing seven skills into one router (#18) deleted | ||||||||||||||||||||||||||||||||||||
| # skills/{nushell,shebang,streams,zsh}/ but left four reference/*.md files | ||||||||||||||||||||||||||||||||||||
| # linking to them. Every other gate stayed green -- lint, tests, examples, | ||||||||||||||||||||||||||||||||||||
| # schemas, ai-integrations -- because none of them reads a link. In a repo | ||||||||||||||||||||||||||||||||||||
| # whose product IS its documentation, a dangling link is a defect. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Only relative targets are checked. External URLs are deliberately not | ||||||||||||||||||||||||||||||||||||
| # fetched: that needs network, is slow, and turns someone else's outage into | ||||||||||||||||||||||||||||||||||||
| # a red build. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # One grep+sed per file is a deliberate choice over a single clever pass. A | ||||||||||||||||||||||||||||||||||||
| # rewrite that hoisted both out of the loop to avoid the subprocesses silently | ||||||||||||||||||||||||||||||||||||
| # mangled its own field splitting and reported every link as broken. Two | ||||||||||||||||||||||||||||||||||||
| # subprocesses per markdown file is cheap; a checker that lies is not. | ||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| status=0 | ||||||||||||||||||||||||||||||||||||
| checked=0 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| while IFS= read -r file; do | ||||||||||||||||||||||||||||||||||||
| dir=$(dirname "${file}") | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| while IFS= read -r target; do | ||||||||||||||||||||||||||||||||||||
| [[ -z ${target} ]] && continue | ||||||||||||||||||||||||||||||||||||
| case "${target}" in | ||||||||||||||||||||||||||||||||||||
| http://* | https://* | mailto:* | '#'*) continue ;; | ||||||||||||||||||||||||||||||||||||
| *) ;; | ||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| target=${target%%#*} | ||||||||||||||||||||||||||||||||||||
| [[ -z ${target} ]] && continue | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| checked=$((checked + 1)) | ||||||||||||||||||||||||||||||||||||
| if [[ ! -e "${dir}/${target}" ]]; then | ||||||||||||||||||||||||||||||||||||
| printf 'broken link: %s -> %s\n' "${file}" "${target}" >&2 | ||||||||||||||||||||||||||||||||||||
| status=1 | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two issues with the path resolution here:
We can resolve both issues by:
Suggested change
|
||||||||||||||||||||||||||||||||||||
| # `[text](target)` with no spaces or parens inside the target, which is | ||||||||||||||||||||||||||||||||||||
| # what every link in this repo looks like. | ||||||||||||||||||||||||||||||||||||
| done < <(grep -o '\[[^][]*\]([^() ]*)' "${file}" | sed 's/.*(\(.*\))/\1/') | ||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a markdown file contains no links at all, Appending
Suggested change
|
||||||||||||||||||||||||||||||||||||
| done < <(git ls-files '*.md') | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if [[ ${status} -eq 0 ]]; then | ||||||||||||||||||||||||||||||||||||
| printf 'doc-links: OK (%s relative links resolve)\n' "${checked}" | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| exit "${status}" | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current
casestatement only excludes a hardcoded list of protocols (http,https,mailto). It will fail on other valid URI schemes (likeftp://,news:,tel:, etc.) or protocol-relative URLs (like//example.com), incorrectly treating them as relative file paths and reporting them as broken.We can make this much more robust and simpler by skipping any target that contains a colon
:(which covers all URI schemes) or starts with//(protocol-relative).