Add support for SDT

This commit is contained in:
Abe Jellinek 2026-04-20 15:27:54 -04:00
parent bf8c6f2027
commit 16f6a4d4eb
5 changed files with 83 additions and 4 deletions

View file

@ -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<Object|null>}
*/
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
*

View file

@ -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();

@ -1 +1 @@
Subproject commit fd642b38287f1e59aaf8e02c3132da6d3daa39c1
Subproject commit 0631cda250d1068544ee1b86e0072be1108b175c

View file

@ -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 };
}

2
reader

@ -1 +1 @@
Subproject commit 46d009be885cf7cf2543d4bfae50483d85a9c01b
Subproject commit 55c09dd963fe9baaceb75d4fdc584cae8a97f228