www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

citeproc.js (693206B)


      1 /*
      2  * Copyright (c) 2009-2016 Frank Bennett
      3  * 
      4  * 	This program is free software: you can redistribute it and/or
      5  * 	modify it under EITHER
      6  * 
      7  *       * the terms of the Common Public Attribution License (CPAL) as
      8  * 	    published by the Open Source Initiative, either version 1 of
      9  * 	    the CPAL, or (at your option) any later version; OR
     10  * 
     11  *       * the terms of the GNU Affero General Public License (AGPL)
     12  *         as published by the Free Software Foundation, either version
     13  *         3 of the AGPL, or (at your option) any later version.
     14  * 
     15  * 	This program is distributed in the hope that it will be useful,
     16  * 	but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * 	Affero General Public License for more details.
     19  * 
     20  * 	You should have received copies of the Common Public Attribution
     21  *     License and of the GNU Affero General Public License along with
     22  *     this program.  If not, see <https://opensource.org/licenses/> or
     23  *     <http://www.gnu.org/licenses/> respectively.
     24  */
     25 
     26 var CSL = {
     27     PROCESSOR_VERSION: "1.1.206",
     28     CONDITION_LEVEL_TOP: 1,
     29     CONDITION_LEVEL_BOTTOM: 2,
     30     PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/,
     31     LOCATOR_LABELS_REGEXP: new RegExp("^((art|ch|subch|col|fig|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\\.)\\s+(.*)"),
     32     STATUTE_SUBDIV_GROUPED_REGEX: /((?:^| )(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/g,
     33     STATUTE_SUBDIV_PLAIN_REGEX: /(?:(?:^| )(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/,
     34     STATUTE_SUBDIV_PLAIN_REGEX_FRONT: /(?:^\s*[.,;]*\s*(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/,
     35     STATUTE_SUBDIV_STRINGS: {
     36         "art.": "article",
     37         "bk.": "book",
     38         "ch.": "chapter",
     39         "subch.": "subchapter",
     40         "p.": "page",
     41         "pp.": "page",
     42         "para.": "paragraph",
     43         "subpara.": "subparagraph",
     44         "pt.": "part",
     45         "r.": "rule",
     46         "sec.": "section",
     47         "subsec.": "subsection",
     48         "sch.": "schedule",
     49         "tit.": "title",
     50         "col.": "column",
     51         "fig.": "figure",
     52         "fol.": "folio",
     53         "l.": "line",
     54         "n.": "note",
     55         "no.": "issue",
     56         "op.": "opus",
     57         "sv.": "sub-verbo",
     58         "vrs.": "verse",
     59         "vol.": "volume"
     60     },
     61     STATUTE_SUBDIV_STRINGS_REVERSE: {
     62         "article": "art.",
     63         "book": "bk.",
     64         "chapter": "ch.",
     65         "subchapter": "subch.",
     66         "page": "p.",
     67         "paragraph": "para.",
     68         "subparagraph": "subpara.",
     69         "part": "pt.",
     70         "rule": "r.",
     71         "section": "sec.",
     72         "subsection": "subsec.",
     73         "schedule": "sch.",
     74         "title": "tit.",
     75         "column": "col.",
     76         "figure": "fig.",
     77         "folio": "fol.",
     78         "line": "l.",
     79         "note": "n.",
     80         "issue": "no.",
     81         "opus": "op.",
     82         "sub-verbo": "sv.",
     83         "sub verbo": "sv.",
     84         "verse": "vrs.",
     85         "volume": "vol."
     86     },
     87     LOCATOR_LABELS_MAP: {
     88         "art": "article",
     89         "bk": "book",
     90         "ch": "chapter",
     91         "subch": "subchapter",
     92         "col": "column",
     93         "fig": "figure",
     94         "fol": "folio",
     95         "l": "line",
     96         "n": "note",
     97         "no": "issue",
     98         "op": "opus",
     99         "p": "page",
    100         "pp": "page",
    101         "para": "paragraph",
    102         "subpara": "subparagraph",
    103         "pt": "part",
    104         "r": "rule",
    105 		"sec": "section",
    106 		"subsec": "subsection",
    107 		"sv": "sub-verbo",
    108         "sch": "schedule",
    109         "tit": "title",
    110         "vrs": "verse",
    111         "vol": "volume"
    112     },
    113     MODULE_MACROS: {
    114         "juris-pretitle": true,
    115         "juris-title": true,
    116         "juris-pretitle-short": true,
    117         "juris-title-short": true,
    118         "juris-main": true,
    119         "juris-main-short": true,
    120         "juris-tail": true,
    121         "juris-tail-short": true,
    122         "juris-locator": true
    123     },
    124     MODULE_TYPES: {
    125         "legal_case": true,
    126         "legislation": true,
    127         "bill": true,
    128         "hearing": true,
    129         "gazette": true,
    130         "report": true,
    131         "regulation": true,
    132         "standard": true
    133     },
    134     NestedBraces: [
    135         ["(", "["],
    136         [")", "]"]
    137     ],
    138     checkNestedBrace: function(state) {
    139         if (state.opt.xclass === "note") {
    140             this.depth = 0;
    141             this.update = function(str) {
    142                 var str = str ? str : '';
    143                 var lst = str.split(/([\(\)])/);
    144                 for (var i=1,ilen=lst.length;i<ilen;i += 2) {
    145                     if (lst[i] === '(') {
    146                         if (1 === (this.depth % 2)) {
    147                             lst[i] = '['
    148                         }
    149                         this.depth += 1;
    150                     } else if (lst[i] === ')') {
    151                         if (0 === (this.depth % 2)) {
    152                             lst[i] = ']'
    153                         }
    154                         this.depth -= 1;
    155                     }
    156                 }
    157                 var ret = lst.join("");
    158                 return ret;
    159             }
    160         } else {
    161             this.update = function(str) {
    162                 return str;
    163             }
    164         };
    165     },
    166     MULTI_FIELDS: ["event", "publisher", "publisher-place", "event-place", "title", "container-title", "collection-title", "authority","genre","title-short","medium","country","jurisdiction","archive","archive-place"],
    167     LangPrefsMap: {
    168         "title":"titles",
    169         "title-short":"titles",
    170         "event":"titles",
    171         "genre":"titles",
    172         "medium":"titles",
    173         "container-title":"journals",
    174         "collection-title":"journals",
    175         "archive":"journals",
    176         "publisher":"publishers",
    177         "authority":"publishers",
    178         "publisher-place": "places",
    179         "event-place": "places",
    180         "archive-place": "places",
    181         "jurisdiction": "places",
    182         "number": "number",
    183         "edition":"number",
    184         "issue":"number",
    185         "volume":"number"
    186     },
    187     AbbreviationSegments: function () {
    188         this["container-title"] = {};
    189         this["collection-title"] = {};
    190         this["institution-entire"] = {};
    191         this["institution-part"] = {};
    192         this.nickname = {};
    193         this.number = {};
    194         this.title = {};
    195         this.place = {};
    196         this.hereinafter = {};
    197         this.classic = {};
    198         this["container-phrase"] = {};
    199         this["title-phrase"] = {};
    200     },
    201     FIELD_CATEGORY_REMAP: {
    202         "title": "title",
    203         "container-title": "container-title",
    204         "collection-title": "collection-title",
    205         "country": "place",
    206         "number": "number",
    207         "place": "place",
    208         "archive": "collection-title",
    209         "title-short": "title",
    210         "genre": "title",
    211         "event": "title",
    212         "medium": "title",
    213 		"archive-place": "place",
    214 		"publisher-place": "place",
    215 		"event-place": "place",
    216 		"jurisdiction": "place",
    217 		"language-name": "place",
    218 		"language-name-original": "place",
    219         "call-number": "number",
    220         "chapter-number": "number",
    221         "collection-number": "number",
    222         "edition": "number",
    223         "page": "number",
    224         "issue": "number",
    225         "locator": "number",
    226         "number-of-pages": "number",
    227         "number-of-volumes": "number",
    228         "volume": "number",
    229         "citation-number": "number",
    230         "publisher": "institution-part"
    231     },
    232     parseLocator: function(item) {
    233         if (this.opt.development_extensions.locator_date_and_revision) {
    234             if (item.locator) {
    235                 item.locator = "" + item.locator;
    236                 var idx = item.locator.indexOf("|");
    237                 if (idx > -1) {
    238                     var raw_locator = item.locator;
    239                     item.locator = raw_locator.slice(0, idx);
    240                     raw_locator = raw_locator.slice(idx + 1);
    241                     var m = raw_locator.match(/^([0-9]{4}-[0-9]{2}-[0-9]{2}).*/);
    242                     if (m) {
    243                         item["locator-date"] = this.fun.dateparser.parseDateToObject(m[1]);
    244                         raw_locator = raw_locator.slice(m[1].length);
    245                     }
    246                     item["locator-extra"] = raw_locator.replace(/^\s+/, "").replace(/\s+$/, "");
    247                 }
    248             }
    249         }
    250         if (item.locator) {
    251             item.locator = ("" + item.locator).replace(/\s+$/, '');
    252         }
    253         return item;
    254     },
    255     normalizeLocaleStr: function(str) {
    256         if (!str) return;
    257         var lst = str.split('-');
    258         lst[0] = lst[0].toLowerCase();
    259         if (lst[1]) {
    260             lst[1] = lst[1].toUpperCase();
    261         }
    262         return lst.join("-");
    263     },
    264     isDatePart: function(str, less, more) {
    265         if (str.length > less && str.length < more && parseInt(str)) {
    266             return true
    267         } else {
    268             return false;
    269         }
    270     },
    271     isDateString: function(str) {
    272         if (!str) return false;
    273         var strLst = str.split("-");
    274         if (strLst.length > 0) {
    275             if (!isDatePart(strLst[0], 3, 5)) {
    276                 return false;
    277             }
    278         }
    279         if (strLst.length > 1) {
    280             if (!isDatePart(strLst[1], 0, 3)) {
    281                 return false
    282             }
    283         }
    284         if (strLst.length > 2) {
    285             if (!isDatePart(strLst[2], 0, 3)) {
    286                 return false
    287             }
    288         }
    289         if (strLst.length > 3) {
    290             return false;
    291         }
    292         return true;
    293     },
    294     parseNoteFieldHacks: function(Item, validFieldsForType, allowDateOverride) {
    295         if ("string" !== typeof Item.note) return;
    296         var elems = [];
    297         var lines = Item.note.split('\n');
    298         var lastline = "";
    299         for (var i=0, ilen=lines.length; i<ilen; i++) {
    300             var line = lines[i];
    301             var elems = [];
    302             var m = line.match(CSL.NOTE_FIELDS_REGEXP);
    303             if (m) {
    304                 var splt = line.split(CSL.NOTE_FIELDS_REGEXP);
    305                 for (var j=0,jlen=(splt.length-1);j<jlen;j++) {
    306                     elems.push(splt[j]);
    307                     elems.push(m[j]);
    308                 }
    309                 elems.push(splt[splt.length-1])
    310                 for (var j=1,jlen=elems.length;j<jlen;j += 2) {
    311                     if (elems[j-1].trim() && (i>0 || j>1) && !elems[j-1].match(CSL.NOTE_FIELD_REGEXP)) {
    312                         break
    313                     } else {
    314                         elems[j] = '\n' + elems[j].slice(2,-1).trim() + '\n';
    315                     }
    316                 }
    317                 lines[i] = elems.join('');
    318             }
    319         }
    320         lines = lines.join('\n').split('\n');
    321         var offset = 0;
    322         var names = {};
    323         for (var i=0,ilen=lines.length;i<ilen;i++) {
    324             var line = lines[i];
    325             var mm = line.match(CSL.NOTE_FIELD_REGEXP);
    326             if (!line.trim()) {
    327                 continue;
    328             } else if (!mm) {
    329                 if (i === 0) {
    330                     continue;
    331                 } else {
    332                     offset = i;
    333                     break;
    334                 }
    335             }
    336             var key = mm[1];
    337             var val = mm[2].replace(/^\s+/, "").replace(/\s+$/, "");
    338             if (key === "type") {
    339                 Item.type = val;
    340                 lines[i] = "";
    341             } else if (CSL.DATE_VARIABLES.indexOf(key) > -1) {
    342                 if (allowDateOverride) {
    343                     Item[key] = {raw: val};
    344                     if (!validFieldsForType || (validFieldsForType[key] && isDateString(val))) {
    345                         lines[i] = "";
    346                     }
    347                 }
    348             } else if (!Item[key]) {
    349                 if (CSL.NAME_VARIABLES.indexOf(key) > -1) {
    350                     if (!names[key]) {
    351                         names[key] = [];
    352                     }
    353                     var lst = val.split(/\s*\|\|\s*/);
    354                     if (lst.length === 1) {
    355                         names[key].push({literal:lst[0]});
    356                     } else if (lst.length === 2) {
    357                         var name = {family:lst[0],given:lst[1]};
    358                         CSL.parseParticles(name);
    359                         names[key].push(name);
    360                     }
    361                 } else {
    362                     Item[key] = val;
    363                 }
    364                 if (!validFieldsForType || validFieldsForType[key]) {
    365                     lines[i] = "";
    366                 }
    367             }
    368         }
    369         for (var key in names) {
    370             Item[key] = names[key];
    371         }
    372         if (validFieldsForType) {
    373             if (lines[offset].trim()) {
    374                 lines[offset] = '\n' + lines[offset]
    375             }
    376             for (var i=offset-1;i>-1;i--) {
    377                 if (!lines[i].trim()) {
    378                     lines = lines.slice(0, i).concat(lines.slice(i + 1));
    379                 }
    380             }
    381         }
    382         Item.note = lines.join("\n").trim();
    383     },
    384     GENDERS: ["masculine", "feminine"],
    385     ERROR_NO_RENDERED_FORM: 1,
    386     PREVIEW: "Just for laughs.",
    387     ASSUME_ALL_ITEMS_REGISTERED: 2,
    388     START: 0,
    389     END: 1,
    390     SINGLETON: 2,
    391     SEEN: 6,
    392     SUCCESSOR: 3,
    393     SUCCESSOR_OF_SUCCESSOR: 4,
    394     SUPPRESS: 5,
    395     SINGULAR: 0,
    396     PLURAL: 1,
    397     LITERAL: true,
    398     BEFORE: 1,
    399     AFTER: 2,
    400     DESCENDING: 1,
    401     ASCENDING: 2,
    402     ONLY_FIRST: 1,
    403     ALWAYS: 2,
    404     ONLY_LAST: 3,
    405     FINISH: 1,
    406     POSITION_FIRST: 0,
    407     POSITION_SUBSEQUENT: 1,
    408     POSITION_IBID: 2,
    409     POSITION_IBID_WITH_LOCATOR: 3,
    410     MARK_TRAILING_NAMES: true,
    411     POSITION_TEST_VARS: ["position", "first-reference-note-number", "near-note"],
    412     AREAS: ["citation", "citation_sort", "bibliography", "bibliography_sort"],
    413     CITE_FIELDS: ["first-reference-note-number", "locator", "locator-extra"],
    414     MINIMAL_NAME_FIELDS: ["literal", "family"],
    415     SWAPPING_PUNCTUATION: [".", "!", "?", ":", ","],
    416     TERMINAL_PUNCTUATION: [":", ".", ";", "!", "?", " "],
    417     NONE: 0,
    418     NUMERIC: 1,
    419     POSITION: 2,
    420     COLLAPSE_VALUES: ["citation-number", "year", "year-suffix"],
    421     DATE_PARTS: ["year", "month", "day"],
    422     DATE_PARTS_ALL: ["year", "month", "day", "season"],
    423     DATE_PARTS_INTERNAL: ["year", "month", "day", "year_end", "month_end", "day_end"],
    424     NAME_PARTS: ["non-dropping-particle", "family", "given", "dropping-particle", "suffix", "literal"],
    425     DECORABLE_NAME_PARTS: ["given", "family", "suffix"],
    426     DISAMBIGUATE_OPTIONS: [
    427         "disambiguate-add-names",
    428         "disambiguate-add-givenname",
    429         "disambiguate-add-year-suffix"
    430     ],
    431     GIVENNAME_DISAMBIGUATION_RULES: [
    432         "all-names",
    433         "all-names-with-initials",
    434         "primary-name",
    435         "primary-name-with-initials",
    436         "by-cite"
    437     ],
    438     NAME_ATTRIBUTES: [
    439         "and",
    440         "delimiter-precedes-last",
    441         "delimiter-precedes-et-al",
    442         "initialize-with",
    443         "initialize",
    444         "name-as-sort-order",
    445         "sort-separator",
    446         "et-al-min",
    447         "et-al-use-first",
    448         "et-al-subsequent-min",
    449         "et-al-subsequent-use-first",
    450         "form",
    451         "prefix",
    452         "suffix",
    453         "delimiter"
    454     ],
    455     PARALLEL_MATCH_VARS: ["container-title"],
    456     PARALLEL_TYPES: ["bill","gazette","regulation","legislation","legal_case","treaty","article-magazine","article-journal"],
    457     PARALLEL_COLLAPSING_MID_VARSET: ["volume", "issue", "container-title", "section", "collection-number"],
    458     LOOSE: 0,
    459     STRICT: 1,
    460     TOLERANT: 2,
    461     PREFIX_PUNCTUATION: /[.;:]\s*$/,
    462     SUFFIX_PUNCTUATION: /^\s*[.;:,\(\)]/,
    463     NUMBER_REGEXP: /(?:^\d+|\d+$)/,
    464     NAME_INITIAL_REGEXP: /^([A-Z\u00c0-\u017f\u0400-\u042f\u0590-\u05d4\u05d6-\u05ff\u0600-\u06ff\u0370\u0372\u0376\u0386\u0388-\u03ab\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03fd-\u03ff])([a-zA-Z\u00c0-\u017f\u0400-\u052f\u0600-\u06ff\u0370-\u03ff\u1f00-\u1fff]*|)/,
    465     ROMANESQUE_REGEXP: /[-0-9a-zA-Z\u00c0-\u017f\u0370-\u03ff\u0400-\u052f\u0590-\u05d4\u05d6-\u05ff\u1f00-\u1fff\u0600-\u06ff\u200c\u200d\u200e\u0218\u0219\u021a\u021b\u202a-\u202e]/,
    466     ROMANESQUE_NOT_REGEXP: /[^a-zA-Z\u00c0-\u017f\u0370-\u03ff\u0400-\u052f\u0590-\u05d4\u05d6-\u05ff\u1f00-\u1fff\u0600-\u06ff\u200c\u200d\u200e\u0218\u0219\u021a\u021b\u202a-\u202e]/g,
    467     STARTSWITH_ROMANESQUE_REGEXP: /^[&a-zA-Z\u00c0-\u017f\u0370-\u03ff\u0400-\u052f\u0590-\u05d4\u05d6-\u05ff\u1f00-\u1fff\u0600-\u06ff\u200c\u200d\u200e\u0218\u0219\u021a\u021b\u202a-\u202e]/,
    468     ENDSWITH_ROMANESQUE_REGEXP: /[.;:&a-zA-Z\u00c0-\u017f\u0370-\u03ff\u0400-\u052f\u0590-\u05d4\u05d6-\u05ff\u1f00-\u1fff\u0600-\u06ff\u200c\u200d\u200e\u0218\u0219\u021a\u021b\u202a-\u202e]$/,
    469     ALL_ROMANESQUE_REGEXP: /^[a-zA-Z\u00c0-\u017f\u0370-\u03ff\u0400-\u052f\u0590-\u05d4\u05d6-\u05ff\u1f00-\u1fff\u0600-\u06ff\u200c\u200d\u200e\u0218\u0219\u021a\u021b\u202a-\u202e]+$/,
    470     VIETNAMESE_SPECIALS: /[\u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]/,
    471     VIETNAMESE_NAMES: /^(?:(?:[.AaBbCcDdEeGgHhIiKkLlMmNnOoPpQqRrSsTtUuVvXxYy \u00c0-\u00c3\u00c8-\u00ca\u00cc\u00cd\u00d2-\u00d5\u00d9\u00da\u00dd\u00e0-\u00e3\u00e8-\u00ea\u00ec\u00ed\u00f2-\u00f5\u00f9\u00fa\u00fd\u0101\u0103\u0110\u0111\u0128\u0129\u0168\u0169\u01a0\u01a1\u01af\u01b0\u1ea0-\u1ef9]{2,6})(\s+|$))+$/,
    472     NOTE_FIELDS_REGEXP: /\{:(?:[\-_a-z]+|[A-Z]+):[^\}]+\}/g,
    473     NOTE_FIELD_REGEXP: /^([\-_a-z]+|[A-Z]+):\s*([^\}]+)$/,
    474 	PARTICLE_GIVEN_REGEXP: /^([^ ]+(?:\u02bb |\u2019 | |\' ) *)(.+)$/,
    475 	PARTICLE_FAMILY_REGEXP: /^([^ ]+(?:\-|\u02bb|\u2019| |\') *)(.+)$/,
    476     DISPLAY_CLASSES: ["block", "left-margin", "right-inline", "indent"],
    477     NAME_VARIABLES: [
    478         "author",
    479         "editor",
    480         "translator",
    481         "contributor",
    482         "collection-editor",
    483         "composer",
    484         "container-author",
    485         "director",
    486         "editorial-director",
    487         "interviewer",
    488         "original-author",
    489         "recipient"
    490     ],
    491     NUMERIC_VARIABLES: [
    492         "call-number",
    493         "chapter-number",
    494         "collection-number",
    495         "edition",
    496         "page",
    497         "issue",
    498         "locator",
    499         "number",
    500         "number-of-pages",
    501         "number-of-volumes",
    502         "volume",
    503         "citation-number"
    504     ],
    505     DATE_VARIABLES: [
    506         "locator-date", 
    507         "issued", 
    508         "event-date", 
    509         "accessed", 
    510         "container", 
    511         "original-date",
    512         "publication-date",
    513         "original-date",
    514         "available-date",
    515         "submitted"
    516     ],
    517     TITLE_FIELD_SPLITS: function(seg) {
    518         var keys = ["title", "short", "main", "sub"];
    519         var ret = {};
    520         for (var i=0,ilen=keys.length;i<ilen;i++) {
    521             ret[keys[i]] = seg + "title" + (keys[i] === "title" ? "" : "-" + keys[i]);
    522         }
    523         return ret;
    524     },
    525     TAG_USEALL: function (str) {
    526         var ret, open, close, end;
    527         ret = [""];
    528         open = str.indexOf("<");
    529         close = str.indexOf(">");
    530         while (open > -1 && close > -1) {
    531             if (open > close) {
    532                 end = open + 1;
    533             } else {
    534                 end = close + 1;
    535             }
    536             if (open < close && str.slice(open + 1, close).indexOf("<") === -1) {
    537                 ret[ret.length - 1] += str.slice(0, open);
    538                 ret.push(str.slice(open, close + 1));
    539                 ret.push("");
    540                 str = str.slice(end);
    541             } else {
    542                 ret[ret.length - 1] += str.slice(0, close + 1);
    543                 str = str.slice(end);
    544             }
    545             open = str.indexOf("<");
    546             close = str.indexOf(">");
    547         }
    548         ret[ret.length - 1] += str;
    549         return ret;
    550     },
    551     demoteNoiseWords: function (state, fld, drop_or_demote) {
    552         var SKIP_WORDS = state.locale[state.opt.lang].opts["leading-noise-words"];
    553         if (fld && drop_or_demote) {
    554             fld = fld.split(/\s+/);
    555             fld.reverse();
    556             var toEnd = [];
    557             for (var j  = fld.length - 1; j > -1; j += -1) {
    558                 if (SKIP_WORDS.indexOf(fld[j].toLowerCase()) > -1) {
    559                     toEnd.push(fld.pop());
    560                 } else {
    561                     break;
    562                 }
    563             }
    564             fld.reverse();
    565             var start = fld.join(" ");
    566             var end = toEnd.join(" ");
    567             if ("drop" === drop_or_demote || !end) {
    568                 fld = start;
    569             } else if ("demote" === drop_or_demote) {
    570                 fld = [start, end].join(", ");
    571             }
    572         }
    573         return fld;
    574     },
    575     extractTitleAndSubtitle: function (Item) {
    576         var segments = ["", "container-"];
    577         for (var i=0,ilen=segments.length;i<ilen;i++) {
    578             var seg = segments[i];
    579             var title = CSL.TITLE_FIELD_SPLITS(seg);
    580             var langs = [false];
    581             if (Item.multi) {
    582                 for (var lang in Item.multi._keys[title.short]) {
    583                     langs.push(lang);
    584                 }
    585             }
    586             for (var j=0,jlen=langs.length;j<ilen;j++) {
    587                 var lang = langs[j];
    588                 var vals = {};
    589                 if (lang) {
    590                     if (Item.multi._keys[title.title]) {
    591                         vals[title.title] = Item.multi._keys[title.title][lang];
    592                     }
    593                     if (Item.multi._keys[title["short"]]) {
    594                         vals[title["short"]] = Item.multi._keys[title["short"]][lang];
    595                     }
    596                 } else {
    597                     vals[title.title] = Item[title.title];
    598                     vals[title["short"]] = Item[title["short"]];
    599                 }
    600                 vals[title.main] = vals[title.title];
    601                 vals[title.sub] = false;
    602                 if (vals[title.title] && vals[title["short"]]) {
    603                     var shortTitle = vals[title["short"]];
    604                     var offset = shortTitle.length;
    605                     if (vals[title.title].slice(0,offset) === shortTitle && vals[title.title].slice(offset).match(/^\s*:/)) {
    606                         vals[title.main] = vals[title.title].slice(0,offset).replace(/\s+$/,"");
    607                         vals[title.sub] = vals[title.title].slice(offset).replace(/^\s*:\s*/,"");
    608                     }
    609                 }
    610                 if (lang) {
    611                     for (var key in vals) {
    612                         if (!Item.multi._keys[key]) {
    613                             Item.multi._keys[key] = {};
    614                         }
    615                         Item.multi._keys[key][lang] = vals[key];
    616                     }
    617                 } else {
    618                     for (var key in vals) {
    619                         Item[key] = vals[key];
    620                     }
    621                 }
    622             }
    623         }
    624     },
    625     titlecaseSentenceOrNormal: function(state, Item, seg, lang, sentenceCase) {
    626         var title = CSL.TITLE_FIELD_SPLITS(seg);
    627         var vals = {};
    628         if (lang && Item.multi) {
    629             if (Item.multi._keys[title.title]) {
    630                 vals[title.title] = Item.multi._keys[title.title][lang];
    631             }
    632             if (Item.multi._keys[title.main]) {
    633                 vals[title.main] = Item.multi._keys[title.main][lang];
    634             }
    635             if (Item.multi._keys[title.sub]) {
    636                 vals[title.sub] = Item.multi._keys[title.sub][lang];
    637             }
    638         } else {
    639             vals[title.title] = Item[title.title];
    640             vals[title.main] = Item[title.main];
    641             vals[title.sub] = Item[title.sub];
    642         }
    643         if (vals[title.main] && vals[title.sub]) {
    644             var mainTitle = vals[title.main];
    645             var subTitle = vals[title.sub];
    646             if (sentenceCase) {
    647                 mainTitle = CSL.Output.Formatters.sentence(state, mainTitle);
    648                 subTitle = CSL.Output.Formatters.sentence(state, subTitle);
    649             } else {
    650                 subTitle = CSL.Output.Formatters["capitalize-first"](state, subTitle);
    651             }
    652             return [mainTitle, subTitle].join(vals[title.title].slice(mainTitle.length, -1 * subTitle.length));
    653         } else {
    654             if (sentenceCase) {
    655                 return CSL.Output.Formatters.sentence(state, vals[title.title]);
    656             } else {
    657                 return vals[title.title];
    658             }
    659         }
    660     },
    661     getSafeEscape: function(state) {
    662         if (["bibliography", "citation"].indexOf(state.tmp.area) > -1) {
    663             var callbacks = [];
    664             if (state.opt.development_extensions.thin_non_breaking_space_html_hack && state.opt.mode === "html") {
    665                 callbacks.push(function (txt) {
    666                     return txt.replace(/\u202f/g, '<span style="white-space:nowrap">&thinsp;</span>');
    667                 });
    668             }
    669             if (callbacks.length) {
    670                 return function (txt) {
    671                     for (var i = 0, ilen = callbacks.length; i < ilen; i += 1) {
    672                         txt = callbacks[i](txt);
    673                     }
    674                     return CSL.Output.Formats[state.opt.mode].text_escape(txt);
    675                 }
    676             } else {
    677                 return CSL.Output.Formats[state.opt.mode].text_escape;
    678             }
    679         } else {
    680             return function (txt) { return txt; };
    681         }
    682     },
    683     SKIP_WORDS: ["about","above","across","afore","after","against","along","alongside","amid","amidst","among","amongst","anenst","apropos","apud","around","as","aside","astride","at","athwart","atop","barring","before","behind","below","beneath","beside","besides","between","beyond","but","by","circa","despite","down","during","except","for","forenenst","from","given","in","inside","into","lest","like","modulo","near","next","notwithstanding","of","off","on","onto","out","over","per","plus","pro","qua","sans","since","than","through"," thru","throughout","thruout","till","to","toward","towards","under","underneath","until","unto","up","upon","versus","vs.","v.","vs","v","via","vis-à-vis","with","within","without","according to","ahead of","apart from","as for","as of","as per","as regards","aside from","back to","because of","close to","due to","except for","far from","inside of","instead of","near to","next to","on to","out from","out of","outside of","prior to","pursuant to","rather than","regardless of","such as","that of","up to","where as","or", "yet", "so", "for", "and", "nor", "a", "an", "the", "de", "d'", "von", "van", "c", "et", "ca"],
    684     FORMAT_KEY_SEQUENCE: [
    685         "@strip-periods",
    686         "@font-style",
    687         "@font-variant",
    688         "@font-weight",
    689         "@text-decoration",
    690         "@vertical-align",
    691         "@quotes"
    692     ],
    693     INSTITUTION_KEYS: [
    694         "font-style",
    695         "font-variant",
    696         "font-weight",
    697         "text-decoration",
    698         "text-case"
    699     ],
    700     SUFFIX_CHARS: "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z",
    701     ROMAN_NUMERALS: [
    702         [ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ],
    703         [ "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ],
    704         [ "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ],
    705         [ "", "m", "mm", "mmm", "mmmm", "mmmmm"]
    706     ],
    707     CREATORS: [
    708         "author",
    709         "editor",
    710         "contributor",
    711         "translator",
    712         "recipient",
    713         "interviewer",
    714         "composer",
    715         "original-author",
    716         "container-author",
    717         "collection-editor"
    718     ],
    719     LANGS: {
    720         "af-ZA":"Afrikaans",
    721         "ar":"Arabic",
    722         "bg-BG":"Bulgarian",
    723         "ca-AD":"Catalan",
    724         "cs-CZ":"Czech",
    725         "da-DK":"Danish",
    726         "de-AT":"Austrian",
    727         "de-CH":"German (CH)",
    728         "de-DE":"German (DE)",
    729         "el-GR":"Greek",
    730         "en-GB":"English (GB)",
    731         "en-US":"English (US)",
    732         "es-ES":"Spanish",
    733         "et-EE":"Estonian",
    734         "eu":"European",
    735         "fa-IR":"Persian",
    736         "fi-FI":"Finnish",
    737         "fr-CA":"French (CA)",
    738         "fr-FR":"French (FR)",
    739         "he-IL":"Hebrew",
    740         "hr-HR":"Croatian",
    741         "hu-HU":"Hungarian",
    742         "is-IS":"Icelandic",
    743         "it-IT":"Italian",
    744         "ja-JP":"Japanese",
    745         "km-KH":"Khmer",
    746         "ko-KR":"Korean",
    747         "lt-LT":"Lithuanian",
    748         "lv-LV":"Latvian",
    749         "mn-MN":"Mongolian",
    750         "nb-NO":"Norwegian (Bokmål)",
    751         "nl-NL":"Dutch",
    752         "nn-NO":"Norwegian (Nynorsk)",
    753         "pl-PL":"Polish",
    754         "pt-BR":"Portuguese (BR)",
    755         "pt-PT":"Portuguese (PT)",
    756         "ro-RO":"Romanian",
    757         "ru-RU":"Russian",
    758         "sk-SK":"Slovak",
    759         "sl-SI":"Slovenian",
    760         "sr-RS":"Serbian",
    761         "sv-SE":"Swedish",
    762         "th-TH":"Thai",
    763         "tr-TR":"Turkish",
    764         "uk-UA":"Ukranian",
    765         "vi-VN":"Vietnamese",
    766         "zh-CN":"Chinese (CN)",
    767         "zh-TW":"Chinese (TW)"
    768     },
    769     LANG_BASES: {
    770         af: "af_ZA",
    771         ar: "ar",
    772         bg: "bg_BG",
    773         ca: "ca_AD",
    774         cs: "cs_CZ",
    775         da: "da_DK",
    776         de: "de_DE",
    777         el: "el_GR",
    778         en: "en_US",
    779         es: "es_ES",
    780         et: "et_EE",
    781         eu: "eu",
    782         fa: "fa_IR",
    783         fi: "fi_FI",
    784         fr: "fr_FR",
    785         he: "he_IL",
    786         hr: "hr-HR",
    787         hu: "hu_HU",
    788         is: "is_IS",
    789         it: "it_IT",
    790         ja: "ja_JP",
    791         km: "km_KH",
    792         ko: "ko_KR",
    793         lt: "lt_LT",
    794         lv: "lv-LV",
    795         mn: "mn_MN",
    796         nb: "nb_NO",
    797         nl: "nl_NL",
    798         nn: "nn-NO",
    799         pl: "pl_PL",
    800         pt: "pt_PT",
    801         ro: "ro_RO",
    802         ru: "ru_RU",
    803         sk: "sk_SK",
    804         sl: "sl_SI",
    805         sr: "sr_RS",
    806         sv: "sv_SE",
    807         th: "th_TH",
    808         tr: "tr_TR",
    809         uk: "uk_UA",
    810         vi: "vi_VN",
    811         zh: "zh_CN"
    812     },
    813     SUPERSCRIPTS: {
    814         "\u00AA": "\u0061",
    815         "\u00B2": "\u0032",
    816         "\u00B3": "\u0033",
    817         "\u00B9": "\u0031",
    818         "\u00BA": "\u006F",
    819         "\u02B0": "\u0068",
    820         "\u02B1": "\u0266",
    821         "\u02B2": "\u006A",
    822         "\u02B3": "\u0072",
    823         "\u02B4": "\u0279",
    824         "\u02B5": "\u027B",
    825         "\u02B6": "\u0281",
    826         "\u02B7": "\u0077",
    827         "\u02B8": "\u0079",
    828         "\u02E0": "\u0263",
    829         "\u02E1": "\u006C",
    830         "\u02E2": "\u0073",
    831         "\u02E3": "\u0078",
    832         "\u02E4": "\u0295",
    833         "\u1D2C": "\u0041",
    834         "\u1D2D": "\u00C6",
    835         "\u1D2E": "\u0042",
    836         "\u1D30": "\u0044",
    837         "\u1D31": "\u0045",
    838         "\u1D32": "\u018E",
    839         "\u1D33": "\u0047",
    840         "\u1D34": "\u0048",
    841         "\u1D35": "\u0049",
    842         "\u1D36": "\u004A",
    843         "\u1D37": "\u004B",
    844         "\u1D38": "\u004C",
    845         "\u1D39": "\u004D",
    846         "\u1D3A": "\u004E",
    847         "\u1D3C": "\u004F",
    848         "\u1D3D": "\u0222",
    849         "\u1D3E": "\u0050",
    850         "\u1D3F": "\u0052",
    851         "\u1D40": "\u0054",
    852         "\u1D41": "\u0055",
    853         "\u1D42": "\u0057",
    854         "\u1D43": "\u0061",
    855         "\u1D44": "\u0250",
    856         "\u1D45": "\u0251",
    857         "\u1D46": "\u1D02",
    858         "\u1D47": "\u0062",
    859         "\u1D48": "\u0064",
    860         "\u1D49": "\u0065",
    861         "\u1D4A": "\u0259",
    862         "\u1D4B": "\u025B",
    863         "\u1D4C": "\u025C",
    864         "\u1D4D": "\u0067",
    865         "\u1D4F": "\u006B",
    866         "\u1D50": "\u006D",
    867         "\u1D51": "\u014B",
    868         "\u1D52": "\u006F",
    869         "\u1D53": "\u0254",
    870         "\u1D54": "\u1D16",
    871         "\u1D55": "\u1D17",
    872         "\u1D56": "\u0070",
    873         "\u1D57": "\u0074",
    874         "\u1D58": "\u0075",
    875         "\u1D59": "\u1D1D",
    876         "\u1D5A": "\u026F",
    877         "\u1D5B": "\u0076",
    878         "\u1D5C": "\u1D25",
    879         "\u1D5D": "\u03B2",
    880         "\u1D5E": "\u03B3",
    881         "\u1D5F": "\u03B4",
    882         "\u1D60": "\u03C6",
    883         "\u1D61": "\u03C7",
    884         "\u2070": "\u0030",
    885         "\u2071": "\u0069",
    886         "\u2074": "\u0034",
    887         "\u2075": "\u0035",
    888         "\u2076": "\u0036",
    889         "\u2077": "\u0037",
    890         "\u2078": "\u0038",
    891         "\u2079": "\u0039",
    892         "\u207A": "\u002B",
    893         "\u207B": "\u2212",
    894         "\u207C": "\u003D",
    895         "\u207D": "\u0028",
    896         "\u207E": "\u0029",
    897         "\u207F": "\u006E",
    898         "\u2120": "\u0053\u004D",
    899         "\u2122": "\u0054\u004D",
    900         "\u3192": "\u4E00",
    901         "\u3193": "\u4E8C",
    902         "\u3194": "\u4E09",
    903         "\u3195": "\u56DB",
    904         "\u3196": "\u4E0A",
    905         "\u3197": "\u4E2D",
    906         "\u3198": "\u4E0B",
    907         "\u3199": "\u7532",
    908         "\u319A": "\u4E59",
    909         "\u319B": "\u4E19",
    910         "\u319C": "\u4E01",
    911         "\u319D": "\u5929",
    912         "\u319E": "\u5730",
    913         "\u319F": "\u4EBA",
    914         "\u02C0": "\u0294",
    915         "\u02C1": "\u0295",
    916         "\u06E5": "\u0648",
    917         "\u06E6": "\u064A"
    918     },
    919     SUPERSCRIPTS_REGEXP: new RegExp("[\u00AA\u00B2\u00B3\u00B9\u00BA\u02B0\u02B1\u02B2\u02B3\u02B4\u02B5\u02B6\u02B7\u02B8\u02E0\u02E1\u02E2\u02E3\u02E4\u1D2C\u1D2D\u1D2E\u1D30\u1D31\u1D32\u1D33\u1D34\u1D35\u1D36\u1D37\u1D38\u1D39\u1D3A\u1D3C\u1D3D\u1D3E\u1D3F\u1D40\u1D41\u1D42\u1D43\u1D44\u1D45\u1D46\u1D47\u1D48\u1D49\u1D4A\u1D4B\u1D4C\u1D4D\u1D4F\u1D50\u1D51\u1D52\u1D53\u1D54\u1D55\u1D56\u1D57\u1D58\u1D59\u1D5A\u1D5B\u1D5C\u1D5D\u1D5E\u1D5F\u1D60\u1D61\u2070\u2071\u2074\u2075\u2076\u2077\u2078\u2079\u207A\u207B\u207C\u207D\u207E\u207F\u2120\u2122\u3192\u3193\u3194\u3195\u3196\u3197\u3198\u3199\u319A\u319B\u319C\u319D\u319E\u319F\u02C0\u02C1\u06E5\u06E6]", "g"),
    920     UPDATE_GROUP_CONTEXT_CONDITION: function (state, termtxt, valueTerm) {
    921         if (state.tmp.group_context.tip.condition) {
    922             if (state.tmp.group_context.tip.condition.test) {
    923                 var testres;
    924                 if (state.tmp.group_context.tip.condition.test === "empty-label") {
    925                     testres = !termtxt;
    926                 } else if (state.tmp.group_context.tip.condition.test === "empty-label-no-decor") {
    927                     testres = !termtxt || termtxt.indexOf("%s") > -1;
    928                 } else if (state.tmp.group_context.tip.condition.test === "comma-safe") {
    929                     var empty = !termtxt;
    930                     var alpha = termtxt.slice(0,1).match(CSL.ALL_ROMANESQUE_REGEXP);
    931                     var num = state.tmp.just_did_number;
    932                     if (empty) {
    933                         testres = true;
    934                     } else if (num) {
    935                         if (alpha && !valueTerm) {
    936                             testres = true;
    937                         } else {
    938                             testres = false;
    939                         }
    940                     } else {
    941                         if (alpha && !valueTerm) {
    942                             testres = true;
    943                         } else {
    944                             testres = false;
    945                         }
    946                     }
    947                 }
    948                 if (testres) {
    949                     state.tmp.group_context.tip.force_suppress = false;
    950                 } else {
    951                     state.tmp.group_context.tip.force_suppress = true;
    952                 }
    953                 if (state.tmp.group_context.tip.condition.not) {
    954                     state.tmp.group_context.tip.force_suppress = !state.tmp.group_context.tip.force_suppress;
    955                 }
    956             }
    957         } else {
    958             if (termtxt.slice(-1).match(/[0-9]/)) {
    959                 state.tmp.just_did_number = true;
    960             } else {
    961                 state.tmp.just_did_number = false;
    962             }
    963         }
    964     },
    965     locale: {},
    966     locale_opts: {},
    967     locale_dates: {}
    968 };
    969 if (typeof require !== "undefined" && typeof module !== 'undefined' && "exports" in module) {
    970     var CSL_IS_NODEJS = true;
    971     exports.CSL = CSL;
    972 }
    973 CSL.TERMINAL_PUNCTUATION_REGEXP = new RegExp("^([" + CSL.TERMINAL_PUNCTUATION.slice(0, -1).join("") + "])(.*)");
    974 CSL.CLOSURES = new RegExp(".*[\\]\\)]");
    975 if ("undefined" === typeof console) {
    976     CSL.debug = function (str) {
    977         dump("CSL: " + str + "\n");
    978     };
    979     CSL.error = function (str) {
    980         dump("CSL error: " + str + "\n");
    981     };
    982 } else {
    983     CSL.debug = function (str) {
    984         console.log("CSL: " + str);
    985     };
    986     CSL.error = function (str) {
    987         console.log("CSL error: " + str);
    988     };
    989 }
    990 CSL.XmlJSON = function (dataObj) {
    991     this.dataObj = dataObj;
    992     this.institution = {
    993         name:"institution",
    994         attrs:{
    995             "institution-parts":"long",
    996             "delimiter":", ",
    997             "substitute-use-first":"1",
    998             "use-last":"1"
    999         },
   1000         children:[
   1001             {
   1002                 name:"institution-part",
   1003                 attrs:{
   1004                     name:"long"
   1005                 },
   1006                 children:[]
   1007             }
   1008         ]
   1009     };
   1010 };
   1011 CSL.XmlJSON.prototype.clean = function (json) {
   1012     return json;
   1013 };
   1014 CSL.XmlJSON.prototype.getStyleId = function (myjson, styleName) {
   1015     var tagName = 'id';
   1016     if (styleName) {
   1017         tagName = 'title';
   1018     }
   1019     var ret = "";
   1020     var children = myjson.children;
   1021     for (var i=0,ilen=children.length;i<ilen;i++) {
   1022         if (children[i].name === 'info') {
   1023             var grandkids = children[i].children;
   1024             for (var j=0,jlen=grandkids.length;j<jlen;j++) {
   1025                 if (grandkids[j].name === tagName) {
   1026                     ret = grandkids[j].children[0];
   1027                 }
   1028             }
   1029         }
   1030     }
   1031     return ret;
   1032 };
   1033 CSL.XmlJSON.prototype.children = function (myjson) {
   1034     if (myjson && myjson.children.length) {
   1035         return myjson.children.slice();
   1036     } else {
   1037         return false;
   1038     }
   1039 };
   1040 CSL.XmlJSON.prototype.nodename = function (myjson) {
   1041     return myjson ? myjson.name : null;
   1042 };
   1043 CSL.XmlJSON.prototype.attributes = function (myjson) {
   1044     var ret = {};
   1045     for (var attrname in myjson.attrs) {
   1046         ret["@"+attrname] = myjson.attrs[attrname];
   1047     }
   1048     return ret;
   1049 };
   1050 CSL.XmlJSON.prototype.content = function (myjson) {
   1051     var ret = "";
   1052     if (!myjson || !myjson.children) {
   1053         return ret;
   1054     }
   1055     for (var i=0, ilen=myjson.children.length; i < ilen; i += 1) {
   1056         if ("string" === typeof myjson.children[i]) {
   1057             ret += myjson.children[i];
   1058         }
   1059     }
   1060     return ret;
   1061 };
   1062 CSL.XmlJSON.prototype.namespace = {}
   1063 CSL.XmlJSON.prototype.numberofnodes = function (myjson) {
   1064     if (myjson && "number" == typeof myjson.length) {
   1065         return myjson.length;
   1066     } else {
   1067         return 0;
   1068     }
   1069 };
   1070 CSL.XmlJSON.prototype.getAttributeValue = function (myjson,name,namespace) {
   1071     var ret = "";
   1072     if (namespace) {
   1073         name = namespace+":"+name;
   1074     }
   1075     if (myjson) {
   1076         if (myjson.attrs) {
   1077             if (myjson.attrs[name]) {
   1078                 ret = myjson.attrs[name];
   1079             } else {
   1080                 ret = "";
   1081             }
   1082         }
   1083     }
   1084     return ret;
   1085 }
   1086 CSL.XmlJSON.prototype.getNodeValue = function (myjson,name) {
   1087     var ret = "";
   1088     if (name){
   1089         for (var i=0, ilen=myjson.children.length; i < ilen; i += 1) {
   1090             if (myjson.children[i].name === name) {
   1091                 if (myjson.children[i].children.length) {
   1092                     ret = myjson.children[i];
   1093                 } else {
   1094                     ret = "";
   1095                 }
   1096             }
   1097         }
   1098     } else if (myjson) {
   1099         ret = myjson;
   1100     }
   1101     if (ret && ret.children && ret.children.length == 1 && "string" === typeof ret.children[0]) {
   1102         ret = ret.children[0];
   1103     }
   1104     return ret;
   1105 }
   1106 CSL.XmlJSON.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myjson,nodename,partname,attrname,val) {
   1107     var pos, len, xml, nodes, node;
   1108     if (attrname.slice(0,1) === '@'){
   1109         attrname = attrname.slice(1);
   1110     }
   1111     for (var i=0,ilen=myjson.children.length; i<ilen; i += 1) {
   1112         if (myjson.children[i].name === nodename && myjson.children[i].attrs.name === partname) {
   1113             myjson.children[i].attrs[attrname] = val;
   1114         }
   1115     }
   1116 }
   1117 CSL.XmlJSON.prototype.deleteNodeByNameAttribute = function (myjson,val) {
   1118     var i, ilen;
   1119     for (i = 0, ilen = myjson.children.length; i < ilen; i += 1) {
   1120         if (!myjson.children[i] || "string" === typeof myjson.children[i]) {
   1121             continue;
   1122         }
   1123         if (myjson.children[i].attrs.name == val) {
   1124             myjson.children = myjson.children.slice(0,i).concat(myjson.children.slice(i+1));
   1125         }
   1126     }
   1127 }
   1128 CSL.XmlJSON.prototype.deleteAttribute = function (myjson,attrname) {
   1129     var i, ilen;
   1130     if ("undefined" !== typeof myjson.attrs[attrname]) {
   1131         myjson.attrs.pop(attrname);
   1132     }
   1133 }
   1134 CSL.XmlJSON.prototype.setAttribute = function (myjson,attr,val) {
   1135     myjson.attrs[attr] = val;
   1136     return false;
   1137 }
   1138 CSL.XmlJSON.prototype.nodeCopy = function (myjson,clone) {
   1139     if (!clone) {
   1140         var clone = {};
   1141     }
   1142     if ("object" === typeof clone && "undefined" === typeof clone.length) {
   1143         for (var key in myjson) {
   1144             if ("string" === typeof myjson[key]) {
   1145                 clone[key] = myjson[key];
   1146             } else if ("object" === typeof myjson[key]) {
   1147                 if ("undefined" === typeof myjson[key].length) {
   1148                     clone[key] = this.nodeCopy(myjson[key],{});
   1149                 } else {
   1150                     clone[key] = this.nodeCopy(myjson[key],[]);
   1151                 }
   1152             }
   1153         }
   1154     } else {
   1155         for (var i=0,ilen=myjson.length;i<ilen; i += 1) {
   1156             if ("string" === typeof myjson[i]) {
   1157                 clone[i] = myjson[i];
   1158             } else {
   1159                 clone[i] = this.nodeCopy(myjson[i],{});
   1160             }
   1161         }
   1162     }
   1163     return clone;
   1164 }
   1165 CSL.XmlJSON.prototype.getNodesByName = function (myjson,name,nameattrval,ret) {
   1166     var nodes, node, pos, len;
   1167     if (!ret) {
   1168         var ret = [];
   1169     }
   1170     if (!myjson || !myjson.children) {
   1171         return ret;
   1172     }
   1173     if (name === myjson.name) {
   1174         if (nameattrval) {
   1175             if (nameattrval === myjson.attrs.name) {
   1176                 ret.push(myjson);
   1177             }
   1178         } else {
   1179             ret.push(myjson);
   1180         }
   1181     }
   1182     for (var i=0,ilen=myjson.children.length;i<ilen;i+=1){
   1183         if ("object" !== typeof myjson.children[i]) {
   1184             continue;
   1185         }
   1186         this.getNodesByName(myjson.children[i],name,nameattrval,ret);
   1187     }
   1188     return ret;
   1189 }
   1190 CSL.XmlJSON.prototype.nodeNameIs = function (myjson,name) {
   1191     if (typeof myjson === "undefined") {
   1192         return false;
   1193     }
   1194     if (name == myjson.name) {
   1195         return true;
   1196     }
   1197     return false;
   1198 }
   1199 CSL.XmlJSON.prototype.makeXml = function (myjson) {
   1200     if ("string" === typeof myjson) {
   1201         if (myjson.slice(0, 1) === "<") {
   1202             myjson = this.jsonStringWalker.walkToObject(myjson);
   1203         } else {
   1204             myjson = JSON.parse(myjson);
   1205         }
   1206     }
   1207     return myjson;
   1208 };
   1209 CSL.XmlJSON.prototype.insertChildNodeAfter = function (parent,node,pos,datejson) {
   1210     for (var i=0,ilen=parent.children.length;i<ilen;i+=1) {
   1211         if (node === parent.children[i]) {
   1212             parent.children = parent.children.slice(0,i).concat([datejson]).concat(parent.children.slice(i+1));
   1213             break;
   1214         }
   1215     }
   1216     return parent;
   1217 };
   1218 CSL.XmlJSON.prototype.insertPublisherAndPlace = function(myjson) {
   1219     if (myjson.name === "group") {
   1220         var useme = true;
   1221         var mustHaves = ["publisher","publisher-place"];
   1222         for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1223             var haveVarname = mustHaves.indexOf(myjson.children[i].attrs.variable);
   1224             var isText = myjson.children[i].name === "text";
   1225             if (isText && haveVarname > -1 && !myjson.children[i].attrs.prefix && !myjson.children[i].attrs.suffix) {
   1226                 mustHaves = mustHaves.slice(0,haveVarname).concat(mustHaves.slice(haveVarname+1));
   1227             } else {
   1228                 useme = false;
   1229                 break;
   1230             }
   1231         }
   1232         if (useme && !mustHaves.length) {
   1233             myjson.attrs["has-publisher-and-publisher-place"] = true;
   1234        }
   1235     }
   1236     for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1237         if ("object" === typeof myjson.children[i]) {
   1238             this.insertPublisherAndPlace(myjson.children[i]);
   1239         }
   1240     }    
   1241 }
   1242 CSL.XmlJSON.prototype.isChildOfSubstitute = function(parents) {
   1243     if (parents.length > 0) {
   1244         var myparents = parents.slice();
   1245         var parent = myparents.pop();
   1246         if (parent === "substitute") {
   1247             return true;
   1248         } else {
   1249             return this.isChildOfSubstitute(myparents);
   1250         }
   1251     }
   1252     return false;
   1253 };
   1254 CSL.XmlJSON.prototype.addMissingNameNodes = function(myjson,parents) {
   1255     if (!parents) {
   1256         parents = [];
   1257     }
   1258     if (myjson.name === "names") {
   1259         if (!this.isChildOfSubstitute(parents)) {
   1260             var addName = true;
   1261             for (var i=0,ilen=myjson.children.length;i<ilen;i++) {
   1262                 if (myjson.children[i].name === "name") {
   1263                     addName = false;
   1264                     break;
   1265                 }
   1266             }
   1267             if (addName) {
   1268                 myjson.children = [{name:"name",attrs:{},children:[]}].concat(myjson.children);
   1269             }
   1270         }
   1271     }
   1272     parents.push(myjson.name);
   1273     for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1274         if ("object" === typeof myjson.children[i]) {
   1275             this.addMissingNameNodes(myjson.children[i],parents);
   1276         }
   1277     }
   1278     parents.pop();
   1279 }
   1280 CSL.XmlJSON.prototype.addInstitutionNodes = function(myjson) {
   1281     var names, thenames, institution, theinstitution, name, thename, xml, pos, len;
   1282     if (myjson.name === "names") {
   1283         var attributes = {};
   1284         var insertPos = -1;
   1285         for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1286             if (myjson.children[i].name == "name") {
   1287                 for (var key in myjson.children[i].attrs) {
   1288                     attributes[key] = myjson.children[i].attrs[key];
   1289                 }
   1290                 attributes.delimiter = myjson.children[i].attrs.delimiter;
   1291                 attributes.and = myjson.children[i].attrs.and;
   1292                 insertPos = i;
   1293                 for (var k=0,klen=myjson.children[i].children.length;k<klen;k+=1) {
   1294                     if (myjson.children[i].children[k].attrs.name !== 'family') {
   1295                         continue;
   1296                     }
   1297                     for (var key in myjson.children[i].children[k].attrs) {
   1298                         attributes[key] = myjson.children[i].children[k].attrs[key];
   1299                     }
   1300                 }
   1301             }
   1302             if (myjson.children[i].name == "institution") {
   1303                 insertPos = -1;
   1304                 break;
   1305             }
   1306         }
   1307         if (insertPos > -1) {
   1308             var institution = this.nodeCopy(this.institution);
   1309             for (var i=0,ilen = CSL.INSTITUTION_KEYS.length;i<ilen;i+=1) {
   1310                 var attrname = CSL.INSTITUTION_KEYS[i];
   1311                 if ("undefined" !== typeof attributes[attrname]) {
   1312                     institution.children[0].attrs[attrname] = attributes[attrname];
   1313                 }
   1314                 if (attributes.delimiter) {
   1315                     institution.attrs.delimiter = attributes.delimiter;
   1316                 }
   1317                 if (attributes.and) {
   1318                     institution.attrs.and = "text";
   1319                 }
   1320             }
   1321             myjson.children = myjson.children.slice(0,insertPos+1).concat([institution]).concat(myjson.children.slice(insertPos+1));
   1322         }
   1323     }
   1324     for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1325         if ("string" === typeof myjson.children[i]) {
   1326             continue;
   1327         }
   1328         this.addInstitutionNodes(myjson.children[i]);
   1329     }
   1330 }
   1331 CSL.XmlJSON.prototype.flagDateMacros = function(myjson) {
   1332     for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1333         if (myjson.children[i].name === "macro") {
   1334             if (this.inspectDateMacros(myjson.children[i])) {
   1335                 myjson.children[i].attrs["macro-has-date"] = "true";
   1336             }
   1337         }
   1338     }
   1339 }
   1340 CSL.XmlJSON.prototype.inspectDateMacros = function(myjson) {
   1341     if (!myjson || !myjson.children) {
   1342         return false;
   1343     }
   1344     if (myjson.name === "date") {
   1345         return true;
   1346     } else {
   1347         for (var i=0,ilen=myjson.children.length;i<ilen;i+=1) {
   1348             if (this.inspectDateMacros(myjson.children[i])) {
   1349                 return true;
   1350             }
   1351         }
   1352     }
   1353     return false;
   1354 }
   1355 CSL.stripXmlProcessingInstruction = function (xml) {
   1356     if (!xml) {
   1357         return xml;
   1358     }
   1359     xml = xml.replace(/^<\?[^?]+\?>/, "");
   1360     xml = xml.replace(/<!--[^>]+-->/g, "");
   1361     xml = xml.replace(/^\s+/g, "");
   1362     xml = xml.replace(/\s+$/g, "");
   1363     return xml;
   1364 };
   1365 CSL.parseXml = function(str) {
   1366     var _pos = 0;
   1367     var _obj = {children:[]};
   1368     var _stack = [_obj.children];
   1369     function _listifyString(str) {
   1370         str = str.split(/(?:\r\n|\n|\r)/).join(" ").replace(/>[	 ]+</g, "><").replace(/<\!--.*?-->/g, "");
   1371         var lst = str.split("><");
   1372         var stylePos = null;
   1373         for (var i=0,ilen=lst.length;i<ilen;i++) {
   1374             if (i > 0) {
   1375                 lst[i] = "<" + lst[i];
   1376             }
   1377             if (i < (lst.length-1)) {
   1378                 lst[i] = lst[i] + ">";
   1379             }
   1380             if ("number" != typeof stylePos) {
   1381                 if (lst[i].slice(0, 7) === "<style " || lst[i].slice(0, 8) == "<locale ") {
   1382                     stylePos = i;
   1383                 }
   1384             }
   1385         }
   1386         lst = lst.slice(stylePos);
   1387         for (var i=lst.length-2;i>-1;i--) {
   1388             if (lst[i].slice(1).indexOf("<") === -1) {
   1389                 var stub = lst[i].slice(0, 5);
   1390                 if (lst[i].slice(-2) !== "/>") {
   1391                     if (stub === "<term") {
   1392                         if (lst[i+1].slice(0, 6) === "</term") {
   1393                             lst[i] = lst[i] + lst[i+1];
   1394                             lst = lst.slice(0, i+1).concat(lst.slice(i+2));
   1395                         }
   1396                     } else if (["<sing", "<mult"].indexOf(stub) > -1) {
   1397                         if (lst[i].slice(-2) !== "/>" && lst[i+1].slice(0, 1) === "<") {
   1398                             lst[i] = lst[i] + lst[i+1];
   1399                             lst = lst.slice(0, i+1).concat(lst.slice(i+2));
   1400                         }
   1401                     }
   1402                 }
   1403             }
   1404         }
   1405         return lst;
   1406     }
   1407     function _decodeHtmlEntities(str) {
   1408         return str
   1409             .split("&amp;").join("&")
   1410             .split("&quot;").join("\"")
   1411             .split("&gt;").join(">").split("&lt;").join("<")
   1412             .replace(/&#([0-9]{1,6});/gi, function(match, numStr) {
   1413                 var num = parseInt(numStr, 10); // read num as normal number
   1414                 return String.fromCharCode(num);
   1415             })
   1416             .replace(/&#x([a-f0-9]{1,6});/gi, function(match, numStr){
   1417                 var num = parseInt(numStr, 16); // read num as hex
   1418                 return String.fromCharCode(num);
   1419             });
   1420     }
   1421     function _getAttributes(elem) {
   1422         var m = elem.match(/([^\'\"=	 ]+)=(?:\"[^\"]*\"|\'[^\']*\')/g);
   1423         if (m) {
   1424             for (var i=0,ilen=m.length;i<ilen;i++) {
   1425                 m[i] = m[i].replace(/=.*/, "");
   1426             }
   1427         }
   1428         return m;
   1429     }
   1430     function _getAttribute(elem, attr) {
   1431         var rex = RegExp('^.*[	 ]+' + attr + '=(\"(?:[^\"]*)\"|\'(?:[^\']*)\').*$');
   1432         var m = elem.match(rex);
   1433         return m ? m[1].slice(1, -1) : null;
   1434     }
   1435     function _getTagName(elem) {
   1436         var rex = RegExp("^<([^	 />]+)");
   1437         var m = elem.match(rex);
   1438         return m ? m[1] : null;
   1439     }
   1440     function _castObjectFromOpeningTag(elem) {
   1441         var obj = {};
   1442         obj.name = _getTagName(elem);
   1443         obj.attrs = {};
   1444         var attributes = _getAttributes(elem);
   1445         if (attributes) {
   1446             for (var i=0,ilen=attributes.length;i<ilen;i++) {
   1447                 var attr = {
   1448                     name: attributes[i],
   1449                     value: _getAttribute(elem, attributes[i])
   1450                 }
   1451                 obj.attrs[attr.name] = _decodeHtmlEntities(attr.value);
   1452             }
   1453         }
   1454         obj.children = [];
   1455         return obj;
   1456     }
   1457     function _extractTextFromCompositeElement(elem) {
   1458         var m = elem.match(/^.*>([^<]*)<.*$/);
   1459         return _decodeHtmlEntities(m[1]);
   1460     }
   1461     function _appendToChildren(obj) {
   1462         _stack.slice(-1)[0].push(obj);
   1463     }
   1464     function _extendStackWithNewChildren(obj) {
   1465         _stack.push(obj.children);
   1466     }
   1467     function processElement(elem) {
   1468         var obj;
   1469         if (elem.slice(1).indexOf('<') > -1) {
   1470             var tag = elem.slice(0, elem.indexOf('>')+1);
   1471             obj = _castObjectFromOpeningTag(tag);
   1472             obj.children = [_extractTextFromCompositeElement(elem)];
   1473             _appendToChildren(obj);
   1474         } else if (elem.slice(-2) === '/>') {
   1475             obj = _castObjectFromOpeningTag(elem);
   1476             if (_getTagName(elem) === 'term') {
   1477                 obj.children.push('');
   1478             }
   1479             _appendToChildren(obj);
   1480         } else if (elem.slice(0, 2) === '</') {
   1481             _stack.pop();
   1482         } else {
   1483             obj = _castObjectFromOpeningTag(elem);
   1484             _appendToChildren(obj)
   1485             _extendStackWithNewChildren(obj);
   1486         }
   1487     }
   1488     var lst = _listifyString(str);
   1489     for (var i=0,ilen=lst.length;i<ilen;i++) {
   1490         var elem = lst[i];
   1491         processElement(elem);
   1492     }
   1493     return _obj.children[0];
   1494 }
   1495 CSL.XmlDOM = function (dataObj) {
   1496     this.dataObj = dataObj;
   1497     if ("undefined" == typeof DOMParser) {
   1498         DOMParser = function() {};
   1499         DOMParser.prototype.parseFromString = function(str, contentType) {
   1500             if ("undefined" != typeof ActiveXObject) {
   1501                 var xmldata = new ActiveXObject('MSXML.DomDocument');
   1502                 xmldata.async = false;
   1503                 xmldata.loadXML(str);
   1504                 return xmldata;
   1505             } else if ("undefined" != typeof XMLHttpRequest) {
   1506                 var xmldata = new XMLHttpRequest;
   1507                 if (!contentType) {
   1508                     contentType = 'text/xml';
   1509                 }
   1510                 xmldata.open('GET', 'data:' + contentType + ';charset=utf-8,' + encodeURIComponent(str), false);
   1511                 if(xmldata.overrideMimeType) {
   1512                     xmldata.overrideMimeType(contentType);
   1513                 }
   1514                 xmldata.send(null);
   1515                 return xmldata.responseXML;
   1516             } else if ("undefined" != typeof marknote) {
   1517                 var parser = new marknote.Parser();
   1518                 return parser.parse(str);
   1519             }
   1520         };
   1521         this.hasAttributes = function (node) {
   1522             var ret;
   1523             if (node.attributes && node.attributes.length) {
   1524                 ret = true;
   1525             } else {
   1526                 ret = false;
   1527             }
   1528             return ret;
   1529         };
   1530     } else {
   1531         this.hasAttributes = function (node) {
   1532             var ret;
   1533             if (node.attributes && node.attributes.length) {
   1534                 ret = true;
   1535             } else {
   1536                 ret = false;
   1537             }
   1538             return ret;
   1539         };
   1540     }
   1541     this.importNode = function (doc, srcElement) {
   1542         if ("undefined" == typeof doc.importNode) {
   1543             var ret = this._importNode(doc, srcElement, true);
   1544         } else {
   1545             var ret = doc.importNode(srcElement, true);
   1546         }
   1547         return ret;
   1548     };
   1549     this._importNode = function(doc, node, allChildren) {
   1550         switch (node.nodeType) {
   1551             case 1:
   1552                 var newNode = doc.createElement(node.nodeName);
   1553                 if (node.attributes && node.attributes.length > 0)
   1554                     for (var i = 0, il = node.attributes.length; i < il;)
   1555                         newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i++].nodeName));
   1556                     if (allChildren && node.childNodes && node.childNodes.length > 0)
   1557                         for (var i = 0, il = node.childNodes.length; i < il;)
   1558                             newNode.appendChild(this._importNode(doc, node.childNodes[i++], allChildren));
   1559                 return newNode;
   1560                 break;
   1561             case 3:
   1562             case 4:
   1563             case 8:
   1564         }
   1565     };
   1566     this.parser = new DOMParser();
   1567     var str = "<docco><institution institution-parts=\"long\" delimiter=\", \" substitute-use-first=\"1\" use-last=\"1\"><institution-part name=\"long\"/></institution></docco>";
   1568     var inst_doc = this.parser.parseFromString(str, "text/xml");
   1569     var inst_node = inst_doc.getElementsByTagName("institution");
   1570     this.institution = inst_node.item(0);
   1571     var inst_part_node = inst_doc.getElementsByTagName("institution-part");
   1572     this.institutionpart = inst_part_node.item(0);
   1573     this.ns = "http://purl.org/net/xbiblio/csl";
   1574 };
   1575 CSL.XmlDOM.prototype.clean = function (xml) {
   1576     xml = xml.replace(/<\?[^?]+\?>/g, "");
   1577     xml = xml.replace(/<![^>]+>/g, "");
   1578     xml = xml.replace(/^\s+/, "");
   1579     xml = xml.replace(/\s+$/, "");
   1580     xml = xml.replace(/^\n*/, "");
   1581     return xml;
   1582 };
   1583 CSL.XmlDOM.prototype.getStyleId = function (myxml, styleName) {
   1584     var text = "";
   1585     var tagName = "id";
   1586     if (styleName) {
   1587         tagName = "title";
   1588     }
   1589     var node = myxml.getElementsByTagName(tagName);
   1590     if (node && node.length) {
   1591         node = node.item(0);
   1592     }
   1593     if (node) {
   1594         text = node.textContent;
   1595     }
   1596     if (!text) {
   1597         text = node.innerText;
   1598     }
   1599     if (!text) {
   1600         text = node.innerHTML;
   1601     }
   1602     return text;
   1603 };
   1604 CSL.XmlDOM.prototype.children = function (myxml) {
   1605     var children, pos, len, ret;
   1606     if (myxml) {
   1607         ret = [];
   1608         children = myxml.childNodes;
   1609         for (pos = 0, len = children.length; pos < len; pos += 1) {
   1610             if (children[pos].nodeName != "#text") {
   1611                 ret.push(children[pos]);
   1612             }
   1613         }
   1614         return ret;
   1615     } else {
   1616         return [];
   1617     }
   1618 };
   1619 CSL.XmlDOM.prototype.nodename = function (myxml) {
   1620     var ret = myxml.nodeName;
   1621     return ret;
   1622 };
   1623 CSL.XmlDOM.prototype.attributes = function (myxml) {
   1624     var ret, attrs, attr, key, xml, pos, len;
   1625     ret = new Object();
   1626     if (myxml && this.hasAttributes(myxml)) {
   1627         attrs = myxml.attributes;
   1628         for (pos = 0, len=attrs.length; pos < len; pos += 1) {
   1629             attr = attrs[pos];
   1630             ret["@" + attr.name] = attr.value;
   1631         }
   1632     }
   1633     return ret;
   1634 };
   1635 CSL.XmlDOM.prototype.content = function (myxml) {
   1636     var ret;
   1637     if ("undefined" != typeof myxml.textContent) {
   1638         ret = myxml.textContent;
   1639     } else if ("undefined" != typeof myxml.innerText) {
   1640         ret = myxml.innerText;
   1641     } else {
   1642         ret = myxml.txt;
   1643     }
   1644     return ret;
   1645 };
   1646 CSL.XmlDOM.prototype.namespace = {
   1647     "xml":"http://www.w3.org/XML/1998/namespace"
   1648 }
   1649 CSL.XmlDOM.prototype.numberofnodes = function (myxml) {
   1650     if (myxml) {
   1651         return myxml.length;
   1652     } else {
   1653         return 0;
   1654     }
   1655 };
   1656 CSL.XmlDOM.prototype.getAttributeName = function (attr) {
   1657     var ret = attr.name;
   1658     return ret;
   1659 }
   1660 CSL.XmlDOM.prototype.getAttributeValue = function (myxml,name,namespace) {
   1661     var ret = "";
   1662     if (namespace) {
   1663         name = namespace+":"+name;
   1664     }
   1665     if (myxml && this.hasAttributes(myxml) && myxml.getAttribute(name)) {
   1666         ret = myxml.getAttribute(name);
   1667     }
   1668     return ret;
   1669 }
   1670 CSL.XmlDOM.prototype.getNodeValue = function (myxml,name) {
   1671     var ret = null;
   1672     if (name){
   1673         var vals = myxml.getElementsByTagName(name);
   1674         if (vals.length > 0) {
   1675             if ("undefined" != typeof vals[0].textContent) {
   1676                 ret = vals[0].textContent;
   1677             } else if ("undefined" != typeof vals[0].innerText) {
   1678                 ret = vals[0].innerText;
   1679             } else {
   1680                 ret = vals[0].text;
   1681             }
   1682         }
   1683     }
   1684     if (ret === null && myxml && myxml.childNodes && (myxml.childNodes.length == 0 || (myxml.childNodes.length == 1 && myxml.firstChild.nodeName == "#text"))) {
   1685         if ("undefined" != typeof myxml.textContent) {
   1686             ret = myxml.textContent;
   1687         } else if ("undefined" != typeof myxml.innerText) {
   1688             ret = myxml.innerText;
   1689         } else {
   1690             ret = myxml.text;
   1691         }
   1692     }
   1693     if (ret === null) {
   1694         ret = myxml;
   1695     }
   1696     return ret;
   1697 }
   1698 CSL.XmlDOM.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myxml,nodename,partname,attrname,val) {
   1699     var pos, len, xml, nodes, node;
   1700     if (attrname.slice(0,1) === '@'){
   1701         attrname = attrname.slice(1);
   1702     }
   1703     nodes = myxml.getElementsByTagName(nodename);
   1704     for (pos = 0, len = nodes.length; pos < len; pos += 1) {
   1705         node = nodes[pos];
   1706         if (node.getAttribute("name") != partname) {
   1707             continue;
   1708         }
   1709         node.setAttribute(attrname, val);
   1710     }
   1711 }
   1712 CSL.XmlDOM.prototype.deleteNodeByNameAttribute = function (myxml,val) {
   1713     var pos, len, node, nodes;
   1714     nodes = myxml.childNodes;
   1715     for (pos = 0, len = nodes.length; pos < len; pos += 1) {
   1716         node = nodes[pos];
   1717         if (!node || node.nodeType == node.TEXT_NODE) {
   1718             continue;
   1719         }
   1720         if (this.hasAttributes(node) && node.getAttribute("name") == val) {
   1721             myxml.removeChild(nodes[pos]);
   1722         }
   1723     }
   1724 }
   1725 CSL.XmlDOM.prototype.deleteAttribute = function (myxml,attr) {
   1726     myxml.removeAttribute(attr);
   1727 }
   1728 CSL.XmlDOM.prototype.setAttribute = function (myxml,attr,val) {
   1729     if (!myxml.ownerDocument) {
   1730         myxml = myxml.firstChild;
   1731     }
   1732     if (["function", "unknown"].indexOf(typeof myxml.setAttribute) > -1) {
   1733         myxml.setAttribute(attr, val);
   1734     }
   1735     return false;
   1736 }
   1737 CSL.XmlDOM.prototype.nodeCopy = function (myxml) {
   1738     var cloned_node = myxml.cloneNode(true);
   1739     return cloned_node;
   1740 }
   1741 CSL.XmlDOM.prototype.getNodesByName = function (myxml,name,nameattrval) {
   1742     var ret, nodes, node, pos, len;
   1743     ret = [];
   1744     nodes = myxml.getElementsByTagName(name);
   1745     for (pos = 0, len = nodes.length; pos < len; pos += 1) {
   1746         node = nodes.item(pos);
   1747         if (nameattrval && !(this.hasAttributes(node) && node.getAttribute("name") == nameattrval)) {
   1748             continue;
   1749         }
   1750         ret.push(node);
   1751     }
   1752     return ret;
   1753 }
   1754 CSL.XmlDOM.prototype.nodeNameIs = function (myxml,name) {
   1755     if (name == myxml.nodeName) {
   1756         return true;
   1757     }
   1758     return false;
   1759 }
   1760 CSL.XmlDOM.prototype.makeXml = function (myxml) {
   1761     var ret, topnode;
   1762     if (!myxml) {
   1763         myxml = "<docco><bogus/></docco>";
   1764     }
   1765     myxml = myxml.replace(/\s*<\?[^>]*\?>\s*\n*/g, "");
   1766     var nodetree = this.parser.parseFromString(myxml, "application/xml");
   1767     return nodetree.firstChild;
   1768 };
   1769 CSL.XmlDOM.prototype.insertChildNodeAfter = function (parent,node,pos,datexml) {
   1770     var myxml, xml;
   1771     myxml = this.importNode(node.ownerDocument, datexml);
   1772     parent.replaceChild(myxml, node);
   1773      return parent;
   1774 };
   1775 CSL.XmlDOM.prototype.insertPublisherAndPlace = function(myxml) {
   1776     var group = myxml.getElementsByTagName("group");
   1777     for (var i = 0, ilen = group.length; i < ilen; i += 1) {
   1778         var node = group.item(i);
   1779         var skippers = [];
   1780         for (var j = 0, jlen = node.childNodes.length; j < jlen; j += 1) {
   1781             if (node.childNodes.item(j).nodeType !== 1) {
   1782                 skippers.push(j);
   1783             }
   1784         }
   1785         if (node.childNodes.length - skippers.length === 2) {
   1786             var twovars = [];
   1787             for (var j = 0, jlen = 2; j < jlen; j += 1) {
   1788                 if (skippers.indexOf(j) > -1) {
   1789                     continue;
   1790                 }
   1791                 var child = node.childNodes.item(j);                    
   1792                 var subskippers = [];
   1793                 for (var k = 0, klen = child.childNodes.length; k < klen; k += 1) {
   1794                     if (child.childNodes.item(k).nodeType !== 1) {
   1795                         subskippers.push(k);
   1796                     }
   1797                 }
   1798                 if (child.childNodes.length - subskippers.length === 0) {
   1799                     twovars.push(child.getAttribute('variable'));
   1800                     if (child.getAttribute('suffix')
   1801                         || child.getAttribute('prefix')) {
   1802                         twovars = [];
   1803                         break;
   1804                     }
   1805                 }
   1806             }
   1807             if (twovars.indexOf("publisher") > -1 && twovars.indexOf("publisher-place") > -1) {
   1808                 node.setAttribute('has-publisher-and-publisher-place', true);
   1809             }
   1810         }
   1811     }
   1812 };
   1813 CSL.XmlDOM.prototype.isChildOfSubstitute = function(node) {
   1814     if (node.parentNode) {
   1815         if (node.parentNode.tagName.toLowerCase() === "substitute") {
   1816             return true;
   1817         } else {
   1818             return this.isChildOfSubstitute(node.parentNode);
   1819         }
   1820     }
   1821     return false;
   1822 };
   1823 CSL.XmlDOM.prototype.addMissingNameNodes = function(myxml) {
   1824     var nameslist = myxml.getElementsByTagName("names");
   1825     for (var i = 0, ilen = nameslist.length; i < ilen; i += 1) {
   1826         var names = nameslist.item(i);
   1827         var namelist = names.getElementsByTagName("name");
   1828         if ((!namelist || namelist.length === 0)
   1829             && !this.isChildOfSubstitute(names)) {
   1830             var doc = names.ownerDocument;
   1831             var name = doc.createElement("name");
   1832             names.appendChild(name);
   1833         }
   1834     }
   1835 };
   1836 CSL.XmlDOM.prototype.addInstitutionNodes = function(myxml) {
   1837     var names, thenames, institution, theinstitution, name, thename, xml, pos, len;
   1838     names = myxml.getElementsByTagName("names");
   1839     for (pos = 0, len = names.length; pos < len; pos += 1) {
   1840         thenames = names.item(pos);
   1841         name = thenames.getElementsByTagName("name");
   1842         if (name.length == 0) {
   1843             continue;
   1844         }
   1845         institution = thenames.getElementsByTagName("institution");
   1846         if (institution.length == 0) {
   1847             theinstitution = this.importNode(myxml.ownerDocument, this.institution);
   1848             theinstitutionpart = theinstitution.getElementsByTagName("institution-part").item(0);
   1849             thename = name.item(0);
   1850             thenames.insertBefore(theinstitution, thename.nextSibling);
   1851             for (var j = 0, jlen = CSL.INSTITUTION_KEYS.length; j < jlen; j += 1) {
   1852                 var attrname = CSL.INSTITUTION_KEYS[j];
   1853                 var attrval = thename.getAttribute(attrname);
   1854                 if (attrval) {
   1855                     theinstitutionpart.setAttribute(attrname, attrval);
   1856                 }
   1857             }
   1858             var nameparts = thename.getElementsByTagName("name-part");
   1859             for (var j = 0, jlen = nameparts.length; j < jlen; j += 1) {
   1860                 if ('family' === nameparts[j].getAttribute('name')) {
   1861                     for (var k = 0, klen = CSL.INSTITUTION_KEYS.length; k < klen; k += 1) {
   1862                         var attrname = CSL.INSTITUTION_KEYS[k];
   1863                         var attrval = nameparts[j].getAttribute(attrname);
   1864                         if (attrval) {
   1865                             theinstitutionpart.setAttribute(attrname, attrval);
   1866                         }
   1867                     }
   1868                 }
   1869             }
   1870         }
   1871     }
   1872 };
   1873 CSL.XmlDOM.prototype.flagDateMacros = function(myxml) {
   1874     var pos, len, thenode, thedate;
   1875     nodes = myxml.getElementsByTagName("macro");
   1876     for (pos = 0, len = nodes.length; pos < len; pos += 1) {
   1877         thenode = nodes.item(pos);
   1878         thedate = thenode.getElementsByTagName("date");
   1879         if (thedate.length) {
   1880             thenode.setAttribute('macro-has-date', 'true');
   1881         }
   1882     }
   1883 };
   1884 if ("undefined" !== typeof XML) {
   1885     try {
   1886     } catch (e) {
   1887         throw "OOPS: "+e;
   1888     }
   1889 }
   1890 CSL.setupXml = function(xmlObject) {
   1891     var dataObj = {};
   1892     var parser = null;
   1893     if ("undefined" !== typeof xmlObject) {
   1894         if ("string" === typeof xmlObject) {
   1895             xmlObject = xmlObject.replace("^\uFEFF", "")
   1896                 .replace(/^\s+/, "");
   1897             if (xmlObject.slice(0, 1) === "<") {
   1898                 dataObj = CSL.parseXml(xmlObject);
   1899             } else {
   1900                 dataObj = JSON.parse(xmlObject);
   1901             }
   1902             parser = new CSL.XmlJSON(dataObj);
   1903         } else if ("undefined" !== typeof xmlObject.getAttribute) {
   1904             parser = new CSL.XmlDOM(xmlObject);
   1905         } else if ("undefined" !== typeof xmlObject.toXMLString) {
   1906             parser = new CSL.XmlE4X(xmlObject);
   1907         } else {
   1908             parser = new CSL.XmlJSON(xmlObject);
   1909         }
   1910     } else {
   1911         CSL.error("unable to parse XML input");
   1912     }
   1913     if (!parser) {
   1914         throw "citeproc-js error: unable to parse CSL style or locale object";
   1915     }
   1916     return parser;
   1917 }
   1918 CSL.getSortCompare = function (default_locale) {
   1919     if (CSL.stringCompare) {
   1920         return CSL.stringCompare;
   1921     }
   1922     var strcmp;
   1923     var strcmp_opts = {
   1924         sensitivity:"base",
   1925         ignorePunctuation:true,
   1926         numeric:true
   1927    }
   1928     if (!default_locale) {
   1929         default_locale = "en-US";
   1930     }
   1931     strcmp = function (a, b) {
   1932         return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase(),default_locale,strcmp_opts);
   1933     };
   1934     var stripPunct = function (str) {
   1935         return str.replace(/^[\[\]\'\"]*/g, "");
   1936     }
   1937     var getBracketPreSort = function () {
   1938         if (!strcmp("[x","x")) {
   1939             return false;
   1940         } else {
   1941             return function (a, b) {
   1942                 return strcmp(stripPunct(a), stripPunct(b));
   1943             }
   1944         }
   1945     }
   1946     var bracketPreSort = getBracketPreSort();
   1947     var sortCompare = function (a, b) {
   1948         if (bracketPreSort) {
   1949             return bracketPreSort(a, b);
   1950         } else {
   1951             return strcmp(a, b);
   1952         }
   1953     }
   1954     return sortCompare;
   1955 };
   1956 CSL.ambigConfigDiff = function(a, b) {
   1957     var ret, pos, len, ppos, llen;
   1958     if (a.names.length !== b.names.length) {
   1959         return 1;
   1960     } else {
   1961         for (pos = 0, len = a.names.length; pos < len; pos += 1) {
   1962             if (a.names[pos] !== b.names[pos]) {
   1963                 return 1;
   1964             } else {
   1965                 for (ppos = 0, llen = a.givens[pos]; ppos < llen; ppos += 1) {
   1966                     if (a.givens[pos][ppos] !== b.givens[pos][ppos]) {
   1967                         return 1;
   1968                     }
   1969                 }
   1970             }
   1971         }
   1972     }
   1973     if (a.disambiguate != b.disambiguate) {
   1974         return 1;
   1975     }
   1976     if (a.year_suffix !== b.year_suffix) {
   1977         return 1;
   1978     }
   1979     return 0;
   1980 };
   1981 CSL.cloneAmbigConfig = function (config, oldconfig, tainters) {
   1982     var i, ilen, j, jlen, k, klen, param;
   1983     var ret = {};
   1984     ret.names = [];
   1985     ret.givens = [];
   1986     ret.year_suffix = false;
   1987     ret.disambiguate = false;
   1988     for (i = 0, ilen = config.names.length; i < ilen; i += 1) {
   1989         param = config.names[i];
   1990         ret.names[i] = param;
   1991     }
   1992     for (i  = 0, ilen = config.givens.length; i < ilen; i += 1) {
   1993         param = [];
   1994         for (j = 0, jlen = config.givens[i].length; j < jlen; j += 1) {
   1995             param.push(config.givens[i][j]);
   1996         }
   1997         ret.givens.push(param);
   1998     }
   1999     if (oldconfig) {
   2000         ret.year_suffix = oldconfig.year_suffix;
   2001         ret.disambiguate = oldconfig.disambiguate;
   2002     } else {
   2003         ret.year_suffix = config.year_suffix;
   2004         ret.disambiguate = config.disambiguate;
   2005     }
   2006     return ret;
   2007 };
   2008 CSL.getAmbigConfig = function () {
   2009     var config, ret;
   2010     config = this.tmp.disambig_request;
   2011     if (!config) {
   2012         config = this.tmp.disambig_settings;
   2013     }
   2014     var ret = CSL.cloneAmbigConfig(config);
   2015     return ret;
   2016 };
   2017 CSL.getMaxVals = function () {
   2018     return this.tmp.names_max.mystack.slice();
   2019 };
   2020 CSL.getMinVal = function () {
   2021     return this.tmp["et-al-min"];
   2022 };
   2023 CSL.tokenExec = function (token, Item, item) {
   2024     var next, maybenext, exec, debug;
   2025     debug = false;
   2026     next = token.next;
   2027     maybenext = false;
   2028     var record = function (result) {
   2029         if (result) {
   2030             this.tmp.jump.replace("succeed");
   2031             return token.succeed;
   2032         } else {
   2033             this.tmp.jump.replace("fail");
   2034             return token.fail;
   2035         }
   2036     }
   2037     if (token.test) {
   2038         next = record.call(this,token.test(Item, item));
   2039     }
   2040     for (var i=0,ilen=token.execs.length;i<ilen;i++) {
   2041         exec = token.execs[i];
   2042         maybenext = exec.call(token, this, Item, item);
   2043         if (maybenext) {
   2044             next = maybenext;
   2045         }
   2046     }
   2047     return next;
   2048 };
   2049 CSL.expandMacro = function (macro_key_token, target) {
   2050     var mkey, start_token, key, end_token, navi, macro_nodes, newoutput, mergeoutput, end_of_macro, func;
   2051     mkey = macro_key_token.postponed_macro;
   2052     macro_key_token = new CSL.Token("group", CSL.START);
   2053     var hasDate = false;
   2054     var macroid = false;
   2055     macro_nodes = this.cslXml.getNodesByName(this.cslXml.dataObj, 'macro', mkey);
   2056     if (macro_nodes.length) {
   2057         macroid = this.cslXml.getAttributeValue(macro_nodes[0],'cslid');
   2058         hasDate = this.cslXml.getAttributeValue(macro_nodes[0], "macro-has-date");
   2059     }
   2060     if (hasDate) {
   2061         mkey = mkey + "@" + this.build.current_default_locale;
   2062         func = function (state, Item) {
   2063             if (state.tmp.extension) {
   2064                 state.tmp["doing-macro-with-date"] = true;
   2065             }
   2066         };
   2067         macro_key_token.execs.push(func);
   2068     }
   2069     if (this.build.macro_stack.indexOf(mkey) > -1) {
   2070         throw "CSL processor error: call to macro \"" + mkey + "\" would cause an infinite loop";
   2071     } else {
   2072         this.build.macro_stack.push(mkey);
   2073     }
   2074     macro_key_token.cslid = macroid;
   2075     if (CSL.MODULE_MACROS[mkey]) {
   2076         macro_key_token.juris = mkey;
   2077         this.opt.update_mode = CSL.POSITION;
   2078     }
   2079     CSL.Node.group.build.call(macro_key_token, this, target, true);
   2080     if (!this.cslXml.getNodeValue(macro_nodes)) {
   2081         throw "CSL style error: undefined macro \"" + mkey + "\"";
   2082     }
   2083     var mytarget = CSL.getMacroTarget.call(this, mkey);
   2084     if (mytarget) {
   2085         CSL.buildMacro.call(this, mytarget, macro_nodes);
   2086         CSL.configureMacro.call(this, mytarget);
   2087     }
   2088     if (!this.build.extension) {
   2089         var func = function(macro_name) {
   2090             return function (state, Item, item) {
   2091                 var next = 0;
   2092                 while (next < state.macros[macro_name].length) {
   2093                     next = CSL.tokenExec.call(state, state.macros[macro_name][next], Item, item);
   2094                 }
   2095             }
   2096         }(mkey);
   2097         var text_node = new CSL.Token("text", CSL.SINGLETON);
   2098         text_node.execs.push(func);
   2099         target.push(text_node);
   2100     }
   2101     end_of_macro = new CSL.Token("group", CSL.END);
   2102     if (hasDate) {
   2103         func = function (state, Item) {
   2104             if (state.tmp.extension) {
   2105                 state.tmp["doing-macro-with-date"] = false;
   2106             }
   2107         };
   2108         end_of_macro.execs.push(func);
   2109     }
   2110     if (macro_key_token.juris) {
   2111         end_of_macro.juris = mkey;
   2112      }
   2113     CSL.Node.group.build.call(end_of_macro, this, target, true);
   2114     this.build.macro_stack.pop();
   2115 };
   2116 CSL.getMacroTarget = function (mkey) {
   2117     var mytarget = false;
   2118     if (this.build.extension) {
   2119         mytarget = this[this.build.root + this.build.extension].tokens;
   2120     } else if (!this.macros[mkey]) {
   2121         mytarget = [];
   2122         this.macros[mkey] = mytarget;
   2123     }
   2124     return mytarget;
   2125 }
   2126 CSL.buildMacro = function (mytarget, macro_nodes) {
   2127     var builder = CSL.makeBuilder(this, mytarget);
   2128     var mynode;
   2129     if ("undefined" === typeof macro_nodes.length) {
   2130         mynode = macro_nodes;
   2131     } else {
   2132         mynode = macro_nodes[0];
   2133     }
   2134     builder(mynode);
   2135 }
   2136 CSL.configureMacro = function (mytarget) {
   2137     if (!this.build.extension) {
   2138         this.configureTokenList(mytarget);
   2139     }
   2140 }
   2141 CSL.XmlToToken = function (state, tokentype, explicitTarget, var_stack) {
   2142     var name, txt, attrfuncs, attributes, decorations, token, key, target;
   2143     name = state.cslXml.nodename(this);
   2144     if (state.build.skip && state.build.skip !== name) {
   2145         return;
   2146     }
   2147     if (!name) {
   2148         txt = state.cslXml.content(this);
   2149         if (txt) {
   2150             state.build.text = txt;
   2151         }
   2152         return;
   2153     }
   2154     if (!CSL.Node[state.cslXml.nodename(this)]) {
   2155         throw "Undefined node name \"" + name + "\".";
   2156     }
   2157     attrfuncs = [];
   2158     attributes = state.cslXml.attributes(this);
   2159     decorations = CSL.setDecorations.call(this, state, attributes);
   2160     token = new CSL.Token(name, tokentype);
   2161     if (tokentype !== CSL.END || name === "if" || name === "else-if" || name === "layout") {
   2162         for (var key in attributes) {
   2163             if (attributes.hasOwnProperty(key)) {
   2164                 if (tokentype === CSL.END && key !== "@language" && key !== "@locale") {
   2165                     continue;
   2166                 }
   2167                 if (attributes.hasOwnProperty(key)) {
   2168                     if (CSL.Attributes[key]) {
   2169                         try {
   2170                             CSL.Attributes[key].call(token, state, "" + attributes[key]);
   2171                         } catch (e) {
   2172                             CSL.error(e);
   2173                             throw "CSL processor error, " + key + " attribute: " + e;
   2174                         }
   2175                     } else {
   2176                         CSL.debug("warning: undefined attribute \""+key+"\" in style");
   2177                     }
   2178                 }
   2179             }
   2180         }
   2181         token.decorations = decorations;
   2182         if (CSL.DATE_VARIABLES.indexOf(attributes['@variable']) > -1) {
   2183             var_stack.push(token.variables);
   2184         }
   2185     } else if (tokentype === CSL.END && attributes['@variable']) {
   2186         token.hasVariable = true;
   2187         if (CSL.DATE_VARIABLES.indexOf(attributes['@variable']) > -1) {
   2188             token.variables = var_stack.pop();
   2189         }
   2190     }
   2191     if (explicitTarget) {
   2192         target = explicitTarget;
   2193     } else {
   2194         target = state[state.build.area].tokens;
   2195     }
   2196     CSL.Node[name].build.call(token, state, target, true);
   2197 };
   2198 CSL.DateParser = new function () {
   2199     var epochPairs = [
   2200         ["\u660E\u6CBB", 1867],
   2201         ["\u5927\u6B63", 1911],
   2202         ["\u662D\u548C", 1925],
   2203         ["\u5E73\u6210", 1988]
   2204     ];
   2205     var epochYearByName = {};
   2206     for (var i=0,ilen=epochPairs.length; i<ilen; i++) {
   2207         var key = epochPairs[i][0];
   2208         var val = epochPairs[i][1];
   2209         epochYearByName[key] = val;
   2210     }
   2211     var epochMatchStrings = [];
   2212     for (var i=0,ilen=epochPairs.length; i<ilen; i++) {
   2213         var val = epochPairs[i][0];
   2214         epochMatchStrings.push(val);
   2215     }
   2216     var epochMatchString = epochMatchStrings.join("|");
   2217     var epochSplitter = new RegExp("(?:" + epochMatchString + ")(?:[0-9]+)");
   2218     var epochMatcher = new RegExp("(?:" + epochMatchString + ")(?:[0-9]+)", "g");
   2219     var kanjiMonthDay = /(\u6708|\u5E74)/g;
   2220     var kanjiYear = /\u65E5/g;
   2221     var kanjiRange = /\u301c/g;
   2222     var yearLast = "(?:[?0-9]{1,2}%%NUMD%%){0,2}[?0-9]{4}(?![0-9])";
   2223     var yearFirst = "[?0-9]{4}(?:%%NUMD%%[?0-9]{1,2}){0,2}(?![0-9])";
   2224     var numberVal = "[?0-9]{1,3}";
   2225     var rangeSeparator = "[%%DATED%%]";
   2226     var fuzzyChar = "[?~]";
   2227     var chars = "[^\-\/\~\?0-9]+";
   2228     var rexString = "(" + yearFirst + "|" + yearLast + "|" + numberVal + "|" + rangeSeparator + "|" + fuzzyChar + "|" + chars + ")";
   2229     var rexDash = new RegExp(rexString.replace(/%%NUMD%%/g, "-").replace(/%%DATED%%/g, "-"));
   2230     var rexDashSlash = new RegExp(rexString.replace(/%%NUMD%%/g, "-").replace(/%%DATED%%/g, "\/"));
   2231     var rexSlashDash = new RegExp(rexString.replace(/%%NUMD%%/g, "\/").replace(/%%DATED%%/g, "-"));
   2232     var monthString = "january february march april may june july august september october november december spring summer fall winter spring summer";
   2233     this.monthStrings = monthString.split(" ");
   2234     this.setOrderDayMonth = function() {
   2235         this.monthGuess = 1;
   2236         this.dayGuess = 0;
   2237     };
   2238     this.setOrderMonthDay = function() {
   2239         this.monthGuess = 0;
   2240         this.dayGuess = 1;
   2241     };
   2242     this.resetDateParserMonths = function() {
   2243         this.monthSets = [];
   2244         for (var i=0,ilen=this.monthStrings.length; i<ilen; i++) {
   2245             this.monthSets.push([this.monthStrings[i]]);
   2246         }
   2247         this.monthAbbrevs = [];
   2248         for (var i=0,ilen=this.monthSets.length; i<ilen; i++) {
   2249             this.monthAbbrevs.push([]);
   2250             for (var j=0,jlen=this.monthSets[i].length; j<jlen; j++) {
   2251                 this.monthAbbrevs[i].push(this.monthSets[i][0].slice(0, 3));
   2252             }
   2253         }
   2254         this.monthRexes = [];
   2255         for (var i=0,ilen=this.monthAbbrevs.length; i<ilen; i++) {
   2256             this.monthRexes.push(new RegExp("(?:" + this.monthAbbrevs[i].join("|") + ")"));
   2257         }
   2258     };
   2259     this.addDateParserMonths = function(lst) {
   2260         if ("string" === typeof lst) {
   2261             lst = lst.split(/\s+/);
   2262         }
   2263         if (lst.length !== 12 && lst.length !== 16) {
   2264             CSL.debug("month [+season] list of "+lst.length+", expected 12 or 16. Ignoring.");
   2265             return;
   2266         }
   2267         var otherMatch = [];
   2268         var thisMatch = [];
   2269         for (var i=0,ilen=lst.length; i<ilen; i++) {
   2270             var abbrevLength = null;
   2271             var skip = false;
   2272             var insert = 3;
   2273             var extendedSets = {};
   2274             for (var j=0,jlen=this.monthAbbrevs.length; j<jlen; j++) {
   2275                 extendedSets[j] = {};
   2276                 if (j === i) {
   2277                     for (var k=0,klen=this.monthAbbrevs[i].length; k<klen; k++) {
   2278                         if (this.monthAbbrevs[i][k] === lst[i].slice(0, this.monthAbbrevs[i][k].length)) {
   2279                             skip = true;
   2280                             break;
   2281                         }
   2282                     }
   2283                 } else {
   2284                     for (var k=0,klen=this.monthAbbrevs[j].length; k<klen; k++) {
   2285                         abbrevLength = this.monthAbbrevs[j][k].length;
   2286                         if (this.monthAbbrevs[j][k] === lst[i].slice(0, abbrevLength)) {
   2287                             while (this.monthSets[j][k].slice(0, abbrevLength) === lst[i].slice(0, abbrevLength)) {
   2288                                 if (abbrevLength > lst[i].length || abbrevLength > this.monthSets[j][k].length) {
   2289                                     CSL.debug("unable to disambiguate month string in date parser: "+lst[i]);
   2290                                     break;
   2291                                 } else {
   2292                                     abbrevLength += 1;
   2293                                 }
   2294                             }
   2295                             insert = abbrevLength;
   2296                             extendedSets[j][k] = abbrevLength;
   2297                         }
   2298                     }
   2299                 }
   2300                 for (var jKey in extendedSets) {
   2301                     for (kKey in extendedSets[jKey]) {
   2302                         abbrevLength = extendedSets[jKey][kKey];
   2303                         jKey = parseInt(jKey, 10);
   2304                         kKey = parseInt(kKey, 10);
   2305                         this.monthAbbrevs[jKey][kKey] = this.monthSets[jKey][kKey].slice(0, abbrevLength);
   2306                     }
   2307                 }
   2308             }
   2309             if (!skip) {
   2310                 this.monthSets[i].push(lst[i]);
   2311                 this.monthAbbrevs[i].push(lst[i].slice(0, insert));
   2312             }
   2313         }
   2314         this.monthRexes = [];
   2315         this.monthRexStrs = [];
   2316         for (var i=0,ilen=this.monthAbbrevs.length; i<ilen; i++) {
   2317             this.monthRexes.push(new RegExp("^(?:" + this.monthAbbrevs[i].join("|") + ")"));
   2318             this.monthRexStrs.push("^(?:" + this.monthAbbrevs[i].join("|") + ")");
   2319         }
   2320         if (this.monthAbbrevs.length === 18) {
   2321             for (var i=12,ilen=14; i<ilen; i++) {
   2322                 this.monthRexes[i+4] = new RegExp("^(?:" + this.monthAbbrevs[i].join("|") + ")");
   2323                 this.monthRexStrs[i+4] = "^(?:" + this.monthAbbrevs[i].join("|") + ")";
   2324             }
   2325         }
   2326     };
   2327     this.convertDateObjectToArray = function (thedate) {
   2328         thedate["date-parts"] = [];
   2329         thedate["date-parts"].push([]);
   2330         var slicelen = 0;
   2331         for (var i=0,ilen=3; i<ilen; i++) {
   2332             var part = ["year", "month", "day"][i];
   2333             if (!thedate[part]) {
   2334                 break;
   2335             }
   2336             slicelen += 1;
   2337             thedate["date-parts"][0].push(thedate[part]);
   2338             delete thedate[part];
   2339         }
   2340         thedate["date-parts"].push([]);
   2341         for (var i=0, ilen=slicelen; i<ilen; i++) {
   2342             part = ["year_end", "month_end", "day_end"][i];
   2343             if (!thedate[part]) {
   2344                 break;
   2345             }
   2346             thedate["date-parts"][1].push(thedate[part]);
   2347             delete thedate[part];
   2348         }
   2349         if (thedate["date-parts"][0].length !== thedate["date-parts"][1].length) {
   2350             thedate["date-parts"].pop();
   2351         }
   2352         return thedate;
   2353     };
   2354     this.convertDateObjectToString = function(thedate) {
   2355         var ret = [];
   2356         for (var i = 0, ilen = 3; i < ilen; i += 1) {
   2357             if (thedate[DATE_PARTS_ALL[i]]) {
   2358                 ret.push(thedate[DATE_PARTS_ALL[i]]);
   2359             } else {
   2360                 break;
   2361             }
   2362         }
   2363         return ret.join("-");
   2364     }
   2365     this._parseNumericDate = function (ret, delim, suff, txt) {
   2366         if (!suff) suff = "";
   2367         var lst = txt.split(delim);
   2368         for (var i=0, ilen=lst.length; i<ilen; i++) {
   2369             if (lst[i].length === 4) {
   2370                 ret[("year" + suff)] = lst[i].replace(/^0*/, "");
   2371                 if (!i) {
   2372                     lst = lst.slice(1);
   2373                 } else {
   2374                     lst = lst.slice(0, i);
   2375                 }
   2376                 break;
   2377             }
   2378         }
   2379         for (var i=0,ilen=lst.length; i<ilen; i++) {
   2380             lst[i] = parseInt(lst[i], 10);
   2381         }
   2382         if (lst.length === 1 || (lst.length === 2 && !lst[1])) {
   2383             ret[("month" + suff)] = "" + lst[0];
   2384         } else if (lst.length === 2) {
   2385             if (lst[this.monthGuess] > 12) {
   2386                 ret[("month" + suff)] = "" + lst[this.dayGuess];
   2387                 ret[("day" + suff)] = "" + lst[this.monthGuess];
   2388             } else {
   2389                 ret[("month" + suff)] = "" + lst[this.monthGuess];
   2390                 ret[("day" + suff)] = "" + lst[this.dayGuess];
   2391             }
   2392         }
   2393     };
   2394     this.parseDateToObject = function (txt) {
   2395         var orig = txt;
   2396         var slashPos = -1;
   2397         var dashPos = -1;
   2398         var yearIsNegative = false;
   2399         var lst;
   2400         if (txt) {
   2401             if (txt.slice(0, 1) === "-") {
   2402                 yearIsNegative = true;
   2403                 txt = txt.slice(1);
   2404             }
   2405             if (txt.match(/^[0-9]{1,3}$/)) {
   2406                 while (txt.length < 4) {
   2407                     txt = "0" + txt;
   2408                 }
   2409             }
   2410             txt = "" + txt;
   2411             txt = txt.replace(/\s*[0-9]{2}:[0-9]{2}(?::[0-9]+)/,"");
   2412             var m = txt.match(kanjiMonthDay);
   2413             if (m) {
   2414                 txt = txt.replace(/\s+/g, "");
   2415                 txt = txt.replace(kanjiYear, "");
   2416                 txt = txt.replace(kanjiMonthDay, "-");
   2417                 txt = txt.replace(kanjiRange, "/");
   2418                 txt = txt.replace(/\-\//g, "/");
   2419                 txt = txt.replace(/-$/g,"");
   2420                 var slst = txt.split(epochSplitter);
   2421                 lst = [];
   2422                 var mm = txt.match(epochMatcher);
   2423                 if (mm) {
   2424                     var mmx = [];
   2425                     for (var i=0,ilen=mm.length; i<ilen; i++) {
   2426                         mmx = mmx.concat(mm[i].match(/([^0-9]+)([0-9]+)/).slice(1));
   2427                     }
   2428                     for (var i=0,ilen=slst.length; i<ilen; i++) {
   2429                         lst.push(slst[i]);
   2430                         if (i !== (len - 1)) {
   2431                             var mmpos = (pos * 2);
   2432                             lst.push(mmx[mmpos]);
   2433                             lst.push(mmx[mmpos + 1]);
   2434                         }
   2435                     }
   2436                 } else {
   2437                     lst = slst;
   2438                 }
   2439                 for (var i=1,ilen=lst.length; i<ilen; i+=3) {
   2440                     lst[i + 1] = jiy[lst[i]] + parseInt(lst[i + 1], 10);
   2441                     lst[i] = "";
   2442                 }
   2443                 txt = lst.join("");
   2444                 txt = txt.replace(/\s*-\s*$/, "").replace(/\s*-\s*\//, "/");
   2445                 txt = txt.replace(/\.\s*$/, "");
   2446                 txt = txt.replace(/\.(?! )/, "");
   2447                 slashPos = txt.indexOf("/");
   2448                 dashPos = txt.indexOf("-");
   2449             }
   2450         }
   2451         txt = txt.replace(/([A-Za-z])\./g, "$1");
   2452         var number = "";
   2453         var note = "";
   2454         var thedate = {};
   2455         var rangeDelim;
   2456         var dateDelim;
   2457         if (txt.slice(0, 1) === "\"" && txt.slice(-1) === "\"") {
   2458             thedate.literal = txt.slice(1, -1);
   2459             return thedate;
   2460         }
   2461         if (slashPos > -1 && dashPos > -1) {
   2462             var slashCount = txt.split("/");
   2463             if (slashCount.length > 3) {
   2464                 rangeDelim = "-";
   2465                 txt = txt.replace(/\_/g, "-");
   2466                 dateDelim = "/";
   2467                 lst = txt.split(rexSlashDash);
   2468             } else {
   2469                 rangeDelim = "/";
   2470                 txt = txt.replace(/\_/g, "/");
   2471                 dateDelim = "-";
   2472                 lst = txt.split(rexDashSlash);
   2473             }
   2474         } else {
   2475             txt = txt.replace(/\//g, "-");
   2476             txt = txt.replace(/\_/g, "-");
   2477             rangeDelim = "-";
   2478             dateDelim = "-";
   2479             lst = txt.split(rexDash);
   2480         }
   2481         var ret = [];
   2482         for (var i=0,ilen=lst.length; i<ilen; i++) {
   2483             var m = lst[i].match(/^\s*([\-\/]|[^\-\/\~\?0-9]+|[\-~?0-9]+)\s*$/);
   2484             if (m) {
   2485                 ret.push(m[1]);
   2486             }
   2487         }
   2488         var delimPos = ret.indexOf(rangeDelim);
   2489         var delims = [];
   2490         var isRange = false;
   2491         if (delimPos > -1) {
   2492             delims.push([0, delimPos]);
   2493             delims.push([(delimPos + 1), ret.length]);
   2494             isRange = true;
   2495         } else {
   2496             delims.push([0, ret.length]);
   2497         }
   2498         var suff = "";
   2499         for (var i=0,ilen=delims.length; i<ilen; i++) {
   2500             var delim = delims[i];
   2501             var date = ret.slice(delim[0], delim[1]);
   2502             outer: 
   2503             for (var j=0,jlen=date.length; j<jlen; j++) {
   2504                 var element = date[j];
   2505                 if (element.indexOf(dateDelim) > -1) {
   2506                     this._parseNumericDate(thedate, dateDelim, suff, element);
   2507                     continue;
   2508                 }
   2509                 if (element.match(/[0-9]{4}/)) {
   2510                     thedate[("year" + suff)] = element.replace(/^0*/, "");
   2511                     continue;
   2512                 }
   2513                 for (var k=0,klen=this.monthRexes.length; k<klen; k++) {
   2514                     if (element.toLocaleLowerCase().match(this.monthRexes[k])) {
   2515                         thedate[("month" + suff)] = "" + (parseInt(k, 10) + 1);
   2516                         continue outer;
   2517                     }
   2518                 }
   2519                 if (element.match(/^[0-9]+$/)) {
   2520                     number = element;
   2521                 }
   2522                 if (element.toLocaleLowerCase().match(/^bc/) && number) {
   2523                     thedate[("year" + suff)] = "" + (number * -1);
   2524                     number = "";
   2525                     continue;
   2526                 }
   2527                 if (element.toLocaleLowerCase().match(/^ad/) && number) {
   2528                     thedate[("year" + suff)] = "" + number;
   2529                     number = "";
   2530                     continue;
   2531                 }
   2532                 if (element === "~" || element === "?" || element === "c" || element.match(/^cir/)) {
   2533                     thedate.circa = "" + 1;
   2534                     continue;
   2535                 }
   2536                 if (element.toLocaleLowerCase().match(/(?:mic|tri|hil|eas)/) && !thedate[("season" + suff)]) {
   2537                     note = element;
   2538                     continue;
   2539                 }
   2540             }
   2541             if (number) {
   2542                 thedate[("day" + suff)] = number;
   2543                 number = "";
   2544             }
   2545             if (note && !thedate[("season" + suff)]) {
   2546                 thedate[("season" + suff)] = note;
   2547                 note = "";
   2548             }
   2549             suff = "_end";
   2550         }
   2551         if (isRange) {
   2552             for (var j=0,jlen=CSL.DATE_PARTS_ALL.length; j<jlen; j++) {
   2553                 var item = CSL.DATE_PARTS_ALL[j];
   2554                 if (thedate[item] && !thedate[(item + "_end")]) {
   2555                     thedate[(item + "_end")] = thedate[item];
   2556                 } else if (!thedate[item] && thedate[(item + "_end")]) {
   2557                     thedate[item] = thedate[(item + "_end")];
   2558                 }
   2559             }
   2560         }
   2561         if (!thedate.year || (thedate.year && thedate.day && !thedate.month)) {
   2562             thedate = { "literal": orig };
   2563         }
   2564         var parts = ["year", "month", "day", "year_end", "month_end", "day_end"];
   2565         for (var i=0,ilen=parts.length; i<ilen; i++) {
   2566             var part = parts[i];
   2567             if ("string" === typeof thedate[part] && thedate[part].match(/^[0-9]+$/)) {
   2568                 thedate[part] = parseInt(thedate[part], 10);
   2569             }
   2570         }
   2571         if (yearIsNegative && Object.keys(thedate).indexOf("year") > -1) {
   2572             thedate.year = (thedate.year * -1);
   2573         }
   2574         return thedate;
   2575     };
   2576     this.parseDateToArray = function(txt) {
   2577         return this.convertDateObjectToArray(this.parseDateToObject(txt));            
   2578     }
   2579     this.parseDateToString = function(txt) {
   2580         return this.convertDateObjectToString(this.parseDateToObject(txt));
   2581     }
   2582     this.parse = function(txt) {
   2583         return this.parseDateToObject(txt);
   2584     }
   2585     this.setOrderMonthDay();
   2586     this.resetDateParserMonths();
   2587 };
   2588 CSL.Engine = function (sys, style, lang, forceLang) {
   2589     var attrs, langspec, localexml, locale;
   2590     this.processor_version = CSL.PROCESSOR_VERSION;
   2591     this.csl_version = "1.0";
   2592     this.sys = sys;
   2593     if (sys.variableWrapper) {
   2594         CSL.VARIABLE_WRAPPER_PREPUNCT_REX = new RegExp('^([' + [" "].concat(CSL.SWAPPING_PUNCTUATION).join("") + ']*)(.*)');
   2595     }
   2596     if (CSL.retrieveStyleModule) {
   2597         this.sys.retrieveStyleModule = CSL.retrieveStyleModule;
   2598     }
   2599     if (CSL.getAbbreviation) {
   2600         this.sys.getAbbreviation = CSL.getAbbreviation;
   2601     }
   2602     if (this.sys.stringCompare) {
   2603         CSL.stringCompare = this.sys.stringCompare;
   2604     }
   2605     this.sys.AbbreviationSegments = CSL.AbbreviationSegments;
   2606     this.parallel = new CSL.Parallel(this);
   2607     this.transform = new CSL.Transform(this);
   2608     this.setParseNames = function (val) {
   2609         this.opt['parse-names'] = val;
   2610     };
   2611     this.opt = new CSL.Engine.Opt();
   2612     this.tmp = new CSL.Engine.Tmp();
   2613     this.build = new CSL.Engine.Build();
   2614     this.fun = new CSL.Engine.Fun(this);
   2615     this.configure = new CSL.Engine.Configure();
   2616     this.citation_sort = new CSL.Engine.CitationSort();
   2617     this.bibliography_sort = new CSL.Engine.BibliographySort();
   2618     this.citation = new CSL.Engine.Citation(this);
   2619     this.bibliography = new CSL.Engine.Bibliography();
   2620     this.output = new CSL.Output.Queue(this);
   2621     this.dateput = new CSL.Output.Queue(this);
   2622     this.cslXml = CSL.setupXml(style);
   2623     if (this.opt.development_extensions.csl_reverse_lookup_support || this.sys.csl_reverse_lookup_support) {
   2624         this.build.cslNodeId = 0;
   2625         this.setCslNodeIds = function(myxml, nodename) {
   2626             var children = this.cslXml.children(myxml);
   2627             this.cslXml.setAttribute(myxml, 'cslid', this.build.cslNodeId);
   2628             this.opt.nodenames.push(nodename);
   2629             this.build.cslNodeId += 1;
   2630             for (var i = 0, ilen = this.cslXml.numberofnodes(children); i < ilen; i += 1) {
   2631                 nodename = this.cslXml.nodename(children[i]);
   2632                 if (nodename) {
   2633                     this.setCslNodeIds(children[i], nodename);
   2634                 }
   2635             }
   2636         };
   2637         this.setCslNodeIds(this.cslXml.dataObj, "style");
   2638     }
   2639     this.cslXml.addMissingNameNodes(this.cslXml.dataObj);
   2640     this.cslXml.addInstitutionNodes(this.cslXml.dataObj);
   2641     this.cslXml.insertPublisherAndPlace(this.cslXml.dataObj);
   2642     this.cslXml.flagDateMacros(this.cslXml.dataObj);
   2643     attrs = this.cslXml.attributes(this.cslXml.dataObj);
   2644     if ("undefined" === typeof attrs["@sort-separator"]) {
   2645         this.cslXml.setAttribute(this.cslXml.dataObj, "sort-separator", ", ");
   2646     }
   2647     this.opt["initialize-with-hyphen"] = true;
   2648     this.setStyleAttributes();
   2649     this.opt.xclass = this.cslXml.getAttributeValue(this.cslXml.dataObj, "class");
   2650     this.opt["class"] = this.opt.xclass;
   2651     this.opt.styleID = this.cslXml.getStyleId(this.cslXml.dataObj);
   2652     this.opt.styleName = this.cslXml.getStyleId(this.cslXml.dataObj, true);
   2653     if (this.opt.version.slice(0,4) === "1.1m") {
   2654         this.opt.development_extensions.static_statute_locator = true;
   2655         this.opt.development_extensions.handle_parallel_articles = true;
   2656         this.opt.development_extensions.main_title_from_short_title = true;
   2657         this.opt.development_extensions.rtl_support = true;
   2658         this.opt.development_extensions.expect_and_symbol_form = true;
   2659         this.opt.development_extensions.require_explicit_legal_case_title_short = true;
   2660         this.opt.development_extensions.force_jurisdiction = true;
   2661     }
   2662     if (lang) {
   2663         lang = lang.replace("_", "-");
   2664         lang = CSL.normalizeLocaleStr(lang);
   2665     }
   2666     if (this.opt["default-locale"][0]) {
   2667         this.opt["default-locale"][0] = this.opt["default-locale"][0].replace("_", "-");
   2668         this.opt["default-locale"][0] = CSL.normalizeLocaleStr(this.opt["default-locale"][0]);
   2669     }
   2670     if (lang && forceLang) {
   2671         this.opt["default-locale"] = [lang];
   2672     }
   2673     if (lang && !forceLang && this.opt["default-locale"][0]) {
   2674         lang = this.opt["default-locale"][0];
   2675     }
   2676     if (this.opt["default-locale"].length === 0) {
   2677         if (!lang) {
   2678             lang = "en-US";
   2679         }
   2680         this.opt["default-locale"].push("en-US");
   2681     }
   2682     if (!lang) {
   2683         lang = this.opt["default-locale"][0];
   2684     }
   2685     langspec = CSL.localeResolve(lang);
   2686     this.opt.lang = langspec.best;
   2687     this.opt["default-locale"][0] = langspec.best;
   2688     this.locale = {};
   2689     if (!this.opt["default-locale-sort"]) {
   2690         this.opt["default-locale-sort"] = this.opt["default-locale"][0];
   2691     }
   2692     if ('dale|'.localeCompare('daleb', this.opt["default-locale-sort"]) > -1) {
   2693         this.opt.sort_sep = "@";
   2694     } else {
   2695         this.opt.sort_sep = "|";
   2696     }
   2697     this.localeConfigure(langspec);
   2698     function makeRegExp(lst) {
   2699         var lst = lst.slice();
   2700         var ret = new RegExp( "(?:(?:[?!:]*\\s+|-|^)(?:" + lst.join("|") + ")(?=[!?:]*\\s+|-|$))", "g");
   2701         return ret;
   2702     }
   2703     this.locale[this.opt.lang].opts["skip-words-regexp"] = makeRegExp(this.locale[this.opt.lang].opts["skip-words"]);
   2704     this.output.adjust = new CSL.Output.Queue.adjust(this.getOpt('punctuation-in-quote'));
   2705     this.registry = new CSL.Registry(this);
   2706     this.macros = {};
   2707     this.build.area = "citation";
   2708     var area_nodes = this.cslXml.getNodesByName(this.cslXml.dataObj, this.build.area);
   2709     this.buildTokenLists(area_nodes, this[this.build.area].tokens);
   2710     this.build.area = "bibliography";
   2711     var area_nodes = this.cslXml.getNodesByName(this.cslXml.dataObj, this.build.area);
   2712     this.buildTokenLists(area_nodes, this[this.build.area].tokens);
   2713     this.juris = {};
   2714     this.configureTokenLists();
   2715     this.disambiguate = new CSL.Disambiguation(this);
   2716     this.splice_delimiter = false;
   2717     this.fun.dateparser = CSL.DateParser;
   2718     this.fun.flipflopper = new CSL.Util.FlipFlopper(this);
   2719     this.setCloseQuotesArray();
   2720     this.fun.ordinalizer.init(this);
   2721     this.fun.long_ordinalizer.init(this);
   2722     this.fun.page_mangler = CSL.Util.PageRangeMangler.getFunction(this, "page");
   2723     this.fun.year_mangler = CSL.Util.PageRangeMangler.getFunction(this, "year");
   2724     this.setOutputFormat("html");
   2725 };
   2726 CSL.Engine.prototype.setCloseQuotesArray = function () {
   2727     var ret;
   2728     ret = [];
   2729     ret.push(this.getTerm("close-quote"));
   2730     ret.push(this.getTerm("close-inner-quote"));
   2731     ret.push('"');
   2732     ret.push("'");
   2733     this.opt.close_quotes_array = ret;
   2734 };
   2735 CSL.makeBuilder = function (me, target) {
   2736     var var_stack = [];
   2737     function enterFunc (node) {
   2738         CSL.XmlToToken.call(node, me, CSL.START, target, var_stack);
   2739     };
   2740     function leaveFunc (node) {
   2741         CSL.XmlToToken.call(node, me, CSL.END, target, var_stack);
   2742     };
   2743     function singletonFunc (node) {
   2744         CSL.XmlToToken.call(node, me, CSL.SINGLETON, target, var_stack);
   2745     };
   2746     function buildStyle (node) {
   2747         var starttag, origparent;
   2748         if (me.cslXml.numberofnodes(me.cslXml.children(node))) {
   2749             origparent = node;
   2750             enterFunc(origparent);
   2751             for (var i=0;i<me.cslXml.numberofnodes(me.cslXml.children(origparent));i+=1) {
   2752                 node = me.cslXml.children(origparent)[i];
   2753                 if (me.cslXml.nodename(node) === null) {
   2754                     continue;
   2755                 }
   2756                 if (me.cslXml.nodename(node) === "date") {
   2757                     CSL.Util.fixDateNode.call(me, origparent, i, node)
   2758                     node = me.cslXml.children(origparent)[i];
   2759                 }
   2760                 buildStyle(node, enterFunc, leaveFunc, singletonFunc);
   2761             }
   2762             leaveFunc(origparent);
   2763         } else {
   2764             singletonFunc(node);
   2765         }
   2766     }
   2767     return buildStyle;
   2768 };
   2769 CSL.Engine.prototype.buildTokenLists = function (area_nodes, target) {
   2770     if (!this.cslXml.getNodeValue(area_nodes)) return;
   2771     var builder = CSL.makeBuilder(this, target);
   2772     var mynode;
   2773     if ("undefined" === typeof area_nodes.length) {
   2774         mynode = area_nodes;
   2775     } else {
   2776         mynode = area_nodes[0];
   2777     }
   2778     builder(mynode);
   2779 };
   2780 CSL.Engine.prototype.setStyleAttributes = function () {
   2781     var dummy, attr, key, attributes, attrname;
   2782     var dummy = {};
   2783     dummy.name = this.cslXml.nodename(this.cslXml.dataObj);
   2784     attributes = this.cslXml.attributes(this.cslXml.dataObj);
   2785     for (attrname in attributes) {
   2786         if (attributes.hasOwnProperty(attrname)) {
   2787             CSL.Attributes[attrname].call(dummy, this, attributes[attrname]);
   2788         }
   2789     }
   2790 };
   2791 CSL.Engine.prototype.getTerm = function (term, form, plural, gender, mode, forceDefaultLocale) {
   2792     if (term && term.match(/[A-Z]/) && term === term.toUpperCase()) {
   2793         CSL.debug("Warning: term key is in uppercase form: "+term);
   2794         term = term.toLowerCase();
   2795     }
   2796     var lang;
   2797     if (forceDefaultLocale) {
   2798         lang = this.opt["default-locale"][0];
   2799     } else {
   2800         lang = this.opt.lang;
   2801     }
   2802     var ret = CSL.Engine.getField(CSL.LOOSE, this.locale[lang].terms, term, form, plural, gender);
   2803     if (!ret && term === "range-delimiter") {
   2804         ret = "\u2013";
   2805     }
   2806     if (typeof ret === "undefined") {
   2807         if (mode === CSL.STRICT) {
   2808             throw "Error in getTerm: term \"" + term + "\" does not exist.";
   2809         } else if (mode === CSL.TOLERANT) {
   2810             ret = "";
   2811         }
   2812     }
   2813     if (ret) {
   2814         this.tmp.cite_renders_content = true;
   2815     }
   2816     return ret;
   2817 };
   2818 CSL.Engine.prototype.getDate = function (form, forceDefaultLocale) {
   2819     var lang;
   2820     if (forceDefaultLocale) {
   2821         lang = this.opt["default-locale"];
   2822     } else {
   2823         lang = this.opt.lang;
   2824     }
   2825     if (this.locale[lang].dates[form]) {
   2826         return this.locale[lang].dates[form];
   2827     } else {
   2828         return false;
   2829     }
   2830 };
   2831 CSL.Engine.prototype.getOpt = function (arg) {
   2832     if ("undefined" !== typeof this.locale[this.opt.lang].opts[arg]) {
   2833         return this.locale[this.opt.lang].opts[arg];
   2834     } else {
   2835         return false;
   2836     }
   2837 };
   2838 CSL.Engine.prototype.getVariable = function (Item, varname, form, plural) {
   2839     return CSL.Engine.getField(CSL.LOOSE, Item, varname, form, plural);
   2840 };
   2841 CSL.Engine.prototype.getDateNum = function (ItemField, partname) {
   2842     if ("undefined" === typeof ItemField) {
   2843         return 0;
   2844     } else {
   2845         return ItemField[partname];
   2846     }
   2847 };
   2848 CSL.Engine.getField = function (mode, hash, term, form, plural, gender) {
   2849     var ret, forms, f, pos, len, hashterm;
   2850     ret = "";
   2851     if ("undefined" === typeof hash[term]) {
   2852         if (mode === CSL.STRICT) {
   2853             throw "Error in getField: term \"" + term + "\" does not exist.";
   2854         } else {
   2855             return undefined;
   2856         }
   2857     }
   2858     if (gender && hash[term][gender]) {
   2859         hashterm = hash[term][gender];
   2860     } else {
   2861         hashterm = hash[term];
   2862     }
   2863     forms = [];
   2864     if (form === "symbol") {
   2865         forms = ["symbol", "short"];
   2866     } else if (form === "verb-short") {
   2867         forms = ["verb-short", "verb"];
   2868     } else if (form !== "long") {
   2869         forms = [form];
   2870     }
   2871     forms = forms.concat(["long"]);
   2872     len = forms.length;
   2873     for (pos = 0; pos < len; pos += 1) {
   2874         f = forms[pos];
   2875         if ("string" === typeof hashterm || "number" === typeof hashterm) {
   2876             ret = hashterm;
   2877         } else if ("undefined" !== typeof hashterm[f]) {
   2878             if ("string" === typeof hashterm[f] || "number" === typeof hashterm[f]) {
   2879                 ret = hashterm[f];
   2880             } else {
   2881                 if ("number" === typeof plural) {
   2882                     ret = hashterm[f][plural];
   2883                 } else {
   2884                     ret = hashterm[f][0];
   2885                 }
   2886             }
   2887             break;
   2888         }
   2889     }
   2890     return ret;
   2891 };
   2892 CSL.Engine.prototype.configureTokenLists = function () {
   2893     var dateparts_master, area, pos, token, dateparts, part, ppos, pppos, len, llen, lllen;
   2894     len = CSL.AREAS.length;
   2895     for (pos = 0; pos < len; pos += 1) {
   2896         area = CSL.AREAS[pos];
   2897         var tokens = this[area].tokens;
   2898         this.configureTokenList(tokens);
   2899     }
   2900     this.version = CSL.version;
   2901     return this.state;
   2902 };
   2903 CSL.Engine.prototype.configureTokenList = function (tokens) {
   2904     var dateparts_master, area, pos, token, dateparts, part, ppos, pppos, len, llen, lllen;
   2905     dateparts_master = ["year", "month", "day"];
   2906     llen = tokens.length - 1;
   2907     for (ppos = llen; ppos > -1; ppos += -1) {
   2908         token = tokens[ppos];
   2909         if ("date" === token.name && CSL.END === token.tokentype) {
   2910             dateparts = [];
   2911         }
   2912         if ("date-part" === token.name && token.strings.name) {
   2913             lllen = dateparts_master.length;
   2914             for (pppos = 0; pppos < lllen; pppos += 1) {
   2915                 part = dateparts_master[pppos];
   2916                 if (part === token.strings.name) {
   2917                     dateparts.push(token.strings.name);
   2918                 }
   2919             }
   2920         }
   2921         if ("date" === token.name && CSL.START === token.tokentype) {
   2922             dateparts.reverse();
   2923             token.dateparts = dateparts;
   2924         }
   2925         token.next = (ppos + 1);
   2926         if (token.name && CSL.Node[token.name].configure) {
   2927             CSL.Node[token.name].configure.call(token, this, ppos);
   2928         }
   2929     }
   2930 }
   2931 CSL.Engine.prototype.retrieveItems = function (ids) {
   2932     var ret, pos, len;
   2933     ret = [];
   2934     for (var i = 0, ilen = ids.length; i < ilen; i += 1) {
   2935         ret.push(this.retrieveItem("" + ids[i]));
   2936     }
   2937     return ret;
   2938 };
   2939 CSL.ITERATION = 0;
   2940 CSL.Engine.prototype.retrieveItem = function (id) {
   2941     var Item, m, pos, len, mm, i;
   2942     if (!this.tmp.loadedItemIDs[id]) {
   2943         this.tmp.loadedItemIDs[id] = true;
   2944     } else {
   2945         return this.registry.refhash[id];
   2946     }
   2947     if (this.opt.development_extensions.normalize_lang_keys_to_lowercase &&
   2948         "boolean" === typeof this.opt.development_extensions.normalize_lang_keys_to_lowercase) {
   2949         for (var i=0,ilen=this.opt["default-locale"].length; i<ilen; i+=1) {
   2950             this.opt["default-locale"][i] = this.opt["default-locale"][i].toLowerCase();
   2951         }
   2952         for (var i=0,ilen=this.opt["locale-translit"].length; i<ilen; i+=1) {
   2953             this.opt["locale-translit"][i] = this.opt["locale-translit"][i].toLowerCase();
   2954         }
   2955         for (var i=0,ilen=this.opt["locale-translat"].length; i<ilen; i+=1) {
   2956             this.opt["locale-translat"][i] = this.opt["locale-translat"][i].toLowerCase();
   2957         }
   2958         this.opt.development_extensions.normalize_lang_keys_to_lowercase = 100;
   2959     }
   2960     CSL.ITERATION += 1;
   2961     Item = JSON.parse(JSON.stringify(this.sys.retrieveItem("" + id)));
   2962     if (this.opt.development_extensions.normalize_lang_keys_to_lowercase) {
   2963         if (Item.multi) {
   2964             if (Item.multi._keys) {
   2965                 for (var field in Item.multi._keys) {
   2966                     for (var key in Item.multi._keys[field]) {
   2967                         if (key !== key.toLowerCase()) {
   2968                             Item.multi._keys[field][key.toLowerCase()] = Item.multi._keys[field][key];
   2969                             delete Item.multi._keys[field][key];
   2970                         }
   2971                     }
   2972                 }
   2973             }
   2974             if (Item.multi.main) {
   2975                 for (var field in Item.multi.main) {
   2976                     Item.multi.main[field] = Item.multi.main[field].toLowerCase();
   2977                 }
   2978             }
   2979         }
   2980         for (var i=0, ilen=CSL.CREATORS.length; i>ilen; i+=1) {
   2981             var ctype = CSL.CREATORS[i];
   2982             if (Item[ctype] && Item[ctype].multi) {
   2983                 for (var j=0, jlen=Item[ctype].length; j<jlen; j+=1) {
   2984                     var creator = Item[ctype][j];
   2985                     if (creator.multi) {
   2986                         if (creator.multi._key) {
   2987                             for (var key in creator.multi._key) {
   2988                                 if (key !== key.toLowerCase()) {
   2989                                     creator.multi._key[key.toLowerCase()] = creator.multi._key[key];
   2990                                     delete creator.multi._key[key];
   2991                                 }
   2992                             }
   2993                         }
   2994                         if (creator.multi.main) {
   2995                             creator.multi.main = creator.multi.main.toLowerCase();
   2996                         }
   2997                     }
   2998                 }
   2999             }
   3000         }
   3001     }
   3002     if (Item.language) {
   3003         var lst = Item.language.split("<");
   3004         if (lst.length > 0) {
   3005             Item["language-name"] = lst[0];
   3006         }
   3007         if (lst.length === 2) {
   3008             Item["language-name-original"] = lst[1];
   3009         }
   3010     }
   3011     if (Item.page) {
   3012         Item["page-first"] = Item.page;
   3013         var num = "" + Item.page;
   3014         var m = num.split(/\s*(?:&|, |-|\u2013)\s*/);
   3015         if (m[0].slice(-1) !== "\\") {
   3016             Item["page-first"] = m[0];
   3017         }
   3018     }
   3019     if (this.opt.development_extensions.field_hack && Item.note) {
   3020         CSL.parseNoteFieldHacks(Item, false, this.opt.development_extensions.allow_field_hack_date_override);
   3021     }
   3022     for (var i = 1, ilen = CSL.DATE_VARIABLES.length; i < ilen; i += 1) {
   3023         var dateobj = Item[CSL.DATE_VARIABLES[i]];
   3024         if (dateobj) {
   3025             if (this.opt.development_extensions.raw_date_parsing) {
   3026                 if (dateobj.raw) {
   3027                     dateobj = this.fun.dateparser.parseDateToObject(dateobj.raw);
   3028                 }
   3029             }
   3030             Item[CSL.DATE_VARIABLES[i]] = this.dateParseArray(dateobj);
   3031         }
   3032     }
   3033     if (this.opt.development_extensions.static_statute_locator) {
   3034         if (Item.type && ["bill","gazette","legislation","regulation","treaty"].indexOf(Item.type) > -1) {
   3035             var varname;
   3036             var elements = ["type", "title", "jurisdiction", "genre", "volume", "container-title"];
   3037             var legislation_id = [];
   3038             for (i = 0, ilen = elements.length; i < ilen; i += 1) {
   3039                 varname = elements[i];
   3040 				if (Item[varname]) {
   3041 					legislation_id.push(Item[varname]);
   3042 				}
   3043 			}
   3044             elements = ["original-date", "issued"];
   3045 			for (i = 0, elements.length; i < ilen; i += 1) {
   3046                 varname = elements[i];
   3047 				if (Item[varname] && Item[varname].year) {
   3048 					var value = Item[varname].year;
   3049 					legislation_id.push(value);
   3050 					break;
   3051 				}
   3052 			}
   3053 			Item.legislation_id = legislation_id.join("::");
   3054         }
   3055     }
   3056     if (this.opt.development_extensions.force_jurisdiction) {
   3057         if ("string" === typeof Item.authority) {
   3058             Item.authority = [
   3059                 {
   3060                     literal: Item.authority
   3061                 }
   3062             ]
   3063         }
   3064     }
   3065     if (!Item["title-short"]) {
   3066         Item["title-short"] = Item.shortTitle;
   3067     }
   3068     if (this.opt.development_extensions.main_title_from_short_title) {
   3069         CSL.extractTitleAndSubtitle(Item);
   3070     }
   3071     var isLegalType = ["bill","legal_case","legislation","gazette","regulation"].indexOf(Item.type) > -1;
   3072     if (this.opt.development_extensions.force_jurisdiction && isLegalType) {
   3073         if (!Item.jurisdiction) {
   3074             Item.jurisdiction = "us";
   3075         }
   3076     }
   3077     if (!isLegalType && Item.title && this.sys.getAbbreviation) {
   3078         var noHints = false;
   3079         if (!Item.jurisdiction) {
   3080             noHints = true;
   3081         }
   3082         if (this.sys.normalizeAbbrevsKey) {
   3083             var normalizedKey = this.sys.normalizeAbbrevsKey(Item.title);
   3084         } else {
   3085             var normalizedKey = Item.title;
   3086         }
   3087         var jurisdiction = this.transform.loadAbbreviation(Item.jurisdiction, "title", normalizedKey, Item.type);
   3088         if (this.transform.abbrevs[jurisdiction]["title"]) {
   3089             if (this.transform.abbrevs[jurisdiction]["title"][normalizedKey]) {
   3090                 Item["title-short"] = this.transform.abbrevs[jurisdiction]["title"][normalizedKey];
   3091             }
   3092         }
   3093     }
   3094     if (!Item["container-title-short"]) {
   3095         Item["container-title-short"] = Item.journalAbbreviation;
   3096     }
   3097     if (Item["container-title"] && this.sys.getAbbreviation) {
   3098         if (this.sys.normalizeAbbrevsKey) {
   3099             var normalizedKey = this.sys.normalizeAbbrevsKey(Item["container-title"]);
   3100         } else {
   3101             var normalizedKey = Item["container-title"];
   3102         }
   3103         var jurisdiction = this.transform.loadAbbreviation(Item.jurisdiction, "container-title", normalizedKey);
   3104         if (this.transform.abbrevs[jurisdiction]["container-title"]) {
   3105             if (this.transform.abbrevs[jurisdiction]["container-title"][normalizedKey]) {
   3106                 Item["container-title-short"] = this.transform.abbrevs[jurisdiction]["container-title"][normalizedKey];
   3107             }
   3108         }
   3109     }
   3110     if (Item["jurisdiction"]) {
   3111         Item["country"] = Item["jurisdiction"].split(":")[0];
   3112     }
   3113     this.registry.refhash[id] = Item;
   3114     return Item;
   3115 };
   3116 CSL.Engine.prototype.setOpt = function (token, name, value) {
   3117     if (token.name === "style" || token.name === "cslstyle") {
   3118         this.opt.inheritedAttributes[name] = value;
   3119         this.citation.opt.inheritedAttributes[name] = value;
   3120         this.bibliography.opt.inheritedAttributes[name] = value;
   3121     } else if (["citation", "bibliography"].indexOf(token.name) > -1) {
   3122         this[token.name].opt.inheritedAttributes[name] = value;
   3123     } else {
   3124         token.strings[name] = value;
   3125     }
   3126 };
   3127 CSL.Engine.prototype.inheritOpt = function (token, attrname, parentname, defaultValue) {
   3128     if ("undefined" !== typeof token.strings[attrname]) {
   3129         return token.strings[attrname];
   3130     } else {
   3131         var parentValue = this[this.tmp.root].opt.inheritedAttributes[parentname ? parentname : attrname];
   3132         if ("undefined" !== typeof parentValue) {
   3133             return parentValue;
   3134         } else {
   3135             return defaultValue;
   3136         }
   3137     }
   3138 };
   3139 CSL.Engine.prototype.remapSectionVariable = function (inputList) {
   3140     for (var i = 0, ilen = inputList.length; i < ilen; i += 1) {
   3141         var Item = inputList[i][0];
   3142         var item = inputList[i][1];
   3143         if (["bill","gazette","legislation","regulation","treaty"].indexOf(Item.type) > -1) {
   3144             if (item.locator) {
   3145                 item.locator = item.locator.trim();
   3146                 var m = item.locator.match(CSL.STATUTE_SUBDIV_PLAIN_REGEX_FRONT);
   3147                 if (!m) {
   3148                     if (item.label) {
   3149                         item.locator = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[item.label] + " " + item.locator;
   3150                     } else {
   3151                         item.locator = "p. " + item.locator;
   3152                     }
   3153                 }
   3154             }
   3155             var sectionMasterLabel = null;
   3156             if (Item.section) {
   3157                 Item.section = Item.section.trim();
   3158                 var m = Item.section.match(CSL.STATUTE_SUBDIV_PLAIN_REGEX_FRONT);
   3159                 if (!m) {
   3160                     Item.section = "sec. " + Item.section;
   3161                     sectionMasterLabel = "sec.";
   3162                 } else {
   3163                     sectionMasterLabel = m[0].trim();
   3164                 }
   3165             }
   3166             if (Item.section) {
   3167                 if (!item.locator) {
   3168                     item.locator = Item.section;
   3169                 } else {
   3170                     var m = item.locator.match(/^([^ ]*)\s*(.*)/);
   3171                     var space = " ";
   3172                     if (m) {
   3173                         if (m[1] === "p." && sectionMasterLabel !== "p.") {
   3174                             item.locator = m[2];
   3175                         }
   3176                         if (["[", "(", ".", ",", ";", ":", "?"].indexOf(item.locator.slice(0, 1)) > -1) {
   3177                             space = "";
   3178                         }
   3179                     } else {
   3180                        space = ""; 
   3181                     }
   3182                     item.locator = Item.section + space + item.locator;
   3183                 }
   3184             }
   3185             item.label = "";
   3186         }
   3187     }
   3188 }
   3189 CSL.Engine.prototype.setNumberLabels = function (Item) {
   3190      if (Item.number
   3191         && ["bill", "gazette", "legislation","regulation","treaty"].indexOf(Item.type) > -1
   3192         && this.opt.development_extensions.static_statute_locator
   3193         && !this.tmp.shadow_numbers["number"]) {
   3194         this.tmp.shadow_numbers["number"] = {};
   3195         this.tmp.shadow_numbers["number"].values = [];
   3196         this.tmp.shadow_numbers["number"].plural = 0;
   3197         this.tmp.shadow_numbers["number"].numeric = false;
   3198         this.tmp.shadow_numbers["number"].label = false;
   3199         var value = "" + Item.number;
   3200         value = value.split("\\").join("");
   3201         var firstword = value.split(/\s+/)[0];
   3202         var firstlabel = CSL.STATUTE_SUBDIV_STRINGS[firstword];
   3203         if (firstlabel) {
   3204             var m = value.match(CSL.STATUTE_SUBDIV_GROUPED_REGEX);
   3205             var splt = value.split(CSL.STATUTE_SUBDIV_PLAIN_REGEX);
   3206             if (splt.length > 1) {
   3207                 var lst = [];
   3208                 for (var j=1, jlen=splt.length; j < jlen; j += 1) {
   3209                     var subdiv = m[j - 1].replace(/^\s*/, "");
   3210                     lst.push(splt[j].replace(/\s*$/, "").replace(/^\s*/, ""));
   3211                 }
   3212                 value = lst.join(" ");
   3213             } else {
   3214                 value = splt[0];
   3215             }
   3216             this.tmp.shadow_numbers["number"].label = firstlabel;
   3217             this.tmp.shadow_numbers["number"].values.push(["Blob", value, false]);
   3218             this.tmp.shadow_numbers["number"].numeric = false;
   3219         } else {
   3220             this.tmp.shadow_numbers["number"].values.push(["Blob", value, false]);
   3221             this.tmp.shadow_numbers["number"].numeric = true;
   3222         }
   3223     }
   3224 }
   3225 CSL.substituteOne = function (template) {
   3226     return function (state, list) {
   3227         if (!list) {
   3228             return "";
   3229         } else {
   3230             return template.replace("%%STRING%%", list);
   3231         }
   3232     };
   3233 };
   3234 CSL.substituteTwo = function (template) {
   3235     return function (param) {
   3236         var template2 = template.replace("%%PARAM%%", param);
   3237         return function (state, list) {
   3238             if (!list) {
   3239                 return "";
   3240             } else {
   3241                 return template2.replace("%%STRING%%", list);
   3242             }
   3243         };
   3244     };
   3245 };
   3246 CSL.Mode = function (mode) {
   3247     var decorations, params, param, func, val, args;
   3248     decorations = {};
   3249     params = CSL.Output.Formats[mode];
   3250     for (param in params) {
   3251         if (true) {
   3252             if ("@" !== param.slice(0, 1)) {
   3253                 decorations[param] = params[param];
   3254                 continue;
   3255             }
   3256             func = false;
   3257             val = params[param];
   3258             args = param.split('/');
   3259             if (typeof val === "string" && val.indexOf("%%STRING%%") > -1)  {
   3260                 if (val.indexOf("%%PARAM%%") > -1) {
   3261                     func = CSL.substituteTwo(val);
   3262                 } else {
   3263                     func = CSL.substituteOne(val);
   3264                 }
   3265             } else if (typeof val === "boolean" && !val) {
   3266                 func = CSL.Output.Formatters.passthrough;
   3267             } else if (typeof val === "function") {
   3268                 func = val;
   3269             } else {
   3270                 throw "CSL.Compiler: Bad " + mode + " config entry for " + param + ": " + val;
   3271             }
   3272             if (args.length === 1) {
   3273                 decorations[args[0]] = func;
   3274             } else if (args.length === 2) {
   3275                 if (!decorations[args[0]]) {
   3276                     decorations[args[0]] = {};
   3277                 }
   3278                 decorations[args[0]][args[1]] = func;
   3279             }
   3280         }
   3281     }
   3282     return decorations;
   3283 };
   3284 CSL.setDecorations = function (state, attributes) {
   3285     var ret, key, pos;
   3286     ret = [];
   3287     for (pos in CSL.FORMAT_KEY_SEQUENCE) {
   3288         if (true) {
   3289             var key = CSL.FORMAT_KEY_SEQUENCE[pos];
   3290             if (attributes[key]) {
   3291                 ret.push([key, attributes[key]]);
   3292                 delete attributes[key];
   3293             }
   3294         }
   3295     }
   3296     return ret;
   3297 };
   3298 CSL.Doppeler = function(rexStr, stringMangler) {
   3299     var mx, lst, len, pos, m, buf1, buf2, idx, ret, myret;
   3300     this.split = split;
   3301     this.join = join;
   3302     var matchRex = new RegExp("(" + rexStr + ")", "g");
   3303     var splitRex = new RegExp(rexStr, "g");
   3304     function split(str) {
   3305         if (stringMangler) {
   3306             str = stringMangler(str);
   3307         }
   3308         var match = str.match(matchRex);
   3309         if (!match) {
   3310             return {
   3311                 tags: [],
   3312                 strings: [str]
   3313             };
   3314         }
   3315         var split = str.split(splitRex);
   3316         for (var i=match.length-1; i> -1; i--) {
   3317             var tag = match[i];
   3318             if (tag === "\'" && split[i+1].length > 0) {
   3319                 split[i+1] = match[i] + split[i+1];
   3320                 match[i] = "";
   3321             }
   3322         }
   3323         return {
   3324             tags: match,
   3325             strings: split,
   3326             origStrings: split.slice()
   3327         }
   3328     }
   3329     function join(obj) {
   3330         var lst = obj.strings.slice(-1);
   3331         for (var i=obj.tags.length-1; i>-1; i--) {
   3332             lst.push(obj.tags[i]);
   3333             lst.push(obj.strings[i]);
   3334         }
   3335         lst.reverse();
   3336         return lst.join("");
   3337     }
   3338 }
   3339 CSL.Engine.prototype.normalDecorIsOrphan = function (blob, params) {
   3340     if (params[1] === "normal") {
   3341         var use_param = false;
   3342         var all_the_decor;
   3343         if (this.tmp.area === "citation") {
   3344             all_the_decor = [this.citation.opt.layout_decorations].concat(blob.alldecor);
   3345         } else {
   3346             all_the_decor = blob.alldecor;
   3347         }
   3348         for (var k = all_the_decor.length - 1; k > -1; k += -1) {
   3349             for (var n = all_the_decor[k].length - 1; n > -1; n += -1) {
   3350                 if (all_the_decor[k][n][0] === params[0]) {
   3351                     if (all_the_decor[k][n][1] !== "normal") {
   3352                         use_param = true;
   3353                     }
   3354                 }
   3355             }
   3356         }
   3357         if (!use_param) {
   3358             return true;
   3359         }
   3360     }
   3361     return false;
   3362 };
   3363 CSL.Engine.prototype.getCitationLabel = function (Item) {
   3364     var label = "";
   3365     var params = this.getTrigraphParams();
   3366     var config = params[0];
   3367     var myname = this.getTerm("reference", "short", 0);
   3368     if ("undefined" === typeof myname) {
   3369         myname = "reference";
   3370     }
   3371     myname = myname.replace(".", "");
   3372     myname = myname.slice(0, 1).toUpperCase() + myname.slice(1);
   3373     for (var i = 0, ilen = CSL.CREATORS.length; i < ilen; i += 1) {
   3374         var n = CSL.CREATORS[i];
   3375         if (Item[n]) {
   3376             var names = Item[n];
   3377             if (names.length > params.length) {
   3378                 config = params[params.length - 1];
   3379             } else {
   3380                 config = params[names.length - 1];
   3381             }
   3382             for (var j = 0, jlen = names.length; j < jlen; j += 1) {
   3383                 if (j === config.authors.length) {
   3384                     break;
   3385                 }
   3386                 var res = this.nameOutput.getName(names[j], "locale-translit", true);
   3387                 var name = res.name;
   3388                 if (name && name.family) {
   3389                     myname = name.family;
   3390                     myname = myname.replace(/^([ \'\u2019a-z]+\s+)/, "");
   3391                 } else if (name && name.literal) {
   3392                     myname = name.literal;
   3393                 }
   3394                 var m = myname.toLowerCase().match(/^(a\s+|the\s+|an\s+)/);
   3395                 if (m) {
   3396                     myname = myname.slice(m[1].length);
   3397                 }
   3398                 myname = myname.replace(CSL.ROMANESQUE_NOT_REGEXP, "");
   3399                 if (!myname) {
   3400                     break;
   3401                 }
   3402                 myname = myname.slice(0, config.authors[j]);
   3403                 if (myname.length > 1) {
   3404                     myname = myname.slice(0, 1).toUpperCase() + myname.slice(1).toLowerCase();
   3405                 } else if (myname.length === 1) {
   3406                     myname = myname.toUpperCase();
   3407                 }
   3408                 label += myname;
   3409             }
   3410             break;
   3411         }
   3412     }
   3413     if (!label) {
   3414         if (Item.title) {
   3415             var skipWords = this.locale[this.opt.lang].opts["skip-words"];
   3416             var lst = Item.title.split(/\s+/);
   3417             for (var i = lst.length - 1; i > -1; i--) {
   3418                 if (skipWords.indexOf(lst[i]) > -1) {
   3419                     lst = lst.slice(0, i).concat(lst.slice(i + 1));
   3420                 }
   3421             }
   3422             var str = lst.join('');
   3423             str = str.slice(0, params[0].authors[0]);
   3424             if (str.length > 1) {
   3425                 str = str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
   3426             } else if (str.length === 1) {
   3427                 str = str.toUpperCase();
   3428             }
   3429             label = str;
   3430         }
   3431     }
   3432     var year = "0000";
   3433     if (Item.issued) {
   3434         if (Item.issued.year) {
   3435             year = "" + Item.issued.year;
   3436         }
   3437     }
   3438     year = year.slice((config.year * -1));
   3439     label = label + year;
   3440     return label;
   3441 };
   3442 CSL.Engine.prototype.getTrigraphParams = function () {
   3443     var params = [];
   3444     var ilst = this.opt.trigraph.split(":");
   3445     if (!this.opt.trigraph || this.opt.trigraph.slice(0,1) !== "A") {
   3446         throw "Bad trigraph definition: "+this.opt.trigraph;
   3447     }
   3448     for (var i = 0, ilen = ilst.length; i < ilen; i += 1) {
   3449         var str = ilst[i];
   3450         var config = {authors:[], year:0};
   3451         for (var j = 0, jlen = str.length; j < jlen; j += 1) {
   3452             switch (str.slice(j,j+1)) {
   3453             case "A":
   3454                 config.authors.push(1);
   3455                 break;
   3456             case "a":
   3457                 config.authors[config.authors.length - 1] += 1;
   3458                 break;
   3459             case "0":
   3460                 config.year += 1;
   3461                 break;
   3462             default:
   3463                 throw "Invalid character in trigraph definition: "+this.opt.trigraph;
   3464             }
   3465         }
   3466         params.push(config);
   3467     }
   3468     return params;
   3469 };
   3470 CSL.Engine.prototype.setOutputFormat = function (mode) {
   3471     this.opt.mode = mode;
   3472     this.fun.decorate = CSL.Mode(mode);
   3473     if (!this.output[mode]) {
   3474         this.output[mode] = {};
   3475         this.output[mode].tmp = {};
   3476     }
   3477 };
   3478 CSL.Engine.prototype.getSortFunc = function () {
   3479     return function (a,b) {
   3480         a = a.split("-");
   3481         b = b.split("-");
   3482         if (a.length < b.length) {
   3483             return 1
   3484         } else if (a.length > b.length) {
   3485             return -1
   3486         } else {
   3487             a = a.slice(-1)[0];
   3488             b = b.slice(-1)[0];
   3489             if (a.length < b.length) {
   3490                 return 1;
   3491             } else if (a.length > b.length) {
   3492                 return -1;
   3493             } else {
   3494                 return 0;
   3495             }
   3496         }
   3497     };
   3498 };
   3499 CSL.Engine.prototype.setLangTagsForCslSort = function (tags) {
   3500     var i, ilen;
   3501     if (tags) {
   3502         this.opt['locale-sort'] = [];
   3503         for (i = 0, ilen = tags.length; i < ilen; i += 1) {
   3504             this.opt['locale-sort'].push(tags[i]);
   3505         }
   3506     }
   3507     this.opt['locale-sort'].sort(this.getSortFunc());
   3508 };
   3509 CSL.Engine.prototype.setLangTagsForCslTransliteration = function (tags) {
   3510     var i, ilen;
   3511     this.opt['locale-translit'] = [];
   3512     if (tags) {
   3513         for (i = 0, ilen = tags.length; i < ilen; i += 1) {
   3514             this.opt['locale-translit'].push(tags[i]);
   3515         }
   3516     }
   3517     this.opt['locale-translit'].sort(this.getSortFunc());
   3518 };
   3519 CSL.Engine.prototype.setLangTagsForCslTranslation = function (tags) {
   3520     var i, ilen;
   3521     this.opt['locale-translat'] = [];
   3522     if (tags) {
   3523         for (i = 0, ilen = tags.length; i < ilen; i += 1) {
   3524             this.opt['locale-translat'].push(tags[i]);
   3525         }
   3526     }
   3527     this.opt['locale-translat'].sort(this.getSortFunc());
   3528 };
   3529 CSL.Engine.prototype.setLangPrefsForCites = function (obj, conv) {
   3530     var opt = this.opt['cite-lang-prefs'];
   3531     if (!conv) {
   3532         conv = function (key) {
   3533             return key.toLowerCase();
   3534         };
   3535     }
   3536     var segments = ['Persons', 'Institutions', 'Titles', 'Journals', 'Publishers', 'Places'];
   3537     for (var i = 0, ilen = segments.length; i < ilen; i += 1) {
   3538         var clientSegment = conv(segments[i]);
   3539         var citeprocSegment = segments[i].toLowerCase();
   3540         if (!obj[clientSegment]) {
   3541             continue;
   3542         }
   3543         var supplements = [];
   3544         while (obj[clientSegment].length > 1) {
   3545             supplements.push(obj[clientSegment].pop());
   3546         }
   3547         var sortval = {orig:1,translit:2,translat:3};
   3548         if (supplements.length === 2 && sortval[supplements[0]] < sortval[supplements[1]]) {
   3549             supplements.reverse();
   3550         }
   3551         while (supplements.length) {
   3552             obj[clientSegment].push(supplements.pop());
   3553         }
   3554         var lst = opt[citeprocSegment];
   3555         while (lst.length) {
   3556             lst.pop();
   3557         }
   3558         for (var j = 0, jlen = obj[clientSegment].length; j < jlen; j += 1) {
   3559             lst.push(obj[clientSegment][j]);
   3560         }
   3561     }
   3562 };
   3563 CSL.Engine.prototype.setLangPrefsForCiteAffixes = function (affixList) {
   3564     if (affixList && affixList.length === 48) {
   3565         var affixes = this.opt.citeAffixes;
   3566         var count = 0;
   3567         var settings = ["persons", "institutions", "titles", "journals", "publishers", "places"];
   3568         var forms = ["translit", "orig", "translit", "translat"];
   3569         var value;
   3570         for (var i = 0, ilen = settings.length; i < ilen; i += 1) {
   3571             for (var j = 0, jlen = forms.length; j < jlen; j += 1) {
   3572                 value = "";
   3573                 if ((count % 8) === 4) {
   3574                     if (!affixes[settings[i]]["locale-"+forms[j]].prefix
   3575                         && !affixes[settings[i]]["locale-"+forms[j]].suffix) {
   3576                         value = affixList[count] ? affixList[count] : "";
   3577                         affixes[settings[i]]["locale-" + forms[j]].prefix = value;
   3578                         value = affixList[count] ? affixList[count + 1] : "";
   3579                         affixes[settings[i]]["locale-" + forms[j]].suffix = value;
   3580                     }
   3581                 } else {
   3582                     value = affixList[count] ? affixList[count] : "";
   3583                     affixes[settings[i]]["locale-" + forms[j]].prefix = value;
   3584                     value = affixList[count] ? affixList[count + 1] : "";
   3585                     affixes[settings[i]]["locale-" + forms[j]].suffix = value;
   3586                 }
   3587                 count += 2;
   3588             }
   3589         }
   3590         this.opt.citeAffixes = affixes;
   3591     }
   3592 };
   3593 CSL.Engine.prototype.setAutoVietnameseNamesOption = function (arg) {
   3594     if (arg) {
   3595         this.opt["auto-vietnamese-names"] = true;
   3596     } else {
   3597         this.opt["auto-vietnamese-names"] = false;
   3598     }
   3599 };
   3600 CSL.Engine.prototype.setAbbreviations = function (arg) {
   3601     if (this.sys.setAbbreviations) {
   3602         this.sys.setAbbreviations(arg);
   3603     }
   3604 };
   3605 CSL.Engine.prototype.setSuppressTrailingPunctuation = function (arg) {
   3606     this.citation.opt.suppressTrailingPunctuation = !!arg;
   3607 };
   3608 CSL.Output = {};
   3609 CSL.Output.Queue = function (state) {
   3610     this.levelname = ["top"];
   3611     this.state = state;
   3612     this.queue = [];
   3613     this.empty = new CSL.Token("empty");
   3614     var tokenstore = {};
   3615     tokenstore.empty = this.empty;
   3616     this.formats = new CSL.Stack(tokenstore);
   3617     this.current = new CSL.Stack(this.queue);
   3618 };
   3619 CSL.Output.Queue.prototype.pop = function () {
   3620     var drip = this.current.value();
   3621     if (drip.length) {
   3622         return drip.pop();
   3623     } else {
   3624         return drip.blobs.pop();
   3625     }
   3626 };
   3627 CSL.Output.Queue.prototype.getToken = function (name) {
   3628     var ret = this.formats.value()[name];
   3629     return ret;
   3630 };
   3631 CSL.Output.Queue.prototype.mergeTokenStrings = function (base, modifier) {
   3632     var base_token, modifier_token, ret, key;
   3633     base_token = this.formats.value()[base];
   3634     modifier_token = this.formats.value()[modifier];
   3635     ret = base_token;
   3636     if (modifier_token) {
   3637         if (!base_token) {
   3638             base_token = new CSL.Token(base, CSL.SINGLETON);
   3639             base_token.decorations = [];
   3640         }
   3641         ret = new CSL.Token(base, CSL.SINGLETON);
   3642         var key = "";
   3643         for (var key in base_token.strings) {
   3644             if (base_token.strings.hasOwnProperty(key)) {
   3645                 ret.strings[key] = base_token.strings[key];
   3646             }
   3647         }
   3648         for (var key in modifier_token.strings) {
   3649             if (modifier_token.strings.hasOwnProperty(key)) {
   3650                 ret.strings[key] = modifier_token.strings[key];
   3651             }
   3652         }
   3653         ret.decorations = base_token.decorations.concat(modifier_token.decorations);
   3654     }
   3655     return ret;
   3656 };
   3657 CSL.Output.Queue.prototype.addToken = function (name, modifier, token) {
   3658     var newtok, attr;
   3659     newtok = new CSL.Token("output");
   3660     if ("string" === typeof token) {
   3661         token = this.formats.value()[token];
   3662     }
   3663     if (token && token.strings) {
   3664         for (attr in token.strings) {
   3665             if (token.strings.hasOwnProperty(attr)) {
   3666                 newtok.strings[attr] = token.strings[attr];
   3667             }
   3668         }
   3669         newtok.decorations = token.decorations;
   3670     }
   3671     if ("string" === typeof modifier) {
   3672         newtok.strings.delimiter = modifier;
   3673     }
   3674     this.formats.value()[name] = newtok;
   3675 };
   3676 CSL.Output.Queue.prototype.pushFormats = function (tokenstore) {
   3677     if (!tokenstore) {
   3678         tokenstore = {};
   3679     }
   3680     tokenstore.empty = this.empty;
   3681     this.formats.push(tokenstore);
   3682 };
   3683 CSL.Output.Queue.prototype.popFormats = function (tokenstore) {
   3684     this.formats.pop();
   3685 };
   3686 CSL.Output.Queue.prototype.startTag = function (name, token) {
   3687     var tokenstore = {};
   3688     if (this.state.tmp["doing-macro-with-date"] && this.state.tmp.extension) {
   3689         token = this.empty;
   3690         name = "empty";
   3691     }
   3692     tokenstore[name] = token;
   3693     this.pushFormats(tokenstore);
   3694     this.openLevel(name);
   3695 };
   3696 CSL.Output.Queue.prototype.endTag = function (name) {
   3697     this.closeLevel(name);
   3698     this.popFormats();
   3699 };
   3700 CSL.Output.Queue.prototype.openLevel = function (token, ephemeral) {
   3701     var blob, curr, x, has_ephemeral;
   3702     if ("object" === typeof token) {
   3703         blob = new CSL.Blob(undefined, token);
   3704     } else if ("undefined" === typeof token) {
   3705         blob = new CSL.Blob(undefined, this.formats.value().empty, "empty");
   3706     } else {
   3707         if (!this.formats.value() || !this.formats.value()[token]) {
   3708             throw "CSL processor error: call to nonexistent format token \"" + token + "\"";
   3709         }
   3710         blob = new CSL.Blob(undefined, this.formats.value()[token], token);
   3711     }
   3712     curr = this.current.value();
   3713     if (!this.state.tmp.just_looking && this.checkNestedBrace) {
   3714         blob.strings.prefix = this.checkNestedBrace.update(blob.strings.prefix);
   3715     }
   3716     curr.push(blob);
   3717     this.current.push(blob);
   3718 };
   3719 CSL.Output.Queue.prototype.closeLevel = function (name) {
   3720     if (name && name !== this.current.value().levelname) {
   3721         CSL.error("Level mismatch error:  wanted " + name + " but found " + this.current.value().levelname);
   3722     }
   3723     var blob = this.current.pop();
   3724     if (!this.state.tmp.just_looking && this.checkNestedBrace) {
   3725         blob.strings.suffix = this.checkNestedBrace.update(blob.strings.suffix);
   3726     }
   3727 };
   3728 CSL.Output.Queue.prototype.append = function (str, tokname, notSerious, ignorePredecessor, noStripPeriods) {
   3729     var token, blob, curr;
   3730     var useblob = true;
   3731     if (notSerious) {
   3732         ignorePredecessor = true;
   3733     }
   3734     if (this.state.tmp["doing-macro-with-date"] && !notSerious) {
   3735         if (tokname !== "macro-with-date") {
   3736             return false;
   3737         }
   3738         if (tokname === "macro-with-date") {
   3739             tokname = "empty";
   3740         }
   3741     }
   3742     if ("undefined" === typeof str) {
   3743         return false;
   3744     }
   3745     if ("number" === typeof str) {
   3746         str = "" + str;
   3747     }
   3748     if (!notSerious 
   3749         && this.state.tmp.element_trace 
   3750         && this.state.tmp.element_trace.value() === "suppress-me") {
   3751         return false;
   3752     }
   3753     blob = false;
   3754     if (!tokname) {
   3755         token = this.formats.value().empty;
   3756     } else if (tokname === "literal") {
   3757         token = true;
   3758         useblob = false;
   3759     } else if ("string" === typeof tokname) {
   3760         token = this.formats.value()[tokname];
   3761     } else {
   3762         token = tokname;
   3763     }
   3764     if (!token) {
   3765         throw "CSL processor error: unknown format token name: " + tokname;
   3766     }
   3767     if (token.strings && "undefined" === typeof token.strings.delimiter) {
   3768         token.strings.delimiter = "";
   3769     }
   3770     if ("string" === typeof str && str.length) {
   3771         str = str.replace(/ ([:;?!\u00bb])/g, "\u202f$1").replace(/\u00ab /g, "\u00ab\u202f");
   3772         this.last_char_rendered = str.slice(-1);
   3773         str = str.replace(/\s+'/g, " \'");
   3774         if (!notSerious) {
   3775             str = str.replace(/^'/g, " \'");
   3776         }
   3777         if (!ignorePredecessor) {
   3778             this.state.tmp.term_predecessor = true;
   3779             this.state.tmp.in_cite_predecessor = true;
   3780         } else if (notSerious) {
   3781             this.state.tmp.term_predecessor_name = true;
   3782         }
   3783     }
   3784     blob = new CSL.Blob(str, token);
   3785     curr = this.current.value();
   3786     if ("undefined" === typeof curr && this.current.mystack.length === 0) {
   3787         this.current.mystack.push([]);
   3788         curr = this.current.value();
   3789     }
   3790     if ("string" === typeof blob.blobs) {
   3791         if (!ignorePredecessor) {
   3792             this.state.tmp.term_predecessor = true;
   3793             this.state.tmp.in_cite_predecessor = true;
   3794         } else if (notSerious) {
   3795             this.state.tmp.term_predecessor_name = true;
   3796         }
   3797     }
   3798     if (!notSerious) {
   3799         this.state.parallel.AppendBlobPointer(curr);
   3800     }
   3801     if ("string" === typeof str) {
   3802         if ("string" === typeof blob.blobs) {
   3803             if (blob.blobs.slice(0, 1) !== " ") {
   3804                 var blobPrefix = "";
   3805                 var blobBlobs = blob.blobs;
   3806                 while (CSL.TERMINAL_PUNCTUATION.indexOf(blobBlobs.slice(0, 1)) > -1) {
   3807                     blobPrefix = blobPrefix + blobBlobs.slice(0, 1);
   3808                     blobBlobs = blobBlobs.slice(1);
   3809                 }
   3810                 if (blobBlobs && blobPrefix) {
   3811                     blob.strings.prefix = blob.strings.prefix + blobPrefix;
   3812                     blob.blobs = blobBlobs;
   3813                 }
   3814             }
   3815         }
   3816         if (blob.strings["text-case"]) {
   3817             blob.blobs = CSL.Output.Formatters[blob.strings["text-case"]](this.state, str);
   3818         }
   3819         if (this.state.tmp.strip_periods && !noStripPeriods) {
   3820             blob.blobs = blob.blobs.replace(/\.([^a-z]|$)/g, "$1");
   3821         }
   3822         for (var i = blob.decorations.length - 1; i > -1; i += -1) {
   3823             if (blob.decorations[i][0] === "@quotes" && blob.decorations[i][1] !== "false") {
   3824                 blob.punctuation_in_quote = this.state.getOpt("punctuation-in-quote");
   3825             }
   3826             if (!blob.blobs.match(CSL.ROMANESQUE_REGEXP)) {
   3827                 if (blob.decorations[i][0] === "@font-style") {
   3828                     blob.decorations = blob.decorations.slice(0, i).concat(blob.decorations.slice(i + 1));
   3829                 }
   3830             }
   3831         }
   3832         curr.push(blob);
   3833         this.state.fun.flipflopper.processTags(blob);
   3834     } else if (useblob) {
   3835         curr.push(blob);
   3836     } else {
   3837         curr.push(str);
   3838     }
   3839     return true;
   3840 };
   3841 CSL.Output.Queue.prototype.string = function (state, myblobs, blob) {
   3842     var i, ilen, j, jlen, b;
   3843     var txt_esc = CSL.getSafeEscape(this.state);
   3844     var blobs = myblobs.slice();
   3845     var ret = [];
   3846     if (blobs.length === 0) {
   3847         return ret;
   3848     }
   3849     var blob_delimiter = "";
   3850     if (blob) {
   3851         blob_delimiter = blob.strings.delimiter;
   3852     } else {
   3853         state.tmp.count_offset_characters = false;
   3854         state.tmp.offset_characters = 0;
   3855     }
   3856     if (blob && blob.new_locale) {
   3857         blob.old_locale = state.opt.lang;
   3858         state.opt.lang = blob.new_locale;
   3859     }
   3860     var blobjr, use_suffix, use_prefix, params;
   3861     for (var i = 0, ilen = blobs.length; i < ilen; i += 1) {
   3862         blobjr = blobs[i];
   3863         if (blobjr.strings.first_blob) {
   3864             state.tmp.count_offset_characters = blobjr.strings.first_blob;
   3865         }
   3866         if ("string" === typeof blobjr.blobs) {
   3867             if ("number" === typeof blobjr.num) {
   3868                 ret.push(blobjr);
   3869             } else if (blobjr.blobs) {
   3870                 if (blobjr.particle) {
   3871                     blobjr.blobs = blobjr.particle + blobjr.blobs;
   3872                     blobjr.particle = "";
   3873                 }
   3874                 b = txt_esc(blobjr.blobs);
   3875                 var blen = b.length;
   3876                 if (!state.tmp.suppress_decorations) {
   3877                     for (j = 0, jlen = blobjr.decorations.length; j < jlen; j += 1) {
   3878                         params = blobjr.decorations[j];
   3879                         if (params[0] === "@showid") {
   3880                             continue;
   3881                         }
   3882                         if (state.normalDecorIsOrphan(blobjr, params)) {
   3883                             continue;
   3884                         }
   3885                         b = state.fun.decorate[params[0]][params[1]].call(blobjr, state, b, params[2]);
   3886                     }
   3887                 }
   3888                 if (b && b.length) {
   3889                     b = txt_esc(blobjr.strings.prefix) + b + txt_esc(blobjr.strings.suffix);
   3890                     if ((state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support) && !state.tmp.suppress_decorations) {
   3891                         for (j = 0, jlen = blobjr.decorations.length; j < jlen; j += 1) {
   3892                             params = blobjr.decorations[j];
   3893                             if (params[0] === "@showid") {
   3894                                 b = state.fun.decorate[params[0]][params[1]].call(blobjr, state, b, params[2]);
   3895                             }
   3896                         }
   3897                     }
   3898                     ret.push(b);
   3899                     if (state.tmp.count_offset_characters) {
   3900                         state.tmp.offset_characters += (blen + blobjr.strings.suffix.length + blobjr.strings.prefix.length);
   3901                     }
   3902                 }
   3903             }
   3904         } else if (blobjr.blobs.length) {
   3905             var addtoret = state.output.string(state, blobjr.blobs, blobjr);
   3906             if (blob) {
   3907                 if ("string" !== addtoret && addtoret.length > 1 && blobjr.strings.delimiter) {
   3908                     var numberSeen = false;
   3909                     for (var j=0,jlen=addtoret.length;j<jlen;j++) {
   3910                         if ("string" !== typeof addtoret[j]) {
   3911                             numberSeen = true;
   3912                         } else if (numberSeen) {
   3913                             addtoret[j] = (blobjr.strings.delimiter + addtoret[j]);
   3914                         }
   3915                     }
   3916                 }
   3917             }
   3918             ret = ret.concat(addtoret);
   3919         }
   3920         if (blobjr.strings.first_blob && state.registry.registry[blobjr.strings.first_blob]) {
   3921             state.registry.registry[blobjr.strings.first_blob].offset = state.tmp.offset_characters;
   3922             state.tmp.count_offset_characters = false;
   3923         }
   3924     }
   3925     for (i=0,ilen=ret.length - 1;i<ilen;i+=1) {
   3926         if ("number" === typeof ret[i].num && "number" === typeof ret[i+1].num && !ret[i+1].UGLY_DELIMITER_SUPPRESS_HACK) {
   3927             ret[i].strings.suffix = ret[i].strings.suffix + (blob_delimiter ? blob_delimiter : "");
   3928             ret[i+1].successor_prefix = "";
   3929             ret[i+1].UGLY_DELIMITER_SUPPRESS_HACK = true;
   3930         }
   3931     }
   3932     var span_split = 0;
   3933     for (var i = 0, ilen = ret.length; i < ilen; i += 1) {
   3934         if ("string" === typeof ret[i]) {
   3935             span_split = (parseInt(i, 10) + 1);
   3936             if (i < ret.length - 1  && "object" === typeof ret[i + 1]) {
   3937                 if (blob_delimiter && !ret[i + 1].UGLY_DELIMITER_SUPPRESS_HACK) {
   3938                     ret[i] += txt_esc(blob_delimiter);
   3939                 }
   3940                 ret[i + 1].UGLY_DELIMITER_SUPPRESS_HACK = true;
   3941             }
   3942         }
   3943     }
   3944     if (blob && (blob.decorations.length || blob.strings.suffix)) {
   3945         span_split = ret.length;
   3946     } else if (blob && blob.strings.prefix) {
   3947         for (var i=0,ilen=ret.length;i<ilen;i++) {
   3948             if ("undefined" !== typeof ret[i].num) {
   3949                 span_split = i;
   3950                 if (i === 0) {
   3951                     ret[i].strings.prefix = blob.strings.prefix + ret[i].strings.prefix;
   3952                 }
   3953                 break;
   3954             }
   3955         }
   3956     }
   3957     var blobs_start = state.output.renderBlobs(ret.slice(0, span_split), blob_delimiter, false, blob);
   3958     if (blobs_start && blob && (blob.decorations.length || blob.strings.suffix || blob.strings.prefix)) {
   3959         if (!state.tmp.suppress_decorations) {
   3960             for (var i = 0, ilen = blob.decorations.length; i < ilen; i += 1) {
   3961                 params = blob.decorations[i];
   3962                 if (["@cite","@bibliography", "@display", "@showid"].indexOf(params[0]) > -1) {
   3963                     continue;
   3964                 }
   3965                 if (state.normalDecorIsOrphan(blobjr, params)) {
   3966                     continue;
   3967                 }
   3968                 if ("string" === typeof blobs_start) {
   3969                     blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]);
   3970                 }
   3971             }
   3972         }
   3973         b = blobs_start;
   3974         use_suffix = blob.strings.suffix;
   3975         if (b && b.length) {
   3976             use_prefix = blob.strings.prefix;
   3977             b = txt_esc(use_prefix) + b + txt_esc(use_suffix);
   3978             if (state.tmp.count_offset_characters) {
   3979                 state.tmp.offset_characters += (use_prefix.length + use_suffix.length);
   3980             }
   3981         }
   3982         blobs_start = b;
   3983         if (!state.tmp.suppress_decorations) {
   3984             for (var i = 0, ilen = blob.decorations.length; i < ilen; i += 1) {
   3985                 params = blob.decorations[i];
   3986                 if (["@cite","@bibliography", "@display", "@showid"].indexOf(params[0]) === -1) {
   3987                     continue;
   3988                 }
   3989                 if ("string" === typeof blobs_start) {
   3990                     blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]);
   3991                 }
   3992             }
   3993         }
   3994     }
   3995     var blobs_end = ret.slice(span_split, ret.length);
   3996     if (!blobs_end.length && blobs_start) {
   3997         ret = [blobs_start];
   3998     } else if (blobs_end.length && !blobs_start) {
   3999         ret = blobs_end;
   4000     } else if (blobs_start && blobs_end.length) {
   4001         ret = [blobs_start].concat(blobs_end);
   4002     }
   4003     if ("undefined" === typeof blob) {
   4004         this.queue = [];
   4005         this.current.mystack = [];
   4006         this.current.mystack.push(this.queue);
   4007         if (state.tmp.suppress_decorations) {
   4008             ret = state.output.renderBlobs(ret, undefined, false);
   4009         }
   4010     } else if ("boolean" === typeof blob) {
   4011         ret = state.output.renderBlobs(ret, undefined, true);
   4012     }
   4013     if (blob && blob.new_locale) {
   4014         state.opt.lang = blob.old_locale;
   4015     }
   4016     return ret;
   4017 };
   4018 CSL.Output.Queue.prototype.clearlevel = function () {
   4019     var blob, pos, len;
   4020     blob = this.current.value();
   4021     len = blob.blobs.length;
   4022     for (pos = 0; pos < len; pos += 1) {
   4023         blob.blobs.pop();
   4024     }
   4025 };
   4026 CSL.Output.Queue.prototype.renderBlobs = function (blobs, delim, in_cite, parent) {
   4027     var state, ret, ret_last_char, use_delim, i, blob, pos, len, ppos, llen, pppos, lllen, res, str, params, txt_esc;
   4028     txt_esc = CSL.getSafeEscape(this.state);
   4029     if (!delim) {
   4030         delim = "";
   4031     }
   4032     state = this.state;
   4033     ret = "";
   4034     ret_last_char = [];
   4035     use_delim = "";
   4036     len = blobs.length;
   4037     if (this.state.tmp.area === "citation" && !this.state.tmp.just_looking && len === 1 && typeof blobs[0] === "object" && parent) {
   4038         blobs[0].strings.prefix = parent.strings.prefix + blobs[0].strings.prefix;
   4039         blobs[0].strings.suffix = blobs[0].strings.suffix + parent.strings.suffix;
   4040         blobs[0].decorations = blobs[0].decorations.concat(parent.decorations);
   4041         blobs[0].params = parent.params;
   4042         return blobs[0];
   4043     }
   4044     var start = true;
   4045     for (pos = 0; pos < len; pos += 1) {
   4046         if (blobs[pos].checkNext) {
   4047             blobs[pos].checkNext(blobs[pos + 1],start);
   4048             start = false;
   4049         } else if (blobs[pos+1] && blobs[pos+1].splice_prefix) {
   4050             start = false;
   4051         } else {
   4052             start = true;
   4053         }
   4054     }
   4055     var doit = true;
   4056     for (pos = blobs.length - 1; pos > 0; pos += -1) {
   4057         if (blobs[pos].checkLast) {
   4058             if (doit && blobs[pos].checkLast(blobs[pos - 1])) {
   4059                 doit = false;
   4060             }
   4061         } else {
   4062             doit = true;
   4063         }
   4064     }
   4065     len = blobs.length;
   4066     for (pos = 0; pos < len; pos += 1) {
   4067         blob = blobs[pos];
   4068         if (ret) {
   4069             use_delim = delim;
   4070         }
   4071         if ("string" === typeof blob) {
   4072             ret += txt_esc(use_delim);
   4073             ret += blob;
   4074             if (state.tmp.count_offset_characters) {
   4075                 state.tmp.offset_characters += (use_delim.length);
   4076             }
   4077         } else if (in_cite) {
   4078             if (ret) {
   4079                 ret = [ret, blob];
   4080             } else {
   4081                 ret = [blob];
   4082             }
   4083         } else if (blob.status !== CSL.SUPPRESS) {
   4084             if (blob.particle) {
   4085                 str = blob.particle + blob.num;
   4086             } else {
   4087                 str = blob.formatter.format(blob.num, blob.gender);
   4088             }
   4089             var strlen = str.replace(/<[^>]*>/g, "").length;
   4090             this.append(str, "empty", true);
   4091             var str_blob = this.pop();
   4092             var count_offset_characters = state.tmp.count_offset_characters;
   4093             str = this.string(state, [str_blob], false);
   4094             state.tmp.count_offset_characters = count_offset_characters;
   4095             if (blob.strings["text-case"]) {
   4096                 str = CSL.Output.Formatters[blob.strings["text-case"]](this.state, str);
   4097             }
   4098             if (str && this.state.tmp.strip_periods) {
   4099                 str = str.replace(/\.([^a-z]|$)/g, "$1");
   4100             }
   4101             if (!state.tmp.suppress_decorations) {
   4102                 llen = blob.decorations.length;
   4103                 for (ppos = 0; ppos < llen; ppos += 1) {
   4104                     params = blob.decorations[ppos];
   4105                     if (state.normalDecorIsOrphan(blob, params)) {
   4106                         continue;
   4107                     }
   4108                     str = state.fun.decorate[params[0]][params[1]].call(blob, state, str, params[2]);
   4109                 }
   4110             }
   4111             str = txt_esc(blob.strings.prefix) + str + txt_esc(blob.strings.suffix);
   4112             var addme = "";
   4113             if (blob.status === CSL.END) {
   4114                 addme = txt_esc(blob.range_prefix);
   4115             } else if (blob.status === CSL.SUCCESSOR) {
   4116                 addme = txt_esc(blob.successor_prefix);
   4117             } else if (blob.status === CSL.START) {
   4118                 if (pos > 0 && !blob.suppress_splice_prefix) {
   4119                     addme = txt_esc(blob.splice_prefix);
   4120                 } else {
   4121                     addme = "";
   4122                 }
   4123             } else if (blob.status === CSL.SEEN) {
   4124                 addme = txt_esc(blob.splice_prefix);
   4125             }
   4126             ret += addme;
   4127             ret += str;
   4128             if (state.tmp.count_offset_characters) {
   4129                 state.tmp.offset_characters += (addme.length + blob.strings.prefix.length + strlen + blob.strings.suffix.length);
   4130             }
   4131         }
   4132     }
   4133     return ret;
   4134 };
   4135 CSL.Output.Queue.purgeEmptyBlobs = function (parent) {
   4136     if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) {
   4137         return;
   4138     }
   4139     for (var i=parent.blobs.length-1;i>-1;i--) {
   4140         CSL.Output.Queue.purgeEmptyBlobs(parent.blobs[i]);
   4141         var child = parent.blobs[i];
   4142         if (!child || !child.blobs || !child.blobs.length) {
   4143             var buf = [];
   4144             while ((parent.blobs.length-1) > i) {
   4145                 buf.push(parent.blobs.pop());
   4146             }
   4147             parent.blobs.pop();
   4148             while (buf.length) {
   4149                 parent.blobs.push(buf.pop());
   4150             }
   4151         }
   4152     }
   4153 };
   4154 CSL.Output.Queue.adjust = function (punctInQuote) {
   4155     var NO_SWAP_IN = {
   4156         ";": true,
   4157         ":": true
   4158     }
   4159     var NO_SWAP_OUT = {
   4160         ".": true,
   4161         "!": true,
   4162         "?": true
   4163     }
   4164     this.upward = upward;
   4165     this.leftward = leftward;
   4166     this.downward = downward;
   4167     this.fix = fix;
   4168     var LtoR_MAP = {
   4169         "!": {
   4170             ".": "!",
   4171             "?": "!?",
   4172             ":": "!",
   4173             ",": "!,",
   4174             ";": "!;"
   4175         },
   4176         "?": {
   4177             "!": "?!",
   4178             ".": "?",
   4179             ":": "?",
   4180             ",": "?,",
   4181             ";": "?;"
   4182         },
   4183         ".": {
   4184             "!": ".!",
   4185             "?": ".?",
   4186             ":": ".:",
   4187             ",": ".,",
   4188             ";": ".;"
   4189         },
   4190         ":": {
   4191             "!": "!",
   4192             "?": "?",
   4193             ".": ":",
   4194             ",": ":,",
   4195             ";": ":;"
   4196         },
   4197         ",": {
   4198             "!": ",!",
   4199             "?": ",?",
   4200             ":": ",:",
   4201             ".": ",.",
   4202             ";": ",;"
   4203         },
   4204         ";": {
   4205             "!": "!",
   4206             "?": "?",
   4207             ":": ";",
   4208             ",": ";,",
   4209             ".": ";"
   4210         }
   4211     }
   4212     var SWAP_IN = {};
   4213     var SWAP_OUT = {};
   4214     var PUNCT = {};
   4215     var PUNCT_OR_SPACE = {};
   4216     for (var key in LtoR_MAP) {
   4217         PUNCT[key] = true;
   4218         PUNCT_OR_SPACE[key] = true;
   4219         if (!NO_SWAP_IN[key]) {
   4220             SWAP_IN[key] = true;
   4221         }
   4222         if (!NO_SWAP_OUT[key]) {
   4223             SWAP_OUT[key] = true;
   4224         }
   4225     }
   4226     PUNCT_OR_SPACE[" "] = true;
   4227     PUNCT_OR_SPACE[" "] = true;
   4228     var RtoL_MAP = {};
   4229     for (var key in LtoR_MAP) {
   4230         for (var subkey in LtoR_MAP[key]) {
   4231             if (!RtoL_MAP[subkey]) {
   4232                 RtoL_MAP[subkey] = {};
   4233             }
   4234             RtoL_MAP[subkey][key] = LtoR_MAP[key][subkey];
   4235         }
   4236     }
   4237     function blobIsNumber(blob) {
   4238         return ("number" === typeof blob.num || (blob.blobs && blob.blobs.length === 1 && "number" === typeof blob.blobs[0].num));
   4239     };
   4240     function blobEndsInNumber(blob) {
   4241         if ("number" === typeof blob.num) {
   4242             return true;
   4243         }
   4244         if (!blob.blobs || "object" !==  typeof blob.blobs) return false;
   4245         if (blobEndsInNumber(blob.blobs[blob.blobs.length-1])) return true;
   4246     }
   4247     function blobHasDecorations(blob,includeQuotes) {
   4248         var ret = false;
   4249         var decorlist = ['@font-style','@font-variant','@font-weight','@text-decoration','@vertical-align'];
   4250         if (includeQuotes) {
   4251             decorlist.push('@quotes');
   4252         }
   4253         if (blob.decorations) {
   4254             for (var i=0,ilen=blob.decorations.length;i<ilen;i++) {
   4255                 if (decorlist.indexOf(blob.decorations[i][0]) > -1) {
   4256                     ret = true;
   4257                     break;
   4258                 }
   4259             }
   4260         }
   4261         return ret;
   4262     };
   4263     function blobHasDescendantQuotes(blob) {
   4264         if (blob.decorations) {
   4265             for (var i=0,ilen=blob.decorations.length;i<ilen;i++) {
   4266                 if (blob.decorations[i][0] === '@quotes' && blob.decorations[i][1] !== "false") {
   4267                     return true;
   4268                 }
   4269             }
   4270         }
   4271         if ("object" !== typeof blob.blobs) {
   4272             return false
   4273         };
   4274         return blobHasDescendantQuotes(blob.blobs[blob.blobs.length-1]);
   4275     }
   4276     function blobHasDescendantMergingPunctuation(parentChar,blob) {
   4277         var childChar = blob.strings.suffix.slice(-1);
   4278         if (!childChar && "string" === typeof blob.blobs) {
   4279             childChar = blob.blobs.slice(-1);
   4280         }
   4281         var mergedChars = RtoL_MAP[parentChar][childChar];
   4282         if (mergedChars && mergedChars.length === 1) {
   4283             return true;
   4284         }
   4285         if ("object" !== typeof blob.blobs) return false;
   4286         if (blobHasDescendantMergingPunctuation(parentChar,blob.blobs[blob.blobs.length-1])) return true;
   4287         return false;
   4288     }
   4289     function matchLastChar(blob, chr) {
   4290         if (!PUNCT[chr]) {
   4291             return false;
   4292         }
   4293         if ("string" === typeof blob.blobs) {
   4294             if (blob.blobs.slice(-1) === chr) {
   4295                 return true;
   4296             } else {
   4297                 return false;
   4298             }
   4299         } else {
   4300             var child = blob.blobs[blob.blobs.length-1];
   4301             if (child) {
   4302                 var childChar = child.strings.suffix.slice(-1);
   4303                 if (!childChar) {
   4304                     return matchLastChar(child,chr);
   4305                 } else if (child.strings.suffix.slice(-1) == chr) {
   4306                     return true;
   4307                 } else {
   4308                     return false;
   4309                 }
   4310             } else {
   4311                 return false;
   4312             }
   4313         }
   4314     };
   4315     function mergeChars (First, first, Second, second, merge_right) {
   4316         var FirstStrings = "blobs" === first ? First : First.strings;
   4317         var SecondStrings = "blobs" === second ? Second: Second.strings;
   4318         var firstChar = FirstStrings[first].slice(-1);
   4319         var secondChar = SecondStrings[second].slice(0,1);
   4320         function cullRight () {
   4321             SecondStrings[second] = SecondStrings[second].slice(1);
   4322         };
   4323         function cullLeft () {
   4324             FirstStrings[first] = FirstStrings[first].slice(0,-1);
   4325         };
   4326         function addRight (chr) {
   4327             SecondStrings[second] = chr + SecondStrings[second];
   4328         }
   4329         function addLeft (chr) {
   4330             FirstStrings[first] += chr;
   4331         }
   4332         var cull = merge_right ? cullLeft : cullRight;
   4333         function matchOnRight () {
   4334             return RtoL_MAP[secondChar];
   4335         }
   4336         function matchOnLeft () {
   4337             return LtoR_MAP[firstChar];
   4338         }
   4339         var match = merge_right ? matchOnLeft : matchOnRight;
   4340         function mergeToRight () {
   4341             var chr = LtoR_MAP[firstChar][secondChar];
   4342             if ("string" === typeof chr) {
   4343                 cullLeft();
   4344                 cullRight();
   4345                 addRight(chr);
   4346             } else {
   4347                 addRight(firstChar);
   4348                 cullLeft();
   4349             }
   4350         }
   4351         function mergeToLeft () {
   4352             var chr = RtoL_MAP[secondChar][firstChar];
   4353             if ("string" === typeof chr) {
   4354                 cullLeft();
   4355                 cullRight();
   4356                 addLeft(chr);
   4357             } else {
   4358                 addLeft(secondChar);
   4359                 cullRight();
   4360             }
   4361         }
   4362         var merge = merge_right ? mergeToRight: mergeToLeft;
   4363         var isDuplicate = firstChar === secondChar;
   4364         if (isDuplicate) {
   4365             cull();
   4366         } else {
   4367             if (match()) {
   4368                 merge();
   4369             }
   4370         }
   4371     };
   4372     function upward (parent) {
   4373         if (parent.blobs && "string" == typeof parent.blobs) {
   4374             if (PUNCT[parent.strings.suffix.slice(0,1)]
   4375                 && parent.strings.suffix.slice(0,1) === parent.blobs.slice(-1)) {
   4376                 parent.strings.suffix = parent.strings.suffix.slice(1);
   4377             }
   4378             return;
   4379         } else if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) {
   4380             return;
   4381         }
   4382         var parentDecorations = blobHasDecorations(parent,true);
   4383         for (var i=parent.blobs.length-1;i>-1;i--) {
   4384             var endFlag = i === (parent.blobs.length-1);
   4385             this.upward(parent.blobs[i]);
   4386             var parentStrings = parent.strings;
   4387             var childStrings = parent.blobs[i].strings;
   4388             if (i === 0) {
   4389                 if (" " === parentStrings.prefix.slice(-1) && " " === childStrings.prefix.slice(0, 1)) {
   4390                     childStrings.prefix = childStrings.prefix.slice(1);
   4391                 }
   4392                 var childChar = childStrings.prefix.slice(0, 1);
   4393                 if (!parentDecorations && PUNCT_OR_SPACE[childChar] && !parentStrings.prefix) {
   4394                     parentStrings.prefix += childChar;
   4395                     childStrings.prefix = childStrings.prefix.slice(1);
   4396                 }
   4397             }
   4398             if (i === (parent.blobs.length - 1)) {
   4399                 var childChar = childStrings.suffix.slice(-1);
   4400                 if (!parentDecorations && [" "].indexOf(childChar) > -1) {
   4401                     if (parentStrings.suffix.slice(0,1) !== childChar) {
   4402                         parentStrings.suffix = childChar + parentStrings.suffix;
   4403                     }
   4404                     childStrings.suffix = childStrings.suffix.slice(0, -1);
   4405                 }
   4406             }
   4407             if (parentStrings.delimiter && i > 0) {
   4408                 if (PUNCT_OR_SPACE[parentStrings.delimiter.slice(-1)]
   4409                     && parentStrings.delimiter.slice(-1) === childStrings.prefix.slice(0, 1)) {
   4410                     childStrings.prefix = childStrings.prefix.slice(1);
   4411                 }
   4412             }
   4413         }
   4414     };
   4415     function leftward (parent) {
   4416         if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) {
   4417             return;
   4418         }
   4419         for (var i=parent.blobs.length-1;i>-1;i--) {
   4420             this.leftward(parent.blobs[i]);
   4421             if ((i < parent.blobs.length -1) && !parent.strings.delimiter) {
   4422                 var child = parent.blobs[i];
   4423                 var childChar = child.strings.suffix.slice(-1);
   4424                 var sibling = parent.blobs[i+1];
   4425                 var siblingChar = sibling.strings.prefix.slice(0, 1);
   4426                 var hasDecorations = blobHasDecorations(child) || blobHasDecorations(sibling);
   4427                 var hasNumber = "number" === typeof childChar || "number" === typeof siblingChar;
   4428                 if (!hasDecorations && !hasNumber && PUNCT[siblingChar] && !hasNumber) {
   4429                     var suffixAndPrefixMatch = siblingChar === child.strings.suffix.slice(-1);
   4430                     var suffixAndFieldMatch = (!child.strings.suffix && "string" === typeof child.blobs && child.blobs.slice(-1) === siblingChar);
   4431                     if (!suffixAndPrefixMatch && !suffixAndFieldMatch) {
   4432                         mergeChars(child, 'suffix', sibling, 'prefix');
   4433                     } else {
   4434                         sibling.strings.prefix = sibling.strings.prefix.slice(1);
   4435                     }
   4436                 }
   4437             }
   4438         }
   4439     };
   4440     function downward (parent, top) {
   4441         if (parent.blobs && "string" == typeof parent.blobs) {
   4442             if (PUNCT[parent.strings.suffix.slice(0,1)]
   4443                 && parent.strings.suffix.slice(0,1) === parent.blobs.slice(-1)) {
   4444                 parent.strings.suffix = parent.strings.suffix.slice(1);
   4445             }
   4446             return;
   4447         } else if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) {
   4448             return;
   4449         }
   4450         var parentStrings = parent.strings;
   4451         var someChildrenAreNumbers = false;
   4452         for (var i=0,ilen=parent.blobs.length;i<ilen;i++) {
   4453             if (blobIsNumber(parent.blobs[i])) {
   4454                 someChildrenAreNumbers = true;
   4455                 break;
   4456             }
   4457         }
   4458         if (true || !someChildrenAreNumbers) {
   4459             if (parentStrings.delimiter && PUNCT[parentStrings.delimiter.slice(0, 1)]) {
   4460                 var delimChar = parentStrings.delimiter.slice(0, 1);
   4461                 for (var i=parent.blobs.length-2;i>-1;i--) {
   4462                     var childStrings = parent.blobs[i].strings;
   4463                     if (childStrings.suffix.slice(-1) !== delimChar) {
   4464                         childStrings.suffix += delimChar;
   4465                     }
   4466                 }
   4467                 parentStrings.delimiter = parentStrings.delimiter.slice(1);
   4468             }
   4469         }
   4470         var parentDecorations = blobHasDecorations(parent, true);
   4471         var parentIsNumber = blobIsNumber(parent);
   4472         for (var i=parent.blobs.length-1;i>-1;i--) {
   4473             var child = parent.blobs[i];
   4474             var childStrings = parent.blobs[i].strings;
   4475             var childDecorations = blobHasDecorations(child, true);
   4476             var childIsNumber = blobIsNumber(child);
   4477             if (i === (parent.blobs.length - 1)) {
   4478                 if (true || !someChildrenAreNumbers) {
   4479                     var parentChar = parentStrings.suffix.slice(0, 1);
   4480                     var allowMigration = false;
   4481                     if (PUNCT[parentChar]) {
   4482                         allowMigration = blobHasDescendantMergingPunctuation(parentChar,child);
   4483                         if (!allowMigration && punctInQuote) {
   4484                             allowMigration = blobHasDescendantQuotes(child);
   4485                         }
   4486                     }
   4487                     if (allowMigration) {
   4488                         if (PUNCT[parentChar]) {
   4489                             if (!blobEndsInNumber(child)) {
   4490                                 if ("string" === typeof child.blobs) {
   4491                                     mergeChars(child, 'blobs', parent, 'suffix');
   4492                                 } else {
   4493                                     mergeChars(child, 'suffix', parent, 'suffix');
   4494                                 }
   4495                                 if (parentStrings.suffix.slice(0,1) === ".") {
   4496                                     childStrings.suffix += parentStrings.suffix.slice(0,1);
   4497                                     parentStrings.suffix = parentStrings.suffix.slice(1);
   4498                                 }
   4499                             }
   4500                         }
   4501                     }
   4502                     if (childStrings.suffix.slice(-1) === " " && parentStrings.suffix.slice(0,1) === " ") {
   4503                         parentStrings.suffix = parentStrings.suffix.slice(1);
   4504                     }
   4505                     if (PUNCT_OR_SPACE[childStrings.suffix.slice(0,1)]) {
   4506                         if ("string" === typeof child.blobs && child.blobs.slice(-1) === childStrings.suffix.slice(0,1)) {
   4507                             childStrings.suffix = childStrings.suffix.slice(1);
   4508                         }
   4509                         if (childStrings.suffix.slice(-1) === parentStrings.suffix.slice(0, 1)) {
   4510                             parentStrings.suffix = parentStrings.suffix.slice(0, -1);
   4511                         }
   4512                     }
   4513                 }
   4514                 if (matchLastChar(parent,parent.strings.suffix.slice(0,1))) {
   4515                     parent.strings.suffix = parent.strings.suffix.slice(1);
   4516                 }
   4517             } else if (parentStrings.delimiter) {
   4518                 if (PUNCT_OR_SPACE[parentStrings.delimiter.slice(0,1)]
   4519                     && parentStrings.delimiter.slice(0, 1) === childStrings.suffix.slice(-1)) {
   4520                     parent.blobs[i].strings.suffix = parent.blobs[i].strings.suffix.slice(0, -1);
   4521                 }
   4522             } else {
   4523                 var siblingStrings = parent.blobs[i+1].strings;
   4524                 if (!blobIsNumber(child) 
   4525                     && !childDecorations
   4526                     && PUNCT_OR_SPACE[childStrings.suffix.slice(-1)]
   4527                     && childStrings.suffix.slice(-1) === siblingStrings.prefix.slice(0, 1)) {
   4528                     siblingStrings.prefix = siblingStrings.prefix.slice(1);
   4529                 }
   4530             }
   4531             if (!childIsNumber && !childDecorations && PUNCT[childStrings.suffix.slice(0,1)]
   4532                 && "string" === typeof child.blobs) {
   4533                 mergeChars(child, 'blobs', child, 'suffix')
   4534             }
   4535             this.downward(parent.blobs[i]);
   4536         }
   4537     };
   4538     function swapToTheLeft (child) {
   4539         var childChar = child.strings.suffix.slice(0,1);
   4540         if ("string" === typeof child.blobs) {
   4541             while (SWAP_IN[childChar]) {
   4542                 mergeChars(child, 'blobs', child, 'suffix');
   4543                 childChar = child.strings.suffix.slice(0,1);
   4544             }                                
   4545         } else {
   4546             while (SWAP_IN[childChar]) {
   4547                 mergeChars(child.blobs[child.blobs.length-1], 'suffix', child, 'suffix');
   4548                 childChar = child.strings.suffix.slice(0,1);
   4549             }
   4550         }
   4551     }
   4552     function swapToTheRight (child) {
   4553         if ("string" === typeof child.blobs) {
   4554             var childChar = child.blobs.slice(-1);
   4555             while (SWAP_OUT[childChar]) {
   4556                 mergeChars(child, 'blobs', child, 'suffix', true);
   4557                 childChar = child.blobs.slice(-1);
   4558             }
   4559         } else {
   4560             var childChar = child.blobs[child.blobs.length-1].strings.suffix.slice(-1);
   4561             while (SWAP_OUT[childChar]) {
   4562                 mergeChars(child.blobs[child.blobs.length-1], 'suffix', child, 'suffix', true);
   4563                 childChar = child.blobs[child.blobs.length-1].strings.suffix.slice(-1);
   4564             }
   4565         }
   4566     }
   4567     function fix (parent) {
   4568         if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) {
   4569             return;
   4570         }
   4571         var lastChar;
   4572         for (var i=0,ilen=parent.blobs.length;i<ilen;i++) {
   4573             var child = parent.blobs[i];
   4574             var quoteSwap = false;
   4575             for (var j=0,jlen=child.decorations.length;j<jlen;j++) {
   4576                 var decoration = child.decorations[j];
   4577                 if (decoration[0] === "@quotes" && decoration[1] !== "false") {
   4578                     quoteSwap = true;
   4579                 }
   4580             }
   4581             if (quoteSwap) {
   4582                 if (punctInQuote) {
   4583                     swapToTheLeft(child);
   4584                 } else {
   4585                     swapToTheRight(child);
   4586                 }
   4587             }
   4588             lastChar = this.fix(parent.blobs[i]);
   4589             if (child.blobs && "string" === typeof child.blobs) {
   4590                 lastChar = child.blobs.slice(-1);
   4591             }
   4592         }
   4593         return lastChar;
   4594     };
   4595 }
   4596 CSL.Engine.Opt = function () {
   4597     this.has_disambiguate = false;
   4598     this.mode = "html";
   4599     this.dates = {};
   4600     this.jurisdictions_seen = {};
   4601     this.suppressedJurisdictions = {};
   4602     this.inheritedAttributes = {};
   4603     this["locale-sort"] = [];
   4604     this["locale-translit"] = [];
   4605     this["locale-translat"] = [];
   4606     this.citeAffixes = {
   4607         persons:{
   4608             "locale-orig":{
   4609                 prefix:"",
   4610                 suffix:""
   4611             },
   4612             "locale-translit":{
   4613                 prefix:"",
   4614                 suffix:""
   4615             },
   4616             "locale-translat":{
   4617                 prefix:"",
   4618                 suffix:""
   4619             }
   4620         },
   4621         institutions:{
   4622             "locale-orig":{
   4623                 prefix:"",
   4624                 suffix:""
   4625             },
   4626             "locale-translit":{
   4627                 prefix:"",
   4628                 suffix:""
   4629             },
   4630             "locale-translat":{
   4631                 prefix:"",
   4632                 suffix:""
   4633             }
   4634         },
   4635         titles:{
   4636             "locale-orig":{
   4637                 prefix:"",
   4638                 suffix:""
   4639             },
   4640             "locale-translit":{
   4641                 prefix:"",
   4642                 suffix:""
   4643             },
   4644             "locale-translat":{
   4645                 prefix:"",
   4646                 suffix:""
   4647             }
   4648         },
   4649         journals:{
   4650             "locale-orig":{
   4651                 prefix:"",
   4652                 suffix:""
   4653             },
   4654             "locale-translit":{
   4655                 prefix:"",
   4656                 suffix:""
   4657             },
   4658             "locale-translat":{
   4659                 prefix:"",
   4660                 suffix:""
   4661             }
   4662         },
   4663         publishers:{
   4664             "locale-orig":{
   4665                 prefix:"",
   4666                 suffix:""
   4667             },
   4668             "locale-translit":{
   4669                 prefix:"",
   4670                 suffix:""
   4671             },
   4672             "locale-translat":{
   4673                 prefix:"",
   4674                 suffix:""
   4675             }
   4676         },
   4677         places:{
   4678             "locale-orig":{
   4679                 prefix:"",
   4680                 suffix:""
   4681             },
   4682             "locale-translit":{
   4683                 prefix:"",
   4684                 suffix:""
   4685             },
   4686             "locale-translat":{
   4687                 prefix:"",
   4688                 suffix:""
   4689             }
   4690         }
   4691     };
   4692     this["default-locale"] = [];
   4693     this.update_mode = CSL.NONE;
   4694     this.bib_mode = CSL.NONE;
   4695     this.sort_citations = false;
   4696     this["et-al-min"] = 0;
   4697     this["et-al-use-first"] = 1;
   4698     this["et-al-use-last"] = false;
   4699     this["et-al-subsequent-min"] = false;
   4700     this["et-al-subsequent-use-first"] = false;
   4701     this["demote-non-dropping-particle"] = "display-and-sort";
   4702     this["parse-names"] = true;
   4703     this.citation_number_slug = false;
   4704     this.trigraph = "Aaaa00:AaAa00:AaAA00:AAAA00";
   4705     this.nodenames = [];
   4706     this.gender = {};
   4707     this['cite-lang-prefs'] = {
   4708         persons:['orig'],
   4709         institutions:['orig'],
   4710         titles:['orig'],
   4711         journals:['orig'],
   4712         publishers:['orig'],
   4713         places:['orig'],
   4714         number:['orig']
   4715     };
   4716     this.has_layout_locale = false;
   4717     this.development_extensions = {};
   4718     this.development_extensions.field_hack = true;
   4719     this.development_extensions.allow_field_hack_date_override = true;
   4720     this.development_extensions.locator_date_and_revision = true;
   4721     this.development_extensions.locator_parsing_for_plurals = true;
   4722     this.development_extensions.locator_label_parse = true;
   4723     this.development_extensions.raw_date_parsing = true;
   4724     this.development_extensions.clean_up_csl_flaws = true;
   4725     this.development_extensions.flip_parentheses_to_braces = true;
   4726     this.development_extensions.jurisdiction_subfield = true;
   4727     this.development_extensions.static_statute_locator = false;
   4728     this.development_extensions.csl_reverse_lookup_support = false;
   4729     this.development_extensions.clobber_locator_if_no_statute_section = false;
   4730     this.development_extensions.wrap_url_and_doi = false;
   4731     this.development_extensions.allow_force_lowercase = false;
   4732     this.development_extensions.handle_parallel_articles = false;
   4733     this.development_extensions.thin_non_breaking_space_html_hack = false;
   4734     this.development_extensions.apply_citation_wrapper = false;
   4735     this.development_extensions.main_title_from_short_title = false;
   4736     this.development_extensions.uppercase_subtitles = false;
   4737     this.development_extensions.normalize_lang_keys_to_lowercase = false;
   4738     this.development_extensions.strict_text_case_locales = false;
   4739     this.development_extensions.rtl_support = false;
   4740     this.development_extensions.expect_and_symbol_form = false;
   4741     this.development_extensions.require_explicit_legal_case_title_short = false;
   4742     this.development_extensions.spoof_institutional_affiliations = false;
   4743     this.development_extensions.force_jurisdiction = false;
   4744     this.development_extensions.parse_names = true;
   4745 };
   4746 CSL.Engine.Tmp = function () {
   4747     this.names_max = new CSL.Stack();
   4748     this.names_base = new CSL.Stack();
   4749     this.givens_base = new CSL.Stack();
   4750     this.value = [];
   4751     this.namepart_decorations = {};
   4752     this.namepart_type = false;
   4753     this.area = "citation";
   4754     this.root = "citation";
   4755     this.extension = "";
   4756     this.can_substitute = new CSL.Stack(0, CSL.LITERAL);
   4757     this.element_rendered_ok = false;
   4758     this.element_trace = new CSL.Stack("style");
   4759     this.nameset_counter = 0;
   4760     this.group_context = new CSL.Stack({
   4761         term_intended: false,
   4762         variable_attempt: false,
   4763         variable_success: false,
   4764         output_tip: undefined,
   4765         label_form:  undefined,
   4766         parallel_conditions: undefined,
   4767         condition: false,
   4768         force_suppress: false,
   4769         done_vars: []
   4770     });
   4771     this.term_predecessor = false;
   4772     this.in_cite_predecessor = false;
   4773     this.jump = new CSL.Stack(0, CSL.LITERAL);
   4774     this.decorations = new CSL.Stack();
   4775     this.tokenstore_stack = new CSL.Stack();
   4776     this.last_suffix_used = "";
   4777     this.last_names_used = [];
   4778     this.last_years_used = [];
   4779     this.years_used = [];
   4780     this.names_used = [];
   4781     this.taintedItemIDs = {};
   4782     this.taintedCitationIDs = {};
   4783     this.initialize_with = new CSL.Stack();
   4784     this.disambig_request = false;
   4785     this["name-as-sort-order"] = false;
   4786     this.suppress_decorations = false;
   4787     this.disambig_settings = new CSL.AmbigConfig();
   4788     this.bib_sort_keys = [];
   4789     this.prefix = new CSL.Stack("", CSL.LITERAL);
   4790     this.suffix = new CSL.Stack("", CSL.LITERAL);
   4791     this.delimiter = new CSL.Stack("", CSL.LITERAL);
   4792     this.cite_locales = [];
   4793     this.cite_affixes = {
   4794         citation: false, 
   4795         bibliography: false,
   4796         citation_sort: false, 
   4797         bibliography_sort: false
   4798     };
   4799     this.strip_periods = 0;
   4800     this.shadow_numbers = {};
   4801     this.authority_stop_last = 0;
   4802     this.loadedItemIDs = {};
   4803 };
   4804 CSL.Engine.Fun = function (state) {
   4805     this.match = new CSL.Util.Match;
   4806     this.suffixator = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS);
   4807     this.romanizer = new CSL.Util.Romanizer();
   4808     this.ordinalizer = new CSL.Util.Ordinalizer(state);
   4809     this.long_ordinalizer = new CSL.Util.LongOrdinalizer();
   4810 };
   4811 CSL.Engine.Build = function () {
   4812     this["alternate-term"] = false;
   4813     this.in_bibliography = false;
   4814     this.in_style = false;
   4815     this.skip = false;
   4816     this.postponed_macro = false;
   4817     this.layout_flag = false;
   4818     this.name = false;
   4819     this.form = false;
   4820     this.term = false;
   4821     this.macro = {};
   4822     this.macro_stack = [];
   4823     this.text = false;
   4824     this.lang = false;
   4825     this.area = "citation";
   4826     this.root = "citation";
   4827     this.extension = "";
   4828     this.substitute_level = new CSL.Stack(0, CSL.LITERAL);
   4829     this.names_level = 0;
   4830     this.render_nesting_level = 0;
   4831     this.render_seen = false;
   4832 };
   4833 CSL.Engine.Configure = function () {
   4834     this.fail = [];
   4835     this.succeed = [];
   4836 };
   4837 CSL.Engine.Citation = function (state) {
   4838     this.opt = {
   4839         inheritedAttributes: {}
   4840     };
   4841     this.tokens = [];
   4842     this.srt = new CSL.Registry.Comparifier(state, "citation_sort");
   4843     this.opt.collapse = [];
   4844     this.opt["disambiguate-add-names"] = false;
   4845     this.opt["disambiguate-add-givenname"] = false;
   4846     this.opt["disambiguate-add-year-suffix"] = false;
   4847     this.opt["givenname-disambiguation-rule"] = "by-cite";
   4848     this.opt["near-note-distance"] = 5;
   4849     this.opt.topdecor = [];
   4850     this.opt.layout_decorations = [];
   4851     this.opt.layout_prefix = "";
   4852     this.opt.layout_suffix = "";
   4853     this.opt.layout_delimiter = "";
   4854     this.opt.sort_locales = [];
   4855     this.opt.max_number_of_names = 0;
   4856     this.root = "citation";
   4857 };
   4858 CSL.Engine.Bibliography = function () {
   4859     this.opt = {
   4860         inheritedAttributes: {}
   4861     };
   4862     this.tokens = [];
   4863     this.opt.collapse = [];
   4864     this.opt.topdecor = [];
   4865     this.opt.layout_decorations = [];
   4866     this.opt.layout_prefix = "";
   4867     this.opt.layout_suffix = "";
   4868     this.opt.layout_delimiter = "";
   4869     this.opt["line-spacing"] = 1;
   4870     this.opt["entry-spacing"] = 1;
   4871     this.opt.sort_locales = [];
   4872     this.opt.max_number_of_names = 0;
   4873     this.root = "bibliography";
   4874 };
   4875 CSL.Engine.BibliographySort = function () {
   4876     this.tokens = [];
   4877     this.opt = {};
   4878     this.opt.sort_directions = [];
   4879     this.keys = [];
   4880     this.opt.topdecor = [];
   4881     this.root = "bibliography";
   4882 };
   4883 CSL.Engine.CitationSort = function () {
   4884     this.tokens = [];
   4885     this.opt = {};
   4886     this.opt.sort_directions = [];
   4887     this.keys = [];
   4888     this.opt.topdecor = [];
   4889     this.root = "citation";
   4890 };
   4891 CSL.Engine.prototype.previewCitationCluster = function (citation, citationsPre, citationsPost, newMode) {
   4892     var oldMode = this.opt.mode;
   4893     this.setOutputFormat(newMode);
   4894     var ret = this.processCitationCluster(citation, citationsPre, citationsPost, CSL.PREVIEW);
   4895     this.setOutputFormat(oldMode);
   4896     return ret[1];
   4897 };
   4898 CSL.Engine.prototype.appendCitationCluster = function (citation) {
   4899     var citationsPre = [];
   4900     var len = this.registry.citationreg.citationByIndex.length;
   4901     for (var pos = 0; pos < len; pos += 1) {
   4902         var c = this.registry.citationreg.citationByIndex[pos];
   4903         citationsPre.push(["" + c.citationID, c.properties.noteIndex]);
   4904     }
   4905     return this.processCitationCluster(citation, citationsPre, [])[1];
   4906 };
   4907 CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, citationsPost, flag) {
   4908     var c, i, ilen, j, jlen, k, klen, n, nlen, key, Item, item, noteCitations, textCitations, m, citationsInNote;
   4909     this.debug = false;
   4910     this.tmp.loadedItemIDs = {};
   4911     this.tmp.citation_errors = [];
   4912     var return_data = {"bibchange": false};
   4913     this.setCitationId(citation);
   4914     var oldCitationList;
   4915     var oldItemList;
   4916     var oldAmbigs;
   4917     if (flag === CSL.PREVIEW) {
   4918         oldCitationList = this.registry.citationreg.citationByIndex.slice();
   4919         oldItemList = this.registry.reflist.slice();
   4920         var newCitationList = citationsPre.concat([["" + citation.citationID, citation.properties.noteIndex]]).concat(citationsPost);
   4921         var newItemIds = {};
   4922         var newItemIdsList = [];
   4923         for (var i = 0, ilen = newCitationList.length; i < ilen; i += 1) {
   4924             c = this.registry.citationreg.citationById[newCitationList[i][0]];
   4925             for (j = 0, jlen = c.citationItems.length; j < jlen; j += 1) {
   4926                 newItemIds[c.citationItems[j].id] = true;
   4927                 newItemIdsList.push("" + c.citationItems[j].id);
   4928             }
   4929         }
   4930         oldAmbigs = {};
   4931         for (var i = 0, ilen = oldItemList.length; i < ilen; i += 1) {
   4932             if (!newItemIds[oldItemList[i].id]) {
   4933                 var oldAkey = this.registry.registry[oldItemList[i].id].ambig;
   4934                 var ids = this.registry.ambigcites[oldAkey];
   4935                 if (ids) {
   4936                     for (j = 0, jlen = ids.length; j < jlen; j += 1) {
   4937                         oldAmbigs[ids[j]] = CSL.cloneAmbigConfig(this.registry.registry[ids[j]].disambig);
   4938                     }
   4939                 }
   4940             }
   4941         }
   4942     }
   4943     this.tmp.taintedCitationIDs = {};
   4944     var sortedItems = [];
   4945     var rerunAkeys = {};
   4946     for (var i = 0, ilen = citation.citationItems.length; i < ilen; i += 1) {
   4947         item = {};
   4948         for (var key in citation.citationItems[i]) {
   4949             item[key] = citation.citationItems[i][key];
   4950         }
   4951         Item = this.retrieveItem("" + item.id);
   4952         if (Item.id) {
   4953             this.transform.loadAbbreviation("default", "hereinafter", Item.id);
   4954         }
   4955         item = CSL.parseLocator.call(this, item);
   4956         if (this.opt.development_extensions.static_statute_locator) {
   4957             this.remapSectionVariable([[Item,item]]);
   4958         }
   4959         if (this.opt.development_extensions.locator_label_parse) {
   4960             if (item.locator && ["bill","gazette","legislation","regulation","treaty"].indexOf(Item.type) === -1 && (!item.label || item.label === 'page')) {
   4961                 var m = CSL.LOCATOR_LABELS_REGEXP.exec(item.locator);
   4962                 if (m) {
   4963                     var tryLabel = CSL.LOCATOR_LABELS_MAP[m[2]];
   4964                     if (this.getTerm(tryLabel)) {
   4965                         item.label = tryLabel;
   4966                         item.locator = m[3];
   4967                     }
   4968                 }
   4969             }
   4970         }
   4971         var newitem = [Item, item];
   4972         sortedItems.push(newitem);
   4973         citation.citationItems[i].item = Item;
   4974     }
   4975     citation.sortedItems = sortedItems;
   4976     var citationByIndex = [];
   4977     for (var i = 0, ilen = citationsPre.length; i < ilen; i += 1) {
   4978         c = citationsPre[i];
   4979         try {
   4980             this.registry.citationreg.citationById[c[0]].properties.noteIndex = c[1];
   4981         } catch (e) {
   4982             var err = "CSL error\n";
   4983             err += "  " + e + "\n";
   4984             err += "  citationID=" + c[0] + "\n";
   4985             err += "  noteIndex=" + c[1] + "\n";
   4986             err += "  atarray citationsPre index " + i + ", from citation at document position " + citationsPre.length;
   4987             throw err;
   4988         }
   4989         citationByIndex.push(this.registry.citationreg.citationById[c[0]]);
   4990     }
   4991     citationByIndex.push(citation);
   4992     for (var i = 0, ilen = citationsPost.length; i < ilen; i += 1) {
   4993         c = citationsPost[i];
   4994         try {
   4995             this.registry.citationreg.citationById[c[0]].properties.noteIndex = c[1];
   4996         } catch (e) {
   4997             var err = "CSL error\n";
   4998             err += "  " + e + "\n";
   4999             err += "  citationID=" + c[0] + "\n";
   5000             err += "  noteIndex=" + c[1] + "\n";
   5001             err += "  at array citationsPost index " + i + ", from citation at document position " + citationsPre.length;
   5002             throw err;
   5003         }
   5004         citationByIndex.push(this.registry.citationreg.citationById[c[0]]);
   5005     }
   5006     this.registry.citationreg.citationByIndex = citationByIndex;
   5007     this.registry.citationreg.citationsByItemId = {};
   5008     if (this.opt.update_mode === CSL.POSITION) {
   5009         textCitations = [];
   5010         noteCitations = [];
   5011         citationsInNote = {};
   5012     }
   5013     var update_items = [];
   5014     for (var i = 0, ilen = citationByIndex.length; i < ilen; i += 1) {
   5015         if (!citationByIndex[i].properties) {
   5016             citationByIndex[i].properties = {};
   5017         }
   5018         citationByIndex[i].properties.index = i;
   5019         for (j = 0, jlen = citationByIndex[i].sortedItems.length; j < jlen; j += 1) {
   5020             item = citationByIndex[i].sortedItems[j];
   5021             if (!this.registry.citationreg.citationsByItemId[item[1].id]) {
   5022                 this.registry.citationreg.citationsByItemId[item[1].id] = [];
   5023                 update_items.push("" + item[1].id);
   5024             }
   5025             if (this.registry.citationreg.citationsByItemId[item[1].id].indexOf(citationByIndex[i]) === -1) {
   5026                 this.registry.citationreg.citationsByItemId[item[1].id].push(citationByIndex[i]);
   5027             }
   5028         }
   5029         if (this.opt.update_mode === CSL.POSITION) {
   5030             if (citationByIndex[i].properties.noteIndex) {
   5031                 noteCitations.push(citationByIndex[i]);
   5032             } else {
   5033                 citationByIndex[i].properties.noteIndex = 0;
   5034                 textCitations.push(citationByIndex[i]);
   5035             }
   5036         }
   5037     }
   5038     if (flag !== CSL.ASSUME_ALL_ITEMS_REGISTERED) {
   5039         this.updateItems(update_items, null, null, true);
   5040     }
   5041     if (!this.opt.citation_number_sort && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
   5042         for (var i = 0, ilen = sortedItems.length; i < ilen; i += 1) {
   5043             sortedItems[i][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[i][0], "citation_sort");
   5044         }
   5045         if (this.opt.grouped_sort &&  !citation.properties.unsorted) {
   5046             for (var i = 0, ilen = sortedItems.length; i < ilen; i += 1) {
   5047                 var sortkeys = sortedItems[i][1].sortkeys;
   5048                 this.tmp.authorstring_request = true;
   5049                 var mydisambig = this.registry.registry[sortedItems[i][0].id].disambig;
   5050                 this.tmp.authorstring_request = true;
   5051                 CSL.getAmbiguousCite.call(this, sortedItems[i][0], mydisambig);
   5052                 var authorstring = this.registry.authorstrings[sortedItems[i][0].id];
   5053                 this.tmp.authorstring_request = false;
   5054                 sortedItems[i][1].sortkeys = [authorstring].concat(sortkeys);
   5055             }
   5056             sortedItems.sort(this.citation.srt.compareCompositeKeys);
   5057             var lastauthor = false;
   5058             var thiskey = false;
   5059             var thisauthor = false;
   5060             for (var i = 0, ilen = sortedItems.length; i < ilen; i += 1) {
   5061                 if (sortedItems[i][1].sortkeys[0] !== lastauthor) {
   5062                     thisauthor = sortedItems[i][1].sortkeys[0];
   5063                     thiskey =  sortedItems[i][1].sortkeys[1];
   5064                 }
   5065                 sortedItems[i][1].sortkeys[0] = "" + thiskey + i;
   5066                 lastauthor = thisauthor;
   5067             }
   5068         }
   5069         if (!citation.properties.unsorted) {
   5070             sortedItems.sort(this.citation.srt.compareCompositeKeys);
   5071         }
   5072     }
   5073     var citations;
   5074     if (this.opt.update_mode === CSL.POSITION) {
   5075         for (var i = 0; i < 2; i += 1) {
   5076             citations = [textCitations, noteCitations][i];
   5077             var first_ref = {};
   5078             var last_ref = {};
   5079             for (j = 0, jlen = citations.length; j < jlen; j += 1) {
   5080                 var onecitation = citations[j];
   5081                 if (!citations[j].properties.noteIndex) {
   5082                     citations[j].properties.noteIndex = 0;
   5083                 }
   5084                 citations[j].properties.noteIndex = parseInt(citations[j].properties.noteIndex, 10);
   5085                 if (j > 0 && citations[j - 1].properties.noteIndex > citations[j].properties.noteIndex) {
   5086                     citationsInNote = {};
   5087                     first_ref = {};
   5088                     last_ref = {};
   5089                 }
   5090                 for (k = 0, klen = onecitation.sortedItems.length; k < klen; k += 1) {
   5091                     if (!this.registry.registry[onecitation.sortedItems[k][1].id].parallel) {
   5092                         if (!citationsInNote[onecitation.properties.noteIndex]) {
   5093                             citationsInNote[onecitation.properties.noteIndex] = 1;
   5094                         } else {
   5095                             citationsInNote[onecitation.properties.noteIndex] += 1;
   5096                         }
   5097                     }
   5098                 }
   5099                 for (k = 0, klen = citations[j].sortedItems.length; k < klen; k += 1) {
   5100                     item = citations[j].sortedItems[k];
   5101                     var myid = item[0].id;
   5102                     var mylocator = item[1].locator;
   5103                     var mylabel = item[1].label;
   5104                     if (item[0].legislation_id) {
   5105                         myid = item[0].legislation_id;
   5106                     }
   5107                     var incitationid;
   5108                     if (k > 0) {
   5109                         if (onecitation.sortedItems[k - 1][0].legislation_id) {
   5110                             incitationid = onecitation.sortedItems[k - 1][0].legislation_id;
   5111                         } else {
   5112                             incitationid = onecitation.sortedItems[k - 1][1].id;
   5113                         }
   5114                     }
   5115                     if (flag === CSL.PREVIEW) {
   5116                         if (onecitation.citationID != citation.citationID) {
   5117                             if ("undefined" === typeof first_ref[item[1].id]) {
   5118                                 first_ref[myid] = onecitation.properties.noteIndex;
   5119                                 last_ref[myid] = onecitation.properties.noteIndex;
   5120                             } else {
   5121                                 last_ref[myid] = onecitation.properties.noteIndex;
   5122                             }
   5123                             continue;
   5124                         }
   5125                     }
   5126                     var oldvalue = {};
   5127                     oldvalue.position = item[1].position;
   5128                     oldvalue["first-reference-note-number"] = item[1]["first-reference-note-number"];
   5129                     oldvalue["near-note"] = item[1]["near-note"];
   5130                     item[1]["first-reference-note-number"] = 0;
   5131                     item[1]["near-note"] = false;
   5132                     if (this.registry.citationreg.citationsByItemId[myid]) {
   5133                         if (this.opt.xclass === 'note' && this.opt.has_disambiguate) {
   5134                             var oldCount = this.registry.registry[myid]["citation-count"]
   5135                             var newCount = this.registry.citationreg.citationsByItemId[myid].length;
   5136                             this.registry.registry[myid]["citation-count"] = this.registry.citationreg.citationsByItemId[myid].length;
   5137                             if ("number" === typeof oldCount) {
   5138                                 var oldCountCheck = (oldCount < 2);
   5139                                 var newCountCheck = (newCount < 2);
   5140                                 if (oldCountCheck !== newCountCheck) {
   5141                                     for (var l=0,llen=this.registry.citationreg.citationsByItemId[myid].length;l<llen;l++) {
   5142                                         rerunAkeys[this.registry.registry[myid].ambig] = true;
   5143                                         this.tmp.taintedCitationIDs[this.registry.citationreg.citationsByItemId[myid][l].citationID] = true;
   5144                                     }
   5145                                 }
   5146                             } else {
   5147                                 for (var l=0,llen=this.registry.citationreg.citationsByItemId[myid].length;l<llen;l++) {
   5148                                     rerunAkeys[this.registry.registry[myid].ambig] = true;
   5149                                     this.tmp.taintedCitationIDs[this.registry.citationreg.citationsByItemId[myid][l].citationID] = true;
   5150                                 }
   5151                             }
   5152                         }
   5153                     }
   5154                     var oldlastid;
   5155                     if ("undefined" === typeof first_ref[myid]) {
   5156                         first_ref[myid] = onecitation.properties.noteIndex;
   5157                         if (this.registry.registry[myid]) {
   5158                             this.registry.registry[myid]['first-reference-note-number'] = onecitation.properties.noteIndex;
   5159                         }
   5160                         last_ref[myid] = onecitation.properties.noteIndex;
   5161                         item[1].position = CSL.POSITION_FIRST;
   5162                     } else {
   5163                         var ibidme = false;
   5164                         var suprame = false;
   5165                         if (j > 0) {
   5166                             try {
   5167                                 oldlastid =  citations[j - 1].sortedItems.slice(-1)[0][1].id;
   5168                             } catch (e) {
   5169                                 var err = "CSL Error\n";
   5170                                 err += "  " + e;
   5171                                 err += "  in citation object " + citations[j - 1].citationID + " at index " + (j - 1);
   5172                                 throw err;
   5173                             }
   5174                             if (citations[j - 1].sortedItems[0].slice(-1)[0].legislation_id) {
   5175                                 oldlastid = citations[j - 1].sortedItems[0].slice(-1)[0].legislation_id;
   5176                             }
   5177                         }
   5178                         if (j > 0 && parseInt(k, 10) === 0 && citations[j - 1].properties.noteIndex !== citations[j].properties.noteIndex) {
   5179                             var items = citations[(j - 1)].sortedItems;
   5180                             var useme = false;
   5181                             var oldid = citations[j - 1].sortedItems[0][0].id;
   5182                             if (citations[j - 1].sortedItems[0][0].legislation_id) {
   5183                                 oldid = citations[j - 1].sortedItems[0][0].legislation_id;
   5184                             }
   5185                             if ((oldid  == myid && citations[j - 1].properties.noteIndex >= (citations[j].properties.noteIndex - 1)) || citations[j - 1].sortedItems[0][1].id == this.registry.registry[item[1].id].parallel) {
   5186                                 if (citationsInNote[citations[j - 1].properties.noteIndex] === 1 || citations[j - 1].properties.noteIndex === 0) {
   5187                                     useme = true;
   5188                                 }
   5189                             }
   5190                             for (n = 0, nlen = items.slice(1).length; n < nlen; n += 1) {
   5191                                 var itmp = items.slice(1)[n];
   5192                                 if (!this.registry.registry[itmp[1].id].parallel || this.registry.registry[itmp[1].id].parallel == this.registry.registry[itmp[1].id]) {
   5193                                     useme = false;
   5194                                 }
   5195                             }
   5196                             if (useme) {
   5197                                 ibidme = true;
   5198                             } else {
   5199                                 suprame = true;
   5200                             }
   5201                         } else if (k > 0 && incitationid == myid) {
   5202                             ibidme = true;
   5203                         } else if (k === 0 && citations[j - 1].properties.noteIndex == citations[j].properties.noteIndex
   5204                                    && citations[j - 1].sortedItems.length 
   5205                                    && oldlastid == myid) {
   5206                             ibidme = true;
   5207                         } else {
   5208                             suprame = true;
   5209                         }
   5210                         var prev, prev_locator, prev_label, curr_locator, curr_label;
   5211                         if (ibidme) {
   5212                             if (k > 0) {
   5213                                 prev = onecitation.sortedItems[(k - 1)][1];
   5214                             } else {
   5215                                 prev = citations[(j - 1)].sortedItems[0][1];
   5216                             }
   5217                             if (prev.locator) {
   5218                                 if (prev.label) {
   5219                                     prev_label = prev.label;
   5220                                 } else {
   5221                                     prev_label = "";
   5222                                 }
   5223                                 prev_locator = "" + prev.locator + prev_label;
   5224                             } else {
   5225                                 prev_locator = prev.locator;
   5226                             }
   5227                             if (mylocator) {
   5228                                 if (mylabel) {
   5229                                     curr_label = mylabel;
   5230                                 } else {
   5231                                     curr_label = "";
   5232                                 }
   5233                                 curr_locator = "" + mylocator + curr_label;
   5234                             } else {
   5235                                 curr_locator = mylocator;
   5236                             }
   5237                         }
   5238                         if (ibidme && prev_locator && !curr_locator) {
   5239                             ibidme = false;
   5240                             suprame = true;
   5241                         }
   5242                         if (ibidme) {
   5243                             if (!prev_locator && curr_locator) {
   5244                                 item[1].position = CSL.POSITION_IBID_WITH_LOCATOR;
   5245                             } else if (!prev_locator && !curr_locator) {
   5246                                 item[1].position = CSL.POSITION_IBID;
   5247                             } else if (prev_locator && curr_locator === prev_locator) {
   5248                                 item[1].position = CSL.POSITION_IBID;
   5249                             } else if (prev_locator && curr_locator && curr_locator !== prev_locator) {
   5250                                 item[1].position = CSL.POSITION_IBID_WITH_LOCATOR;
   5251                             } else {
   5252                                 ibidme = false; // just to be clear
   5253                                 suprame = true;
   5254                             }
   5255                         }
   5256                         if (suprame) {
   5257                             item[1].position = CSL.POSITION_SUBSEQUENT;
   5258                         }
   5259                         if (suprame || ibidme) {
   5260                             if (first_ref[myid] != onecitation.properties.noteIndex) {
   5261                                 item[1]["first-reference-note-number"] = first_ref[myid];
   5262                                 if (this.registry.registry[myid]) {
   5263                                     var oldFirst = this.registry.citationreg.citationsByItemId[myid][0].properties.noteIndex;
   5264                                     var newFirst = onecitation.properties.noteIndex;
   5265                                     this.registry.registry[myid]['first-reference-note-number'] = newFirst < oldFirst ? newFirst: oldFirst;
   5266                                 }
   5267                             }
   5268                         }
   5269                     }
   5270                     if (onecitation.properties.noteIndex) {
   5271                         var note_distance = parseInt(onecitation.properties.noteIndex, 10) - parseInt(last_ref[myid], 10);
   5272                         if (item[1].position !== CSL.POSITION_FIRST 
   5273                             && note_distance <= this.citation.opt["near-note-distance"]) {
   5274                             item[1]["near-note"] = true;
   5275                         }
   5276                         last_ref[myid] = onecitation.properties.noteIndex;
   5277                     }
   5278                     if (onecitation.citationID != citation.citationID) {
   5279                         for (n = 0, nlen = CSL.POSITION_TEST_VARS.length; n < nlen; n += 1) {
   5280                             var param = CSL.POSITION_TEST_VARS[n];
   5281                             if (item[1][param] !== oldvalue[param]) {
   5282                                 if (this.registry.registry[myid]) {
   5283                                     if (param === 'first-reference-note-number') {
   5284                                         rerunAkeys[this.registry.registry[myid].ambig] = true;
   5285                                         this.tmp.taintedItemIDs[myid] = true;
   5286                                     }
   5287                                 }
   5288                                 this.tmp.taintedCitationIDs[onecitation.citationID] = true;
   5289                             }
   5290                         }
   5291                     }
   5292                     if (this.sys.variableWrapper) {
   5293                         item[1].index = onecitation.properties.index;
   5294                         item[1].noteIndex = onecitation.properties.noteIndex;
   5295                     }
   5296                 }
   5297             }
   5298         }
   5299     }
   5300     if (this.opt.citation_number_sort && sortedItems && sortedItems.length > 1 && this.citation_sort.tokens.length > 0) {
   5301         if (!citation.properties.unsorted) {
   5302             for (var i = 0, ilen = sortedItems.length; i < ilen; i += 1) {
   5303                 sortedItems[i][1].sortkeys = CSL.getSortKeys.call(this, sortedItems[i][0], "citation_sort");
   5304             }
   5305             sortedItems.sort(this.citation.srt.compareCompositeKeys);
   5306         }
   5307     }
   5308     for (var key in this.tmp.taintedItemIDs) {
   5309         if (this.tmp.taintedItemIDs.hasOwnProperty(key)) {
   5310             citations = this.registry.citationreg.citationsByItemId[key];
   5311             if (citations) {
   5312                 for (var i = 0, ilen = citations.length; i < ilen; i += 1) {
   5313                     this.tmp.taintedCitationIDs[citations[i].citationID] = true;
   5314                 }
   5315             }
   5316         }
   5317     }
   5318     var ret = [];
   5319     if (flag === CSL.PREVIEW) {
   5320         try {
   5321             ret = this.process_CitationCluster.call(this, citation.sortedItems, citation.citationID);
   5322         } catch (e) {
   5323             CSL.error("Error running CSL processor for preview: "+e);
   5324         }
   5325         this.registry.citationreg.citationByIndex = oldCitationList;
   5326         this.registry.citationreg.citationById = {};
   5327         for (var i = 0, ilen = oldCitationList.length; i < ilen; i += 1) {
   5328             this.registry.citationreg.citationById[oldCitationList[i].citationID] = oldCitationList[i];
   5329         }
   5330         var oldItemIds = [];
   5331         for (var i = 0, ilen = oldItemList.length; i < ilen; i += 1) {
   5332             oldItemIds.push("" + oldItemList[i].id);
   5333         }
   5334         this.updateItems(oldItemIds, null, null, true);
   5335         for (var key in oldAmbigs) {
   5336             if (oldAmbigs.hasOwnProperty(key)) {
   5337                 this.registry.registry[key].disambig = oldAmbigs[key];
   5338             }
   5339         }
   5340     } else {
   5341         for (var rerunAkey in rerunAkeys) {
   5342             this.disambiguate.run(rerunAkey, citation);
   5343         }
   5344         var obj;
   5345         for (var key in this.tmp.taintedCitationIDs) {
   5346             if (key == citation.citationID) {
   5347                 continue;
   5348             }
   5349             var mycitation = this.registry.citationreg.citationById[key];
   5350             if (!mycitation.properties.unsorted) {
   5351                 for (var i = 0, ilen = mycitation.sortedItems.length; i < ilen; i += 1) {
   5352                     mycitation.sortedItems[i][1].sortkeys = CSL.getSortKeys.call(this, mycitation.sortedItems[i][0], "citation_sort");
   5353                 }
   5354                 mycitation.sortedItems.sort(this.citation.srt.compareCompositeKeys);
   5355             }
   5356             this.tmp.citation_pos = mycitation.properties.index;
   5357             this.tmp.citation_note_index = mycitation.properties.noteIndex;
   5358             this.tmp.citation_id = "" + mycitation.citationID;
   5359             obj = [];
   5360             obj.push(mycitation.properties.index);
   5361             obj.push(this.process_CitationCluster.call(this, mycitation.sortedItems, mycitation.citationID));
   5362             obj.push(mycitation.citationID);
   5363             ret.push(obj);
   5364         }
   5365         this.tmp.taintedItemIDs = {};
   5366         this.tmp.taintedCitationIDs = {};
   5367         this.tmp.citation_pos = citation.properties.index;
   5368         this.tmp.citation_note_index = citation.properties.noteIndex;
   5369         this.tmp.citation_id = "" + citation.citationID;
   5370         obj = [];
   5371         obj.push(citationsPre.length);
   5372         obj.push(this.process_CitationCluster.call(this, sortedItems, citation.citationID));
   5373         obj.push(citation.citationID);
   5374         ret.push(obj);
   5375         ret.sort(function (a, b) {
   5376             if (a[0] > b[0]) {
   5377                 return 1;
   5378             } else if (a[0] < b[0]) {
   5379                 return -1;
   5380             } else {
   5381                 return 0;
   5382             }
   5383         });
   5384     }
   5385     return_data.citation_errors = this.tmp.citation_errors.slice();
   5386     return [return_data, ret];
   5387 };
   5388 CSL.Engine.prototype.process_CitationCluster = function (sortedItems, citationID) {
   5389     var str;
   5390     this.parallel.StartCitation(sortedItems);
   5391     str = CSL.getCitationCluster.call(this, sortedItems, citationID);
   5392     return str;
   5393 };
   5394 CSL.Engine.prototype.makeCitationCluster = function (rawList) {
   5395     var inputList, newitem, str, pos, len, item, Item;
   5396     inputList = [];
   5397     len = rawList.length;
   5398     for (pos = 0; pos < len; pos += 1) {
   5399         item = {};
   5400         for (var key in rawList[pos]) {
   5401             item[key] = rawList[pos][key];
   5402         }
   5403         Item = this.retrieveItem("" + item.id);
   5404         if (this.opt.development_extensions.locator_label_parse) {
   5405             if (item.locator && ["bill","gazette","legislation","regulation","treaty"].indexOf(Item.type) === -1 && (!item.label || item.label === 'page')) {
   5406                 var m = CSL.LOCATOR_LABELS_REGEXP.exec(item.locator);
   5407                 if (m) {
   5408                     var tryLabel = CSL.LOCATOR_LABELS_MAP[m[2]];
   5409                     if (this.getTerm(tryLabel)) {
   5410                         item.label = tryLabel;
   5411                         item.locator = m[3];
   5412                     }
   5413                 }
   5414             }
   5415         }
   5416         if (item.locator) {
   5417             item.locator = ("" + item.locator).replace(/\s+$/, '');
   5418         }
   5419         newitem = [Item, item];
   5420         inputList.push(newitem);
   5421     }
   5422     if (this.opt.development_extensions.static_statute_locator) {
   5423         this.remapSectionVariable(inputList);
   5424     }
   5425     if (inputList && inputList.length > 1 && this.citation_sort.tokens.length > 0) {
   5426         len = inputList.length;
   5427         for (pos = 0; pos < len; pos += 1) {
   5428             inputList[pos][1].sortkeys = CSL.getSortKeys.call(this, inputList[pos][0], "citation_sort");
   5429         }
   5430         inputList.sort(this.citation.srt.compareCompositeKeys);
   5431     }
   5432     this.tmp.citation_errors = [];
   5433     this.parallel.StartCitation(inputList);
   5434     str = CSL.getCitationCluster.call(this, inputList);
   5435     return str;
   5436 };
   5437 CSL.getAmbiguousCite = function (Item, disambig, visualForm, item) {
   5438     var use_parallels, ret;
   5439     var flags = this.tmp.group_context.tip;
   5440     var oldTermSiblingLayer = {
   5441         term_intended: flags.term_intended,
   5442         variable_attempt: flags.variable_attempt,
   5443         variable_success: flags.variable_success,
   5444         output_tip: flags.output_tip,
   5445         label_form: flags.label_form,
   5446         parallel_conditions: flags.parallel_conditions,
   5447         condition: flags.condition,
   5448         force_suppress: flags.force_suppress,
   5449         done_vars: flags.done_vars.slice()
   5450     }
   5451     if (disambig) {
   5452         this.tmp.disambig_request = disambig;
   5453     } else {
   5454         this.tmp.disambig_request = false;
   5455     }
   5456     var itemSupp = {
   5457         position: 1,
   5458         "near-note": true
   5459     };
   5460     if (item) {
   5461         itemSupp.locator = item.locator;
   5462         itemSupp.label = item.label;
   5463     }
   5464     if (this.registry.registry[Item.id] 
   5465         && this.registry.citationreg.citationsByItemId
   5466         && this.registry.citationreg.citationsByItemId[Item.id]
   5467         && this.registry.citationreg.citationsByItemId[Item.id].length 
   5468         && visualForm) {
   5469         if (this.citation.opt["givenname-disambiguation-rule"] === "by-cite") {
   5470             itemSupp['first-reference-note-number'] = this.registry.registry[Item.id]['first-reference-note-number'];
   5471         }
   5472     }
   5473     this.tmp.area = "citation";
   5474     this.tmp.root = "citation";
   5475     this.parallel.use_parallels = (this.parallel.use_parallels === true || this.parallel.use_parallels === null) ? null : false;
   5476     this.tmp.suppress_decorations = true;
   5477     this.tmp.just_looking = true;
   5478     CSL.getCite.call(this, Item, itemSupp, null, false);
   5479     for (var i=0,ilen=this.output.queue.length;i<ilen;i+=1) {
   5480         CSL.Output.Queue.purgeEmptyBlobs(this.output.queue[i]);
   5481     }
   5482     if (this.opt.development_extensions.clean_up_csl_flaws) {
   5483         for (var j=0,jlen=this.output.queue.length;j<jlen;j+=1) {
   5484             this.output.adjust.upward(this.output.queue[j]);
   5485             this.output.adjust.leftward(this.output.queue[j]);
   5486             this.output.adjust.downward(this.output.queue[j]);
   5487             this.output.adjust.fix(this.output.queue[j]);
   5488         }
   5489     }
   5490     var ret = this.output.string(this, this.output.queue);
   5491     this.tmp.just_looking = false;
   5492     this.tmp.suppress_decorations = false;
   5493     this.parallel.use_parallels = this.parallel.use_parallels === null ? true : false;
   5494     this.tmp.group_context.replace(oldTermSiblingLayer);
   5495     return ret;
   5496 };
   5497 CSL.getSpliceDelimiter = function (last_locator, last_collapsed, pos) {
   5498     if (undefined !== this.citation.opt["after-collapse-delimiter"]) {
   5499         if (last_locator) {
   5500             this.tmp.splice_delimiter = this.citation.opt["after-collapse-delimiter"];
   5501         } else if (last_collapsed && !this.tmp.have_collapsed) {
   5502             this.tmp.splice_delimiter = this.citation.opt["after-collapse-delimiter"];
   5503         } else if (!last_collapsed && !this.tmp.have_collapsed && this.citation.opt.collapse !== "year-suffix") {
   5504             this.tmp.splice_delimiter = this.citation.opt["after-collapse-delimiter"];
   5505         } else {
   5506             this.tmp.splice_delimiter = this.citation.opt.layout_delimiter;
   5507         }
   5508     } else if (this.tmp.use_cite_group_delimiter) {
   5509         this.tmp.splice_delimiter = this.citation.opt.cite_group_delimiter;
   5510     } else {
   5511         if (this.tmp.have_collapsed && this.opt.xclass === "in-text" && this.opt.update_mode !== CSL.NUMERIC) {
   5512             this.tmp.splice_delimiter = ", ";
   5513         } else if (this.tmp.cite_locales[pos - 1]) {
   5514             var alt_affixes = this.tmp.cite_affixes[this.tmp.area][this.tmp.cite_locales[pos - 1]];
   5515             if (alt_affixes && alt_affixes.delimiter) {
   5516                 this.tmp.splice_delimiter = alt_affixes.delimiter;
   5517             }
   5518         } else if (!this.tmp.splice_delimiter) {
   5519             this.tmp.splice_delimiter = "";
   5520         }
   5521     }
   5522     return this.tmp.splice_delimiter;
   5523 };
   5524 CSL.getCitationCluster = function (inputList, citationID) {
   5525     var result, objects, myparams, len, pos, item, last_collapsed, params, empties, composite, compie, myblobs, Item, llen, ppos, obj, preceding_item, txt_esc, error_object;
   5526     inputList = inputList ? inputList : [];
   5527     this.tmp.last_primary_names_string = false;
   5528     txt_esc = CSL.getSafeEscape(this);
   5529     this.tmp.area = "citation";
   5530     this.tmp.root = "citation";
   5531     result = "";
   5532     objects = [];
   5533     this.tmp.last_suffix_used = "";
   5534     this.tmp.last_names_used = [];
   5535     this.tmp.last_years_used = [];
   5536     this.tmp.backref_index = [];
   5537     this.tmp.cite_locales = [];
   5538     this.output.checkNestedBrace = new CSL.checkNestedBrace(this);
   5539     var use_layout_prefix = this.output.checkNestedBrace.update(this.citation.opt.layout_prefix);
   5540     var suppressTrailingPunctuation = false;
   5541     if (this.opt.xclass === "note" && this.citation.opt.suppressTrailingPunctuation) {
   5542         suppressTrailingPunctuation = true;
   5543     }
   5544     if (citationID) {
   5545         if (this.registry.citationreg.citationById[citationID].properties["suppress-trailing-punctuation"]) {
   5546             suppressTrailingPunctuation = true;
   5547         }
   5548     }
   5549     if (this.opt.xclass === "note") {
   5550         var parasets = [];
   5551         var lastTitle = false;
   5552         var lastPosition = false;
   5553         var lastID = false;
   5554         var lst = [];
   5555         for (var i=0, ilen = inputList.length; i < ilen; i += 1) {
   5556             var type = inputList[i][0].type;
   5557             var title = inputList[i][0].title;
   5558             var position = inputList[i][1].position;
   5559             var id = inputList[i][0].id;
   5560             if (title && type === "legal_case" && id !== lastID && position) {
   5561                 if (title !== lastTitle || parasets.length === 0) {
   5562                     lst = [];
   5563                     parasets.push(lst);
   5564                 }
   5565                 lst.push(inputList[i][1]);
   5566             }
   5567             lastTitle = title;
   5568             lastPosition = position;
   5569             lastID = id;
   5570         }
   5571         for (i=0, ilen=parasets.length; i < ilen; i += 1) {
   5572             lst = parasets[i];
   5573             if (lst.length < 2) {
   5574                 continue;
   5575             }
   5576             var locatorInLastPosition = lst.slice(-1)[0].locator;
   5577             if (locatorInLastPosition) {
   5578                 for (var j=0, jlen=lst.length - 1; j < jlen; j += 1) {
   5579                     if (lst[j].locator) {
   5580                         locatorInLastPosition = false;
   5581                     }
   5582                 }
   5583             }
   5584             if (locatorInLastPosition) {
   5585                 lst[0].locator = locatorInLastPosition;
   5586                 delete lst.slice(-1)[0].locator;
   5587                 lst[0].label = lst.slice(-1)[0].label;
   5588                 if (lst.slice(-1)[0].label) {
   5589                     delete lst.slice(-1)[0].label;
   5590                 }
   5591             }
   5592        }
   5593     }
   5594     myparams = [];
   5595     len = inputList.length;
   5596     for (pos = 0; pos < len; pos += 1) {
   5597         Item = inputList[pos][0];
   5598         item = inputList[pos][1];
   5599         item = CSL.parseLocator.call(this, item);
   5600         last_collapsed = this.tmp.have_collapsed;
   5601         var last_locator = false;
   5602         if (pos > 0 && inputList[pos-1][1]) {
   5603             last_locator = !!inputList[pos-1][1].locator;
   5604         }
   5605         params = {};
   5606         this.tmp.shadow_numbers = {};
   5607         if (!this.tmp.just_looking && this.opt.hasPlaceholderTerm) {
   5608             var output = this.output;
   5609             this.output = new CSL.Output.Queue(this);
   5610             this.output.adjust = new CSL.Output.Queue.adjust();
   5611             CSL.getAmbiguousCite.call(this, Item, null, false, item);
   5612             this.output = output;
   5613         }
   5614         this.tmp.in_cite_predecessor = false;
   5615         if (pos > 0) {
   5616             CSL.getCite.call(this, Item, item, "" + inputList[(pos - 1)][0].id, true);
   5617         } else {
   5618             this.tmp.term_predecessor = false;
   5619             CSL.getCite.call(this, Item, item, null, true);
   5620         }
   5621         if (!this.tmp.cite_renders_content) {
   5622             error_object = {
   5623                 citationID: "" + this.tmp.citation_id,
   5624                 index: this.tmp.citation_pos,
   5625                 noteIndex: this.tmp.citation_note_index,
   5626                 itemID: "" + Item.id,
   5627                 citationItems_pos: pos,
   5628                 error_code: CSL.ERROR_NO_RENDERED_FORM
   5629             };
   5630             this.tmp.citation_errors.push(error_object);
   5631         }
   5632         if (pos === (inputList.length - 1)) {
   5633             this.parallel.ComposeSet();
   5634         }
   5635         params.splice_delimiter = CSL.getSpliceDelimiter.call(this, last_locator, last_collapsed, pos);
   5636         if (item && item["author-only"]) {
   5637             this.tmp.suppress_decorations = true;
   5638         }
   5639         if (pos > 0) {
   5640             preceding_item = inputList[pos - 1][1];
   5641             var precedingEndsInPeriodOrComma = preceding_item.suffix && [".", ","].indexOf(preceding_item.suffix.slice(-1)) > -1;
   5642             var currentStartsWithPeriodOrComma = !preceding_item.suffix && item.prefix && [".", ","].indexOf(item.prefix.slice(0, 1)) > -1;
   5643             if (precedingEndsInPeriodOrComma || currentStartsWithPeriodOrComma) {
   5644                 var spaceidx = params.splice_delimiter.indexOf(" ");
   5645                 if (spaceidx > -1 && !currentStartsWithPeriodOrComma) {
   5646                     params.splice_delimiter = params.splice_delimiter.slice(spaceidx);
   5647                 } else {
   5648                     params.splice_delimiter = "";
   5649                 }
   5650             }
   5651         }
   5652         params.suppress_decorations = this.tmp.suppress_decorations;
   5653         params.have_collapsed = this.tmp.have_collapsed;
   5654         myparams.push(params);
   5655     }
   5656     this.tmp.has_purged_parallel = false;
   5657     this.parallel.PruneOutputQueue(this);
   5658     empties = 0;
   5659     myblobs = this.output.queue.slice();
   5660     var fakeblob = {
   5661         strings: {
   5662             suffix: this.citation.opt.layout_suffix,
   5663             delimiter: this.citation.opt.layout_delimiter                
   5664         }
   5665     };
   5666     var suffix = this.citation.opt.layout_suffix;
   5667     var last_locale = this.tmp.cite_locales[this.tmp.cite_locales.length - 1];
   5668     if (last_locale && this.tmp.cite_affixes[this.tmp.area][last_locale] && this.tmp.cite_affixes[this.tmp.area][last_locale].suffix) {
   5669         suffix = this.tmp.cite_affixes[this.tmp.area][last_locale].suffix;
   5670     }
   5671     if (CSL.TERMINAL_PUNCTUATION.slice(0, -1).indexOf(suffix.slice(0, 1)) > -1) {
   5672         suffix = suffix.slice(0, 1);
   5673     }
   5674     var delimiter = this.citation.opt.layout_delimiter;
   5675     if (!delimiter) {
   5676         delimiter = "";
   5677     }
   5678     if (CSL.TERMINAL_PUNCTUATION.slice(0, -1).indexOf(delimiter.slice(0, 1)) > -1) {
   5679         delimiter = delimiter.slice(0, 1);
   5680     }
   5681     suffix = this.output.checkNestedBrace.update(suffix);
   5682     for (var i=0,ilen=this.output.queue.length;i<ilen;i+=1) {
   5683         CSL.Output.Queue.purgeEmptyBlobs(this.output.queue[i]);
   5684     }
   5685     if (!this.tmp.suppress_decorations && this.output.queue.length) {
   5686         if (!(this.opt.development_extensions.apply_citation_wrapper
   5687               && this.sys.wrapCitationEntry
   5688                && !this.tmp.just_looking
   5689               && this.tmp.area === "citation")) { 
   5690             if (!suppressTrailingPunctuation) {
   5691                 this.output.queue[this.output.queue.length - 1].strings.suffix = suffix;
   5692             }
   5693             this.output.queue[0].strings.prefix = use_layout_prefix;
   5694         }
   5695     }
   5696     if (this.opt.development_extensions.clean_up_csl_flaws) {
   5697         for (var j=0,jlen=this.output.queue.length;j<jlen;j+=1) {
   5698             this.output.adjust.upward(this.output.queue[j]);
   5699             this.output.adjust.leftward(this.output.queue[j]);
   5700             this.output.adjust.downward(this.output.queue[j]);
   5701             this.tmp.last_chr = this.output.adjust.fix(this.output.queue[j]);
   5702         }
   5703     }
   5704     for (pos = 0, len = myblobs.length; pos < len; pos += 1) {
   5705         var buffer = [];
   5706         this.output.queue = [myblobs[pos]];
   5707         this.tmp.suppress_decorations = myparams[pos].suppress_decorations;
   5708         this.tmp.splice_delimiter = myparams[pos].splice_delimiter;
   5709         if (myblobs[pos].parallel_delimiter) {
   5710             this.tmp.splice_delimiter = myblobs[pos].parallel_delimiter;
   5711         }
   5712         this.tmp.have_collapsed = myparams[pos].have_collapsed;
   5713         composite = this.output.string(this, this.output.queue);
   5714         this.tmp.suppress_decorations = false;
   5715         if ("string" === typeof composite) {
   5716             this.tmp.suppress_decorations = false;
   5717             return composite;
   5718         }
   5719         if ("object" === typeof composite && composite.length === 0 && !item["suppress-author"]) {
   5720             if (this.tmp.has_purged_parallel) {
   5721                 composite.push("");
   5722             } else {
   5723                 var errStr = "[CSL STYLE ERROR: reference with no printed form.]";
   5724                 var preStr = pos === 0 ? txt_esc(this.citation.opt.layout_prefix) : "";
   5725                 var sufStr = pos === (myblobs.length - 1) ? txt_esc(this.citation.opt.layout_suffix) : "";
   5726                 composite.push(preStr + errStr + sufStr);
   5727             }
   5728         }
   5729         if (buffer.length && "string" === typeof composite[0]) {
   5730             composite.reverse();
   5731             var tmpstr = composite.pop();
   5732             if (tmpstr && tmpstr.slice(0, 1) === ",") {
   5733                 buffer.push(tmpstr);
   5734             } else if ("string" == typeof buffer.slice(-1)[0] && buffer.slice(-1)[0].slice(-1) === ",") {
   5735                 buffer.push(" " + tmpstr);
   5736             } else if (tmpstr) {
   5737                 buffer.push(txt_esc(this.tmp.splice_delimiter) + tmpstr);
   5738             }
   5739         } else {
   5740             composite.reverse();
   5741             compie = composite.pop();
   5742             if ("undefined" !== typeof compie) {
   5743                 if (buffer.length && "string" === typeof buffer[buffer.length - 1]) {
   5744                     buffer[buffer.length - 1] += compie.successor_prefix;
   5745                 }
   5746                 buffer.push(compie);
   5747             }
   5748         }
   5749         llen = composite.length;
   5750         for (ppos = 0; ppos < llen; ppos += 1) {
   5751             obj = composite[ppos];
   5752             if ("string" === typeof obj) {
   5753                 buffer.push(txt_esc(this.tmp.splice_delimiter) + obj);
   5754                 continue;
   5755             }
   5756             compie = composite.pop();
   5757             if ("undefined" !== typeof compie) {
   5758                 buffer.push(compie);
   5759             }
   5760         }
   5761         if (buffer.length === 0 && !inputList[pos][1]["suppress-author"]) {
   5762             empties += 1;
   5763         }
   5764         if (buffer.length > 1 && typeof buffer[0] !== "string") {
   5765             buffer = [this.output.renderBlobs(buffer)];
   5766         }
   5767         if (buffer.length) {
   5768             if ("string" === typeof buffer[0]) {
   5769                 if (pos > 0) {
   5770                     buffer[0] = txt_esc(this.tmp.splice_delimiter) + buffer[0];
   5771                 }
   5772             } else {
   5773                 if (pos > 0) {
   5774                     buffer[0].splice_prefix = this.tmp.splice_delimiter;
   5775                 } else {
   5776                     buffer[0].splice_prefix = "";
   5777                 }
   5778             }
   5779         }
   5780         objects = objects.concat(buffer);
   5781     }
   5782     result += this.output.renderBlobs(objects);
   5783     if (result) {
   5784         if (!this.tmp.suppress_decorations) {
   5785             len = this.citation.opt.layout_decorations.length;
   5786             for (pos = 0; pos < len; pos += 1) {
   5787                 params = this.citation.opt.layout_decorations[pos];
   5788                 if (params[1] === "normal") {
   5789                     continue;
   5790                 }
   5791                 if (!item || !item["author-only"]) {
   5792                     result = this.fun.decorate[params[0]][params[1]](this, result);
   5793                 }
   5794             }
   5795         }
   5796     }
   5797     this.tmp.suppress_decorations = false;
   5798     return result;
   5799 };
   5800 CSL.getCite = function (Item, item, prevItemID, blockShadowNumberReset) {
   5801     var next, error_object;
   5802     this.tmp.cite_renders_content = false;
   5803     this.parallel.StartCite(Item, item, prevItemID);
   5804     CSL.citeStart.call(this, Item, item, blockShadowNumberReset);
   5805     next = 0;
   5806     this.tmp.name_node = {};
   5807     this.nameOutput = new CSL.NameOutput(this, Item, item);
   5808     while (next < this[this.tmp.area].tokens.length) {
   5809         next = CSL.tokenExec.call(this, this[this.tmp.area].tokens[next], Item, item);
   5810     }
   5811     CSL.citeEnd.call(this, Item, item);
   5812     this.parallel.CloseCite(this);
   5813     if (!this.tmp.cite_renders_content && !this.tmp.just_looking) {
   5814         if (this.tmp.area === "bibliography") {
   5815             error_object = {
   5816                 index: this.tmp.bibliography_pos,
   5817                 itemID: "" + Item.id,
   5818                 error_code: CSL.ERROR_NO_RENDERED_FORM
   5819             };
   5820             this.tmp.bibliography_errors.push(error_object);
   5821         }
   5822     }
   5823     return "" + Item.id;
   5824 };
   5825 CSL.citeStart = function (Item, item, blockShadowNumberReset) {
   5826     if (!blockShadowNumberReset) {
   5827         this.tmp.shadow_numbers = {};
   5828     }
   5829     this.tmp.disambiguate_count = 0;
   5830     this.tmp.disambiguate_maxMax = 0;
   5831     this.tmp.same_author_as_previous_cite = false;
   5832     if (!this.tmp.suppress_decorations) {
   5833         this.tmp.subsequent_author_substitute_ok = true;
   5834     } else {
   5835         this.tmp.subsequent_author_substitute_ok = false;
   5836     }
   5837     this.tmp.lastchr = "";
   5838     if (this.tmp.area === "citation" && this.citation.opt.collapse && this.citation.opt.collapse.length) {
   5839         this.tmp.have_collapsed = true;
   5840     } else {
   5841         this.tmp.have_collapsed = false;
   5842     }
   5843     this.tmp.render_seen = false;
   5844     if (this.tmp.disambig_request  && ! this.tmp.disambig_override) {
   5845         this.tmp.disambig_settings = this.tmp.disambig_request;
   5846     } else if (this.registry.registry[Item.id] && ! this.tmp.disambig_override) {
   5847         this.tmp.disambig_request = this.registry.registry[Item.id].disambig;
   5848         this.tmp.disambig_settings = this.registry.registry[Item.id].disambig;
   5849     } else {
   5850         this.tmp.disambig_settings = new CSL.AmbigConfig();
   5851     }
   5852     if (this.tmp.area !== 'citation') {
   5853         if (!this.registry.registry[Item.id]) {
   5854             this.tmp.disambig_restore = new CSL.AmbigConfig();
   5855         } else {
   5856             this.tmp.disambig_restore = CSL.cloneAmbigConfig(this.registry.registry[Item.id].disambig);
   5857             if (this.tmp.area === 'bibliography' && this.tmp.disambig_settings && this.tmp.disambig_override) {
   5858                 if (this.opt["disambiguate-add-names"]) {
   5859                     this.tmp.disambig_settings.names = this.registry.registry[Item.id].disambig.names.slice();
   5860                     if (this.tmp.disambig_request) {
   5861                         this.tmp.disambig_request.names = this.registry.registry[Item.id].disambig.names.slice();
   5862                     }
   5863                 }
   5864                 if (this.opt["disambiguate-add-givenname"]) {
   5865                     this.tmp.disambig_request = this.tmp.disambig_settings;
   5866                     this.tmp.disambig_settings.givens = this.registry.registry[Item.id].disambig.givens.slice();
   5867                     this.tmp.disambig_request.givens = this.registry.registry[Item.id].disambig.givens.slice();
   5868                     for (var i=0,ilen=this.tmp.disambig_settings.givens.length;i<ilen;i+=1) {
   5869                         this.tmp.disambig_settings.givens[i] = this.registry.registry[Item.id].disambig.givens[i].slice();
   5870                     }
   5871                     for (var i=0,ilen=this.tmp.disambig_request.givens.length;i<ilen;i+=1) {
   5872                         this.tmp.disambig_request.givens[i] = this.registry.registry[Item.id].disambig.givens[i].slice();
   5873                     }
   5874                 }
   5875             }
   5876         }
   5877     }
   5878     this.tmp.names_used = [];
   5879     this.tmp.nameset_counter = 0;
   5880     this.tmp.years_used = [];
   5881     this.tmp.names_max.clear();
   5882     this.tmp.splice_delimiter = this[this.tmp.area].opt.layout_delimiter;
   5883     this.bibliography_sort.keys = [];
   5884     this.citation_sort.keys = [];
   5885     this.tmp.has_done_year_suffix = false;
   5886     this.tmp.last_cite_locale = false;
   5887     if (!this.tmp.just_looking && item && !item.position && this.registry.registry[Item.id]) {
   5888         this.tmp.disambig_restore = CSL.cloneAmbigConfig(this.registry.registry[Item.id].disambig);
   5889     }
   5890     this.tmp.first_name_string = false;
   5891     this.tmp.authority_stop_last = 0;
   5892 };
   5893 CSL.citeEnd = function (Item, item) {
   5894     if (this.tmp.disambig_restore && this.registry.registry[Item.id]) {
   5895         this.registry.registry[Item.id].disambig.names = this.tmp.disambig_restore.names.slice();
   5896         this.registry.registry[Item.id].disambig.givens = this.tmp.disambig_restore.givens.slice();
   5897         for (var i=0,ilen=this.registry.registry[Item.id].disambig.givens.length;i<ilen;i+=1) {
   5898             this.registry.registry[Item.id].disambig.givens[i] = this.tmp.disambig_restore.givens[i].slice();
   5899         }
   5900     }
   5901     this.tmp.disambig_restore = false;
   5902     if (item && item.suffix) {
   5903         this.tmp.last_suffix_used = item.suffix;
   5904     } else {
   5905         this.tmp.last_suffix_used = "";
   5906     }
   5907     this.tmp.last_years_used = this.tmp.years_used.slice();
   5908     this.tmp.last_names_used = this.tmp.names_used.slice();
   5909     this.tmp.cut_var = false;
   5910     this.tmp.disambig_request = false;
   5911     this.tmp.cite_locales.push(this.tmp.last_cite_locale);
   5912     if (this.tmp.issued_date && this.tmp.renders_collection_number) {
   5913         var buf = [];
   5914         for (var i = this.tmp.issued_date.list.length - 1; i > this.tmp.issued_date.pos; i += -1) {
   5915             buf.push(this.tmp.issued_date.list.pop());
   5916         }
   5917         this.tmp.issued_date.list.pop();
   5918         for (i = buf.length - 1; i > -1; i += -1) {
   5919             this.tmp.issued_date.list.push(buf.pop());
   5920         }
   5921         if (this.parallel.use_parallels) {
   5922             this.parallel.cite["issued"] = false;
   5923         }
   5924     }
   5925     this.tmp.issued_date = false;
   5926     this.tmp.renders_collection_number = false;
   5927 };
   5928 CSL.Engine.prototype.makeBibliography = function (bibsection) {
   5929     var debug, ret, params, maxoffset, item, len, pos, tok, tokk, tokkk, entry_ids, entry_strings, bibliography_errors;
   5930     debug = false;
   5931     if (!this.bibliography.tokens.length) {
   5932         return false;
   5933     }
   5934     if ("string" === typeof bibsection) {
   5935         this.opt.citation_number_slug = bibsection;
   5936         bibsection = false;
   5937     }
   5938     ret = CSL.getBibliographyEntries.call(this, bibsection);
   5939     entry_ids = ret[0];
   5940     entry_strings = ret[1];
   5941     var done = ret[2];
   5942     params = {
   5943         "maxoffset": 0,
   5944         "entryspacing": this.bibliography.opt["entry-spacing"],
   5945         "linespacing": this.bibliography.opt["line-spacing"],
   5946         "second-field-align": false,
   5947         "entry_ids": entry_ids,
   5948         "bibliography_errors": this.tmp.bibliography_errors.slice(),
   5949         "done": done
   5950     };
   5951     if (this.bibliography.opt["second-field-align"]) {
   5952         params["second-field-align"] = this.bibliography.opt["second-field-align"];
   5953     }
   5954     maxoffset = 0;
   5955     len = this.registry.reflist.length;
   5956     for (pos = 0; pos < len; pos += 1) {
   5957         item = this.registry.reflist[pos];
   5958         if (item.offset > params.maxoffset) {
   5959             params.maxoffset = item.offset;
   5960         }
   5961     }
   5962     if (this.bibliography.opt.hangingindent) {
   5963         params.hangingindent = this.bibliography.opt.hangingindent;
   5964     }
   5965     params.bibstart = this.fun.decorate.bibstart;
   5966     params.bibend = this.fun.decorate.bibend;
   5967     this.opt.citation_number_slug = false;
   5968     return [params, entry_strings];
   5969 };
   5970 CSL.getBibliographyEntries = function (bibsection) {
   5971     var ret, input, include, anymatch, allmatch, bib_entry, res, len, pos, item, llen, ppos, spec, lllen, pppos, bib_layout, topblobs, all_item_ids, entry_item_ids, debug, collapse_parallel, i, ilen, siblings, skips, sortedItems, eyetem, chr, entry_item_data, j, jlen, newIDs, originalIDs;
   5972     ret = [];
   5973     entry_item_data = [];
   5974     this.tmp.area = "bibliography";
   5975     this.tmp.root = "bibliography";
   5976     this.tmp.last_rendered_name = false;
   5977     this.tmp.bibliography_errors = [];
   5978     this.tmp.bibliography_pos = 0;
   5979     if (bibsection && bibsection.page_start && bibsection.page_length) {
   5980         input = this.registry.getSortedIds();        
   5981     } else {
   5982         input = this.retrieveItems(this.registry.getSortedIds());
   5983     }
   5984     this.tmp.disambig_override = true;
   5985     function eval_string(a, b) {
   5986         if (a === b) {
   5987             return true;
   5988         }
   5989         return false;
   5990     }
   5991     function eval_list(a, lst) {
   5992         lllen = lst.length;
   5993         for (pppos = 0; pppos < lllen; pppos += 1) {
   5994             if (eval_string(a, lst[pppos])) {
   5995                 return true;
   5996             }
   5997         }
   5998         return false;
   5999     }
   6000     function eval_spec(a, b) {
   6001         if ((a === "none" || !a) && !b) {
   6002             return true;
   6003         }
   6004         if ("string" === typeof b) {
   6005             return eval_string(a, b);
   6006         } else if (!b) {
   6007             return false;
   6008         } else {
   6009             return eval_list(a, b);
   6010         }
   6011     }
   6012     skips = {};
   6013     var page_item_count;
   6014     if (bibsection && bibsection.page_start && bibsection.page_length) {
   6015         page_item_count = 0;
   6016         if (bibsection.page_start !== true) {
   6017             for (var i = 0, ilen = input.length; i < ilen; i += 1) {
   6018                 skips[input[i]] = true;
   6019                 if (bibsection.page_start == input[i]) {
   6020                     break;
   6021                 }
   6022             }
   6023         }
   6024     }
   6025     var processed_item_ids = [];
   6026     for (var i = 0, ilen = input.length; i < ilen; i += 1) {
   6027         if (bibsection && bibsection.page_start && bibsection.page_length) {
   6028             if (skips[input[i]]) {
   6029                 continue;
   6030             }
   6031             item = this.retrieveItem(input[i]);
   6032             if (page_item_count === bibsection.page_length) {
   6033                 break;
   6034             }
   6035         } else {
   6036             item = input[i];
   6037             if (skips[item.id]) {
   6038                 continue;
   6039             }
   6040         }
   6041         if (bibsection) {
   6042             include = true;
   6043             if (bibsection.include) {
   6044                 include = false;
   6045                 for (j = 0, jlen = bibsection.include.length; j < jlen; j += 1) {
   6046                     spec = bibsection.include[j];
   6047                     if (eval_spec(spec.value, item[spec.field])) {
   6048                         include = true;
   6049                         break;
   6050                     }
   6051                 }
   6052             } else if (bibsection.exclude) {
   6053                 anymatch = false;
   6054                 for (j = 0, jlen = bibsection.exclude.length; j < jlen; j += 1) {
   6055                     spec = bibsection.exclude[j];
   6056                     if (eval_spec(spec.value, item[spec.field])) {
   6057                         anymatch = true;
   6058                         break;
   6059                     }
   6060                 }
   6061                 if (anymatch) {
   6062                     include = false;
   6063                 }
   6064             } else if (bibsection.select) {
   6065                 include = false;
   6066                 allmatch = true;
   6067                 for (j = 0, jlen = bibsection.select.length; j < jlen; j += 1) {
   6068                     spec = bibsection.select[j];
   6069                     if (!eval_spec(spec.value, item[spec.field])) {
   6070                         allmatch = false;
   6071                     }
   6072                 }
   6073                 if (allmatch) {
   6074                     include = true;
   6075                 }
   6076             }
   6077             if (bibsection.quash) {
   6078                 allmatch = true;
   6079                 for (j = 0, jlen = bibsection.quash.length; j < jlen; j += 1) {
   6080                     spec = bibsection.quash[j];
   6081                     if (!eval_spec(spec.value, item[spec.field])) {
   6082                         allmatch = false;
   6083                     }
   6084                 }
   6085                 if (allmatch) {
   6086                     include = false;
   6087                 }
   6088             }
   6089             if (!include) {
   6090                 continue;
   6091             }
   6092         }
   6093         bib_entry = new CSL.Token("group", CSL.START);
   6094         bib_entry.decorations = [["@bibliography", "entry"]].concat(this.bibliography.opt.layout_decorations);
   6095         this.output.startTag("bib_entry", bib_entry);
   6096         if (item.system_id && this.sys.embedBibliographyEntry) {
   6097             this.output.current.value().item_id = item.system_id;
   6098         } else {
   6099             this.output.current.value().system_id = item.id;
   6100         }
   6101         sortedItems = [[{id: "" + item.id}, item]];
   6102         entry_item_ids = [];
   6103         if (this.registry.registry[item.id].master 
   6104             && !(bibsection && bibsection.page_start && bibsection.page_length)) {
   6105             collapse_parallel = true;
   6106             this.parallel.StartCitation(sortedItems);
   6107             this.output.queue[0].strings.delimiter = ", ";
   6108             this.tmp.term_predecessor = false;
   6109             entry_item_ids.push("" + CSL.getCite.call(this, item));
   6110             skips[item.id] = true;
   6111             siblings = this.registry.registry[item.id].siblings;
   6112             for (j = 0, jlen = siblings.length; j < jlen; j += 1) {
   6113                 var k = this.registry.registry[item.id].siblings[j];
   6114                 eyetem = this.retrieveItem(k);
   6115                 entry_item_ids.push("" + CSL.getCite.call(this, eyetem));
   6116                 skips[eyetem.id] = true;
   6117             }
   6118             this.parallel.ComposeSet();
   6119             this.parallel.PruneOutputQueue();
   6120         } else if (!this.registry.registry[item.id].siblings) {
   6121             this.parallel.StartCitation(sortedItems);
   6122             this.tmp.term_predecessor = false;
   6123             entry_item_ids.push("" + CSL.getCite.call(this, item));
   6124             if (bibsection && bibsection.page_start && bibsection.page_length) {
   6125                 page_item_count += 1;
   6126             }
   6127         }
   6128         entry_item_data.push("");
   6129         this.tmp.bibliography_pos += 1;
   6130         processed_item_ids.push(entry_item_ids);
   6131         this.output.endTag("bib_entry");
   6132         if (this.output.queue[0].blobs.length && this.output.queue[0].blobs[0].blobs.length) {
   6133             if (collapse_parallel || !this.output.queue[0].blobs[0].blobs[0].strings) {
   6134                 topblobs = this.output.queue[0].blobs;
   6135                 collapse_parallel = false;
   6136             } else {
   6137                 topblobs = this.output.queue[0].blobs[0].blobs;
   6138             }
   6139             topblobs[0].strings.prefix = this.bibliography.opt.layout_prefix + topblobs[0].strings.prefix;
   6140         }
   6141         for (var j=0,jlen=this.output.queue.length;j<jlen;j+=1) {
   6142             CSL.Output.Queue.purgeEmptyBlobs(this.output.queue[j]);
   6143         }
   6144         for (var j=0,jlen=this.output.queue.length;j<jlen;j+=1) {
   6145             this.output.adjust.upward(this.output.queue[j]);
   6146             this.output.adjust.leftward(this.output.queue[j]);
   6147             this.output.adjust.downward(this.output.queue[j],true);
   6148             this.output.adjust.fix(this.output.queue[j]);
   6149         }
   6150         var res = this.output.string(this, this.output.queue)[0];
   6151         if (!res && this.opt.update_mode === CSL.NUMERIC) {
   6152             var err = (ret.length + 1) + ". [CSL STYLE ERROR: reference with no printed form.]"
   6153             res = CSL.Output.Formats[this.opt.mode]["@bibliography/entry"](this, err) 
   6154         }
   6155         if (res) {
   6156             ret.push(res);
   6157         }
   6158     }
   6159     var done = false;
   6160     if (bibsection && bibsection.page_start && bibsection.page_length) {
   6161         var last_expected_id = input.slice(-1)[0];
   6162         var last_seen_id = processed_item_ids.slice(-1)[0];
   6163         if (!last_expected_id || !last_seen_id || last_expected_id == last_seen_id) {
   6164             done = true;
   6165         }
   6166     }
   6167     this.tmp.disambig_override = false;
   6168     return [processed_item_ids, ret, done];
   6169 };
   6170 CSL.Engine.prototype.setCitationId = function (citation, force) {
   6171     var ret, id, direction;
   6172     ret = false;
   6173     if (!citation.citationID || force) {
   6174         id = Math.floor(Math.random() * 100000000000000);
   6175         while (true) {
   6176             direction = 0;
   6177             if (!this.registry.citationreg.citationById[id]) {
   6178                 citation.citationID = "a" + id.toString(32);
   6179                 break;
   6180             } else if (!direction && id < 50000000000000) {
   6181                 direction = 1;
   6182             } else {
   6183                 direction = -1;
   6184             }
   6185             if (direction === 1) {
   6186                 id += 1;
   6187             } else {
   6188                 id += -1;
   6189             }
   6190         }
   6191         ret = "" + id;
   6192     }
   6193     this.registry.citationreg.citationById[citation.citationID] = citation;
   6194     return ret;
   6195 };
   6196 CSL.Engine.prototype.rebuildProcessorState = function (citations, mode, uncitedItemIDs) {
   6197     if (!citations) {
   6198         citations = [];
   6199     }
   6200     if (!mode) {
   6201         mode = 'html';
   6202     }
   6203     var doneIDs = {};
   6204     var itemIDs = [];
   6205     for (var i=0,ilen=citations.length;i<ilen;i+=1) {
   6206         for (var j=0,jlen=citations[i].citationItems.length;j<jlen;j+=1) {
   6207             var itemID = "" + citations[i].citationItems[j].id;
   6208             if (!doneIDs[itemID]) {
   6209                 itemIDs.push(itemID);
   6210             }
   6211             doneIDs[itemID] = true;
   6212         }
   6213     }
   6214     this.updateItems(itemIDs);
   6215     var pre = [];
   6216     var post = [];
   6217     var ret = [];
   6218     var oldMode = this.opt.mode;
   6219     this.setOutputFormat(mode);
   6220     for (var i=0,ilen=citations.length;i<ilen;i+=1) {
   6221         var res = this.processCitationCluster(citations[i],pre,post,CSL.ASSUME_ALL_ITEMS_REGISTERED);
   6222         pre.push([citations[i].citationID,citations[i].properties.noteIndex]);
   6223         for (var j=0,jlen=res[1].length;j<jlen;j+=1) {
   6224             var index = res[1][j][0];
   6225             ret[index] = [
   6226                 pre[index][0],
   6227                 pre[index][1],
   6228                 res[1][j][1]
   6229             ];
   6230         }
   6231     }
   6232     this.updateUncitedItems(uncitedItemIDs);
   6233     this.setOutputFormat(oldMode);
   6234     return ret;
   6235 }
   6236 CSL.Engine.prototype.restoreProcessorState = function (citations) {
   6237     var i, ilen, j, jlen, item, Item, newitem, citationList, itemList, sortedItems;
   6238     citationList = [];
   6239     itemList = [];
   6240     if (!citations) {
   6241         citations = [];
   6242     }
   6243     var indexNumbers = [];
   6244     var citationIds = {};
   6245     for (i = 0, ilen = citations.length; i < ilen; i += 1) {
   6246         if (citationIds[citations[i].citationID]) {
   6247             this.setCitationId(citations[i], true);
   6248         }
   6249         citationIds[citations[i].citationID] = true;
   6250         indexNumbers.push(citations[i].properties.index);
   6251     }
   6252     var oldCitations = citations.slice();
   6253     oldCitations.sort(
   6254         function (a,b) {
   6255             if (a.properties.index < b.properties.index) {
   6256                 return -1;
   6257             } else if (a.properties.index > b.properties.index) {
   6258                 return 1;
   6259             } else {
   6260                 return 0;
   6261             }
   6262         }
   6263     );
   6264     for (i = 0, ilen = oldCitations.length; i < ilen; i += 1) {
   6265         oldCitations[i].properties.index = i;
   6266     }
   6267     for (i = 0, ilen = oldCitations.length; i < ilen; i += 1) {
   6268         sortedItems = [];
   6269         for (j = 0, jlen = oldCitations[i].citationItems.length; j < jlen; j += 1) {
   6270             item = oldCitations[i].citationItems[j];
   6271             if ("undefined" === typeof item.sortkeys) {
   6272                 item.sortkeys = [];
   6273             }
   6274             Item = this.retrieveItem("" + item.id);
   6275             newitem = [Item, item];
   6276             sortedItems.push(newitem);
   6277             oldCitations[i].citationItems[j].item = Item;
   6278             itemList.push("" + item.id);
   6279         }
   6280         if (!oldCitations[i].properties.unsorted) {
   6281             sortedItems.sort(this.citation.srt.compareCompositeKeys);
   6282         }
   6283         oldCitations[i].sortedItems = sortedItems;
   6284         this.registry.citationreg.citationById[oldCitations[i].citationID] = oldCitations[i];
   6285     }
   6286     this.updateItems(itemList);
   6287     for (i = 0, ilen = citations.length; i < ilen; i += 1) {
   6288         citationList.push(["" + citations[i].citationID, citations[i].properties.noteIndex]);
   6289     }
   6290     var ret = [];
   6291     if (citations && citations.length) {
   6292         ret = this.processCitationCluster(citations[0], [], citationList.slice(1));
   6293     } else {
   6294         this.registry = new CSL.Registry(this);
   6295         this.tmp = new CSL.Engine.Tmp();
   6296         this.disambiguate = new CSL.Disambiguation(this);
   6297     }
   6298     return ret;
   6299 };
   6300 CSL.Engine.prototype.updateItems = function (idList, nosort, rerun_ambigs, implicitUpdate) {
   6301     var debug = false;
   6302     var oldArea = this.tmp.area;
   6303     var oldRoot = this.tmp.root;
   6304     var oldExtension = this.tmp.extension;
   6305     this.tmp.area = "citation";
   6306     this.tmp.root = "citation";
   6307     this.tmp.extension = "";
   6308     if (!implicitUpdate) {
   6309         this.tmp.loadedItemIDs = {};
   6310     }
   6311     this.registry.init(idList);
   6312 	if (rerun_ambigs) {
   6313 		for (var ambig in this.registry.ambigcites) {
   6314 			this.registry.ambigsTouched[ambig] = true;
   6315 		}
   6316 	}
   6317     this.registry.dodeletes(this.registry.myhash);
   6318     this.registry.doinserts(this.registry.mylist);
   6319     this.registry.dorefreshes();
   6320     this.registry.rebuildlist();
   6321     this.registry.setsortkeys();
   6322     this.registry.setdisambigs();
   6323     if (!nosort) {
   6324         this.registry.sorttokens();
   6325     }
   6326     this.registry.renumber();
   6327     this.tmp.extension = oldExtension;
   6328     this.tmp.area = oldArea;
   6329     this.tmp.root = oldRoot;
   6330     return this.registry.getSortedIds();
   6331 };
   6332 CSL.Engine.prototype.updateUncitedItems = function (idList, nosort) {
   6333     var debug = false;
   6334     var oldArea = this.tmp.area;
   6335     var oldRoot = this.tmp.root;
   6336     var oldExtension = this.tmp.extension;
   6337     this.tmp.area = "citation";
   6338     this.tmp.root = "citation"
   6339     this.tmp.extension = ""
   6340     this.tmp.loadedItemIDs = {};
   6341     if (!idList) {
   6342         idList = [];
   6343     }
   6344     if ("object" == typeof idList) {
   6345         if ("undefined" == typeof idList.length) {
   6346             var idHash = idList;
   6347             idList = [];
   6348             for (var key in idHash) {
   6349                 idList.push(key);
   6350             }
   6351         } else if ("number" == typeof idList.length) {
   6352             var idHash = {};
   6353             for (var i=0,ilen=idList.length;i<ilen;i+=1) {
   6354                 idHash[idList[i]] = true;
   6355             }
   6356         }
   6357     }
   6358     this.registry.init(idList, true);
   6359     this.registry.dopurge(idHash);
   6360     this.registry.doinserts(this.registry.mylist);
   6361     this.registry.dorefreshes();
   6362     this.registry.rebuildlist();
   6363     this.registry.setsortkeys();
   6364     this.registry.setdisambigs();
   6365     if (!nosort) {
   6366         this.registry.sorttokens();
   6367     }
   6368     this.registry.renumber();
   6369     this.tmp.extension = oldExtension;
   6370     this.tmp.area = oldArea;
   6371     this.tmp.root = oldRoot;
   6372     return this.registry.getSortedIds();
   6373 };
   6374 CSL.localeResolve = function (langstr, defaultLocale) {
   6375     var ret, langlst;
   6376     if (!defaultLocale) {
   6377         defaultLocale = "en-US";
   6378     }
   6379     if (!langstr) {
   6380         langstr = defaultLocale;
   6381     }
   6382     ret = {};
   6383     langlst = langstr.split(/[\-_]/);
   6384     ret.base = CSL.LANG_BASES[langlst[0]];
   6385     if ("undefined" === typeof ret.base) {
   6386         return {base:defaultLocale, best:langstr, bare:langlst[0]};
   6387     }
   6388     if (langlst.length === 1) {
   6389         ret.generic = true;
   6390     }
   6391     if (langlst.length === 1 || langlst[1] === "x") {
   6392         ret.best = ret.base.replace("_", "-");
   6393     } else {
   6394         ret.best = langlst.slice(0, 2).join("-");
   6395     }
   6396     ret.base = ret.base.replace("_", "-");
   6397     ret.bare = langlst[0];
   6398     return ret;
   6399 };
   6400 CSL.Engine.prototype.localeConfigure = function (langspec, beShy) {
   6401     var localexml;
   6402     if (beShy && this.locale[langspec.best]) {
   6403         return;
   6404     }
   6405     if (langspec.best === "en-US") {
   6406         localexml = CSL.setupXml(this.sys.retrieveLocale("en-US"));
   6407         this.localeSet(localexml, "en-US", langspec.best);
   6408     } else if (langspec.best !== "en-US") {
   6409         if (langspec.base !== langspec.best) {
   6410             localexml = CSL.setupXml(this.sys.retrieveLocale(langspec.base));
   6411             this.localeSet(localexml, langspec.base, langspec.best);
   6412         }
   6413         localexml = CSL.setupXml(this.sys.retrieveLocale(langspec.best));
   6414         this.localeSet(localexml, langspec.best, langspec.best);        
   6415     }
   6416     this.localeSet(this.cslXml, "", langspec.best);
   6417     this.localeSet(this.cslXml, langspec.bare, langspec.best);
   6418     if (langspec.base !== langspec.best) {
   6419         this.localeSet(this.cslXml, langspec.base, langspec.best);
   6420     }
   6421     this.localeSet(this.cslXml, langspec.best, langspec.best);
   6422     if ("undefined" === typeof this.locale[langspec.best].terms["page-range-delimiter"]) {
   6423         if (["fr", "pt"].indexOf(langspec.best.slice(0, 2).toLowerCase()) > -1) {
   6424             this.locale[langspec.best].terms["page-range-delimiter"] = "-";
   6425         } else {
   6426             this.locale[langspec.best].terms["page-range-delimiter"] = "\u2013";
   6427         }
   6428     }
   6429     if ("undefined" === typeof this.locale[langspec.best].terms["year-range-delimiter"]) {
   6430         this.locale[langspec.best].terms["year-range-delimiter"] = "\u2013";
   6431     }
   6432     if ("undefined" === typeof this.locale[langspec.best].terms["citation-range-delimiter"]) {
   6433         this.locale[langspec.best].terms["citation-range-delimiter"] = "\u2013";
   6434     }
   6435     if (this.opt.development_extensions.normalize_lang_keys_to_lowercase) {
   6436         var localeLists = ["default-locale","locale-sort","locale-translit","locale-translat"];
   6437         for (var i=0,ilen=localeLists.length;i<ilen;i+=1) {
   6438             for (var j=0,jlen=this.opt[localeLists[i]].length;j<jlen;j+=1) {
   6439                 this.opt[localeLists[i]][j] = this.opt[localeLists[i]][j].toLowerCase();
   6440             }
   6441         }
   6442         this.opt.lang = this.opt.lang.toLowerCase();
   6443     }
   6444 };
   6445 CSL.Engine.prototype.localeSet = function (myxml, lang_in, lang_out) {
   6446     var blob, locale, nodes, attributes, pos, ppos, term, form, termname, styleopts, attr, date, attrname, len, genderform, target, i, ilen;
   6447     lang_in = lang_in.replace("_", "-");
   6448     lang_out = lang_out.replace("_", "-");
   6449     if (this.opt.development_extensions.normalize_lang_keys_to_lowercase) {
   6450         lang_in = lang_in.toLowerCase();
   6451         lang_out = lang_out.toLowerCase();
   6452     }
   6453     if (!this.locale[lang_out]) {
   6454         this.locale[lang_out] = {};
   6455         this.locale[lang_out].terms = {};
   6456         this.locale[lang_out].opts = {};
   6457         this.locale[lang_out].opts["skip-words"] = CSL.SKIP_WORDS;
   6458         if (!this.locale[lang_out].opts["leading-noise-words"]) {
   6459             this.locale[lang_out].opts["leading-noise-words"] = [];
   6460         }
   6461         this.locale[lang_out].dates = {};
   6462         this.locale[lang_out].ord = {'1.0.1':false,keys:{}};
   6463         this.locale[lang_out]["noun-genders"] = {};
   6464     }
   6465     locale = myxml.makeXml();
   6466     if (myxml.nodeNameIs(myxml.dataObj, 'locale')) {
   6467         locale = myxml.dataObj;
   6468     } else {
   6469         nodes = myxml.getNodesByName(myxml.dataObj, "locale");
   6470         for (pos = 0, len = myxml.numberofnodes(nodes); pos < len; pos += 1) {
   6471             blob = nodes[pos];
   6472             if (myxml.getAttributeValue(blob, 'lang', 'xml') === lang_in) {
   6473                 locale = blob;
   6474                 break;
   6475             }
   6476         }
   6477     }
   6478     nodes = myxml.getNodesByName(locale, 'type');
   6479     for (i = 0, ilen = myxml.numberofnodes(nodes); i < ilen; i += 1) {
   6480         var typenode = nodes[i];
   6481         var type = myxml.getAttributeValue(typenode, 'name');
   6482         var gender = myxml.getAttributeValue(typenode, 'gender');
   6483         this.opt.gender[type] = gender;
   6484     }
   6485     var hasCslOrdinals101 = myxml.getNodesByName(locale, 'term', 'ordinal').length;
   6486     if (hasCslOrdinals101) {
   6487         for (var key in this.locale[lang_out].ord.keys) {
   6488             delete this.locale[lang_out].terms[key];
   6489         }
   6490         this.locale[lang_out].ord = {"1.0.1":false,keys:{}};
   6491     }
   6492     nodes = myxml.getNodesByName(locale, 'term');
   6493     var ordinals101 = {"last-digit":{},"last-two-digits":{},"whole-number":{}};
   6494     var ordinals101_toggle = false;
   6495     var genderized_terms = {};
   6496     for (pos = 0, len = myxml.numberofnodes(nodes); pos < len; pos += 1) {
   6497         term = nodes[pos];
   6498         termname = myxml.getAttributeValue(term, 'name');
   6499         if (termname === "sub verbo") {
   6500             termname = "sub-verbo";
   6501         }
   6502         if (termname.slice(0,7) === "ordinal") {
   6503             var termstring = myxml.getNodeValue(term);
   6504             if (termname === "ordinal") {
   6505                 ordinals101_toggle = true;
   6506             } else {
   6507                 var match = myxml.getAttributeValue(term, 'match');
   6508                 var termstub = termname.slice(8);
   6509                 var genderform = myxml.getAttributeValue(term, 'gender-form');
   6510                 if (!genderform) {
   6511                     genderform = "neuter";
   6512                 }
   6513                 if (!match) {
   6514                     match = "last-two-digits";
   6515                     if (termstub.slice(0,1) === "0") {
   6516                         match = "last-digit";
   6517                     }
   6518                 }
   6519                 if (termstub.slice(0,1) === "0") {
   6520                     termstub = termstub.slice(1);
   6521                 }
   6522                 if (!ordinals101[match][termstub]) {
   6523                     ordinals101[match][termstub] = {};
   6524                 }
   6525                 ordinals101[match][termstub][genderform] = termname;
   6526             }
   6527             this.locale[lang_out].ord.keys[termname] = true;
   6528         }
   6529         if ("undefined" === typeof this.locale[lang_out].terms[termname]) {
   6530             this.locale[lang_out].terms[termname] = {};
   6531         }
   6532         form = "long";
   6533         genderform = false;
   6534         if (myxml.getAttributeValue(term, 'form')) {
   6535             form = myxml.getAttributeValue(term, 'form');
   6536         }
   6537         if (myxml.getAttributeValue(term, 'gender-form')) {
   6538             genderform = myxml.getAttributeValue(term, 'gender-form');
   6539         }
   6540         if (myxml.getAttributeValue(term, 'gender')) {
   6541             this.locale[lang_out]["noun-genders"][termname] = myxml.getAttributeValue(term, 'gender');
   6542         }
   6543         if (genderform) {
   6544             this.locale[lang_out].terms[termname][genderform] = {};
   6545             this.locale[lang_out].terms[termname][genderform][form] = [];
   6546             target = this.locale[lang_out].terms[termname][genderform];
   6547             genderized_terms[termname] = true;
   6548         } else {
   6549             this.locale[lang_out].terms[termname][form] = [];
   6550             target = this.locale[lang_out].terms[termname];
   6551         }
   6552         if (myxml.numberofnodes(myxml.getNodesByName(term, 'multiple'))) {
   6553             target[form][0] = myxml.getNodeValue(term, 'single');
   6554             if (target[form][0].indexOf("%s") > -1) {
   6555                 this.opt.hasPlaceholderTerm = true;
   6556             }
   6557             target[form][1] = myxml.getNodeValue(term, 'multiple');
   6558             if (target[form][1].indexOf("%s") > -1) {
   6559                 this.opt.hasPlaceholderTerm = true;
   6560             }
   6561         } else {
   6562             target[form] = myxml.getNodeValue(term);
   6563             if (target[form].indexOf("%s") > -1) {
   6564                 this.opt.hasPlaceholderTerm = true;
   6565             }
   6566         }
   6567     }
   6568     if (ordinals101_toggle) {
   6569         for (var ikey in genderized_terms) {
   6570             var gender_segments = {};
   6571             var form_segments = 0;
   6572             for (var jkey in this.locale[lang_out].terms[ikey]) {
   6573                 if (["masculine","feminine"].indexOf(jkey) > -1) {
   6574                     gender_segments[jkey] = this.locale[lang_out].terms[ikey][jkey];
   6575                 } else {
   6576                     form_segments += 1;
   6577                 }
   6578             }
   6579             if (!form_segments) {
   6580                 if (gender_segments.feminine) {
   6581                     for (var jkey in gender_segments.feminine) {
   6582                         this.locale[lang_out].terms[ikey][jkey] = gender_segments.feminine[jkey];
   6583                     }
   6584                 } else if (gender_segments.masculine) {
   6585                     for (var jkey in gender_segments.masculine) {
   6586                         this.locale[lang_out].terms[ikey][jkey] = gender_segments.masculine[jkey];
   6587                     }
   6588                 }
   6589             }
   6590         }
   6591         this.locale[lang_out].ord['1.0.1'] = ordinals101;
   6592     }
   6593     for (termname in this.locale[lang_out].terms) {
   6594         for (i = 0, ilen = 2; i < ilen; i += 1) {
   6595             genderform = CSL.GENDERS[i];
   6596             if (this.locale[lang_out].terms[termname][genderform]) {
   6597                 for (form in this.locale[lang_out].terms[termname]) {
   6598                     if (!this.locale[lang_out].terms[termname][genderform][form]) {
   6599                         this.locale[lang_out].terms[termname][genderform][form] = this.locale[lang_out].terms[termname][form];
   6600                     }
   6601                 }
   6602             }
   6603         }
   6604     }
   6605     nodes = myxml.getNodesByName(locale, 'style-options');
   6606     for (pos = 0, len = myxml.numberofnodes(nodes); pos < len; pos += 1) {
   6607         if (true) {
   6608             styleopts = nodes[pos];
   6609             attributes = myxml.attributes(styleopts);
   6610             for (attrname in attributes) {
   6611                 if (attributes.hasOwnProperty(attrname)) {
   6612                     if (attrname === "@punctuation-in-quote" || attrname === "@limit-day-ordinals-to-day-1") {
   6613                         if (attributes[attrname] === "true") {
   6614                             this.locale[lang_out].opts[attrname.slice(1)] = true;
   6615                         } else {
   6616                             this.locale[lang_out].opts[attrname.slice(1)] = false;
   6617                         }
   6618                     } else if (attrname === "@jurisdiction-preference") {
   6619                         var jurisdiction_preference = attributes[attrname].split(/\s*,\s*/);
   6620                         this.locale[lang_out].opts[attrname.slice(1)] = jurisdiction_preference;
   6621                     } else if (attrname === "@skip-words") {
   6622                         var skip_words = attributes[attrname].split(/\s*,\s*/);
   6623                         this.locale[lang_out].opts[attrname.slice(1)] = skip_words;
   6624                     } else if (attrname === "@leading-noise-words") {
   6625                         var val = attributes[attrname].split(/\s*,\s*/);
   6626                         this.locale[lang_out].opts["leading-noise-words"] = val;
   6627                     } else if (attrname === "@name-as-sort-order") {
   6628                         this.locale[lang_out].opts["name-as-sort-order"] = {};
   6629                         var lst = attributes[attrname].split(/\s+/);
   6630                         for (var i=0,ilen=lst.length;i<ilen;i+=1) {
   6631                             this.locale[lang_out].opts["name-as-sort-order"][lst[i]] = true;
   6632                         }
   6633                     } else if (attrname === "@name-as-reverse-order") {
   6634                         this.locale[lang_out].opts["name-as-reverse-order"] = {};
   6635                         var lst = attributes[attrname].split(/\s+/);
   6636                         for (var i=0,ilen=lst.length;i<ilen;i+=1) {
   6637                             this.locale[lang_out].opts["name-as-reverse-order"][lst[i]] = true;
   6638                         }
   6639                     } else if (attrname === "@name-never-short") {
   6640                         this.locale[lang_out].opts["name-never-short"] = {};
   6641                         var lst = attributes[attrname].split(/\s+/);
   6642                         for (var i=0,ilen=lst.length;i<ilen;i+=1) {
   6643                             this.locale[lang_out].opts["name-never-short"][lst[i]] = true;
   6644                         }
   6645                     }
   6646                 }
   6647             }
   6648         }
   6649     }
   6650     nodes = myxml.getNodesByName(locale, 'date');
   6651     for (pos = 0, len = myxml.numberofnodes(nodes); pos < len; pos += 1) {
   6652         if (true) {
   6653             var date = nodes[pos];
   6654             this.locale[lang_out].dates[myxml.getAttributeValue(date, "form")] = date;
   6655         }
   6656     }
   6657 };
   6658 CSL.getLocaleNames = function (myxml, preferredLocale) {
   6659     var stylexml = CSL.setupXml(myxml);
   6660     function extendLocaleList(localeList, locale) {
   6661         var forms = ["base", "best"];
   6662         if (locale) {
   6663             normalizedLocale = CSL.localeResolve(locale);
   6664             for (var i=0,ilen=forms.length;i<ilen;i++) {
   6665                 if (normalizedLocale[forms[i]] && localeList.indexOf(normalizedLocale[forms[i]]) === -1) {
   6666                     localeList.push(normalizedLocale[forms[i]]);
   6667                 }
   6668             }
   6669         }
   6670     }
   6671     function sniffLocaleOnOneNodeName(nodeName) {
   6672         var nodes = stylexml.getNodesByName(stylexml.dataObj, nodeName);
   6673         for (var i=0,ilen=nodes.length;i<ilen;i++) {
   6674             var nodeLocales = stylexml.getAttributeValue(nodes[i], "locale");
   6675             if (nodeLocales) {
   6676                 nodeLocales = nodeLocales.split(/ +/);
   6677                 for (var j=0,jlen=nodeLocales.length;j<jlen;j++) {
   6678                     this.extendLocaleList(localeIDs, nodeLocales[j]);
   6679                 }
   6680             }
   6681         }
   6682     }
   6683     var localeIDs = ["en-US"];
   6684     extendLocaleList(localeIDs, preferredLocale);
   6685     var styleNode = stylexml.getNodesByName(stylexml.dataObj, "style")[0];
   6686     var defaultLocale = stylexml.getAttributeValue(styleNode, "default-locale");
   6687     extendLocaleList(localeIDs, defaultLocale);
   6688     var nodeNames = ["layout", "if", "else-if", "condition"];
   6689     for (var i=0,ilen=nodeNames.length;i<ilen;i++) {
   6690         sniffLocaleOnOneNodeName(stylexml, localeIDs, nodeNames[i]);
   6691     }
   6692     return localeIDs;
   6693 };
   6694 CSL.Node = {};
   6695 CSL.Node.bibliography = {
   6696     build: function (state, target) {
   6697         if (this.tokentype === CSL.START) {
   6698             state.build.area = "bibliography";
   6699             state.build.root = "bibliography";
   6700             state.build.extension = "";
   6701             var func = function(state, Item) {
   6702                 state.tmp.area = "bibliography";
   6703                 state.tmp.root = "bibliography";
   6704                 state.tmp.extension = "";
   6705             }
   6706             this.execs.push(func);
   6707         }
   6708         target.push(this);
   6709     }
   6710 };
   6711 CSL.Node.choose = {
   6712     build: function (state, target) {
   6713         var func;
   6714         if (this.tokentype === CSL.START) {
   6715             func = function (state, Item) {
   6716                 state.tmp.jump.push(undefined, CSL.LITERAL);
   6717             };
   6718         }
   6719         if (this.tokentype === CSL.END) {
   6720             func = function (state, Item) {
   6721                 state.tmp.jump.pop();
   6722             };
   6723         }
   6724         this.execs.push(func);
   6725         target.push(this);
   6726     },
   6727     configure: function (state, pos) {
   6728         if (this.tokentype === CSL.END) {
   6729             state.configure.fail.push((pos));
   6730             state.configure.succeed.push((pos));
   6731         } else {
   6732             state.configure.fail.pop();
   6733             state.configure.succeed.pop();
   6734         }
   6735     }
   6736 };
   6737 CSL.Node.citation = {
   6738     build: function (state, target) {
   6739         if (this.tokentype === CSL.START) {
   6740             state.build.area = "citation";
   6741             state.build.root = "citation";
   6742             state.build.extension = "";
   6743             var func = function(state, Item) {
   6744                 state.tmp.area = "citation";
   6745                 state.tmp.root = "citation";
   6746                 state.tmp.extension = "";
   6747             }
   6748             this.execs.push(func);
   6749         }
   6750         if (this.tokentype === CSL.END) {
   6751             state.opt.grouped_sort = state.opt.xclass === "in-text" 
   6752                 && (state.citation.opt.collapse 
   6753                     && state.citation.opt.collapse.length)
   6754                 || (state.citation.opt.cite_group_delimiter
   6755                     && state.citation.opt.cite_group_delimiter.length)
   6756                 && state.opt.update_mode !== CSL.POSITION
   6757                 && state.opt.update_mode !== CSL.NUMERIC;
   6758             if (state.opt.grouped_sort 
   6759                 && state.citation_sort.opt.sort_directions.length) {
   6760                 var firstkey = state.citation_sort.opt.sort_directions[0].slice();
   6761                 state.citation_sort.opt.sort_directions = [firstkey].concat(state.citation_sort.opt.sort_directions);
   6762             }
   6763             state.citation.srt = new CSL.Registry.Comparifier(state, "citation_sort");
   6764         }
   6765         target.push(this);
   6766     }
   6767 };
   6768 CSL.Node["#comment"] = {
   6769        build: function (state, target) {
   6770        }
   6771 };
   6772 CSL.Node.date = {
   6773     build: function (state, target) {
   6774         var func, date_obj, tok, len, pos, part, dpx, parts, mypos, start, end;
   6775         if (this.tokentype === CSL.START || this.tokentype === CSL.SINGLETON) {
   6776             state.build.date_parts = [];
   6777             state.build.date_variables = this.variables;
   6778             if (!state.build.extension) {
   6779                 CSL.Util.substituteStart.call(this, state, target);
   6780             }
   6781             if (state.build.extension) {
   6782                 func = CSL.dateMacroAsSortKey;
   6783             } else {
   6784                 func = function (state, Item, item) {
   6785                     var key, dp;
   6786                     state.tmp.element_rendered_ok = false;
   6787                     state.tmp.donesies = [];
   6788                     state.tmp.dateparts = [];
   6789                     dp = [];
   6790                     if (this.variables.length
   6791                         && !(state.tmp.just_looking
   6792                              && this.variables[0] === "accessed")) {
   6793                         date_obj = Item[this.variables[0]];
   6794                         if ("undefined" === typeof date_obj) {
   6795                             date_obj = {"date-parts": [[0]] };
   6796                             if (state.opt.development_extensions.locator_date_and_revision) {
   6797                                 if (item && this.variables[0] === "locator-date" && item["locator-date"]) {
   6798                                     date_obj = item["locator-date"];
   6799                                 }
   6800                             }
   6801                         }
   6802                         state.tmp.date_object = date_obj;
   6803                         len = this.dateparts.length;
   6804                         for (pos = 0; pos < len; pos += 1) {
   6805                             part = this.dateparts[pos];
   6806                             if ("undefined" !== typeof state.tmp.date_object[(part +  "_end")]) {
   6807                                 dp.push(part);
   6808                             } else if (part === "month" && "undefined" !== typeof state.tmp.date_object.season_end) {
   6809                                 dp.push(part);
   6810                             }
   6811                         }
   6812                         dpx = [];
   6813                         parts = ["year", "month", "day"];
   6814                         len = parts.length;
   6815                         for (pos = 0; pos < len; pos += 1) {
   6816                             if (dp.indexOf(parts[pos]) > -1) {
   6817                                 dpx.push(parts[pos]);
   6818                             }
   6819                         }
   6820                         dp = dpx.slice();
   6821                         mypos = 2;
   6822                         len = dp.length;
   6823                         for (pos = 0; pos < len; pos += 1) {
   6824                             part = dp[pos];
   6825                             start = state.tmp.date_object[part];
   6826                             end = state.tmp.date_object[(part + "_end")];
   6827                             if (start !== end) {
   6828                                 mypos = pos;
   6829                                 break;
   6830                             }
   6831                         }
   6832                         state.tmp.date_collapse_at = dp.slice(mypos);
   6833                     } else {
   6834                         state.tmp.date_object = false;
   6835                     }
   6836                 };
   6837             }
   6838             this.execs.push(func);
   6839             func = function (state, Item) {
   6840                 if (!Item[this.variables[0]]) return;
   6841                 state.parallel.StartVariable(this.variables[0]);
   6842                 state.output.startTag("date", this);
   6843                 if (this.variables[0] === "issued"
   6844                     && Item.type === "legal_case"
   6845                     && !state.tmp.extension
   6846                     && "" + Item["collection-number"] === "" + state.tmp.date_object.year
   6847                     && this.dateparts.length === 1
   6848                     && this.dateparts[0] === "year") {
   6849                     for (var key in state.tmp.date_object) {
   6850                         if (state.tmp.date_object.hasOwnProperty(key)) {
   6851                             if (key.slice(0, 4) === "year") {
   6852                                 state.tmp.issued_date = {};
   6853                                 var lst = state.output.current.mystack.slice(-2)[0].blobs;
   6854                                 state.tmp.issued_date.list = lst;
   6855                                 state.tmp.issued_date.pos = lst.length - 1;
   6856                             }
   6857                         }
   6858                     }
   6859                 }
   6860             };
   6861             this.execs.push(func);
   6862         }
   6863         if (!state.build.extension && (this.tokentype === CSL.END || this.tokentype === CSL.SINGLETON)) {
   6864             func = function (state, Item) {
   6865                 if (!Item[this.variables[0]]) return;
   6866                 state.output.endTag();
   6867                 state.parallel.CloseVariable(this.variables[0]);
   6868             };
   6869             this.execs.push(func);
   6870         }
   6871         target.push(this);
   6872         if (this.tokentype === CSL.END || this.tokentype === CSL.SINGLETON) {
   6873             if (!state.build.extension) {
   6874                 CSL.Util.substituteEnd.call(this, state, target);
   6875             }
   6876         }
   6877     }
   6878 };
   6879 CSL.Node["date-part"] = {
   6880     build: function (state, target) {
   6881         var func, pos, len, decor, first_date, value, value_end, real, have_collapsed, invoked, precondition, known_year, bc, ad, bc_end, ad_end, ready, curr, dcurr, number, num, formatter, item, i, ilen;
   6882         if (!this.strings.form) {
   6883             this.strings.form = "long";
   6884         }
   6885         state.build.date_parts.push(this.strings.name);
   6886         var date_variable = state.build.date_variables[0];
   6887         func = function (state, Item) {
   6888             if (!state.tmp.date_object) {
   6889                 return;
   6890             }
   6891             first_date = true;
   6892             value = "";
   6893             value_end = "";
   6894             state.tmp.donesies.push(this.strings.name);
   6895             if (state.tmp.date_object.literal && "year" === this.strings.name) {
   6896                 state.parallel.AppendToVariable(state.tmp.date_object.literal);
   6897                 state.output.append(state.tmp.date_object.literal, this);
   6898             }
   6899             if (state.tmp.date_object) {
   6900                 value = state.tmp.date_object[this.strings.name];
   6901                 value_end = state.tmp.date_object[(this.strings.name + "_end")];
   6902             }
   6903             if ("year" === this.strings.name && value === 0 && !state.tmp.suppress_decorations) {
   6904                 value = false;
   6905             }
   6906             real = !state.tmp.suppress_decorations;
   6907             have_collapsed = state.tmp.have_collapsed;
   6908             invoked = state[state.tmp.area].opt.collapse === "year-suffix" || state[state.tmp.area].opt.collapse === "year-suffix-ranged";
   6909             precondition = state.opt["disambiguate-add-year-suffix"];
   6910             if (real && precondition && invoked) {
   6911                 state.tmp.years_used.push(value);
   6912                 known_year = state.tmp.last_years_used.length >= state.tmp.years_used.length;
   6913                 if (known_year && have_collapsed) {
   6914                     if (state.tmp.last_years_used[(state.tmp.years_used.length - 1)] === value) {
   6915                         value = false;
   6916                     }
   6917                 }
   6918             }
   6919             if ("undefined" !== typeof value) {
   6920                 bc = false;
   6921                 ad = false;
   6922                 bc_end = false;
   6923                 ad_end = false;
   6924                 if ("year" === this.strings.name) {
   6925                     if (parseInt(value, 10) < 500 && parseInt(value, 10) > 0) {
   6926                         ad = state.getTerm("ad");
   6927                     }
   6928                     if (parseInt(value, 10) < 0) {
   6929                         bc = state.getTerm("bc");
   6930                         value = (parseInt(value, 10) * -1);
   6931                     }
   6932                     if (value_end) {
   6933                         if (parseInt(value_end, 10) < 500 && parseInt(value_end, 10) > 0) {
   6934                             ad_end = state.getTerm("ad");
   6935                         }
   6936                         if (parseInt(value_end, 10) < 0) {
   6937                             bc_end = state.getTerm("bc");
   6938                             value_end = (parseInt(value_end, 10) * -1);
   6939                         }
   6940                     }
   6941                 }
   6942                 state.parallel.AppendToVariable(value);
   6943                 var monthnameid = ""+state.tmp.date_object.month;
   6944                 while (monthnameid.length < 2) {
   6945                     monthnameid = "0"+monthnameid;
   6946                 }
   6947                 monthnameid = "month-"+monthnameid;
   6948                 var gender = state.locale[state.opt.lang]["noun-genders"][monthnameid];
   6949                 if (this.strings.form) {
   6950                     var myform = this.strings.form;
   6951                     if (this.strings.name === "day") {
   6952                         if (myform === "ordinal"
   6953                             && state.locale[state.opt.lang].opts["limit-day-ordinals-to-day-1"]
   6954                             && ("" + value) !== "1") {
   6955                             myform = "numeric";
   6956                         }
   6957                     }
   6958                     value = CSL.Util.Dates[this.strings.name][myform](state, value, gender, this.default_locale);
   6959                     if ("month" === this.strings.name) {
   6960                         if (state.tmp.strip_periods) {
   6961                             value = value.replace(/\./g, "");
   6962                         } else {
   6963                             for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) {
   6964                                 if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) {
   6965                                     value = value.replace(/\./g, "");
   6966                                     break;
   6967                                 }
   6968                             }
   6969                         }
   6970                     }
   6971                     if (value_end) {
   6972                         value_end = CSL.Util.Dates[this.strings.name][myform](state, value_end, gender, ("accessed" === date_variable), "_end");
   6973                         if (state.tmp.strip_periods) {
   6974                             value_end = value_end.replace(/\./g, "");
   6975                         } else {
   6976                             for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) {
   6977                                 if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) {
   6978                                     value_end = value_end.replace(/\./g, "");
   6979                                     break;
   6980                                 }
   6981                             }
   6982                         }
   6983                     }
   6984                 }
   6985                 state.output.openLevel("empty");
   6986                 if (state.tmp.date_collapse_at.length) {
   6987                     ready = true;
   6988                     len = state.tmp.date_collapse_at.length;
   6989                     for (pos = 0; pos < len; pos += 1) {
   6990                         item = state.tmp.date_collapse_at[pos];
   6991                         if (state.tmp.donesies.indexOf(item) === -1) {
   6992                             ready = false;
   6993                             break;
   6994                         }
   6995                     }
   6996                     if (ready) {
   6997                         if ("" + value_end !== "0") {
   6998                             if (state.dateput.queue.length === 0) {
   6999                                 first_date = true;
   7000                             }
   7001                             if (state.opt["year-range-format"]
   7002                                 && state.opt["year-range-format"] !== "expanded"
   7003                                 && !state.tmp.date_object.day
   7004                                 && !state.tmp.date_object.month
   7005                                 && !state.tmp.date_object.season
   7006                                 && this.strings.name === "year"
   7007                                 && value && value_end) {
   7008                                 value_end = state.fun.year_mangler(value + "-" + value_end, true);
   7009                                 var range_delimiter = state.getTerm("year-range-delimiter");
   7010                                 value_end = value_end.slice(value_end.indexOf(range_delimiter) + 1);
   7011                             }
   7012                             state.dateput.append(value_end, this);
   7013                             if (first_date) {
   7014                                 state.dateput.current.value()[0].strings.prefix = "";
   7015                             }
   7016                         }
   7017                         state.output.append(value, this);
   7018                         curr = state.output.current.value();
   7019                         curr.blobs[(curr.blobs.length - 1)].strings.suffix = "";
   7020                         state.output.append(state.getTerm("year-range-delimiter"), "empty");
   7021                         dcurr = state.dateput.current.value();
   7022                         curr.blobs = curr.blobs.concat(dcurr);
   7023                         state.dateput.string(state, state.dateput.queue);
   7024                         state.tmp.date_collapse_at = [];
   7025                     } else {
   7026                         state.output.append(value, this);
   7027                         if (state.tmp.date_collapse_at.indexOf(this.strings.name) > -1) {
   7028                             if ("" + value_end !== "0") {
   7029                                 if (state.dateput.queue.length === 0) {
   7030                                     first_date = true;
   7031                                 }
   7032                                 state.dateput.openLevel("empty");
   7033                                 state.dateput.append(value_end, this);
   7034                                 if (first_date) {
   7035                                     state.dateput.current.value().blobs[0].strings.prefix = "";
   7036                                 }
   7037                                 if (bc) {
   7038                                     state.dateput.append(bc);
   7039                                 }
   7040                                 if (ad) {
   7041                                     state.dateput.append(ad);
   7042                                 }
   7043                                 state.dateput.closeLevel();
   7044                             }
   7045                         }
   7046                     }
   7047                 } else {
   7048                     state.output.append(value, this);
   7049                 }
   7050                 if (bc) {
   7051                     state.output.append(bc);
   7052                 }
   7053                 if (ad) {
   7054                     state.output.append(ad);
   7055                 }
   7056                 state.output.closeLevel();
   7057             } else if ("month" === this.strings.name) {
   7058                 if (state.tmp.date_object.season) {
   7059                     value = "" + state.tmp.date_object.season;
   7060                     if (value && value.match(/^[1-4]$/)) {
   7061                         state.tmp.group_context.tip.variable_success = true;
   7062                         state.output.append(state.getTerm(("season-0" + value)), this);
   7063                     } else if (value) {
   7064                         state.output.append(value, this);
   7065                     }
   7066                 }
   7067             }
   7068             state.tmp.value = [];
   7069             if (Item[date_variable] && (value || state.tmp.have_collapsed) && !state.opt.has_year_suffix && "year" === this.strings.name && !state.tmp.just_looking) {
   7070                 if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.has_done_year_suffix) {
   7071                     state.tmp.has_done_year_suffix = true;
   7072                     num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10);
   7073                     number = new CSL.NumericBlob(false, num, this, Item.id);
   7074                     this.successor_prefix = state[state.build.area].opt.layout_delimiter;
   7075                     this.splice_prefix = state[state.build.area].opt.layout_delimiter;
   7076                     formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS);
   7077                     number.setFormatter(formatter);
   7078                     if (state[state.tmp.area].opt.collapse === "year-suffix-ranged") {
   7079                         number.range_prefix = state.getTerm("citation-range-delimiter");
   7080                     }
   7081                     if (state[state.tmp.area].opt.cite_group_delimiter) {
   7082                         number.successor_prefix = state[state.tmp.area].opt.cite_group_delimiter;
   7083                     } else if (state[state.tmp.area].opt["year-suffix-delimiter"]) {
   7084                         number.successor_prefix = state[state.tmp.area].opt["year-suffix-delimiter"];
   7085                     } else {
   7086                         number.successor_prefix = state[state.tmp.area].opt.layout_delimiter;
   7087                     }
   7088                     number.UGLY_DELIMITER_SUPPRESS_HACK = true;
   7089                     state.output.append(number, "literal");
   7090                 }
   7091             }
   7092         };
   7093         this.execs.push(func);
   7094         target.push(this);
   7095     }
   7096 };
   7097 CSL.Node["else-if"] = {
   7098     build: function (state, target) {
   7099         CSL.Conditions.TopNode.call(this, state, target);
   7100         target.push(this);
   7101     },
   7102     configure: function (state, pos) {
   7103         CSL.Conditions.Configure.call(this, state, pos);
   7104     }
   7105 };
   7106 CSL.Node["else"] = {
   7107     build: function (state, target) {
   7108         target.push(this);
   7109     },
   7110     configure: function (state, pos) {
   7111         if (this.tokentype === CSL.START) {
   7112             state.configure.fail[(state.configure.fail.length - 1)] = pos;
   7113         }
   7114     }
   7115 };
   7116 CSL.Node["et-al"] = {
   7117     build: function (state, target) {
   7118         if (state.build.area === "citation" || state.build.area === "bibliography") {
   7119             var func = function (state, Item, item) {
   7120                 state.tmp.etal_node = this;
   7121                 if ("string" === typeof this.strings.term) {
   7122                     state.tmp.etal_term = this.strings.term;
   7123                 }
   7124             }
   7125             this.execs.push(func);
   7126         }
   7127         target.push(this);
   7128     }
   7129 };
   7130 CSL.Node.group = {
   7131     build: function (state, target, realGroup) {
   7132         var func, execs, done_vars;
   7133         this.realGroup = realGroup;
   7134         if (this.tokentype === CSL.START) {
   7135             CSL.Util.substituteStart.call(this, state, target);
   7136             if (state.build.substitute_level.value()) {
   7137                 state.build.substitute_level.replace((state.build.substitute_level.value() + 1));
   7138             }
   7139             if (!this.juris) {
   7140                 target.push(this);
   7141             }
   7142             func = function (state, Item) {
   7143                 state.output.startTag("group", this);
   7144                 if (this.strings.label_form_override) {
   7145                     if (!state.tmp.group_context.tip.label_form) {
   7146                         state.tmp.group_context.tip.label_form = this.strings.label_form_override;
   7147                     }
   7148                 }
   7149                 if (this.strings.label_capitalize_if_first_override) {
   7150                     if (!state.tmp.group_context.tip.label_capitalize_if_first) {
   7151                         state.tmp.group_context.tip.label_capitalize_if_first = this.strings.label_capitalize_if_first_override;
   7152                     }
   7153                 }
   7154                 if (this.realGroup) {
   7155                     var condition = false;
   7156                     var force_suppress = false;
   7157                     if (state.tmp.group_context.mystack.length) {
   7158                         state.output.current.value().parent = state.tmp.group_context.tip.output_tip;
   7159                     }
   7160                     var label_form = state.tmp.group_context.tip.label_form;
   7161                     if (!label_form) {
   7162                         label_form = this.strings.label_form_override;
   7163                     }
   7164                     var label_capitalize_if_first = state.tmp.group_context.tip.label_capitalize_if_first;
   7165                     if (!label_capitalize_if_first) {
   7166                         label_capitalize_if_first = this.strings.label_capitalize_if_first;
   7167                     }
   7168                     if (state.tmp.group_context.tip.condition) {
   7169                         condition = state.tmp.group_context.tip.condition;
   7170                         force_suppress = state.tmp.group_context.tip.force_suppress;
   7171                     } else if (this.strings.reject) {
   7172                         condition = {
   7173                             test: this.strings.reject,
   7174                             not: true
   7175                         }
   7176                         force_suppress = true;
   7177                         done_vars = [];
   7178                     } else if (this.strings.require) {
   7179                         condition = {
   7180                             test: this.strings.require,
   7181                             not: false
   7182                         }
   7183                         done_vars = [];
   7184                     }
   7185                     state.tmp.group_context.push({
   7186                         old_term_predecessor: state.tmp.term_predecessor,
   7187                         term_intended: false,
   7188                         variable_attempt: false,
   7189                         variable_success: false,
   7190                         variable_success_parent: state.tmp.group_context.tip.variable_success,
   7191                         output_tip: state.output.current.tip,
   7192                         label_form: label_form,
   7193                         label_capitalize_if_first: label_capitalize_if_first,
   7194                         parallel_conditions: this.strings.set_parallel_condition,
   7195                         condition: condition,
   7196                         force_suppress: force_suppress,
   7197                         done_vars: state.tmp.group_context.tip.done_vars.slice()
   7198                     });
   7199                 }
   7200             };
   7201             execs = [];
   7202             execs.push(func);
   7203             this.execs = execs.concat(this.execs);
   7204             if (this.strings["has-publisher-and-publisher-place"]) {
   7205                 state.build["publisher-special"] = true;
   7206                 func = function (state, Item) {
   7207                     if (this.strings["subgroup-delimiter"]
   7208                         && Item.publisher && Item["publisher-place"]) {
   7209                         var publisher_lst = Item.publisher.split(/;\s*/);
   7210                         var publisher_place_lst = Item["publisher-place"].split(/;\s*/);
   7211                         if (publisher_lst.length > 1
   7212                             && publisher_lst.length === publisher_place_lst.length) {
   7213                             state.publisherOutput = new CSL.PublisherOutput(state, this);
   7214                             state.publisherOutput["publisher-list"] = publisher_lst;
   7215                             state.publisherOutput["publisher-place-list"] = publisher_place_lst;
   7216                         }
   7217                     }
   7218                 };
   7219                 this.execs.push(func);
   7220             }
   7221             if (this.juris) {
   7222                 for (var x=0,xlen=target.length;x<xlen;x++) {
   7223                     var token = target[x];
   7224                 }
   7225                 var choose_start = new CSL.Token("choose", CSL.START);
   7226                 CSL.Node.choose.build.call(choose_start, state, target);
   7227                 var if_start = new CSL.Token("if", CSL.START);
   7228                 func = function (macroName) {
   7229                     return function (Item) {
   7230                         if (!state.sys.retrieveStyleModule || !CSL.MODULE_MACROS[macroName] || !Item.jurisdiction) return false;
   7231                         var jurisdictionList = state.getJurisdictionList(Item.jurisdiction);
   7232                         if (!state.opt.jurisdictions_seen[jurisdictionList[0]]) {
   7233                             var res = state.retrieveAllStyleModules(jurisdictionList);
   7234                             for (var jurisdiction in res) {
   7235                                 var macroCount = 0;
   7236                                 state.juris[jurisdiction] = {};
   7237                                 var myXml = CSL.setupXml(res[jurisdiction]);
   7238                                 var myNodes = myXml.getNodesByName(myXml.dataObj, "law-module");
   7239                                 for (var i=0,ilen=myNodes.length;i<ilen;i++) {
   7240                                     var myTypes = myXml.getAttributeValue(myNodes[i],"types");
   7241                                     if (myTypes) {
   7242                                         state.juris[jurisdiction].types = {};
   7243                                         myTypes =  myTypes.split(/\s+/);
   7244                                         for (var j=0,jlen=myTypes.length;j<jlen;j++) {
   7245                                             state.juris[jurisdiction].types[myTypes[j]] = true;
   7246                                         }
   7247                                     }
   7248                                 }
   7249                                 if (!state.juris[jurisdiction].types) {
   7250                                     state.juris[jurisdiction].types = CSL.MODULE_TYPES;
   7251                                 }
   7252                                 var myNodes = myXml.getNodesByName(myXml.dataObj, "macro");
   7253                                 for (var i=0,ilen=myNodes.length;i<ilen;i++) {
   7254                                     var myName = myXml.getAttributeValue(myNodes[i], "name");
   7255                                     if (!CSL.MODULE_MACROS[myName]) {
   7256                                         CSL.debug("CSL: skipping non-modular macro name \"" + myName + "\" in module context");
   7257                                         continue;
   7258                                     };
   7259                                     macroCount++;
   7260                                     state.juris[jurisdiction][myName] = [];
   7261                                     state.buildTokenLists(myNodes[i], state.juris[jurisdiction][myName]);
   7262                                     state.configureTokenList(state.juris[jurisdiction][myName]);
   7263                                 }
   7264                             }
   7265                         }
   7266                         for (var i=0,ilen=jurisdictionList.length;i<ilen;i++) {
   7267                             var jurisdiction = jurisdictionList[i];
   7268                             if(state.juris[jurisdiction] && state.juris[jurisdiction].types[Item.type]) {
   7269                                 Item["best-jurisdiction"] = jurisdiction;
   7270                                 return true;
   7271                             }
   7272                         }
   7273                         return false;
   7274                     };
   7275                 }(this.juris);
   7276                 if_start.tests.push(func);
   7277                 if_start.test = state.fun.match.any(if_start, state, if_start.tests);
   7278                 target.push(if_start);
   7279                 var text_node = new CSL.Token("text", CSL.SINGLETON);
   7280                 func = function (state, Item, item) {
   7281                     var next = 0;
   7282                     if (state.juris[Item["best-jurisdiction"]][this.juris]) {
   7283                         while (next < state.juris[Item["best-jurisdiction"]][this.juris].length) {
   7284                             next = CSL.tokenExec.call(state, state.juris[Item["best-jurisdiction"]][this.juris][next], Item, item);
   7285                         }
   7286                     }
   7287                 }
   7288                 text_node.juris = this.juris;
   7289                 text_node.execs.push(func);
   7290                 target.push(text_node);
   7291                 var if_end = new CSL.Token("if", CSL.END);
   7292                 CSL.Node["if"].build.call(if_end, state, target);
   7293                 var else_start = new CSL.Token("else", CSL.START);
   7294                 CSL.Node["else"].build.call(else_start, state, target);
   7295             }
   7296         }
   7297         if (this.tokentype === CSL.END) {
   7298             if (state.build["publisher-special"]) {
   7299                 state.build["publisher-special"] = false;
   7300                 if ("string" === typeof state[state.build.root].opt["name-delimiter"]) {
   7301                     func = function (state, Item) {
   7302                         if (state.publisherOutput) {
   7303                             state.publisherOutput.render();
   7304                             state.publisherOutput = false;
   7305                         }
   7306                     };
   7307                     this.execs.push(func);
   7308                 }
   7309             }
   7310             func = function (state, Item) {
   7311                 state.output.endTag();
   7312                 if (this.realGroup) {
   7313                     var flags = state.tmp.group_context.pop();
   7314                     if (state.tmp.group_context.tip.condition) {
   7315                         state.tmp.group_context.tip.force_suppress = flags.force_suppress;
   7316                     }
   7317                     if (!flags.force_suppress && (flags.variable_success || (flags.term_intended && !flags.variable_attempt))) {
   7318                         if (!this.isJurisLocatorLabel) {
   7319                             state.tmp.group_context.tip.variable_success = true;
   7320                         }
   7321                         var blobs = state.output.current.value().blobs;
   7322                         var pos = state.output.current.value().blobs.length - 1;
   7323                         if (!state.tmp.just_looking && "undefined" !== typeof flags.parallel_conditions) {
   7324                             var parallel_condition_object = {
   7325                                 blobs: blobs,
   7326                                 conditions: flags.parallel_conditions,
   7327                                 id: Item.id,
   7328                                 pos: pos
   7329                             };
   7330                             state.parallel.parallel_conditional_blobs_list.push(parallel_condition_object);
   7331                         }
   7332                     } else {
   7333                         state.tmp.term_predecessor = flags.old_term_predecessor;
   7334                         state.tmp.group_context.tip.variable_attempt = flags.variable_attempt;
   7335                         if (flags.force_suppress && !state.tmp.group_context.tip.condition) {
   7336                             state.tmp.group_context.tip.variable_attempt = true;
   7337                             state.tmp.group_context.tip.variable_success = flags.variable_success_parent;
   7338                             for (var i=0,ilen=flags.done_vars.length;i<ilen;i++) {
   7339                                 if (state.tmp.done_vars.indexOf(flags.done_vars[i]) > -1) {
   7340                                     state.tmp.done_vars = state.tmp.done_vars.slice(0, i).concat(state.tmp.done_vars.slice(i+1));
   7341                                 }
   7342                             }
   7343                         }
   7344                         if (state.output.current.value().blobs) {
   7345                             state.output.current.value().blobs.pop();
   7346                         }
   7347                     }
   7348                 }
   7349             };
   7350             this.execs.push(func);
   7351             if (this.juris) {
   7352                 var else_end = new CSL.Token("else", CSL.END);
   7353                 CSL.Node["else"].build.call(else_end, state, target);
   7354                 var choose_end = new CSL.Token("choose", CSL.END);
   7355                 CSL.Node.choose.build.call(choose_end, state, target);
   7356             }
   7357         }
   7358         if (this.tokentype === CSL.END) {
   7359             if (!this.juris) {
   7360                 target.push(this);
   7361             }
   7362             if (state.build.substitute_level.value()) {
   7363                 state.build.substitute_level.replace((state.build.substitute_level.value() - 1));
   7364             }
   7365             CSL.Util.substituteEnd.call(this, state, target);
   7366         }
   7367     }
   7368 };
   7369 CSL.Node["if"] = {
   7370     build: function (state, target) {
   7371         CSL.Conditions.TopNode.call(this, state, target);
   7372         target.push(this);
   7373     },
   7374     configure: function (state, pos) {
   7375         CSL.Conditions.Configure.call(this, state, pos);
   7376     }
   7377 };
   7378 CSL.Node["conditions"] = {
   7379     build: function (state, target) {
   7380         if (this.tokentype === CSL.START) {
   7381             state.tmp.conditions.addMatch(this.match);
   7382         }
   7383         if (this.tokentype === CSL.END) {
   7384             state.tmp.conditions.matchCombine();
   7385         }
   7386     }
   7387 };
   7388 CSL.Node["condition"] = {
   7389     build: function (state, target) {
   7390         if (this.tokentype === CSL.SINGLETON) {
   7391             var test = state.fun.match[this.match](this, state, this.tests);
   7392             state.tmp.conditions.addTest(test);
   7393         }
   7394     }
   7395 };
   7396 CSL.Conditions = {};
   7397 CSL.Conditions.TopNode = function (state, target) {
   7398     var func;
   7399     if (this.tokentype === CSL.START || this.tokentype === CSL.SINGLETON) {
   7400         if (this.locale) {
   7401             state.opt.lang = this.locale;
   7402         }
   7403         if (!this.tests || !this.tests.length) {
   7404             state.tmp.conditions = new CSL.Conditions.Engine(state, this);
   7405         } else {
   7406             this.test = state.fun.match[this.match](this, state, this.tests);
   7407         }
   7408     }
   7409     if (this.tokentype === CSL.END || this.tokentype === CSL.SINGLETON) {
   7410         func = function (state, Item) {
   7411             if (this.locale_default) {
   7412                 state.output.current.value().old_locale = this.locale_default;
   7413                 state.output.closeLevel("empty");
   7414                 state.opt.lang = this.locale_default;
   7415             }
   7416             var next = this[state.tmp.jump.value()];
   7417             return next;
   7418         };
   7419         this.execs.push(func);
   7420         if (this.locale_default) {
   7421             state.opt.lang = this.locale_default;
   7422         }
   7423     }
   7424 };
   7425 CSL.Conditions.Configure = function (state, pos) {
   7426     if (this.tokentype === CSL.START) {
   7427         this.fail = state.configure.fail.slice(-1)[0];
   7428         this.succeed = this.next;
   7429         state.configure.fail[(state.configure.fail.length - 1)] = pos;
   7430     } else if (this.tokentype === CSL.SINGLETON) {
   7431         this.fail = this.next;
   7432         this.succeed = state.configure.succeed.slice(-1)[0];
   7433         state.configure.fail[(state.configure.fail.length - 1)] = pos;
   7434     } else {
   7435         this.succeed = state.configure.succeed.slice(-1)[0];
   7436         this.fail = this.next;
   7437     }
   7438 };
   7439 CSL.Conditions.Engine = function (state, token) {
   7440     this.token = token;
   7441     this.state = state;
   7442 };
   7443 CSL.Conditions.Engine.prototype.addTest = function (test) {
   7444     this.token.tests.push(test);
   7445 };
   7446 CSL.Conditions.Engine.prototype.addMatch = function (match) {
   7447     this.token.match = match;
   7448 };
   7449 CSL.Conditions.Engine.prototype.matchCombine = function () {
   7450     this.token.test = this.state.fun.match[this.token.match](this.token, this.state, this.token.tests);
   7451 };
   7452 CSL.Node.info = {
   7453     build: function (state, target) {
   7454         if (this.tokentype === CSL.START) {
   7455             state.build.skip = "info";
   7456         } else {
   7457             state.build.skip = false;
   7458         }
   7459     }
   7460 };
   7461 CSL.Node.institution = {
   7462     build: function (state, target) {
   7463         if ([CSL.SINGLETON, CSL.START].indexOf(this.tokentype) > -1) {
   7464             var func = function (state, Item) {
   7465                 if ("string" === typeof this.strings.delimiter) {
   7466                     state.tmp.institution_delimiter = this.strings.delimiter;
   7467                 } else {
   7468                     state.tmp.institution_delimiter = state.tmp.name_delimiter;
   7469                 }
   7470                 var myand, and_default_prefix, and_suffix;
   7471                 if ("text" === state.inheritOpt(this, "and")) {
   7472                     this.and_term = state.getTerm("and", "long", 0);
   7473                 } else if ("symbol" === state.inheritOpt(this, "and")) {
   7474                     if (state.opt.development_extensions.expect_and_symbol_form) {
   7475                         this.and_term = state.getTerm("and", "symbol", 0);
   7476                     } else {
   7477                         this.and_term = "&";
   7478                     }
   7479                 } else if ("none" === state.inheritOpt(this, "and")) {
   7480                     this.and_term = state.tmp.institution_delimiter;
   7481                 }
   7482                 if ("undefined" === typeof this.and_term && state.tmp.and_term) {
   7483                     this.and_term = state.getTerm("and", "long", 0);
   7484                 }
   7485                 if (CSL.STARTSWITH_ROMANESQUE_REGEXP.test(this.and_term)) {
   7486                     this.and_prefix_single = " ";
   7487                     this.and_prefix_multiple = ", ";
   7488                     if ("string" === typeof state.tmp.institution_delimiter) {
   7489                         this.and_prefix_multiple = state.tmp.institution_delimiter;
   7490                     }
   7491                     this.and_suffix = " ";
   7492                 } else {
   7493                     this.and_prefix_single = "";
   7494                     this.and_prefix_multiple = "";
   7495                     this.and_suffix = "";
   7496                 }
   7497                 if (state.inheritOpt(this, "delimiter-precedes-last") === "always") {
   7498                     this.and_prefix_single = state.tmp.institution_delimiter;
   7499                 } else if (state.inheritOpt(this, "delimiter-precedes-last") === "never") {
   7500                     if (this.and_prefix_multiple) {
   7501                         this.and_prefix_multiple = " ";
   7502                     }
   7503                 }
   7504                 this.and = {};
   7505                 if ("undefined" !== typeof this.and_term) {
   7506                     state.output.append(this.and_term, "empty", true);
   7507                     this.and.single = state.output.pop();
   7508                     this.and.single.strings.prefix = this.and_prefix_single;
   7509                     this.and.single.strings.suffix = this.and_suffix;
   7510                     state.output.append(this.and_term, "empty", true);
   7511                     this.and.multiple = state.output.pop();
   7512                     this.and.multiple.strings.prefix = this.and_prefix_multiple;
   7513                     this.and.multiple.strings.suffix = this.and_suffix;
   7514                 } else if ("undefined" !== this.strings.delimiter) {
   7515                     this.and.single = new CSL.Blob(state.tmp.institution_delimiter);
   7516                     this.and.single.strings.prefix = "";
   7517                     this.and.single.strings.suffix = "";
   7518                     this.and.multiple = new CSL.Blob(state.tmp.institution_delimiter);
   7519                     this.and.multiple.strings.prefix = "";
   7520                     this.and.multiple.strings.suffix = "";
   7521                 }
   7522                 state.nameOutput.institution = this;
   7523             };
   7524             this.execs.push(func);
   7525         }
   7526         target.push(this);
   7527     },
   7528     configure: function (state, pos) {
   7529         if ([CSL.SINGLETON, CSL.START].indexOf(this.tokentype) > -1) {
   7530             state.build.has_institution = true;
   7531         }
   7532     }
   7533 };
   7534 CSL.Node["institution-part"] = {
   7535     build: function (state, target) {
   7536         var func;
   7537         if ("long" === this.strings.name) {
   7538             if (this.strings["if-short"]) {
   7539                 func = function (state, Item) {
   7540                     state.nameOutput.institutionpart["long-with-short"] = this;
   7541                 };
   7542             } else {
   7543                 func = function (state, Item) {
   7544                     state.nameOutput.institutionpart["long"] = this;
   7545                 };
   7546             }
   7547         } else if ("short" === this.strings.name) {
   7548             func = function (state, Item) {
   7549                 state.nameOutput.institutionpart["short"] = this;
   7550             };
   7551         }
   7552         this.execs.push(func);
   7553         target.push(this);
   7554     }
   7555 };
   7556 CSL.Node.key = {
   7557     build: function (state, target) {
   7558         target = state[state.build.root + "_sort"].tokens;
   7559         var func, i, ilen;
   7560         var debug = false;
   7561         var start_key = new CSL.Token("key", CSL.START);
   7562         state.tmp.root = state.build.root;
   7563         start_key.strings["et-al-min"] = state.inheritOpt(this, "et-al-min");
   7564         start_key.strings["et-al-use-first"] = state.inheritOpt(this, "et-al-use-first");
   7565         start_key.strings["et-al-use-last"] = state.inheritOpt(this, "et-al-use-last");
   7566         func = function (state, Item) {
   7567             state.tmp.done_vars = [];
   7568         };
   7569         start_key.execs.push(func);
   7570         state.opt.citation_number_sort_direction = this.strings.sort_direction;
   7571         func = function (state, Item) {
   7572             state.output.openLevel("empty");
   7573         };
   7574         start_key.execs.push(func);
   7575         var sort_direction = [];
   7576         if (this.strings.sort_direction === CSL.DESCENDING) {
   7577             sort_direction.push(1);
   7578             sort_direction.push(-1);
   7579         } else {
   7580             sort_direction.push(-1);
   7581             sort_direction.push(1);
   7582         }
   7583         state[state.build.area].opt.sort_directions.push(sort_direction);
   7584         if (CSL.DATE_VARIABLES.indexOf(this.variables[0]) > -1) {
   7585             state.build.date_key = true;
   7586         }
   7587         func = function (state, Item) {
   7588             state.tmp.sort_key_flag = true;
   7589             if (state.inheritOpt(this, "et-al-min")) {
   7590                 state.tmp["et-al-min"] = state.inheritOpt(this, "et-al-min");
   7591             }
   7592             if (state.inheritOpt(this, "et-al-use-first")) {
   7593                 state.tmp["et-al-use-first"] = state.inheritOpt(this, "et-al-use-first");
   7594             }
   7595             if ("boolean" === typeof state.inheritOpt(this, "et-al-use-last")) {
   7596                 state.tmp["et-al-use-last"] = state.inheritOpt(this, "et-al-use-last");
   7597             }
   7598         };
   7599         start_key.execs.push(func);
   7600         target.push(start_key);
   7601         if (this.variables.length) {
   7602             var variable = this.variables[0];
   7603             if (variable === "citation-number") {
   7604                 if (state.build.area === "citation" && state.build.extension === "_sort") {
   7605                     state.opt.citation_number_sort = false;
   7606                 }
   7607                 if (state.build.root === "bibliography" && state.build.extension === "_sort") {
   7608                     state.opt.citation_number_sort_used = false;
   7609                 }
   7610             }
   7611             if (CSL.CREATORS.indexOf(variable) > -1) {
   7612                 var names_start_token = new CSL.Token("names", CSL.START);
   7613                 names_start_token.tokentype = CSL.START;
   7614                 names_start_token.variables = this.variables;
   7615                 CSL.Node.names.build.call(names_start_token, state, target);
   7616                 var name_token = new CSL.Token("name", CSL.SINGLETON);
   7617                 name_token.tokentype = CSL.SINGLETON;
   7618                 name_token.strings["name-as-sort-order"] = "all";
   7619                 name_token.strings["sort-separator"] = " ";
   7620                 name_token.strings["et-al-use-last"] = state.inheritOpt(this, "et-al-use-last");
   7621                 name_token.strings["et-al-min"] = state.inheritOpt(this, "et-al-min");
   7622                 name_token.strings["et-al-use-first"] = state.inheritOpt(this, "et-al-use-first");
   7623                 CSL.Node.name.build.call(name_token, state, target);
   7624                 var institution_token = new CSL.Token("institution", CSL.SINGLETON);
   7625                 institution_token.tokentype = CSL.SINGLETON;
   7626                 CSL.Node.institution.build.call(institution_token, state, target);
   7627                 var names_end_token = new CSL.Token("names", CSL.END);
   7628                 names_end_token.tokentype = CSL.END;
   7629                 CSL.Node.names.build.call(names_end_token, state, target);
   7630             } else {
   7631                 var single_text = new CSL.Token("text", CSL.SINGLETON);
   7632                 single_text.dateparts = this.dateparts;
   7633                 if (CSL.NUMERIC_VARIABLES.indexOf(variable) > -1) {
   7634                     func = function (state, Item) {
   7635                         var num, m;
   7636                         num = false;
   7637                         if ("citation-number" === variable) {
   7638                             num = state.registry.registry[Item.id].seq.toString();
   7639                         } else {
   7640                             num = Item[variable];
   7641                         }
   7642                         if (num) {
   7643                             num = CSL.Util.padding(num);
   7644                         }
   7645                         state.output.append(num, this);
   7646                     };
   7647                 } else if (variable === "citation-label") {
   7648                     func = function (state, Item) {
   7649                         var trigraph = state.getCitationLabel(Item);
   7650                         state.output.append(trigraph, this);
   7651                     };
   7652                 } else if (CSL.DATE_VARIABLES.indexOf(variable) > -1) {
   7653                     func = CSL.dateAsSortKey;
   7654                     single_text.variables = this.variables;
   7655                 } else if ("title" === variable) {
   7656                     var abbrevfam = "title";
   7657                     var abbrfall = false;
   7658                     var altvar = false;
   7659                     var transfall = true;
   7660                     func = state.transform.getOutputFunction(this.variables, abbrevfam, abbrfall, altvar, transfall);
   7661                 } else {
   7662                     func = function (state, Item) {
   7663                         var varval = Item[variable];
   7664                         state.output.append(varval, "empty");
   7665                     };
   7666                 }
   7667                 single_text.execs.push(func);
   7668                 target.push(single_text);
   7669             }
   7670         } else { // macro
   7671             var token = new CSL.Token("text", CSL.SINGLETON);
   7672             token.postponed_macro = this.postponed_macro;
   7673             CSL.expandMacro.call(state, token, target);
   7674         }
   7675         var end_key = new CSL.Token("key", CSL.END);
   7676         func = function (state, Item) {
   7677             var keystring = state.output.string(state, state.output.queue);
   7678             if (state.sys.normalizeUnicode) {
   7679                 keystring = state.sys.normalizeUnicode(keystring);
   7680             }
   7681             keystring = keystring ? (keystring.split(" ").join(state.opt.sort_sep) + state.opt.sort_sep) : "";
   7682             if ("" === keystring) {
   7683                 keystring = undefined;
   7684             }
   7685             if ("string" !== typeof keystring || state.tmp.empty_date) {
   7686                 keystring = undefined;
   7687                 state.tmp.empty_date = false;
   7688             }
   7689             state[state[state.tmp.area].root + "_sort"].keys.push(keystring);
   7690             state.tmp.value = [];
   7691         };
   7692         end_key.execs.push(func);
   7693         if (state.build.date_key) {
   7694             if (state.build.area === "citation" && state.build.extension === "_sort") {
   7695                 state[state.build.area].opt.sort_directions.push([-1,1]);
   7696                 func = function (state, Item) {
   7697                     var year_suffix = state.registry.registry[Item.id].disambig.year_suffix;
   7698                     if (!year_suffix) {
   7699                         year_suffix = 0;
   7700                     }
   7701                     var key = CSL.Util.padding("" + year_suffix);
   7702                     state[state.tmp.area].keys.push(key);
   7703                 }
   7704                 end_key.execs.push(func);
   7705             }
   7706             state.build.date_key = false;
   7707         }
   7708         func = function (state, Item) {
   7709             state.tmp["et-al-min"] = undefined;
   7710             state.tmp["et-al-use-first"] = undefined;
   7711             state.tmp["et-al-use-last"] = undefined;
   7712             state.tmp.sort_key_flag = false;
   7713         };
   7714         end_key.execs.push(func);
   7715         target.push(end_key);
   7716     }
   7717 };
   7718 CSL.Node.label = {
   7719     build: function (state, target) {
   7720         var debug = false;
   7721         if (this.strings.term) {
   7722             var plural = false;
   7723             if (!this.strings.form) {
   7724             }
   7725             var func = function (state, Item, item) {
   7726                 var termtxt = CSL.evaluateLabel(this, state, Item, item);
   7727                 if (item && this.strings.term === "locator") {
   7728                     state.parallel.StartVariable("label");
   7729                     state.parallel.AppendToVariable(item.label);
   7730                     item.section_form_override = this.strings.form;
   7731                 }
   7732                 if (termtxt) {
   7733                     state.tmp.group_context.tip.term_intended = true;
   7734                 }
   7735                 CSL.UPDATE_GROUP_CONTEXT_CONDITION(state, termtxt);
   7736                 if (termtxt.indexOf("%s") === -1) {
   7737                     if (this.strings.capitalize_if_first) {
   7738                         if (!state.tmp.term_predecessor && !(state.opt["class"] === "in-text" && state.tmp.area === "citation")) {
   7739                             termtxt = CSL.Output.Formatters["capitalize-first"](state, termtxt);
   7740                         }
   7741                     }
   7742                     state.output.append(termtxt, this);
   7743                 }
   7744                 if (item && this.strings.term === "locator") {
   7745                     state.parallel.CloseVariable();
   7746                 }
   7747             };
   7748             this.execs.push(func);
   7749         } else {
   7750             var namevars = state.build.names_variables.slice(-1)[0];
   7751             if (!state.build.name_label) {
   7752                 state.build.name_label = {};
   7753             }
   7754             for (var i = 0, ilen = namevars.length; i < ilen; i += 1) {
   7755                 if (!state.build.name_label[namevars[i]]) {
   7756                     state.build.name_label[namevars[i]] = {};
   7757                 }
   7758             }
   7759             if (!state.build.name_flag) {
   7760                 for (var i = 0, ilen = namevars.length; i < ilen; i += 1) {
   7761                     state.build.name_label[namevars[i]].before = this;
   7762                 }
   7763             } else {
   7764                 for (var i = 0, ilen = namevars.length; i < ilen; i += 1) {
   7765                     state.build.name_label[namevars[i]].after = this;
   7766                 }
   7767             }
   7768         }
   7769         target.push(this);
   7770     }
   7771 };
   7772 CSL.Node.layout = {
   7773     build: function (state, target) {
   7774         var func, prefix_token, suffix_token, tok;
   7775         function setSuffix() {
   7776             if (state.build.area === "bibliography") {
   7777                 suffix_token = new CSL.Token("text", CSL.SINGLETON);
   7778                 func = function(state, Item, item) {
   7779                     var last_locale = state.tmp.cite_locales[state.tmp.cite_locales.length - 1];
   7780                     var suffix;
   7781                     if (state.tmp.cite_affixes[state.tmp.area][state.tmp.last_cite_locale]) {
   7782                         suffix = state.tmp.cite_affixes[state.tmp.area][state.tmp.last_cite_locale].suffix;
   7783                     } else {
   7784                         suffix = state.bibliography.opt.layout_suffix;
   7785                     }
   7786                     var topblob = state.output.current.value();
   7787                     if (state.opt.using_display) {
   7788                         topblob.blobs[topblob.blobs.length-1].strings.suffix = suffix;
   7789                     } else {
   7790                         topblob.strings.suffix = suffix;
   7791                     }
   7792                     if (state.bibliography.opt["second-field-align"]) {
   7793                         state.output.endTag("bib_other");
   7794                     }
   7795                 };
   7796                 suffix_token.execs.push(func);
   7797                 target.push(suffix_token);
   7798             }
   7799         }
   7800         if (this.tokentype === CSL.START) {
   7801             if (this.locale_raw) {
   7802                 state.build.current_default_locale = this.locale_raw;
   7803             } else {
   7804                 state.build.current_default_locale = state.opt["default-locale"];
   7805             }
   7806             func = function (state, Item, item) {
   7807                 if (state.opt.development_extensions.apply_citation_wrapper
   7808                     && state.sys.wrapCitationEntry
   7809                     && !state.tmp.just_looking
   7810                     && Item.system_id 
   7811                     && state.tmp.area === "citation") { 
   7812                     cite_entry = new CSL.Token("group", CSL.START);
   7813                     cite_entry.decorations = [["@cite", "entry"]];
   7814                     state.output.startTag("cite_entry", cite_entry);
   7815                     state.output.current.value().item_id = Item.system_id;
   7816                     if (item) {
   7817                         state.output.current.value().locator_txt = item.locator_txt;
   7818                         state.output.current.value().suffix_txt = item.suffix_txt;
   7819                     }
   7820                 }
   7821             }
   7822             this.execs.push(func);
   7823         }
   7824         if (this.tokentype === CSL.START && !state.tmp.cite_affixes[state.build.area]) {
   7825             func = function (state, Item) {
   7826                 state.tmp.done_vars = [];
   7827                 if (state.opt.suppressedJurisdictions[Item["country"]]
   7828                     && Item["country"]
   7829                     && ["treaty", "patent"].indexOf(Item.type) === -1) {
   7830                     state.tmp.done_vars.push("country");
   7831                 }
   7832                 if (!state.tmp.just_looking && state.registry.registry[Item.id] && state.registry.registry[Item.id].parallel) {
   7833                     state.tmp.done_vars.push("first-reference-note-number");
   7834                 }
   7835                 state.tmp.rendered_name = false;
   7836             };
   7837             this.execs.push(func);
   7838             func = function (state, Item) {
   7839                 state.tmp.sort_key_flag = false;
   7840             };
   7841             this.execs.push(func);
   7842             func = function (state, Item) {
   7843                 state.tmp.nameset_counter = 0;
   7844             };
   7845             this.execs.push(func);
   7846             func = function (state, Item) {
   7847                 var tok = new CSL.Token();
   7848                 if (state.opt.development_extensions.rtl_support) {
   7849                     if (["ar", "he", "fa", "ur", "yi", "ps", "syr"].indexOf(Item.language) > -1) {
   7850                         tok = new CSL.Token();
   7851                         tok.strings.prefix = "\u202b";
   7852                         tok.strings.suffix = "\u202c";
   7853                     }
   7854                 }
   7855                 state.output.openLevel(tok);
   7856             }
   7857             this.execs.push(func);
   7858             target.push(this);
   7859             if (state.opt.development_extensions.rtl_support && false) {
   7860                 this.strings.prefix = this.strings.prefix.replace(/\((.|$)/g,"(\u200e$1");
   7861                 this.strings.suffix = this.strings.suffix.replace(/\)(.|$)/g,")\u200e$1");
   7862             }
   7863             if (state.build.area === "citation") {
   7864                 prefix_token = new CSL.Token("text", CSL.SINGLETON);
   7865                 func = function (state, Item, item) {
   7866                     var sp;
   7867                     if (item && item.prefix) {
   7868                         sp = "";
   7869                         var test_prefix = item.prefix.replace(/<[^>]+>/g, "").replace(/["'\u201d\u2019\u00bb\u202f\u00a0 ]+$/g,"");
   7870                         var test_char = test_prefix.slice(-1);
   7871                         if (test_prefix.match(CSL.ENDSWITH_ROMANESQUE_REGEXP)) {
   7872                             sp = " ";
   7873                         } else if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(test_char) > -1) {
   7874                             sp = " ";
   7875                         } else if (test_char.match(/[\)\],0-9]/)) {
   7876                             sp = " ";
   7877                         }
   7878                         var ignorePredecessor = false;
   7879                         if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(test_char) > -1 && item.prefix.trim().indexOf(" ") > -1) {
   7880                             state.tmp.term_predecessor = false;
   7881                             ignorePredecessor = true;
   7882                         }
   7883                         var prefix = (item.prefix + sp).replace(/\s+/g, " ");
   7884                         if (!state.tmp.just_looking) {
   7885                             prefix = state.output.checkNestedBrace.update(prefix);
   7886                         }
   7887                         state.output.append(prefix, this, false, ignorePredecessor);
   7888                     }
   7889                 };
   7890                 prefix_token.execs.push(func);
   7891                 target.push(prefix_token);
   7892             }
   7893         }
   7894         var my_tok;
   7895         if (this.locale_raw) {
   7896             my_tok = new CSL.Token("dummy", CSL.START);
   7897             my_tok.locale = this.locale_raw;
   7898             my_tok.strings.delimiter = this.strings.delimiter;
   7899             my_tok.strings.suffix = this.strings.suffix;
   7900             if (!state.tmp.cite_affixes[state.build.area]) {
   7901                 state.tmp.cite_affixes[state.build.area] = {};
   7902             }
   7903         }
   7904         if (this.tokentype === CSL.START) {
   7905             state.build.layout_flag = true;
   7906             if (!this.locale_raw) {
   7907                 state[state.tmp.area].opt.topdecor = [this.decorations];
   7908                 state[(state.tmp.area + "_sort")].opt.topdecor = [this.decorations];
   7909                 state[state.build.area].opt.layout_prefix = this.strings.prefix;
   7910                 state[state.build.area].opt.layout_suffix = this.strings.suffix;
   7911                 state[state.build.area].opt.layout_delimiter = this.strings.delimiter;
   7912                 state[state.build.area].opt.layout_decorations = this.decorations;
   7913                 if (state.tmp.cite_affixes[state.build.area]) {
   7914                     tok = new CSL.Token("else", CSL.START);
   7915                     CSL.Node["else"].build.call(tok, state, target);
   7916                 }
   7917             } // !this.locale_raw
   7918             if (this.locale_raw) {
   7919                 if (!state.build.layout_locale_flag) {
   7920                     var choose_tok = new CSL.Token("choose", CSL.START);
   7921                     CSL.Node.choose.build.call(choose_tok, state, target);
   7922                     my_tok.name = "if";
   7923                     CSL.Attributes["@locale-internal"].call(my_tok, state, this.locale_raw);
   7924                     CSL.Node["if"].build.call(my_tok, state, target);
   7925                 } else {
   7926                     my_tok.name = "else-if";
   7927                     CSL.Attributes["@locale-internal"].call(my_tok, state, this.locale_raw);
   7928                     CSL.Node["else-if"].build.call(my_tok, state, target);
   7929                 }
   7930                 state.tmp.cite_affixes[state.build.area][my_tok.locale] = {};
   7931                 state.tmp.cite_affixes[state.build.area][my_tok.locale].delimiter = this.strings.delimiter;
   7932                 state.tmp.cite_affixes[state.build.area][my_tok.locale].suffix = this.strings.suffix;
   7933             }
   7934         }
   7935         if (this.tokentype === CSL.END) {
   7936             if (this.locale_raw) {
   7937                 setSuffix();
   7938                 if (!state.build.layout_locale_flag) {
   7939                     my_tok.name = "if";
   7940                     my_tok.tokentype = CSL.END;
   7941                     CSL.Attributes["@locale-internal"].call(my_tok, state, this.locale_raw);
   7942                     CSL.Node["if"].build.call(my_tok, state, target);
   7943                     state.build.layout_locale_flag = true;
   7944                 } else {
   7945                     my_tok.name = "else-if";
   7946                     my_tok.tokentype = CSL.END;
   7947                     CSL.Attributes["@locale-internal"].call(my_tok, state, this.locale_raw);
   7948                     CSL.Node["else-if"].build.call(my_tok, state, target);
   7949                 }
   7950             }
   7951             if (!this.locale_raw) {
   7952                 setSuffix();
   7953                 if (state.tmp.cite_affixes[state.build.area]) {
   7954                     if (state.build.layout_locale_flag) {
   7955                         tok = new CSL.Token("else", CSL.END);
   7956                         CSL.Node["else"].build.call(tok, state, target);
   7957                         tok = new CSL.Token("choose", CSL.END);
   7958                         CSL.Node.choose.build.call(tok, state, target);
   7959                     }
   7960                 }
   7961                 state.build_layout_locale_flag = true;
   7962                 if (state.build.area === "citation") {
   7963                     suffix_token = new CSL.Token("text", CSL.SINGLETON);
   7964                     func = function (state, Item, item) {
   7965                         var sp;
   7966                         if (item && item.suffix) {
   7967                             sp = "";
   7968                             if (item.suffix.match(CSL.STARTSWITH_ROMANESQUE_REGEXP)
   7969                                 || ['[','('].indexOf(item.suffix.slice(0,1)) > -1) {
   7970                                 sp = " ";
   7971                             }
   7972                             var suffix = item.suffix;
   7973                             if (!state.tmp.just_looking) {
   7974                                 suffix = state.output.checkNestedBrace.update(suffix);
   7975                             }
   7976                             state.output.append((sp + suffix), this);
   7977                         }
   7978                     };
   7979                     suffix_token.execs.push(func);
   7980                     target.push(suffix_token);
   7981                 }
   7982                 func = function (state, Item) {
   7983                     state.output.closeLevel();
   7984                 };
   7985                 this.execs.push(func);
   7986                 func = function (state, Item) {
   7987                     if (state.opt.development_extensions.apply_citation_wrapper
   7988                         && state.sys.wrapCitationEntry
   7989                         && !state.tmp.just_looking
   7990                         && Item.system_id 
   7991                         && state.tmp.area === "citation") { 
   7992                         state.output.endTag(); // closes citation link wrapper
   7993                     }
   7994                 }
   7995                 this.execs.push(func);
   7996                 target.push(this);
   7997                 state.build.layout_flag = false;
   7998                 state.build.layout_locale_flag = false;
   7999             } // !this.layout_raw
   8000         }
   8001     }
   8002 };
   8003 CSL.Node.macro = {
   8004     build: function (state, target) {}
   8005 };
   8006 CSL.NameOutput = function(state, Item, item, variables) {
   8007     this.debug = false;
   8008     this.state = state;
   8009     this.Item = Item;
   8010     this.item = item;
   8011     this.nameset_base = 0;
   8012     this.etal_spec = {};
   8013     this._first_creator_variable = false;
   8014     this._please_chop = false;
   8015 };
   8016 CSL.NameOutput.prototype.init = function (names) {
   8017     if (this.state.tmp.term_predecessor) {
   8018         this.state.tmp.subsequent_author_substitute_ok = false;
   8019     }
   8020     if (this.nameset_offset) {
   8021         this.nameset_base = this.nameset_base + this.nameset_offset;
   8022     }
   8023     this.nameset_offset = 0;
   8024     this.names = names;
   8025     this.variables = names.variables;
   8026     this.state.tmp.value = [];
   8027     this.state.tmp.rendered_name = [];
   8028     this.state.tmp.label_blob = false;
   8029     this.state.tmp.etal_node = false;
   8030     this.state.tmp.etal_term = false;
   8031     for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8032         if (this.Item[this.variables[i]] && this.Item[this.variables[i]].length) {
   8033             this.state.tmp.value = this.state.tmp.value.concat(this.Item[this.variables[i]]);
   8034         }
   8035     }
   8036     this["et-al"] = undefined;
   8037     this["with"] = undefined;
   8038     this.name = undefined;
   8039     this.institutionpart = {};
   8040     this.state.tmp.group_context.tip.variable_attempt = true;
   8041     this.labelVariable = this.variables[0];
   8042     if (!this.state.tmp.value.length) {
   8043         return;
   8044     }
   8045 };
   8046 CSL.NameOutput.prototype.reinit = function (names, labelVariable) {
   8047     this.labelVariable = labelVariable;
   8048     if (this.state.tmp.can_substitute.value()) {
   8049         this.nameset_offset = 0;
   8050         this.variables = names.variables;
   8051         var oldval = this.state.tmp.value.slice();
   8052         this.state.tmp.value = [];
   8053         for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8054             if (this.Item[this.variables[i]] && this.Item[this.variables[i]].length) {
   8055                 this.state.tmp.value = this.state.tmp.value.concat(this.Item[this.variables[i]]);
   8056             }
   8057         }
   8058         if (this.state.tmp.value.length) {
   8059             this.state.tmp.can_substitute.replace(false, CSL.LITERAL);
   8060         }
   8061         this.state.tmp.value = oldval;
   8062     }
   8063 };
   8064 CSL.NameOutput.prototype.outputNames = function () {
   8065     var i, ilen;
   8066     var variables = this.variables;
   8067     if (this.institution.and) {
   8068         if (!this.institution.and.single.blobs || !this.institution.and.single.blobs.length) {
   8069             this.institution.and.single.blobs = this.name.and.single.blobs;
   8070         }
   8071         if (!this.institution.and.multiple.blobs || !this.institution.and.multiple.blobs.length) {
   8072             this.institution.and.multiple.blobs = this.name.and.multiple.blobs;
   8073         }
   8074     }
   8075     this.variable_offset = {};
   8076     if (this.family) {
   8077         this.family_decor = CSL.Util.cloneToken(this.family);
   8078         this.family_decor.strings.prefix = "";
   8079         this.family_decor.strings.suffix = "";
   8080         for (i = 0, ilen = this.family.execs.length; i < ilen; i += 1) {
   8081             this.family.execs[i].call(this.family_decor, this.state, this.Item);
   8082         }
   8083     } else {
   8084         this.family_decor = false;
   8085     }
   8086     if (this.given) {
   8087         this.given_decor = CSL.Util.cloneToken(this.given);
   8088         this.given_decor.strings.prefix = "";
   8089         this.given_decor.strings.suffix = "";
   8090         for (i = 0, ilen = this.given.execs.length; i < ilen; i += 1) {
   8091             this.given.execs[i].call(this.given_decor, this.state, this.Item);
   8092         }
   8093     } else {
   8094         this.given_decor = false;
   8095     }
   8096     this.getEtAlConfig();
   8097     this.divideAndTransliterateNames();
   8098     this.truncatePersonalNameLists();
   8099     this.disambigNames();
   8100     this.constrainNames();
   8101     if (this.name.strings.form === "count") {
   8102         if (this.state.tmp.extension || this.names_count != 0) {
   8103             this.state.output.append(this.names_count, "empty");
   8104             this.state.tmp.group_context.tip.variable_success = true;
   8105         }
   8106         return;
   8107     }
   8108     this.setEtAlParameters();
   8109     this.setCommonTerm();
   8110     this.state.tmp.name_node = {};
   8111     this.state.tmp.name_node.children = [];
   8112     this.renderAllNames();
   8113     var blob_list = [];
   8114     for (i = 0, ilen = variables.length; i < ilen; i += 1) {
   8115         var v = variables[i];
   8116         var institution_sets = [];
   8117         var institutions = false;
   8118         var varblob = null;
   8119         if (!this.state.opt.development_extensions.spoof_institutional_affiliations) {
   8120             varblob = this._join([this.freeters[v]], "");
   8121         } else {
   8122             for (var j = 0, jlen = this.institutions[v].length; j < jlen; j += 1) {
   8123                 institution_sets.push(this.joinPersonsAndInstitutions([this.persons[v][j], this.institutions[v][j]]));
   8124             }
   8125             if (this.institutions[v].length) {
   8126                 var pos = this.nameset_base + this.variable_offset[v];
   8127                 if (this.freeters[v].length) {
   8128                     pos += 1;
   8129                 }
   8130                 institutions = this.joinInstitutionSets(institution_sets, pos);
   8131             }
   8132             var varblob = this.joinFreetersAndInstitutionSets([this.freeters[v], institutions]);
   8133         }
   8134         if (varblob) {
   8135             if (!this.state.tmp.extension) {
   8136                 varblob = this._applyLabels(varblob, v);
   8137             }
   8138             blob_list.push(varblob);
   8139         }
   8140         if (this.common_term) {
   8141             break;
   8142         }
   8143     }
   8144     this.state.output.openLevel("empty");
   8145     this.state.output.current.value().strings.delimiter = this.state.inheritOpt(this.names, "delimiter", "names-delimiter");
   8146     for (i = 0, ilen = blob_list.length; i < ilen; i += 1) {
   8147         this.state.output.append(blob_list[i], "literal", true);
   8148     }
   8149     this.state.output.closeLevel("empty");
   8150     var blob = this.state.output.pop();
   8151     var namesToken = CSL.Util.cloneToken(this.names);
   8152     this.state.output.append(blob, namesToken);
   8153     if (this.state.tmp.term_predecessor_name) {
   8154         this.state.tmp.term_predecessor = true;
   8155     }
   8156     this.state.tmp.name_node.top = this.state.output.current.value();
   8157     if (variables[0] !== "authority") {
   8158         var name_node_string = [];
   8159         var nameobjs = this.Item[variables[0]];
   8160         if (nameobjs) {
   8161             for (var i = 0, ilen = nameobjs.length; i < ilen; i += 1) {
   8162                 var substring = CSL.Util.Names.getRawName(nameobjs[i]);
   8163                 if (substring) {
   8164                     name_node_string.push(substring);
   8165                 }
   8166             }
   8167         }
   8168         name_node_string = name_node_string.join(", ");
   8169         if (name_node_string) {
   8170             this.state.tmp.name_node.string = name_node_string;
   8171         }
   8172     }
   8173     if (this.state.tmp.name_node.string && !this.state.tmp.first_name_string) {
   8174         this.state.tmp.first_name_string = this.state.tmp.name_node.string;
   8175     }
   8176     if ("classic" === this.Item.type) {
   8177         var author_title = [];
   8178         if (this.state.tmp.first_name_string) {
   8179             author_title.push(this.state.tmp.first_name_string);
   8180         }
   8181         if (this.Item.title) {
   8182             author_title.push(this.Item.title);
   8183         }
   8184         author_title = author_title.join(", ");
   8185         if (author_title && this.state.sys.getAbbreviation) {
   8186             this.state.transform.loadAbbreviation("default", "classic", author_title);
   8187             if (this.state.transform.abbrevs["default"].classic[author_title]) {
   8188                 this.state.tmp.done_vars.push("title");
   8189                 this.state.output.append(this.state.transform.abbrevs["default"].classic[author_title], "empty", true);
   8190                 blob = this.state.output.pop();
   8191 				this.state.tmp.name_node.top.blobs.pop();
   8192                 this.state.tmp.name_node.top.blobs.push(blob);
   8193             }
   8194         }
   8195     }
   8196     this._collapseAuthor();
   8197     this.variables = [];
   8198 };
   8199 CSL.NameOutput.prototype._applyLabels = function (blob, v) {
   8200     var txt;
   8201     if (!this.label || !this.label[this.labelVariable]) {
   8202         return blob;
   8203     }
   8204     var plural = 0;
   8205     var num = this.freeters_count[v] + this.institutions_count[v];
   8206     if (num > 1) {
   8207         plural = 1;
   8208     } else {
   8209         for (var i = 0, ilen = this.persons[v].length; i < ilen; i += 1) {
   8210             num += this.persons_count[v][i];
   8211         }
   8212         if (num > 1) {
   8213             plural = 1;
   8214         }
   8215     }
   8216     if (this.label[this.labelVariable].before) {
   8217         if ("number" === typeof this.label[this.labelVariable].before.strings.plural) {
   8218             plural = this.label[this.labelVariable].before.strings.plural;
   8219         }
   8220         txt = this._buildLabel(v, plural, "before", this.labelVariable);
   8221         this.state.output.openLevel("empty");
   8222         this.state.output.append(txt, this.label[this.labelVariable].before, true);
   8223         this.state.output.append(blob, "literal", true);
   8224         this.state.output.closeLevel("empty");
   8225         blob = this.state.output.pop();
   8226     } else if (this.label[this.labelVariable].after) {
   8227         if ("number" === typeof this.label[this.labelVariable].after.strings.plural) {
   8228             plural = this.label[this.labelVariable].after.strings.plural;
   8229         }
   8230         txt = this._buildLabel(v, plural, "after", this.labelVariable);
   8231         this.state.output.openLevel("empty");
   8232         this.state.output.append(blob, "literal", true);
   8233         this.state.output.append(txt, this.label[this.labelVariable].after, true);
   8234         this.state.tmp.label_blob = this.state.output.pop();
   8235         this.state.output.append(this.state.tmp.label_blob,"literal",true);
   8236         this.state.output.closeLevel("empty");
   8237         blob = this.state.output.pop();
   8238     }
   8239     return blob;
   8240 };
   8241 CSL.NameOutput.prototype._buildLabel = function (term, plural, position, v) {
   8242     if (this.common_term) {
   8243         term = this.common_term;
   8244     }
   8245     var ret = false;
   8246     var node = this.label[v][position];
   8247     if (node) {
   8248         ret = CSL.castLabel(this.state, node, term, plural, CSL.TOLERANT);
   8249     }
   8250     return ret;
   8251 };
   8252 CSL.NameOutput.prototype._collapseAuthor = function () {
   8253     var myqueue, mystr, oldchars;
   8254     if (this.nameset_base === 0 && this.Item[this.variables[0]] && !this._first_creator_variable) {
   8255         this._first_creator_variable = this.variables[0];
   8256     }
   8257     if ((this.item && this.item["suppress-author"] && this._first_creator_variable == this.variables[0])
   8258         || (this.state[this.state.tmp.area].opt.collapse 
   8259             && this.state[this.state.tmp.area].opt.collapse.length)
   8260         || (this.state[this.state.tmp.area].opt.cite_group_delimiter 
   8261             && this.state[this.state.tmp.area].opt.cite_group_delimiter.length)) {
   8262         if (this.state.tmp.authorstring_request) {
   8263             mystr = "";
   8264             myqueue = this.state.tmp.name_node.top.blobs.slice(-1)[0].blobs;
   8265             oldchars = this.state.tmp.offset_characters;
   8266             if (myqueue) {
   8267                 mystr = this.state.output.string(this.state, myqueue, false);
   8268             }
   8269             this.state.tmp.offset_characters = oldchars;
   8270             this.state.registry.authorstrings[this.Item.id] = mystr;
   8271         } else if (!this.state.tmp.just_looking
   8272                    && !this.state.tmp.suppress_decorations && (this.item["suppress-author"] || (this.state[this.state.tmp.area].opt.collapse && this.state[this.state.tmp.area].opt.collapse.length) || this.state[this.state.tmp.area].opt.cite_group_delimiter && this.state[this.state.tmp.area].opt.cite_group_delimiter)) {
   8273             mystr = "";
   8274             myqueue = this.state.tmp.name_node.top.blobs.slice(-1)[0].blobs;
   8275             oldchars = this.state.tmp.offset_characters;
   8276             if (myqueue) {
   8277                 mystr = this.state.output.string(this.state, myqueue, false);
   8278             }
   8279             if (mystr === this.state.tmp.last_primary_names_string) {
   8280                 if (this.item["suppress-author"] || (this.state[this.state.tmp.area].opt.collapse && this.state[this.state.tmp.area].opt.collapse.length)) {
   8281                     this.state.tmp.name_node.top.blobs.pop();
   8282                     this.state.tmp.name_node.children = [];
   8283                     this.state.tmp.offset_characters = oldchars;
   8284                 }
   8285                 if (this.state[this.state.tmp.area].opt.cite_group_delimiter && this.state[this.state.tmp.area].opt.cite_group_delimiter) {
   8286                     this.state.tmp.use_cite_group_delimiter = true;
   8287                 }
   8288             } else {
   8289                 this.state.tmp.last_primary_names_string = mystr;
   8290                 if (this.variables.indexOf(this._first_creator_variable) > -1 && this.item && this.item["suppress-author"] && this.Item.type !== "legal_case") {
   8291                     this.state.tmp.name_node.top.blobs.pop();
   8292                     this.state.tmp.name_node.children = [];
   8293                     this.state.tmp.offset_characters = oldchars;
   8294                     this.state.tmp.term_predecessor = false;
   8295                 }
   8296                 this.state.tmp.have_collapsed = false;
   8297                 if (this.state[this.state.tmp.area].opt.cite_group_delimiter && this.state[this.state.tmp.area].opt.cite_group_delimiter) {
   8298                     this.state.tmp.use_cite_group_delimiter = false;
   8299                 }
   8300             }
   8301         }
   8302     }
   8303 };
   8304 CSL.NameOutput.prototype.isPerson = function (value) {
   8305     if (value.literal
   8306         || (!value.given && value.family && value.isInstitution)) {
   8307         return false;
   8308     } else {
   8309         return true;
   8310     }
   8311 };
   8312 CSL.NameOutput.prototype.truncatePersonalNameLists = function () {
   8313     var v, i, ilen, j, jlen, chopvar, values;
   8314     this.freeters_count = {};
   8315     this.persons_count = {};
   8316     this.institutions_count = {};
   8317     for (v in this.freeters) {
   8318         if (this.freeters.hasOwnProperty(v)) {
   8319             this.freeters_count[v] = this.freeters[v].length;
   8320             this.freeters[v] = this._truncateNameList(this.freeters, v);
   8321         }
   8322     }
   8323     for (v in this.persons) {
   8324         if (this.persons.hasOwnProperty(v)) {
   8325             this.institutions_count[v] = this.institutions[v].length;
   8326             this._truncateNameList(this.institutions, v);
   8327             this.persons[v] = this.persons[v].slice(0, this.institutions[v].length);
   8328             this.persons_count[v] = [];
   8329             for (j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8330                 this.persons_count[v][j] = this.persons[v][j].length;
   8331                 this.persons[v][j] = this._truncateNameList(this.persons, v, j);
   8332             }
   8333         }
   8334     }
   8335     if (this.etal_min === 1 && this.etal_use_first === 1 
   8336         && !(this.state.tmp.extension
   8337              || this.state.tmp.just_looking)) {
   8338         chopvar = v;
   8339     } else {
   8340         chopvar = false;
   8341     }
   8342     if (chopvar || this._please_chop) {
   8343         for (i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8344             v = this.variables[i];
   8345             if (this.freeters[v].length) {
   8346                 if (this._please_chop === v) {
   8347                     this.freeters[v] = this.freeters[v].slice(1);
   8348                     this.freeters_count[v] += -1;
   8349                     this._please_chop = false;
   8350                 } else if (chopvar && !this._please_chop) {
   8351                     this.freeters[v] = this.freeters[v].slice(0, 1);
   8352                     this.freeters_count[v] = 1;
   8353                     this.institutions[v] = [];
   8354                     this.persons[v] = [];
   8355                     this._please_chop = chopvar;
   8356                 }
   8357             }
   8358             for (var j=0,jlen = this.persons[v].length;j<jlen;j++) {
   8359                 if (this.persons[v][j].length) {
   8360                     if (this._please_chop === v) {
   8361                         this.persons[v][j] = this.persons[v][j].slice(1);
   8362                         this.persons_count[v][j] += -1;
   8363                         this._please_chop = false;
   8364                         break;
   8365                     } else if (chopvar && !this._please_chop) {
   8366                         this.freeters[v] = this.persons[v][j].slice(0, 1);
   8367                         this.freeters_count[v] = 1;
   8368                         this.institutions[v] = [];
   8369                         this.persons[v] = [];
   8370                         values = [];
   8371                         this._please_chop = chopvar;
   8372                         break;
   8373                     }
   8374                 }
   8375             }
   8376             if (this.institutions[v].length) {
   8377                 if (this._please_chop === v) {
   8378                     this.institutions[v] = this.institutions[v].slice(1);
   8379                     this.institutions_count[v] += -1;
   8380                     this._please_chop = false;
   8381                 } else if (chopvar && !this._please_chop) {
   8382                     this.institutions[v] = this.institutions[v].slice(0, 1);
   8383                     this.institutions_count[v] = 1;
   8384                     values = [];
   8385                     this._please_chop = chopvar;
   8386                 }
   8387             }
   8388         }
   8389     }
   8390     for (i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8391         if (this.institutions[v].length) {
   8392             this.nameset_offset += 1;
   8393         }
   8394         for (var j=0,jlen=this.persons[v].length;j<jlen;j++) {
   8395             if (this.persons[v][j].length) {
   8396                 this.nameset_offset += 1;
   8397             }
   8398         }
   8399     }
   8400 };
   8401 CSL.NameOutput.prototype._truncateNameList = function (container, variable, index) {
   8402     var lst;
   8403     if ("undefined" === typeof index) {
   8404         lst = container[variable];
   8405     } else {
   8406         lst = container[variable][index];
   8407     }
   8408     if (this.state[this.state[this.state.tmp.area].root].opt.max_number_of_names 
   8409         && lst.length > 50 
   8410         && lst.length > (this.state[this.state[this.state.tmp.area].root].opt.max_number_of_names + 2)) {
   8411         var limit = this.state[this.state[this.state.tmp.area].root].opt.max_number_of_names;
   8412         lst = lst.slice(0, limit+1).concat(lst.slice(-1));
   8413     }
   8414     return lst;
   8415 };
   8416 CSL.NameOutput.prototype.divideAndTransliterateNames = function () {
   8417     var i, ilen, j, jlen;
   8418     var Item = this.Item;
   8419     var variables = this.variables;
   8420     this.varnames = variables.slice();
   8421     this.freeters = {};
   8422     this.persons = {};
   8423     this.institutions = {};
   8424     for (i = 0, ilen = variables.length; i < ilen; i += 1) {
   8425         var v = variables[i];
   8426         this.variable_offset[v] = this.nameset_offset;
   8427         var values = this._normalizeVariableValue(Item, v);
   8428         if (this.name.strings["suppress-min"] && values.length >= this.name.strings["suppress-min"]) {
   8429             values = [];
   8430         }
   8431         if (this.name.strings["suppress-max"] && values.length <= this.name.strings["suppress-max"]) {
   8432             values = [];
   8433         }
   8434         this._getFreeters(v, values);
   8435         this._getPersonsAndInstitutions(v, values);
   8436         if (this.state.opt.development_extensions.spoof_institutional_affiliations) {
   8437             if (this.name.strings["suppress-min"] === 0) {
   8438                 this.freeters[v] = [];
   8439                 for (j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8440                     this.persons[v][j] = [];
   8441                 }
   8442             } else if (this.institution.strings["suppress-min"] === 0) {
   8443                 this.institutions[v] = [];
   8444                 this.freeters[v] = this.freeters[v].concat(this.persons[v]);
   8445                 for (j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8446                     for (var k = 0, klen = this.persons[v][j].length; k < klen; k += 1) {
   8447                         this.freeters[v].push(this.persons[v][j][k]);
   8448                     }
   8449                 }
   8450                 this.persons[v] = [];
   8451             }
   8452         }
   8453     }
   8454 };
   8455 CSL.NameOutput.prototype._normalizeVariableValue = function (Item, variable) {
   8456     var names, name, i, ilen;
   8457     if ("string" === typeof Item[variable] || "number" === typeof Item[variable]) {
   8458         CSL.debug("name variable \"" + variable + "\" is string or number, not array. Attempting to fix.");
   8459         names = [{literal: Item[variable] + ""}];
   8460     } else if (!Item[variable]) {
   8461         names = [];
   8462     } else if ("number" !== typeof Item[variable].length) {
   8463         CSL.debug("name variable \"" + variable + "\" is object, not array. Attempting to fix.");
   8464         Item[variable] = [Item[variable]];
   8465         names = Item[variable].slice();
   8466     } else {
   8467         names = Item[variable].slice();
   8468     }
   8469     return names;
   8470 };
   8471 CSL.NameOutput.prototype._getFreeters = function (v, values) {
   8472     this.freeters[v] = [];
   8473     if (this.state.opt.development_extensions.spoof_institutional_affiliations) {
   8474         for (var i=values.length-1;i>-1;i--) {
   8475             if (this.isPerson(values[i])) {
   8476                 var value = this._checkNickname(values.pop());
   8477                 if (value) {
   8478                     this.freeters[v].push(value);
   8479                 }
   8480             } else {
   8481                 break;
   8482             }
   8483         }
   8484     } else {
   8485         for (var i=values.length-1;i>-1;i--) {
   8486             var value = values.pop();
   8487             if (this.isPerson(value)) {
   8488                 var value = this._checkNickname(value);
   8489             }
   8490             this.freeters[v].push(value);
   8491         }
   8492     }
   8493     this.freeters[v].reverse();
   8494     if (this.freeters[v].length) {
   8495         this.nameset_offset += 1;
   8496     }
   8497 };
   8498 CSL.NameOutput.prototype._getPersonsAndInstitutions = function (v, values) {
   8499     this.persons[v] = [];
   8500     this.institutions[v] = [];
   8501     if (!this.state.opt.development_extensions.spoof_institutional_affiliations) return;
   8502     var persons = [];
   8503     var has_affiliates = false;
   8504     var first = true;
   8505     for (var i = values.length - 1; i > -1; i += -1) {
   8506         if (this.isPerson(values[i])) {
   8507             var value = this._checkNickname(values[i]);
   8508             if (value) {
   8509                 persons.push(value);
   8510             }
   8511         } else {
   8512             has_affiliates = true;
   8513             this.institutions[v].push(values[i]);
   8514             if (!first) {
   8515                 persons.reverse();
   8516                 this.persons[v].push(persons);
   8517                 persons = [];
   8518             }
   8519             first = false;
   8520         }
   8521     }
   8522     if (has_affiliates) {
   8523         persons.reverse();
   8524         this.persons[v].push(persons);
   8525         this.persons[v].reverse();
   8526         this.institutions[v].reverse();
   8527     }
   8528 };
   8529 CSL.NameOutput.prototype._clearValues = function (values) {
   8530     for (var i = values.length - 1; i > -1; i += -1) {
   8531         values.pop();
   8532     }
   8533 };
   8534 CSL.NameOutput.prototype._checkNickname = function (name) {
   8535     if (["interview", "personal_communication"].indexOf(this.Item.type) > -1) {
   8536         var author = "";
   8537         author = CSL.Util.Names.getRawName(name);
   8538         if (author && this.state.sys.getAbbreviation && !(this.item && this.item["suppress-author"])) {
   8539             var normalizedKey = author;
   8540             if (this.state.sys.normalizeAbbrevsKey) {
   8541                 normalizedKey = this.state.sys.normalizeAbbrevsKey("author", author);
   8542             }
   8543             this.state.transform.loadAbbreviation("default", "nickname", normalizedKey);
   8544             var myLocalName = this.state.transform.abbrevs["default"].nickname[normalizedKey];
   8545             if (myLocalName) {
   8546                 if (myLocalName === "!here>>>") {
   8547                     name = false;
   8548                 } else {
   8549                     name = {family:myLocalName,given:''};
   8550                 }
   8551             }
   8552         }
   8553     }
   8554     return name;
   8555 };
   8556 CSL.NameOutput.prototype.joinPersons = function (blobs, pos, j, tokenname) {
   8557     var ret;
   8558     if (!tokenname) {
   8559         tokenname = "name";
   8560     }
   8561     if ("undefined" === typeof j) {
   8562         if (this.etal_spec[pos].freeters === 1) {
   8563            ret = this._joinEtAl(blobs, tokenname);
   8564         } else if (this.etal_spec[pos].freeters === 2) {
   8565             ret = this._joinEllipsis(blobs, tokenname);
   8566         } else if (!this.state.tmp.sort_key_flag) {
   8567             ret = this._joinAnd(blobs, tokenname);
   8568         } else {
   8569             ret = this._join(blobs, " ");
   8570         }
   8571     } else {
   8572         if (this.etal_spec[pos].persons[j] === 1) {
   8573             ret = this._joinEtAl(blobs, tokenname);
   8574         } else if (this.etal_spec[pos].persons[j] === 2) {
   8575             ret = this._joinEllipsis(blobs, tokenname);
   8576         } else if (!this.state.tmp.sort_key_flag) {
   8577             ret = this._joinAnd(blobs, tokenname);
   8578         } else {
   8579             ret = this._join(blobs, " ");
   8580         }
   8581     }
   8582     return ret;
   8583 };
   8584 CSL.NameOutput.prototype.joinInstitutionSets = function (blobs, pos) {
   8585     var ret;
   8586     if (this.etal_spec[pos].institutions === 1) {
   8587         ret = this._joinEtAl(blobs, "institution");
   8588     } else if (this.etal_spec[pos].institutions === 2) {
   8589         ret = this._joinEllipsis(blobs, "institution");
   8590     } else {
   8591         ret = this._joinAnd(blobs, "institution");
   8592     }
   8593     return ret;
   8594 };
   8595 CSL.NameOutput.prototype.joinPersonsAndInstitutions = function (blobs) {
   8596     return this._join(blobs, this.state.tmp.name_delimiter);
   8597 };
   8598 CSL.NameOutput.prototype.joinFreetersAndInstitutionSets = function (blobs) {
   8599     var ret = this._join(blobs, "[never here]", this["with"].single, this["with"].multiple);
   8600     return ret;
   8601 };
   8602 CSL.NameOutput.prototype._joinEtAl = function (blobs, tokenname) {
   8603     var blob = this._join(blobs, this.state.tmp.name_delimiter);
   8604     this.state.output.openLevel(this._getToken(tokenname));
   8605     this.state.output.current.value().strings.delimiter = "";
   8606     this.state.output.append(blob, "literal", true);
   8607     if (blobs.length > 1) {
   8608         this.state.output.append(this["et-al"].multiple, "literal", true);
   8609     } else if (blobs.length === 1) {
   8610         this.state.output.append(this["et-al"].single, "literal", true);
   8611     }
   8612     this.state.output.closeLevel();
   8613     return this.state.output.pop();
   8614 };
   8615 CSL.NameOutput.prototype._joinEllipsis = function (blobs, tokenname) {
   8616     return this._join(blobs, this.state.tmp.name_delimiter, this.name.ellipsis.single, this.name.ellipsis.multiple, tokenname);
   8617 };
   8618 CSL.NameOutput.prototype._joinAnd = function (blobs, tokenname) {
   8619     return this._join(blobs, this.state.inheritOpt(this[tokenname], "delimiter", (tokenname + "-delimiter"), ", "), this[tokenname].and.single, this[tokenname].and.multiple, tokenname);
   8620 };
   8621 CSL.NameOutput.prototype._join = function (blobs, delimiter, single, multiple, tokenname) {
   8622     var i, ilen;
   8623     if (!blobs) {
   8624         return false;
   8625     }
   8626     for (i = blobs.length - 1; i > -1; i += -1) {
   8627         if (!blobs[i] || blobs[i].length === 0 || !blobs[i].blobs.length) {
   8628             blobs = blobs.slice(0, i).concat(blobs.slice(i + 1));
   8629         }
   8630     }
   8631     if (!blobs.length) {
   8632         return false;
   8633     } else if (single && blobs.length === 2) {
   8634         if (single) {
   8635             single = new CSL.Blob(single.blobs,single);
   8636         }
   8637         blobs = [blobs[0], single, blobs[1]];
   8638     } else {
   8639         var delimiter_offset;
   8640         if (multiple) {
   8641             delimiter_offset = 2;
   8642         } else {
   8643             delimiter_offset = 1;
   8644         }
   8645         for (i = 0, ilen = blobs.length - delimiter_offset; i < ilen; i += 1) {
   8646             blobs[i].strings.suffix += delimiter;
   8647         }
   8648         if (blobs.length > 1) {
   8649             var blob = blobs.pop();
   8650             if (multiple) {
   8651                 multiple = new CSL.Blob(multiple.blobs,multiple);
   8652                 blobs.push(multiple);
   8653             } else {
   8654                 if (single) {
   8655                     single = new CSL.Blob(single.blobs,single);
   8656                 }
   8657                 blobs.push(single);
   8658             }
   8659             blobs.push(blob);
   8660         }
   8661     }
   8662     this.state.output.openLevel();
   8663     if (single && multiple) {
   8664         this.state.output.current.value().strings.delimiter = "";
   8665     }
   8666     for (i = 0, ilen = blobs.length; i < ilen; i += 1) {
   8667         this.state.output.append(blobs[i], false, true);
   8668     }
   8669     this.state.output.closeLevel();
   8670     return this.state.output.pop();
   8671 };
   8672 CSL.NameOutput.prototype._getToken = function (tokenname) {
   8673     var token = this[tokenname];
   8674     if (tokenname === "institution") {
   8675         var newtoken = new CSL.Token();
   8676         return newtoken;
   8677     }
   8678     return token;
   8679 };
   8680 CSL.NameOutput.prototype.setCommonTerm = function () {
   8681     var variables = this.variables;
   8682     var varnames = variables.slice();
   8683     varnames.sort();
   8684     this.common_term = varnames.join("");
   8685     if (!this.common_term) {
   8686         return false;
   8687     }
   8688     var has_term = false;
   8689     if (this.label && this.label[this.variables[0]]) {
   8690         if (this.label[this.variables[0]].before) {
   8691             has_term = this.state.getTerm(this.common_term, this.label[this.variables[0]].before.strings.form, 0);
   8692         } else if (this.label[this.variables[0]].after) {
   8693             has_term = this.state.getTerm(this.common_term, this.label[this.variables[0]].after.strings.form, 0);
   8694         }
   8695     }
   8696     if (!this.state.locale[this.state.opt.lang].terms[this.common_term]
   8697         || !has_term
   8698         || this.variables.length < 2) {
   8699         this.common_term = false;
   8700         return;
   8701     }
   8702     var freeters_offset = 0;
   8703     for (var i = 0, ilen = this.variables.length - 1; i < ilen; i += 1) {
   8704         var v = this.variables[i];
   8705         var vv = this.variables[i + 1];
   8706         if (this.freeters[v].length || this.freeters[vv].length) {
   8707             if (this.etal_spec[v].freeters !== this.etal_spec[vv].freeters
   8708                 || !this._compareNamesets(this.freeters[v], this.freeters[vv])) {
   8709                 this.common_term = false;
   8710                 return;
   8711             }
   8712             freeters_offset += 1;
   8713         }
   8714         if (this.persons[v].length !== this.persons[vv].length) {
   8715             this.common_term = false;
   8716             return;
   8717         }
   8718         for (var j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8719             if (this.etal_spec[v].persons[j] !== this.etal_spec[vv].persons[j]
   8720                 || !this._compareNamesets(this.persons[v][j], this.persons[vv][j])) {
   8721                 this.common_term = false;
   8722                 return;
   8723             }
   8724         }
   8725     }
   8726 };
   8727 CSL.NameOutput.prototype._compareNamesets = function (base_nameset, nameset) {
   8728     if (base_nameset.length !== nameset.length) {
   8729         return false;
   8730     }
   8731     for (var i = 0, ilen = nameset.length; i < ilen; i += 1) {
   8732         var name = nameset[i];
   8733         for (var j = 0, jlen = CSL.NAME_PARTS.length; j < jlen; j += 1) {
   8734             var part = CSL.NAME_PARTS[j];
   8735             if (!base_nameset[i] || base_nameset[i][part] != nameset[i][part]) {
   8736                 return false;
   8737             }
   8738         }
   8739     }
   8740     return true;
   8741 };
   8742 CSL.NameOutput.prototype.constrainNames = function () {
   8743     this.names_count = 0;
   8744     var pos;
   8745     for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8746         var v = this.variables[i];
   8747         pos = this.nameset_base + i;
   8748         if (this.freeters[v].length) {
   8749             this.state.tmp.names_max.push(this.freeters[v].length, "literal");
   8750             this._imposeNameConstraints(this.freeters, this.freeters_count, v, pos);
   8751             this.names_count += this.freeters[v].length;
   8752         }
   8753         if (this.institutions[v].length) {
   8754             this.state.tmp.names_max.push(this.institutions[v].length, "literal");
   8755             this._imposeNameConstraints(this.institutions, this.institutions_count, v, pos);
   8756             this.persons[v] = this.persons[v].slice(0, this.institutions[v].length);
   8757             this.names_count += this.institutions[v].length;
   8758         }
   8759         for (var j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8760             if (this.persons[v][j].length) {
   8761                 this.state.tmp.names_max.push(this.persons[v][j].length, "literal");
   8762                 this._imposeNameConstraints(this.persons[v], this.persons_count[v], j, pos);
   8763                 this.names_count += this.persons[v][j].length;
   8764             }
   8765         }
   8766     }
   8767 };
   8768 CSL.NameOutput.prototype._imposeNameConstraints = function (lst, count, key, pos) {
   8769     var display_names = lst[key];
   8770     var discretionary_names_length = this.state.tmp["et-al-min"];
   8771     if (this.state.tmp.suppress_decorations) {
   8772         if (this.state.tmp.disambig_request && this.state.tmp.disambig_request.names[pos]) {
   8773             discretionary_names_length = this.state.tmp.disambig_request.names[pos];
   8774         } else if (count[key] >= this.etal_min) {
   8775             discretionary_names_length = this.etal_use_first;
   8776         }
   8777     } else {
   8778         if (this.state.tmp.disambig_request 
   8779             && this.state.tmp.disambig_request.names[pos] > this.etal_use_first) {
   8780             if (count[key] < this.etal_min) {
   8781                 discretionary_names_length = count[key];
   8782             } else {
   8783                 discretionary_names_length = this.state.tmp.disambig_request.names[pos];
   8784             }
   8785         } else if (count[key] >= this.etal_min) {
   8786             discretionary_names_length = this.etal_use_first;
   8787         }
   8788         if (this.etal_use_last && discretionary_names_length > (this.etal_min - 2)) {
   8789             discretionary_names_length = this.etal_min - 2;
   8790         }
   8791     }
   8792     var sane = this.etal_min >= this.etal_use_first;
   8793     var overlength = count[key] > discretionary_names_length;
   8794     if (discretionary_names_length > count[key]) {
   8795         discretionary_names_length = display_names.length;
   8796     }
   8797     if (sane && overlength) {
   8798         if (this.etal_use_last) {
   8799             lst[key] = display_names.slice(0, discretionary_names_length).concat(display_names.slice(-1));
   8800         } else {
   8801             lst[key] = display_names.slice(0, discretionary_names_length);
   8802         }
   8803     }
   8804     this.state.tmp.disambig_settings.names[pos] = lst[key].length;
   8805     this.state.disambiguate.padBase(this.state.tmp.disambig_settings);
   8806 };
   8807 CSL.NameOutput.prototype.disambigNames = function () {
   8808     var pos;
   8809     for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8810         var v = this.variables[i];
   8811         pos = this.nameset_base + i;
   8812         if (this.freeters[v].length) {
   8813             this._runDisambigNames(this.freeters[v], pos);
   8814         }
   8815         if (this.institutions[v].length) {
   8816             if ("undefined" === typeof this.state.tmp.disambig_settings.givens[pos]) {
   8817                 this.state.tmp.disambig_settings.givens[pos] = [];
   8818             }
   8819             for (var j=0,jlen=this.institutions[v].length;j<jlen;j+=1) {
   8820                 if ("undefined" === typeof this.state.tmp.disambig_settings.givens[pos][j]) {
   8821                     this.state.tmp.disambig_settings.givens[pos].push(2);
   8822                 }
   8823             }
   8824         }
   8825         for (var j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8826             if (this.persons[v][j].length) {
   8827                 this._runDisambigNames(this.persons[v][j], pos);
   8828             }
   8829         }
   8830     }
   8831 };
   8832 CSL.NameOutput.prototype._runDisambigNames = function (lst, pos) {
   8833     var chk, myform, myinitials, param, i, ilen, paramx;
   8834     for (i = 0, ilen = lst.length; i < ilen; i += 1) {
   8835         if (!lst[i].given && !lst[i].family) {
   8836             continue;
   8837         }
   8838         myinitials = this.state.inheritOpt(this.name, "initialize-with");
   8839         this.state.registry.namereg.addname("" + this.Item.id, lst[i], i);
   8840         chk = this.state.tmp.disambig_settings.givens[pos];
   8841         if ("undefined" === typeof chk) {
   8842             for (var j = 0, jlen = pos + 1; j < jlen; j += 1) {
   8843                 if (!this.state.tmp.disambig_settings.givens[j]) {
   8844                     this.state.tmp.disambig_settings.givens[j] = [];
   8845                 }
   8846             }
   8847         }
   8848         chk = this.state.tmp.disambig_settings.givens[pos][i];
   8849         if ("undefined" === typeof chk) {
   8850             myform = this.state.inheritOpt(this.name, "form", "name-form", "long");
   8851             param = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, 0, myform, myinitials);
   8852             this.state.tmp.disambig_settings.givens[pos].push(param);
   8853         }
   8854         myform = this.state.inheritOpt(this.name, "form", "name-form", "long");
   8855         paramx = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, 0, myform, myinitials);
   8856         if (this.state.tmp.disambig_request) {
   8857             var val = this.state.tmp.disambig_settings.givens[pos][i];
   8858             if (val === 1 && 
   8859                 this.state.citation.opt["givenname-disambiguation-rule"] === "by-cite" && 
   8860                 ("undefined" === typeof this.state.inheritOpt(this.name, "initialize-with")
   8861                  || "undefined" === typeof lst[i].given)) {
   8862                 val = 2;
   8863             }
   8864             param = val;
   8865             if (this.state.opt["disambiguate-add-givenname"] && lst[i].given) {
   8866                 param = this.state.registry.namereg.evalname("" + this.Item.id, lst[i], i, param, this.state.inheritOpt(this.name, "form", "name-form", "long"), this.state.inheritOpt(this.name, "initialize-with"));
   8867             }
   8868         } else {
   8869             param = paramx;
   8870         }
   8871         if (!this.state.tmp.just_looking && this.item && this.item.position === CSL.POSITION_FIRST) {
   8872             if (paramx > param) {
   8873                 param = paramx;
   8874             }
   8875         }
   8876         if (!this.state.tmp.sort_key_flag) {
   8877             this.state.tmp.disambig_settings.givens[pos][i] = param;
   8878             if ("string" === typeof myinitials
   8879                 && ("undefined" === typeof this.name.strings["initialize"]
   8880                     || true === this.name.strings["initialize"])) {
   8881                 this.state.tmp.disambig_settings.use_initials = true;
   8882             }
   8883         }
   8884     }
   8885 };
   8886 CSL.NameOutput.prototype.getEtAlConfig = function () {
   8887     var item = this.item;
   8888     this["et-al"] = {};
   8889     this.state.output.append(this.etal_term, this.etal_style, true);
   8890     this["et-al"].single = this.state.output.pop();
   8891     this["et-al"].single.strings.suffix = this.etal_suffix;
   8892     this["et-al"].single.strings.prefix = this.etal_prefix_single;
   8893     this.state.output.append(this.etal_term, this.etal_style, true);
   8894     this["et-al"].multiple = this.state.output.pop();
   8895     this["et-al"].multiple.strings.suffix = this.etal_suffix;
   8896     this["et-al"].multiple.strings.prefix = this.etal_prefix_multiple;
   8897     if ("undefined" === typeof item) {
   8898         item = {};
   8899     }
   8900     if (item.position) {
   8901         if (this.state.inheritOpt(this.name, "et-al-subsequent-min")) {
   8902             this.etal_min = this.state.inheritOpt(this.name, "et-al-subsequent-min");
   8903         } else {
   8904             this.etal_min = this.state.inheritOpt(this.name, "et-al-min");
   8905         }
   8906         if (this.state.inheritOpt(this.name, "et-al-subsequent-use-first")) {
   8907             this.etal_use_first = this.state.inheritOpt(this.name, "et-al-subsequent-use-first");
   8908         } else {
   8909             this.etal_use_first = this.state.inheritOpt(this.name, "et-al-use-first");
   8910         }
   8911     } else {
   8912         if (this.state.tmp["et-al-min"]) {
   8913             this.etal_min = this.state.tmp["et-al-min"];
   8914         } else {
   8915             this.etal_min = this.state.inheritOpt(this.name, "et-al-min");
   8916         }
   8917         if (this.state.tmp["et-al-use-first"]) {
   8918             this.etal_use_first = this.state.tmp["et-al-use-first"];
   8919         } else {
   8920             this.etal_use_first = this.state.inheritOpt(this.name, "et-al-use-first");
   8921         }
   8922         if ("boolean" === typeof this.state.tmp["et-al-use-last"]) {
   8923             this.etal_use_last = this.state.tmp["et-al-use-last"];
   8924         } else {
   8925             this.etal_use_last = this.state.inheritOpt(this.name, "et-al-use-last");
   8926         }
   8927     }
   8928     if (!this.state.tmp["et-al-min"]) {
   8929         this.state.tmp["et-al-min"] = this.etal_min;
   8930     }
   8931 };
   8932 CSL.NameOutput.prototype.setEtAlParameters = function () {
   8933     var i, ilen, j, jlen;
   8934     for (i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8935         var v = this.variables[i];
   8936         if ("undefined" === typeof this.etal_spec[v]) {
   8937             this.etal_spec[v] = {freeters:0,institutions:0,persons:[]};
   8938         }
   8939         this.etal_spec[this.nameset_base + i] = this.etal_spec[v];
   8940         if (this.freeters[v].length) {
   8941             this._setEtAlParameter("freeters", v);
   8942         }
   8943         for (j = 0, jlen = this.persons[v].length; j < jlen; j += 1) {
   8944             if ("undefined" === typeof this.etal_spec[v][j]) {
   8945                 this.etal_spec[v].persons[j] = 0;
   8946             }
   8947             this._setEtAlParameter("persons", v, j);
   8948         }
   8949         if (this.institutions[v].length) {
   8950             this._setEtAlParameter("institutions", v);
   8951         }
   8952     }
   8953 };
   8954 CSL.NameOutput.prototype._setEtAlParameter = function (type, v, j) {
   8955     var lst, count;
   8956     if (type === "persons") {
   8957         lst = this.persons[v][j];
   8958         count = this.persons_count[v][j];
   8959     } else {
   8960         lst = this[type][v];
   8961         count = this[type + "_count"][v];
   8962     }
   8963     if (lst.length < count && !this.state.tmp.sort_key_flag) {
   8964         if (this.etal_use_last) {
   8965             if (type === "persons") {
   8966                 this.etal_spec[v].persons[j] = 2
   8967             } else {
   8968                 this.etal_spec[v][type] = 2;
   8969             }
   8970         } else {
   8971             if (type === "persons") {
   8972                 this.etal_spec[v].persons[j] = 1;
   8973             } else {
   8974                 this.etal_spec[v][type] = 1;
   8975             }
   8976         }
   8977     } else {
   8978         if (type === "persons") {
   8979             this.etal_spec[v].persons[j] = 0;
   8980         } else {
   8981             this.etal_spec[v][type] = 0;
   8982         }
   8983     }
   8984 };
   8985 CSL.NameOutput.prototype.renderAllNames = function () {
   8986     var pos;
   8987     for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   8988         var v = this.variables[i];
   8989         if (this.freeters[v].length || this.institutions[v].length) {
   8990             if (!this.state.tmp.group_context.tip.condition) {
   8991                 this.state.tmp.just_did_number = false;
   8992             }
   8993         }
   8994         pos = this.nameset_base + i;
   8995         if (this.freeters[v].length) {
   8996             this.freeters[v] = this._renderNames(v, this.freeters[v], pos);
   8997         }
   8998         for (var j = 0, jlen = this.institutions[v].length; j < jlen; j += 1) {
   8999             this.persons[v][j] = this._renderNames(v, this.persons[v][j], pos, j);
   9000         }
   9001     }
   9002     this.renderInstitutionNames();
   9003 };
   9004 CSL.NameOutput.prototype.renderInstitutionNames = function () {
   9005     for (var i = 0, ilen = this.variables.length; i < ilen; i += 1) {
   9006         var v = this.variables[i];
   9007         for (var j = 0, jlen = this.institutions[v].length; j < jlen; j += 1) {
   9008             var institution, institution_short, institution_long, short_style, long_style;
   9009             var name = this.institutions[v][j];
   9010             var j, ret, optLangTag, jlen, key, localesets;
   9011             if (this.state.tmp.extension) {
   9012                 localesets = ["sort"];
   9013             } else if (name.isInstitution || name.literal) {
   9014                 localesets = this.state.opt['cite-lang-prefs'].institutions;
   9015             } else {
   9016                 localesets = this.state.opt['cite-lang-prefs'].persons;
   9017             }
   9018             var slot = {primary:'locale-orig',secondary:false,tertiary:false};
   9019 	        if (localesets) {
   9020 		        var slotnames = ["primary", "secondary", "tertiary"];
   9021 		        for (var k = 0, klen = slotnames.length; k < klen; k += 1) {
   9022 			        if (localesets.length - 1 <  k) {
   9023 				        break;
   9024 			        }
   9025                     if (localesets[k]) {
   9026 			            slot[slotnames[k]] = 'locale-' + localesets[k];
   9027                     }
   9028 		        }
   9029 	        } else {
   9030 		        slot.primary = 'locale-translat';
   9031 	        }
   9032 	        if (this.state.tmp.area !== "bibliography"
   9033 		        && !(this.state.tmp.area === "citation"
   9034 			         && this.state.opt.xclass === "note"
   9035 			         && this.item && !this.item.position)) {
   9036 		        slot.secondary = false;
   9037 		        slot.tertiary = false;
   9038 	        }
   9039             var res;
   9040             this.setRenderedName(name);
   9041             var institution = this._renderInstitutionName(v, name, slot, j);
   9042             this.institutions[v][j] = institution;
   9043         }
   9044     }
   9045 }
   9046 CSL.NameOutput.prototype._renderInstitutionName = function (v, name, slot, j) {
   9047     var secondary, tertiary, long_style, short_style, institution, institution_short, institution_long;
   9048     var res = this.getName(name, slot.primary, true);
   9049     var primary = res.name;
   9050     var usedOrig = res.usedOrig;
   9051     if (primary) {
   9052         primary = this.fixupInstitution(primary, v, j);
   9053     }
   9054 	secondary = false;
   9055 	if (slot.secondary) {
   9056         res = this.getName(name, slot.secondary, false, usedOrig);
   9057         var secondary = res.name;
   9058         usedOrig = res.usedOrig;
   9059         if (secondary) {
   9060 			secondary = this.fixupInstitution(secondary, v, j);
   9061         }
   9062 	}
   9063 	tertiary = false;
   9064 	if (slot.tertiary) {
   9065         res = this.getName(name, slot.tertiary, false, usedOrig);
   9066         tertiary = res.name;
   9067         if (tertiary) {
   9068 			tertiary = this.fixupInstitution(tertiary, v, j);
   9069         }
   9070 	}
   9071     var n = {
   9072         l: {
   9073             pri: false,
   9074             sec: false,
   9075             ter: false
   9076         },
   9077         s: {
   9078             pri: false,
   9079             sec: false,
   9080             ter: false
   9081         }
   9082     };
   9083     if (primary) {
   9084         n.l.pri = primary["long"];
   9085         n.s.pri = primary["short"].length ? primary["short"] : primary["long"];
   9086     }
   9087     if (secondary) {
   9088         n.l.sec = secondary["long"];
   9089         n.s.sec = secondary["short"].length ? secondary["short"] : secondary["long"];
   9090     }
   9091     if (tertiary) {
   9092         n.l.ter = tertiary["long"];
   9093         n.s.ter = tertiary["short"].length ? tertiary["short"] : tertiary["long"];
   9094     }
   9095     switch (this.institution.strings["institution-parts"]) {
   9096     case "short":
   9097         if (primary["short"].length) {
   9098             short_style = this._getShortStyle();
   9099             institution = [this._composeOneInstitutionPart([n.s.pri, n.s.sec, n.s.ter], slot, short_style, v)];
   9100         } else {
   9101             long_style = this._getLongStyle(primary, v, j);
   9102             institution = [this._composeOneInstitutionPart([n.l.pri, n.l.sec, n.l.ter], slot, long_style, v)];
   9103         }
   9104         break;
   9105     case "short-long":
   9106         long_style = this._getLongStyle(primary, v, j);
   9107         short_style = this._getShortStyle();
   9108         institution_short = this._renderOneInstitutionPart(primary["short"], short_style);
   9109         institution_long = this._composeOneInstitutionPart([n.l.pri, n.l.sec, n.l.ter], slot, long_style, v);
   9110         institution = [institution_short, institution_long];
   9111         break;
   9112     case "long-short":
   9113         long_style = this._getLongStyle(primary, v, j);
   9114         short_style = this._getShortStyle();
   9115         institution_short = this._renderOneInstitutionPart(primary["short"], short_style);
   9116         institution_long = this._composeOneInstitutionPart([n.l.pri, n.l.sec, n.l.ter], slot, long_style, v);
   9117         institution = [institution_long, institution_short];
   9118         break;
   9119     default:
   9120         long_style = this._getLongStyle(primary, v, j);
   9121         institution = [this._composeOneInstitutionPart([n.l.pri, n.l.sec, n.l.ter], slot, long_style, v)];
   9122         break;
   9123     }
   9124     var blob = this._join(institution, " ");
   9125     this.state.tmp.name_node.children.push(blob);
   9126     return blob;
   9127 };
   9128 CSL.NameOutput.prototype._composeOneInstitutionPart = function (names, slot, style, v) {
   9129     var primary = false, secondary = false, tertiary = false, primary_tok, secondary_tok, tertiary_tok;
   9130     if (names[0]) {
   9131         primary_tok = CSL.Util.cloneToken(style);
   9132         if (this.state.opt.citeAffixes[slot.primary]){
   9133             if ("<i>" === this.state.opt.citeAffixes.institutions[slot.primary].prefix) {
   9134                 var hasItalic = false;
   9135                 for (var i = 0, ilen = primary_tok.decorations.length; i < ilen; i += 1) {
   9136                     if (style.decorations[i][0] === "@font-style"
   9137                         && primary_tok.decorations[i][1] === "italic") {
   9138                         hasItalic = true;
   9139                     }
   9140                 }
   9141                 if (!hasItalic) {
   9142                     primary_tok.decorations.push(["@font-style", "italic"])
   9143                 }
   9144             }
   9145         }
   9146         primary = this._renderOneInstitutionPart(names[0], primary_tok);
   9147      }
   9148     if (names[1]) {
   9149         secondary = this._renderOneInstitutionPart(names[1], style);
   9150     }
   9151     if (names[2]) {
   9152         tertiary = this._renderOneInstitutionPart(names[2], style);
   9153     }
   9154     var institutionblob;
   9155     if (secondary || tertiary) {
   9156         this.state.output.openLevel("empty");
   9157         this.state.output.append(primary);
   9158         secondary_tok = CSL.Util.cloneToken(style);
   9159         if (slot.secondary) {
   9160             secondary_tok.strings.prefix = this.state.opt.citeAffixes.institutions[slot.secondary].prefix;
   9161             secondary_tok.strings.suffix = this.state.opt.citeAffixes.institutions[slot.secondary].suffix;
   9162             if (!secondary_tok.strings.prefix) {
   9163                 secondary_tok.strings.prefix = " ";
   9164             }
   9165         }
   9166         var secondary_outer = new CSL.Token();
   9167         secondary_outer.decorations.push(["@font-style", "normal"]);
   9168         secondary_outer.decorations.push(["@font-weight", "normal"]);
   9169         this.state.output.openLevel(secondary_outer);
   9170         this.state.output.append(secondary, secondary_tok);
   9171         this.state.output.closeLevel();
   9172         tertiary_tok = CSL.Util.cloneToken(style);
   9173         if (slot.tertiary) {
   9174             tertiary_tok.strings.prefix = this.state.opt.citeAffixes.institutions[slot.tertiary].prefix;
   9175             tertiary_tok.strings.suffix = this.state.opt.citeAffixes.institutions[slot.tertiary].suffix;
   9176             if (!tertiary_tok.strings.prefix) {
   9177                 tertiary_tok.strings.prefix = " ";
   9178             }
   9179         }
   9180         var tertiary_outer = new CSL.Token();
   9181         tertiary_outer.decorations.push(["@font-style", "normal"]);
   9182         tertiary_outer.decorations.push(["@font-weight", "normal"]);
   9183         this.state.output.openLevel(tertiary_outer);
   9184         this.state.output.append(tertiary, tertiary_tok);
   9185         this.state.output.closeLevel();
   9186         this.state.output.closeLevel();
   9187         institutionblob = this.state.output.pop();
   9188     } else {
   9189         institutionblob = primary;
   9190     }
   9191     return institutionblob;
   9192 }
   9193 CSL.NameOutput.prototype._renderOneInstitutionPart = function (blobs, style) {
   9194     for (var i = 0, ilen = blobs.length; i < ilen; i += 1) {
   9195         if (blobs[i]) {
   9196             var str = blobs[i];
   9197             if (this.state.tmp.strip_periods) {
   9198                 str = str.replace(/\./g, "");
   9199             } else {
   9200                 for (var j = 0, jlen = style.decorations.length; j < jlen; j += 1) {
   9201                     if ("@strip-periods" === style.decorations[j][0] && "true" === style.decorations[j][1]) {
   9202                         str = str.replace(/\./g, "");
   9203                         break;
   9204                     }
   9205                 }
   9206             }
   9207             this.state.tmp.group_context.tip.variable_success = true;
   9208             this.state.tmp.can_substitute.replace(false, CSL.LITERAL);
   9209             if (str === "!here>>>") {
   9210                 blobs[i] = false;
   9211             } else {
   9212                 this.state.output.append(str, style, true);
   9213                 blobs[i] = this.state.output.pop();
   9214             }
   9215         }
   9216     }
   9217     if ("undefined" === typeof this.institution.strings["part-separator"]) {
   9218         this.institution.strings["part-separator"] = this.state.tmp.name_delimiter;
   9219     }
   9220     return this._join(blobs, this.institution.strings["part-separator"]);
   9221 };
   9222 CSL.NameOutput.prototype._renderNames = function (v, values, pos, j) {
   9223     var ret = false;
   9224     if (values.length) {
   9225         var names = [];
   9226         for (var i = 0, ilen = values.length; i < ilen; i += 1) {
   9227             var name = values[i];
   9228             var ret, optLangTag, jlen, key, localesets;
   9229             if (this.state.tmp.extension) {
   9230                 localesets = ["sort"];
   9231             } else if (name.isInstitution || name.literal) {
   9232                 localesets = this.state.opt['cite-lang-prefs'].institutions;
   9233             } else {
   9234                 localesets = this.state.opt['cite-lang-prefs'].persons;
   9235             }
   9236             var slot = {primary:'locale-orig',secondary:false,tertiary:false};
   9237 	        if (localesets) {
   9238 		        var slotnames = ["primary", "secondary", "tertiary"];
   9239 		        for (var k = 0, klen = slotnames.length; k < klen; k += 1) {
   9240 			        if (localesets.length - 1 <  k) {
   9241 				        break;
   9242 			        }
   9243 			        slot[slotnames[k]] = 'locale-' + localesets[k];
   9244 		        }
   9245 	        } else {
   9246 		        slot.primary = 'locale-translat';
   9247 	        }
   9248 	        if (this.state.tmp.sort_key_flag || (this.state.tmp.area !== "bibliography"
   9249 		        && !(this.state.tmp.area === "citation"
   9250 			         && this.state.opt.xclass === "note"
   9251 			         && this.item && !this.item.position))) {
   9252 		        slot.secondary = false;
   9253 		        slot.tertiary = false;
   9254 	        }
   9255             this.setRenderedName(name);
   9256             if (!name.literal && !name.isInstitution) {
   9257                 var nameBlob = this._renderPersonalName(v, name, slot, pos, i, j);
   9258                 var nameToken = CSL.Util.cloneToken(this.name);
   9259                 this.state.output.append(nameBlob, nameToken, true);
   9260                 names.push(this.state.output.pop());
   9261             } else {
   9262                 names.push(this._renderInstitutionName(v, name, slot, j));
   9263             }
   9264         }
   9265         ret = this.joinPersons(names, pos, j);
   9266     }
   9267     return ret
   9268 }
   9269 CSL.NameOutput.prototype._renderPersonalName = function (v, name, slot, pos, i, j) {
   9270     var res = this.getName(name, slot.primary, true);
   9271     var primary = this._renderOnePersonalName(res.name, pos, i, j);
   9272 	var secondary = false;
   9273 	if (slot.secondary) {
   9274         res = this.getName(name, slot.secondary, false, res.usedOrig);
   9275         if (res.name) {
   9276 			secondary = this._renderOnePersonalName(res.name, pos, i, j);
   9277         }
   9278 	}
   9279 	var tertiary = false;
   9280 	if (slot.tertiary) {
   9281         res = this.getName(name, slot.tertiary, false, res.usedOrig);
   9282         if (res.name) {
   9283 			tertiary = this._renderOnePersonalName(res.name, pos, i, j);
   9284         }
   9285 	}
   9286     var personblob;
   9287     if (secondary || tertiary) {
   9288         this.state.output.openLevel("empty");
   9289         this.state.output.append(primary);
   9290         var secondary_tok = new CSL.Token();
   9291         if (slot.secondary) {
   9292             secondary_tok.strings.prefix = this.state.opt.citeAffixes.persons[slot.secondary].prefix;
   9293             secondary_tok.strings.suffix = this.state.opt.citeAffixes.persons[slot.secondary].suffix;
   9294             if (!secondary_tok.strings.prefix) {
   9295                 secondary_tok.strings.prefix = " ";
   9296             }
   9297         }
   9298         this.state.output.append(secondary, secondary_tok);
   9299         var tertiary_tok = new CSL.Token();
   9300         if (slot.tertiary) {
   9301             tertiary_tok.strings.prefix = this.state.opt.citeAffixes.persons[slot.tertiary].prefix;
   9302             tertiary_tok.strings.suffix = this.state.opt.citeAffixes.persons[slot.tertiary].suffix;
   9303             if (!tertiary_tok.strings.prefix) {
   9304                 tertiary_tok.strings.prefix = " ";
   9305             }
   9306         }
   9307         this.state.output.append(tertiary, tertiary_tok);
   9308         this.state.output.closeLevel();
   9309         personblob = this.state.output.pop();
   9310     } else {
   9311         personblob = primary;
   9312     }
   9313     return personblob;
   9314 };
   9315 CSL.NameOutput.prototype._isRomanesque = function (name) {
   9316     var ret = 2;
   9317     if (!name.family.replace(/\"/g, '').match(CSL.ROMANESQUE_REGEXP)) {
   9318         ret = 0;
   9319     }
   9320     if (!ret && name.given && name.given.match(CSL.STARTSWITH_ROMANESQUE_REGEXP)) {
   9321         ret = 1;
   9322     }
   9323     if (ret == 2) {
   9324         if (name.multi && name.multi.main) {
   9325             var top_locale = name.multi.main.slice(0, 2);
   9326         } else if (this.Item.language) {
   9327             top_locale = this.Item.language.slice(0, 2);
   9328         }
   9329         if (["ja", "zh"].indexOf(top_locale) > -1) {
   9330             ret = 1;
   9331         }
   9332     }
   9333     return ret;
   9334 };
   9335 CSL.NameOutput.prototype._renderOnePersonalName = function (value, pos, i, j) {
   9336     var name = value;
   9337     var dropping_particle = this._droppingParticle(name, pos, j);
   9338     var family = this._familyName(name);
   9339     var non_dropping_particle = this._nonDroppingParticle(name);
   9340     var given = this._givenName(name, pos, i);
   9341     var suffix = this._nameSuffix(name);
   9342     if (given === false) {
   9343         dropping_particle = false;
   9344         suffix = false;
   9345     }
   9346     var sort_sep = this.state.inheritOpt(this.name, "sort-separator");
   9347     if (!sort_sep) {
   9348         sort_sep = "";
   9349     }
   9350     var suffix_sep;
   9351     if (name["comma-suffix"]) {
   9352         suffix_sep = ", ";
   9353     } else {
   9354         suffix_sep = " ";
   9355     }
   9356     var romanesque = this._isRomanesque(name);
   9357     function hasJoiningPunctuation(blob) {
   9358         if (!blob) {
   9359             return false;
   9360         } else if ("string" === typeof blob.blobs) {
   9361             if (["\u2019", "\'", "-", " "].indexOf(blob.blobs.slice(-1)) > -1) {
   9362                 return true;
   9363             } else {
   9364                 return false;
   9365             }
   9366         } else {
   9367             return hasJoiningPunctuation(blob.blobs[blob.blobs.length-1]);
   9368         }
   9369     }
   9370     var has_hyphenated_non_dropping_particle = hasJoiningPunctuation(non_dropping_particle);
   9371     var blob, merged, first, second;
   9372     if (romanesque === 0) {
   9373         blob = this._join([non_dropping_particle, family, given], "");
   9374     } else if (romanesque === 1 || name["static-ordering"]) { // entry likes sort order
   9375         blob = this._join([non_dropping_particle, family, given], " ");
   9376     } else if (name["reverse-ordering"]) { // entry likes reverse order
   9377         blob = this._join([given, non_dropping_particle, family], " ");
   9378     } else if (this.state.tmp.sort_key_flag) {
   9379         if (this.state.opt["demote-non-dropping-particle"] === "never") {
   9380             first = this._join([non_dropping_particle, family, dropping_particle], " ");
   9381             merged = this._join([first, given], this.state.opt.sort_sep);
   9382             blob = this._join([merged, suffix], " ");
   9383         } else {
   9384             second = this._join([given, dropping_particle, non_dropping_particle], " ");
   9385             merged = this._join([family, second], this.state.opt.sort_sep);
   9386             blob = this._join([merged, suffix], " ");
   9387         }
   9388     } else if (this.state.inheritOpt(this.name, "name-as-sort-order") === "all" || (this.state.inheritOpt(this.name, "name-as-sort-order") === "first" && i === 0 && (j === 0 || "undefined" === typeof j))) {
   9389         if (["Lord", "Lady"].indexOf(name.given) > -1) {
   9390             sort_sep = ", ";
   9391         }
   9392         if (["always", "display-and-sort"].indexOf(this.state.opt["demote-non-dropping-particle"]) > -1) {
   9393             second = this._join([given, dropping_particle], (name["comma-dropping-particle"] + " "));
   9394             second = this._join([second, non_dropping_particle], " ");
   9395             if (second && this.given) {
   9396                 second.strings.prefix = this.given.strings.prefix;
   9397                 second.strings.suffix = this.given.strings.suffix;
   9398             }
   9399             if (family && this.family) {
   9400                 family.strings.prefix = this.family.strings.prefix;
   9401                 family.strings.suffix = this.family.strings.suffix;
   9402             }
   9403             merged = this._join([family, second], sort_sep);
   9404             blob = this._join([merged, suffix], sort_sep);
   9405         } else {
   9406             if (has_hyphenated_non_dropping_particle) {
   9407                 first = this._join([non_dropping_particle, family], "");
   9408             } else {
   9409                 first = this._join([non_dropping_particle, family], " ");
   9410             }
   9411             if (first && this.family) {
   9412                 first.strings.prefix = this.family.strings.prefix;
   9413                 first.strings.suffix = this.family.strings.suffix;
   9414             }
   9415             second = this._join([given, dropping_particle], (name["comma-dropping-particle"] + " "));
   9416             if (second && this.given) {
   9417                 second.strings.prefix = this.given.strings.prefix;
   9418                 second.strings.suffix = this.given.strings.suffix;
   9419             }
   9420             merged = this._join([first, second], sort_sep);
   9421             blob = this._join([merged, suffix], sort_sep);
   9422         }
   9423     } else { // plain vanilla
   9424         if (name["dropping-particle"] && name.family && !name["non-dropping-particle"]) {
   9425             if (["'","\u02bc","\u2019","-"].indexOf(name["dropping-particle"].slice(-1)) > -1) {
   9426                 family = this._join([dropping_particle, family], "");
   9427                 dropping_particle = false;
   9428             }
   9429         }
   9430         if (!this.state.tmp.term_predecessor) {
   9431         }
   9432         var space = " ";
   9433         if (this.state.inheritOpt(this.name, "initialize-with")
   9434             && this.state.inheritOpt(this.name, "initialize-with").match(/[\u00a0\ufeff]/)
   9435             && ["fr", "ru", "cs"].indexOf(this.state.opt["default-locale"][0].slice(0, 2)) > -1) {
   9436             space = "\u00a0"
   9437         }
   9438         if (has_hyphenated_non_dropping_particle) {
   9439             second = this._join([non_dropping_particle, family], "");
   9440             second = this._join([dropping_particle, second], space);
   9441         } else {
   9442             second = this._join([dropping_particle, non_dropping_particle, family], space);
   9443         }
   9444         second = this._join([second, suffix], suffix_sep);
   9445         if (second && this.family) {
   9446             second.strings.prefix = this.family.strings.prefix;
   9447             second.strings.suffix = this.family.strings.suffix;
   9448         }
   9449         if (given && this.given) {
   9450             given.strings.prefix = this.given.strings.prefix;
   9451             given.strings.suffix = this.given.strings.suffix;
   9452         }
   9453         if (second.strings.prefix) {
   9454             name["comma-dropping-particle"] = "";
   9455         }
   9456         blob = this._join([given, second], (name["comma-dropping-particle"] + space));
   9457     }
   9458     this.state.tmp.group_context.tip.variable_success = true;
   9459     this.state.tmp.can_substitute.replace(false, CSL.LITERAL);
   9460     this.state.tmp.term_predecessor = true;
   9461     this.state.tmp.name_node.children.push(blob);
   9462     return blob;
   9463 };
   9464 CSL.NameOutput.prototype._normalizeNameInput = function (value) {
   9465     var name = {
   9466         literal:value.literal,
   9467         family:value.family,
   9468         isInstitution:value.isInstitution,
   9469         given:value.given,
   9470         suffix:value.suffix,
   9471         "comma-suffix":value["comma-suffix"],
   9472         "non-dropping-particle":value["non-dropping-particle"],
   9473         "dropping-particle":value["dropping-particle"],
   9474         "static-ordering":value["static-ordering"],
   9475         "static-particles":value["static-particles"],
   9476         "reverse-ordering":value["reverse-ordering"],
   9477         "full-form-always": value["full-form-always"],
   9478         "parse-names":value["parse-names"],
   9479         "comma-dropping-particle": "",
   9480         block_initialize:value.block_initialize,
   9481         multi:value.multi
   9482     };
   9483     this._parseName(name);
   9484     return name;
   9485 };
   9486 CSL.NameOutput.prototype._stripPeriods = function (tokname, str) {
   9487     var decor_tok = this[tokname + "_decor"];
   9488     if (str) {
   9489         if (this.state.tmp.strip_periods) {
   9490             str = str.replace(/\./g, "");
   9491         } else  if (decor_tok) {
   9492             for (var i = 0, ilen = decor_tok.decorations.length; i < ilen; i += 1) {
   9493                 if ("@strip-periods" === decor_tok.decorations[i][0] && "true" === decor_tok.decorations[i][1]) {
   9494                     str = str.replace(/\./g, "");
   9495                     break;
   9496                 }
   9497             }
   9498         }
   9499     }
   9500     return str;
   9501 };
   9502 CSL.NameOutput.prototype._nonDroppingParticle = function (name) {
   9503     var ndp = name["non-dropping-particle"];
   9504     if (ndp && this.state.tmp.sort_key_flag) {
   9505         ndp = ndp.replace(/[\'\u2019]/, "");
   9506     }
   9507     var str = this._stripPeriods("family", ndp);
   9508     if (this.state.output.append(str, this.family_decor, true)) {
   9509         return this.state.output.pop();
   9510     }
   9511     return false;
   9512 };
   9513 CSL.NameOutput.prototype._droppingParticle = function (name, pos, j) {
   9514     var dp = name["dropping-particle"];
   9515     if (dp && this.state.tmp.sort_key_flag) {
   9516         dp = dp.replace(/[\'\u2019]/, "");
   9517     }
   9518     var str = this._stripPeriods("given", dp);
   9519     if (name["dropping-particle"] && name["dropping-particle"].match(/^et.?al[^a-z]$/)) {
   9520         if (this.state.inheritOpt(this.name, "et-al-use-last")) {
   9521             if ("undefined" === typeof j) { 
   9522                 this.etal_spec[pos].freeters = 2;
   9523             } else {
   9524                 this.etal_spec[pos].persons = 2;
   9525             }
   9526         } else {
   9527             if ("undefined" === typeof j) { 
   9528                 this.etal_spec[pos].freeters = 1;
   9529             } else {
   9530                 this.etal_spec[pos].persons = 1;
   9531             }
   9532         }
   9533         name["comma-dropping-particle"] = "";
   9534     } else if (this.state.output.append(str, this.given_decor, true)) {
   9535         return this.state.output.pop();
   9536     }
   9537     return false;
   9538 };
   9539 CSL.NameOutput.prototype._familyName = function (name) {
   9540     var str = this._stripPeriods("family", name.family);
   9541     if (this.state.output.append(str, this.family_decor, true)) {
   9542         return this.state.output.pop();
   9543     }
   9544     return false;
   9545 };
   9546 CSL.NameOutput.prototype._givenName = function (name, pos, i) {
   9547     var ret;
   9548     var formIsShort = this.state.inheritOpt(this.name, "form", "name-form", "long") !== "long";
   9549     var initializeIsTurnedOn = !(this.state.inheritOpt(this.name, "initialize") === false);
   9550     var hasInitializeWith = "string" === typeof this.state.inheritOpt(this.name, "initialize-with") && !name.block_initialize;
   9551     var inBibliography = this.state.tmp.area.slice(0, 12) === "bibliography";
   9552     var defaultLevel;
   9553     var useLevel;
   9554     if (name["full-form-always"]) {
   9555         useLevel = 2;
   9556     } else {
   9557         if (formIsShort) {
   9558             defaultLevel = 0;
   9559         } else if (hasInitializeWith) {
   9560             defaultLevel = 1;
   9561         } else {
   9562             defaultLevel = 2;
   9563         }
   9564         var requestedLevel = this.state.tmp.disambig_settings.givens[pos][i];
   9565         if (requestedLevel > defaultLevel) {
   9566             useLevel = requestedLevel;
   9567         } else {
   9568             useLevel = defaultLevel;
   9569         }
   9570     }
   9571     var gdropt = this.state.citation.opt["givenname-disambiguation-rule"];
   9572    if (gdropt && gdropt.slice(-14) === "-with-initials") {
   9573         hasInitializeWith = true;
   9574     }
   9575     if (name.family && useLevel === 1) {
   9576         if (hasInitializeWith) {
   9577             var initialize_with = this.state.inheritOpt(this.name, "initialize-with", false, "");
   9578             name.given = CSL.Util.Names.initializeWith(this.state, name.given, initialize_with, !initializeIsTurnedOn);
   9579         } else {
   9580             name.given = CSL.Util.Names.unInitialize(this.state, name.given);
   9581         }
   9582     } else if (useLevel === 0) {
   9583         return false;
   9584     } else if (useLevel === 2) {
   9585         name.given = CSL.Util.Names.unInitialize(this.state, name.given);
   9586     }
   9587     var str = this._stripPeriods("given", name.given);
   9588     var rendered = this.state.output.append(str, this.given_decor, true);
   9589     if (rendered) {
   9590         ret = this.state.output.pop();
   9591 	    return ret;
   9592     }
   9593     return false;
   9594 };
   9595 CSL.NameOutput.prototype._nameSuffix = function (name) {
   9596     var str = name.suffix, ret;
   9597     if ("string" === typeof this.state.inheritOpt(this.name, "initialize-with")) {
   9598         str = CSL.Util.Names.initializeWith(this.state, name.suffix, this.state.inheritOpt(this.name, "initialize-with"), true);
   9599     }
   9600     str = this._stripPeriods("family", str);
   9601     var toSuffix = '';
   9602     if (str && str.slice(-1) === '.') {
   9603 	str = str.slice(0, -1);
   9604 	toSuffix = '.';
   9605     }
   9606     var rendered = this.state.output.append(str, "empty", true);
   9607     if (rendered) {
   9608         ret = this.state.output.pop();
   9609 	ret.strings.suffix = toSuffix + ret.strings.suffix;
   9610 	return ret;
   9611     }
   9612     return false;
   9613 };
   9614 CSL.NameOutput.prototype._getLongStyle = function (name, v, i) {
   9615     var long_style, short_style;
   9616     if (name["short"].length) {
   9617         if (this.institutionpart["long-with-short"]) {
   9618             long_style = this.institutionpart["long-with-short"];
   9619         } else {
   9620             long_style = this.institutionpart["long"];
   9621         }
   9622     } else {
   9623         long_style = this.institutionpart["long"];
   9624     }
   9625     if (!long_style) {
   9626         long_style = new CSL.Token();
   9627     }
   9628     return long_style;
   9629 };
   9630 CSL.NameOutput.prototype._getShortStyle = function () {
   9631     var short_style;
   9632     if (this.institutionpart["short"]) {
   9633         short_style = this.institutionpart["short"];
   9634     } else {
   9635         short_style = new CSL.Token();
   9636     }
   9637     return short_style;
   9638 };
   9639 CSL.NameOutput.prototype._parseName = function (name) {
   9640     var m, idx;
   9641     if (!name["parse-names"] && "undefined" !== typeof name["parse-names"]) {
   9642         return name;
   9643     }
   9644     if (name.family && !name.given && name.isInstitution) {
   9645         name.literal = name.family;
   9646         name.family = undefined;
   9647         name.isInstitution = undefined;
   9648     }
   9649     var noparse;
   9650     if (name.family 
   9651         && (name.family.slice(0, 1) === '"' && name.family.slice(-1) === '"')
   9652         || (!name["parse-names"] && "undefined" !== typeof name["parse-names"])) {
   9653         name.family = name.family.slice(1, -1);
   9654         noparse = true;
   9655         name["parse-names"] = 0;
   9656     } else {
   9657         noparse = false;
   9658     }
   9659     if (this.state.opt.development_extensions.parse_names) {
   9660         if (!name["non-dropping-particle"] && name.family && !noparse && name.given) {
   9661             if (!name["static-particles"]) {
   9662                 CSL.parseParticles(name, true);
   9663             }
   9664         }
   9665     }
   9666 };
   9667 CSL.NameOutput.prototype.getName = function (name, slotLocaleset, fallback, stopOrig) {
   9668     if (stopOrig && slotLocaleset === 'locale-orig') {
   9669         return {name:false,usedOrig:stopOrig};
   9670     }
   9671     if (!name.family) {
   9672         name.family = "";
   9673     }
   9674     if (!name.given) {
   9675         name.given = "";
   9676     }
   9677     var name_params = {};
   9678     name_params["static-ordering"] = this.getStaticOrder(name);
   9679     var foundTag = true;
   9680     if (slotLocaleset !== 'locale-orig') {
   9681         foundTag = false;
   9682         if (name.multi) {
   9683             var langTags = this.state.opt[slotLocaleset]
   9684             for (var i = 0, ilen = langTags.length; i < ilen; i += 1) {
   9685                 langTag = langTags[i];
   9686                 if (name.multi._key[langTag]) {
   9687                     foundTag = true;
   9688                     var isInstitution = name.isInstitution;
   9689                     name = name.multi._key[langTag];
   9690                     name.isInstitution = isInstitution;
   9691                     name_params = this.getNameParams(langTag);
   9692                     name_params.transliterated = true;
   9693                     break;
   9694                 }
   9695             }
   9696         }
   9697     }
   9698     if (!foundTag) {
   9699         var langTag = false;
   9700         if (name.multi && name.multi.main) {
   9701             langTag = name.multi.main;
   9702         } else if (this.Item.language) {
   9703             langTag = this.Item.language;
   9704         }
   9705         if (langTag) {
   9706             name_params = this.getNameParams(langTag);
   9707         }
   9708     }
   9709     if (!fallback && !foundTag) {
   9710         return {name:false,usedOrig:stopOrig};
   9711     }
   9712     if (!name.family) {
   9713         name.family = "";
   9714     }
   9715     if (!name.given) {
   9716         name.given = "";
   9717     }
   9718     name = {
   9719         family:name.family,
   9720         given:name.given,
   9721         "non-dropping-particle":name["non-dropping-particle"],
   9722         "dropping-particle":name["dropping-particle"],
   9723         suffix:name.suffix,
   9724         "static-ordering":name_params["static-ordering"],
   9725         "static-particles":name["static-particles"],
   9726         "reverse-ordering":name_params["reverse-ordering"],
   9727         "full-form-always": name_params["full-form-always"],
   9728         "parse-names":name["parse-names"],
   9729         "comma-suffix":name["comma-suffix"],
   9730         "comma-dropping-particle":name["comma-dropping-particle"],
   9731         transliterated: name_params.transliterated,
   9732         block_initialize: name_params["block-initialize"],
   9733         literal:name.literal,
   9734         isInstitution:name.isInstitution,
   9735         multi:name.multi
   9736     };
   9737     if (!name.literal && (!name.given && name.family && name.isInstitution)) {
   9738         name.literal = name.family;
   9739     }
   9740     if (name.literal) {
   9741         delete name.family;
   9742         delete name.given;
   9743     }
   9744     name = this._normalizeNameInput(name);
   9745     var usedOrig;
   9746     if (stopOrig) {
   9747         usedOrig = stopOrig;
   9748     } else {
   9749         usedOrig = !foundTag;
   9750     }
   9751     return {name:name,usedOrig:usedOrig};
   9752 }
   9753 CSL.NameOutput.prototype.getNameParams = function (langTag) {
   9754     var ret = {};
   9755     var langspec = CSL.localeResolve(this.Item.language, this.state.opt["default-locale"][0]);
   9756     var try_locale = this.state.locale[langspec.best] ? langspec.best : this.state.opt["default-locale"][0];
   9757     var name_as_sort_order = this.state.locale[try_locale].opts["name-as-sort-order"]
   9758     var name_as_reverse_order = this.state.locale[try_locale].opts["name-as-reverse-order"]
   9759     var name_never_short = this.state.locale[try_locale].opts["name-never-short"]
   9760     var field_lang_bare = langTag.split("-")[0];
   9761     if (name_as_sort_order && name_as_sort_order[field_lang_bare]) {
   9762         ret["static-ordering"] = true;
   9763         ret["reverse-ordering"] = false;
   9764     }
   9765     if (name_as_reverse_order && name_as_reverse_order[field_lang_bare]) {
   9766         ret["reverse-ordering"] = true;
   9767         ret["static-ordering"] = false;
   9768     }
   9769     if (name_never_short && name_never_short[field_lang_bare]) {
   9770         ret["full-form-always"] = true;
   9771     }
   9772     if (ret["static-ordering"]) {
   9773         ret["block-initialize"] = true;
   9774     }
   9775     return ret;
   9776 }
   9777 CSL.NameOutput.prototype.setRenderedName = function (name) {
   9778     if (this.state.tmp.area === "bibliography") {
   9779         var strname = "";
   9780         for (var j=0,jlen=CSL.NAME_PARTS.length;j<jlen;j+=1) {
   9781             if (name[CSL.NAME_PARTS[j]]) {
   9782                 strname += name[CSL.NAME_PARTS[j]];
   9783             }
   9784         }
   9785         this.state.tmp.rendered_name.push(strname);
   9786     }
   9787 }
   9788 CSL.NameOutput.prototype.fixupInstitution = function (name, varname, listpos) {
   9789     if (this.state.sys.getHumanForm && "legal_case" === this.Item.type && "authority" === varname) {
   9790         name.literal = this.state.sys.getHumanForm(this.Item.jurisdiction, name.literal, true);
   9791     }
   9792     name = this._splitInstitution(name, varname, listpos);
   9793     if (this.institution.strings["reverse-order"]) {
   9794         name["long"].reverse();
   9795     }
   9796     var long_form = name["long"];
   9797     var short_form = name["long"].slice();
   9798     var use_short_form = false;
   9799     if (this.state.sys.getAbbreviation) {
   9800         var jurisdiction = this.Item.jurisdiction;
   9801         for (var j = 0, jlen = long_form.length; j < jlen; j += 1) {
   9802             var normalizedKey = long_form[j];
   9803             if (this.state.sys.normalizeAbbrevsKey) {
   9804                 normalizedKey = this.state.sys.normalizeAbbrevsKey(varname, long_form[j]);
   9805             }
   9806             jurisdiction = this.state.transform.loadAbbreviation(jurisdiction, "institution-part", normalizedKey);
   9807             if (this.state.transform.abbrevs[jurisdiction]["institution-part"][normalizedKey]) {
   9808                 short_form[j] = this.state.transform.abbrevs[jurisdiction]["institution-part"][normalizedKey];
   9809                 use_short_form = true;
   9810             }
   9811         }
   9812     }
   9813     if (use_short_form) {
   9814         name["short"] = short_form;
   9815     } else {
   9816         name["short"] = [];
   9817     }
   9818     return name;
   9819 }
   9820 CSL.NameOutput.prototype.getStaticOrder = function (name, refresh) {
   9821     var static_ordering_val = false;
   9822     if (!refresh && name["static-ordering"]) {
   9823         static_ordering_val = true;
   9824     } else if (this._isRomanesque(name) === 0) {
   9825         static_ordering_val = true;
   9826     } else if ((!name.multi || !name.multi.main) && this.Item.language && ['vi', 'hu'].indexOf(this.Item.language) > -1) {
   9827         static_ordering_val = true;
   9828     } else if (name.multi && name.multi.main && ['vi', 'hu'].indexOf(name.multi.main.slice(0,2)) > -1) {
   9829         static_ordering_val = true;
   9830     } else {
   9831         if (this.state.opt['auto-vietnamese-names']
   9832             && (CSL.VIETNAMESE_NAMES.exec(name.family + " " + name.given)
   9833                 && CSL.VIETNAMESE_SPECIALS.exec(name.family + name.given))) {
   9834             static_ordering_val = true;
   9835         }
   9836     }
   9837     return static_ordering_val;
   9838 }
   9839 CSL.NameOutput.prototype._splitInstitution = function (value, v, i) {
   9840     var ret = {};
   9841     if (!value.literal && value.family) {
   9842         value.literal = value.family;
   9843         delete value.family;
   9844     }
   9845     var splitInstitution = value.literal.replace(/\s*\|\s*/g, "|");
   9846     splitInstitution = splitInstitution.split("|");
   9847     if (this.institution.strings.form === "short" && this.state.sys.getAbbreviation) {
   9848         var jurisdiction = this.Item.jurisdiction;
   9849         for (var j = splitInstitution.length; j > 0; j += -1) {
   9850             var str = splitInstitution.slice(0, j).join("|");
   9851             var normalizedKey = str;
   9852             if (this.state.sys.normalizeAbbrevsKey) {
   9853                 normalizedKey = this.state.sys.normalizeAbbrevsKey(v, str);
   9854             }
   9855             jurisdiction = this.state.transform.loadAbbreviation(jurisdiction, "institution-entire", normalizedKey);
   9856             if (this.state.transform.abbrevs[jurisdiction]["institution-entire"][normalizedKey]) {
   9857                 var splitLst = this.state.transform.abbrevs[jurisdiction]["institution-entire"][normalizedKey];
   9858                 splitLst = this.state.transform.quashCheck(splitLst);
   9859                 var splitSplitLst = splitLst.split(/>>[0-9]{4}>>/);
   9860                 var m = splitLst.match(/>>([0-9]{4})>>/);
   9861                 splitLst = splitSplitLst.pop();
   9862                 if (splitSplitLst.length > 0 && this.Item["original-date"] && this.Item["original-date"].year) {
   9863                     for (var k=m.length - 1; k > 0; k += -1) {
   9864                         if (parseInt(this.Item["original-date"].year, 10) >= parseInt(m[k], 10)) {
   9865                             break;
   9866                         }
   9867                         splitLst = splitSplitLst.pop();
   9868                     }
   9869                 }
   9870                 splitLst = splitLst.replace(/\s*\|\s*/g, "|");
   9871                 splitInstitution = [splitLst];
   9872                 break;
   9873             }
   9874         }
   9875     }
   9876     splitInstitution.reverse();
   9877     ret["long"] = this._trimInstitution(splitInstitution, v, i);
   9878     return ret;
   9879 };
   9880 CSL.NameOutput.prototype._trimInstitution = function (subunits, v, i) {
   9881     var use_first = false;
   9882     var append_last = false;
   9883     var s = subunits.slice();
   9884     var stop_last = false;
   9885     if (this.institution) {
   9886         if ("undefined" !== typeof this.institution.strings["use-first"]) {
   9887             use_first = this.institution.strings["use-first"];
   9888         }
   9889         if ("undefined" !== typeof this.institution.strings["stop-last"]) {
   9890             stop_last = this.institution.strings["stop-last"];
   9891         } else if ("authority" === v && this.state.tmp.authority_stop_last) {
   9892             stop_last = this.state.tmp.authority_stop_last;
   9893         }
   9894         if (stop_last) {
   9895             s = s.slice(0, stop_last);
   9896             subunits = subunits.slice(0, stop_last);
   9897         }
   9898         if ("undefined" !== typeof this.institution.strings["use-last"]) {
   9899             append_last = this.institution.strings["use-last"];
   9900         }
   9901         if ("authority" === v) {
   9902             if (stop_last) {
   9903                 this.state.tmp.authority_stop_last = stop_last;
   9904             }
   9905             if (append_last)  {
   9906                 this.state.tmp.authority_stop_last += (append_last * -1);
   9907             }
   9908         }
   9909     }
   9910     if (false === use_first) {
   9911         if (this.persons[v].length === 0) {
   9912             use_first = this.institution.strings["substitute-use-first"];
   9913         }
   9914         if (!use_first) {
   9915             use_first = 0;
   9916         }
   9917     }
   9918     if (false === append_last) {
   9919         if (!use_first) {
   9920             append_last = subunits.length;
   9921         } else {
   9922             append_last = 0;
   9923         }
   9924     }
   9925     if (use_first > subunits.length - append_last) {
   9926         use_first = subunits.length - append_last;
   9927     }
   9928     subunits = subunits.slice(0, use_first);
   9929     s = s.slice(use_first);
   9930     if (append_last) {
   9931         if (append_last > s.length) {
   9932             append_last = s.length;
   9933         }
   9934         if (append_last) {
   9935             subunits = subunits.concat(s.slice((s.length - append_last)));
   9936         }
   9937     }
   9938     return subunits;
   9939 };
   9940 CSL.PublisherOutput = function (state, group_tok) {
   9941     this.state = state;
   9942     this.group_tok = group_tok;
   9943     this.varlist = [];
   9944 };
   9945 CSL.PublisherOutput.prototype.render = function () {
   9946     this.clearVars();
   9947     this.composeAndBlob();
   9948     this.composeElements();
   9949     this.composePublishers();
   9950     this.joinPublishers();
   9951 };
   9952 CSL.PublisherOutput.prototype.composeAndBlob = function () {
   9953     this.and_blob = {};
   9954     var and_term = false;
   9955     if (this.group_tok.strings.and === "text") {
   9956         and_term = this.state.getTerm("and");
   9957     } else if (this.group_tok.strings.and === "symbol") {
   9958         and_term = "&";
   9959     }
   9960     var tok = new CSL.Token();
   9961     tok.strings.suffix = " ";
   9962     tok.strings.prefix = " ";
   9963     this.state.output.append(and_term, tok, true);
   9964     var no_delim = this.state.output.pop();
   9965     tok.strings.prefix = this.group_tok.strings["subgroup-delimiter"];
   9966     this.state.output.append(and_term, tok, true);
   9967     var with_delim = this.state.output.pop();
   9968     this.and_blob.single = false;
   9969     this.and_blob.multiple = false;
   9970     if (and_term) {
   9971         if (this.group_tok.strings["subgroup-delimiter-precedes-last"] === "always") {
   9972             this.and_blob.single = with_delim;
   9973         } else if (this.group_tok.strings["subgroup-delimiter-precedes-last"] === "never") {
   9974             this.and_blob.single = no_delim;
   9975             this.and_blob.multiple = no_delim;
   9976         } else {
   9977             this.and_blob.single = no_delim;
   9978             this.and_blob.multiple = with_delim;
   9979         }
   9980     }
   9981 };
   9982 CSL.PublisherOutput.prototype.composeElements = function () {
   9983     for (var i = 0, ilen = 2; i < ilen; i += 1) {
   9984         var varname = ["publisher", "publisher-place"][i];
   9985         for (var j = 0, jlen = this["publisher-list"].length; j < jlen; j += 1) {
   9986             var str = this[varname + "-list"][j];
   9987             var tok = this[varname + "-token"];
   9988             this.state.output.append(str, tok, true);
   9989             this[varname + "-list"][j] = this.state.output.pop();
   9990         }
   9991     }
   9992 };
   9993 CSL.PublisherOutput.prototype.composePublishers = function () {
   9994     var blobs;
   9995     for (var i = 0, ilen = this["publisher-list"].length; i < ilen; i += 1) {
   9996         var ordered_list = [];
   9997         blobs = [this[this.varlist[0] + "-list"][i], this[this.varlist[1] + "-list"][i]];
   9998         this["publisher-list"][i] = this._join(blobs, this.group_tok.strings.delimiter);
   9999     }
  10000 };
  10001 CSL.PublisherOutput.prototype.joinPublishers = function () {
  10002     var blobs = this["publisher-list"];
  10003     var delim = this.name_delimiter;
  10004     var publishers = this._join(blobs, this.group_tok.strings["subgroup-delimiter"], this.and_blob.single, this.and_blob.multiple, this.group_tok);
  10005     this.state.output.append(publishers, "literal");
  10006 };
  10007 CSL.PublisherOutput.prototype._join = CSL.NameOutput.prototype._join;
  10008 CSL.PublisherOutput.prototype._getToken = CSL.NameOutput.prototype._getToken;
  10009 CSL.PublisherOutput.prototype.clearVars = function () {
  10010     this.state.tmp["publisher-list"] = false;
  10011     this.state.tmp["publisher-place-list"] = false;
  10012     this.state.tmp["publisher-group-token"] = false;
  10013     this.state.tmp["publisher-token"] = false;
  10014     this.state.tmp["publisher-place-token"] = false;
  10015 };
  10016 CSL.evaluateLabel = function (node, state, Item, item) {
  10017     var myterm;
  10018     if ("locator" === node.strings.term) {
  10019         if (item && item.label) {
  10020             if (item.label === "sub verbo") {
  10021                 myterm = "sub-verbo";
  10022             } else {
  10023                 myterm = item.label;
  10024             }
  10025         }
  10026         if (!myterm) {
  10027             myterm = "page";
  10028         }
  10029     } else {
  10030         myterm = node.strings.term;
  10031     }
  10032     var plural = node.strings.plural;
  10033     if ("number" !== typeof plural) {
  10034         var theItem = node.strings.term === "locator" ? item : Item;
  10035         state.processNumber(false, theItem, node.strings.term, Item.type);
  10036         plural = state.tmp.shadow_numbers[node.strings.term].plural;
  10037         if (!state.tmp.shadow_numbers[node.strings.term].labelForm
  10038            && !state.tmp.shadow_numbers[node.strings.term].labelDecorations) {
  10039             state.tmp.shadow_numbers[node.strings.term].labelForm = node.strings.form;
  10040             state.tmp.shadow_numbers[node.strings.term].labelCapitalizeIfFirst = node.strings.capitalize_if_first;
  10041             state.tmp.shadow_numbers[node.strings.term].labelDecorations = node.decorations.slice();
  10042         }
  10043         if (["locator", "number", "page"].indexOf(node.strings.term) > -1 && state.tmp.shadow_numbers[node.strings.term].label) {
  10044             myterm = state.tmp.shadow_numbers[node.strings.term].label;
  10045         }
  10046         if (node.decorations && (state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support)) {
  10047             node.decorations.reverse();
  10048             node.decorations.push(["@showid","true", node.cslid]);
  10049             node.decorations.reverse();
  10050         }
  10051     }
  10052     return CSL.castLabel(state, node, myterm, plural, CSL.TOLERANT);
  10053 };
  10054 CSL.castLabel = function (state, node, term, plural, mode) {
  10055     var label_form = node.strings.form;
  10056     var label_capitalize_if_first = node.strings.capitalize_if_first;
  10057     if (state.tmp.group_context.tip.label_form && label_form !== "static") {
  10058         label_form = state.tmp.group_context.tip.label_form;
  10059     }
  10060     if (state.tmp.group_context.tip.label_capitalize_if_first) {
  10061         label_capitalize_if_first = state.tmp.group_context.tip.label_capitalize_if_first;
  10062     }
  10063     var ret = state.getTerm(term, label_form, plural, false, mode, node.default_locale);
  10064     if (label_capitalize_if_first) {
  10065         ret = CSL.Output.Formatters["capitalize-first"](state, ret);
  10066     }
  10067     if (state.tmp.strip_periods) {
  10068         ret = ret.replace(/\./g, "");
  10069     } else {
  10070         for (var i = 0, ilen = node.decorations.length; i < ilen; i += 1) {
  10071             if ("@strip-periods" === node.decorations[i][0] && "true" === node.decorations[i][1]) {
  10072                 ret = ret.replace(/\./g, "");
  10073                 break;
  10074             }
  10075         }
  10076     }
  10077     return ret;
  10078 };
  10079 CSL.Node.name = {
  10080     build: function (state, target) {
  10081         var func, pos, len, attrname;
  10082         if ([CSL.SINGLETON, CSL.START].indexOf(this.tokentype) > -1) {
  10083             if ("undefined" === typeof state.tmp.root) {
  10084                 var oldTmpRoot = undefined;
  10085                 state.tmp.root = "citation";
  10086             } else {
  10087                 var oldTmpRoot = state.tmp.root;
  10088             }
  10089             if (state.inheritOpt(this, "et-al-subsequent-min")
  10090                 && (state.inheritOpt(this, "et-al-subsequent-min") !== state.inheritOpt(this, "et-al-min"))) {
  10091                 state.opt.update_mode = CSL.POSITION;
  10092             }
  10093             if (state.inheritOpt(this, "et-al-subsequent-use-first")
  10094                 && (state.inheritOpt(this, "et-al-subsequent-use-first") !== state.inheritOpt(this, "et-al-use-first"))) {
  10095                 state.opt.update_mode = CSL.POSITION;
  10096             }
  10097             state.tmp.root = oldTmpRoot;
  10098             func = function (state, Item) {
  10099                 state.tmp.etal_term = "et-al";
  10100                 state.tmp.name_delimiter = state.inheritOpt(this, "delimiter", "name-delimiter", ", ");
  10101                 state.tmp["delimiter-precedes-et-al"] = state.inheritOpt(this, "delimiter-precedes-et-al");
  10102                 if ("text" === state.inheritOpt(this, "and")) {
  10103                     this.and_term = state.getTerm("and", "long", 0);
  10104                 } else if ("symbol" === state.inheritOpt(this, "and")) {
  10105                     if (state.opt.development_extensions.expect_and_symbol_form) {
  10106                         this.and_term = state.getTerm("and", "symbol", 0);
  10107                     } else {
  10108                         this.and_term = "&";
  10109                     }
  10110                 }
  10111                 state.tmp.and_term = this.and_term;
  10112                 if (CSL.STARTSWITH_ROMANESQUE_REGEXP.test(this.and_term)) {
  10113                     this.and_prefix_single = " ";
  10114                     this.and_prefix_multiple = ", ";
  10115                     if ("string" === typeof state.tmp.name_delimiter) {
  10116                         this.and_prefix_multiple = state.tmp.name_delimiter;
  10117                     }
  10118                     this.and_suffix = " ";
  10119                 } else {
  10120                     this.and_prefix_single = "";
  10121                     this.and_prefix_multiple = "";
  10122                     this.and_suffix = "";
  10123                 }
  10124                 if (state.inheritOpt(this, "delimiter-precedes-last") === "always") {
  10125                     this.and_prefix_single = state.tmp.name_delimiter;
  10126                 } else if (state.inheritOpt(this, "delimiter-precedes-last") === "never") {
  10127                     if (this.and_prefix_multiple) {
  10128                         this.and_prefix_multiple = " ";
  10129                     }
  10130                 } else if (state.inheritOpt(this, "delimiter-precedes-last") === "after-inverted-name") {
  10131                     if (this.and_prefix_single) {
  10132                         this.and_prefix_single = state.tmp.name_delimiter;
  10133                     }
  10134                     if (this.and_prefix_multiple) {
  10135                         this.and_prefix_multiple = " ";
  10136                     }
  10137                 }
  10138                 this.and = {};
  10139                 if (state.inheritOpt(this, "and")) {
  10140                     state.output.append(this.and_term, "empty", true);
  10141                     this.and.single = state.output.pop();
  10142                     this.and.single.strings.prefix = this.and_prefix_single;
  10143                     this.and.single.strings.suffix = this.and_suffix;
  10144                     state.output.append(this.and_term, "empty", true);
  10145                     this.and.multiple = state.output.pop();
  10146                     this.and.multiple.strings.prefix = this.and_prefix_multiple;
  10147                     this.and.multiple.strings.suffix = this.and_suffix;
  10148                 } else if (state.tmp.name_delimiter) {
  10149                     this.and.single = new CSL.Blob(state.tmp.name_delimiter);
  10150                     this.and.single.strings.prefix = "";
  10151                     this.and.single.strings.suffix = "";
  10152                     this.and.multiple = new CSL.Blob(state.tmp.name_delimiter);
  10153                     this.and.multiple.strings.prefix = "";
  10154                     this.and.multiple.strings.suffix = "";
  10155                 }
  10156                 this.ellipsis = {};
  10157                 if (state.inheritOpt(this, "et-al-use-last")) {
  10158                     this.ellipsis_term = "\u2026";
  10159                     this.ellipsis_prefix_single = " ";
  10160                     this.ellipsis_prefix_multiple =  state.inheritOpt(this, "delimiter", "name-delimiter", ", ");
  10161                     this.ellipsis_suffix = " ";
  10162                     this.ellipsis.single = new CSL.Blob(this.ellipsis_term);
  10163                     this.ellipsis.single.strings.prefix = this.ellipsis_prefix_single;
  10164                     this.ellipsis.single.strings.suffix = this.ellipsis_suffix;
  10165                     this.ellipsis.multiple = new CSL.Blob(this.ellipsis_term);
  10166                     this.ellipsis.multiple.strings.prefix = this.ellipsis_prefix_multiple;
  10167                     this.ellipsis.multiple.strings.suffix = this.ellipsis_suffix;
  10168                 }
  10169                 if ("undefined" === typeof state.tmp["et-al-min"]) {
  10170                     state.tmp["et-al-min"] = state.inheritOpt(this, "et-al-min");
  10171                 }
  10172                 if ("undefined" === typeof state.tmp["et-al-use-first"]) {
  10173                     state.tmp["et-al-use-first"] = state.inheritOpt(this, "et-al-use-first");
  10174                 }
  10175                 if ("undefined" === typeof state.tmp["et-al-use-last"]) {
  10176                     state.tmp["et-al-use-last"] = state.inheritOpt(this, "et-al-use-last");
  10177                 }
  10178                 state.nameOutput.name = this;
  10179             };
  10180             state.build.name_flag = true;
  10181             this.execs.push(func);
  10182         }
  10183         target.push(this);
  10184     }
  10185 };
  10186 CSL.Node["name-part"] = {
  10187     build: function (state, target) {
  10188         state.build[this.strings.name] = this;
  10189     }
  10190 };
  10191 CSL.Node.names = {
  10192     build: function (state, target) {
  10193         var func, len, pos, attrname;
  10194         var debug = false;
  10195         if (this.tokentype === CSL.START || this.tokentype === CSL.SINGLETON) {
  10196             CSL.Util.substituteStart.call(this, state, target);
  10197             state.build.substitute_level.push(1);
  10198         }
  10199         if (this.tokentype === CSL.SINGLETON) {
  10200             state.build.names_variables.push(this.variables);
  10201             func = function (state, Item, item) {
  10202                 var labelVariable = state.nameOutput.labelVariable;
  10203                 state.nameOutput.reinit(this, labelVariable);
  10204             };
  10205             this.execs.push(func);
  10206         }
  10207         if (this.tokentype === CSL.START) {
  10208             state.build.names_flag = true;
  10209             state.build.names_level += 1;
  10210             if (state.build.names_level === 1) {
  10211                 state.build.names_variables = [];
  10212                 state.build.name_label = {};
  10213             }
  10214             state.build.names_variables.push(this.variables);
  10215             func = function (state, Item, item) {
  10216                 state.tmp.can_substitute.push(true);
  10217                 state.parallel.StartVariable("names",this.variables[0]);
  10218                 state.nameOutput.init(this);
  10219             };
  10220             this.execs.push(func);
  10221         }
  10222         if (this.tokentype === CSL.END) {
  10223             for (var i = 0, ilen = 3; i < ilen; i += 1) {
  10224                 var key = ["family", "given", "et-al"][i];
  10225                 this[key] = state.build[key];
  10226                 if (state.build.names_level === 1) {
  10227                     state.build[key] = undefined;
  10228                 }
  10229             }
  10230             this.label = state.build.name_label;
  10231             if (state.build.names_level === 1) {
  10232                 state.build.name_label = {};
  10233             }
  10234             state.build.names_level += -1;
  10235             state.build.names_variables.pop();
  10236             func = function (state, Item, item) {
  10237                 if (state.tmp.etal_node) {
  10238                     this.etal_style = state.tmp.etal_node;
  10239                 } else {
  10240                     this.etal_style = "empty";
  10241                 }
  10242                 this.etal_term = state.getTerm(state.tmp.etal_term, "long", 0);
  10243                 if (CSL.STARTSWITH_ROMANESQUE_REGEXP.test(this.etal_term)) {
  10244                     this.etal_prefix_single = " ";
  10245                     this.etal_prefix_multiple = state.tmp.name_delimiter;
  10246                     if (state.tmp["delimiter-precedes-et-al"] === "always") {
  10247                         this.etal_prefix_single = state.tmp.name_delimiter;
  10248                     } else if (state.tmp["delimiter-precedes-et-al"] === "never") {
  10249                         this.etal_prefix_multiple = " ";
  10250                     } else if (state.tmp["delimiter-precedes-et-al"] === "after-inverted-name") {
  10251                         this.etal_prefix_single = state.tmp.name_delimiter;
  10252                         this.etal_prefix_multiple = " ";
  10253                     }
  10254                     this.etal_suffix = "";
  10255                 } else {
  10256                     this.etal_prefix_single = "";
  10257                     this.etal_prefix_multiple = "";
  10258                     this.etal_suffix = "";
  10259                 }
  10260                 for (var i = 0, ilen = 3; i < ilen; i += 1) {
  10261                     var key = ["family", "given"][i];
  10262                     state.nameOutput[key] = this[key];
  10263                 }
  10264                 state.nameOutput["with"] = this["with"];
  10265                 var mywith = "with";
  10266                 var with_default_prefix = "";
  10267                 var with_suffix = "";
  10268                 if (CSL.STARTSWITH_ROMANESQUE_REGEXP.test(mywith)) {
  10269                     with_default_prefix = " ";
  10270                     with_suffix = " ";
  10271                 }
  10272                 var thewith = {};
  10273                 thewith.single = new CSL.Blob(mywith);
  10274                 thewith.single.strings.suffix = with_suffix;
  10275                 thewith.multiple = new CSL.Blob(mywith);
  10276                 thewith.multiple.strings.suffix = with_suffix;
  10277                 if (state.inheritOpt(state.nameOutput.name, "delimiter-precedes-last") === "always") {
  10278                     thewith.single.strings.prefix = state.inheritOpt(this, "delimiter", "names-delimiter");
  10279                     thewith.multiple.strings.prefix = state.inheritOpt(this, "delimiter", "names-delimiter");
  10280                 } else if (state.inheritOpt(state.nameOutput.name, "delimiter-precedes-last") === "contextual") {
  10281                     thewith.single.strings.prefix = with_default_prefix;
  10282                     thewith.multiple.strings.prefix = state.inheritOpt(this, "delimiter", "names-delimiter");
  10283                 } else if (state.inheritOpt(state.nameOutput.name, "delimiter-precedes-last") === "after-inverted-name") {
  10284                     thewith.single.strings.prefix = state.inheritOpt(this, "delimiter", "names-delimiter");
  10285                     thewith.multiple.strings.prefix = with_default_prefix;
  10286                 } else {
  10287                     thewith.single.strings.prefix = with_default_prefix;
  10288                     thewith.multiple.strings.prefix = with_default_prefix;
  10289                 }
  10290                 state.nameOutput["with"] = thewith;
  10291                 state.nameOutput.label = this.label;
  10292                 state.nameOutput.etal_style = this.etal_style;
  10293                 state.nameOutput.etal_term = this.etal_term;
  10294                 state.nameOutput.etal_prefix_single = this.etal_prefix_single;
  10295                 state.nameOutput.etal_prefix_multiple = this.etal_prefix_multiple;
  10296                 state.nameOutput.etal_suffix = this.etal_suffix;
  10297                 state.nameOutput.outputNames();
  10298                 state.tmp["et-al-use-first"] = undefined;
  10299                 state.tmp["et-al-min"] = undefined;
  10300                 state.tmp["et-al-use-last"] = undefined;
  10301             };
  10302             this.execs.push(func);
  10303             func = function (state, Item) {
  10304                 if (!state.tmp.can_substitute.pop()) {
  10305                     state.tmp.can_substitute.replace(false, CSL.LITERAL);
  10306                 }
  10307                 state.parallel.CloseVariable("names");
  10308                 if (state.tmp.can_substitute.mystack.length === 1) {
  10309                     state.tmp.can_block_substitute = false;
  10310                 }
  10311             };
  10312             this.execs.push(func);
  10313             state.build.name_flag = false;
  10314         }
  10315         target.push(this);
  10316         if (this.tokentype === CSL.END || this.tokentype === CSL.SINGLETON) {
  10317             state.build.substitute_level.pop();
  10318             CSL.Util.substituteEnd.call(this, state, target);
  10319         }
  10320     }
  10321 };
  10322 CSL.Node.number = {
  10323     build: function (state, target) {
  10324         var func;
  10325         CSL.Util.substituteStart.call(this, state, target);
  10326         if (this.strings.form === "roman") {
  10327             this.formatter = state.fun.romanizer;
  10328         } else if (this.strings.form === "ordinal") {
  10329             this.formatter = state.fun.ordinalizer;
  10330         } else if (this.strings.form === "long-ordinal") {
  10331             this.formatter = state.fun.long_ordinalizer;
  10332         }
  10333         if ("undefined" === typeof this.successor_prefix) {
  10334             this.successor_prefix = state[state.build.area].opt.layout_delimiter;
  10335         }
  10336         if ("undefined" === typeof this.splice_prefix) {
  10337             this.splice_prefix = state[state.build.area].opt.layout_delimiter;
  10338         }
  10339         func = function (state, Item, item) {
  10340             var i, ilen, newlst, lst;
  10341             if (this.variables.length === 0) {
  10342                 return;
  10343             }
  10344             if ("undefined" === typeof item) {
  10345                 var item = {};
  10346             }
  10347             var varname, num, number, m, j, jlen;
  10348             varname = this.variables[0];
  10349             if (varname === "locator" && state.tmp.just_looking) {
  10350                 return;
  10351             }
  10352             state.parallel.StartVariable(this.variables[0]);
  10353             if (this.variables[0] === "locator") {
  10354                 state.parallel.AppendToVariable(Item.section);
  10355             } else {
  10356                 state.parallel.AppendToVariable(Item[this.variables[0]]);
  10357             }
  10358             var rex = new RegExp("(?:&|, | and |" + state.getTerm("page-range-delimiter") + ")");
  10359             if (varname === 'collection-number' && Item.type === 'legal_case') {
  10360                 state.tmp.renders_collection_number = true;
  10361             }
  10362             var value = Item[this.variables[0]];
  10363             var node = this;
  10364             if (state.tmp.group_context.tip.force_suppress) {
  10365                 return false;
  10366             }
  10367             if (varname === "locator") {
  10368                 state.processNumber(node, item, varname, Item.type);
  10369             } else {
  10370                 if (!state.tmp.group_context.tip.condition && Item[varname]) {
  10371                     state.tmp.just_did_number = true;
  10372                 }
  10373                 state.processNumber(node, Item, varname, Item.type);
  10374             }
  10375             CSL.Util.outputNumericField(state, varname, Item.id);
  10376             state.parallel.CloseVariable("number");
  10377             if (["locator", "locator-extra"].indexOf(this.variables_real[0]) > -1
  10378                && !state.tmp.just_looking) {
  10379                 state.tmp.done_vars.push(this.variables_real[0]);
  10380                 state.tmp.group_context.tip.done_vars.push(this.variables_real[0]);
  10381             }
  10382         };
  10383         this.execs.push(func);
  10384         target.push(this);
  10385         CSL.Util.substituteEnd.call(this, state, target);
  10386     }
  10387 };
  10388 CSL.Node.sort = {
  10389     build: function (state, target) {
  10390         target = state[state.build.root + "_sort"].tokens;
  10391         if (this.tokentype === CSL.START) {
  10392             if (state.build.area === "citation") {
  10393                 state.parallel.use_parallels = false;
  10394                 state.opt.sort_citations = true;
  10395             }
  10396             state.build.area = state.build.root + "_sort";
  10397             state.build.extension = "_sort";
  10398             var func = function (state, Item) {
  10399                 if (state.opt.has_layout_locale) {
  10400                     var langspec = CSL.localeResolve(Item.language, state.opt["default-locale"][0]);
  10401                     var sort_locales = state[state.tmp.area.slice(0,-5)].opt.sort_locales;
  10402                     var langForItem;
  10403                     for (var i=0,ilen=sort_locales.length;i<ilen;i+=1) {
  10404                         langForItem = sort_locales[i][langspec.bare];
  10405                         if (!langForItem) {
  10406                             langForItem = sort_locales[i][langspec.best];
  10407                         }
  10408                         if (langForItem) {
  10409                             break;
  10410                         }
  10411                     }
  10412                     if (!langForItem) {
  10413                         langForItem = state.opt["default-locale"][0];
  10414                     }
  10415                     state.tmp.lang_sort_hold = state.opt.lang;
  10416                     state.opt.lang = langForItem;
  10417                 }
  10418             }
  10419             this.execs.push(func);
  10420         }
  10421         if (this.tokentype === CSL.END) {
  10422             state.build.area = state.build.root;
  10423             state.build.extension = "";
  10424             var func = function (state, Item) {
  10425                 if (state.opt.has_layout_locale) {
  10426                     state.opt.lang = state.tmp.lang_sort_hold;
  10427                     delete state.tmp.lang_sort_hold;
  10428                 }
  10429             }
  10430             this.execs.push(func);
  10431         }
  10432         target.push(this);
  10433     }
  10434 };
  10435 CSL.Node.substitute = {
  10436     build: function (state, target) {
  10437         var func;
  10438         if (this.tokentype === CSL.START) {
  10439             func = function (state, Item) {
  10440                 state.tmp.can_block_substitute = true;
  10441                 if (state.tmp.value.length) {
  10442                     state.tmp.can_substitute.replace(false, CSL.LITERAL);
  10443                 }
  10444             };
  10445             this.execs.push(func);
  10446         }
  10447         target.push(this);
  10448     }
  10449 };
  10450 CSL.Node.text = {
  10451     build: function (state, target) {
  10452         var variable, func, form, plural, id, num, number, formatter, firstoutput, specialdelimiter, label, myname, names, name, year, suffix, term, dp, len, pos, n, m, value, flag;
  10453         if (this.postponed_macro) {
  10454             var group_start = CSL.Util.cloneToken(this);
  10455             group_start.name = "group";
  10456             group_start.tokentype = CSL.START;
  10457             CSL.Node.group.build.call(group_start, state, target);
  10458             CSL.expandMacro.call(state, this, target);
  10459             var group_end = CSL.Util.cloneToken(this);
  10460             group_end.name = "group";
  10461             group_end.tokentype = CSL.END;
  10462             if (this.postponed_macro === 'juris-locator-label') {
  10463                 group_end.isJurisLocatorLabel = true;
  10464             }
  10465             CSL.Node.group.build.call(group_end, state, target);
  10466         } else {
  10467             CSL.Util.substituteStart.call(this, state, target);
  10468             if (!this.variables_real) {
  10469                 this.variables_real = [];
  10470             }
  10471             if (!this.variables) {
  10472                 this.variables = [];
  10473             }
  10474             form = "long";
  10475             plural = 0;
  10476             if (this.strings.form) {
  10477                 form = this.strings.form;
  10478             }
  10479             if (this.strings.plural) {
  10480                 plural = this.strings.plural;
  10481             }
  10482             if ("citation-number" === this.variables_real[0] || "year-suffix" === this.variables_real[0] || "citation-label" === this.variables_real[0]) {
  10483                 if (this.variables_real[0] === "citation-number") {
  10484                     if (state.build.root === "citation") {
  10485                         state.opt.update_mode = CSL.NUMERIC;
  10486                     }
  10487                     if (state.build.root === "bibliography") {
  10488                         state.opt.bib_mode = CSL.NUMERIC;
  10489                     }
  10490                     if (state.build.area === "bibliography_sort") {
  10491                         state.opt.citation_number_sort_used = true;
  10492                     }
  10493                     if ("citation-number" === state[state.tmp.area].opt.collapse) {
  10494                         this.range_prefix = state.getTerm("citation-range-delimiter");
  10495                     }
  10496                     this.successor_prefix = state[state.build.area].opt.layout_delimiter;
  10497                     this.splice_prefix = state[state.build.area].opt.layout_delimiter;
  10498                     func = function (state, Item, item) {
  10499                         id = "" + Item.id;
  10500                         if (!state.tmp.just_looking) {
  10501                             if (item && item["author-only"]) {
  10502                                 state.tmp.element_trace.replace("do-not-suppress-me");
  10503                                 var reference_term = state.getTerm("reference", "long", "singular");
  10504                                 if ("undefined" === typeof reference_term) {
  10505                                     reference_term = "reference";
  10506                                 }
  10507                                 term = CSL.Output.Formatters["capitalize-first"](state, reference_term);
  10508                                 state.output.append(term + " ");
  10509                                 state.tmp.last_element_trace = true;
  10510                             }
  10511                             if (item && item["suppress-author"]) {
  10512                                 if (state.tmp.last_element_trace) {
  10513                                     state.tmp.element_trace.replace("suppress-me");
  10514                                 }
  10515                                 state.tmp.last_element_trace = false;
  10516                             }
  10517                             num = state.registry.registry[id].seq;
  10518                             if (state.opt.citation_number_slug) {
  10519                                 state.output.append(state.opt.citation_number_slug, this);
  10520                             } else {
  10521                                 number = new CSL.NumericBlob(false, num, this, Item.id);
  10522                                 if (state.tmp.in_cite_predecessor) {
  10523                                     if (!state.tmp.just_looking) {
  10524                                     }
  10525                                     number.suppress_splice_prefix = true;
  10526                                 }
  10527                                 state.output.append(number, "literal");
  10528                             }
  10529                         }
  10530                     };
  10531                     this.execs.push(func);
  10532                 } else if (this.variables_real[0] === "year-suffix") {
  10533                     state.opt.has_year_suffix = true;
  10534                     if (state[state.tmp.area].opt.collapse === "year-suffix-ranged") {
  10535                         this.range_prefix = state.getTerm("citation-range-delimiter");
  10536                     }
  10537                     this.successor_prefix = state[state.build.area].opt.layout_delimiter;
  10538                     if (state[state.tmp.area].opt["year-suffix-delimiter"]) {
  10539                         this.successor_prefix = state[state.build.area].opt["year-suffix-delimiter"];
  10540                     }
  10541                     func = function (state, Item) {
  10542                         if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.just_looking) {
  10543                             num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10);
  10544                             if (state[state.tmp.area].opt.cite_group_delimiter) {
  10545                                 this.successor_prefix = state[state.tmp.area].opt.cite_group_delimiter;
  10546                             }
  10547                             number = new CSL.NumericBlob(false, num, this, Item.id);
  10548                             formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS);
  10549                             number.setFormatter(formatter);
  10550                             state.output.append(number, "literal");
  10551                             firstoutput = false;
  10552                             for (var i=0,ilen=state.tmp.group_context.mystack.length; i<ilen; i++) {
  10553                                 var flags = state.tmp.group_context.mystack[i];
  10554                                 if (!flags.variable_success && (flags.variable_attempt || (!flags.variable_attempt && !flags.term_intended))) {
  10555                                     firstoutput = true;
  10556                                     break;
  10557                                 }
  10558                             }
  10559                             specialdelimiter = state[state.tmp.area].opt["year-suffix-delimiter"];
  10560                             if (firstoutput && specialdelimiter && !state.tmp.sort_key_flag) {
  10561                                 state.tmp.splice_delimiter = state[state.tmp.area].opt["year-suffix-delimiter"];
  10562                             }
  10563                         }
  10564                     };
  10565                     this.execs.push(func);
  10566                 } else if (this.variables_real[0] === "citation-label") {
  10567                     state.opt.has_year_suffix = true;
  10568                     func = function (state, Item) {
  10569                         label = Item["citation-label"];
  10570                         if (!label) {
  10571                             label = state.getCitationLabel(Item);
  10572                         }
  10573                         if (!state.tmp.just_looking) {
  10574                             suffix = "";
  10575                             if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false) {
  10576                                 num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10);
  10577                                 suffix = state.fun.suffixator.format(num);
  10578                             }
  10579                             label += suffix;
  10580                         }
  10581                         state.output.append(label, this);
  10582                     };
  10583                     this.execs.push(func);
  10584                 }
  10585             } else {
  10586                 if (this.strings.term) {
  10587                     func = function (state, Item, item) {
  10588                         var gender = state.opt.gender[Item.type];
  10589                         var term = this.strings.term;
  10590                         term = state.getTerm(term, form, plural, gender, CSL.TOLERANT, this.default_locale);
  10591                         var myterm;
  10592                         if (term !== "") {
  10593                             state.tmp.group_context.tip.term_intended = true;
  10594                         }
  10595                         CSL.UPDATE_GROUP_CONTEXT_CONDITION(state, term);
  10596                         if (!state.tmp.term_predecessor && !(state.opt["class"] === "in-text" && state.tmp.area === "citation")) {
  10597                             myterm = CSL.Output.Formatters["capitalize-first"](state, term);
  10598                         } else {
  10599                             myterm = term;
  10600                         }
  10601                         if (state.tmp.strip_periods) {
  10602                             myterm = myterm.replace(/\./g, "");
  10603                         } else {
  10604                             for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) {
  10605                                 if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) {
  10606                                     myterm = myterm.replace(/\./g, "");
  10607                                     break;
  10608                                 }
  10609                             }
  10610                         }
  10611                         state.output.append(myterm, this);
  10612                     };
  10613                     this.execs.push(func);
  10614                     state.build.term = false;
  10615                     state.build.form = false;
  10616                     state.build.plural = false;
  10617                 } else if (this.variables_real.length) {
  10618                     func = function (state, Item, item) {
  10619                         if (this.variables_real[0] !== "locator") {
  10620                             state.tmp.have_collapsed = false;
  10621                         }
  10622                         var parallel_variable = this.variables[0];
  10623                         if (parallel_variable === "title" 
  10624                             && (form === "short" || Item["title-short"])) { 
  10625                             parallel_variable = "title-short";
  10626                         }
  10627                         state.parallel.StartVariable(parallel_variable);
  10628                         state.parallel.AppendToVariable(Item[parallel_variable],parallel_variable);
  10629                         if (!state.tmp.group_context.tip.condition && Item[this.variables[0]]) {
  10630                             state.tmp.just_did_number = false;
  10631                         }
  10632                     };
  10633                     this.execs.push(func);
  10634                     if (CSL.MULTI_FIELDS.indexOf(this.variables_real[0]) > -1
  10635                         || ["language-name", "language-name-original"].indexOf(this.variables_real[0]) > -1) {
  10636                         var abbrevfam = this.variables[0];
  10637                         var abbrfall = false;
  10638                         var altvar = false;
  10639                         var transfall = false;
  10640                         if (form === "short" || ["country", "jurisdiction"].indexOf(this.variables_real[0]) > -1) {
  10641                             if (this.variables_real[0] === "container-title") {
  10642                                 altvar = "journalAbbreviation";
  10643                             } else if (this.variables_real[0] === "title") {
  10644                                 altvar = "title-short";
  10645                             }
  10646                         } else {
  10647                             abbrevfam = false;
  10648                         }
  10649                         if (state.build.extension) {
  10650                             transfall = true;
  10651                         } else {
  10652                             transfall = true;
  10653                             abbrfall = true;
  10654 						}
  10655                         func = state.transform.getOutputFunction(this.variables, abbrevfam, abbrfall, altvar, transfall);
  10656                     } else {
  10657                         if (CSL.CITE_FIELDS.indexOf(this.variables_real[0]) > -1) {
  10658                             func = function (state, Item, item) {
  10659                                 if (item && item[this.variables[0]]) {
  10660                                     state.processNumber(this, item, this.variables[0], Item.type);
  10661                                     CSL.Util.outputNumericField(state, this.variables[0], Item.id);
  10662                                     if (["locator", "locator-extra"].indexOf(this.variables_real[0]) > -1
  10663                                        && !state.tmp.just_looking) { 
  10664                                         state.tmp.done_vars.push(this.variables_real[0]);
  10665                                     }
  10666                                 }
  10667                             };
  10668                         } 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) {
  10669                             func = function(state, Item) {
  10670                                 state.processNumber(this, Item, this.variables[0], Item.type);
  10671                                 CSL.Util.outputNumericField(state, this.variables[0], Item.id);
  10672                             }
  10673                         } else if (["URL", "DOI"].indexOf(this.variables_real[0]) > -1) {
  10674                             func = function (state, Item) {
  10675                                 var value;
  10676                                 if (this.variables[0]) {
  10677                                     value = state.getVariable(Item, this.variables[0], form);
  10678                                     if (value) {
  10679                                         if (state.opt.development_extensions.wrap_url_and_doi) {
  10680                                             if (!this.decorations.length || this.decorations[0][0] !== "@" + this.variables[0]) {
  10681                                                 if (this.variables_real[0] === "DOI" && this.strings.prefix === "https://doi.org/") {
  10682                                                     var clonetoken = CSL.Util.cloneToken(this);
  10683                                                     var groupblob = new CSL.Blob(null, null, "url-wrapper");
  10684                                                     groupblob.decorations.push(["@DOI", "true"]);
  10685                                                     value = value.replace(/^https?:\/\/doi\.org\//, "");
  10686                                                     if (value.match(/^https?:\/\//)) {
  10687                                                         var prefix = "";
  10688                                                     } else {
  10689                                                         var prefix = "https://doi.org/";
  10690                                                     }
  10691                                                     var prefixblob = new CSL.Blob(prefix);
  10692                                                     var valueblob = new CSL.Blob(value);
  10693                                                     clonetoken.strings.prefix = "";
  10694                                                     groupblob.push(prefixblob);
  10695                                                     groupblob.push(valueblob);
  10696                                                     state.output.append(groupblob, clonetoken, false, false, true);
  10697                                                 } else {
  10698                                                     this.decorations = [["@" + this.variables[0], "true"]].concat(this.decorations);
  10699                                                     state.output.append(value, this, false, false, true);
  10700                                                 }
  10701                                             } else {
  10702                                                 state.output.append(value, this, false, false, true);
  10703                                             }
  10704                                         } else {
  10705                                             if (this.decorations.length) {
  10706                                                 for (var i=this.decorations.length-1; i>-1; i--) {
  10707                                                     if (this.decorations[i][0] === "@" + this.variables[0]) {
  10708                                                         this.decorations = this.decorations.slice(0, i).concat(this.decorations.slice(i+1));
  10709                                                     }
  10710                                                 }
  10711                                             }
  10712                                             state.output.append(value, this, false, false, true);
  10713                                         }
  10714                                     }
  10715                                 }
  10716                             };
  10717                         } else if (this.variables_real[0] === "section") {
  10718                             func = function (state, Item) {
  10719                                 var value;
  10720                                 value = state.getVariable(Item, this.variables[0], form);
  10721                                 if (value) {
  10722                                     state.output.append(value, this);
  10723                                 }
  10724                             };
  10725                         } else if (this.variables_real[0] === "hereinafter") {
  10726                             func = function (state, Item) {
  10727                                 var value = state.transform.abbrevs["default"]["hereinafter"][Item.id];
  10728                                 if (value) {
  10729                                     state.output.append(value, this);
  10730                                     state.tmp.group_context.tip.variable_success = true;
  10731                                 }
  10732                             }
  10733                         } else {
  10734                             func = function (state, Item) {
  10735                                 var value;
  10736                                 if (this.variables[0]) {
  10737                                     value = state.getVariable(Item, this.variables[0], form);
  10738                                     if (value) {
  10739                                         value = "" + value;
  10740                                         value = value.split("\\").join("");
  10741                                         state.output.append(value, this);
  10742                                     }
  10743                                 }
  10744                             };
  10745                         }
  10746                     }
  10747                     this.execs.push(func);
  10748                     func = function (state, Item) {
  10749                         state.parallel.CloseVariable("text");
  10750                     };
  10751                     this.execs.push(func);
  10752                 } else if (this.strings.value) {
  10753                     func = function (state, Item) {
  10754                         state.tmp.group_context.tip.term_intended = true;
  10755                         CSL.UPDATE_GROUP_CONTEXT_CONDITION(state, this.strings.value, true);
  10756                         state.output.append(this.strings.value, this);
  10757                     };
  10758                     this.execs.push(func);
  10759                 }
  10760             }
  10761             target.push(this);
  10762             CSL.Util.substituteEnd.call(this, state, target);
  10763         }
  10764     }
  10765 };
  10766 CSL.Attributes = {};
  10767 CSL.Attributes["@genre"] = function (state, arg) {
  10768     arg = arg.replace("-", " ");
  10769     var func = function (Item, item) {
  10770         var ret;
  10771         if (arg === Item.genre) {
  10772             return true;
  10773         }
  10774         return false;
  10775     }
  10776     this.tests.push(func);
  10777 }
  10778 CSL.Attributes["@disambiguate"] = function (state, arg) {
  10779     if (arg === "true") {
  10780         state.opt.has_disambiguate = true;
  10781         var func = function (Item, item) {
  10782             if (state.tmp.area === "bibliography") {
  10783                 if (state.tmp.disambiguate_count < state.registry.registry[Item.id].disambig.disambiguate) {
  10784                     state.tmp.disambiguate_count += 1;
  10785                     return true;
  10786                 }
  10787             } else {
  10788                 state.tmp.disambiguate_maxMax += 1;
  10789                 if (state.tmp.disambig_settings.disambiguate
  10790                     && state.tmp.disambiguate_count < state.tmp.disambig_settings.disambiguate) {
  10791                     state.tmp.disambiguate_count += 1;
  10792                     return true;
  10793                 }
  10794             }
  10795             return false;
  10796         };
  10797         this.tests.push(func);
  10798     } else if (arg === "check-ambiguity-and-backreference") {
  10799         var func = function (Item, item) {
  10800             if (state.registry.registry[Item.id].disambig.disambiguate && state.registry.registry[Item.id]["citation-count"] > 1) {
  10801                 return true;
  10802             }
  10803             return false;
  10804         };
  10805         this.tests.push(func);
  10806     }
  10807 };
  10808 CSL.Attributes["@is-numeric"] = function (state, arg, joiner) {
  10809     var variables = arg.split(/\s+/);
  10810     var maketest = function(variable) {
  10811         return function (Item, item) {
  10812             var myitem = Item;
  10813             if (["locator","locator-extra"].indexOf(variable) > -1) {
  10814                 myitem = item;
  10815             }
  10816             if ("undefined" === typeof myitem) {
  10817                 return false;
  10818             }
  10819             if (CSL.NUMERIC_VARIABLES.indexOf(variable) > -1) {
  10820                 if (!state.tmp.shadow_numbers[variable]) {
  10821                     state.processNumber(false, myitem, variable, Item.type);
  10822                 }
  10823                 if (myitem[variable] && state.tmp.shadow_numbers[variable].numeric) {
  10824                     return true;
  10825                 }
  10826             } else if (["title", "locator-extra","version"].indexOf(variable) > -1) {
  10827                 if (myitem[variable]) {
  10828                     if (myitem[variable].slice(-1) === "" + parseInt(myitem[variable].slice(-1), 10)) {
  10829                         return true;
  10830                     }
  10831                 }
  10832             }
  10833             return false;
  10834         }
  10835     }
  10836     for (var i=0; i<variables.length; i+=1) {
  10837         this.tests.push(maketest(variables[i]));
  10838     }
  10839 };
  10840 CSL.Attributes["@is-uncertain-date"] = function (state, arg) {
  10841     var variables = arg.split(/\s+/);
  10842     var maketest = function (myvariable) {
  10843         return function(Item, item) {
  10844             if (Item[myvariable] && Item[myvariable].circa) {
  10845                 return true;
  10846             } else {
  10847                 return false;
  10848             }
  10849         }
  10850     }
  10851     for (var i=0,ilen=variables.length;i<ilen;i+=1) {
  10852         this.tests.push(maketest(variables[i]));
  10853     };
  10854 };
  10855 CSL.Attributes["@locator"] = function (state, arg) {
  10856     var trylabels = arg.replace("sub verbo", "sub-verbo");
  10857     trylabels = trylabels.split(/\s+/);
  10858     var maketest = function (trylabel) {
  10859         return function(Item, item) {
  10860             var label;
  10861             state.processNumber(false, item, "locator");
  10862             label = state.tmp.shadow_numbers.locator.label;
  10863             if (trylabel === label) {
  10864                 return true;
  10865             } else {
  10866                 return false;
  10867             }
  10868         }
  10869     }
  10870     for (var i=0,ilen=trylabels.length;i<ilen;i+=1) {
  10871         this.tests.push(maketest(trylabels[i]));
  10872     }
  10873 };
  10874 CSL.Attributes["@position"] = function (state, arg) {
  10875     var tryposition;
  10876     state.opt.update_mode = CSL.POSITION;
  10877     state.parallel.use_parallels = null;
  10878     var trypositions = arg.split(/\s+/);
  10879     var maketest = function(tryposition) {
  10880         return function (Item, item) {
  10881             if (state.tmp.area === "bibliography") {
  10882                 return false;
  10883             }
  10884             if (item && "undefined" === typeof item.position) {
  10885                 item.position = 0;
  10886             }
  10887             if (item && typeof item.position === "number") {
  10888                 if (item.position === 0 && tryposition === 0) {
  10889                     return true;
  10890                 } else if (tryposition > 0 && item.position >= tryposition) {
  10891                     return true;
  10892                 }
  10893             } else if (tryposition === 0) {
  10894                 return true;
  10895             }
  10896             return false;
  10897         }
  10898     }
  10899     for (var i=0,ilen=trypositions.length;i<ilen;i+=1) {
  10900         var tryposition = trypositions[i];
  10901         if (tryposition === "first") {
  10902             tryposition = CSL.POSITION_FIRST;
  10903         } else if (tryposition === "subsequent") {
  10904             tryposition = CSL.POSITION_SUBSEQUENT;
  10905         } else if (tryposition === "ibid") {
  10906             tryposition = CSL.POSITION_IBID;
  10907         } else if (tryposition === "ibid-with-locator") {
  10908             tryposition = CSL.POSITION_IBID_WITH_LOCATOR;
  10909         }
  10910         if ("near-note" === tryposition) {
  10911             this.tests.push(function (Item, item) {
  10912                 if (item && item.position >= CSL.POSITION_SUBSEQUENT && item["near-note"]) {
  10913                     return true;
  10914                 }
  10915                 return false;
  10916             });
  10917         } else if ("far-note" === tryposition) {
  10918             this.tests.push(function (Item, item) {
  10919                 if (item && item.position == CSL.POSITION_SUBSEQUENT && !item["near-note"]) {
  10920                     return true;
  10921                 }
  10922                 return false;
  10923             });
  10924         } else {
  10925             this.tests.push(maketest(tryposition));
  10926         }
  10927     }
  10928 };
  10929 CSL.Attributes["@type"] = function (state, arg) {
  10930     var types = arg.split(/\s+/);
  10931     var maketest = function (mytype) {
  10932         return function(Item,item) {
  10933             var ret = (Item.type === mytype);
  10934             if (ret) {
  10935                 return true;
  10936             } else {
  10937                 return false;
  10938             }
  10939         }
  10940     }
  10941     var tests = [];
  10942     for (var i=0,ilen=types.length;i<ilen;i+=1) {
  10943         tests.push(maketest(types[i]));
  10944     }
  10945     this.tests.push(state.fun.match.any(this, state, tests));
  10946 };
  10947 CSL.Attributes["@variable"] = function (state, arg) {
  10948     var func;
  10949     this.variables = arg.split(/\s+/);
  10950     this.variables_real = this.variables.slice();
  10951     if ("label" === this.name && this.variables[0]) {
  10952         this.strings.term = this.variables[0];
  10953     } else if (["names", "date", "text", "number"].indexOf(this.name) > -1) {
  10954         func = function (state, Item, item) {
  10955             for (var i = this.variables.length - 1; i > -1; i += -1) {
  10956                 this.variables.pop();
  10957             }
  10958             for (var i=0,ilen=this.variables_real.length;i<ilen;i++) {
  10959                 if (state.tmp.done_vars.indexOf(this.variables_real[i]) === -1 
  10960                     && !(item && Item.type === "legal_case" && item["suppress-author"] && this.variables_real[i] === "title")
  10961                    ) {
  10962                     this.variables.push(this.variables_real[i]);
  10963                 }
  10964                 if (state.tmp.can_block_substitute) {
  10965                     state.tmp.done_vars.push(this.variables_real[i]);
  10966                 }
  10967             }
  10968         };
  10969         this.execs.push(func);
  10970         func = function (state, Item, item) {
  10971             var mydate;
  10972             var output = false;
  10973             for (var i=0,ilen=this.variables.length;i<ilen;i++) {
  10974                 var variable = this.variables[i];
  10975                 if (["authority", "committee"].indexOf(variable) > -1
  10976                     && "string" === typeof Item[variable]
  10977                     && "names" === this.name) {
  10978                     var creatorParents = [];
  10979                     var isValid = true;
  10980                     var rawNames = Item[variable].split(/\s*;\s*/);
  10981                     var rawMultiNames = {};
  10982                     if (Item.multi && Item.multi._keys[variable]) {
  10983                         for (var langTag in Item.multi._keys[variable]) {
  10984                             rawMultiNames[langTag] = Item.multi._keys[variable][langTag].split(/\s*;\s*/);
  10985                             if (rawMultiNames[langTag].length !== rawNames.length) {
  10986                                 isValid = false;
  10987                                 break;
  10988                             }
  10989                         }
  10990                     }
  10991                     if (!isValid) {
  10992                         rawNames = [Item[variable]];
  10993                         rawMultiNames = Item.multi._keys[variable];
  10994                     }
  10995                     for (var j = 0, jlen = rawNames.length; j < jlen; j++) {
  10996                         var creatorParent = {
  10997                             literal:rawNames[j],
  10998                             multi:{
  10999                                 _key:{}
  11000                             }
  11001                         };
  11002                         for (var langTag in rawMultiNames) {
  11003                             var creatorChild = {
  11004                                 literal:rawMultiNames[langTag][j]
  11005                             }
  11006                             creatorParent.multi._key[langTag] = creatorChild;
  11007                         }
  11008                         rawNames[j] = creatorParent;
  11009                     }
  11010                     Item[variable] = rawNames;
  11011                 }
  11012                 if (this.strings.form === "short" && !Item[variable]) {
  11013                     if (variable === "title") {
  11014                         variable = "title-short";
  11015                     } else if (variable === "container-title") {
  11016                         variable = "journalAbbreviation";
  11017                     }
  11018                 }
  11019                 if (variable === "year-suffix") {
  11020                     output = true;
  11021                     break;
  11022                 } else if (CSL.DATE_VARIABLES.indexOf(variable) > -1) {
  11023                     if (state.opt.development_extensions.locator_date_and_revision && "locator-date" === variable) {
  11024                         output = true;
  11025                         break;
  11026                     }
  11027                     if (Item[variable]) {
  11028                         for (var key in Item[variable]) {
  11029                             if (this.dateparts.indexOf(key) === -1 && "literal" !== key) {
  11030                                 continue;
  11031                             }
  11032                             if (Item[variable][key]) {
  11033                                 output = true;
  11034                                 break;
  11035                             }
  11036                         }
  11037                         if (output) {
  11038                             break;
  11039                         }
  11040                     }
  11041                 } else if ("locator" === variable) {
  11042                     if (item && item.locator) {
  11043                         output = true;
  11044                     }
  11045                     break;
  11046                 } else if ("locator-extra" === variable) {
  11047                     if (item && item["locator-extra"]) {
  11048                         output = true;
  11049                     }
  11050                     break;
  11051                 } else if (["citation-number","citation-label"].indexOf(variable) > -1) {
  11052                     output = true;
  11053                     break;
  11054                 } else if ("first-reference-note-number" === variable) {
  11055                     if (item && item["first-reference-note-number"]) {
  11056                         output = true;
  11057                     }
  11058                     break;
  11059                 } else if ("hereinafter" === variable) {
  11060                     if (state.transform.abbrevs["default"].hereinafter[Item.id]
  11061                         && state.sys.getAbbreviation
  11062                         && Item.id) {
  11063                         output = true;
  11064                     }
  11065                     break;
  11066                 } else if ("object" === typeof Item[variable]) {
  11067                     if (Item[variable].length) {
  11068                     }
  11069                     break;
  11070                 } else if ("string" === typeof Item[variable] && Item[variable]) {
  11071                     output = true;
  11072                     break;
  11073                 } else if ("number" === typeof Item[variable]) {
  11074                     output = true;
  11075                     break;
  11076                 }
  11077                 if (output) {
  11078                     break;
  11079                 }
  11080             }
  11081             if (output) {
  11082                 for (var i=0,ilen=this.variables_real.length;i<ilen;i++) {
  11083                     var variable = this.variables_real[i];
  11084                     if (variable !== "citation-number" || state.tmp.area !== "bibliography") {
  11085                         state.tmp.cite_renders_content = true;
  11086                     }
  11087                     state.tmp.group_context.tip.variable_success = true;
  11088                     if (state.tmp.can_substitute.value() 
  11089                         && state.tmp.area === "bibliography"
  11090                         && "string" === typeof Item[variable]) {
  11091                         state.tmp.name_node.top = state.output.current.value();
  11092                         state.tmp.rendered_name.push(Item[variable]);
  11093                     }
  11094                 }
  11095                 state.tmp.can_substitute.replace(false,  CSL.LITERAL);
  11096             } else {
  11097                 state.tmp.group_context.tip.variable_attempt = true;
  11098             }
  11099         };
  11100         this.execs.push(func);
  11101     } else if (["if",  "else-if", "condition"].indexOf(this.name) > -1) {
  11102         var maketest = function (variable) {
  11103             return function(Item,item){
  11104                 var myitem = Item;
  11105                 if (item && ["locator", "locator-extra", "first-reference-note-number", "locator-date"].indexOf(variable) > -1) {
  11106                     myitem = item;
  11107                 }
  11108                 if (variable === "hereinafter" && state.sys.getAbbreviation && myitem.id) {
  11109                     if (state.transform.abbrevs["default"].hereinafter[myitem.id]) {
  11110                         return true;
  11111                     }
  11112                 } else if (myitem[variable]) {
  11113                     if ("number" === typeof myitem[variable] || "string" === typeof myitem[variable]) {
  11114                         return true;
  11115                     } else if ("object" === typeof myitem[variable]) {
  11116                         for (var key in myitem[variable]) {
  11117                             if (myitem[variable][key]) {
  11118                                 return true;
  11119                             }
  11120                         }
  11121                     }
  11122                 }
  11123                 return false;
  11124             }
  11125         }
  11126         for (var i=0,ilen=this.variables.length;i<ilen;i+=1) {
  11127             this.tests.push(maketest(this.variables[i]));
  11128         }
  11129     }
  11130 };
  11131 CSL.Attributes["@page"] = function (state, arg) {
  11132     var trylabels = arg.replace("sub verbo", "sub-verbo");
  11133     trylabels = trylabels.split(/\s+/);
  11134     var maketest = function (trylabel) {
  11135         return function(Item, item) {
  11136             var label;
  11137             state.processNumber(false, Item, "page", Item.type);
  11138             if (!state.tmp.shadow_numbers.page.label) {
  11139                 label = "page";
  11140             } else if (state.tmp.shadow_numbers.page.label === "sub verbo") {
  11141                 label = "sub-verbo";
  11142             } else {
  11143                 label = state.tmp.shadow_numbers.page.label;
  11144             }
  11145             if (trylabel === label) {
  11146                 return true;
  11147             } else {
  11148                 return false;
  11149             }
  11150         }
  11151     }
  11152     for (var i=0,ilen=trylabels.length;i<ilen;i+=1) {
  11153         this.tests.push(maketest(trylabels[i]));
  11154     }
  11155 };
  11156 CSL.Attributes["@number"] = function (state, arg) {
  11157     var trylabels = arg.replace("sub verbo", "sub-verbo");
  11158     trylabels = trylabels.split(/\s+/);
  11159     var maketest = function(trylabel) {
  11160         return function (Item, item) {
  11161             var label;
  11162             state.processNumber(false, Item, "number", Item.type);
  11163             if (!state.tmp.shadow_numbers.number.label) {
  11164                 label = "number";
  11165             } else if (state.tmp.shadow_numbers.number.label === "sub verbo") {
  11166                 label = "sub-verbo";
  11167             } else {
  11168                 label = state.tmp.shadow_numbers.number.label;
  11169             }
  11170             if (trylabel === label) {
  11171                 return true;
  11172             } else {
  11173                 return false;
  11174             }
  11175         }
  11176     }
  11177     for (var i=0,ilen=trylabels.length;i<ilen;i+=1) {
  11178         this.tests.push(maketest(trylabels[i]));
  11179     }
  11180 };
  11181 CSL.Attributes["@jurisdiction"] = function (state, arg) {
  11182     var tryjurisdictions = arg.split(/\s+/);
  11183     for (var i=0,ilen=tryjurisdictions.length;i<ilen;i+=1) {
  11184         tryjurisdictions[i] = tryjurisdictions[i].split(":");
  11185     }
  11186     var maketests = function (tryjurisdiction) {
  11187         return function(Item,item){
  11188             if (!Item.jurisdiction) {
  11189                 return false;
  11190             }
  11191             var jurisdictions = Item.jurisdiction.split(":");
  11192             for (var i=0,ilen=jurisdictions.length;i<ilen;i+=1) {
  11193                 jurisdictions[i] = jurisdictions[i].split(":");
  11194             }
  11195             for (i=tryjurisdiction.length;i>0;i+=-1) {
  11196                 var tryjurisdictionStr = tryjurisdiction.slice(0,i).join(":");
  11197                 var jurisdiction = jurisdictions.slice(0,i).join(":");
  11198                 if (tryjurisdictionStr !== jurisdiction) {
  11199                     return false;
  11200                 }
  11201             }
  11202             return true;
  11203         }
  11204     }
  11205     for (var i=0,ilen=tryjurisdictions.length;i<ilen;i+=1) {
  11206         var tryjurisdictionSlice = tryjurisdictions[i].slice();
  11207         this.tests.push(maketests(tryjurisdictionSlice));
  11208     }
  11209 };
  11210 CSL.Attributes["@context"] = function (state, arg) {
  11211     var func = function (Item, item) {
  11212 		var area = state.tmp.area.slice(0, arg.length);
  11213 		if (area === arg) {
  11214 			return true;
  11215 		}
  11216 		return false;
  11217     };
  11218     this.tests.push(func);
  11219 };
  11220 CSL.Attributes["@has-year-only"] = function (state, arg) {
  11221     var trydates = arg.split(/\s+/);
  11222     var maketest = function (trydate) {
  11223         return function(Item,item){
  11224             var date = Item[trydate];
  11225             if (!date || date.month || date.season) {
  11226                 return false;
  11227             } else {
  11228                 return true;
  11229             }
  11230         }
  11231     }
  11232     for (var i=0,ilen=trydates.length;i<ilen;i+=1) {
  11233         this.tests.push(maketest(trydates[i]));
  11234     }
  11235 };
  11236 CSL.Attributes["@has-to-month-or-season"] = function (state, arg) {
  11237     var trydates = arg.split(/\s+/);
  11238     var maketest = function (trydate) {
  11239         return function(Item,item){
  11240             var date = Item[trydate];
  11241             if (!date || (!date.month && !date.season) || date.day) {
  11242                 return false;
  11243             } else {
  11244                 return true;
  11245             }
  11246         }
  11247     }
  11248     for (var i=0,ilen=trydates.length;i<ilen;i+=1) {
  11249         this.tests.push(maketest(trydates[i]));
  11250     }
  11251 };
  11252 CSL.Attributes["@has-day"] = function (state, arg) {
  11253     var trydates = arg.split(/\s+/);
  11254     var maketest = function (trydate) {
  11255         return function(Item,item){
  11256             var date = Item[trydate];
  11257             if (!date || !date.day) {
  11258                 return false;
  11259             } else {
  11260                 return true;
  11261             }
  11262         }
  11263     }
  11264     for (var i=0,ilen=trydates.length;i<ilen;i+=1) {
  11265         this.tests.push(maketest(trydates[i]));
  11266     };
  11267 };
  11268 CSL.Attributes["@subjurisdictions"] = function (state, arg) {
  11269     var trysubjurisdictions = parseInt(arg, 10);
  11270     var func = function (Item, item) {
  11271         var subjurisdictions = 0;
  11272         if (Item.jurisdiction) {
  11273             subjurisdictions = Item.jurisdiction.split(":").length;
  11274         }
  11275         if (subjurisdictions) {
  11276             subjurisdictions += -1;
  11277         }
  11278         if (subjurisdictions >= trysubjurisdictions) {
  11279             return true;
  11280         }
  11281         return false;
  11282     };
  11283     this.tests.push(func);
  11284 };
  11285 CSL.Attributes["@is-plural"] = function (state, arg) {
  11286     var func = function (Item, item) {
  11287         var nameList = Item[arg];
  11288         if (nameList && nameList.length) {
  11289             var persons = 0;
  11290             var institutions = 0;
  11291             var last_is_person = false;
  11292             for (var i = 0, ilen = nameList.length; i < ilen; i += 1) {
  11293                 if (state.opt.development_extensions.spoof_institutional_affiliations
  11294                     && (nameList[i].literal || (nameList[i].isInstitution && nameList[i].family && !nameList[i].given))) {
  11295                     institutions += 1;
  11296                     last_is_person = false;
  11297                 } else {
  11298                     persons += 1;
  11299                     last_is_person = true;
  11300                 }
  11301             }
  11302             if (persons > 1) {
  11303                 return true;
  11304             } else if (institutions > 1) {
  11305                 return true;
  11306             } else if (institutions && last_is_person) {
  11307                 return true;
  11308             }
  11309         }
  11310         return false;
  11311     };
  11312     this.tests.push(func);
  11313 };
  11314 CSL.Attributes["@locale"] = function (state, arg) {
  11315     var func, ret, len, pos, variable, myitem, langspec, lang, lst, i, ilen, fallback;
  11316     var locale_default = state.opt["default-locale"][0];
  11317     if (this.name === "layout") {
  11318         this.locale_raw = arg;
  11319         if (this.tokentype === CSL.START) {
  11320             var locales = arg.split(/\s+/);
  11321             var sort_locale = {};
  11322             var localeMaster = CSL.localeResolve(locales[0], locale_default);
  11323             if (localeMaster.generic) {
  11324                 sort_locale[localeMaster.generic] = localeMaster.best;
  11325             } else {
  11326                 sort_locale[localeMaster.best] = localeMaster.best;
  11327             }
  11328             for (var i=1,ilen=locales.length;i<ilen;i+=1) {
  11329                 var localeServant = CSL.localeResolve(locales[i], locale_default);
  11330                 if (localeServant.generic) {
  11331                     sort_locale[localeServant.generic] = localeMaster.best;
  11332                 } else {
  11333                     sort_locale[localeServant.best] = localeMaster.best;
  11334                 }
  11335             }
  11336             state[state.build.area].opt.sort_locales.push(sort_locale);
  11337         }
  11338         state.opt.has_layout_locale = true;
  11339     } else {
  11340         lst = arg.split(/\s+/);
  11341         var locale_bares = [];
  11342         for (i = 0, ilen = lst.length; i < ilen; i += 1) {
  11343             lang = lst[i];
  11344             langspec = CSL.localeResolve(lang, locale_default);
  11345             if (lst[i].length === 2) {
  11346                 locale_bares.push(langspec.bare);
  11347             }
  11348             state.localeConfigure(langspec, true);
  11349             lst[i] = langspec;
  11350         }
  11351         var locale_list = lst.slice();
  11352         var maketest = function (locale_list, locale_default,locale_bares) {
  11353             return function (Item, item) {
  11354                 var key, res;
  11355                 ret = [];
  11356                 res = false;
  11357                 var langspec = false;
  11358                 var lang;
  11359                 if (!Item.language) {
  11360                     lang = locale_default;
  11361                 } else {
  11362                     lang = Item.language;
  11363                 }
  11364                 langspec = CSL.localeResolve(lang, locale_default);
  11365                 for (i = 0, ilen = locale_list.length; i < ilen; i += 1) {
  11366                     if (langspec.best === locale_list[i].best) {
  11367                         res = true;
  11368                         break;
  11369                     }
  11370                 }
  11371                 if (!res && locale_bares.indexOf(langspec.bare) > -1) {
  11372                     res = true;
  11373                 }
  11374                 return res;
  11375             }
  11376         }
  11377         this.tests.push(maketest(locale_list,locale_default,locale_bares));
  11378     }
  11379 };
  11380 CSL.Attributes["@authority-residue"] = function (state, arg) {
  11381     var maketest = function () {
  11382         var succeed = (arg === "true") ? true : false;
  11383         return function(Item, item) {
  11384             if (!Item.authority || !Item.authority[0] || !Item.authority[0].family) return !succeed;
  11385             var varLen = Item.authority[0].family.split("|").length;
  11386             var stopLast = state.tmp.authority_stop_last;
  11387             if ((varLen + stopLast) > 0) {
  11388                 return succeed;
  11389             } else {
  11390                 return !succeed;
  11391             }
  11392         }
  11393     }
  11394     this.tests.push(maketest());
  11395 }
  11396 CSL.Attributes["@locale-internal"] = function (state, arg) {
  11397     var func, ret, len, pos, variable, myitem, langspec, lang, lst, i, ilen, fallback;
  11398         lst = arg.split(/\s+/);
  11399         this.locale_bares = [];
  11400         for (i = 0, ilen = lst.length; i < ilen; i += 1) {
  11401             lang = lst[i];
  11402             langspec = CSL.localeResolve(lang, state.opt["default-locale"][0]);
  11403             if (lst[i].length === 2) {
  11404                 this.locale_bares.push(langspec.bare);
  11405             }
  11406             state.localeConfigure(langspec);
  11407             lst[i] = langspec;
  11408         }
  11409         this.locale_default = state.opt["default-locale"][0];
  11410         this.locale = lst[0].best;
  11411         this.locale_list = lst.slice();
  11412         var maketest = function (me) {
  11413             return function (Item, item) {
  11414                 var key, res;
  11415                 ret = [];
  11416                 res = false;
  11417                 var langspec = false;
  11418                 if (Item.language) {
  11419                     lang = Item.language;
  11420                     langspec = CSL.localeResolve(lang, state.opt["default-locale"][0]);
  11421                     if (langspec.best === state.opt["default-locale"][0]) {
  11422                         langspec = false;
  11423                     }
  11424                 }
  11425                 if (langspec) {
  11426                     for (i = 0, ilen = me.locale_list.length; i < ilen; i += 1) {
  11427                         if (langspec.best === me.locale_list[i].best) {
  11428                             state.opt.lang = me.locale;
  11429                             state.tmp.last_cite_locale = me.locale;
  11430                             state.output.openLevel("empty");
  11431                             state.output.current.value().new_locale = me.locale;
  11432                             res = true;
  11433                             break;
  11434                         }
  11435                     }
  11436                     if (!res && me.locale_bares.indexOf(langspec.bare) > -1) {
  11437                         state.opt.lang = me.locale;
  11438                         state.tmp.last_cite_locale = me.locale;
  11439                         state.output.openLevel("empty");
  11440                         state.output.current.value().new_locale = me.locale;
  11441                         res = true;
  11442                     }
  11443                 }
  11444                 return res;
  11445             }
  11446         }
  11447         var me = this;
  11448         this.tests.push(maketest(me));
  11449 }
  11450 CSL.Attributes["@is-parallel"] = function (state, arg) {
  11451     var values = arg.split(" ");
  11452     for (var i = 0, ilen = values.length; i < ilen; i += 1) {
  11453         if (values[i] === "true") {
  11454             values[i] = true;
  11455         } else if (values[i] === "false") {
  11456             values[i] = false;
  11457         }
  11458     }
  11459     this.strings.set_parallel_condition = values;
  11460 };
  11461 CSL.Attributes["@jurisdiction-depth"] = function (state, arg) {
  11462     this.strings.jurisdiction_depth = parseInt(arg, 10);
  11463 };
  11464 CSL.Attributes["@require"] = function (state, arg) {
  11465     this.strings.require = arg;
  11466 }
  11467 CSL.Attributes["@reject"] = function (state, arg) {
  11468     this.strings.reject = arg;
  11469 }
  11470 CSL.Attributes["@gender"] = function (state, arg) {
  11471     this.gender = arg;
  11472 }
  11473 CSL.Attributes["@cslid"] = function (state, arg) {
  11474     this.cslid = parseInt(arg, 10);
  11475 };
  11476 CSL.Attributes["@capitalize-if-first"] = function (state, arg) {
  11477     this.strings.capitalize_if_first_override = arg;
  11478 };
  11479 CSL.Attributes["@label-capitalize-if-first"] = function (state, arg) {
  11480     this.strings.label_capitalize_if_first_override = arg;
  11481 };
  11482 CSL.Attributes["@label-form"] = function (state, arg) {
  11483     this.strings.label_form_override = arg;
  11484 };
  11485 CSL.Attributes["@part-separator"] = function (state, arg) {
  11486     this.strings["part-separator"] = arg;
  11487 };
  11488 CSL.Attributes["@leading-noise-words"] = function (state, arg) {
  11489     this["leading-noise-words"] = arg;
  11490 };
  11491 CSL.Attributes["@name-never-short"] = function (state, arg) {
  11492     this["name-never-short"] = arg;
  11493 };
  11494 CSL.Attributes["@class"] = function (state, arg) {
  11495     state.opt["class"] = arg;
  11496 };
  11497 CSL.Attributes["@version"] = function (state, arg) {
  11498     state.opt.version = arg;
  11499 };
  11500 CSL.Attributes["@value"] = function (state, arg) {
  11501     this.strings.value = arg;
  11502 };
  11503 CSL.Attributes["@name"] = function (state, arg) {
  11504     this.strings.name = arg;
  11505 };
  11506 CSL.Attributes["@form"] = function (state, arg) {
  11507     this.strings.form = arg;
  11508 };
  11509 CSL.Attributes["@date-parts"] = function (state, arg) {
  11510     this.strings["date-parts"] = arg;
  11511 };
  11512 CSL.Attributes["@range-delimiter"] = function (state, arg) {
  11513     this.strings["range-delimiter"] = arg;
  11514 };
  11515 CSL.Attributes["@macro"] = function (state, arg) {
  11516     this.postponed_macro = arg;
  11517 };
  11518 CSL.Attributes["@term"] = function (state, arg) {
  11519     if (arg === "sub verbo") {
  11520         this.strings.term = "sub-verbo";
  11521     } else {
  11522         this.strings.term = arg;
  11523     }
  11524 };
  11525 CSL.Attributes["@xmlns"] = function (state, arg) {};
  11526 CSL.Attributes["@lang"] = function (state, arg) {
  11527     if (arg) {
  11528         state.build.lang = arg;
  11529     }
  11530 };
  11531 CSL.Attributes["@lingo"] = function (state, arg) {
  11532 };
  11533 CSL.Attributes["@macro-has-date"] = function (state, arg) {
  11534     this["macro-has-date"] = true;
  11535 };
  11536 CSL.Attributes["@suffix"] = function (state, arg) {
  11537     this.strings.suffix = arg;
  11538 };
  11539 CSL.Attributes["@prefix"] = function (state, arg) {
  11540     this.strings.prefix = arg;
  11541 };
  11542 CSL.Attributes["@delimiter"] = function (state, arg) {
  11543     this.strings.delimiter = arg;
  11544 };
  11545 CSL.Attributes["@match"] = function (state, arg) {
  11546     this.match = arg;
  11547 };
  11548 CSL.Attributes["@names-min"] = function (state, arg) {
  11549     var val = parseInt(arg, 10);
  11550     if (state[state.build.area].opt.max_number_of_names < val) {
  11551         state[state.build.area].opt.max_number_of_names = val;
  11552     }
  11553     this.strings["et-al-min"] = val;
  11554 };
  11555 CSL.Attributes["@names-use-first"] = function (state, arg) {
  11556     this.strings["et-al-use-first"] = parseInt(arg, 10);
  11557 };
  11558 CSL.Attributes["@names-use-last"] = function (state, arg) {
  11559     if (arg === "true") {
  11560         this.strings["et-al-use-last"] = true;
  11561     } else {
  11562         this.strings["et-al-use-last"] = false;
  11563     }
  11564 };
  11565 CSL.Attributes["@sort"] = function (state, arg) {
  11566     if (arg === "descending") {
  11567         this.strings.sort_direction = CSL.DESCENDING;
  11568     }
  11569 };
  11570 CSL.Attributes["@plural"] = function (state, arg) {
  11571     if ("always" === arg || "true" === arg) {
  11572         this.strings.plural = 1;
  11573     } else if ("never" === arg || "false" === arg) {
  11574         this.strings.plural = 0;
  11575     } else if ("contextual" === arg) {
  11576         this.strings.plural = false;
  11577     }
  11578 };
  11579 CSL.Attributes["@has-publisher-and-publisher-place"] = function (state, arg) {
  11580     this.strings["has-publisher-and-publisher-place"] = true;
  11581 };
  11582 CSL.Attributes["@publisher-delimiter-precedes-last"] = function (state, arg) {
  11583     this.strings["publisher-delimiter-precedes-last"] = arg;
  11584 };
  11585 CSL.Attributes["@publisher-delimiter"] = function (state, arg) {
  11586     this.strings["publisher-delimiter"] = arg;
  11587 };
  11588 CSL.Attributes["@publisher-and"] = function (state, arg) {
  11589     this.strings["publisher-and"] = arg;
  11590 };
  11591 CSL.Attributes["@newdate"] = function (state, arg) {
  11592 };
  11593 CSL.Attributes["@givenname-disambiguation-rule"] = function (state, arg) {
  11594     if (CSL.GIVENNAME_DISAMBIGUATION_RULES.indexOf(arg) > -1) {
  11595         state.citation.opt["givenname-disambiguation-rule"] = arg;
  11596     }
  11597 };
  11598 CSL.Attributes["@collapse"] = function (state, arg) {
  11599     if (arg) {
  11600         state[this.name].opt.collapse = arg;
  11601     }
  11602 };
  11603 CSL.Attributes["@cite-group-delimiter"] = function (state, arg) {
  11604     if (arg) {
  11605         state[state.tmp.area].opt.cite_group_delimiter = arg;
  11606     }
  11607 };
  11608 CSL.Attributes["@names-delimiter"] = function (state, arg) {
  11609     state.setOpt(this, "names-delimiter", arg);
  11610 };
  11611 CSL.Attributes["@name-form"] = function (state, arg) {
  11612     state.setOpt(this, "name-form", arg);
  11613 };
  11614 CSL.Attributes["@subgroup-delimiter"] = function (state, arg) {
  11615     this.strings["subgroup-delimiter"] = arg;
  11616 };
  11617 CSL.Attributes["@subgroup-delimiter-precedes-last"] = function (state, arg) {
  11618     this.strings["subgroup-delimiter-precedes-last"] = arg;
  11619 };
  11620 CSL.Attributes["@name-delimiter"] = function (state, arg) {
  11621     state.setOpt(this, "name-delimiter", arg);
  11622 };
  11623 CSL.Attributes["@et-al-min"] = function (state, arg) {
  11624     var val = parseInt(arg, 10);
  11625     if (state[state.build.area].opt.max_number_of_names < val) {
  11626         state[state.build.area].opt.max_number_of_names = val;
  11627     }
  11628     state.setOpt(this, "et-al-min", val);
  11629 };
  11630 CSL.Attributes["@et-al-use-first"] = function (state, arg) {
  11631     state.setOpt(this, "et-al-use-first", parseInt(arg, 10));
  11632 };
  11633 CSL.Attributes["@et-al-use-last"] = function (state, arg) {
  11634     if (arg === "true") {
  11635         state.setOpt(this, "et-al-use-last", true);
  11636     } else {
  11637         state.setOpt(this, "et-al-use-last", false);
  11638     }
  11639 };
  11640 CSL.Attributes["@et-al-subsequent-min"] = function (state, arg) {
  11641     var val = parseInt(arg, 10);
  11642     if (state[state.build.area].opt.max_number_of_names < val) {
  11643         state[state.build.area].opt.max_number_of_names = val;
  11644     }
  11645     state.setOpt(this, "et-al-subsequent-min", val);
  11646 };
  11647 CSL.Attributes["@et-al-subsequent-use-first"] = function (state, arg) {
  11648     state.setOpt(this, "et-al-subsequent-use-first", parseInt(arg, 10));
  11649 };
  11650 CSL.Attributes["@suppress-min"] = function (state, arg) {
  11651     this.strings["suppress-min"] = parseInt(arg, 10);
  11652 };
  11653 CSL.Attributes["@suppress-max"] = function (state, arg) {
  11654     this.strings["suppress-max"] = parseInt(arg, 10);
  11655 };
  11656 CSL.Attributes["@and"] = function (state, arg) {
  11657     state.setOpt(this, "and", arg);
  11658 };
  11659 CSL.Attributes["@delimiter-precedes-last"] = function (state, arg) {
  11660     state.setOpt(this, "delimiter-precedes-last", arg);
  11661 };
  11662 CSL.Attributes["@delimiter-precedes-et-al"] = function (state, arg) {
  11663     state.setOpt(this, "delimiter-precedes-et-al", arg);
  11664 };
  11665 CSL.Attributes["@initialize-with"] = function (state, arg) {
  11666     state.setOpt(this, "initialize-with", arg);
  11667 };
  11668 CSL.Attributes["@initialize"] = function (state, arg) {
  11669     if (arg === "false") {
  11670         state.setOpt(this, "initialize", false);
  11671     }
  11672 };
  11673 CSL.Attributes["@name-as-reverse-order"] = function (state, arg) {
  11674     this["name-as-reverse-order"] = arg;
  11675 };
  11676 CSL.Attributes["@name-as-sort-order"] = function (state, arg) {
  11677     if (this.name === "style-options") {
  11678         this["name-as-sort-order"] = arg;
  11679     } else {
  11680         state.setOpt(this, "name-as-sort-order", arg);
  11681     }
  11682 };
  11683 CSL.Attributes["@sort-separator"] = function (state, arg) {
  11684     state.setOpt(this, "sort-separator", arg);
  11685 };
  11686 CSL.Attributes["@year-suffix-delimiter"] = function (state, arg) {
  11687     state[this.name].opt["year-suffix-delimiter"] = arg;
  11688 };
  11689 CSL.Attributes["@after-collapse-delimiter"] = function (state, arg) {
  11690     state[this.name].opt["after-collapse-delimiter"] = arg;
  11691 };
  11692 CSL.Attributes["@subsequent-author-substitute"] = function (state, arg) {
  11693     state[this.name].opt["subsequent-author-substitute"] = arg;
  11694 };
  11695 CSL.Attributes["@subsequent-author-substitute-rule"] = function (state, arg) {
  11696     state[this.name].opt["subsequent-author-substitute-rule"] = arg;
  11697 };
  11698 CSL.Attributes["@disambiguate-add-names"] = function (state, arg) {
  11699     if (arg === "true") {
  11700         state.opt["disambiguate-add-names"] = true;
  11701     }
  11702 };
  11703 CSL.Attributes["@disambiguate-add-givenname"] = function (state, arg) {
  11704     if (arg === "true") {
  11705         state.opt["disambiguate-add-givenname"] = true;
  11706     }
  11707 };
  11708 CSL.Attributes["@disambiguate-add-year-suffix"] = function (state, arg) {
  11709     if (arg === "true" && state.opt.xclass !== "numeric") {
  11710         state.opt["disambiguate-add-year-suffix"] = true;
  11711     }
  11712 };
  11713 CSL.Attributes["@second-field-align"] = function (state, arg) {
  11714     if (arg === "flush" || arg === "margin") {
  11715         state[this.name].opt["second-field-align"] = arg;
  11716     }
  11717 };
  11718 CSL.Attributes["@hanging-indent"] = function (state, arg) {
  11719     if (arg === "true") {
  11720         state[this.name].opt.hangingindent = 2;
  11721     }
  11722 };
  11723 CSL.Attributes["@line-spacing"] = function (state, arg) {
  11724     if (arg && arg.match(/^[.0-9]+$/)) {
  11725         state[this.name].opt["line-spacing"] = parseFloat(arg, 10);
  11726     }
  11727 };
  11728 CSL.Attributes["@entry-spacing"] = function (state, arg) {
  11729     if (arg && arg.match(/^[.0-9]+$/)) {
  11730         state[this.name].opt["entry-spacing"] = parseFloat(arg, 10);
  11731     }
  11732 };
  11733 CSL.Attributes["@near-note-distance"] = function (state, arg) {
  11734     state[this.name].opt["near-note-distance"] = parseInt(arg, 10);
  11735 };
  11736 CSL.Attributes["@text-case"] = function (state, arg) {
  11737     var func = function (state, Item) {
  11738         if (arg === "normal") {
  11739             this.text_case_normal = true;
  11740         } else {
  11741             this.strings["text-case"] = arg;
  11742             if (arg === "title") {
  11743                 var m = false;
  11744                 var default_locale = state.opt["default-locale"][0].slice(0, 2);
  11745                 if (Item.jurisdiction) {
  11746                     this.strings["text-case"] = "passthrough";
  11747                 }
  11748             }
  11749         }
  11750     };
  11751     this.execs.push(func);
  11752 };
  11753 CSL.Attributes["@page-range-format"] = function (state, arg) {
  11754     state.opt["page-range-format"] = arg;
  11755 };
  11756 CSL.Attributes["@year-range-format"] = function (state, arg) {
  11757     state.opt["year-range-format"] = arg;
  11758 };
  11759 CSL.Attributes["@default-locale"] = function (state, arg) {
  11760     if (this.name === 'style') {
  11761         var lst, len, pos, m, ret;
  11762         var m = arg.match(/-x-(sort|translit|translat)-/g);
  11763         if (m) {
  11764             for (pos = 0, len = m.length; pos < len; pos += 1) {
  11765                 m[pos] = m[pos].replace(/^-x-/, "").replace(/-$/, "");
  11766             }
  11767         }
  11768         lst = arg.split(/-x-(?:sort|translit|translat)-/);
  11769         ret = [lst[0]];
  11770         for (pos = 1, len = lst.length; pos < len; pos += 1) {
  11771             ret.push(m[pos - 1]);
  11772             ret.push(lst[pos]);
  11773         }
  11774         lst = ret.slice();
  11775         len = lst.length;
  11776         for (pos = 1; pos < len; pos += 2) {
  11777             state.opt[("locale-" + lst[pos])].push(lst[(pos + 1)].replace(/^\s*/g, "").replace(/\s*$/g, ""));
  11778         }
  11779         if (lst.length) {
  11780             state.opt["default-locale"] = lst.slice(0, 1);
  11781         } else {
  11782             state.opt["default-locale"] = ["en"];
  11783         }
  11784     } else if (arg === "true") {
  11785         this.default_locale = true;
  11786     }
  11787 };
  11788 CSL.Attributes["@default-locale-sort"] = function (state, arg) {
  11789     var lst, len, pos, m, ret;
  11790     state.opt["default-locale-sort"] = arg;
  11791 };
  11792 CSL.Attributes["@demote-non-dropping-particle"] = function (state, arg) {
  11793     state.opt["demote-non-dropping-particle"] = arg;
  11794 };
  11795 CSL.Attributes["@initialize-with-hyphen"] = function (state, arg) {
  11796     if (arg === "false") {
  11797         state.opt["initialize-with-hyphen"] = false;
  11798     }
  11799 };
  11800 CSL.Attributes["@institution-parts"] = function (state, arg) {
  11801     this.strings["institution-parts"] = arg;
  11802 };
  11803 CSL.Attributes["@if-short"] = function (state, arg) {
  11804     if (arg === "true") {
  11805         this.strings["if-short"] = true;
  11806     }
  11807 };
  11808 CSL.Attributes["@substitute-use-first"] = function (state, arg) {
  11809     this.strings["substitute-use-first"] = parseInt(arg, 10);
  11810 };
  11811 CSL.Attributes["@use-first"] = function (state, arg) {
  11812     this.strings["use-first"] = parseInt(arg, 10);
  11813 };
  11814 CSL.Attributes["@stop-last"] = function (state, arg) {
  11815     this.strings["stop-last"] = parseInt(arg, 10) * -1;
  11816 };
  11817 CSL.Attributes["@use-last"] = function (state, arg) {
  11818     this.strings["use-last"] = parseInt(arg, 10);
  11819 };
  11820 CSL.Attributes["@reverse-order"] = function (state, arg) {
  11821     if ("true" === arg) {
  11822         this.strings["reverse-order"] = true;
  11823     }
  11824 };
  11825 CSL.Attributes["@display"] = function (state, arg) {
  11826     if (state.bibliography.tokens.length === 2) {
  11827         state.opt.using_display = true;
  11828     }
  11829     this.strings.cls = arg;
  11830 };
  11831 CSL.Stack = function (val, literal) {
  11832     this.mystack = [];
  11833     if (literal || val) {
  11834         this.mystack.push(val);
  11835     }
  11836     this.tip = this.mystack[0];
  11837 };
  11838 CSL.Stack.prototype.push = function (val, literal) {
  11839     if (literal || val) {
  11840         this.mystack.push(val);
  11841     } else {
  11842         this.mystack.push("");
  11843     }
  11844     this.tip = this.mystack[this.mystack.length - 1];
  11845 };
  11846 CSL.Stack.prototype.clear = function () {
  11847     this.mystack = [];
  11848     this.tip = {};
  11849 };
  11850 CSL.Stack.prototype.replace = function (val, literal) {
  11851     if (this.mystack.length === 0) {
  11852         throw "Internal CSL processor error: attempt to replace nonexistent stack item with " + val;
  11853     }
  11854     if (literal || val) {
  11855         this.mystack[(this.mystack.length - 1)] = val;
  11856     } else {
  11857         this.mystack[(this.mystack.length - 1)] = "";
  11858     }
  11859     this.tip = this.mystack[this.mystack.length - 1];
  11860 };
  11861 CSL.Stack.prototype.pop = function () {
  11862     var ret = this.mystack.pop();
  11863     if (this.mystack.length) {
  11864         this.tip = this.mystack[this.mystack.length - 1];
  11865     } else {
  11866         this.tip = {};
  11867     }
  11868     return ret;
  11869 };
  11870 CSL.Stack.prototype.value = function () {
  11871     return this.mystack.slice(-1)[0];
  11872 };
  11873 CSL.Stack.prototype.length = function () {
  11874     return this.mystack.length;
  11875 };
  11876 CSL.Parallel = function (state) {
  11877     this.state = state;
  11878     this.sets = new CSL.Stack([]);
  11879     this.try_cite = true;
  11880     this.use_parallels = false;
  11881     this.midVars = ["section", "volume", "container-title", "collection-number", "issue", "page-first", "page", "number"];
  11882     this.ignoreVarsLawGeneral = ["first-reference-note-number", "locator", "label","page-first","page","genre"];
  11883     this.ignoreVarsLawProceduralHistory = ["issued", "first-reference-note-number", "locator", "label","page-first","page","genre","jurisdiction"];
  11884     this.ignoreVarsOrders = ["first-reference-note-number"];
  11885     this.ignoreVarsOther = ["first-reference-note-number", "locator", "label","section","page-first","page"];
  11886 };
  11887 CSL.Parallel.prototype.isMid = function (variable) {
  11888     return (this.midVars.indexOf(variable) > -1);
  11889 };
  11890 CSL.Parallel.prototype.StartCitation = function (sortedItems, out) {
  11891     this.parallel_conditional_blobs_list = [];
  11892     if (this.use_parallels) {
  11893         this.sortedItems = sortedItems;
  11894         this.sortedItemsPos = -1;
  11895         this.sets.clear();
  11896         this.sets.push([]);
  11897         this.in_series = true;
  11898         this.delim_counter = 0;
  11899         this.delim_pointers = [];
  11900         if (out) {
  11901             this.out = out;
  11902         } else {
  11903             this.out = this.state.output.queue;
  11904         }
  11905         this.master_was_neutral_cite = true;
  11906     }
  11907 };
  11908 CSL.Parallel.prototype.StartCite = function (Item, item, prevItemID) {
  11909     var position, len, pos, x, curr, master, last_id, prev_locator, curr_locator, is_master, parallel;
  11910     if (this.use_parallels) {
  11911         if (this.sets.value().length && this.sets.value()[0].itemId == Item.id) {
  11912             this.ComposeSet();
  11913         }
  11914         this.sortedItemsPos += 1;
  11915         if (item) {
  11916             position = item.position;
  11917         }
  11918         this.try_cite = true;
  11919         var has_required_var = false;
  11920         for (var i = 0, ilen = CSL.PARALLEL_MATCH_VARS.length; i < ilen; i += 1) {
  11921             if (Item[CSL.PARALLEL_MATCH_VARS[i]]) {
  11922                 has_required_var = true;
  11923                 break;
  11924             }
  11925         }
  11926         var basics_ok = true;
  11927         var last_cite = this.sets.value().slice(-1)[0];
  11928         if (last_cite && last_cite.Item) {
  11929             var lastJuris = last_cite.Item.jurisdiction ? last_cite.Item.jurisdiction.split(":")[0] : "";
  11930             var thisJuris = Item.jurisdiction ? Item.jurisdiction.split(":")[0] : "";
  11931             if (last_cite.Item.title !== Item.title) {
  11932                 basics_ok = false;
  11933             } else if (lastJuris !== thisJuris) {
  11934                 basics_ok = false;
  11935             } else if (last_cite.Item.type !== Item.type) {
  11936                 basics_ok = false;
  11937             } else if (["article-journal","article-magazine"].indexOf(Item.type) > -1) {
  11938                 if (!this.state.opt.development_extensions.handle_parallel_articles
  11939                    || last_cite.Item["container-title"] !== Item["container-title"]) {
  11940                     basics_ok = false;
  11941                 }
  11942             }
  11943         }
  11944         if (!basics_ok || !has_required_var || CSL.PARALLEL_TYPES.indexOf(Item.type) === -1) {
  11945             this.try_cite = true;
  11946             if (this.in_series) {
  11947                 this.in_series = false;
  11948             }
  11949         }
  11950         this.cite = {};
  11951         this.cite.front = [];
  11952         this.cite.mid = [];
  11953         this.cite.back = [];
  11954         this.cite.front_collapse = {};
  11955         this.cite.back_forceme = [];
  11956         this.cite.position = position;
  11957         this.cite.Item = Item;
  11958         this.cite.itemId = "" + Item.id;
  11959         this.cite.prevItemID = "" + prevItemID;
  11960         this.target = "front";
  11961         if (["treaty"].indexOf(Item.type) > -1) {
  11962             this.ignoreVars = this.ignoreVarsOrders;
  11963         } else if (["article-journal","article-magazine"].indexOf(Item.type) > -1) {
  11964             this.ignoreVars = this.ignoreVarsOther;
  11965         } else if (item && item.prefix) {
  11966             this.ignoreVars = this.ignoreVarsLawProceduralHistory;
  11967             this.cite.useProceduralHistory = true;
  11968             var prev = this.sets.value()[(this.sets.value().length - 1)];
  11969             if (prev && prev.back) {
  11970                 for (var i=prev.back.length-1;i>-1;i+=-1) {
  11971                     if (prev.back[i] && prev[prev.back[i]]) {
  11972                         delete prev[prev.back[i]];
  11973                     }
  11974                 }
  11975             }
  11976         } else {
  11977             this.ignoreVars = this.ignoreVarsLawGeneral;
  11978         }
  11979         if (this.sortedItems && this.sortedItemsPos > 0 && this.sortedItemsPos < this.sortedItems.length) {
  11980             curr = this.sortedItems[this.sortedItemsPos][1];
  11981             last_id = "" + this.sortedItems[(this.sortedItemsPos - 1)][1].id;
  11982             master = this.state.registry.registry[last_id].parallel;
  11983             prev_locator = false;
  11984             if (master == curr.id) {
  11985                 len = this.sortedItemsPos - 1;
  11986                 for (pos = len; pos > -1; pos += -1) {
  11987                     if (this.sortedItems[pos][1].id == Item.id) {
  11988                         prev_locator = this.sortedItems[pos][1].locator;
  11989                         break;
  11990                     }
  11991                 }
  11992                 curr_locator = this.sortedItems[this.sortedItemsPos][1].locator;
  11993                 if (!prev_locator && curr_locator) {
  11994                     curr.position = CSL.POSITION_IBID_WITH_LOCATOR;
  11995                 } else if (curr_locator === prev_locator) {
  11996                     curr.position = CSL.POSITION_IBID;
  11997                 } else {
  11998                     curr.position = CSL.POSITION_IBID_WITH_LOCATOR;
  11999                 }
  12000             }
  12001         } else if (this.state.registry.registry[Item.id]) {
  12002             this.state.registry.registry[Item.id].parallel = false;
  12003         } else {
  12004             this.try_cite = false;
  12005             this.force_collapse = false;
  12006             return;
  12007         }
  12008         this.force_collapse = false;
  12009         if (this.state.registry.registry[Item.id].parallel) {
  12010             this.force_collapse = true;
  12011         }
  12012     }
  12013 };
  12014 CSL.Parallel.prototype.StartVariable = function (variable, real_variable) {
  12015     if (this.use_parallels && (this.try_cite || this.force_collapse)) {
  12016         if (variable === "names") {
  12017             this.variable = variable + ":" + this.target;
  12018         } else {
  12019             this.variable = variable;
  12020         }
  12021         if (this.ignoreVars.indexOf(variable) > -1) {
  12022             return;
  12023         }
  12024         if (variable === "container-title" && this.sets.value().length === 0) {
  12025             this.master_was_neutral_cite = false;
  12026         }
  12027         this.data = {};
  12028         this.data.value = "";
  12029         this.data.blobs = [];
  12030         var is_mid = this.isMid(variable);
  12031         if (real_variable === "authority" && this.variable === "names:front" && this.sets.value().length) {
  12032             var prev = this.sets.value()[(this.sets.value().length - 1)].Item;
  12033             var thisAuthority = false;
  12034             if (this.cite.Item.authority && this.cite.Item.authority.length) {
  12035                 thisAuthority = this.cite.Item.authority[0].literal;
  12036             }
  12037             var thatAuthority = false;
  12038             if (prev.authority && prev.authority.length) {
  12039                 thatAuthority = prev.authority[0].literal;
  12040             }
  12041             if (thisAuthority !== thatAuthority) {
  12042                 this.try_cite = true;
  12043                 this.in_series = false;
  12044             }
  12045          } else if (this.target === "front" && is_mid) {
  12046             this.target = "mid";
  12047         } else if (this.target === "mid" && !is_mid && this.cite.Item.title && variable !== "names") {
  12048             this.target = "back";
  12049         } else if (this.target === "back" && is_mid) {
  12050             this.try_cite = true;
  12051             this.in_series = false;
  12052         }
  12053         if (variable === "number") {
  12054             this.cite.front.push(this.variable);
  12055         } else if (CSL.PARALLEL_COLLAPSING_MID_VARSET.indexOf(variable) > -1) {
  12056             if (["article-journal","article-magazine"].indexOf(this.cite.Item.type) > -1) {
  12057                 this.cite.mid.push(this.variable);
  12058             } else {
  12059                 this.cite.front.push(this.variable);
  12060             }
  12061         } else {
  12062             this.cite[this.target].push(this.variable);
  12063         }
  12064    }
  12065 };
  12066 CSL.Parallel.prototype.AppendBlobPointer = function (blob) {
  12067     if (this.use_parallels) {
  12068         if (this.ignoreVars.indexOf(this.variable) > -1) {
  12069             return;
  12070         }
  12071         if (this.use_parallels && (this.force_collapse || this.try_cite)) {
  12072             if (["article-journal", "article-magazine"].indexOf(this.cite.Item.type) > -1) {
  12073                 if (["volume","page","page-first","issue"].indexOf(this.variable) > -1) {
  12074                     return;
  12075                 }
  12076                 if ("container-title" === this.variable && this.cite.mid.length > 1) {
  12077                     return;
  12078                 }
  12079             }
  12080             if (this.variable && (this.try_cite || this.force_collapse) && blob && blob.blobs) {
  12081                 if (!(this.cite.useProceduralHistory && this.target === "back")) {
  12082                     this.data.blobs.push([blob, blob.blobs.length]);
  12083                 }
  12084             }
  12085         }
  12086     }
  12087 };
  12088 CSL.Parallel.prototype.AppendToVariable = function (str, varname) {
  12089     if (this.use_parallels) {
  12090         if (this.ignoreVars.indexOf(this.variable) > -1) {
  12091             return;
  12092         }
  12093         if (this.try_cite || this.force_collapse) {
  12094             if (this.target !== "back" || true) {
  12095                 this.data.value += "::" + str;
  12096             } else {
  12097                 var prev = this.sets.value()[(this.sets.value().length - 1)];
  12098                 if (prev) {
  12099                     if (prev[this.variable]) {
  12100                         if (prev[this.variable].value) {
  12101                             this.data.value += "::" + str;
  12102                         }
  12103                     }
  12104                 }
  12105             }
  12106         }
  12107     }
  12108 };
  12109 CSL.Parallel.prototype.CloseVariable = function () {
  12110     if (this.use_parallels) {
  12111         if (this.ignoreVars.indexOf(this.variable) > -1) {
  12112             return;
  12113         }
  12114         if (this.try_cite || this.force_collapse) {
  12115             this.cite[this.variable] = this.data;
  12116             if (this.sets.value().length > 0) {
  12117                 var prev = this.sets.value()[(this.sets.value().length - 1)];
  12118                 if (this.target === "front" && this.variable === "issued") {
  12119                     if (this.data.value && this.master_was_neutral_cite) {
  12120                         this.target = "mid";
  12121                     }
  12122                 }
  12123                 if (this.target === "front") {
  12124                     if ((prev[this.variable] || this.data.value) && (!prev[this.variable] || this.data.value !== prev[this.variable].value)) {
  12125                         if ("issued" !== this.variable) {
  12126                             this.in_series = false;
  12127                         }
  12128                     }
  12129                 } else if (this.target === "mid") {
  12130                     if (CSL.PARALLEL_COLLAPSING_MID_VARSET.indexOf(this.variable) > -1) {
  12131                         if (prev[this.variable]) {
  12132                             if (prev[this.variable].value === this.data.value) {
  12133                                 this.cite.front_collapse[this.variable] = true;
  12134                             } else {
  12135                                 this.cite.front_collapse[this.variable] = false;
  12136                             }
  12137                         } else {
  12138                             this.cite.front_collapse[this.variable] = false;
  12139                         }
  12140                     }
  12141                 } else if (this.target === "back") {
  12142                     if (prev[this.variable]) {
  12143                         if (this.data.value !== prev[this.variable].value 
  12144                             && this.sets.value().slice(-1)[0].back_forceme.indexOf(this.variable) === -1) {
  12145                             this.in_series = false;
  12146                         }
  12147                     }
  12148                 }
  12149             }
  12150         }
  12151         this.variable = false;
  12152     }
  12153 };
  12154 CSL.Parallel.prototype.CloseCite = function () {
  12155     var x, pos, len, has_issued, use_journal_info, volume_pos, container_title_pos, section_pos;
  12156     if (this.use_parallels && (this.force_collapse || this.try_cite)) {
  12157         use_journal_info = false;
  12158         if (!this.cite.front_collapse["container-title"]) {
  12159             use_journal_info = true;
  12160         }
  12161         if (this.cite.front_collapse.volume === false) {
  12162             use_journal_info = true;
  12163         }
  12164         if (this.cite.front_collapse["collection-number"] === false) {
  12165             use_journal_info = true;
  12166         }
  12167         if (this.cite.front_collapse.section === false) {
  12168             use_journal_info = true;
  12169         }
  12170         if (use_journal_info) {
  12171             this.cite.use_journal_info = true;
  12172             section_pos = this.cite.front.indexOf("section");
  12173             if (section_pos > -1) {
  12174                 this.cite.front = this.cite.front.slice(0,section_pos).concat(this.cite.front.slice(section_pos + 1));
  12175             }
  12176             volume_pos = this.cite.front.indexOf("volume");
  12177             if (volume_pos > -1) {
  12178                 this.cite.front = this.cite.front.slice(0,volume_pos).concat(this.cite.front.slice(volume_pos + 1));
  12179             }
  12180             container_title_pos = this.cite.front.indexOf("container-title");
  12181             if (container_title_pos > -1) {
  12182                 this.cite.front = this.cite.front.slice(0,container_title_pos).concat(this.cite.front.slice(container_title_pos + 1));
  12183             }
  12184             var collection_number_pos = this.cite.front.indexOf("collection-number");
  12185             if (collection_number_pos > -1) {
  12186                 this.cite.front = this.cite.front.slice(0,collection_number_pos).concat(this.cite.front.slice(collection_number_pos + 1));
  12187             }
  12188         }
  12189         if (!this.in_series && !this.force_collapse) {
  12190             this.ComposeSet(true);
  12191         }
  12192         if (this.sets.value().length === 0) {
  12193             var has_date = false;
  12194             for (pos = 0, len = this.cite.back.length; pos < len; pos += 1) {
  12195                 x = this.cite.back[pos];
  12196                 if (x === "issued" && this.cite["issued"] && this.cite["issued"].value) {
  12197                     has_date = true;
  12198                     break;
  12199                 }
  12200             }
  12201             if (!has_date) {
  12202                 this.cite.back_forceme.push("issued");
  12203             }
  12204         } else {
  12205             var idx = this.cite.front.indexOf("issued");
  12206             if (idx === -1 || this.master_was_neutral_cite) {
  12207                 this.cite.back_forceme = this.sets.value().slice(-1)[0].back_forceme;
  12208             }
  12209             if (idx > -1) {
  12210                 var prev = this.sets.value()[this.sets.value().length - 1];
  12211                 if (!prev["issued"]) {
  12212                     this.cite.front = this.cite.front.slice(0, idx).concat(this.cite.front.slice(idx + 1));
  12213                 }
  12214             }
  12215             if (this.master_was_neutral_cite && this.cite.mid.indexOf("names:mid") > -1) {
  12216                 this.cite.front.push("names:mid");
  12217             }
  12218         }
  12219         this.sets.value().push(this.cite);
  12220     }
  12221 };
  12222 CSL.Parallel.prototype.ComposeSet = function (next_output_in_progress) {
  12223     var cite, pos, master, len;
  12224     if (this.use_parallels && (this.force_collapse || this.try_cite)) {
  12225         var lengthCheck = this.sets.value().length;
  12226         if (this.sets.value().length === 1) {
  12227             if (!this.in_series) {
  12228                 this.sets.value().pop();
  12229                 this.delim_counter += 1;
  12230             }
  12231         } else {
  12232             len = this.sets.value().length;
  12233             for (pos = 0; pos < len; pos += 1) {
  12234                 cite = this.sets.value()[pos];
  12235                 if (pos === 0) {
  12236                     this.delim_counter += 1;
  12237                 } else {
  12238                     if (!cite.Item.title && cite.use_journal_info) {
  12239                         this.delim_pointers.push(false);
  12240                     } else {
  12241                         this.delim_pointers.push(this.delim_counter);
  12242                     }
  12243                     this.delim_counter += 1;
  12244                 }
  12245                 if (CSL.POSITION_FIRST === cite.position) {
  12246                     if (pos === 0) {
  12247                         this.state.registry.registry[cite.itemId].master = true;
  12248                         this.state.registry.registry[cite.itemId].siblings = [];
  12249                         this.state.registry.registry[cite.itemId].parallel = false;
  12250                     } else {
  12251                         if (cite.prevItemID) {
  12252                             if (!this.state.registry.registry[cite.prevItemID].parallel) {
  12253                                 this.state.registry.registry[cite.itemId].parallel = cite.prevItemID;
  12254                             } else {
  12255                                 this.state.registry.registry[cite.itemId].parallel = this.state.registry.registry[cite.prevItemID].parallel;
  12256                             }
  12257                             this.state.registry.registry[cite.itemId].siblings = this.state.registry.registry[cite.prevItemID].siblings;
  12258                             if (!this.state.registry.registry[cite.itemId].siblings) {
  12259                                 this.state.registry.registry[cite.itemId].siblings = [];
  12260                                 CSL.debug("WARNING: adding missing siblings array to registry object");
  12261                             }
  12262                             this.state.registry.registry[cite.itemId].siblings.push(cite.itemId);
  12263                         }
  12264                     }
  12265                 }
  12266             }
  12267             this.sets.push([]);
  12268         }
  12269         if (lengthCheck < 2) {
  12270             this.purgeGroupsIfParallel(false);
  12271         } else {
  12272             this.purgeGroupsIfParallel(true);
  12273         }
  12274         this.in_series = true;
  12275     }
  12276 };
  12277 CSL.Parallel.prototype.PruneOutputQueue = function () {
  12278     var len, pos, series, ppos, llen, cite;
  12279     if (this.use_parallels) {
  12280         len = this.sets.mystack.length;
  12281         for (pos = 0; pos < len; pos += 1) {
  12282             series = this.sets.mystack[pos];
  12283             if (series.length > 1) {
  12284                 llen = series.length;
  12285                 for (ppos = 0; ppos < llen; ppos += 1) {
  12286                     cite = series[ppos];
  12287                     if (ppos === 0) {
  12288                         this.purgeVariableBlobs(cite, cite.back);
  12289                     } else if (ppos === (series.length - 1)) {
  12290                         this.purgeVariableBlobs(cite, cite.front.concat(cite.back_forceme));
  12291                     } else {
  12292                         this.purgeVariableBlobs(cite, cite.front.concat(cite.back));
  12293                     }
  12294                 }
  12295             }
  12296         }
  12297     }
  12298 };
  12299 CSL.Parallel.prototype.purgeVariableBlobs = function (cite, varnames) {
  12300     var len, pos, varname, b, llen, ppos, out;
  12301     if (this.use_parallels) {
  12302         out = this.state.output.current.value();
  12303         if ("undefined" === typeof out.length) {
  12304             out = out.blobs;
  12305         }
  12306         for (pos = 0, len = this.delim_pointers.length; pos < len; pos += 1) {
  12307             ppos = this.delim_pointers[pos];
  12308             if (ppos !== false) {
  12309                 out[ppos].parallel_delimiter = ", ";
  12310             }
  12311         }
  12312         len = varnames.length - 1;
  12313         for (pos = len; pos > -1; pos += -1) {
  12314             varname = varnames[pos];
  12315             if (cite[varname]) {
  12316                 llen = cite[varname].blobs.length - 1;
  12317                 for (ppos = llen; ppos > -1; ppos += -1) {
  12318                     b = cite[varname].blobs[ppos];
  12319                     b[0].blobs = b[0].blobs.slice(0, b[1]).concat(b[0].blobs.slice((b[1] + 1)));
  12320                     this.state.tmp.has_purged_parallel = true;
  12321                     if (b[0] && b[0].strings && "string" == typeof b[0].strings.oops
  12322                         && b[0].parent && b[0].parent) {
  12323                         b[0].parent.parent.strings.delimiter = b[0].strings.oops;
  12324                     }
  12325                 }
  12326             }
  12327         }
  12328     }
  12329 };
  12330 CSL.Parallel.prototype.purgeGroupsIfParallel = function (original_condition) {
  12331     for (var i = this.parallel_conditional_blobs_list.length - 1; i > -1; i += -1) {
  12332         var obj = this.parallel_conditional_blobs_list[i];
  12333         var purgeme = true;
  12334         for (var j = 0, jlen = obj.conditions.length; j < jlen; j += 1) {
  12335             if (!(!obj.conditions[j] === !!original_condition
  12336                 || ("master" === obj.conditions[j]
  12337                     && !this.state.registry.registry[obj.id].master)
  12338                 || ("servant" === obj.conditions[j]
  12339                     && !this.state.registry.registry[obj.id].parallel))) {
  12340                 var purgeme = false;
  12341                 break;
  12342             }
  12343         }
  12344         if (purgeme) {
  12345             var buffer = [];
  12346             while (obj.blobs.length > obj.pos) {
  12347                 buffer.push(obj.blobs.pop());
  12348             }
  12349             if (buffer.length) {
  12350                 buffer.pop();
  12351             }
  12352             while (buffer.length) {
  12353                 obj.blobs.push(buffer.pop());
  12354             }
  12355         }
  12356         this.parallel_conditional_blobs_list.pop();
  12357     }
  12358 }
  12359 CSL.Util = {};
  12360 CSL.Util.Match = function () {
  12361     this.any = function (token, state, tests) {
  12362         return function (Item, item) {
  12363             for (var i=0, ilen=tests.length; i < ilen; i += 1) {
  12364                 var result = tests[i](Item, item);
  12365                 if (result) {
  12366                     return true;
  12367                 }
  12368             }
  12369             return false;
  12370         };
  12371     };
  12372     this.none = function (token, state, tests) {
  12373         return function (Item, item) {
  12374             for (var i=0,ilen=tests.length;i<ilen;i+=1) {
  12375                 var result = tests[i](Item,item);
  12376                 if (result) {
  12377                     return false;
  12378                 }
  12379             }
  12380             return true;
  12381         };
  12382     };
  12383     this.all = function (token, state, tests) {
  12384         return function (Item, item) {
  12385             for (var i=0,ilen=tests.length;i<ilen;i+=1) {
  12386                 var result = tests[i](Item,item);
  12387                 if (!result) {
  12388                     return false;
  12389                 }
  12390             }
  12391             return true;
  12392         };
  12393     };
  12394     this[undefined] = this.all;
  12395     this.nand = function (token, state, tests) {
  12396         return function (Item, item) {
  12397             for (var i=0,ilen=tests.length;i<ilen;i+=1) {
  12398                 var result = tests[i](Item,item);
  12399                 if (!result) {
  12400                     return true;
  12401                 }
  12402             }
  12403             return false;
  12404         };
  12405     };
  12406 };
  12407 CSL.Transform = function (state) {
  12408     var debug = false, abbreviations, token, fieldname, abbrev_family, opt;
  12409     this.abbrevs = {};
  12410     this.abbrevs["default"] = new state.sys.AbbreviationSegments();
  12411     this.getTextSubField = getTextSubField;
  12412     function getCountryOrJurisdiction(variable, normalizedKey, quashCountry) {
  12413         var value = "";
  12414         if (state.sys.getHumanForm) {
  12415             if (variable === "country") {
  12416                 value = state.sys.getHumanForm(normalizedKey.toLowerCase(), false, true);
  12417                 value = value.split("|")[0];
  12418             } else if (variable === "jurisdiction") {
  12419                 value = state.sys.getHumanForm(normalizedKey.toLowerCase(), false, true);
  12420                 if (!quashCountry) {
  12421                     value = value.split("|").slice(1).join(", ");
  12422                 } else {
  12423                     value = "";
  12424                 }
  12425             }
  12426 	    }
  12427 	    return value;
  12428     }
  12429     function abbreviate(state, tok, Item, altvar, basevalue, family_var, use_field, form) {
  12430         var value = "";
  12431         var myabbrev_family = CSL.FIELD_CATEGORY_REMAP[family_var];
  12432         if (!myabbrev_family) {
  12433             return basevalue;
  12434         }
  12435         var variable = family_var;
  12436         var normalizedKey = basevalue;
  12437         if (state.sys.normalizeAbbrevsKey) {
  12438             normalizedKey = state.sys.normalizeAbbrevsKey(family_var, basevalue);
  12439         }
  12440         var quashCountry = false;
  12441         if (variable === "jurisdiction" && normalizedKey) {
  12442             quashCountry = normalizedKey.indexOf(":") === -1;
  12443         }
  12444         if (state.sys.getAbbreviation) {
  12445             if (["jurisdiction", "country", "language-name", "language-name-original"].indexOf(variable) > -1) {
  12446                 var loadJurisdiction = "default";
  12447             } else if (Item.jurisdiction) {
  12448                 var loadJurisdiction = Item.jurisdiction;
  12449             } else {
  12450                 var loadJurisdiction = "default";
  12451             }
  12452             var jurisdiction = state.transform.loadAbbreviation(loadJurisdiction, myabbrev_family, normalizedKey, Item.type);
  12453             if (state.transform.abbrevs[jurisdiction][myabbrev_family] && normalizedKey) {
  12454                 var abbrev = state.transform.abbrevs[jurisdiction][myabbrev_family][normalizedKey];
  12455                 if (tok.strings.form === "short" && abbrev) {
  12456                     if (quashCountry) {
  12457                         value = "";
  12458                     } else {
  12459                         value = abbrev;
  12460                     }
  12461                 } else {
  12462 	                value = getCountryOrJurisdiction(variable, normalizedKey, quashCountry);
  12463                 }
  12464             }
  12465         }
  12466         if (!value 
  12467             && (!state.opt.development_extensions.require_explicit_legal_case_title_short || Item.type !== 'legal_case') 
  12468             && altvar && Item[altvar] && use_field) {
  12469             value = Item[altvar];
  12470         }
  12471         if (!value && !state.sys.getAbbreviation && state.sys.getHumanForm) {
  12472 	        value = getCountryOrJurisdiction(variable, normalizedKey, quashCountry);
  12473 	    }
  12474         if (!value && !quashCountry && (!state.sys.getHumanForm || variable !== "jurisdiction")) {
  12475             value = basevalue;
  12476         }
  12477         return value;
  12478     }
  12479     function getFieldLocale(Item,field) {
  12480         var ret = state.opt["default-locale"][0].slice(0, 2)
  12481         var localeRex;
  12482         if (state.opt.development_extensions.strict_text_case_locales) {
  12483             localeRex = new RegExp("^([a-zA-Z]{2})(?:$|-.*| .*)");
  12484         } else {
  12485             localeRex = new RegExp("^([a-zA-Z]{2})(?:$|-.*|.*)");
  12486         }
  12487         if (Item.language) {
  12488             var m = ("" + Item.language).match(localeRex);
  12489             if (m) {
  12490                 ret = m[1];
  12491             } else {
  12492                 ret = "tlh";
  12493             }
  12494         }
  12495         if (Item.multi && Item.multi && Item.multi.main && Item.multi.main[field]) {
  12496             ret = Item.multi.main[field];
  12497         }
  12498         if (!state.opt.development_extensions.strict_text_case_locales
  12499            || state.opt.development_extensions.normalize_lang_keys_to_lowercase) {
  12500             ret = ret.toLowerCase();
  12501         }
  12502         return ret;
  12503     };
  12504     function getTextSubField (Item, field, locale_type, use_default, stopOrig) {
  12505         var m, lst, opt, o, oo, pos, key, ret, len, myret, opts;
  12506         var usedOrig = stopOrig;
  12507         var usingOrig = false;
  12508         if (!Item[field]) {
  12509             return {
  12510                 name:"",
  12511                 usedOrig:stopOrig,
  12512                 token: CSL.Util.cloneToken(this)
  12513             };
  12514         }
  12515         ret = {name:"", usedOrig:stopOrig,locale:getFieldLocale(Item,field)};
  12516         opts = state.opt[locale_type];
  12517         var hasVal = false;
  12518         var jurisdictionName = false;
  12519         if (locale_type === 'locale-orig') {
  12520             if (stopOrig) {
  12521                 ret = {name:"", usedOrig:stopOrig};
  12522             } else {
  12523                 ret = {name:Item[field], usedOrig:false, locale:getFieldLocale(Item,field)};
  12524             }
  12525             hasVal = true;
  12526             usingOrig = true;
  12527         } else if (use_default && ("undefined" === typeof opts || opts.length === 0)) {
  12528             var ret = {name:Item[field], usedOrig:true, locale:getFieldLocale(Item,field)};
  12529             hasVal = true;
  12530             usingOrig = true;
  12531         }
  12532         if (!hasVal) {
  12533             for (var i = 0, ilen = opts.length; i < ilen; i += 1) {
  12534                 opt = opts[i];
  12535                 o = opt.split(/[\-_]/)[0];
  12536                 if (opt && Item.multi && Item.multi._keys[field] && Item.multi._keys[field][opt]) {
  12537                     ret.name = Item.multi._keys[field][opt];
  12538                     ret.locale = opt;
  12539                     break;
  12540                 } else if (o && Item.multi && Item.multi._keys[field] && Item.multi._keys[field][o]) {
  12541                     ret.name = Item.multi._keys[field][o];
  12542                     ret.locale = o;
  12543                     break;
  12544                 }
  12545             }
  12546             if (!ret.name && use_default) {
  12547                 ret = {name:Item[field], usedOrig:true, locale:getFieldLocale(Item,field)};
  12548                 usingOrig = true;
  12549             }
  12550         }
  12551         ret.token = CSL.Util.cloneToken(this);
  12552         if (["title", "container-title"].indexOf(field) > -1) {
  12553             if (!usedOrig
  12554                 && (!ret.token.strings["text-case"]
  12555                     || ret.token.strings["text-case"] === "sentence"
  12556                     || ret.token.strings["text-case"] === "normal")) {
  12557                 var locale = usingOrig ? false : ret.locale;
  12558                 var seg = field.slice(0,-5);
  12559                 var sentenceCase = ret.token.strings["text-case"] === "sentence" ? true : false;
  12560                 ret.name = CSL.titlecaseSentenceOrNormal(state, Item, seg, locale, sentenceCase);
  12561                 delete ret.token.strings["text-case"];
  12562             }
  12563         }
  12564         return ret;
  12565     }
  12566     function loadAbbreviation(jurisdiction, category, orig, itemType) {
  12567         var pos, len;
  12568         if (!jurisdiction) {
  12569             jurisdiction = "default";
  12570         }
  12571         if (!orig) {
  12572             if (!state.transform.abbrevs[jurisdiction]) {
  12573                 state.transform.abbrevs[jurisdiction] = new state.sys.AbbreviationSegments();
  12574             }
  12575             if (!state.transform.abbrevs[jurisdiction][category]) {
  12576                 state.transform.abbrevs[jurisdiction][category] = {};
  12577             }
  12578             return jurisdiction;
  12579         }
  12580         if (state.sys.getAbbreviation) {
  12581             jurisdiction = state.sys.getAbbreviation(state.opt.styleID, state.transform.abbrevs, jurisdiction, category, orig, itemType, true);
  12582             if (!jurisdiction) {
  12583                 jurisdiction = "default";
  12584             }
  12585         }
  12586         return jurisdiction;
  12587     }
  12588     this.loadAbbreviation = loadAbbreviation;
  12589     function publisherCheck (tok, Item, primary, family_var) {
  12590         var varname = tok.variables[0];
  12591         if (state.publisherOutput && primary) {
  12592             if (["publisher","publisher-place"].indexOf(varname) === -1) {
  12593                 return false;
  12594             } else {
  12595                 state.publisherOutput[varname + "-token"] = tok;
  12596                 state.publisherOutput.varlist.push(varname);
  12597                 var lst = primary.split(/;\s*/);
  12598                 if (lst.length === state.publisherOutput[varname + "-list"].length) {
  12599                     state.publisherOutput[varname + "-list"] = lst;
  12600                 }
  12601                 for (var i = 0, ilen = lst.length; i < ilen; i += 1) {
  12602                     lst[i] = abbreviate(state, tok, Item, false, lst[i], family_var, true);
  12603                 }
  12604                 state.tmp[varname + "-token"] = tok;
  12605                 return true;
  12606             }
  12607         }
  12608         return false;
  12609     }
  12610     function getOutputFunction(variables, family_var, abbreviation_fallback, alternative_varname, transform_fallback) {
  12611         var localesets;
  12612         var langPrefs = CSL.LangPrefsMap[variables[0]];
  12613         if (!langPrefs) {
  12614             localesets = false;
  12615         } else {
  12616             localesets = state.opt['cite-lang-prefs'][langPrefs];
  12617         }
  12618         return function (state, Item, item, usedOrig) {
  12619             var primary, primary_locale, secondary, secondary_locale, tertiary, tertiary_locale, primary_tok, group_tok, key;
  12620             if (!variables[0] || (!Item[variables[0]] && !Item[alternative_varname])) {
  12621                 return null;
  12622             }
  12623             var slot = {primary:false, secondary:false, tertiary:false};
  12624             if (state.tmp.area.slice(-5) === "_sort") {
  12625                 slot.primary = 'locale-sort';
  12626             } else {
  12627                 if (localesets) {
  12628                     var slotnames = ["primary", "secondary", "tertiary"];
  12629                     for (var i = 0, ilen = slotnames.length; i < ilen; i += 1) {
  12630                         if (localesets.length - 1 <  i) {
  12631                             break;
  12632                         }
  12633                         if (localesets[i]) {
  12634                             slot[slotnames[i]] = 'locale-' + localesets[i];
  12635                         }
  12636                     }
  12637                 } else {
  12638                     slot.primary = 'locale-orig';
  12639                 }
  12640             }
  12641             if (variables[0] === "title-short" 
  12642                 || (state.tmp.area !== "bibliography"
  12643                     && !(state.tmp.area === "citation"
  12644                          && state.opt.xclass === "note"
  12645                          && item && !item.position))) {
  12646                 slot.secondary = false;
  12647                 slot.tertiary = false;
  12648             }
  12649             if (state.tmp["publisher-list"]) {
  12650                 if (variables[0] === "publisher") {
  12651                     state.tmp["publisher-token"] = this;
  12652                 } else if (variables[0] === "publisher-place") {
  12653                     state.tmp["publisher-place-token"] = this;
  12654                 }
  12655                 return null;
  12656             }
  12657             var res = getTextSubField.call(this, Item, variables[0], slot.primary, true);
  12658             primary = res.name;
  12659             primary_locale = res.locale;
  12660             var primary_tok = res.token;
  12661             var primaryUsedOrig = res.usedOrig;
  12662             if (publisherCheck(this, Item, primary, family_var)) {
  12663                 return null;
  12664             }
  12665             secondary = false;
  12666             tertiary = false;
  12667             if (slot.secondary) {
  12668                 res = getTextSubField.call(this, Item, variables[0], slot.secondary, false, res.usedOrig);
  12669                 secondary = res.name;
  12670                 secondary_locale = res.locale;
  12671                 var secondary_tok = res.token;
  12672             }
  12673             if (slot.tertiary) {
  12674                 res = getTextSubField.call(this, Item, variables[0], slot.tertiary, false, res.usedOrig);
  12675                 tertiary = res.name;
  12676                 tertiary_locale = res.locale;
  12677                 var tertiary_tok = res.token;
  12678             }
  12679             if (family_var) {
  12680                 primary = abbreviate(state, primary_tok, Item, alternative_varname, primary, family_var, true);
  12681                 if (primary) {
  12682                     primary = quashCheck(primary);
  12683                 }
  12684                 if (secondary) {
  12685                     secondary = abbreviate(state, secondary_tok, Item, false, secondary, family_var, true);
  12686                 }
  12687                 if (tertiary) {
  12688                     tertiary = abbreviate(state, tertiary_tok, Item, false, tertiary, family_var, true);
  12689                 }
  12690             }
  12691             var primaryPrefix;
  12692             if (slot.primary === "locale-translit") {
  12693                 primaryPrefix = state.opt.citeAffixes[langPrefs][slot.primary].prefix;
  12694             }                
  12695             if (primaryPrefix === "<i>" && variables[0] === 'title' && !primaryUsedOrig) {
  12696                 var hasItalic = false;
  12697                 for (var i = 0, ilen = primary_tok.decorations.length; i < ilen; i += 1) {
  12698                     if (primary_tok.decorations[i][0] === "@font-style"
  12699                         && primary_tok.decorations[i][1] === "italic") {
  12700                         hasItalic = true;
  12701                     }
  12702                 }
  12703                 if (!hasItalic) {
  12704                     primary_tok.decorations.push(["@font-style", "italic"])
  12705                 }
  12706             }
  12707             if (primary_locale !== "en" && primary_tok.strings["text-case"] === "title") {
  12708                 primary_tok.strings["text-case"] = "passthrough";
  12709             }
  12710             if ("title" === variables[0]) {
  12711                 primary = CSL.demoteNoiseWords(state, primary, this["leading-noise-words"]);
  12712             }
  12713             if (secondary || tertiary) {
  12714                 state.output.openLevel("empty");
  12715                 primary_tok.strings.suffix = primary_tok.strings.suffix.replace(/[ .,]+$/,"");
  12716                 state.output.append(primary, primary_tok);
  12717                 if (secondary) {
  12718                     secondary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.secondary].prefix;
  12719                     secondary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.secondary].suffix;
  12720                     if (!secondary_tok.strings.prefix) {
  12721                         secondary_tok.strings.prefix = " ";
  12722                     }
  12723                     for (var i = secondary_tok.decorations.length - 1; i > -1; i += -1) {
  12724                         if (['@quotes/true', '@font-style/italic', '@font-style/oblique', '@font-weight/bold'].indexOf(secondary_tok.decorations[i].join('/')) > -1) {
  12725                             secondary_tok.decorations = secondary_tok.decorations.slice(0, i).concat(secondary_tok.decorations.slice(i + 1))
  12726                         }
  12727                     }
  12728                     if (secondary_locale !== "en" && secondary_tok.strings["text-case"] === "title") {
  12729                         secondary_tok.strings["text-case"] = "passthrough";
  12730                     }
  12731                     var secondary_outer = new CSL.Token();
  12732                     secondary_outer.decorations.push(["@font-style", "normal"]);
  12733                     secondary_outer.decorations.push(["@font-weight", "normal"]);
  12734                     state.output.openLevel(secondary_outer);
  12735                     state.output.append(secondary, secondary_tok);
  12736                     state.output.closeLevel();
  12737                     var blob_obj = state.output.current.value();
  12738                     var blobs_pos = state.output.current.value().blobs.length - 1;
  12739                     if (state.parallel.use_parallels) {
  12740                         state.parallel.cite.front.push(variables[0] + ":secondary");
  12741                         state.parallel.cite[variables[0] + ":secondary"] = {blobs:[[blob_obj, blobs_pos]]};
  12742                     }
  12743                 }
  12744                 if (tertiary) {
  12745                     tertiary_tok.strings.prefix = state.opt.citeAffixes[langPrefs][slot.tertiary].prefix;
  12746                     tertiary_tok.strings.suffix = state.opt.citeAffixes[langPrefs][slot.tertiary].suffix;
  12747                     if (!tertiary_tok.strings.prefix) {
  12748                         tertiary_tok.strings.prefix = " ";
  12749                     }
  12750                     for (var i = tertiary_tok.decorations.length - 1; i > -1; i += -1) {
  12751                         if (['@quotes/true', '@font-style/italic', '@font-style/oblique', '@font-weight/bold'].indexOf(tertiary_tok.decorations[i].join('/')) > -1) {
  12752                             tertiary_tok.decorations = tertiary_tok.decorations.slice(0, i).concat(tertiary_tok.decorations.slice(i + 1))
  12753                         }
  12754                     }
  12755                     if (tertiary_locale !== "en" && tertiary_tok.strings["text-case"] === "title") {
  12756                         tertiary_tok.strings["text-case"] = "passthrough";
  12757                     }
  12758                     var tertiary_outer = new CSL.Token();
  12759                     tertiary_outer.decorations.push(["@font-style", "normal"]);
  12760                     tertiary_outer.decorations.push(["@font-weight", "normal"]);
  12761                     state.output.openLevel(tertiary_outer);
  12762                     state.output.append(tertiary, tertiary_tok);
  12763                     state.output.closeLevel();
  12764                     var blob_obj = state.output.current.value();
  12765                     var blobs_pos = state.output.current.value().blobs.length - 1;
  12766                     if (state.parallel.use_parallels) {
  12767                         state.parallel.cite.front.push(variables[0] + ":tertiary");
  12768                         state.parallel.cite[variables[0] + ":tertiary"] = {blobs:[[blob_obj, blobs_pos]]};
  12769                     }
  12770                 }
  12771                 state.output.closeLevel();
  12772             } else {
  12773                 state.output.append(primary, primary_tok);
  12774             }
  12775             return null;
  12776         };
  12777     }
  12778     this.getOutputFunction = getOutputFunction;
  12779     function quashCheck(value) {
  12780         var m = value.match(/^!([-,_a-z]+)>>>/);
  12781         if (m) {
  12782             var fields = m[1].split(",");
  12783             value = value.slice(m[0].length);
  12784             for (var i = 0, ilen = fields.length; i < ilen; i += 1) {
  12785                 if (state.tmp.done_vars.indexOf(fields[i]) === -1) {
  12786                     state.tmp.done_vars.push(fields[i]);
  12787                 }
  12788             }
  12789         }
  12790         return value;
  12791     }
  12792     this.quashCheck = quashCheck;
  12793 };
  12794 CSL.Token = function (name, tokentype) {
  12795     this.name = name;
  12796     this.strings = {};
  12797     this.strings.delimiter = undefined;
  12798     this.strings.prefix = "";
  12799     this.strings.suffix = "";
  12800     this.decorations = [];
  12801     this.variables = [];
  12802     this.execs = [];
  12803     this.tokentype = tokentype;
  12804     this.evaluator = false;
  12805     this.tests = [];
  12806     this.rawtests = [];
  12807     this.succeed = false;
  12808     this.fail = false;
  12809     this.next = false;
  12810 };
  12811 CSL.Util.cloneToken = function (token) {
  12812     var newtok, key, pos, len;
  12813     if ("string" === typeof token) {
  12814         return token;
  12815     }
  12816     newtok = new CSL.Token(token.name, token.tokentype);
  12817     for (var key in token.strings) {
  12818         if (token.strings.hasOwnProperty(key)) {
  12819             newtok.strings[key] = token.strings[key];
  12820         }
  12821     }
  12822     if (token.decorations) {
  12823         newtok.decorations = [];
  12824         for (pos = 0, len = token.decorations.length; pos < len; pos += 1) {
  12825             newtok.decorations.push(token.decorations[pos].slice());
  12826         }
  12827     }
  12828     if (token.variables) {
  12829         newtok.variables = token.variables.slice();
  12830     }
  12831     if (token.execs) {
  12832         newtok.execs = token.execs.slice();
  12833         newtok.tests = token.tests.slice();
  12834         newtok.rawtests = token.tests.slice();
  12835     }
  12836     return newtok;
  12837 };
  12838 CSL.AmbigConfig = function () {
  12839     this.maxvals = [];
  12840     this.minval = 1;
  12841     this.names = [];
  12842     this.givens = [];
  12843     this.year_suffix = false;
  12844     this.disambiguate = 0;
  12845 };
  12846 CSL.Blob = function (str, token, levelname) {
  12847     var len, pos, key;
  12848     this.levelname = levelname;
  12849     if (token) {
  12850         this.strings = {"prefix":"","suffix":""};
  12851         for (var key in token.strings) {
  12852             if (token.strings.hasOwnProperty(key)) {
  12853                 this.strings[key] = token.strings[key];
  12854             }
  12855         }
  12856         this.decorations = [];
  12857         if (token.decorations === undefined) {
  12858             len = 0;
  12859         } else {
  12860             len = token.decorations.length;
  12861         }
  12862         for (pos = 0; pos < len; pos += 1) {
  12863             this.decorations.push(token.decorations[pos].slice());
  12864         }
  12865     } else {
  12866         this.strings = {};
  12867         this.strings.prefix = "";
  12868         this.strings.suffix = "";
  12869         this.strings.delimiter = "";
  12870         this.decorations = [];
  12871     }
  12872     if ("string" === typeof str) {
  12873         this.blobs = str;
  12874     } else if (str) {
  12875         this.blobs = [str];
  12876     } else {
  12877         this.blobs = [];
  12878     }
  12879     this.alldecor = [this.decorations];
  12880 };
  12881 CSL.Blob.prototype.push = function (blob) {
  12882     if ("string" === typeof this.blobs) {
  12883         throw "Attempt to push blob onto string object";
  12884     } else if (false !== blob) {
  12885         blob.alldecor = blob.alldecor.concat(this.alldecor);
  12886         this.blobs.push(blob);
  12887     }
  12888 };
  12889 CSL.NumericBlob = function (particle, num, mother_token, id) {
  12890     this.id = id;
  12891     this.alldecor = [];
  12892     this.num = num;
  12893     this.particle = particle;
  12894     this.blobs = num.toString();
  12895     this.status = CSL.START;
  12896     this.strings = {};
  12897     if (mother_token) {
  12898         this.gender = mother_token.gender;
  12899         this.decorations = mother_token.decorations;
  12900         this.strings.prefix = mother_token.strings.prefix;
  12901         this.strings.suffix = mother_token.strings.suffix;
  12902         this.strings["text-case"] = mother_token.strings["text-case"];
  12903         this.successor_prefix = mother_token.successor_prefix;
  12904         this.range_prefix = mother_token.range_prefix;
  12905         this.splice_prefix = mother_token.splice_prefix;
  12906         this.formatter = mother_token.formatter;
  12907         if (!this.formatter) {
  12908             this.formatter =  new CSL.Output.DefaultFormatter();
  12909         }
  12910         if (this.formatter) {
  12911             this.type = this.formatter.format(1);
  12912         }
  12913     } else {
  12914         this.decorations = [];
  12915         this.strings.prefix = "";
  12916         this.strings.suffix = "";
  12917         this.successor_prefix = "";
  12918         this.range_prefix = "";
  12919         this.splice_prefix = "";
  12920         this.formatter = new CSL.Output.DefaultFormatter();
  12921     }
  12922 };
  12923 CSL.NumericBlob.prototype.setFormatter = function (formatter) {
  12924     this.formatter = formatter;
  12925     this.type = this.formatter.format(1);
  12926 };
  12927 CSL.Output.DefaultFormatter = function () {};
  12928 CSL.Output.DefaultFormatter.prototype.format = function (num) {
  12929     return num.toString();
  12930 };
  12931 CSL.NumericBlob.prototype.checkNext = function (next,start) {
  12932     if (start) {
  12933         this.status = CSL.START;
  12934         if ("object" === typeof next) {
  12935             if (next.num === (this.num + 1)) {
  12936                 next.status = CSL.SUCCESSOR;
  12937             } else {
  12938                 next.status = CSL.SEEN;
  12939             }
  12940         }
  12941     } else if (! next || !next.num || this.type !== next.type || next.num !== (this.num + 1)) {
  12942         if (this.status === CSL.SUCCESSOR_OF_SUCCESSOR) {
  12943             this.status = CSL.END;
  12944         }
  12945         if ("object" === typeof next) { 
  12946            next.status = CSL.SEEN;
  12947         }
  12948     } else { // next number is in the sequence
  12949         if (this.status === CSL.START || this.status === CSL.SEEN) {
  12950             next.status = CSL.SUCCESSOR;
  12951         } else if (this.status === CSL.SUCCESSOR || this.status === CSL.SUCCESSOR_OF_SUCCESSOR) {
  12952             if (this.range_prefix) {
  12953                 next.status = CSL.SUCCESSOR_OF_SUCCESSOR;
  12954                 this.status = CSL.SUPPRESS;
  12955             } else {
  12956                 next.status = CSL.SUCCESSOR;
  12957             }
  12958         }
  12959     }
  12960 };
  12961 CSL.NumericBlob.prototype.checkLast = function (last) {
  12962     if (this.status === CSL.SEEN 
  12963     || (last.num !== (this.num - 1) && this.status === CSL.SUCCESSOR)) {
  12964         this.status = CSL.SUCCESSOR;
  12965         return true;
  12966     }
  12967     return false;
  12968 };
  12969 CSL.Util.fixDateNode = function (parent, pos, node) {
  12970     var form, variable, datexml, subnode, partname, attr, val, prefix, suffix, children, key, subchildren, kkey, display, cslid;
  12971     var lingo = this.cslXml.getAttributeValue(node, "lingo");
  12972     var default_locale = this.cslXml.getAttributeValue(node, "default-locale");
  12973     this.build.date_key = true;
  12974     form = this.cslXml.getAttributeValue(node, "form");
  12975     var lingo;
  12976     if (default_locale) {
  12977         lingo = this.opt["default-locale"][0];
  12978     } else {
  12979         lingo = this.cslXml.getAttributeValue(node, "lingo");
  12980     }
  12981     if (!this.getDate(form, default_locale)) {
  12982         return parent;
  12983     }
  12984     var dateparts = this.cslXml.getAttributeValue(node, "date-parts");
  12985     variable = this.cslXml.getAttributeValue(node, "variable");
  12986     prefix = this.cslXml.getAttributeValue(node, "prefix");
  12987     suffix = this.cslXml.getAttributeValue(node, "suffix");
  12988     display = this.cslXml.getAttributeValue(node, "display");
  12989     cslid = this.cslXml.getAttributeValue(node, "cslid");
  12990     datexml = this.cslXml.nodeCopy(this.getDate(form, default_locale));
  12991     this.cslXml.setAttribute(datexml, 'lingo', this.opt.lang);
  12992     this.cslXml.setAttribute(datexml, 'form', form);
  12993     this.cslXml.setAttribute(datexml, 'date-parts', dateparts);
  12994     this.cslXml.setAttribute(datexml, "cslid", cslid);
  12995     this.cslXml.setAttribute(datexml, 'variable', variable);
  12996     this.cslXml.setAttribute(datexml, 'default-locale', default_locale);
  12997     if (prefix) {
  12998         this.cslXml.setAttribute(datexml, "prefix", prefix);
  12999     }
  13000     if (suffix) {
  13001         this.cslXml.setAttribute(datexml, "suffix", suffix);
  13002     }
  13003     if (display) {
  13004         this.cslXml.setAttribute(datexml, "display", display);
  13005     }
  13006     children = this.cslXml.children(datexml);
  13007     for (var key in children) {
  13008         subnode = children[key];
  13009         if ("date-part" === this.cslXml.nodename(subnode)) {
  13010             partname = this.cslXml.getAttributeValue(subnode, "name");
  13011             if (default_locale) {
  13012                 this.cslXml.setAttributeOnNodeIdentifiedByNameAttribute(datexml, "date-part", partname, "@default-locale", "true");
  13013             }
  13014         }
  13015     }
  13016     children = this.cslXml.children(node);
  13017     for (var key in children) {
  13018         subnode = children[key];
  13019         if ("date-part" === this.cslXml.nodename(subnode)) {
  13020             partname = this.cslXml.getAttributeValue(subnode, "name");
  13021             subchildren = this.cslXml.attributes(subnode);
  13022             for (attr in subchildren) {
  13023                 if ("@name" === attr) {
  13024                     continue;
  13025                 }
  13026                 if (lingo && lingo !== this.opt.lang) {
  13027                     if (["@suffix", "@prefix", "@form"].indexOf(attr) > -1) {
  13028                         continue;
  13029                     }
  13030                 }
  13031                 val = subchildren[attr];
  13032                 this.cslXml.setAttributeOnNodeIdentifiedByNameAttribute(datexml, "date-part", partname, attr, val);
  13033             }
  13034         }
  13035     }
  13036     if ("year" === this.cslXml.getAttributeValue(node, "date-parts")) {
  13037         this.cslXml.deleteNodeByNameAttribute(datexml, 'month');
  13038         this.cslXml.deleteNodeByNameAttribute(datexml, 'day');
  13039     } else if ("year-month" === this.cslXml.getAttributeValue(node, "date-parts")) {
  13040         this.cslXml.deleteNodeByNameAttribute(datexml, 'day');
  13041     } else if ("month-day" === this.cslXml.getAttributeValue(node, "date-parts")) {
  13042         var childNodes = this.cslXml.children(datexml);
  13043         for (var i=1,ilen=this.cslXml.numberofnodes(childNodes);i<ilen;i++) {
  13044             if (this.cslXml.getAttributeValue(childNodes[i], 'name') === "year") {
  13045                 this.cslXml.setAttribute(childNodes[i-1], "suffix", "");
  13046                 break;
  13047             }
  13048         }
  13049         this.cslXml.deleteNodeByNameAttribute(datexml, 'year');
  13050     }
  13051     return this.cslXml.insertChildNodeAfter(parent, node, pos, datexml);
  13052 };
  13053 CSL.dateMacroAsSortKey = function (state, Item) {
  13054     CSL.dateAsSortKey.call(this, state, Item, true);
  13055 };
  13056 CSL.dateAsSortKey = function (state, Item, isMacro) {
  13057     var dp, elem, value, e, yr, prefix, i, ilen, num;
  13058     var variable = this.variables[0];
  13059     var macroFlag = "empty";
  13060     if (isMacro && state.tmp.extension) {
  13061         macroFlag = "macro-with-date";
  13062     }
  13063     dp = Item[variable];
  13064     if ("undefined" === typeof dp) {
  13065         dp = {"date-parts": [[0]] };
  13066         if (!dp.year) {
  13067             state.tmp.empty_date = true;
  13068         }
  13069     }
  13070     if ("undefined" === typeof this.dateparts) {
  13071         this.dateparts = ["year", "month", "day"];
  13072     }
  13073     if (dp.raw) {
  13074         dp = state.fun.dateparser.parseDateToArray(dp.raw);
  13075     } else if (dp["date-parts"]) {
  13076         dp = state.dateParseArray(dp);
  13077     }
  13078     if ("undefined" === typeof dp) {
  13079         dp = {};
  13080     }
  13081     for (i = 0, ilen = CSL.DATE_PARTS_INTERNAL.length; i < ilen; i += 1) {
  13082         elem = CSL.DATE_PARTS_INTERNAL[i];
  13083         value = 0;
  13084         e = elem;
  13085         if (e.slice(-4) === "_end") {
  13086             e = e.slice(0, -4);
  13087         }
  13088         if (dp[elem] && this.dateparts.indexOf(e) > -1) {
  13089             value = dp[elem];
  13090         }
  13091         if (elem.slice(0, 4) === "year") {
  13092             yr = CSL.Util.Dates[e].numeric(state, value);
  13093             var prefix = "Y";
  13094             if (yr[0] === "-") {
  13095                 prefix = "X";
  13096                 yr = yr.slice(1);
  13097                 yr = 9999 - parseInt(yr, 10);
  13098             }
  13099             state.output.append(CSL.Util.Dates[elem.slice(0, 4)].numeric(state, (prefix + yr)), macroFlag);
  13100         } else {
  13101             value = CSL.Util.Dates[e]["numeric-leading-zeros"](state, value);
  13102             if (!value) {
  13103                 value = "00";
  13104             }
  13105             state.output.append(value, macroFlag);
  13106         }
  13107     }
  13108 };
  13109 CSL.Engine.prototype.dateParseArray = function (date_obj) {
  13110     var ret, field, dpos, ppos, dp, exts, llen, pos, len, pppos, lllen;
  13111     ret = {};
  13112     for (field in date_obj) {
  13113         if (field === "date-parts") {
  13114             dp = date_obj["date-parts"];
  13115             if (dp.length > 1) {
  13116                 if (dp[0].length !== dp[1].length) {
  13117                     CSL.error("CSL data error: element mismatch in date range input.");
  13118                 }
  13119             }
  13120             exts = ["", "_end"];
  13121             for (var i = 0, ilen = dp.length; i < ilen; i += 1) {
  13122                 for (var j = 0, jlen = CSL.DATE_PARTS.length; j < jlen; j += 1) {
  13123                     if (isNaN(parseInt(dp[i][j], 10))) {
  13124                         ret[(CSL.DATE_PARTS[j] + exts[i])] = undefined;
  13125                     } else {
  13126                         ret[(CSL.DATE_PARTS[j] + exts[i])] = parseInt(dp[i][j], 10);
  13127                     }
  13128                 }
  13129             }
  13130         } else if (date_obj.hasOwnProperty(field)) {
  13131             if (field === "literal" && "object" === typeof date_obj.literal && "string" === typeof date_obj.literal.part) {
  13132                 CSL.debug("Warning: fixing up weird literal date value");
  13133                 ret.literal = date_obj.literal.part;
  13134             } else {
  13135                 ret[field] = date_obj[field];
  13136             }
  13137         }
  13138     }
  13139     return ret;
  13140 };
  13141 CSL.Util.Names = {};
  13142 CSL.Util.Names.compareNamesets = CSL.NameOutput.prototype._compareNamesets;
  13143 CSL.Util.Names.unInitialize = function (state, name) {
  13144     var i, ilen, namelist, punctlist, ret;
  13145     if (!name) {
  13146         return "";
  13147     }
  13148     namelist = name.split(/(?:\-|\s+)/);
  13149     punctlist = name.match(/(\-|\s+)/g);
  13150     ret = "";
  13151     for (i = 0, ilen = namelist.length; i < ilen; i += 1) {
  13152         ret += namelist[i];
  13153         if (i < ilen - 1) {
  13154             ret += punctlist[i];
  13155         }
  13156     }
  13157     return ret;
  13158 };
  13159 CSL.Util.Names.initializeWith = function (state, name, terminator, normalizeOnly) {
  13160     var i, ilen, j, jlen, n, m, mm, str, lst, ret;
  13161     if (!name) {
  13162         return "";
  13163     }
  13164     if (!terminator) {
  13165         terminator = "";
  13166     }
  13167     if (["Lord", "Lady"].indexOf(name) > -1
  13168         || (!name.match(CSL.STARTSWITH_ROMANESQUE_REGEXP)
  13169             && !terminator.match("%s"))) {
  13170         return name;
  13171     }
  13172     var namelist = name;
  13173     if (state.opt["initialize-with-hyphen"] === false) {
  13174         namelist = namelist.replace(/\-/g, " ");
  13175     }
  13176     namelist = namelist.replace(/\s*\-\s*/g, "-").replace(/\s+/g, " ");
  13177     namelist = namelist.replace(/-([a-z])/g, "\u2013$1");
  13178     mm = namelist.match(/[\-\s]+/g);
  13179     lst = namelist.split(/[\-\s]+/);
  13180     if (lst.length === 0) {
  13181         namelist = mm;
  13182     } else {
  13183         namelist = [lst[0]];
  13184         for (i = 1, ilen = lst.length; i < ilen; i += 1) {
  13185             namelist.push(mm[i - 1]);
  13186             namelist.push(lst[i]);
  13187         }
  13188     }
  13189     lst = namelist;
  13190     for (i = lst.length -1; i > -1; i += -1) {
  13191         if (lst[i] && lst[i].slice(0, -1).indexOf(".") > -1) {
  13192             var lstend = lst.slice(i + 1);
  13193             var lstmid = lst[i].slice(0, -1).split(".");
  13194             lst = lst.slice(0, i);
  13195             for (j = 0, jlen = lstmid.length; j < jlen; j += 1) {
  13196                 lst.push(lstmid[j] + ".");
  13197                 if (j < lstmid.length - 1) {
  13198                     lst.push(" ");
  13199                 }
  13200             }
  13201             lst = lst.concat(lstend);
  13202         }
  13203     }
  13204     if (normalizeOnly) {
  13205         ret = CSL.Util.Names.doNormalize(state, lst, terminator);
  13206     } else {
  13207         ret = CSL.Util.Names.doInitialize(state, lst, terminator);
  13208     }
  13209     ret = ret.replace(/\u2013([a-z])/g, "-$1");
  13210     return ret;
  13211 };
  13212 CSL.Util.Names.doNormalize = function (state, namelist, terminator, mode) {
  13213     var i, ilen;
  13214     terminator = terminator ? terminator : "";
  13215     var isAbbrev = [];
  13216     for (i = 0, ilen = namelist.length; i < ilen; i += 1) {
  13217         if (namelist[i].length > 1 && namelist[i].slice(-1) === ".") {
  13218             namelist[i] = namelist[i].slice(0, -1);
  13219             isAbbrev.push(true);
  13220         } else if (namelist[i].length === 1 && namelist[i].toUpperCase() === namelist[i]) {
  13221             isAbbrev.push(true);
  13222         } else {
  13223             isAbbrev.push(false);
  13224         }
  13225     }
  13226     var ret = [];
  13227     for (i = 0, ilen = namelist.length; i < ilen; i += 2) {
  13228         if (isAbbrev[i]) {
  13229             if (i < namelist.length - 2) {
  13230                 namelist[i + 1] = "";
  13231                 var onlySpace = terminator.match(/^[\u0009\u000a\u000b\u000c\u000d\u0020\u00a0]+$/)
  13232                 if (
  13233                     onlySpace
  13234                     || (
  13235                         (!terminator || (terminator.slice(-1) && !terminator.slice(-1).match(/[\u0009\u000a\u000b\u000c\u000d\u0020\u00a0]/)))
  13236                         && namelist[i].length && namelist[i].match(CSL.ALL_ROMANESQUE_REGEXP)
  13237                         && (namelist[i].length > 1 || namelist[i + 2].length > 1)
  13238                     )
  13239                 ) {
  13240                     namelist[i + 1] = " ";
  13241                 }
  13242                 if (namelist[i + 2].length > 1) {
  13243                     namelist[i] = namelist[i] + terminator.replace(/\ufeff$/, "");
  13244                 } else {
  13245                     namelist[i] = namelist[i] + terminator;
  13246                 }
  13247             }
  13248             if (i === namelist.length - 1) {
  13249                 namelist[i] = namelist[i] + terminator;
  13250             }
  13251         }
  13252     }
  13253     return namelist.join("").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020\ufeff\u00a0]+$/,"").replace(/\s*\-\s*/g, "-").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020]+/g, " ");
  13254 };
  13255 CSL.Util.Names.doInitialize = function (state, namelist, terminator, mode) {
  13256     var i, ilen, m, j, jlen, lst, n;
  13257     for (i = 0, ilen = namelist.length; i < ilen; i += 2) {
  13258         n = namelist[i];
  13259         if (!n) {
  13260             continue;
  13261         }
  13262         m = n.match(CSL.NAME_INITIAL_REGEXP);
  13263         if (!m && (!n.match(CSL.STARTSWITH_ROMANESQUE_REGEXP) && n.length > 1 && terminator.match("%s"))) {
  13264             m = n.match(/(.)(.*)/);
  13265         }
  13266         if (m && m[1] === m[1].toUpperCase()) {
  13267             var extra = "";
  13268             if (m[2]) {
  13269                 var s = "";
  13270                 lst = m[2].split("");
  13271                 for (j = 0, jlen = lst.length; j < jlen; j += 1) {
  13272                     var c = lst[j];
  13273                     if (c === c.toUpperCase()) {
  13274                         s += c;
  13275                     } else {
  13276                         break;
  13277                     }
  13278                 }
  13279                 if (s.length < m[2].length) {
  13280                     extra = s.toLocaleLowerCase();
  13281                 }
  13282             }
  13283             namelist[i] = m[1].toLocaleUpperCase() + extra;
  13284             if (i < (ilen - 1)) {
  13285                 if (terminator.match("%s")) {
  13286                     namelist[i] = terminator.replace("%s", namelist[i]);
  13287                 } else {
  13288                     if (namelist[i + 1].indexOf("-") > -1) {
  13289                         namelist[i + 1] = terminator + namelist[i + 1];
  13290                     } else {
  13291                         namelist[i + 1] = terminator;
  13292                     }
  13293                 }
  13294             } else {
  13295                 if (terminator.match("%s")) {
  13296                     namelist[i] = terminator.replace("%s", namelist[i]);
  13297                 } else {
  13298                     namelist.push(terminator);
  13299                 }
  13300             }
  13301         } else if (n.match(CSL.ROMANESQUE_REGEXP)) {
  13302             namelist[i] = " " + n;
  13303         }
  13304     }
  13305     var ret = namelist.join("");
  13306     ret = ret.replace(/[\u0009\u000a\u000b\u000c\u000d\u0020\ufeff\u00a0]+$/,"").replace(/\s*\-\s*/g, "-").replace(/[\u0009\u000a\u000b\u000c\u000d\u0020]+/g, " ");
  13307     return ret;
  13308 };
  13309 CSL.Util.Names.getRawName = function (name) {
  13310     var ret = [];
  13311     if (name.given) {
  13312         ret.push(name.given);
  13313     }
  13314     if (name.family) {
  13315         ret.push(name.family);
  13316     }
  13317     return ret.join(" ");
  13318 };
  13319 CSL.Util.Dates = {};
  13320 CSL.Util.Dates.year = {};
  13321 CSL.Util.Dates.year["long"] = function (state, num) {
  13322     if (!num) {
  13323         if ("boolean" === typeof num) {
  13324             num = "";
  13325         } else {
  13326             num = 0;
  13327         }
  13328     }
  13329     return num.toString();
  13330 };
  13331 CSL.Util.Dates.year.imperial = function (state, num, end, makeShort) {
  13332     var year = "";
  13333     if (!num) {
  13334         if ("boolean" === typeof num) {
  13335             num = "";
  13336         } else {
  13337             num = 0;
  13338         }
  13339     }
  13340     end = end ? "_end" : "";
  13341     var month = state.tmp.date_object["month" + end];
  13342     month = month ? ""+month : "1";
  13343     while (month.length < 2) {
  13344         month = "0" + month;
  13345     }
  13346     var day = state.tmp.date_object["day" + end];
  13347     day = day ? ""+day : "1";
  13348     while (day.length < 2) {
  13349         day = "0" + day;
  13350     }
  13351     var date = parseInt(num + month + day, 10);
  13352     var label;
  13353     var offset;
  13354     if (date >= 18680908 && date < 19120730) {
  13355         label = '\u660e\u6cbb';
  13356         offset = 1867;
  13357     } else if (date >= 19120730 && date < 19261225) {
  13358         label = '\u5927\u6b63';
  13359         offset = 1911;
  13360     } else if (date >= 19261225 && date < 19890108) {
  13361         label = '\u662d\u548c';
  13362         offset = 1925;
  13363     } else if (date >= 19890108) {
  13364         label = '\u5e73\u6210';
  13365         offset = 1988;
  13366     }
  13367     if (label && offset) {
  13368         var normalizedKey = label;
  13369         if (state.sys.normalizeAbbrevsKey) {
  13370             normalizedKey = state.sys.normalizeAbbrevsKey("number", label);
  13371         }
  13372         if (!state.transform.abbrevs['default']['number'][normalizedKey]) {
  13373             state.transform.loadAbbreviation('default', "number", normalizedKey);
  13374         }
  13375         if (state.transform.abbrevs['default']['number'][normalizedKey]) {
  13376             label = state.transform.abbrevs['default']['number'][normalizedKey];
  13377         };
  13378         year = label + (num - offset);
  13379     }
  13380     return year;
  13381 };
  13382 CSL.Util.Dates.year["short"] = function (state, num) {
  13383     num = num.toString();
  13384     if (num && num.length === 4) {
  13385         return num.substr(2);
  13386     }
  13387 };
  13388 CSL.Util.Dates.year.numeric = function (state, num) {
  13389     var m, pre;
  13390     num = "" + num;
  13391     var m = num.match(/([0-9]*)$/);
  13392     if (m) {
  13393         pre = num.slice(0, m[1].length * -1);
  13394         num = m[1];
  13395     } else {
  13396         pre = num;
  13397         num = "";
  13398     }
  13399     while (num.length < 4) {
  13400         num = "0" + num;
  13401     }
  13402     return (pre + num);
  13403 };
  13404 CSL.Util.Dates.normalizeMonth = function (num, useSeason) {
  13405     var ret;
  13406     if (!num) {
  13407         num = 0;
  13408     }
  13409     num = "" + num;
  13410     if (!num.match(/^[0-9]+$/)) {
  13411         num = 0;
  13412     }
  13413     num = parseInt(num, 10);
  13414     if (useSeason) {
  13415         var res = {stub: "month-", num: num};
  13416         if (res.num < 1 || res.num > 20) {
  13417             res.num = 0;
  13418         } else if (res.num > 16) {
  13419             res.stub = "season-";
  13420             res.num = res.num - 16;
  13421         } else if (res.num > 12) {
  13422             res.stub = "season-";
  13423             res.num = res.num - 12;
  13424         }
  13425         ret = res;
  13426     } else {
  13427         if (num < 1 || num > 12) {
  13428             num = 0;
  13429         }
  13430         ret = num;
  13431     }
  13432     return ret;
  13433 }
  13434 CSL.Util.Dates.month = {};
  13435 CSL.Util.Dates.month.numeric = function (state, num) {
  13436     var num = CSL.Util.Dates.normalizeMonth(num);
  13437     if (!num) {
  13438         num = "";
  13439     }
  13440     return num;
  13441 };
  13442 CSL.Util.Dates.month["numeric-leading-zeros"] = function (state, num) {
  13443     var num = CSL.Util.Dates.normalizeMonth(num);
  13444     if (!num) {
  13445         num = "";
  13446     } else {
  13447         num = "" + num;
  13448         while (num.length < 2) {
  13449             num = "0" + num;
  13450         }
  13451     }
  13452     return num;
  13453 };
  13454 CSL.Util.Dates.month["long"] = function (state, num, gender, forceDefaultLocale) {
  13455     var res = CSL.Util.Dates.normalizeMonth(num, true);
  13456     var num = res.num;
  13457     if (!num) {
  13458         num = "";
  13459     } else {
  13460         num = "" + num;
  13461         while (num.length < 2) {
  13462             num = "0" + num;
  13463         }
  13464         num = state.getTerm(res.stub + num, "long", 0, 0, false, forceDefaultLocale);
  13465     }
  13466     return num;
  13467 };
  13468 CSL.Util.Dates.month["short"] = function (state, num, gender, forceDefaultLocale) {
  13469     var res = CSL.Util.Dates.normalizeMonth(num, true);
  13470     var num = res.num;
  13471     if (!num) {
  13472         num = "";
  13473     } else {
  13474         num = "" + num;
  13475         while (num.length < 2) {
  13476             num = "0" + num;
  13477         }
  13478         num = state.getTerm(res.stub + num, "short", 0, 0, false, forceDefaultLocale);
  13479     }
  13480     return num;
  13481 };
  13482 CSL.Util.Dates.day = {};
  13483 CSL.Util.Dates.day.numeric = function (state, num) {
  13484     return num.toString();
  13485 };
  13486 CSL.Util.Dates.day["long"] = CSL.Util.Dates.day.numeric;
  13487 CSL.Util.Dates.day["numeric-leading-zeros"] = function (state, num) {
  13488     if (!num) {
  13489         num = 0;
  13490     }
  13491     num = num.toString();
  13492     while (num.length < 2) {
  13493         num = "0" + num;
  13494     }
  13495     return num.toString();
  13496 };
  13497 CSL.Util.Dates.day.ordinal = function (state, num, gender) {
  13498     return state.fun.ordinalizer.format(num, gender);
  13499 };
  13500 CSL.Util.Sort = {};
  13501 CSL.Util.Sort.strip_prepositions = function (str) {
  13502     var m;
  13503     if ("string" === typeof str) {
  13504         m = str.toLocaleLowerCase();
  13505         m = str.match(/^((a|an|the)\s+)/);
  13506     }
  13507     if (m) {
  13508         str = str.substr(m[1].length);
  13509     }
  13510     return str;
  13511 };
  13512 CSL.Util.substituteStart = function (state, target) {
  13513     var element_trace, display, bib_first, func, choose_start, if_start, nodetypes;
  13514     func = function (state, Item) {
  13515         for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) {
  13516             if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) {
  13517                 state.tmp.strip_periods += 1;
  13518                 break;
  13519             }
  13520         }
  13521     };
  13522     this.execs.push(func);
  13523     if (this.decorations && (state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support)) {
  13524         this.decorations.reverse();
  13525         this.decorations.push(["@showid","true", this.cslid]);
  13526         this.decorations.reverse();
  13527     }
  13528     nodetypes = ["number", "date", "names"];
  13529     if (("text" === this.name && !this.postponed_macro) || nodetypes.indexOf(this.name) > -1) {
  13530         element_trace = function (state, Item, item) {
  13531             if (state.tmp.element_trace.value() === "author" || "names" === this.name) {
  13532                 if (item && item["author-only"]) {
  13533                     state.tmp.element_trace.push("do-not-suppress-me");
  13534                 } else if (item && item["suppress-author"]) {
  13535                 }
  13536             } else {
  13537                 if (item && item["author-only"]) {
  13538                     state.tmp.element_trace.push("suppress-me");
  13539                 } else if (item && item["suppress-author"]) {
  13540                     state.tmp.element_trace.push("do-not-suppress-me");
  13541                 }
  13542             }
  13543         };
  13544         this.execs.push(element_trace);
  13545     }
  13546     display = this.strings.cls;
  13547     this.strings.cls = false;
  13548     if (state.build.render_nesting_level === 0) {
  13549         if (state.build.area === "bibliography" && state.bibliography.opt["second-field-align"]) {
  13550             bib_first = new CSL.Token("group", CSL.START);
  13551             bib_first.decorations = [["@display", "left-margin"]];
  13552             func = function (state, Item) {
  13553                 if (!state.tmp.render_seen) {
  13554                     bib_first.strings.first_blob = Item.id;
  13555                     state.output.startTag("bib_first", bib_first);
  13556                 }
  13557             };
  13558             bib_first.execs.push(func);
  13559             target.push(bib_first);
  13560         } else if (CSL.DISPLAY_CLASSES.indexOf(display) > -1) {
  13561             bib_first = new CSL.Token("group", CSL.START);
  13562             bib_first.decorations = [["@display", display]];
  13563             func = function (state, Item) {
  13564                 bib_first.strings.first_blob = Item.id;
  13565                 state.output.startTag("bib_first", bib_first);
  13566             };
  13567             bib_first.execs.push(func);
  13568             target.push(bib_first);
  13569         }
  13570         state.build.cls = display;
  13571     }
  13572     state.build.render_nesting_level += 1;
  13573     if (state.build.substitute_level.value() === 1) {
  13574         choose_start = new CSL.Token("choose", CSL.START);
  13575         CSL.Node.choose.build.call(choose_start, state, target);
  13576         if_start = new CSL.Token("if", CSL.START);
  13577         func = function (Item,item) {
  13578             if (state.tmp.can_substitute.value()) {
  13579                 return true;
  13580             }
  13581             return false;
  13582         };
  13583         if_start.tests.push(func);
  13584         if_start.test = state.fun.match.any(this, state, if_start.tests);
  13585         target.push(if_start);
  13586     }
  13587     if (state.sys.variableWrapper
  13588         && this.variables_real
  13589         && this.variables_real.length) {
  13590         func = function (state, Item, item) {
  13591             if (!state.tmp.just_looking && !state.tmp.suppress_decorations) {
  13592                 var variable_entry = new CSL.Token("text", CSL.START);
  13593                 variable_entry.decorations = [["@showid", "true"]];
  13594                 state.output.startTag("variable_entry", variable_entry);
  13595                 var position = null;
  13596                 if (item) {
  13597                     position = item.position;
  13598                 }
  13599                 if (!position) position = 0;
  13600                 var positionMap = [
  13601                     "first",
  13602                     "subsequent",
  13603                     "ibid",
  13604                     "ibid-with-locator"
  13605                 ]
  13606                 var noteNumber = 0;
  13607                 if (item && item.noteIndex) {
  13608                     noteNumber = item.noteIndex;
  13609                 }
  13610                 var firstReferenceNoteNumber = 0;
  13611                 if (item && item['first-reference-note-number']) {
  13612                     firstReferenceNoteNumber = item['first-reference-note-number'];
  13613                 }
  13614                 var citationNumber = 0;
  13615                 if (item && item['citation-number']) {
  13616                     citationNumber = item['citation-number'];
  13617                 }
  13618                 var index = 0;
  13619                 if (item && item.index) {
  13620                     index = item.index;
  13621                 }
  13622                 var params = {
  13623                     itemData: Item,
  13624                     variableNames: this.variables,
  13625                     context: state.tmp.area,
  13626                     xclass: state.opt.xclass,
  13627                     position: positionMap[position],
  13628                     "note-number": noteNumber,
  13629                     "first-reference-note-number": firstReferenceNoteNumber,
  13630                     "citation-number": citationNumber,
  13631                     "index": index,
  13632                     "mode": state.opt.mode
  13633                 };
  13634                 state.output.current.value().params = params;
  13635             }
  13636         }
  13637         this.execs.push(func);
  13638     }
  13639 };
  13640 CSL.Util.substituteEnd = function (state, target) {
  13641     var func, bib_first_end, bib_other, if_end, choose_end, toplevel, hasval, author_substitute, str;
  13642     if (state.sys.variableWrapper
  13643         && (this.hasVariable || (this.variables_real && this.variables_real.length))) {
  13644         func = function (state,Item) {
  13645             if (!state.tmp.just_looking && !state.tmp.suppress_decorations) {
  13646                 state.output.endTag("variable_entry");
  13647             }
  13648         }
  13649         this.execs.push(func);
  13650     }
  13651     func = function (state, Item) {
  13652         for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) {
  13653             if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) {
  13654                 state.tmp.strip_periods += -1;
  13655                 break;
  13656             }
  13657         }
  13658     };
  13659     this.execs.push(func);
  13660     state.build.render_nesting_level += -1;
  13661     if (state.build.render_nesting_level === 0) {
  13662         if (state.build.cls) {
  13663             func = function (state, Item) {
  13664                 state.output.endTag("bib_first");
  13665             };
  13666             this.execs.push(func);
  13667             state.build.cls = false;
  13668         } else if (state.build.area === "bibliography" && state.bibliography.opt["second-field-align"]) {
  13669             bib_first_end = new CSL.Token("group", CSL.END);
  13670             func = function (state, Item) {
  13671                 if (!state.tmp.render_seen) {
  13672                     state.output.endTag("bib_first"); // closes bib_first
  13673                 }
  13674             };
  13675             bib_first_end.execs.push(func);
  13676             target.push(bib_first_end);
  13677             bib_other = new CSL.Token("group", CSL.START);
  13678             bib_other.decorations = [["@display", "right-inline"]];
  13679             func = function (state, Item) {
  13680                 if (!state.tmp.render_seen) {
  13681                     state.tmp.render_seen = true;
  13682                     state.output.startTag("bib_other", bib_other);
  13683                 }
  13684             };
  13685             bib_other.execs.push(func);
  13686             target.push(bib_other);
  13687         }
  13688     }
  13689     if (state.build.substitute_level.value() === 1) {
  13690         if_end = new CSL.Token("if", CSL.END);
  13691         target.push(if_end);
  13692         choose_end = new CSL.Token("choose", CSL.END);
  13693         CSL.Node.choose.build.call(choose_end, state, target);
  13694     }
  13695     if ("names" === this.name || ("text" === this.name && this.variables_real !== "title")) {
  13696         author_substitute = new CSL.Token("text", CSL.SINGLETON);
  13697         func = function (state, Item) {
  13698             if (state.tmp.area !== "bibliography") return;
  13699             if ("string" !== typeof state.bibliography.opt["subsequent-author-substitute"]) return;
  13700             if (this.variables_real && !Item[this.variables_real]) return;
  13701             if (state.tmp.substituted_variable !== this.variables_real) {
  13702                 return;
  13703             }
  13704             var subrule = state.bibliography.opt["subsequent-author-substitute-rule"];
  13705             var i, ilen;
  13706             var printing = !state.tmp.suppress_decorations;
  13707             if (printing && state.tmp.subsequent_author_substitute_ok) {
  13708                 if (state.tmp.rendered_name) {
  13709                     if ("partial-each" === subrule || "partial-first" === subrule) {
  13710                         var dosub = true;
  13711                         var rendered_name = [];
  13712                         for (i = 0, ilen = state.tmp.name_node.children.length; i < ilen; i += 1) {
  13713                             var name = state.tmp.rendered_name[i];
  13714                             if (dosub
  13715                                 && state.tmp.last_rendered_name && state.tmp.last_rendered_name.length > (i - 1)
  13716                                 && name && !name.localeCompare(state.tmp.last_rendered_name[i])) {
  13717                                 str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]);
  13718                                 state.tmp.name_node.children[i].blobs = [str];
  13719                                 if ("partial-first" === subrule) {
  13720                                     dosub = false;
  13721                                 }
  13722                             } else {
  13723                                 dosub = false;
  13724                             }
  13725                             rendered_name.push(name);
  13726                         }
  13727                         state.tmp.last_rendered_name = rendered_name;
  13728                     } else if ("complete-each" === subrule) {
  13729                         var rendered_name = state.tmp.rendered_name.join(",");
  13730                         if (rendered_name) {
  13731                             if (state.tmp.last_rendered_name && !rendered_name.localeCompare(state.tmp.last_rendered_name)) {
  13732                                 for (i = 0, ilen = state.tmp.name_node.children.length; i < ilen; i += 1) {
  13733                                     str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]);
  13734                                     state.tmp.name_node.children[i].blobs = [str];
  13735                                 }
  13736                             }
  13737                             state.tmp.last_rendered_name = rendered_name;
  13738                         }
  13739                     } else {
  13740                         var rendered_name = state.tmp.rendered_name.join(",");
  13741                         if (rendered_name) {
  13742                             if (state.tmp.last_rendered_name && !rendered_name.localeCompare(state.tmp.last_rendered_name)) {
  13743                                 str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]);
  13744                                 if (state.tmp.label_blob) {
  13745                                     state.tmp.name_node.top.blobs = [str,state.tmp.label_blob];
  13746                                 } else if (state.tmp.name_node.top.blobs.length) {
  13747                                     state.tmp.name_node.top.blobs[0].blobs = [str];
  13748                                 } else {
  13749                                     state.tmp.name_node.top.blobs = [str];
  13750                                 }
  13751                                 state.tmp.substituted_variable = this.variables_real;
  13752                             }
  13753                             state.tmp.last_rendered_name = rendered_name;
  13754                         }
  13755                     }
  13756                     state.tmp.subsequent_author_substitute_ok = false;
  13757                 }
  13758             }
  13759         };
  13760         this.execs.push(func);
  13761     }
  13762     if (("text" === this.name && !this.postponed_macro) || ["number", "date", "names"].indexOf(this.name) > -1) {
  13763         func = function (state, Item) {
  13764             state.tmp.element_trace.pop();
  13765         };
  13766         this.execs.push(func);
  13767     }
  13768 };
  13769 CSL.Util.padding = function (num) {
  13770     var m = num.match(/\s*(-{0,1}[0-9]+)/);
  13771     if (m) {
  13772         num = parseInt(m[1], 10);
  13773         if (num < 0) {
  13774             num = 99999999999999999999 + num;
  13775         }
  13776         num = "" + num;
  13777         while (num.length < 20) {
  13778             num = "0" + num;
  13779         }
  13780     }
  13781     return num;
  13782 };
  13783 CSL.Util.LongOrdinalizer = function () {};
  13784 CSL.Util.LongOrdinalizer.prototype.init = function (state) {
  13785     this.state = state;
  13786 };
  13787 CSL.Util.LongOrdinalizer.prototype.format = function (num, gender) {
  13788     if (num < 10) {
  13789         num = "0" + num;
  13790     }
  13791     var ret = CSL.Engine.getField(
  13792         CSL.LOOSE, 
  13793         this.state.locale[this.state.opt.lang].terms,
  13794         "long-ordinal-" + num,
  13795         "long", 
  13796         0, 
  13797         gender
  13798     );
  13799     if (!ret) {
  13800         ret = this.state.fun.ordinalizer.format(num, gender);
  13801     }
  13802     this.state.tmp.cite_renders_content = true;
  13803     return ret;
  13804 };
  13805 CSL.Util.Ordinalizer = function (state) {
  13806     this.state = state;
  13807     this.suffixes = {};
  13808 };
  13809 CSL.Util.Ordinalizer.prototype.init = function () {
  13810     if (!this.suffixes[this.state.opt.lang]) {
  13811         this.suffixes[this.state.opt.lang] = {};
  13812         for (var i = 0, ilen = 3; i < ilen; i += 1) {
  13813             var gender = [undefined, "masculine", "feminine"][i];
  13814             this.suffixes[this.state.opt.lang][gender] = [];
  13815             for (var j = 1; j < 5; j += 1) {
  13816                 var ordinal = this.state.getTerm("ordinal-0" + j, "long", false, gender);
  13817                 if ("undefined" === typeof ordinal) {
  13818                     delete this.suffixes[this.state.opt.lang][gender];
  13819                     break;
  13820                 }
  13821                 this.suffixes[this.state.opt.lang][gender].push(ordinal);
  13822             }
  13823         }
  13824     }
  13825 };
  13826 CSL.Util.Ordinalizer.prototype.format = function (num, gender) {
  13827     var str;
  13828     num = parseInt(num, 10);
  13829     str = "" + num;
  13830     var suffix = "";
  13831     var trygenders = [];
  13832     if (gender) {
  13833         trygenders.push(gender);
  13834     }
  13835     trygenders.push("neuter");
  13836     if (this.state.locale[this.state.opt.lang].ord["1.0.1"]) {
  13837         suffix = this.state.getTerm("ordinal",false,0,gender);
  13838         var trygender;
  13839         for (var i = 0, ilen = trygenders.length; i < ilen; i += 1) {
  13840             trygender = trygenders[i];
  13841             var ordinfo = this.state.locale[this.state.opt.lang].ord["1.0.1"];
  13842             if (ordinfo["whole-number"][str] && ordinfo["whole-number"][str][trygender]) {
  13843                 suffix = this.state.getTerm(this.state.locale[this.state.opt.lang].ord["1.0.1"]["whole-number"][str][trygender],false,0,gender);
  13844             } else if (ordinfo["last-two-digits"][str.slice(str.length - 2)] && ordinfo["last-two-digits"][str.slice(str.length - 2)][trygender]) {
  13845                 suffix = this.state.getTerm(this.state.locale[this.state.opt.lang].ord["1.0.1"]["last-two-digits"][str.slice(str.length - 2)][trygender],false,0,gender);
  13846             } else if (ordinfo["last-digit"][str.slice(str.length - 1)] && ordinfo["last-digit"][str.slice(str.length - 1)][trygender]) {
  13847                 suffix = this.state.getTerm(this.state.locale[this.state.opt.lang].ord["1.0.1"]["last-digit"][str.slice(str.length - 1)][trygender],false,0,gender);
  13848             }
  13849             if (suffix) {
  13850                 break;
  13851             }
  13852         }
  13853     } else {
  13854         if (!gender) {
  13855             gender = undefined;
  13856         }
  13857         this.state.fun.ordinalizer.init();
  13858         if ((num / 10) % 10 === 1 || (num > 10 && num < 20)) {
  13859             suffix = this.suffixes[this.state.opt.lang][gender][3];
  13860         } else if (num % 10 === 1 && num % 100 !== 11) {
  13861             suffix = this.suffixes[this.state.opt.lang][gender][0];
  13862         } else if (num % 10 === 2 && num % 100 !== 12) {
  13863             suffix = this.suffixes[this.state.opt.lang][gender][1];
  13864         } else if (num % 10 === 3 && num % 100 !== 13) {
  13865             suffix = this.suffixes[this.state.opt.lang][gender][2];
  13866         } else {
  13867             suffix = this.suffixes[this.state.opt.lang][gender][3];
  13868         }
  13869     }
  13870     str = str += suffix;
  13871     return str;
  13872 };
  13873 CSL.Util.Romanizer = function () {};
  13874 CSL.Util.Romanizer.prototype.format = function (num) {
  13875     var ret, pos, n, numstr, len;
  13876     ret = "";
  13877     if (num < 6000) {
  13878         numstr = num.toString().split("");
  13879         numstr.reverse();
  13880         pos = 0;
  13881         n = 0;
  13882         len = numstr.length;
  13883         for (pos = 0; pos < len; pos += 1) {
  13884             n = parseInt(numstr[pos], 10);
  13885             ret = CSL.ROMAN_NUMERALS[pos][n] + ret;
  13886         }
  13887     }
  13888     return ret;
  13889 };
  13890 CSL.Util.Suffixator = function (slist) {
  13891     if (!slist) {
  13892         slist = CSL.SUFFIX_CHARS;
  13893     }
  13894     this.slist = slist.split(",");
  13895 };
  13896 CSL.Util.Suffixator.prototype.format = function (N) {
  13897     var X;
  13898     N += 1;
  13899     var key = "";
  13900     do {
  13901         X = ((N % 26) === 0) ? 26 : (N % 26);
  13902         var key = this.slist[X-1] + key;
  13903         N = (N - X) / 26;
  13904     } while ( N !== 0 );
  13905     return key;
  13906 };
  13907 CSL.Engine.prototype.processNumber = function (node, ItemObject, variable, type) {
  13908     var val, m, i, ilen, j, jlen;
  13909     var debug = false;
  13910     var me = this;
  13911     function normalizeFieldValue(str, defaultLabel) {
  13912         str = str.trim();
  13913         var m = str.match(/^([^ ]+)/);
  13914         if (m && !CSL.STATUTE_SUBDIV_STRINGS[m[1]]) {
  13915             var embeddedLabel = null;
  13916             if (variable === "locator" ) {
  13917                 if (ItemObject.label) {
  13918                     embeddedLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[ItemObject.label];
  13919                 } else {
  13920                     embeddedLabel = "p.";
  13921                 }
  13922             } else {
  13923                 embeddedLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable];
  13924             }
  13925             if (embeddedLabel) {
  13926                 str = embeddedLabel + " " + str;
  13927             }
  13928         }
  13929         return str;
  13930     }
  13931     function composeNumberInfo(origLabel, label, val, joiningSuffix) {
  13932         joiningSuffix = joiningSuffix ? joiningSuffix : "";
  13933         var info = {};
  13934         if (!label && !CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable]) {
  13935                 label = "var:"+variable;
  13936         }
  13937         if (label) {
  13938             var m = label.match(/(\s*)([^\s]+)(\s*)/);
  13939             info.label = m[2];
  13940             info.origLabel = origLabel;
  13941             info.labelSuffix = m[3] ? m[3] : "";
  13942             info.plural = 0;
  13943             info.labelVisibility = false;
  13944         }
  13945         var m = val.match(/^([0-9]*[a-zA-Z]+0*)?([0-9]+(?:[a-zA-Z]*|[-,a-zA-Z]+))$/);
  13946         if (m) {
  13947             info.particle = m[1] ? m[1] : "";
  13948             info.value = m[2];
  13949         } else {
  13950             info.particle = "";
  13951             info.value = val;
  13952         }
  13953         info.joiningSuffix = joiningSuffix.replace(/\s*-\s*/, "-");
  13954         return info;
  13955     };
  13956     function fixupSubsections(elems) {
  13957         for (var i=elems.length-2;i>-1;i-=2) {
  13958             if (elems[i] === "-"
  13959                && elems[i-1].match(/^(?:(?:[a-z]|[a-z][a-z]|[a-z][a-z][a-z]|[a-z][a-z][a-z][a-z])\.  *)*[0-9]+[,a-zA-Z]+$/)
  13960                && elems[i+1].match(/^[,a-zA-Z]+$/)) {
  13961                 elems[i-1] = elems.slice(i-1,i+2).join("");
  13962                 elems = elems.slice(0,i).concat(elems.slice(i+2));
  13963             }
  13964         }
  13965         return elems;
  13966     }
  13967     function parseString(str, defaultLabel) {
  13968         defaultLabel = defaultLabel ? defaultLabel : "";
  13969         str = normalizeFieldValue(str, defaultLabel);
  13970         var elems = [];
  13971         var m = str.match(/(;\s+|,\s+|\s*\\*[\-\u2013]+\s*|\s*&\s*)/g);
  13972         if (m) {
  13973             var lst = str.split(/(?:;\s+|,\s+|\s*\\*[\-\u2013]+\s*|\s*&\s*)/);
  13974             for (var i=0,ilen=lst.length-1; i<ilen; i++) {
  13975                 elems.push(lst[i]);
  13976                 elems.push(m[i]);
  13977             }
  13978             elems.push(lst[lst.length-1]);
  13979             elems = fixupSubsections(elems);
  13980         } else {
  13981             var elems = [str];
  13982         }
  13983         var values = [];
  13984         var label = defaultLabel;
  13985         var origLabel = "";
  13986         for (var i=0,ilen=elems.length;i<ilen;i += 2) {
  13987             var m = elems[i].match(/((?:^| )(?:[a-z]|[a-z][a-z]|[a-z][a-z][a-z]|[a-z][a-z][a-z][a-z])(?:\.| ) *)/g);
  13988             if (m) {
  13989                 var lst = elems[i].split(/(?:(?:^| )(?:[a-z]|[a-z][a-z]|[a-z][a-z][a-z]|[a-z][a-z][a-z][a-z])(?:\.| ) *)/);
  13990                 for (var j=lst.length-1;j>0;j--) {
  13991                     if (lst[j-1] && (!lst[j].match(/^[0-9]+([-;,:a-zA-Z]*)$/) || !lst[j-1].match(/^[0-9]+([-;,:a-zA-Z]*)$/))) {
  13992                         lst[j-1] = lst[j-1] + m[j-1] + lst[j];
  13993                         lst = lst.slice(0,j).concat(lst.slice(j+1))
  13994                         m = m.slice(0,j-1).concat(m.slice(j))
  13995                     }
  13996                 }
  13997                 if (m.length > 0) {
  13998                     var slug = m[0].trim();
  13999                     var notAlabel = !CSL.STATUTE_SUBDIV_STRINGS[slug]
  14000                         || !me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[slug])
  14001                         || (["locator", "number"].indexOf(variable) === -1 && CSL.STATUTE_SUBDIV_STRINGS[slug] !== variable);
  14002                     if (notAlabel) {
  14003                         if (i === 0) {
  14004                             m = m.slice(1);
  14005                             lst[0] = lst[0] + " " + slug + " " + lst[1];
  14006                             lst = lst.slice(0,1).concat(lst.slice(2))
  14007                         }
  14008                     } else {
  14009                         origLabel = slug;
  14010                     }
  14011                 }
  14012                 for (var j=0,jlen=lst.length; j<jlen; j++) {
  14013                     if (lst[j] || j === (lst.length-1)) {
  14014                         var filteredOrigLabel;
  14015                         label = m[j-1] ? m[j-1] : label;
  14016                         if (origLabel === label.trim()) {
  14017                             filteredOrigLabel = "";
  14018                         } else {
  14019                             filteredOrigLabel = origLabel;
  14020                         }
  14021                         var str = lst[j] ? lst[j].trim() : "";
  14022                         if (j === (lst.length-1)) {
  14023                             values.push(composeNumberInfo(filteredOrigLabel, label, str, elems[i+1]));
  14024                         } else {
  14025                             values.push(composeNumberInfo(filteredOrigLabel, label, str));
  14026                         }
  14027                     }
  14028                 }
  14029             } else {
  14030                 var filteredOrigLabel;
  14031                 if (origLabel === label.trim()) {
  14032                     filteredOrigLabel = "";
  14033                 } else {
  14034                     filteredOrigLabel = origLabel;
  14035                 }
  14036                 values.push(composeNumberInfo(filteredOrigLabel, label, elems[i], elems[i+1]));
  14037             }
  14038         }
  14039         return values;
  14040     }
  14041     function setSpaces(values) {
  14042         for (var i=0,ilen=values.length-1;i<ilen;i++) {
  14043             if (!values[i].joiningSuffix && values[i+1].label) {
  14044                 values[i].joiningSuffix = " ";
  14045             }
  14046         }
  14047     }
  14048     function fixNumericAndCount(values, i, currentLabelInfo) {
  14049         var master = values[currentLabelInfo.pos];
  14050         var val = values[i].value;
  14051         var isEscapedHyphen = master.joiningSuffix === "\\-";
  14052         if (val.particle && val.particle !== master.particle) {
  14053             currentLabelInfo.collapsible = false;
  14054         }
  14055         var mVal = val.match(/^[0-9]+([-,:a-zA-Z]*)$/);
  14056         var mCurrentLabel = master.value.match(/^[0-9]+([-,:a-zA-Z]*)$/);
  14057         if (!val || !mVal || !mCurrentLabel || isEscapedHyphen) {
  14058             currentLabelInfo.collapsible = false;
  14059             if (!val || !mCurrentLabel) {
  14060                 currentLabelInfo.numeric = false;
  14061             }
  14062             if (isEscapedHyphen) {
  14063                 currentLabelInfo.count--;
  14064             }
  14065         }
  14066         if ((mVal && mVal[1]) || (mCurrentLabel && mCurrentLabel[1])) {
  14067             currentLabelInfo.collapsible = false;
  14068         }
  14069         if (undefined === values[i].collapsible) {
  14070             for (var j=i,jlen=i+currentLabelInfo.count;j<jlen;j++) {
  14071                 if (isNaN(parseInt(values[j].value)) && !values[j].value.match(/^[ivxlcmIVXLCM]+$/)) {
  14072                     values[j].collapsible = false;
  14073                 } else {
  14074                     values[j].collapsible = true;
  14075                 }
  14076             }
  14077             currentLabelInfo.collapsible = values[i].collapsible;
  14078         }
  14079         var isCollapsible = currentLabelInfo.collapsible;
  14080         for (var j=currentLabelInfo.pos,jlen=(currentLabelInfo.pos + currentLabelInfo.count); j<jlen; j++) {
  14081             if (currentLabelInfo.count > 1 && isCollapsible) {
  14082                 values[j].plural = 1;
  14083             }
  14084             values[j].numeric = currentLabelInfo.numeric;
  14085             values[j].collapsible = currentLabelInfo.collapsible;
  14086         }
  14087     }
  14088     function fixLabelVisibility(values, groupStartPos, currentLabelInfo) {
  14089         if (currentLabelInfo.label.slice(0, 4) !== "var:") {
  14090             if (currentLabelInfo.pos === 0) {
  14091                 if (variable === "locator" || variable === "number") {
  14092                     if (!me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label])) {
  14093                         values[currentLabelInfo.pos].labelVisibility = true;
  14094                     }
  14095                 }
  14096                 if (["locator", "number"].indexOf(variable) === -1) {
  14097                     if (CSL.STATUTE_SUBDIV_STRINGS[currentLabelInfo.label] !== variable) {
  14098                         values[0].labelVisibility = true;
  14099                     }
  14100                 }
  14101             } else {
  14102                 values[currentLabelInfo.pos].labelVisibility = true;
  14103             }
  14104         }
  14105     }
  14106     function setPluralsAndNumerics(values) {
  14107         if (values.length === 0) return;
  14108         var groupStartPos = 0;
  14109         var groupCount = 1;
  14110         for (var i=1,ilen=values.length;i<ilen;i++) {
  14111             var lastVal = values[i-1];
  14112             var thisVal = values[i];
  14113             if (lastVal.label === thisVal.label && lastVal.particle === lastVal.particle) {
  14114                 groupCount++;
  14115             } else {
  14116                 var currentLabelInfo = JSON.parse(JSON.stringify(values[groupStartPos]));
  14117                 currentLabelInfo.pos = groupStartPos;
  14118                 currentLabelInfo.count = groupCount;
  14119                 currentLabelInfo.numeric = true;
  14120                 fixNumericAndCount(values, groupStartPos, currentLabelInfo);
  14121                 if (i === 0 || (lastVal.label !== thisVal.label)) {
  14122                     fixLabelVisibility(values, groupStartPos, currentLabelInfo);
  14123                 }
  14124                 groupStartPos = i;
  14125                 groupCount = 1;
  14126             }
  14127         }
  14128         var currentLabelInfo = JSON.parse(JSON.stringify(values[groupStartPos]));
  14129         currentLabelInfo.pos = groupStartPos;
  14130         currentLabelInfo.count = groupCount;
  14131         currentLabelInfo.numeric = true;
  14132         fixNumericAndCount(values, groupStartPos, currentLabelInfo);
  14133         fixLabelVisibility(values, groupStartPos, currentLabelInfo);
  14134         if (values.length && values[0].numeric && variable.slice(0, 10) === "number-of-") {
  14135             if (parseInt(ItemObject[variable], 10) > 1) {
  14136                 values[0].plural = 1;
  14137             }
  14138         }
  14139     }        
  14140     function setStyling(values) {
  14141         var masterNode = CSL.Util.cloneToken(node);
  14142         var masterStyling = new CSL.Token();
  14143         if (!me.tmp.just_looking) {
  14144             for (var j=masterNode.decorations.length-1;j>-1;j--) {
  14145                 if (masterNode.decorations[j][0] === "@quotes") {
  14146                     masterStyling.decorations = masterStyling.decorations.concat(masterNode.decorations.slice(j, j+1));
  14147                     masterNode.decorations = masterNode.decorations.slice(0, j).concat(masterNode.decorations.slice(j+1))
  14148                 }
  14149             }
  14150             masterStyling.strings.prefix = masterNode.strings.prefix;
  14151             masterNode.strings.prefix = "";
  14152             masterStyling.strings.suffix = masterNode.strings.suffix;
  14153             masterNode.strings.suffix = "";
  14154         }
  14155         var masterLabel = values.length ? values[0].label : null;
  14156         if (values.length) {
  14157             for (var i=0,ilen=values.length; i<ilen; i++) {
  14158                 var val = values[i];
  14159                 var newnode = CSL.Util.cloneToken(masterNode);
  14160                 newnode.gender = node.gender;
  14161                 if (masterLabel === val.label) {
  14162                     newnode.formatter = node.formatter;
  14163                 }
  14164                 if (val.numeric) {
  14165                     newnode.successor_prefix = val.successor_prefix;
  14166                 }
  14167                 newnode.strings.suffix = newnode.strings.suffix + stripHyphenBackslash(val.joiningSuffix);
  14168                 val.styling = newnode;
  14169             }
  14170             if (!me.tmp.just_looking) {
  14171                 if (values[0].value.slice(0,1) === "\"" && values[values.length-1].value.slice(-1) === "\"") {
  14172                     values[0].value = values[0].value.slice(1);
  14173                     values[values.length-1].value = values[values.length-1].value.slice(0,-1);
  14174                     masterStyling.decorations.push(["@quotes", true]);
  14175                 }
  14176             }
  14177         }
  14178         return masterStyling;
  14179     }
  14180     function stripHyphenBackslash(joiningSuffix) {
  14181         return joiningSuffix.replace("\\-", "-");
  14182     }
  14183     function fixupRangeDelimiter(variable, val, rangeDelimiter, isNumeric) {
  14184         var isPage = checkPage(variable, val);
  14185         var hasTerm = checkTerm(variable, val);
  14186         if (hasTerm && rangeDelimiter === "-") {
  14187             if (isNumeric) {
  14188                 if (isPage || ["locator", "issue", "volume", "edition", "number"].indexOf(variable) > -1) {
  14189                     rangeDelimiter = me.getTerm("page-range-delimiter")
  14190                     if (!rangeDelimiter) {
  14191                         rangeDelimiter = "\u2013";
  14192                     }
  14193                 }
  14194                 if (variable === "collection-number") {
  14195                     rangeDelimiter = me.getTerm("year-range-delimiter");
  14196                     if (!rangeDelimiter) {
  14197                         rangeDelimiter = "\u2013";
  14198                     }
  14199                 }
  14200             }
  14201         }
  14202         return rangeDelimiter;
  14203     }
  14204     function checkPage(variable, val) {
  14205         return variable === "page" 
  14206             || (variable === "locator" && (["p."].indexOf(val.label) > -1 || ["p."].indexOf(val.origLabel) > -1));
  14207     }
  14208     function checkTerm(variable, val) {
  14209         var ret = true;
  14210         if (variable === "locator") {
  14211             var label;
  14212             if (val.origLabel) {
  14213                 label = val.origLabel;
  14214             } else {
  14215                 label = val.label;
  14216             }
  14217             ret = !!me.getTerm(CSL.STATUTE_SUBDIV_STRINGS[label]);
  14218         }
  14219         return ret;
  14220     }
  14221     function manglePageNumbers(values, i, currentInfo) {
  14222         if (i<1) return;
  14223         if (currentInfo.count !== 2) {
  14224             return;
  14225         }
  14226         if (values[i-1].particle !== values[i].particle) {
  14227             return;
  14228         }
  14229         if (values[i-1].joiningSuffix !== "-") {
  14230             currentInfo.count = 1;
  14231             return;
  14232         }
  14233         if (!me.opt["page-range-format"] && parseInt(values[i-1].value, 10) > parseInt(values[i].value, 10)) {
  14234             values[i-1].joiningSuffix = fixupRangeDelimiter(variable, values[i], values[i-1].joiningSuffix, true);
  14235             return;
  14236         }
  14237         var val = values[i];
  14238         var isPage = checkPage(variable, val);
  14239         if (isPage && !isNaN(parseInt(values[i-1].value)) && !isNaN(parseInt(values[i].value))) {
  14240             var str = values[i-1].particle + values[i-1].value + " - " + values[i].particle + values[i].value;
  14241             str = me.fun.page_mangler(str);
  14242         } else {
  14243             if (("" + values[i-1].value).match(/^([0-9]+|[ivxlcmIVXLCM]+)$/) && ("" + values[i].value).match(/^([0-9]+|[ivxlcmIVXLCM]+)$/)) {
  14244                 values[i-1].joiningSuffix = me.getTerm("page-range-delimiter");
  14245             }
  14246             str = values[i-1].value + stripHyphenBackslash(values[i-1].joiningSuffix) + values[i].value;
  14247         }
  14248         var m = str.match(/^((?:[0-9]*[a-zA-Z]+0*))?([0-9]+)(\s*[^0-9]+\s*)([-,a-zA-Z]?0*)([0-9]+)$/);
  14249         if (m) {
  14250             var rangeDelimiter = m[3];
  14251             rangeDelimiter = fixupRangeDelimiter(variable, val, rangeDelimiter, values[i].numeric);
  14252             values[i-1].particle = m[1];
  14253             values[i-1].value = m[2];
  14254             values[i-1].joiningSuffix = rangeDelimiter;
  14255             values[i].particle = m[4];
  14256             values[i].value = m[5];
  14257         }
  14258         currentInfo.count = 0;
  14259     }
  14260     function fixRanges(values) {
  14261         if (!node) return;
  14262         if (["page", "page-first", "chapter-number", "collection-number", "edition", "issue", "number", "number-of-pages", "number-of-volumes", "volume", "locator"].indexOf(variable) === -1) return;
  14263         var currentInfo = {
  14264             count: 0,
  14265             label: null,
  14266             lastHadRangeDelimiter: false
  14267         }
  14268         for (var i=0,ilen=values.length; i<ilen; i++) {
  14269             var val = values[i];
  14270             if (!val.collapsible) {
  14271                 currentInfo.count = 0;
  14272                 currentInfo.label = null;
  14273                 var isNumeric = val.numeric;
  14274                 val.joiningSuffix = fixupRangeDelimiter(variable, val, val.joiningSuffix, isNumeric);
  14275             } else if (currentInfo.label === val.label && val.joiningSuffix === "-") {
  14276                 currentInfo.count = 1;
  14277             } else if (currentInfo.label === val.label && val.joiningSuffix !== "-") {
  14278                 currentInfo.count++;
  14279                 if (currentInfo.count === 2) {
  14280                     manglePageNumbers(values, i, currentInfo);
  14281                 }
  14282             } else if (currentInfo.label !== val.label) {
  14283                 currentInfo.label = val.label;
  14284                 currentInfo.count = 1;
  14285             } else {
  14286                 currentInfo.count = 1;
  14287                 currentInfo.label = val.label;
  14288             }
  14289         }
  14290         if (currentInfo.count === 2) {
  14291             manglePageNumbers(values, values.length-1, currentInfo);
  14292         }
  14293     }
  14294     function setVariableParams(shadow_numbers, variable, values) {
  14295         var obj = shadow_numbers[variable];
  14296         if (values.length) {
  14297             obj.numeric = values[0].numeric;
  14298             obj.collapsible = values[0].collapsible;
  14299             obj.plural = values[0].plural;
  14300             obj.label = CSL.STATUTE_SUBDIV_STRINGS[values[0].label];
  14301             if (variable === "number" && obj.label === "issue" && me.getTerm("number")) {
  14302                 obj.label = "number";
  14303             }
  14304         }
  14305     }
  14306     if (node && this.tmp.shadow_numbers[variable] && this.tmp.shadow_numbers[variable].values.length) {
  14307         var values = this.tmp.shadow_numbers[variable].values;
  14308         fixRanges(values);
  14309             this.tmp.shadow_numbers[variable].masterStyling = setStyling(values);
  14310         return;
  14311     }
  14312     if (!this.tmp.shadow_numbers[variable]) {
  14313         this.tmp.shadow_numbers[variable] = {
  14314             values:[]
  14315         };
  14316     }
  14317     if (!ItemObject) {
  14318         return;
  14319     }
  14320     var languageRole = CSL.LangPrefsMap[variable];
  14321     if (languageRole) {
  14322         var localeType = this.opt["cite-lang-prefs"][languageRole][0];
  14323         val = this.transform.getTextSubField(ItemObject, variable, "locale-"+localeType, true);
  14324         val = val.name;
  14325     } else {
  14326         val = ItemObject[variable];
  14327     }
  14328     if (val && this.sys.getAbbreviation) {
  14329         var jurisdiction = this.transform.loadAbbreviation(ItemObject.jurisdiction, "number", val);
  14330         if (this.transform.abbrevs[jurisdiction].number) {
  14331             if (this.transform.abbrevs[jurisdiction].number[val]) {
  14332                 val = this.transform.abbrevs[jurisdiction].number[val];
  14333             } else {
  14334                 if ("undefined" !== typeof this.transform.abbrevs[jurisdiction].number[val]) {
  14335                     delete this.transform.abbrevs[jurisdiction].number[val];
  14336                 }
  14337             }
  14338         }
  14339     }
  14340     if ("undefined" !== typeof val && ("string" === typeof val || "number" === typeof val)) {
  14341         if ("number" === typeof val) {
  14342             val = "" + val;
  14343         }
  14344         var defaultLabel = CSL.STATUTE_SUBDIV_STRINGS_REVERSE[variable];
  14345         if (!this.tmp.shadow_numbers.values) {
  14346             var values = parseString(val, defaultLabel);
  14347             setSpaces(values);
  14348             setPluralsAndNumerics(values);
  14349             this.tmp.shadow_numbers[variable].values = values;
  14350         }
  14351         if (node) {
  14352             fixRanges(values);
  14353             this.tmp.shadow_numbers[variable].masterStyling = setStyling(values)
  14354         }
  14355         setVariableParams(this.tmp.shadow_numbers, variable, values);
  14356     }
  14357 };
  14358 CSL.Util.outputNumericField = function(state, varname, itemID) {
  14359     state.output.openLevel(state.tmp.shadow_numbers[varname].masterStyling);
  14360     var nums = state.tmp.shadow_numbers[varname].values;
  14361     var masterLabel = nums.length ? nums[0].label : null;
  14362     var labelForm = state.tmp.shadow_numbers[varname].labelForm;
  14363     var embeddedLabelForm;
  14364     if (labelForm) {
  14365         embeddedLabelForm = labelForm
  14366     } else {
  14367         embeddedLabelForm = "short";
  14368     }
  14369     var labelCapitalizeIfFirst = state.tmp.shadow_numbers[varname].labelCapitalizeIfFirst;
  14370     var labelDecorations = state.tmp.shadow_numbers[varname].labelDecorations;
  14371     var lastLabelName = null;
  14372     for (var i=0,ilen=nums.length;i<ilen;i++) {
  14373         var num = nums[i];
  14374         var label = "";
  14375         if (num.label) {
  14376             var labelName;
  14377             if ('var:' === num.label.slice(0,4)) {
  14378                 labelName = num.label.slice(4);
  14379             } else {
  14380                 labelName = CSL.STATUTE_SUBDIV_STRINGS[num.label];
  14381             }
  14382             if (labelName) {
  14383                 if (num.label === masterLabel) {
  14384                     label = state.getTerm(labelName, labelForm, num.plural);
  14385                 } else {
  14386                     label = state.getTerm(labelName, embeddedLabelForm, num.plural);
  14387                 }
  14388                 if (labelCapitalizeIfFirst) {
  14389                     label = CSL.Output.Formatters["capitalize-first"](state, label);
  14390                 }
  14391             }
  14392         }
  14393         var labelPlaceholderPos = -1;
  14394         if (label) {
  14395             labelPlaceholderPos = label.indexOf("%s");
  14396         }
  14397         var numStyling = CSL.Util.cloneToken(num.styling);
  14398         numStyling.formatter = num.styling.formatter;
  14399         numStyling.type = num.styling.type;
  14400         numStyling.num = num.styling.num;
  14401         numStyling.gender = num.styling.gender;
  14402         if (labelPlaceholderPos > 0 && labelPlaceholderPos < (label.length-2)) {
  14403             numStyling.strings.prefix += label.slice(0,labelPlaceholderPos);
  14404             numStyling.strings.suffix = label.slice(labelPlaceholderPos+2) + numStyling.strings.suffix;
  14405         } else if (num.labelVisibility) {
  14406             if (!label) {
  14407                 label = num.label;
  14408                 labelName = num.label;
  14409             }
  14410             if (labelPlaceholderPos > 0) {
  14411                 var prefixLabelStyling = new CSL.Token();
  14412                 prefixLabelStyling.decorations = labelDecorations;
  14413                 state.output.append(label.slice(0,labelPlaceholderPos), prefixLabelStyling);
  14414             } else if (labelPlaceholderPos === (label.length-2) || labelPlaceholderPos === -1) {
  14415                 state.output.append(label+num.labelSuffix, "empty");
  14416             }
  14417         }
  14418         if (num.collapsible) {
  14419             if (num.value.match(/^[1-9][0-9]*$/)) {
  14420                 var blob = new CSL.NumericBlob(num.particle, parseInt(num.value, 10), numStyling, itemID);
  14421             } else {
  14422                 var blob = new CSL.NumericBlob(num.particle, num.value, numStyling, itemID);
  14423             }
  14424             if ("undefined" === typeof blob.gender) {
  14425                 blob.gender = state.locale[state.opt.lang]["noun-genders"][varname];
  14426             }
  14427             state.output.append(blob, "literal");
  14428         } else {
  14429             state.output.append(num.particle + num.value, numStyling)
  14430         }
  14431         if (labelPlaceholderPos === 0 && labelPlaceholderPos < (label.length-2)) {
  14432             if (lastLabelName === null) {
  14433                 lastLabelName = labelName;
  14434             }
  14435             if (labelName !== lastLabelName || i === (nums.length-1)) {
  14436                 var suffixLabelStyling = new CSL.Token();
  14437                 suffixLabelStyling.decorations = labelDecorations;
  14438                 state.output.append(label.slice(labelPlaceholderPos+2), suffixLabelStyling);
  14439             }
  14440         }
  14441         lastLabelName === labelName;
  14442         state.tmp.term_predecessor = true;
  14443     }
  14444     state.output.closeLevel();
  14445 }
  14446 CSL.Util.PageRangeMangler = {};
  14447 CSL.Util.PageRangeMangler.getFunction = function (state, rangeType) {
  14448     var rangerex, pos, len, stringify, listify, expand, minimize, minimize_internal, chicago, lst, m, b, e, ret, begin, end, ret_func, ppos, llen;
  14449     var range_delimiter = state.getTerm(rangeType + "-range-delimiter");
  14450     rangerex = /([0-9]*[a-zA-Z]+0*)?([0-9]+)\s*(?:\u2013|-)\s*([0-9]*[a-zA-Z]+0*)?([0-9]+)/;
  14451     stringify = function (lst) {
  14452         len = lst.length;
  14453         for (pos = 1; pos < len; pos += 2) {
  14454             if ("object" === typeof lst[pos]) {
  14455                 lst[pos] = lst[pos].join("");
  14456             }
  14457         }
  14458         var ret = lst.join("");
  14459         ret = ret.replace(/([^\\])\-/g, "$1"+state.getTerm(rangeType + "-range-delimiter"));
  14460         return ret;
  14461     };
  14462     listify = function (str) {
  14463         var m, lst, ret;
  14464         var hyphens = "\\s+\\-\\s+";
  14465         var this_range_delimiter = range_delimiter === "-" ? "" : range_delimiter;
  14466         var delimRex = new RegExp("([^\\\\])[-" + this_range_delimiter + "\\u2013]", "g");
  14467         str = str.replace(delimRex, "$1 - ").replace(/\s+-\s+/g, " - ");
  14468         var rexm = new RegExp("((?:[0-9]*[a-zA-Z]+0*)?[0-9]+" + hyphens + "(?:[0-9]*[a-zA-Z]+0*)?[0-9]+)", "g");
  14469         var rexlst = new RegExp("(?:[0-9]*[a-zA-Z]+0*)?[0-9]+" + hyphens + "(?:[0-9]*[a-zA-Z]+0*)?[0-9]+");
  14470         m = str.match(rexm);
  14471         lst = str.split(rexlst);
  14472         if (lst.length === 0) {
  14473             ret = m;
  14474         } else {
  14475             ret = [lst[0]];
  14476             for (pos = 1, len = lst.length; pos < len; pos += 1) {
  14477                 ret.push(m[pos - 1].replace(/\s*\-\s*/g, "-"));
  14478                 ret.push(lst[pos]);
  14479             }
  14480         }
  14481         return ret;
  14482     };
  14483     expand = function (str) {
  14484         str = "" + str;
  14485         lst = listify(str);
  14486         len = lst.length;
  14487         for (pos = 1; pos < len; pos += 2) {
  14488             m = lst[pos].match(rangerex);
  14489             if (m) {
  14490                 if (!m[3] || m[1] === m[3]) {
  14491                     if (m[4].length < m[2].length) {
  14492                         m[4] = m[2].slice(0, (m[2].length - m[4].length)) + m[4];
  14493                     }
  14494                     if (parseInt(m[2], 10) < parseInt(m[4], 10)) {
  14495                         m[3] = range_delimiter + (m[1] ? m[1] : "");
  14496                         lst[pos] = m.slice(1);
  14497                     }
  14498                 }
  14499             }
  14500             if ("string" === typeof lst[pos]) {
  14501                 lst[pos] = lst[pos].replace(/\-/g, range_delimiter);
  14502             }
  14503         }
  14504         return lst;
  14505     };
  14506     minimize = function (lst, minchars, isyear) {
  14507         len = lst.length;
  14508         for (var i = 1, ilen = lst.length; i < ilen; i += 2) {
  14509             lst[i][3] = minimize_internal(lst[i][1], lst[i][3], minchars, isyear);
  14510             if (lst[i][2].slice(1) === lst[i][0]) {
  14511                 lst[i][2] = range_delimiter;
  14512             }
  14513         }
  14514         return stringify(lst);
  14515     };
  14516     minimize_internal = function (begin, end, minchars, isyear) {
  14517         if (!minchars) {
  14518             minchars = 0;
  14519         }
  14520         b = ("" + begin).split("");
  14521         e = ("" + end).split("");
  14522         ret = e.slice();
  14523         ret.reverse();
  14524         if (b.length === e.length) {
  14525             for (var i = 0, ilen = b.length; i < ilen; i += 1) {
  14526                 if (b[i] === e[i] && ret.length > minchars) {
  14527                     ret.pop();
  14528                 } else {
  14529                     if (minchars && isyear && ret.length === 3) {
  14530                         var front = b.slice(0, i);
  14531                         front.reverse();
  14532                         ret = ret.concat(front);
  14533                     }
  14534                     break;
  14535                 }
  14536             }
  14537         }
  14538         ret.reverse();
  14539         return ret.join("");
  14540     };
  14541     chicago = function (lst) {
  14542         len = lst.length;
  14543         for (pos = 1; pos < len; pos += 2) {
  14544             if ("object" === typeof lst[pos]) {
  14545                 m = lst[pos];
  14546                 begin = parseInt(m[1], 10);
  14547                 end = parseInt(m[3], 10);
  14548                 if (begin > 100 && begin % 100 && parseInt((begin / 100), 10) === parseInt((end / 100), 10)) {
  14549                     m[3] = "" + (end % 100);
  14550                 } else if (begin >= 10000) {
  14551                     m[3] = "" + (end % 1000);
  14552                 }
  14553             }
  14554             if (m[2].slice(1) === m[0]) {
  14555                 m[2] = range_delimiter;
  14556             }
  14557         }
  14558         return stringify(lst);
  14559     };
  14560     var sniff = function (str, func, minchars, isyear) {
  14561         var ret;
  14562 		str = "" + str;
  14563 		var lst = expand(str);
  14564         var ret = func(lst, minchars, isyear);
  14565         return ret;
  14566     }
  14567     if (!state.opt[rangeType + "-range-format"]) {
  14568         ret_func = function (str) {
  14569             return sniff(str, stringify);
  14570         };
  14571     } else if (state.opt[rangeType + "-range-format"] === "expanded") {
  14572         ret_func = function (str) {
  14573             return sniff(str, stringify);
  14574         };
  14575     } else if (state.opt[rangeType + "-range-format"] === "minimal") {
  14576         ret_func = function (str) {
  14577             return sniff(str, minimize);
  14578         };
  14579     } else if (state.opt[rangeType + "-range-format"] === "minimal-two") {
  14580         ret_func = function (str, isyear) {
  14581             return sniff(str, minimize, 2, isyear);
  14582         };
  14583     } else if (state.opt[rangeType + "-range-format"] === "chicago") {
  14584         ret_func = function (str) {
  14585             return sniff(str, chicago);
  14586         };
  14587     }
  14588     return ret_func;
  14589 };
  14590 CSL.Util.FlipFlopper = function(state) {
  14591     this.processTags = processTags;
  14592     var _nestingState = [];
  14593     var _nestingData = {
  14594         "<span class=\"nocase\">": {
  14595             type: "nocase",
  14596             opener: "<span class=\"nocase\">",
  14597             closer: "</span>",
  14598             attr: null,
  14599             outer: null,
  14600             flipflop: null
  14601         },
  14602         "<span class=\"nodecor\">": {
  14603             type: "nodecor",
  14604             opener: "<span class=\"nodecor\">",
  14605             closer: "</span>",
  14606             attr: "@class",
  14607             outer: "nodecor",
  14608             flipflop: {
  14609                 "nodecor": "nodecor"
  14610             }
  14611         },
  14612         "<span style=\"font-variant:small-caps;\">": {
  14613             type: "tag",
  14614             opener: "<span style=\"font-variant:small-caps;\">",
  14615             closer: "</span>",
  14616             attr: "@font-variant",
  14617             outer: "small-caps",
  14618             flipflop: {
  14619                 "small-caps": "normal",
  14620                 "normal": "small-caps"
  14621             }
  14622         },
  14623         "<sc>": {
  14624             type: "tag",
  14625             opener: "<sc>",
  14626             closer: "</sc>",
  14627             attr: "@font-variant",
  14628             outer: "small-caps",
  14629             flipflop: {
  14630                 "small-caps": "normal",
  14631                 "normal": "small-caps"
  14632             }
  14633         },
  14634         "<i>": {
  14635             type: "tag",
  14636             opener: "<i>",
  14637             closer: "</i>",
  14638             attr: "@font-style",
  14639             outer: "italic",
  14640             flipflop: {
  14641                 "italic": "normal",
  14642                 "normal": "italic"
  14643             }
  14644         },
  14645         "<b>": {
  14646             type: "tag",
  14647             opener: "<b>",
  14648             closer: "</b>",
  14649             attr: "@font-weight",
  14650             outer: "bold",
  14651             flipflop: {
  14652                 "bold": "normal",
  14653                 "normal": "bold"
  14654             }
  14655         },
  14656         "<sup>": {
  14657             type: "tag",
  14658             opener: "<sup>",
  14659             closer: "</sup>",
  14660             attr: "@vertical-align",
  14661             outer: "sup",
  14662             flipflop: {
  14663                 "sub": "sup",
  14664                 "sup": "sup"
  14665             }
  14666         },
  14667         "<sub>": {
  14668             type: "tag",
  14669             opener: "<sub>",
  14670             closer: "</sub>",
  14671             attr: "@vertical-align",
  14672             outer: "sub",
  14673             flipflop: {
  14674                 "sup": "sub",
  14675                 "sub": "sub"
  14676             }
  14677         },
  14678         " \"": {
  14679             type: "quote",
  14680             opener: " \"",
  14681             closer: "\"",
  14682             attr: "@quotes",
  14683             outer: "true",
  14684             flipflop: {
  14685                 "true": "inner",
  14686                 "inner": "true",
  14687                 "false": "true"
  14688             }
  14689         },
  14690         " \'": {
  14691             type: "quote",
  14692             opener: " \'",
  14693             closer: "\'",
  14694             attr: "@quotes",
  14695             outer: "inner",
  14696             flipflop: {
  14697                 "true": "inner",
  14698                 "inner": "true",
  14699                 "false": "true"
  14700             }
  14701         }
  14702     }
  14703     _nestingData["(\""] = _nestingData[" \""]
  14704     _nestingData["(\'"] = _nestingData[" \'"]
  14705     var localeOpenQuote = state.getTerm("open-quote");
  14706     var localeCloseQuote = state.getTerm("close-quote");
  14707     var localeOpenInnerQuote = state.getTerm("open-inner-quote");
  14708     var localeCloseInnerQuote = state.getTerm("close-inner-quote");
  14709     if (localeOpenQuote && localeCloseQuote && [" \""," \'","\"","\'"].indexOf(localeOpenQuote) === -1) {
  14710         _nestingData[localeOpenQuote] = JSON.parse(JSON.stringify(_nestingData[" \""]));
  14711         _nestingData[localeOpenQuote].opener = localeOpenQuote;
  14712         _nestingData[localeOpenQuote].closer = localeCloseQuote;
  14713     }
  14714     if (localeOpenInnerQuote && localeCloseInnerQuote && [" \""," \'","\"","\'"].indexOf(localeOpenInnerQuote) === -1) {
  14715         _nestingData[localeOpenInnerQuote] = JSON.parse(JSON.stringify(_nestingData[" \'"]));
  14716         _nestingData[localeOpenInnerQuote].opener = localeOpenInnerQuote;
  14717         _nestingData[localeOpenInnerQuote].closer = localeCloseInnerQuote;
  14718     }
  14719     var _nestingQuoteReverse = function() {
  14720         var ret = {};
  14721         var keys = Object.keys(_nestingData);
  14722         for (var i = 0, l = keys.length; i < l; i++) {
  14723             var key = keys[i];
  14724             if (_nestingData[key].type === "quote") {
  14725                 ret[_nestingData[key].closer] = _nestingData[key];
  14726             }
  14727         }
  14728         return ret;
  14729     }();
  14730     var _nestingDataAttr = function() {
  14731         var ret = {};
  14732         var keys = Object.keys(_nestingData);
  14733         for (var i = 0, l = keys.length; i < l; i++) {
  14734             var key = keys[i];
  14735             if (_nestingData[key].type === "nocase") continue;
  14736             var attr = _nestingData[key].attr;
  14737             var outer = _nestingData[key].outer;
  14738             var inner = _nestingData[key].flipflop[_nestingData[key].outer];
  14739             ret[attr + "/" + outer] = _nestingData[key];
  14740             ret[attr + "/" + inner] = _nestingData[key];
  14741         }
  14742         return ret;
  14743     }();
  14744     function _setOuterQuoteForm(quot) {
  14745         var flip = {
  14746             " \'": " \"",
  14747             " \"": " \'",
  14748             "(\"": "(\'",
  14749             "(\'": "(\""
  14750         }
  14751         _nestingData[quot].outer = "true";
  14752         _nestingData[flip[quot]].outer = "inner";
  14753     }
  14754     function _getNestingOpenerParams(opener) {
  14755         var openers = [];
  14756         var closer;
  14757         var keys = Object.keys(_nestingData);
  14758         for (var i = 0, l = keys.length; i < l; i++) {
  14759             var key = keys[i];
  14760             if (_nestingData[opener].type !== "quote" || !_nestingData[opener]) {
  14761                 openers.push(key);
  14762             }
  14763         }
  14764         var ret = _nestingData[opener];
  14765         ret.opener = new RegExp("^(?:" + openers.map(function(str){return str.replace("(", "\\(")}).join("|") + ")"); 
  14766         return ret;
  14767     }
  14768     var _nestingParams = function() {
  14769         var ret = {};
  14770         var keys = Object.keys(_nestingData);
  14771         for (var i = 0, l = keys.length; i < l; i++) {
  14772             var key = keys[i];
  14773             ret[key] = _getNestingOpenerParams(key);
  14774         }
  14775         return ret;
  14776     }()
  14777     var _tagRex = function() {
  14778         var openers = [];
  14779         var closers = [];
  14780         var vals = {};
  14781         for (var opener in _nestingParams) {
  14782             openers.push(opener);
  14783             vals[_nestingParams[opener].closer] = true;
  14784         }
  14785         var keys = Object.keys(vals);
  14786         for (var i = 0, l = keys.length; i < l; i++) {
  14787             var closer = keys[i];
  14788             closers.push(closer);
  14789         }
  14790         var all = openers.concat(closers).map(function(str){return str.replace("(", "\\(")}).join("|");
  14791         return {
  14792             matchAll: new RegExp("((?:" + all + "))", "g"),
  14793             splitAll: new RegExp("(?:" + all + ")", "g"),
  14794             open: new RegExp("(^(?:" + openers.map(function(str){return str.replace("(", "\\(")}).join("|") + ")$)"),
  14795             close: new RegExp("(^(?:" + closers.join("|") + ")$)"),
  14796         }
  14797     }();
  14798     function _nestingFix (tag, pos) {
  14799         return _pushNestingState(tag, pos);
  14800     }
  14801     function _pushNestingState(tag, pos) {
  14802         if (tag.match(_tagRex.open)) {
  14803             return _tryOpen(tag, pos);
  14804         } else {
  14805             return _tryClose(tag, pos);
  14806         }
  14807     }
  14808     function _tryOpen(tag, pos) {
  14809         var params = _nestingState[_nestingState.length - 1];
  14810         if (!params || tag.match(params.opener)) {
  14811             _nestingState.push({
  14812                 type: _nestingParams[tag].type,
  14813                 opener: _nestingParams[tag].opener,
  14814                 closer: _nestingParams[tag].closer,
  14815                 pos: pos
  14816             });
  14817             return false;
  14818         } else {
  14819             _nestingState.pop()
  14820             _nestingState.push({
  14821                 type: _nestingParams[tag].type,
  14822                 opener: _nestingParams[tag].opener,
  14823                 closer: _nestingParams[tag].closer,
  14824                 pos: pos
  14825             });
  14826             return {
  14827                 fixtag: params.pos
  14828             };
  14829         }
  14830     }
  14831     function _tryClose(tag, pos) {
  14832         var params = _nestingState[_nestingState.length - 1];
  14833         if (params && tag === params.closer) {
  14834             _nestingState.pop()
  14835             if (params.type === "nocase") {
  14836                 return {
  14837                     nocase: {
  14838                         open: params.pos,
  14839                         close: pos
  14840                     }
  14841                 }
  14842             } else {
  14843                 return false;
  14844             }
  14845         } else {
  14846             if (params) {
  14847                 return {
  14848                     fixtag: params.pos
  14849                 };
  14850             } else {
  14851                 return {
  14852                     fixtag: pos
  14853                 };
  14854             }
  14855         }
  14856     }
  14857     function _doppelString(str) {
  14858         var forcedSpaces = [];
  14859         str = str.replace(/(<span)\s+(style=\"font-variant:)\s*(small-caps);?\"[^>]*(>)/g, "$1 $2$3;\"$4");
  14860         str = str.replace(/(<span)\s+(class=\"no(?:case|decor)\")[^>]*(>)/g, "$1 $2$3");
  14861         var match = str.match(_tagRex.matchAll);
  14862         if (!match) {
  14863             return {
  14864                 tags: [],
  14865                 strings: [str],
  14866                 forcedSpaces: []
  14867             };
  14868         }
  14869         var split = str.split(_tagRex.splitAll);
  14870         for (var i=0,ilen=match.length-1;i<ilen;i++) {
  14871             if (_nestingData[match[i]]) {
  14872                 if (split[i+1] === "" && ["\"", "'"].indexOf(match[i+1]) > -1) {
  14873                     match[i+1] = " " + match[i+1]
  14874                     forcedSpaces.push(true);
  14875                 } else {
  14876                     forcedSpaces.push(false);
  14877                 }
  14878             }
  14879         }
  14880         return {
  14881             tags: match,
  14882             strings: split,
  14883             forcedSpaces: forcedSpaces
  14884         }
  14885     }
  14886     function _undoppelString(obj) {
  14887         var lst = obj.strings.slice(-1);
  14888         for (var i=obj.tags.length-1; i>-1; i+=-1) {
  14889             lst.push(obj.tags[i]);
  14890             lst.push(obj.strings[i]);
  14891         }
  14892         lst.reverse();
  14893         return lst.join("|");
  14894     }
  14895     var _TagReg = function(blob) {
  14896         this.set = set;
  14897         this.pair = pair;
  14898         this.pop = pop;
  14899         var _stack = [];
  14900         function set(tag) {
  14901             var attr = _nestingData[tag].attr;
  14902             var decor = null;
  14903             for (var i=_stack.length-1;i>-1;i--) {
  14904                 var _decor = _stack[i];
  14905                 if (_decor[0] === attr) {
  14906                     decor = _decor;
  14907                     break;
  14908                 }
  14909             }
  14910             if (!decor) {
  14911                 var allTheDecor = [state[state.tmp.area].opt.layout_decorations].concat(blob.alldecor)
  14912                 outer:
  14913                 for (var i=allTheDecor.length-1;i>-1;i--) {
  14914                     var decorset = allTheDecor[i];
  14915                     if (!decorset) continue;
  14916                     for (var j=decorset.length-1;j>-1;j--) {
  14917                         var _decor = decorset[j];
  14918                         if (_decor[0] === attr) {
  14919                             decor = _decor;
  14920                             break outer;
  14921                         }
  14922                     }
  14923                 }
  14924             }
  14925             if (!decor) {
  14926                 decor = [attr, _nestingData[tag].outer];
  14927             } else {
  14928                 decor = [attr, _nestingData[tag].flipflop[decor[1]]];
  14929             }
  14930             _stack.push(decor);
  14931         }
  14932         function pair() {
  14933             return _stack[_stack.length-1];
  14934         }
  14935         function pop() {
  14936             _stack.pop();
  14937         }
  14938     }
  14939     function _apostropheForce(tag, str) {
  14940         if (tag === "\'") {
  14941             if (str && str.match(/^[^\,\.\?\:\;\ ]/)) {
  14942                 return true;
  14943             }
  14944         } else if (tag === " \'" && str && str.match(/^[\ ]/)) {
  14945             return true;
  14946         }
  14947         return false;
  14948     }
  14949     function _undoppelToQueue(blob, doppel, leadingSpace) {
  14950         var TOP = blob;
  14951         var firstString = true;
  14952         var tagReg = new _TagReg(blob);
  14953         blob.blobs = [];
  14954         function Stack (blob) {
  14955             this.stack = [blob];
  14956             this.latest = blob;
  14957             this.addStyling = function(str, decor, forcedSpace) {
  14958                 if (firstString) {
  14959                     if (str.slice(0, 1) === " ") {
  14960                         str = str.slice(1);
  14961                     }
  14962                     if (str.slice(0, 1) === " ") {
  14963                         str = str.slice(1);
  14964                     }
  14965                     firstString = false;
  14966                 }
  14967                 this.latest = this.stack[this.stack.length-1];
  14968                 if (decor) {
  14969                     if ("string" === typeof this.latest.blobs) {
  14970                         var child = new CSL.Blob();
  14971                         child.blobs = this.latest.blobs;
  14972                         child.alldecor = this.latest.alldecor.slice();
  14973                         this.latest.blobs = [child];
  14974                     }
  14975                     var tok = new CSL.Token();
  14976                     var newblob = new CSL.Blob(null, tok);
  14977                     newblob.alldecor = this.latest.alldecor.slice();
  14978                     if (decor[0] === "@class" && decor[1] === "nodecor") {
  14979                         var newdecorset = [];
  14980                         var seen = {};
  14981                         var allTheDecor = [state[state.tmp.area].opt.layout_decorations].concat(newblob.alldecor)
  14982                         for (var i=allTheDecor.length-1;i>-1;i--) {
  14983                             var _decorset = allTheDecor[i];
  14984                             if (!_decorset) continue;
  14985                             for (var j=_decorset.length-1;j>-1;j--) {
  14986                                 var _olddecor = _decorset[j];
  14987                                 if (["@font-weight", "@font-style", "@font-variant"].indexOf(_olddecor[0]) > -1
  14988                                     && !seen[_olddecor[0]]) {
  14989                                     if (decor[1] !== "normal") {
  14990                                         newblob.decorations.push([_olddecor[0], "normal"]);
  14991                                         newdecorset.push([_olddecor[0], "normal"])
  14992                                     }
  14993                                     seen[_olddecor[0]] = true;
  14994                                 }
  14995                             }
  14996                         }
  14997                         newblob.alldecor.push(newdecorset);
  14998                     } else {
  14999                         newblob.decorations.push(decor);
  15000                         newblob.alldecor.push([decor]);
  15001                     }
  15002                     this.latest.blobs.push(newblob);
  15003                     this.stack.push(newblob);
  15004                     this.latest = newblob;
  15005                     if (str) {
  15006                         var tok = new CSL.Token();
  15007                         var newblob = new CSL.Blob(null, tok);
  15008                         newblob.blobs = str;
  15009                         newblob.alldecor = this.latest.alldecor.slice();
  15010                         this.latest.blobs.push(newblob);
  15011                     }
  15012                 } else {
  15013                     if (str) {
  15014                         var child = new CSL.Blob();
  15015                         child.blobs = str;
  15016                         child.alldecor = this.latest.alldecor.slice();
  15017                         this.latest.blobs.push(child);
  15018                     }
  15019                 }
  15020             }
  15021             this.popStyling = function() {
  15022                 this.stack.pop();
  15023             }
  15024         };
  15025         var stack = new Stack(blob);
  15026         if (doppel.strings.length) {
  15027             var str = doppel.strings[0];
  15028             if (leadingSpace) {
  15029                 str = " " + str;
  15030             }
  15031             stack.addStyling(str);
  15032         }
  15033         for (var i=0,ilen=doppel.tags.length;i<ilen;i++) {
  15034             var tag = doppel.tags[i];
  15035             var str = doppel.strings[i+1];
  15036             if (tag.match(_tagRex.open)) {
  15037                 tagReg.set(tag);
  15038                 stack.addStyling(str, tagReg.pair());
  15039             } else {
  15040                 tagReg.pop();
  15041                 stack.popStyling();
  15042                 stack.addStyling(str);
  15043             }
  15044         }
  15045     }
  15046     function processTags(blob) {
  15047         var str = blob.blobs;
  15048         var leadingSpace = false;
  15049         if (str.slice(0, 1) === " " && !str.match(/^\s+[\'\"]/)) {
  15050             leadingSpace = true;
  15051         }
  15052         var rex = new RegExp("(" + CSL.ROMANESQUE_REGEXP.source + ")\u2019(" + CSL.ROMANESQUE_REGEXP.source + ")", "g")
  15053         var str = " " + str.replace(rex, "$1\'$2");
  15054         var doppel = _doppelString(str);
  15055         if (doppel.tags.length === 0) return;
  15056         var quoteFormSeen = false;
  15057     	for (var i=0,ilen=doppel.tags.length;i<ilen;i++) {
  15058             var tag = doppel.tags[i];
  15059             var str = doppel.strings[i+1];
  15060             if (_apostropheForce(tag, str)) {
  15061                 if (tag === " \'") {
  15062                     doppel.strings[i+1] = " \u2019" + doppel.strings[i+1];
  15063                 } else {
  15064                     doppel.strings[i+1] = "\u2019" + doppel.strings[i+1];
  15065                 }
  15066                 doppel.tags[i] = "";
  15067             } else {
  15068                 var tagInfo;
  15069                 while (true) {
  15070                     tagInfo = _nestingFix(tag, i);
  15071                     if (tagInfo) {
  15072                         if (Object.keys(tagInfo).indexOf("fixtag") > -1) {
  15073                             if (tag.match(_tagRex.close)
  15074                                 && tag === "\'") {
  15075                                 doppel.strings[i+1] = "\u2019" + doppel.strings[i+1];
  15076                                 doppel.tags[i] = "";
  15077                             } else {
  15078                                 var failedTag = doppel.tags[tagInfo.fixtag];
  15079                                 if (doppel.forcedSpaces[tagInfo.fixtag-1]) {
  15080                                     failedTag = failedTag.slice(1);
  15081                                 }
  15082                                 doppel.strings[tagInfo.fixtag+1] = failedTag + doppel.strings[tagInfo.fixtag+1];
  15083                                 doppel.tags[tagInfo.fixtag] = "";
  15084                             }
  15085                             if (_nestingState.length > 0) {
  15086                                 _nestingState.pop();
  15087                             } else {
  15088                                 break;
  15089                             }
  15090                         } else if (tagInfo.nocase) {
  15091                             doppel.tags[tagInfo.nocase.open] = "";
  15092                             doppel.tags[tagInfo.nocase.close] = "";
  15093                             break;
  15094                         } else {
  15095                             break;
  15096                         }
  15097                     } else {
  15098                         break;
  15099                     }
  15100                 }
  15101                 if (tagInfo && (tagInfo.fixtag|| tagInfo.fixtag === 0)) {
  15102                     doppel.strings[i+1] = doppel.tags[i] + doppel.strings[i+1];
  15103                     doppel.tags[i] = "";
  15104                 }
  15105             }
  15106         }
  15107         for (var i=_nestingState.length-1;i>-1;i--) {
  15108             var tagPos = _nestingState[i].pos
  15109             var tag = doppel.tags[tagPos];
  15110             if (tag === " \'" || tag === "\'") {
  15111                 doppel.strings[tagPos+1] = " \u2019" + doppel.strings[tagPos+1];
  15112             } else {
  15113                 doppel.strings[tagPos+1] = doppel.tags[tagPos] + doppel.strings[tagPos+1];
  15114             }
  15115             doppel.tags[tagPos] = "";
  15116             _nestingState.pop();
  15117         }
  15118         for (var i=doppel.tags.length-1;i>-1;i--) {
  15119             if (!doppel.tags[i]) {
  15120                 doppel.tags = doppel.tags.slice(0,i).concat(doppel.tags.slice(i+1));
  15121                 doppel.strings[i] = doppel.strings[i] + doppel.strings[i+1];
  15122                 doppel.strings = doppel.strings.slice(0,i+1).concat(doppel.strings.slice(i+2));
  15123             }
  15124         }
  15125         for (var i=0,ilen=doppel.tags.length;i<ilen;i++) {
  15126             var tag = doppel.tags[i];
  15127             var forcedSpace = doppel.forcedSpaces[i-1];
  15128             if ([" \"", " \'", "(\"", "(\'"].indexOf(tag) > -1) {
  15129                 if (!quoteFormSeen) {
  15130                     _setOuterQuoteForm(tag);
  15131                     quoteFormSeen = true;
  15132                 }
  15133                 if (!forcedSpace) {
  15134                     doppel.strings[i] += tag.slice(0, 1);
  15135                 }
  15136             }
  15137         }
  15138         _undoppelToQueue(blob, doppel, leadingSpace);
  15139     }
  15140 }
  15141 CSL.Output.Formatters = new function () {
  15142     this.passthrough = passthrough;
  15143     this.lowercase = lowercase;
  15144     this.uppercase = uppercase;
  15145     this.sentence = sentence;
  15146     this.title = title;
  15147     this["capitalize-first"] = capitalizeFirst;
  15148     this["capitalize-all"] = capitalizeAll;
  15149     var rexStr = "(?:\u2018|\u2019|\u201C|\u201D| \"| \'|\"|\'|[-\u2013\u2014\/.,;?!:]|\\[|\\]|\\(|\\)|<span style=\"font-variant: small-caps;\">|<span class=\"no(?:case|decor)\">|<\/span>|<\/?(?:i|sc|b|sub|sup)>)";
  15150     var tagDoppel = new CSL.Doppeler(rexStr, function(str) {
  15151         return str.replace(/(<span)\s+(class=\"no(?:case|decor)\")[^>]*(>)/g, "$1 $2$3").replace(/(<span)\s+(style=\"font-variant:)\s*(small-caps);?(\")[^>]*(>)/g, "$1 $2 $3;$4$5");
  15152     });
  15153     var wordDoppel = new CSL.Doppeler("(?:[\u0020\u00A0\u2000-\u200B\u205F\u3000]+)");
  15154     var _tagParams = {
  15155         "<span style=\"font-variant: small-caps;\">": "</span>",
  15156         "<span class=\"nocase\">": "</span>",
  15157         "<span class=\"nodecor\">": "</span>"
  15158     }
  15159     function _capitalise (word, force) {
  15160         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]))(.*)/);
  15161         if (m && !(m[2].match(/^[\u0370-\u03FF]$/) && !m[3])) {
  15162             return m[1] + m[2].toUpperCase() + m[3];
  15163         }
  15164         return word;
  15165     }
  15166     function _textcaseEngine(config, string) {
  15167         if (!string) {
  15168             return "";
  15169         }
  15170         config.doppel = tagDoppel.split(string);
  15171         var quoteParams = {
  15172             " \"": {
  15173                 opener: " \'",
  15174                 closer: "\""
  15175             },
  15176             " \'": {
  15177                 opener: " \"",
  15178                 closer: "\'"
  15179             },
  15180             "\u2018": {
  15181                 opener: "\u2018",
  15182                 closer: "\u2019"
  15183             },
  15184             "\u201C": {
  15185                 opener: "\u201C",
  15186                 closer: "\u201D"
  15187             },
  15188         }
  15189         function quoteFix (tag, positions) {
  15190             var m = tag.match(/(^(?:\u2018|\u2019|\u201C|\u201D|\"|\')|(?: \"| \')$)/);
  15191             if (m) {
  15192                 return pushQuoteState(m[1], positions);
  15193             }
  15194         }
  15195         function pushQuoteState(tag, pos) {
  15196             var isOpener = ["\u201C", "\u2018", " \"", " \'"].indexOf(tag) > -1 ? true : false;
  15197             if (isOpener) {
  15198                 return tryOpen(tag, pos);
  15199             } else {
  15200                 return tryClose(tag, pos);
  15201             }
  15202         }
  15203         function tryOpen(tag, pos) {
  15204             if (config.quoteState.length === 0 || tag === config.quoteState[config.quoteState.length - 1].opener) {
  15205                 config.quoteState.push({
  15206                     opener: quoteParams[tag].opener,
  15207                     closer: quoteParams[tag].closer,
  15208                     pos: pos
  15209                 });
  15210                 return false;
  15211             } else {
  15212                 var prevPos = config.quoteState[config.quoteState.length-1].pos;
  15213                 config.quoteState.pop()
  15214                 config.quoteState.push({
  15215                     opener: quoteParams[tag].opener,
  15216                     closer: quoteParams[tag].closer,
  15217                     positions: pos
  15218                 });
  15219                 return prevPos;
  15220             }
  15221         }
  15222         function tryClose(tag, pos) {
  15223             if (config.quoteState.length > 0 && tag === config.quoteState[config.quoteState.length - 1].closer) {
  15224                 config.quoteState.pop()
  15225             } else {
  15226                 return pos;
  15227             }
  15228         }
  15229         if (config.doppel.strings.length && config.doppel.strings[0].trim()) {
  15230             config.doppel.strings[0] = config.capitaliseWords(config.doppel.strings[0], 0, config.doppel.tags[0]);
  15231         }
  15232     	for (var i=0,ilen=config.doppel.tags.length;i<ilen;i++) {
  15233             var tag = config.doppel.tags[i];
  15234             var str = config.doppel.strings[i+1];
  15235             if (config.tagState !== null) {
  15236                 if (_tagParams[tag]) {
  15237                     config.tagState.push(_tagParams[tag]);
  15238                 } else if (config.tagState.length && tag === config.tagState[config.tagState.length - 1]) {
  15239                     config.tagState.pop();
  15240                 }
  15241             }
  15242             if (config.afterPunct !== null) {
  15243                 if (tag.match(/[\!\?\:]$/)) {
  15244                     config.afterPunct = true;
  15245                 }
  15246             }
  15247             if (config.tagState.length === 0) {
  15248                 config.doppel.strings[i+1] = config.capitaliseWords(str, i+1, config.doppel,config.doppel.tags[i+1]);
  15249             } else if (config.doppel.strings[i+1].trim()) {
  15250                 config.lastWordPos = null;
  15251             }
  15252             if (config.quoteState !== null) {
  15253                 var quotePos = quoteFix(tag, i);
  15254                 if (quotePos || quotePos === 0) {
  15255                     var origChar = config.doppel.origStrings[quotePos+1].slice(0, 1);
  15256                     config.doppel.strings[quotePos+1] = origChar + config.doppel.strings[quotePos+1].slice(1);
  15257                     config.lastWordPos = null;
  15258                 }
  15259             }
  15260             if (config.isFirst) {
  15261                 if (str.trim()) {
  15262                     config.isFirst = false;
  15263                 }
  15264             }
  15265             if (config.afterPunct) {
  15266                 if (str.trim()) {
  15267                     config.afterPunct = false;
  15268                 }
  15269             }
  15270         }
  15271         if (config.quoteState) {
  15272             for (var i=0,ilen=config.quoteState.length;i<ilen;i++) {
  15273                 var quotePos = config.quoteState[i].pos;
  15274                 if (typeof quotePos !== 'undefined') {
  15275                     var origChar = config.doppel.origStrings[quotePos+1].slice(0, 1);
  15276                     config.doppel.strings[quotePos+1] = origChar + config.doppel.strings[quotePos+1].slice(1);
  15277                 }
  15278             }
  15279         }
  15280         if (config.lastWordPos) {
  15281             var lastWords = wordDoppel.split(config.doppel.strings[config.lastWordPos.strings]);
  15282             var lastWord = _capitalise(lastWords.strings[config.lastWordPos.words]);
  15283             lastWords.strings[config.lastWordPos.words] = lastWord;
  15284             config.doppel.strings[config.lastWordPos.strings] = wordDoppel.join(lastWords);
  15285         }
  15286         return tagDoppel.join(config.doppel);
  15287     }
  15288     function passthrough (state, str) {
  15289         return str;
  15290     }
  15291     function lowercase(state, string) {
  15292         var config = {
  15293             quoteState: null,
  15294             capitaliseWords: function(str) {
  15295                 var words = str.split(" ");
  15296                 for (var i=0,ilen=words.length;i<ilen;i++) {
  15297                     var word = words[i];
  15298                     if (word) {
  15299                         words[i] = word.toLowerCase();
  15300                     }
  15301                 }
  15302                 return words.join(" ");
  15303             },
  15304             skipWordsRex: null,
  15305             tagState: [],
  15306             afterPunct: null,
  15307             isFirst: null
  15308         }
  15309         return _textcaseEngine(config, string);
  15310     }
  15311     function uppercase(state, string) {
  15312         var config = {
  15313             quoteState: null,
  15314             capitaliseWords: function(str) {
  15315                 var words = str.split(" ");
  15316                 for (var i=0,ilen=words.length;i<ilen;i++) {
  15317                     var word = words[i];
  15318                     if (word) {
  15319                         words[i] = word.toUpperCase();
  15320                     }
  15321                 }
  15322                 return words.join(" ");
  15323             },
  15324             skipWordsRex: null,
  15325             tagState: [],
  15326             afterPunct: null,
  15327             isFirst: null
  15328         }
  15329         return _textcaseEngine(config, string);
  15330     }
  15331     function sentence(state, string) {
  15332         var config = {
  15333             quoteState: [],
  15334             capitaliseWords: function(str) {
  15335                 var words = str.split(" ");
  15336                 for (var i=0,ilen=words.length;i<ilen;i++) {
  15337                     var word = words[i];
  15338                     if (word) {
  15339                         if (config.isFirst) {
  15340                             words[i] = _capitalise(word);
  15341                             config.isFirst = false;
  15342                         } else {
  15343                             words[i] = word.toLowerCase();
  15344                         }
  15345                     }
  15346                 }
  15347                 return words.join(" ");
  15348             },
  15349             skipWordsRex: null,
  15350             tagState: [],
  15351             afterPunct: null,
  15352             isFirst: true
  15353         }
  15354         return _textcaseEngine(config, string);
  15355     }
  15356     function title(state, string) {
  15357         var config = {
  15358             quoteState: [],
  15359             capitaliseWords: function(str, i, followingTag) {
  15360                 if (str.trim()) {
  15361                     var words = str.split(/[ \u00A0]+/);
  15362                     var wordle = wordDoppel.split(str);
  15363                     var words = wordle.strings;
  15364                     for (var j=0,jlen=words.length;j<jlen;j++) {
  15365                         var word = words[j];
  15366                         if (!word) continue;
  15367                         if (word.length > 1 && !word.toLowerCase().match(config.skipWordsRex)) {
  15368                             words[j] = _capitalise(words[j]);
  15369                         } else if (j === (words.length - 1) && followingTag === "-") {
  15370                             words[j] = _capitalise(words[j]);
  15371                         } else if (config.isFirst) {
  15372                             words[j] = _capitalise(words[j]);
  15373                         } else if (config.afterPunct) {
  15374                             words[j] = _capitalise(words[j]);
  15375                         }
  15376                         config.afterPunct = false;
  15377                         config.isFirst = false;
  15378                         config.lastWordPos = {
  15379                             strings: i,
  15380                             words: j
  15381                         }
  15382                     }
  15383                     str = wordDoppel.join(wordle);
  15384                 }
  15385                 return str;
  15386             },
  15387             skipWordsRex: state.locale[state.opt.lang].opts["skip-words-regexp"],
  15388             tagState: [],
  15389             afterPunct: false,
  15390             isFirst: true
  15391         }
  15392         return _textcaseEngine(config, string);
  15393     }
  15394     function capitalizeFirst(state, string) {
  15395         var config = {
  15396             quoteState: [],
  15397             capitaliseWords: function(str) {
  15398                 var words = str.split(" ");
  15399                 for (var i=0,ilen=words.length;i<ilen;i++) {
  15400                     var word = words[i];
  15401                     if (word) {
  15402                         if (config.isFirst) {
  15403                             words[i] = _capitalise(word);
  15404                             config.isFirst = false;
  15405                             break;
  15406                         }
  15407                     }
  15408                 }
  15409                 return words.join(" ");
  15410             },
  15411             skipWordsRex: null,
  15412             tagState: [],
  15413             afterPunct: null,
  15414             isFirst: true
  15415         }
  15416         return _textcaseEngine(config, string);
  15417     }
  15418     function capitalizeAll (state, string) {
  15419         var config = {
  15420             quoteState: [],
  15421             capitaliseWords: function(str) {
  15422                 var words = str.split(" ");
  15423                 for (var i=0,ilen=words.length;i<ilen;i++) {
  15424                     var word = words[i];
  15425                     if (word) {
  15426                         words[i] = _capitalise(word);
  15427                     }
  15428                 }
  15429                 return words.join(" ");
  15430             },
  15431             skipWordsRex: null,
  15432             tagState: [],
  15433             afterPunct: null,
  15434             isFirst: null
  15435         }
  15436         return _textcaseEngine(config, string);
  15437     }
  15438 }
  15439 CSL.Output.Formats = function () {};
  15440 CSL.Output.Formats.prototype.html = {
  15441     "text_escape": function (text) {
  15442         if (!text) {
  15443             text = "";
  15444         }
  15445         return text.replace(/&/g, "&#38;")
  15446             .replace(/</g, "&#60;")
  15447             .replace(/>/g, "&#62;")
  15448             .replace(/\s\s/g, "\u00A0 ")
  15449             .replace(CSL.SUPERSCRIPTS_REGEXP,
  15450                      function(aChar) {
  15451                          return "<sup>" + CSL.SUPERSCRIPTS[aChar] + "</sup>";
  15452                      });
  15453     },
  15454     "bibstart": "<div class=\"csl-bib-body\">\n",
  15455     "bibend": "</div>",
  15456     "@font-style/italic": "<i>%%STRING%%</i>",
  15457     "@font-style/oblique": "<em>%%STRING%%</em>",
  15458     "@font-style/normal": "<span style=\"font-style:normal;\">%%STRING%%</span>",
  15459     "@font-variant/small-caps": "<span style=\"font-variant:small-caps;\">%%STRING%%</span>",
  15460     "@passthrough/true": CSL.Output.Formatters.passthrough,
  15461     "@font-variant/normal": "<span style=\"font-variant:normal;\">%%STRING%%</span>",
  15462     "@font-weight/bold": "<b>%%STRING%%</b>",
  15463     "@font-weight/normal": "<span style=\"font-weight:normal;\">%%STRING%%</span>",
  15464     "@font-weight/light": false,
  15465     "@text-decoration/none": "<span style=\"text-decoration:none;\">%%STRING%%</span>",
  15466     "@text-decoration/underline": "<span style=\"text-decoration:underline;\">%%STRING%%</span>",
  15467     "@vertical-align/sup": "<sup>%%STRING%%</sup>",
  15468     "@vertical-align/sub": "<sub>%%STRING%%</sub>",
  15469     "@vertical-align/baseline": "<span style=\"baseline\">%%STRING%%</span>",
  15470     "@strip-periods/true": CSL.Output.Formatters.passthrough,
  15471     "@strip-periods/false": CSL.Output.Formatters.passthrough,
  15472     "@quotes/true": function (state, str) {
  15473         if ("undefined" === typeof str) {
  15474             return state.getTerm("open-quote");
  15475         }
  15476         return state.getTerm("open-quote") + str + state.getTerm("close-quote");
  15477     },
  15478     "@quotes/inner": function (state, str) {
  15479         if ("undefined" === typeof str) {
  15480             return "\u2019";
  15481         }
  15482         return state.getTerm("open-inner-quote") + str + state.getTerm("close-inner-quote");
  15483     },
  15484     "@quotes/false": false,
  15485     "@cite/entry": function (state, str) {
  15486         return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt);
  15487 	},
  15488     "@bibliography/entry": function (state, str) {
  15489         var insert = "";
  15490         if (state.sys.embedBibliographyEntry) {
  15491             insert = state.sys.embedBibliographyEntry(this.item_id) + "\n";
  15492         }
  15493         return "  <div class=\"csl-entry\">" + str + "</div>\n" + insert;
  15494     },
  15495     "@display/block": function (state, str) {
  15496         return "\n\n    <div class=\"csl-block\">" + str + "</div>\n";
  15497     },
  15498     "@display/left-margin": function (state, str) {
  15499         return "\n    <div class=\"csl-left-margin\">" + str + "</div>";
  15500     },
  15501     "@display/right-inline": function (state, str) {
  15502         return "<div class=\"csl-right-inline\">" + str + "</div>\n  ";
  15503     },
  15504     "@display/indent": function (state, str) {
  15505         return "<div class=\"csl-indent\">" + str + "</div>\n  ";
  15506     },
  15507     "@showid/true": function (state, str, cslid) {
  15508         if (!state.tmp.just_looking && ! state.tmp.suppress_decorations) {
  15509             if (cslid) {
  15510                 return "<span class=\"" + state.opt.nodenames[cslid] + "\" cslid=\"" + cslid + "\">" + str + "</span>";
  15511             } else if (this.params && "string" === typeof str) {
  15512                 var prePunct = "";
  15513                 if (str) {
  15514                     var m = str.match(CSL.VARIABLE_WRAPPER_PREPUNCT_REX);
  15515                     prePunct = m[1];
  15516                     str = m[2];
  15517                 }
  15518                 var postPunct = "";
  15519                 if (str && CSL.SWAPPING_PUNCTUATION.indexOf(str.slice(-1)) > -1) {
  15520                     postPunct = str.slice(-1);
  15521                     str = str.slice(0,-1);
  15522                 }
  15523                 return state.sys.variableWrapper(this.params, prePunct, str, postPunct);
  15524             } else {
  15525                 return str;
  15526             }
  15527         } else {
  15528             return str;
  15529         }
  15530     },
  15531     "@URL/true": function (state, str) {
  15532         return "<a href=\"" + str + "\">" + str + "</a>";
  15533     },
  15534     "@DOI/true": function (state, str) {
  15535         var doiurl = str;
  15536         if (!str.match(/^https?:\/\//)) {
  15537             doiurl = "https://doi.org/" + str;
  15538         }
  15539         return "<a href=\"" + doiurl + "\">" + str + "</a>";
  15540     }
  15541 };
  15542 CSL.Output.Formats.prototype.text = {
  15543     "text_escape": function (text) {
  15544         if (!text) {
  15545             text = "";
  15546         }
  15547         return text;
  15548     },
  15549     "bibstart": "",
  15550     "bibend": "",
  15551     "@font-style/italic": false,
  15552     "@font-style/oblique": false,
  15553     "@font-style/normal": false,
  15554     "@font-variant/small-caps": false,
  15555     "@passthrough/true": CSL.Output.Formatters.passthrough,
  15556     "@font-variant/normal": false,
  15557     "@font-weight/bold": false,
  15558     "@font-weight/normal": false,
  15559     "@font-weight/light": false,
  15560     "@text-decoration/none": false,
  15561     "@text-decoration/underline": false,
  15562     "@vertical-align/baseline": false,
  15563     "@vertical-align/sup": false,
  15564     "@vertical-align/sub": false,
  15565     "@strip-periods/true": CSL.Output.Formatters.passthrough,
  15566     "@strip-periods/false": CSL.Output.Formatters.passthrough,
  15567     "@quotes/true": function (state, str) {
  15568         if ("undefined" === typeof str) {
  15569             return state.getTerm("open-quote");
  15570         }
  15571         return state.getTerm("open-quote") + str + state.getTerm("close-quote");
  15572     },
  15573     "@quotes/inner": function (state, str) {
  15574         if ("undefined" === typeof str) {
  15575             return "\u2019";
  15576         }
  15577         return state.getTerm("open-inner-quote") + str + state.getTerm("close-inner-quote");
  15578     },
  15579     "@quotes/false": false,
  15580     "@cite/entry": function (state, str) {
  15581 		return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt);
  15582 	},
  15583     "@bibliography/entry": function (state, str) {
  15584         return str+"\n";
  15585     },
  15586     "@display/block": function (state, str) {
  15587         return "\n"+str;
  15588     },
  15589     "@display/left-margin": function (state, str) {
  15590         return str;
  15591     },
  15592     "@display/right-inline": function (state, str) {
  15593         return str;
  15594     },
  15595     "@display/indent": function (state, str) {
  15596         return "\n    "+str;
  15597     },
  15598     "@showid/true": function (state, str, cslid) {
  15599         return str;
  15600     },
  15601     "@URL/true": function (state, str) {
  15602         return str;
  15603     },
  15604     "@DOI/true": function (state, str) {
  15605         return str;
  15606     }
  15607 };
  15608 CSL.Output.Formats.prototype.rtf = {
  15609     "text_escape": function (text) {
  15610         if (!text) {
  15611             text = "";
  15612         }
  15613         return text
  15614         .replace(/([\\{}])/g, "\\$1")
  15615         .replace(CSL.SUPERSCRIPTS_REGEXP,
  15616                  function(aChar) {
  15617                      return "\\super " + CSL.SUPERSCRIPTS[aChar] + "\\nosupersub{}";
  15618                  })
  15619         .replace(/[\u007F-\uFFFF]/g,
  15620                  function(aChar) { return "\\uc0\\u"+aChar.charCodeAt(0).toString()+"{}"; })
  15621         .split("\t").join("\\tab{}");
  15622     },
  15623     "@passthrough/true": CSL.Output.Formatters.passthrough,
  15624     "@font-style/italic":"{\\i{}%%STRING%%}",
  15625     "@font-style/normal":"{\\i0{}%%STRING%%}",
  15626     "@font-style/oblique":"{\\i{}%%STRING%%}",
  15627     "@font-variant/small-caps":"{\\scaps %%STRING%%}",
  15628     "@font-variant/normal":"{\\scaps0{}%%STRING%%}",
  15629     "@font-weight/bold":"{\\b{}%%STRING%%}",
  15630     "@font-weight/normal":"{\\b0{}%%STRING%%}",
  15631     "@font-weight/light":false,
  15632     "@text-decoration/none":false,
  15633     "@text-decoration/underline":"{\\ul{}%%STRING%%}",
  15634     "@vertical-align/baseline":false,
  15635     "@vertical-align/sup":"\\super %%STRING%%\\nosupersub{}",
  15636     "@vertical-align/sub":"\\sub %%STRING%%\\nosupersub{}",
  15637     "@strip-periods/true": CSL.Output.Formatters.passthrough,
  15638     "@strip-periods/false": CSL.Output.Formatters.passthrough,
  15639     "@quotes/true": function (state, str) {
  15640         if ("undefined" === typeof str) {
  15641             return CSL.Output.Formats.rtf.text_escape(state.getTerm("open-quote"));
  15642         }
  15643         return CSL.Output.Formats.rtf.text_escape(state.getTerm("open-quote")) + str + CSL.Output.Formats.rtf.text_escape(state.getTerm("close-quote"));
  15644     },
  15645     "@quotes/inner": function (state, str) {
  15646         if ("undefined" === typeof str) {
  15647             return CSL.Output.Formats.rtf.text_escape("\u2019");
  15648         }
  15649         return CSL.Output.Formats.rtf.text_escape(state.getTerm("open-inner-quote")) + str + CSL.Output.Formats.rtf.text_escape(state.getTerm("close-inner-quote"));
  15650     },
  15651     "@quotes/false": false,
  15652     "bibstart":"{\\rtf ",
  15653     "bibend":"}",
  15654     "@display/block": "\\line{}%%STRING%%\\line\r\n",
  15655     "@cite/entry": function (state, str) {
  15656 		return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt);
  15657 	},
  15658     "@bibliography/entry": function(state,str){
  15659         return str;
  15660     },
  15661     "@display/left-margin": function(state,str){
  15662         return str+"\\tab ";
  15663     },
  15664     "@display/right-inline": function (state, str) {
  15665         return str+"\r\n";
  15666     },
  15667     "@display/indent": function (state, str) {
  15668         return "\n\\tab "+str+"\\line\r\n";
  15669     },
  15670     "@showid/true": function (state, str, cslid) {
  15671         if (!state.tmp.just_looking && ! state.tmp.suppress_decorations) {
  15672             var prePunct = "";
  15673             if (str) {
  15674                 var m = str.match(CSL.VARIABLE_WRAPPER_PREPUNCT_REX);
  15675                 prePunct = m[1];
  15676                 str = m[2];
  15677             }
  15678             var postPunct = "";
  15679             if (str && CSL.SWAPPING_PUNCTUATION.indexOf(str.slice(-1)) > -1) {
  15680                 postPunct = str.slice(-1);
  15681                 str = str.slice(0,-1);
  15682             }
  15683             return state.sys.variableWrapper(this.params, prePunct, str, postPunct);
  15684         } else {
  15685             return str;
  15686         }
  15687     },
  15688     "@URL/true": function (state, str) {
  15689         return str;
  15690     },
  15691     "@DOI/true": function (state, str) {
  15692         return str;
  15693     }
  15694 };
  15695 CSL.Output.Formats = new CSL.Output.Formats();
  15696 CSL.Registry = function (state) {
  15697     var pos, len, ret, i, ilen;
  15698     this.debug = false;
  15699     this.state = state;
  15700     this.registry = {};
  15701     this.reflist = [];
  15702     this.refhash = {};
  15703     this.namereg = new CSL.Registry.NameReg(state);
  15704     this.citationreg = new CSL.Registry.CitationReg(state);
  15705     this.authorstrings = {};
  15706     this.mylist = [];
  15707     this.myhash = {};
  15708     this.deletes = [];
  15709     this.inserts = [];
  15710     this.uncited = {};
  15711     this.refreshes = {};
  15712     this.akeys = {};
  15713     this.oldseq = {};
  15714     this.return_data = {};
  15715     this.ambigcites = {};
  15716     this.ambigresets = {};
  15717     this.sorter = new CSL.Registry.Comparifier(state, "bibliography_sort");
  15718     this.getSortedIds = function () {
  15719         var ret = [];
  15720         for (var i = 0, ilen = this.reflist.length; i < ilen; i += 1) {
  15721             ret.push("" + this.reflist[i].id);
  15722         }
  15723         return ret;
  15724     };
  15725     this.getSortedRegistryItems = function () {
  15726         var ret = [];
  15727         for (var i = 0, ilen = this.reflist.length; i < ilen; i += 1) {
  15728             ret.push(this.reflist[i]);
  15729         }
  15730         return ret;
  15731     };
  15732 };
  15733 CSL.Registry.prototype.init = function (itemIDs, uncited_flag) {
  15734     var i, ilen;
  15735     this.oldseq = {};
  15736     if (uncited_flag) {
  15737         this.uncited = {};
  15738         for (var i=0,ilen=itemIDs.length;i<ilen; i += 1) {
  15739             if (!this.myhash[itemIDs[i]]) {
  15740                 this.mylist.push("" + itemIDs[i]);
  15741             }
  15742             this.uncited[itemIDs[i]] = true;
  15743             this.myhash[itemIDs[i]] = true;
  15744         }
  15745     } else {
  15746         for (var key in this.uncited) {
  15747             itemIDs.push(key);
  15748         }
  15749         var myhash = {};
  15750         for (i=itemIDs.length-1;i>-1; i += -1) {
  15751             if (myhash[itemIDs[i]]) {
  15752                 itemIDs = itemIDs.slice(0, i).concat(itemIDs.slice(i + 1));
  15753             } else {
  15754                 myhash[itemIDs[i]] = true;
  15755             }
  15756         }
  15757         this.mylist = [];
  15758         for (var i=0,ilen=itemIDs.length;i<ilen;i+=1) {
  15759             this.mylist.push("" + itemIDs[i]);
  15760         }
  15761         this.myhash = myhash;
  15762     }
  15763     this.refreshes = {};
  15764     this.touched = {};
  15765     this.ambigsTouched = {};
  15766     this.ambigresets = {};
  15767 };
  15768 CSL.Registry.prototype.dopurge = function (myhash) {
  15769     for (var i=this.mylist.length-1;i>-1;i+=-1) {
  15770         if (this.citationreg.citationsByItemId) {
  15771             if (!this.citationreg.citationsByItemId[this.mylist[i]] && !myhash[this.mylist[i]]) {
  15772                 delete this.myhash[this.mylist[i]];
  15773                 this.mylist = this.mylist.slice(0,i).concat(this.mylist.slice(i+1));
  15774             }
  15775         }
  15776     }
  15777     this.dodeletes(this.myhash);
  15778 };
  15779 CSL.Registry.prototype.dodeletes = function (myhash) {
  15780     var otheritems, key, ambig, pos, len, items, kkey, mypos, id;
  15781     if ("string" === typeof myhash) {
  15782         myhash = {};
  15783         myhash[myhash] = true;
  15784     }
  15785     for (var key in this.registry) {
  15786         if (!myhash[key]) {
  15787             if (this.uncited[key]) {
  15788                 continue;
  15789             }
  15790             otheritems = this.namereg.delitems(key);
  15791             for (kkey in otheritems) {
  15792                 this.refreshes[kkey] = true;
  15793             }
  15794             ambig = this.registry[key].ambig;
  15795             mypos = this.ambigcites[ambig].indexOf(key);
  15796             if (mypos > -1) {
  15797                 items = this.ambigcites[ambig].slice();
  15798                 this.ambigcites[ambig] = items.slice(0, mypos).concat(items.slice(mypos+1, items.length));
  15799                 this.ambigresets[ambig] = this.ambigcites[ambig].length;
  15800             }
  15801             len = this.ambigcites[ambig].length;
  15802             for (pos = 0; pos < len; pos += 1) {
  15803                 id = "" + this.ambigcites[ambig][pos];
  15804                 this.refreshes[id] = true;
  15805             }
  15806             if (this.registry[key].siblings) {
  15807                 if (this.registry[key].siblings.length == 1) {
  15808                     var loneSiblingID = this.registry[key].siblings[0];
  15809                     this.registry[loneSiblingID].master = true;
  15810                     this.registry[loneSiblingID].siblings.pop();
  15811                     this.registry[loneSiblingID].parallel = false;
  15812                 } else if (this.registry[key].siblings.length > 1) {
  15813                     var removeIDs = [key];
  15814                     if (this.registry[key].master) {
  15815                         var newmasterID = this.registry[key].siblings[0];
  15816                         var newmaster = this.registry[newmasterID];
  15817                         newmaster.master = true;
  15818                         newmaster.parallel = false;
  15819                         removeIDs.push(newmasterID);
  15820                         for (var k = 0, klen = this.registry[key].siblings.length; k < klen; k += 1) {
  15821                             this.registry[this.registry[key].siblings[k]].parallel = newmasterID;
  15822                         }
  15823                     }
  15824                     var buffer = [];
  15825                     for (var k = this.registry[key].siblings.length - 1; k > -1; k += -1) {
  15826                         var siblingID = this.registry[key].siblings.pop();
  15827                         if (removeIDs.indexOf(siblingID) === -1) {
  15828                             buffer.push(siblingID)
  15829                         }
  15830                     }
  15831                     for (var k = buffer.length - 1; k > -1; k += -1) {
  15832                         this.registry[key].siblings.push(buffer[k]);
  15833                     }
  15834                 }
  15835             }
  15836             delete this.registry[key];
  15837             delete this.refhash[key];
  15838             this.return_data.bibchange = true;
  15839         }
  15840     }
  15841 };
  15842 CSL.Registry.prototype.doinserts = function (mylist) {
  15843     var len, pos, item, Item, akey, newitem, abase, j, jlen, k, klen, i, ilen;
  15844     if ("string" === typeof mylist) {
  15845         mylist = [mylist];
  15846     }
  15847     for (var i = 0, ilen = mylist.length; i < ilen; i += 1) {
  15848         item = mylist[i];
  15849         if (!this.registry[item]) {
  15850             Item = this.state.retrieveItem(item);
  15851             akey = CSL.getAmbiguousCite.call(this.state, Item);
  15852             this.ambigsTouched[akey] = true;
  15853             if (!Item.legislation_id) {
  15854                 this.akeys[akey] = true;
  15855             }
  15856             newitem = {
  15857                 "id": "" + item,
  15858                 "seq": 0,
  15859                 "offset": 0,
  15860                 "sortkeys": false,
  15861                 "ambig": false,
  15862                 "rendered": false,
  15863                 "disambig": false,
  15864                 "ref": Item
  15865             };
  15866             this.registry[item] = newitem;
  15867             if (this.citationreg.citationsByItemId && this.citationreg.citationsByItemId[item]) {
  15868                 this.registry[item]["first-reference-note-number"] = this.citationreg.citationsByItemId[item][0].properties.noteIndex;
  15869             }
  15870             abase = CSL.getAmbigConfig.call(this.state);
  15871             this.registerAmbigToken(akey, item, abase);
  15872             this.touched[item] = true;
  15873             this.return_data.bibchange = true;
  15874         }
  15875     }
  15876 };
  15877 CSL.Registry.prototype.rebuildlist = function () {
  15878     var count, len, pos, item;
  15879     this.reflist = [];
  15880     if (this.state.opt.citation_number_sort_direction === CSL.DESCENDING
  15881        && this.state.opt.citation_number_sort_used) {
  15882     }
  15883     len = this.mylist.length;
  15884     for (pos = 0; pos < len; pos += 1) {
  15885         item = this.mylist[pos];
  15886         this.reflist.push(this.registry[item]);
  15887         this.oldseq[item] = this.registry[item].seq;
  15888         this.registry[item].seq = (pos + 1);
  15889     }
  15890     if (this.state.opt.citation_number_sort_direction === CSL.DESCENDING
  15891        && this.state.opt.citation_number_sort_used) {
  15892     }
  15893 };
  15894 CSL.Registry.prototype.dorefreshes = function () {
  15895     var key, regtoken, Item, old_akey, akey, abase;
  15896     for (var key in this.refreshes) {
  15897         regtoken = this.registry[key];
  15898         if (!regtoken) {
  15899             continue;
  15900         }
  15901         regtoken.sortkeys = undefined;
  15902         Item = this.state.retrieveItem(key);
  15903         var akey = regtoken.ambig;
  15904         if ("undefined" === typeof akey) {
  15905             this.state.tmp.disambig_settings = false;
  15906             akey = CSL.getAmbiguousCite.call(this.state, Item);
  15907             abase = CSL.getAmbigConfig.call(this.state);
  15908             this.registerAmbigToken(akey, key, abase);
  15909         }
  15910         for (var akkey in this.ambigresets) {
  15911             if (this.ambigresets[akkey] === 1) {
  15912                 var loneKey = this.ambigcites[akey][0];
  15913                 var Item = this.state.retrieveItem(loneKey);
  15914                 this.registry[loneKey].disambig = new CSL.AmbigConfig;
  15915                 this.state.tmp.disambig_settings = false;
  15916                 var akey = CSL.getAmbiguousCite.call(this.state, Item);
  15917                 var abase = CSL.getAmbigConfig.call(this.state);
  15918                 this.registerAmbigToken(akey, loneKey, abase);
  15919             }
  15920         }
  15921         this.state.tmp.taintedItemIDs[key] = true;
  15922         this.ambigsTouched[akey] = true;
  15923         if (!Item.legislation_id) {
  15924             this.akeys[akey] = true;
  15925         }
  15926         this.touched[key] = true;
  15927     }
  15928 };
  15929 CSL.Registry.prototype.setdisambigs = function () {
  15930     var akey, leftovers, key, pos, len, id;
  15931     this.leftovers = [];
  15932     for (akey in this.ambigsTouched) {
  15933         this.state.disambiguate.run(akey);
  15934     }
  15935     this.ambigsTouched = {};
  15936     this.akeys = {};
  15937 };
  15938 CSL.Registry.prototype.renumber = function () {
  15939     var len, pos, item;
  15940     if (this.state.opt.citation_number_sort_direction === CSL.DESCENDING
  15941        && this.state.opt.citation_number_sort_used) {
  15942     }
  15943     len = this.reflist.length;
  15944     for (pos = 0; pos < len; pos += 1) {
  15945         item = this.reflist[pos];
  15946         item.seq = (pos + 1);
  15947         if (this.state.opt.update_mode === CSL.NUMERIC && item.seq != this.oldseq[item.id]) {
  15948             this.state.tmp.taintedItemIDs[item.id] = true;
  15949         }
  15950         if (this.state.opt.bib_mode === CSL.NUMERIC && item.seq != this.oldseq[item.id]) {
  15951             this.return_data.bibchange = true;
  15952         }
  15953     }
  15954     if (this.state.opt.citation_number_sort_direction === CSL.DESCENDING
  15955        && this.state.opt.citation_number_sort_used) {
  15956         this.reflist.reverse();
  15957     }
  15958 };
  15959 CSL.Registry.prototype.setsortkeys = function () {
  15960     var key;
  15961     for (var i = 0, ilen = this.mylist.length; i < ilen; i += 1) {
  15962         var key = this.mylist[i];
  15963         if (this.touched[key] || this.state.tmp.taintedItemIDs[key] || !this.registry[key].sortkeys) {
  15964             this.registry[key].sortkeys = CSL.getSortKeys.call(this.state, this.state.retrieveItem(key), "bibliography_sort");
  15965         }
  15966     }
  15967 };
  15968 CSL.Registry.prototype.sorttokens = function () {
  15969     this.reflist.sort(this.sorter.compareKeys);
  15970 };
  15971 CSL.Registry.Comparifier = function (state, keyset) {
  15972     var sort_directions, len, pos, compareKeys;
  15973     var sortCompare = CSL.getSortCompare(state.opt["default-locale-sort"]);
  15974     sort_directions = state[keyset].opt.sort_directions;
  15975     this.compareKeys = function (a, b) {
  15976         len = a.sortkeys ? a.sortkeys.length : 0;
  15977         for (pos = 0; pos < len; pos += 1) {
  15978             var cmp = 0;
  15979             if (a.sortkeys[pos] === b.sortkeys[pos]) {
  15980                 cmp = 0;
  15981             } else if ("undefined" === typeof a.sortkeys[pos]) {
  15982                 cmp = sort_directions[pos][1];
  15983             } else if ("undefined" === typeof b.sortkeys[pos]) {
  15984                 cmp = sort_directions[pos][0];
  15985             } else {
  15986                 cmp = sortCompare(a.sortkeys[pos], b.sortkeys[pos]);
  15987             }
  15988             if (0 < cmp) {
  15989                 return sort_directions[pos][1];
  15990             } else if (0 > cmp) {
  15991                 return sort_directions[pos][0];
  15992             }
  15993         }
  15994         if (a.seq > b.seq) {
  15995             return 1;
  15996         } else if (a.seq < b.seq) {
  15997             return -1;
  15998         }
  15999         return 0;
  16000     };
  16001     compareKeys = this.compareKeys;
  16002     this.compareCompositeKeys = function (a, b) {
  16003         return compareKeys(a[1], b[1]);
  16004     };
  16005 };
  16006 CSL.Registry.prototype.compareRegistryTokens = function (a, b) {
  16007     if (a.seq > b.seq) {
  16008         return 1;
  16009     } else if (a.seq < b.seq) {
  16010         return -1;
  16011     }
  16012     return 0;
  16013 };
  16014 CSL.Registry.prototype.registerAmbigToken = function (akey, id, ambig_config) {
  16015     if (this.registry[id] && this.registry[id].disambig && this.registry[id].disambig.names) {
  16016         for (var i = 0, ilen = ambig_config.names.length; i < ilen; i += 1) {
  16017             var new_names_params = ambig_config.names[i];
  16018             var old_names_params = this.registry[id].disambig.names[i];
  16019             if (new_names_params !== old_names_params) {
  16020                 this.state.tmp.taintedItemIDs[id] = true;
  16021             } else if (ambig_config.givens[i]) {
  16022                 for (var j=0,jlen=ambig_config.givens[i].length;j<jlen;j+=1) {
  16023                     var new_gnames_params = ambig_config.givens[i][j];
  16024                     var old_gnames_params = this.registry[id].disambig.givens[i][j];
  16025                     if (new_gnames_params !== old_gnames_params) {
  16026                         this.state.tmp.taintedItemIDs[id] = true;
  16027                     }
  16028                 }
  16029             }
  16030         }
  16031     }
  16032     if (!this.ambigcites[akey]) {
  16033         this.ambigcites[akey] = [];
  16034     }
  16035     if (this.ambigcites[akey].indexOf("" + id) === -1) {
  16036         this.ambigcites[akey].push("" + id);
  16037     }
  16038     this.registry[id].ambig = akey;
  16039     var dome = false;
  16040     this.registry[id].disambig = CSL.cloneAmbigConfig(ambig_config);
  16041 };
  16042 CSL.getSortKeys = function (Item, key_type) {
  16043     var area, root, extension, strip_prepositions, use_parallels, len, pos;
  16044     area = this.tmp.area;
  16045     root = this.tmp.root;
  16046     extension = this.tmp.extension;
  16047     strip_prepositions = CSL.Util.Sort.strip_prepositions;
  16048     this.tmp.area = key_type;
  16049     this.tmp.root = key_type.indexOf("_") > -1 ? key_type.slice(0,-5) : key_type;
  16050     this.tmp.extension = "_sort";
  16051     this.tmp.disambig_override = true;
  16052     this.tmp.disambig_request = false;
  16053     this.parallel.use_parallels = (this.parallel.use_parallels === true || this.parallel.use_parallels === null) ? null : false;
  16054     this.tmp.suppress_decorations = true;
  16055     CSL.getCite.call(this, Item);
  16056     this.tmp.suppress_decorations = false;
  16057     this.parallel.use_parallels = this.parallel.use_parallels === null ? true : false;
  16058     this.tmp.disambig_override = false;
  16059     len = this[key_type].keys.length;
  16060     for (pos = 0; pos < len; pos += 1) {
  16061         this[key_type].keys[pos] = strip_prepositions(this[key_type].keys[pos]);
  16062     }
  16063     this.tmp.area = area;
  16064     this.tmp.root = root;
  16065     this.tmp.extension = extension;
  16066     return this[key_type].keys;
  16067 };
  16068 CSL.Registry.NameReg = function (state) {
  16069     var pkey, ikey, skey, floor, ceiling, dagopt, gdropt, ret, pos, items, strip_periods, set_keys, evalname, delitems, addname, key, myitems, i, ilen;
  16070     this.state = state;
  16071     this.namereg = {};
  16072     this.nameind = {};
  16073     this.nameindpkeys = {};
  16074     this.itemkeyreg = {};
  16075     strip_periods = function (str) {
  16076         if (!str) {
  16077             str = "";
  16078         }
  16079         return str.replace(/\./g, " ").replace(/\s+/g, " ").replace(/\s+$/,"");
  16080     };
  16081     set_keys = function (state, itemid, nameobj) {
  16082         pkey = strip_periods(nameobj.family);
  16083         skey = strip_periods(nameobj.given);
  16084         var m = skey.match(/[,\!]* ([^,]+)$/);
  16085         if (m && m[1] === m[1].toLowerCase()) {
  16086             skey = skey.replace(/[,\!]* [^,]+$/, "");
  16087         }
  16088         ikey = CSL.Util.Names.initializeWith(state, skey, "%s");
  16089         if (state.citation.opt["givenname-disambiguation-rule"] === "by-cite") {
  16090             pkey = "" + itemid + pkey;
  16091         }
  16092     };
  16093     evalname = function (item_id, nameobj, namenum, request_base, form, initials) {
  16094         var pos, len, items, param;
  16095         if (state.tmp.area.slice(0, 12) === "bibliography" && !form) {
  16096             if ("string" === typeof initials) {
  16097                 return 1;
  16098             } else {
  16099                 return 2;
  16100             }
  16101         }
  16102         var res = state.nameOutput.getName(nameobj, "locale-translit", true);
  16103         nameobj = res.name;
  16104         set_keys(this.state, "" + item_id, nameobj);
  16105         param = 2;
  16106         dagopt = state.opt["disambiguate-add-givenname"];
  16107         gdropt = state.citation.opt["givenname-disambiguation-rule"];
  16108         var gdropt_orig = gdropt;
  16109         if (gdropt === "by-cite") {
  16110             gdropt = "all-names";
  16111         }
  16112         if ("short" === form) {
  16113             param = 0;
  16114         } else if ("string" === typeof initials) {
  16115             param = 1;
  16116         }
  16117         if ("undefined" === typeof this.namereg[pkey] || "undefined" === typeof this.namereg[pkey].ikey[ikey]) {
  16118             return param;
  16119         }
  16120         if (gdropt_orig === "by-cite" && param <= request_base) {
  16121             return request_base;
  16122         }
  16123         if (!dagopt) {
  16124             return param;
  16125         }
  16126         if ("string" === typeof gdropt && gdropt.slice(0, 12) === "primary-name" && namenum > 0) {
  16127             return param;
  16128         }
  16129         if (!gdropt || gdropt === "all-names" || gdropt === "primary-name") {
  16130             if (this.namereg[pkey].count > 1) {
  16131                 param = 1;
  16132             }
  16133             if ((this.namereg[pkey].ikey 
  16134                  && this.namereg[pkey].ikey[ikey].count > 1)
  16135                 || (this.namereg[pkey].count > 1 
  16136                     && "string" !== typeof initials)) {
  16137                 param = 2;
  16138             }
  16139         } else if (gdropt === "all-names-with-initials" || gdropt === "primary-name-with-initials") {
  16140             if (this.namereg[pkey].count > 1) {
  16141                 param = 1;
  16142             } else {
  16143                 param = 0;
  16144             }
  16145         }
  16146         if (!state.registry.registry[item_id]) {
  16147             if (form == "short") {
  16148                 return 0;
  16149             } else if ("string" == typeof initials) {
  16150                 return 1;
  16151             }
  16152         } else {
  16153             return param;
  16154         }
  16155     };
  16156     delitems = function (ids) {
  16157         var item, pos, len, posA, posB, id, fullkey, llen, ppos, otherid;
  16158         if ("string" === typeof ids || "number" === typeof ids) {
  16159             ids = ["" + ids];
  16160         }
  16161         var ret = {};
  16162         len = ids.length;
  16163         for (pos = 0; pos < len; pos += 1) {
  16164             id = "" + ids[pos];
  16165             if (!this.nameind[id]) {
  16166                 continue;
  16167             }
  16168             for (fullkey in this.nameind[id]) {
  16169                 if (this.nameind[id].hasOwnProperty(fullkey)) {
  16170                     var key = fullkey.split("::");
  16171                     pkey = key[0];
  16172                     ikey = key[1];
  16173                     skey = key[2];
  16174                     if ("undefined" === typeof this.namereg[pkey]) {
  16175                         continue;
  16176                     }
  16177                     items = this.namereg[pkey].items;
  16178                     if (skey && this.namereg[pkey].ikey[ikey] && this.namereg[pkey].ikey[ikey].skey[skey]) {
  16179                         myitems = this.namereg[pkey].ikey[ikey].skey[skey].items;
  16180                         posB = myitems.indexOf("" + id);
  16181                         if (posB > -1) {
  16182                             this.namereg[pkey].ikey[ikey].skey[skey].items = myitems.slice(0, posB).concat(myitems.slice([(posB + 1)]));
  16183                         }
  16184                         if (this.namereg[pkey].ikey[ikey].skey[skey].items.length === 0) {
  16185                             delete this.namereg[pkey].ikey[ikey].skey[skey];
  16186                             this.namereg[pkey].ikey[ikey].count += -1;
  16187                             if (this.namereg[pkey].ikey[ikey].count < 2) {
  16188                                 for (var i = 0, ilen = this.namereg[pkey].ikey[ikey].items.length; i < ilen; i += 1) {
  16189                                     state.tmp.taintedItemIDs[this.namereg[pkey].ikey[ikey].items[i]] = true;
  16190                                 }
  16191                             }
  16192                         }
  16193                     }
  16194                     if (ikey && this.namereg[pkey].ikey[ikey]) {
  16195                         posB = this.namereg[pkey].ikey[ikey].items.indexOf("" + id);
  16196                         if (posB > -1) {
  16197                             items = this.namereg[pkey].ikey[ikey].items.slice();
  16198                             this.namereg[pkey].ikey[ikey].items = items.slice(0, posB).concat(items.slice([posB + 1]));
  16199                         }
  16200                         if (this.namereg[pkey].ikey[ikey].items.length === 0) {
  16201                             delete this.namereg[pkey].ikey[ikey];
  16202                             this.namereg[pkey].count += -1;
  16203                             if (this.namereg[pkey].count < 2) {
  16204                                 for (var i = 0, ilen = this.namereg[pkey].items.length; i < ilen; i += 1) {
  16205                                     state.tmp.taintedItemIDs[this.namereg[pkey].items[i]] = true;
  16206                                 }
  16207                             }
  16208                         }
  16209                     }
  16210                     if (pkey) {
  16211                         posB = this.namereg[pkey].items.indexOf("" + id);
  16212                         if (posB > -1) {
  16213                             items = this.namereg[pkey].items.slice();
  16214                             this.namereg[pkey].items = items.slice(0, posB).concat(items.slice([posB + 1], items.length));
  16215                         }
  16216                         if (this.namereg[pkey].items.length < 2) {
  16217                             delete this.namereg[pkey];
  16218                         }
  16219                     }
  16220                     delete this.nameind[id][fullkey];
  16221                 }
  16222             }
  16223             delete this.nameind[id];
  16224             delete this.nameindpkeys[id];
  16225         }
  16226         return ret;
  16227     };
  16228     addname = function (item_id, nameobj, pos) {
  16229         var i, ilen;
  16230         var res = state.nameOutput.getName(nameobj, "locale-translit", true);
  16231         nameobj = res.name;
  16232         if (state.citation.opt["givenname-disambiguation-rule"]
  16233             && state.citation.opt["givenname-disambiguation-rule"].slice(0, 8) === "primary-"
  16234             && pos !== 0) {
  16235                 return;
  16236         }
  16237         set_keys(this.state, "" + item_id, nameobj);
  16238         if (pkey) {
  16239             if ("undefined" === typeof this.namereg[pkey]) {
  16240                 this.namereg[pkey] = {};
  16241                 this.namereg[pkey].count = 0;
  16242                 this.namereg[pkey].ikey = {};
  16243                 this.namereg[pkey].items = [item_id];
  16244             } else if (this.namereg[pkey].items.indexOf(item_id) === -1) {
  16245                 this.namereg[pkey].items.push(item_id);
  16246             }
  16247         }
  16248         if (pkey && ikey) {
  16249             if ("undefined" === typeof this.namereg[pkey].ikey[ikey]) {
  16250                 this.namereg[pkey].ikey[ikey] = {};
  16251                 this.namereg[pkey].ikey[ikey].count = 0;
  16252                 this.namereg[pkey].ikey[ikey].skey = {};
  16253                 this.namereg[pkey].ikey[ikey].items = [item_id];
  16254                 this.namereg[pkey].count += 1;
  16255                 if (this.namereg[pkey].count === 2) {
  16256                     for (var i = 0, ilen = this.namereg[pkey].items.length; i < ilen; i += 1) {
  16257                         state.tmp.taintedItemIDs[this.namereg[pkey].items[i]] = true;
  16258                     }
  16259                 }
  16260             } else if (this.namereg[pkey].ikey[ikey].items.indexOf(item_id) === -1) {
  16261                 this.namereg[pkey].ikey[ikey].items.push(item_id);
  16262             }
  16263         }
  16264         if (pkey && ikey && skey) {
  16265             if ("undefined" === typeof this.namereg[pkey].ikey[ikey].skey[skey]) {
  16266                 this.namereg[pkey].ikey[ikey].skey[skey] = {};
  16267                 this.namereg[pkey].ikey[ikey].skey[skey].items = [item_id];
  16268                 this.namereg[pkey].ikey[ikey].count += 1;
  16269                 if (this.namereg[pkey].ikey[ikey].count === 2) {
  16270                     for (var i = 0, ilen = this.namereg[pkey].ikey[ikey].items.length; i < ilen; i += 1) {
  16271                         state.tmp.taintedItemIDs[this.namereg[pkey].ikey[ikey].items[i]] = true;
  16272                     }
  16273                 }
  16274             } else if (this.namereg[pkey].ikey[ikey].skey[skey].items.indexOf(item_id) === -1) {
  16275                 this.namereg[pkey].ikey[ikey].skey[skey].items.push(item_id);
  16276             }
  16277         }
  16278         if ("undefined" === typeof this.nameind[item_id]) {
  16279             this.nameind[item_id] = {};
  16280             this.nameindpkeys[item_id] = {};
  16281         }
  16282         if (pkey) {
  16283             this.nameind[item_id][pkey + "::" + ikey + "::" + skey] = true;
  16284             this.nameindpkeys[item_id][pkey] = this.namereg[pkey];
  16285         }
  16286     };
  16287     this.addname = addname;
  16288     this.delitems = delitems;
  16289     this.evalname = evalname;
  16290 };
  16291 CSL.Registry.CitationReg = function (state) {
  16292     this.citationById = {};
  16293     this.citationByIndex = [];
  16294 };
  16295 CSL.Disambiguation = function (state) {
  16296     this.state = state;
  16297     this.sys = this.state.sys;
  16298     this.registry = state.registry.registry;
  16299     this.ambigcites = state.registry.ambigcites;
  16300     this.configModes();
  16301     this.debug = false;
  16302 };
  16303 CSL.Disambiguation.prototype.run = function(akey) {
  16304     if (!this.modes.length) {
  16305         return;
  16306     }
  16307     this.akey = akey;
  16308     if (this.initVars(akey)) {
  16309         this.runDisambig();
  16310     }
  16311 };
  16312 CSL.Disambiguation.prototype.runDisambig = function () {
  16313     var pos, len, ppos, llen, pppos, lllen, ismax;
  16314     this.initGivens = true;
  16315     while (this.lists.length) {
  16316         this.gnameset = 0;
  16317         this.gname = 0;
  16318         this.clashes = [1, 0];
  16319         while(this.lists[0][1].length) {
  16320             this.listpos = 0;
  16321             if (!this.base) {
  16322                 this.base = this.lists[0][0];
  16323             }
  16324             var names_used = [];
  16325             ismax = this.incrementDisambig();
  16326             this.scanItems(this.lists[0]);
  16327             this.evalScan(ismax);
  16328         }
  16329         this.lists = this.lists.slice(1);
  16330     }
  16331 };
  16332 CSL.Disambiguation.prototype.scanItems = function (list) {
  16333     var pos, len, Item, otherItem, ItemCite, ignore, base;
  16334     this.Item = list[1][0];
  16335     this.ItemCite = CSL.getAmbiguousCite.call(this.state, this.Item, this.base, true);
  16336     this.scanlist = list[1];
  16337     this.partners = [];
  16338     this.partners.push(this.Item);
  16339     this.nonpartners = [];
  16340     var clashes = 0;
  16341     for (var pos = 1, len = list[1].length; pos < len; pos += 1) {
  16342         otherItem = list[1][pos];
  16343         var otherItemCite = CSL.getAmbiguousCite.call(this.state, otherItem, this.base, true);
  16344         if (this.ItemCite === otherItemCite) {
  16345             clashes += 1;
  16346             this.partners.push(otherItem);
  16347         } else {
  16348             this.nonpartners.push(otherItem);
  16349         }
  16350     }
  16351     this.clashes[0] = this.clashes[1];
  16352     this.clashes[1] = clashes;
  16353 };
  16354 CSL.Disambiguation.prototype.evalScan = function (maxed) {
  16355     this[this.modes[this.modeindex]](maxed);
  16356     if (maxed) {
  16357         if (this.modeindex < this.modes.length - 1) {
  16358             this.modeindex += 1;
  16359         } else {
  16360             this.lists[this.listpos + 1] = [this.base, []];
  16361         }
  16362     }
  16363 };
  16364 CSL.Disambiguation.prototype.disNames = function (ismax) {
  16365     var pos, len, mybase, i, ilen;
  16366     if (this.clashes[1] === 0 && this.nonpartners.length === 1) {
  16367         this.captureStepToBase();
  16368         this.state.registry.registerAmbigToken(this.akey, "" + this.nonpartners[0].id, this.betterbase);
  16369         this.state.registry.registerAmbigToken(this.akey, "" + this.partners[0].id, this.betterbase);
  16370         this.lists[this.listpos] = [this.betterbase, []];
  16371     } else if (this.clashes[1] === 0) {
  16372         this.captureStepToBase();
  16373         this.state.registry.registerAmbigToken(this.akey, "" + this.partners[0].id, this.betterbase);
  16374         this.lists[this.listpos] = [this.betterbase, this.nonpartners];
  16375         if (this.nonpartners.length) {
  16376             this.initGivens = true;
  16377         }
  16378     } else if (this.nonpartners.length === 1) {
  16379         this.captureStepToBase();
  16380         this.state.registry.registerAmbigToken(this.akey, "" + this.nonpartners[0].id, this.betterbase);
  16381         this.lists[this.listpos] = [this.betterbase, this.partners];
  16382     } else if (this.clashes[1] < this.clashes[0]) {
  16383         this.captureStepToBase();
  16384         this.lists[this.listpos] = [this.betterbase, this.partners];
  16385         this.lists.push([this.betterbase, this.nonpartners]);
  16386     } else {
  16387         if (ismax) {
  16388             this.lists[this.listpos] = [this.betterbase, this.nonpartners];
  16389             this.lists.push([this.betterbase, this.partners]);
  16390             if (this.modeindex === this.modes.length - 1) {
  16391                 for (var i = 0, ilen = this.partners.length; i < ilen; i += 1) {
  16392                     this.state.registry.registerAmbigToken(this.akey, "" + this.partners[i].id, this.betterbase);
  16393                 }
  16394                 this.lists[this.listpos] = [this.betterbase, []];
  16395             }
  16396         }
  16397     }
  16398 };
  16399 CSL.Disambiguation.prototype.disExtraText = function () {
  16400     var pos, len, mybase;
  16401     var done = false;
  16402     if (this.clashes[1] === 0 && this.nonpartners.length < 2) {
  16403         done = true;
  16404     }
  16405     if (!done && (!this.base.disambiguate || this.state.tmp.disambiguate_count !== this.state.tmp.disambiguate_maxMax)) {
  16406         this.modeindex = 0;
  16407         this.base.disambiguate = this.state.tmp.disambiguate_count;
  16408         this.betterbase.disambiguate = this.state.tmp.disambiguate_count;
  16409         if (!this.base.disambiguate) {
  16410             this.initGivens = true;
  16411             this.base.disambiguate = 1;
  16412             for (var i = 0, ilen = this.lists[this.listpos][1].length; i < ilen; i += 1) {
  16413                 this.state.tmp.taintedItemIDs[this.lists[this.listpos][1][i].id] = true;
  16414             }
  16415         } else {
  16416             this.disNames();
  16417         }
  16418     } else if (done || this.state.tmp.disambiguate_count === this.state.tmp.disambiguate_maxMax) {
  16419         if (done || this.modeindex === this.modes.length - 1) {
  16420             var base = this.lists[this.listpos][0];
  16421             for (var i = 0, ilen = this.lists[this.listpos][1].length; i < ilen; i += 1) {
  16422                 this.state.tmp.taintedItemIDs[this.lists[this.listpos][1][i].id] = true;
  16423                 this.state.registry.registerAmbigToken(this.akey, "" + this.lists[this.listpos][1][i].id, base);
  16424             }
  16425             this.lists[this.listpos] = [this.betterbase, []];
  16426         } else {
  16427             this.modeindex = this.modes.length - 1;
  16428             var base = this.lists[this.listpos][0];
  16429             base.disambiguate = true;
  16430             for (var i = 0, ilen = this.lists[this.listpos][1].length; i < ilen; i += 1) {
  16431                 this.state.tmp.taintedItemIDs[this.lists[this.listpos][1][i].id] = true;
  16432                 this.state.registry.registerAmbigToken(this.akey, "" + this.lists[this.listpos][1][i].id, base);
  16433             }
  16434         }
  16435     }
  16436 };
  16437 CSL.Disambiguation.prototype.disYears = function () {
  16438     var pos, len, tokens, token, item;
  16439     tokens = [];
  16440     var base = this.lists[this.listpos][0];
  16441     if (this.clashes[1]) {
  16442 		for (var i = 0, ilen = this.state.registry.mylist.length; i < ilen; i += 1) {
  16443 			var origid = this.state.registry.mylist[i];
  16444 			for (var j = 0, jlen = this.lists[this.listpos][1].length; j < jlen; j += 1) {
  16445 				var token = this.lists[this.listpos][1][j];
  16446 				if (token.id == origid) {
  16447 					tokens.push(this.registry[token.id]);
  16448 					break;
  16449 				}
  16450 			}
  16451 		}
  16452     }
  16453     tokens.sort(this.state.registry.sorter.compareKeys);
  16454     for (var pos = 0, len = tokens.length; pos < len; pos += 1) {
  16455         base.year_suffix = ""+pos;
  16456         var oldBase = this.state.registry.registry[tokens[pos].id].disambig;
  16457         this.state.registry.registerAmbigToken(this.akey, "" + tokens[pos].id, base);
  16458         if (CSL.ambigConfigDiff(oldBase,base)) {
  16459             this.state.tmp.taintedItemIDs[tokens[pos].id] = true;
  16460         }
  16461     }
  16462     this.lists[this.listpos] = [this.betterbase, []];
  16463 };
  16464 CSL.Disambiguation.prototype.incrementDisambig = function () {
  16465     var val;
  16466     if (this.initGivens) {
  16467         this.initGivens = false;
  16468         return false;
  16469     }
  16470     var maxed = false;
  16471     var increment_names = true;
  16472     var increment_givens = true;
  16473     if ("disNames" === this.modes[this.modeindex]) {
  16474         increment_names = false;
  16475         if ("number" !== typeof this.givensMax) {
  16476             increment_names = true;
  16477         }
  16478         var increment_namesets = false;
  16479         if ("number" !== typeof this.namesMax) {
  16480             increment_namesets = true;
  16481         }
  16482         if ("number" === typeof this.givensMax) {
  16483             if (this.base.givens.length && this.base.givens[this.gnameset][this.gname] < this.givensMax) {
  16484                 this.base.givens[this.gnameset][this.gname] += 1;
  16485             } else {
  16486                 increment_names = true;
  16487             }
  16488         }
  16489         if ("number" === typeof this.namesMax 
  16490             && increment_names) {
  16491             if (this.state.opt["disambiguate-add-names"]) {
  16492                 increment_namesets = false;
  16493                 if (this.gname < this.namesMax) {
  16494                     this.base.names[this.gnameset] += 1;
  16495                     this.gname += 1;
  16496                 } else {
  16497                     increment_namesets = true;
  16498                 }
  16499             } else {
  16500                 increment_namesets = true;
  16501             }
  16502         }
  16503         if ("number" === typeof this.namesetsMax && increment_namesets) {
  16504             if (this.gnameset < this.namesetsMax) {
  16505                 this.gnameset += 1;
  16506                 this.base.names[this.gnameset] = 1;
  16507                 this.gname = 0;
  16508             } else {
  16509                 var increment_mode = true;
  16510             }
  16511         }
  16512         if (("number" !== typeof this.namesetsMax || this.namesetsMax === -1 || this.gnameset === this.namesetsMax)
  16513             && (!this.state.opt["disambiguate-add-names"] || "number" !== typeof this.namesMax || this.gname === this.namesMax)
  16514             && ("number" != typeof this.givensMax || "undefined" === typeof this.base.givens[this.gnameset] || "undefined" === typeof this.base.givens[this.gnameset][this.gname] || this.base.givens[this.gnameset][this.gname] === this.givensMax)) {
  16515             maxed = true;
  16516         }
  16517     } else if ("disExtraText" === this.modes[this.modeindex]) {
  16518         this.base.disambiguate += 1;
  16519         this.betterbase.disambiguate += 1;
  16520     }
  16521     return maxed;
  16522 };
  16523 CSL.Disambiguation.prototype.initVars = function (akey) {
  16524     var i, ilen, myIds, myItemBundles, myItems;
  16525     this.lists = [];
  16526     this.base = false;
  16527     this.betterbase = false;
  16528     this.akey = akey;
  16529     this.maxNamesByItemId = {};
  16530     myItemBundles = [];
  16531     myIds = this.ambigcites[akey];
  16532     if (!myIds || !myIds.length) {
  16533         return false;
  16534     }
  16535     var Item = false;
  16536     var myItem = this.state.retrieveItem("" + myIds[0]);
  16537     this.getCiteData(myItem);
  16538     this.base = CSL.getAmbigConfig.call(this.state);
  16539     if (myIds && myIds.length > 1) {
  16540         myItemBundles.push([this.maxNamesByItemId[myItem.id], myItem]);
  16541         for (var i = 1, ilen = myIds.length; i < ilen; i += 1) {
  16542             myItem = this.state.retrieveItem("" + myIds[i]);
  16543             this.getCiteData(myItem, this.base);
  16544             myItemBundles.push([this.maxNamesByItemId[myItem.id], myItem]);
  16545         }
  16546         myItemBundles.sort(
  16547             function (a, b) {
  16548                 if (a[0] > b[0]) {
  16549                     return 1;
  16550                 } else if (a[0] < b[0]) {
  16551                     return -1;
  16552                 } else {
  16553                     if (a[1].id > b[1].id) {
  16554                         return 1;
  16555                     } else if (a[1].id < b[1].id) {
  16556                         return -1;
  16557                     } else {
  16558                         return 0;
  16559                     }
  16560                 }
  16561             }
  16562         );
  16563         myItems = [];
  16564         for (var i = 0, ilen = myItemBundles.length; i < ilen; i += 1) {
  16565             myItems.push(myItemBundles[i][1]);
  16566         }
  16567         this.lists.push([this.base, myItems]);
  16568         this.Item = this.lists[0][1][0];
  16569     } else {
  16570         this.Item = this.state.retrieveItem("" + myIds[0]);
  16571     }
  16572     this.modeindex = 0;
  16573     if (this.state.citation.opt["disambiguate-add-names"] || true) {
  16574         this.namesMax = this.maxNamesByItemId[this.Item.id][0];
  16575     } else {
  16576         var namesMax = this.base.names[0];
  16577         for (var i=1,ilen=this.base.names.length;i<ilen;i+=1){
  16578             namesMax = Math.max(namesMax,this.base.names.names[i]);
  16579         }
  16580     }
  16581     this.padBase(this.base);
  16582     this.padBase(this.betterbase);
  16583     this.base.year_suffix = false;
  16584     this.base.disambiguate = false;
  16585     this.betterbase.year_suffix = false;
  16586     this.betterbase.disambiguate = false;
  16587     if (this.state.citation.opt["givenname-disambiguation-rule"] === "by-cite"
  16588        && this.state.opt["disambiguate-add-givenname"]) {
  16589         this.givensMax = 2;
  16590     }
  16591     return true;
  16592 };
  16593 CSL.Disambiguation.prototype.padBase = function (base) {
  16594     for (var i = 0, ilen = base.names.length; i < ilen; i += 1) {
  16595         if (!base.givens[i]) {
  16596             base.givens[i] = [];
  16597         }
  16598         for (var j=0,jlen=base.names[i];j<jlen;j+=1) {
  16599             if (!base.givens[i][j]) {
  16600                 base.givens[i][j] = 0;
  16601             }
  16602         }
  16603     }
  16604 }
  16605 CSL.Disambiguation.prototype.configModes = function () {
  16606     var dagopt, gdropt;
  16607     this.modes = [];
  16608     dagopt = this.state.opt["disambiguate-add-givenname"];
  16609     gdropt = this.state.citation.opt["givenname-disambiguation-rule"];
  16610     if (this.state.opt['disambiguate-add-names'] || (dagopt && gdropt === "by-cite")) {
  16611         this.modes.push("disNames");
  16612     }
  16613     if (this.state.opt.has_disambiguate) {
  16614         this.modes.push("disExtraText");
  16615     }
  16616     if (this.state.opt["disambiguate-add-year-suffix"]) {
  16617         this.modes.push("disYears");
  16618     }
  16619 };
  16620 CSL.Disambiguation.prototype.getCiteData = function(Item, base) {
  16621     if (!this.maxNamesByItemId[Item.id]) {
  16622         CSL.getAmbiguousCite.call(this.state, Item, base);
  16623         base = CSL.getAmbigConfig.call(this.state);
  16624         this.maxNamesByItemId[Item.id] = CSL.getMaxVals.call(this.state);
  16625         this.state.registry.registry[Item.id].disambig.givens = this.state.tmp.disambig_settings.givens.slice();
  16626         for (var i=0,ilen=this.state.registry.registry[Item.id].disambig.givens.length;i<ilen;i+=1) {
  16627             this.state.registry.registry[Item.id].disambig.givens[i] = this.state.tmp.disambig_settings.givens[i].slice();
  16628         }
  16629         this.namesetsMax = this.state.registry.registry[Item.id].disambig.names.length - 1;
  16630         if (!this.base) {
  16631             this.base = base;
  16632             this.betterbase = CSL.cloneAmbigConfig(base);
  16633         }
  16634         if (base.names.length < this.base.names.length) {
  16635             this.base = base;
  16636         }
  16637         var update = false;
  16638         for (var i = 0, ilen = base.names.length; i < ilen; i += 1) {
  16639             if (base.names[i] > this.base.names[i]) {
  16640                 this.base.givens[i] = base.givens[i].slice();
  16641                 this.base.names[i] = base.names[i];
  16642                 this.betterbase.names = this.base.names.slice();
  16643                 this.betterbase.givens = this.base.givens.slice();
  16644                 this.padBase(this.base);
  16645                 this.padBase(this.betterbase);
  16646             }
  16647         }
  16648         this.betterbase.givens = this.base.givens.slice();
  16649         for (var j = 0, jlen = this.base.givens.length; j < jlen; j += 1) {
  16650             this.betterbase.givens[j] = this.base.givens[j].slice();
  16651         }
  16652     }
  16653 };
  16654 CSL.Disambiguation.prototype.captureStepToBase = function() {
  16655     if (this.state.citation.opt["givenname-disambiguation-rule"] === "by-cite"
  16656         && this.base.givens && this.base.givens.length) {
  16657         if ("undefined" !== typeof this.base.givens[this.gnameset][this.gname]) {
  16658             this.betterbase.givens[this.gnameset][this.gname] = this.base.givens[this.gnameset][this.gname];
  16659         }
  16660     }
  16661     this.betterbase.names[this.gnameset] = this.base.names[this.gnameset];
  16662 };
  16663 CSL.Engine.prototype.getJurisdictionList = function (jurisdiction) {
  16664     var jurisdictionList = [];
  16665     var jurisdictionElems = jurisdiction.split(":");
  16666     for (var j=jurisdictionElems.length;j>0;j--) {
  16667         jurisdictionList.push(jurisdictionElems.slice(0,j).join(":"));
  16668     }
  16669     if (jurisdictionList.indexOf("us") === -1) {
  16670         jurisdictionList.push("us");
  16671     }
  16672     return jurisdictionList;
  16673 }
  16674 CSL.Engine.prototype.retrieveAllStyleModules = function (jurisdictionList) {
  16675     var ret = {};
  16676     var preferences = this.locale[this.opt.lang].opts["jurisdiction-preference"];
  16677     preferences = preferences ? preferences : [];
  16678     preferences = [""].concat(preferences);
  16679     for (var i=preferences.length-1;i>-1;i--) {
  16680         var preference = preferences[i];
  16681         for (var j=0,jlen=jurisdictionList.length;j<jlen;j++) {
  16682             var jurisdiction = jurisdictionList[j];
  16683             if (this.opt.jurisdictions_seen[jurisdiction]) continue;
  16684             var res = this.sys.retrieveStyleModule(jurisdiction, preference);
  16685             if ((!res && !preference) || res) {
  16686                 this.opt.jurisdictions_seen[jurisdiction] = true;
  16687             }
  16688             if (!res) continue;
  16689             ret[jurisdiction] = res;
  16690         }
  16691     }
  16692     return ret;
  16693 }
  16694 CSL.ParticleList = function() {
  16695 	var always_dropping_1 = [[[0,1], null]];
  16696 	var always_dropping_2 = [[[0,2], null]];
  16697 	var always_dropping_3 = [[[0,3], null]]
  16698 	var always_non_dropping_1 = [[null, [0,1]]];
  16699 	var always_non_dropping_2 = [[null, [0,2]]];
  16700 	var always_non_dropping_3 = [[null, [0,3]]];
  16701 	var either_1 = [[null, [0,1]],[[0,1],null]];
  16702 	var either_2 = [[null, [0,2]],[[0,2],null]];
  16703 	var either_1_dropping_best = [[[0,1],null],[null, [0,1]]];
  16704 	var either_2_dropping_best = [[[0,2],null],[null, [0,2]]];
  16705 	var either_3_dropping_best = [[[0,3],null],[null, [0,3]]];
  16706 	var non_dropping_2_alt_dropping_1_non_dropping_1 = [[null, [0,2]], [[0,1], [1,2]]];
  16707 	var PARTICLES = [
  16708 		["'s", always_non_dropping_1],
  16709 		["'s-", always_non_dropping_1],
  16710 		["'t", always_non_dropping_1],
  16711 		["a", 	always_non_dropping_1],
  16712 		["aan 't", always_non_dropping_2],
  16713 		["aan de", always_non_dropping_2],
  16714 		["aan den", always_non_dropping_2],
  16715 		["aan der", always_non_dropping_2],
  16716 		["aan het", always_non_dropping_2],
  16717 		["aan t", always_non_dropping_2],
  16718 		["aan", always_non_dropping_1],
  16719 		["ad-", either_1],
  16720 		["adh-", either_1],
  16721 		["af", either_1],
  16722 		["al", either_1],
  16723 		["al-", either_1],
  16724 		["am de", always_non_dropping_2],
  16725 		["am", always_non_dropping_1],
  16726 		["an-", either_1],
  16727 		["ar-", either_1],
  16728 		["as-", either_1],
  16729 		["ash-", either_1],
  16730 		["at-", either_1],
  16731 		["ath-", either_1],
  16732 		["auf dem", either_2_dropping_best],
  16733 		["auf den", either_2_dropping_best],
  16734 		["auf der", either_2_dropping_best],
  16735 		["auf ter", always_non_dropping_2],
  16736 		["auf", either_1_dropping_best],
  16737 		["aus 'm", either_2_dropping_best],
  16738 		["aus dem", either_2_dropping_best],
  16739 		["aus den", either_2_dropping_best],
  16740 		["aus der", either_2_dropping_best],
  16741 		["aus m", either_2_dropping_best],
  16742 		["aus", either_1_dropping_best],
  16743 		["aus'm", either_2_dropping_best],
  16744 		["az-", either_1],
  16745 		["aš-", either_1],
  16746 		["aḍ-", either_1],
  16747 		["aḏ-", either_1],
  16748 		["aṣ-", either_1],
  16749 		["aṭ-", either_1],
  16750 		["aṯ-", either_1],
  16751 		["aẓ-", either_1],
  16752 		["ben", always_non_dropping_1],
  16753 		["bij 't", always_non_dropping_2],
  16754 		["bij de", always_non_dropping_2],
  16755 		["bij den", always_non_dropping_2],
  16756 		["bij het", always_non_dropping_2],
  16757 		["bij t", always_non_dropping_2],
  16758 		["bij", always_non_dropping_1],
  16759 		["bin", always_non_dropping_1],
  16760 		["boven d", always_non_dropping_2],
  16761 		["boven d'", always_non_dropping_2],
  16762 		["d", always_non_dropping_1],
  16763 		["d'", either_1],
  16764 		["da", either_1],
  16765 		["dal", always_non_dropping_1],
  16766 		["dal'", always_non_dropping_1],
  16767 		["dall'", always_non_dropping_1],
  16768 		["dalla", always_non_dropping_1],
  16769 		["das", either_1],
  16770 		["de die le", always_non_dropping_3],
  16771 		["de die", always_non_dropping_2],
  16772 		["de l", always_non_dropping_2],
  16773 		["de l'", always_non_dropping_2],
  16774 		["de la", non_dropping_2_alt_dropping_1_non_dropping_1],
  16775 		["de las", non_dropping_2_alt_dropping_1_non_dropping_1],
  16776 		["de le", always_non_dropping_2],
  16777 		["de li", either_2],
  16778 		["de van der", always_non_dropping_3],
  16779 		["de", either_1],
  16780 		["de'", either_1],
  16781 		["deca", always_non_dropping_1],
  16782 		["degli", either_1],
  16783 		["dei", either_1],
  16784 		["del", either_1],
  16785 		["dela", always_dropping_1],
  16786 		["dell'", either_1],
  16787 		["della", either_1],
  16788 		["delle", either_1],
  16789 		["dello", either_1],
  16790 		["den", either_1],
  16791 		["der", either_1],
  16792 		["des", either_1],
  16793 		["di", either_1],
  16794 		["die le", always_non_dropping_2],
  16795 		["do", always_non_dropping_1],
  16796 		["don", always_non_dropping_1],
  16797 		["dos", either_1],
  16798 		["du", either_1],
  16799 		["ed-", either_1],
  16800 		["edh-", either_1],
  16801 		["el", either_1],
  16802 		["el-", either_1],
  16803 		["en-", either_1],
  16804 		["er-", either_1],
  16805 		["es-", either_1],
  16806 		["esh-", either_1],
  16807 		["et-", either_1],
  16808 		["eth-", either_1],
  16809 		["ez-", either_1],
  16810 		["eš-", either_1],
  16811 		["eḍ-", either_1],
  16812 		["eḏ-", either_1],
  16813 		["eṣ-", either_1],
  16814 		["eṭ-", either_1],
  16815 		["eṯ-", either_1],
  16816 		["eẓ-", either_1],
  16817 		["het", always_non_dropping_1],
  16818 		["i", always_non_dropping_1],
  16819 		["il", always_dropping_1],
  16820 		["im", always_non_dropping_1],
  16821 		["in 't", always_non_dropping_2],
  16822 		["in de", always_non_dropping_2],
  16823 		["in den", always_non_dropping_2],
  16824 		["in der", either_2],
  16825 		["in het", always_non_dropping_2],
  16826 		["in t", always_non_dropping_2],
  16827 		["in", always_non_dropping_1],
  16828 		["l", always_non_dropping_1],
  16829 		["l'", always_non_dropping_1],
  16830 		["la", always_non_dropping_1],
  16831 		["las", always_non_dropping_1],
  16832 		["le", always_non_dropping_1],
  16833 		["les", either_1],
  16834 		["lo", either_1],
  16835 		["los", always_non_dropping_1],
  16836 		["lou", always_non_dropping_1],
  16837 		["of", always_non_dropping_1],
  16838 		["onder 't", always_non_dropping_2],
  16839 		["onder de", always_non_dropping_2],
  16840 		["onder den", always_non_dropping_2],
  16841 		["onder het", always_non_dropping_2],
  16842 		["onder t", always_non_dropping_2],
  16843 		["onder", always_non_dropping_1],
  16844 		["op 't", always_non_dropping_2],
  16845 		["op de", either_2],
  16846 		["op den", always_non_dropping_2],
  16847 		["op der", always_non_dropping_2],
  16848 		["op gen", always_non_dropping_2],
  16849 		["op het", always_non_dropping_2],
  16850 		["op t", always_non_dropping_2],
  16851 		["op ten", always_non_dropping_2],
  16852 		["op", always_non_dropping_1],
  16853 		["over 't", always_non_dropping_2],
  16854 		["over de", always_non_dropping_2],
  16855 		["over den", always_non_dropping_2],
  16856 		["over het", always_non_dropping_2],
  16857 		["over t", always_non_dropping_2],
  16858 		["over", always_non_dropping_1],
  16859 		["s", always_non_dropping_1],
  16860 		["s'", always_non_dropping_1],
  16861 		["sen", always_dropping_1],
  16862 		["t", always_non_dropping_1],
  16863 		["te", always_non_dropping_1],
  16864 		["ten", always_non_dropping_1],
  16865 		["ter", always_non_dropping_1],
  16866 		["tho", always_non_dropping_1],
  16867 		["thoe", always_non_dropping_1],
  16868 		["thor", always_non_dropping_1],
  16869 		["to", always_non_dropping_1],
  16870 		["toe", always_non_dropping_1],
  16871 		["tot", always_non_dropping_1],
  16872 		["uijt 't", always_non_dropping_2],
  16873 		["uijt de", always_non_dropping_2],
  16874 		["uijt den", always_non_dropping_2],
  16875 		["uijt te de", always_non_dropping_3],
  16876 		["uijt ten", always_non_dropping_2],
  16877 		["uijt", always_non_dropping_1],
  16878 		["uit 't", always_non_dropping_2],
  16879 		["uit de", always_non_dropping_2],
  16880 		["uit den", always_non_dropping_2],
  16881 		["uit het", always_non_dropping_2],
  16882 		["uit t", always_non_dropping_2],
  16883 		["uit te de", always_non_dropping_3],
  16884 		["uit ten", always_non_dropping_2],
  16885 		["uit", always_non_dropping_1],
  16886 		["unter", always_non_dropping_1],
  16887 		["v", always_non_dropping_1],
  16888 		["v.", always_non_dropping_1],
  16889 		["v.d.", always_non_dropping_1],
  16890 		["van 't", always_non_dropping_2],
  16891 		["van de l", always_non_dropping_3],
  16892 		["van de l'", always_non_dropping_3],
  16893 		["van de", always_non_dropping_2],
  16894 		["van de", always_non_dropping_2],
  16895 		["van den", always_non_dropping_2],
  16896 		["van der", always_non_dropping_2],
  16897 		["van gen", always_non_dropping_2],
  16898 		["van het", always_non_dropping_2],
  16899 		["van la", always_non_dropping_2],
  16900 		["van t", always_non_dropping_2],
  16901 		["van ter", always_non_dropping_2],
  16902 		["van van de", always_non_dropping_3],
  16903 		["van", either_1],
  16904 		["vander", always_non_dropping_1],
  16905 		["vd", always_non_dropping_1],
  16906 		["ver", always_non_dropping_1],
  16907 		["vom und zum", always_dropping_3],
  16908 		["vom", either_1],
  16909 		["von 't", always_non_dropping_2],
  16910 		["von dem", either_2_dropping_best],
  16911 		["von den", either_2_dropping_best],
  16912 		["von der", either_2_dropping_best],
  16913 		["von t", always_non_dropping_2],
  16914 		["von und zu", either_3_dropping_best],
  16915 		["von zu", either_2_dropping_best],
  16916 		["von", either_1_dropping_best],
  16917 		["voor 't", always_non_dropping_2],
  16918 		["voor de", always_non_dropping_2],
  16919 		["voor den", always_non_dropping_2],
  16920 		["voor in 't", always_non_dropping_3],
  16921 		["voor in t", always_non_dropping_3],
  16922 		["voor", always_non_dropping_1],
  16923 		["vor der", either_2_dropping_best],
  16924 		["vor", either_1_dropping_best],
  16925 		["z", always_dropping_1],
  16926 		["ze", always_dropping_1],
  16927 		["zu", either_1_dropping_best],
  16928 		["zum", either_1],
  16929 		["zur", either_1]
  16930 	];
  16931     return PARTICLES;
  16932 }();
  16933 CSL.parseParticles = function(){
  16934     function splitParticles(nameValue, firstNameFlag, caseOverride) {
  16935 		var origNameValue = nameValue;
  16936 		nameValue = caseOverride ? nameValue.toLowerCase() : nameValue;
  16937 		var particleList = [];
  16938 		var apostrophe;
  16939 		var rex;
  16940 		if (firstNameFlag) {
  16941 			nameValue = nameValue.split("").reverse().join("");
  16942 			rex = CSL.PARTICLE_GIVEN_REGEXP;
  16943 		} else {
  16944 			rex = CSL.PARTICLE_FAMILY_REGEXP;
  16945 		}
  16946 		var m = nameValue.match(rex);
  16947 		while (m) {
  16948 			var m1 = firstNameFlag ? m[1].split("").reverse().join("") : m[1];
  16949 			var firstChar = m ? m1 : false;
  16950 			var firstChar = firstChar ? m1.replace(/^[-\'\u02bb\u2019\s]*(.).*$/, "$1") : false;
  16951 			var hasParticle = firstChar ? firstChar.toUpperCase() !== firstChar : false;
  16952 			if (!hasParticle) break;
  16953 			if (firstNameFlag) {
  16954 				particleList.push(origNameValue.slice(m1.length * -1));
  16955 				origNameValue = origNameValue.slice(0,m1.length * -1);
  16956 			} else {
  16957 				particleList.push(origNameValue.slice(0,m1.length));
  16958 				origNameValue = origNameValue.slice(m1.length);
  16959 			}
  16960 			nameValue = m[2];
  16961 			m = nameValue.match(rex);
  16962 		}
  16963 		if (firstNameFlag) {
  16964 			nameValue = nameValue.split("").reverse().join("");
  16965 			particleList.reverse();
  16966 			for (var i=1,ilen=particleList.length;i<ilen;i++) {
  16967 				if (particleList[i].slice(0, 1) == " ") {
  16968 					particleList[i-1] += " ";
  16969 				}
  16970 			}
  16971 			for (var i=0,ilen=particleList.length;i<ilen;i++) {
  16972 				if (particleList[i].slice(0, 1) == " ") {
  16973 					particleList[i] = particleList[i].slice(1);
  16974 				}
  16975 			}
  16976 			nameValue = origNameValue.slice(0, nameValue.length);
  16977 		} else {
  16978 			nameValue = origNameValue.slice(nameValue.length * -1);
  16979 		}
  16980 		return [hasParticle, nameValue, particleList];
  16981 	}
  16982     function trimLast(str) {
  16983         var lastChar = str.slice(-1);
  16984         str = str.trim();
  16985         if (lastChar === " " && ["\'", "\u2019"].indexOf(str.slice(-1)) > -1) {
  16986             str += " ";
  16987         }
  16988         return str;
  16989     }
  16990     function parseSuffix(nameObj) {
  16991         if (!nameObj.suffix && nameObj.given) {
  16992             var m = nameObj.given.match(/(\s*,!*\s*)/);
  16993             if (m) {
  16994                 var idx = nameObj.given.indexOf(m[1]);
  16995                 var possible_suffix = nameObj.given.slice(idx + m[1].length);
  16996                 var possible_comma = nameObj.given.slice(idx, idx + m[1].length).replace(/\s*/g, "");
  16997                 if (possible_suffix.replace(/\./g, "") === 'et al' && !nameObj["dropping-particle"]) {
  16998                     nameObj["dropping-particle"] = possible_suffix;
  16999                     nameObj["comma-dropping-particle"] = ",";
  17000                 } else {
  17001                     if (possible_comma.length === 2) {
  17002                         nameObj["comma-suffix"] = true;
  17003                     }
  17004                     nameObj.suffix = possible_suffix;
  17005                 }
  17006                 nameObj.given = nameObj.given.slice(0, idx);
  17007             }
  17008         }
  17009     }
  17010     return function(nameObj) {
  17011         var res = splitParticles(nameObj.family);
  17012         var hasLastParticle = res[0];
  17013         var lastNameValue = res[1];
  17014         var lastParticleList = res[2];
  17015         nameObj.family = lastNameValue;
  17016         var nonDroppingParticle = trimLast(lastParticleList.join(""));
  17017         if (nonDroppingParticle) {
  17018             nameObj['non-dropping-particle'] = nonDroppingParticle;
  17019         }
  17020         parseSuffix(nameObj);
  17021         var res = splitParticles(nameObj.given, true);
  17022         var hasFirstParticle = res[0];
  17023         var firstNameValue = res[1];
  17024         var firstParticleList = res[2];
  17025         nameObj.given = firstNameValue;
  17026         var droppingParticle = firstParticleList.join("").trim();
  17027         if (droppingParticle) {
  17028             nameObj['dropping-particle'] = droppingParticle;
  17029         }
  17030     }
  17031 }();