commit 877063e73dfb8cdaa0db49005e18cf7ba0d938f2
parent 3663f13fa998c105bbe847e5ca86afede5002919
Author: Dan Stillman <dstillman@zotero.org>
Date: Fri, 29 Apr 2016 20:29:31 -0400
Merge branch '4.0'
Diffstat:
5 files changed, 109 insertions(+), 95 deletions(-)
diff --git 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.101",
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);
}
@@ -6640,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);
@@ -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<ilen; i++) {
- flags = state.tmp.group_context.mystack[i];
- if (!flags.variable_success && (flags.variable_attempt || (!flags.variable_attempt && !flags.term_intended))) {
- firstoutput = true;
- break;
- }
- }
- specialdelimiter = state[state.tmp.area].opt["year-suffix-delimiter"];
- if (firstoutput && specialdelimiter && !state.tmp.sort_key_flag) {
- state.tmp.splice_delimiter = state[state.tmp.area].opt["year-suffix-delimiter"];
- }
- }
- };
- this.execs.push(func);
} else if (this.variables_real[0] === "citation-label") {
- state.opt.has_year_suffix = true;
func = function (state, Item) {
+ state.tmp.has_done_year_suffix = true;
label = Item["citation-label"];
if (!label) {
label = state.getCitationLabel(Item);
@@ -10113,7 +10094,17 @@ CSL.Node.text = {
}
}
};
- } else if (["page", "page-first", "chapter-number", "collection-number", "edition", "issue", "number", "number-of-pages", "number-of-volumes", "volume"].indexOf(this.variables_real[0]) > -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,23 @@ 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;
+ }
+ }
if ("undefined" === typeof blob.gender) {
blob.gender = state.locale[state.opt.lang]["noun-genders"][varname];
}
diff --git a/chrome/content/zotero/xpcom/data/items.js b/chrome/content/zotero/xpcom/data/items.js
@@ -812,6 +812,9 @@ Zotero.Items = function() {
for (let i in toSave) {
yield toSave[i].save();
}
+
+ // Hack to remove master item from duplicates view without recalculating duplicates
+ Zotero.Notifier.trigger('removeDuplicatesMaster', 'item', item.id);
}.bind(this));
};
diff --git a/chrome/content/zotero/xpcom/duplicates.js b/chrome/content/zotero/xpcom/duplicates.js
@@ -91,6 +91,8 @@ Zotero.Duplicates.prototype._getObjectFromID = function (id) {
Zotero.Duplicates.prototype._findDuplicates = Zotero.Promise.coroutine(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
@@ -591,56 +591,46 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio
//this._treebox.beginUpdateBatch();
if ((action == 'remove' && !collectionTreeRow.isLibrary(true))
- || action == 'delete' || action == 'trash') {
-
- // On a delete in duplicates mode, just refresh rather than figuring
- // out what to remove
- if (collectionTreeRow.isDuplicates()) {
- yield this.refresh();
- refreshed = true;
- madeChanges = true;
- sort = true;
- }
- else {
- // Since a remove involves shifting of rows, we have to do it in order,
- // so sort the ids by row
- var rows = [];
- let push = action == 'delete' || action == 'trash';
- for (var i=0, len=ids.length; i<len; i++) {
- if (!push) {
- push = !collectionTreeRow.ref.hasItem(ids[i]);
- }
- // Row might already be gone (e.g. if this is a child and
- // 'modify' was sent to parent)
- let row = this._rowMap[ids[i]];
- if (push && row !== undefined) {
- // Don't remove child items from collections, because it's handled by 'modify'
- if (action == 'remove' && this.getParentIndex(row) != -1) {
- continue;
- }
- rows.push(row);
-
- // Remove child items of removed parents
- if (this.isContainer(row) && this.isContainerOpen(row)) {
- while (++row < this.rowCount && this.getLevel(row) > 0) {
- rows.push(row);
- }
+ || action == 'delete' || action == 'trash'
+ || (action == 'removeDuplicatesMaster' && collectionTreeRow.isDuplicates())) {
+ // Since a remove involves shifting of rows, we have to do it in order,
+ // so sort the ids by row
+ var rows = [];
+ let push = action == 'delete' || action == 'trash' || action == 'removeDuplicatesMaster';
+ for (var i=0, len=ids.length; i<len; i++) {
+ if (!push) {
+ push = !collectionTreeRow.ref.hasItem(ids[i]);
+ }
+ // Row might already be gone (e.g. if this is a child and
+ // 'modify' was sent to parent)
+ let row = this._rowMap[ids[i]];
+ if (push && row !== undefined) {
+ // Don't remove child items from collections, because it's handled by 'modify'
+ if (action == 'remove' && this.getParentIndex(row) != -1) {
+ continue;
+ }
+ rows.push(row);
+
+ // Remove child items of removed parents
+ if (this.isContainer(row) && this.isContainerOpen(row)) {
+ while (++row < this.rowCount && this.getLevel(row) > 0) {
+ rows.push(row);
}
}
}
+ }
+
+ if (rows.length > 0) {
+ // Child items might have been added more than once
+ rows = Zotero.Utilities.arrayUnique(rows);
+ rows.sort(function(a,b) { return a-b });
- if (rows.length > 0) {
- // Child items might have been added more than once
- rows = Zotero.Utilities.arrayUnique(rows);
- rows.sort(function(a,b) { return a-b });
-
- for (let i = rows.length - 1; i >= 0; i--) {
- this._removeRow(rows[i]);
- }
-
- madeChanges = true;
- sort = true;
+ for (let i = rows.length - 1; i >= 0; i--) {
+ this._removeRow(rows[i]);
}
+
+ madeChanges = true;
+ sort = true;
}
}
else if (type == 'item' && action == 'modify')
diff --git 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;