From 7cf0ff2683d16e080c2ed716d539b311518f5677 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sun, 24 Apr 2016 06:50:45 -0400 Subject: [PATCH 1/6] Update citeproc-js to 1.1.100 --- chrome/content/zotero/xpcom/citeproc.js | 110 ++++++++++++++---------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 451d9e745..34eab5a23 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -34,7 +34,7 @@ if (!Array.indexOf) { }; } var CSL = { - PROCESSOR_VERSION: "1.1.99", + PROCESSOR_VERSION: "1.1.100", CONDITION_LEVEL_TOP: 1, CONDITION_LEVEL_BOTTOM: 2, PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/, @@ -372,7 +372,8 @@ var CSL = { "number-of-pages", "number-of-volumes", "volume", - "citation-number" + "citation-number", + "year-suffix" ], DATE_VARIABLES: [ "locator-date", @@ -1962,6 +1963,9 @@ CSL.XmlToToken = function (state, tokentype, explicitTarget) { token.decorations = decorations; } else if (tokentype === CSL.END && attributes['@variable']) { token.hasVariable = true; + if (CSL.DATE_VARIABLES.indexOf(attributes['@variable']) > -1) { + token.variables = attributes['@variable'].split(/\s+/); + } } if (explicitTarget) { target = explicitTarget; @@ -6366,7 +6370,6 @@ CSL.Node.date = { if (this.variables.length && !(state.tmp.just_looking && this.variables[0] === "accessed")) { - state.parallel.StartVariable(this.variables[0]); date_obj = Item[this.variables[0]]; if ("undefined" === typeof date_obj) { date_obj = {"date-parts": [[0]] }; @@ -6414,6 +6417,8 @@ CSL.Node.date = { } this.execs.push(func); func = function (state, Item) { + if (!Item[this.variables[0]]) return; + state.parallel.StartVariable(this.variables[0]); state.output.startTag("date", this); if (this.variables[0] === "issued" && Item.type === "legal_case" @@ -6437,8 +6442,9 @@ CSL.Node.date = { } if (!state.build.extension && (this.tokentype === CSL.END || this.tokentype === CSL.SINGLETON)) { func = function (state, Item) { + if (!Item[this.variables[0]]) return; state.output.endTag(); - state.parallel.CloseVariable("date"); + state.parallel.CloseVariable(this.variables[0]); }; this.execs.push(func); } @@ -8911,11 +8917,17 @@ CSL.NameOutput.prototype._renderOnePersonalName = function (value, pos, i, j) { } if (!this.state.tmp.term_predecessor) { } + var space = " "; + if (this.name.strings["initialize-with"] + && this.name.strings["initialize-with"].match(/[\u00a0\ufeff]/) + && ["fr", "ru"].indexOf(this.state.opt["default-locale"][0].slice(0, 2)) > -1) { + space = "\u00a0" + } if (has_hyphenated_non_dropping_particle) { second = this._join([non_dropping_particle, family], ""); - second = this._join([dropping_particle, second], " "); + second = this._join([dropping_particle, second], space); } else { - second = this._join([dropping_particle, non_dropping_particle, family], " "); + second = this._join([dropping_particle, non_dropping_particle, family], space); } second = this._join([second, suffix], suffix_sep); if (second && this.family) { @@ -8929,7 +8941,7 @@ CSL.NameOutput.prototype._renderOnePersonalName = function (value, pos, i, j) { if (second.strings.prefix) { name["comma-dropping-particle"] = ""; } - blob = this._join([given, second], (name["comma-dropping-particle"] + " ")); + blob = this._join([given, second], (name["comma-dropping-particle"] + space)); } this.state.tmp.group_context.tip.variable_success = true; this.state.tmp.can_substitute.replace(false, CSL.LITERAL); @@ -9937,7 +9949,7 @@ CSL.Node.text = { if (this.strings.plural) { plural = this.strings.plural; } - if ("citation-number" === this.variables_real[0] || "year-suffix" === this.variables_real[0] || "citation-label" === this.variables_real[0]) { + if ("citation-number" === this.variables_real[0] || "citation-label" === this.variables_real[0]) { if (this.variables_real[0] === "citation-number") { if (state.build.root === "citation") { state.opt.update_mode = CSL.NUMERIC; @@ -9982,40 +9994,9 @@ CSL.Node.text = { } }; this.execs.push(func); - } else if (this.variables_real[0] === "year-suffix") { - state.opt.has_year_suffix = true; - if (state[state.tmp.area].opt.collapse === "year-suffix-ranged") { - this.range_prefix = state.getTerm("citation-range-delimiter"); - } - this.successor_prefix = state[state.build.area].opt.layout_delimiter; - if (state[state.tmp.area].opt["year-suffix-delimiter"]) { - this.successor_prefix = state[state.build.area].opt["year-suffix-delimiter"]; - } - func = function (state, Item) { - if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.just_looking) { - num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10); - number = new CSL.NumericBlob(false, num, this, Item.id); - formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS); - number.setFormatter(formatter); - state.output.append(number, "literal"); - firstoutput = false; - for (var i=0,ilen=state.tmp.group_context.mystack.length; i -1) { + } else if (["page", "page-first", "chapter-number", "collection-number", "edition", "issue", "number", "number-of-pages", "number-of-volumes", "volume", "year-suffix"].indexOf(this.variables_real[0]) > -1) { + if (this.variables_real[0] === "year-suffix") { + state.opt.has_year_suffix = true; + if (state[state.tmp.area].opt.collapse === "year-suffix-ranged") { + this.range_prefix = state.getTerm("citation-range-delimiter"); + } + this.successor_prefix = state[state.build.area].opt.layout_delimiter; + if (state[state.tmp.area].opt["year-suffix-delimiter"]) { + this.successor_prefix = state[state.build.area].opt["year-suffix-delimiter"]; + } + } func = function(state, Item) { state.processNumber(this, Item, this.variables[0], Item.type); CSL.Util.outputNumericField(state, this.variables[0], Item.id); @@ -12556,6 +12547,7 @@ CSL.Util.Names.initializeWith = function (state, name, terminator, normalizeOnly }; CSL.Util.Names.doNormalize = function (state, namelist, terminator, mode) { var i, ilen; + terminator = terminator ? terminator : ""; var isAbbrev = []; for (i = 0, ilen = namelist.length; i < ilen; i += 1) { if (namelist[i].length > 1 && namelist[i].slice(-1) === ".") { @@ -12577,14 +12569,18 @@ CSL.Util.Names.doNormalize = function (state, namelist, terminator, mode) { && (namelist[i].length > 1 || namelist[i + 2].length > 1)) { namelist[i + 1] = " "; } - namelist[i] = namelist[i] + terminator; + if (namelist[i + 2].length > 1) { + namelist[i] = namelist[i] + terminator.replace(/[\u0009\u000a\u000b\u000c\u000d\u0020\ufeff\u00a0]+$/, ""); + } else { + namelist[i] = namelist[i] + terminator; + } } if (i === namelist.length - 1) { namelist[i] = namelist[i] + terminator; } } } - return namelist.join("").replace(/\s+$/,""); + return namelist.join("").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020\ufeff\u00a0]+$/,"").replace(/\s*\-\s*/g, "-").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020]+/g, " "); }; CSL.Util.Names.doInitialize = function (state, namelist, terminator, mode) { var i, ilen, m, j, jlen, lst, n; @@ -12637,7 +12633,7 @@ CSL.Util.Names.doInitialize = function (state, namelist, terminator, mode) { } } var ret = namelist.join(""); - ret = ret.replace(/\s+$/,"").replace(/\s*\-\s*/g, "-").replace(/\s+/g, " "); + ret = ret.replace(/[\u0009\u000a\u000b\u000c\u000d\u0020\ufeff\u00a0]+$/,"").replace(/\s*\-\s*/g, "-").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020]+/g, " "); return ret; }; CSL.Util.Names.getRawName = function (name) { @@ -13435,6 +13431,8 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable, type) function setStyling(values) { var masterNode = CSL.Util.cloneToken(node); var masterStyling = new CSL.Token(); + masterStyling.range_prefix = node.range_prefix; + masterStyling.successor_prefix = node.successor_prefix; if (!me.tmp.just_looking) { for (var j=masterNode.decorations.length-1;j>-1;j--) { if (masterNode.decorations[j][0] === "@quotes") { @@ -13599,6 +13597,12 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable, type) var localeType = this.opt["cite-lang-prefs"][languageRole][0]; val = this.transform.getTextSubField(ItemObject, variable, "locale-"+localeType, true); val = val.name; + } else if (variable === "year-suffix" && this.registry.registry[ItemObject.id]) { + this.opt.has_year_suffix = true; + val = parseInt(this.registry.registry[ItemObject.id].disambig.year_suffix, 10); + if (!val && val !== 0) { + val = ""; + } } else { val = ItemObject[variable]; } @@ -13634,6 +13638,7 @@ CSL.Util.outputNumericField = function(state, varname, itemID) { state.output.openLevel(state.tmp.shadow_numbers[varname].masterStyling); var nums = state.tmp.shadow_numbers[varname].values; var masterLabel = nums.length ? nums[0].label : null; + var masterStyling = state.tmp.shadow_numbers[varname].masterStyling; var labelForm = state.tmp.shadow_numbers[varname].labelForm; var embeddedLabelForm; if (labelForm) { @@ -13677,7 +13682,24 @@ CSL.Util.outputNumericField = function(state, varname, itemID) { } } if (num.collapsible) { + if (varname === "year-suffix") { + numStyling.range_prefix = masterStyling.range_prefix; + numStyling.successor_prefix = masterStyling.successor_prefix; + } var blob = new CSL.NumericBlob(num.particle, parseInt(num.value, 10), numStyling, itemID); + if (varname === "year-suffix") { + state.tmp.has_done_year_suffix = true; + var formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS); + blob.setFormatter(formatter); + if (state[state.tmp.area].opt.cite_group_delimiter) { + blob.successor_prefix = state[state.tmp.area].opt.cite_group_delimiter; + } else if (state[state.tmp.area].opt["year-suffix-delimiter"]) { + blob.successor_prefix = state[state.tmp.area].opt["year-suffix-delimiter"]; + } else { + blob.successor_prefix = state[state.tmp.area].opt.layout_delimiter; + } + blob.UGLY_DELIMITER_SUPPRESS_HACK = true; + } if ("undefined" === typeof blob.gender) { blob.gender = state.locale[state.opt.lang]["noun-genders"][varname]; } From bee32d1a51a8c6fc4aefdc0dc5b602777f67f2c6 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sun, 24 Apr 2016 19:58:44 -0400 Subject: [PATCH 2/6] Remove merged items from duplicates view without regenerating list --- chrome/content/zotero/xpcom/data/items.js | 3 + chrome/content/zotero/xpcom/duplicates.js | 2 + chrome/content/zotero/xpcom/itemTreeView.js | 86 +++++++++------------ 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/chrome/content/zotero/xpcom/data/items.js b/chrome/content/zotero/xpcom/data/items.js index abc500e8a..62ed5905c 100644 --- a/chrome/content/zotero/xpcom/data/items.js +++ b/chrome/content/zotero/xpcom/data/items.js @@ -460,6 +460,9 @@ Zotero.Items = new function() { item.save(); + // Hack to remove master item from duplicates view without recalculating duplicates + Zotero.Notifier.trigger('removeDuplicatesMaster', 'item', item.id); + Zotero.DB.commitTransaction(); } diff --git a/chrome/content/zotero/xpcom/duplicates.js b/chrome/content/zotero/xpcom/duplicates.js index 6a990a63a..13c67ba94 100644 --- a/chrome/content/zotero/xpcom/duplicates.js +++ b/chrome/content/zotero/xpcom/duplicates.js @@ -101,6 +101,8 @@ Zotero.Duplicates.prototype._getObjectFromID = function (id) { Zotero.Duplicates.prototype._findDuplicates = function () { + Zotero.debug("Finding duplicates"); + var start = Date.now(); var self = this; diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js index 08d67df30..5952df6f7 100644 --- a/chrome/content/zotero/xpcom/itemTreeView.js +++ b/chrome/content/zotero/xpcom/itemTreeView.js @@ -551,58 +551,48 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData) this._treebox.beginUpdateBatch(); if ((action == 'remove' && !itemGroup.isLibrary(true)) - || action == 'delete' || action == 'trash') { - - // On a delete in duplicates mode, just refresh rather than figuring - // out what to remove - if (itemGroup.isDuplicates()) { - previousRow = this._itemRowMap[ids[0]]; - this.refresh(); - madeChanges = true; - sort = true; + || action == 'delete' || action == 'trash' + || (action == 'removeDuplicatesMaster' && itemGroup.isDuplicates())) { + // Since a remove involves shifting of rows, we have to do it in order, + // so sort the ids by row + var rows = []; + for (var i=0, len=ids.length; i 0) { + rows.push(row); + } + } + } } - else { - // Since a remove involves shifting of rows, we have to do it in order, - // so sort the ids by row - var rows = []; - for (var i=0, len=ids.length; i 0) { - rows.push(row); - } - } + + if (rows.length > 0) { + rows.sort(function(a,b) { return a-b }); + + for(var i=0, len=rows.length; i 0) { - rows.sort(function(a,b) { return a-b }); - - for(var i=0, len=rows.length; i Date: Sun, 24 Apr 2016 20:06:22 -0400 Subject: [PATCH 3/6] Update citeproc-js to 1.1.101 --- chrome/content/zotero/xpcom/citeproc.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 34eab5a23..a3b0f2e67 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -34,7 +34,7 @@ if (!Array.indexOf) { }; } var CSL = { - PROCESSOR_VERSION: "1.1.100", + PROCESSOR_VERSION: "1.1.101", CONDITION_LEVEL_TOP: 1, CONDITION_LEVEL_BOTTOM: 2, PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/, @@ -6646,7 +6646,7 @@ CSL.Node["date-part"] = { } } state.tmp.value = []; - if ((value || state.tmp.have_collapsed) && !state.opt.has_year_suffix && "year" === this.strings.name && !state.tmp.just_looking) { + if (Item[date_variable] && (value || state.tmp.have_collapsed) && !state.opt.has_year_suffix && "year" === this.strings.name && !state.tmp.just_looking) { if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.has_done_year_suffix) { state.tmp.has_done_year_suffix = true; num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10); @@ -13698,7 +13698,6 @@ CSL.Util.outputNumericField = function(state, varname, itemID) { } else { blob.successor_prefix = state[state.tmp.area].opt.layout_delimiter; } - blob.UGLY_DELIMITER_SUPPRESS_HACK = true; } if ("undefined" === typeof blob.gender) { blob.gender = state.locale[state.opt.lang]["noun-genders"][varname]; From adec007df06b83b537563debde054a0eb4d30587 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Fri, 29 Apr 2016 00:38:19 -0400 Subject: [PATCH 4/6] Try disabling gzip compression of uploads, in case it fixes sync error Just to see if it fixes the "Error connecting to server" errors some people are seeing after upgrading to Firefox 46. --- chrome/content/zotero/xpcom/sync.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/sync.js b/chrome/content/zotero/xpcom/sync.js index dd9b09bdd..3c6411486 100644 --- a/chrome/content/zotero/xpcom/sync.js +++ b/chrome/content/zotero/xpcom/sync.js @@ -1803,7 +1803,8 @@ Zotero.Sync.Server = new function () { var compress = Zotero.Prefs.get('sync.server.compressData'); // Compress upload data - if (compress) { + // TEMP: Disabled in case it fixes sync error in Firefox 46 + if (false && compress) { // Callback when compressed data is available var bufferUploader = function (data) { var gzurl = url + '?gzip=1'; From ef71d3f72991e3b0cb3cf8d73f0b4dac71eaf332 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Fri, 29 Apr 2016 11:57:11 -0400 Subject: [PATCH 5/6] Revert "Try disabling gzip compression of uploads, in case it fixes sync error" This reverts commit adec007df06b83b537563debde054a0eb4d30587. Doesn't seem to make a difference. --- chrome/content/zotero/xpcom/sync.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chrome/content/zotero/xpcom/sync.js b/chrome/content/zotero/xpcom/sync.js index 3c6411486..dd9b09bdd 100644 --- a/chrome/content/zotero/xpcom/sync.js +++ b/chrome/content/zotero/xpcom/sync.js @@ -1803,8 +1803,7 @@ Zotero.Sync.Server = new function () { var compress = Zotero.Prefs.get('sync.server.compressData'); // Compress upload data - // TEMP: Disabled in case it fixes sync error in Firefox 46 - if (false && compress) { + if (compress) { // Callback when compressed data is available var bufferUploader = function (data) { var gzurl = url + '?gzip=1'; From b4ac43fd7758304cc71c9626cf0576aee284b78a Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Fri, 29 Apr 2016 13:09:37 -0400 Subject: [PATCH 6/6] Fix startup error on Firefox 48 Addresses #980. There are a couple other uses of the old API, but I'm not sure how they're triggered, and we might be gone from Firefox before this is relevant. --- .../content/zotero/xpcom/translation/translate_firefox.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/chrome/content/zotero/xpcom/translation/translate_firefox.js b/chrome/content/zotero/xpcom/translation/translate_firefox.js index bc0c1bde4..f2cf4f691 100644 --- a/chrome/content/zotero/xpcom/translation/translate_firefox.js +++ b/chrome/content/zotero/xpcom/translation/translate_firefox.js @@ -152,15 +152,13 @@ Zotero.Translate.DOMWrapper = new function() { var _permit = { value: 'rw', writable: false, configurable: false, enumerable: true }; return { getOwnPropertyDescriptor: function(name) { return _permit; }, - getPropertyDescriptor: function(name) { return _permit; }, - getOwnPropertyNames: function() { throw Error("Can't enumerate ExposedPropsWaiver"); }, - getPropertyNames: function() { throw Error("Can't enumerate ExposedPropsWaiver"); }, + ownKeys: function() { throw Error("Can't enumerate ExposedPropsWaiver"); }, enumerate: function() { throw Error("Can't enumerate ExposedPropsWaiver"); }, defineProperty: function(name) { throw Error("Can't define props on ExposedPropsWaiver"); }, - delete: function(name) { throw Error("Can't delete props from ExposedPropsWaiver"); } + deleteProperty: function(name) { throw Error("Can't delete props from ExposedPropsWaiver"); } }; }; - ExposedPropsWaiver = Proxy.create(ExposedPropsWaiverHandler()); + ExposedPropsWaiver = new Proxy({}, ExposedPropsWaiverHandler()); function SpecialPowersHandler(obj, overrides) { this.wrappedObject = obj;