From 16f6a4d4eb59773247a6f1a42dbfb5ac176b8eaf Mon Sep 17 00:00:00 2001 From: Abe Jellinek <1770299+AbeJellinek@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:27:54 -0400 Subject: [PATCH] Add support for SDT --- .../content/zotero/xpcom/pdfWorker/manager.js | 67 +++++++++++++++++++ chrome/content/zotero/xpcom/reader.js | 12 ++++ document-worker | 2 +- js-build/document-worker.js | 4 +- reader | 2 +- 5 files changed, 83 insertions(+), 4 deletions(-) diff --git a/chrome/content/zotero/xpcom/pdfWorker/manager.js b/chrome/content/zotero/xpcom/pdfWorker/manager.js index b95c5bb57f..d7b9b35b5a 100644 --- a/chrome/content/zotero/xpcom/pdfWorker/manager.js +++ b/chrome/content/zotero/xpcom/pdfWorker/manager.js @@ -24,6 +24,7 @@ */ const WORKER_URL = 'chrome://zotero/content/xpcom/pdfWorker/worker.js'; +const ASSETS_URL = 'chrome://zotero/content/xpcom/pdfWorker/'; const CMAPS_URL = 'resource://zotero/reader/pdf/web/cmaps/'; const STANDARD_FONTS_URL = 'resource://zotero/reader/pdf/web/standard_fonts/'; const WASM_URL = 'resource://zotero/reader/pdf/web/wasm/'; @@ -143,6 +144,20 @@ class PDFWorker { Zotero.debug('Failed to fetch wasm data:'); Zotero.debug(e); } + try { + if (message.action === 'FetchData') { + let response = await Zotero.HTTP.request( + 'GET', + ASSETS_URL + message.data, + { responseType: 'arraybuffer' } + ); + respData = new Uint8Array(response.response); + } + } + catch (e) { + Zotero.debug(`Failed to fetch data (${message.data}):`); + Zotero.debug(e); + } try { if (message.action === 'SaveRenderedAnnotation') { let { libraryID, annotationKey, buf } = message.data; @@ -679,6 +694,58 @@ class PDFWorker { }, isPriority); } + /** + * Get Zotero Structured Text JSON for a PDF, EPUB, or snapshot attachment + * + * @param {Integer} itemID Attachment item id + * @param {Boolean} [isPriority] + * @param {String} [password] + * @returns {Promise} + */ + async getStructuredData(itemID, isPriority, password) { + return this._enqueue(async () => { + let attachment = await Zotero.Items.getAsync(itemID); + + Zotero.debug(`Getting structured data from item ${attachment.libraryKey}`); + let t = new Date(); + + let contentType = attachment.attachmentContentType; + if (!(attachment.isPDFAttachment() + || attachment.isEPUBAttachment() + || attachment.isSnapshotAttachment())) { + throw new Error('Item must be a PDF, EPUB, or snapshot attachment'); + } + + let path = await attachment.getFilePathAsync(); + if (!path) { + return null; + } + let buf = await IOUtils.read(path); + buf = new Uint8Array(buf).buffer; + + try { + var result = await this._query('getStructuredData', { + buf, contentType, password + }, [buf]); + } + catch (e) { + let error = new Error(`Worker 'getStructuredData' failed: ${JSON.stringify({ error: e.message })}`); + try { + error.name = JSON.parse(e.message).name; + } + catch (e) { + Zotero.logError(e); + } + Zotero.logError(error); + throw error; + } + + Zotero.debug(`Extracted structured data for item ${attachment.libraryKey} in ${new Date() - t} ms`); + + return result; + }, isPriority); + } + /** * Get data for recognizer-server * diff --git a/chrome/content/zotero/xpcom/reader.js b/chrome/content/zotero/xpcom/reader.js index b4cecf3d70..b1a61fd3ec 100644 --- a/chrome/content/zotero/xpcom/reader.js +++ b/chrome/content/zotero/xpcom/reader.js @@ -631,6 +631,18 @@ class ReaderInstance { // As above setTimeout(() => this._openReadAloudVoicesDialog({ lang, tier, ftl })); }, + getSDT: (password) => { + return new this._iframeWindow.Promise(async (resolve) => { + try { + let sdt = await Zotero.PDFWorker.getStructuredData(this._item.id, true, password); + resolve(sdt ? Cu.cloneInto(sdt, this._iframeWindow) : null); + } + catch (e) { + Zotero.logError(e); + resolve(null); + } + }); + }, }, this._iframeWindow, { cloneFunctions: true })); this._resolveInitPromise(); diff --git a/document-worker b/document-worker index fd642b3828..0631cda250 160000 --- a/document-worker +++ b/document-worker @@ -1 +1 @@ -Subproject commit fd642b38287f1e59aaf8e02c3132da6d3daa39c1 +Subproject commit 0631cda250d1068544ee1b86e0072be1108b175c diff --git a/js-build/document-worker.js b/js-build/document-worker.js index 3bdc7c3e50..1dc8ea42df 100644 --- a/js-build/document-worker.js +++ b/js-build/document-worker.js @@ -29,14 +29,14 @@ async function getDocumentWorker(signatures) { await exec( `cd ${tmpDir}` + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` - + ` && unzip -o ${filename} worker.js -d ${targetDir}` + + ` && unzip -o ${filename} -d ${targetDir}` ); } catch (e) { console.error(e); await exec('npm ci', { cwd: modulePath }); await exec('npm run build', { cwd: modulePath }); - await fs.copy(path.join(modulePath, 'build', 'worker.js'), path.join(targetDir, 'worker.js')); + await fs.copy(path.join(modulePath, 'build'), targetDir); } signatures['document-worker'] = { hash }; } diff --git a/reader b/reader index 46d009be88..55c09dd963 160000 --- a/reader +++ b/reader @@ -1 +1 @@ -Subproject commit 46d009be885cf7cf2543d4bfae50483d85a9c01b +Subproject commit 55c09dd963fe9baaceb75d4fdc584cae8a97f228