@majordigital/create-acorn 1.6.5 → 1.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-acorn.mjs +20 -8
- package/package.json +1 -1
- package/template/scripts/check-links.mjs +16 -27
package/bin/create-acorn.mjs
CHANGED
|
@@ -116,23 +116,35 @@ async function setupPreDeploy() {
|
|
|
116
116
|
cpSync(scriptsSrc, scriptsDest, { recursive: true, force: true });
|
|
117
117
|
console.log('Pre-deploy scripts copied to scripts/.');
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
// Write devDependencies and scripts into package.json explicitly, rather than
|
|
120
|
+
// relying on `npm install --save-dev` to persist them. When the packages are
|
|
121
|
+
// already present in node_modules, npm reports "up to date" and may skip
|
|
122
|
+
// updating package.json — leaving the deps unrecorded.
|
|
123
|
+
const preDeployDeps = {
|
|
124
|
+
lighthouse: '^13',
|
|
125
|
+
'chrome-launcher': '^1',
|
|
126
|
+
playwright: '^1',
|
|
127
|
+
linkinator: '^7',
|
|
128
|
+
};
|
|
125
129
|
try {
|
|
130
|
+
if (!pkg.devDependencies) pkg.devDependencies = {};
|
|
131
|
+
for (const [name, range] of Object.entries(preDeployDeps)) {
|
|
132
|
+
if (!pkg.devDependencies[name]) pkg.devDependencies[name] = range;
|
|
133
|
+
}
|
|
126
134
|
if (!pkg.scripts) pkg.scripts = {};
|
|
127
135
|
pkg.scripts['lighthouse'] = 'node scripts/lighthouse-audit.mjs';
|
|
128
136
|
pkg.scripts['check-links'] = 'node scripts/check-links.mjs';
|
|
129
137
|
pkg.scripts['cross-browser'] = 'node scripts/cross-browser-check.mjs';
|
|
130
138
|
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
131
|
-
console.log('Added pre-deploy scripts to package.json.');
|
|
139
|
+
console.log('Added pre-deploy scripts and dependencies to package.json.');
|
|
132
140
|
} catch {
|
|
133
|
-
console.log('Warning: Could not
|
|
141
|
+
console.log('Warning: Could not update package.json with pre-deploy setup.');
|
|
134
142
|
}
|
|
135
143
|
console.log('');
|
|
144
|
+
|
|
145
|
+
console.log('Installing pre-deploy tools (Lighthouse, Playwright, linkinator)...');
|
|
146
|
+
await runCommand('npm', ['install', '--legacy-peer-deps']);
|
|
147
|
+
console.log('');
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
async function setupNextApp() {
|
package/package.json
CHANGED
|
@@ -28,30 +28,21 @@ const concurrency = isLocalhost ? 2 : 5;
|
|
|
28
28
|
|
|
29
29
|
// Support Netlify Basic Auth (password-protected preview deploys).
|
|
30
30
|
// Set NETLIFY_AUTH=user:password in your environment before running.
|
|
31
|
+
// NOTE: requires linkinator >=7 (the `headers` option is applied to every
|
|
32
|
+
// fetch). Credentials are sent via an Authorization header, not embedded in
|
|
33
|
+
// the URL — Node's fetch (undici) rejects URLs that contain credentials.
|
|
31
34
|
const netlifyAuth = process.env.NETLIFY_AUTH;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const escapedHostname = hostname.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
36
|
-
|
|
37
|
-
// Rewrite every internal link to include credentials so all requests authenticate.
|
|
38
|
-
// Without this, links found in HTML use clean URLs and get 401.
|
|
39
|
-
const urlRewriteExpressions = netlifyAuth
|
|
40
|
-
? [{ pattern: new RegExp(`^${protocol}//${escapedHostname}`), replacement: `${protocol}//${netlifyAuth}@${hostname}` }]
|
|
41
|
-
: [];
|
|
42
|
-
|
|
43
|
-
const crawlUrl = netlifyAuth
|
|
44
|
-
? baseUrl.replace(/^(https?:\/\/)/, `$1${netlifyAuth}@`)
|
|
45
|
-
: baseUrl;
|
|
35
|
+
const headers = netlifyAuth
|
|
36
|
+
? { Authorization: `Basic ${Buffer.from(netlifyAuth).toString("base64")}` }
|
|
37
|
+
: {};
|
|
46
38
|
|
|
47
39
|
const checker = new LinkChecker();
|
|
48
40
|
|
|
49
41
|
checker.on("link", (result) => {
|
|
50
42
|
if (result.state === "BROKEN") {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
console.log(` BROKEN [${result.status}] ${url} (from ${parent})`);
|
|
43
|
+
console.log(
|
|
44
|
+
` BROKEN [${result.status}] ${result.url} (from ${result.parent})`,
|
|
45
|
+
);
|
|
55
46
|
}
|
|
56
47
|
});
|
|
57
48
|
|
|
@@ -61,14 +52,14 @@ console.log(`Concurrency: ${concurrency}`);
|
|
|
61
52
|
console.log("This may take several minutes...\n");
|
|
62
53
|
|
|
63
54
|
const result = await checker.check({
|
|
64
|
-
path:
|
|
55
|
+
path: baseUrl,
|
|
65
56
|
recurse: true,
|
|
66
57
|
concurrency,
|
|
67
58
|
timeout: 30000,
|
|
68
|
-
|
|
59
|
+
headers,
|
|
69
60
|
linksToSkip: [
|
|
70
|
-
// Skip
|
|
71
|
-
`^(?!
|
|
61
|
+
// Skip external links to avoid false positives from rate limiting
|
|
62
|
+
`^(?!(${baseUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}))`,
|
|
72
63
|
// Skip multi-filter URLs — the filter UI generates combinatorial links
|
|
73
64
|
// (e.g. ?filter=a%2Cb%2Cc) that cause a crawl explosion. Not real links.
|
|
74
65
|
".*[?&]filter=.*%2C.*",
|
|
@@ -95,8 +86,6 @@ console.log(`OK: ${ok.length}`);
|
|
|
95
86
|
console.log(`Broken: ${broken.length}`);
|
|
96
87
|
console.log(`Skipped: ${skipped.length}`);
|
|
97
88
|
|
|
98
|
-
const stripAuth = (u) => u?.replace(/\/\/[^@]+@/, "//") ?? u;
|
|
99
|
-
|
|
100
89
|
let md = `## Broken Link Check\n\n`;
|
|
101
90
|
md += `Crawled: ${baseUrl}\n\n`;
|
|
102
91
|
md += `| Metric | Count |\n|--------|-------|\n`;
|
|
@@ -108,11 +97,11 @@ md += `| Skipped | ${skipped.length} |\n\n`;
|
|
|
108
97
|
if (broken.length > 0) {
|
|
109
98
|
const grouped = new Map();
|
|
110
99
|
for (const link of broken) {
|
|
111
|
-
const key =
|
|
100
|
+
const key = link.url;
|
|
112
101
|
if (!grouped.has(key)) {
|
|
113
|
-
grouped.set(key, { status: link.status, url:
|
|
102
|
+
grouped.set(key, { status: link.status, url: link.url, foundOn: new Set() });
|
|
114
103
|
}
|
|
115
|
-
grouped.get(key).foundOn.add(
|
|
104
|
+
grouped.get(key).foundOn.add(link.parent);
|
|
116
105
|
}
|
|
117
106
|
|
|
118
107
|
md += `### Broken Links (${grouped.size} unique)\n\n`;
|