fix(file-manager): harden the merged previews - PDF.js legacy build, server PDF thumbnails, STEP progress (issue #2976)

Follow-ups after merging PR #3128 (with the #2990 preview work):

- PDF preview failed on every browser without
  Map.prototype.getOrInsertComputed (Chrome < 145, Firefox < 144,
  older Safari): "This file cannot be previewed" for any PDF. Load
  pdf.js's legacy build, which bundles the polyfills for page and
  worker, and bundle the worker through Vite (?worker&url) so
  build.target lowers its class static block for Safari 16.0-16.3.
  The browser-baseline check only scanned .js output and never saw
  the copied .mjs worker; it scans .mjs too.
- PDF grid thumbnails only existed after someone opened the preview.
  Page one is now rendered server-side with PDFium (pypdfium2, new
  dependency, prebuilt wheels for every shipped platform) on upload,
  ZIP extraction and external-folder scans; Generate Thumbnails
  backfills PDFs as well. Renders are serialised behind a lock
  (PDFium is not thread-safe), run off the event loop, and scale
  from the page size so a huge MediaBox cannot allocate a huge
  bitmap. Unreadable PDFs land without a thumbnail and keep the
  browser fallback.
- A large STEP file takes over a minute to mesh in the browser and
  showed only a spinner. STEP loads now show "Converting STEP
  model... N s" and a note that large files can take a minute or
  more, in all 15 locales.
- Drop the two occt-import-js "externalized for browser
  compatibility" build warnings (path/crypto are only required in
  its Node branch); any other externalization still shows.
This commit is contained in:
maziggy
2026-09-26 09:51:52 +02:00
parent 12dddada0a
commit 86bd9e1bd4
42 changed files with 1005 additions and 206 deletions
+5 -2
View File
@@ -62,14 +62,17 @@ const FORBIDDEN = [
let bundles;
try {
bundles = readdirSync(ASSETS).filter((f) => f.endsWith('.js'));
// .mjs too: a dependency's worker imported with `?url` is copied verbatim
// under its own extension, bypasses `build.target`, and was invisible here -
// the pdf.js worker shipped a class static block that way (#2976).
bundles = readdirSync(ASSETS).filter((f) => f.endsWith('.js') || f.endsWith('.mjs'));
} catch {
console.error(`check-browser-baseline: no build output at ${ASSETS} - run \`vite build\` first.`);
process.exit(1);
}
if (bundles.length === 0) {
console.error(`check-browser-baseline: no .js files in ${ASSETS} - did the build succeed?`);
console.error(`check-browser-baseline: no .js or .mjs files in ${ASSETS} - did the build succeed?`);
process.exit(1);
}