Markdown note export (#2214)
This commit is contained in:
parent
63a0452a77
commit
19977598eb
17 changed files with 383 additions and 251 deletions
|
@ -49,8 +49,7 @@ var Zotero_File_Interface_Export = new function() {
|
||||||
|
|
||||||
var addedOptions = new Object();
|
var addedOptions = new Object();
|
||||||
|
|
||||||
var translators = window.arguments[0].translators;
|
var { translators, exportingNotes } = window.arguments[0];
|
||||||
translators.sort(function(a, b) { return a.label.localeCompare(b.label) });
|
|
||||||
|
|
||||||
// get format popup
|
// get format popup
|
||||||
var formatPopup = document.getElementById("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 optionsBox = document.getElementById("translator-options");
|
||||||
var charsetBox = document.getElementById("charset-box");
|
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
|
// add styles to format popup
|
||||||
for(var i in translators) {
|
for(var i in translators) {
|
||||||
|
@ -72,7 +73,12 @@ var Zotero_File_Interface_Export = new function() {
|
||||||
// presented to the user
|
// presented to the user
|
||||||
// get readable name for option
|
// get readable name for option
|
||||||
try {
|
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) {
|
} catch(e) {
|
||||||
var optionLabel = option;
|
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);
|
_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];
|
window.arguments[0].selectedTranslator = window.arguments[0].translators[index];
|
||||||
|
|
||||||
// save selected translator
|
// 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
|
// set options on selected translator and generate optionString
|
||||||
var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions;
|
var optionsAvailable = window.arguments[0].selectedTranslator.displayOptions;
|
||||||
|
@ -253,7 +264,10 @@ var Zotero_File_Interface_Export = new function() {
|
||||||
|
|
||||||
// save options
|
// save options
|
||||||
var optionString = JSON.stringify(displayOptions);
|
var optionString = JSON.stringify(displayOptions);
|
||||||
Zotero.Prefs.set("export.translatorSettings", optionString);
|
Zotero.Prefs.set(
|
||||||
|
window.arguments[0].exportingNotes ? "export.noteTranslatorSettings" : "export.translatorSettings",
|
||||||
|
optionString
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -50,8 +50,41 @@ Zotero_File_Exporter.prototype.save = async function () {
|
||||||
var translation = new Zotero.Translate.Export();
|
var translation = new Zotero.Translate.Export();
|
||||||
var translators = await translation.getTranslators();
|
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 == '154c2785-ec83-4c27-8a8a-d27b3a2eded1');
|
||||||
|
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 == '897a81c2-9f60-4bec-ae6b-85a5030b8be5');
|
||||||
|
if (htmlTranslator) {
|
||||||
|
htmlTranslator.label = 'HTML';
|
||||||
|
}
|
||||||
|
|
||||||
// present options dialog
|
// present options dialog
|
||||||
var io = {translators:translators}
|
var io = { translators, exportingNotes };
|
||||||
window.openDialog("chrome://zotero/content/exportOptions.xul",
|
window.openDialog("chrome://zotero/content/exportOptions.xul",
|
||||||
"_blank", "chrome,modal,centerscreen,resizable=no", io);
|
"_blank", "chrome,modal,centerscreen,resizable=no", io);
|
||||||
if(!io.selectedTranslator) {
|
if(!io.selectedTranslator) {
|
||||||
|
@ -89,33 +122,49 @@ Zotero_File_Exporter.prototype.save = async function () {
|
||||||
translation.setLibraryID(this.libraryID);
|
translation.setLibraryID(this.libraryID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function _exportDone(obj, worked) {
|
||||||
|
if (!worked) {
|
||||||
|
Zotero.alert(
|
||||||
|
null,
|
||||||
|
Zotero.getString('general.error'),
|
||||||
|
Zotero.getString('fileInterface.exportError')
|
||||||
|
);
|
||||||
|
Zotero_File_Interface.Progress.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Note Markdown translator replace zotero:// URI scheme,
|
||||||
|
// if the current app is not Zotero
|
||||||
|
if (io.selectedTranslator.translatorID == '154c2785-ec83-4c27-8a8a-d27b3a2eded1'
|
||||||
|
&& ZOTERO_CONFIG.ID != 'zotero') {
|
||||||
|
let text = obj.string;
|
||||||
|
text = text.replace(/zotero:\/\//g, ZOTERO_CONFIG.ID + '://');
|
||||||
|
await Zotero.File.putContentsAsync(fp.file, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the items exported indicator
|
||||||
|
Zotero_File_Interface.Progress.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post process and save translator output in _exportDone, if using
|
||||||
|
// Note Markdown translator and the current app is not Zotero.
|
||||||
|
// For other translators setLocation is better because it uses streaming
|
||||||
|
if (!(io.selectedTranslator.translatorID == '154c2785-ec83-4c27-8a8a-d27b3a2eded1'
|
||||||
|
&& ZOTERO_CONFIG.ID != 'zotero')) {
|
||||||
translation.setLocation(Zotero.File.pathToFile(fp.file));
|
translation.setLocation(Zotero.File.pathToFile(fp.file));
|
||||||
|
}
|
||||||
translation.setTranslator(io.selectedTranslator);
|
translation.setTranslator(io.selectedTranslator);
|
||||||
translation.setDisplayOptions(io.displayOptions);
|
translation.setDisplayOptions(io.displayOptions);
|
||||||
translation.setHandler("itemDone", function () {
|
translation.setHandler("itemDone", function () {
|
||||||
Zotero.updateZoteroPaneProgressMeter(translation.getProgress());
|
Zotero.updateZoteroPaneProgressMeter(translation.getProgress());
|
||||||
});
|
});
|
||||||
translation.setHandler("done", this._exportDone);
|
translation.setHandler("done", _exportDone);
|
||||||
Zotero_File_Interface.Progress.show(
|
Zotero_File_Interface.Progress.show(
|
||||||
Zotero.getString("fileInterface.itemsExported")
|
Zotero.getString("fileInterface.itemsExported")
|
||||||
);
|
);
|
||||||
translation.translate()
|
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****
|
/****Zotero_File_Interface****
|
||||||
**
|
**
|
||||||
|
@ -175,36 +224,91 @@ var Zotero_File_Interface = new function() {
|
||||||
*/
|
*/
|
||||||
function exportItems() {
|
function exportItems() {
|
||||||
var exporter = new Zotero_File_Exporter();
|
var exporter = new Zotero_File_Exporter();
|
||||||
|
let itemIDs = ZoteroPane_Local.getSelectedItems(true);
|
||||||
exporter.items = ZoteroPane_Local.getSelectedItems();
|
// 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");
|
if(!exporter.items || !exporter.items.length) throw("no items currently selected");
|
||||||
|
|
||||||
exporter.save();
|
exporter.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exports items to clipboard
|
* exports items to clipboard
|
||||||
*/
|
*/
|
||||||
function exportItemsToClipboard(items, translatorID) {
|
function exportItemsToClipboard(items, translatorID) {
|
||||||
var translation = new Zotero.Translate.Export();
|
function _translate(items, translatorID, callback) {
|
||||||
translation.setItems(items);
|
let translation = new Zotero.Translate.Export();
|
||||||
|
translation.setItems(items.slice());
|
||||||
translation.setTranslator(translatorID);
|
translation.setTranslator(translatorID);
|
||||||
translation.setHandler("done", _copyToClipboard);
|
translation.setHandler("done", callback);
|
||||||
translation.translate();
|
translation.translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// If translating with virtual "Markdown + Rich Text" translator, use Note Markdown and
|
||||||
* handler when done exporting items to clipboard
|
// Note HTML instead
|
||||||
*/
|
if (translatorID == 'a45eca67-1ee8-45e5-b4c6-23fb8a852873') {
|
||||||
function _copyToClipboard(obj, worked) {
|
translatorID = '154c2785-ec83-4c27-8a8a-d27b3a2eded1';
|
||||||
if(!worked) {
|
_translate(items, translatorID, (obj, worked) => {
|
||||||
Zotero.alert(
|
if (!worked) {
|
||||||
null, Zotero.getString('general.error'), Zotero.getString("fileInterface.exportError")
|
Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
translatorID = '897a81c2-9f60-4bec-ae6b-85a5030b8be5';
|
||||||
|
_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 {
|
});
|
||||||
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
|
});
|
||||||
|
}
|
||||||
|
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 == '897a81c2-9f60-4bec-ae6b-85a5030b8be5') {
|
||||||
|
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)
|
.getService(Components.interfaces.nsIClipboardHelper)
|
||||||
.copyString(obj.string.replace(/\r\n/g, "\n"));
|
.copyString(text.replace(/\r\n/g, '\n'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1891,6 +1891,8 @@ var ItemTree = class ItemTree extends LibraryTree {
|
||||||
event.dataTransfer.setDragImage(this._dragImageContainer, 0, 0);
|
event.dataTransfer.setDragImage(this._dragImageContainer, 0, 0);
|
||||||
|
|
||||||
var itemIDs = this.getSelectedItems(true);
|
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);
|
event.dataTransfer.setData("zotero/item", itemIDs);
|
||||||
|
|
||||||
var items = Zotero.Items.get(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)
|
// Get Quick Copy format for current URL (set via /ping from connector)
|
||||||
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
||||||
|
|
||||||
|
// 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);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
format = Zotero.QuickCopy.unserializeSetting(format);
|
format = Zotero.QuickCopy.unserializeSetting(format);
|
||||||
try {
|
try {
|
||||||
if (format.mode == 'export') {
|
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 === 'a45eca67-1ee8-45e5-b4c6-23fb8a852873') {
|
||||||
|
let markdownFormat = { mode: 'export', id: '154c2785-ec83-4c27-8a8a-d27b3a2eded1' };
|
||||||
|
let htmlFormat = { mode: 'export', id: '897a81c2-9f60-4bec-ae6b-85a5030b8be5' };
|
||||||
|
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 == '897a81c2-9f60-4bec-ae6b-85a5030b8be5') {
|
||||||
|
// 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') {
|
else if (format.mode == 'bibliography') {
|
||||||
var content = Zotero.QuickCopy.getContentFromItems(items, format, null, event.shiftKey);
|
var content = Zotero.QuickCopy.getContentFromItems(items, format, null, event.shiftKey);
|
||||||
|
|
|
@ -35,6 +35,7 @@ Zotero_Preferences.Export = {
|
||||||
init: Zotero.Promise.coroutine(function* () {
|
init: Zotero.Promise.coroutine(function* () {
|
||||||
this.updateQuickCopyInstructions();
|
this.updateQuickCopyInstructions();
|
||||||
yield this.populateQuickCopyList();
|
yield this.populateQuickCopyList();
|
||||||
|
yield this.populateNoteQuickCopyList();
|
||||||
|
|
||||||
var charsetMenu = document.getElementById("zotero-import-charsetMenu");
|
var charsetMenu = document.getElementById("zotero-import-charsetMenu");
|
||||||
var charsetMap = Zotero_Charset_Menu.populate(charsetMenu, false);
|
var charsetMap = Zotero_Charset_Menu.populate(charsetMenu, false);
|
||||||
|
@ -51,6 +52,8 @@ Zotero_Preferences.Export = {
|
||||||
var collation = Zotero.getLocaleCollation();
|
var collation = Zotero.getLocaleCollation();
|
||||||
return collation.compareString(1, a.label, b.label);
|
return collation.compareString(1, a.label, b.label);
|
||||||
});
|
});
|
||||||
|
// Exclude note export translators
|
||||||
|
translators = translators.filter(x => !x.configOptions || !x.configOptions.noteTranslator);
|
||||||
return translators;
|
return translators;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -82,6 +85,80 @@ 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 == '897a81c2-9f60-4bec-ae6b-85a5030b8be5');
|
||||||
|
if (htmlTranslator) {
|
||||||
|
htmlTranslator.label = 'HTML';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure virtual "Markdown + Rich Text" translator doesn't actually exist
|
||||||
|
translators = translators.filter(x => x.translatorID != 'a45eca67-1ee8-45e5-b4c6-23fb8a852873');
|
||||||
|
|
||||||
|
let markdownTranslatorIdx = translators.findIndex(x => x.translatorID == '154c2785-ec83-4c27-8a8a-d27b3a2eded1');
|
||||||
|
// 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: 'a45eca67-1ee8-45e5-b4c6-23fb8a852873',
|
||||||
|
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
|
* Builds a Quick Copy drop-down
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
<preference id="pref-quickCopy-setting" name="extensions.zotero.export.quickCopy.setting" type="string"/>
|
<preference id="pref-quickCopy-setting" name="extensions.zotero.export.quickCopy.setting" type="string"/>
|
||||||
<preference id="pref-quickCopy-dragLimit" name="extensions.zotero.export.quickCopy.dragLimit" type="int"/>
|
<preference id="pref-quickCopy-dragLimit" name="extensions.zotero.export.quickCopy.dragLimit" type="int"/>
|
||||||
<preference id="pref-quickCopy-locale" name="extensions.zotero.export.quickCopy.locale" type="string"/>
|
<preference id="pref-quickCopy-locale" name="extensions.zotero.export.quickCopy.locale" type="string"/>
|
||||||
|
<preference id="pref-noteQuickCopy-setting" name="extensions.zotero.export.noteQuickCopy.setting" type="string"/>
|
||||||
<preference id="pref-import-charset" name="extensions.zotero.import.charset" type="string"/>
|
<preference id="pref-import-charset" name="extensions.zotero.import.charset" type="string"/>
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
|
|
||||||
<separator/>
|
<separator/>
|
||||||
|
|
||||||
<label value="&zotero.preferences.quickCopy.defaultFormat;" control="quickCopy-menu"/>
|
<label value="&zotero.preferences.quickCopy.itemFormat;" control="quickCopy-menu"/>
|
||||||
<menulist id="zotero-quickCopy-menu" label="&zotero.general.loading;"/>
|
<menulist id="zotero-quickCopy-menu" label="&zotero.general.loading;"/>
|
||||||
|
|
||||||
<hbox align="center">
|
<hbox align="center">
|
||||||
|
@ -68,8 +69,13 @@
|
||||||
|
|
||||||
<separator/>
|
<separator/>
|
||||||
|
|
||||||
|
<label value="&zotero.preferences.quickCopy.noteFormat;" control="zotero-noteQuickCopy-menu"/>
|
||||||
|
<menulist id="zotero-noteQuickCopy-menu" label="&zotero.general.loading;"/>
|
||||||
|
|
||||||
|
<separator/>
|
||||||
|
|
||||||
<label value="&zotero.preferences.quickCopy.siteEditor.setings;" control="quickCopy-siteSettings"/>
|
<label value="&zotero.preferences.quickCopy.siteEditor.setings;" control="quickCopy-siteSettings"/>
|
||||||
<hbox class="virtualized-table-container" flex="1" height="300px">
|
<hbox class="virtualized-table-container" flex="1" height="120px">
|
||||||
<html:div id="quickCopy-siteSettings"/>
|
<html:div id="quickCopy-siteSettings"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
<separator class="thin"/>
|
<separator class="thin"/>
|
||||||
|
|
|
@ -306,26 +306,23 @@ const ZoteroStandalone = new function() {
|
||||||
|
|
||||||
|
|
||||||
this.updateQuickCopyOptions = function () {
|
this.updateQuickCopyOptions = function () {
|
||||||
var selected = false;
|
var selected = [];
|
||||||
|
|
||||||
let win = Zotero.getMainWindow();
|
let win = Zotero.getMainWindow();
|
||||||
if (win) {
|
if (win) {
|
||||||
if (win.Zotero_Tabs.selectedID == 'zotero-pane') {
|
if (win.Zotero_Tabs.selectedID == 'zotero-pane') {
|
||||||
try {
|
try {
|
||||||
selected = win.ZoteroPane
|
selected = win.ZoteroPane.getSelectedItems();
|
||||||
.getSelectedItems()
|
|
||||||
.filter(item => item.isRegularItem())
|
|
||||||
.length;
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
}
|
}
|
||||||
win.ZoteroPane.updateQuickCopyCommands(win.ZoteroPane.getSelectedItems());
|
win.ZoteroPane.updateQuickCopyCommands(selected);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let reader = Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID);
|
let reader = Zotero.Reader.getByTabID(win.Zotero_Tabs.selectedID);
|
||||||
if (reader) {
|
if (reader) {
|
||||||
let item = Zotero.Items.get(reader.itemID);
|
let item = Zotero.Items.get(reader.itemID);
|
||||||
selected = !!item.parentItemID;
|
selected = item.parentItem && [item.parentItem] || [];
|
||||||
item = item.parentItem || item;
|
item = item.parentItem || item;
|
||||||
win.ZoteroPane.updateQuickCopyCommands([item]);
|
win.ZoteroPane.updateQuickCopyCommands([item]);
|
||||||
}
|
}
|
||||||
|
@ -333,15 +330,21 @@ const ZoteroStandalone = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
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);
|
format = Zotero.QuickCopy.unserializeSetting(format);
|
||||||
|
|
||||||
var copyCitation = document.getElementById('menu_copyCitation');
|
var copyCitation = document.getElementById('menu_copyCitation');
|
||||||
var copyBibliography = document.getElementById('menu_copyBibliography');
|
var copyBibliography = document.getElementById('menu_copyBibliography');
|
||||||
var copyExport = document.getElementById('menu_copyExport');
|
var copyExport = document.getElementById('menu_copyExport');
|
||||||
|
var copyNote = document.getElementById('menu_copyNote');
|
||||||
|
|
||||||
copyCitation.hidden = !selected || format.mode != 'bibliography';
|
copyCitation.hidden = !selected.length || format.mode != 'bibliography';
|
||||||
copyBibliography.hidden = !selected || format.mode != 'bibliography';
|
copyBibliography.hidden = !selected.length || format.mode != 'bibliography';
|
||||||
copyExport.hidden = !selected || format.mode != 'export';
|
copyExport.hidden = !selected.length || format.mode != 'export' || exportingNotes;
|
||||||
|
copyNote.hidden = !selected.length || format.mode != 'export' || !exportingNotes;
|
||||||
if (format.mode == 'export') {
|
if (format.mode == 'export') {
|
||||||
try {
|
try {
|
||||||
let obj = Zotero.Translators.get(format.id);
|
let obj = Zotero.Translators.get(format.id);
|
||||||
|
|
|
@ -210,6 +210,11 @@
|
||||||
key="key_copyBibliography"
|
key="key_copyBibliography"
|
||||||
command="cmd_zotero_copyBibliography"
|
command="cmd_zotero_copyBibliography"
|
||||||
hidden="true"/>
|
hidden="true"/>
|
||||||
|
<menuitem id="menu_copyNote"
|
||||||
|
label="©NoteCmd.label;"
|
||||||
|
command="cmd_zotero_copyBibliography"
|
||||||
|
key="key_copyBibliography"
|
||||||
|
hidden="true"/>
|
||||||
<menuitem id="menu_paste"/>
|
<menuitem id="menu_paste"/>
|
||||||
<menuitem id="menu_delete"/>
|
<menuitem id="menu_delete"/>
|
||||||
<menuseparator class="menu-type-library"/>
|
<menuseparator class="menu-type-library"/>
|
||||||
|
|
|
@ -43,6 +43,10 @@ Zotero.QuickCopy = new function() {
|
||||||
this._prefObserverID = Zotero.Prefs.registerObserver(
|
this._prefObserverID = Zotero.Prefs.registerObserver(
|
||||||
"export.quickCopy.setting", _loadOutputFormat
|
"export.quickCopy.setting", _loadOutputFormat
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this._prefObserverID = Zotero.Prefs.registerObserver(
|
||||||
|
"export.noteQuickCopy.setting", _loadNoteOutputFormat
|
||||||
|
);
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ Zotero.QuickCopy = new function() {
|
||||||
_initPromise = Zotero.Promise.each(
|
_initPromise = Zotero.Promise.each(
|
||||||
[
|
[
|
||||||
() => _loadOutputFormat(),
|
() => _loadOutputFormat(),
|
||||||
|
() => _loadNoteOutputFormat(),
|
||||||
() => this.loadSiteSettings()
|
() => this.loadSiteSettings()
|
||||||
],
|
],
|
||||||
f => f()
|
f => f()
|
||||||
|
@ -157,6 +162,11 @@ Zotero.QuickCopy = new function() {
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.getNoteFormat = function () {
|
||||||
|
var pref = Zotero.Prefs.get('export.noteQuickCopy.setting');
|
||||||
|
pref = JSON.stringify(this.unserializeSetting(pref));
|
||||||
|
return pref;
|
||||||
|
};
|
||||||
|
|
||||||
this.getFormatFromURL = function(url) {
|
this.getFormatFromURL = function(url) {
|
||||||
var quickCopyPref = Zotero.Prefs.get("export.quickCopy.setting");
|
var quickCopyPref = Zotero.Prefs.get("export.quickCopy.setting");
|
||||||
|
@ -256,167 +266,15 @@ Zotero.QuickCopy = new function() {
|
||||||
if (format.mode == 'export') {
|
if (format.mode == 'export') {
|
||||||
var translation = new Zotero.Translate.Export;
|
var translation = new Zotero.Translate.Export;
|
||||||
translation.noWait = true; // needed not to break drags
|
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.setTranslator(format.id);
|
||||||
translation.setHandler("done", callback);
|
translation.setHandler("done", callback);
|
||||||
translation.translate();
|
translation.translate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (format.mode == 'bibliography') {
|
else if (format.mode == 'bibliography') {
|
||||||
// Move notes to separate array
|
items = items.filter(item => !item.isNote());
|
||||||
var allNotes = true;
|
|
||||||
var notes = [];
|
|
||||||
for (var i=0; i<items.length; i++) {
|
|
||||||
if (items[i].isNote()) {
|
|
||||||
notes.push(items.splice(i, 1)[0]);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
allNotes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all notes, export full content
|
|
||||||
if (allNotes) {
|
|
||||||
var content = [];
|
|
||||||
let parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
|
||||||
.createInstance(Components.interfaces.nsIDOMParser);
|
|
||||||
let docHTML = '<html><body><div class="zotero-notes"/></body></html>';
|
|
||||||
let doc = parser.parseFromString(docHTML, 'text/html');
|
|
||||||
let textDoc = parser.parseFromString(docHTML, 'text/html');
|
|
||||||
let container = doc.body.firstChild;
|
|
||||||
let textContainer = textDoc.body.firstChild;
|
|
||||||
|
|
||||||
for (var i=0; i<notes.length; i++) {
|
|
||||||
var div = doc.createElement("div");
|
|
||||||
div.className = "zotero-note";
|
|
||||||
// AMO reviewer: This documented is never rendered (and the inserted markup
|
|
||||||
// is sanitized anyway)
|
|
||||||
div.insertAdjacentHTML('afterbegin', notes[i].note);
|
|
||||||
container.appendChild(div);
|
|
||||||
textContainer.appendChild(textDoc.importNode(div, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raw HTML output
|
|
||||||
var html = container.outerHTML;
|
|
||||||
|
|
||||||
// Add placeholders for newlines between notes
|
|
||||||
if (notes.length > 1) {
|
|
||||||
var divs = Zotero.Utilities.xpath(container, "div"),
|
|
||||||
textDivs = Zotero.Utilities.xpath(textContainer, "div");
|
|
||||||
for (var i=1, len=divs.length; i<len; i++) {
|
|
||||||
var p = doc.createElement("p");
|
|
||||||
p.appendChild(doc.createTextNode("--------------------------------------------------"));
|
|
||||||
container.insertBefore(p, divs[i]);
|
|
||||||
textContainer.insertBefore(textDoc.importNode(p, true), textDivs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const BLOCKQUOTE_PREFS = {
|
|
||||||
'export.quickCopy.quoteBlockquotes.richText':doc,
|
|
||||||
'export.quickCopy.quoteBlockquotes.plainText':textDoc
|
|
||||||
};
|
|
||||||
for(var pref in BLOCKQUOTE_PREFS) {
|
|
||||||
if (Zotero.Prefs.get(pref)) {
|
|
||||||
var currentDoc = BLOCKQUOTE_PREFS[pref];
|
|
||||||
// Add quotes around blockquote paragraphs
|
|
||||||
var addOpenQuote = Zotero.Utilities.xpath(currentDoc, "//blockquote/p[1]"),
|
|
||||||
addCloseQuote = Zotero.Utilities.xpath(currentDoc, "//blockquote/p[last()]");
|
|
||||||
for(var i=0; i<addOpenQuote.length; i++) {
|
|
||||||
addOpenQuote[i].insertBefore(currentDoc.createTextNode("\u201c"),
|
|
||||||
addOpenQuote[i].firstChild);
|
|
||||||
}
|
|
||||||
for(var i=0; i<addCloseQuote.length; i++) {
|
|
||||||
addCloseQuote[i].appendChild(currentDoc.createTextNode("\u201d"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Text-only adjustments
|
|
||||||
//
|
|
||||||
|
|
||||||
// Replace span styles with characters
|
|
||||||
var spans = textDoc.getElementsByTagName("span");
|
|
||||||
for(var i=0; i<spans.length; i++) {
|
|
||||||
var span = spans[i];
|
|
||||||
if(span.style.textDecoration == "underline") {
|
|
||||||
span.insertBefore(textDoc.createTextNode("_"), span.firstChild);
|
|
||||||
span.appendChild(textDoc.createTextNode("_"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// And add spaces for indents
|
|
||||||
//
|
|
||||||
// Placeholder for 4 spaces in final output
|
|
||||||
const ZTAB = "%%ZOTEROTAB%%";
|
|
||||||
var ps = textDoc.getElementsByTagName("p");
|
|
||||||
for(var i=0; i<ps.length; i++) {
|
|
||||||
var p = ps[i],
|
|
||||||
paddingLeft = p.style.paddingLeft;
|
|
||||||
if(paddingLeft && paddingLeft.substr(paddingLeft.length-2) === "px") {
|
|
||||||
var paddingPx = parseInt(paddingLeft, 10),
|
|
||||||
ztabs = "";
|
|
||||||
for (let j = 30; j <= paddingPx; j += 30) ztabs += ZTAB;
|
|
||||||
p.insertBefore(textDoc.createTextNode(ztabs), p.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use plaintext serializer to output formatted text
|
|
||||||
var docEncoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/html"]
|
|
||||||
.createInstance(Components.interfaces.nsIDocumentEncoder);
|
|
||||||
docEncoder.init(textDoc, "text/plain", docEncoder.OutputFormatted);
|
|
||||||
var text = docEncoder.encodeToString().trim().replace(ZTAB, " ", "g");
|
|
||||||
|
|
||||||
//
|
|
||||||
// Adjustments for the HTML copied to the clipboard
|
|
||||||
//
|
|
||||||
|
|
||||||
// Everything seems to like margin-left better than padding-left
|
|
||||||
var ps = Zotero.Utilities.xpath(doc, "p");
|
|
||||||
for(var i=0; i<ps.length; i++) {
|
|
||||||
var p = ps[i];
|
|
||||||
if(p.style.paddingLeft) {
|
|
||||||
p.style.marginLeft = p.style.paddingLeft;
|
|
||||||
p.style.paddingLeft = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Word and TextEdit don't indent blockquotes on their own and need this
|
|
||||||
//
|
|
||||||
// OO gets it right, so this results in an extra indent
|
|
||||||
if (Zotero.Prefs.get('export.quickCopy.compatibility.indentBlockquotes')) {
|
|
||||||
var ps = Zotero.Utilities.xpath(doc, "//blockquote/p");
|
|
||||||
for(var i=0; i<ps.length; i++) ps[i].style.marginLeft = "30px";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Word Normal style to paragraphs and add double-spacing
|
|
||||||
//
|
|
||||||
// OO inserts the conditional style code as a document comment
|
|
||||||
if (Zotero.Prefs.get('export.quickCopy.compatibility.word')) {
|
|
||||||
var ps = doc.getElementsByTagName("p");
|
|
||||||
for (var i=0; i<ps.length; i++) ps[i].className = "msoNormal";
|
|
||||||
var copyHTML = "<!--[if gte mso 0]>"
|
|
||||||
+ "<style>"
|
|
||||||
+ "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 }"
|
|
||||||
+ "</style>"
|
|
||||||
+ "<![endif]-->\n"
|
|
||||||
+ container.outerHTML;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var copyHTML = container.outerHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
var content = {
|
|
||||||
text: format.contentType == "html" ? html : text,
|
|
||||||
html: copyHTML
|
|
||||||
};
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine locale preference
|
// determine locale preference
|
||||||
var locale = format.locale ? format.locale : Zotero.Prefs.get('export.quickCopy.locale');
|
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 == 'a45eca67-1ee8-45e5-b4c6-23fb8a852873') {
|
||||||
|
await _preloadFormat({ mode: 'export', id: '154c2785-ec83-4c27-8a8a-d27b3a2eded1' });
|
||||||
|
await _preloadFormat({ mode: 'export', id: '897a81c2-9f60-4bec-ae6b-85a5030b8be5' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return _preloadFormat(format);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var _preloadFormat = async function (format) {
|
var _preloadFormat = async function (format) {
|
||||||
format = Zotero.QuickCopy.unserializeSetting(format);
|
format = Zotero.QuickCopy.unserializeSetting(format);
|
||||||
if (format.mode == 'export') {
|
if (format.mode == 'export') {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 85b39a5be5bb59c5ee5e7447609273a29ea0b799
|
Subproject commit b75bc2550ae2df3bb307e7abf0d3abad96f79c82
|
|
@ -1014,7 +1014,10 @@ Zotero.Translate.ItemGetter = function() {
|
||||||
Zotero.Translate.ItemGetter.prototype = {
|
Zotero.Translate.ItemGetter.prototype = {
|
||||||
setItems: function (items) {
|
setItems: function (items) {
|
||||||
this._itemsLeft = items;
|
this._itemsLeft = items;
|
||||||
|
// 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._itemsLeft.sort((a, b) => a.id - b.id);
|
||||||
|
}
|
||||||
this.numItems = this._itemsLeft.length;
|
this.numItems = this._itemsLeft.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1605,18 +1605,28 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the <command> elements that control the shortcut keys and the enabled state of the
|
* Update the <command> 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.
|
* still caught in handleKeyPress so that we can show an alert about not having references selected.
|
||||||
*/
|
*/
|
||||||
this.updateQuickCopyCommands = function (selectedItems) {
|
this.updateQuickCopyCommands = function (selectedItems) {
|
||||||
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
let canCopy = false;
|
||||||
format = Zotero.QuickCopy.unserializeSetting(format);
|
// If all items are notes/attachments and at least one note is not empty
|
||||||
if (format.mode == 'bibliography') {
|
if (selectedItems.every(item => item.isNote() || item.isAttachment())) {
|
||||||
var canCopy = selectedItems.some(item => item.isRegularItem());
|
if (selectedItems.some(item => item.note)) {
|
||||||
|
canCopy = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
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_copyCitation').setAttribute('disabled', !canCopy);
|
||||||
document.getElementById('cmd_zotero_copyBibliography').setAttribute('disabled', !canCopy);
|
document.getElementById('cmd_zotero_copyBibliography').setAttribute('disabled', !canCopy);
|
||||||
};
|
};
|
||||||
|
@ -2075,7 +2085,10 @@ var ZoteroPane = new function()
|
||||||
this.copySelectedItemsToClipboard = function (asCitations) {
|
this.copySelectedItemsToClipboard = function (asCitations) {
|
||||||
var items = [];
|
var items = [];
|
||||||
if (Zotero_Tabs.selectedID == 'zotero-pane') {
|
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 {
|
else {
|
||||||
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||||
|
@ -2092,6 +2105,9 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
|
|
||||||
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
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);
|
format = Zotero.QuickCopy.unserializeSetting(format);
|
||||||
|
|
||||||
// In bibliography mode, remove notes and attachments
|
// In bibliography mode, remove notes and attachments
|
||||||
|
@ -2967,6 +2983,12 @@ var ZoteroPane = new function()
|
||||||
m.moveToTrash, m.deleteFromLibrary, m.exportItems, m.createBib, m.loadReport);
|
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()) {
|
if ((!collectionTreeRow.editable || collectionTreeRow.isPublications()) && !collectionTreeRow.isFeed()) {
|
||||||
for (let i in m) {
|
for (let i in m) {
|
||||||
// Still allow some options for non-editable views
|
// Still allow some options for non-editable views
|
||||||
|
|
|
@ -104,7 +104,8 @@
|
||||||
<!ENTITY zotero.preferences.export.citePaperJournalArticleURL.description "When this option is disabled, Zotero includes URLs when citing journal, magazine, and newspaper articles only if the article does not have a page range specified.">
|
<!ENTITY zotero.preferences.export.citePaperJournalArticleURL.description "When this option is disabled, Zotero includes URLs when citing journal, magazine, and newspaper articles only if the article does not have a page range specified.">
|
||||||
|
|
||||||
<!ENTITY zotero.preferences.quickCopy.caption "Quick Copy">
|
<!ENTITY zotero.preferences.quickCopy.caption "Quick Copy">
|
||||||
<!ENTITY zotero.preferences.quickCopy.defaultFormat "Default Format:">
|
<!ENTITY zotero.preferences.quickCopy.itemFormat "Item Format:">
|
||||||
|
<!ENTITY zotero.preferences.quickCopy.noteFormat "Note Format:">
|
||||||
<!ENTITY zotero.preferences.quickCopy.copyAsHTML "Copy as HTML">
|
<!ENTITY zotero.preferences.quickCopy.copyAsHTML "Copy as HTML">
|
||||||
<!ENTITY zotero.preferences.quickCopy.siteEditor.setings "Site-Specific Settings:">
|
<!ENTITY zotero.preferences.quickCopy.siteEditor.setings "Site-Specific Settings:">
|
||||||
<!ENTITY zotero.preferences.quickCopy.siteEditor.domainPath "Domain/Path">
|
<!ENTITY zotero.preferences.quickCopy.siteEditor.domainPath "Domain/Path">
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
<!--EDIT MENU-->
|
<!--EDIT MENU-->
|
||||||
<!ENTITY copyCitationCmd.label "Copy Citation">
|
<!ENTITY copyCitationCmd.label "Copy Citation">
|
||||||
<!ENTITY copyBibliographyCmd.label "Copy Bibliography">
|
<!ENTITY copyBibliographyCmd.label "Copy Bibliography">
|
||||||
|
<!ENTITY copyNoteCmd.label "Copy Note">
|
||||||
|
|
||||||
<!ENTITY bidiSwitchPageDirectionItem.label "Switch Page Direction">
|
<!ENTITY bidiSwitchPageDirectionItem.label "Switch Page Direction">
|
||||||
<!ENTITY bidiSwitchPageDirectionItem.accesskey "g">
|
<!ENTITY bidiSwitchPageDirectionItem.accesskey "g">
|
||||||
|
|
|
@ -87,6 +87,7 @@ general.languages = Languages
|
||||||
general.default = Default
|
general.default = Default
|
||||||
general.custom = Custom
|
general.custom = Custom
|
||||||
general.loading = Loading…
|
general.loading = Loading…
|
||||||
|
general.richText = Rich Text
|
||||||
|
|
||||||
general.yellow = Yellow
|
general.yellow = Yellow
|
||||||
general.red = Red
|
general.red = Red
|
||||||
|
@ -826,6 +827,7 @@ fulltext.indexState.queued = Queued
|
||||||
exportOptions.exportNotes = Export Notes
|
exportOptions.exportNotes = Export Notes
|
||||||
exportOptions.exportFileData = Export Files
|
exportOptions.exportFileData = Export Files
|
||||||
exportOptions.includeAnnotations = Include Annotations
|
exportOptions.includeAnnotations = Include Annotations
|
||||||
|
exportOptions.includeAppLinks = Include %S Links
|
||||||
exportOptions.useJournalAbbreviation = Use Journal Abbreviation
|
exportOptions.useJournalAbbreviation = Use Journal Abbreviation
|
||||||
charset.UTF8withoutBOM = Unicode (UTF-8 without BOM)
|
charset.UTF8withoutBOM = Unicode (UTF-8 without BOM)
|
||||||
charset.autoDetect = (auto detect)
|
charset.autoDetect = (auto detect)
|
||||||
|
|
|
@ -109,6 +109,8 @@ pref("extensions.zotero.report.combineChildItems", true);
|
||||||
// Export and citation settings
|
// Export and citation settings
|
||||||
pref("extensions.zotero.export.lastTranslator", "14763d24-8ba0-45df-8f52-b8d1108e7ac9");
|
pref("extensions.zotero.export.lastTranslator", "14763d24-8ba0-45df-8f52-b8d1108e7ac9");
|
||||||
pref("extensions.zotero.export.translatorSettings", "true,false");
|
pref("extensions.zotero.export.translatorSettings", "true,false");
|
||||||
|
pref("extensions.zotero.export.lastNoteTranslator", "154c2785-ec83-4c27-8a8a-d27b3a2eded1");
|
||||||
|
pref("extensions.zotero.export.noteTranslatorSettings", "");
|
||||||
pref("extensions.zotero.export.lastStyle", "http://www.zotero.org/styles/chicago-note-bibliography");
|
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.bibliographySettings", "save-as-rtf");
|
||||||
pref("extensions.zotero.export.displayCharsetOption", true);
|
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.setting", "bibliography=http://www.zotero.org/styles/chicago-note-bibliography");
|
||||||
pref("extensions.zotero.export.quickCopy.dragLimit", 50);
|
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.noteQuickCopy.setting", '{"mode": "export", "id": "a45eca67-1ee8-45e5-b4c6-23fb8a852873"}');
|
||||||
pref("extensions.zotero.export.quickCopy.compatibility.indentBlockquotes", true);
|
|
||||||
pref("extensions.zotero.export.quickCopy.compatibility.word", false);
|
|
||||||
|
|
||||||
// Integration settings
|
// Integration settings
|
||||||
pref("extensions.zotero.integration.port", 50001);
|
pref("extensions.zotero.integration.port", 50001);
|
||||||
|
|
|
@ -73,17 +73,6 @@ describe("Zotero.QuickCopy", function() {
|
||||||
assert.isTrue(worked);
|
assert.isTrue(worked);
|
||||||
assert.isTrue(content.trim().startsWith('@'));
|
assert.isTrue(content.trim().startsWith('@'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should copy note content", async function () {
|
|
||||||
var item = await createDataObject('item', { itemType: 'note', note: '<p>Foo</p>' });
|
|
||||||
|
|
||||||
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', '<div class=\"zotero-notes\"><div class=\"zotero-note\"><p>Foo</p></div></div>');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should generate bibliography in default locale if Quick Copy locale not set", async function () {
|
it("should generate bibliography in default locale if Quick Copy locale not set", async function () {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d652a4de827b2ce25b6fac69f2e3e6e37cb74488
|
Subproject commit be5fc1633d0473bd662c35e887564a02abac7874
|
Loading…
Reference in a new issue