Skip to content

Commit 147aa49

Browse files
committed
feat: add install-grade PWA icons
1 parent a477752 commit 147aa49

7 files changed

Lines changed: 36 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ All notable changes to ScriptHunt will be documented in this file.
2626
- Added exact-URL applicability simulation for userscript scheme, host, port, path, include globs, and exclusion rules while retaining domain-only host hints.
2727
- Versioned offline search records now preserve source route, status, partiality, failures, and scan evidence; legacy IndexedDB/localStorage copies migrate and deduplicate by newest valid record, with visible schema and eviction diagnostics.
2828
- Added a local accessibility matrix across four themes and 320/375/768/1280px viewports, including text contrast, focus visibility, reduced motion, native/fallback popovers, keyboard result actions, comparison focus, and overflow checks.
29+
- Added verified 192×192 and 512×512 PWA icons to the manifest and offline shell.
2930

3031
## [v0.5.1]
3132

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ npm run qa
8282
| **Content Security Policy** | Static parser-safe CSP limits network requests to HTTPS while URL validation and source/proxy contracts constrain destinations |
8383
| **View Transitions** | GPU-accelerated smooth transitions between search states |
8484
| **Themes** | Dark, Light, OLED black, and Auto (follows OS preference) |
85-
| **PWA** | Installable Progressive Web App with update prompts, offline shell fallback notices, and recent-search cache |
85+
| **PWA** | Installable Progressive Web App with 192px/512px icons, update prompts, offline shell fallback notices, and recent-search cache |
8686
| **Responsive Design** | Full mobile/tablet/desktop support with CSS container queries |
8787
| **Runtime Zero Dependencies** | Single HTML file, no app runtime dependencies; npm is used only for local tests via `npm run qa` |
8888

icon-192.png

35.7 KB
Loading

icon-512.png

222 KB
Loading

manifest.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
{
2-
"name": "ScriptHunt",
3-
"short_name": "ScriptHunt",
4-
"description": "Unified search across every userscript source",
5-
"start_url": "./",
6-
"scope": "./",
7-
"display": "standalone",
8-
"background_color": "#060810",
1+
{
2+
"name": "ScriptHunt",
3+
"short_name": "ScriptHunt",
4+
"description": "Unified search across every userscript source",
5+
"start_url": "./",
6+
"scope": "./",
7+
"display": "standalone",
8+
"background_color": "#060810",
99
"theme_color": "#0b0e16",
1010
"icons": [
11-
{ "src": "icon.png", "sizes": "256x256", "type": "image/png" }
11+
{ "src": "icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
12+
{ "src": "icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }
1213
]
1314
}

sw.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ var SHELL_ASSETS = [
33
'./',
44
'./index.html',
55
'./icon.png',
6+
'./icon-192.png',
7+
'./icon-512.png',
68
'./manifest.json',
79
'./fonts/jetbrains-mono-latin.woff2',
810
'./fonts/jetbrains-mono-latin-ext.woff2',

tests/source-docs.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,25 @@ test('package release metadata identifies the public application', () => {
8080
assert.equal(pkg.homepage, 'https://sysadmindoc.github.io/UserScriptHunt/');
8181
assert.match(pkg.description, /seven built-in catalogs/);
8282
});
83+
84+
test('PWA manifest declares install-grade PNG icons with matching dimensions', () => {
85+
const manifest = JSON.parse(readFile('manifest.json'));
86+
const expected = new Map([[192, 'icon-192.png'], [512, 'icon-512.png']]);
87+
const icons = Array.isArray(manifest.icons) ? manifest.icons : [];
88+
89+
for (const [size, filename] of expected) {
90+
const icon = icons.find((entry) => entry.src === filename);
91+
assert.ok(icon, `manifest should declare ${filename}`);
92+
assert.equal(icon.sizes, `${size}x${size}`);
93+
assert.equal(icon.type, 'image/png');
94+
const png = fs.readFileSync(path.join(root, filename));
95+
assert.equal(png.toString('hex', 0, 8), '89504e470d0a1a0a', `${filename} should be a PNG`);
96+
assert.equal(png.readUInt32BE(16), size, `${filename} width should match manifest`);
97+
assert.equal(png.readUInt32BE(20), size, `${filename} height should match manifest`);
98+
}
99+
100+
const serviceWorker = readFile('sw.js');
101+
for (const filename of expected.values()) {
102+
assert.ok(serviceWorker.includes(`'./${filename}'`), `${filename} should be in the offline shell`);
103+
}
104+
});

0 commit comments

Comments
 (0)