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 451d9e745d..34eab5a238 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 abc500e8a4..62ed5905c9 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 6a990a63a7..13c67ba942 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 08d67df308..5952df6f77 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 34eab5a238..a3b0f2e672 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 dd9b09bdd8..3c6411486a 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 3c6411486a..dd9b09bdd8 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 bc0c1bde4b..f2cf4f691b 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;