From ed8ca1bfce69eb9e57b12eb363e81719d5607793 Mon Sep 17 00:00:00 2001 From: Abe Jellinek <1770299+AbeJellinek@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:53:08 -0400 Subject: [PATCH] Item merging: Don't merge web link attachments with different URLs https://forums.zotero.org/discussion/133795 --- chrome/content/zotero/mergeItems.mjs | 6 ++++-- test/tests/mergeItemsTest.js | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/chrome/content/zotero/mergeItems.mjs b/chrome/content/zotero/mergeItems.mjs index 496b4dd844..0b1f6df09e 100644 --- a/chrome/content/zotero/mergeItems.mjs +++ b/chrome/content/zotero/mergeItems.mjs @@ -240,12 +240,14 @@ async function mergeWebAttachments(item, otherItems) { } // If we can find an attachment with the same title *and* URL, use it. + // For snapshots, fall back to matching on title alone. let masterAttachment = ( masterAttachments.find(attachment => attachment.getField('title') == otherAttachment.getField('title') && attachment.getField('url') == otherAttachment.getField('url') && attachment.attachmentLinkMode === otherAttachment.attachmentLinkMode) - || masterAttachments.find(attachment => attachment.getField('title') == otherAttachment.getField('title') - && attachment.attachmentLinkMode === otherAttachment.attachmentLinkMode) + || otherAttachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL + && masterAttachments.find(attachment => attachment.getField('title') == otherAttachment.getField('title') + && attachment.attachmentLinkMode === otherAttachment.attachmentLinkMode) ); if (!masterAttachment) { diff --git a/test/tests/mergeItemsTest.js b/test/tests/mergeItemsTest.js index 6867e2f0eb..a46936b5ba 100644 --- a/test/tests/mergeItemsTest.js +++ b/test/tests/mergeItemsTest.js @@ -573,6 +573,33 @@ describe("Item merging", function () { assert.isFalse(attachment3.deleted); }); + it("should keep linked URL with same title but different URL", async function () { + let item1 = await createDataObject('item', { setTitle: true }); + let attachment1 = await Zotero.Attachments.linkFromURL({ + url: 'https://example.com/', + title: 'Catalog Entry', + parentItemID: item1.id + }); + + let item2 = item1.clone(); + await item2.saveTx(); + let attachment2 = await Zotero.Attachments.linkFromURL({ + url: 'https://otherdomain.example.com/', + title: 'Catalog Entry', + parentItemID: item2.id + }); + + await mergeItems(item1, [item2]); + + assert.isFalse(item1.deleted); + assert.isFalse(attachment1.deleted); + assert.equal(item1.numAttachments(true), 2); + assert.isTrue(item2.deleted); + assert.equal(attachment2.parentItemID, item1.id); + assert.isFalse(attachment2.deleted); + assert.equal(attachment2.getField('url'), 'https://otherdomain.example.com/'); + }); + it("should keep web attachment with same URL but different title", async function () { let item1 = await createDataObject('item', { setTitle: true }); let attachment1 = await Zotero.Attachments.linkFromURL({