mirror of
https://github.com/zotero/zotero.git
synced 2026-10-07 02:58:09 +00:00
all content generation in getContentFromItems
- getContentFromItems is the single content producer for clipboard copy,
drag-and-drop from library and reader tabs. Handles annotation
wrapping, note-citation reformatting, and bib-mode regular-item
filtering internally.
- writeToClipboard replaces copyItemsToClipboard and exportItemsToClipboard.
- getFormat takes { mode, items }; note-only selections return the note
pref's format regardless of mode. getNoteFormat removed.
This commit is contained in:
parent
b2a884bf5f
commit
ac6c26096e
9 changed files with 277 additions and 419 deletions
|
|
@ -398,13 +398,16 @@
|
|||
Zotero.Utilities.Internal.copyTextToClipboard(this.creatorYear.textContent);
|
||||
}
|
||||
else if (selectedMode === 'bibEntry') {
|
||||
Zotero_File_Interface.copyItemsToClipboard(
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
[this._item],
|
||||
Zotero.Prefs.get(PREF_BIB_ENTRY_STYLE),
|
||||
Zotero.Prefs.get(PREF_BIB_ENTRY_LOCALE),
|
||||
false,
|
||||
false
|
||||
{
|
||||
mode: 'bibliography',
|
||||
id: Zotero.Prefs.get(PREF_BIB_ENTRY_STYLE),
|
||||
contentType: '',
|
||||
locale: Zotero.Prefs.get(PREF_BIB_ENTRY_LOCALE)
|
||||
}
|
||||
);
|
||||
Zotero_File_Interface.writeToClipboard(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,6 @@ var Zotero_File_Interface = new function () {
|
|||
var _unlock;
|
||||
|
||||
this.exportCollection = exportCollection;
|
||||
this.exportItemsToClipboard = exportItemsToClipboard;
|
||||
this.exportItems = exportItems;
|
||||
this.bibliographyFromItems = bibliographyFromItems;
|
||||
|
||||
|
|
@ -238,85 +237,42 @@ var Zotero_File_Interface = new function () {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* exports items to clipboard
|
||||
/**
|
||||
* Write QuickCopy content to the system clipboard.
|
||||
*
|
||||
* Accepts the `{ text, html? }` shape returned by getContentFromItems().
|
||||
* Each present flavor is added; consumers (plain vs. rich-text targets)
|
||||
* each pick what they support.
|
||||
*
|
||||
* @param {{text: String, html?: String}} content
|
||||
*/
|
||||
function exportItemsToClipboard(items, format) {
|
||||
function _translate(items, format, callback) {
|
||||
let translation = new Zotero.Translate.Export();
|
||||
translation.setItems(items.slice());
|
||||
translation.setTranslator(format.id);
|
||||
if (format.options) {
|
||||
translation.setDisplayOptions(format.options);
|
||||
}
|
||||
translation.setHandler("done", callback);
|
||||
translation.translate();
|
||||
this.writeToClipboard = function (content) {
|
||||
if (!content) return;
|
||||
let { text, html } = content;
|
||||
|
||||
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);
|
||||
transferable.init(null);
|
||||
|
||||
if (html) {
|
||||
let 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);
|
||||
}
|
||||
|
||||
// If translating with virtual "Markdown + Rich Text" translator, use Note Markdown and
|
||||
// Note HTML instead
|
||||
if (format.id == Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT) {
|
||||
let markdownFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN, options: format.markdownOptions };
|
||||
let htmlFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML, options: format.htmlOptions };
|
||||
_translate(items, markdownFormat, (obj, worked) => {
|
||||
if (!worked) {
|
||||
Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
|
||||
return;
|
||||
}
|
||||
_translate(items, htmlFormat, (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/plain');
|
||||
transferable.setTransferData('text/plain', 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
|
||||
);
|
||||
});
|
||||
});
|
||||
if (text) {
|
||||
let str = Components.classes['@mozilla.org/supports-string;1']
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = text;
|
||||
transferable.addDataFlavor('text/plain');
|
||||
transferable.setTransferData('text/plain', str, text.length * 2);
|
||||
}
|
||||
else {
|
||||
_translate(items, format, (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 (format.id == Zotero.Translators.TRANSLATOR_ID_NOTE_HTML) {
|
||||
let parser = new DOMParser();
|
||||
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'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
};
|
||||
|
||||
|
||||
this.getMendeleyDirectory = function () {
|
||||
|
|
@ -755,70 +711,6 @@ var Zotero_File_Interface = new function () {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
this.copyItemsToClipboard = function (items, style, locale, asHTML, asCitations) {
|
||||
var d = new Date();
|
||||
|
||||
// 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);
|
||||
style = Zotero.Styles.get(style);
|
||||
var cslEngine = style.getCiteProc(locale, 'html', { cache: true });
|
||||
|
||||
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 = 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 {
|
||||
output = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, 'text');
|
||||
}
|
||||
}
|
||||
cslEngine.free();
|
||||
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = output;
|
||||
transferable.addDataFlavor("text/plain");
|
||||
transferable.setTransferData("text/plain", str, output.length * 2);
|
||||
|
||||
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
|
||||
Zotero.debug(`Copied bibliography to clipboard in ${new Date() - d} ms`);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shows bibliography options and creates a bibliography
|
||||
*/
|
||||
|
|
@ -852,7 +744,12 @@ var Zotero_File_Interface = new function () {
|
|||
// generate bibliography
|
||||
try {
|
||||
if(io.method == 'copy-to-clipboard') {
|
||||
Zotero_File_Interface.copyItemsToClipboard(items, io.style, locale, false, io.mode === "citations");
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
items,
|
||||
{ mode: 'bibliography', id: io.style, contentType: '', locale },
|
||||
{ asCitations: io.mode === "citations" }
|
||||
);
|
||||
Zotero_File_Interface.writeToClipboard(content);
|
||||
}
|
||||
else {
|
||||
var style = Zotero.Styles.get(io.style);
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ const ZoteroStandalone = new function () {
|
|||
document.l10n.setAttributes(copyAnnotation, "menu-edit-copy-annotation", { count: selected.length });
|
||||
|
||||
// Label the export menu with the selected translator name
|
||||
var exportFormat = Zotero.QuickCopy.getFormat('export');
|
||||
var exportFormat = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
if (exportFormat.id) {
|
||||
try {
|
||||
let translator = Zotero.Translators.get(exportFormat.id);
|
||||
|
|
|
|||
|
|
@ -235,11 +235,6 @@ Zotero.QuickCopy = new function () {
|
|||
return '';
|
||||
};
|
||||
|
||||
this.getNoteFormat = function () {
|
||||
return this.unserializeSetting(Zotero.Prefs.get('export.noteQuickCopy.setting'));
|
||||
};
|
||||
|
||||
|
||||
this.getLocale = function () {
|
||||
return this.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.bibliographySetting')
|
||||
|
|
@ -303,12 +298,21 @@ Zotero.QuickCopy = new function () {
|
|||
|
||||
|
||||
/**
|
||||
* Get the Quick Copy format for the currently active URL if any.
|
||||
* Get the Quick Copy format for the currently active URL.
|
||||
* When `items` is a selection composed entirely of notes/annotations,
|
||||
* return the user's note-format pref.
|
||||
*
|
||||
* @param {String} [mode] - Optional 'bibliography' or 'export' - omit for drag-drop
|
||||
* @return {Object} - `{mode, id, contentType, locale}` for bibliography; `{mode, id}` for export
|
||||
* @param {Object} [options]
|
||||
* @param {String} [options.mode] - 'bibliography' or 'export'; omit for drag-drop
|
||||
* @param {Zotero.Item[]} [options.items] - Items the format will be applied to
|
||||
* @return {Object} - `{mode, id, contentType, locale}` for bibliography; `{mode, id, ...}` for export
|
||||
*/
|
||||
this.getFormat = function (mode) {
|
||||
this.getFormat = function ({ mode, items } = {}) {
|
||||
// Note-only selections always use the note format
|
||||
if (items && items.length && items.every(item => item.isNote() || item.isAnnotation())) {
|
||||
return this.unserializeSetting(Zotero.Prefs.get('export.noteQuickCopy.setting'));
|
||||
}
|
||||
|
||||
var siteRaw = _findSiteFormatForURL(this.lastActiveURL);
|
||||
var site = siteRaw ? this.parseSiteFormat(siteRaw) : null;
|
||||
|
||||
|
|
@ -334,80 +338,141 @@ Zotero.QuickCopy = new function () {
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
* Get text and (when applicable) HTML content from items
|
||||
/**
|
||||
* Produce QuickCopy content from items. Single entry point for clipboard
|
||||
* copy, drag-and-drop, and the Bibliography dialog. Item-type prep is
|
||||
* handled here: annotations are wrapped via annotationsToNote, notes are
|
||||
* passed through reformatNoteCitations, and bibliography mode is filtered
|
||||
* to regular items. Always returns { text, html },
|
||||
* unless export translator provides no html format.
|
||||
*
|
||||
* |items| is an array of Zotero.Item objects
|
||||
*
|
||||
* |format| may be a Quick Copy format string
|
||||
* (e.g. "bibliography=http://www.zotero.org/styles/apa")
|
||||
* or an Quick Copy format object
|
||||
*
|
||||
* |callback| is only necessary if using an export format and should be
|
||||
* a function suitable for Zotero.Translate.setHandler, taking parameters
|
||||
* |obj| and |worked|. The generated content should be placed in obj.string
|
||||
* and |worked| should be true if the operation is successful.
|
||||
*
|
||||
* If bibliography format, the process is synchronous and an object
|
||||
* contain properties 'text' and 'html' is returned.
|
||||
* @param {Zotero.Item[]} items
|
||||
* @param {String|Object} format
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.asCitations=false] - Bibliography only: in-text citation cluster
|
||||
* @return {{text: String, html?: String} | null}
|
||||
*/
|
||||
this.getContentFromItems = function (items, format, callback, modified) {
|
||||
if (items.length > Zotero.Prefs.get('export.quickCopy.dragLimit')) {
|
||||
Zotero.debug("Skipping quick copy for " + items.length + " items");
|
||||
return false;
|
||||
}
|
||||
this.getContentFromItems = function (items, format, options = {}) {
|
||||
if (!items.length) return null;
|
||||
|
||||
format = this.unserializeSetting(format);
|
||||
|
||||
if (format.mode == 'export') {
|
||||
var translation = new Zotero.Translate.Export;
|
||||
translation.noWait = true; // needed not to break drags
|
||||
// Allow to reuse items array
|
||||
translation.setItems(items.slice());
|
||||
translation.setTranslator(format.id);
|
||||
if (format.options) {
|
||||
translation.setDisplayOptions(format.options);
|
||||
}
|
||||
translation.setHandler("done", callback);
|
||||
translation.translate();
|
||||
return true;
|
||||
}
|
||||
else if (format.mode == 'bibliography') {
|
||||
items = items.filter(item => !item.isNote());
|
||||
|
||||
var locale = format.locale || this.getLocale();
|
||||
|
||||
// Copy citations if shift key pressed
|
||||
if (modified) {
|
||||
var csl = Zotero.Styles.get(format.id).getCiteProc(locale, "text", { cache: true });
|
||||
// Format-appropriate item transformations:
|
||||
// annotations → wrap into a temp note,
|
||||
// notes → reformat embedded citations in the current bib style,
|
||||
// bibliography mode → keep only regular items.
|
||||
if (items.every(item => item.isAnnotation())) {
|
||||
items = [this.annotationsToNote(items)];
|
||||
}
|
||||
if (items.every(item => item.isNote())) {
|
||||
items = this.reformatNoteCitations(items);
|
||||
}
|
||||
if (format.mode === 'bibliography') {
|
||||
items = items.filter(item => item.isRegularItem());
|
||||
}
|
||||
if (!items.length) return null;
|
||||
|
||||
if (format.mode === 'export') {
|
||||
// Markdown+RichText virtual translator: produces both flavors,
|
||||
// using its `markdownOptions` and `htmlOptions` independently.
|
||||
if (format.id === Zotero.Translators.TRANSLATOR_ID_MARKDOWN_AND_RICH_TEXT) {
|
||||
let text = _runExportTranslator(items, {
|
||||
mode: 'export',
|
||||
id: Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN,
|
||||
options: format.markdownOptions
|
||||
});
|
||||
let html = _runExportTranslator(items, {
|
||||
mode: 'export',
|
||||
id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML,
|
||||
options: format.htmlOptions
|
||||
});
|
||||
if (text === null || html === null) return null;
|
||||
return {
|
||||
text: text.replace(/\r\n/g, '\n'),
|
||||
html: html.replace(/\r\n/g, '\n')
|
||||
};
|
||||
}
|
||||
|
||||
// Note HTML: HTML output, exposed on both flavors so rich-text
|
||||
// targets get the formatting and plain editors get the source.
|
||||
if (format.id === Zotero.Translators.TRANSLATOR_ID_NOTE_HTML) {
|
||||
let output = _runExportTranslator(items, format);
|
||||
if (output === null) return null;
|
||||
output = output.replace(/\r\n/g, '\n');
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(output, 'text/html');
|
||||
output = doc.body.innerHTML;
|
||||
return { text: output, html: output };
|
||||
}
|
||||
|
||||
// Other export translators (e.g. BibTeX): single-flavor output.
|
||||
let output = _runExportTranslator(items, format);
|
||||
if (output === null) return null;
|
||||
return { text: output.replace(/\r\n/g, '\n') };
|
||||
}
|
||||
|
||||
if (format.mode === 'bibliography') {
|
||||
let locale = format.locale || this.getLocale();
|
||||
let style = Zotero.Styles.get(format.id);
|
||||
if (!style) return null;
|
||||
|
||||
// Bibliography mode always produces both flavors: plain text for
|
||||
// `text/plain`, HTML for `text/html`. "Copy as HTML" (contentType
|
||||
// === 'html') sends the HTML version to `text/plain` as well, so
|
||||
// plain editors paste HTML source.
|
||||
let html, text;
|
||||
if (options.asCitations) {
|
||||
let csl = style.getCiteProc(locale, 'html', { cache: true });
|
||||
csl.updateItems(items.map(item => item.id));
|
||||
var citation = {
|
||||
let citation = {
|
||||
citationItems: items.map(item => ({ id: item.id })),
|
||||
properties: {}
|
||||
};
|
||||
var html = csl.previewCitationCluster(citation, [], [], "html");
|
||||
var text = csl.previewCitationCluster(citation, [], [], "text");
|
||||
html = csl.previewCitationCluster(citation, [], [], 'html');
|
||||
text = csl.previewCitationCluster(citation, [], [], 'text');
|
||||
csl.free();
|
||||
}
|
||||
else {
|
||||
var style = Zotero.Styles.get(format.id);
|
||||
var cslEngine = style.getCiteProc(locale, 'html', { cache: true });
|
||||
var html = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "html");
|
||||
cslEngine.free();
|
||||
let cslEngine = style.getCiteProc(locale, 'html', { cache: true });
|
||||
html = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, 'html');
|
||||
cslEngine.free();
|
||||
cslEngine = style.getCiteProc(locale, 'text', { cache: true });
|
||||
var text = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, "text");
|
||||
text = Zotero.Cite.makeFormattedBibliographyOrCitationList(cslEngine, items, 'text');
|
||||
cslEngine.free();
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
text: format.contentType == "html" ? html : text,
|
||||
html,
|
||||
text: format.contentType === 'html' ? html : text,
|
||||
html
|
||||
};
|
||||
}
|
||||
|
||||
throw ("Invalid mode '" + format.mode + "' in Zotero.QuickCopy.getContentFromItems()");
|
||||
|
||||
throw new Error(`Invalid Quick Copy mode '${format.mode}'`);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Run an export translator synchronously (relies on noWait + preloaded
|
||||
* translator code) and return its string output, or null on failure.
|
||||
*/
|
||||
function _runExportTranslator(items, format) {
|
||||
let result = null;
|
||||
let translation = new Zotero.Translate.Export();
|
||||
translation.noWait = true;
|
||||
translation.setItems(items.slice());
|
||||
translation.setTranslator(format.id);
|
||||
if (format.options) {
|
||||
translation.setDisplayOptions(format.options);
|
||||
}
|
||||
translation.setHandler("done", (obj, worked) => {
|
||||
if (worked) {
|
||||
result = obj.string;
|
||||
}
|
||||
});
|
||||
translation.translate();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a note item to pass to getContentFromItems() from an array of annotations
|
||||
*
|
||||
|
|
@ -462,7 +527,7 @@ Zotero.QuickCopy = new function () {
|
|||
|
||||
// Use getFormat() so site-specific bibliography overrides apply when
|
||||
// the user is on a URL with a configured site setting
|
||||
let format = this.getFormat('bibliography');
|
||||
let format = this.getFormat({ mode: 'bibliography' });
|
||||
if (format.mode !== 'bibliography' || !format.id) {
|
||||
return items;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -410,48 +410,20 @@ class ReaderInstance {
|
|||
if (fromText) {
|
||||
return;
|
||||
}
|
||||
// annotations are wrapped in a temp note for translation
|
||||
// Convert the iframe's JSON annotations into a single note
|
||||
// item; getContentFromItems handles the rest (reformatting
|
||||
// embedded citations, picking the right output flavors).
|
||||
let items = [Zotero.QuickCopy.annotationsToNote(annotations)];
|
||||
// Reformat any citations in the annotation note using the
|
||||
// current bibliography style (matches main pane drag behavior)
|
||||
items = Zotero.QuickCopy.reformatNoteCitations(items);
|
||||
let format = Zotero.QuickCopy.getNoteFormat();
|
||||
let format = Zotero.QuickCopy.getFormat({ items });
|
||||
Zotero.debug(`Copying/dragging (${annotations.length}) annotation(s) with ${JSON.stringify(format)}`);
|
||||
// Basically the same code is used in itemTree.jsx onDragStart
|
||||
if (format.mode === 'export') {
|
||||
// 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, options: format.markdownOptions };
|
||||
let htmlFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML, options: format.htmlOptions };
|
||||
Zotero.QuickCopy.getContentFromItems(items, markdownFormat, (obj, worked) => {
|
||||
if (!worked) {
|
||||
return;
|
||||
}
|
||||
Zotero.QuickCopy.getContentFromItems(items, htmlFormat, (obj2, worked) => {
|
||||
if (!worked) {
|
||||
return;
|
||||
}
|
||||
dataTransfer.setData('text/plain', obj.string.replace(/\r\n/g, '\n'));
|
||||
dataTransfer.setData('text/html', obj2.string.replace(/\r\n/g, '\n'));
|
||||
});
|
||||
});
|
||||
|
||||
let content = Zotero.QuickCopy.getContentFromItems(items, format);
|
||||
if (content) {
|
||||
if (content.html) {
|
||||
dataTransfer.setData('text/html', content.html);
|
||||
}
|
||||
else {
|
||||
Zotero.QuickCopy.getContentFromItems(items, format, (obj, worked) => {
|
||||
if (!worked) {
|
||||
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 = new DOMParser();
|
||||
let doc = parser.parseFromString(text, 'text/html');
|
||||
text = doc.body.innerHTML;
|
||||
}
|
||||
dataTransfer.setData('text/plain', text);
|
||||
});
|
||||
if (content.text) {
|
||||
dataTransfer.setData('text/plain', content.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3401,73 +3401,46 @@ Zotero.Utilities.Internal.onDragItems = function (event, itemIDs, dragImage = ev
|
|||
}
|
||||
}
|
||||
|
||||
// Get Quick Copy format for current URL (set via /ping from connector)
|
||||
let format = Zotero.QuickCopy.getFormat();
|
||||
|
||||
// If all items are annotations, wrap them in a note object for translation
|
||||
// Skip Quick Copy data for very large drags so we don't hang the drag
|
||||
// preview while generating bibliography for the full set. The limit
|
||||
// applies only to drag; keyboard-shortcut copy has no cap.
|
||||
if (items.length > Zotero.Prefs.get('export.quickCopy.dragLimit')) {
|
||||
Zotero.debug("Skipping Quick Copy drag data for " + items.length + " items");
|
||||
return;
|
||||
}
|
||||
// When dragging annotation items, also set the zotero/annotation flavor
|
||||
// so the note editor knows how to handle them.
|
||||
if (items.every(item => item.isAnnotation())) {
|
||||
items = [Zotero.QuickCopy.annotationsToNote(items)];
|
||||
let jsonAnnotations = items.map((annotation) => {
|
||||
let json = Zotero.Annotations.toJSONSync(annotation);
|
||||
json.id = annotation.key;
|
||||
delete json.key;
|
||||
json.attachmentItemID = annotation.parentItemID;
|
||||
json.tags = json.tags || [];
|
||||
return json;
|
||||
});
|
||||
event.dataTransfer.setData('zotero/annotation', JSON.stringify(jsonAnnotations));
|
||||
}
|
||||
|
||||
// If all items are notes, use one of the note export translators
|
||||
if (items.every(item => item.isNote())) {
|
||||
format = Zotero.QuickCopy.getNoteFormat();
|
||||
items = Zotero.QuickCopy.reformatNoteCitations(items);
|
||||
}
|
||||
// Get Quick Copy format for current URL (set via /ping from connector)
|
||||
// and the items being dragged. getContentFromItems handles the rest
|
||||
// (annotation wrapping, note-citation reformatting, regular-item filter).
|
||||
let format = Zotero.QuickCopy.getFormat({ items });
|
||||
|
||||
Zotero.debug("Dragging with format " + JSON.stringify(format));
|
||||
try {
|
||||
if (format.mode == 'export') {
|
||||
// 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, options: format.markdownOptions };
|
||||
let htmlFormat = { mode: 'export', id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML, options: format.htmlOptions };
|
||||
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'));
|
||||
});
|
||||
});
|
||||
let content = Zotero.QuickCopy.getContentFromItems(items, format, {
|
||||
// Shift on drag → in-text citation (bibliography mode only)
|
||||
asCitations: format.mode === 'bibliography' && event.shiftKey
|
||||
});
|
||||
if (content) {
|
||||
if (content.html) {
|
||||
event.dataTransfer.setData('text/html', content.html);
|
||||
}
|
||||
else {
|
||||
Zotero.QuickCopy.getContentFromItems(items, format, (obj, worked) => {
|
||||
if (!worked) {
|
||||
Zotero.log(Zotero.getString('fileInterface.exportError'), 'warning');
|
||||
return;
|
||||
}
|
||||
let 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 = new DOMParser();
|
||||
let doc = parser.parseFromString(text, 'text/html');
|
||||
text = doc.body.innerHTML;
|
||||
}
|
||||
event.dataTransfer.setData('text/plain', text);
|
||||
});
|
||||
if (content.text) {
|
||||
event.dataTransfer.setData('text/plain', content.text);
|
||||
}
|
||||
}
|
||||
else if (format.mode == 'bibliography') {
|
||||
let content = Zotero.QuickCopy.getContentFromItems(items, format, null, event.shiftKey);
|
||||
if (content) {
|
||||
if (content.html) {
|
||||
event.dataTransfer.setData("text/html", content.html);
|
||||
}
|
||||
event.dataTransfer.setData("text/plain", content.text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Zotero.logError("Invalid Quick Copy mode");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
|
|
|
|||
|
|
@ -2698,62 +2698,23 @@ var ZoteroPane = new function () {
|
|||
|
||||
|
||||
this.copySelectedItemsToClipboard = function (asCitations, mode = 'bibliography') {
|
||||
var items = [];
|
||||
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);
|
||||
let items = Zotero.Items.get(itemIDs);
|
||||
if (!items.length) return;
|
||||
|
||||
if (!items.length) {
|
||||
return;
|
||||
}
|
||||
let format = Zotero.QuickCopy.getFormat({ mode, items });
|
||||
|
||||
var format = Zotero.QuickCopy.getFormat(mode);
|
||||
if (items.every(item => item.isNote() || item.isAttachment() || item.isAnnotation())) {
|
||||
format = Zotero.QuickCopy.getNoteFormat();
|
||||
}
|
||||
// To copy annotations, wrap them in a temp note
|
||||
if (items.every(item => item.isAnnotation())) {
|
||||
items = [Zotero.QuickCopy.annotationsToNote(items)];
|
||||
}
|
||||
if (items.every(item => item.isNote())) {
|
||||
items = Zotero.QuickCopy.reformatNoteCitations(items);
|
||||
}
|
||||
// asCitations only applies to bibliography mode
|
||||
if (asCitations && format.mode !== 'bibliography') return;
|
||||
|
||||
// In bibliography mode, remove notes and attachments
|
||||
if (format.mode == 'bibliography') {
|
||||
items = items.filter(item => item.isRegularItem());
|
||||
}
|
||||
|
||||
// DEBUG: We could copy notes via keyboard shortcut if we altered
|
||||
// Z_F_I.copyItemsToClipboard() to use Z.QuickCopy.getContentFromItems(),
|
||||
// but 1) we'd need to override that function's drag limit and 2) when I
|
||||
// tried it the OS X clipboard seemed to be getting text vs. HTML wrong,
|
||||
// automatically converting text/html to plaintext rather than using
|
||||
// text/unicode. (That may be fixable, however.)
|
||||
//
|
||||
// This isn't currently shown, because the commands are disabled when not relevant, so this
|
||||
// function isn't called
|
||||
if (!items.length) {
|
||||
let content = Zotero.QuickCopy.getContentFromItems(items, format, { asCitations });
|
||||
if (!content) {
|
||||
Services.prompt.alert(null, "", Zotero.getString("fileInterface.noReferencesError"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (format.mode == 'bibliography') {
|
||||
var locale = format.locale;
|
||||
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
|
||||
if (asCitations) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Zotero_File_Interface.exportItemsToClipboard(items, format);
|
||||
}
|
||||
}
|
||||
Zotero_File_Interface.writeToClipboard(content);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ describe("Zotero_File_Interface", function () {
|
|||
});
|
||||
|
||||
|
||||
describe("#copyItemsToClipboard()", function () {
|
||||
describe("#writeToClipboard()", function () {
|
||||
var clipboardService, item1, item2;
|
||||
|
||||
before(function* () {
|
||||
|
|
@ -164,73 +164,70 @@ describe("Zotero_File_Interface", function () {
|
|||
// Non-"Copy as HTML" mode
|
||||
//
|
||||
it("should copy HTML and text citations to the clipboard", async function () {
|
||||
win.Zotero_File_Interface.copyItemsToClipboard(
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
[item1, item2],
|
||||
'http://www.zotero.org/styles/apa',
|
||||
'en-US',
|
||||
false,
|
||||
true
|
||||
{ mode: 'bibliography', id: 'http://www.zotero.org/styles/apa', contentType: '', locale: 'en-US' },
|
||||
{ asCitations: true }
|
||||
);
|
||||
|
||||
win.Zotero_File_Interface.writeToClipboard(content);
|
||||
|
||||
// HTML
|
||||
var str = getDataForFlavor('text/html');
|
||||
assert.equal(str, '(<i>A</i>, 2016; <i>B</i>, 2016)');
|
||||
|
||||
|
||||
// Plain text
|
||||
str = getDataForFlavor('text/plain');
|
||||
assert.equal(str, '(A, 2016; B, 2016)');
|
||||
});
|
||||
|
||||
|
||||
it("should copy HTML and text bibliography to the clipboard", async function () {
|
||||
win.Zotero_File_Interface.copyItemsToClipboard(
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
[item1, item2],
|
||||
'http://www.zotero.org/styles/apa',
|
||||
'en-US'
|
||||
{ mode: 'bibliography', id: 'http://www.zotero.org/styles/apa', contentType: '', locale: 'en-US' }
|
||||
);
|
||||
|
||||
win.Zotero_File_Interface.writeToClipboard(content);
|
||||
|
||||
var str = getDataForFlavor('text/html');
|
||||
assert.include(str, 'line-height');
|
||||
assert.include(str, '<i>A</i>');
|
||||
assert.include(str, '<i>B</i>');
|
||||
|
||||
|
||||
// Plain text
|
||||
str = getDataForFlavor('text/plain');
|
||||
assert.equal(str, 'A. (2016).\nB. (2016).\n');
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// "Copy as HTML" mode
|
||||
//
|
||||
it("should copy HTML and HTML source citations to the clipboard", async function () {
|
||||
win.Zotero_File_Interface.copyItemsToClipboard(
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
[item1, item2],
|
||||
'http://www.zotero.org/styles/apa',
|
||||
'en-US',
|
||||
true,
|
||||
true
|
||||
{ mode: 'bibliography', id: 'http://www.zotero.org/styles/apa', contentType: 'html', locale: 'en-US' },
|
||||
{ asCitations: true }
|
||||
);
|
||||
|
||||
win.Zotero_File_Interface.writeToClipboard(content);
|
||||
|
||||
var str = getDataForFlavor('text/html');
|
||||
assert.equal(str, '(<i>A</i>, 2016; <i>B</i>, 2016)');
|
||||
|
||||
|
||||
// Plain text
|
||||
str = getDataForFlavor('text/plain');
|
||||
assert.equal(str, '(<i>A</i>, 2016; <i>B</i>, 2016)');
|
||||
});
|
||||
|
||||
|
||||
it("should copy HTML and HTML source bibliography to the clipboard", async function () {
|
||||
win.Zotero_File_Interface.copyItemsToClipboard(
|
||||
let content = Zotero.QuickCopy.getContentFromItems(
|
||||
[item1, item2],
|
||||
'http://www.zotero.org/styles/apa',
|
||||
'en-US',
|
||||
true
|
||||
{ mode: 'bibliography', id: 'http://www.zotero.org/styles/apa', contentType: 'html', locale: 'en-US' }
|
||||
);
|
||||
|
||||
win.Zotero_File_Interface.writeToClipboard(content);
|
||||
|
||||
var str = getDataForFlavor('text/html');
|
||||
assert.include(str, 'line-height');
|
||||
assert.include(str, '<i>A</i>');
|
||||
assert.include(str, '<i>B</i>');
|
||||
|
||||
|
||||
// Plain text
|
||||
str = getDataForFlavor('text/plain');
|
||||
assert.include(str, 'line-height');
|
||||
|
|
@ -475,7 +472,8 @@ describe("Zotero_File_Interface", function () {
|
|||
markdownOptions: { includeAppLinks: false },
|
||||
htmlOptions: { includeAppLinks: false }
|
||||
};
|
||||
win.Zotero_File_Interface.exportItemsToClipboard(items, format);
|
||||
let content = Zotero.QuickCopy.getContentFromItems(items, format);
|
||||
win.Zotero_File_Interface.writeToClipboard(content);
|
||||
await Zotero.Promise.delay();
|
||||
|
||||
var text = getClipboardText();
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ describe("Zotero.QuickCopy", function () {
|
|||
await Zotero.QuickCopy.loadSiteSettings();
|
||||
|
||||
Zotero.QuickCopy.lastActiveURL = 'https://wiki.test.org/page';
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
});
|
||||
|
||||
|
|
@ -107,14 +107,14 @@ describe("Zotero.QuickCopy", function () {
|
|||
await Zotero.QuickCopy.loadSiteSettings();
|
||||
|
||||
Zotero.QuickCopy.lastActiveURL = 'https://test.org/styles/apa';
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
});
|
||||
|
||||
describe("default settings (no site match)", function () {
|
||||
it("should return the default bibliographySetting for mode='bibliography'", function () {
|
||||
Zotero.QuickCopy.lastActiveURL = 'https://no-match.test/';
|
||||
let result = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let result = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
let expected = Zotero.QuickCopy.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.bibliographySetting')
|
||||
);
|
||||
|
|
@ -124,7 +124,7 @@ describe("Zotero.QuickCopy", function () {
|
|||
|
||||
it("should return the default exportSetting for mode='export'", function () {
|
||||
Zotero.QuickCopy.lastActiveURL = 'https://no-match.test/';
|
||||
let result = Zotero.QuickCopy.getFormat('export');
|
||||
let result = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
let expected = Zotero.QuickCopy.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.exportSetting')
|
||||
);
|
||||
|
|
@ -156,14 +156,14 @@ describe("Zotero.QuickCopy", function () {
|
|||
await setSiteSetting(legacy);
|
||||
|
||||
// bibliography mode → site override
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.mode, 'bibliography');
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
assert.equal(bib.contentType, 'html');
|
||||
assert.equal(bib.locale, 'en-US');
|
||||
|
||||
// export mode → no site override → global default
|
||||
let exp = Zotero.QuickCopy.getFormat('export');
|
||||
let exp = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
let globalExport = Zotero.QuickCopy.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.exportSetting')
|
||||
);
|
||||
|
|
@ -185,12 +185,12 @@ describe("Zotero.QuickCopy", function () {
|
|||
await setSiteSetting(legacy);
|
||||
|
||||
// export mode → site override
|
||||
let exp = Zotero.QuickCopy.getFormat('export');
|
||||
let exp = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
assert.equal(exp.mode, 'export');
|
||||
assert.equal(exp.id, BIBTEX_TRANSLATOR_ID);
|
||||
|
||||
// bibliography mode → no site override → global default
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
let globalBib = Zotero.QuickCopy.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.bibliographySetting')
|
||||
);
|
||||
|
|
@ -207,7 +207,7 @@ describe("Zotero.QuickCopy", function () {
|
|||
Zotero.QuickCopy.lastActiveURL = `https://${domain}/`;
|
||||
await setSiteSetting(`bibliography/html=${APA_STYLE_ID}`);
|
||||
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.mode, 'bibliography');
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
assert.equal(bib.contentType, 'html');
|
||||
|
|
@ -227,13 +227,13 @@ describe("Zotero.QuickCopy", function () {
|
|||
});
|
||||
await setSiteSetting(siteFormat);
|
||||
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.mode, 'bibliography');
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
assert.equal(bib.locale, 'fr-FR');
|
||||
|
||||
// export → no site override → global default
|
||||
let exp = Zotero.QuickCopy.getFormat('export');
|
||||
let exp = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
let globalExport = Zotero.QuickCopy.unserializeSetting(
|
||||
Zotero.Prefs.get('export.quickCopy.exportSetting')
|
||||
);
|
||||
|
|
@ -254,11 +254,11 @@ describe("Zotero.QuickCopy", function () {
|
|||
});
|
||||
await setSiteSetting(siteFormat);
|
||||
|
||||
let bib = Zotero.QuickCopy.getFormat('bibliography');
|
||||
let bib = Zotero.QuickCopy.getFormat({ mode: 'bibliography' });
|
||||
assert.equal(bib.mode, 'bibliography');
|
||||
assert.equal(bib.id, APA_STYLE_ID);
|
||||
|
||||
let exp = Zotero.QuickCopy.getFormat('export');
|
||||
let exp = Zotero.QuickCopy.getFormat({ mode: 'export' });
|
||||
assert.equal(exp.mode, 'export');
|
||||
assert.equal(exp.id, BIBTEX_TRANSLATOR_ID);
|
||||
|
||||
|
|
@ -288,11 +288,9 @@ describe("Zotero.QuickCopy", function () {
|
|||
describe("#getContentFromItems()", function () {
|
||||
it("should generate BibTeX", async function () {
|
||||
var item = await createDataObject('item');
|
||||
var content = "";
|
||||
var worked = false;
|
||||
|
||||
await Zotero.Translators.init();
|
||||
|
||||
|
||||
var translatorID = '9cb70025-a888-4a29-a210-93ec52da40d4'; // BibTeX
|
||||
var format = 'export=' + translatorID;
|
||||
Zotero.Prefs.set("export.quickCopy.exportSetting", format);
|
||||
|
|
@ -301,17 +299,10 @@ describe("Zotero.QuickCopy", function () {
|
|||
while (!translator.code) {
|
||||
await Zotero.Promise.delay(50);
|
||||
}
|
||||
|
||||
Zotero.QuickCopy.getContentFromItems(
|
||||
[item],
|
||||
format,
|
||||
(obj, w) => {
|
||||
content = obj.string;
|
||||
worked = w;
|
||||
}
|
||||
);
|
||||
assert.isTrue(worked);
|
||||
assert.isTrue(content.trim().startsWith('@'));
|
||||
|
||||
let content = Zotero.QuickCopy.getContentFromItems([item], format);
|
||||
assert.isString(content.text);
|
||||
assert.isTrue(content.text.trim().startsWith('@'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -319,13 +310,11 @@ describe("Zotero.QuickCopy", function () {
|
|||
var item = createUnsavedDataObject('item', { itemType: 'webpage', title: 'Foo' });
|
||||
item.setField('date', '2020-03-11');
|
||||
await item.saveTx();
|
||||
var content = "";
|
||||
var worked = false;
|
||||
|
||||
|
||||
// This shouldn't be used
|
||||
Zotero.Prefs.set('export.lastLocale', 'fr-FR');
|
||||
await Zotero.Styles.init();
|
||||
|
||||
|
||||
var format = 'bibliography=http://www.zotero.org/styles/apa';
|
||||
Zotero.Prefs.set("export.quickCopy.bibliographySetting", format);
|
||||
|
||||
|
|
@ -357,7 +346,7 @@ describe("Zotero.QuickCopy", function () {
|
|||
await item.saveTx();
|
||||
|
||||
// Copy citation, not bibliography
|
||||
let { text } = Zotero.QuickCopy.getContentFromItems([item], format, null, true);
|
||||
assert.equal(text, '《新型数据财产的行为主义保护:基于财产权理论的分析》。');
|
||||
let content = Zotero.QuickCopy.getContentFromItems([item], format, { asCitations: true });
|
||||
assert.equal(content.text, '《新型数据财产的行为主义保护:基于财产权理论的分析》。');
|
||||
});
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue