Merge branch '3.0'
Conflicts: chrome/content/zotero/overlay.js chrome/content/zotero/xpcom/schema.js
This commit is contained in:
commit
b3f9f5102b
|
@ -152,10 +152,10 @@ var ZoteroOverlay = new function()
|
|||
// save current state
|
||||
_stateBeforeReload = !zoteroPane.hidden && !zoteroPane.collapsed;
|
||||
// ensure pane is closed
|
||||
if(!zoteroPane.collapsed) ZoteroOverlay.toggleDisplay(false);
|
||||
if(!zoteroPane.collapsed) ZoteroOverlay.toggleDisplay(false, true);
|
||||
} else {
|
||||
// reopen pane if it was open before
|
||||
ZoteroOverlay.toggleDisplay(_stateBeforeReload);
|
||||
ZoteroOverlay.toggleDisplay(_stateBeforeReload, true);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -202,9 +202,13 @@ var ZoteroOverlay = new function()
|
|||
|
||||
/**
|
||||
* Hides/displays the Zotero interface
|
||||
* @param {Boolean} makeVisible Whether or not Zotero interface should be visible
|
||||
* @param {Boolean} dontRefocus If true, don't focus content when closing Zotero pane. Used
|
||||
* when closing pane because Zotero Standalone is being opened, to avoid pulling Firefox to
|
||||
* the foreground.
|
||||
*/
|
||||
this.toggleDisplay = function(makeVisible)
|
||||
{
|
||||
this.toggleDisplay = function(makeVisible, dontRefocus)
|
||||
{
|
||||
if(!Zotero || !Zotero.initialized) {
|
||||
ZoteroPane.displayStartupError();
|
||||
return;
|
||||
|
@ -271,6 +275,11 @@ var ZoteroOverlay = new function()
|
|||
zoteroPane.height = 0;
|
||||
|
||||
document.getElementById('content').setAttribute('collapsed', false);
|
||||
|
||||
if(!dontRefocus) {
|
||||
// Return focus to the browser content pane
|
||||
window.content.window.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -604,7 +604,9 @@ function populateQuickCopyList() {
|
|||
menulist.setAttribute('preference', "pref-quickCopy-setting");
|
||||
updateQuickCopyHTMLCheckbox();
|
||||
|
||||
refreshQuickCopySiteList();
|
||||
if (!Zotero.isStandalone) {
|
||||
refreshQuickCopySiteList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -776,11 +778,18 @@ function deleteSelectedQuickCopySite() {
|
|||
|
||||
function updateQuickCopyInstructions() {
|
||||
var prefix = Zotero.isMac ? 'Cmd+Shift+' : 'Ctrl+Alt+';
|
||||
|
||||
var key = Zotero.Prefs.get('keys.copySelectedItemsToClipboard');
|
||||
|
||||
var instr = document.getElementById('quickCopy-instructions');
|
||||
var str = Zotero.getString('zotero.preferences.export.quickCopy.instructions', prefix + key);
|
||||
var instr = document.getElementById('quickCopy-instructions');
|
||||
while (instr.hasChildNodes()) {
|
||||
instr.removeChild(instr.firstChild);
|
||||
}
|
||||
instr.appendChild(document.createTextNode(str));
|
||||
|
||||
var key = Zotero.Prefs.get('keys.copySelectedItemCitationsToClipboard');
|
||||
var str = Zotero.getString('zotero.preferences.export.quickCopy.citationInstructions', prefix + key);
|
||||
var instr = document.getElementById('quickCopy-citationInstructions');
|
||||
while (instr.hasChildNodes()) {
|
||||
instr.removeChild(instr.firstChild);
|
||||
}
|
||||
|
@ -1258,6 +1267,55 @@ function runIntegrityCheck() {
|
|||
var ok = Zotero.DB.integrityCheck();
|
||||
if (ok) {
|
||||
ok = Zotero.Schema.integrityCheck();
|
||||
if (!ok) {
|
||||
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
|
||||
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
|
||||
var index = ps.confirmEx(window,
|
||||
Zotero.getString('general.failed'),
|
||||
Zotero.getString('db.integrityCheck.failed') + "\n\n" +
|
||||
Zotero.getString('db.integrityCheck.repairAttempt') + " " +
|
||||
Zotero.getString('db.integrityCheck.appRestartNeeded', Zotero.appName),
|
||||
buttonFlags,
|
||||
Zotero.getString('db.integrityCheck.fixAndRestart', Zotero.appName),
|
||||
null, null, null, {}
|
||||
);
|
||||
|
||||
if (index == 0) {
|
||||
// Safety first
|
||||
Zotero.DB.backupDatabase();
|
||||
|
||||
// Fix the errors
|
||||
Zotero.Schema.integrityCheck(true);
|
||||
|
||||
// And run the check again
|
||||
ok = Zotero.Schema.integrityCheck();
|
||||
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING);
|
||||
if (ok) {
|
||||
var str = 'success';
|
||||
var msg = Zotero.getString('db.integrityCheck.errorsFixed');
|
||||
}
|
||||
else {
|
||||
var str = 'failed';
|
||||
var msg = Zotero.getString('db.integrityCheck.errorsNotFixed')
|
||||
+ "\n\n" + Zotero.getString('db.integrityCheck.reportInForums');
|
||||
}
|
||||
|
||||
ps.confirmEx(window,
|
||||
Zotero.getString('general.' + str),
|
||||
msg,
|
||||
buttonFlags,
|
||||
Zotero.getString('general.restartApp', Zotero.appName),
|
||||
null, null, null, {}
|
||||
);
|
||||
|
||||
var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Components.interfaces.nsIAppStartup);
|
||||
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit
|
||||
| Components.interfaces.nsIAppStartup.eRestart);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
var str = ok ? 'passed' : 'failed';
|
||||
|
||||
|
|
|
@ -522,39 +522,24 @@ To add a new preference:
|
|||
<preference id="pref-quickCopy-dragLimit" name="extensions.zotero.export.quickCopy.dragLimit" type="int"/>
|
||||
</preferences>
|
||||
|
||||
<groupbox>
|
||||
<groupbox id="zotero-prefpane-export-groupbox">
|
||||
<caption label="&zotero.preferences.quickCopy.caption;"/>
|
||||
|
||||
<label id="quickCopy-instructions"/>
|
||||
<separator class="thin"/>
|
||||
<label id="quickCopy-citationInstructions"/>
|
||||
|
||||
<separator/>
|
||||
|
||||
<label value="&zotero.preferences.quickCopy.defaultOutputFormat;" control="quickCopy-menu"/>
|
||||
<menulist id="zotero-quickCopy-menu"/>
|
||||
|
||||
<separator/>
|
||||
<separator class="thin"/>
|
||||
|
||||
<checkbox id="zotero-quickCopy-copyAsHTML" label="&zotero.preferences.quickCopy.copyAsHTML;"
|
||||
oncommand="buildQuickCopyFormatDropDown(document.getElementById('zotero-quickCopy-menu'), this.checked ? 'html' : '');"/>
|
||||
|
||||
<separator/>
|
||||
|
||||
<label value="&zotero.preferences.quickCopy.siteEditor.setings;" control="quickCopy-siteSettings"/>
|
||||
<tree flex="1" id="quickCopy-siteSettings" hidecolumnpicker="true" rows="6" seltype="single"
|
||||
ondblclick="showQuickCopySiteEditor(this.currentIndex)"
|
||||
onkeypress="if (event.keyCode == event.DOM_VK_DELETE) { deleteSelectedQuickCopySite(); }">
|
||||
<treecols>
|
||||
<treecol id="quickCopy-urlColumn" label="&zotero.preferences.quickCopy.siteEditor.domainPath;" flex="1"/>
|
||||
<treecol id="quickCopy-formatColumn" label="&zotero.preferences.quickCopy.siteEditor.outputFormat;" flex="2"/>
|
||||
<treecol id="quickCopy-copyAsHTML" label="HTML"/>
|
||||
</treecols>
|
||||
<treechildren id="quickCopy-siteSettings-rows"/>
|
||||
</tree>
|
||||
<separator class="thin"/>
|
||||
<hbox pack="end">
|
||||
<button label="-" onclick="deleteSelectedQuickCopySite()"/>
|
||||
<button label="+" onclick="showQuickCopySiteEditor()"/>
|
||||
</hbox>
|
||||
<vbox id="zotero-prefpane-export-siteSettings"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&zotero.preferences.quickCopy.dragLimit;"/>
|
||||
|
|
|
@ -76,6 +76,35 @@ To add a new preference:
|
|||
</grid>
|
||||
</groupbox>
|
||||
</prefpane>
|
||||
|
||||
<prefpane id="zotero-prefpane-export"
|
||||
label="&zotero.preferences.prefpane.export;"
|
||||
image="chrome://zotero/skin/prefs-export.png"
|
||||
helpTopic="export">
|
||||
<groupbox id="zotero-prefpane-export-groupbox">
|
||||
<vbox id="zotero-prefpane-export-siteSettings">
|
||||
<separator/>
|
||||
|
||||
<label value="&zotero.preferences.quickCopy.siteEditor.setings;" control="quickCopy-siteSettings"/>
|
||||
<tree flex="1" id="quickCopy-siteSettings" hidecolumnpicker="true" rows="6" seltype="single"
|
||||
ondblclick="showQuickCopySiteEditor(this.currentIndex)"
|
||||
onkeypress="if (event.keyCode == event.DOM_VK_DELETE) { deleteSelectedQuickCopySite(); }">
|
||||
<treecols>
|
||||
<treecol id="quickCopy-urlColumn" label="&zotero.preferences.quickCopy.siteEditor.domainPath;" flex="1"/>
|
||||
<treecol id="quickCopy-formatColumn" label="&zotero.preferences.quickCopy.siteEditor.outputFormat;" flex="2"/>
|
||||
<treecol id="quickCopy-copyAsHTML" label="HTML"/>
|
||||
</treecols>
|
||||
<treechildren id="quickCopy-siteSettings-rows"/>
|
||||
</tree>
|
||||
<separator class="thin"/>
|
||||
<hbox pack="end">
|
||||
<button label="-" onclick="deleteSelectedQuickCopySite()"/>
|
||||
<button label="+" onclick="showQuickCopySiteEditor()"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
</prefpane>
|
||||
|
||||
<prefpane id="zotero-prefpane-proxies"
|
||||
label="&zotero.preferences.prefpane.proxies;"
|
||||
image="chrome://zotero/skin/prefs-proxies.png" position="6"
|
||||
|
|
|
@ -8,6 +8,7 @@ table {
|
|||
border-width: 0 0 1px 1px;
|
||||
border-style: solid;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td, th {
|
||||
|
@ -18,16 +19,19 @@ td, th {
|
|||
}
|
||||
|
||||
.th-translator {
|
||||
width: 500px;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.th-status {
|
||||
width: 100px;
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.th-pending, .th-supported, .th-succeeded, .th-failed, .th-unknown {
|
||||
.th-pending, .th-supported, .th-succeeded, .th-failed, .th-mismatch {
|
||||
width: 75px;
|
||||
max-width: 75px;
|
||||
}
|
||||
|
||||
.th-issues {
|
||||
}
|
||||
|
||||
.status-succeeded, .supported-yes {
|
||||
|
@ -38,7 +42,7 @@ td, th {
|
|||
background-color: #ff9090;
|
||||
}
|
||||
|
||||
.status-unknown {
|
||||
.status-mismatch {
|
||||
background-color: #FFB;
|
||||
}
|
||||
|
||||
|
@ -50,6 +54,10 @@ td, th {
|
|||
background-color: #9FF;
|
||||
}
|
||||
|
||||
.status-partial-failure {
|
||||
background-color: rgb(249, 180, 98);
|
||||
}
|
||||
|
||||
tr.output-displayed > td {
|
||||
background-color: #b4d5ff !important;
|
||||
}
|
||||
|
|
|
@ -25,16 +25,64 @@
|
|||
|
||||
const NUM_CONCURRENT_TESTS = 6;
|
||||
const TRANSLATOR_TYPES = ["Web", "Import", "Export", "Search"];
|
||||
const TABLE_COLUMNS = ["Translator", "Supported", "Status", "Pending", "Succeeded", "Failed", "Unknown"];
|
||||
const TABLE_COLUMNS = ["Translator", "Supported", "Status", "Pending", "Succeeded", "Failed", "Mismatch", "Issues"];
|
||||
var translatorTables = {},
|
||||
translatorTestViews = {},
|
||||
translatorTestViewsToRun = {},
|
||||
translatorTestStats = {},
|
||||
translatorBox,
|
||||
outputBox,
|
||||
allOutputView,
|
||||
currentOutputView,
|
||||
viewerMode = true;
|
||||
|
||||
/**
|
||||
* Fetches issue information from GitHub
|
||||
*/
|
||||
var Issues = new function() {
|
||||
var _executeWhenRetrieved = [];
|
||||
var githubInfo;
|
||||
|
||||
/**
|
||||
* Gets issues for a specific translator
|
||||
* @param {String} translatorLabel Gets issues starting with translatorLabel
|
||||
* @param {Function} callback Function to call when issue information is available
|
||||
*/
|
||||
this.getFor = function(translatorLabel, callback) {
|
||||
translatorLabel = translatorLabel.toLowerCase();
|
||||
|
||||
var whenRetrieved = function() {
|
||||
var issues = [];
|
||||
for(var i=0; i<githubInfo.length; i++) {
|
||||
var issue = githubInfo[i];
|
||||
if(issue.title.substr(0, translatorLabel.length).toLowerCase() === translatorLabel) {
|
||||
issues.push(issue);
|
||||
}
|
||||
}
|
||||
callback(issues);
|
||||
};
|
||||
|
||||
if(githubInfo) {
|
||||
whenRetrieved();
|
||||
} else {
|
||||
_executeWhenRetrieved.push(whenRetrieved);
|
||||
}
|
||||
};
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", "https://api.github.com/repos/zotero/translators/issues", true);
|
||||
req.onreadystatechange = function(e) {
|
||||
if(req.readyState != 4) return;
|
||||
|
||||
githubInfo = JSON.parse(req.responseText);
|
||||
for(var i=0; i<_executeWhenRetrieved.length; i++) {
|
||||
_executeWhenRetrieved[i]();
|
||||
}
|
||||
_executeWhenRetrieved = [];
|
||||
};
|
||||
req.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding debug output to the output box
|
||||
* @param {HTMLElement} el An element to add class="selected" to when this outputView is displayed
|
||||
|
@ -89,7 +137,7 @@ var TranslatorTestView = function(translator, type) {
|
|||
this._status = document.createElement("td");
|
||||
row.appendChild(this._status);
|
||||
|
||||
// Unknown
|
||||
// Pending
|
||||
this._pending = document.createElement("td");
|
||||
row.appendChild(this._pending);
|
||||
|
||||
|
@ -101,10 +149,14 @@ var TranslatorTestView = function(translator, type) {
|
|||
this._failed = document.createElement("td");
|
||||
row.appendChild(this._failed);
|
||||
|
||||
// Unknown
|
||||
// Mismatch
|
||||
this._unknown = document.createElement("td");
|
||||
row.appendChild(this._unknown);
|
||||
|
||||
// Issues
|
||||
this._issues = document.createElement("td");
|
||||
row.appendChild(this._issues);
|
||||
|
||||
// create output view and debug function
|
||||
var outputView = this._outputView = new OutputView(row);
|
||||
this._debug = function(obj, msg, level) {
|
||||
|
@ -125,21 +177,48 @@ var TranslatorTestView = function(translator, type) {
|
|||
this.isRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label and retrieves corresponding GitHub issues
|
||||
*/
|
||||
TranslatorTestView.prototype.setLabel = function(label) {
|
||||
this._label.appendChild(document.createTextNode(label));
|
||||
var issuesNode = this._issues;
|
||||
Issues.getFor(label, function(issues) {
|
||||
for(var i=0; i<issues.length; i++) {
|
||||
var issue = issues[i];
|
||||
var div = document.createElement("div"),
|
||||
a = document.createElement("a");
|
||||
|
||||
var date = issue.updated_at;
|
||||
date = new Date(Date.UTC(date.substr(0, 4), date.substr(5, 2)-1, date.substr(8, 2),
|
||||
date.substr(11, 2), date.substr(14, 2), date.substr(17, 2)));
|
||||
if("toLocaleFormat" in date) {
|
||||
date = date.toLocaleFormat("%x");
|
||||
} else {
|
||||
date = date.getFullYear()+"-"+date.getMonth()+"-"+date.getDate();
|
||||
}
|
||||
|
||||
a.textContent = issue.title+" (#"+issue.number+"; "+date+")";
|
||||
a.setAttribute("href", issue.html_url);
|
||||
a.setAttribute("target", "_blank");
|
||||
div.appendChild(a);
|
||||
issuesNode.appendChild(div);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes TranslatorTestView given a translator and its type
|
||||
*/
|
||||
TranslatorTestView.prototype.initWithTranslatorAndType = function(translator, type) {
|
||||
this._label.appendChild(document.createTextNode(translator.label));
|
||||
|
||||
this.isSupported = translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER;
|
||||
this._supported.appendChild(document.createTextNode(this.isSupported ? "Yes" : "No"));
|
||||
this._supported.className = this.isSupported ? "supported-yes" : "supported-no";
|
||||
this.setLabel(translator.label);
|
||||
|
||||
this._translatorTester = new Zotero_TranslatorTester(translator, type, this._debug);
|
||||
this.canRun = !!this._translatorTester.tests.length;
|
||||
this.updateStatus(this._translatorTester);
|
||||
|
||||
this._type = type;
|
||||
translatorTestViews[type].push(this);
|
||||
translatorTables[this._type].appendChild(this._row);
|
||||
}
|
||||
|
||||
|
@ -148,16 +227,13 @@ TranslatorTestView.prototype.initWithTranslatorAndType = function(translator, ty
|
|||
*/
|
||||
TranslatorTestView.prototype.unserialize = function(serializedData) {
|
||||
this._outputView.addOutput(serializedData.output);
|
||||
this._label.appendChild(document.createTextNode(serializedData.label));
|
||||
this.setLabel(serializedData.label);
|
||||
|
||||
this.isSupported = serializedData.isSupported;
|
||||
this._supported.appendChild(document.createTextNode(this.isSupported ? "Yes" : "No"));
|
||||
this._supported.className = this.isSupported ? "supported-yes" : "supported-no";
|
||||
this._type = serializedData.type;
|
||||
translatorTestViews[serializedData.type].push(this);
|
||||
|
||||
this.canRun = false;
|
||||
this.updateStatus(serializedData);
|
||||
|
||||
this._type = serializedData.type;
|
||||
translatorTables[this._type].appendChild(this._row);
|
||||
}
|
||||
|
||||
|
@ -165,16 +241,7 @@ TranslatorTestView.prototype.unserialize = function(serializedData) {
|
|||
* Initializes TranslatorTestView given a JSON-ified translatorTester
|
||||
*/
|
||||
TranslatorTestView.prototype.serialize = function(serializedData) {
|
||||
return {
|
||||
"type":this._type,
|
||||
"output":this._outputView.getOutput(),
|
||||
"label":this._label.textContent,
|
||||
"isSupported":this.isSupported,
|
||||
"pending":parseInt(this._pending.textContent),
|
||||
"failed":parseInt(this._failed.textContent),
|
||||
"succeeded":parseInt(this._succeeded.textContent),
|
||||
"unknown":parseInt(this._unknown.textContent)
|
||||
};
|
||||
return this._translatorTester.serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,6 +252,9 @@ TranslatorTestView.prototype.updateStatus = function(obj, status) {
|
|||
this._status.removeChild(this._status.firstChild);
|
||||
}
|
||||
|
||||
this._supported.textContent = obj.isSupported ? "Yes" : "No";
|
||||
this._supported.className = obj.isSupported ? "supported-yes" : "supported-no";
|
||||
|
||||
var pending = typeof obj.pending === "object" ? obj.pending.length : obj.pending;
|
||||
var succeeded = typeof obj.succeeded === "object" ? obj.succeeded.length : obj.succeeded;
|
||||
var failed = typeof obj.failed === "object" ? obj.failed.length : obj.failed;
|
||||
|
@ -212,15 +282,18 @@ TranslatorTestView.prototype.updateStatus = function(obj, status) {
|
|||
} else {
|
||||
this._status.textContent = "Not Run";
|
||||
}
|
||||
} else if((succeeded || unknown) && failed) {
|
||||
this._status.className = "status-partial-failure";
|
||||
this._status.textContent = "Partial Failure";
|
||||
} else if(failed) {
|
||||
this._status.className = "status-failed";
|
||||
this._status.textContent = "Failed";
|
||||
this._status.textContent = "Failure";
|
||||
} else if(unknown) {
|
||||
this._status.className = "status-unknown";
|
||||
this._status.textContent = "Unknown";
|
||||
this._status.className = "status-mismatch";
|
||||
this._status.textContent = "Data Mismatch";
|
||||
} else {
|
||||
this._status.className = "status-succeeded";
|
||||
this._status.textContent = "Succeeded";
|
||||
this._status.textContent = "Success";
|
||||
}
|
||||
} else {
|
||||
this._status.className = "status-untested";
|
||||
|
@ -231,6 +304,8 @@ TranslatorTestView.prototype.updateStatus = function(obj, status) {
|
|||
this._succeeded.textContent = succeeded;
|
||||
this._failed.textContent = failed;
|
||||
this._unknown.textContent = unknown;
|
||||
|
||||
if(this._type) translatorTestStats[this._type].update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,6 +330,44 @@ TranslatorTestView.prototype.runTests = function(doneCallback) {
|
|||
this._translatorTester.runTests(newCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets overall stats for translators
|
||||
*/
|
||||
var TranslatorTestStats = function(translatorType) {
|
||||
this.translatorType = translatorType
|
||||
this.node = document.createElement("p");
|
||||
};
|
||||
|
||||
TranslatorTestStats.prototype.update = function() {
|
||||
var types = {
|
||||
"Success":0,
|
||||
"Data Mismatch":0,
|
||||
"Partial Failure":0,
|
||||
"Failure":0,
|
||||
"Untested":0,
|
||||
"Running":0,
|
||||
"Pending":0,
|
||||
"Not Run":0
|
||||
};
|
||||
|
||||
var testViews = translatorTestViews[this.translatorType];
|
||||
for(var i in testViews) {
|
||||
var status = testViews[i]._status ? testViews[i]._status.textContent : "Not Run";
|
||||
if(status in types) {
|
||||
types[status] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var typeInfo = [];
|
||||
for(var i in types) {
|
||||
if(types[i]) {
|
||||
typeInfo.push(i+": "+types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.node.textContent = typeInfo.join(" | ");
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when loaded
|
||||
*/
|
||||
|
@ -308,6 +421,8 @@ function init() {
|
|||
var displayType = TRANSLATOR_TYPES[i];
|
||||
var translatorType = displayType.toLowerCase();
|
||||
|
||||
translatorTestViews[translatorType] = [];
|
||||
|
||||
// create header
|
||||
var h1 = document.createElement("h1");
|
||||
h1.appendChild(document.createTextNode(displayType+" Translators "));
|
||||
|
@ -321,13 +436,7 @@ function init() {
|
|||
var type = translatorType;
|
||||
return function(e) {
|
||||
e.preventDefault();
|
||||
for(var i in translatorTestViewsToRun[type]) {
|
||||
var testView = translatorTestViewsToRun[type][i];
|
||||
testView.updateStatus(testView._translatorTester, "pending");
|
||||
}
|
||||
for(var i=0; i<NUM_CONCURRENT_TESTS; i++) {
|
||||
runTranslatorTests(type);
|
||||
}
|
||||
runTranslatorTests(type);
|
||||
}
|
||||
}, false);
|
||||
h1.appendChild(runAll);
|
||||
|
@ -339,6 +448,9 @@ function init() {
|
|||
var translatorTable = document.createElement("table");
|
||||
translatorTables[translatorType] = translatorTable;
|
||||
|
||||
translatorTestStats[translatorType] = new TranslatorTestStats(translatorType);
|
||||
translatorBox.appendChild(translatorTestStats[translatorType].node);
|
||||
|
||||
// add headings to table
|
||||
var headings = document.createElement("tr");
|
||||
for(var j in TABLE_COLUMNS) {
|
||||
|
@ -366,16 +478,34 @@ function init() {
|
|||
if(viewerMode) {
|
||||
// if no Zotero object, try to unserialize data
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", "testResults.json", true);
|
||||
var loc = "testResults.json";
|
||||
if(window.location.hash) {
|
||||
var hashVars = {};
|
||||
var hashVarsSplit = window.location.hash.substr(1).split("&");
|
||||
for(var i=0; i<hashVarsSplit.length; i++) {
|
||||
var myVar = hashVarsSplit[i];
|
||||
var index = myVar.indexOf("=");
|
||||
hashVars[myVar.substr(0, index)] = myVar.substr(index+1);
|
||||
}
|
||||
|
||||
if(hashVars["browser"] && /^[a-z]$/.test(hashVars["browser"])
|
||||
&& hashVars["version"] && /^[0-9a-zA-Z\-._]/.test(hashVars["version"])) {
|
||||
loc = "testResults-"+hashVars["browser"]+"-"+hashVars["version"]+".json";
|
||||
}
|
||||
if(hashVars["date"] && /^[0-9\-]+$/.test(hashVars["date"])) {
|
||||
loc = hashVars["date"]+"/"+loc;
|
||||
}
|
||||
}
|
||||
req.open("GET", loc, true);
|
||||
req.overrideMimeType("text/plain");
|
||||
req.onreadystatechange = function(e) {
|
||||
if(req.readyState != 4) return;
|
||||
|
||||
if(req.responseText) { // success; unserialize
|
||||
if(req.status === 200 && req.responseText) { // success; unserialize
|
||||
var data = JSON.parse(req.responseText);
|
||||
for(var i=0, n=data.length; i<n; i++) {
|
||||
for(var i=0, n=data.results.length; i<n; i++) {
|
||||
var translatorTestView = new TranslatorTestView();
|
||||
translatorTestView.unserialize(data[i]);
|
||||
translatorTestView.unserialize(data.results[i]);
|
||||
}
|
||||
} else {
|
||||
jsonNotFound("XMLHttpRequest returned "+req.status);
|
||||
|
@ -393,13 +523,12 @@ function init() {
|
|||
var serialize = document.createElement("a");
|
||||
serialize.href = "#";
|
||||
serialize.appendChild(document.createTextNode("Serialize Results"));
|
||||
serialize.addEventListener("click", serializeAll, false);
|
||||
serialize.addEventListener("click", serializeToDownload, false);
|
||||
lastP.appendChild(serialize);
|
||||
translatorBox.appendChild(lastP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates no JSON file could be found.
|
||||
*/
|
||||
|
@ -413,7 +542,6 @@ function jsonNotFound(str) {
|
|||
* Called after translators are returned from main script
|
||||
*/
|
||||
function haveTranslators(translators, type) {
|
||||
translatorTestViews[type] = [];
|
||||
translatorTestViewsToRun[type] = [];
|
||||
|
||||
translators = translators.sort(function(a, b) {
|
||||
|
@ -423,38 +551,62 @@ function haveTranslators(translators, type) {
|
|||
for(var i in translators) {
|
||||
var translatorTestView = new TranslatorTestView();
|
||||
translatorTestView.initWithTranslatorAndType(translators[i], type);
|
||||
translatorTestViews[type].push(translatorTestView);
|
||||
if(translatorTestView.canRun) {
|
||||
translatorTestViewsToRun[type].push(translatorTestView);
|
||||
}
|
||||
}
|
||||
|
||||
translatorTestStats[type].update();
|
||||
var ev = document.createEvent('HTMLEvents');
|
||||
ev.initEvent('ZoteroHaveTranslators-'+type, true, true);
|
||||
document.dispatchEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs translator tests recursively, after translatorTestViews has been populated
|
||||
* Begin running all translator tests of a given type
|
||||
*/
|
||||
function runTranslatorTests(type, callback, runCallbackIfComplete) {
|
||||
function runTranslatorTests(type, callback) {
|
||||
for(var i in translatorTestViewsToRun[type]) {
|
||||
var testView = translatorTestViewsToRun[type][i];
|
||||
testView.updateStatus(testView._translatorTester, "pending");
|
||||
}
|
||||
for(var i=0; i<NUM_CONCURRENT_TESTS; i++) {
|
||||
initTests(type, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run translator tests recursively, after translatorTestViews has been populated
|
||||
*/
|
||||
function initTests(type, callback, runCallbackIfComplete) {
|
||||
if(translatorTestViewsToRun[type].length) {
|
||||
if(translatorTestViewsToRun[type].length === 1) runCallbackIfComplete = true;
|
||||
var translatorTestView = translatorTestViewsToRun[type].shift();
|
||||
translatorTestView.runTests(function() { runTranslatorTests(type, callback, runCallbackIfComplete) });
|
||||
translatorTestView.runTests(function() { initTests(type, callback, runCallbackIfComplete) });
|
||||
} else if(callback && runCallbackIfComplete) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes all run translator tests
|
||||
* Serializes translator tests to JSON
|
||||
*/
|
||||
function serializeAll(e) {
|
||||
var serializedData = [];
|
||||
function serializeToJSON() {
|
||||
var serializedData = {"browser":Zotero.browser, "version":Zotero.version, "results":[]};
|
||||
for(var i in translatorTestViews) {
|
||||
var n = translatorTestViews[i].length;
|
||||
for(var j=0; j<n; j++) {
|
||||
serializedData.push(translatorTestViews[i][j].serialize());
|
||||
serializedData.results.push(translatorTestViews[i][j].serialize());
|
||||
}
|
||||
}
|
||||
|
||||
return serializedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes all run translator tests
|
||||
*/
|
||||
function serializeToDownload(e) {
|
||||
var serializedData = serializeToJSON();
|
||||
document.location.href = "data:application/octet-stream,"+encodeURIComponent(JSON.stringify(serializedData, null, "\t"));
|
||||
e.preventDefault();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,107 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
var Zotero_TranslatorTester_IGNORE_FIELDS = ["complete", "accessDate", "checkFields"];
|
||||
// Timeout for test to complete
|
||||
const TEST_RUN_TIMEOUT = 600000;
|
||||
var EXPORTED_SYMBOLS = ["Zotero_TranslatorTesters"];
|
||||
|
||||
try {
|
||||
Zotero;
|
||||
} catch(e) {
|
||||
var Zotero;
|
||||
}
|
||||
|
||||
Zotero_TranslatorTesters = new function() {
|
||||
const TEST_TYPES = ["web", "import", "export", "search"];
|
||||
|
||||
/**
|
||||
* Runs all tests
|
||||
*/
|
||||
this.runAllTests = function(numConcurrentTests, skipTranslators, doneCallback) {
|
||||
if(!Zotero) {
|
||||
Zotero = Components.classes["@zotero.org/Zotero;1"]
|
||||
.getService(Components.interfaces.nsISupports).wrappedJSObject;
|
||||
}
|
||||
|
||||
var testers = [];
|
||||
var waitingForTranslators = TEST_TYPES.length;
|
||||
for(var i=0; i<TEST_TYPES.length; i++) {
|
||||
Zotero.Translators.getAllForType(TEST_TYPES[i], new function() {
|
||||
var type = TEST_TYPES[i];
|
||||
return function(translators) {
|
||||
for(var i=0; i<translators.length; i++) {
|
||||
if(skipTranslators && !skipTranslators[translators[i].translatorID]) {
|
||||
testers.push(new Zotero_TranslatorTester(translators[i], type));
|
||||
}
|
||||
};
|
||||
|
||||
if(!(--waitingForTranslators)) {
|
||||
runTesters(testers, numConcurrentTests, doneCallback);
|
||||
}
|
||||
};
|
||||
}, true);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs a specific set of tests
|
||||
*/
|
||||
function runTesters(testers, numConcurrentTests, doneCallback) {
|
||||
var testersRunning = 0;
|
||||
var results = [];
|
||||
|
||||
if("getLocaleCollation" in Zotero) {
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
strcmp = function(a, b) {
|
||||
return collation.compareString(1, a, b);
|
||||
};
|
||||
} else {
|
||||
strcmp = function (a, b) {
|
||||
return a.localeCompare(b);
|
||||
};
|
||||
}
|
||||
|
||||
var testerDoneCallback = function(tester) {
|
||||
if(tester.pending.length) return;
|
||||
|
||||
Zotero.debug("Done testing "+tester.translator.label);
|
||||
|
||||
// Done translating, so serialize test results
|
||||
testersRunning--;
|
||||
results.push(tester.serialize());
|
||||
|
||||
if(testers.length) {
|
||||
// Run next tester if one is available
|
||||
runNextTester();
|
||||
} else if(testersRunning === 0) {
|
||||
// Testing is done, so sort results
|
||||
results = results.sort(function(a, b) {
|
||||
if(a.type !== b.type) {
|
||||
return TEST_TYPES.indexOf(a.type) - TEST_TYPES.indexOf(b.type);
|
||||
}
|
||||
return strcmp(a.label, b.label);
|
||||
});
|
||||
|
||||
// Call done callback
|
||||
doneCallback({
|
||||
"browser":Zotero.browser,
|
||||
"version":Zotero.version,
|
||||
"results":results
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var runNextTester = function() {
|
||||
testersRunning++;
|
||||
Zotero.debug("Testing "+testers[0].translator.label);
|
||||
testers.shift().runTests(testerDoneCallback);
|
||||
};
|
||||
|
||||
for(var i=0; i<numConcurrentTests; i++) {
|
||||
runNextTester();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A tool to run unit tests for a given translator
|
||||
|
@ -36,13 +136,14 @@ var Zotero_TranslatorTester_IGNORE_FIELDS = ["complete", "accessDate", "checkFie
|
|||
* @constructor
|
||||
* @param {Zotero.Translator[]} translator The translator for which to run tests
|
||||
* @param {String} type The type of tests to run (web, import, export, or search)
|
||||
* @param {Function} [debug] A function to call to write debug output. If not present, Zotero.debug
|
||||
* will be used.
|
||||
* @param {Function} [debugCallback] A function to call to write debug output. If not present,
|
||||
* Zotero.debug will be used.
|
||||
*/
|
||||
Zotero_TranslatorTester = function(translator, type, debug) {
|
||||
Zotero_TranslatorTester = function(translator, type, debugCallback) {
|
||||
this.type = type;
|
||||
this.translator = translator;
|
||||
this._debug = debug ? debug : function(obj, a, b) { Zotero.debug(a, b) };
|
||||
this.output = "";
|
||||
this.isSupported = this.translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER;
|
||||
|
||||
this.tests = [];
|
||||
this.pending = [];
|
||||
|
@ -50,6 +151,16 @@ Zotero_TranslatorTester = function(translator, type, debug) {
|
|||
this.failed = [];
|
||||
this.unknown = [];
|
||||
|
||||
var me = this;
|
||||
this._debug = function(obj, a, b) {
|
||||
me.output += me.output ? "\n"+a : a;
|
||||
if(debugCallback) {
|
||||
debugCallback(me, a, b);
|
||||
} else {
|
||||
Zotero.debug(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
var code = translator.code;
|
||||
var testStart = code.indexOf("/** BEGIN TEST CASES **/");
|
||||
var testEnd = code.indexOf("/** END TEST CASES **/");
|
||||
|
@ -82,25 +193,50 @@ Zotero_TranslatorTester._sanitizeItem = function(item, forSave) {
|
|||
if(item.attachments && item.attachments.length) {
|
||||
// don't actually test URI equality
|
||||
for (var i=0; i<item.attachments.length; i++) {
|
||||
if(item.attachments[i].document) {
|
||||
item.attachments[i].document = false;
|
||||
} else if(item.attachments[i].url) {
|
||||
item.attachments[i].url = false;
|
||||
var attachment = item.attachments[i];
|
||||
if(attachment.document) {
|
||||
delete attachment.document;
|
||||
}
|
||||
|
||||
if(attachment.url) {
|
||||
delete attachment.url;
|
||||
}
|
||||
|
||||
if(attachment.complete) {
|
||||
delete attachment.complete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try to convert to JSON and back to get rid of undesirable undeletable elements; this may fail
|
||||
try {
|
||||
item = JSON.parse(JSON.stringify(item));
|
||||
} catch(e) {};
|
||||
|
||||
// remove fields to be ignored
|
||||
for(var j=0, n=Zotero_TranslatorTester_IGNORE_FIELDS.length; j<n; j++) {
|
||||
if(forSave) {
|
||||
delete item[Zotero_TranslatorTester_IGNORE_FIELDS[j]]
|
||||
} else {
|
||||
item[Zotero_TranslatorTester_IGNORE_FIELDS[j]] = false;
|
||||
}
|
||||
const IGNORE_FIELDS = ["complete", "accessDate", "checkFields"];
|
||||
for(var j=0, n=IGNORE_FIELDS.length; j<n; j++) {
|
||||
delete item[IGNORE_FIELDS[j]];
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
/**
|
||||
* Serializes translator tester results to JSON
|
||||
*/
|
||||
Zotero_TranslatorTester.prototype.serialize = function() {
|
||||
return {
|
||||
"translatorID":this.translator.translatorID,
|
||||
"type":this.type,
|
||||
"output":this.output,
|
||||
"label":this.translator.label,
|
||||
"isSupported":this.isSupported,
|
||||
"pending":this.pending,
|
||||
"failed":this.failed,
|
||||
"succeeded":this.succeeded,
|
||||
"unknown":this.unknown
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets tests for this translatorTester
|
||||
|
@ -137,16 +273,20 @@ Zotero_TranslatorTester.prototype.runTests = function(testDoneCallback, recursiv
|
|||
* @param {Function} testDoneCallback A callback to be executed each time a test is complete
|
||||
*/
|
||||
Zotero_TranslatorTester.prototype._runTestsRecursively = function(testDoneCallback) {
|
||||
|
||||
var test = this.pending.shift();
|
||||
var testNumber = this.tests.length-this.pending.length;
|
||||
var me = this;
|
||||
|
||||
this._debug(this, "\nTranslatorTester: Running "+this.translator.label+" Test "+testNumber);
|
||||
|
||||
var executedCallback = false;
|
||||
var callback = function(obj, test, status, message) {
|
||||
if(executedCallback) return;
|
||||
executedCallback = true;
|
||||
|
||||
me._debug(this, "TranslatorTester: "+me.translator.label+" Test "+testNumber+": "+status+" ("+message+")");
|
||||
me[status].push(test);
|
||||
test.message = message;
|
||||
if(testDoneCallback) testDoneCallback(me, test, status, message);
|
||||
me.runTests(testDoneCallback, true);
|
||||
};
|
||||
|
@ -156,6 +296,10 @@ Zotero_TranslatorTester.prototype._runTestsRecursively = function(testDoneCallba
|
|||
} else {
|
||||
this.runTest(test, null, callback);
|
||||
}
|
||||
|
||||
(Zotero.setTimeout ? Zotero : window).setTimeout(function() {
|
||||
callback(me, test, "failed", "Test timed out after "+TEST_RUN_TIMEOUT/1000+" seconds");
|
||||
}, TEST_RUN_TIMEOUT);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -167,13 +311,31 @@ Zotero_TranslatorTester.prototype._runTestsRecursively = function(testDoneCallba
|
|||
* @param {Function} testDoneCallback A callback to be executed when test is complete
|
||||
*/
|
||||
Zotero_TranslatorTester.prototype.fetchPageAndRunTest = function(test, testDoneCallback) {
|
||||
var timer = Components.classes["@mozilla.org/timer;1"].
|
||||
createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback({"notify":function() {
|
||||
try {
|
||||
Zotero.Browser.deleteHiddenBrowser(hiddenBrowser);
|
||||
} catch(e) {}
|
||||
}}, TEST_RUN_TIMEOUT, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
var me = this;
|
||||
var runTest = function(doc) {
|
||||
me.runTest(test, doc, function(obj, test, status, message) {
|
||||
try {
|
||||
timer.cancel();
|
||||
} catch(e) {};
|
||||
if(hiddenBrowser) Zotero.Browser.deleteHiddenBrowser(hiddenBrowser);
|
||||
testDoneCallback(obj, test, status, message);
|
||||
});
|
||||
};
|
||||
var hiddenBrowser = Zotero.HTTP.processDocuments(test.url,
|
||||
function(doc) {
|
||||
me.runTest(test, doc, function(obj, test, status, message) {
|
||||
if(hiddenBrowser) Zotero.Browser.deleteHiddenBrowser(hiddenBrowser);
|
||||
testDoneCallback(obj, test, status, message);
|
||||
});
|
||||
if(test.defer) {
|
||||
Zotero.setTimeout(function() { runTest(doc) }, 10000, true);
|
||||
} else {
|
||||
runTest(doc);
|
||||
}
|
||||
},
|
||||
null,
|
||||
function(e) {
|
||||
|
@ -190,7 +352,7 @@ Zotero_TranslatorTester.prototype.fetchPageAndRunTest = function(test, testDoneC
|
|||
* @param {Function} testDoneCallback A callback to be executed when test is complete
|
||||
*/
|
||||
Zotero_TranslatorTester.prototype.runTest = function(test, doc, testDoneCallback) {
|
||||
this._debug(this, "TranslatorTester: Translating "+test.url);
|
||||
this._debug(this, "TranslatorTester: Translating"+(test.url ? " "+test.url : ""));
|
||||
|
||||
var me = this;
|
||||
var translate = Zotero.Translate.newInstance(this.type);
|
||||
|
@ -207,8 +369,12 @@ Zotero_TranslatorTester.prototype.runTest = function(test, doc, testDoneCallback
|
|||
me._runTestTranslate(translate, translators, test, testDoneCallback);
|
||||
});
|
||||
translate.setHandler("debug", this._debug);
|
||||
var errorReturned;
|
||||
translate.setHandler("error", function(obj, err) {
|
||||
errorReturned = err;
|
||||
});
|
||||
translate.setHandler("done", function(obj, returnValue) {
|
||||
me._checkResult(test, obj, returnValue, testDoneCallback);
|
||||
me._checkResult(test, obj, returnValue, errorReturned, testDoneCallback);
|
||||
});
|
||||
translate.setHandler("select", function(obj, items, callback) {
|
||||
if(test.items !== "multiple" && test.items.length <= 1) {
|
||||
|
@ -265,9 +431,23 @@ Zotero_TranslatorTester.prototype._runTestTranslate = function(translate, transl
|
|||
* @param {Object} test Test that was executed
|
||||
* @param {Zotero.Translate} translate The Zotero.Translate instance
|
||||
* @param {Boolean} returnValue Whether translation completed successfully
|
||||
* @param {Error} error Error code, if one was specified
|
||||
* @param {Function} testDoneCallback A callback to be executed when test is complete
|
||||
*/
|
||||
Zotero_TranslatorTester.prototype._checkResult = function(test, translate, returnValue, testDoneCallback) {
|
||||
Zotero_TranslatorTester.prototype._checkResult = function(test, translate, returnValue, error, testDoneCallback) {
|
||||
if(error) {
|
||||
var errorString = "Translation failed: "+error.toString();
|
||||
if(typeof error === "object") {
|
||||
for(var i in error) {
|
||||
if(typeof(error[i]) != "object") {
|
||||
errorString += "\n"+i+' => '+error[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
testDoneCallback(this, test, "failed", errorString);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!returnValue) {
|
||||
testDoneCallback(this, test, "failed", "Translation failed; examine debug output for errors");
|
||||
return;
|
||||
|
@ -289,6 +469,12 @@ Zotero_TranslatorTester.prototype._checkResult = function(test, translate, retur
|
|||
var translatedItem = Zotero_TranslatorTester._sanitizeItem(translate.newItems[i]);
|
||||
|
||||
if(!this._compare(testItem, translatedItem)) {
|
||||
var m = translate.newItems.length;
|
||||
test.itemsReturned = new Array(m);
|
||||
for(var j=0; j<m; j++) {
|
||||
test.itemsReturned[j] = Zotero_TranslatorTester._sanitizeItem(translate.newItems[i], true);
|
||||
}
|
||||
|
||||
testDoneCallback(this, test, "unknown", "Item "+i+" does not match");
|
||||
return;
|
||||
}
|
||||
|
@ -347,7 +533,7 @@ Zotero_TranslatorTester.prototype._createTest = function(translate, multipleMode
|
|||
if(multipleMode) {
|
||||
var items = "multiple";
|
||||
} else {
|
||||
for(var i=0, n=translate.newItems; i<n; i++) {
|
||||
for(var i=0, n=translate.newItems.length; i<n; i++) {
|
||||
Zotero_TranslatorTester._sanitizeItem(translate.newItems[i], true);
|
||||
}
|
||||
var items = translate.newItems;
|
||||
|
@ -409,17 +595,10 @@ Zotero_TranslatorTester.prototype._objectCompare = function(x, y) {
|
|||
if(y[p] || y[p] === 0) {
|
||||
switch(typeof(y[p])) {
|
||||
case 'object':
|
||||
if (!this._objectCompare(y[p],x[p])) {
|
||||
if (!this._objectCompare(x[p],y[p])) {
|
||||
return false;
|
||||
};
|
||||
break;
|
||||
case 'function':
|
||||
if (typeof(x[p])=='undefined'
|
||||
|| (y[p].toString() != x[p].toString())) {
|
||||
this._debug(this, "TranslatorTester: Function "+p+" defined in y, not in x, or definitions differ");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (y[p] != x[p] && x[p] !== false) { // special exemption: x (test item)
|
||||
// can have a property set to false
|
||||
|
|
|
@ -102,6 +102,10 @@ Zotero.Attachments = new function(){
|
|||
// hmph
|
||||
Zotero.DB.rollbackTransaction();
|
||||
|
||||
var msg = "Failed importing file " + file.path;
|
||||
Components.utils.reportError(msg);
|
||||
Zotero.debug(msg, 1);
|
||||
|
||||
try {
|
||||
// Clean up
|
||||
if (itemID) {
|
||||
|
|
|
@ -178,16 +178,16 @@ var CSL = {
|
|||
PREFIX_PUNCTUATION: /[.;:]\s*$/,
|
||||
SUFFIX_PUNCTUATION: /^\s*[.;:,\(\)]/,
|
||||
NUMBER_REGEXP: /(?:^\d+|\d+$)/,
|
||||
NAME_INITIAL_REGEXP: /^([A-Z\u0080-\u017f\u0400-\u042f])([a-zA-Z\u0080-\u017f\u0400-\u052f]*|)/,
|
||||
ROMANESQUE_REGEXP: /[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]/,
|
||||
ROMANESQUE_NOT_REGEXP: /[^a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]/g,
|
||||
STARTSWITH_ROMANESQUE_REGEXP: /^[&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]/,
|
||||
ENDSWITH_ROMANESQUE_REGEXP: /[.;:&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]$/,
|
||||
ALL_ROMANESQUE_REGEXP: /^[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe]+$/,
|
||||
NAME_INITIAL_REGEXP: /^([A-Z\u0080-\u017f\u0400-\u042f\u0600-\u06ff])([a-zA-Z\u0080-\u017f\u0400-\u052f\u0600-\u06ff]*|)/,
|
||||
ROMANESQUE_REGEXP: /[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe\u0600-\u06ff\u200c\u200d\u200e\u202a-\u202e]/,
|
||||
ROMANESQUE_NOT_REGEXP: /[^a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe\u0600-\u06ff\u200c\u200d\u200e\u202a-\u202e]/g,
|
||||
STARTSWITH_ROMANESQUE_REGEXP: /^[&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe\u0600-\u06ff\u200c\u200d\u200e\u202a-\u202e]/,
|
||||
ENDSWITH_ROMANESQUE_REGEXP: /[.;:&a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe\u0600-\u06ff\u200c\u200d\u200e\u202a-\u202e]$/,
|
||||
ALL_ROMANESQUE_REGEXP: /^[a-zA-Z\u0080-\u017f\u0400-\u052f\u0386-\u03fb\u1f00-\u1ffe\u0600-\u06ff\u200c\u200d\u200e\u202a-\u202e]+$/,
|
||||
VIETNAMESE_SPECIALS: /[\u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]/,
|
||||
VIETNAMESE_NAMES: /^(?:(?:[.AaBbCcDdEeGgHhIiKkLlMmNnOoPpQqRrSsTtUuVvXxYy \u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]{2,6})(\s+|$))+$/,
|
||||
NOTE_FIELDS_REGEXP: /\{:[\-a-z]+:[^\}]+\}/g,
|
||||
NOTE_FIELD_REGEXP: /\{:([\-a-z]+):\s*([^\}]+)\}/,
|
||||
NOTE_FIELDS_REGEXP: /\{:[\-_a-z]+:[^\}]+\}/g,
|
||||
NOTE_FIELD_REGEXP: /\{:([\-_a-z]+):\s*([^\}]+)\}/,
|
||||
DISPLAY_CLASSES: ["block", "left-margin", "right-inline", "indent"],
|
||||
NAME_VARIABLES: [
|
||||
"author",
|
||||
|
@ -302,6 +302,7 @@ var CSL = {
|
|||
es: "es_ES",
|
||||
et: "et_EE",
|
||||
fa: "fa_FA",
|
||||
fi: "fi_FI",
|
||||
fr: "fr_FR",
|
||||
he: "he_IL",
|
||||
hu: "hu_HU",
|
||||
|
@ -455,6 +456,11 @@ var CSL = {
|
|||
locale_opts: {},
|
||||
locale_dates: {}
|
||||
};
|
||||
if (typeof require !== "undefined" && typeof module !== 'undefined' && "exports" in module) {
|
||||
var CSL_IS_NODEJS = true;
|
||||
var CSL_NODEJS = require("./csl_nodejs_jsdom").CSL_NODEJS_JSDOM;
|
||||
exports.CSL = CSL;
|
||||
}
|
||||
CSL.TERMINAL_PUNCTUATION_REGEXP = new RegExp("^([" + CSL.TERMINAL_PUNCTUATION.slice(0, -1).join("") + "])(.*)");
|
||||
CSL.CLOSURES = new RegExp(".*[\\]\\)]");
|
||||
CSL.debug = function (str) {
|
||||
|
@ -839,7 +845,6 @@ CSL_CHROME.prototype.flagDateMacros = function(myxml) {
|
|||
CSL.getSortCompare = function () {
|
||||
var strcmp;
|
||||
try {
|
||||
var Components;
|
||||
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
|
||||
.getService(Components.interfaces.nsILocaleService);
|
||||
var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
|
||||
|
@ -2148,7 +2153,7 @@ CSL.DateParser = function () {
|
|||
};
|
||||
CSL.Engine = function (sys, style, lang, forceLang) {
|
||||
var attrs, langspec, localexml, locale;
|
||||
this.processor_version = "1.0.285";
|
||||
this.processor_version = "1.0.295";
|
||||
this.csl_version = "1.0";
|
||||
this.sys = sys;
|
||||
this.sys.xml = new CSL.System.Xml.Parsing();
|
||||
|
@ -2493,7 +2498,7 @@ CSL.Engine.prototype.retrieveItem = function (id) {
|
|||
if (this.opt.development_extensions.jurisdiction_subfield && Item.jurisdiction) {
|
||||
var subjurisdictions = Item.jurisdiction.split(";");
|
||||
if (subjurisdictions.length > 1) {
|
||||
Item.subjurisdiction = subjurisdictions.slice(0,2).join(";");
|
||||
Item.subjurisdiction = subjurisdictions.join(";");
|
||||
}
|
||||
}
|
||||
for (var i = 1, ilen = CSL.DATE_VARIABLES.length; i < ilen; i += 1) {
|
||||
|
@ -2510,7 +2515,7 @@ CSL.Engine.prototype.retrieveItem = function (id) {
|
|||
return Item;
|
||||
};
|
||||
CSL.Engine.prototype.setOpt = function (token, name, value) {
|
||||
if (token.name === "style") {
|
||||
if (token.name === "style" || token.name === "cslstyle") {
|
||||
this.opt[name] = value;
|
||||
} else if (["citation", "bibliography"].indexOf(token.name) > -1) {
|
||||
this[token.name].opt[name] = value;
|
||||
|
@ -2690,7 +2695,20 @@ CSL.Engine.prototype.setAbbreviations = function (arg) {
|
|||
if (this.sys.setAbbreviations) {
|
||||
this.sys.setAbbreviations(arg);
|
||||
}
|
||||
}
|
||||
};
|
||||
CSL.Engine.prototype.setEnglishLocaleEscapes = function (arg) {
|
||||
if ("string" === typeof arg) {
|
||||
arg = arg.split(/\s+,\s+/);
|
||||
}
|
||||
if (!arg || !arg.length) {
|
||||
arg = [];
|
||||
}
|
||||
for (var i = 0, ilen = arg.length; i < ilen; i += 1) {
|
||||
if (this.opt.english_locale_escapes.indexOf(arg[i]) === -1) {
|
||||
this.opt.english_locale_escapes.push(arg[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
CSL.Engine.Opt = function () {
|
||||
this.has_disambiguate = false;
|
||||
this.mode = "html";
|
||||
|
@ -2713,6 +2731,7 @@ CSL.Engine.Opt = function () {
|
|||
this.citation_number_slug = false;
|
||||
this.max_number_of_names = 0;
|
||||
this.trigraph = "Aaaa00:AaAa00:AaAA00:AAAA00";
|
||||
this.english_locale_escapes = [];
|
||||
this.development_extensions = {};
|
||||
this.development_extensions.field_hack = true;
|
||||
this.development_extensions.locator_date_and_revision = true;
|
||||
|
@ -2933,6 +2952,7 @@ CSL.Engine.prototype.restoreProcessorState = function (citations) {
|
|||
} else {
|
||||
this.registry = new CSL.Registry(this);
|
||||
this.tmp = new CSL.Engine.Tmp();
|
||||
this.disambiguate = new CSL.Disambiguation(this);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
@ -3240,6 +3260,7 @@ CSL.getBibliographyEntries = function (bibsection) {
|
|||
this.parallel.ComposeSet();
|
||||
this.parallel.PruneOutputQueue();
|
||||
} else if (!this.registry.registry[item.id].siblings) {
|
||||
this.parallel.StartCitation(sortedItems);
|
||||
this.tmp.term_predecessor = false;
|
||||
entry_item_ids.push("" + CSL.getCite.call(this, item));
|
||||
}
|
||||
|
@ -3387,11 +3408,12 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
|||
if (this.opt.update_mode === CSL.POSITION) {
|
||||
textCitations = [];
|
||||
noteCitations = [];
|
||||
var citationsInNote = {};
|
||||
}
|
||||
var update_items = [];
|
||||
for (i = 0, ilen = citationByIndex.length; i < ilen; i += 1) {
|
||||
citationByIndex[i].properties.index = i;
|
||||
for (j = 0, jlen = citationByIndex[i].sortedItems.length; j < jlen; j += 1) {
|
||||
for (j = 0, jlen = citationByIndex[i].sortedItems.length; j < jlen; j += 1) {
|
||||
item = citationByIndex[i].sortedItems[j];
|
||||
if (!this.registry.citationreg.citationsByItemId[item[1].id]) {
|
||||
this.registry.citationreg.citationsByItemId[item[1].id] = [];
|
||||
|
@ -3405,6 +3427,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
|||
if (citationByIndex[i].properties.noteIndex) {
|
||||
noteCitations.push(citationByIndex[i]);
|
||||
} else {
|
||||
citationByIndex[i].properties.noteIndex = 0;
|
||||
textCitations.push(citationByIndex[i]);
|
||||
}
|
||||
}
|
||||
|
@ -3446,20 +3469,20 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
|||
}
|
||||
var citations;
|
||||
if (this.opt.update_mode === CSL.POSITION) {
|
||||
var citationsInNote = {};
|
||||
for (i = 0; i < 2; i += 1) {
|
||||
citations = [textCitations, noteCitations][i];
|
||||
var first_ref = {};
|
||||
var last_ref = {};
|
||||
for (j = 0, jlen = citations.length; j < jlen; j += 1) {
|
||||
var onecitation = citations[j];
|
||||
if (!onecitation.properties.noteIndex) {
|
||||
onecitation.properties.noteIndex = 0;
|
||||
}
|
||||
if (!citationsInNote[onecitation.properties.noteIndex]) {
|
||||
citationsInNote[onecitation.properties.noteIndex] = 1;
|
||||
} else {
|
||||
citationsInNote[onecitation.properties.noteIndex] += 1;
|
||||
for (var k = 0, klen = onecitation.sortedItems.length; k < klen; k += 1) {
|
||||
if (!this.registry.registry[onecitation.sortedItems[k][1].id].parallel) {
|
||||
if (!citationsInNote[onecitation.properties.noteIndex]) {
|
||||
citationsInNote[onecitation.properties.noteIndex] = 1;
|
||||
} else {
|
||||
citationsInNote[onecitation.properties.noteIndex] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (k = 0, klen = citations[j].sortedItems.length; k < klen; k += 1) {
|
||||
item = citations[j].sortedItems[k];
|
||||
|
@ -3491,7 +3514,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
|||
var items = citations[(j - 1)].sortedItems;
|
||||
var useme = false;
|
||||
if ((citations[(j - 1)].sortedItems[0][1].id == item[1].id && citations[j - 1].properties.noteIndex >= (citations[j].properties.noteIndex - 1)) || citations[(j - 1)].sortedItems[0][1].id == this.registry.registry[item[1].id].parallel) {
|
||||
if (citationsInNote[citations[j - 1].properties.noteIndex] === 1 || citations[j - 1].properties.noteIndex === 0) {
|
||||
if (citationsInNote[citations[j - 1].properties.noteIndex] == 1 || citations[j - 1].properties.noteIndex == 0) {
|
||||
useme = true;
|
||||
}
|
||||
}
|
||||
|
@ -4226,17 +4249,22 @@ CSL.Engine.prototype.localeSet = function (myxml, lang_in, lang_out) {
|
|||
}
|
||||
for (termname in this.locale[lang_out].terms) {
|
||||
if (this.locale[lang_out].terms.hasOwnProperty(termname)) {
|
||||
for (i = 0, ilen = 2; i < ilen; i += 1) {
|
||||
genderform = CSL.GENDERS[i];
|
||||
if (this.locale[lang_out].terms[termname][genderform]) {
|
||||
for (form in this.locale[lang_out].terms[termname]) {
|
||||
if (!this.locale[lang_out].terms[termname][genderform][form]) {
|
||||
this.locale[lang_out].terms[termname][genderform][form] = this.locale[lang_out].terms[termname][form];
|
||||
for (i = 0, ilen = 2; i < ilen; i += 1) {
|
||||
genderform = CSL.GENDERS[i];
|
||||
if (this.locale[lang_out].terms[termname][genderform]) {
|
||||
for (form in this.locale[lang_out].terms[termname]) {
|
||||
if (!this.locale[lang_out].terms[termname][genderform][form]) {
|
||||
this.locale[lang_out].terms[termname][genderform][form] = this.locale[lang_out].terms[termname][form];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lang_out && ["fr", "pt"].indexOf(lang_out.slice(0, 2).toLowerCase()) > -1) {
|
||||
this.locale[lang_out].terms["page-range-delimiter"] = "-";
|
||||
} else {
|
||||
this.locale[lang_out].terms["page-range-delimiter"] = "\u2013";
|
||||
}
|
||||
nodes = this.sys.xml.getNodesByName(locale, 'style-options');
|
||||
for (pos = 0, len = this.sys.xml.numberofnodes(nodes); pos < len; pos += 1) {
|
||||
|
@ -5334,15 +5362,17 @@ CSL.NameOutput.prototype.outputNames = function () {
|
|||
var blob = this.state.output.pop();
|
||||
this.state.output.append(blob, this.names);
|
||||
this.state.tmp.name_node.top = this.state.output.current.value();
|
||||
var oldSuppressDecorations = this.state.tmp.suppress_decorations;
|
||||
this.state.tmp.suppress_decorations = true;
|
||||
var lastBlob = this.state.tmp.name_node.top.blobs.pop();
|
||||
var name_node_string = this.state.output.string(this.state, lastBlob.blobs, false);
|
||||
this.state.tmp.name_node.top.blobs.push(lastBlob);
|
||||
if (name_node_string) {
|
||||
this.state.tmp.name_node.string = name_node_string;
|
||||
if (variables[0] !== "authority") {
|
||||
var oldSuppressDecorations = this.state.tmp.suppress_decorations;
|
||||
this.state.tmp.suppress_decorations = true;
|
||||
var lastBlob = this.state.tmp.name_node.top.blobs.pop();
|
||||
var name_node_string = this.state.output.string(this.state, lastBlob.blobs, false);
|
||||
this.state.tmp.name_node.top.blobs.push(lastBlob);
|
||||
if (name_node_string) {
|
||||
this.state.tmp.name_node.string = name_node_string;
|
||||
}
|
||||
this.state.tmp.suppress_decorations = oldSuppressDecorations;
|
||||
}
|
||||
this.state.tmp.suppress_decorations = oldSuppressDecorations;
|
||||
if (this.state.tmp.name_node.string && !this.state.tmp.first_name_string) {
|
||||
this.state.tmp.first_name_string = this.state.tmp.name_node.string;
|
||||
}
|
||||
|
@ -5813,6 +5843,9 @@ CSL.NameOutput.prototype.disambigNames = function () {
|
|||
CSL.NameOutput.prototype._runDisambigNames = function (lst, pos) {
|
||||
var chk, myform, myinitials, param, i, ilen, paramx;
|
||||
for (i = 0, ilen = lst.length; i < ilen; i += 1) {
|
||||
if (!lst[i].given || !lst[i].family) {
|
||||
continue;
|
||||
}
|
||||
this.state.registry.namereg.addname("" + this.Item.id, lst[i], i);
|
||||
chk = this.state.tmp.disambig_settings.givens[pos];
|
||||
if ("undefined" === typeof chk) {
|
||||
|
@ -7260,6 +7293,9 @@ CSL.Node.number = {
|
|||
state.processNumber(node, Item, varname);
|
||||
}
|
||||
}
|
||||
if (varname === "locator") {
|
||||
state.tmp.done_vars.push("locator");
|
||||
}
|
||||
var values = state.tmp.shadow_numbers[varname].values;
|
||||
var blob;
|
||||
var newstr = ""
|
||||
|
@ -7273,18 +7309,20 @@ CSL.Node.number = {
|
|||
if (newstr && !newstr.match(/^[-.\u20130-9]+$/)) {
|
||||
state.output.append(newstr, this);
|
||||
} else {
|
||||
state.output.openLevel("empty");
|
||||
for (var i = 0, ilen = values.length; i < ilen; i += 1) {
|
||||
var blob = new CSL[values[i][0]](values[i][1], values[i][2], Item.id);
|
||||
if (i > 0) {
|
||||
blob.strings.prefix = blob.strings.prefix.replace(/^\s*/, "");
|
||||
if (values.length) {
|
||||
state.output.openLevel("empty");
|
||||
for (var i = 0, ilen = values.length; i < ilen; i += 1) {
|
||||
var blob = new CSL[values[i][0]](values[i][1], values[i][2], Item.id);
|
||||
if (i > 0) {
|
||||
blob.strings.prefix = blob.strings.prefix.replace(/^\s*/, "");
|
||||
}
|
||||
if (i < values.length - 1) {
|
||||
blob.strings.suffix = blob.strings.suffix.replace(/\s*$/, "");
|
||||
}
|
||||
state.output.append(blob, "literal", false, false, true);
|
||||
}
|
||||
if (i < values.length - 1) {
|
||||
blob.strings.suffix = blob.strings.suffix.replace(/\s*$/, "");
|
||||
}
|
||||
state.output.append(blob, "literal", false, false, true);
|
||||
state.output.closeLevel("empty");
|
||||
}
|
||||
state.output.closeLevel("empty");
|
||||
}
|
||||
state.parallel.CloseVariable("number");
|
||||
};
|
||||
|
@ -7500,9 +7538,6 @@ CSL.Node.text = {
|
|||
} else {
|
||||
state.transform.setTransformFallback(true);
|
||||
state.transform.setAbbreviationFallback(true);
|
||||
if (this.variables_real[0] === "subjurisdiction") {
|
||||
state.transform.setSuppressMonitor("container-title");
|
||||
}
|
||||
func = state.transform.getOutputFunction(this.variables);
|
||||
}
|
||||
if (this.variables_real[0] === "container-title") {
|
||||
|
@ -7518,7 +7553,7 @@ CSL.Node.text = {
|
|||
func = function (state, Item, item) {
|
||||
if (item && item[this.variables[0]]) {
|
||||
var locator = "" + item[this.variables[0]];
|
||||
locator = locator.replace(/([^\\])--*/g,"$1\u2013");
|
||||
locator = locator.replace(/([^\\])--*/g,"$1"+state.getTerm("page-range-delimiter"));
|
||||
locator = locator.replace(/\\-/g,"-");
|
||||
state.output.append(locator, this, false, false, true);
|
||||
}
|
||||
|
@ -7528,6 +7563,7 @@ CSL.Node.text = {
|
|||
var idx, value;
|
||||
value = state.getVariable(Item, "page", form);
|
||||
if (value) {
|
||||
value = ""+value;
|
||||
value = value.replace("\u2013", "-", "g");
|
||||
idx = value.indexOf("-");
|
||||
if (idx > -1) {
|
||||
|
@ -7540,7 +7576,8 @@ CSL.Node.text = {
|
|||
func = function (state, Item) {
|
||||
var value = state.getVariable(Item, "page", form);
|
||||
if (value) {
|
||||
value = value.replace(/([^\\])--*/g,"$1\u2013");
|
||||
value = ""+value;
|
||||
value = value.replace(/([^\\])--*/g,"$1"+state.getTerm("page-range-delimiter"));
|
||||
value = value.replace(/\\-/g,"-");
|
||||
value = state.fun.page_mangler(value);
|
||||
state.output.append(value, this, false, false, true);
|
||||
|
@ -8363,18 +8400,22 @@ CSL.Attributes["@text-case"] = function (state, arg) {
|
|||
this.strings["text-case"] = arg;
|
||||
if (arg === "title") {
|
||||
var m = false;
|
||||
var default_locale = state.opt["default-locale"][0].slice(0, 2);
|
||||
if (Item.language) {
|
||||
m = Item.language.match(/^\s*([a-z]{2})(?:$|-| )/);
|
||||
}
|
||||
if (state.opt["default-locale"][0].slice(0, 2) === "en") {
|
||||
if (m && m[1] !== "en") {
|
||||
m = Item.language.match(/^\s*([A-Za-z]{2})(?:$|-| )/);
|
||||
if (!m) {
|
||||
this.strings["text-case"] = "passthrough";
|
||||
} else if (m[1].toLowerCase() !== "en") {
|
||||
this.strings["text-case"] = "passthrough";
|
||||
for (var i = 0, ilen = state.opt.english_locale_escapes.length; i < ilen; i += 1) {
|
||||
var escaper = state.opt.english_locale_escapes[i];
|
||||
if (m[1].slice(0, escaper.length).toLowerCase() === escaper) {
|
||||
this.strings["text-case"] = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (default_locale !== "en") {
|
||||
this.strings["text-case"] = "passthrough";
|
||||
if (m && m[1] === "en") {
|
||||
this.strings["text-case"] = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -8448,10 +8489,9 @@ CSL.Attributes["@display"] = function (state, arg) {
|
|||
this.strings.cls = arg;
|
||||
};
|
||||
var XML_PARSING;
|
||||
var CSL_E4X;
|
||||
var CSL_CHROME;
|
||||
var DOMParser;
|
||||
if ("undefined" !== typeof CSL_E4X) {
|
||||
if ("undefined" !== typeof CSL_IS_NODEJS) {
|
||||
XML_PARSING = CSL_NODEJS;
|
||||
} else if ("undefined" !== typeof CSL_E4X) {
|
||||
XML_PARSING = CSL_E4X;
|
||||
} else {
|
||||
XML_PARSING = CSL_CHROME;
|
||||
|
@ -8590,8 +8630,7 @@ CSL.Transform = function (state) {
|
|||
opt = {
|
||||
abbreviation_fallback: false,
|
||||
alternative_varname: false,
|
||||
transform_fallback: false,
|
||||
suppress_monitor: false
|
||||
transform_fallback: false
|
||||
};
|
||||
}
|
||||
this.init = init;
|
||||
|
@ -8667,10 +8706,6 @@ CSL.Transform = function (state) {
|
|||
opt.abbreviation_fallback = b;
|
||||
}
|
||||
this.setAbbreviationFallback = setAbbreviationFallback;
|
||||
function setSuppressMonitor(b) {
|
||||
opt.suppress_monitor = b;
|
||||
}
|
||||
this.setSuppressMonitor = setSuppressMonitor;
|
||||
function setAlternativeVariableName(s) {
|
||||
opt.alternative_varname = s;
|
||||
}
|
||||
|
@ -8744,7 +8779,6 @@ CSL.Transform = function (state) {
|
|||
var abbreviation_fallback = opt.abbreviation_fallback;
|
||||
var alternative_varname = opt.alternative_varname;
|
||||
var transform_fallback = opt.transform_fallback;
|
||||
var suppress_monitor = opt.suppress_monitor;
|
||||
var localesets;
|
||||
var langPrefs = CSL.LangPrefsMap[myfieldname];
|
||||
if (!langPrefs) {
|
||||
|
@ -8808,10 +8842,13 @@ CSL.Transform = function (state) {
|
|||
}
|
||||
if (myabbrev_family) {
|
||||
primary = abbreviate(state, Item, alternative_varname, primary, myabbrev_family, true);
|
||||
if (suppress_monitor && primary) {
|
||||
suppressing_partner = abbreviate(state, Item, false, Item["container-title"], "container-title", true);
|
||||
if (suppressing_partner && suppressing_partner.slice(0, primary.length) === primary) {
|
||||
return null;
|
||||
if (primary) {
|
||||
var m = primary.match(/^!([-_a-z]+)<<</);
|
||||
if (m) {
|
||||
primary = primary.slice(m[0].length);
|
||||
if (state.tmp.done_vars.indexOf(m[1]) === -1) {
|
||||
state.tmp.done_vars.push(m[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
secondary = abbreviate(state, Item, false, secondary, myabbrev_family, true);
|
||||
|
@ -10092,10 +10129,10 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) {
|
|||
&& elements[i].match(/^[0-9]+/)
|
||||
&& parseInt(elements[i - 2]) < parseInt(elements[i].replace(/[^0-9].*/,""))) {
|
||||
var start = this.tmp.shadow_numbers[variable].values.slice(-2);
|
||||
middle[0][1] = "\u2013";
|
||||
middle[0][1] = this.getTerm("page-range-delimiter");
|
||||
if (this.opt["page-range-format"] ) {
|
||||
var newstr = this.fun.page_mangler(start[0][1] +"-"+elements[i]);
|
||||
newstr = newstr.split(/\u2013/);
|
||||
newstr = newstr.split(this.getTerm("page-range-delimiter"));
|
||||
elements[i] = newstr[1];
|
||||
}
|
||||
count = count + 1;
|
||||
|
@ -10162,7 +10199,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) {
|
|||
CSL.Util.PageRangeMangler = {};
|
||||
CSL.Util.PageRangeMangler.getFunction = function (state) {
|
||||
var rangerex, pos, len, stringify, listify, expand, minimize, minimize_internal, chicago, lst, m, b, e, ret, begin, end, ret_func, ppos, llen;
|
||||
var range_delimiter = state.getTerm("range-delimiter");
|
||||
var range_delimiter = state.getTerm("page-range-delimiter");
|
||||
rangerex = /([a-zA-Z]*)([0-9]+)\s*-\s*([a-zA-Z]*)([0-9]+)/;
|
||||
stringify = function (lst) {
|
||||
len = lst.length;
|
||||
|
@ -10172,7 +10209,7 @@ CSL.Util.PageRangeMangler.getFunction = function (state) {
|
|||
}
|
||||
}
|
||||
var ret = lst.join("");
|
||||
ret = ret.replace(/([0-9])\-/, "$1\u2013", "g").replace(/\-([0-9])/, "\u2013$1", "g")
|
||||
ret = ret.replace(/([0-9])\-/, "$1"+state.getTerm("page-range-delimiter"), "g").replace(/\-([0-9])/, state.getTerm("page-range-delimiter")+"$1", "g")
|
||||
return ret;
|
||||
};
|
||||
listify = function (str, hyphens) {
|
||||
|
|
|
@ -141,38 +141,40 @@ Zotero.CookieSandbox.Observer = new function() {
|
|||
notificationCallbacks = channel.notificationCallbacks;
|
||||
|
||||
// try the notification callbacks
|
||||
trackedBy = this.trackedInterfaceRequestors.get(notificationCallbacks);
|
||||
if(trackedBy) {
|
||||
tested = true;
|
||||
} else {
|
||||
// try the browser
|
||||
try {
|
||||
browser = notificationCallbacks.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
|
||||
} catch(e) {}
|
||||
if(browser) {
|
||||
if(notificationCallbacks) {
|
||||
trackedBy = this.trackedInterfaceRequestors.get(notificationCallbacks);
|
||||
if(trackedBy) {
|
||||
tested = true;
|
||||
trackedBy = this.trackedBrowsers.get(browser);
|
||||
} else {
|
||||
// try the document for the load group
|
||||
// try the browser
|
||||
try {
|
||||
browser = channel.loadGroup.notificationCallbacks.getInterface(Ci.nsIWebNavigation)
|
||||
browser = notificationCallbacks.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
|
||||
} catch(e) {}
|
||||
if(browser) {
|
||||
tested = true;
|
||||
trackedBy = this.trackedBrowsers.get(browser);
|
||||
} else {
|
||||
// try getting as an XHR or nsIWBP
|
||||
// try the document for the load group
|
||||
try {
|
||||
notificationCallbacks.QueryInterface(Components.interfaces.nsIXMLHttpRequest);
|
||||
tested = true;
|
||||
browser = channel.loadGroup.notificationCallbacks.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
|
||||
} catch(e) {}
|
||||
if(!tested) {
|
||||
if(browser) {
|
||||
tested = true;
|
||||
trackedBy = this.trackedBrowsers.get(browser);
|
||||
} else {
|
||||
// try getting as an XHR or nsIWBP
|
||||
try {
|
||||
notificationCallbacks.QueryInterface(Components.interfaces.nsIWebBrowserPersist);
|
||||
notificationCallbacks.QueryInterface(Components.interfaces.nsIXMLHttpRequest);
|
||||
tested = true;
|
||||
} catch(e) {}
|
||||
if(!tested) {
|
||||
try {
|
||||
notificationCallbacks.QueryInterface(Components.interfaces.nsIWebBrowserPersist);
|
||||
tested = true;
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ Zotero.ItemTypes = new function() {
|
|||
mru = mru.split(',').slice(0, limit);
|
||||
for (var i=0, len=mru.length; i<len; i++) {
|
||||
var id = parseInt(mru[i]);
|
||||
if (!isNaN(id)) {
|
||||
if (!isNaN(id) && id != 13) { // ignore 'webpage' item type
|
||||
params.push(id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,6 +227,9 @@ Zotero.Creator.prototype.save = function () {
|
|||
|
||||
if (!creatorDataID) {
|
||||
var creatorDataID = Zotero.Creators.getDataID(this, true);
|
||||
if (creatorDataID != this.creatorDataID) {
|
||||
this._creatorDataID = creatorDataID;
|
||||
}
|
||||
}
|
||||
|
||||
var columns = [
|
||||
|
|
|
@ -4333,7 +4333,7 @@ Zotero.Item.prototype.erase = function() {
|
|||
catch (e) {
|
||||
// If deletion fails, try to correct a few things that have come up before
|
||||
Zotero.debug("Item deletion failed -- trying to fix", 2);
|
||||
Zotero.DB.query('DELETE FROM fulltextItemWords WHERE itemID=?', this.id);
|
||||
Zotero.Fulltext.clearItemWords(this.id);
|
||||
Zotero.DB.query('DELETE FROM itemTags WHERE itemID=?', this.id);
|
||||
|
||||
// And then try again
|
||||
|
|
|
@ -62,7 +62,8 @@ Zotero.Debug = new function () {
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (typeof message != 'string') {
|
||||
|
||||
if (typeof message != 'string') {
|
||||
message = Zotero.Utilities.varDump(message);
|
||||
}
|
||||
|
||||
|
@ -152,10 +153,14 @@ Zotero.Debug = new function () {
|
|||
}
|
||||
}
|
||||
|
||||
return Zotero.getErrors(true).join('\n\n') +
|
||||
"\n\n" + Zotero.getSystemInfo() + "\n\n" +
|
||||
"=========================================================\n\n" +
|
||||
output;
|
||||
if(Zotero.getErrors) {
|
||||
return Zotero.getErrors(true).join('\n\n') +
|
||||
"\n\n" + Zotero.getSystemInfo() + "\n\n" +
|
||||
"=========================================================\n\n" +
|
||||
output;
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -372,8 +372,9 @@ Zotero.File = new function(){
|
|||
var checkFileWindows = "Check that the file is not currently "
|
||||
+ "in use and that it is not marked as read-only. To check "
|
||||
+ "all files in your Zotero data directory, right-click on "
|
||||
+ "the 'zotero' directory, click Properties, and ensure that "
|
||||
+ "the Read-Only checkbox is empty.";
|
||||
+ "the 'zotero' directory, click Properties, clear "
|
||||
+ "the Read-Only checkbox, and apply the change to all folders "
|
||||
+ "and files in the directory.";
|
||||
var checkFileOther = "Check that the file is not currently "
|
||||
+ "in use and that its permissions allow write access.";
|
||||
var msg = str + " "
|
||||
|
|
|
@ -507,12 +507,13 @@ Zotero.HTTP = new function() {
|
|||
* @inner
|
||||
*/
|
||||
var onLoad = function() {
|
||||
if(hiddenBrowser.contentDocument.location.href == "about:blank") return;
|
||||
Zotero.debug(hiddenBrowser.contentDocument.location.href+" has been loaded");
|
||||
if(hiddenBrowser.contentDocument.location.href != prevUrl) { // Just in case it fires too many times
|
||||
prevUrl = hiddenBrowser.contentDocument.location.href;
|
||||
var doc = hiddenBrowser.contentDocument,
|
||||
url = doc.location.href.toString();
|
||||
if(url == "about:blank" || doc.readyState === "loading") return;
|
||||
if(url !== prevUrl) { // Just in case it fires too many times
|
||||
prevUrl = url;
|
||||
try {
|
||||
processor(hiddenBrowser.contentDocument);
|
||||
processor(doc);
|
||||
} catch(e) {
|
||||
removeListeners();
|
||||
if(exception) {
|
||||
|
|
|
@ -1256,7 +1256,10 @@ Zotero.Integration.Fields.prototype._retrieveFields = function() {
|
|||
* Shows an error if a field code is corrupted
|
||||
* @param {Exception} e The exception thrown
|
||||
* @param {Field} field The Zotero field object
|
||||
* @param {Function} callback The callback passed to updateSession
|
||||
* @param {Function} errorCallback The error callback passed to updateSession
|
||||
* @param {Integer} i The field index
|
||||
* @return {Boolean} Whether to continue updating the session
|
||||
*/
|
||||
Zotero.Integration.Fields.prototype._showCorruptFieldError = function(e, field, callback, errorCallback, i) {
|
||||
Zotero.logError(e);
|
||||
|
@ -1287,6 +1290,58 @@ Zotero.Integration.Fields.prototype._showCorruptFieldError = function(e, field,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an error if a field code is missing
|
||||
* @param {Exception} e The exception thrown
|
||||
* @param {Exception} e The exception thrown
|
||||
* @param {Field} field The Zotero field object
|
||||
* @param {Function} callback The callback passed to updateSession
|
||||
* @param {Function} errorCallback The error callback passed to updateSession
|
||||
* @param {Integer} i The field index
|
||||
* @return {Boolean} Whether to continue updating the session
|
||||
*/
|
||||
Zotero.Integration.Fields.prototype._showMissingItemError = function(e, field, callback, errorCallback, i) {
|
||||
// First, check if we've already decided to remove field codes from these
|
||||
var reselect = true;
|
||||
for each(var reselectKey in e.reselectKeys) {
|
||||
if(this._deleteKeys[reselectKey]) {
|
||||
this._removeCodeFields.push(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ask user what to do with this item
|
||||
if(e.citationLength == 1) {
|
||||
var msg = Zotero.getString("integration.missingItem.single");
|
||||
} else {
|
||||
var msg = Zotero.getString("integration.missingItem.multiple", (e.citationIndex+1).toString());
|
||||
}
|
||||
msg += '\n\n'+Zotero.getString('integration.missingItem.description');
|
||||
field.select();
|
||||
this._doc.activate();
|
||||
var result = this._doc.displayAlert(msg, 1, 3);
|
||||
if(result == 0) { // Cancel
|
||||
throw new Zotero.Integration.UserCancelledException();
|
||||
} else if(result == 1) { // No
|
||||
for each(var reselectKey in e.reselectKeys) {
|
||||
this._deleteKeys[reselectKey] = true;
|
||||
}
|
||||
this._removeCodeFields.push(i);
|
||||
return true;
|
||||
} else { // Yes
|
||||
// Display reselect item dialog
|
||||
var me = this;
|
||||
var oldCurrentWindow = Zotero.Integration.currentWindow;
|
||||
this._session.reselectItem(this._doc, e, function() {
|
||||
// Now try again
|
||||
Zotero.Integration.currentWindow = oldCurrentWindow;
|
||||
me._doc.activate();
|
||||
me._processFields(me._fields, callback, errorCallback, i);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Zotero.Integration.Session attached to Zotero.Integration.Fields in line with document
|
||||
*/
|
||||
|
@ -1315,23 +1370,28 @@ Zotero.Integration.Fields.prototype.updateSession = function(callback, errorCall
|
|||
try {
|
||||
me._session.loadBibliographyData(me._bibliographyData);
|
||||
} catch(e) {
|
||||
if(errorCallback) {
|
||||
errorCallback(e);
|
||||
} else if(e instanceof Zotero.Integration.CorruptFieldException) {
|
||||
var msg = Zotero.getString("integration.corruptBibliography")+'\n\n'+
|
||||
Zotero.getString('integration.corruptBibliography.description');
|
||||
var result = me._doc.displayAlert(msg,
|
||||
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_CAUTION,
|
||||
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
|
||||
if(result == 0) {
|
||||
throw e;
|
||||
var defaultHandler = function() {
|
||||
if(e instanceof Zotero.Integration.CorruptFieldException) {
|
||||
var msg = Zotero.getString("integration.corruptBibliography")+'\n\n'+
|
||||
Zotero.getString('integration.corruptBibliography.description');
|
||||
var result = me._doc.displayAlert(msg,
|
||||
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_CAUTION,
|
||||
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
|
||||
if(result == 0) {
|
||||
throw e;
|
||||
} else {
|
||||
me._bibliographyData = "";
|
||||
me._session.bibliographyHasChanged = true;
|
||||
me._session.bibliographyDataHasChanged = true;
|
||||
}
|
||||
} else {
|
||||
me._bibliographyData = "";
|
||||
me._session.bibliographyHasChanged = true;
|
||||
me._session.bibliographyDataHasChanged = true;
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
};
|
||||
if(errorCallback) {
|
||||
if(!errorCallback(e, defaultHandler)) return;
|
||||
} else if(!defaultHandler()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1362,13 +1422,26 @@ Zotero.Integration.Fields.prototype.updateSession = function(callback, errorCall
|
|||
Zotero.Integration.Fields.prototype._processFields = function(fields, callback, errorCallback, i) {
|
||||
if(!i) i = 0;
|
||||
|
||||
var me = this;
|
||||
for(var n = fields.length; i<n; i++) {
|
||||
var field = fields[i];
|
||||
|
||||
try {
|
||||
var fieldCode = field.getCode();
|
||||
} catch(e) {
|
||||
if(!this._showCorruptFieldError(e, field, callback, errorCallback, i)) return;
|
||||
var defaultHandler = function() {
|
||||
return me._showCorruptFieldError(e, field, callback, errorCallback, i);
|
||||
};
|
||||
|
||||
if(errorCallback) {
|
||||
if(errorCallback(e, defaultHandler)) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if(!defaultHandler()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var [type, content] = this.getCodeTypeAndContent(fieldCode);
|
||||
|
@ -1377,54 +1450,24 @@ Zotero.Integration.Fields.prototype._processFields = function(fields, callback,
|
|||
try {
|
||||
this._session.addCitation(i, noteIndex, content);
|
||||
} catch(e) {
|
||||
var defaultHandler = function() {
|
||||
if(e instanceof Zotero.Integration.MissingItemException) {
|
||||
return me._showMissingItemError(e, field, callback, errorCallback, i);
|
||||
} else if(e instanceof Zotero.Integration.CorruptFieldException) {
|
||||
return me._showCorruptFieldError(e, field, callback, errorCallback, i);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
if(errorCallback) {
|
||||
errorCallback(e);
|
||||
} else if(e instanceof Zotero.Integration.MissingItemException) {
|
||||
// First, check if we've already decided to remove field codes from these
|
||||
var reselect = true;
|
||||
for each(var reselectKey in e.reselectKeys) {
|
||||
if(this._deleteKeys[reselectKey]) {
|
||||
this._removeCodeFields.push(i);
|
||||
reselect = false;
|
||||
break;
|
||||
}
|
||||
if(errorCallback(e, defaultHandler)) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if(reselect) {
|
||||
// Ask user what to do with this item
|
||||
if(e.citationLength == 1) {
|
||||
var msg = Zotero.getString("integration.missingItem.single");
|
||||
} else {
|
||||
var msg = Zotero.getString("integration.missingItem.multiple", (e.citationIndex+1).toString());
|
||||
}
|
||||
msg += '\n\n'+Zotero.getString('integration.missingItem.description');
|
||||
field.select();
|
||||
this._doc.activate();
|
||||
var result = this._doc.displayAlert(msg, 1, 3);
|
||||
if(result == 0) { // Cancel
|
||||
throw new Zotero.Integration.UserCancelledException();
|
||||
} else if(result == 1) { // No
|
||||
for each(var reselectKey in e.reselectKeys) {
|
||||
this._deleteKeys[reselectKey] = true;
|
||||
}
|
||||
this._removeCodeFields.push(i);
|
||||
} else { // Yes
|
||||
// Display reselect item dialog
|
||||
var me = this;
|
||||
var oldCurrentWindow = Zotero.Integration.currentWindow;
|
||||
this._session.reselectItem(this._doc, e, function() {
|
||||
// Now try again
|
||||
Zotero.Integration.currentWindow = oldCurrentWindow;
|
||||
me._doc.activate();
|
||||
me._processFields(fields, callback, errorCallback, i);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if(e instanceof Zotero.Integration.CorruptFieldException) {
|
||||
if(!this._showCorruptFieldError(e, field, callback, errorCallback, i)) return;
|
||||
} else {
|
||||
throw e;
|
||||
} if(!defaultHandler()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if(type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
|
||||
|
@ -1447,12 +1490,17 @@ Zotero.Integration.Fields.prototype._processFields = function(fields, callback,
|
|||
Zotero.Integration.Fields.prototype.updateDocument = function(forceCitations, forceBibliography,
|
||||
ignoreCitationChanges, callback) {
|
||||
// update citations
|
||||
this._session.updateUpdateIndices(forceCitations);
|
||||
var me = this;
|
||||
var deleteCitations = Zotero.pumpGenerator(this._session.updateCitations(function(deleteCitations) {
|
||||
Zotero.pumpGenerator(me._updateDocument(forceCitations, forceBibliography,
|
||||
ignoreCitationChanges, deleteCitations, callback));
|
||||
}));
|
||||
try {
|
||||
this._session.updateUpdateIndices(forceCitations);
|
||||
var me = this;
|
||||
var deleteCitations = Zotero.pumpGenerator(this._session.updateCitations(function(deleteCitations) {
|
||||
Zotero.pumpGenerator(me._updateDocument(forceCitations, forceBibliography,
|
||||
ignoreCitationChanges, deleteCitations, callback));
|
||||
}));
|
||||
} catch(e) {
|
||||
Zotero.logError(e);
|
||||
Zotero.Integration.handleError(e, this._doc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1722,6 +1770,26 @@ Zotero.Integration.CitationEditInterface = function(citation, field, fields, ses
|
|||
}
|
||||
|
||||
Zotero.Integration.CitationEditInterface.prototype = {
|
||||
/**
|
||||
* Handles an error in updateSession
|
||||
*/
|
||||
"_errorHandler":function(e, defaultHandler) {
|
||||
Zotero.debug('Integration.CitationEditInterface: Error "'+e.toString()+'" caught by handler');
|
||||
if(this._haveAccepted) {
|
||||
try {
|
||||
return defaultHandler();
|
||||
} catch(e) {
|
||||
if(e instanceof Zotero.Integration.UserCancelledException) {
|
||||
this._field.delete();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
this._errorOccurred = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Run a function when the session information has been updated
|
||||
* @param {Function} sessionUpdatedCallback
|
||||
|
@ -1743,12 +1811,7 @@ Zotero.Integration.CitationEditInterface.prototype = {
|
|||
}
|
||||
me._sessionUpdated = true;
|
||||
delete me._sessionCallbackQueue;
|
||||
}, function(e) {
|
||||
if(e instanceof Zotero.Integration.MissingItemException
|
||||
|| e instanceof Zotero.Integration.CorruptFieldException) {
|
||||
me._errorOccurred = true;
|
||||
}
|
||||
});
|
||||
}, function(e, defaultHandler) { return me._errorHandler(e, defaultHandler) });
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1795,8 +1858,9 @@ Zotero.Integration.CitationEditInterface.prototype = {
|
|||
Zotero.setTimeout(function() {
|
||||
me._fields.updateSession(function() {
|
||||
me._errorOccurred = false;
|
||||
me._sessionUpdated = true;
|
||||
me.accept(progressCallback, true);
|
||||
})
|
||||
}, function(e, defaultHandler) { return me._errorHandler(e, defaultHandler) });
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -114,11 +114,11 @@ Zotero.IPC = new function() {
|
|||
close = lib.declare("close", ctypes.default_abi, ctypes.int, ctypes.int);
|
||||
}
|
||||
|
||||
// On OS X, O_NONBLOCK = 0x0004
|
||||
// On OS X and FreeBSD, O_NONBLOCK = 0x0004
|
||||
// On Linux, O_NONBLOCK = 00004000
|
||||
// On both, O_WRONLY = 0x0001
|
||||
var mode = 0x0001;
|
||||
if(!block) mode = mode | (Zotero.isMac ? 0x0004 : 00004000);
|
||||
if(!block) mode = mode | (Zotero.isLinux ? 00004000 : 0x0004);
|
||||
|
||||
var fd = open(pipe.path, mode);
|
||||
if(fd === -1) return false;
|
||||
|
|
|
@ -2452,6 +2452,34 @@ Zotero.ItemTreeView.prototype.canDrop = function(row, orient, dragData)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Don't allow children to be dragged within their own parents
|
||||
var parentItemID = item.getSource();
|
||||
var parentIndex = this._itemRowMap[parentItemID];
|
||||
if (this.getLevel(row) > 0) {
|
||||
if (this._getItemAtRow(this.getParentIndex(row)).ref.id == parentItemID) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Including immediately after the parent
|
||||
if (orient == 1) {
|
||||
if (row == parentIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// And immediately before the next parent
|
||||
if (orient == -1) {
|
||||
var nextParentIndex = null;
|
||||
for (var i = parentIndex + 1; i < this.rowCount; i++) {
|
||||
if (this.getLevel(i) == 0) {
|
||||
nextParentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (row === nextParentIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow cross-library child drag
|
||||
if (item.libraryID != itemGroup.ref.libraryID) {
|
||||
return false;
|
||||
|
|
|
@ -39,6 +39,11 @@ Zotero.MIMETypeHandler = new function () {
|
|||
getService(Components.interfaces.nsIObserverService).
|
||||
addObserver(_Observer, "http-on-examine-response", false);
|
||||
this.initializeHandlers();
|
||||
Zotero.addShutdownListener(function() {
|
||||
Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService).
|
||||
removeObserver(_Observer, "http-on-examine-response", false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -206,20 +206,15 @@ Zotero.Schema = new function(){
|
|||
Zotero.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var up4 = this.updateBundledFiles(null, null, up2 || up3);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
Zotero.logError(e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Zotero.UnresponsiveScriptIndicator.enable();
|
||||
}
|
||||
|
||||
return up1 || up2 || up3 || up4;
|
||||
// After a delay, start update of bundled files and repo updates
|
||||
setTimeout(function () {
|
||||
Zotero.Schema.updateBundledFiles(null, null, up2 || up3);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1119,59 +1114,205 @@ Zotero.Schema = new function(){
|
|||
}
|
||||
|
||||
|
||||
this.integrityCheck = function () {
|
||||
this.integrityCheck = function (fix) {
|
||||
// There should be an equivalent SELECT COUNT(*) statement for every
|
||||
// statement run by the DB Repair Tool
|
||||
var queries = [
|
||||
"SELECT COUNT(*) FROM annotations WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM collectionItems WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM fulltextItems)",
|
||||
"SELECT COUNT(*) FROM highlights WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemCreators WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemData WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemNotes WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemSeeAlso WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemSeeAlso WHERE linkedItemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemTags WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"SELECT COUNT(*) FROM itemTags WHERE tagID NOT IN (SELECT tagID FROM tags)",
|
||||
"SELECT COUNT(*) FROM savedSearchConditions WHERE savedSearchID NOT IN (select savedSearchID FROM savedSearches)",
|
||||
"SELECT COUNT(*) FROM items WHERE itemTypeID IS NULL",
|
||||
[
|
||||
"SELECT COUNT(*) FROM annotations WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM annotations WHERE itemID NOT IN (SELECT itemID FROM items)"
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM collectionItems WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM collectionItems WHERE itemID NOT IN (SELECT itemID FROM items)"
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items)"
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM fulltextItems)",
|
||||
"DELETE FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM fulltextItems)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM highlights WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM highlights WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemAttachments WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemCreators WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemCreators WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemData WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemData WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemNotes WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemNotes WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemSeeAlso WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemSeeAlso WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemSeeAlso WHERE linkedItemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemSeeAlso WHERE linkedItemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemTags WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
"DELETE FROM itemTags WHERE itemID NOT IN (SELECT itemID FROM items)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemTags WHERE tagID NOT IN (SELECT tagID FROM tags)",
|
||||
"DELETE FROM itemTags WHERE tagID NOT IN (SELECT tagID FROM tags)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM savedSearchConditions WHERE savedSearchID NOT IN (select savedSearchID FROM savedSearches)",
|
||||
"DELETE FROM savedSearchConditions WHERE savedSearchID NOT IN (select savedSearchID FROM savedSearches)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM items WHERE itemTypeID IS NULL",
|
||||
"DELETE FROM items WHERE itemTypeID IS NULL",
|
||||
],
|
||||
|
||||
"SELECT COUNT(*) FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE wordID NOT IN (SELECT wordID FROM fulltextWords)",
|
||||
"SELECT COUNT(*) FROM collectionItems WHERE collectionID NOT IN (SELECT collectionID FROM collections)",
|
||||
"SELECT COUNT(*) FROM itemCreators WHERE creatorID NOT IN (SELECT creatorID FROM creators)",
|
||||
"SELECT COUNT(*) FROM itemTags WHERE tagID NOT IN (SELECT tagID FROM tags)",
|
||||
"SELECT COUNT(*) FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM fields)",
|
||||
"SELECT COUNT(*) FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
|
||||
"SELECT COUNT(*) FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFields WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
"DELETE FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE wordID NOT IN (SELECT wordID FROM fulltextWords)",
|
||||
"DELETE FROM fulltextItemWords WHERE wordID NOT IN (SELECT wordID FROM fulltextWords)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM collectionItems WHERE collectionID NOT IN (SELECT collectionID FROM collections)",
|
||||
"DELETE FROM collectionItems WHERE collectionID NOT IN (SELECT collectionID FROM collections)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemCreators WHERE creatorID NOT IN (SELECT creatorID FROM creators)",
|
||||
"DELETE FROM itemCreators WHERE creatorID NOT IN (SELECT creatorID FROM creators)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM fields)",
|
||||
"DELETE FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM fields)",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
"DELETE FROM itemData WHERE valueID NOT IN (SELECT valueID FROM itemDataValues)",
|
||||
],
|
||||
|
||||
"SELECT COUNT(*) FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
|
||||
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
"SELECT COUNT(*) FROM itemNotes WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
// Attachments row with itemTypeID != 14
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemAttachments JOIN items USING (itemID) WHERE itemTypeID != 14",
|
||||
"UPDATE items SET itemTypeID=14, clientDateModified=CURRENT_TIMESTAMP WHERE itemTypeID != 14 AND itemID IN (SELECT itemID FROM itemAttachments)",
|
||||
],
|
||||
// Fields not in type
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFields WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
|
||||
"DELETE FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFields WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
|
||||
],
|
||||
// Missing itemAttachments row
|
||||
[
|
||||
"SELECT COUNT(*) FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
|
||||
"INSERT INTO itemAttachments (itemID, linkMode) SELECT itemID, 0 FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
|
||||
],
|
||||
// Note/child parents
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
"UPDATE itemAttachments SET sourceItemID=NULL WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemNotes WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
"UPDATE itemNotes SET sourceItemID=NULL WHERE sourceItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
|
||||
],
|
||||
|
||||
"SELECT COUNT(*) FROM tags NATURAL JOIN itemTags JOIN items USING (itemID) WHERE IFNULL(tags.libraryID, 0)!=IFNULL(items.libraryID,0)",
|
||||
|
||||
"SELECT COUNT(*) FROM itemTags WHERE tagID IS NULL",
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE charsetID='NULL'",
|
||||
// Wrong library tags
|
||||
[
|
||||
"SELECT COUNT(*) FROM tags NATURAL JOIN itemTags JOIN items USING (itemID) WHERE IFNULL(tags.libraryID, 0)!=IFNULL(items.libraryID,0)",
|
||||
[
|
||||
"CREATE TEMPORARY TABLE tmpWrongLibraryTags AS SELECT itemTags.ROWID AS tagRowID, tagID, name, itemID, IFNULL(tags.libraryID,0) AS tagLibraryID, IFNULL(items.libraryID,0) AS itemLibraryID FROM tags NATURAL JOIN itemTags JOIN items USING (itemID) WHERE IFNULL(tags.libraryID, 0)!=IFNULL(items.libraryID,0)",
|
||||
"DELETE FROM itemTags WHERE ROWID IN (SELECT tagRowID FROM tmpWrongLibraryTags)",
|
||||
"DROP TABLE tmpWrongLibraryTags"
|
||||
]
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemTags WHERE tagID IS NULL",
|
||||
"DELETE FROM itemTags WHERE tagID IS NULL",
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM itemAttachments WHERE charsetID='NULL'",
|
||||
"UPDATE itemAttachments SET charsetID=NULL WHERE charsetID='NULL'",
|
||||
],
|
||||
|
||||
// Reported by one user
|
||||
// http://forums.zotero.org/discussion/19347/continual-synching-error-message/
|
||||
// TODO: check 'libraries', not 'groups', but first add a
|
||||
// migration step to delete 'libraries' rows not in 'groups'
|
||||
//"SELECT COUNT(*) FROM syncDeleteLog WHERE libraryID != 0 AND libraryID NOT IN (SELECT libraryID FROM libraries)"
|
||||
"SELECT COUNT(*) FROM syncDeleteLog WHERE libraryID != 0 AND libraryID NOT IN (SELECT libraryID FROM groups)",
|
||||
[
|
||||
"SELECT COUNT(*) FROM syncDeleteLog WHERE libraryID != 0 AND libraryID NOT IN (SELECT libraryID FROM groups)",
|
||||
"DELETE FROM syncDeleteLog WHERE libraryID != 0 AND libraryID NOT IN (SELECT libraryID FROM libraries)",
|
||||
],
|
||||
|
||||
"SELECT COUNT(*) FROM creatorData WHERE firstName='' AND lastName=''",
|
||||
|
||||
"SELECT COUNT(*) FROM itemAttachments JOIN items USING (itemID) WHERE itemTypeID != 14"
|
||||
// Delete empty creators
|
||||
// This may cause itemCreator gaps, but that's better than empty creators
|
||||
[
|
||||
"SELECT COUNT(*) FROM creatorData WHERE firstName='' AND lastName=''",
|
||||
[
|
||||
"DELETE FROM itemCreators WHERE creatorID IN (SELECT creatorID FROM creators WHERE creatorDataID IN (SELECT creatorDataID FROM creatorData WHERE firstName='' AND lastName=''))",
|
||||
"DELETE FROM creators WHERE creatorDataID IN (SELECT creatorDataID FROM creatorData WHERE firstName='' AND lastName='')",
|
||||
"DELETE FROM creatorData WHERE firstName='' AND lastName=''"
|
||||
],
|
||||
],
|
||||
|
||||
// Non-attachment items in the full-text index
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
|
||||
[
|
||||
"DELETE FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
|
||||
"SELECT 1"
|
||||
]
|
||||
],
|
||||
[
|
||||
"SELECT COUNT(*) FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
|
||||
"DELETE FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)"
|
||||
]
|
||||
];
|
||||
|
||||
for each(var sql in queries) {
|
||||
if (Zotero.DB.valueQuery(sql)) {
|
||||
if (Zotero.DB.valueQuery(sql[0])) {
|
||||
Zotero.debug("Test failed!", 1);
|
||||
|
||||
if (fix) {
|
||||
try {
|
||||
// Single query
|
||||
if (typeof sql[1] == 'string') {
|
||||
Zotero.DB.valueQuery(sql[1]);
|
||||
}
|
||||
// Multiple queries
|
||||
else {
|
||||
for each(var s in sql[1]) {
|
||||
Zotero.DB.valueQuery(s);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1180,7 +1321,6 @@ Zotero.Schema = new function(){
|
|||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private methods
|
||||
|
|
|
@ -53,8 +53,8 @@ Zotero.Sync.Storage = new function () {
|
|||
|
||||
// TEMP
|
||||
// TODO: localize
|
||||
this.defaultError = "A file sync error occurred. Please try syncing again.\n\nIf you receive this message repeatedly, restart " + Zotero.appName + " and/or your computer and try again. If you continue to receive the message, submit an error report and post the Report ID to a new thread in the Zotero Forums.";
|
||||
this.defaultErrorRestart = "A file sync error occurred. Please restart " + Zotero.appName + " and/or your computer and try syncing again.\n\nIf you receive this message repeatedly, submit an error report and post the Report ID to a new thread in the Zotero Forums.";
|
||||
this.__defineGetter__("defaultError", function () "A file sync error occurred. Please try syncing again.\n\nIf you receive this message repeatedly, restart " + Zotero.appName + " and/or your computer and try again. If you continue to receive the message, submit an error report and post the Report ID to a new thread in the Zotero Forums.");
|
||||
this.__defineGetter__("defaultErrorRestart", function () "A file sync error occurred. Please restart " + Zotero.appName + " and/or your computer and try syncing again.\n\nIf you receive this message repeatedly, submit an error report and post the Report ID to a new thread in the Zotero Forums.");
|
||||
|
||||
//
|
||||
// Public properties
|
||||
|
@ -1339,7 +1339,10 @@ Zotero.Sync.Storage = new function () {
|
|||
|
||||
if (windowsLength) {
|
||||
var pathLength = destFile.path.length - destFile.leafName.length;
|
||||
var newLength = 254 - pathLength;
|
||||
// Limit should be 255, but a shorter limit seems to be
|
||||
// enforced for nsIZipReader.extract() below on
|
||||
// non-English systems
|
||||
var newLength = 240 - pathLength;
|
||||
// Require 40 available characters in path -- this is arbitrary,
|
||||
// but otherwise filenames are going to end up being cut off
|
||||
if (newLength < 40) {
|
||||
|
@ -1351,7 +1354,7 @@ Zotero.Sync.Storage = new function () {
|
|||
}
|
||||
}
|
||||
else {
|
||||
var newLength = 254;
|
||||
var newLength = 240;
|
||||
}
|
||||
|
||||
// Shorten file if it's too long -- we don't relink it, but this should
|
||||
|
@ -1415,6 +1418,7 @@ Zotero.Sync.Storage = new function () {
|
|||
zipReader.extract(entryName, destFile);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(destFile.path);
|
||||
Zotero.File.checkFileAccessError(e, destFile, 'create');
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ Zotero.Translate.Sandbox = {
|
|||
for(var j=0; j<nAttachments; j++) {
|
||||
if(attachments[j].document) {
|
||||
attachments[j].url = attachments[j].document.location.href;
|
||||
attachments[j].mimeType = "text/html";
|
||||
delete attachments[j].document;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -646,7 +646,6 @@ const ZOTERO_CONFIG = {
|
|||
}
|
||||
|
||||
Zotero.DB.startDummyStatement();
|
||||
Zotero.Schema.updateFromRepository();
|
||||
|
||||
// Populate combined tables for custom types and fields -- this is likely temporary
|
||||
if (!upgraded && !updated) {
|
||||
|
@ -2303,6 +2302,7 @@ Zotero.VersionHeader = {
|
|||
if (Zotero.Prefs.get("zoteroDotOrgVersionHeader")) {
|
||||
this.register();
|
||||
}
|
||||
Zotero.addShutdownListener(this.unregister);
|
||||
},
|
||||
|
||||
// Called from this.init() and Zotero.Prefs.observe()
|
||||
|
@ -2327,7 +2327,7 @@ Zotero.VersionHeader = {
|
|||
unregister: function () {
|
||||
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
observerService.removeObserver(this, "http-on-modify-request");
|
||||
observerService.removeObserver(Zotero.VersionHeader, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ var ZoteroPane = new function()
|
|||
menuitem.setAttribute("label", itemTypes[i].localized);
|
||||
menuitem.setAttribute("tooltiptext", "");
|
||||
let type = itemTypes[i].id;
|
||||
menuitem.addEventListener("command", function() { ZoteroPane_Local.newItem(type); }, false);
|
||||
menuitem.addEventListener("command", function() { ZoteroPane_Local.newItem(type, {}, null, true); }, false);
|
||||
moreMenu.appendChild(menuitem);
|
||||
}
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ var ZoteroPane = new function()
|
|||
menuitem.setAttribute("label", itemTypes[i].localized);
|
||||
menuitem.setAttribute("tooltiptext", "");
|
||||
let type = itemTypes[i].id;
|
||||
menuitem.addEventListener("command", function() { ZoteroPane_Local.newItem(type); }, false);
|
||||
menuitem.addEventListener("command", function() { ZoteroPane_Local.newItem(type, {}, null, true); }, false);
|
||||
menuitem.className = "zotero-tb-add";
|
||||
addMenu.insertBefore(menuitem, separator);
|
||||
}
|
||||
|
@ -658,7 +658,7 @@ var ZoteroPane = new function()
|
|||
*
|
||||
* _data_ is an optional object with field:value for itemData
|
||||
*/
|
||||
function newItem(typeID, data, row)
|
||||
function newItem(typeID, data, row, manual)
|
||||
{
|
||||
if (!Zotero.stateCheck()) {
|
||||
this.displayErrorMessage(true);
|
||||
|
@ -675,7 +675,7 @@ var ZoteroPane = new function()
|
|||
}
|
||||
}
|
||||
|
||||
if (row !== undefined) {
|
||||
if (row !== undefined && row !== null) {
|
||||
var itemGroup = this.collectionsView._getItemAtRow(row);
|
||||
var libraryID = itemGroup.ref.libraryID;
|
||||
}
|
||||
|
@ -703,19 +703,21 @@ var ZoteroPane = new function()
|
|||
document.getElementById('zotero-view-item').selectedIndex = 0;
|
||||
|
||||
// Update most-recently-used list for New Item menu
|
||||
var mru = Zotero.Prefs.get('newItemTypeMRU');
|
||||
if (mru) {
|
||||
var mru = mru.split(',');
|
||||
var pos = mru.indexOf(typeID + '');
|
||||
if (pos != -1) {
|
||||
mru.splice(pos, 1);
|
||||
if (manual) {
|
||||
var mru = Zotero.Prefs.get('newItemTypeMRU');
|
||||
if (mru) {
|
||||
var mru = mru.split(',');
|
||||
var pos = mru.indexOf(typeID + '');
|
||||
if (pos != -1) {
|
||||
mru.splice(pos, 1);
|
||||
}
|
||||
mru.unshift(typeID);
|
||||
}
|
||||
mru.unshift(typeID);
|
||||
else {
|
||||
var mru = [typeID + ''];
|
||||
}
|
||||
Zotero.Prefs.set('newItemTypeMRU', mru.slice(0, 5).join(','));
|
||||
}
|
||||
else {
|
||||
var mru = [typeID + ''];
|
||||
}
|
||||
Zotero.Prefs.set('newItemTypeMRU', mru.slice(0, 5).join(','));
|
||||
|
||||
return Zotero.Items.get(itemID);
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
|
||||
<!ENTITY zotero.integration.prefs.formatUsing.label "Format Using:">
|
||||
<!ENTITY zotero.integration.prefs.bookmarks.label "Bookmarks">
|
||||
<!ENTITY zotero.integration.prefs.bookmarks.caption "Bookmarks are preserved across Microsoft Word and OpenOffice, but may be accidentally modified. For 
compatibility reasons, citations cannot be inserted into footnotes or endnotes when this option is selected.">
|
||||
<!ENTITY zotero.integration.prefs.bookmarks.caption "Bookmarks are preserved across Microsoft Word and LibreOffice, but may be accidentally modified. For 
compatibility reasons, citations cannot be inserted into footnotes or endnotes when this option is selected.">
|
||||
|
||||
<!ENTITY zotero.integration.prefs.storeReferences.label "Store references in document">
|
||||
<!ENTITY zotero.integration.prefs.storeReferences.caption "Storing references in your document slightly increases file size, but will allow you to share your document with others without using a Zotero group. Zotero 3.0 or later is required to update documents created with this option.">
|
||||
|
|
|
@ -11,6 +11,7 @@ general.restartRequiredForChange = %S must be restarted for the change to take e
|
|||
general.restartRequiredForChanges = %S must be restarted for the changes to take effect.
|
||||
general.restartNow = Restart now
|
||||
general.restartLater = Restart later
|
||||
general.restartApp = Restart %S
|
||||
general.errorHasOccurred = An error has occurred.
|
||||
general.unknownErrorOccurred = An unknown error occurred.
|
||||
general.restartFirefox = Please restart %S.
|
||||
|
@ -426,8 +427,14 @@ db.dbRestored = The Zotero database '%1$S' appears to have become corrupted.
|
|||
db.dbRestoreFailed = The Zotero database '%S' appears to have become corrupted, and an attempt to restore from the last automatic backup failed.\n\nA new database file has been created. The damaged file was saved in your Zotero directory.
|
||||
|
||||
db.integrityCheck.passed = No errors were found in the database.
|
||||
db.integrityCheck.failed = Errors were found in the Zotero database!
|
||||
db.integrityCheck.failed = Errors were found in your Zotero database.
|
||||
db.integrityCheck.dbRepairTool = You can use the database repair tool at http://zotero.org/utils/dbfix to attempt to correct these errors.
|
||||
db.integrityCheck.repairAttempt = Zotero can attempt to correct these errors.
|
||||
db.integrityCheck.appRestartNeeded = %S will need to be restarted.
|
||||
db.integrityCheck.fixAndRestart = Fix Errors and Restart %S
|
||||
db.integrityCheck.errorsFixed = The errors in your Zotero database have been corrected.
|
||||
db.integrityCheck.errorsNotFixed = Zotero was unable to correct all the errors in your database.
|
||||
db.integrityCheck.reportInForums = You can report this problem in the Zotero Forums.
|
||||
|
||||
zotero.preferences.update.updated = Updated
|
||||
zotero.preferences.update.upToDate = Up to date
|
||||
|
@ -460,7 +467,8 @@ zotero.preferences.search.pdf.toolsDownloadError = An error occurred while at
|
|||
zotero.preferences.search.pdf.tryAgainOrViewManualInstructions = Please try again later, or view the documentation for manual installation instructions.
|
||||
zotero.preferences.export.quickCopy.bibStyles = Bibliographic Styles
|
||||
zotero.preferences.export.quickCopy.exportFormats = Export Formats
|
||||
zotero.preferences.export.quickCopy.instructions = Quick Copy allows you to copy selected references to the clipboard by pressing a shortcut key (%S) or dragging items into a text box on a web page.
|
||||
zotero.preferences.export.quickCopy.instructions = Quick Copy allows you to copy selected items to the clipboard by pressing %S or dragging items into a text box on a web page.
|
||||
zotero.preferences.export.quickCopy.citationInstructions = For bibliography styles, you can copy citations or footnotes by pressing %S or holding down Shift before dragging items.
|
||||
zotero.preferences.styles.addStyle = Add Style
|
||||
|
||||
zotero.preferences.advanced.resetTranslatorsAndStyles = Reset Translators and Styles
|
||||
|
@ -581,7 +589,7 @@ integration.revertAll.button = Revert All
|
|||
integration.revert.title = Are you sure you want to revert this edit?
|
||||
integration.revert.body = If you choose to continue, the text of the bibliography entries corresponded to the selected item(s) will be replaced with the unmodified text specified by the selected style.
|
||||
integration.revert.button = Revert
|
||||
integration.removeBibEntry.title = The selected references is cited within your document.
|
||||
integration.removeBibEntry.title = The selected reference is cited within your document.
|
||||
integration.removeBibEntry.body = Are you sure you want to omit it from your bibliography?
|
||||
|
||||
integration.cited = Cited
|
||||
|
@ -602,7 +610,7 @@ integration.error.cannotInsertHere = Zotero fields cannot be inserted here.
|
|||
integration.error.notInCitation = You must place the cursor in a Zotero citation to edit it.
|
||||
integration.error.noBibliography = The current bibliographic style does not define a bibliography. If you wish to add a bibliography, please choose another style.
|
||||
integration.error.deletePipe = The pipe that Zotero uses to communicate with the word processor could not be initialized. Would you like Zotero to attempt to correct this error? You will be prompted for your password.
|
||||
integration.error.invalidStyle = The style you have selected does not appear to be valid. If you have created this style yourself, please ensure that it passes validation as described at http://zotero.org/support/dev/citation_styles. Alternatively, try selecting another style.
|
||||
integration.error.invalidStyle = The style you have selected does not appear to be valid. If you have created this style yourself, please ensure that it passes validation as described at https://github.com/citation-style-language/styles/wiki/Validation. Alternatively, try selecting another style.
|
||||
integration.error.fieldTypeMismatch = Zotero cannot update this document because it was created by a different word processing application with an incompatible field encoding. In order to make a document compatible with both Word and OpenOffice.org/LibreOffice/NeoOffice, open the document in the word processor with which it was originally created and switch the field type to Bookmarks in the Zotero Document Preferences.
|
||||
|
||||
integration.replace = Replace this Zotero field?
|
||||
|
@ -617,7 +625,7 @@ integration.corruptField.description = Clicking "No" will delete the field codes
|
|||
integration.corruptBibliography = The Zotero field code for your bibliography is corrupted. Should Zotero clear this field code and generate a new bibliography?
|
||||
integration.corruptBibliography.description = All items cited in the text will appear in the new bibliography, but modifications you made in the "Edit Bibliography" dialog will be lost.
|
||||
integration.citationChanged = You have modified this citation since Zotero generated it. Do you want to keep your modifications and prevent future updates?
|
||||
integration.citationChanged.description = Clicking "Yes" will prevent Zotero from updating this citation if you add additional citations, switch styles, or modify the reference to which it refers. Clicking "No" will erase your changes.
|
||||
integration.citationChanged.description = Clicking "Yes" will prevent Zotero from updating this citation if you add additional citations, switch styles, or modify the item to which it refers. Clicking "No" will erase your changes.
|
||||
integration.citationChanged.edit = You have modified this citation since Zotero generated it. Editing will clear your modifications. Do you want to continue?
|
||||
|
||||
styles.installStyle = Install style "%1$S" from %2$S?
|
||||
|
@ -758,7 +766,7 @@ standalone.addonInstallationFailed.body = The add-on "%S" could not be installe
|
|||
connector.error.title = Zotero Connector Error
|
||||
connector.standaloneOpen = Your database cannot be accessed because Zotero Standalone is currently open. Please view your items in Zotero Standalone.
|
||||
|
||||
firstRunGuidance.saveIcon = Zotero can recognize a reference on this page. Click this icon in the address bar to save the reference to your Zotero library.
|
||||
firstRunGuidance.saveIcon = Zotero has found a reference on this page. Click this icon in the address bar to save the reference to your Zotero library.
|
||||
firstRunGuidance.authorMenu = Zotero lets you specify editors and translators, too. You can turn an author into an editor or translator by selecting from this menu.
|
||||
firstRunGuidance.quickFormat = Type a title or author to search for a reference.\n\nAfter you've made your selection, click the bubble or press Ctrl-\u2193 to add page numbers, prefixes, or suffixes. You can also include a page number along with your search terms to add it directly.\n\nYou can edit citations directly in the word processor document.
|
||||
firstRunGuidance.quickFormatMac = Type a title or author to search for a reference.\n\nAfter you've made your selection, click the bubble or press Cmd-\u2193 to add page numbers, prefixes, or suffixes. You can also include a page number along with your search terms to add it directly.\n\nYou can edit citations directly in the word processor document.
|
|
@ -1 +1 @@
|
|||
Subproject commit 1ba73cb10ad0c77c171a389dd60bad78ea6a007f
|
||||
Subproject commit 7b8cb18ea06006a89cf1afb94bb481cebed3e43c
|
Loading…
Reference in New Issue
Block a user