@piercebarney/whs-eleventy 2026.9.23 → 2026.9.24
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/lib/check-links.js +15 -7
- package/package.json +1 -1
- package/standard/CHANGELOG.md +28 -0
- package/standard/core.md +2 -2
package/lib/check-links.js
CHANGED
|
@@ -135,7 +135,7 @@ function outputHas(urlPath) {
|
|
|
135
135
|
return fs.existsSync(asFile + "/index.html") || fs.existsSync(asFile + ".html");
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
function checkRef(file, pageUrl, raw, { external = true, isHyperlink = false } = {}) {
|
|
138
|
+
function checkRef(file, pageUrl, resolveBase, raw, { external = true, isHyperlink = false } = {}) {
|
|
139
139
|
if (!raw) return;
|
|
140
140
|
const v = raw.trim();
|
|
141
141
|
if (v === "" || v.startsWith("data:") || v.startsWith("mailto:") || v.startsWith("tel:")) return;
|
|
@@ -185,13 +185,15 @@ function checkRef(file, pageUrl, raw, { external = true, isHyperlink = false } =
|
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
187
|
// relative path — resolve against the page dir
|
|
188
|
-
const resolved = path.posix.join(
|
|
188
|
+
const resolved = path.posix.join(resolveBase, v);
|
|
189
189
|
if (!outputHas(resolved)) err(file, `relative reference does not resolve: ${v}`);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
for (const f of htmlFiles) {
|
|
193
193
|
const rel = "/" + path.relative(SITE, f).replace(/\\/g, "/");
|
|
194
194
|
const pageUrl = rel.replace(/index\.html$/, "");
|
|
195
|
+
const dir = path.posix.dirname(rel);
|
|
196
|
+
const resolveBase = dir === "/" ? "/" : dir + "/";
|
|
195
197
|
const root = parse(fs.readFileSync(f, "utf8"));
|
|
196
198
|
|
|
197
199
|
// CSP-safety: the strict CSP (script-src 'self'; style-src 'self') rejects
|
|
@@ -216,7 +218,7 @@ for (const f of htmlFiles) {
|
|
|
216
218
|
|
|
217
219
|
root.querySelectorAll("a[href]").forEach((a) => {
|
|
218
220
|
const href = a.getAttribute("href");
|
|
219
|
-
checkRef(f, pageUrl, href, { isHyperlink: true });
|
|
221
|
+
checkRef(f, pageUrl, resolveBase, href, { isHyperlink: true });
|
|
220
222
|
if (/^https?:\/\//i.test(href || "")) {
|
|
221
223
|
let origin;
|
|
222
224
|
try {
|
|
@@ -233,12 +235,18 @@ for (const f of htmlFiles) {
|
|
|
233
235
|
}
|
|
234
236
|
});
|
|
235
237
|
|
|
236
|
-
root
|
|
237
|
-
|
|
238
|
-
|
|
238
|
+
root
|
|
239
|
+
.querySelectorAll("link[href]")
|
|
240
|
+
.forEach((l) => checkRef(f, pageUrl, resolveBase, l.getAttribute("href")));
|
|
241
|
+
root
|
|
242
|
+
.querySelectorAll("script[src]")
|
|
243
|
+
.forEach((s) => checkRef(f, pageUrl, resolveBase, s.getAttribute("src")));
|
|
244
|
+
root
|
|
245
|
+
.querySelectorAll("img[src]")
|
|
246
|
+
.forEach((i) => checkRef(f, pageUrl, resolveBase, i.getAttribute("src")));
|
|
239
247
|
root
|
|
240
248
|
.querySelectorAll('meta[property="og:image"], meta[name="twitter:image"]')
|
|
241
|
-
.forEach((m) => checkRef(f, pageUrl, m.getAttribute("content")));
|
|
249
|
+
.forEach((m) => checkRef(f, pageUrl, resolveBase, m.getAttribute("content")));
|
|
242
250
|
|
|
243
251
|
root.querySelectorAll('script[type="application/ld+json"]').forEach((s, i) => {
|
|
244
252
|
let data;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piercebarney/whs-eleventy",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.24",
|
|
4
4
|
"description": "The web house style's Eleventy + Netlify tooling — the compliance sweep, the infra doctor, the link/CSP integrity check, and the a11y scan, shared by every project on the stack.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"whs": "cli.js"
|
package/standard/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,34 @@ enforced, new *opt-in* chapters/capabilities, tooling-only changes — is
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
+
## 2026-09-24 [non-breaking]
|
|
25
|
+
|
|
26
|
+
### packages/whs-eleventy
|
|
27
|
+
|
|
28
|
+
`check-links.js` resolved a relative reference (`favicon.svg`, `styles.css`,
|
|
29
|
+
etc.) against `pageUrl`, a literal `index.html`-stripped path — correct for
|
|
30
|
+
directory-style permalinks (`/foo/index.html` → `/foo/`) but wrong for a
|
|
31
|
+
flat, non-directory permalink like `privacy.html`, where `pageUrl` stayed
|
|
32
|
+
`/privacy.html` and `path.posix.join` then treated it as if it were a
|
|
33
|
+
directory, producing false `relative reference does not resolve` findings
|
|
34
|
+
for files that genuinely exist and resolve correctly in a real browser.
|
|
35
|
+
`pageUrl` is also used for same-page `#anchor` lookups, where the literal
|
|
36
|
+
value is exactly what's needed — so the fix doesn't touch `pageUrl` itself.
|
|
37
|
+
Instead `checkRef()` now takes a separate `resolveBase` (the directory
|
|
38
|
+
containing the page, via `path.posix.dirname`) used only for relative-
|
|
39
|
+
reference resolution, leaving anchor lookups untouched. Found while
|
|
40
|
+
covenant-in-color's adoption session ran the newly-fixed `npm run links` for
|
|
41
|
+
the first time and filed as
|
|
42
|
+
`feedback/2026-09-23-check-links-relative-resolution-non-directory-permalink.md`;
|
|
43
|
+
fixed in `7edbc68`.
|
|
44
|
+
|
|
45
|
+
This is the fourth `packages/whs-eleventy`-only fix shipped this week (the
|
|
46
|
+
third, 2026.9.23, already published and live) — `core.md`, `stacks/*.md`,
|
|
47
|
+
and `index.json` content are unchanged; only the doc pins and
|
|
48
|
+
`packages/whs-eleventy/package.json` (now `2026.9.24`) moved.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
24
52
|
## 2026-09-23 — Republish 2026-09-22-2 as a clean bare-date version [non-breaking]
|
|
25
53
|
|
|
26
54
|
### packages/whs-eleventy
|
package/standard/core.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web project house style — CORE (stack-agnostic)
|
|
2
2
|
|
|
3
|
-
**Version:** 2026-09-
|
|
3
|
+
**Version:** 2026-09-24 · **Status:** active
|
|
4
4
|
|
|
5
5
|
This is the stack-agnostic contract every web project follows, regardless of
|
|
6
6
|
framework, host, or CSS system. It says **what** must be true, with concrete
|
|
@@ -1467,7 +1467,7 @@ governs it and follow that chapter — the slugs are the index (a `<script>` →
|
|
|
1467
1467
|
- production-url: https://example.com
|
|
1468
1468
|
- content-type: tool # tool | article (article => feeds)
|
|
1469
1469
|
- publishing-rate: ~5 pages/week
|
|
1470
|
-
- standard-version: 2026-09-
|
|
1470
|
+
- standard-version: 2026-09-24 # recommended — enables standard-version drift tracking (#compliance)
|
|
1471
1471
|
```
|
|
1472
1472
|
|
|
1473
1473
|
If the section is absent, the assistant's first action is to run the flow above
|