Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/zotero/zotero into jurism…
Browse files Browse the repository at this point in the history
…-5.0-dev
  • Loading branch information
fbennett committed Mar 26, 2018
2 parents 62a3187 + 3445519 commit 79d1cc7
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 62 deletions.
7 changes: 5 additions & 2 deletions COPYING
@@ -1,8 +1,11 @@
Zotero is Copyright © 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
Zotero is Copyright © 2018 Corporation for Digital Scholarship,
Vienna, Virginia, USA http://digitalscholar.org

Copyright © 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
Roy Rosenzweig Center for History and New Media, George Mason University,
Fairfax, Virginia, USA http://zotero.org

The Roy Rosenzweig Center for History and New Media distributes the Zotero source code
The Corporation for Digital Scholarship distributes the Zotero source code
under the GNU Affero General Public License, version 3 (AGPLv3). The full text
of this license is given below.

Expand Down
23 changes: 1 addition & 22 deletions chrome/content/zotero/bindings/relatedbox.xml
Expand Up @@ -152,28 +152,7 @@
let id = relatedItem.id;
let icon = document.createElement("image");
icon.className = "zotero-box-icon";
let type = Zotero.ItemTypes.getName(relatedItem.itemTypeID);
if (type=='attachment')
{
switch (relatedItem.attaachmentLinkMode) {
case Zotero.Attachments.LINK_MODE_LINKED_URL:
type += '-web-link';
break;
case Zotero.Attachments.LINK_MODE_IMPORTED_URL:
type += '-snapshot';
break;
case Zotero.Attachments.LINK_MODE_LINKED_FILE:
type += '-link';
break;
case Zotero.Attachments.LINK_MODE_IMPORTED_FILE:
type += '-file';
break;
}
}
icon.setAttribute('src','chrome://zotero/skin/treeitem-' + type + '.png');
icon.setAttribute('src', relatedItem.getImageSrc());
var label = document.createElement("label");
label.className = "zotero-box-label";
Expand Down
8 changes: 8 additions & 0 deletions chrome/content/zotero/preferences/preferences_search.xul
Expand Up @@ -49,6 +49,14 @@
<textbox size="10" preference="pref-fulltext-textMaxLength"/>
<label value="(&zotero.preferences.default; 500000)"/>
</hbox>

<separator class="thin"/>

<hbox align="center">
<label value="&zotero.preferences.fulltext.pdfMaxPages;"/>
<textbox size="5" preference="pref-fulltext-pdfmaxpages"/>
<label value="(&zotero.preferences.default; 100)"/>
</hbox>
</groupbox>

<groupbox id="fulltext-stats">
Expand Down
72 changes: 50 additions & 22 deletions chrome/content/zotero/xpcom/integration.js
Expand Up @@ -565,7 +565,7 @@ Zotero.Integration.Interface.prototype.editBibliography = Zotero.Promise.corouti
throw new Zotero.Exception.Alert("integration.error.mustInsertBibliography",
[], "integration.error.title");
}
let bibliography = new Zotero.Integration.Bibliography(bibliographyField);
let bibliography = new Zotero.Integration.Bibliography(bibliographyField, bibliographyField.unserialize());
var citationsMode = FORCE_CITATIONS_FALSE;
if(this._session.data.prefs.delayCitationUpdates) {
// Refreshes citeproc state before proceeding
Expand Down Expand Up @@ -604,7 +604,7 @@ Zotero.Integration.Interface.prototype.addEditBibliography = Zotero.Promise.coro
bibliographyField.clearCode();
}

let bibliography = new Zotero.Integration.Bibliography(bibliographyField);
let bibliography = new Zotero.Integration.Bibliography(bibliographyField, bibliographyField.unserialize());
var citationsMode = FORCE_CITATIONS_FALSE;
if(this._session.data.prefs.delayCitationUpdates) {
// Refreshes citeproc state before proceeding
Expand Down Expand Up @@ -893,7 +893,8 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu
let field = Zotero.Integration.Field.loadExisting(this._fields[i]);
if (field.type === INTEGRATION_TYPE_ITEM) {
var noteIndex = field.getNoteIndex(),
citation = new Zotero.Integration.Citation(field, noteIndex);
data = field.unserialize(),
citation = new Zotero.Integration.Citation(field, noteIndex, data);

yield this._session.addCitation(i, noteIndex, citation);
} else if (field.type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
Expand All @@ -905,7 +906,8 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu
}
}
if (this._bibliographyFields.length) {
this._session.bibliography = new Zotero.Integration.Bibliography(this._bibliographyFields[0]);
var data = this._bibliographyFields[0].unserialize()
this._session.bibliography = new Zotero.Integration.Bibliography(this._bibliographyFields[0], data);
yield this._session.bibliography.loadItemData();
} else {
delete this._session.bibliography;
Expand Down Expand Up @@ -1118,20 +1120,21 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
*/
Zotero.Integration.Fields.prototype.addEditCitation = Zotero.Promise.coroutine(function* (field) {
var newField;
var citation;

if (field) {
field = Zotero.Integration.Field.loadExisting(field);

if (field.type != INTEGRATION_TYPE_ITEM) {
throw new Zotero.Exception.Alert("integration.error.notInCitation");
}
citation = new Zotero.Integration.Citation(field, field.getNoteIndex(), field.unserialize());
} else {
newField = true;
field = new Zotero.Integration.CitationField(yield this.addField(true));
field.clearCode();
citation = new Zotero.Integration.Citation(field);
}

var citation = new Zotero.Integration.Citation(field);
yield citation.prepareForEditing();

// -------------------
Expand All @@ -1158,19 +1161,31 @@ Zotero.Integration.Fields.prototype.addEditCitation = Zotero.Promise.coroutine(f
}.bind(this));
}

var previewFn = Zotero.Promise.coroutine(function* (citation) {
let idx = yield fieldIndexPromise;
yield citationsByItemIDPromise;
var previewFn = async function (citation) {
let idx = await fieldIndexPromise;
await citationsByItemIDPromise;
var fields = await this.get();

var [citations, fieldToCitationIdxMapping, citationToFieldIdxMapping] = this._session.getCiteprocLists();
let citationsPre = citations.slice(0, fieldToCitationIdxMapping[idx]);
let citationsPost = citations.slice(fieldToCitationIdxMapping[idx]+1);
var [citations, fieldToCitationIdxMapping, citationToFieldIdxMapping] = this._session.getCiteprocLists(true);
for (var prevIdx = idx-1; prevIdx >= 0; prevIdx--) {
if (prevIdx in fieldToCitationIdxMapping) break;
}
for (var nextIdx = idx+1; nextIdx < fields.length; nextIdx++) {
if (nextIdx in fieldToCitationIdxMapping) break;
}
let citationsPre = citations.slice(0, fieldToCitationIdxMapping[prevIdx]+1);
let citationsPost = citations.slice(fieldToCitationIdxMapping[nextIdx]);
try {
return this._session.style.previewCitationCluster(citation, citationsPre, citationsPost, "rtf");
var result = this._session.style.previewCitationCluster(citation, citationsPre, citationsPost, "rtf");
} catch(e) {
throw e;
} finally {
// CSL.previewCitationCluster() sets citationID, which means that we do not mark it
// as a new citation in Session.addCitation() if the ID is still present
delete citation.citationID;
}
}.bind(this));
return result;
}.bind(this);

var io = new Zotero.Integration.CitationEditInterface(
citation, this._session.style.opt.sort_citations,
Expand Down Expand Up @@ -1571,26 +1586,37 @@ Zotero.Integration.Session.prototype.addCitation = Zotero.Promise.coroutine(func
}

// We need a new ID if there's another citation with the same citation ID in this document
var needNewID = !citation.citationID || this.documentCitationIDs[citation.citationID];
var duplicateIndex = this.documentCitationIDs[citation.citationID];
var needNewID = !citation.citationID || duplicateIndex != undefined;
if(needNewID || this.regenAll) {
if (duplicateIndex != undefined) {
// If this is a duplicate, we need to mark both citations as "new"
// since we do not know which one was the "original" one
// and either one may need to be updated
this.newIndices[duplicateIndex] = true;
}
if(needNewID) {
Zotero.debug("Integration: "+citation.citationID+" ("+index+") needs new citationID");
citation.citationID = Zotero.randomString();
}
this.newIndices[index] = true;
}
Zotero.debug("Integration: Adding citationID "+citation.citationID);
this.documentCitationIDs[citation.citationID] = citation.citationID;
this.documentCitationIDs[citation.citationID] = index;
});

Zotero.Integration.Session.prototype.getCiteprocLists = function() {
Zotero.Integration.Session.prototype.getCiteprocLists = function(excludeNew) {
var citations = [];
var fieldToCitationIdxMapping = [];
var fieldToCitationIdxMapping = {};
var citationToFieldIdxMapping = {};
var i = 0;
// This relies on the order of citationsByIndex keys being stable and sorted in ascending order
// Which it seems to currently be true for every modern JS engine, so we're probably fine
for(let idx in this.citationsByIndex) {
if (excludeNew && this.newIndices[idx]) {
i++;
continue;
}
citations.push([this.citationsByIndex[idx].citationID, this.citationsByIndex[idx].properties.noteIndex]);
fieldToCitationIdxMapping[i] = idx;
citationToFieldIdxMapping[idx] = i++;
Expand Down Expand Up @@ -2360,8 +2386,10 @@ Zotero.Integration.BibliographyField = class extends Zotero.Integration.Field {
};

Zotero.Integration.Citation = class {
constructor(citationField, noteIndex) {
let data = citationField.unserialize();
constructor(citationField, noteIndex, data) {
if (!data) {
data = {citationItems: [], properties: {}};
}
this.citationID = data.citationID;
this.citationItems = data.citationItems;
this.properties = data.properties;
Expand Down Expand Up @@ -2605,9 +2633,9 @@ Zotero.Integration.Citation = class {
};

Zotero.Integration.Bibliography = class {
constructor(bibliographyField) {
constructor(bibliographyField, data) {
this._field = bibliographyField;
this.data = bibliographyField.unserialize();
this.data = data;

this.uncitedItemIDs = new Set();
this.omittedItemIDs = new Set();
Expand Down
6 changes: 5 additions & 1 deletion chrome/content/zotero/xpcom/proxy.js
Expand Up @@ -321,7 +321,11 @@ Zotero.Proxy.prototype.compileRegexp = function() {
})

// now replace with regexp fragment in reverse order
var re = "^"+Zotero.Utilities.quotemeta(this.scheme)+"$";
if (this.scheme.includes('://')) {
re = "^"+Zotero.Utilities.quotemeta(this.scheme)+"$";
} else {
re = "^https?"+Zotero.Utilities.quotemeta('://'+this.scheme)+"$";
}
for(var i=this.parameters.length-1; i>=0; i--) {
var param = this.parameters[i];
re = re.replace(Zotero_Proxy_schemeParameterRegexps[param], "$1"+parametersToCheck[param]);
Expand Down
17 changes: 17 additions & 0 deletions chrome/content/zotero/xpcom/schema.js
Expand Up @@ -2615,6 +2615,23 @@ Zotero.Schema = new function(){
yield Zotero.DB.queryAsync("DELETE FROM relationPredicates WHERE predicate='dc:isReplacedBy'");
}

else if (i == 100) {
let userID = yield Zotero.DB.valueQueryAsync("SELECT value FROM settings WHERE setting='account' AND key='userID'");
let predicateID = yield Zotero.DB.valueQueryAsync("SELECT predicateID FROM relationPredicates WHERE predicate='dc:relation'");
if (userID && predicateID) {
let rows = yield Zotero.DB.queryAsync("SELECT itemID, object FROM items JOIN itemRelations IR USING (itemID) WHERE libraryID=? AND predicateID=?", [1, predicateID]);
for (let row of rows) {
let matches = row.object.match(/^http:\/\/zotero.org\/users\/(\d+)\/items\/([A-Z0-9]+)$/);
if (matches) {
// Wrong libraryID
if (matches[1] != userID) {
yield Zotero.DB.queryAsync(`UPDATE itemRelations SET object='http://zotero.org/users/${userID}/items/${matches[2]}' WHERE itemID=? AND predicateID=?`, [row.itemID, predicateID]);
}
}
}
}
}

// If breaking compatibility or doing anything dangerous, clear minorUpdateFrom
}

Expand Down
1 change: 1 addition & 0 deletions chrome/content/zotero/xpcom/server.js
Expand Up @@ -28,6 +28,7 @@ Zotero.Server = new function() {
this.responseCodes = {
200:"OK",
201:"Created",
204:"No Content",
300:"Multiple Choices",
400:"Bad Request",
404:"Not Found",
Expand Down
11 changes: 11 additions & 0 deletions chrome/content/zotero/xpcom/server_connector.js
Expand Up @@ -799,6 +799,17 @@ Zotero.Server.Connector.UpdateSession.prototype = {
}
};

Zotero.Server.Connector.DelaySync = function () {};
Zotero.Server.Endpoints["/connector/delaySync"] = Zotero.Server.Connector.DelaySync;
Zotero.Server.Connector.DelaySync.prototype = {
supportedMethods: ["POST"],

init: async function (options) {
Zotero.Sync.Runner.delaySync(10000);
return [204];
}
};

/**
* Gets progress for an attachment that is currently being saved
*
Expand Down
25 changes: 24 additions & 1 deletion chrome/content/zotero/xpcom/sync/syncRunner.js
Expand Up @@ -69,6 +69,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {

var _enabled = false;
var _autoSyncTimer;
var _delaySyncUntil;
var _firstInSession = true;
var _syncInProgress = false;
var _stopping = false;
Expand Down Expand Up @@ -139,6 +140,14 @@ Zotero.Sync.Runner_Module = function (options = {}) {

this.updateIcons('animate');

// If a delay is set (e.g., from the connector target selector), wait to sync
while (_delaySyncUntil && new Date() < _delaySyncUntil) {
this.setSyncStatus(Zotero.getString('sync.status.waiting'));
let delay = _delaySyncUntil - new Date();
Zotero.debug(`Waiting ${delay} ms to sync`);
yield Zotero.Promise.delay(delay);
}

// purgeDataObjects() starts a transaction, so if there's an active one then show a
// nice message and wait until there's not. Another transaction could still start
// before purgeDataObjects() and result in a wait timeout, but this should reduce the
Expand Down Expand Up @@ -884,11 +893,20 @@ Zotero.Sync.Runner_Module = function (options = {}) {

// Implements nsITimerCallback
var callback = {
notify: function (timer) {
notify: async function (timer) {
if (!_getAPIKey()) {
return;
}

// If a delay is set (e.g., from the connector target selector), wait to sync.
// We do this in sync() too for manual syncs, but no need to start spinning if
// it's just an auto-sync.
while (_delaySyncUntil && new Date() < _delaySyncUntil) {
let delay = _delaySyncUntil - new Date();
Zotero.debug(`Waiting ${delay} ms to start auto-sync`);
await Zotero.Promise.delay(delay);
}

if (Zotero.locked) {
Zotero.debug('Zotero is locked -- skipping auto-sync', 4);
return;
Expand Down Expand Up @@ -935,6 +953,11 @@ Zotero.Sync.Runner_Module = function (options = {}) {
}


this.delaySync = function (ms) {
_delaySyncUntil = new Date(Date.now() + ms);
};


/**
* Trigger updating of the main sync icon, the sync error icon, and
* library-specific sync error icons across all windows
Expand Down
2 changes: 1 addition & 1 deletion resource/schema/userdata.sql
@@ -1,4 +1,4 @@
-- 99
-- 100

-- Copyright (c) 2009 Center for History and New Media
-- George Mason University, Fairfax, Virginia, USA
Expand Down

0 comments on commit 79d1cc7

Please sign in to comment.