Skip to content

Conversation

@mirko314
Copy link
Contributor

@mirko314 mirko314 commented Jan 7, 2026

No description provided.

Add comprehensive test that reproduces the runtime error customers
experience when using the plugin with Angular + Webpack 5:

"Cannot find module 'file:///.../node_modules/@imgly/plugin-print-ready-pdfs-web/dist/gs.js'"

The test creates a minimal Angular 18 project that:
- Uses @angular-builders/custom-webpack with Webpack 5
- Imports and calls convertToPDFX3 at runtime
- Verifies whether the gs.js module loads correctly

This confirms the issue is caused by incorrect Node.js environment
detection in ghostscript-module.ts when bundled with Webpack 5.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fix runtime error when using the plugin with Angular + Webpack 5:
"Cannot find module 'file:///.../gs.js'"

The issue had two parts:

1. Environment detection: Webpack 5 polyfills `process.versions.node`,
   causing the code to incorrectly detect a Node.js environment in
   browsers. Fixed by checking for browser globals (window/document)
   first before trusting the Node.js detection.

2. import.meta.url transformation: Webpack transforms import.meta.url
   to the original source file path (a file:// URL) at build time,
   which doesn't work in browsers. Fixed by:
   - Detecting when import.meta.url is a file:// URL
   - Probing common asset paths (/assets/wasm/, /assets/, /) to find
     the actual location of gs.js, gs.wasm, and ICC profiles
   - Using indirect dynamic import (new Function) to prevent Webpack
     from transforming the import statement

The fix applies to both ghostscript-module.ts (WASM loading) and
pdfx.ts (ICC profile loading).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add explicit assetPath option to configure where plugin assets (gs.js,
gs.wasm, *.icc profiles) are served from. This is required for bundled
environments like Webpack 5 and Angular CLI where import.meta.url gets
transformed to file:// URLs that don't work in browsers.

- Add assetPath option to PDFX3Options interface
- Update ghostscript-module.ts to use assetPath for loading WASM
- Update pdfx.ts to use assetPath for loading ICC profiles
- Add helpful error message when assetPath is required but not provided
- Add Angular + CE.SDK integration test to verify the fix
- Add test project generator script for reproducible testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…dule

- Create src/utils/asset-path.ts with normalizeAssetPath and resolveAssetBasePath
- Remove duplicated code from pdfx.ts and ghostscript-module.ts
- Remove unused loadedAssetPath variable from ghostscript-loader.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…oject

- Extract duplicate indirect import logic to shared `dynamic-import.ts` utility
- Fix test project to pass required `assetPath` option for Webpack 5
- Consolidate angular.json asset copying to single `/assets/print-ready-pdfs/` folder
- Add bundler setup documentation section to README
- Update error message link to point to GitHub README

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…injection

Introduce AssetLoader interface to abstract asset loading (gs.js, gs.wasm, ICC profiles).
This enables platform-specific implementations and custom loaders for CDN/service workers.

- Add AssetLoader interface with loadGhostscriptModule, getWasmPath, loadICCProfile
- Convert .d.ts type files to .ts for better tooling support
- Update PDFX3Options to accept assetLoader or assetPath options
Implement platform-specific asset loaders:

- BrowserAssetLoader: loads assets via fetch/dynamic import with webpackIgnore
- NodeAssetLoader: loads assets from filesystem relative to module location
- node-loader.browser.ts: stub for browser bundles to avoid Node.js code

BrowserAssetLoader uses /* webpackIgnore: true */ for CSP-safe dynamic imports.
Update core modules to use dependency-injected AssetLoader:

- pdfx.ts: auto-detect environment and create appropriate loader
- ghostscript-loader.ts: accept AssetLoader instead of assetPath string
- ghostscript-module.ts: simplified to use AssetLoader for module/WASM loading
- Remove dynamic-import.ts utility (no longer needed)

Browser environments require explicit assetPath or assetLoader option.
Node.js environments auto-detect and use NodeAssetLoader.
…l exports

Add platform-specific entry points for optimal bundle sizes:

- index.browser.ts: browser-only, no Node.js code
- index.node.ts: Node.js-only, uses filesystem APIs
- index.ts: universal entry with auto-detection (backwards compatible)

Update package.json exports map with conditional exports:
- "." resolves to browser/node/default based on environment
- "./browser" and "./node" subpaths for explicit imports

Simplify esbuild/config.mjs (build logic moved to scripts/build.mjs).
- Add window type declarations for test globals
- Add minimal PDF/X test fixture
- Update CHANGELOG date to 2025-12-23 and description to match final implementation
- Add JSDoc for AssetLoader.getWasmPath() call ordering requirement
- Enhance NodeAssetLoader.getWasmPath() documentation and error message
- Add Custom Asset Loading section to README with AssetLoader example
- Update API reference with assetPath and assetLoader options
- Remove unverified Next.js specific documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@vercel
Copy link

vercel bot commented Jan 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
plugins-bytedance Ready Ready Preview, Comment Jan 7, 2026 11:44am
plugins-web Ready Ready Preview, Comment Jan 7, 2026 11:44am

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.

1 participant