diff --git a/package.json b/package.json index 1dfa944..c03fa43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "citeproc", - "version": "1.0.4", + "version": "1.0.6", "description": "A wrapper for citeproc-js.", "main": "citeproc-wrapper.js", "repository": { diff --git a/src/citeproc.js b/src/citeproc.js index 08a8008..bafa8d1 100644 --- a/src/citeproc.js +++ b/src/citeproc.js @@ -1,73 +1,3 @@ -/* - * 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 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) { var i, len; @@ -80,7 +10,7 @@ if (!Array.indexOf) { }; } var CSL = { - PROCESSOR_VERSION: "1.1.7", + PROCESSOR_VERSION: "1.1.9", CONDITION_LEVEL_TOP: 1, CONDITION_LEVEL_BOTTOM: 2, PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/, @@ -162,10 +92,10 @@ var CSL = { "subpara": "subparagraph", "pt": "part", "r": "rule", - "sec": "section", - "subsec": "subsection", + "sec": "section", + "subsec": "subsection", "Sec": "Section", - "sv": "sub-verbo", + "sv": "sub-verbo", "sch": "schedule", "tit": "title", "vrs": "verse", @@ -189,8 +119,8 @@ var CSL = { "bill": true, "hearing": true, "gazette": true, - "regulation": true, - "treaty": true + "report": true, + "regulation": true }, NestedBraces: [ ["(", "["], @@ -637,7 +567,7 @@ var CSL = { }; if (typeof require !== "undefined" && typeof module !== 'undefined' && "exports" in module) { var CSL_IS_NODEJS = true; - var CSL_JSON = require("./csl_json.js").CSL_JSON; + var CSL_NODEJS = require("./csl_nodejs_jsdom").CSL_NODEJS_JSDOM; exports.CSL = CSL; } CSL.TERMINAL_PUNCTUATION_REGEXP = new RegExp("^([" + CSL.TERMINAL_PUNCTUATION.slice(0, -1).join("") + "])(.*)"); @@ -656,7 +586,9 @@ if ("object" === typeof console && "function" === typeof console.log) { }; } var XML_PARSING; -if ("undefined" !== typeof CSL_E4X) { +if ("undefined" !== typeof CSL_IS_NODEJS) { + XML_PARSING = CSL_NODEJS; +} else if ("undefined" !== typeof CSL_E4X) { XML_PARSING = CSL_E4X; } else if ("undefined" !== typeof CSL_JSON) { XML_PARSING = CSL_JSON; @@ -1105,7 +1037,7 @@ CSL.DateParser = function () { }; this.parse = function (txt) { var slash, dash, lst, l, m, number, note, thedate, slashcount, range_delim, date_delim, ret, delim_pos, delims, isrange, suff, date, breakme, item, delim, element, mm, slst, mmpos, i, ilen, j, jlen, k, klen; - if (txt) { + if (txt) { txt = "" + txt; txt = txt.replace(/\s*[0-9]{2}:[0-9]{2}(?::[0-9]+)/,""); m = txt.match(jmd); @@ -1147,7 +1079,7 @@ CSL.DateParser = function () { slash = txt.indexOf("/"); dash = txt.indexOf("-"); } - } + } txt = txt.replace(/([A-Za-z])\./g, "$1"); number = ""; note = ""; @@ -1533,7 +1465,7 @@ CSL.Engine.prototype.setStyleAttributes = function () { var dummy, attr, key, attributes, attrname; dummy = {}; var cslXml = this.cslXml; - var tagName = this.cslXml.tagName ? ("" + this.cslXml.tagName).toLowerCase() : ""; + 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]; @@ -1804,20 +1736,20 @@ CSL.Engine.prototype.retrieveItem = function (id) { var legislation_id = []; for (i = 0, ilen = elements.length; i < ilen; i += 1) { varname = elements[i]; - if (Item[varname]) { - legislation_id.push(Item[varname]); - } - } + if (Item[varname]) { + legislation_id.push(Item[varname]); + } + } elements = ["original-date", "issued"]; - for (i = 0, elements.length; i < ilen; i += 1) { + for (i = 0, elements.length; i < ilen; i += 1) { varname = elements[i]; - if (Item[varname] && Item[varname].year) { - var value = Item[varname].year; - legislation_id.push(value); - break; - } - } - Item.legislation_id = legislation_id.join("::"); + if (Item[varname] && Item[varname].year) { + var value = Item[varname].year; + legislation_id.push(value); + break; + } + } + Item.legislation_id = legislation_id.join("::"); } } if (!Item["title-short"]) { @@ -2903,7 +2835,7 @@ CSL.Output.Queue.adjust = function (punctInQuote) { } } PUNCT_OR_SPACE[" "] = true; - PUNCT_OR_SPACE[" "] = true; + PUNCT_OR_SPACE[" "] = true; var RtoL_MAP = {}; for (var key in LtoR_MAP) { for (var subkey in LtoR_MAP[key]) { @@ -3174,7 +3106,7 @@ CSL.Output.Queue.adjust = function (punctInQuote) { } } } - if (childStrings.suffix.slice(-1) === " " && parentStrings.suffix.slice(0,1) === " ") { + if (childStrings.suffix.slice(-1) === " " && parentStrings.suffix.slice(0,1) === " ") { parentStrings.suffix = parentStrings.suffix.slice(1); } if (PUNCT_OR_SPACE[childStrings.suffix.slice(0,1)]) { @@ -4893,11 +4825,11 @@ CSL.Engine.prototype.updateItems = function (idList, nosort, rerun_ambigs) { var debug = false; var oldArea = this.tmp.area; this.registry.init(idList); - if (rerun_ambigs) { - for (var ambig in this.registry.ambigcites) { - this.registry.ambigsTouched[ambig] = true; - } - } + if (rerun_ambigs) { + for (var ambig in this.registry.ambigcites) { + this.registry.ambigsTouched[ambig] = true; + } + } this.registry.dodeletes(this.registry.myhash); this.registry.doinserts(this.registry.mylist); this.registry.dorefreshes(); @@ -5733,9 +5665,9 @@ CSL.Node.group = { if (res) { state.juris[jurisdiction] = {}; var myXml = state.sys.xml.makeXml(res); - var myNodes = state.sys.xml.getNodesByName(myXml, "category"); + var myNodes = state.sys.xml.getNodesByName(myXml, "law-module"); for (var i=0,ilen=myNodes.length;i -1) { @@ -9577,6 +9508,31 @@ CSL.Attributes["@page"] = function (state, arg) { this.tests.push(maketest(trylabels[i])); } }; +CSL.Attributes["@number"] = function (state, arg) { + var trylabels = arg.replace("sub verbo", "sub-verbo"); + trylabels = trylabels.split(/\s+/); + var maketest = function(trylabel) { + return function (Item, item) { + var label; + state.processNumber(false, Item, "number", Item.type); + if (!state.tmp.shadow_numbers.number.label) { + label = "number"; + } else if (state.tmp.shadow_numbers.number.label === "sub verbo") { + label = "sub-verbo"; + } else { + label = state.tmp.shadow_numbers.number.label; + } + if (trylabel === label) { + return true; + } else { + return false; + } + } + } + for (var i=0,ilen=trylabels.length;i -1) { - func = function (state, Item, item) { - var ret = []; - var label; - state.processNumber(false, Item, "number", Item.type); - if (!state.tmp.shadow_numbers.number.label) { - label = "number"; - } else if (state.tmp.shadow_numbers.number.label === "sub verbo") { - label = "sub-verbo"; - } else { - label = state.tmp.shadow_numbers.number.label; - } - for (var i = 0, ilen = trylabels.length; i < ilen; i += 1) { - if (trylabels[i] === label) { - ret.push(true); - } else { - ret.push(false); - } - } - return ret; - }; - this.tests.push(func); - } -}; CSL.Attributes["@has-publisher-and-publisher-place"] = function (state, arg) { this.strings["has-publisher-and-publisher-place"] = true; }; @@ -12498,8 +12426,8 @@ CSL.Util.PageRangeMangler.getFunction = function (state, rangeType) { }; var sniff = function (str, func, minchars, isyear) { var ret; - str = "" + str; - var lst = expand(str); + str = "" + str; + var lst = expand(str); var ret = func(lst, minchars, isyear); return ret; } @@ -12920,11 +12848,11 @@ CSL.Output.Formatters["capitalize-all"] = function (state, string) { var strings = str.string.split(" "); for (var i = 0, ilen = strings.length; i < ilen; i += 1) { if (strings[i].length > 1) { - if (state.opt.development_extensions.allow_force_lowercase) { - strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1).toLowerCase(); - } else { - strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1); - } + if (state.opt.development_extensions.allow_force_lowercase) { + strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1).toLowerCase(); + } else { + strings[i] = strings[i].slice(0, 1).toUpperCase() + strings[i].substr(1); + } } else if (strings[i].length === 1) { strings[i] = strings[i].toUpperCase(); } @@ -13089,13 +13017,13 @@ CSL.Output.Formats.prototype.html = { "@quotes/false": false, "@cite/entry": function (state, str) { return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt); - }, + }, "@bibliography/entry": function (state, str) { var insert = ""; if (state.sys.embedBibliographyEntry) { insert = state.sys.embedBibliographyEntry(this.item_id) + "\n"; } - return "
" + str + "
\n" + insert; + return "
" + str + "
\n" + insert; }, "@display/block": function (state, str) { return "\n\n
" + str + "
\n"; @@ -13179,8 +13107,8 @@ CSL.Output.Formats.prototype.text = { }, "@quotes/false": false, "@cite/entry": function (state, str) { - return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt); - }, + return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt); + }, "@bibliography/entry": function (state, str) { return str+"\n"; }, @@ -13255,10 +13183,10 @@ CSL.Output.Formats.prototype.rtf = { "@display/block": "\\line{}%%STRING%%\\line\r\n", "@cite/entry": function (state, str) { return str; - }, + }, "@cite/entry": function (state, str) { - return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt); - }, + return state.sys.wrapCitationEntry(str, this.item_id, this.locator_txt, this.suffix_txt); + }, "@bibliography/entry": function(state,str){ return str; }, @@ -14038,16 +13966,16 @@ CSL.Disambiguation.prototype.disYears = function () { tokens = []; var base = this.lists[this.listpos][0]; if (this.clashes[1]) { - for (var i = 0, ilen = this.state.registry.mylist.length; i < ilen; i += 1) { - var origid = this.state.registry.mylist[i]; - for (var j = 0, jlen = this.lists[this.listpos][1].length; j < jlen; j += 1) { - var token = this.lists[this.listpos][1][j]; - if (token.id == origid) { - tokens.push(this.registry[token.id]); - break; - } - } - } + for (var i = 0, ilen = this.state.registry.mylist.length; i < ilen; i += 1) { + var origid = this.state.registry.mylist[i]; + for (var j = 0, jlen = this.lists[this.listpos][1].length; j < jlen; j += 1) { + var token = this.lists[this.listpos][1][j]; + if (token.id == origid) { + tokens.push(this.registry[token.id]); + break; + } + } + } } tokens.sort(this.state.registry.sorter.compareKeys); for (pos = 0, len = tokens.length; pos < len; pos += 1) { diff --git a/src/csl_json.js b/src/csl_json.js deleted file mode 100644 index c90692b..0000000 --- a/src/csl_json.js +++ /dev/null @@ -1,453 +0,0 @@ -/* - * CSL_JSON is copied from xmljson.js from the citeproc-js project - * - */ - -var CSL_JSON = function () { - this.institution = { - name:"institution", - attrs:{ - "institution-parts":"long", - "delimiter":", ", - "substitute-use-first":"1", - "use-last":"1" - }, - children:[ - { - name:"institution-part", - attrs:{ - name:"long" - }, - children:[] - } - ] - }; -}; - -/** - * No need for cleaning with native JSON. - */ -CSL_JSON.prototype.clean = function (json) { - return json; -}; - - -/** - * Methods to call on a node. - */ -CSL_JSON.prototype.getStyleId = function (myjson, styleName) { - var tagName = 'id'; - if (styleName) { - tagName = 'title'; - } - return myjson.attrs[tagName]; -}; - -CSL_JSON.prototype.children = function (myjson) { - //print("children()"); - if (myjson && myjson.children.length) { - return myjson.children.slice(); - } else { - return false; - } -}; - -CSL_JSON.prototype.nodename = function (myjson) { - //print("nodename()"); - return myjson.name; -}; - -CSL_JSON.prototype.attributes = function (myjson) { - //print("attributes()"); - var ret = {}; - for (var attrname in myjson.attrs) { - ret["@"+attrname] = myjson.attrs[attrname]; - } - return ret; -}; - - -CSL_JSON.prototype.content = function (myjson) { - //print("content()"); - // xmldom.js and xmle4x.js have "undefined" as default - var ret = ""; - // This only catches content at first level, but that is good enough - // for us. - if (!myjson || !myjson.children) { - return ret; - } - for (var i=0, ilen=myjson.children.length; i < ilen; i += 1) { - if ("string" === typeof myjson.children[i]) { - ret += myjson.children[i]; - } - } - return ret; -}; - - -CSL_JSON.prototype.namespace = {} - -CSL_JSON.prototype.numberofnodes = function (myjson) { - //print("numberofnodes()"); - if (myjson && "number" == typeof myjson.length) { - return myjson.length; - } else { - return 0; - } -}; - -// getAttributeName() removed. Looks like it was not being used. - -CSL_JSON.prototype.getAttributeValue = function (myjson,name,namespace) { - //print("getAttributeValue()"); - var ret = ""; - if (namespace) { - name = namespace+":"+name; - } - if (myjson) { - if (myjson.attrs) { - if (myjson.attrs[name]) { - ret = myjson.attrs[name]; - } else { - ret = ""; - } - } - } - return ret; -} - -CSL_JSON.prototype.getNodeValue = function (myjson,name) { - //print("getNodeValue()"); - var ret = ""; - if (name){ - for (var i=0, ilen=myjson.children.length; i < ilen; i += 1) { - if (myjson.children[i].name === name) { - // This will always be Object() unless empty - if (myjson.children[i].children.length) { - ret = myjson.children[i]; - } else { - ret = ""; - } - } - } - } else if (myjson) { - ret = myjson; - } - // Just being careful here, following the former DOM code. The JSON object we receive - // for this should be fully normalized. - if (ret && ret.children && ret.children.length == 1 && "string" === typeof ret.children[0]) { - ret = ret.children[0]; - } - return ret; -} - -CSL_JSON.prototype.setAttributeOnNodeIdentifiedByNameAttribute = function (myjson,nodename,partname,attrname,val) { - //print("setAttributeOnNodeIdentifiedByNameAttribute()"); - var pos, len, xml, nodes, node; - if (attrname.slice(0,1) === '@'){ - attrname = attrname.slice(1); - } - // In the one place this is used in citeproc-js code, it doesn't need to recurse. - for (var i=0,ilen=myjson.children.length; i -1 && !myjson.children[i].attrs.prefix && !myjson.children[i].attrs.suffix) { - mustHaves = mustHaves.slice(0,haveVarname).concat(mustHaves.slice(haveVarname+1)); - } else { - useme = false; - break; - } - } - if (useme && !mustHaves.length) { - myjson.attrs["has-publisher-and-publisher-place"] = true; - } - } - for (var i=0,ilen=myjson.children.length;i -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_JSON.prototype.addMissingNameNodes = function(myjson,parentname) { - //print("addMissingNameNodes()"); - if (myjson.name === "names") { - // Trawl through children to decide whether a name node is needed here - var addNameNode = true; - if ("substitute" !== parentname) { - for (var i=0,ilen=myjson.children.length;i -1) { - var institution = this.nodeCopy(this.institution); - for (var i=0,ilen = INSTITUTION_KEYS.length;i "~") + { + 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;