- fix (most) unnecessary citation update issues
- switch Zotero.JSON to native Firefox JSON support - update to citeproc-js 1.0.21 From Frank's announcement: In this release: - Tighten up internal "NUMERIC" update_mode to mean styles that render citation-number in citations (renderings in the bibliography are now ignored for purposes of setting this flag). - The numeric styles fix introduced at version 1.0.17 broke with styles that sort the bibliography on anything other than citation- number (i.e. document first-reference order). With this release, arbitrary sorts of the bibliography work with numeric styles. - Position evaluation code is now invoked only in styles that make use of position testing (to save a few cycles). - Numeric styles now perform targetted citation updates correctly.
This commit is contained in:
parent
e44dcb1bb4
commit
f0f22009c4
|
@ -1432,7 +1432,7 @@ CSL.dateParser = function (txt) {
|
||||||
};
|
};
|
||||||
CSL.Engine = function (sys, style, lang, xmlmode) {
|
CSL.Engine = function (sys, style, lang, xmlmode) {
|
||||||
var attrs, langspec, localexml, locale;
|
var attrs, langspec, localexml, locale;
|
||||||
this.processor_version = "1.0.20";
|
this.processor_version = "1.0.21";
|
||||||
this.csl_version = "1.0";
|
this.csl_version = "1.0";
|
||||||
this.sys = sys;
|
this.sys = sys;
|
||||||
this.sys.xml = new CSL.System.Xml.Parsing();
|
this.sys.xml = new CSL.System.Xml.Parsing();
|
||||||
|
@ -2224,7 +2224,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
||||||
sortedItems.push(newitem);
|
sortedItems.push(newitem);
|
||||||
citation.citationItems[pos].item = Item;
|
citation.citationItems[pos].item = Item;
|
||||||
}
|
}
|
||||||
if (!this[this.tmp.area].opt["citation-number-sort"] && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
|
if (!this.citation.opt["citation-number-sort"] && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
|
||||||
len = sortedItems.length;
|
len = sortedItems.length;
|
||||||
for (pos = 0; pos < len; pos += 1) {
|
for (pos = 0; pos < len; pos += 1) {
|
||||||
sortedItems[pos][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[pos][0], "citation_sort");
|
sortedItems[pos][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[pos][0], "citation_sort");
|
||||||
|
@ -2248,7 +2248,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
||||||
}
|
}
|
||||||
this.registry.citationreg.citationByIndex = citationByIndex;
|
this.registry.citationreg.citationByIndex = citationByIndex;
|
||||||
this.registry.citationreg.citationsByItemId = {};
|
this.registry.citationreg.citationsByItemId = {};
|
||||||
if (this.opt.update_mode === CSL.POSITION || true) {
|
if (this.opt.update_mode === CSL.POSITION) {
|
||||||
textCitations = [];
|
textCitations = [];
|
||||||
noteCitations = [];
|
noteCitations = [];
|
||||||
}
|
}
|
||||||
|
@ -2267,7 +2267,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
||||||
this.registry.citationreg.citationsByItemId[item[1].id].push(citationByIndex[pos]);
|
this.registry.citationreg.citationsByItemId[item[1].id].push(citationByIndex[pos]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.opt.update_mode === CSL.POSITION || true) {
|
if (this.opt.update_mode === CSL.POSITION) {
|
||||||
if (citationByIndex[pos].properties.noteIndex) {
|
if (citationByIndex[pos].properties.noteIndex) {
|
||||||
noteCitations.push(citationByIndex[pos]);
|
noteCitations.push(citationByIndex[pos]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2278,7 +2278,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
||||||
if (!has_bibliography) {
|
if (!has_bibliography) {
|
||||||
this.updateItems(update_items);
|
this.updateItems(update_items);
|
||||||
}
|
}
|
||||||
if (this.opt.update_mode === CSL.POSITION || true) {
|
if (this.opt.update_mode === CSL.POSITION) {
|
||||||
for (pos = 0; pos < 2; pos += 1) {
|
for (pos = 0; pos < 2; pos += 1) {
|
||||||
citations = [textCitations, noteCitations][pos];
|
citations = [textCitations, noteCitations][pos];
|
||||||
first_ref = {};
|
first_ref = {};
|
||||||
|
@ -2385,7 +2385,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this[this.tmp.area].opt["citation-number-sort"] && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
|
if (this.citation.opt["citation-number-sort"] && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
|
||||||
len = sortedItems.length;
|
len = sortedItems.length;
|
||||||
for (pos = 0; pos < len; pos += 1) {
|
for (pos = 0; pos < len; pos += 1) {
|
||||||
sortedItems[pos][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[pos][0], "citation_sort");
|
sortedItems[pos][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[pos][0], "citation_sort");
|
||||||
|
@ -4188,7 +4188,9 @@ CSL.Node.text = {
|
||||||
}
|
}
|
||||||
if ("citation-number" === variable || "year-suffix" === variable || "citation-label" === variable) {
|
if ("citation-number" === variable || "year-suffix" === variable || "citation-label" === variable) {
|
||||||
if (variable === "citation-number") {
|
if (variable === "citation-number") {
|
||||||
|
if (state.build.area === "citation") {
|
||||||
state.opt.update_mode = CSL.NUMERIC;
|
state.opt.update_mode = CSL.NUMERIC;
|
||||||
|
}
|
||||||
if ("citation-number" === state[state.tmp.area].opt.collapse) {
|
if ("citation-number" === state[state.tmp.area].opt.collapse) {
|
||||||
this.range_prefix = "-";
|
this.range_prefix = "-";
|
||||||
}
|
}
|
||||||
|
@ -7032,6 +7034,7 @@ CSL.Registry = function (state) {
|
||||||
this.uncited = [];
|
this.uncited = [];
|
||||||
this.refreshes = {};
|
this.refreshes = {};
|
||||||
this.akeys = {};
|
this.akeys = {};
|
||||||
|
this.oldseq = {};
|
||||||
this.ambigcites = {};
|
this.ambigcites = {};
|
||||||
this.sorter = new CSL.Registry.Comparifier(state, "bibliography_sort");
|
this.sorter = new CSL.Registry.Comparifier(state, "bibliography_sort");
|
||||||
this.modes = CSL.getModes.call(this.state);
|
this.modes = CSL.getModes.call(this.state);
|
||||||
|
@ -7047,6 +7050,7 @@ CSL.Registry = function (state) {
|
||||||
};
|
};
|
||||||
CSL.Registry.prototype.init = function (myitems, uncited_flag) {
|
CSL.Registry.prototype.init = function (myitems, uncited_flag) {
|
||||||
var len, pos;
|
var len, pos;
|
||||||
|
this.oldseq = {};
|
||||||
if (uncited_flag && this.mylist && this.mylist.length) {
|
if (uncited_flag && this.mylist && this.mylist.length) {
|
||||||
this.uncited = myitems;
|
this.uncited = myitems;
|
||||||
for (pos = 0, len = myitems.length; pos < len; pos += 1) {
|
for (pos = 0, len = myitems.length; pos < len; pos += 1) {
|
||||||
|
@ -7139,6 +7143,7 @@ CSL.Registry.prototype.rebuildlist = function () {
|
||||||
for (pos = 0; pos < len; pos += 1) {
|
for (pos = 0; pos < len; pos += 1) {
|
||||||
item = this.mylist[pos];
|
item = this.mylist[pos];
|
||||||
this.reflist.push(this.registry[item]);
|
this.reflist.push(this.registry[item]);
|
||||||
|
this.oldseq[item] = this.registry[item].seq;
|
||||||
this.registry[item].seq = (pos + 1);
|
this.registry[item].seq = (pos + 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7200,10 +7205,10 @@ CSL.Registry.prototype.renumber = function () {
|
||||||
len = this.reflist.length;
|
len = this.reflist.length;
|
||||||
for (pos = 0; pos < len; pos += 1) {
|
for (pos = 0; pos < len; pos += 1) {
|
||||||
item = this.reflist[pos];
|
item = this.reflist[pos];
|
||||||
if (this.state.opt.update_mode === CSL.NUMERIC && this.state.tmp.taintedItemIDs && item.seq !== (pos + 1)) {
|
item.seq = (pos + 1);
|
||||||
|
if (this.state.opt.update_mode === CSL.NUMERIC && this.state.tmp.taintedItemIDs && item.seq !== this.oldseq[item.id]) {
|
||||||
this.state.tmp.taintedItemIDs[item.id] = true;
|
this.state.tmp.taintedItemIDs[item.id] = true;
|
||||||
}
|
}
|
||||||
item.seq = (pos + 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CSL.Registry.prototype.yearsuffix = function () {
|
CSL.Registry.prototype.yearsuffix = function () {
|
||||||
|
|
|
@ -558,12 +558,6 @@ Zotero.Integration.Document.prototype._updateSession = function(newField, editFi
|
||||||
var endTime = (new Date()).getTime();
|
var endTime = (new Date()).getTime();
|
||||||
Zotero.debug("Collected "+this._fields.length+" fields in "+(endTime-collectFieldsTime)/1000+"; "+1000/((endTime-collectFieldsTime)/this._fields.length)+" fields/second");
|
Zotero.debug("Collected "+this._fields.length+" fields in "+(endTime-collectFieldsTime)/1000+"; "+1000/((endTime-collectFieldsTime)/this._fields.length)+" fields/second");
|
||||||
|
|
||||||
// if we are reloading this session, assume no item IDs to be updated except for edited items
|
|
||||||
if(this._reloadSession) {
|
|
||||||
this._session.updateItemIDs = {};
|
|
||||||
this._session.bibliographyHasChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load uncited items from bibliography
|
// load uncited items from bibliography
|
||||||
if(bibliographyData && !this._session.bibliographyData) {
|
if(bibliographyData && !this._session.bibliographyData) {
|
||||||
try {
|
try {
|
||||||
|
@ -588,7 +582,13 @@ Zotero.Integration.Document.prototype._updateSession = function(newField, editFi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._session.updateCitations(true);
|
// if we are reloading this session, assume no item IDs to be updated except for edited items
|
||||||
|
if(this._reloadSession) {
|
||||||
|
this._session.updateCitations();
|
||||||
|
this._session.updateIndices = {};
|
||||||
|
this._session.updateItemIDs = {};
|
||||||
|
this._session.bibliographyHasChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
// create new citation or edit existing citation
|
// create new citation or edit existing citation
|
||||||
if(editFieldIndex) {
|
if(editFieldIndex) {
|
||||||
|
@ -886,7 +886,6 @@ Zotero.Integration.Session.prototype.setData = function(data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
if(data.style.styleID && oldStyleID != data.style.styleID) {
|
if(data.style.styleID && oldStyleID != data.style.styleID) {
|
||||||
this.styleID = data.style.styleID;
|
this.styleID = data.style.styleID;
|
||||||
Zotero.debug("style is "+data.style.styleID);
|
|
||||||
try {
|
try {
|
||||||
var getStyle = Zotero.Styles.get(data.style.styleID);
|
var getStyle = Zotero.Styles.get(data.style.styleID);
|
||||||
data.style.hasBibliography = getStyle.hasBibliography;
|
data.style.hasBibliography = getStyle.hasBibliography;
|
||||||
|
@ -990,12 +989,15 @@ Zotero.Integration.Session.prototype.getCitationField = function(citation) {
|
||||||
var type;
|
var type;
|
||||||
var field = [];
|
var field = [];
|
||||||
|
|
||||||
field.push('"citationID":'+Zotero.JSON.serialize(citation.citationID));
|
field.push('"citationID":'+uneval(citation.citationID));
|
||||||
var properties = [];
|
var properties = [];
|
||||||
for(var j=0; j<Zotero.Integration.Session._saveProperties.length; j++) {
|
for(var j=0; j<Zotero.Integration.Session._saveProperties.length; j++) {
|
||||||
var property = Zotero.Integration.Session._saveProperties[j];
|
var property = Zotero.Integration.Session._saveProperties[j];
|
||||||
if(citation.properties[property] || citation.properties[property] === false) {
|
if(citation.properties[property] || citation.properties[property] === false) {
|
||||||
properties.push('"'+property+'":'+Zotero.JSON.serialize(citation.properties[property]));
|
let propval = typeof citation.properties[property] == "object" ?
|
||||||
|
Zotero.JSON.serialize(citation.properties[property]) :
|
||||||
|
uneval(citation.properties[property]);
|
||||||
|
properties.push('"'+property+'":'+propval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(properties.length) field.push('"properties":{'+properties.join(",")+"}");
|
if(properties.length) field.push('"properties":{'+properties.join(",")+"}");
|
||||||
|
@ -1009,7 +1011,10 @@ Zotero.Integration.Session.prototype.getCitationField = function(citation) {
|
||||||
type = typeof(citation.citationItems[j][k]);
|
type = typeof(citation.citationItems[j][k]);
|
||||||
if(citation.citationItems[j][k] && Zotero.Integration.Session._saveItems.indexOf(k) !== -1
|
if(citation.citationItems[j][k] && Zotero.Integration.Session._saveItems.indexOf(k) !== -1
|
||||||
&& Zotero.Integration.Session._acceptableTypes.indexOf(type) !== -1) {
|
&& Zotero.Integration.Session._acceptableTypes.indexOf(type) !== -1) {
|
||||||
citationItem.push('"'+k+'":'+Zotero.JSON.serialize(citation.citationItems[j][k]));
|
let propval = typeof citation.citationItems[j][k] == "object" ?
|
||||||
|
Zotero.JSON.serialize(citation.citationItems[j][k]) :
|
||||||
|
uneval(citation.citationItems[j][k]);
|
||||||
|
citationItem.push('"'+k+'":'+propval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,13 +1130,16 @@ Zotero.Integration.Session.prototype.addCitation = function(index, noteIndex, ar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!citation.citationID) {
|
var needNewID = !citation.citationID || this.citationIDs[citation.citationID];
|
||||||
this.newIndices[index] = true;
|
if(needNewID || !this.oldCitationIDs[citation.citationID]) {
|
||||||
this.updateIndices[index] = true;
|
if(needNewID) {
|
||||||
} else if(!this.oldCitationIDs[citation.citationID]) {
|
Zotero.debug("Zotero.Integration: "+citation.citationID+" ("+index+") needs new citationID");
|
||||||
|
citation.citationID = Zotero.randomString();
|
||||||
|
}
|
||||||
this.newIndices[index] = true;
|
this.newIndices[index] = true;
|
||||||
this.updateIndices[index] = true;
|
this.updateIndices[index] = true;
|
||||||
}
|
}
|
||||||
|
Zotero.debug("Zotero.Integration: adding citationID "+citation.citationID);
|
||||||
this.citationIDs[citation.citationID] = true;
|
this.citationIDs[citation.citationID] = true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1251,9 +1259,9 @@ Zotero.Integration.Session.prototype.deleteCitation = function(index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(oldCitation.citationID) delete this.citationIDs[oldCitation.citationID];
|
|
||||||
}
|
}
|
||||||
|
Zotero.debug("Zotero.Integration: deleting old citationID "+oldCitation.citationID);
|
||||||
|
if(oldCitation.citationID) delete this.citationIDs[oldCitation.citationID];
|
||||||
|
|
||||||
this.updateIndices[index] = true;
|
this.updateIndices[index] = true;
|
||||||
}
|
}
|
||||||
|
@ -1319,7 +1327,9 @@ Zotero.Integration.Session.prototype.formatCitation = function(index, citation)
|
||||||
//Zotero.debug("style.processCitationCluster("+citation.toSource()+", "+citationsPre.toSource()+", "+citationsPost.toSource());
|
//Zotero.debug("style.processCitationCluster("+citation.toSource()+", "+citationsPre.toSource()+", "+citationsPost.toSource());
|
||||||
var newCitations = this.style.processCitationCluster(citation, citationsPre, citationsPost);
|
var newCitations = this.style.processCitationCluster(citation, citationsPre, citationsPost);
|
||||||
for each(var newCitation in newCitations) {
|
for each(var newCitation in newCitations) {
|
||||||
|
Zotero.debug("Zotero.Integration: Citation "+citationIndices[newCitation[0]]+" needs to be updated");
|
||||||
this.citationText[citationIndices[newCitation[0]]] = newCitation[1];
|
this.citationText[citationIndices[newCitation[0]]] = newCitation[1];
|
||||||
|
this.updateIndices[citationIndices[newCitation[0]]] = true;
|
||||||
}
|
}
|
||||||
// this is a heuristic: if other citations get updated, then we should update the
|
// this is a heuristic: if other citations get updated, then we should update the
|
||||||
// bibliography. it would be nice if citeproc-js gave us a better hint about this
|
// bibliography. it would be nice if citeproc-js gave us a better hint about this
|
||||||
|
@ -1330,8 +1340,8 @@ Zotero.Integration.Session.prototype.formatCitation = function(index, citation)
|
||||||
/**
|
/**
|
||||||
* Updates the list of citations to be serialized to the document
|
* Updates the list of citations to be serialized to the document
|
||||||
*/
|
*/
|
||||||
Zotero.Integration.Session.prototype.updateCitations = function(force) {
|
Zotero.Integration.Session.prototype.updateCitations = function() {
|
||||||
var allUpdatesForced = false;
|
/*var allUpdatesForced = false;
|
||||||
var forcedUpdates = {};
|
var forcedUpdates = {};
|
||||||
if(force) {
|
if(force) {
|
||||||
allUpdatesForced = true;
|
allUpdatesForced = true;
|
||||||
|
@ -1353,23 +1363,21 @@ Zotero.Integration.Session.prototype.updateCitations = function(force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Zotero.debug("Zotero.Integration: indices of new citations");
|
Zotero.debug("Zotero.Integration: indices of new citations");
|
||||||
Zotero.debug([key for(key in this.newIndices)]);
|
Zotero.debug([key for(key in this.newIndices)]);
|
||||||
Zotero.debug("Zotero.Integration: indices of updated citations");
|
Zotero.debug("Zotero.Integration: indices of updated citations");
|
||||||
Zotero.debug([key for(key in this.updateIndices)]);
|
Zotero.debug([key for(key in this.updateIndices)]);
|
||||||
Zotero.debug("Zotero.Integration: indices of forcedUpdates");
|
|
||||||
Zotero.debug([key for(key in forcedUpdates)]);
|
|
||||||
|
|
||||||
var deleteCitations = [];
|
var deleteCitations = [];
|
||||||
for each(var indexList in [this.newIndices, this.updateIndices, forcedUpdates]) {
|
for each(var indexList in [this.newIndices, this.updateIndices]) {
|
||||||
for(var index in indexList) {
|
for(var index in indexList) {
|
||||||
index = parseInt(index);
|
index = parseInt(index);
|
||||||
|
|
||||||
var citation = this.citationsByIndex[index];
|
var citation = this.citationsByIndex[index];
|
||||||
if(citation.properties.delete) {
|
if(citation.properties.delete) {
|
||||||
deleteCitations.push(index);
|
if(deleteCitations.indexOf(index) == -1) deleteCitations.push(index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(this.formatCitation(index, citation)) {
|
if(this.formatCitation(index, citation)) {
|
||||||
|
@ -1382,10 +1390,10 @@ Zotero.Integration.Session.prototype.updateCitations = function(force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allUpdatesForced) {
|
/*if(allUpdatesForced) {
|
||||||
this.newIndices = {};
|
this.newIndices = {};
|
||||||
this.updateIndices = {};
|
this.updateIndices = {};
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return deleteCitations;
|
return deleteCitations;
|
||||||
}
|
}
|
||||||
|
@ -1489,18 +1497,20 @@ Zotero.Integration.Session.prototype.getBibliographyData = function() {
|
||||||
* and position)
|
* and position)
|
||||||
*/
|
*/
|
||||||
Zotero.Integration.Session.prototype.previewCitation = function(citation) {
|
Zotero.Integration.Session.prototype.previewCitation = function(citation) {
|
||||||
|
// remove cached citation text
|
||||||
|
this.citationText = {};
|
||||||
|
this.addCitation(citation.properties.index, citation.properties.noteIndex, citation);
|
||||||
|
|
||||||
// add citation items
|
// add citation items
|
||||||
try {
|
try {
|
||||||
this.addCitation(citation.properties.index, citation.properties.noteIndex, citation);
|
|
||||||
this.formatCitation(citation.properties.index, citation);
|
this.formatCitation(citation.properties.index, citation);
|
||||||
this.deleteCitation(citation.properties.index);
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.debug(e);
|
Zotero.debug(e);
|
||||||
|
this.deleteCitation(citation.properties.index);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
this.deleteCitation(citation.properties.index);
|
||||||
|
|
||||||
// we don't delete the citationText only because the add citation dialog always calls
|
|
||||||
// previewCitation before returning
|
|
||||||
return this.citationText[citation.properties.index];
|
return this.citationText[citation.properties.index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1543,10 +1553,6 @@ Zotero.Integration.Session.prototype.editCitation = function(index, noteIndex, c
|
||||||
'chrome,centerscreen,resizable', io);
|
'chrome,centerscreen,resizable', io);
|
||||||
while(!window.closed) Zotero.mainThread.processNextEvent(true);
|
while(!window.closed) Zotero.mainThread.processNextEvent(true);
|
||||||
|
|
||||||
if(citation && !io.citation.citationItems.length) {
|
|
||||||
io.citation = citation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(io.citation.citationItems.length) { // we have an item
|
if(io.citation.citationItems.length) { // we have an item
|
||||||
this.addCitation(index, noteIndex, io.citation);
|
this.addCitation(index, noteIndex, io.citation);
|
||||||
this.updateIndices[index] = true;
|
this.updateIndices[index] = true;
|
||||||
|
@ -1625,7 +1631,7 @@ Zotero.Integration.Session.BibliographyEditInterface.prototype.remove = function
|
||||||
citation.properties["delete"] = true;
|
citation.properties["delete"] = true;
|
||||||
}
|
}
|
||||||
delete this.session.citationsByItemID[itemID];
|
delete this.session.citationsByItemID[itemID];
|
||||||
this.session.updateCitations(true);
|
this.session.updateCitations();
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete uncited if neceessary
|
// delete uncited if neceessary
|
||||||
|
|
|
@ -2552,144 +2552,16 @@ Zotero.WebProgressFinishListener = function(onFinish) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Saves or loads JSON objects. Based on public domain code from
|
* Saves or loads JSON objects.
|
||||||
* http://www.json.org/json.js
|
|
||||||
*/
|
*/
|
||||||
Zotero.JSON = new function() {
|
Zotero.JSON = new function() {
|
||||||
this.serialize = serialize;
|
var nativeJSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);
|
||||||
this.unserialize = unserialize;
|
|
||||||
|
|
||||||
// m is a table of character substitutions.
|
this.serialize = function(arg) {
|
||||||
var m = {
|
return nativeJSON.encode(arg);
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
function f(n) {
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceFunction(a) {
|
this.unserialize = function(arg) {
|
||||||
var c = m[a];
|
return nativeJSON.decode(arg);
|
||||||
if (c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
c = a.charCodeAt();
|
|
||||||
return '\\u00' +
|
|
||||||
Math.floor(c / 16).toString(16) +
|
|
||||||
(c % 16).toString(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
function serialize(arg) {
|
|
||||||
if(arg === null) {
|
|
||||||
return "null";
|
|
||||||
} else if(arg instanceof Array) {
|
|
||||||
var a = [], // The array holding the partial texts.
|
|
||||||
i, // Loop counter.
|
|
||||||
l = arg.length,
|
|
||||||
v; // The value to be stringified.
|
|
||||||
|
|
||||||
|
|
||||||
// For each value in arg array...
|
|
||||||
|
|
||||||
for (i = 0; i < l; i += 1) {
|
|
||||||
var out = serialize(arg[i]);
|
|
||||||
if(out !== undefined) {
|
|
||||||
a.push(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together and wrap them in brackets.
|
|
||||||
|
|
||||||
return '[' + a.join(',') + ']';
|
|
||||||
} else if(typeof(arg) == "boolean") {
|
|
||||||
return String(arg);
|
|
||||||
} else if(arg instanceof Date) {
|
|
||||||
// Eventually, this method will be based on the date.toISOString method.
|
|
||||||
|
|
||||||
return '"' + arg.getUTCFullYear() + '-' +
|
|
||||||
f(arg.getUTCMonth() + 1) + '-' +
|
|
||||||
f(arg.getUTCDate()) + 'T' +
|
|
||||||
f(arg.getUTCHours()) + ':' +
|
|
||||||
f(arg.getUTCMinutes()) + ':' +
|
|
||||||
f(arg.getUTCSeconds()) + 'Z"';
|
|
||||||
} else if(typeof(arg) == "number") {
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(arg) ? String(arg) : 'null';
|
|
||||||
} else if(typeof(arg) == "string") {
|
|
||||||
if (/["\\\x00-\x1f]/.test(arg)) {
|
|
||||||
return '"' + arg.replace(/[\x00-\x1f\\"]/g, replaceFunction) + '"';
|
|
||||||
}
|
|
||||||
return '"' + arg + '"';
|
|
||||||
} else if(arg instanceof Object) {
|
|
||||||
var a = [], // The array holding the partial texts.
|
|
||||||
k, // The current key.
|
|
||||||
v; // The current value.
|
|
||||||
|
|
||||||
// Iterate through all of the keys in the object, ignoring the proto chain
|
|
||||||
// and keys that are not strings.
|
|
||||||
|
|
||||||
for (k in arg) {
|
|
||||||
if (typeof k === 'string' &&
|
|
||||||
Object.prototype.hasOwnProperty.apply(arg, [k])) {
|
|
||||||
var out = serialize(arg[k]);
|
|
||||||
if(out !== undefined) {
|
|
||||||
a.push(serialize(k) + ':' + out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together and wrap them in braces.
|
|
||||||
|
|
||||||
return '{' + a.join(',') + '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function unserialize(arg) {
|
|
||||||
var j;
|
|
||||||
|
|
||||||
// Parsing happens in three stages. In the first stage, we run the text against
|
|
||||||
// a regular expression which looks for non-JSON characters. We are especially
|
|
||||||
// concerned with '()' and 'new' because they can cause invocation, and '='
|
|
||||||
// because it can cause mutation. But just to be safe, we will reject all
|
|
||||||
// unexpected characters.
|
|
||||||
|
|
||||||
// We split the first stage into 3 regexp operations in order to work around
|
|
||||||
// crippling deficiencies in Safari's regexp engine. First we replace all
|
|
||||||
// backslash pairs with '@' (a non-JSON character). Second we delete all of
|
|
||||||
// the string literals. Third, we look to see if only JSON characters
|
|
||||||
// remain. If so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(arg.
|
|
||||||
replace(/\\./g, '@').
|
|
||||||
replace(/"[^"\\\n\r]*"/g, ''))) {
|
|
||||||
|
|
||||||
// In the second stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
// Friendly AMO reviewer: This is the official json.org library and is safe.
|
|
||||||
j = eval('(' + arg + ')');
|
|
||||||
|
|
||||||
// In the optional third stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a filter function for possible transformation.
|
|
||||||
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('parseJSON');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user