1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
deps@{
cacert,
formats,
lib,
lychee,
stdenv,
writeShellApplication,
}:
let
inherit (lib) mapAttrsToList optionalString throwIf;
inherit (lib.strings) hasInfix hasPrefix escapeNixString;
toURL =
v:
let
s = "${v}";
in
if hasPrefix builtins.storeDir s then # lychee requires that paths on the file system are prefixed with file://
"file://${s}"
else
s;
withCheckedName =
name:
throwIf (hasInfix " " name) ''
lycheeLinkCheck: remap patterns must not contain spaces.
A space marks the end of the regex in lychee.toml.
Please change attribute name 'remap.${escapeNixString name}'
'';
# See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck
# or doc/build-helpers/testers.chapter.md
lycheeLinkCheck =
{
site,
relocatable ? null,
remap ? { },
lychee ? deps.lychee,
extraConfig ? { },
extraArgs ? [ ],
}:
stdenv.mkDerivation (finalAttrs: {
name = "lychee-link-check";
__structuredAttrs = true;
inherit site;
nativeBuildInputs = [
finalAttrs.passthru.lychee
cacert
];
configFile = (formats.toml { }).generate "lychee.toml" finalAttrs.passthru.config;
inherit extraArgs;
# These can be overridden with overrideAttrs if needed.
passthru = {
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 (
name: value: withCheckedName name "${name} ${toURL value}"
) 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 ];
# Comment out to run shellcheck:
checkPhase = "";
text = ''
site=${finalAttrs.site}
configFile=${finalAttrs.configFile}
echo Checking links on $site
exec lychee --config $configFile ${lib.escapeShellArgs extraArgs} $site "$@"
'';
};
};
buildCommand = ''
echo Checking internal links on $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
'';
});
in
{
inherit lycheeLinkCheck;
}
|