From 6646be66d0a82a58a84d8cab36fb1c90c8b3a349 Mon Sep 17 00:00:00 2001 From: Martynas Bagdonas Date: Thu, 18 Aug 2022 18:17:43 +0300 Subject: [PATCH] EditorInstance.createNoteFromAnnotations(): Handle multiple attachments --- chrome/content/zotero/xpcom/editorInstance.js | 53 ++++++++++++- test/tests/annotationsTest.js | 77 ++++++++++++++++++- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/chrome/content/zotero/xpcom/editorInstance.js b/chrome/content/zotero/xpcom/editorInstance.js index 8460226bd0..869acbcb73 100644 --- a/chrome/content/zotero/xpcom/editorInstance.js +++ b/chrome/content/zotero/xpcom/editorInstance.js @@ -1258,8 +1258,57 @@ class EditorInstance { html += '\n'; await editorInstance.importImages(jsonAnnotations); - let { html: serializedHTML, citationItems } = Zotero.EditorInstanceUtilities.serializeAnnotations(jsonAnnotations, true); - html += serializedHTML; + + let multipleParentParent = false; + let lastParentParentID; + let lastParentID; + // Group annotations per attachment + let groups = []; + for (let i = 0; i < annotations.length; i++) { + let annotation = annotations[i]; + let jsonAnnotation = jsonAnnotations[i]; + let parentParentID = annotation.parentItem.parentID; + let parentID = annotation.parentID; + if (groups.length) { + if (parentParentID !== lastParentParentID) { + // Multiple top level regular items detected, allow including their titles + multipleParentParent = true; + } + } + if (!groups.length || parentID !== lastParentID) { + groups.push({ + parentTitle: annotation.parentItem.getDisplayTitle(), + parentParentID, + parentParentTitle: annotation.parentItem.parentItem && annotation.parentItem.parentItem.getDisplayTitle(), + jsonAnnotations: [jsonAnnotation] + }); + } + else { + let group = groups[groups.length - 1]; + group.jsonAnnotations.push(jsonAnnotation); + } + lastParentParentID = parentParentID; + lastParentID = parentID; + } + let citationItems = []; + lastParentParentID = null; + for (let group of groups) { + if (multipleParentParent && group.parentParentTitle && lastParentParentID !== group.parentParentID) { + html += `

${group.parentParentTitle}

\n`; + } + lastParentParentID = group.parentParentID; + // If attachment doesn't have a parent or there are more attachments with the same parent, show attachment title + if (!group.parentParentID || groups.filter(x => x.parentParentID === group.parentParentID).length > 1) { + html += `

${group.parentTitle}

\n`; + } + let { html: _html, citationItems: _citationItems } = Zotero.EditorInstanceUtilities.serializeAnnotations(group.jsonAnnotations, true); + html += _html + '\n'; + for (let _citationItem of _citationItems) { + if (!citationItems.find(item => item.uris.some(uri => _citationItem.uris.includes(uri)))) { + citationItems.push(_citationItem); + } + } + } citationItems = encodeURIComponent(JSON.stringify(citationItems)); // Note: Update schema version only if using new features let schemaVersion = 8; diff --git a/test/tests/annotationsTest.js b/test/tests/annotationsTest.js index fa97d7f8ba..6070240878 100644 --- a/test/tests/annotationsTest.js +++ b/test/tests/annotationsTest.js @@ -403,4 +403,79 @@ describe("Zotero.Annotations", function() { await Zotero.Items.erase(splitAnnotations.map(x => x.id)); }); }); -}) \ No newline at end of file +}); + +describe("Create a note from annotations from multiple items and attachments", function () { + it("should create a note from single PDF file containing multiple annotations", async function () { + let annotations = []; + let attachment = await importPDFAttachment(); + let annotation1 = await createAnnotation('highlight', attachment); + annotations.push(annotation1); + let annotation2 = await createAnnotation('highlight', attachment); + annotations.push(annotation2); + let note = await Zotero.EditorInstance.createNoteFromAnnotations(annotations, null); + assert.equal(note.note.split('test.pdf').length - 1, 1); + assert.equal(note.note.split(annotation1.annotationText).length - 1, 1); + assert.equal(note.note.split(annotation2.annotationText).length - 1, 1); + }); + + it("should create a note from multiple PDF files containing single annotation", async function () { + let annotations = []; + let item = await createDataObject('item', { setTitle: true }); + let attachment1 = await importPDFAttachment(item); + let attachment2 = await importPDFAttachment(item); + let annotation1 = await createAnnotation('highlight', attachment1); + annotations.push(annotation1); + let annotation2 = await createAnnotation('highlight', attachment2); + annotations.push(annotation2); + let note = await Zotero.EditorInstance.createNoteFromAnnotations(annotations, null); + assert.equal(note.note.split('test.pdf').length - 1, 2); + assert.equal(note.note.split('>' + item.getField('title') + '<').length - 1, 0); + assert.equal(note.note.split(annotation1.annotationText).length - 1, 1); + assert.equal(note.note.split(annotation2.annotationText).length - 1, 1); + }); + + it("should create a note from multiple parent items containing single PDF file with single annotation", async function () { + let annotations = []; + let item1 = await createDataObject('item', { setTitle: true }); + let item2 = await createDataObject('item', { setTitle: true }); + let attachment1 = await importPDFAttachment(item1); + let attachment2 = await importPDFAttachment(item2); + let annotation1 = await createAnnotation('highlight', attachment1); + annotations.push(annotation1); + let annotation2 = await createAnnotation('highlight', attachment2); + annotations.push(annotation2); + let note = await Zotero.EditorInstance.createNoteFromAnnotations(annotations, null); + assert.equal(note.note.split('test.pdf').length - 1, 0); + assert.equal(note.note.split('>' + item1.getField('title') + '<').length - 1, 1); + assert.equal(note.note.split('>' + item2.getField('title') + '<').length - 1, 1); + assert.equal(note.note.split(annotation1.annotationText).length - 1, 1); + assert.equal(note.note.split(annotation2.annotationText).length - 1, 1); + }); + + it("should create a note from multiple parent items containing multiple PDF files with multiple annotations", async function () { + let annotations = []; + let item1 = await createDataObject('item', { setTitle: true }); + let item2 = await createDataObject('item', { setTitle: true }); + let attachment1 = await importPDFAttachment(item1); + let attachment2 = await importPDFAttachment(item2); + let attachment3 = await importPDFAttachment(item2); + let annotation1 = await createAnnotation('highlight', attachment1); + annotations.push(annotation1); + let annotation2 = await createAnnotation('highlight', attachment2); + annotations.push(annotation2); + let annotation3 = await createAnnotation('highlight', attachment3); + annotations.push(annotation3); + let annotation4 = await createAnnotation('highlight', attachment3); + annotations.push(annotation4); + let note = await Zotero.EditorInstance.createNoteFromAnnotations(annotations, null); + Zotero.debug(note.note); + assert.equal(note.note.split('test.pdf').length - 1, 2); + assert.equal(note.note.split('>' + item1.getField('title') + '<').length - 1, 1); + assert.equal(note.note.split('>' + item2.getField('title') + '<').length - 1, 1); + assert.equal(note.note.split(annotation1.annotationText).length - 1, 1); + assert.equal(note.note.split(annotation2.annotationText).length - 1, 1); + // Check item URIs count + assert.equal(note.note.split('zotero.org').length - 1, 16); + }); +});