diff --git a/src/modules/convert/api.ts b/src/modules/convert/api.ts index c663e7b..699a8d8 100644 --- a/src/modules/convert/api.ts +++ b/src/modules/convert/api.ts @@ -59,6 +59,7 @@ async function note2md( options: { keepNoteLink?: boolean; withYAMLHeader?: boolean; + cachedYAMLHeader?: Record; skipSavingImages?: boolean; } = {}, ) { @@ -102,22 +103,25 @@ async function note2md( } if (options.withYAMLHeader) { - let header = {}; + let header = {} as Record; try { - header = JSON.parse( - await addon.api.template.runTemplate( - "[ExportMDFileHeaderV2]", - "noteItem", - [noteItem], + header = Object.assign( + JSON.parse( + await addon.api.template.runTemplate( + "[ExportMDFileHeaderV2]", + "noteItem", + [noteItem], + ), ), + options.cachedYAMLHeader || {}, ); } catch (e) { ztoolkit.log(e); } Object.assign(header, { - version: noteItem.version, - libraryID: noteItem.libraryID, - itemKey: noteItem.key, + $version: noteItem.version, + $libraryID: noteItem.libraryID, + $itemKey: noteItem.key, }); const yamlFrontMatter = `---\n${YAML.stringify(header, 10)}\n---`; md = `${yamlFrontMatter}\n${md}`; diff --git a/src/modules/export/markdown.ts b/src/modules/export/markdown.ts index 1bfb601..3b33186 100644 --- a/src/modules/export/markdown.ts +++ b/src/modules/export/markdown.ts @@ -31,7 +31,11 @@ export async function saveMD( }); } -export async function syncMDBatch(saveDir: string, noteIds: number[]) { +export async function syncMDBatch( + saveDir: string, + noteIds: number[], + metaList?: Record[], +) { const noteItems = Zotero.Items.get(noteIds); await IOUtils.makeDirectory(saveDir); const attachmentsDir = jointPath( @@ -44,12 +48,14 @@ export async function syncMDBatch(saveDir: string, noteIds: number[]) { if (hasImage) { await IOUtils.makeDirectory(attachmentsDir); } + let i = 0; for (const noteItem of noteItems) { const filename = await addon.api.sync.getMDFileName(noteItem.id, saveDir); const filePath = jointPath(saveDir, filename); const content = await addon.api.convert.note2md(noteItem, saveDir, { keepNoteLink: false, withYAMLHeader: true, + cachedYAMLHeader: metaList?.[i], }); await Zotero.File.putContentsAsync(filePath, content); addon.api.sync.updateSyncStatus(noteItem.id, { @@ -63,5 +69,6 @@ export async function syncMDBatch(saveDir: string, noteIds: number[]) { noteMd5: Zotero.Utilities.Internal.md5(noteItem.getNote(), false), lastsync: new Date().getTime(), }); + i += 1; } } diff --git a/src/modules/import/markdown.ts b/src/modules/import/markdown.ts index 98593a8..4ec7efd 100644 --- a/src/modules/import/markdown.ts +++ b/src/modules/import/markdown.ts @@ -20,9 +20,9 @@ export async function fromMD( let noteItem = options.noteId ? Zotero.Items.get(options.noteId) : undefined; if ( !options.ignoreVersion && - typeof mdStatus.meta?.version === "number" && + typeof mdStatus.meta?.$version === "number" && typeof noteItem?.version === "number" && - mdStatus.meta?.version < noteItem?.version + mdStatus.meta?.$version < noteItem?.version ) { if ( !window.confirm( diff --git a/src/modules/sync/api.ts b/src/modules/sync/api.ts index 9b642f1..8060e86 100644 --- a/src/modules/sync/api.ts +++ b/src/modules/sync/api.ts @@ -109,7 +109,7 @@ function getMDStatusFromContent(contentRaw: string): MDStatus { contentRaw = contentRaw.replace(/\r\n/g, "\n"); const result = contentRaw.match(/^---\n(.*\n)+?---$/gm); const ret: MDStatus = { - meta: { version: -1 }, + meta: { $version: -1 }, content: contentRaw, filedir: "", filename: "", diff --git a/src/modules/sync/diffWindow.ts b/src/modules/sync/diffWindow.ts index f4714ae..c031556 100644 --- a/src/modules/sync/diffWindow.ts +++ b/src/modules/sync/diffWindow.ts @@ -133,7 +133,7 @@ export async function showSyncDiff(noteId: number, mdPath: string) { autoSyncDelay: Zotero.Notes.AUTO_SYNC_DELAY, }, }); - await addon.api.$export.syncMDBatch(mdStatus.filedir, [noteItem.id]); + await addon.api.$export.syncMDBatch(mdStatus.filedir, [noteItem.id], [mdStatus.meta]); break; default: break; diff --git a/src/modules/sync/hooks.ts b/src/modules/sync/hooks.ts index 001f2f3..8f5a3a7 100644 --- a/src/modules/sync/hooks.ts +++ b/src/modules/sync/hooks.ts @@ -98,11 +98,15 @@ async function callSyncing( const toExport = {} as Record; const toImport: SyncStatus[] = []; const toDiff: SyncStatus[] = []; + const mdStatusMap = {} as Record; let i = 1; for (const item of items) { const syncStatus = addon.api.sync.getSyncStatus(item.id); const filepath = syncStatus.path; - const compareResult = await doCompare(item); + const mdStatus = await addon.api.sync.getMDStatus(item.id); + mdStatusMap[item.id] = mdStatus; + + const compareResult = await doCompare(item, mdStatus); switch (compareResult) { case SyncCode.NoteAhead: if (Object.keys(toExport).includes(filepath)) { @@ -138,7 +142,12 @@ async function callSyncing( } ...`, progress: ((i - 1) / items.length) * 100, }); - await addon.api.$export.syncMDBatch(filepath, toExport[filepath]); + const itemIDs = toExport[filepath]; + await addon.api.$export.syncMDBatch( + filepath, + itemIDs, + itemIDs.map((id) => mdStatusMap[id].meta!), + ); i += 1; } i = 1; @@ -154,7 +163,11 @@ async function callSyncing( const filepath = jointPath(syncStatus.path, syncStatus.filename); await addon.api.$import.fromMD(filepath, { noteId: item.id }); // Update md file to keep the metadata synced - await addon.api.$export.syncMDBatch(syncStatus.path, [item.id]); + await addon.api.$export.syncMDBatch( + syncStatus.path, + [item.id], + [mdStatusMap[item.id].meta!], + ); i += 1; } i = 1; @@ -193,20 +206,22 @@ async function callSyncing( addon.data.sync.lock = false; } -async function doCompare(noteItem: Zotero.Item): Promise { +async function doCompare( + noteItem: Zotero.Item, + mdStatus: MDStatus, +): Promise { const syncStatus = addon.api.sync.getSyncStatus(noteItem.id); - const MDStatus = await addon.api.sync.getMDStatus(noteItem.id); // No file found - if (!MDStatus.meta) { + if (!mdStatus.meta) { return SyncCode.NoteAhead; } // File meta is unavailable - if (MDStatus.meta.version < 0) { + if (mdStatus.meta.$version < 0) { return SyncCode.NeedDiff; } let MDAhead = false; let noteAhead = false; - const md5 = Zotero.Utilities.Internal.md5(MDStatus.content, false); + const md5 = Zotero.Utilities.Internal.md5(mdStatus.content, false); const noteMd5 = Zotero.Utilities.Internal.md5(noteItem.getNote(), false); // MD5 doesn't match (md side change) if (md5 !== syncStatus.md5) { @@ -218,7 +233,7 @@ async function doCompare(noteItem: Zotero.Item): Promise { } // Note version doesn't match (note side change) // This might be unreliable when Zotero account is not login - if (Number(MDStatus.meta.version) !== noteItem.version) { + if (Number(mdStatus.meta.$version) !== noteItem.version) { noteAhead = true; } if (noteAhead && MDAhead) { diff --git a/typings/note.d.ts b/typings/note.d.ts index dc41334..5ecf81c 100644 --- a/typings/note.d.ts +++ b/typings/note.d.ts @@ -25,7 +25,9 @@ declare interface SyncStatus { declare interface MDStatus { meta: { - version: number; + $version: number; + $libraryID?: number; + $itemKey?: string; } | null; content: string; filedir: string;