Merge branch '3.0'

Conflicts:
	chrome/content/zotero/overlay.js
	chrome/content/zotero/xpcom/schema.js
This commit is contained in:
Simon Kornblith 2012-02-28 17:22:34 -05:00
commit b3f9f5102b
28 changed files with 1103 additions and 378 deletions

View File

@ -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();
}
}
}

View File

@ -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';

View File

@ -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;"/>

View File

@ -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"

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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 = [

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 + " "

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
});
}
/**

View File

@ -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

View File

@ -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');
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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 &#xA;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 &#xA;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.">

View File

@ -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