/* * Copyright (c) 2009 and 2010 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: * * http://bitbucket.org/fbennett/citeproc-js/src/tip/LICENSE. * * The License is based on the Mozilla Public License Version 1.1 but * Sections 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 ./std 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 and 2010 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.” */ var zotero = {}; zotero.Debug = function(s, level){ return; console.log(s); } var Encoder = { // When encoding do we convert characters into html or numerical entities EncodeType : "entity", // entity OR numerical isEmpty : function(val){ if(val){ //replaced by fcheslack so whitespace separators are not stripped from CSL //return ((val===null) || val.length==0 || /^\s+$/.test(val)); return ((val===null) || val.length==0); }else{ return true; } }, // Convert HTML entities into numerical entities HTML2Numerical : function(s){ var arr1 = new Array(' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','à','á','â','ã','Ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','Ö','×','ø','ù','ú','û','Ü','ý','þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','Ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','œ','œ','š','š','ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','†','‰','‹','›','€','ƒ','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','σ','τ','υ','φ','χ','ψ','ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','′','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','←','↑','→','↓','↔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','⟨','⟩','◊','♠','♣','♥','♦'); var arr2 = new Array(' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','×','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','Œ','œ','Š','š','Ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','‡','‰','‹','›','€','ƒ','Α','Β','Γ','Δ','Ε','Ζ','Η','Θ','Ι','Κ','Λ','Μ','Ν','Ξ','Ο','Π','Ρ','Σ','Τ','Υ','Φ','Χ','Ψ','Ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','″','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','⇐','⇑','⇒','⇓','⇔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','〈','〉','◊','♠','♣','♥','♦'); return this.swapArrayVals(s,arr1,arr2); }, // Convert Numerical entities into HTML entities NumericalToHTML : function(s){ var arr1 = new Array(' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','×','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','Œ','œ','Š','š','Ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','‡','‰','‹','›','€','ƒ','Α','Β','Γ','Δ','Ε','Ζ','Η','Θ','Ι','Κ','Λ','Μ','Ν','Ξ','Ο','Π','Ρ','Σ','Τ','Υ','Φ','Χ','Ψ','Ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','″','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','⇐','⇑','⇒','⇓','⇔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','〈','〉','◊','♠','♣','♥','♦'); var arr2 = new Array(' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','à','á','â','ã','Ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','Ö','×','ø','ù','ú','û','Ü','ý','þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','Ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','œ','œ','š','š','ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','†','‰','‹','›','€','ƒ','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','σ','τ','υ','φ','χ','ψ','ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','′','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','←','↑','→','↓','↔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','⟨','⟩','◊','♠','♣','♥','♦'); return this.swapArrayVals(s,arr1,arr2); }, // Numerically encodes all unicode characters numEncode : function(s){ if(this.isEmpty(s)) return ""; var e = ""; for (var i = 0; i < s.length; i++) { var c = s.charAt(i); if (c < " " || c > "~") { c = "&#" + c.charCodeAt() + ";"; } e += c; } return e; }, // HTML Decode numerical and HTML entities back to original values htmlDecode : function(s){ var c,m,d = s; if(this.isEmpty(d)) return ""; // convert HTML entites back to numerical entites first d = this.HTML2Numerical(d); // look for numerical entities " arr=d.match(/&#[0-9]{1,5};/g); // if no matches found in string then skip if(arr!=null){ for(var x=0;x= -32768 && c <= 65535){ // decode every single match within string d = d.replace(m, String.fromCharCode(c)); }else{ d = d.replace(m, ""); //invalid so replace with nada } } } return d; }, // encode an input string into either numerical or HTML entities htmlEncode : function(s,dbl){ if(this.isEmpty(s)) return ""; // do we allow double encoding? E.g will & be turned into &amp; dbl = dbl || false; //default to prevent double encoding // if allowing double encoding we do ampersands first if(dbl){ if(this.EncodeType=="numerical"){ s = s.replace(/&/g, "&"); }else{ s = s.replace(/&/g, "&"); } } // convert the xss chars to numerical entities ' " < > s = this.XSSEncode(s,false); if(this.EncodeType=="numerical" || !dbl){ // Now call function that will convert any HTML entities to numerical codes s = this.HTML2Numerical(s); } // Now encode all chars above 127 e.g unicode s = this.numEncode(s); // now we know anything that needs to be encoded has been converted to numerical entities we // can encode any ampersands & that are not part of encoded entities // to handle the fact that I need to do a negative check and handle multiple ampersands &&& // I am going to use a placeholder // if we don't want double encoded entities we ignore the & in existing entities if(!dbl){ s = s.replace(/&#/g,"##AMPHASH##"); if(this.EncodeType=="numerical"){ s = s.replace(/&/g, "&"); }else{ s = s.replace(/&/g, "&"); } s = s.replace(/##AMPHASH##/g,"&#"); } // replace any malformed entities s = s.replace(/&#\d*([^\d;]|$)/g, "$1"); if(!dbl){ // safety check to correct any double encoded & s = this.correctEncoding(s); } // now do we need to convert our numerical encoded string into entities if(this.EncodeType=="entity"){ s = this.NumericalToHTML(s); } return s; }, // Encodes the basic 4 characters used to malform HTML in XSS hacks XSSEncode : function(s,en){ if(!this.isEmpty(s)){ en = en || true; // do we convert to numerical or html entity? if(en){ s = s.replace(/\'/g,"'"); //no HTML equivalent as &apos is not cross browser supported s = s.replace(/\"/g,"""); s = s.replace(//g,">"); }else{ s = s.replace(/\'/g,"'"); //no HTML equivalent as &apos is not cross browser supported s = s.replace(/\"/g,"""); s = s.replace(//g,">"); } return s; }else{ return ""; } }, // returns true if a string contains html or numerical encoded entities hasEncoded : function(s){ if(/&#[0-9]{1,5};/g.test(s)){ return true; }else if(/&[A-Z]{2,6};/gi.test(s)){ return true; }else{ return false; } }, // will remove any unicode characters stripUnicode : function(s){ return s.replace(/[^\x20-\x7E]/g,""); }, // corrects any double encoded & entities e.g &amp; correctEncoding : function(s){ return s.replace(/(&)(amp;)+/,"$1"); }, // Function to loop through an array swaping each item with the value from another array e.g swap HTML entities with Numericals swapArrayVals : function(s,arr1,arr2){ if(this.isEmpty(s)) return ""; var re; if(arr1 && arr2){ //ShowDebug("in swapArrayVals arr1.length = " + arr1.length + " arr2.length = " + arr2.length) // array lengths must match if(arr1.length == arr2.length){ for(var x=0,i=arr1.length;x 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: } }; this.parser = new DOMParser(); // This seems horribly tormented, but there might be a reason for it. // Perhaps this was the only way I found to get namespacing to work ... ? var str = ""; 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_NODEJS_JSDOM.prototype.clean = function (xml) { zotero.Debug('CSL_NODEJS.clean', 3); xml = xml.replace(/<\?[^?]+\?>/g, ""); xml = xml.replace(/]+>/g, ""); xml = xml.replace(/^\s+/, ""); xml = xml.replace(/\s+$/, ""); xml = xml.replace(/^\n*/, ""); return xml; }; CSL_NODEJS_JSDOM.prototype.getStyleId = function (myxml) { var text = ""; var node = myxml.getElementsByTagName("id"); if (node && node.length) { node = node.item(0); } if (node) { // W3C conformant browsers text = node.textContent; } return text; }; CSL_NODEJS_JSDOM.prototype.children = function (myxml) { zotero.Debug("children called on: " + myxml, 3); 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_NODEJS_JSDOM.prototype.nodename = function (myxml) { zotero.Debug('CSL_NODEJS.nodename ' + myxml, 3); //zotero.Debug(myxml); var ret = myxml.nodeName; if(ret) ret = ret.toLowerCase(); zotero.Debug("node name = " + ret, 3); return ret; }; CSL_NODEJS_JSDOM.prototype.attributes = function (myxml) { zotero.Debug('CSL_NODEJS.attributes'); 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]; var v = attr.value; //v = v.replace('<', '&60;').replace('>', '&62').replace('"', '&34').replace('&', '&38;'); v = Encoder.htmlDecode(v); ret["@" + attr.name] = v; } } return ret; }; CSL_NODEJS_JSDOM.prototype.content = function (myxml) { zotero.Debug('CSL_NODEJS.content', 3); 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_NODEJS_JSDOM.prototype.namespace = { "xml":"http://www.w3.org/XML/1998/namespace" } CSL_NODEJS_JSDOM.prototype.numberofnodes = function (myxml) { zotero.Debug('CSL_NODEJS.numberofnodes', 3); if (myxml) { zotero.Debug(myxml.length); return myxml.length; } else { zotero.Debug('0'); return 0; } }; CSL_NODEJS_JSDOM.prototype.getAttributeName = function (attr) { zotero.Debug('CSL_NODEJS.getAttributeName', 3); var ret = attr.name; return ret; } CSL_NODEJS_JSDOM.prototype.getAttributeValue = function (myxml,name,namespace) { zotero.Debug('CSL_NODEJS.getAttributeValue', 3); var ret = ""; if (myxml && this.hasAttributes(myxml) && myxml.getAttribute(name)) { ret = myxml.getAttribute(name); } return ret; } CSL_NODEJS_JSDOM.prototype.getNodeValue = function (myxml,name) { zotero.Debug('CSL_NODEJS.getNodeValue : ' + name, 3); 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_NODEJS_JSDOM.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myxml,nodename,partname,attrname,val) { zotero.Debug('CSL_NODEJS.setAttributeOnNodeIdentifiedByNameAttribute', 3); 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_NODEJS_JSDOM.prototype.deleteNodeByNameAttribute = function (myxml,val) { zotero.Debug('CSL_NODEJS.deleteNodeByNameAttribute', 3); 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_NODEJS_JSDOM.prototype.deleteAttribute = function (myxml,attr) { zotero.Debug('CSL_NODEJS.deleteAttribute', 3); myxml.removeAttribute(attr); } CSL_NODEJS_JSDOM.prototype.setAttribute = function (myxml,attr,val) { zotero.Debug('CSL_NODEJS.setAttribute', 3); var attribute; if (!myxml.ownerDocument) { myxml = myxml.firstChild; } attribute = myxml.ownerDocument.createAttribute(attr); zotero.Debug('created attribute:'); //zotero.Debug(attribute); myxml.setAttribute(attr, val); return false; } CSL_NODEJS_JSDOM.prototype.nodeCopy = function (myxml) { zotero.Debug('CSL_NODEJS.nodeCopy', 3); var cloned_node = myxml.cloneNode(true); return cloned_node; } CSL_NODEJS_JSDOM.prototype.getNodesByName = function (myxml,name,nameattrval) { zotero.Debug('CSL_NODEJS.getNodesByName : ' + name + " = " + nameattrval, 3); var ret, nodes, node, pos, len; ret = []; if(typeof myxml.getElementsByTagName == 'undefined'){ return 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_NODEJS_JSDOM.prototype.nodeNameIs = function (myxml,name) { zotero.Debug('CSL_NODEJS.nodeNameIs', 3); if (name == myxml.nodeName.toLowerCase()) { return true; } return false; } CSL_NODEJS_JSDOM.prototype.makeXml = function (myxml) { zotero.Debug('CSL_NODEJS.makeXml', 3); var ret, topnode; if (!myxml) { myxml = ""; } myxml = myxml.replace(/\s*<\?[^>]*\?>\s*\n*/g, ""); myxml = myxml.replace(/ -1 && twovars.indexOf("publisher-place") > -1) { node.setAttribute('has-publisher-and-publisher-place', true); } } } }; CSL_NODEJS_JSDOM.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_NODEJS_JSDOM.prototype.addInstitutionNodes = function(myxml) { zotero.Debug('CSL_NODEJS.addInstitutionNodes'); //zotero.Debug("myxml : " + myxml.nodeName + " : " + myxml.nodeValue); /* 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); } } */ var names, thenames, institution, theinstitution, name, thename, xml, pos, len; var CSL_INSTITUTION_KEYS = [ "font-style", "font-variant", "font-weight", "text-decoration", "text-case" ]; 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); } } } } } } zotero.Debug("done with addInstitutionNodes"); }; CSL_NODEJS_JSDOM.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'); } } }; exports.CSL_NODEJS_JSDOM = CSL_NODEJS_JSDOM;