From 343fa7ca9f3f72c76977b2ef2abcdd5afa749001 Mon Sep 17 00:00:00 2001 From: Aden Linday Date: Sun, 29 Mar 2026 20:25:06 +1030 Subject: [PATCH] feat: migrate pdfjs to local & bump ver --- package.json | 2 +- src/lib/pdfjsExtension.ts | 26 +++++++++++++++++++ src/manifests/manifest.json | 7 ++++- .../built-in/assessmentsAverage/utils.ts | 22 ++++++++++++---- vite.config.ts | 18 +++++++++++++ 5 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 src/lib/pdfjsExtension.ts diff --git a/package.json b/package.json index a7608e40..083609b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "betterseqtaplus", - "version": "3.5.1", + "version": "3.5.2", "type": "module", "description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development add add heaps more features!", "browserslist": "> 0.5%, last 2 versions, not dead", diff --git a/src/lib/pdfjsExtension.ts b/src/lib/pdfjsExtension.ts new file mode 100644 index 00000000..09c00b42 --- /dev/null +++ b/src/lib/pdfjsExtension.ts @@ -0,0 +1,26 @@ +import * as pdfjs from "pdfjs-dist"; +import browser from "webextension-polyfill"; +import pdfWorkerHref from "pdfjs-dist/build/pdf.worker.min.mjs?url"; +import pdfLegacyHref from "pdfjs-dist/legacy/build/pdf.min.mjs?url"; + +function extensionAssetUrl(viteAssetHref: string): string { + const path = viteAssetHref.replace(/^\/+/, ""); + return browser.runtime.getURL(path); +} + +let workerConfigured = false; + +/** Required before pdfjs spawns a worker (content-script / extension isolate). */ +export function ensurePdfjsWorker(): void { + if (workerConfigured) return; + pdfjs.GlobalWorkerOptions.workerSrc = extensionAssetUrl(pdfWorkerHref); + workerConfigured = true; +} + +/** Page-context script on Firefox must load these chrome-extension:// URLs (see web_accessible_resources). */ +export function getPdfjsPageContextUrls(): { lib: string; worker: string } { + return { + lib: extensionAssetUrl(pdfLegacyHref), + worker: extensionAssetUrl(pdfWorkerHref), + }; +} diff --git a/src/manifests/manifest.json b/src/manifests/manifest.json index 7a3ba7e1..b4bfe4e4 100644 --- a/src/manifests/manifest.json +++ b/src/manifests/manifest.json @@ -32,7 +32,12 @@ ], "web_accessible_resources": [ { - "resources": ["resources/icons/*", "resources/update-image.webp"], + "resources": [ + "resources/icons/*", + "resources/update-image.webp", + "resources/pdfjs/pdf.worker.min.mjs", + "resources/pdfjs/pdf.legacy.min.mjs" + ], "matches": ["*://*/*"] } ] diff --git a/src/plugins/built-in/assessmentsAverage/utils.ts b/src/plugins/built-in/assessmentsAverage/utils.ts index 1f579e23..29491982 100644 --- a/src/plugins/built-in/assessmentsAverage/utils.ts +++ b/src/plugins/built-in/assessmentsAverage/utils.ts @@ -1,8 +1,12 @@ import { getUserInfo } from "@/seqta/ui/AddBetterSEQTAElements.ts"; import ReactFiber from "@/seqta/utils/ReactFiber.ts"; +import { + ensurePdfjsWorker, + getPdfjsPageContextUrls, +} from "@/lib/pdfjsExtension.ts"; import * as pdfjs from "pdfjs-dist"; -pdfjs.GlobalWorkerOptions.workerSrc = - `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`; + +ensurePdfjsWorker(); export async function initStorage(api: any) { await api.storage.loaded; @@ -219,6 +223,12 @@ async function fetchPDFAsArrayBuffer(url: string): Promise { export async function extractPDFText(url: string): Promise { try { if (isFirefox) { + const { lib: pdfLibUrl, worker: pdfWorkerUrl } = getPdfjsPageContextUrls(); + const escJsSingleQuoted = (s: string) => + s.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); + const pdfLibInj = escJsSingleQuoted(pdfLibUrl); + const pdfWorkerInj = escJsSingleQuoted(pdfWorkerUrl); + return new Promise((resolve, reject) => { const script = document.createElement("script"); const requestId = `pdf-extract-${Date.now()}-${Math.random()}`; @@ -232,13 +242,15 @@ export async function extractPDFText(url: string): Promise { (function() { const requestId = '${requestId}'; const url = '${escapedUrl}'; + const pdfLibSrc = '${pdfLibInj}'; + const pdfWorkerSrc = '${pdfWorkerInj}'; if (window.pdfjsLib) { extractPDF(); } else { const pdfjsScript = document.createElement('script'); - pdfjsScript.src = 'https://cdn.jsdelivr.net/npm/pdfjs-dist/build/pdf.min.js'; - pdfjsScript.type = 'text/javascript'; + pdfjsScript.src = pdfLibSrc; + pdfjsScript.type = 'module'; pdfjsScript.onload = function() { extractPDF(); @@ -256,7 +268,7 @@ export async function extractPDFText(url: string): Promise { function extractPDF() { try { - window.pdfjsLib.GlobalWorkerOptions.workerSrc = ''; + window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorkerSrc; const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); diff --git a/vite.config.ts b/vite.config.ts index 8bbf4abb..0dfc3932 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -84,6 +84,24 @@ export default defineConfig(({ command }) => ({ settings: join(__dirname, "src", "interface", "index.html"), pageState: join(__dirname, "src", "pageState.js"), }, + output: { + assetFileNames(info) { + const labels = [ + ...(info.names ?? []), + ...(info.originalFileNames ?? []), + ].join(" "); + if ( + labels.includes("pdf.worker.min") || + labels.includes("pdf.worker.mjs") + ) { + return "resources/pdfjs/pdf.worker.min.mjs"; + } + if (labels.includes("legacy") && labels.includes("pdf.min")) { + return "resources/pdfjs/pdf.legacy.min.mjs"; + } + return "assets/[name]-[hash][extname]"; + }, + }, onwarn(warning, warn) { if (warning.code === "FILE_NAME_CONFLICT") return; warn(warning);