From 557ef7b6bc8d175b2cb4d517e19bf852af44436e Mon Sep 17 00:00:00 2001 From: mgmeyers Date: Sat, 9 Apr 2022 13:44:35 -0700 Subject: [PATCH] Fix misc bugs; Enable auto-updating of pdf utility --- manifest.json | 2 +- src/bbt/basicTemplates/applyBasicTemplates.ts | 9 +- src/bbt/export.ts | 96 ++++++++++++++----- src/bbt/extractAnnotations.ts | 11 +++ src/bbt/template.helpers.ts | 2 +- src/main.ts | 27 +++++- src/settings/AssetDownloader.tsx | 2 +- src/settings/ExportFormatSettings.tsx | 1 - src/settings/settings.tsx | 2 +- 9 files changed, 118 insertions(+), 34 deletions(-) diff --git a/manifest.json b/manifest.json index 3461ce2..34f6436 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-zotero-desktop-connector", "name": "Zotero Desktop Connector", - "version": "1.2.14", + "version": "1.2.15", "minAppVersion": "0.12.0", "description": "Insert citations, bibliographies, and notes directly from Zotero desktop.", "author": "mgmeyers", diff --git a/src/bbt/basicTemplates/applyBasicTemplates.ts b/src/bbt/basicTemplates/applyBasicTemplates.ts index 8d65a70..4bdcb61 100644 --- a/src/bbt/basicTemplates/applyBasicTemplates.ts +++ b/src/bbt/basicTemplates/applyBasicTemplates.ts @@ -1,4 +1,5 @@ import { template } from '../template.helpers'; +import { moment } from 'obsidian'; const creatorTemplate = ` {%- for creator in creators -%} @@ -32,7 +33,7 @@ const annotationsTemplate = ` {% for annotation in annots -%} {%- if annotation.annotatedText -%} - > “{{annotation.annotatedText}}”{% if annotation.color %} {{annotation.type | capitalize}} {% else %} {{annotation.type | capitalize}} {% endif %}[Page {{annotation.page}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.page}}) + > “{{annotation.annotatedText}}”{% if annotation.color %} {{annotation.colorCategory}} {{annotation.type | capitalize}} {% else %} {{annotation.type | capitalize}} {% endif %}[Page {{annotation.page}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.page}}) {%- endif %} {%- if annotation.imageRelativePath -%} > ![[{{annotation.imageRelativePath}}]] @@ -88,7 +89,11 @@ export function applyBasicTemplates(itemData: Record) { } if (itemData.annotations?.length) { - itemData.formattedAnnotations = template.renderString(annotationsTemplate, itemData).trim() + itemData.formattedAnnotationsNew = template.renderString(annotationsTemplate, itemData).trim() + itemData.formattedAnnotations = template.renderString(annotationsTemplate, { + ...itemData, + lastExportDate: moment(0) + }).trim() } return itemData; diff --git a/src/bbt/export.ts b/src/bbt/export.ts index 4ed8c11..41be091 100644 --- a/src/bbt/export.ts +++ b/src/bbt/export.ts @@ -77,7 +77,8 @@ function processAnnotation( async function processItem( item: any, exportDate: moment.Moment, - database: Database + database: Database, + cslStyle?: string ) { item.exportDate = exportDate; item.desktopURI = `zotero://select/library/items/${item.itemKey}`; @@ -101,7 +102,11 @@ async function processItem( } try { - item.bibliography = await getBibFromCiteKey(item.citekey, database); + item.bibliography = await getBibFromCiteKey( + item.citekey, + database, + cslStyle + ); } catch { item.bibliography = 'Error generating bibliography'; } @@ -280,20 +285,50 @@ export async function exportToMarkdown( } for (let i = 0, len = itemData.length; i < len; i++) { - await processItem(itemData[i], exportDate, database); + await processItem(itemData[i], exportDate, database, exportFormat.cslStyle); } const vaultRoot = getVaultRoot(); for (let i = 0, len = itemData.length; i < len; i++) { - const attachments = itemData[i].attachments; + const attachments = itemData[i].attachments as any[]; + const hasPDF = attachments.some((a) => a.path?.endsWith('.pdf')); + + // Handle the case of an item with no PDF attachments + if (!hasPDF) { + const templateData = itemData[i]; + const markdownPath = exportFormat.outputPathTemplate + ? removeStartingSlash( + template.renderString(exportFormat.outputPathTemplate, templateData) + ) + : './'; + + const existingMarkdown = app.vault.getAbstractFileByPath(markdownPath); + + applyBasicTemplates(templateData); + + const rendered = await renderTemplates(app, params, templateData, ''); + + if (!rendered) return false; + + if (existingMarkdown) { + app.vault.modify(existingMarkdown as TFile, rendered); + } else { + await mkMDDir(markdownPath); + app.vault.create(markdownPath, rendered); + } + + continue; + } + + // Handle the case of an item WITH PDF attachments for (let j = 0, jLen = attachments.length; j < jLen; j++) { const pdfInputPath = attachments[j].path; if (!pdfInputPath?.endsWith('.pdf')) continue; const pathTemplateData = { - ...itemData[i], ...attachments[j], + ...itemData[i], }; const imageOutputPath = path.resolve( @@ -337,7 +372,7 @@ export async function exportToMarkdown( const existingMarkdown = app.vault.getAbstractFileByPath(markdownPath); - let lastExportDate = moment().set('year', 1970); + let lastExportDate = moment(0); let existingAnnotations = ''; if (existingMarkdown) { @@ -359,24 +394,22 @@ export async function exportToMarkdown( imageQuality: settings.pdfExportImageQuality, }); annots = JSON.parse(res); + annots.forEach((a: any) => { + processAnnotation(a, attachments[j], imageRelativePath); + }); + attachments[j].annotations = annots; } catch (e) { return false; } - - annots.forEach((a: any) => { - processAnnotation(a, attachments[j], imageRelativePath); - }); - attachments[j].annotations = annots; } const templateData: Record = { ...itemData[i], lastExportDate, + annotations: annots ? annots : [] }; - if (annots) templateData.annotations = annots; - - applyBasicTemplates(templateData) + applyBasicTemplates(templateData); const rendered = await renderTemplates( app, @@ -399,6 +432,20 @@ export async function exportToMarkdown( return true; } +function getAStyle(settings: ZoteroConnectorSettings) { + const exportStyle = settings.exportFormats.find((f) => !!f.cslStyle); + + if (exportStyle) { + return exportStyle.cslStyle; + } + + const citeStyle = settings.citeFormats.find((f) => !!f.cslStyle); + + if (citeStyle) { + return citeStyle.cslStyle; + } +} + export async function dataExplorerPrompt(settings: ZoteroConnectorSettings) { const citeKeys: string[] = await getCiteKeys(settings.database); @@ -412,9 +459,10 @@ export async function dataExplorerPrompt(settings: ZoteroConnectorSettings) { } const exportDate = moment(); + const style = getAStyle(settings); for (let i = 0, len = itemData.length; i < len; i++) { - await processItem(itemData[i], exportDate, settings.database); + await processItem(itemData[i], exportDate, settings.database, style); } if (doesEXEExist()) { @@ -438,15 +486,14 @@ export async function dataExplorerPrompt(settings: ZoteroConnectorSettings) { imageQuality: settings.pdfExportImageQuality, }); annots = JSON.parse(res); + annots.forEach((a: any) => { + processAnnotation(a, attachments[j], 'output_path'); + }); + + attachments[j].annotations = annots; } catch (e) { return false; } - - annots.forEach((a: any) => { - processAnnotation(a, attachments[j], 'output_path'); - }); - - attachments[j].annotations = annots; } } } @@ -456,11 +503,8 @@ export async function dataExplorerPrompt(settings: ZoteroConnectorSettings) { a.path?.endsWith('.pdf') ); - if (firstPDF?.annotations) { - data.annotations = firstPDF.annotations; - } - - data.lastExportDate = moment().set('year', 1970); + data.annotations = firstPDF?.annotations ? firstPDF.annotations : []; + data.lastExportDate = moment(0); applyBasicTemplates(data); }); diff --git a/src/bbt/extractAnnotations.ts b/src/bbt/extractAnnotations.ts index c8a8f2f..9eb79a5 100644 --- a/src/bbt/extractAnnotations.ts +++ b/src/bbt/extractAnnotations.ts @@ -1,5 +1,6 @@ import { execa } from 'execa'; import { Notice } from 'obsidian'; +import path from "path"; import { getExeName, getExeRoot } from 'src/helpers'; @@ -58,6 +59,11 @@ export async function extractAnnotations(input: string, params: ExtractParams) { modal.close(); + if (result.stderr.toLowerCase().includes('password')) { + new Notice(`Error opening ${path.basename(input)}: PDF is password protected`, 10000); + return '[]' + } + if (result.stderr && !result.stderr.includes('warning')) { new Notice(`Error processing PDF: ${result.stderr}`, 10000); throw new Error(result.stderr); @@ -66,6 +72,11 @@ export async function extractAnnotations(input: string, params: ExtractParams) { return result.stdout; } catch (e) { modal.close(); + if (e.message.toLowerCase().includes('password')) { + new Notice(`Error opening ${path.basename(input)}: PDF is password protected`, 10000); + return '[]' + } + console.error(e); new Notice(`Error processing PDF: ${e.message}`, 10000); throw e; diff --git a/src/bbt/template.helpers.ts b/src/bbt/template.helpers.ts index 8ac80c6..fd7cf27 100644 --- a/src/bbt/template.helpers.ts +++ b/src/bbt/template.helpers.ts @@ -144,7 +144,7 @@ export function getLastExport(md: string): moment.Moment { return moment(new Date(match[1])); } - return moment().set('year', 1970); + return moment(0); } export function appendExportDate(md: string): string { diff --git a/src/main.ts b/src/main.ts index c736309..0f70c8d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,6 +14,8 @@ import { DataExplorerView, viewType } from './DataExplorerView'; import { ZoteroConnectorSettingsTab } from './settings/settings'; import { CitationFormat, ExportFormat, ZoteroConnectorSettings } from './types'; import { createEmitter, Emitter } from './emitter'; +import { currentVersion, downloadAndExtract } from './settings/AssetDownloader'; +import { LoadingModal } from './bbt/LoadingModal'; const citationCommandIDPrefix = 'zdc-'; const exportCommandIDPrefix = 'zdc-exp-'; @@ -38,9 +40,9 @@ export default class ZoteroConnector extends Plugin { async onload() { await this.loadSettings(); - this.emitter = createEmitter(); + this.updatePDFUtility(); this.addSettingTab(new ZoteroConnectorSettingsTab(this.app, this)); this.registerView(viewType, (leaf) => new DataExplorerView(this, leaf)); @@ -171,4 +173,27 @@ export default class ZoteroConnector extends Plugin { type: viewType, }); } + + async updatePDFUtility() { + if (this.settings.exeVersion && this.settings.exeVersion !== currentVersion) { + const modal = new LoadingModal( + (window as any).app, + 'Updating Zotero Desktop Connector PDF Utility...' + ); + modal.open(); + + try { + const success = await downloadAndExtract() + + if (success) { + this.settings.exeVersion = currentVersion; + this.saveSettings(); + } + } catch { + // + } + + modal.close(); + } + } } diff --git a/src/settings/AssetDownloader.tsx b/src/settings/AssetDownloader.tsx index 492b474..0ba6bbc 100644 --- a/src/settings/AssetDownloader.tsx +++ b/src/settings/AssetDownloader.tsx @@ -10,7 +10,7 @@ import { ZoteroConnectorSettings } from 'src/types'; import { Icon } from './Icon'; import { SettingItem } from './SettingItem'; -const currentVersion = '0.0.14'; +export const currentVersion = '0.1.0'; const options: Record> = { darwin: { diff --git a/src/settings/ExportFormatSettings.tsx b/src/settings/ExportFormatSettings.tsx index 10b521a..114ed05 100644 --- a/src/settings/ExportFormatSettings.tsx +++ b/src/settings/ExportFormatSettings.tsx @@ -128,7 +128,6 @@ export function ExportFormatSettings({ const onChangeHeaderPath = React.useCallback( (e: SingleValue<{ value: string; label: string }>) => { - console.log(e?.value); updateFormat(index, { ...format, headerTemplatePath: e?.value, diff --git a/src/settings/settings.tsx b/src/settings/settings.tsx index 4d2bd3b..ba787e5 100644 --- a/src/settings/settings.tsx +++ b/src/settings/settings.tsx @@ -188,7 +188,7 @@ function SettingsComponent({ {exportFormatState.map((f, i) => { return (