Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Zotero PDF URI links #248

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
InsertCitationModal,
InsertNoteLinkModal,
InsertNoteContentModal,
InsertZoteroLinkModal,
OpenNoteModal,
} from './modals';
import { VaultExt } from './obsidian-extensions.d';
Expand Down Expand Up @@ -171,6 +172,15 @@ export default class CitationPlugin extends Plugin {
},
});

this.addCommand({
id: 'insert-zotero-link',
name: 'Insert Zotero link to pdf or entry',
callback: () => {
const modal = new InsertZoteroLinkModal(this.app, this);
modal.open();
},
});

this.addCommand({
id: 'insert-markdown-citation',
name: 'Insert Markdown citation',
Expand Down Expand Up @@ -334,6 +344,16 @@ export default class CitationPlugin extends Plugin {
);
}

getEntryZoteroLinkForCitekey(citekey: string): string {
return `[${citekey}](zotero://select/items/${citekey})`;
}

getPdfZoteroLinkForCitekey(citekey: string): string {
const variables = this.library.getTemplateVariablesForCitekey(citekey);
return `[${citekey}:pdf](${variables.zoteroPdfURI})`;
}


/**
* Run a case-insensitive search for the literature note file corresponding to
* the given citekey. If no corresponding file is found, create one.
Expand Down Expand Up @@ -417,4 +437,16 @@ export default class CitationPlugin extends Plugin {

this.editor.replaceRange(citation, this.editor.getCursor());
}

async insertZoteroLink(
citekey: string,
alternative = false,
): Promise<void> {
const func = alternative
? this.getEntryZoteroLinkForCitekey
: this.getPdfZoteroLinkForCitekey;
const link = func.bind(this)(citekey);

this.editor.replaceRange(link, this.editor.getCursor());
}
}
24 changes: 24 additions & 0 deletions src/modals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,30 @@ export class InsertNoteContentModal extends SearchModal {
}
}

export class InsertZoteroLinkModal extends SearchModal {
constructor(app: App, plugin: CitationPlugin) {
super(app, plugin);

this.setInstructions([
{ command: '↑↓', purpose: 'to navigate' },
{
command: '↵',
purpose: 'to insert Zotero Link to pdf',
},
{ command: 'shift ↵', purpose: 'to insert Zoter Link to entry' },
{ command: 'esc', purpose: 'to dismiss' },
]);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
onChooseItem(item: Entry, evt: MouseEvent | KeyboardEvent): void {
const isAlternative = evt instanceof KeyboardEvent && evt.shiftKey;
this.plugin
.insertZoteroLink(item.id, isAlternative)
.catch(console.error);
}
}

export class InsertCitationModal extends SearchModal {
constructor(app: App, plugin: CitationPlugin) {
super(app, plugin);
Expand Down
27 changes: 27 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as BibTeXParser from '@retorquere/bibtex-parser';
import { Entry as EntryDataBibLaTeX } from '@retorquere/bibtex-parser';
import { has } from 'lodash';
// Also make EntryDataBibLaTeX available to other modules
export { Entry as EntryDataBibLaTeX } from '@retorquere/bibtex-parser';

Expand Down Expand Up @@ -31,6 +32,8 @@ export const TEMPLATE_VARIABLES = {
URL: '',
year: 'Publication year',
zoteroSelectURI: 'URI to open the reference in Zotero',
zoteroPdfURI: 'URI to open the PDF attachment in Zotero',
zoteroPdfHash: 'Hash of the PDF attachment',
};

export class Library {
Expand Down Expand Up @@ -65,6 +68,8 @@ export class Library {
URL: entry.URL,
year: entry.year?.toString(),
zoteroSelectURI: entry.zoteroSelectURI,
zoteroPdfURI: entry.zoteroPdfURI,
zoteroPdfHash: entry.zoteroPdfHash,
};

return { entry: entry.toJSON(), ...shortcuts };
Expand Down Expand Up @@ -199,6 +204,28 @@ export abstract class Entry {
return `zotero://select/items/@${this.id}`;
}

public get zoteroPdfHash(): string {
const files = this.files || [];

const pdfPath = files.find((f) => f.toLowerCase().endsWith('.pdf'));

if (!pdfPath) {
return null;
}
const idxStorage = pdfPath.toLowerCase().indexOf('/storage/');
const pdfHash = pdfPath.substring(idxStorage + 9, idxStorage + 9 + 8);
return pdfHash;
}

public get zoteroPdfURI(): string {
const hashPdf = this.zoteroPdfHash;
if (hashPdf) {
return `zotero://open-pdf/library/items/${hashPdf}`;
} else {
return null;
}
}

toJSON(): Record<string, unknown> {
const jsonObj: Record<string, unknown> = Object.assign({}, this);

Expand Down