Root-relative stylesheet hrefs resolve against the project, not the drive root

Bugbot on #599: path.resolve treated /assets/hero.css as filesystem-absolute. Both the working directory and the artifact's directory are tried; unreadable candidates skip.

AI-assisted (Claude Code).
This commit is contained in:
Paul Bakaus
2026-08-28 15:32:22 -07:00
parent 64001fe213
commit 0d2df39339
2 changed files with 9 additions and 1 deletions
+6 -1
View File
@@ -355,7 +355,12 @@ export function unreferencedPlates(spec, artifact = null) {
const href = m[1];
if (/^(https?:|data:|\/\/)/i.test(href)) continue;
if (!/rel=["']?stylesheet/i.test(m[0]) && !/\.css(\?|$)/i.test(href)) continue;
linked.push(path.resolve(path.dirname(artifact), href.split('?')[0]));
const clean = href.split('?')[0];
// a root-relative href serves from the project root, not the drive
// root: try the working directory and the artifact's own directory
// (unreadable candidates are skipped by the corpus loop)
if (clean.startsWith('/')) { linked.push(path.join(process.cwd(), clean), path.join(path.dirname(artifact), clean)); }
else linked.push(path.resolve(path.dirname(artifact), clean));
}
} catch { /* the artifact still counts */ }
}
+3
View File
@@ -485,6 +485,9 @@ describe('unreferencedPlates', () => {
fs.writeFileSync(path.join(d, 'index.html'), `<link rel="stylesheet" href="a/b/c/e/f/g/h/styles/deep.css"><main class="hero"></main>`);
fs.writeFileSync(path.join(d, 'assets', 'hero.css'), '.hero { background: red; }');
assert.deepEqual(unreferencedPlates(spec, path.join(d, 'index.html')), [], 'a stylesheet linked by the artifact counts wherever it lives');
// a root-relative href resolves against the project, not the drive root
fs.writeFileSync(path.join(d, 'index.html'), `<link rel="stylesheet" href="/a/b/c/e/f/g/h/styles/deep.css"><main class="hero"></main>`);
assert.deepEqual(unreferencedPlates(spec, path.join(d, 'index.html')), [], 'a root-relative stylesheet href counts');
fs.writeFileSync(path.join(deep, 'deep.css'), '.hero { background: red; }');
assert.equal(unreferencedPlates(spec, null).length, 1, 'an unreferenced plate is still named');
assert.equal(unreferencedPlates(spec, path.join(d, 'index.html')).length, 1, 'and with the artifact set too');