parent
b909f1cd19
commit
5be1eef76a
|
|
@ -59,6 +59,7 @@ async function note2md(
|
|||
options: {
|
||||
keepNoteLink?: boolean;
|
||||
withYAMLHeader?: boolean;
|
||||
cachedYAMLHeader?: Record<string, any>;
|
||||
skipSavingImages?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
|
|
@ -102,22 +103,25 @@ async function note2md(
|
|||
}
|
||||
|
||||
if (options.withYAMLHeader) {
|
||||
let header = {};
|
||||
let header = {} as Record<string, any>;
|
||||
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}`;
|
||||
|
|
|
|||
|
|
@ -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<string, any>[],
|
||||
) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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: "",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -98,11 +98,15 @@ async function callSyncing(
|
|||
const toExport = {} as Record<string, number[]>;
|
||||
const toImport: SyncStatus[] = [];
|
||||
const toDiff: SyncStatus[] = [];
|
||||
const mdStatusMap = {} as Record<number, MDStatus>;
|
||||
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<SyncCode> {
|
||||
async function doCompare(
|
||||
noteItem: Zotero.Item,
|
||||
mdStatus: MDStatus,
|
||||
): Promise<SyncCode> {
|
||||
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<SyncCode> {
|
|||
}
|
||||
// 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) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ declare interface SyncStatus {
|
|||
|
||||
declare interface MDStatus {
|
||||
meta: {
|
||||
version: number;
|
||||
$version: number;
|
||||
$libraryID?: number;
|
||||
$itemKey?: string;
|
||||
} | null;
|
||||
content: string;
|
||||
filedir: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue