diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js
index a29cc134ac..b458b3d520 100644
--- a/chrome/content/zotero/fileInterface.js
+++ b/chrome/content/zotero/fileInterface.js
@@ -124,8 +124,6 @@ var Zotero_File_Interface = new function() {
this.exportItems = exportItems;
this.bibliographyFromCollection = bibliographyFromCollection;
this.bibliographyFromItems = bibliographyFromItems;
- this.copyItemsToClipboard = copyItemsToClipboard;
- this.copyCitationToClipboard = copyCitationToClipboard;
/**
* Creates Zotero.Translate instance and shows file picker for file export
@@ -399,84 +397,68 @@ var Zotero_File_Interface = new function() {
}
- /*
- * Copies HTML and text bibliography entries for passed items in given style
+ /**
+ * Copies HTML and text citations or bibliography entries for passed items in given style
*
* Does not check that items are actual references (and not notes or attachments)
+ *
+ * @param {Zotero.Item[]} items
+ * @param {String} style - Style id string (e.g., 'http://www.zotero.org/styles/apa')
+ * @param {String} locale - Locale (e.g., 'en-US')
+ * @param {Boolean} [asHTML=false] - Use HTML source for plain-text data
+ * @param {Boolean} [asCitations=false] - Copy citation cluster instead of bibliography
*/
- function copyItemsToClipboard(items, style, locale, asHTML, asCitations) {
+ this.copyItemsToClipboard = function (items, style, locale, asHTML, asCitations) {
// copy to clipboard
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
getService(Components.interfaces.nsIClipboard);
- var style = Zotero.Styles.get(style);
+ style = Zotero.Styles.get(style);
var cslEngine = style.getCiteProc(locale);
-
- // add HTML
- var bibliography = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "html", asCitations);
- var str = Components.classes["@mozilla.org/supports-string;1"].
- createInstance(Components.interfaces.nsISupportsString);
- str.data = bibliography;
- transferable.addDataFlavor("text/html");
- transferable.setTransferData("text/html", str, bibliography.length*2);
- // add text (or HTML source)
- if(!asHTML) {
- cslEngine = style.getCiteProc(locale);
- var bibliography = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "text", asCitations);
+ if (asCitations) {
+ cslEngine.updateItems(items.map(item => item.id));
+ var citation = {
+ citationItems: items.map(item => ({ id: item.id })),
+ properties: {}
+ };
+ var output = cslEngine.previewCitationCluster(citation, [], [], "html");
}
+ else {
+ var output = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "html");
+ }
+
+ // add HTML
var str = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
- str.data = bibliography;
+ str.data = output;
+ transferable.addDataFlavor("text/html");
+ transferable.setTransferData("text/html", str, output.length * 2);
+
+ // If not "Copy as HTML", add plaintext; otherwise use HTML from above and just mark as text
+ if(!asHTML) {
+ if (asCitations) {
+ output = cslEngine.previewCitationCluster(citation, [], [], "text");
+ }
+ else {
+ // Generate engine again to work around citeproc-js problem:
+ // https://github.com/zotero/zotero/commit/4a475ff3
+ cslEngine = style.getCiteProc(locale);
+ output = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "text");
+ }
+ }
+
+ var str = Components.classes["@mozilla.org/supports-string;1"].
+ createInstance(Components.interfaces.nsISupportsString);
+ str.data = output;
transferable.addDataFlavor("text/unicode");
- transferable.setTransferData("text/unicode", str, bibliography.length*2);
+ transferable.setTransferData("text/unicode", str, output.length * 2);
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
}
- /*
- * Copies HTML and text citations for passed items in given style
- *
- * Does not check that items are actual references (and not notes or attachments)
- *
- * if |asHTML| is true, copy HTML source as text
- */
- function copyCitationToClipboard(items, style, locale, asHTML) {
- // copy to clipboard
- var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
- createInstance(Components.interfaces.nsITransferable);
- var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
- getService(Components.interfaces.nsIClipboard);
-
- var style = Zotero.Styles.get(style).getCiteProc(locale);
- var citation = {
- citationItems: items.map(item => ({ id: item.id })),
- properties: {}
- };
-
- // add HTML
- var bibliography = style.previewCitationCluster(citation, [], [], "html");
- var str = Components.classes["@mozilla.org/supports-string;1"].
- createInstance(Components.interfaces.nsISupportsString);
- str.data = bibliography;
- transferable.addDataFlavor("text/html");
- transferable.setTransferData("text/html", str, bibliography.length*2);
-
- // add text (or HTML source)
- if(!asHTML) {
- var bibliography = style.previewCitationCluster(citation, [], [], "text");
- }
- var str = Components.classes["@mozilla.org/supports-string;1"].
- createInstance(Components.interfaces.nsISupportsString);
- str.data = bibliography;
- transferable.addDataFlavor("text/unicode");
- transferable.setTransferData("text/unicode", str, bibliography.length*2);
-
- clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
- }
-
/*
* Shows bibliography options and creates a bibliography
*/
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
index b52cbf9efd..67eeaed191 100644
--- a/chrome/content/zotero/zoteroPane.js
+++ b/chrome/content/zotero/zoteroPane.js
@@ -2090,12 +2090,9 @@ var ZoteroPane = new function()
var locale = format.locale ? format.locale : Zotero.Prefs.get('export.quickCopy.locale');
if (format.mode == 'bibliography') {
- if (asCitations) {
- Zotero_File_Interface.copyCitationToClipboard(items, format.id, locale, format.contentType == 'html');
- }
- else {
- Zotero_File_Interface.copyItemsToClipboard(items, format.id, locale, format.contentType == 'html');
- }
+ Zotero_File_Interface.copyItemsToClipboard(
+ items, format.id, locale, format.contentType == 'html', asCitations
+ );
}
else if (format.mode == 'export') {
// Copy citations doesn't work in export mode
diff --git a/test/tests/fileInterfaceTest.js b/test/tests/fileInterfaceTest.js
index 13d119deec..e364a2af88 100644
--- a/test/tests/fileInterfaceTest.js
+++ b/test/tests/fileInterfaceTest.js
@@ -86,4 +86,111 @@ describe("Zotero_File_Interface", function() {
assert.equal(item.itemTypeID, Zotero.ItemTypes.getID('journalArticle'));
assert.equal(item.getField('title'), "Test");
});
+
+ describe("#copyItemsToClipboard()", function () {
+ var clipboardService, item1, item2;
+
+ before(function* () {
+ yield Zotero.Styles.init();
+
+ clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"]
+ .getService(Components.interfaces.nsIClipboard);
+
+ item1 = createUnsavedDataObject('item', { title: "A" });
+ item1.setField('date', '2016');
+ yield item1.saveTx();
+ item2 = createUnsavedDataObject('item', { title: "B" });
+ item2.setField('date', '2016');
+ yield item2.saveTx();
+ });
+
+ function getDataForFlavor(flavor) {
+ var transferable = Components.classes["@mozilla.org/widget/transferable;1"]
+ .createInstance(Components.interfaces.nsITransferable);
+ transferable.init(null);
+ transferable.addDataFlavor(flavor);
+ clipboardService.getData(transferable, Components.interfaces.nsIClipboard.kGlobalClipboard);
+ var str = {};
+ transferable.getTransferData(flavor, str, {})
+ return str.value.QueryInterface(Components.interfaces.nsISupportsString).data;
+ }
+
+ //
+ // Non-"Copy as HTML" mode
+ //
+ it("should copy HTML and text citations to the clipboard", function* () {
+ win.Zotero_File_Interface.copyItemsToClipboard(
+ [item1, item2],
+ 'http://www.zotero.org/styles/apa',
+ 'en-US',
+ false,
+ true
+ );
+
+ // HTML
+ var str = getDataForFlavor('text/html');
+ assert.equal(str, '(A, 2016, B, 2016)');
+
+ // Plain text
+ str = getDataForFlavor('text/unicode');
+ assert.equal(str, '(A, 2016, B, 2016)');
+ });
+
+ it("should copy HTML and text bibliography to the clipboard", function* () {
+ win.Zotero_File_Interface.copyItemsToClipboard(
+ [item1, item2],
+ 'http://www.zotero.org/styles/apa',
+ 'en-US'
+ );
+
+ var str = getDataForFlavor('text/html');
+ assert.include(str, 'line-height');
+ assert.include(str, 'A');
+ assert.include(str, 'B');
+
+ // Plain text
+ str = getDataForFlavor('text/unicode');
+ assert.equal(str, 'A. (2016).\nB. (2016).\n');
+ });
+
+ //
+ // "Copy as HTML" mode
+ //
+ it("should copy HTML and HTML source citations to the clipboard", function* () {
+ win.Zotero_File_Interface.copyItemsToClipboard(
+ [item1, item2],
+ 'http://www.zotero.org/styles/apa',
+ 'en-US',
+ true,
+ true
+ );
+
+ var str = getDataForFlavor('text/html');
+ assert.equal(str, '(A, 2016, B, 2016)');
+
+ // Plain text
+ str = getDataForFlavor('text/unicode');
+ assert.equal(str, '(A, 2016, B, 2016)');
+ });
+
+ it("should copy HTML and HTML source bibliography to the clipboard", function* () {
+ win.Zotero_File_Interface.copyItemsToClipboard(
+ [item1, item2],
+ 'http://www.zotero.org/styles/apa',
+ 'en-US',
+ true
+ );
+
+ var str = getDataForFlavor('text/html');
+ assert.include(str, 'line-height');
+ assert.include(str, 'A');
+ assert.include(str, 'B');
+
+ // Plain text
+ str = getDataForFlavor('text/unicode');
+ assert.include(str, 'line-height');
+ assert.include(str, 'A');
+ assert.include(str, 'B');
+ });
+ });
});
\ No newline at end of file