From 2647f60141f1907c7281ca0ca47a8c6357e0ef85 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 31 Mar 2026 09:22:30 +0900 Subject: [PATCH 01/10] refactor: split files --- docs/prd.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/prd.md b/docs/prd.md index 14c78c5..aaef34b 100644 --- a/docs/prd.md +++ b/docs/prd.md @@ -14,8 +14,13 @@ - add try/catch around unzipSync for corrupt/non-zip files - consider async unzip for large zips (fflate has async `unzip`) - SW scope may break under subpath hosting -- [ ] "Load another zip" button — currently the drop zone hides permanently after first load, no way to swap without refresh + - fix XSS: fetch error display uses innerHTML with unsanitized err.message and ?url= param + - parallelize cache.put() with Promise.all (currently sequential per-file) + - status bar never hides — should reset to hidden when idle + - SW ready blocks event listener registration — make non-blocking, show "registering…" status instead + +## Backlog + - [ ] Persist last zip in IndexedDB so refresh doesn't lose state -- [ ] Multi-zip / tabbed view — drop multiple zips, or auto-detect multiple dirs in one zip -- [ ] Publish as `npx zipview` -- [ ] Self-bootstrapping: embed SW in the static site output itself so the zip is directly openable +- [ ] Provide CLI / API to package SPA into "index.html + sw.js" bundle +- [ ] Integrate as Vitest html reporter two files mode From 0dd0e177b4b21590cb174bd3637fdb48d328d3c6 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 31 Mar 2026 09:46:49 +0900 Subject: [PATCH 02/10] refactor: ui with preact --- docs/prd.md | 1 + src/index.html | 423 ++++++++++++++++++++++++++++--------------------- src/sw.js | 3 + 3 files changed, 243 insertions(+), 184 deletions(-) diff --git a/docs/prd.md b/docs/prd.md index aaef34b..99e4562 100644 --- a/docs/prd.md +++ b/docs/prd.md @@ -18,6 +18,7 @@ - parallelize cache.put() with Promise.all (currently sequential per-file) - status bar never hides — should reset to hidden when idle - SW ready blocks event listener registration — make non-blocking, show "registering…" status instead +- [ ] setup e2e ## Backlog diff --git a/src/index.html b/src/index.html index 2a73ed9..2bc4a4e 100644 --- a/src/index.html +++ b/src/index.html @@ -4,7 +4,6 @@ Vitest Viewer - -
- Vitest Viewer -
- - Source code -
- -
-
Drag & drop or click to upload
-
.zip files only
-
-
- or try an - example -
- - - +
diff --git a/src/sw.js b/src/sw.js index 2f152a3..db6fd54 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,6 +1,9 @@ const CACHE_NAME = "zipview-v1"; const PREFIX = "/zipview/site/"; +// skipWaiting: activate immediately instead of waiting for old clients to close. +// clients.claim: take control of existing tabs right away. +// Together these ensure the new SW is serving before index.html writes to the cache. self.addEventListener("install", () => self.skipWaiting()); self.addEventListener("activate", (e) => e.waitUntil(self.clients.claim())); From a7536b2de06bf00bf7a9cd46f1bbc8bdeddaef4b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 31 Mar 2026 09:55:17 +0900 Subject: [PATCH 03/10] chore: prd.md --- docs/prd.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/prd.md b/docs/prd.md index 99e4562..e1a8f34 100644 --- a/docs/prd.md +++ b/docs/prd.md @@ -7,17 +7,16 @@ - [x] chore: add example zip from vitest html artifact - [x] `?url=` param for public URLs (GitHub artifact download requires auth, but pre-signed Azure blob URLs and S3 buckets work) - [x] File picker button (not just drag-and-drop) — mobile/accessibility -- [ ] refactor: rework code - - deduplicate fflate import (script tag on line 6 is dead weight, only the ES module import is needed) - - share constants (CACHE_NAME, PREFIX) between index.html and sw.js instead of duplicating - - move MIME map to sw.js (it's serving the files, not the main thread) - - add try/catch around unzipSync for corrupt/non-zip files - - consider async unzip for large zips (fflate has async `unzip`) - - SW scope may break under subpath hosting - - fix XSS: fetch error display uses innerHTML with unsanitized err.message and ?url= param - - parallelize cache.put() with Promise.all (currently sequential per-file) - - status bar never hides — should reset to hidden when idle - - SW ready blocks event listener registration — make non-blocking, show "registering…" status instead +- [x] refactor: remove dead fflate script tag, use single ESM import +- [x] refactor: fix XSS in fetch error display (Preact escapes by default) +- [x] refactor: parallelize cache.put() with Promise.all +- [ ] refactor: add try/catch around unzipSync for corrupt/non-zip files +- [ ] refactor: status bar never hides — reset to hidden when idle +- [ ] refactor: SW ready blocks event listeners — make non-blocking, show "registering…" status +- [ ] refactor: share constants (CACHE_NAME, PREFIX) between index.html and sw.js +- [ ] refactor: extract `