Add zotero://open-pdf handler to open PDF at a given page
This is loosely based on the same functionality in ZotFile, but it tries to do the right thing based on existing Zotero settings: either the new PDF handler setting in the prefs or the system-default app. The latter can only reliably be determined on Windows (and this uses ZotFile's function to read that from the registry), but this tries to figure it out on macOS and Linux too using the Mozilla handler service. (The handler service only gets you an app name, not a path, so on Linux we can try reading mimetypes.list and the like in case someone is using a system-default okular or evince not in /usr/bin, but that's not yet implemented.) This uses the new 5.0 URL format, and a 'page' query parameter instead of a path component: zotero://open-pdf/library/items/[itemKey]?page=[page] zotero://open-pdf/groups/[groupID]/items/[itemKey]?page=[page] It also accepts ZotFile-style URLs, though, so if you uninstall ZotFile you should still be able to open those links. ZotFile will need to accept the new format for new links to work when ZotFile is installed, since it will override this handler. This functionality will be necessary for annotation extraction (#1018) and for imported annotations from Mendeley (#1451).
This commit is contained in:
parent
c0a4fa43f0
commit
609657a8e4
3 changed files with 387 additions and 0 deletions
|
@ -1000,6 +1000,119 @@ function ZoteroProtocolHandler() {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Open a PDF at a given page (or try to)
|
||||
*
|
||||
* zotero://open-pdf/library/items/[itemKey]?page=[page]
|
||||
* zotero://open-pdf/groups/[groupID]/items/[itemKey]?page=[page]
|
||||
*
|
||||
* Also supports ZotFile format:
|
||||
* zotero://open-pdf/[libraryID]_[key]/[page]
|
||||
*/
|
||||
var OpenPDFExtension = {
|
||||
noContent: true,
|
||||
|
||||
doAction: async function (uri) {
|
||||
var userLibraryID = Zotero.Libraries.userLibraryID;
|
||||
|
||||
var uriPath = uri.path;
|
||||
if (!uriPath) {
|
||||
return 'Invalid URL';
|
||||
}
|
||||
// Strip leading '/'
|
||||
uriPath = uriPath.substr(1);
|
||||
var mimeType, content = '';
|
||||
|
||||
var params = {
|
||||
objectType: 'item'
|
||||
};
|
||||
var router = new Zotero.Router(params);
|
||||
|
||||
// All items
|
||||
router.add('library/items/:objectKey/:pathPage', function () {
|
||||
params.libraryID = userLibraryID;
|
||||
});
|
||||
router.add('groups/:groupID/items/:objectKey/:pathPage');
|
||||
|
||||
// ZotFile URLs
|
||||
router.add(':id/:pathPage', function () {
|
||||
var lkh = Zotero.Items.parseLibraryKeyHash(params.id);
|
||||
if (!lkh) {
|
||||
Zotero.warn(`Invalid URL ${url}`);
|
||||
return;
|
||||
}
|
||||
params.libraryID = lkh.libraryID || userLibraryID;
|
||||
params.objectKey = lkh.key;
|
||||
delete params.id;
|
||||
});
|
||||
router.run(uriPath);
|
||||
|
||||
Zotero.API.parseParams(params);
|
||||
var results = await Zotero.API.getResultsFromParams(params);
|
||||
var page = params.pathPage || params.page;
|
||||
if (parseInt(page) != page) {
|
||||
page = null;
|
||||
}
|
||||
|
||||
if (!results.length) {
|
||||
Zotero.warn(`No item found for ${uriPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
var item = results[0];
|
||||
|
||||
if (!item.isFileAttachment()) {
|
||||
Zotero.warn(`Item for ${uriPath} is not a file attachment`);
|
||||
return;
|
||||
}
|
||||
|
||||
var path = await item.getFilePathAsync();
|
||||
if (!path) {
|
||||
Zotero.warn(`${path} not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!path.toLowerCase().endsWith('.pdf')
|
||||
&& Zotero.MIME.sniffForMIMEType(await Zotero.File.getSample(path)) != 'application/pdf') {
|
||||
Zotero.warn(`${path} is not a PDF`);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no page number, just open normally
|
||||
if (!page) {
|
||||
let zp = Zotero.getActiveZoteroPane();
|
||||
// TODO: Open pane if closed (macOS)
|
||||
if (zp) {
|
||||
zp.viewAttachment([item.id]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var opened = Zotero.OpenPDF.openToPage(path, page);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
// If something went wrong, just open PDF without page
|
||||
if (!opened) {
|
||||
let zp = Zotero.getActiveZoteroPane();
|
||||
// TODO: Open pane if closed (macOS)
|
||||
if (zp) {
|
||||
zp.viewAttachment([item.id]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Zotero.Notifier.trigger('open', 'file', item.id);
|
||||
},
|
||||
|
||||
|
||||
newChannel: function (uri) {
|
||||
this.doAction(uri);
|
||||
}
|
||||
};
|
||||
|
||||
this._extensions[ZOTERO_SCHEME + "://data"] = DataExtension;
|
||||
this._extensions[ZOTERO_SCHEME + "://report"] = ReportExtension;
|
||||
this._extensions[ZOTERO_SCHEME + "://timeline"] = TimelineExtension;
|
||||
|
@ -1008,6 +1121,7 @@ function ZoteroProtocolHandler() {
|
|||
this._extensions[ZOTERO_SCHEME + "://fullscreen"] = FullscreenExtension;
|
||||
this._extensions[ZOTERO_SCHEME + "://debug"] = DebugExtension;
|
||||
this._extensions[ZOTERO_SCHEME + "://connector"] = ConnectorExtension;
|
||||
this._extensions[ZOTERO_SCHEME + "://open-pdf"] = OpenPDFExtension;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue