diff --git a/src/js/utils/ghostscript-loader.ts b/src/js/utils/ghostscript-loader.ts index f8993f8..3ed86a0 100644 --- a/src/js/utils/ghostscript-loader.ts +++ b/src/js/utils/ghostscript-loader.ts @@ -33,6 +33,38 @@ export function getCachedGsModule(): GhostscriptModule | null { return cachedGsModule; } +export async function loadGsModule(): Promise { + const gsBaseUrl = getWasmBaseUrl('ghostscript')!; + const normalizedUrl = gsBaseUrl.endsWith('/') ? gsBaseUrl : `${gsBaseUrl}/`; + + const gsJsUrl = `${normalizedUrl}gs.js`; + const response = await fetch(gsJsUrl); + if (!response.ok) { + throw new Error(`Failed to fetch gs.js: HTTP ${response.status}`); + } + const jsText = await response.text(); + const blob = new Blob([jsText], { type: 'application/javascript' }); + const blobUrl = URL.createObjectURL(blob); + + try { + const gsModule = await import(/* @vite-ignore */ blobUrl); + const ModuleFactory = gsModule.default; + + return (await ModuleFactory({ + locateFile: (path: string) => { + if (path.endsWith('.wasm')) { + return `${normalizedUrl}gs.wasm`; + } + return `${normalizedUrl}${path}`; + }, + print: (text: string) => console.log('[GS]', text), + printErr: (text: string) => console.error('[GS Error]', text), + })) as GhostscriptModule; + } finally { + URL.revokeObjectURL(blobUrl); + } +} + export async function convertToPdfA( pdfData: Uint8Array, level: PdfALevel = 'PDF/A-2b', @@ -51,35 +83,7 @@ export async function convertToPdfA( if (cachedGsModule) { gs = cachedGsModule; } else { - const gsBaseUrl = getWasmBaseUrl('ghostscript')!; - let packageBaseUrl = gsBaseUrl; - if (packageBaseUrl.endsWith('/assets/')) { - packageBaseUrl = packageBaseUrl.slice(0, -8); - } else if (packageBaseUrl.endsWith('/assets')) { - packageBaseUrl = packageBaseUrl.slice(0, -7); - } - const normalizedPkgUrl = packageBaseUrl.endsWith('/') - ? packageBaseUrl - : `${packageBaseUrl}/`; - const normalizedAssetsUrl = gsBaseUrl.endsWith('/') - ? gsBaseUrl - : `${gsBaseUrl}/`; - - const libUrl = `${normalizedPkgUrl}dist/index.js`; - const module = await import(/* @vite-ignore */ libUrl); - const loadWASM = module.loadGhostscriptWASM || module.default; - - gs = (await loadWASM({ - baseUrl: normalizedAssetsUrl, - locateFile: (path: string) => { - if (path.endsWith('.wasm')) { - return `${normalizedAssetsUrl}gs.wasm`; - } - return path; - }, - print: (text: string) => console.log('[GS]', text), - printErr: (text: string) => console.error('[GS Error]', text), - })) as GhostscriptModule; + gs = await loadGsModule(); cachedGsModule = gs; } @@ -404,35 +408,7 @@ export async function convertFontsToOutlines( if (cachedGsModule) { gs = cachedGsModule; } else { - const gsBaseUrl = getWasmBaseUrl('ghostscript')!; - let packageBaseUrl = gsBaseUrl; - if (packageBaseUrl.endsWith('/assets/')) { - packageBaseUrl = packageBaseUrl.slice(0, -8); - } else if (packageBaseUrl.endsWith('/assets')) { - packageBaseUrl = packageBaseUrl.slice(0, -7); - } - const normalizedPkgUrl = packageBaseUrl.endsWith('/') - ? packageBaseUrl - : `${packageBaseUrl}/`; - const normalizedAssetsUrl = gsBaseUrl.endsWith('/') - ? gsBaseUrl - : `${gsBaseUrl}/`; - - const libUrl = `${normalizedPkgUrl}dist/index.js`; - const module = await import(/* @vite-ignore */ libUrl); - const loadWASM = module.loadGhostscriptWASM || module.default; - - gs = (await loadWASM({ - baseUrl: normalizedAssetsUrl, - locateFile: (path: string) => { - if (path.endsWith('.wasm')) { - return `${normalizedAssetsUrl}gs.wasm`; - } - return path; - }, - print: (text: string) => console.log('[GS]', text), - printErr: (text: string) => console.error('[GS Error]', text), - })) as GhostscriptModule; + gs = await loadGsModule(); cachedGsModule = gs; } diff --git a/src/js/utils/wasm-preloader.ts b/src/js/utils/wasm-preloader.ts index 188f694..818e281 100644 --- a/src/js/utils/wasm-preloader.ts +++ b/src/js/utils/wasm-preloader.ts @@ -73,34 +73,10 @@ async function preloadGhostscript(): Promise { console.log('[Preloader] Starting Ghostscript WASM preload...'); try { - const gsBaseUrl = getWasmBaseUrl('ghostscript')!; + const { loadGsModule, setCachedGsModule } = + await import('./ghostscript-loader.js'); - let packageBaseUrl = gsBaseUrl; - if (packageBaseUrl.endsWith('/assets/')) { - packageBaseUrl = packageBaseUrl.slice(0, -8); - } else if (packageBaseUrl.endsWith('/assets')) { - packageBaseUrl = packageBaseUrl.slice(0, -7); - } - const normalizedUrl = packageBaseUrl.endsWith('/') - ? packageBaseUrl - : `${packageBaseUrl}/`; - - const libUrl = `${normalizedUrl}dist/index.js`; - const module = await import(/* @vite-ignore */ libUrl); - const loadGsWASM = module.loadGhostscriptWASM || module.default; - const { setCachedGsModule } = await import('./ghostscript-loader.js'); - - const gsModule = await loadGsWASM({ - baseUrl: `${normalizedUrl}assets/`, - locateFile: (path: string) => { - if (path.endsWith('.wasm')) { - return `${normalizedUrl}assets/gs.wasm`; - } - return path; - }, - print: () => {}, - printErr: () => {}, - }); + const gsModule = await loadGsModule(); setCachedGsModule(gsModule as any); preloadState.ghostscript = PreloadStatus.READY; console.log('[Preloader] Ghostscript WASM ready');