From 23c616bbfba4c99a92b2321356a85e151de55b22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 Aug 2025 01:16:37 +0000 Subject: [PATCH 01/10] Initial plan From b69818df963cfde6ee843281c75633341a587ffb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 Aug 2025 01:27:29 +0000 Subject: [PATCH 02/10] Create unused assets checker script with basic functionality Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com> --- package.json | 2 +- source/assets/css/style.css | 8 ++ source/assets/images/test.png | 1 + source/assets/js/main.js | 6 ++ source/assets/js/unused.js | 4 + source/index.html | 6 +- test/find-unused-assets.mjs | 172 ++++++++++++++++++++++++++++++ test/unused-assets-allowlist.json | 6 ++ 8 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 source/assets/css/style.css create mode 100644 source/assets/images/test.png create mode 100644 source/assets/js/main.js create mode 100644 source/assets/js/unused.js create mode 100644 test/find-unused-assets.mjs create mode 100644 test/unused-assets-allowlist.json diff --git a/package.json b/package.json index 383bac2..8b377e2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "shell-quote": "^1.8.3" }, "scripts": { - "test": "node test/fixtures-html-validate-should-fail.mjs && node test/build-html-validate.mjs && node test/dirty-words-checker.mjs && node test/dirty-file-paths-checker.mjs", + "test": "node test/fixtures-html-validate-should-fail.mjs && node test/build-html-validate.mjs && node test/dirty-words-checker.mjs && node test/dirty-file-paths-checker.mjs && node test/find-unused-assets.mjs", "lint": "yarn prettier-check && yarn markdownlint-check", "lint-fix": "yarn prettier-fix && yarn markdownlint-fix", "generate-sitemap": "node scripts/generate-sitemap.mjs", diff --git a/source/assets/css/style.css b/source/assets/css/style.css new file mode 100644 index 0000000..9954465 --- /dev/null +++ b/source/assets/css/style.css @@ -0,0 +1,8 @@ +/* Test CSS file */ +body { + font-family: Arial, sans-serif; +} + +.test-class { + color: red; +} \ No newline at end of file diff --git a/source/assets/images/test.png b/source/assets/images/test.png new file mode 100644 index 0000000..4e8d202 --- /dev/null +++ b/source/assets/images/test.png @@ -0,0 +1 @@ +fake PNG file for testing \ No newline at end of file diff --git a/source/assets/js/main.js b/source/assets/js/main.js new file mode 100644 index 0000000..9220823 --- /dev/null +++ b/source/assets/js/main.js @@ -0,0 +1,6 @@ +// Test JavaScript file +console.log('Hello world'); + +function testFunction() { + return 'test'; +} \ No newline at end of file diff --git a/source/assets/js/unused.js b/source/assets/js/unused.js new file mode 100644 index 0000000..6a67a41 --- /dev/null +++ b/source/assets/js/unused.js @@ -0,0 +1,4 @@ +// This JS file should be reported as unused +function unusedFunction() { + return 'unused'; +} \ No newline at end of file diff --git a/source/index.html b/source/index.html index ebf950d..647ebd7 100644 --- a/source/index.html +++ b/source/index.html @@ -7,6 +7,8 @@
This page tests various asset references.
+ + External link +
+
+
+ Internal anchor
+
+
+ Home
+
+
+ Test page
+
+
\ No newline at end of file
diff --git a/test/README-unused-assets.md b/test/README-unused-assets.md
new file mode 100644
index 0000000..f80e22d
--- /dev/null
+++ b/test/README-unused-assets.md
@@ -0,0 +1,72 @@
+# Unused Assets Checker
+
+The `find-unused-assets.mjs` script checks for asset files that are not referenced from any HTML file in the build directory.
+
+## What it checks
+
+The script scans for the following asset types:
+- CSS files (`.css`)
+- JavaScript files (`.js`)
+- Images (`.jpg`, `.jpeg`, `.png`, `.gif`, `.svg`, `.webp`)
+- Fonts (`.woff`, `.woff2`, `.ttf`, `.otf`, `.eot`)
+- Icons (`.ico`)
+- Media files (`.mp4`, `.webm`, `.mp3`, `.wav`, `.ogg`)
+- Documents (`.pdf`)
+- Archives (`.zip`, `.tar`, `.gz`)
+
+## How it works
+
+1. **Finds all asset files** in the `build/` directory
+2. **Scans HTML files** for references to assets via:
+ - `src` attributes (images, scripts, etc.)
+ - `href` attributes (stylesheets, links, etc.)
+ - CSS `url()` references (both inline and in external CSS files)
+3. **Resolves relative paths** correctly based on the HTML file's location
+4. **Ignores external links** (http/https URLs) and data URLs
+5. **Handles extensionless URLs** that might map to `.html` files
+6. **Reports unused assets** that have no references
+
+## Configuration
+
+You can create an allowlist for files that should be ignored even if not directly referenced:
+
+**File:** `test/unused-assets-allowlist.json`
+
+```json
+[
+ "assets/js/analytics\\.js",
+ "assets/images/social-.*",
+ "^robots\\.txt$",
+ "^\\.well-known/.*"
+]
+```
+
+Each entry is a regular expression pattern that will be tested against the asset file path.
+
+## Usage
+
+```bash
+# Run the checker
+yarn node test/find-unused-assets.mjs
+
+# Or as part of the test suite
+yarn test
+```
+
+## Exit codes
+
+- `0`: No unused assets found
+- `1`: Unused assets found or error occurred
+
+## Example output
+
+```
+๐งช Checking for unused asset files
+๐ Found 6 asset files and 4 HTML files
+
+โ Found unused asset files:
+ assets/js/unused-analytics.js
+ assets/images/old-logo.png
+
+โ Found 2 unused asset files
+```
\ No newline at end of file
diff --git a/test/find-unused-assets.mjs b/test/find-unused-assets.mjs
index 884d694..12c4e85 100644
--- a/test/find-unused-assets.mjs
+++ b/test/find-unused-assets.mjs
@@ -36,7 +36,7 @@ function findHtmlFiles() {
.filter((file) => fs.lstatSync(path.join(BUILD_DIR, file)).isFile());
}
-// Extract all asset references from HTML files
+// Extract all asset references from HTML and CSS files
function extractAssetReferences(htmlFiles) {
const references = new Set();
@@ -61,15 +61,59 @@ function extractAssetReferences(htmlFiles) {
if (!path.extname(resolvedPath)) {
references.add(resolvedPath + ".html");
}
+
+ // If this is a CSS file, parse it for url() references
+ if (resolvedPath.endsWith('.css')) {
+ parseCssFile(resolvedPath, references);
+ }
}
}
});
});
+
+ // Also scan the entire HTML content for CSS url() references
+ const urlMatches = content.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/gi) || [];
+ urlMatches.forEach(match => {
+ const urlMatch = match.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/i);
+ if (urlMatch && urlMatch[1]) {
+ const url = urlMatch[1];
+ if (!isExternalUrl(url) && !isDataUrl(url)) {
+ const resolvedPath = resolveRelativeUrl(url, htmlDir);
+ if (resolvedPath) {
+ references.add(resolvedPath);
+ }
+ }
+ }
+ });
});
return references;
}
+// Parse CSS file for url() references
+function parseCssFile(cssFilePath, references) {
+ try {
+ const cssContent = fs.readFileSync(path.join(BUILD_DIR, cssFilePath), "utf-8");
+ const cssDir = path.dirname(cssFilePath);
+
+ const urlMatches = cssContent.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/gi) || [];
+ urlMatches.forEach(match => {
+ const urlMatch = match.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/i);
+ if (urlMatch && urlMatch[1]) {
+ const url = urlMatch[1];
+ if (!isExternalUrl(url) && !isDataUrl(url)) {
+ const resolvedPath = resolveRelativeUrl(url, cssDir);
+ if (resolvedPath) {
+ references.add(resolvedPath);
+ }
+ }
+ }
+ });
+ } catch (error) {
+ console.warn(`Warning: Could not parse CSS file ${cssFilePath}:`, error.message);
+ }
+}
+
// Check if URL is external (starts with http/https or //)
function isExternalUrl(url) {
return /^(https?:)?\/\//.test(url);
From 520f43b7e555897063cd8ab37f4ef6c42e8cb728 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 01:33:13 +0000
Subject: [PATCH 04/10] Add unused assets checker for build directory
Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com>
---
source/assets/js/unused.js | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/source/assets/js/unused.js b/source/assets/js/unused.js
index 6a67a41..acbc962 100644
--- a/source/assets/js/unused.js
+++ b/source/assets/js/unused.js
@@ -1,4 +1 @@
-// This JS file should be reported as unused
-function unusedFunction() {
- return 'unused';
-}
\ No newline at end of file
+fake
From a6306396a16b0360d421a1a984ccc4f909130a0e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 02:18:44 +0000
Subject: [PATCH 05/10] Make unused assets checker work with arbitrary
directories and add comprehensive tests
Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com>
---
package.json | 2 +-
test/find-unused-assets.mjs | 46 +++++++---
.../unused-assets/clean/assets/css/style.css | 4 +
.../clean/assets/images/icon.png | 1 +
.../unused-assets/clean/assets/js/app.js | 1 +
test/fixtures/unused-assets/clean/index.html | 14 +++
.../with-unused/assets/css/main.css | 8 ++
.../with-unused/assets/images/background.jpg | 1 +
.../with-unused/assets/images/logo.png | 1 +
.../with-unused/assets/images/unused.png | 1 +
.../with-unused/assets/js/main.js | 1 +
.../with-unused/assets/js/really-unused.js | 2 +
.../with-unused/assets/js/unused.js | 2 +
.../unused-assets/with-unused/index.html | 14 +++
test/test-unused-assets-fixtures.mjs | 85 +++++++++++++++++++
15 files changed, 171 insertions(+), 12 deletions(-)
create mode 100644 test/fixtures/unused-assets/clean/assets/css/style.css
create mode 100644 test/fixtures/unused-assets/clean/assets/images/icon.png
create mode 100644 test/fixtures/unused-assets/clean/assets/js/app.js
create mode 100644 test/fixtures/unused-assets/clean/index.html
create mode 100644 test/fixtures/unused-assets/with-unused/assets/css/main.css
create mode 100644 test/fixtures/unused-assets/with-unused/assets/images/background.jpg
create mode 100644 test/fixtures/unused-assets/with-unused/assets/images/logo.png
create mode 100644 test/fixtures/unused-assets/with-unused/assets/images/unused.png
create mode 100644 test/fixtures/unused-assets/with-unused/assets/js/main.js
create mode 100644 test/fixtures/unused-assets/with-unused/assets/js/really-unused.js
create mode 100644 test/fixtures/unused-assets/with-unused/assets/js/unused.js
create mode 100644 test/fixtures/unused-assets/with-unused/index.html
create mode 100644 test/test-unused-assets-fixtures.mjs
diff --git a/package.json b/package.json
index 8b377e2..7a85771 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
"shell-quote": "^1.8.3"
},
"scripts": {
- "test": "node test/fixtures-html-validate-should-fail.mjs && node test/build-html-validate.mjs && node test/dirty-words-checker.mjs && node test/dirty-file-paths-checker.mjs && node test/find-unused-assets.mjs",
+ "test": "node test/fixtures-html-validate-should-fail.mjs && node test/build-html-validate.mjs && node test/dirty-words-checker.mjs && node test/dirty-file-paths-checker.mjs && node test/test-unused-assets-fixtures.mjs && node test/find-unused-assets.mjs",
"lint": "yarn prettier-check && yarn markdownlint-check",
"lint-fix": "yarn prettier-fix && yarn markdownlint-fix",
"generate-sitemap": "node scripts/generate-sitemap.mjs",
diff --git a/test/find-unused-assets.mjs b/test/find-unused-assets.mjs
index 12c4e85..2bf58c1 100644
--- a/test/find-unused-assets.mjs
+++ b/test/find-unused-assets.mjs
@@ -4,7 +4,24 @@ import path from "path";
import { glob } from "glob";
import { load } from "cheerio";
-const BUILD_DIR = path.join(process.cwd(), "build");
+// Get target directory from command line argument or default to "build"
+const TARGET_DIR = process.argv[2] ? path.resolve(process.argv[2]) : path.join(process.cwd(), "build");
+
+// Show usage if help is requested
+if (process.argv[2] === '--help' || process.argv[2] === '-h') {
+ console.log('Usage: node find-unused-assets.mjs [directory]');
+ console.log('');
+ console.log('Finds asset files that are not referenced from any HTML file in the target directory.');
+ console.log('');
+ console.log('Arguments:');
+ console.log(' directory Directory to scan (default: "./build")');
+ console.log('');
+ console.log('Examples:');
+ console.log(' node find-unused-assets.mjs # Scan ./build directory');
+ console.log(' node find-unused-assets.mjs /path/to/site # Scan custom directory');
+ console.log(' node find-unused-assets.mjs test/fixtures/clean # Scan test fixtures');
+ process.exit(0);
+}
// Asset file extensions to check
const ASSET_EXTENSIONS = [
@@ -13,27 +30,27 @@ const ASSET_EXTENSIONS = [
"mp3", "wav", "ogg", "pdf", "zip", "tar", "gz"
];
-// Find all asset files in the build directory
+// Find all asset files in the target directory
function findAssetFiles() {
const extensions = ASSET_EXTENSIONS.map(ext => `**/*.${ext}`);
return glob
.sync(extensions, {
- cwd: BUILD_DIR,
+ cwd: TARGET_DIR,
nocase: true,
dot: false,
})
- .filter((file) => fs.lstatSync(path.join(BUILD_DIR, file)).isFile());
+ .filter((file) => fs.lstatSync(path.join(TARGET_DIR, file)).isFile());
}
-// Find all HTML files in the build directory
+// Find all HTML files in the target directory
function findHtmlFiles() {
return glob
.sync("**/*.html", {
- cwd: BUILD_DIR,
+ cwd: TARGET_DIR,
nocase: true,
dot: false,
})
- .filter((file) => fs.lstatSync(path.join(BUILD_DIR, file)).isFile());
+ .filter((file) => fs.lstatSync(path.join(TARGET_DIR, file)).isFile());
}
// Extract all asset references from HTML and CSS files
@@ -41,7 +58,7 @@ function extractAssetReferences(htmlFiles) {
const references = new Set();
htmlFiles.forEach((htmlFile) => {
- const content = fs.readFileSync(path.join(BUILD_DIR, htmlFile), "utf-8");
+ const content = fs.readFileSync(path.join(TARGET_DIR, htmlFile), "utf-8");
const $ = load(content);
const htmlDir = path.dirname(htmlFile);
@@ -93,7 +110,7 @@ function extractAssetReferences(htmlFiles) {
// Parse CSS file for url() references
function parseCssFile(cssFilePath, references) {
try {
- const cssContent = fs.readFileSync(path.join(BUILD_DIR, cssFilePath), "utf-8");
+ const cssContent = fs.readFileSync(path.join(TARGET_DIR, cssFilePath), "utf-8");
const cssDir = path.dirname(cssFilePath);
const urlMatches = cssContent.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/gi) || [];
@@ -175,17 +192,24 @@ function shouldIgnoreFile(filePath, config) {
// Main execution
console.log("๐งช Checking for unused asset files");
+console.log(`๐ Scanning directory: ${TARGET_DIR}`);
+
+// Verify target directory exists
+if (!fs.existsSync(TARGET_DIR)) {
+ console.error(`โ Target directory does not exist: ${TARGET_DIR}`);
+ process.exit(1);
+}
const assetFiles = findAssetFiles();
const htmlFiles = findHtmlFiles();
if (assetFiles.length === 0) {
- console.log("โจ No asset files found in build directory");
+ console.log("โจ No asset files found in target directory");
process.exit(0);
}
if (htmlFiles.length === 0) {
- console.log("โ No HTML files found in build directory");
+ console.log("โ No HTML files found in target directory");
process.exit(1);
}
diff --git a/test/fixtures/unused-assets/clean/assets/css/style.css b/test/fixtures/unused-assets/clean/assets/css/style.css
new file mode 100644
index 0000000..1d46b3c
--- /dev/null
+++ b/test/fixtures/unused-assets/clean/assets/css/style.css
@@ -0,0 +1,4 @@
+body {
+ margin: 0;
+ padding: 20px;
+}
\ No newline at end of file
diff --git a/test/fixtures/unused-assets/clean/assets/images/icon.png b/test/fixtures/unused-assets/clean/assets/images/icon.png
new file mode 100644
index 0000000..b56fb6d
--- /dev/null
+++ b/test/fixtures/unused-assets/clean/assets/images/icon.png
@@ -0,0 +1 @@
+clean icon
diff --git a/test/fixtures/unused-assets/clean/assets/js/app.js b/test/fixtures/unused-assets/clean/assets/js/app.js
new file mode 100644
index 0000000..61f5319
--- /dev/null
+++ b/test/fixtures/unused-assets/clean/assets/js/app.js
@@ -0,0 +1 @@
+console.log('App loaded');
\ No newline at end of file
diff --git a/test/fixtures/unused-assets/clean/index.html b/test/fixtures/unused-assets/clean/index.html
new file mode 100644
index 0000000..797f4b3
--- /dev/null
+++ b/test/fixtures/unused-assets/clean/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/test-unused-assets-fixtures.mjs b/test/test-unused-assets-fixtures.mjs
new file mode 100644
index 0000000..4cd905a
--- /dev/null
+++ b/test/test-unused-assets-fixtures.mjs
@@ -0,0 +1,85 @@
+// test-unused-assets-fixtures.mjs
+import { execSync } from 'child_process';
+import path from 'path';
+
+const testFixtures = [
+ {
+ name: 'clean fixture (no unused assets)',
+ path: 'test/fixtures/unused-assets/clean',
+ expectedExitCode: 0,
+ shouldContain: ['โจ No unused asset files found!']
+ },
+ {
+ name: 'with-unused fixture (has unused assets)',
+ path: 'test/fixtures/unused-assets/with-unused',
+ expectedExitCode: 1,
+ shouldContain: ['Found 2 unused asset files', 'assets/js/really-unused.js', 'assets/images/unused.png']
+ }
+];
+
+console.log('๐งช Testing unused assets checker against fixtures');
+
+let allTestsPassed = true;
+
+for (const test of testFixtures) {
+ console.log(`\n๐ Testing: ${test.name}`);
+
+ try {
+ const output = execSync(`yarn node test/find-unused-assets.mjs ${test.path}`, {
+ encoding: 'utf8',
+ stdio: 'pipe'
+ });
+
+ if (test.expectedExitCode !== 0) {
+ console.log(`โ Expected exit code ${test.expectedExitCode}, got 0`);
+ allTestsPassed = false;
+ continue;
+ }
+
+ // Check expected content
+ for (const expected of test.shouldContain) {
+ if (!output.includes(expected)) {
+ console.log(`โ Output missing expected text: "${expected}"`);
+ console.log(` Actual output: ${output}`);
+ allTestsPassed = false;
+ }
+ }
+
+ if (allTestsPassed) {
+ console.log(`โ
Test passed`);
+ }
+
+ } catch (error) {
+ // For tests expecting non-zero exit codes, this is normal
+ if (test.expectedExitCode !== 0 && error.status === test.expectedExitCode) {
+ const output = error.stdout + error.stderr;
+
+ // Check expected content
+ let testPassed = true;
+ for (const expected of test.shouldContain) {
+ if (!output.includes(expected)) {
+ console.log(`โ Output missing expected text: "${expected}"`);
+ console.log(` Actual output: ${output}`);
+ testPassed = false;
+ allTestsPassed = false;
+ }
+ }
+
+ if (testPassed) {
+ console.log(`โ
Test passed (expected exit code ${test.expectedExitCode})`);
+ }
+ } else {
+ console.log(`โ Unexpected error: ${error.message}`);
+ console.log(` Status: ${error.status}, Expected: ${test.expectedExitCode}`);
+ allTestsPassed = false;
+ }
+ }
+}
+
+if (allTestsPassed) {
+ console.log('\nโจ All fixture tests passed!');
+ process.exit(0);
+} else {
+ console.log('\nโ Some fixture tests failed!');
+ process.exit(1);
+}
\ No newline at end of file
From 1a90efd36348c4ebe4d0ba5331d91ce9c468936c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 02:30:05 +0000
Subject: [PATCH 06/10] Remove source directory changes to keep PR focused on
testing infrastructure only
Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com>
---
source/assets/css/style.css | 13 -------------
source/assets/fonts/test.woff2 | 1 -
source/assets/fonts/unused.ttf | 1 -
source/assets/images/test.png | 1 -
source/assets/js/main.js | 6 ------
source/assets/js/unused.js | 1 -
source/favicon.ico | 1 -
source/index.html | 6 ++----
source/test-page.html | 35 ----------------------------------
9 files changed, 2 insertions(+), 63 deletions(-)
delete mode 100644 source/assets/css/style.css
delete mode 100644 source/assets/fonts/test.woff2
delete mode 100644 source/assets/fonts/unused.ttf
delete mode 100644 source/assets/images/test.png
delete mode 100644 source/assets/js/main.js
delete mode 100644 source/assets/js/unused.js
delete mode 100644 source/favicon.ico
delete mode 100644 source/test-page.html
diff --git a/source/assets/css/style.css b/source/assets/css/style.css
deleted file mode 100644
index ec63c4d..0000000
--- a/source/assets/css/style.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Test CSS file */
-body {
- font-family: Arial, sans-serif;
-}
-
-.test-class {
- color: red;
-}
-
-@font-face {
- font-family: 'UnusedFont';
- src: url('../fonts/unused.ttf') format('truetype');
-}
\ No newline at end of file
diff --git a/source/assets/fonts/test.woff2 b/source/assets/fonts/test.woff2
deleted file mode 100644
index 2f4309c..0000000
--- a/source/assets/fonts/test.woff2
+++ /dev/null
@@ -1 +0,0 @@
-fake font file
\ No newline at end of file
diff --git a/source/assets/fonts/unused.ttf b/source/assets/fonts/unused.ttf
deleted file mode 100644
index da6a57c..0000000
--- a/source/assets/fonts/unused.ttf
+++ /dev/null
@@ -1 +0,0 @@
-fake unused font
\ No newline at end of file
diff --git a/source/assets/images/test.png b/source/assets/images/test.png
deleted file mode 100644
index 4e8d202..0000000
--- a/source/assets/images/test.png
+++ /dev/null
@@ -1 +0,0 @@
-fake PNG file for testing
\ No newline at end of file
diff --git a/source/assets/js/main.js b/source/assets/js/main.js
deleted file mode 100644
index 9220823..0000000
--- a/source/assets/js/main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// Test JavaScript file
-console.log('Hello world');
-
-function testFunction() {
- return 'test';
-}
\ No newline at end of file
diff --git a/source/assets/js/unused.js b/source/assets/js/unused.js
deleted file mode 100644
index acbc962..0000000
--- a/source/assets/js/unused.js
+++ /dev/null
@@ -1 +0,0 @@
-fake
diff --git a/source/favicon.ico b/source/favicon.ico
deleted file mode 100644
index 2fff4dc..0000000
--- a/source/favicon.ico
+++ /dev/null
@@ -1 +0,0 @@
-fake favicon
\ No newline at end of file
diff --git a/source/index.html b/source/index.html
index 647ebd7..ebf950d 100644
--- a/source/index.html
+++ b/source/index.html
@@ -7,8 +7,6 @@
diff --git a/source/test-page.html b/source/test-page.html
deleted file mode 100644
index 9837114..0000000
--- a/source/test-page.html
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: Test Page
----
-
-
-
-
-
- This page tests various asset references.
- - External link -
-
-
- Internal anchor
-
-
- Home
-
-
- Test page
-
-
\ No newline at end of file
From c6ba22d199590ad7ee14583f7ecd61b86b7d1f25 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 03:00:18 +0000
Subject: [PATCH 07/10] Fix linting errors: Prettier formatting and markdown
language specification
Co-authored-by: fulldecent <382183+fulldecent@users.noreply.github.com>
---
test/README-unused-assets.md | 4 +-
test/find-unused-assets.mjs | 80 ++++++++++++-------
.../unused-assets/clean/assets/css/style.css | 6 +-
.../unused-assets/clean/assets/js/app.js | 2 +-
test/fixtures/unused-assets/clean/index.html | 12 +--
.../with-unused/assets/css/main.css | 8 +-
.../with-unused/assets/js/main.js | 2 +-
.../with-unused/assets/js/really-unused.js | 2 +-
.../with-unused/assets/js/unused.js | 2 +-
.../unused-assets/with-unused/index.html | 12 +--
test/test-unused-assets-fixtures.mjs | 45 +++++------
test/unused-assets-allowlist.json | 7 +-
12 files changed, 98 insertions(+), 84 deletions(-)
diff --git a/test/README-unused-assets.md b/test/README-unused-assets.md
index f80e22d..a4c8b0e 100644
--- a/test/README-unused-assets.md
+++ b/test/README-unused-assets.md
@@ -60,7 +60,7 @@ yarn test
## Example output
-```
+```text
๐งช Checking for unused asset files
๐ Found 6 asset files and 4 HTML files
@@ -69,4 +69,4 @@ yarn test
assets/images/old-logo.png
โ Found 2 unused asset files
-```
\ No newline at end of file
+```
diff --git a/test/find-unused-assets.mjs b/test/find-unused-assets.mjs
index 2bf58c1..e542844 100644
--- a/test/find-unused-assets.mjs
+++ b/test/find-unused-assets.mjs
@@ -8,31 +8,51 @@ import { load } from "cheerio";
const TARGET_DIR = process.argv[2] ? path.resolve(process.argv[2]) : path.join(process.cwd(), "build");
// Show usage if help is requested
-if (process.argv[2] === '--help' || process.argv[2] === '-h') {
- console.log('Usage: node find-unused-assets.mjs [directory]');
- console.log('');
- console.log('Finds asset files that are not referenced from any HTML file in the target directory.');
- console.log('');
- console.log('Arguments:');
+if (process.argv[2] === "--help" || process.argv[2] === "-h") {
+ console.log("Usage: node find-unused-assets.mjs [directory]");
+ console.log("");
+ console.log("Finds asset files that are not referenced from any HTML file in the target directory.");
+ console.log("");
+ console.log("Arguments:");
console.log(' directory Directory to scan (default: "./build")');
- console.log('');
- console.log('Examples:');
- console.log(' node find-unused-assets.mjs # Scan ./build directory');
- console.log(' node find-unused-assets.mjs /path/to/site # Scan custom directory');
- console.log(' node find-unused-assets.mjs test/fixtures/clean # Scan test fixtures');
+ console.log("");
+ console.log("Examples:");
+ console.log(" node find-unused-assets.mjs # Scan ./build directory");
+ console.log(" node find-unused-assets.mjs /path/to/site # Scan custom directory");
+ console.log(" node find-unused-assets.mjs test/fixtures/clean # Scan test fixtures");
process.exit(0);
}
// Asset file extensions to check
const ASSET_EXTENSIONS = [
- "css", "js", "jpg", "jpeg", "png", "gif", "svg", "webp",
- "woff", "woff2", "ttf", "otf", "eot", "ico", "mp4", "webm",
- "mp3", "wav", "ogg", "pdf", "zip", "tar", "gz"
+ "css",
+ "js",
+ "jpg",
+ "jpeg",
+ "png",
+ "gif",
+ "svg",
+ "webp",
+ "woff",
+ "woff2",
+ "ttf",
+ "otf",
+ "eot",
+ "ico",
+ "mp4",
+ "webm",
+ "mp3",
+ "wav",
+ "ogg",
+ "pdf",
+ "zip",
+ "tar",
+ "gz",
];
// Find all asset files in the target directory
function findAssetFiles() {
- const extensions = ASSET_EXTENSIONS.map(ext => `**/*.${ext}`);
+ const extensions = ASSET_EXTENSIONS.map((ext) => `**/*.${ext}`);
return glob
.sync(extensions, {
cwd: TARGET_DIR,
@@ -67,30 +87,30 @@ function extractAssetReferences(htmlFiles) {
const $el = $(element);
const src = $el.attr("src");
const href = $el.attr("href");
-
- [src, href].forEach(url => {
+
+ [src, href].forEach((url) => {
if (url && !isExternalUrl(url) && !isDataUrl(url)) {
const resolvedPath = resolveRelativeUrl(url, htmlDir);
if (resolvedPath) {
references.add(resolvedPath);
-
+
// If the URL is extensionless, also check for .html version
if (!path.extname(resolvedPath)) {
references.add(resolvedPath + ".html");
}
-
+
// If this is a CSS file, parse it for url() references
- if (resolvedPath.endsWith('.css')) {
+ if (resolvedPath.endsWith(".css")) {
parseCssFile(resolvedPath, references);
}
}
}
});
});
-
+
// Also scan the entire HTML content for CSS url() references
const urlMatches = content.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/gi) || [];
- urlMatches.forEach(match => {
+ urlMatches.forEach((match) => {
const urlMatch = match.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/i);
if (urlMatch && urlMatch[1]) {
const url = urlMatch[1];
@@ -112,9 +132,9 @@ function parseCssFile(cssFilePath, references) {
try {
const cssContent = fs.readFileSync(path.join(TARGET_DIR, cssFilePath), "utf-8");
const cssDir = path.dirname(cssFilePath);
-
+
const urlMatches = cssContent.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/gi) || [];
- urlMatches.forEach(match => {
+ urlMatches.forEach((match) => {
const urlMatch = match.match(/url\s*\(\s*['"]?([^'")]+)['"]?\s*\)/i);
if (urlMatch && urlMatch[1]) {
const url = urlMatch[1];
@@ -146,7 +166,7 @@ function resolveRelativeUrl(url, htmlDir) {
try {
// Remove query string and fragment
const cleanUrl = url.split("?")[0].split("#")[0];
-
+
let resolvedPath;
if (cleanUrl.startsWith("/")) {
// Absolute path relative to site root
@@ -155,7 +175,7 @@ function resolveRelativeUrl(url, htmlDir) {
// Relative path
resolvedPath = path.join(htmlDir, cleanUrl);
}
-
+
// Normalize the path (resolve .. and . segments)
return path.normalize(resolvedPath);
} catch (error) {
@@ -179,7 +199,7 @@ function loadConfig() {
// Check if a file should be ignored based on configuration
function shouldIgnoreFile(filePath, config) {
- return config.some(pattern => {
+ return config.some((pattern) => {
try {
const regex = new RegExp(pattern);
return regex.test(filePath);
@@ -221,7 +241,7 @@ const unusedAssets = [];
assetFiles.forEach((assetFile) => {
const normalizedPath = path.normalize(assetFile);
-
+
if (!referencedAssets.has(normalizedPath) && !shouldIgnoreFile(normalizedPath, config)) {
unusedAssets.push(normalizedPath);
}
@@ -232,9 +252,9 @@ if (unusedAssets.length > 0) {
unusedAssets.forEach((asset) => {
console.log(` ${asset}`);
});
-
+
console.error(`\nโ Found ${unusedAssets.length} unused asset files`);
process.exit(1);
} else {
console.log("\nโจ No unused asset files found!");
-}
\ No newline at end of file
+}
diff --git a/test/fixtures/unused-assets/clean/assets/css/style.css b/test/fixtures/unused-assets/clean/assets/css/style.css
index 1d46b3c..b8a8404 100644
--- a/test/fixtures/unused-assets/clean/assets/css/style.css
+++ b/test/fixtures/unused-assets/clean/assets/css/style.css
@@ -1,4 +1,4 @@
body {
- margin: 0;
- padding: 20px;
-}
\ No newline at end of file
+ margin: 0;
+ padding: 20px;
+}
diff --git a/test/fixtures/unused-assets/clean/assets/js/app.js b/test/fixtures/unused-assets/clean/assets/js/app.js
index 61f5319..186cd9a 100644
--- a/test/fixtures/unused-assets/clean/assets/js/app.js
+++ b/test/fixtures/unused-assets/clean/assets/js/app.js
@@ -1 +1 @@
-console.log('App loaded');
\ No newline at end of file
+console.log("App loaded");
diff --git a/test/fixtures/unused-assets/clean/index.html b/test/fixtures/unused-assets/clean/index.html
index 797f4b3..c9a2a16 100644
--- a/test/fixtures/unused-assets/clean/index.html
+++ b/test/fixtures/unused-assets/clean/index.html
@@ -1,14 +1,14 @@
-
+
-
+
-
-
\ No newline at end of file
+
+