diff --git a/chrome/content/zotero/exportOptions.js b/chrome/content/zotero/exportOptions.js
index 9919f9915f..2474815713 100644
--- a/chrome/content/zotero/exportOptions.js
+++ b/chrome/content/zotero/exportOptions.js
@@ -49,8 +49,7 @@ var Zotero_File_Interface_Export = new function() {
var addedOptions = new Object();
- var translators = window.arguments[0].translators;
- translators.sort(function(a, b) { return a.label.localeCompare(b.label) });
+ var { translators, exportingNotes } = window.arguments[0];
// get format popup
var formatPopup = document.getElementById("format-popup");
@@ -58,7 +57,9 @@ var Zotero_File_Interface_Export = new function() {
var optionsBox = document.getElementById("translator-options");
var charsetBox = document.getElementById("charset-box");
- var selectedTranslator = Zotero.Prefs.get("export.lastTranslator");
+ var selectedTranslator = Zotero.Prefs.get(
+ exportingNotes ? "export.lastNoteTranslator" : "export.lastTranslator"
+ );
// add styles to format popup
for(var i in translators) {
@@ -72,7 +73,12 @@ var Zotero_File_Interface_Export = new function() {
// presented to the user
// get readable name for option
try {
- var optionLabel = Zotero.getString("exportOptions."+option);
+ if (option == 'includeAppLinks') {
+ var optionLabel = Zotero.getString("exportOptions." + option, Zotero.appName);
+ }
+ else {
+ var optionLabel = Zotero.getString("exportOptions." + option);
+ }
} catch(e) {
var optionLabel = option;
}
@@ -121,7 +127,9 @@ var Zotero_File_Interface_Export = new function() {
_charsets = Zotero_Charset_Menu.populate(document.getElementById(OPTION_PREFIX+"exportCharset"), true);
}
- this.updateOptions(Zotero.Prefs.get("export.translatorSettings"));
+ this.updateOptions(Zotero.Prefs.get(
+ exportingNotes ? "export.noteTranslatorSettings" : "export.translatorSettings"
+ ));
}
/*
@@ -224,7 +232,10 @@ var Zotero_File_Interface_Export = new function() {
window.arguments[0].selectedTranslator = window.arguments[0].translators[index];
// save selected translator
- Zotero.Prefs.set("export.lastTranslator", window.arguments[0].translators[index].translatorID);
+ Zotero.Prefs.set(
+ window.arguments[0].exportingNotes ? "export.lastNoteTranslator" : "export.lastTranslator",
+ window.arguments[0].translators[index].translatorID
+ );
// set options on selected translator and generate optionString
var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions;
@@ -253,7 +264,10 @@ var Zotero_File_Interface_Export = new function() {
// save options
var optionString = JSON.stringify(displayOptions);
- Zotero.Prefs.set("export.translatorSettings", optionString);
+ Zotero.Prefs.set(
+ window.arguments[0].exportingNotes ? "export.noteTranslatorSettings" : "export.translatorSettings",
+ optionString
+ );
}
/*
diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js
index 9e0e228048..39d0be740a 100644
--- a/chrome/content/zotero/fileInterface.js
+++ b/chrome/content/zotero/fileInterface.js
@@ -49,9 +49,46 @@ var Zotero_File_Exporter = function() {
Zotero_File_Exporter.prototype.save = async function () {
var translation = new Zotero.Translate.Export();
var translators = await translation.getTranslators();
+
+ if (!this.items) {
+ return;
+ }
+
+ let exportingNotes = this.items.every(item => item.isNote() || item.isAttachment());
+ // Keep only note export and Zotero RDF translators, if all items are notes or attachments
+ if (exportingNotes) {
+ translators = translators.filter((translator) => {
+ return (
+ translator.translatorID === '14763d24-8ba0-45df-8f52-b8d1108e7ac9'
+ || translator.configOptions && translator.configOptions.noteTranslator
+ );
+ });
+ }
+ // Otherwise exclude note export translators
+ else {
+ translators = translators.filter(t => !t.configOptions || !t.configOptions.noteTranslator);
+ }
+
+ translators.sort((a, b) => a.label.localeCompare(b.label));
+
+ // Remove "Note" prefix from Note Markdown and Note HTML translators
+ let markdownTranslator = translators.find(
+ t => t.translatorID == Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN
+ );
+ if (markdownTranslator) {
+ markdownTranslator.label = 'Markdown';
+ // Move Note Markdown translator to the top
+ translators.unshift(...translators.splice(translators.indexOf(markdownTranslator), 1));
+ }
+ let htmlTranslator = translators.find(
+ t => t.translatorID == Zotero.Translators.TRANSLATOR_ID_NOTE_HTML
+ );
+ if (htmlTranslator) {
+ htmlTranslator.label = 'HTML';
+ }
// present options dialog
- var io = {translators:translators}
+ var io = { translators, exportingNotes };
window.openDialog("chrome://zotero/content/exportOptions.xul",
"_blank", "chrome,modal,centerscreen,resizable=no", io);
if(!io.selectedTranslator) {
@@ -89,33 +126,34 @@ Zotero_File_Exporter.prototype.save = async function () {
translation.setLibraryID(this.libraryID);
}
+ async function _exportDone(obj, worked) {
+ // Close the items exported indicator
+ Zotero_File_Interface.Progress.close();
+
+ if (!worked) {
+ Zotero.alert(
+ null,
+ Zotero.getString('general.error'),
+ Zotero.getString('fileInterface.exportError')
+ );
+ Zotero_File_Interface.Progress.close();
+ return;
+ }
+ }
+
translation.setLocation(Zotero.File.pathToFile(fp.file));
translation.setTranslator(io.selectedTranslator);
translation.setDisplayOptions(io.displayOptions);
translation.setHandler("itemDone", function () {
Zotero.updateZoteroPaneProgressMeter(translation.getProgress());
});
- translation.setHandler("done", this._exportDone);
+ translation.setHandler("done", _exportDone);
Zotero_File_Interface.Progress.show(
Zotero.getString("fileInterface.itemsExported")
);
translation.translate()
};
-
-/*
- * Closes the items exported indicator
- */
-Zotero_File_Exporter.prototype._exportDone = function(obj, worked) {
- Zotero_File_Interface.Progress.close();
-
- if(!worked) {
- Zotero.alert(
- null,
- Zotero.getString('general.error'),
- Zotero.getString("fileInterface.exportError")
- );
- }
-}
+
/****Zotero_File_Interface****
**
@@ -175,36 +213,91 @@ var Zotero_File_Interface = new function() {
*/
function exportItems() {
var exporter = new Zotero_File_Exporter();
-
- exporter.items = ZoteroPane_Local.getSelectedItems();
+ let itemIDs = ZoteroPane_Local.getSelectedItems(true);
+ // Get selected item IDs in the item tree order
+ itemIDs = ZoteroPane_Local.getSortedItems(true).filter(id => itemIDs.includes(id));
+ exporter.items = Zotero.Items.get(itemIDs);
if(!exporter.items || !exporter.items.length) throw("no items currently selected");
exporter.save();
}
+
/*
* exports items to clipboard
*/
function exportItemsToClipboard(items, translatorID) {
- var translation = new Zotero.Translate.Export();
- translation.setItems(items);
- translation.setTranslator(translatorID);
- translation.setHandler("done", _copyToClipboard);
- translation.translate();
- }
-
- /*
- * handler when done exporting items to clipboard
- */
- function _copyToClipboard(obj, worked) {
- if(!worked) {
- Zotero.alert(
- null, Zotero.getString('general.error'), Zotero.getString("fileInterface.exportError")
- );
- } else {
- Components.classes["@mozilla.org/widget/clipboardhelper;1"]
- .getService(Components.interfaces.nsIClipboardHelper)
- .copyString(obj.string.replace(/\r\n/g, "\n"));
+ function _translate(items, translatorID, callback) {
+ let translation = new Zotero.Translate.Export();
+ translation.setItems(items.slice());
+ translation.setTranslator(translatorID);
+ translation.setHandler("done", callback);
+ translation.translate();
+ }
+
+ // If translating with virtual "Markdown + Rich Text" translator, use Note Markdown and
+ // Note HTML instead
+ if (translatorID == Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT) {
+ translatorID = Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN;
+ _translate(items, translatorID, (obj, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+ translatorID = Zotero.Translators.TRANSLATOR_ID_NOTE_HTML;
+ _translate(items, translatorID, (obj2, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+
+ let text = obj.string.replace(/\r\n/g, '\n');
+ let html = obj2.string.replace(/\r\n/g, '\n');
+
+ // copy to clipboard
+ let transferable = Components.classes['@mozilla.org/widget/transferable;1']
+ .createInstance(Components.interfaces.nsITransferable);
+ let clipboardService = Components.classes['@mozilla.org/widget/clipboard;1']
+ .getService(Components.interfaces.nsIClipboard);
+
+ // Add Text
+ let str = Components.classes['@mozilla.org/supports-string;1']
+ .createInstance(Components.interfaces.nsISupportsString);
+ str.data = text;
+ transferable.addDataFlavor('text/unicode');
+ transferable.setTransferData('text/unicode', str, text.length * 2);
+
+ // Add HTML
+ str = Components.classes['@mozilla.org/supports-string;1']
+ .createInstance(Components.interfaces.nsISupportsString);
+ str.data = html;
+ transferable.addDataFlavor('text/html');
+ transferable.setTransferData('text/html', str, html.length * 2);
+
+ clipboardService.setData(
+ transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard
+ );
+ });
+ });
+ }
+ else {
+ _translate(items, translatorID, (obj, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+ let text = obj.string;
+ // For Note HTML translator use body content only
+ if (translatorID == Zotero.Translators.TRANSLATOR_ID_NOTE_HTML) {
+ let parser = Components.classes['@mozilla.org/xmlextras/domparser;1']
+ .createInstance(Components.interfaces.nsIDOMParser);
+ let doc = parser.parseFromString(text, 'text/html');
+ text = doc.body.innerHTML;
+ }
+ Components.classes['@mozilla.org/widget/clipboardhelper;1']
+ .getService(Components.interfaces.nsIClipboardHelper)
+ .copyString(text.replace(/\r\n/g, '\n'));
+ });
}
}
diff --git a/chrome/content/zotero/itemTree.jsx b/chrome/content/zotero/itemTree.jsx
index d9154e0e8c..8bcbaf3193 100644
--- a/chrome/content/zotero/itemTree.jsx
+++ b/chrome/content/zotero/itemTree.jsx
@@ -1891,6 +1891,8 @@ var ItemTree = class ItemTree extends LibraryTree {
event.dataTransfer.setDragImage(this._dragImageContainer, 0, 0);
var itemIDs = this.getSelectedItems(true);
+ // Get selected item IDs in the item tree order
+ itemIDs = this.getSortedItems(true).filter(id => itemIDs.includes(id));
event.dataTransfer.setData("zotero/item", itemIDs);
var items = Zotero.Items.get(itemIDs);
@@ -1946,22 +1948,53 @@ var ItemTree = class ItemTree extends LibraryTree {
// Get Quick Copy format for current URL (set via /ping from connector)
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
- Zotero.debug("Dragging with format " + format);
-
- var exportCallback = function(obj, worked) {
- if (!worked) {
- Zotero.log(Zotero.getString("fileInterface.exportError"), 'warning');
- return;
- }
-
- var text = obj.string.replace(/\r\n/g, "\n");
- event.dataTransfer.setData("text/plain", text);
+ // If all items are notes, use one of the note export translators
+ if (items.every(item => item.isNote())) {
+ format = Zotero.QuickCopy.getNoteFormat();
}
+ Zotero.debug("Dragging with format " + format);
format = Zotero.QuickCopy.unserializeSetting(format);
try {
if (format.mode == 'export') {
- Zotero.QuickCopy.getContentFromItems(items, format, exportCallback);
+ // If exporting with virtual "Markdown + Rich Text" translator, call Note Markdown
+ // and Note HTML translators instead
+ if (format.id === Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT) {
+ let markdownFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN };
+ let htmlFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML };
+ Zotero.QuickCopy.getContentFromItems(items, markdownFormat, (obj, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+ Zotero.QuickCopy.getContentFromItems(items, htmlFormat, (obj2, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+ event.dataTransfer.setData('text/plain', obj.string.replace(/\r\n/g, '\n'));
+ event.dataTransfer.setData('text/html', obj2.string.replace(/\r\n/g, '\n'));
+ });
+ });
+ }
+ else {
+ Zotero.QuickCopy.getContentFromItems(items, format, (obj, worked) => {
+ if (!worked) {
+ Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
+ return;
+ }
+ var text = obj.string.replace(/\r\n/g, '\n');
+ // For Note HTML translator use body content only
+ if (format.id == Zotero.Translators.TRANSLATOR_ID_NOTE_HTML) {
+ // Use body content only
+ let parser = Cc['@mozilla.org/xmlextras/domparser;1']
+ .createInstance(Ci.nsIDOMParser);
+ let doc = parser.parseFromString(text, 'text/html');
+ text = doc.body.innerHTML;
+ }
+ event.dataTransfer.setData('text/plain', text);
+ });
+ }
}
else if (format.mode == 'bibliography') {
var content = Zotero.QuickCopy.getContentFromItems(items, format, null, event.shiftKey);
diff --git a/chrome/content/zotero/preferences/preferences_export.jsx b/chrome/content/zotero/preferences/preferences_export.jsx
index 6176f2f951..fa60a58064 100644
--- a/chrome/content/zotero/preferences/preferences_export.jsx
+++ b/chrome/content/zotero/preferences/preferences_export.jsx
@@ -35,6 +35,7 @@ Zotero_Preferences.Export = {
init: Zotero.Promise.coroutine(function* () {
this.updateQuickCopyInstructions();
yield this.populateQuickCopyList();
+ yield this.populateNoteQuickCopyList();
var charsetMenu = document.getElementById("zotero-import-charsetMenu");
var charsetMap = Zotero_Charset_Menu.populate(charsetMenu, false);
@@ -51,6 +52,8 @@ Zotero_Preferences.Export = {
var collation = Zotero.getLocaleCollation();
return collation.compareString(1, a.label, b.label);
});
+ // Exclude note export translators
+ translators = translators.filter(x => !x.configOptions || !x.configOptions.noteTranslator);
return translators;
},
@@ -82,6 +85,86 @@ Zotero_Preferences.Export = {
}),
+ /*
+ * Builds the note Quick Copy drop-down from the current global pref
+ */
+ populateNoteQuickCopyList: async function () {
+ // Initialize default format drop-down
+ var format = Zotero.Prefs.get("export.noteQuickCopy.setting");
+ format = Zotero.QuickCopy.unserializeSetting(format);
+ var menulist = document.getElementById("zotero-noteQuickCopy-menu");
+ menulist.setAttribute('preference', "pref-noteQuickCopy-setting");
+
+ if (!format) {
+ format = menulist.value;
+ }
+
+ format = Zotero.QuickCopy.unserializeSetting(format);
+
+ menulist.selectedItem = null;
+ menulist.removeAllItems();
+
+ var popup = document.createElement('menupopup');
+ menulist.appendChild(popup);
+
+ // add export formats to list
+ var translation = new Zotero.Translate("export");
+ var translators = await translation.getTranslators();
+
+ translators.sort((a, b) => a.label.localeCompare(b.label));
+
+ // Remove "Note" prefix from Note HTML translator
+ let htmlTranslator = translators.find(
+ x => x.translatorID == Zotero.Translators.TRANSLATOR_ID_NOTE_HTML
+ );
+ if (htmlTranslator) {
+ htmlTranslator.label = 'HTML';
+ }
+
+ // Make sure virtual "Markdown + Rich Text" translator doesn't actually exist
+ translators = translators.filter(
+ x => x.translatorID != Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT
+ );
+
+ let markdownTranslatorIdx = translators.findIndex(
+ x => x.translatorID == Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN
+ );
+ // Make sure we actually have both translators
+ if (markdownTranslatorIdx != -1 && htmlTranslator) {
+ // Exclude standalone Note Markdown translator
+ translators.splice(markdownTranslatorIdx, 1);
+ // Add virtual "Markdown + Rich Text" translator to the top
+ translators.unshift({
+ translatorID: Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT,
+ label: 'Markdown + ' + Zotero.getString('general.richText'),
+ configOptions: {
+ noteTranslator: true
+ }
+ });
+ }
+
+ translators.forEach(function (translator) {
+ // Allow only note export translators
+ if (!translator.configOptions || !translator.configOptions.noteTranslator) {
+ return;
+ }
+
+ var val = JSON.stringify({ mode: 'export', id: translator.translatorID });
+ var itemNode = document.createElement('menuitem');
+ itemNode.setAttribute('value', val);
+ itemNode.setAttribute('label', translator.label);
+ // itemNode.setAttribute('oncommand', 'Zotero_Preferences.Export.updateQuickCopyUI()');
+ popup.appendChild(itemNode);
+
+ if (format.mode == 'export' && format.id == translator.translatorID) {
+ menulist.selectedItem = itemNode;
+ }
+ });
+
+ menulist.click();
+ },
+
+
/*
* Builds a Quick Copy drop-down
*/
diff --git a/chrome/content/zotero/preferences/preferences_export.xul b/chrome/content/zotero/preferences/preferences_export.xul
index 8881e864fc..c8b7e4ad0c 100644
--- a/chrome/content/zotero/preferences/preferences_export.xul
+++ b/chrome/content/zotero/preferences/preferences_export.xul
@@ -41,6 +41,7 @@
+
@@ -53,7 +54,7 @@
-
+
@@ -68,8 +69,13 @@
+
+
+
+
+
-
+
diff --git a/chrome/content/zotero/standalone/standalone.js b/chrome/content/zotero/standalone/standalone.js
index 5c72c0a12b..b229dee234 100644
--- a/chrome/content/zotero/standalone/standalone.js
+++ b/chrome/content/zotero/standalone/standalone.js
@@ -306,42 +306,45 @@ const ZoteroStandalone = new function() {
this.updateQuickCopyOptions = function () {
- var selected = false;
+ var selected = [];
let win = Zotero.getMainWindow();
if (win) {
if (win.Zotero_Tabs.selectedID == 'zotero-pane') {
try {
- selected = win.ZoteroPane
- .getSelectedItems()
- .filter(item => item.isRegularItem())
- .length;
+ selected = win.ZoteroPane.getSelectedItems();
}
catch (e) {
}
- win.ZoteroPane.updateQuickCopyCommands(win.ZoteroPane.getSelectedItems());
+ win.ZoteroPane.updateQuickCopyCommands(selected);
}
else {
let reader = Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID);
if (reader) {
let item = Zotero.Items.get(reader.itemID);
- selected = !!item.parentItemID;
+ selected = item.parentItem && [item.parentItem] || [];
item = item.parentItem || item;
win.ZoteroPane.updateQuickCopyCommands([item]);
}
}
}
-
+
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
+ var exportingNotes = selected.every(item => item.isNote() || item.isAttachment());
+ if (exportingNotes) {
+ format = Zotero.QuickCopy.getNoteFormat();
+ }
format = Zotero.QuickCopy.unserializeSetting(format);
var copyCitation = document.getElementById('menu_copyCitation');
var copyBibliography = document.getElementById('menu_copyBibliography');
var copyExport = document.getElementById('menu_copyExport');
+ var copyNote = document.getElementById('menu_copyNote');
- copyCitation.hidden = !selected || format.mode != 'bibliography';
- copyBibliography.hidden = !selected || format.mode != 'bibliography';
- copyExport.hidden = !selected || format.mode != 'export';
+ copyCitation.hidden = !selected.length || format.mode != 'bibliography';
+ copyBibliography.hidden = !selected.length || format.mode != 'bibliography';
+ copyExport.hidden = !selected.length || format.mode != 'export' || exportingNotes;
+ copyNote.hidden = !selected.length || format.mode != 'export' || !exportingNotes;
if (format.mode == 'export') {
try {
let obj = Zotero.Translators.get(format.id);
diff --git a/chrome/content/zotero/standalone/standalone.xul b/chrome/content/zotero/standalone/standalone.xul
index ab88817d6d..62e52e1835 100644
--- a/chrome/content/zotero/standalone/standalone.xul
+++ b/chrome/content/zotero/standalone/standalone.xul
@@ -210,6 +210,11 @@
key="key_copyBibliography"
command="cmd_zotero_copyBibliography"
hidden="true"/>
+
diff --git a/chrome/content/zotero/xpcom/quickCopy.js b/chrome/content/zotero/xpcom/quickCopy.js
index 034639d731..8f4bd72ebe 100644
--- a/chrome/content/zotero/xpcom/quickCopy.js
+++ b/chrome/content/zotero/xpcom/quickCopy.js
@@ -43,6 +43,10 @@ Zotero.QuickCopy = new function() {
this._prefObserverID = Zotero.Prefs.registerObserver(
"export.quickCopy.setting", _loadOutputFormat
);
+
+ this._prefObserverID = Zotero.Prefs.registerObserver(
+ "export.noteQuickCopy.setting", _loadNoteOutputFormat
+ );
_initialized = true;
}
@@ -59,6 +63,7 @@ Zotero.QuickCopy = new function() {
_initPromise = Zotero.Promise.each(
[
() => _loadOutputFormat(),
+ () => _loadNoteOutputFormat(),
() => this.loadSiteSettings()
],
f => f()
@@ -157,6 +162,11 @@ Zotero.QuickCopy = new function() {
return '';
});
+ this.getNoteFormat = function () {
+ var pref = Zotero.Prefs.get('export.noteQuickCopy.setting');
+ pref = JSON.stringify(this.unserializeSetting(pref));
+ return pref;
+ };
this.getFormatFromURL = function(url) {
var quickCopyPref = Zotero.Prefs.get("export.quickCopy.setting");
@@ -256,167 +266,15 @@ Zotero.QuickCopy = new function() {
if (format.mode == 'export') {
var translation = new Zotero.Translate.Export;
translation.noWait = true; // needed not to break drags
- translation.setItems(items);
+ // Allow to reuse items array
+ translation.setItems(items.slice());
translation.setTranslator(format.id);
translation.setHandler("done", callback);
translation.translate();
return true;
}
else if (format.mode == 'bibliography') {
- // Move notes to separate array
- var allNotes = true;
- var notes = [];
- for (var i=0; i 1) {
- var divs = Zotero.Utilities.xpath(container, "div"),
- textDivs = Zotero.Utilities.xpath(textContainer, "div");
- for (var i=1, len=divs.length; i"
- + "p { margin-top:.1pt;margin-right:0in;margin-bottom:.1pt;margin-left:0in; line-height: 200%; }"
- + "li { margin-top:.1pt;margin-right:0in;margin-bottom:.1pt;margin-left:0in; line-height: 200%; }"
- + "blockquote p { margin-left: 11px; margin-right: 11px }"
- + ""
- + "\n"
- + container.outerHTML;
- }
- else {
- var copyHTML = container.outerHTML;
- }
-
- var content = {
- text: format.contentType == "html" ? html : text,
- html: copyHTML
- };
-
- return content;
- }
+ items = items.filter(item => !item.isNote());
// determine locale preference
var locale = format.locale ? format.locale : Zotero.Prefs.get('export.quickCopy.locale');
@@ -458,6 +316,20 @@ Zotero.QuickCopy = new function() {
});
+ var _loadNoteOutputFormat = async function () {
+ var format = Zotero.Prefs.get("export.noteQuickCopy.setting");
+ format = Zotero.QuickCopy.unserializeSetting(format);
+ // If virtual "Markdown + Rich Text" translator is selected, preload Note Markdown and
+ // Note HTML translators
+ if (format.id == Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT) {
+ await _preloadFormat({ mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN });
+ await _preloadFormat({ mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML });
+ return;
+ }
+ return _preloadFormat(format);
+ };
+
+
var _preloadFormat = async function (format) {
format = Zotero.QuickCopy.unserializeSetting(format);
if (format.mode == 'export') {
diff --git a/chrome/content/zotero/xpcom/translate b/chrome/content/zotero/xpcom/translate
index 85b39a5be5..b75bc2550a 160000
--- a/chrome/content/zotero/xpcom/translate
+++ b/chrome/content/zotero/xpcom/translate
@@ -1 +1 @@
-Subproject commit 85b39a5be5bb59c5ee5e7447609273a29ea0b799
+Subproject commit b75bc2550ae2df3bb307e7abf0d3abad96f79c82
diff --git a/chrome/content/zotero/xpcom/translation/translate_firefox.js b/chrome/content/zotero/xpcom/translation/translate_firefox.js
index 00160e28ef..2a55aa5eb8 100644
--- a/chrome/content/zotero/xpcom/translation/translate_firefox.js
+++ b/chrome/content/zotero/xpcom/translation/translate_firefox.js
@@ -809,9 +809,20 @@ Zotero.Translate.IO.Write.prototype = {
this._charset = charset;
},
+ /**
+ * Set a function to modify data on each write()
+ */
+ setDataProcessor: function (processor) {
+ this._processor = processor;
+ },
+
"write":function(data) {
if(!this._charset) this.setCharacterSet("UTF-8");
+ if (this._processor) {
+ data = this._processor(data);
+ }
+
if(!this._writtenToStream && this._charset.substr(this._charset.length-4) == "xBOM"
&& BOMs[this._charset.substr(0, this._charset.length-4).toUpperCase()]) {
// If stream has not yet been written to, and a UTF type has been selected, write BOM
diff --git a/chrome/content/zotero/xpcom/translation/translate_item.js b/chrome/content/zotero/xpcom/translation/translate_item.js
index ee52e86528..fd8e6a7c9c 100644
--- a/chrome/content/zotero/xpcom/translation/translate_item.js
+++ b/chrome/content/zotero/xpcom/translation/translate_item.js
@@ -1014,7 +1014,10 @@ Zotero.Translate.ItemGetter = function() {
Zotero.Translate.ItemGetter.prototype = {
setItems: function (items) {
this._itemsLeft = items;
- this._itemsLeft.sort((a, b) => a.id - b.id);
+ // Don't sort items if doing notes export
+ if (!items.every(item => item.isNote() || item.isAttachment())) {
+ this._itemsLeft.sort((a, b) => a.id - b.id);
+ }
this.numItems = this._itemsLeft.length;
},
diff --git a/chrome/content/zotero/xpcom/translation/translators.js b/chrome/content/zotero/xpcom/translation/translators.js
index c566551a46..3bafc88b33 100644
--- a/chrome/content/zotero/xpcom/translation/translators.js
+++ b/chrome/content/zotero/xpcom/translation/translators.js
@@ -34,6 +34,10 @@ Zotero.Translators = new function() {
var _initialized = false;
var _initializationDeferred = false;
+ this.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT = 'a45eca67-1ee8-45e5-b4c6-23fb8a852873';
+ this.TRANSLATOR_ID_NOTE_MARKDOWN = '1412e9e2-51e1-42ec-aa35-e036a895534b';
+ this.TRANSLATOR_ID_NOTE_HTML = '897a81c2-9f60-4bec-ae6b-85a5030b8be5';
+
/**
* Initializes translator cache, loading all translator metadata into memory
*
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
index 4453d14939..f84398f5d3 100644
--- a/chrome/content/zotero/zoteroPane.js
+++ b/chrome/content/zotero/zoteroPane.js
@@ -1605,18 +1605,28 @@ var ZoteroPane = new function()
/**
* Update the elements that control the shortcut keys and the enabled state of the
- * "Copy Citation"/"Copy Bibliography"/"Copy as" menu options. When disabled, the shortcuts are
+ * "Copy Citation"/"Copy Bibliography"/"Copy as"/"Copy Note" menu options. When disabled, the shortcuts are
* still caught in handleKeyPress so that we can show an alert about not having references selected.
*/
this.updateQuickCopyCommands = function (selectedItems) {
- var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
- format = Zotero.QuickCopy.unserializeSetting(format);
- if (format.mode == 'bibliography') {
- var canCopy = selectedItems.some(item => item.isRegularItem());
+ let canCopy = false;
+ // If all items are notes/attachments and at least one note is not empty
+ if (selectedItems.every(item => item.isNote() || item.isAttachment())) {
+ if (selectedItems.some(item => item.note)) {
+ canCopy = true;
+ }
}
else {
- var canCopy = true;
+ let format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
+ format = Zotero.QuickCopy.unserializeSetting(format);
+ if (format.mode == 'bibliography') {
+ canCopy = selectedItems.some(item => item.isRegularItem());
+ }
+ else {
+ canCopy = true;
+ }
}
+
document.getElementById('cmd_zotero_copyCitation').setAttribute('disabled', !canCopy);
document.getElementById('cmd_zotero_copyBibliography').setAttribute('disabled', !canCopy);
};
@@ -2075,7 +2085,10 @@ var ZoteroPane = new function()
this.copySelectedItemsToClipboard = function (asCitations) {
var items = [];
if (Zotero_Tabs.selectedID == 'zotero-pane') {
- items = this.getSelectedItems();
+ let itemIDs = this.getSelectedItems(true);
+ // Get selected item IDs in the item tree order
+ itemIDs = this.getSortedItems(true).filter(id => itemIDs.includes(id));
+ items = Zotero.Items.get(itemIDs);
}
else {
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
@@ -2092,6 +2105,9 @@ var ZoteroPane = new function()
}
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
+ if (items.every(item => item.isNote() || item.isAttachment())) {
+ format = Zotero.QuickCopy.getNoteFormat();
+ }
format = Zotero.QuickCopy.unserializeSetting(format);
// In bibliography mode, remove notes and attachments
@@ -2966,6 +2982,12 @@ var ZoteroPane = new function()
disable.push(m.showInLibrary, m.duplicateItem, m.removeItems,
m.moveToTrash, m.deleteFromLibrary, m.exportItems, m.createBib, m.loadReport);
}
+
+ if (!disable.includes(m.exportItems)
+ && items.every(item => item.isNote() || item.isAttachment())
+ && !items.some(item => item.note)) {
+ disable.push(m.exportItems);
+ }
if ((!collectionTreeRow.editable || collectionTreeRow.isPublications()) && !collectionTreeRow.isFeed()) {
for (let i in m) {
diff --git a/chrome/locale/en-US/zotero/preferences.dtd b/chrome/locale/en-US/zotero/preferences.dtd
index 06c3647b02..96812d7fe0 100644
--- a/chrome/locale/en-US/zotero/preferences.dtd
+++ b/chrome/locale/en-US/zotero/preferences.dtd
@@ -104,7 +104,8 @@
-
+
+
diff --git a/chrome/locale/en-US/zotero/standalone.dtd b/chrome/locale/en-US/zotero/standalone.dtd
index c493639259..7f94eb8ebc 100644
--- a/chrome/locale/en-US/zotero/standalone.dtd
+++ b/chrome/locale/en-US/zotero/standalone.dtd
@@ -37,6 +37,7 @@
+
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
index 143530f973..f6bd87611b 100644
--- a/chrome/locale/en-US/zotero/zotero.properties
+++ b/chrome/locale/en-US/zotero/zotero.properties
@@ -87,6 +87,7 @@ general.languages = Languages
general.default = Default
general.custom = Custom
general.loading = Loading…
+general.richText = Rich Text
general.yellow = Yellow
general.red = Red
@@ -826,6 +827,7 @@ fulltext.indexState.queued = Queued
exportOptions.exportNotes = Export Notes
exportOptions.exportFileData = Export Files
exportOptions.includeAnnotations = Include Annotations
+exportOptions.includeAppLinks = Include %S Links
exportOptions.useJournalAbbreviation = Use Journal Abbreviation
charset.UTF8withoutBOM = Unicode (UTF-8 without BOM)
charset.autoDetect = (auto detect)
diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js
index 48e83821a9..5596a1e5d0 100644
--- a/defaults/preferences/zotero.js
+++ b/defaults/preferences/zotero.js
@@ -109,6 +109,8 @@ pref("extensions.zotero.report.combineChildItems", true);
// Export and citation settings
pref("extensions.zotero.export.lastTranslator", "14763d24-8ba0-45df-8f52-b8d1108e7ac9");
pref("extensions.zotero.export.translatorSettings", "true,false");
+pref("extensions.zotero.export.lastNoteTranslator", "1412e9e2-51e1-42ec-aa35-e036a895534b");
+pref("extensions.zotero.export.noteTranslatorSettings", "");
pref("extensions.zotero.export.lastStyle", "http://www.zotero.org/styles/chicago-note-bibliography");
pref("extensions.zotero.export.bibliographySettings", "save-as-rtf");
pref("extensions.zotero.export.displayCharsetOption", true);
@@ -121,10 +123,8 @@ pref("extensions.zotero.rtfScan.lastOutputFile", "");
pref("extensions.zotero.export.quickCopy.setting", "bibliography=http://www.zotero.org/styles/chicago-note-bibliography");
pref("extensions.zotero.export.quickCopy.dragLimit", 50);
-pref("extensions.zotero.export.quickCopy.quoteBlockquotes.plainText", true);
-pref("extensions.zotero.export.quickCopy.quoteBlockquotes.richText", true);
-pref("extensions.zotero.export.quickCopy.compatibility.indentBlockquotes", true);
-pref("extensions.zotero.export.quickCopy.compatibility.word", false);
+
+pref("extensions.zotero.export.noteQuickCopy.setting", '{"mode": "export", "id": "a45eca67-1ee8-45e5-b4c6-23fb8a852873"}');
// Integration settings
pref("extensions.zotero.integration.port", 50001);
diff --git a/test/tests/quickCopyTest.js b/test/tests/quickCopyTest.js
index d1f812ee72..7bd42a999a 100644
--- a/test/tests/quickCopyTest.js
+++ b/test/tests/quickCopyTest.js
@@ -73,17 +73,6 @@ describe("Zotero.QuickCopy", function() {
assert.isTrue(worked);
assert.isTrue(content.trim().startsWith('@'));
});
-
- it("should copy note content", async function () {
- var item = await createDataObject('item', { itemType: 'note', note: 'Foo
' });
-
- var format = 'bibliography=http://www.zotero.org/styles/apa';
- Zotero.Prefs.set(prefName, format);
-
- var content = Zotero.QuickCopy.getContentFromItems([item], format);
- assert.propertyVal(content, 'text', 'Foo');
- assert.propertyVal(content, 'html', '');
- });
});
it("should generate bibliography in default locale if Quick Copy locale not set", async function () {
diff --git a/translators b/translators
index d652a4de82..be5fc1633d 160000
--- a/translators
+++ b/translators
@@ -1 +1 @@
-Subproject commit d652a4de827b2ce25b6fac69f2e3e6e37cb74488
+Subproject commit be5fc1633d0473bd662c35e887564a02abac7874