diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js index 226117f35..75f607257 100644 --- a/chrome/content/zotero/xpcom/integration.js +++ b/chrome/content/zotero/xpcom/integration.js @@ -1150,6 +1150,40 @@ Zotero.Integration.Document.prototype.editBibliography = function() { }); } + +Zotero.Integration.Document.prototype.addEditBibliography = Zotero.Promise.coroutine(function *() { + // Check if we have a bibliography + var session = yield this._getSession(true, false); + + if (!session.data.style.hasBibliography) { + throw new Zotero.Exception.Alert("integration.error.noBibliography", [], + "integration.error.title"); + } + + var fieldGetter = new Zotero.Integration.Fields(session, this._doc, Zotero.Integration.onFieldError); + var fields = yield fieldGetter.get(); + + var haveBibliography = false; + for (var i=fields.length-1; i>=0; i--) { + var code = fields[i].getCode(); + var [type, content] = fieldGetter.getCodeTypeAndContent(code); + if (type == INTEGRATION_TYPE_BIBLIOGRAPHY) { + haveBibliography = true; + break; + } + } + + if (haveBibliography) { + yield fieldGetter.updateSession(); + yield session.editBibliography(this._doc); + } else { + var field = yield fieldGetter.addField(); + field.setCode("BIBL"); + yield fieldGetter.updateSession(); + } + return fieldGetter.updateDocument(FORCE_CITATIONS_FALSE, true, false); +}); + /** * Updates the citation data for all citations and bibliography entries. * @return {Promise} @@ -1312,24 +1346,29 @@ Zotero.Integration.Fields = function(session, doc, fieldErrorHandler) { */ Zotero.Integration.Fields.prototype.addField = function(note) { // Get citation types if necessary - if(!this._doc.canInsertField(this._session.data.prefs['fieldType'])) { + if (!this._doc.canInsertField(this._session.data.prefs['fieldType'])) { return Zotero.Promise.reject(new Zotero.Exception.Alert("integration.error.cannotInsertHere", [], "integration.error.title")); } var field = this._doc.cursorInField(this._session.data.prefs['fieldType']); - if(field) { - if(!this._doc.displayAlert(Zotero.getString("integration.replace"), + if (field) { + if (!this._doc.displayAlert(Zotero.getString("integration.replace"), DIALOG_ICON_STOP, DIALOG_BUTTONS_OK_CANCEL)) { return Zotero.Promise.reject(new Zotero.Exception.UserCancelled("inserting citation")); } } - if(!field) { - var field = this._doc.insertField(this._session.data.prefs['fieldType'], + if (!field) { + field = this._doc.insertField(this._session.data.prefs['fieldType'], (note ? this._session.data.prefs["noteType"] : 0)); } + // If fields already retrieved, further this.get() calls will returned the cached version + // So we append this field to that list + if (this._fields) { + this._fields.push(field); + } return Zotero.Promise.resolve(field); } @@ -1551,21 +1590,16 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu * modified since they were created, instead of showing a warning * @return {Promise} A promise resolved when the document is updated */ -Zotero.Integration.Fields.prototype.updateDocument = function(forceCitations, forceBibliography, +Zotero.Integration.Fields.prototype.updateDocument = Zotero.Promise.coroutine(function* (forceCitations, forceBibliography, ignoreCitationChanges) { // Update citations this._session.updateUpdateIndices(forceCitations); - var me = this; // Iterate through citations, yielding for UI updates - return Zotero.Promise.each(this._session._updateCitations(), () => {}).then(function() { - return Zotero.Promise.each( - me._updateDocument( - forceCitations, forceBibliography, ignoreCitationChanges - ), - () => {} - ); - }); -} + yield Zotero.Promise.each(this._session._updateCitations(), () => {}); + + yield Zotero.Promise.each( + this._updateDocument(forceCitations, forceBibliography, ignoreCitationChanges), () => {}); +}); /** * Helper function to update bibliographys and fields within a document diff --git a/test/tests/integrationTests.js b/test/tests/integrationTests.js index 170950b5b..f371a09d3 100644 --- a/test/tests/integrationTests.js +++ b/test/tests/integrationTests.js @@ -53,7 +53,10 @@ describe("Zotero.Integration", function () { DocumentPluginDummy.Field = function(doc) { this.doc = doc; - this.code = this.text = ''; + this.code = ''; + // This is actually required and current integration code depends on text being non-empty upon insertion. + // insertBibliography will fail if there is no placeholder text. + this.text = '{Placeholder}'; this.noteIndex = DocumentPluginDummy.Field.noteIndex++; this.wrappedJSObject = this; }; @@ -319,5 +322,35 @@ describe("Zotero.Integration", function () { }); }); }); + + describe('#addEditBibliography', function() { + var docID = this.fullTitle(); + beforeEach(function* () { + initDoc(docID); + yield execCommand('addEditCitation', docID); + }); + + it('should insert bibliography if no bibliography field present', function* () { + yield execCommand('addEditBibliography', docID); + var biblPresent = false; + for (let i = applications[docID].doc.fields.length-1; i >= 0; i--) { + let field = applications[docID].doc.fields[i]; + Zotero.debug(field.getCode(), 1); + if (field.getCode().includes("CSL_BIBLIOGRAPHY")) { + biblPresent = true; + break; + } + } + assert.isTrue(biblPresent); + }); + + it('should display the edit bibliography dialog if bibliography present', function* () { + yield execCommand('addEditBibliography', docID); + displayDialogStub.reset(); + yield execCommand('addEditBibliography', docID); + assert.isTrue(displayDialogStub.calledOnce); + assert.isTrue(displayDialogStub.lastCall.args[1].includes('editBibliographyDialog')); + }); + }); }); });