Skip to content

feat: Museum PDF Tool - 100% client-side WebAssembly version#3

Open
devonurefe wants to merge 1 commit into
mainfrom
feature/wasm-client-side
Open

feat: Museum PDF Tool - 100% client-side WebAssembly version#3
devonurefe wants to merge 1 commit into
mainfrom
feature/wasm-client-side

Conversation

@devonurefe

@devonurefe devonurefe commented Mar 3, 2026

Copy link
Copy Markdown
Owner
  • Replaced Flask/Python backend with browser-based JS (pdf-lib, pdf.js, JSZip)
  • Added PWA service worker for full offline support
  • Added PWA manifest + app icons for Install as App
  • Created English user guide (guide.html)
  • Zero server processing, zero AV issues, zero Render.com timeouts

Note

Medium Risk
Adds a new browser-only processing pipeline (PDF splitting/merging, page exclusion, image rendering, text extraction, ZIP packaging) plus a service worker that caches both local assets and third-party CDN resources, which could introduce runtime/performance issues or caching/update pitfalls.

Overview
Introduces a new wasm_dist standalone web build of Museum PDF Tool that runs 100% client-side: users select a PDF, define page ranges/merges/exclusions, and the app generates per-article PDFs, thumbnails, extracted text, and a downloadable ZIP via wasm_engine.js.

Adds PWA/offline support with manifest.json and service-worker.js (pre-caching app assets and key CDN libraries), plus a new guide.html user guide and updated styling for the new UI.

Written by Cursor Bugbot for commit 2d79500. This will update automatically on new commits. Configure here.

- Replaced Flask/Python backend with browser-based JS (pdf-lib, pdf.js, JSZip)
- Added PWA service worker for full offline support
- Added PWA manifest + app icons for Install as App
- Created English user guide (guide.html)
- Zero server processing, zero AV issues, zero Render.com timeouts
@railway-app

railway-app Bot commented Mar 3, 2026

Copy link
Copy Markdown

This PR was not deployed automatically as @devonurefe does not have access to the Railway project.

In order to get automatic PR deploys, please add @devonurefe to your workspace on Railway.

@netlify

netlify Bot commented Mar 3, 2026

Copy link
Copy Markdown

Deploy Preview for charming-selkie-fc32c4 failed.

Name Link
🔨 Latest commit 2d79500
🔍 Latest deploy log https://app.netlify.com/projects/charming-selkie-fc32c4/deploys/69a6ba2d02eab500080dbe1c

@netlify

netlify Bot commented Mar 3, 2026

Copy link
Copy Markdown

Deploy Preview for museumprojct failed.

Name Link
🔨 Latest commit 2d79500
🔍 Latest deploy log https://app.netlify.com/projects/museumprojct/deploys/69a6ba2d29ebfa0008a217b2

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Bugbot Free Tier Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

e.preventDefault();
if (!globalPdfBytes) return alert("Please select a PDF file first");

btnText.textContent = "Processing... (Do not close tab)";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Button SVG icon destroyed on every submission

Medium Severity

The #btn-text span contains an SVG icon as a child element alongside the "Process PDF" text. Assigning to .textContent replaces all child nodes — including the SVG — with a plain text node. After the first form submission, the play icon is permanently removed from the button and is never restored, because the finally block also resets via .textContent rather than targeting just the text node.

Additional Locations (1)

Fix in Cursor Fix in Web

let allPages = [];
const indicesSet = new Set(validIndices.map(i => i - 1));
validIndices.forEach(i => allPages.push(...ranges[i - 1]));
allPages.sort((a, b) => a - b);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate block index causes doubled PDF pages

Low Severity

In mergeArticles, the filter(n => n) step removes zeros and NaNs but does not deduplicate valid indices. If a user enters the same block number twice (e.g., "1,1"), validIndices is [1, 1], and the forEach on line 83 pushes ranges[0] into allPages twice. The resulting merged article PDF contains every page from that block duplicated.

Fix in Cursor Fix in Web

if (start > end || start < 1 || end > maxPages) throw new Error(`Invalid page range: ${part}`);
const r = [];
for (let i = start; i <= end; i++) r.push(i);
ranges.push(r);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NaN input silently drops articles in range parser

Medium Severity

In parseRanges, when a range like "1-abc" is entered, Number("abc") produces NaN. All comparisons involving NaN (NaN < 1, NaN > maxPages, start > end) return false, so the validation guard never throws. The for loop condition i <= NaN is immediately false, so r stays []. The empty range is pushed into ranges, and later the article loop hits pagesToCopy.length === 0 and silently continues — the article is dropped from the output ZIP with no error or warning to the user.

Fix in Cursor Fix in Web

fullText += pageText + "\n\n";
}
return fullText;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PDF.js documents never destroyed, leaking worker memory

Medium Severity

Both extractTextFromPdf and renderScaledImages call pdfjsLib.getDocument() and await the resulting pdf object but never call pdf.destroy(). The pdf.js worker holds internal references to each loaded document until explicitly destroyed. With two document loads per article, processing a magazine with many articles accumulates all decoded PDF data in the worker thread simultaneously, which can cause significant memory pressure or an out-of-memory crash in the browser tab.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants