diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 6c5feaaa71..fb38d52289 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -1,49 +1,72 @@ /* - * Copyright (c) 2009-2013 Frank G. Bennett, Jr. All Rights - * Reserved. - * - * The contents of this file are subject to the Common Public - * Attribution License Version 1.0 (the “License”); you may not use - * this file except in compliance with the License. You may obtain a - * copy of the License at: - * + * Copyright (c) 2009-2014 Frank G. Bennett + * + * Unless otherwise indicated, the files in this repository are subject + * to the Common Public Attribution License Version 1.0 (the “License”); + * you may not use this file except in compliance with the License. You + * may obtain a copy of the License at: + * * http://bitbucket.org/fbennett/citeproc-js/src/tip/LICENSE. - * + * + * (See also the note on attribution information below) + * * The License is based on the Mozilla Public License Version 1.1 but * Sections 1.13, 14 and 15 have been added to cover use of software over a * computer network and provide for limited attribution for the * Original Developer. In addition, Exhibit A has been modified to be * consistent with Exhibit B. - * + * * Software distributed under the License is distributed on an “AS IS” * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * The Original Code is the citation formatting software known as * "citeproc-js" (an implementation of the Citation Style Language * [CSL]), including the original test fixtures and software located * under the ./tests subdirectory of the distribution archive. - * + * * The Original Developer is not the Initial Developer and is * __________. If left blank, the Original Developer is the Initial * Developer. - * - * The Initial Developer of the Original Code is Frank G. Bennett, - * Jr. All portions of the code written by Frank G. Bennett, Jr. are - * Copyright (c) 2009-2013 Frank G. Bennett, Jr. All Rights Reserved. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Affero General Public License (the [AGPLv3] - * License), in which case the provisions of [AGPLv3] License are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of the [AGPLv3] License - * and not to allow others to use your version of this file under the - * CPAL, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the - * [AGPLv3] License. If you do not delete the provisions above, a - * recipient may use your version of this file under either the CPAL - * or the [AGPLv3] License.” + * + * The Initial Developer of the Original Code is Frank Bennett. All + * portions of the code written by Frank Bennett are Copyright (c) + * 2009-2014 Frank Bennett. + * + * *** + * + * Alternatively, the files in this repository may be used under the + * terms of the GNU Affero General Public License (the [AGPLv3] License), + * in which case the provisions of [AGPLv3] License are applicable + * instead of those above. If you wish to allow use of your version of + * this file only under the terms of the [AGPLv3] License and not to + * allow others to use your version of this file under the CPAL, indicate + * your decision by deleting the provisions above and replace them with + * the notice and other provisions required by the [AGPLv3] License. If + * you do not delete the provisions above, a recipient may use your + * version of this file under either the CPAL or the [AGPLv3] License. + * + * *** + * + * Attribution Information (CPAL) + * + * Attribution Copyright Notice: [no separate attribution copyright notice is required] + * + * Attribution Phrase: "Citations by CSL (citeproc-js)" + * + * Attribution URL: http://citationstyles.org/ + * + * Graphic Image: [there is no requirement to display a Graphic Image] + * + * Display of Attribution Information is REQUIRED in Larger Works which + * are defined in the CPAL as a work which combines Covered Code or + * portions thereof with code not governed by the terms of the CPAL. + * + * Display of Attribution Information is also REQUIRED on Associated + * Websites. + * + * [ citeproc-js license :: version 1.1 :: 2012.06.30 ] */ if (!Array.indexOf) { Array.prototype.indexOf = function (obj) { @@ -57,7 +80,7 @@ if (!Array.indexOf) { }; } var CSL = { - PROCESSOR_VERSION: "1.0.517", + PROCESSOR_VERSION: "1.0.536", CONDITION_LEVEL_TOP: 1, CONDITION_LEVEL_BOTTOM: 2, PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/, @@ -696,9 +719,13 @@ CSL_CHROME.prototype.clean = function (xml) { xml = xml.replace(/^\n*/, ""); return xml; }; -CSL_CHROME.prototype.getStyleId = function (myxml) { +CSL_CHROME.prototype.getStyleId = function (myxml, styleName) { var text = ""; - var node = myxml.getElementsByTagName("id"); + var tagName = "id"; + if (styleName) { + tagName = "title"; + } + var node = myxml.getElementsByTagName(tagName); if (node && node.length) { node = node.item(0); } @@ -780,7 +807,7 @@ CSL_CHROME.prototype.getAttributeValue = function (myxml,name,namespace) { return ret; } CSL_CHROME.prototype.getNodeValue = function (myxml,name) { - var ret = ""; + var ret = null; if (name){ var vals = myxml.getElementsByTagName(name); if (vals.length > 0) { @@ -792,18 +819,19 @@ CSL_CHROME.prototype.getNodeValue = function (myxml,name) { ret = vals[0].text; } } - } else { - ret = myxml; } - if (ret && ret.childNodes && (ret.childNodes.length == 0 || (ret.childNodes.length == 1 && ret.firstChild.nodeName == "#text"))) { - if ("undefined" != typeof ret.textContent) { - ret = ret.textContent; - } else if ("undefined" != typeof ret.innerText) { - ret = ret.innerText; + if (ret === null && myxml && myxml.childNodes && (myxml.childNodes.length == 0 || (myxml.childNodes.length == 1 && myxml.firstChild.nodeName == "#text"))) { + if ("undefined" != typeof myxml.textContent) { + ret = myxml.textContent; + } else if ("undefined" != typeof myxml.innerText) { + ret = myxml.innerText; } else { - ret = ret.text; + ret = myxml.text; } } + if (ret === null) { + ret = myxml; + } return ret; } CSL_CHROME.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myxml,nodename,partname,attrname,val) { @@ -1004,53 +1032,12 @@ CSL.getSortCompare = function (default_locale) { if (!default_locale) { default_locale = "en-US"; } - try { - var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] - .getService(Components.interfaces.nsILocaleService); - var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"] - .getService(Components.interfaces.nsICollationFactory); - var collation = collationFactory.CreateCollation(localeService.newLocale(default_locale)); - strcmp = function(a, b) { - return collation.compareString(1, a, b); - }; - CSL.debug("Using collation sort: "+default_locale); - } catch (e) { - CSL.debug("Using localeCompare sort"); - strcmp = function (a, b) { - return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()); - }; - } - var isKana = /^[\[\]\'\"]*[\u3040-\u309f\u30a0-\u30ff]/; + strcmp = function (a, b) { + return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()); + }; var stripPunct = function (str) { return str.replace(/^[\[\]\'\"]*/g, ""); } - var getKanaPreSort = function () { - if (strcmp("\u3044", "\u3046")) { - return false; - } else { - return function (a, b) { - a = stripPunct(a); - b = stripPunct(b); - var ak = isKana.exec(a); - var bk = isKana.exec(b); - if (ak || bk) { - if (!ak) { - return -1; - } else if (!bk) { - return 1; - } else if (a < b) { - return -1; - } else if (a > b) { - return 1; - } else { - return 0; - } - } else { - return false; - } - }; - } - } var getBracketPreSort = function () { if (!strcmp("[x","x")) { return false; @@ -1060,15 +1047,8 @@ CSL.getSortCompare = function (default_locale) { } } } - var kanaPreSort = getKanaPreSort(); var bracketPreSort = getBracketPreSort(); var sortCompare = function (a, b) { - if (kanaPreSort) { - var ret = kanaPreSort(a, b); - if (false !== ret) { - return ret; - } - } if (bracketPreSort) { return bracketPreSort(a, b); } else { @@ -1258,6 +1238,8 @@ CSL.XmlToToken = function (state, tokentype) { } } token.decorations = decorations; + } else if (tokentype === CSL.END && attributes['@variable']) { + token.hasVariable = true; } target = state[state.build.area].tokens; CSL.Node[name].build.call(token, state, target); @@ -1645,6 +1627,9 @@ CSL.Engine = function (sys, style, lang, forceLang) { this.processor_version = CSL.PROCESSOR_VERSION; this.csl_version = "1.0"; this.sys = sys; + if (sys.variableWrapper) { + CSL.VARIABLE_WRAPPER_PREPUNCT_REX = new RegExp('^([' + [" "].concat(CSL.SWAPPING_PUNCTUATION).join("") + ']*)(.*)'); + } this.sys.xml = new CSL.System.Xml.Parsing(); if ("undefined" === typeof CSL_JSON && "string" !== typeof style) { style = ""; @@ -1673,7 +1658,7 @@ CSL.Engine = function (sys, style, lang, forceLang) { this.output = new CSL.Output.Queue(this); this.dateput = new CSL.Output.Queue(this); this.cslXml = this.sys.xml.makeXml(style); - if (this.opt.development_extensions.csl_reverse_lookup_support) { + if (this.opt.development_extensions.csl_reverse_lookup_support || this.sys.csl_reverse_lookup_support) { this.build.cslNodeId = 0; this.setCslNodeIds = function(myxml, nodename) { var children = this.sys.xml.children(myxml); @@ -1701,6 +1686,10 @@ CSL.Engine = function (sys, style, lang, forceLang) { this.setStyleAttributes(); this.opt.xclass = sys.xml.getAttributeValue(this.cslXml, "class"); this.opt.styleID = this.sys.xml.getStyleId(this.cslXml); + this.opt.styleName = this.sys.xml.getStyleId(this.cslXml, true); + if (CSL.getSuppressJurisdictions) { + this.opt.suppressJurisdictions = CSL.getSuppressJurisdictions(this.opt.styleID); + } if (this.opt.version.slice(0,4) === "1.1m") { this.opt.development_extensions.static_statute_locator = true; this.opt.development_extensions.handle_parallel_articles = true; @@ -1745,6 +1734,7 @@ CSL.Engine = function (sys, style, lang, forceLang) { return ret; } this.locale[this.opt.lang].opts["skip-words-regexp"] = makeRegExp(this.locale[this.opt.lang].opts["skip-words"]); + this.output.adjust = new CSL.Output.Queue.adjust(this.getOpt('punctuation-in-quote')); this.registry = new CSL.Registry(this); this.buildTokenLists("citation"); this.buildTokenLists("bibliography"); @@ -1816,8 +1806,15 @@ CSL.Engine.prototype.buildTokenLists = function (area) { CSL.Engine.prototype.setStyleAttributes = function () { var dummy, attr, key, attributes, attrname; dummy = {}; - dummy.name = this.sys.xml.nodename(this.cslXml); - attributes = this.sys.xml.attributes(this.cslXml); + var cslXml = this.cslXml; + var tagName = this.cslXml.tagName ? ("" + this.cslXml.tagName).toLowerCase() : ""; + if (tagName !== 'style' && tagName !== 'cslstyle') { + if (this.cslXml.getElementsByTagName) { + var cslXml = this.cslXml.getElementsByTagName('style')[0]; + } + } + dummy.name = this.sys.xml.nodename(cslXml); + attributes = this.sys.xml.attributes(cslXml); for (attrname in attributes) { if (attributes.hasOwnProperty(attrname)) { CSL.Attributes[attrname].call(dummy, this, attributes[attrname]); @@ -2092,20 +2089,21 @@ CSL.Engine.prototype.retrieveItem = function (id) { Item.legislation_id = legislation_id.join("::"); } } + if (!Item["title-short"]) { + Item["title-short"] = Item.shortTitle; + } if (this.opt.development_extensions.main_title_from_short_title) { Item["title-main"] = Item.title; Item["title-sub"] = false; - if (Item.title && Item.shortTitle) { - offset = Item.shortTitle.length; - if (Item.title.slice(0,offset) === Item.shortTitle && Item.title.slice(offset).match(/^\s*:/)) { + if (Item.title && Item['title-short']) { + var shortTitle = Item['title-short']; + offset = shortTitle.length; + if (Item.title.slice(0,offset) === shortTitle && Item.title.slice(offset).match(/^\s*:/)) { Item["title-main"] = Item.title.slice(0,offset).replace(/\s+$/,""); Item["title-sub"] = Item.title.slice(offset).replace(/^\s*:\s*/,""); } } } - if (!Item["title-short"]) { - Item["title-short"] = Item.shortTitle; - } var isLegalType = ["legal_case","legislation","gazette","regulation"].indexOf(Item.type) > -1; if (!isLegalType && Item.title && this.sys.getAbbreviation) { var noHints = false; @@ -2121,10 +2119,10 @@ CSL.Engine.prototype.retrieveItem = function (id) { } Item["container-title-short"] = Item.journalAbbreviation; if (Item["container-title"] && this.sys.getAbbreviation) { - var jurisdiction = this.transform.loadAbbreviation(Item.jurisdiction, "title", Item["container-title"]); - if (this.transform.abbrevs[jurisdiction].title) { - if (this.transform.abbrevs[jurisdiction].title[Item["container-title"]]) { - Item["container-title-short"] = this.transform.abbrevs[jurisdiction].title[Item["container-title"]]; + var jurisdiction = this.transform.loadAbbreviation(Item.jurisdiction, "container-title", Item["container-title"]); + if (this.transform.abbrevs[jurisdiction]["container-title"]) { + if (this.transform.abbrevs[jurisdiction]["container-title"][Item["container-title"]]) { + Item["container-title-short"] = this.transform.abbrevs[jurisdiction]["container-title"][Item["container-title"]]; } } } @@ -2796,7 +2794,7 @@ CSL.Output.Queue.prototype.append = function (str, tokname, notSerious, ignorePr } for (var i = blob.decorations.length - 1; i > -1; i += -1) { if (blob.decorations[i][0] === "@quotes" && blob.decorations[i][1] === "true") { - blob.punctuation_in_quote = this.state.getOpt("punctuation-in-quote") + blob.punctuation_in_quote = this.state.getOpt("punctuation-in-quote"); } if (!blob.blobs.match(CSL.ROMANESQUE_REGEXP)) { if (blob.decorations[i][0] === "@font-style") { @@ -2853,16 +2851,16 @@ CSL.Output.Queue.prototype.string = function (state, myblobs, blob) { if (state.normalDecorIsOrphan(blobjr, params)) { continue; } - b = state.fun.decorate[params[0]][params[1]](state, b, params[2]); + b = state.fun.decorate[params[0]][params[1]].call(blobjr, state, b, params[2]); } } if (b && b.length) { b = txt_esc(blobjr.strings.prefix, state.tmp.nestedBraces) + b + txt_esc(blobjr.strings.suffix, state.tmp.nestedBraces); - if (state.opt.development_extensions.csl_reverse_lookup_support && !state.tmp.suppress_decorations) { + if ((state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support) && !state.tmp.suppress_decorations) { for (j = 0, jlen = blobjr.decorations.length; j < jlen; j += 1) { params = blobjr.decorations[j]; if (params[0] === "@showid") { - b = state.fun.decorate[params[0]][params[1]](state, b, params[2]); + b = state.fun.decorate[params[0]][params[1]].call(blobjr, state, b, params[2]); } } } @@ -2915,7 +2913,7 @@ CSL.Output.Queue.prototype.string = function (state, myblobs, blob) { continue; } if ("string" === typeof blobs_start) { - blobs_start = state.fun.decorate[params[0]][params[1]](state, blobs_start, params[2]); + blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]); } } } @@ -2935,7 +2933,9 @@ CSL.Output.Queue.prototype.string = function (state, myblobs, blob) { if (["@cite","@bibliography", "@display", "@showid"].indexOf(params[0]) === -1) { continue; } - blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]); + if ("string" === typeof blobs_start) { + blobs_start = state.fun.decorate[params[0]][params[1]].call(blob, state, blobs_start, params[2]); + } } } } @@ -2985,6 +2985,7 @@ CSL.Output.Queue.prototype.renderBlobs = function (blobs, delim, in_cite, parent blobs[0].strings.prefix = parent.strings.prefix + blobs[0].strings.prefix; blobs[0].strings.suffix = blobs[0].strings.suffix + parent.strings.suffix; blobs[0].decorations = blobs[0].decorations.concat(parent.decorations); + blobs[0].params = parent.params; return blobs[0]; } var start = true; @@ -3039,7 +3040,7 @@ CSL.Output.Queue.prototype.renderBlobs = function (blobs, delim, in_cite, parent if (state.normalDecorIsOrphan(blob, params)) { continue; } - str = state.fun.decorate[params[0]][params[1]](state, str, params[2]); + str = state.fun.decorate[params[0]][params[1]].call(blob, state, str, params[2]); } } str = txt_esc(blob.strings.prefix) + str + txt_esc(blob.strings.suffix); @@ -3062,321 +3063,409 @@ CSL.Output.Queue.prototype.renderBlobs = function (blobs, delim, in_cite, parent } return ret; }; -CSL.Output.Queue.purgeEmptyBlobs = function (myblobs, endOnly) { - var res, i, ilen, j, jlen, tmpblobs; - if ("string" === typeof myblobs || !myblobs.length) { +CSL.Output.Queue.purgeEmptyBlobs = function (parent) { + if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) { return; } - for (i = myblobs.length - 1; i > -1; i += -1) { - if ("undefined" === typeof myblobs[i].blobs) { - myblobs[i].blobs = []; - } - CSL.Output.Queue.purgeEmptyBlobs(myblobs[i].blobs, endOnly); - } - for (i = myblobs.length - 1; i > -1; i += -1) { - if (!myblobs[i].blobs.length) { - tmpblobs = myblobs.slice(i + 1); - for (j = i, jlen = myblobs.length; j < jlen; j += 1) { - myblobs.pop(); + for (var i=parent.blobs.length-1;i>-1;i--) { + CSL.Output.Queue.purgeEmptyBlobs(parent.blobs[i]); + var child = parent.blobs[i]; + if (!child || !child.blobs || !child.blobs.length) { + var buf = []; + while ((parent.blobs.length-1) > i) { + buf.push(parent.blobs.pop()); } - for (j = 0, jlen = tmpblobs.length; j < jlen; j += 1) { - myblobs.push(tmpblobs[j]); + parent.blobs.pop(); + while (buf.length) { + parent.blobs.push(buf.pop()); } } - if (endOnly) { - break; - } } }; -CSL.Output.Queue.purgeNearsidePrefixChars = function(myblob, chr) { - if (!chr) { - return; +CSL.Output.Queue.adjust = function (punctInQuote) { + var NO_SWAP_IN = { + ";": true, + ":": true } - if ("object" === typeof myblob) { - if ((CSL.TERMINAL_PUNCTUATION.indexOf(chr) > -1 - && CSL.TERMINAL_PUNCTUATION.slice(0, -1).indexOf(myblob.strings.prefix.slice(0, 1)) > -1) - && !(myblob.strings.prefix.slice(0,1) === ";" && chr === ".")) { - myblob.strings.prefix = myblob.strings.prefix.slice(1); - } else if ("object" === typeof myblob.blobs) { - CSL.Output.Queue.purgeNearsidePrefixChars(myblob.blobs[0], chr); + var NO_SWAP_OUT = { + ".": true, + "!": true, + "?": true + } + this.upward = upward; + this.leftward = leftward; + this.downward = downward; + this.fix = fix; + var LtoR_MAP = { + "!": { + ".": "!", + "?": "!?", + ":": "!", + ",": "!,", + ";": "!;" + }, + "?": { + "!": "?!", + ".": "?", + ":": "?", + ",": "?,", + ";": "?;" + }, + ".": { + "!": ".!", + "?": ".?", + ":": ".:", + ",": ".,", + ";": ".;" + }, + ":": { + "!": "!", + "?": "?", + ".": ":", + ",": ":,", + ";": ":;" + }, + ",": { + "!": ",!", + "?": ",?", + ":": ",:", + ".": ",.", + ";": ",;" + }, + ";": { + "!": "!", + "?": "?", + ":": ";", + ",": ";,", + ".": ";" } } -}; -CSL.Output.Queue.purgeNearsidePrefixSpaces = function(myblob, chr) { - if ("object" === typeof myblob) { - if (" " === chr && " " === myblob.strings.prefix.slice(0, 1)) { - myblob.strings.prefix = myblob.strings.prefix.slice(1); - } else if ("object" === typeof myblob.blobs) { - CSL.Output.Queue.purgeNearsidePrefixSpaces(myblob.blobs[0], chr); + var SWAP_IN = {}; + var SWAP_OUT = {}; + var PUNCT = {}; + var PUNCT_OR_SPACE = {}; + for (var key in LtoR_MAP) { + PUNCT[key] = true; + PUNCT_OR_SPACE[key] = true; + if (!NO_SWAP_IN[key]) { + SWAP_IN[key] = true; + } + if (!NO_SWAP_OUT[key]) { + SWAP_OUT[key] = true; } } -}; -CSL.Output.Queue.purgeNearsideSuffixSpaces = function(myblob, chr) { - if ("object" === typeof myblob) { - if (" " === chr && " " === myblob.strings.suffix.slice(-1)) { - myblob.strings.suffix = myblob.strings.suffix.slice(0, -1); - } else if ("object" === typeof myblob.blobs) { - if (!chr) { - chr = myblob.strings.suffix.slice(-1); + PUNCT_OR_SPACE[" "] = true; + PUNCT_OR_SPACE[" "] = true; + var RtoL_MAP = {}; + for (var key in LtoR_MAP) { + for (var subkey in LtoR_MAP[key]) { + if (!RtoL_MAP[subkey]) { + RtoL_MAP[subkey] = {}; } - chr = CSL.Output.Queue.purgeNearsideSuffixSpaces(myblob.blobs[myblob.blobs.length - 1], chr); - } else { - chr = myblob.strings.suffix.slice(-1); + RtoL_MAP[subkey][key] = LtoR_MAP[key][subkey]; } } - return chr; -}; -CSL.Output.Queue.adjustPunctuation = function (state, myblobs, stk) { - var chr, suffix, dpref, blob, delimiter, suffixX, dprefX, blobX, delimiterX, prefix, prefixX, dsuffX, dsuff, slast, dsufff, dsufffX, lastchr, firstchr, exposed_suffixes, exposed, j, jlen, i, ilen; - var TERMS = CSL.TERMINAL_PUNCTUATION.slice(0, -1); - var TERM_OR_SPACE = CSL.TERMINAL_PUNCTUATION; - var SWAPS = CSL.SWAPPING_PUNCTUATION; - if (!stk) { - stk = [{suffix: "", delimiter: "", lastNode:true}]; - } - slast = stk.length - 1; - delimiter = stk[slast].delimiter; - dpref = stk[slast].dpref; - dsuff = stk[slast].dsuff; - dsufff = stk[slast].dsufff; - prefix = stk[slast].prefix; - suffix = stk[slast].suffix; - blob = stk[slast].blob; - if ("string" === typeof myblobs) { - if (suffix) { - if (blob && - TERMS.indexOf(myblobs.slice(-1)) > -1 && - TERMS.slice(1).indexOf(suffix) > -1 && - blob.strings.suffix !== " ") { - blob.strings.suffix = blob.strings.suffix.slice(1); - } + function blobIsNumber(blob) { + return ("number" === typeof blob.num || (blob.blobs && blob.blobs.length === 1 && "number" === typeof blob.blobs[0].num)); + }; + function blobEndsInNumber(blob) { + if ("number" === typeof blob.num) { + return true; } - lastchr = myblobs.slice(-1); - firstchr = myblobs.slice(0,1); - } else { - if (dpref) { - for (j = 0, jlen = myblobs.length - 1; j < jlen; j += 1) { - var t = myblobs[j].strings.suffix.slice(-1); - if (TERMS.indexOf(t) === -1 || - TERMS.indexOf(dpref) === -1) { - if (dpref !== " " || dpref !== myblobs[j].strings.suffix.slice(-1)) { - myblobs[j].strings.suffix += dpref; - } + if (!blob.blobs || "object" !== typeof blob.blobs) return false; + if (blobEndsInNumber(blob.blobs[blob.blobs.length-1])) return true; + } + function blobHasDecorations(blob,includeQuotes) { + var ret = false; + var decorlist = ['@font-style','@font-variant','@font-weight','@text-decoration','@vertical-align']; + if (includeQuotes) { + decorlist.push('@quotes'); + } + if (blob.decorations) { + for (var i=0,ilen=blob.decorations.length;i -1) { + ret = true; + break; } } } - if (suffix === " ") { - CSL.Output.Queue.purgeNearsideSuffixSpaces(myblobs[myblobs.length - 1], " "); + return ret; + }; + function blobHasDescendantQuotes(blob) { + if (blob.decorations) { + for (var i=0,ilen=blob.decorations.length;i-1;i--) { + var endFlag = i === (parent.blobs.length-1); + this.upward(parent.blobs[i]); + var parentStrings = parent.strings; + var childStrings = parent.blobs[i].strings; if (i === 0) { - if (prefix) { - if (doblob.strings.prefix.slice(0, 1) === " ") { + if (" " === parentStrings.prefix.slice(-1) && " " === childStrings.prefix.slice(0, 1)) { + childStrings.prefix = childStrings.prefix.slice(1); + } + var childChar = childStrings.prefix.slice(0, 1); + if (!parentDecorations && PUNCT_OR_SPACE[childChar] && !parentStrings.prefix) { + parentStrings.prefix += childChar; + childStrings.prefix = childStrings.prefix.slice(1); + } + } + if (i === (parent.blobs.length - 1)) { + var childChar = childStrings.suffix.slice(-1); + if (!parentDecorations && [" "].indexOf(childChar) > -1) { + if (parentStrings.suffix.slice(0,1) !== childChar) { + parentStrings.suffix = childChar + parentStrings.suffix; + } + childStrings.suffix = childStrings.suffix.slice(0, -1); + } + } + if (parentStrings.delimiter && i > 0) { + if (PUNCT_OR_SPACE[parentStrings.delimiter.slice(-1)] + && parentStrings.delimiter.slice(-1) === childStrings.prefix.slice(0, 1)) { + childStrings.prefix = childStrings.prefix.slice(1); + } + } + } + }; + function leftward (parent) { + if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) { + return; + } + for (var i=parent.blobs.length-1;i>-1;i--) { + this.leftward(parent.blobs[i]); + if ((i < parent.blobs.length -1) && !parent.strings.delimiter) { + var child = parent.blobs[i]; + var childChar = child.strings.suffix.slice(-1); + var sibling = parent.blobs[i+1]; + var siblingChar = sibling.strings.prefix.slice(0, 1); + var hasDecorations = blobHasDecorations(child) || blobHasDecorations(sibling); + var hasNumber = "number" === typeof childChar || "number" === typeof siblingChar; + if (!hasDecorations && !hasNumber && PUNCT[siblingChar] && !hasNumber) { + var suffixAndPrefixMatch = siblingChar === child.strings.suffix.slice(-1); + var suffixAndFieldMatch = (!child.strings.suffix && "string" === typeof child.blobs && child.blobs.slice(-1) === siblingChar); + if (!suffixAndPrefixMatch && !suffixAndFieldMatch) { + mergeChars(child, 'suffix', sibling, 'prefix'); + } else { + sibling.strings.prefix = sibling.strings.prefix.slice(1); } } } - if (dsufff) { - if (doblob.strings.prefix) { - if (i === 0) { - if (doblob.strings.prefix.slice(0, 1) === " ") { - } - } - } + } + }; + function downward (parent) { + if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) { + return; + } + var parentStrings = parent.strings; + var someChildrenAreNumbers = false; + for (var i=0,ilen=parent.blobs.length;i 0) { - if (doblob.strings.prefix.slice(0, 1) === " ") { - } + } + if (!someChildrenAreNumbers) { + if (parentStrings.delimiter && PUNCT[parentStrings.delimiter.slice(0, 1)]) { + var delimChar = parentStrings.delimiter.slice(0, 1); + for (var i=parent.blobs.length-2;i>-1;i--) { + var childStrings = parent.blobs[i].strings; + childStrings.suffix += delimChar; } + parentStrings.delimiter = parentStrings.delimiter.slice(1); } - if (i < (myblobs.length - 1)) { - var nextprefix = myblobs[i + 1].strings.prefix; - if (!delimiter) { - if (nextprefix) { - var nxtchr = nextprefix.slice(0, 1); - if (SWAPS.indexOf(nxtchr) > -1) { - myblobs[i + 1].strings.prefix = nextprefix.slice(1); - if (TERMS.indexOf(nxtchr) === -1 || - (TERMS.indexOf(nxtchr) > -1 && - TERMS.indexOf(doblob.strings.suffix.slice(-1)) === -1)) { - doblob.strings.suffix += nxtchr; + } + var parentDecorations = blobHasDecorations(parent, true); + var parentIsNumber = blobIsNumber(parent); + for (var i=parent.blobs.length-1;i>-1;i--) { + var child = parent.blobs[i]; + var childStrings = parent.blobs[i].strings; + var childDecorations = blobHasDecorations(child, true); + var childIsNumber = blobIsNumber(child); + if (i === (parent.blobs.length - 1)) { + if (true || !someChildrenAreNumbers) { + if (!parentDecorations || blobHasDescendantQuotes(child)) { + var parentChar = parentStrings.suffix.slice(0, 1); + if (PUNCT[parentChar]) { + if (!blobEndsInNumber(child)) { + mergeChars(child, 'suffix', parent, 'suffix'); } - } else if (nxtchr === " " && - doblob.strings.suffix.slice(-1) === " ") { - doblob.strings.suffix = doblob.strings.suffix.slice(0, -1); } - } - } - } - if (i === (myblobs.length - 1)) { - if (suffix) { - if (doblob.strings.suffix && - (TERMS.slice(1).indexOf(suffix) > -1 && - TERMS.indexOf(doblob.strings.suffix.slice(-1)) > -1)) { - blob.strings.suffix = blob.strings.suffix.slice(1); - } - } - } - if (state.getOpt('punctuation-in-quote')) { - var decorations = doblob.decorations; - for (j = 0, jlen = decorations.length; j < jlen; j += 1) { - if (decorations[j][0] === '@quotes' && (decorations[j][1] === 'true' || decorations[j][1] === 'inner')) { - doblob.punctuation_in_quote = true; - stk[slast].lastNode = true; - } - } - } - if (doblob.punctuation_in_quote && stk[slast].lastNode) { - var swapchar = doblob.strings.suffix.slice(0, 1); - var swapblob = false; - if (SWAPS.indexOf(swapchar) > -1) { - swapblob = doblob; - } else if (SWAPS.indexOf(suffix) > -1 && i === (myblobs.length - 1)) { - swapchar = suffix; - swapblob = blob; - } else { - swapchar = false; - } - if (swapchar) { - if ("string" === typeof doblob.blobs) { - if (SWAPS.indexOf(doblob.blobs.slice(-1)) === -1 || - (TERMS.indexOf(doblob.blobs.slice(-1)) > -1 && - SWAPS.indexOf(swapchar) > -1 && - TERMS.indexOf(swapchar) === -1)) { - doblob.blobs += swapchar; + if (childStrings.suffix.slice(-1) === " " && parentStrings.suffix.slice(0,1)) { + parentStrings.suffix = parentStrings.suffix.slice(1); } } else { - if (SWAPS.indexOf(doblob.blobs.slice(-1)[0].strings.suffix.slice(-1)) === -1 || - (TERMS.indexOf(doblob.blobs.slice(-1)[0].strings.suffix.slice(-1)) > -1 && - SWAPS.indexOf(swapchar) > -1 && - TERMS.indexOf(swapchar) === -1)) { - doblob.blobs.slice(-1)[0].strings.suffix += swapchar; + if (matchLastChar(child,parent.strings.suffix.slice(0,1))) { + parent.strings.suffix = parent.strings.suffix.slice(1); + } + } + if (PUNCT_OR_SPACE[childStrings.suffix.slice(0,1)]) { + if ("string" === typeof child.blobs && child.blobs.slice(-1) === childStrings.suffix.slice(0,1)) { + childStrings.suffix = childStrings.suffix.slice(1); + } + if (childStrings.suffix.slice(-1) === parentStrings.suffix.slice(0, 1)) { + childStrings.suffix = childStrings.suffix.slice(0, -1); } } - swapblob.strings.suffix = swapblob.strings.suffix.slice(1); } - } - if (i === (myblobs.length - 1)) { - if (doblob.strings.suffix) { - suffixX = doblob.strings.suffix.slice(0, 1); - blobX = doblob; - } else { - suffixX = stk[stk.length - 1].suffix; - blobX = stk[stk.length - 1].blob; + } else if (parentStrings.delimiter) { + if (PUNCT_OR_SPACE[parentStrings.delimiter.slice(0,1)] + && parentStrings.delimiter.slice(0, 1) === childStrings.suffix.slice(-1)) { + parent.blobs[i].strings.suffix = parent.blobs[i].strings.suffix.slice(0, -1); } } else { - if (doblob.strings.suffix) { - suffixX = doblob.strings.suffix.slice(0, 1); - blobX = doblob; - } else { - suffixX = ""; - blobX = false; + var siblingStrings = parent.blobs[i+1].strings; + if (!blobIsNumber(child) + && !childDecorations + && PUNCT_OR_SPACE[childStrings.suffix.slice(-1)] + && childStrings.suffix.slice(-1) === siblingStrings.prefix.slice(0, 1)) { + siblingStrings.prefix = siblingStrings.prefix.slice(1); } } - if (SWAPS.concat([" "]).indexOf(suffixX) === -1) { - suffixX = ""; - blobX = false; + if (!childIsNumber && !childDecorations && PUNCT[childStrings.suffix.slice(0,1)] + && "string" === typeof child.blobs) { + mergeChars(child, 'blobs', child, 'suffix') } - if (doblob.strings.delimiter && - doblob.blobs.length > 1) { - dprefX = doblob.strings.delimiter.slice(0, 1); - if (SWAPS.concat([" "]).indexOf(dprefX) > -1) { - doblob.strings.delimiter = doblob.strings.delimiter.slice(1); - } else { - dprefX = ""; - } - } else { - dprefX = ""; - } - if (doblob.strings.prefix) { - if (doblob.strings.prefix.slice(-1) === " ") { - prefixX = " "; - } else { - prefixX = ""; - } - } else { - if (i === 0) { - prefixX = prefix; - } else { - prefixX = ""; - } - } - if (dsuff) { - dsufffX = dsuff; - } else { - if (i === 0) { - dsufffX = dsufff; - } else { - dsufffX = ""; - } - } - if (doblob.strings.delimiter) { - if (doblob.strings.delimiter.slice(-1) === " " && - "object" === typeof doblob.blobs && doblob.blobs.length > 1) { - dsuffX = doblob.strings.delimiter.slice(-1); - } else { - dsuffX = ""; - } - } else { - dsuffX = ""; - } - delimiterX = doblob.strings.delimiter; - var lastNode - if (i === (myblobs.length - 1) && stk[slast].lastNode) { - lastNode = true; - } else { - lastNode = false; - } - stk.push({suffix: suffixX, dsuff:dsuffX, blob:blobX, delimiter:delimiterX, prefix:prefixX, dpref: dprefX, dsufff: dsufffX, lastNode: lastNode}); - lastchr = CSL.Output.Queue.adjustPunctuation(state, doblob.blobs, stk); + this.downward(parent.blobs[i]); } - if (myblobs && myblobs.length) { - var last_suffix = myblobs[myblobs.length - 1].strings.suffix; - if (last_suffix) { - lastchr = last_suffix.slice(-1); + }; + function fix (parent) { + if ("object" !== typeof parent || "object" !== typeof parent.blobs || !parent.blobs.length) { + return; + } + var lastChar; + for (var i=0,ilen=parent.blobs.length;i 1) { - stk.pop(); - } - state.tmp.last_chr = lastchr; - return lastchr; -}; + return lastChar; + }; +} CSL.Engine.Opt = function () { this.has_disambiguate = false; this.mode = "html"; @@ -3701,6 +3790,7 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, } this.tmp.taintedCitationIDs = {}; var sortedItems = []; + var rerunAkeys = {}; for (i = 0, ilen = citation.citationItems.length; i < ilen; i += 1) { item = {}; for (key in citation.citationItems[i]) { @@ -3877,9 +3967,34 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, oldvalue["near-note"] = item[1]["near-note"]; item[1]["first-reference-note-number"] = 0; item[1]["near-note"] = false; + if (this.registry.citationreg.citationsByItemId[myid]) { + if (this.opt.xclass === 'note' && this.opt.has_disambiguate) { + var oldCount = this.registry.registry[myid]["citation-count"] + var newCount = this.registry.citationreg.citationsByItemId[myid].length; + this.registry.registry[myid]["citation-count"] = this.registry.citationreg.citationsByItemId[myid].length; + if ("number" === typeof oldCount) { + var oldCountCheck = (oldCount < 2); + var newCountCheck = (newCount < 2); + if (oldCountCheck !== newCountCheck) { + for (var l=0,llen=this.registry.citationreg.citationsByItemId[myid].length;l -1) { delimiter = delimiter.slice(0, 1); } - var mystk = [ - { - suffix: "", - delimiter: delimiter, - blob: fakeblob, - lastNode: true - } - ]; var use_layout_suffix = suffix; - for (pos = 0, len = myblobs.length; pos < len; pos += 1) { - CSL.Output.Queue.purgeEmptyBlobs(this.output.queue, true); + for (var i=0,ilen=this.output.queue.length;i -1 - && this.tmp.last_chr === use_layout_suffix.slice(0, 1)) { - use_layout_suffix = use_layout_suffix.slice(1); - } this.output.nestedBraces = false; - if (!(this.opt.development_extensions.apply_citation_wrapper - && this.sys.wrapCitationEntry - && !this.tmp.just_looking - && this.tmp.area === "citation")) { - result = txt_esc(this.citation.opt.layout_prefix) + result + txt_esc(use_layout_suffix); - } if (!this.tmp.suppress_decorations) { len = this.citation.opt.layout_decorations.length; for (pos = 0; pos < len; pos += 1) { @@ -4774,8 +4921,15 @@ CSL.getBibliographyEntries = function (bibsection) { } topblobs[0].strings.prefix = this.bibliography.opt.layout_prefix + topblobs[0].strings.prefix; } - CSL.Output.Queue.purgeEmptyBlobs(this.output.queue); - CSL.Output.Queue.adjustPunctuation(this, this.output.queue); + for (var j=0,jlen=this.output.queue.length;j]+>/g, "").replace(/["'\u201d\u2019]/g,"").replace(/\s+$/, "").replace(/^[.\s]+/, ""); - if (prefix.match(CSL.ENDSWITH_ROMANESQUE_REGEXP)) { + var test_prefix = item.prefix.replace(/<[^>]+>/g, "").replace(/["'\u201d\u2019]/g,"").replace(/\s+$/, "").replace(/^[.\s]+/, ""); + if (test_prefix.match(CSL.ENDSWITH_ROMANESQUE_REGEXP)) { + sp = " "; + } else if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(test_prefix.slice(-1))) { sp = " "; } var ignorePredecessor = false; - if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(prefix.slice(-1)) > -1 - && prefix.slice(0, 1) != prefix.slice(0, 1).toLowerCase()) { + if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(test_prefix.slice(-1)) > -1 + && test_prefix.slice(0, 1) != test_prefix.slice(0, 1).toLowerCase()) { state.tmp.term_predecessor = false; ignorePredecessor = true; } @@ -6335,7 +6494,8 @@ CSL.Node.layout = { var sp; if (item && item.suffix) { sp = ""; - if (item.suffix.match(CSL.STARTSWITH_ROMANESQUE_REGEXP)) { + if (item.suffix.match(CSL.STARTSWITH_ROMANESQUE_REGEXP) + || ['[','('].indexOf(item.suffix.slice(0,1)) > -1) { sp = " "; } state.output.append((sp + item.suffix), this); @@ -6968,6 +7128,9 @@ CSL.NameOutput.prototype._join = function (blobs, delimiter, single, multiple, t if (!blobs.length) { return false; } else if (single && blobs.length === 2) { + if (single) { + single = new CSL.Blob(single.blobs,single); + } blobs = [blobs[0], single, blobs[1]]; } else { var delimiter_offset; @@ -6982,8 +7145,12 @@ CSL.NameOutput.prototype._join = function (blobs, delimiter, single, multiple, t if (blobs.length > 1) { var blob = blobs.pop(); if (multiple) { + multiple = new CSL.Blob(multiple.blobs,multiple); blobs.push(multiple); } else { + if (single) { + single = new CSL.Blob(single.blobs,single); + } blobs.push(single); } blobs.push(blob); @@ -8262,7 +8429,7 @@ CSL.evaluateLabel = function (node, state, Item, item) { } plural = state.tmp.shadow_numbers[myterm].plural; } - if (node.decorations && state.opt.development_extensions.csl_reverse_lookup_support) { + if (node.decorations && (state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support)) { node.decorations.reverse(); node.decorations.push(["@showid","true", node.cslid]); node.decorations.reverse(); @@ -8930,7 +9097,7 @@ CSL.Node.text = { var parallel_variable = this.variables[0]; if (parallel_variable === "title" && (form === "short" || Item["title-short"])) { - parallel_variable = "shortTitle"; + parallel_variable = "title-short"; } state.parallel.StartVariable(parallel_variable); state.parallel.AppendToVariable(Item[parallel_variable],parallel_variable); @@ -8945,7 +9112,7 @@ CSL.Node.text = { if (this.variables_real[0] === "container-title") { altvar = "journalAbbreviation"; } else if (this.variables_real[0] === "title") { - altvar = "shortTitle"; + altvar = "title-short"; } } else { abbrevfam = false; @@ -9085,16 +9252,23 @@ CSL.Attributes["@disambiguate"] = function (state, arg) { if (arg === "true") { state.opt.has_disambiguate = true; var func = function (Item, item) { - var ret; state.tmp.disambiguate_maxMax += 1; if (state.tmp.disambig_settings.disambiguate - && state.tmp.disambiguate_count < state.tmp.disambig_settings.disambiguate) { + && state.tmp.disambiguate_count < state.tmp.disambig_settings.disambiguate) { state.tmp.disambiguate_count += 1; return true; } return false; }; this.tests.push(func); + } else if (arg === "check-ambiguity-and-backreference") { + var func = function (Item, item) { + if (state.registry.registry[Item.id].disambig.disambiguate && state.registry.registry[Item.id]["citation-count"] > 1) { + return true; + } + return false; + }; + this.tests.push(func); } }; CSL.Attributes["@is-numeric"] = function (state, arg, joiner) { @@ -9266,11 +9440,27 @@ CSL.Attributes["@variable"] = function (state, arg) { if (variable === "authority" && "string" === typeof Item[variable] && "names" === this.name) { - Item[variable] = [{family:Item[variable],isInstitution:true}]; + var creatorParent = { + family:Item[variable], + isInstitution:true, + multi:{ + _key:{} + } + }; + if (Item.multi && Item.multi._keys && Item.multi._keys[variable]) { + for (var langTag in Item.multi._keys[variable]) { + creatorChild = { + family:Item.multi._keys[variable][langTag], + isInstitution:true + } + creatorParent.multi._key[langTag] = creatorChild; + } + } + Item[variable] = [creatorParent]; } if (this.strings.form === "short" && !Item[variable]) { if (variable === "title") { - variable = "shortTitle"; + variable = "title-short"; } else if (variable === "container-title") { variable = "journalAbbreviation"; } @@ -9938,7 +10128,7 @@ CSL.Attributes["@disambiguate-add-givenname"] = function (state, arg) { } }; CSL.Attributes["@disambiguate-add-year-suffix"] = function (state, arg) { - if (arg === "true") { + if (arg === "true" && state.opt.xclass !== "numeric") { state.opt["disambiguate-add-year-suffix"] = true; } }; @@ -10572,7 +10762,6 @@ CSL.Util.Match = function () { return false; }; }; - this[undefined] = this.any; this.none = function (token, state, tests) { return function (Item, item) { for (var i=0,ilen=tests.length;i -1) { + return null; + } var slot = {primary:false, secondary:false, tertiary:false}; if (state.tmp.area.slice(-5) === "_sort") { slot.primary = 'locale-sort'; @@ -11042,7 +11238,7 @@ CSL.Blob = function (str, token, levelname) { CSL.Blob.prototype.push = function (blob) { if ("string" === typeof this.blobs) { throw "Attempt to push blob onto string object"; - } else { + } else if (false !== blob) { blob.alldecor = blob.alldecor.concat(this.alldecor); this.blobs.push(blob); } @@ -11649,7 +11845,7 @@ CSL.Util.substituteStart = function (state, target) { } }; this.execs.push(func); - if (this.decorations && state.opt.development_extensions.csl_reverse_lookup_support) { + if (this.decorations && (state.opt.development_extensions.csl_reverse_lookup_support || state.sys.csl_reverse_lookup_support)) { this.decorations.reverse(); this.decorations.push(["@showid","true", this.cslid]); this.decorations.reverse(); @@ -11713,9 +11909,70 @@ CSL.Util.substituteStart = function (state, target) { if_start.test = state.fun.match.any(this, state, if_start.tests); target.push(if_start); } + if (state.sys.variableWrapper + && this.variables_real + && this.variables_real.length) { + func = function (state, Item, item) { + if (!state.tmp.just_looking && !state.tmp.suppress_decorations) { + variable_entry = new CSL.Token("text", CSL.START); + variable_entry.decorations = [["@showid", "true"]]; + state.output.startTag("variable_entry", variable_entry); + var position = null; + if (item) { + position = item.position; + } + if (!position) position = 0; + var positionMap = [ + "first", + "subsequent", + "ibid", + "ibid-with-locator" + ] + var noteNumber = 0; + if (item && item.noteIndex) { + noteNumber = item.noteIndex; + } + var firstReferenceNoteNumber = 0; + if (item && item['first-reference-note-number']) { + firstReferenceNoteNumber = item['first-reference-note-number']; + } + var citationNumber = 0; + if (item && item['citation-number']) { + citationNumber = item['citation-number']; + } + var index = 0; + if (item && item.index) { + index = item.index; + } + var params = { + itemData: Item, + variableNames: this.variables, + context: state.tmp.area, + xclass: state.opt.xclass, + position: positionMap[position], + "note-number": noteNumber, + "first-reference-note-number": firstReferenceNoteNumber, + "citation-number": citationNumber, + "index": index, + "mode": state.opt.mode + }; + state.output.current.value().params = params; + } + } + this.execs.push(func); + } }; CSL.Util.substituteEnd = function (state, target) { var func, bib_first_end, bib_other, if_end, choose_end, toplevel, hasval, author_substitute, str; + if (state.sys.variableWrapper + && (this.hasVariable || (this.variables_real && this.variables_real.length))) { + func = function (state,Item) { + if (!state.tmp.just_looking && !state.tmp.suppress_decorations) { + state.output.endTag("variable_entry"); + } + } + this.execs.push(func); + } func = function (state, Item) { for (var i = 0, ilen = this.decorations.length; i < ilen; i += 1) { if ("@strip-periods" === this.decorations[i][0] && "true" === this.decorations[i][1]) { @@ -11776,8 +12033,8 @@ CSL.Util.substituteEnd = function (state, target) { for (i = 0, ilen = state.tmp.name_node.children.length; i < ilen; i += 1) { var name = state.tmp.rendered_name[i]; if (dosub - && state.tmp.last_rendered_name && state.tmp.last_rendered_name.length > i - 1 - && state.tmp.last_rendered_name[i] === name) { + && state.tmp.last_rendered_name && state.tmp.last_rendered_name.length > (i - 1) + && name && !name.localeCompare(state.tmp.last_rendered_name[i])) { str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]); state.tmp.name_node.children[i].blobs = [str]; if ("partial-first" === subrule) { @@ -11792,7 +12049,7 @@ CSL.Util.substituteEnd = function (state, target) { } else if ("complete-each" === subrule) { var rendered_name = state.tmp.rendered_name.join(","); if (rendered_name) { - if (rendered_name === state.tmp.last_rendered_name) { + if (!rendered_name.localeCompare(state.tmp.last_rendered_name)) { for (i = 0, ilen = state.tmp.name_node.children.length; i < ilen; i += 1) { str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]); state.tmp.name_node.children[i].blobs = [str]; @@ -11803,7 +12060,7 @@ CSL.Util.substituteEnd = function (state, target) { } else { var rendered_name = state.tmp.rendered_name.join(","); if (rendered_name) { - if (rendered_name === state.tmp.last_rendered_name) { + if (!rendered_name.localeCompare(state.tmp.last_rendered_name)) { str = new CSL.Blob(state[state.tmp.area].opt["subsequent-author-substitute"]); if (state.tmp.label_blob) { state.tmp.name_node.top.blobs = [str,state.tmp.label_blob]; @@ -12152,9 +12409,11 @@ CSL.Util.PageRangeMangler.getFunction = function (state, rangeType) { ret = ret.replace(/([^\\])\-/g, "$1"+state.getTerm(rangeType + "-range-delimiter")); return ret; }; - listify = function (str, hyphens) { + listify = function (str) { var m, lst, ret; - str = str.replace(/([^\\])\u2013/g, "$1-").replace(/\s+\u2013\s+/g, " - "); + var hyphens = "\\s+\\-\\s+"; + var delimRex = new RegExp("([^\\\\])[" + range_delimiter + "\\u2013]", "g"); + str = str.replace(delimRex, "$1 - ").replace(/\s+-\s+/g, " - "); var rexm = new RegExp("([a-zA-Z]*[0-9]+" + hyphens + "[a-zA-Z]*[0-9]+)", "g"); var rexlst = new RegExp("[a-zA-Z]*[0-9]+" + hyphens + "[a-zA-Z]*[0-9]+"); m = str.match(rexm); @@ -12170,9 +12429,9 @@ CSL.Util.PageRangeMangler.getFunction = function (state, rangeType) { } return ret; }; - expand = function (str, hyphens) { + expand = function (str) { str = "" + str; - lst = listify(str, hyphens); + lst = listify(str); len = lst.length; for (pos = 1; pos < len; pos += 2) { m = lst[pos].match(rangerex); @@ -12250,14 +12509,8 @@ CSL.Util.PageRangeMangler.getFunction = function (state, rangeType) { var sniff = function (str, func, minchars, isyear) { var ret; str = "" + str; - var lst; - if (!str.match(/[^\-\u20130-9 ,&]/)) { - lst = expand(str, "-"); - ret = func(lst, minchars, isyear); - } else { - lst = expand(str, "\\s+\\-\\s+"); - ret = func(lst, minchars, isyear); - } + var lst = expand(str); + var ret = func(lst, minchars, isyear); return ret; } if (!state.opt[rangeType + "-range-format"]) { @@ -12718,7 +12971,7 @@ CSL.Output.Formatters.title = function (state, string) { } for (var i=0,ilen=lst.length;i" + str + "\n "; }, "@showid/true": function (state, str, cslid) { - return "" + str + ""; + if (!state.tmp.just_looking && ! state.tmp.suppress_decorations) { + if (cslid) { + return "" + str + ""; + } else if ("string" === typeof str) { + var prePunct = ""; + if (str) { + var m = str.match(CSL.VARIABLE_WRAPPER_PREPUNCT_REX); + prePunct = m[1]; + str = m[2]; + } + var postPunct = ""; + if (str && CSL.SWAPPING_PUNCTUATION.indexOf(str.slice(-1)) > -1) { + postPunct = str.slice(-1); + str = str.slice(0,-1); + } + return state.sys.variableWrapper(this.params, prePunct, str, postPunct); + } else { + return str; + } + } else { + return str; + } }, "@URL/true": function (state, str) { return "" + str + ""; @@ -12932,6 +13206,9 @@ CSL.Output.Formats.prototype.text = { "@display/indent": function (state, str) { return "\n "+str; }, + "@showid/true": function (state, str, cslid) { + return str; + }, "@URL/true": function (state, str) { return str; }, @@ -13004,6 +13281,24 @@ CSL.Output.Formats.prototype.rtf = { "@display/indent": function (state, str) { return "\n\\tab "+str; }, + "@showid/true": function (state, str, cslid) { + if (!state.tmp.just_looking && ! state.tmp.suppress_decorations) { + var prePunct = ""; + if (str) { + var m = str.match(CSL.VARIABLE_WRAPPER_PREPUNCT_REX); + prePunct = m[1]; + str = m[2]; + } + var postPunct = ""; + if (str && CSL.SWAPPING_PUNCTUATION.indexOf(str.slice(-1)) > -1) { + postPunct = str.slice(-1); + str = str.slice(0,-1); + } + return state.sys.variableWrapper(this.params, prePunct, str, postPunct); + } else { + return str; + } + }, "@URL/true": function (state, str) { return str; }, @@ -13181,6 +13476,9 @@ CSL.Registry.prototype.doinserts = function (mylist) { "ref": Item }; this.registry[item] = newitem; + if (this.citationreg.citationsByItemId && this.citationreg.citationsByItemId[item]) { + this.registry[item]["first-reference-note-number"] = this.citationreg.citationsByItemId[item][0].properties.noteIndex; + } abase = CSL.getAmbigConfig.call(this.state); this.registerAmbigToken(akey, item, abase); this.touched[item] = true; @@ -13393,9 +13691,9 @@ CSL.Registry.NameReg = function (state) { set_keys = function (state, itemid, nameobj) { pkey = strip_periods(nameobj.family); skey = strip_periods(nameobj.given); - var m = skey.match(/,\!* [^,]$/); + var m = skey.match(/[,\!]* ([^,]+)$/); if (m && m[1] === m[1].toLowerCase()) { - skey = skey.replace(/,\!* [^,]$/, ""); + skey = skey.replace(/[,\!]* [^,]+$/, ""); } ikey = CSL.Util.Names.initializeWith(state, skey, "%s"); if (state.citation.opt["givenname-disambiguation-rule"] === "by-cite") { @@ -13644,7 +13942,7 @@ CSL.Disambiguation.prototype.runDisambig = function () { CSL.Disambiguation.prototype.scanItems = function (list) { var pos, len, Item, otherItem, ItemCite, ignore, base; this.Item = list[1][0]; - this.ItemCite = CSL.getAmbiguousCite.call(this.state, this.Item, this.base); + this.ItemCite = CSL.getAmbiguousCite.call(this.state, this.Item, this.base, true); this.scanlist = list[1]; this.partners = []; this.partners.push(this.Item); @@ -13652,7 +13950,7 @@ CSL.Disambiguation.prototype.scanItems = function (list) { var clashes = 0; for (pos = 1, len = list[1].length; pos < len; pos += 1) { otherItem = list[1][pos]; - var otherItemCite = CSL.getAmbiguousCite.call(this.state, otherItem, this.base); + var otherItemCite = CSL.getAmbiguousCite.call(this.state, otherItem, this.base, true); if (this.ItemCite === otherItemCite) { clashes += 1; this.partners.push(otherItem); @@ -13710,7 +14008,11 @@ CSL.Disambiguation.prototype.disNames = function (ismax) { }; CSL.Disambiguation.prototype.disExtraText = function () { var pos, len, mybase; - if (!this.base.disambiguate || this.state.tmp.disambiguate_count !== this.state.tmp.disambiguate_maxMax) { + var done = false; + if (this.clashes[1] === 0 && this.nonpartners.length < 2) { + done = true; + } + if (!done && (!this.base.disambiguate || this.state.tmp.disambiguate_count !== this.state.tmp.disambiguate_maxMax)) { this.modeindex = 0; this.base.disambiguate = this.state.tmp.disambiguate_count; this.betterbase.disambiguate = this.state.tmp.disambiguate_count; @@ -13723,8 +14025,8 @@ CSL.Disambiguation.prototype.disExtraText = function () { } else { this.disNames(); } - } else if (this.state.tmp.disambiguate_count === this.state.tmp.disambiguate_maxMax) { - if (this.modeindex === this.modes.length - 1) { + } else if (done || this.state.tmp.disambiguate_count === this.state.tmp.disambiguate_maxMax) { + if (done || this.modeindex === this.modes.length - 1) { var base = this.lists[this.listpos][0]; for (var i = 0, ilen = this.lists[this.listpos][1].length; i < ilen; i += 1) { this.state.tmp.taintedItemIDs[this.lists[this.listpos][1][i].id] = true;