2019-12-18 17:18:55 +03:00
<!--
2021-07-15 16:16:08 +03:00
- SPDX-FileCopyrightText: 2018-2021 Serokell < https: // serokell . io >
2019-12-18 17:18:55 +03:00
-
- SPDX-License-Identifier: MPL-2.0
-->
2020-01-13 15:58:14 +03:00
# Xrefcheck
2019-03-14 20:21:20 +03:00
2023-01-16 17:15:43 +03:00
![Build status ](https://github.com/serokell/xrefcheck/actions/workflows/ci.yml/badge.svg )
2023-07-06 15:34:05 +03:00
< img referrerpolicy = "no-referrer-when-downgrade" src = "https://static.scarf.sh/a.png?x-pxid=bdf72cff-c1f1-4b3a-97f0-5083dbb77fa6" / >
2019-12-05 16:10:15 +03:00
2022-11-07 16:42:30 +03:00
Xrefcheck is a tool for verifying local and external references in a repository's documentation that is quick, easy to setup, and suitable to be run on a CI pipeline.
2019-03-14 20:21:20 +03:00
2022-11-29 13:16:56 +03:00
< img src = "./docs/output-sample/output-sample.png" alt = "Output sample" width = "600" / >
2019-12-05 17:38:25 +03:00
2022-11-07 16:42:30 +03:00
## Motivation [↑](#xrefcheck)
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
As a project evolves, links in markdown documentation have a tendency to become broken. This is usually because:
1. A file has been moved;
2. A markdown header has been renamed;
3. An external site has ceased to exist.
2019-12-05 18:12:01 +03:00
This tool will help you to keep references in order.
2022-11-07 16:42:30 +03:00
You can run `xrefcheck` continuously in your CI pipeline,
and it will let you know when it finds a broken link.
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
## Aims [↑](#xrefcheck)
2019-12-05 17:38:25 +03:00
2019-12-18 12:44:03 +03:00
Comparing to alternative solutions, this tool tries to achieve the following points:
2019-12-05 17:38:25 +03:00
2022-11-07 16:42:30 +03:00
* Quickness
* References are verified in parallel.
* References with the same target URI are only verified once.
* It first attempts to verify external links with a `HEAD` request; only when that fails does it try a `GET` request.
* Resilience
* When you have many links to the same domain, the service is likely to start replying with "429 Too Many Requests".
When this happens, `xrefcheck` will wait the requested amount of seconds before retrying.
* Easy setup - no extra actions required, just run `xrefcheck` in the repository root.
2019-12-05 18:12:01 +03:00
* Conservative verifier allows using this tool in CI, no false positives (e.g. on sites which require authentication) should be reported.
2022-11-07 16:42:30 +03:00
## Features [↑](#xrefcheck)
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
* Supports both GitHub and GitLab flavored markdown.
* Supports Windows and Unix systems.
* Supports relative and absolute local links.
* Supports external links (`http`, `https` , `ftp` and `ftps` ).
* Detects broken and ambiguous anchors in local links.
* Integration with GitHub Actions.
2019-03-14 20:21:20 +03:00
2022-09-26 08:34:13 +03:00
## Dependencies [↑](#xrefcheck)
Xrefcheck requires you to have `git` version 2.18.0 or later in your PATH.
2020-06-29 17:48:16 +03:00
## Usage [↑](#xrefcheck)
2019-12-04 23:37:21 +03:00
2020-06-29 17:48:16 +03:00
We provide the following ways for you to use xrefcheck:
2019-12-09 12:38:33 +03:00
2022-11-07 16:42:30 +03:00
- [GitHub Actions ](https://github.com/marketplace/actions/xrefcheck )
2023-07-06 15:34:05 +03:00
- [Statically linked binaries ](https://github.com/serokell/xrefcheck/releases ), e. g. on Linux:
```
mkdir -p bin/
wget --quiet -O bin/xrefcheck https://serokell.gateway.scarf.sh/xrefcheck/latest/xrefcheck-x86_64-linux
chmod +x bin/xrefcheck
bin/xrefcheck
```
2020-06-29 17:48:16 +03:00
- [Docker image ](https://hub.docker.com/r/serokell/xrefcheck )
2023-07-06 15:34:05 +03:00
```
docker pull serokell.docker.scarf.sh/serokell/xrefcheck
```
2022-11-07 16:42:30 +03:00
- [Building from source ](#build-instructions- )
- Nix
```
nix shell -f https://github.com/serokell/xrefcheck/archive/master.tar.gz -c xrefcheck
```
2019-12-04 23:37:21 +03:00
2020-06-29 17:48:16 +03:00
If none of those are suitable for you, please open an issue!
2019-03-14 20:21:20 +03:00
2022-11-07 16:42:30 +03:00
To find all broken links in a repository, simply run `xrefcheck` from its root folder:
2019-03-14 20:21:20 +03:00
```sh
2020-01-13 15:58:14 +03:00
xrefcheck
2019-03-14 20:21:20 +03:00
```
2022-11-07 16:42:30 +03:00
To also display a list of all links and anchors:
2019-12-05 18:12:01 +03:00
```sh
2022-11-07 16:42:30 +03:00
xrefcheck --verbose
2019-12-05 18:12:01 +03:00
```
2019-12-18 12:44:03 +03:00
For description of other options:
2019-03-14 20:21:20 +03:00
```sh
2020-01-13 15:58:14 +03:00
xrefcheck --help
2019-03-14 20:21:20 +03:00
```
2022-11-07 16:42:30 +03:00
To configure `xrefcheck` , run:
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
```sh
xrefcheck dump-config --type GitHub
```
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
This will create a `.xrefcheck.yaml` file with all the configuration
options, [here's an example ](tests/configs/github-config.yaml ).
This file should be committed to your repository.
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
## Build instructions [↑](#xrefcheck)
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
Run `stack install` to build everything and install the executable.
If you wish to use `cabal` , you need to run [`stack2cabal` ](https://hackage.haskell.org/package/stack2cabal ) first!
2020-12-28 16:37:56 +03:00
2022-10-13 17:07:19 +03:00
### Run on Windows [↑](#xrefcheck)
2022-12-13 12:20:32 +03:00
2022-10-13 17:07:19 +03:00
On Windows, executable requires some dynamic libraries (DLLs).
They are shipped together with executable in [releases page ](https://github.com/serokell/xrefcheck/releases ).
If you have built executable from source using `stack install` ,
those DLLs are downloaded by stack to a location that is not on `%PATH%` by default.
There are several ways to fix this:
- Add `%LocalAppData%\Programs\stack\x86_64-windows\msys2-<...>\mingw64\bin` to your PATH
- run `stack exec xrefcheck.exe -- <args>` instead of `xrefcheck.exe <args>`
- add DLLs from archive from releases page to a folder containing `xrefcheck.exe`
2022-11-07 16:42:30 +03:00
## FAQ [↑](#xrefcheck)
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
1. How do I ignore specific files?
* To ignore a specific file, you can either use the `--ignore <glob pattern>` command-line option,
or the `ignore` list in the config file. Links _to_ those files will be reported as errors, links _from_ those files will not be verified.
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
1. How do I ignore specific links?
* Add an entry to the `ignoreLocalRefsTo` or `ignoreExternalRefsTo` lists in the config file.
* Alternatively, add a `<!-- xrefcheck: ignore link -->` annotation before the link:
```md
<!-- xrefcheck: ignore link -->
Link to some [invalid resource ](https://fictitious.uri/ ).
```
```md
A [valid link ](https://www.google.com )
followed by an <!-- xrefcheck: ignore link --> [invalid link ](https://fictitious.uri/ ).
```
* You can also use a `<!-- xrefcheck: ignore paragraph -->` annotation to ignore all links in a paragraph.
2020-12-28 16:37:56 +03:00
2022-11-07 16:42:30 +03:00
1. How do I ignore all links from a specific markdown file?
* Add a glob pattern to the `ignoreRefsFrom` list in the config file.
* Or add a `<!-- xrefcheck: ignore all -->` at the top of the file.
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
1. How do I ignore all external links?
* If you wish to ignore all http/ftp links, you can use `--mode local-only` .
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
1. How does `xrefcheck` handle links that require authentication?
2022-12-13 12:20:32 +03:00
* It's common for projects to contain links to protected resources.
2022-11-07 16:42:30 +03:00
By default, when `xrefcheck` attempts to verify a link and is faced with a `403 Forbidden` or a `401 Unauthorized` , it assumes the link is valid.
* This behavior can be disabled by setting `ignoreAuthFailures: false` in the config file.
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
1. How does `xrefcheck` handle redirects?
2022-12-19 19:50:07 +03:00
* The rules from the default configuration are as follows:
* Permanent redirects (i.e. 301 and 308) are reported as errors.
2023-01-10 18:32:51 +03:00
* There are no rules for other redirects, except for a special GitLab case, so they are assumed to be valid.
2022-12-19 19:50:07 +03:00
* Redirect rules can be specified with the `externalRefRedirects` parameter within `networking` , which accepts an array of
rules with keys `from` , `to` , `on` and `outcome` . The rule applied is the first one that matches with
the `from` , `to` and `on` fields, if any, where
* `from` is a regular expression, as in `ignoreExternalRefsTo` , for the source link in a single redirection step. Its absence means that
every link matches.
* `to` is a regular expression for the target link in a single redirection step. Its absence also means that every link matches.
* `on` accepts `temporary` , `permanent` or a specific redirect HTTP code. Its absence also means that
every response code matches.
* The `outcome` parameter accepts `valid` , `invalid` or `follow` . The last one follows the redirect by applying the
same configuration rules.
For example, this configuration forbids 307 redirects to a specific domain and makes redirections from HTTP to HTTPS to be followed:
```
externalRefRedirects:
- to: "https?://forbidden.com.*"
on: 307
outcome: invalid
2022-12-28 19:37:58 +03:00
- from: "http://.*"
to: "https://.*"
2022-12-19 19:50:07 +03:00
outcome: follow
```
The first one applies if both of them match.
* The number of redirects allowed in a single redirect chain is limited and can be configured with the
`maxRedirectFollows` parameter, also within `networking` . A number smaller than 0 disables the limit.
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
1. How does `xrefcheck` handle localhost links?
* By default, `xrefcheck` will ignore links to localhost.
* This behavior can be disabled by removing the corresponding entry from the `ignoreExternalRefsTo` list in the config file.
2020-06-29 17:48:16 +03:00
2022-11-07 16:42:30 +03:00
## Further work [↑](#xrefcheck)
2019-12-05 18:12:01 +03:00
2019-12-18 12:44:03 +03:00
- [ ] Support link detection in different languages, not only Markdown.
- [ ] Haskell Haddock is first in turn.
2019-12-05 18:12:01 +03:00
2022-11-07 16:42:30 +03:00
## A comparison with other solutions [↑](#xrefcheck)
* [linky ](https://github.com/mattias-p/linky ) - a well-configurable verifier written in Rust, scans one specified file at a time and works well with system utilities like `find` .
This tool requires some configuring before it can be applied to a repository or added to CI.
* [awesome_bot ](https://github.com/dkhamsing/awesome_bot ) - a solution written in Ruby that can be easily included in CI or integrated into GitHub.
Its features include duplicated URLs detection, specifying allowed HTTP error codes and reporting generation.
At the moment of writing, it scans only external references and checking anchors is not possible.
* [remark-validate-links ](https://github.com/remarkjs/remark-validate-links ) and [remark-lint-no-dead-urls ](https://github.com/davidtheclark/remark-lint-no-dead-urls ) - highly configurable JavaScript solution for checking local and external links respectively.
2022-12-13 12:20:32 +03:00
It is able to check multiple repositories at once if they are gathered in one folder.
2022-11-07 16:42:30 +03:00
Doesn't handle "429 Too Many Requests", so false positives are likely when you have many links to the same domain.
* [markdown-link-check ](https://github.com/tcort/markdown-link-check ) - another checker written in JavaScript, scans one specific file at a time.
Supports `mailto:` link resolution.
* [url-checker ](https://github.com/paramt/url-checker ) - GitHub Action which checks external links in specified files.
Does not check local links.
* [linkcheck ](https://github.com/filiph/linkcheck ) - advanced site crawler, verifies links in `HTML` files. There are other solutions for this particular task which we don't mention here.
At the moment of writing, the listed solutions don't support ftp/ftps links.
2020-01-13 15:58:14 +03:00
## Issue tracker [↑](#xrefcheck)
2019-03-14 20:21:20 +03:00
2019-12-05 19:41:08 +03:00
We use GitHub issues as our issue tracker.
You can login using your GitHub account to leave a comment or create a new issue.
2019-03-14 20:21:20 +03:00
2020-01-13 15:58:14 +03:00
## For Contributors [↑](#xrefcheck)
2019-03-14 20:21:20 +03:00
Please see [CONTRIBUTING.md ](/.github/CONTRIBUTING.md ) for more information.
2020-01-13 15:58:14 +03:00
## About Serokell [↑](#xrefcheck)
2019-03-14 20:21:20 +03:00
2020-01-13 15:58:14 +03:00
Xrefcheck is maintained and funded with ❤️ by [Serokell ](https://serokell.io/ ).
2019-12-05 16:10:25 +03:00
The names and logo for Serokell are trademark of Serokell OÜ.
2019-03-14 20:21:20 +03:00
2019-12-05 16:10:25 +03:00
We love open source software! See [our other projects ](https://serokell.io/community?utm_source=github ) or [hire us ](https://serokell.io/hire-us?utm_source=github ) to design, develop and grow your idea!