@majordigital/create-acorn 1.6.3 → 1.6.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majordigital/create-acorn",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "Interactive starter CLI for Acorn with Storyblok/Prismic/DatoCMS, TypeScript, and Tailwind.",
5
5
  "bin": {
6
6
  "create-acorn": "bin/create-acorn.mjs",
@@ -29,17 +29,29 @@ const concurrency = isLocalhost ? 2 : 5;
29
29
  // Support Netlify Basic Auth (password-protected preview deploys).
30
30
  // Set NETLIFY_AUTH=user:password in your environment before running.
31
31
  const netlifyAuth = process.env.NETLIFY_AUTH;
32
- const headers = netlifyAuth
33
- ? { Authorization: `Basic ${Buffer.from(netlifyAuth).toString("base64")}` }
34
- : {};
32
+
33
+ // Extract hostname so we can match internal URLs with or without credentials.
34
+ const { protocol, hostname } = new URL(baseUrl);
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
46
 
36
47
  const checker = new LinkChecker();
37
48
 
38
49
  checker.on("link", (result) => {
39
50
  if (result.state === "BROKEN") {
40
- console.log(
41
- ` BROKEN [${result.status}] ${result.url} (from ${result.parent})`,
42
- );
51
+ // Strip credentials from URLs before printing
52
+ const url = result.url.replace(/\/\/[^@]+@/, "//");
53
+ const parent = result.parent?.replace(/\/\/[^@]+@/, "//");
54
+ console.log(` BROKEN [${result.status}] ${url} (from ${parent})`);
43
55
  }
44
56
  });
45
57
 
@@ -49,14 +61,14 @@ console.log(`Concurrency: ${concurrency}`);
49
61
  console.log("This may take several minutes...\n");
50
62
 
51
63
  const result = await checker.check({
52
- path: baseUrl,
64
+ path: crawlUrl,
53
65
  recurse: true,
54
66
  concurrency,
55
67
  timeout: 30000,
56
- headers,
68
+ urlRewriteExpressions,
57
69
  linksToSkip: [
58
- // Skip external links to avoid false positives from rate limiting
59
- `^(?!(${baseUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}))`,
70
+ // Skip URLs that don't contain our hostname (handles both clean and credential-embedded forms)
71
+ `^(?!https?://[^/@]*@?${escapedHostname})`,
60
72
  // Skip multi-filter URLs — the filter UI generates combinatorial links
61
73
  // (e.g. ?filter=a%2Cb%2Cc) that cause a crawl explosion. Not real links.
62
74
  ".*[?&]filter=.*%2C.*",
@@ -83,6 +95,8 @@ console.log(`OK: ${ok.length}`);
83
95
  console.log(`Broken: ${broken.length}`);
84
96
  console.log(`Skipped: ${skipped.length}`);
85
97
 
98
+ const stripAuth = (u) => u?.replace(/\/\/[^@]+@/, "//") ?? u;
99
+
86
100
  let md = `## Broken Link Check\n\n`;
87
101
  md += `Crawled: ${baseUrl}\n\n`;
88
102
  md += `| Metric | Count |\n|--------|-------|\n`;
@@ -94,11 +108,11 @@ md += `| Skipped | ${skipped.length} |\n\n`;
94
108
  if (broken.length > 0) {
95
109
  const grouped = new Map();
96
110
  for (const link of broken) {
97
- const key = link.url;
111
+ const key = stripAuth(link.url);
98
112
  if (!grouped.has(key)) {
99
- grouped.set(key, { status: link.status, url: link.url, foundOn: new Set() });
113
+ grouped.set(key, { status: link.status, url: key, foundOn: new Set() });
100
114
  }
101
- grouped.get(key).foundOn.add(link.parent);
115
+ grouped.get(key).foundOn.add(stripAuth(link.parent));
102
116
  }
103
117
 
104
118
  md += `### Broken Links (${grouped.size} unique)\n\n`;