From bb220ad0f2d6bf0eca6df6d225d3d358cb50a27b Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Tue, 2 Jun 2020 17:07:31 -0400 Subject: [PATCH] Update to citeproc-js 1.3.22 --- chrome/content/zotero/xpcom/citeproc.js | 1224 +++++++++++++++-------- 1 file changed, 794 insertions(+), 430 deletions(-) diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 2d9d0ef17c..6c10b3f5e4 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.2.17", + PROCESSOR_VERSION: "1.3.22", error: function(str) { // default error function if ("undefined" === typeof Error) { @@ -76,90 +76,154 @@ var CSL = { } }, - LOCATOR_LABELS_REGEXP: new RegExp("^((art|ch|subch|col|fig|l|n|no|op|p|pp|para|subpara|supp|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\\.)\\s+(.*)"), + 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: /(?:(?:^| )(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|supp|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/, - STATUTE_SUBDIV_PLAIN_REGEX_FRONT: /(?:^\s*[.,;]*\s*(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|supp|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/, + 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)\. *)/, + STATUTE_SUBDIV_PLAIN_REGEX_FRONT: /(?:^\s*[.,;]*\s*(?: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)\. *)/, + STATUTE_SUBDIV_STRINGS: { + "vrs.": "verse", + "sv.": "sub-verbo", + "subpara.": "subparagraph", + "op.": "opus", + "subch.": "subchapter", + "add.": "addendum", + "amend.": "amendment", + "annot.": "annotation", + "app.": "appendix", "art.": "article", + "bibliog.": "bibliography", "bk.": "book", "ch.": "chapter", - "subch.": "subchapter", + "cl.": "clause", + "col.": "column", + "cmt.": "comment", + "dec.": "decision", + "dept.": "department", + "div.": "division", + "ex.": "example", + "fig.": "figure", + "fld.": "field", + "fol.": "folio", + "n.": "note", + "hypo.": "hypothetical", + "illus.": "illustration", + "intro.": "introduction", + "l.": "line", + "no.": "issue", "p.": "page", "pp.": "page", "para.": "paragraph", - "subpara.": "subparagraph", "pt.": "part", + "pmbl.": "preamble", + "princ.": "principle", + "pub.": "publication", "r.": "rule", + "sched.": "schedule", "sec.": "section", + "ser.": "series,", + "subdiv.": "subdivision", "subsec.": "subsection", "supp.": "supplement", - "sch.": "schedule", + "tbl.": "table", "tit.": "title", - "col.": "column", - "fig.": "figure", - "fol.": "folio", - "l.": "line", - "n.": "note", - "no.": "issue", - "op.": "opus", - "sv.": "sub-verbo", - "vrs.": "verse", "vol.": "volume" }, STATUTE_SUBDIV_STRINGS_REVERSE: { + "verse": "vrs.", + "sub-verbo": "sv.", + "sub verbo": "sv.", + "subparagraph": "subpara.", + "opus": "op.", + "subchapter": "subch.", + "addendum": "add.", + "amendment": "amend.", + "annotation": "annot.", + "appendix": "app.", "article": "art.", + "bibliography": "bibliog.", "book": "bk.", "chapter": "ch.", - "subchapter": "subch.", + "clause": "cl.", + "column": "col.", + "comment": "cmt.", + "decision": "dec.", + "department": "dept.", + "division": "div.", + "example": "ex.", + "figure": "fig.", + "field": "fld.", + "folio": "fol.", + "note": "n.", + "hypothetical": "hypo.", + "illustration": "illus.", + "introduction": "intro.", + "line": "l.", + "issue": "no.", "page": "p.", "paragraph": "para.", - "subparagraph": "subpara.", "part": "pt.", + "preamble": "pmbl.", + "principle": "princ.", + "publication": "pub.", "rule": "r.", + "schedule": "sched.", "section": "sec.", + "series,": "ser.", + "subdivision": "subdiv.", "subsection": "subsec.", "supplement": "supp.", - "schedule": "sch.", + "table": "tbl.", "title": "tit.", - "column": "col.", - "figure": "fig.", - "folio": "fol.", - "line": "l.", - "note": "n.", - "issue": "no.", - "opus": "op.", - "sub-verbo": "sv.", - "sub verbo": "sv.", - "verse": "vrs.", "volume": "vol." }, LOCATOR_LABELS_MAP: { + "vrs": "verse", + "sv": "sub-verbo", + "subpara": "subparagraph", + "op": "opus", + "subch": "subchapter", + "add": "addendum", + "amend": "amendment", + "annot": "annotation", + "app": "appendix", "art": "article", + "bibliog": "bibliography", "bk": "book", "ch": "chapter", - "subch": "subchapter", + "cl": "clause", "col": "column", + "cmt": "comment", + "dec": "decision", + "dept": "department", + "div": "division", + "ex": "example", "fig": "figure", + "fld": "field", "fol": "folio", - "l": "line", "n": "note", + "hypo": "hypothetical", + "illus": "illustration", + "intro": "introduction", + "l": "line", "no": "issue", - "op": "opus", "p": "page", "pp": "page", "para": "paragraph", - "subpara": "subparagraph", "pt": "part", + "pmbl": "preamble", + "princ": "principle", + "pub": "publication", "r": "rule", - "sec": "section", - "subsec": "subsection", - "supp": "supplement", - "sv": "sub-verbo", - "sch": "schedule", + "sched": "schedule", + "sec": "section", + "ser": "series,", + "subdiv": "subdivision", + "subsec": "subsection", + "supp": "supplement", + "tbl": "table", "tit": "title", - "vrs": "verse", "vol": "volume" }, MODULE_MACROS: { @@ -182,7 +246,8 @@ var CSL = { "report": true, "regulation": true, "standard": true, - "patent": true + "patent": true, + "locator": true }, checkNestedBrace: function(state) { if (state.opt.xclass === "note") { @@ -558,10 +623,6 @@ var CSL = { "delimiter" ], - PARALLEL_MATCH_VARS: ["container-title"], - PARALLEL_TYPES: ["bill","gazette","regulation","legislation","legal_case","treaty","article-magazine","article-journal"], - PARALLEL_COLLAPSING_MID_VARSET: ["volume", "issue", "container-title", "section", "collection-number"], - LOOSE: 0, STRICT: 1, TOLERANT: 2, @@ -615,7 +676,8 @@ var CSL = { "original-author", "recipient", "reviewed-author", - "translator" + "translator", + "commenter" ], CREATORS: [ "author", @@ -630,7 +692,8 @@ var CSL = { "original-author", "recipient", "reviewed-author", - "translator" + "translator", + "commenter" ], NUMERIC_VARIABLES: [ "call-number", @@ -645,6 +708,7 @@ var CSL = { "number", "number-of-pages", "number-of-volumes", + "version", "volume", // "section", ??? add this? "supplement", @@ -777,6 +841,15 @@ var CSL = { vals[title.main] = splitTitle[0]; vals[title.subjoin] = splitTitle[1]; vals[title.sub] = splitTitle[2]; + if (this.opt.development_extensions.implicit_short_title && Item.type !== "legal_case") { + if (!Item[title.short] && !vals[title.main].match(/^[\-\.[0-9]+$/)) { + var punct = vals[title.subjoin].trim(); + if (["?", "!"].indexOf(punct) === -1) { + punct = ""; + } + vals[title.short] = vals[title.main] + punct; + } + } } else { vals[title.main] = vals[title.title]; vals[title.subjoin] = ""; @@ -1171,7 +1244,7 @@ var CSL = { termStartAlpha = flags.condition.termtxt.slice(0,1).match(CSL.ALL_ROMANESQUE_REGEXP); } var num = state.tmp.just_did_number; - if (empty) { + if (empty || flags.condition.valueTerm) { // i.e. Big L. Rev. 100, 102 // Little L. Rev. 102 // L. Rev. for Plan 9, 102 @@ -1180,14 +1253,19 @@ var CSL = { } else { testres = false; } - } else if (flags.condition.valueTerm) { - // i.e. Ibid. at 102 - testres = false; } else { - if (termStartAlpha) { - testres = true; + if (num) { + if (termStartAlpha || ["always", "after-number"].indexOf(state.opt.require_comma_on_symbol) > -1) { + testres = true; + } else { + testres = false; + } } else { - testres = false; + if (termStartAlpha || state.opt.require_comma_on_symbol === "always") { + testres = true; + } else { + testres = false; + } } } } @@ -1206,7 +1284,9 @@ var CSL = { "prioritize_disambiguate_condition", "csl_reverse_lookup_support", "main_title_from_short_title", - "uppercase_subtitles" + "uppercase_subtitles", + "force_short_title_casing_alignment", + "implicit_short_title" ], TITLE_SPLIT_REGEXP: (function() { @@ -1244,6 +1324,143 @@ var CSL = { } } return lst; + }, + + GET_COURT_CLASS: function(state, Item, sortKey){ + // Get authority as a string + var cls = ""; + var authority = null; + var country = Item.jurisdiction ? Item.jurisdiction.split(":")[0] : null; + // inStyle versus in module + var classType = "court_condition_classes"; + if (sortKey) { + classType = "court_key_classes"; + } + if (country && Item.authority) { + if ("string" === typeof Item.authority) { + authority = Item.authority; + } else { + if (Item.authority[0] && Item.authority[0].literal) { + authority = Item.authority[0].literal; + } + } + } + if (authority) { + if (this.lang && state.locale[this.lang].opts[classType] && state.locale[this.lang].opts[classType][country] && state.locale[this.lang].opts[classType][country][authority]) { + cls = state.locale[this.lang].opts[classType][country][authority]; + } else if (state.locale[state.opt["default-locale"][0]].opts[classType] && state.locale[state.opt["default-locale"][0]].opts[classType][country] && state.locale[state.opt["default-locale"][0]].opts[classType][country][authority]) { + cls = state.locale[state.opt["default-locale"][0]].opts[classType][country][authority] + } + } + return cls; + }, + + SET_COURT_CLASSES: function(state, lang, myxml, dataObj) { + var nodes = myxml.getNodesByName(dataObj, 'court-class'); + for (var pos = 0, len = myxml.numberofnodes(nodes); pos < len; pos += 1) { + var courtclass = nodes[pos]; + var attributes = myxml.attributes(courtclass); + var cls = attributes["@name"]; + var country = attributes["@country"]; + var courts = attributes["@courts"]; + + // Okay, this is a hack. + // If state.registry IS NOT yet defined, this is an in-style declaration. + // If state.registry IS defined, this is an in-module declaration. + var classType = "court_key_classes"; + if (state.registry) { + classType = "court_condition_classes"; + } + + if (cls && country && courts) { + courts = courts.trim().split(/\s+/); + if (!state.locale[lang].opts[classType]) { + state.locale[lang].opts[classType] = {}; + } + if (!state.locale[lang].opts[classType][country]) { + state.locale[lang].opts[classType][country] = {}; + } + for (var i=0,ilen=courts.length;i 12) { - ret[("month" + suff)] = "" + lst[this.dayGuess]; - ret[("day" + suff)] = "" + lst[this.monthGuess]; + var month = lst[this.dayGuess]; + var day = lst[this.monthGuess]; + if (month) { + ret[("month" + suff)] = "" + month; + if (day) { + ret[("day" + suff)] = "" + day; + } + } } else { - ret[("month" + suff)] = "" + lst[this.monthGuess]; - ret[("day" + suff)] = "" + lst[this.dayGuess]; + var month = lst[this.monthGuess]; + var day = lst[this.dayGuess]; + if (month) { + ret[("month" + suff)] = "" + month; + if (day) { + ret[("day" + suff)] = "" + day; + } + } } } }; @@ -3109,6 +3341,7 @@ CSL.DateParser = function () { var yearIsNegative = false; var lst; if (txt) { + txt = txt.replace(/^(.*[0-9])T[0-9].*/, "$1"); // If string leads with a minus sign, strip and memo it. if (txt.slice(0, 1) === "-") { yearIsNegative = true; @@ -3429,8 +3662,6 @@ CSL.Engine = function (sys, style, lang, forceLang) { CSL.stringCompare = this.sys.stringCompare; } this.sys.AbbreviationSegments = CSL.AbbreviationSegments; - this.parallel = new CSL.Parallel(this); - //this.parallel.use_parallels = true; this.transform = new CSL.Transform(this); // true or false @@ -3471,7 +3702,7 @@ CSL.Engine = function (sys, style, lang, forceLang) { } } - if (this.opt.development_extensions.uppercase_subtitles) { + if (this.opt.development_extensions.uppercase_subtitles || this.opt.development_extensions.implicit_short_title) { this.opt.development_extensions.main_title_from_short_title = true; } if (this.opt.development_extensions.csl_reverse_lookup_support) { @@ -3518,7 +3749,6 @@ CSL.Engine = function (sys, style, lang, forceLang) { if (this.opt.version.slice(0,4) === "1.1m") { this.opt.development_extensions.static_statute_locator = true; - this.opt.development_extensions.handle_parallel_articles = true; this.opt.development_extensions.main_title_from_short_title = true; this.opt.development_extensions.expect_and_symbol_form = true; this.opt.development_extensions.require_explicit_legal_case_title_short = true; @@ -3597,6 +3827,10 @@ CSL.Engine = function (sys, style, lang, forceLang) { var area_nodes = this.cslXml.getNodesByName(this.cslXml.dataObj, this.build.area); this.buildTokenLists(area_nodes, this[this.build.area].tokens); + if (this.opt.parallel.enable) { + this.parallel = new CSL.Parallel(this); + } + this.juris = {}; this.configureTokenLists(); @@ -4132,10 +4366,6 @@ CSL.Engine.prototype.refetchItem = function (id) { return this.registry.refhash[id]; }; -CSL.Engine.prototype.refetchItem = function (id) { - return this.registry.refhash[id]; -} - // Executed during style build CSL.Engine.prototype.setOpt = function (token, name, value) { if (token.name === "style" || token.name === "cslstyle") { @@ -5223,6 +5453,7 @@ CSL.Output.Queue.prototype.string = function (state, myblobs, blob) { if (state.normalDecorIsOrphan(blobjr, params)) { continue; } + if (!params[0]) continue; if ("string" === typeof blobs_start) { blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]); } @@ -6017,6 +6248,9 @@ CSL.Output.Queue.adjust = function (punctInQuote) { /*global CSL: true */ CSL.Engine.Opt = function () { + this.parallel = { + enable: false, + }, this.has_disambiguate = false; this.mode = "html"; this.dates = {}; @@ -6164,7 +6398,6 @@ CSL.Engine.Opt = function () { this.development_extensions.static_statute_locator = false; this.development_extensions.csl_reverse_lookup_support = false; this.development_extensions.wrap_url_and_doi = false; - this.development_extensions.handle_parallel_articles = false; this.development_extensions.thin_non_breaking_space_html_hack = false; this.development_extensions.apply_citation_wrapper = false; this.development_extensions.main_title_from_short_title = false; @@ -6181,6 +6414,7 @@ CSL.Engine.Opt = function () { this.development_extensions.strict_inputs = true; this.development_extensions.prioritize_disambiguate_condition = false; this.development_extensions.force_short_title_casing_alignment = true; + this.development_extensions.implicit_short_title = false; }; CSL.Engine.Tmp = function () { @@ -6249,10 +6483,9 @@ CSL.Engine.Tmp = function () { variable_success: false, output_tip: undefined, label_form: undefined, - parallel_condition: undefined, - parallel_result: undefined, - no_repeat_condition: undefined, - parallel_repeats: undefined, + parallel_first: undefined, + parallel_last: undefined, + parallel_delimiter_override: undefined, condition: false, force_suppress: false, done_vars: [] @@ -6752,7 +6985,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, // attach the sorted list to the citation item citation.sortedItems = sortedItems; - + // build reconstituted citations list in current document order var citationByIndex = []; var citationById = {}; @@ -6936,7 +7169,10 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, } // evaluate parallels - this.parallel.StartCitation(citation.sortedItems); + + if (this.opt.parallel.enable) { + this.parallel.StartCitation(citation.sortedItems); + } var citations; if (this.opt.update_mode === CSL.POSITION) { @@ -7077,10 +7313,15 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, if (prevCitation.properties.mode === "author-only" && j > 1) { old_last_id_offset = 2; } - oldlastid = citations[j - old_last_id_offset].sortedItems.slice(-1)[0][1].id; - oldlastxloc = citations[j - old_last_id_offset].sortedItems.slice(-1)[0][1]["locator-extra"]; - if (prevCitation.sortedItems[0].slice(-1)[0].legislation_id) { - oldlastid = prevCitation.sortedItems[0].slice(-1)[0].legislation_id; + var adjusted_offset = (j - old_last_id_offset); + if (citations[adjusted_offset].sortedItems.length) { + oldlastid = citations[adjusted_offset].sortedItems.slice(-1)[0][1].id; + oldlastxloc = citations[j - old_last_id_offset].sortedItems.slice(-1)[0][1]["locator-extra"]; + } + if (prevCitation.sortedItems.length) { + if (prevCitation.sortedItems[0].slice(-1)[0].legislation_id) { + oldlastid = prevCitation.sortedItems[0].slice(-1)[0].legislation_id; + } } } if (j > 0 && k === 0 && prevCitation.properties.noteIndex !== thisCitation.properties.noteIndex) { @@ -7466,7 +7707,9 @@ CSL.Engine.prototype.makeCitationCluster = function (rawList) { inputList.sort(this.citation.srt.compareCompositeKeys); } this.tmp.citation_errors = []; - this.parallel.StartCitation(inputList); + if (this.opt.parallel.enable) { + this.parallel.StartCitation(inputList); + } var str = CSL.getCitationCluster.call(this, inputList); return str; }; @@ -7489,10 +7732,9 @@ CSL.getAmbiguousCite = function (Item, disambig, visualForm, item) { variable_success: flags.variable_success, output_tip: flags.output_tip, label_form: flags.label_form, - parallel_condition: flags.parallel_condition, - parallel_result: flags.parallel_result, - no_repeat_condition: flags.no_repeat_condition, - parallel_repeats: flags.parallel_result, + parallel_last: flags.parallel_last, + parallel_first: flags.parallel_first, + parallel_delimiter_override: flags.parallel_delimiter_override, condition: flags.condition, force_suppress: flags.force_suppress, done_vars: flags.done_vars.slice() @@ -7652,6 +7894,11 @@ CSL.getCitationCluster = function (inputList, citation) { this.tmp.last_years_used = []; this.tmp.backref_index = []; this.tmp.cite_locales = []; + if (!this.tmp.just_looking) { + this.tmp.abbrev_trimmer = { + QUASHES: {} + }; + } var use_layout_prefix = this.output.checkNestedBrace.update(this.citation.opt.layout_prefix + citation_prefix); //var use_layout_prefix = this.citation.opt.layout_prefix; @@ -7730,6 +7977,9 @@ CSL.getCitationCluster = function (inputList, citation) { } } for (pos = 0; pos < len; pos += 1) { + + this.tmp.cite_index = pos; + Item = inputList[pos][0]; item = inputList[pos][1]; item = CSL.parseLocator.call(this, item); @@ -7752,6 +8002,8 @@ CSL.getCitationCluster = function (inputList, citation) { this.tmp.in_cite_predecessor = false; // true is to block reset of shadow numbers + + if (pos > 0) { CSL.getCite.call(this, Item, item, "" + inputList[(pos - 1)][0].id, true); } else { @@ -7805,8 +8057,6 @@ CSL.getCitationCluster = function (inputList, citation) { break; } } - - this.parallel.purgeGroupsIfParallel(); // // output.queue is a simple array. do a slice // of it to get each cite item, setting params from @@ -8096,6 +8346,13 @@ CSL.citeStart = function (Item, item, blockShadowNumberReset) { this.tmp.nameset_counter = 0; this.tmp.years_used = []; this.tmp.names_max.clear(); + if (!this.tmp.just_looking) { + if (!item || item.parallel === "first" || !item.parallel) { + this.tmp.abbrev_trimmer = { + QUASHES: {} + }; + } + } this.tmp.splice_delimiter = this[this.tmp.area].opt.layout_delimiter; //this.tmp.splice_delimiter = this[this.tmp.area].opt.delimiter; @@ -8265,7 +8522,7 @@ CSL.Engine.prototype.makeBibliography = function (bibsection) { * Compose individual cites into a single string. */ CSL.getBibliographyEntries = function (bibsection) { - var ret, input, include, anymatch, allmatch, bib_entry, res, item, spec, lllen, pppos, topblobs, entry_item_ids, debug, collapse_parallel, i, ilen, siblings, skips, sortedItems, eyetem, entry_item_data, j, jlen; + var ret, input, include, anymatch, allmatch, bib_entry, res, item, spec, lllen, pppos, topblobs, entry_item_ids, debug, i, ilen, siblings, skips, sortedItems, eyetem, entry_item_data, j, jlen; ret = []; entry_item_data = []; this.tmp.area = "bibliography"; @@ -8273,7 +8530,7 @@ CSL.getBibliographyEntries = function (bibsection) { this.tmp.last_rendered_name = false; this.tmp.bibliography_errors = []; this.tmp.bibliography_pos = 0; - + // For paged returns: disable generated entries and // do not fetch full items as a batch (input variable // consists of ids only in this case) @@ -8431,31 +8688,30 @@ CSL.getBibliographyEntries = function (bibsection) { } // 2019-06-25 Hacked to conform to new parallels evaluation method + // 2020-04-25 Revised to work with latest, and final, parallel-first/parallel-last attributes entry_item_ids = []; if (this.registry.registry[item.id].master && !(bibsection && bibsection.page_start && bibsection.page_length)) { - + // Fetch item content sortedItems = [[item, {id: item.id}]]; - var siblings = this.registry.registry[item.id].siblings; + siblings = this.registry.registry[item.id].siblings; for (var j=0,jlen=siblings.length; j 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) { + state.output.queue.slice(-1)[0].parallel_delimiter = flags.parallel_delimiter_override; + } + } } } else { state.tmp.term_predecessor = flags.old_term_predecessor; @@ -10676,6 +10863,13 @@ CSL.Node.key = { var altvar = false; var transfall = true; func = state.transform.getOutputFunction(this.variables, abbrevfam, abbrfall, altvar, transfall); + } else if ("court-class" === variable) { + func = function(state, Item, item) { + CSL.INIT_JURISDICTION_MACROS(state, Item, item, "juris-main") + // true is for sortKey mode + var cls = CSL.GET_COURT_CLASS(state, Item, true); + state.output.append(cls, "empty"); + } } else { func = function (state, Item) { var varval = Item[variable]; @@ -10916,6 +11110,13 @@ CSL.Node.layout = { if (!state.tmp.just_looking && state.registry.registry[Item.id] && state.registry.registry[Item.id].parallel) { state.tmp.done_vars.push("first-reference-note-number"); } + // trimmer is not available in getAmbiguousCite + if (!state.tmp.just_looking && state.tmp.abbrev_trimmer && Item.jurisdiction) { + for (var field in state.tmp.abbrev_trimmer.QUASHES[Item.jurisdiction]) { + state.tmp.done_vars.push(field); + } + } + //CSL.debug(" === init rendered_name === "); state.tmp.rendered_name = false; }; @@ -11653,6 +11854,10 @@ CSL.NameOutput.prototype.outputNames = function () { // For name_SubstituteOnNamesSpanNamesSpanFail this.variables = []; + + // Reset stop-last after rendering + this.state.tmp.authority_stop_last = 0; + //SNIP-START if (this.debug) { print("(19)"); @@ -13733,8 +13938,9 @@ CSL.NameOutput.prototype.fixupInstitution = function (name, varname, listpos) { var long_form = name["long"]; var short_form = name["long"].slice(); var use_short_form = false; + var itemJurisdiction = this.Item.jurisdiction; if (this.state.sys.getAbbreviation) { - var jurisdiction = this.Item.jurisdiction; + var jurisdiction = itemJurisdiction; for (var j = 0, jlen = long_form.length; j < jlen; j += 1) { var abbrevKey = long_form[j]; jurisdiction = this.state.transform.loadAbbreviation(jurisdiction, "institution-part", abbrevKey); @@ -13745,10 +13951,33 @@ CSL.NameOutput.prototype.fixupInstitution = function (name, varname, listpos) { } } if (use_short_form) { + var delimiter = this.institution.strings.delimiter; + var use_first = this.institution.strings["use-first"]; + if (use_first) { + if (!delimiter) { + delimiter = "|"; + } + var buf = []; + for (var i=0,ilen=short_form.length;i 0; j += -1) { + var jurisdiction = itemJurisdiction; var str = splitInstitution.slice(0, j).join("|"); var abbrevKey = str; jurisdiction = this.state.transform.loadAbbreviation(jurisdiction, "institution-entire", abbrevKey); if (this.state.transform.abbrevs[jurisdiction]["institution-entire"][abbrevKey]) { var splitLst = this.state.transform.abbrevs[jurisdiction]["institution-entire"][abbrevKey]; - splitLst = this.state.transform.quashCheck(splitLst); + splitLst = this.state.transform.quashCheck(itemJurisdiction, splitLst); // If the abbreviation has date cut-offs, find the most recent // abbreviation within scope. @@ -14023,7 +14253,11 @@ CSL.evaluateLabel = function (node, state, Item, item) { plural = state.tmp.shadow_numbers[node.strings.term].plural; if (!state.tmp.shadow_numbers[node.strings.term].labelForm && !state.tmp.shadow_numbers[node.strings.term].labelDecorations) { - state.tmp.shadow_numbers[node.strings.term].labelForm = node.strings.form; + if (node.strings.form) { + state.tmp.shadow_numbers[node.strings.term].labelForm = node.strings.form; + } else if (state.tmp.group_context.tip.label_form) { + state.tmp.shadow_numbers[node.strings.term].labelForm = state.tmp.group_context.tip.label_form; + } state.tmp.shadow_numbers[node.strings.term].labelCapitalizeIfFirst = node.strings.capitalize_if_first; state.tmp.shadow_numbers[node.strings.term].labelDecorations = node.decorations.slice(); } @@ -14546,7 +14780,12 @@ CSL.Node.number = { state.processNumber.call(state, node, Item, varname, Item.type); } - CSL.Util.outputNumericField(state, varname, Item.id); + if (this.substring) { + var val = Item[varname].slice(this.substring); + state.output.append(val, node); + } else { + CSL.Util.outputNumericField(state, varname, Item.id); + } if (["locator", "locator-extra"].indexOf(this.variables_real[0]) > -1 && !state.tmp.just_looking) { @@ -14575,7 +14814,6 @@ CSL.Node.sort = { target = state[state.build.root + "_sort"].tokens; if (this.tokentype === CSL.START) { if (state.build.area === "citation") { - state.parallel.use_parallels = false; state.opt.sort_citations = true; } state.build.area = state.build.root + "_sort"; @@ -14924,7 +15162,10 @@ CSL.Node.text = { // Deal with multi-fields and ordinary fields separately. if (CSL.MULTI_FIELDS.indexOf(this.variables_real[0]) > -1 - || ["language-name", "language-name-original"].indexOf(this.variables_real[0]) > -1) { + || this.variables_real[0].indexOf("-main") > -1 + || this.variables_real[0].indexOf("-sub") > -1 + || ["language-name", "language-name-original"].indexOf(this.variables_real[0]) > -1 + ) { // multi-fields // Initialize transform factory according to whether @@ -15197,7 +15438,7 @@ CSL.Attributes["@is-numeric"] = function (state, arg) { if (state.tmp.shadow_numbers[variable].numeric) { return true; } - } else if (["title", "locator-extra","version"].indexOf(variable) > -1) { + } else if (["title","version"].indexOf(variable) > -1) { if (myitem[variable].slice(-1) === "" + parseInt(myitem[variable].slice(-1), 10)) { return true; } @@ -15240,7 +15481,7 @@ CSL.Attributes["@locator"] = function (state, arg) { var label; state.processNumber(false, item, "locator"); label = state.tmp.shadow_numbers.locator.label; - if (trylabel === label) { + if (label && trylabel === label) { return true; } else { return false; @@ -15257,7 +15498,6 @@ CSL.Attributes["@position"] = function (state, arg) { this.tests ? {} : this.tests = []; var tryposition; state.opt.update_mode = CSL.POSITION; - state.parallel.use_parallels = null; var trypositions = arg.split(/\s+/); var testSubsequentNear = function (Item, item) { if (item && item.position >= CSL.POSITION_SUBSEQUENT && item["near-note"]) { @@ -15577,6 +15817,11 @@ CSL.Attributes["@page"] = function (state, arg) { } else { label = state.tmp.shadow_numbers.page.label; } + if (state.tmp.shadow_numbers.page.values.length > 0) { + if (state.tmp.shadow_numbers.page.values[0].gotosleepability) { + state.tmp.shadow_numbers.page.values[0].labelVisibility = false; + } + } if (trylabel === label) { return true; } else { @@ -15951,15 +16196,55 @@ CSL.Attributes["@locale-internal"] = function (state, arg) { }; -// These are not evaluated as conditions immediately: they only -// set parameters that are picked up during processing. -CSL.Attributes["@is-parallel"] = function (state, arg) { - this.strings.set_parallel_condition = arg; -}; -CSL.Attributes["@no-repeat"] = function (state, arg) { - this.strings.set_no_repeat_condition = arg.split(/\s+/); +CSL.Attributes["@court-class"] = function (state, arg) { + this.tests ? {} : this.tests = []; + var tryclasses = arg.split(/\s+/); + var maketest = function (tryclass) { + return function(Item) { + var cls = CSL.GET_COURT_CLASS(state, Item); + if (cls === tryclass) { + return true; + } else { + return false; + } + }; + }; + for (var i=0,ilen=tryclasses.length; i 1) { - // Harder than it looks. - // On a first pass, get the seeAlso of each item. - for (var i=0,ilen=sortedItems.length; i 0 && freshMatchList) { + this.state.tmp.suppress_repeats[i-1].START = true; + freshMatchList = false; + } + var currItem = sortedItems[i][0]; + var nextItem = sortedItems[i+1][0]; + for (var varname in this.state.opt.track_repeat) { + // if (varname === "title") { + // this.state.sys.print(`curr: ${currItem}, next: ${JSON.stringify(nextItem, null, 2)}`); + // } + if (!currItem[varname] || !nextItem[varname]) { + // Go ahead and render any value with an empty partner + info[varname] = false; + } else if ("string" === typeof nextItem[varname] || "number" === typeof nextItem[varname]) { + // Simple comparison of string values + if (varname === "title" && currItem["title-short"] && nextItem["title-short"]) { + var currVal = currItem["title-short"]; + var nextVal = nextItem["title-short"]; + } else { + var currVal = currItem[varname]; + var nextVal = nextItem[varname]; } - masterID = prev.id; - this.state.registry.registry[masterID].master = true; - this.state.registry.registry[masterID].siblings = [curr.id]; - - } - } else { - if (seriesRels[curr.id]) { - sortedItems[i][1].parallel = "mid"; - if (!sortedItems[i][1].prefix) { - sortedItems[i][1].prefix = ", "; + if (currVal == nextVal) { + info[varname] = true; + } else { + info[varname] = false; + } + } else if ("undefined" === typeof currItem[varname].length) { + // If a date, use only the year + info[varname] = false; + var currYear = currItem[varname].year; + var nextYear = nextItem[varname].year; + if (currYear && nextYear) { + if (currYear == nextYear) { + info[varname] = true; + } } - delete seriesRels[curr.id]; - sortedItems[i][1].repeats = this.getRepeats(prev, curr); - //sortedItems[i-1][1].repeats = sortedItems[i][1].repeats; - this.state.registry.registry[masterID].siblings.push(curr.id); } else { - sortedItems[i-1][1].parallel = "last"; - sortedItems[i][1].repeats = this.getRepeats(prev, curr); - seriesRels = false; - } - } - if (i === (sortedItems.length-1)) { - if (sortedItems[i][1].parallel === "mid") { - sortedItems[i][1].parallel = "last"; - sortedItems[i][1].repeats = this.getRepeats(prev, curr); - } else if (sortedItems[i][1].parallel !== "last") { - delete sortedItems[i][1].repeats; + // If a creator value, kludge it + var currVal = JSON.stringify(currItem[varname]); + var nextVal = JSON.stringify(nextItem[varname]); + if (currVal === nextVal) { + info[varname] = true; + } else { + info[varname] = false; + } } } + + } + if (idxEnd === i) { + info.END = true; + parallelMatchList = false; + } + this.state.tmp.suppress_repeats.push(info); + } + for (var j=0,jlen=siblingRanges.length;j -1; i += -1) { - var obj = this.parallel_conditional_blobs_list[i]; - if (!obj.result && !obj.repeats) { - purgeme = false; - } else { - if (obj.condition) { - var purgeme = true; - if (obj.result === obj.condition) { - purgeme = false; - } - } - if (purgeme && obj.norepeat && obj.repeats) { - purgeme = false; - var matches = 0; - for (var j=0,jlen=obj.norepeat.length; j obj.pos) { - buffer.push(obj.blobs.pop()); - } - if (buffer.length) { - buffer.pop(); - } - while (buffer.length) { - obj.blobs.push(buffer.pop()); - } - } - this.parallel_conditional_blobs_list.pop(); } + if (params.parallel_last) { + var arr = this.state.tmp.suppress_repeats.concat([{}]); + for (var varname in params.parallel_last) { + if (arr[idx][varname] && !arr[idx].END) { + return true; + } + } + } + return false; }; /*global CSL: true */ @@ -16953,6 +17220,7 @@ CSL.Transform = function (state) { // Internal function function abbreviate(state, tok, Item, altvar, basevalue, family_var, use_field) { + var value = ""; var myabbrev_family = CSL.FIELD_CATEGORY_REMAP[family_var]; var preferredJurisdiction; @@ -16962,6 +17230,7 @@ CSL.Transform = function (state) { var variable = family_var; var normalizedKey = basevalue; + if (state.sys.normalizeAbbrevsKey) { normalizedKey = state.sys.normalizeAbbrevsKey(family_var, basevalue); } @@ -16969,6 +17238,11 @@ CSL.Transform = function (state) { if (variable === "jurisdiction" && normalizedKey) { quashCountry = normalizedKey.indexOf(":") === -1; } + // Fix up jurisdiction codes + if (["jurisdiction", "country"].indexOf(family_var) > -1 && basevalue === basevalue.toLowerCase()) { + normalizedKey = basevalue.toUpperCase(); + } + // Lazy retrieval of abbreviations. if (state.sys.getAbbreviation) { @@ -17252,14 +17526,32 @@ CSL.Transform = function (state) { // The name transform code is placed here to keep similar things // in one place. Obviously this module could do with a little // tidying up. - function quashCheck(value) { - var m = value.match(/^!([-,_a-z]+)>>>/); + function quashCheck(jurisdiction, value) { + var m = value.match(/^!((?:[-_a-z]+(?:(?:.*)))(?:,(?:[-_a-z]+(?:(?:.*))))*)>>>/); if (m) { var fields = m[1].split(","); value = value.slice(m[0].length); for (var i = 0, ilen = fields.length; i < ilen; i += 1) { - if (state.tmp.done_vars.indexOf(fields[i]) === -1) { - state.tmp.done_vars.push(fields[i]); + var rawField = fields[i]; + var mm = rawField.match(/^([-_a-z]+)(?:\:(.*))*$/); + var field = mm[1]; + // trimmer is not available in getAmbiguousCite + var trimmer = state.tmp.abbrev_trimmer; + if (mm[2]) { + if (trimmer && jurisdiction) { + if (!trimmer[jurisdiction]) { + trimmer[jurisdiction] = {}; + } + trimmer[jurisdiction][field] = mm[2]; + } + } else if (state.tmp.done_vars.indexOf(field) === -1) { + if (trimmer && jurisdiction) { + if (!trimmer.QUASHES[jurisdiction]) { + trimmer.QUASHES[jurisdiction] = {}; + } + trimmer.QUASHES[jurisdiction][field] = true; + } + state.tmp.done_vars.push(field); } } } @@ -17357,7 +17649,9 @@ CSL.Transform = function (state) { // hack syntax in this abbreviation short form. if (primary) { // The abbreviate() function could use a cleanup, after Zotero correct to use title-short - primary = quashCheck(primary); + if (!state.tmp.just_looking) { + primary = quashCheck(Item.jurisdiction, primary); + } } } if (publisherCheck(this, Item, primary, family_var)) { @@ -17435,7 +17729,10 @@ CSL.Transform = function (state) { primary_tok.strings.suffix = primary_tok.strings.suffix.replace(/[ .,]+$/,""); state.output.append(primary, primary_tok); state.tmp.probably_rendered_something = true; - + + if (primary === secondary) { + secondary = false; + } if (secondary) { secondary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.secondary].prefix; secondary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.secondary].suffix; @@ -17464,6 +17761,10 @@ CSL.Transform = function (state) { // Suppress supplementary multilingual info on subsequent // partners of a parallel cite? } + if (primary === tertiary) { + tertiary = false; + } + if (tertiary) { tertiary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.tertiary].prefix; tertiary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.tertiary].suffix; @@ -18611,11 +18912,11 @@ CSL.Util.Sort.strip_prepositions = function (str) { CSL.Util.substituteStart = function (state, target) { var element_trace, display, bib_first, func, choose_start, if_start, nodetypes; func = function (state, Item, item) { - if (item && item.parallel) { - state.tmp.group_context.tip.parallel_result = item.parallel; - } - if (item && item.repeats && Object.keys(item.repeats).length > 0) { - state.tmp.group_context.tip.parallel_repeats = item.repeats; + if (this.parallel_first) { + state.tmp.group_context.tip.parallel_first = this.parallel_first; + } + if (this.parallel_last) { + state.tmp.group_context.tip.parallel_last = this.parallel_last; } for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) { if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) { @@ -18634,6 +18935,7 @@ CSL.Util.substituteStart = function (state, target) { // Contains body code for both substitute and first-field/remaining-fields // formatting. // + nodetypes = ["number", "date", "names"]; if (("text" === this.name && !this.postponed_macro) || nodetypes.indexOf(this.name) > -1) { element_trace = function (state, Item, item) { @@ -18867,6 +19169,7 @@ CSL.Util.substituteEnd = function (state, target) { if ("names" === this.name || ("text" === this.name && this.variables_real !== "title")) { author_substitute = new CSL.Token("text", CSL.SINGLETON); + var substitution_name = this.name; func = function (state, Item) { if (state.tmp.area !== "bibliography") { return; @@ -18877,7 +19180,10 @@ CSL.Util.substituteEnd = function (state, target) { if (this.variables_real && !Item[this.variables_real]) { return; } - if (state.tmp.substituted_variable !== this.variables_real) { + // The logic of these two is not obvious. The effect is to enable placeholder substitution + // on a text macro name substitution, without printing both the text macro AND the placeholder. + // See https://forums.zotero.org/discussion/comment/350407 + if (this.variables_real && substitution_name === "names") { return; } @@ -18898,7 +19204,6 @@ CSL.Util.substituteEnd = function (state, target) { if (dosub && state.tmp.last_rendered_name && state.tmp.last_rendered_name.length > (i - 1) && name && !name.localeCompare(state.tmp.last_rendered_name[i])) { - str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]); state.tmp.name_node.children[i].blobs = [str]; if ("partial-first" === subrule) { @@ -18934,7 +19239,7 @@ CSL.Util.substituteEnd = function (state, target) { } else { state.tmp.name_node.top.blobs = [str]; } - state.tmp.substituted_variable = this.variables_real; + state.tmp.substituted_variable = substitution_name; } state.tmp.last_rendered_name = rendered_name; } @@ -19148,7 +19453,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { var symbolAnd = "\\s*&\\s*"; var andRex = new RegExp("^" + symbolAnd+ "$"); var joinerMatchRex = new RegExp("(" + symbolAnd + "|" + fullformAnd + "|;\\s+|,\\s+|\\s*\\\\*[\\-\\u2013]+\\s*)", "g"); - var joinerSplitRex = new RegExp("(?:" + symbolAnd + "|" + fullformAnd + "|;\\s+|,\\s+|\\s*\\\\*[\\-\\u2013]+\\s*|\\s*&\\s*)"); + var joinerSplitRex = new RegExp("(?:" + symbolAnd + "|" + fullformAnd + "|;\\s+|,\\s+|\\s*\\\\*[\\-\\u2013]+\\s*)"); // This guesses whether the symbol form is defined or not. // It's the best we can do, because when locales are built, all of the @@ -19193,7 +19498,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { var m = str.match(/^([^ ]+)/); if (m && !CSL.STATUTE_SUBDIV_STRINGS[m[1]]) { var embeddedLabel = null; - if (["locator", "locator-extra"].indexOf(variable) > -1) { + if (["locator", "locator-extra", "page"].indexOf(variable) > -1) { if (ItemObject.label) { embeddedLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[ItemObject.label]; } else { @@ -19210,21 +19515,26 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { } - function composeNumberInfo(origLabel, label, val, joiningSuffix) { + function composeNumberInfo(origLabel, label, val, joiningSuffix, parsePosition) { joiningSuffix = joiningSuffix ? joiningSuffix : ""; var info = {}; if (!label && !CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable]) { label = "var:"+variable; } - + if (label) { var m = label.match(/(\s*)([^\s]+)(\s*)/); + if (variable === "page" && parsePosition === 0 && ["p.", "pp."].indexOf(m[2]) === -1) { + info.gotosleepability = true; + info.labelVisibility = true; + } else { + info.labelVisibility = false; + } info.label = m[2]; info.origLabel = origLabel; info.labelSuffix = m[3] ? m[3] : ""; info.plural = 0; - info.labelVisibility = false; } var m = val.match(/^([0-9]*[a-zA-Z]+0*)?([0-9]+(?:[a-zA-Z]*|[-,a-zA-Z]+))$/); @@ -19259,16 +19569,38 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { str = normalizeFieldValue(str, defaultLabel); + var jmrex, jsrex, mystr; + if (str.indexOf("\\-") > -1) { + jmrex = new RegExp(joinerMatchRex.source.replace("\\-", "")); + jsrex = new RegExp(joinerSplitRex.source.replace("\\-", "")); + var lst = str.split("\\-"); + for (var i=0,ilen=lst.length;i0;j--) { if (lst[j-1] && (!lst[j].match(/^[0-9]+([-;,:a-zA-Z]*)$/) || !lst[j-1].match(/^[0-9]+([-;,:a-zA-Z]*)$/))) { @@ -19311,8 +19648,8 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { if (m.length > 0) { var slug = m[0].trim(); var notAlabel = !CSL.STATUTE_SUBDIV_STRINGS[slug] - || !me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[slug]) - || (["locator", "number", "locator-extra"].indexOf(variable) === -1 && CSL.STATUTE_SUBDIV_STRINGS[slug] !== variable); + || "undefined" === typeof me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[slug]) + || (["locator", "number", "locator-extra", "page"].indexOf(variable) === -1 && CSL.STATUTE_SUBDIV_STRINGS[slug] !== variable); if (notAlabel) { if (i === 0) { m = m.slice(1); @@ -19334,11 +19671,11 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { filteredOrigLabel = origLabel; } //var origLabel = j > 1 ? m[j-1] : ""; - str = lst[j] ? lst[j].trim() : ""; + mystr = lst[j] ? lst[j].trim() : ""; if (j === (lst.length-1)) { - values.push(composeNumberInfo(filteredOrigLabel, label, str, elems[i+1])); + values.push(composeNumberInfo(filteredOrigLabel, label, mystr, elems[i+1], i)); } else { - values.push(composeNumberInfo(filteredOrigLabel, label, str)); + values.push(composeNumberInfo(filteredOrigLabel, label, mystr, null, i)); } } } @@ -19372,7 +19709,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { currentLabelInfo.collapsible = false; } var mVal = val.match(/^[0-9]+([-,:a-zA-Z]*)$/); - var mCurrentLabel = master.value.match(/^[0-9]+([-,:a-zA-Z]*)$/); + var mCurrentLabel = master.value.match(/^(?:[0-9]+|[ixv]+)([-,:a-zA-Z]*|\-[\-0-9]+)$/); if (!val || !mVal || !mCurrentLabel || isEscapedHyphen) { currentLabelInfo.collapsible = false; if (!val || !mCurrentLabel) { @@ -19408,7 +19745,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { function fixLabelVisibility(values, groupStartPos, currentLabelInfo) { if (currentLabelInfo.label.slice(0, 4) !== "var:") { if (currentLabelInfo.pos === 0) { - if (["locator", "number", "locator-extra"].indexOf(variable) > -1) { + if (["locator", "number", "locator-extra", "page"].indexOf(variable) > -1) { // Actually, shouldn't we do this always? if (!me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label])) { values[currentLabelInfo.pos].labelVisibility = true; @@ -19418,7 +19755,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { // label embedded at the start of a field that // does not match the context, it should be // marked for rendering. - if (["locator", "number", "locator-extra"].indexOf(variable) === -1) { + if (["locator", "number", "locator-extra", "page"].indexOf(variable) === -1) { if (CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label] !== variable) { values[0].labelVisibility = true; } @@ -19525,7 +19862,7 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { function checkTerm(variable, val) { var ret = true; - if (["locator", "locator-extra"].indexOf(variable) > -1) { + if (["locator", "locator-extra", "page"].indexOf(variable) > -1) { var label; if (val.origLabel) { label = val.origLabel; @@ -19750,35 +20087,67 @@ CSL.Engine.prototype.processNumber = function (node, ItemObject, variable) { // Process only if there is a value. if ("undefined" !== typeof val && ("string" === typeof val || "number" === typeof val)) { - if ("number" === typeof val) { val = "" + val; } var defaultLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable]; - if (!this.tmp.shadow_numbers.values) { + if (this.tmp.shadow_numbers[variable].values.length === 0) { // XXX var values = parseString(val, defaultLabel); - + setSpaces(values); //print("setSpaces(): "+JSON.stringify(values, null, 2)); setPluralsAndNumerics(values); //print("setPluralsAndNumerics(): "+JSON.stringify(values, null, 2)); + for (var obj of values) { + if (!obj.numeric) obj.plural = 0; + } this.tmp.shadow_numbers[variable].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)); + } + setVariableParams(this.tmp.shadow_numbers, variable, values); } - - if (node) { - fixRanges(values); - - this.tmp.shadow_numbers[variable].masterStyling = setStyling(values); - //print("setStyling(): "+JSON.stringify(values, null, 2)); + + // hack in support for non-numeric numerics like "91 Civ. 5442 (RPP)|91 Civ. 5471" + var info = this.tmp.shadow_numbers[variable]; + if (variable === "number") { + if (info.values.length === 1 && info.values[0].value.indexOf("|") > -1) { + info.values[0].value = info.values[0].value.replace(/\|/g, ", "); + info.values[0].numeric = true; + info.values[0].plural = 1; + info.values[0].collapsible = false; + info.numeric = true; + info.plural = 1; + info.collapsible = false; + } } - - setVariableParams(this.tmp.shadow_numbers, variable, values); - //print("OK "+JSON.stringify(values, ["label", "origLabel", "labelSuffix", "particle", "collapsible", "value", "numeric", "joiningSuffix", "labelVisibility", "plural"], 2)); + if (info.values.length === 1) { + if (info.values[0].value.match(/^[0-9]+(?:\/[0-9]+)+$/)) { + info.values[0].numeric = true; + info.values[0].plural = 0; + info.values[0].collapsible = false; + info.numeric = true; + info.plural = 0; + info.collapsible = false; + } + } + if (variable === "page") { + if (info.values.length > 0) { + if (info.values[0].gotosleepability) { + info.labelForm = "short"; + } + } + } + //this.sys.print("OK "+JSON.stringify(values, ["label", "origLabel", "labelSuffix", "particle", "collapsible", "value", "numeric", "joiningSuffix", "labelVisibility", "plural"], 2)); } }; @@ -19798,6 +20167,7 @@ CSL.Util.outputNumericField = function(state, varname, itemID) { var labelCapitalizeIfFirst = state.tmp.shadow_numbers[varname].labelCapitalizeIfFirst; var labelDecorations = state.tmp.shadow_numbers[varname].labelDecorations; var lastLabelName = null; + for (var i=0,ilen=nums.length;i -1) { if (tag.match(_tagRex.close) @@ -20571,7 +20930,11 @@ CSL.Util.FlipFlopper = function(state) { doppel.tags[tagInfo.fixtag] = ""; } if (_nestingState.length > 0) { - _nestingState.pop(); + if (tag !== "\'") { + _nestingState.pop(); + } else { + break; + } } else { break; } @@ -21730,7 +22093,10 @@ CSL.Registry = function (state) { // See CSL.NameOutput.prototype.outputNames // and CSL.Registry.prototype.doinserts this.authorstrings = {}; - + + // for parallel delimiter support + this.masterMap = {}; + // // shared scratch vars this.mylist = []; @@ -22447,11 +22813,9 @@ CSL.getSortKeys = function (Item, key_type) { this.tmp.extension = "_sort"; this.tmp.disambig_override = true; this.tmp.disambig_request = false; - this.parallel.use_parallels = (this.parallel.use_parallels === true || this.parallel.use_parallels === null) ? null : false; this.tmp.suppress_decorations = true; CSL.getCite.call(this, Item); this.tmp.suppress_decorations = false; - this.parallel.use_parallels = this.parallel.use_parallels === null ? true : false; this.tmp.disambig_override = false; len = this[key_type].keys.length; for (pos = 0; pos < len; pos += 1) {