From 785b6dd408cf95dc8e8c4d69c8eaf556af88ffd7 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 18 Jul 2020 19:20:50 -0400 Subject: [PATCH] Update citeproc-js to 1.4.11 This fixes the "invalid language tag" error when there are invalid language tags in Language (beta only). https://forums.zotero.org/discussion/84224/zotero-error-refreshing-report-id-337976002 --- chrome/content/zotero/xpcom/citeproc.js | 169 ++++++++++++++---------- 1 file changed, 98 insertions(+), 71 deletions(-) diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 3c08f6efeb..6e3eb721b4 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -59,7 +59,7 @@ Copyright (c) 2009-2019 Frank Bennett var CSL = { - PROCESSOR_VERSION: "1.4.7", + PROCESSOR_VERSION: "1.4.11", error: function(str) { // default error function if ("undefined" === typeof Error) { @@ -76,6 +76,26 @@ var CSL = { } }, + toLocaleUpperCase(str) { + var arr = this.tmp.lang_array; + try { + str = str.toLocaleUpperCase(arr); + } catch (e) { + str = str.toUpperCase(); + } + return str; + }, + + toLocaleLowerCase(str) { + var arr = this.tmp.lang_array; + try { + str = str.toLocaleLowerCase(arr); + } catch (e) { + str = str.toLowerCase(); + } + return str; + }, + LOCATOR_LABELS_REGEXP: new RegExp("^((vrs|sv|subpara|op|subch|add|amend|annot|app|art|bibliog|bk|ch|cl|col|cmt|dec|dept|div|ex|fig|fld|fol|n|hypo|illus|intro|l|no|p|pp|para|pt|pmbl|princ|pub|r|sched|sec|ser|subdiv|subsec|supp|tbl|tit|vol)\\.)\\s+(.*)"), STATUTE_SUBDIV_PLAIN_REGEX: /(?:(?:^| )(?:vrs|sv|subpara|op|subch|add|amend|annot|app|art|bibliog|bk|ch|cl|col|cmt|dec|dept|div|ex|fig|fld|fol|n|hypo|illus|intro|l|no|p|pp|para|pt|pmbl|princ|pub|r|sched|sec|ser|subdiv|subsec|supp|tbl|tit|vol)\. *)/, @@ -2639,6 +2659,7 @@ CSL.getSortCompare = function (default_locale) { if (CSL.stringCompare) { return CSL.stringCompare; } + var me = this; var strcmp; var strcmp_opts = { sensitivity:"base", @@ -2652,10 +2673,7 @@ CSL.getSortCompare = function (default_locale) { default_locale = "en-US"; } strcmp = function (a, b) { - //var ret = a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase(),default_locale,strcmp_opts); - // print(ret+' ('+a+') :: ('+b+')'); - //return ret; - return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase(),default_locale,strcmp_opts); + return CSL.toLocaleLowerCase.call(me, a).localeCompare(CSL.toLocaleLowerCase.call(me, b),default_locale,strcmp_opts); }; var stripPunct = function (str) { return str.replace(/^[\[\]\'\"]*/g, ""); @@ -7639,8 +7657,6 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, CSL.Engine.prototype.process_CitationCluster = function (sortedItems, citation) { var str = ""; - // Parallels must be evaluated in the calling function - //this.parallel.StartCitation(sortedItems); if (citation && citation.properties && citation.properties.mode === "composite") { citation.properties.mode = "author-only"; var firstChunk = CSL.getCitationCluster.call(this, sortedItems, citation); @@ -7709,9 +7725,6 @@ CSL.Engine.prototype.makeCitationCluster = function (rawList) { inputList.sort(this.citation.srt.compareCompositeKeys); } this.tmp.citation_errors = []; - if (this.opt.parallel.enable) { - this.parallel.StartCitation(inputList); - } var str = CSL.getCitationCluster.call(this, inputList); return str; }; @@ -7738,6 +7751,7 @@ CSL.getAmbiguousCite = function (Item, disambig, visualForm, item) { parallel_first: flags.parallel_first, parallel_last_override: flags.parallel_last_override, parallel_delimiter_override: flags.parallel_delimiter_override, + parallel_delimiter_override_on_suppress: flags.parallel_delimiter_override_on_suppress, condition: flags.condition, force_suppress: flags.force_suppress, done_vars: flags.done_vars.slice() @@ -7979,8 +7993,12 @@ CSL.getCitationCluster = function (inputList, citation) { inputList[0][1]["suppress-author"] = true; } } + if (this.opt.parallel.enable) { + this.parallel.StartCitation(inputList); + } for (pos = 0; pos < len; pos += 1) { + // Also for parallels only this.tmp.cite_index = pos; Item = inputList[pos][0]; @@ -10245,6 +10263,7 @@ CSL.Node.group = { label_static: state.tmp.group_context.tip.label_static, label_capitalize_if_first: label_capitalize_if_first, parallel_delimiter_override: this.strings.set_parallel_delimiter_override, + parallel_delimiter_override_on_suppress: this.strings.set_parallel_delimiter_override_on_suppress, condition: condition, force_suppress: force_suppress, done_vars: state.tmp.group_context.tip.done_vars.slice() @@ -10423,6 +10442,12 @@ CSL.Node.group = { state.output.endTag(); if (this.realGroup) { var flags = state.tmp.group_context.pop(); + if (flags.parallel_delimiter_override) { + state.tmp.group_context.tip.parallel_delimiter_override = flags.parallel_delimiter_override; + } + if (flags.parallel_delimiter_override_on_suppress) { + state.tmp.group_context.tip.parallel_delimiter_override_on_suppress = flags.parallel_delimiter_override_on_suppress; + } if (state.tmp.area === "bibliography_sort") { var citationNumberIdx = flags.done_vars.indexOf("citation-number"); if (this.strings.sort_direction && citationNumberIdx > -1 && state.tmp.group_context.length() == 1) { @@ -10451,7 +10476,8 @@ CSL.Node.group = { } var blobs = state.output.current.value().blobs; var pos = state.output.current.value().blobs.length - 1; - if (!state.tmp.just_looking && (flags.parallel_last || flags.parallel_first || flags.parallel_delimiter_override)) { + if (!state.tmp.just_looking && (flags.parallel_last || flags.parallel_first || flags.parallel_delimiter_override || flags.parallel_delimiter_override_on_suppress)) { +// HOWDY // flags.parallel_last // flags.parallel_first var hasRepeat = state.parallel.checkRepeats(flags); @@ -10462,7 +10488,9 @@ CSL.Node.group = { } if (state.tmp.cite_index > 0 && (hasRepeat || (!flags.parallel_first && !flags.parallel_last))) { //state.sys.print(`${state.tmp.cite_index} ${JSON.stringify(state.tmp.suppress_repeats, null, 2)}`) - if (flags.parallel_delimiter_override && state.tmp.suppress_repeats[state.tmp.cite_index-1].SIBLING) { + if (hasRepeat && flags.parallel_delimiter_override_on_suppress && state.tmp.suppress_repeats[state.tmp.cite_index-1].SIBLING) { + state.output.queue.slice(-1)[0].parallel_delimiter = flags.parallel_delimiter_override_on_suppress; + } else if (flags.parallel_delimiter_override && state.tmp.suppress_repeats[state.tmp.cite_index-1].SIBLING) { state.output.queue.slice(-1)[0].parallel_delimiter = flags.parallel_delimiter_override; } } @@ -16328,6 +16356,9 @@ CSL.Attributes["@parallel-last-override"] = function (state, arg) { CSL.Attributes["@parallel-delimiter-override"] = function (state, arg) { this.strings.set_parallel_delimiter_override = arg; }; +CSL.Attributes["@parallel-delimiter-override-on-suppress"] = function (state, arg) { + this.strings.set_parallel_delimiter_override_on_suppress = arg; +}; CSL.Attributes["@require"] = function (state, arg) { @@ -17040,9 +17071,6 @@ CSL.Parallel.prototype.StartCitation = function (sortedItems, out) { var idxEnd = 0; var parallelMatchList = false; var siblingRanges = []; - // Okay, shit. This is hard. - // Start is fine. - // End is failing to tag a penultimate item. for (var i=0,ilen=sortedItems.length-1;i -1) { // Actually, shouldn't we do this always? - if (!me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label])) { + if ("undefined" === typeof me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label])) { values[currentLabelInfo.pos].labelVisibility = true; } } @@ -19922,7 +19951,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { fixNumericAndCount(values, groupStartPos, currentLabelInfo); fixLabelVisibility(values, groupStartPos, currentLabelInfo); if (values.length && values[0].numeric && variable.slice(0, 10) === "number-of-") { - if (parseInt(ItemObject[variable], 10) > 1) { + if (parseInt(ItemObject[realVariable], 10) > 1) { values[0].plural = 1; } } @@ -19994,7 +20023,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { } function checkPage(variable, val) { - return variable === "page" + return "page" === variable || (["locator", "locator-extra"].indexOf(variable) > -1 && (["p."].indexOf(val.label) > -1 || ["p."].indexOf(val.origLabel) > -1)); } @@ -20074,7 +20103,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { if (!node) { return; } - if (["page", "page-first", "chapter-number", "collection-number", "edition", "issue", "number", "number-of-pages", "number-of-volumes", "volume", "locator", "locator-extra"].indexOf(variable) === -1) { + if (["page", "chapter-number", "collection-number", "edition", "issue", "number", "number-of-pages", "number-of-volumes", "volume", "locator", "locator-extra"].indexOf(variable) === -1) { return; } @@ -20117,8 +20146,8 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { } } - function setVariableParams(shadow_numbers, variable, values) { - var obj = shadow_numbers[variable]; + function setVariableParams(shadow_numbers, realVariable, values) { + var obj = shadow_numbers[realVariable]; if (values.length) { obj.numeric = values[0].numeric; obj.collapsible = values[0].collapsible; @@ -20133,11 +20162,11 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { // Split out the labels and values. // short-circuit if object exists: if numeric, set styling, no other action - if (node && this.tmp.shadow_numbers[variable] && this.tmp.shadow_numbers[variable].values.length) { - var values = this.tmp.shadow_numbers[variable].values; + if (node && this.tmp.shadow_numbers[realVariable] && this.tmp.shadow_numbers[realVariable].values.length) { + var values = this.tmp.shadow_numbers[realVariable].values; fixRanges(values); //if (!this.tmp.shadow_numbers[variable].masterStyling && !this.tmp.just_looking) { - this.tmp.shadow_numbers[variable].masterStyling = setStyling(values); + this.tmp.shadow_numbers[realVariable].masterStyling = setStyling(values); //} return; } @@ -20147,8 +20176,8 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { // This carries value, pluralization and numeric info for use in other contexts. // XXX We used to use one set of params for the entire variable value. // XXX Now params are set on individual objects, of which there may be several after parsing. - if (!this.tmp.shadow_numbers[variable]) { - this.tmp.shadow_numbers[variable] = { + if (!this.tmp.shadow_numbers[realVariable]) { + this.tmp.shadow_numbers[realVariable] = { values:[] }; } @@ -20165,10 +20194,10 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { var languageRole = CSL.LangPrefsMap[variable]; if (languageRole) { var localeType = this.opt["cite-lang-prefs"][languageRole][0]; - val = this.transform.getTextSubField(ItemObject, variable, "locale-"+localeType, true); + val = this.transform.getTextSubField(ItemObject, realVariable, "locale-"+localeType, true); val = val.name; } else { - val = ItemObject[variable]; + val = ItemObject[realVariable]; } // XXX HOLDING THIS @@ -20211,7 +20240,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { } var defaultLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable]; - if (this.tmp.shadow_numbers[variable].values.length === 0) { + if (this.tmp.shadow_numbers[realVariable].values.length === 0) { // XXX var values = parseString(val, defaultLabel); @@ -20224,20 +20253,20 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { for (var obj of values) { if (!obj.numeric) obj.plural = 0; } - this.tmp.shadow_numbers[variable].values = values; + this.tmp.shadow_numbers[realVariable].values = values; // me.sys.print(JSON.stringify(values)) if (node) { fixRanges(values); - this.tmp.shadow_numbers[variable].masterStyling = setStyling(values); - //print("setStyling(): "+JSON.stringify(values, null, 2)); + this.tmp.shadow_numbers[realVariable].masterStyling = setStyling(values); + // me.sys.print("setStyling(): "+JSON.stringify(values, null, 2)); } - setVariableParams(this.tmp.shadow_numbers, variable, values); + setVariableParams(this.tmp.shadow_numbers, realVariable, values); } // hack in support for non-numeric numerics like "91 Civ. 5442 (RPP)|91 Civ. 5471" - var info = this.tmp.shadow_numbers[variable]; + var info = this.tmp.shadow_numbers[realVariable]; if (variable === "number") { if (info.values.length === 1 && info.values[0].value.indexOf("|") > -1) { info.values[0].value = info.values[0].value.replace(/\|/g, ", "); @@ -21156,14 +21185,14 @@ CSL.Output.Formatters = (function () { "": "" }; - function _capitalise (langArray, word) { + function _capitalise (word) { // Weird stuff is (.) transpiled with regexpu // https://github.com/mathiasbynens/regexpu var m = word.match(/(^\s*)((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))(.*)/); // Do not uppercase lone Greek letters // (No case transforms in Greek citations, but chars used in titles to science papers) if (m && !(m[2].match(/^[\u0370-\u03FF]$/) && !m[3])) { - return m[1] + m[2].toLocaleUpperCase(langArray) + m[3]; + return m[1] + CSL.toLocaleUpperCase.call(this, m[2]) + m[3]; } return word; } @@ -21301,8 +21330,8 @@ CSL.Output.Formatters = (function () { if (config.lastWordPos) { var lastWords = wordDoppel.split(config.doppel.strings[config.lastWordPos.strings]); var lastWord = lastWords.strings[config.lastWordPos.words]; - if (lastWord.length > 1 && lastWord.toLocaleLowerCase(config.lang_array).match(config.skipWordsRex)) { - lastWord = _capitalise(config.lang_array, lastWord); + if (lastWord.length > 1 && CSL.toLocaleLowerCase.call(this, lastWord).match(config.skipWordsRex)) { + lastWord = _capitalise.call(this, lastWord); lastWords.strings[config.lastWordPos.words] = lastWord; } config.doppel.strings[config.lastWordPos.strings] = wordDoppel.join(lastWords); @@ -21334,7 +21363,7 @@ CSL.Output.Formatters = (function () { for (var i=0,ilen=words.length;i 1 && !word.toLocaleLowerCase(state.tmp.lang_array).match(config.skipWordsRex)) { + if (word.length > 1 && !CSL.toLocaleLowerCase.call(state, word).match(config.skipWordsRex)) { // Capitalize every word that is not a stop-word - words[j] = _capitalise(state.tmp.lang_array, words[j]); + words[j] = _capitalise.call(state, words[j]); } else if (j === (words.length - 1) && followingTag === "-") { - words[j] = _capitalise(state.tmp.lang_array, words[j]); + words[j] = _capitalise.call(state, words[j]); } else if (config.isFirst) { // Capitalize first word, even if a stop-word - words[j] = _capitalise(state.tmp.lang_array, words[j]); + words[j] = _capitalise.call(state, words[j]); } else if (config.afterPunct) { // Capitalize after punctuation - words[j] = _capitalise(state.tmp.lang_array, words[j]); + words[j] = _capitalise.call(state, words[j]); } config.afterPunct = false; config.isFirst = false; @@ -21452,7 +21479,7 @@ CSL.Output.Formatters = (function () { afterPunct: false, isFirst: true }; - return _textcaseEngine(config, string); + return _textcaseEngine.call(state, config, string); } @@ -21462,7 +21489,6 @@ CSL.Output.Formatters = (function () { */ function capitalizeFirst(state, string) { var config = { - langArray: state.tmp.lang_array, quoteState: [], capitaliseWords: function(str) { var words = str.split(" "); @@ -21470,7 +21496,7 @@ CSL.Output.Formatters = (function () { var word = words[i]; if (word) { if (config.isFirst) { - words[i] = _capitalise(state.tmp.lang_array, word); + words[i] = _capitalise.call(state, word); config.isFirst = false; break; } @@ -21483,7 +21509,7 @@ CSL.Output.Formatters = (function () { afterPunct: null, isFirst: true }; - return _textcaseEngine(config, string); + return _textcaseEngine.call(state, config, string); } /** @@ -21494,14 +21520,13 @@ CSL.Output.Formatters = (function () { */ function capitalizeAll (state, string) { var config = { - langArray: state.tmp.lang_array, quoteState: [], capitaliseWords: function(str) { var words = str.split(" "); for (var i=0,ilen=words.length;i 1) { var removeIDs = [key]; if (this.registry[key].master) { @@ -22845,7 +22872,7 @@ CSL.Registry.prototype.sorttokens = function (nosort) { */ CSL.Registry.Comparifier = function (state, keyset) { var sort_directions, len, pos, compareKeys; - var sortCompare = CSL.getSortCompare(state.opt["default-locale-sort"]); + var sortCompare = CSL.getSortCompare.call(state, state.opt["default-locale-sort"]); sort_directions = state[keyset].opt.sort_directions; this.compareKeys = function (a, b) { len = a.sortkeys ? a.sortkeys.length : 0;