Commits

Frank Bennett committed c9606c1

Upgrade to version 1.0.372

Comments (0)

Files changed (1)

chrome/content/citeproc.js

  * recipient may use your version of this file under either the CPAL
  * or the [AGPLv3] License.”
  */
-
 if (!Array.indexOf) {
     Array.prototype.indexOf = function (obj) {
         var i, len;
     };
 }
 var CSL = {
-    PROCESSOR_VERSION: "1.0.366",
+    PROCESSOR_VERSION: "1.0.372",
     STATUTE_SUBDIV_GROUPED_REGEX: /((?:^| )(?:art|ch|Ch|subch|p|pp|para|subpara|pt|r|sec|subsec|Sec|sch|tit)\.)/g,
     STATUTE_SUBDIV_PLAIN_REGEX: /(?:(?:^| )(?:art|ch|Ch|subch|p|pp|para|subpara|pt|r|sec|subsec|Sec|sch|tit)\.)/,
     STATUTE_SUBDIV_STRINGS: {
         "publisher":"publishers",
         "authority":"publishers",
         "publisher-place": "places",
-        "event-place": "places"
+        "event-place": "places",
+        "number": "number",
+        "edition":"number",
+        "issue":"number",
+        "volume":"number"
     },
     AbbreviationSegments: function () {
         this["container-title"] = {};
 }
 CSL.TERMINAL_PUNCTUATION_REGEXP = new RegExp("^([" + CSL.TERMINAL_PUNCTUATION.slice(0, -1).join("") + "])(.*)");
 CSL.CLOSURES = new RegExp(".*[\\]\\)]");
-if ("object" === typeof console && "function" === typeof console.log) {
-    CSL.debug = function (str) {
-        console.log("CSL: " + str);
+CSL.debug = function (str) {
+    Zotero.debug("CSL: " + str);
+};
+CSL.error = function (str) {
+    Zotero.debug("CSL error: " + str);
+};
+function DOMParser() {
+	return Components.classes["@mozilla.org/xmlextras/domparser;1"]
+		.createInstance(Components.interfaces.nsIDOMParser);
+};
+if ("undefined" === typeof CSL_IS_IE) {
+    var CSL_IS_IE;
+};
+var CSL_CHROME = function () {
+    if ("undefined" == typeof DOMParser || CSL_IS_IE) {
+        CSL_IS_IE = true;
+        DOMParser = function() {};
+        DOMParser.prototype.parseFromString = function(str, contentType) {
+            if ("undefined" != typeof ActiveXObject) {
+                var xmldata = new ActiveXObject('MSXML.DomDocument');
+                xmldata.async = false;
+                xmldata.loadXML(str);
+                return xmldata;
+            } else if ("undefined" != typeof XMLHttpRequest) {
+                var xmldata = new XMLHttpRequest;
+                if (!contentType) {
+                    contentType = 'text/xml';
+                }
+                xmldata.open('GET', 'data:' + contentType + ';charset=utf-8,' + encodeURIComponent(str), false);
+                if(xmldata.overrideMimeType) {
+                    xmldata.overrideMimeType(contentType);
+                }
+                xmldata.send(null);
+                return xmldata.responseXML;
+            }
+        };
+        this.hasAttributes = function (node) {
+            var ret;
+            if (node.attributes && node.attributes.length) {
+                ret = true;
+            } else {
+                ret = false;
+            }
+            return ret;
+        };
+    } else {
+        this.hasAttributes = function (node) {
+            var ret;
+            if (node.attributes && node.attributes.length) {
+                ret = true;
+            } else {
+                ret = false;
+            }
+            return ret;
+        };
+    }
+    this.importNode = function (doc, srcElement) {
+        if ("undefined" == typeof doc.importNode) {
+            var ret = this._importNode(doc, srcElement, true);
+        } else {
+            var ret = doc.importNode(srcElement, true);
+        }
+        return ret;
     };
-    CSL.error = function (str) {
-        console.log("CSL error: " + str);
+    this._importNode = function(doc, node, allChildren) {
+        switch (node.nodeType) {
+            case 1:
+                var newNode = doc.createElement(node.nodeName);
+                if (node.attributes && node.attributes.length > 0)
+                    for (var i = 0, il = node.attributes.length; i < il;)
+                        newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i++].nodeName));
+                    if (allChildren && node.childNodes && node.childNodes.length > 0)
+                        for (var i = 0, il = node.childNodes.length; i < il;)
+                            newNode.appendChild(this._importNode(doc, node.childNodes[i++], allChildren));
+                return newNode;
+                break;
+            case 3:
+            case 4:
+            case 8:
+        }
     };
-} else {
-    CSL.debug = function () {};
-    CSL.error = function (str) {
-        throw "CSL error: " + str;
-    };
+    this.parser = new DOMParser();
+    var str = "<docco><institution institution-parts=\"long\" delimiter=\", \" substitute-use-first=\"1\" use-last=\"1\"><institution-part name=\"long\"/></institution></docco>";
+    var inst_doc = this.parser.parseFromString(str, "text/xml");
+    var inst_node = inst_doc.getElementsByTagName("institution");
+    this.institution = inst_node.item(0);
+    var inst_part_node = inst_doc.getElementsByTagName("institution-part");
+    this.institutionpart = inst_part_node.item(0);
+    this.ns = "http://purl.org/net/xbiblio/csl";
+};
+CSL_CHROME.prototype.clean = function (xml) {
+    xml = xml.replace(/<\?[^?]+\?>/g, "");
+    xml = xml.replace(/<![^>]+>/g, "");
+    xml = xml.replace(/^\s+/, "");
+    xml = xml.replace(/\s+$/, "");
+    xml = xml.replace(/^\n*/, "");
+    return xml;
+};
+CSL_CHROME.prototype.getStyleId = function (myxml) {
+    var text = "";
+    var node = myxml.getElementsByTagName("id");
+    if (node && node.length) {
+        node = node.item(0);
+    }
+    if (node) {
+        text = node.textContent;
+    }
+    if (!text) {
+        text = node.innerText;
+    }
+    if (!text) {
+        text = node.innerHTML;
+    }
+    return text;
+};
+CSL_CHROME.prototype.children = function (myxml) {
+    var children, pos, len, ret;
+    if (myxml) {
+        ret = [];
+        children = myxml.childNodes;
+        for (pos = 0, len = children.length; pos < len; pos += 1) {
+            if (children[pos].nodeName != "#text") {
+                ret.push(children[pos]);
+            }
+        }
+        return ret;
+    } else {
+        return [];
+    }
+};
+CSL_CHROME.prototype.nodename = function (myxml) {
+    var ret = myxml.nodeName;
+    return ret;
+};
+CSL_CHROME.prototype.attributes = function (myxml) {
+    var ret, attrs, attr, key, xml, pos, len;
+    ret = new Object();
+    if (myxml && this.hasAttributes(myxml)) {
+        attrs = myxml.attributes;
+        for (pos = 0, len=attrs.length; pos < len; pos += 1) {
+            attr = attrs[pos];
+            ret["@" + attr.name] = attr.value;
+        }
+    }
+    return ret;
+};
+CSL_CHROME.prototype.content = function (myxml) {
+    var ret;
+    if ("undefined" != typeof myxml.textContent) {
+        ret = myxml.textContent;
+    } else if ("undefined" != typeof myxml.innerText) {
+        ret = myxml.innerText;
+    } else {
+        ret = myxml.txt;
+    }
+    return ret;
+};
+CSL_CHROME.prototype.namespace = {
+    "xml":"http://www.w3.org/XML/1998/namespace"
 }
+CSL_CHROME.prototype.numberofnodes = function (myxml) {
+    if (myxml) {
+        return myxml.length;
+    } else {
+        return 0;
+    }
+};
+CSL_CHROME.prototype.getAttributeName = function (attr) {
+    var ret = attr.name;
+    return ret;
+}
+CSL_CHROME.prototype.getAttributeValue = function (myxml,name,namespace) {
+    var ret = "";
+    if (myxml && this.hasAttributes(myxml) && myxml.getAttribute(name)) {
+        ret = myxml.getAttribute(name);
+    }
+    return ret;
+}
+CSL_CHROME.prototype.getNodeValue = function (myxml,name) {
+    var ret = "";
+    if (name){
+        var vals = myxml.getElementsByTagName(name);
+        if (vals.length > 0) {
+            if ("undefined" != typeof vals[0].textContent) {
+                ret = vals[0].textContent;
+            } else if ("undefined" != typeof vals[0].innerText) {
+                ret = vals[0].innerText;
+            } else {
+                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;
+        } else {
+            ret = ret.text;
+        }
+    }
+    return ret;
+}
+CSL_CHROME.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myxml,nodename,partname,attrname,val) {
+    var pos, len, xml, nodes, node;
+    if (attrname.slice(0,1) === '@'){
+        attrname = attrname.slice(1);
+    }
+    nodes = myxml.getElementsByTagName(nodename);
+    for (pos = 0, len = nodes.length; pos < len; pos += 1) {
+        node = nodes[pos];
+        if (node.getAttribute("name") != partname) {
+            continue;
+        }
+        node.setAttribute(attrname, val);
+    }
+}
+CSL_CHROME.prototype.deleteNodeByNameAttribute = function (myxml,val) {
+    var pos, len, node, nodes;
+    nodes = myxml.childNodes;
+    for (pos = 0, len = nodes.length; pos < len; pos += 1) {
+        node = nodes[pos];
+        if (!node || node.nodeType == node.TEXT_NODE) {
+            continue;
+        }
+        if (this.hasAttributes(node) && node.getAttribute("name") == val) {
+            myxml.removeChild(nodes[pos]);
+        }
+    }
+}
+CSL_CHROME.prototype.deleteAttribute = function (myxml,attr) {
+    myxml.removeAttribute(attr);
+}
+CSL_CHROME.prototype.setAttribute = function (myxml,attr,val) {
+    if (!myxml.ownerDocument) {
+        myxml = myxml.firstChild;
+    }
+    if (["function", "unknown"].indexOf(typeof myxml.setAttribute) > -1) {
+        myxml.setAttribute(attr, val);
+    }
+    return false;
+}
+CSL_CHROME.prototype.nodeCopy = function (myxml) {
+    var cloned_node = myxml.cloneNode(true);
+    return cloned_node;
+}
+CSL_CHROME.prototype.getNodesByName = function (myxml,name,nameattrval) {
+    var ret, nodes, node, pos, len;
+    ret = [];
+    nodes = myxml.getElementsByTagName(name);
+    for (pos = 0, len = nodes.length; pos < len; pos += 1) {
+        node = nodes.item(pos);
+        if (nameattrval && !(this.hasAttributes(node) && node.getAttribute("name") == nameattrval)) {
+            continue;
+        }
+        ret.push(node);
+    }
+    return ret;
+}
+CSL_CHROME.prototype.nodeNameIs = function (myxml,name) {
+    if (name == myxml.nodeName) {
+        return true;
+    }
+    return false;
+}
+CSL_CHROME.prototype.makeXml = function (myxml) {
+    var ret, topnode;
+    if (!myxml) {
+        myxml = "<docco><bogus/></docco>";
+    }
+    myxml = myxml.replace(/\s*<\?[^>]*\?>\s*\n*/g, "");
+    var nodetree = this.parser.parseFromString(myxml, "application/xml");
+    return nodetree.firstChild;
+};
+CSL_CHROME.prototype.insertChildNodeAfter = function (parent,node,pos,datexml) {
+    var myxml, xml;
+    myxml = this.importNode(node.ownerDocument, datexml);
+    parent.replaceChild(myxml, node);
+     return parent;
+};
+CSL_CHROME.prototype.insertPublisherAndPlace = function(myxml) {
+    var group = myxml.getElementsByTagName("group");
+    for (var i = 0, ilen = group.length; i < ilen; i += 1) {
+        var node = group.item(i);
+        var skippers = [];
+        for (var j = 0, jlen = node.childNodes.length; j < jlen; j += 1) {
+            if (node.childNodes.item(j).nodeType !== 1) {
+                skippers.push(j);
+            }
+        }
+        if (node.childNodes.length - skippers.length === 2) {
+            var twovars = [];
+            for (var j = 0, jlen = 2; j < jlen; j += 1) {
+                if (skippers.indexOf(j) > -1) {
+                    continue;
+                }
+                var child = node.childNodes.item(j);                    
+                var subskippers = [];
+                for (var k = 0, klen = child.childNodes.length; k < klen; k += 1) {
+                    if (child.childNodes.item(k).nodeType !== 1) {
+                        subskippers.push(k);
+                    }
+                }
+                if (child.childNodes.length - subskippers.length === 0) {
+                    twovars.push(child.getAttribute('variable'));
+                    if (child.getAttribute('suffix')
+                        || child.getAttribute('prefix')) {
+                        twovars = [];
+                        break;
+                    }
+                }
+            }
+            if (twovars.indexOf("publisher") > -1 && twovars.indexOf("publisher-place") > -1) {
+                node.setAttribute('has-publisher-and-publisher-place', true);
+            }
+        }
+    }
+};
+CSL_CHROME.prototype.addMissingNameNodes = function(myxml) {
+    var nameslist = myxml.getElementsByTagName("names");
+    for (var i = 0, ilen = nameslist.length; i < ilen; i += 1) {
+        var names = nameslist.item(i);
+        var namelist = names.getElementsByTagName("name");
+        if ((!namelist || namelist.length === 0)
+            && names.parentNode.tagName.toLowerCase() !== "substitute") {
+            var doc = names.ownerDocument;
+            var name = doc.createElement("name");
+            names.appendChild(name);
+        }
+    }
+};
+CSL_CHROME.prototype.addInstitutionNodes = function(myxml) {
+    var names, thenames, institution, theinstitution, name, thename, xml, pos, len;
+    names = myxml.getElementsByTagName("names");
+    for (pos = 0, len = names.length; pos < len; pos += 1) {
+        thenames = names.item(pos);
+        name = thenames.getElementsByTagName("name");
+        if (name.length == 0) {
+            continue;
+        }
+        institution = thenames.getElementsByTagName("institution");
+        if (institution.length == 0) {
+            theinstitution = this.importNode(myxml.ownerDocument, this.institution);
+            theinstitutionpart = theinstitution.getElementsByTagName("institution-part").item(0);
+            thename = name.item(0);
+            thenames.insertBefore(theinstitution, thename.nextSibling);
+            for (var j = 0, jlen = CSL.INSTITUTION_KEYS.length; j < jlen; j += 1) {
+                var attrname = CSL.INSTITUTION_KEYS[j];
+                var attrval = thename.getAttribute(attrname);
+                if (attrval) {
+                    theinstitutionpart.setAttribute(attrname, attrval);
+                }
+            }
+            var nameparts = thename.getElementsByTagName("name-part");
+            for (var j = 0, jlen = nameparts.length; j < jlen; j += 1) {
+                if ('family' === nameparts[j].getAttribute('name')) {
+                    for (var k = 0, klen = CSL.INSTITUTION_KEYS.length; k < klen; k += 1) {
+                        var attrname = CSL.INSTITUTION_KEYS[k];
+                        var attrval = nameparts[j].getAttribute(attrname);
+                        if (attrval) {
+                            theinstitutionpart.setAttribute(attrname, attrval);
+                        }
+                    }
+                }
+            }
+        }
+    }
+};
+CSL_CHROME.prototype.flagDateMacros = function(myxml) {
+    var pos, len, thenode, thedate;
+    nodes = myxml.getElementsByTagName("macro");
+    for (pos = 0, len = nodes.length; pos < len; pos += 1) {
+        thenode = nodes.item(pos);
+        thedate = thenode.getElementsByTagName("date");
+        if (thedate.length) {
+            thenode.setAttribute('macro-has-date', 'true');
+        }
+    }
+};
 CSL.getSortCompare = function () {
     var strcmp;
     try {
                     continue;
                 }
                 if (attributes.hasOwnProperty(key)) {
-                    try {
-                        CSL.Attributes[key].call(token, state, "" + attributes[key]);
-                    } catch (e) {
-                        if (e === "TypeError: Cannot call method \"call\" of undefined") {
-                            throw "Unknown attribute \"" + key + "\" in node \"" + name + "\" while processing CSL file";
-                        } else {
+                    if (CSL.Attributes[key]) {
+                        try {
+                            CSL.Attributes[key].call(token, state, "" + attributes[key]);
+                        } catch (e) {
+                            CSL.error(e);
                             throw "CSL processor error, " + key + " attribute: " + e;
                         }
+                    } else {
+                        CSL.debug("warning: undefined attribute \""+key+"\" in style");
                     }
                 }
             }
     }
 };
 CSL.Engine.prototype.setLangPrefsForCiteAffixes = function (affixList) {
-    if (affixList && affixList.length === 30) {
+    if (affixList && affixList.length === 40) {
         var affixes = this.opt.citeAffixes;
         var count = 0;
         var settings = ["persons", "institutions", "titles", "publishers", "places"];
-        var forms = ["orig", "translit", "translat"];
+        var forms = ["translit", "orig", "translit", "translat"];
+        var value;
         for (var i = 0, ilen = settings.length; i < ilen; i += 1) {
             for (var j = 0, jlen = forms.length; j < jlen; j += 1) {
-                var value = affixList[count];
-                if (!value) {
-                    value = "";
-                }
-                affixes[settings[i]]["locale-" + forms[j]].prefix = value;
-                count += 1;
-                var value = affixList[count];
-                if (!value) {
-                    value = "";
-                }
-                affixes[settings[i]]["locale-" + forms[j]].suffix = value;
-                count += 1;
+                value = "";
+                if ((count % 8) === 4) {
+                    if (!affixes[settings[i]]["locale-"+forms[j]].prefix
+                        && !affixes[settings[i]]["locale-"+forms[j]].suffix) {
+                        value = affixList[count] ? affixList[count] : "";
+                        affixes[settings[i]]["locale-" + forms[j]].prefix = value;
+                        value = affixList[count] ? affixList[count + 1] : "";
+                        affixes[settings[i]]["locale-" + forms[j]].suffix = value;
+                    }
+                } else {
+                    value = affixList[count] ? affixList[count] : "";
+                    affixes[settings[i]]["locale-" + forms[j]].prefix = value;
+                    value = affixList[count] ? affixList[count + 1] : "";
+                    affixes[settings[i]]["locale-" + forms[j]].suffix = value;
+                }
+                count += 2;
             }
         }
         this.opt.citeAffixes = affixes;
     this.development_extensions.wrap_url_and_doi = false;
     this.development_extensions.allow_force_lowercase = false;
     this.development_extensions.handle_parallel_articles = false;
+    this.development_extensions.thin_non_breaking_space_html_hack = false;
     this.nodenames = [];
     this.gender = {};
-	this['cite-lang-prefs'] = {
-		persons:['orig'],
-		institutions:['orig'],
-		titles:['orig','translat'],
-		publishers:['orig'],
-		places:['orig']
-	};
+    this['cite-lang-prefs'] = {
+        persons:['orig'],
+        institutions:['orig'],
+        titles:['orig','translat'],
+        publishers:['orig'],
+        places:['orig'],
+        number:['translat']
+    };
 };
 CSL.Engine.Tmp = function () {
     this.names_max = new CSL.Stack();
             if (this.strings.label_form_override) {
                 form = this.strings.label_form_override;
             }
-            if (this.text_case_normal) {
-                if (value) {
-                    value = value.replace("\\", "");
-                    state.output.append(value, this);
-                }
-            } else if (varname === "locator"
+            if (varname === "locator"
                        && item.locator) {
                 item.locator = item.locator.replace(/([^\\])\s*-\s*/, "$1" + state.getTerm("page-range-delimiter"));
                 m = item.locator.match(CSL.STATUTE_SUBDIV_GROUPED_REGEX);
     var debug = false, abbreviations, token, fieldname, abbrev_family, opt;
     this.abbrevs = {};
     this.abbrevs["default"] = new state.sys.AbbreviationSegments();
+    this.getTextSubField = getTextSubField;
     function abbreviate(state, Item, altvar, basevalue, myabbrev_family, use_field) {
         var value;
         if (!myabbrev_family) {
             return basevalue;
         }
         var variable = myabbrev_family;
+        if (CSL.NUMERIC_VARIABLES.indexOf(myabbrev_family) > -1) {
+            myabbrev_family = "number";
+        }
         if (["publisher-place", "event-place", "jurisdiction"].indexOf(myabbrev_family) > -1) {
             myabbrev_family = "place";
         }
             }
             var res = getTextSubField(Item, variables[0], slot.primary, true);
             primary = res.name;
+            var primaryUsedOrig = res.usedOrig;
             if (publisherCheck(this, Item, primary, myabbrev_family)) {
                 return null;
             }
                 secondary = CSL.demoteNoiseWords(state, secondary);
                 tertiary = CSL.demoteNoiseWords(state, tertiary);
             }
+            var primary_tok = CSL.Util.cloneToken(this);
+            var primaryPrefix;
+            if (slot.primary === "locale-translit") {
+                primaryPrefix = state.opt.citeAffixes[langPrefs][slot.primary].prefix;
+            }                
+            if (primaryPrefix === "<i>" && !primaryUsedOrig) {
+                var hasItalic = false;
+                for (var i = 0, ilen = primary_tok.decorations.length; i < ilen; i += 1) {
+                    if (primary_tok.decorations[i][0] === "@font-style"
+                        && primary_tok.decorations[i][1] === "italic") {
+                        hasItalic = true;
+                    }
+                }
+                if (!hasItalic) {
+                    primary_tok.decorations.push(["@font-style", "italic"])
+                }
+            }
             if (secondary || tertiary) {
                 state.output.openLevel("empty");
-                primary_tok = CSL.Util.cloneToken(this);
                 primary_tok.strings.suffix = "";
                 state.output.append(primary, primary_tok);
                 if (secondary) {
                 }
 				state.output.closeLevel();
             } else {
-                state.output.append(primary, this);
+                state.output.append(primary, primary_tok);
             }
             return null;
         };
     if (!ItemObject) {
         return;
     }
-    num = ItemObject[variable];
+    var languageRole = CSL.LangPrefsMap[variable];
+    if (languageRole) {
+        var localeType = this.opt["cite-lang-prefs"][languageRole][0];
+        num = this.transform.getTextSubField(ItemObject, variable, "locale-"+localeType, true);
+        num = num.name;
+    } else {
+        num = ItemObject[variable];
+    }
+    if (num && this.sys.getAbbreviation) {
+        num = ("" + num).replace(/^\"/, "").replace(/\"$/, "");
+        var jurisdiction = this.transform.loadAbbreviation(ItemObject.jurisdiction, "number", num);
+        if (this.transform.abbrevs[jurisdiction].number[num]) {
+            num = this.transform.abbrevs[jurisdiction].number[num];
+        } else {
+            if ("undefined" !== typeof this.transform.abbrevs[jurisdiction].number[num]) {
+                delete this.transform.abbrevs[jurisdiction].number[num];
+            }
+        }
+    }
     if ("undefined" !== typeof num) {
         if ("number" === typeof num) {
             num = "" + num;
                             numeric = false;
                         }
                     }
-                    if (i === elements.length - 1) {
-                        if ((elements.length > 1 || subelements.length > 1)) {
-                            var matchterm = this.getTerm(variable, "long");
-                            if (matchterm && !subelements[subelements.length - 1].match(/[0-9]/)) {
-                                matchterm = matchterm.replace(".", "").toLowerCase().split(/\s+/)[0];
-                                if (subelements[subelements.length - 1].slice(0, matchterm.length).toLowerCase() === matchterm) {
-                                    elements[i] = subelements.slice(0, -1).join(" ");
-                                    numeric = true;
-                                }
-                            }
-                        }
-                    }
                     if (elements[i].match(/^[1-9][0-9]*$/)) {
                         elements[i] = parseInt(elements[i], 10);
                         node.gender = this.opt["noun-genders"][variable];
                         this.tmp.shadow_numbers[variable].values.push(["NumericBlob", elements[i], node]);
                     } else {
                         var str = elements[i];
-                        if (this.sys.getAbbreviation) {
-                            var jurisdiction = this.transform.loadAbbreviation(ItemObject.jurisdiction, "number", elements[i]);
-                            if (this.transform.abbrevs[jurisdiction].number[str]) {
-                                str = this.transform.abbrevs[jurisdiction].number[str];
-                            }
-                        }
                         this.tmp.shadow_numbers[variable].values.push(["Blob", str, node]);
                     }
                 }
         } else {
              this.tmp.shadow_numbers[variable].numeric = numeric;
         }
+        if (!this.tmp.shadow_numbers[variable].numeric) {
+            this.transform.loadAbbreviation(ItemObject.jurisdiction, "number", num);
+        }
         if (count > 1) {
             this.tmp.shadow_numbers[variable].plural = 1;
         }
 CSL.Output.Formatters = {};
 CSL.getSafeEscape = function(state) {
     if (["bibliography", "citation"].indexOf(state.tmp.area) > -1) {
-        return CSL.Output.Formats[state.opt.mode].text_escape;
+        var callbacks = [];
+        if (state.opt.development_extensions.thin_non_breaking_space_html_hack && state.opt.mode === "html") {
+            callbacks.push(function (txt) {
+                return txt.replace(/\u202f/g, '<span style="white-space:nowrap">&thinsp;</span>');
+            });
+        }
+        if (state.opt.force_parens_char) {
+            callbacks.push(function (txt) {
+                return txt.replace(/([\(\<\[])/g, state.opt.force_parens_char + "$1")
+                    .replace(/([\)\>\]])/g, "$1" + state.opt.force_parens_char);
+            });
+        }
+        if (callbacks.length) {
+            return function (txt) {
+                for (var i = 0, ilen = callbacks.length; i < ilen; i += 1) {
+                    txt = callbacks[i](txt);
+                }
+                return CSL.Output.Formats[state.opt.mode].text_escape(txt);
+            }
+        } else {
+            return CSL.Output.Formats[state.opt.mode].text_escape;
+        }
     } else {
         return function (txt) { return txt; };
     }