Skip to content

Commit 4f5cbee

Browse files
Copilotfulldecent
andcommitted
Restore dirty file paths checker per @fulldecent feedback
Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com>
1 parent 61b45dc commit 4f5cbee

File tree

3 files changed

+166
-1
lines changed

3 files changed

+166
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"structured-data-testing-tool": "^4.5.0"
1515
},
1616
"scripts": {
17-
"test": "yarn node test/fixtures-html-validate-should-fail.mjs && yarn node test/fixtures-structured-data-should-fail.mjs && yarn node test/build-html-validate.mjs && yarn node test/build-structured-data-validate.mjs",
17+
"test": "yarn node test/fixtures-html-validate-should-fail.mjs && yarn node test/fixtures-structured-data-should-fail.mjs && yarn node test/build-html-validate.mjs && yarn node test/dirty-file-paths-checker.mjs && yarn node test/build-structured-data-validate.mjs",
1818
"test-structured-data": "yarn node test/build-structured-data-validate.mjs",
1919
"lint": "yarn prettier-check && yarn markdownlint-check",
2020
"lint-fix": "yarn prettier-fix && yarn markdownlint-fix",

test/dirty-file-paths-checker.mjs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import { glob } from "glob";
4+
5+
const CONFIG_FILE = path.join(process.cwd(), "test", "dirty-file-paths.json");
6+
const BUILD_DIR = path.join(process.cwd(), "build");
7+
8+
// Load and parse the configuration file
9+
function loadConfig() {
10+
try {
11+
const configContent = fs.readFileSync(CONFIG_FILE, "utf-8");
12+
return JSON.parse(configContent);
13+
} catch (error) {
14+
console.error("Error loading configuration:", error.message);
15+
process.exit(1);
16+
}
17+
}
18+
19+
// Find all files in the build directory
20+
function findTargetFiles() {
21+
return glob
22+
.sync("**/*", {
23+
cwd: BUILD_DIR,
24+
nocase: false, // Case sensitive as per requirements
25+
dot: false,
26+
})
27+
.filter((file) => {
28+
const fullPath = path.join(BUILD_DIR, file);
29+
return fs.lstatSync(fullPath).isFile();
30+
});
31+
}
32+
33+
// Convert relative file path to the format expected by rules (starting with /)
34+
function normalizePathForMatching(filePath) {
35+
// Convert backslashes to forward slashes and ensure it starts with /
36+
const normalized = filePath.replace(/\\/g, "/");
37+
return normalized.startsWith("/") ? normalized : "/" + normalized;
38+
}
39+
40+
// Check a single file's path against the dirty path rules
41+
function checkFile(filePath, config) {
42+
const normalizedPath = normalizePathForMatching(filePath);
43+
44+
// Process rules in order, later rules take precedence
45+
let finalRule = null;
46+
47+
for (const rule of config) {
48+
try {
49+
const regex = new RegExp(rule.path);
50+
if (regex.test(normalizedPath)) {
51+
finalRule = rule;
52+
}
53+
} catch (error) {
54+
console.error(`Invalid regex pattern in rule: ${rule.path}`, error.message);
55+
process.exit(1);
56+
}
57+
}
58+
59+
// Return violation only if the final matching rule is dirty
60+
if (finalRule && finalRule.dirty) {
61+
return { path: normalizedPath, advice: finalRule.advice };
62+
}
63+
64+
return null;
65+
}
66+
67+
console.log("🧪 Testing files for dirty file paths");
68+
69+
const config = loadConfig();
70+
const files = findTargetFiles();
71+
let hasErrors = false;
72+
const violationsByPath = new Map();
73+
74+
// Collect violations
75+
files.forEach((file) => {
76+
const violation = checkFile(file, config);
77+
if (violation) {
78+
hasErrors = true;
79+
console.log(`❌ ${file}: ${violation.advice}`);
80+
violationsByPath.set(violation.path, violation.advice);
81+
}
82+
});
83+
84+
// Summary of clean files
85+
const cleanFiles = files.filter((file) => !checkFile(file, config));
86+
console.log(`✅ Site includes ${cleanFiles.length} clean files`);
87+
88+
// Summary of dirty paths
89+
if (hasErrors) {
90+
console.log("Following are dirty file paths:");
91+
violationsByPath.forEach((advice, path) => {
92+
console.log(`${path} ${advice}`);
93+
});
94+
console.error("\n❌ Dirty paths check failed");
95+
process.exit(1);
96+
} else {
97+
console.log("✨ All files passed dirty paths check!\n");
98+
}

test/dirty-file-paths.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
[
2+
{
3+
"path": "/.*\\.png$",
4+
"dirty": true,
5+
"advice": "Only use WebP for bitmap images https://web.dev/articles/choose-the-right-image-format"
6+
},
7+
{
8+
"path": "/.*\\.jpg$",
9+
"dirty": true,
10+
"advice": "Only use WebP for bitmap images https://web.dev/articles/choose-the-right-image-format"
11+
},
12+
{
13+
"path": "/.*\\.jpeg$",
14+
"dirty": true,
15+
"advice": "Only use WebP for bitmap images https://web.dev/articles/choose-the-right-image-format"
16+
},
17+
{
18+
"path": "/.*\\.gif$",
19+
"dirty": true,
20+
"advice": "Only use WebP for bitmap images https://web.dev/articles/choose-the-right-image-format"
21+
},
22+
{
23+
"path": "/.*\\.woff$",
24+
"dirty": true,
25+
"advice": "Only use WOFF2 for fonts https://web.dev/learn/performance/optimize-web-fonts"
26+
},
27+
{
28+
"path": "/.*\\.eot$",
29+
"dirty": true,
30+
"advice": "Only use WOFF2 for fonts https://web.dev/learn/performance/optimize-web-fonts"
31+
},
32+
{
33+
"path": "/.*\\.ttf$",
34+
"dirty": true,
35+
"advice": "Only use WOFF2 for fonts https://web.dev/learn/performance/optimize-web-fonts"
36+
},
37+
{
38+
"path": "/.*\\.htm$",
39+
"dirty": true,
40+
"advice": "Prefer to use .html file extension"
41+
},
42+
{
43+
"path": "/.*\\.ogv$",
44+
"dirty": true,
45+
"advice": "Only use .webm for video files"
46+
},
47+
{
48+
"path": "/.*\\.mp4$",
49+
"dirty": true,
50+
"advice": "Only use .webm for video files"
51+
},
52+
{
53+
"path": "/.*\\.mp3$",
54+
"dirty": true,
55+
"advice": "Only use .webm for video files"
56+
},
57+
{
58+
"path": "/[^/]*/[^.]*\\.ico$",
59+
"dirty": true,
60+
"advice": "ICO files are not recommended for modern web development"
61+
},
62+
{
63+
"path": "/favicon\\.ico$",
64+
"dirty": false,
65+
"advice": "Favicon.ico is allowed for browser compatibility"
66+
}
67+
]

0 commit comments

Comments
 (0)