testers.lycheeLinkCheck: improve root-relative link UX (#520792)

This commit is contained in:
Philip Taron 2026-06-10 22:51:47 +00:00 committed by GitHub
commit 4c9924ca35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 2 deletions

View file

@ -98,6 +98,14 @@ It has two modes:
: The path to the files to check.
`relocatable` (boolean, optional) {#tester-lycheeLinkCheck-param-relocatable}
: Whether the site is expected to be relocatable, i.e. servable from any URL path prefix.
When `true` (the default), root-relative links (starting with `/`) are treated as errors, because they break when the site is served from a subpath or opened via `file://` URLs.
When `false`, root-relative links are resolved against the `site` directory.
`remap` (attribute set, optional) {#tester-lycheeLinkCheck-param-remap}
: An attribute set where the attribute names are regular expressions.

View file

@ -7,7 +7,7 @@ deps@{
writeShellApplication,
}:
let
inherit (lib) mapAttrsToList throwIf;
inherit (lib) mapAttrsToList optionalString throwIf;
inherit (lib.strings) hasInfix hasPrefix escapeNixString;
toURL =
@ -34,6 +34,7 @@ let
lycheeLinkCheck =
{
site,
relocatable ? null,
remap ? { },
lychee ? deps.lychee,
extraConfig ? { },
@ -55,6 +56,11 @@ let
inherit lychee remap;
config = {
include_fragments = "full";
root_dir =
if relocatable == false then
finalAttrs.site
else
"/root-relative-links-are-forbidden-use-relative-links";
}
// lib.optionalAttrs (finalAttrs.passthru.remap != { }) {
remap = mapAttrsToList (
@ -62,6 +68,9 @@ let
) finalAttrs.passthru.remap;
}
// extraConfig;
# NOTE: The online wrapper does not implement the relocatable hint message.
# It uses the same configFile (with the fake root_dir), so root-relative
# links still fail, but without the custom explanation.
online = writeShellApplication {
name = "run-lychee-online";
runtimeInputs = [ finalAttrs.passthru.lychee ];
@ -77,7 +86,33 @@ let
};
buildCommand = ''
echo Checking internal links on $site
lychee --offline --config $configFile "''${extraArgs[@]}" $site
rc=0
lychee --offline --config $configFile "''${extraArgs[@]}" $site 2>&1 | tee lychee.log || rc="''${PIPESTATUS[0]}"
${optionalString (relocatable != false) ''
if [ "$rc" -ne 0 ] && grep -qF "[ERROR] file:///root-relative-links-are-forbidden" lychee.log; then
echo
${
if relocatable == null then
''
echo " Your site contains root-relative links (starting with '/')."
echo "Please set the relocatable parameter in lycheeLinkCheck:"
echo " - relocatable = true: root-relative links are forbidden because they"
echo " break when the site is served from a subpath or opened via file:// URLs."
echo " - relocatable = false: root-relative links are allowed because the"
echo " site is always served from the root."
''
else
''
echo " Root-relative links (starting with '/') are not allowed because this"
echo "site is marked as relocatable (relocatable = true)."
''
}
echo "See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck-param-relocatable"
fi
''}
if [ "$rc" -ne 0 ]; then
exit "$rc"
fi
touch $out
'';
});

View file

@ -84,6 +84,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
ok = callPackage ./tests/ok.nix { };
fail = callPackage ./tests/fail.nix { };
fail-emptyDirectory = callPackage ./tests/fail-emptyDirectory.nix { };
fail-rootRelative = callPackage ./tests/fail-rootRelative.nix { };
network = testers.runNixOSTest ./tests/network.nix;
};

View file

@ -0,0 +1,21 @@
{ runCommand, testers }:
let
sitePkg = runCommand "site" { } ''
dist=$out/dist
mkdir -p $dist
echo "<html><body>hi</body></html>" > $dist/index.html
echo "<html><body><a href=\"/index.html\">home</a></body></html>" > $dist/page.html
'';
linkCheck = testers.lycheeLinkCheck {
site = sitePkg + "/dist";
};
failure = testers.testBuildFailure linkCheck;
in
runCommand "link-check-fail" { inherit failure; } ''
grep -F "root-relative-links-are-forbidden-use-relative-links/index.html" $failure/testBuildFailure.log >/dev/null
grep -F "Please set the relocatable parameter" $failure/testBuildFailure.log >/dev/null
touch $out
''

View file

@ -5,10 +5,12 @@ let
mkdir -p $dist
echo "<html><body><a href=\"https://example.com/foo.html\">foo</a><a href=\"https://nixos.org/this-is-ignored.html\">bar</a></body></html>" > $dist/index.html
echo "<html><body><a href=\".\">index</a></body></html>" > $dist/foo.html
echo "<html><body><a href=\"/index.html\">home</a></body></html>" > $dist/root-relative.html
'';
in
testers.lycheeLinkCheck rec {
site = sitePkg + "/dist";
relocatable = false;
remap = {
"https://example.com" = site;
};