www

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

commit 5efeeb608915a03ab334166711b7ecfa81ff60a7
parent 0f71fdbc35a2c29ef44d2cb2249a45c2988f4e30
Author: Simon Kornblith <simon@simonster.com>
Date:   Wed, 23 Jul 2008 05:05:03 +0000

remove support for old-style CSLs


Diffstat:
Mchrome/content/zotero/xpcom/cite.js | 16++++++----------
Dchrome/content/zotero/xpcom/cite_compat.js | 2011-------------------------------------------------------------------------------
Mcomponents/zotero-service.js | 2+-
3 files changed, 7 insertions(+), 2022 deletions(-)

diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js @@ -73,17 +73,13 @@ Zotero.Cite = new function() { // create a CSL instance var csl = _getCSL(cslID); - // load CSL in compat mode if it is old-style - if(csl.indexOf("<defaults") != -1) { - _lastCSL = new Zotero.CSL.Compat(csl); - } else { - if(csl.substr(0, 6) == "\x00\x08\xFF\x00\x00\x00") { - // EN style - var enConverter = new Zotero.ENConverter(csl); - csl = enConverter.parse(); - } - _lastCSL = new Zotero.CSL(csl); + // load CSL in EN mode if necessary + if(csl.substr(0, 6) == "\x00\x08\xFF\x00\x00\x00") { + // EN style + var enConverter = new Zotero.ENConverter(csl); + csl = enConverter.parse(); } + _lastCSL = new Zotero.CSL(csl); _lastStyle = cslID; } diff --git a/chrome/content/zotero/xpcom/cite_compat.js b/chrome/content/zotero/xpcom/cite_compat.js @@ -1,2010 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - - Copyright (c) 2006 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - http://chnm.gmu.edu - - Licensed under the Educational Community 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://www.opensource.org/licenses/ecl1.php - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ***** END LICENSE BLOCK ***** -*/ - -/* - * Zotero.Cite: a class for creating bibliographies from within Scholar - * this class handles pulling the CSL file and item data out of the database, - * while CSL, below, handles the actual generation of the bibliography - */ - -/* - * CSL: a class for creating bibliographies from CSL files - * this is abstracted as a separate class for the benefit of anyone who doesn't - * want to use the Scholar data model, but does want to use CSL in JavaScript - */ -Zotero.CSL.Compat = function(csl) { - default xml namespace = "http://purl.org/net/xbiblio/csl"; - - this._csl = new XML(Zotero.CSL.Compat.Global.cleanXML(csl)); - - // initialize CSL - Zotero.CSL.Compat.Global.init(); - - // load localizations - this._terms = Zotero.CSL.Compat.Global.parseLocales(this._csl.terms); - - // load class defaults - this.class = this._csl["@class"].toString(); - this.hasBibliography = true; - Zotero.debug("CSL: style class is "+this.class); - - this._defaults = new Object(); - // load class defaults - if(Zotero.CSL.Compat.Global.classDefaults[this.class]) { - var classDefaults = Zotero.CSL.Compat.Global.classDefaults[this.class]; - for(var i in classDefaults) { - this._defaults[i] = classDefaults[i]; - } - } - // load defaults from CSL - this._parseFieldDefaults(this._csl.defaults); - // parse bibliography and citation options - this._parseBibliographyOptions(); - this._parseCitationOptions(); - // if no bibliography exists, parse citation element as bibliography - if(!this._bib) { - Zotero.debug("CSL: using citation element for bibliography"); - this._bib = this._cit; - this.hasBibliography = false; - } -} - - -Zotero.CSL.Compat.Global = new function() { - default xml namespace = "http://purl.org/net/xbiblio/csl"; - - // for elements that inherit defaults from each other - this.inherit = { - author:"contributor", - editor:"contributor", - translator:"contributor", - recipient:"contributor", - interviewer:"contributor", - pages:"locator", - volume:"locator", - issue:"locator", - isbn:"identifier", - doi:"identifier", - edition:"version" - } - - // for types - this.typeInheritance = { - "article-magazine":"article", - "article-newspaper":"article", - "article-journal":"article", - "bill":"article", - "figure":"article", - "graphic":"article", - "interview":"article", - "legal case":"article", - "manuscript":"article", - "map":"article", - "motion picture":"book", - "musical score":"article", - "pamphlet":"book", - "paper-conference":"chapter", - "patent":"article", - "personal communication":"article", - "report":"book", - "song":"article", - "speech":"article", - "thesis":"article", - "treaty":"article", - "webpage":"article", - } - - // for class definitions - this.classDefaults = new Object(); - this.classDefaults["author-date"] = { - author:{ - substitute:[ - {name:"editor"}, - {name:"translator"}, - {name:"titles", relation:"container", "font-style":"italic"}, - {name:"titles", children:[ - {name:"title", form:"short"} - ]} - ] - } - }; - - this.ns = "http://purl.org/net/xbiblio/csl"; - - /* - * initializes CSL interpreter - */ - this.init = function() { - if(!Zotero.CSL.Compat.Global._xmlLang) { - var prefix = "chrome://zotero/content/locale/csl/locales-"; - var ext = ".xml"; - - // If explicit bib locale, try to use that - var bibLocale = Zotero.Prefs.get('export.bibliographyLocale'); - if (bibLocale) { - var loc = bibLocale; - var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(); - req.open("GET", prefix + loc + ext, false); - req.overrideMimeType("text/plain"); - var fail = false; - try { - req.send(null); - } - catch (e) { - fail = true; - } - - if (!fail) { - Zotero.CSL.Compat.Global._xmlLang = bibLocale; - var xml = req.responseText; - } - } - - // If no or invalid bib locale, try Firefox locale - if (!xml) { - var loc = Zotero.locale; - var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(); - req.open("GET", prefix + loc + ext, false); - req.overrideMimeType("text/plain"); - var fail = false; - try { - req.send(null); - } - catch (e) { - fail = true; - } - - if (!fail) { - Zotero.CSL.Compat.Global._xmlLang = loc; - var xml = req.responseText; - } - } - - // Fall back to en-US if no locales.xml - if (!xml) { - var loc = 'en-US'; - var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(); - req.open("GET", prefix + loc + ext, false); - req.overrideMimeType("text/plain"); - req.send(null); - - Zotero.CSL.Compat.Global._xmlLang = loc; - var xml = req.responseText; - } - - Zotero.debug('CSL: Using ' + loc + ' as bibliography locale'); - - // get default terms - var locales = new XML(Zotero.CSL.Compat.Global.cleanXML(xml)); - Zotero.CSL.Compat.Global._defaultTerms = Zotero.CSL.Compat.Global.parseLocales(locales, true); - } - } - - /* - * returns an array of short or long month strings - */ - this.getMonthStrings = function(form) { - Zotero.CSL.Compat.Global.init(); - return Zotero.CSL.Compat.Global._defaultTerms[form]["_months"]; - } - - /* - * removes parse instructions from XML - */ - this.cleanXML = function(xml) { - return xml.replace(/<\?[^>]*\?>/g, ""); - } - - /* - * parses locale strings into Zotero.CSL.Compat.Global._defaultTerms - */ - this.parseLocales = function(termXML, ignoreLang) { - // return defaults if there are no terms - if(!termXML.length()) { - return (Zotero.CSL.Compat.Global._defaultTerms ? Zotero.CSL.Compat.Global._defaultTerms : {}); - } - - var xml = new Namespace("http://www.w3.org/XML/1998/namespace"); - - if(ignoreLang) { - // ignore lang if loaded from chrome - locale = termXML.locale[0]; - } else { - // get proper locale - var locale = termXML.locale.(@xml::lang == Zotero.CSL.Compat.Global._xmlLang); - if(!locale.length()) { - var xmlLang = Zotero.CSL.Compat.Global._xmlLang.substr(0, 2); - locale = termXML.locale.(@xml::lang == xmlLang); - } - if(!locale.length()) { - // return defaults if there are no locales - return (Zotero.CSL.Compat.Global._defaultTerms ? Zotero.CSL.Compat.Global._defaultTerms : {}); - } - } - - var termArray = new Object(); - termArray["default"] = new Object(); - - if(Zotero.CSL.Compat.Global._defaultTerms) { - // ugh. copy default array. javascript dumb. - for(var i in Zotero.CSL.Compat.Global._defaultTerms) { - termArray[i] = new Object(); - for(var j in Zotero.CSL.Compat.Global._defaultTerms[i]) { - if(typeof(Zotero.CSL.Compat.Global._defaultTerms[i]) == "object") { - termArray[i][j] = [Zotero.CSL.Compat.Global._defaultTerms[i][j][0], - Zotero.CSL.Compat.Global._defaultTerms[i][j][1]]; - } else { - termArray[i][j] = Zotero.CSL.Compat.Global_defaultTerms[i][j]; - } - } - } - } - - // loop through terms - for each(var term in locale.term) { - var name = term.@name.toString(); - if(!name) { - throw("citations cannot be generated: no name defined on term in CSL"); - } - // unless otherwise specified, assume "long" form - var form = term.@form.toString(); - if(!form) { - var form = "long"; - } - if(!termArray[form]) { - termArray[form] = new Object(); - } - - var single = term.single.text().toString(); - var multiple = term.multiple.text().toString(); - if(single || multiple) { - if((single && multiple) // if there's both elements or - || !termArray[form][name]) { // no previously defined value - termArray[form][name] = [single, multiple]; - } else { - if(typeof(termArray[name]) != "object") { - // if old object was just a single value, make it two copies - termArray[form][name] = [termArray[form][name], termArray[form][name]]; - } - - // redefine either single or multiple - if(single) { - termArray[form][name][0] = single; - } else { - termArray[form][name][1] = multiple; - } - } - } else { - if(name.substr(0, 6) == "month-") { - // place months into separate array - if(!termArray[form]["_months"]) { - termArray[form]["_months"] = new Array(); - } - var monthIndex = parseInt(name.substr(6),10)-1; - var term = term.text().toString(); - termArray[form]["_months"][monthIndex] = term[0].toUpperCase()+term.substr(1).toLowerCase(); - } else { - termArray[form][name] = term.text().toString(); - } - } - } - - return termArray; - } - - /* - * pads a number or other string with a given string on the left - */ - this.lpad = function(string, pad, length) { - while(string.length < length) { - string = pad + string; - } - return string; - } -} - -Zotero.CSL.Compat.prototype.createItemSet = function(items) { - return new Zotero.CSL.Compat.ItemSet(items, this); -} - -Zotero.CSL.Compat.prototype.createCitation = function(citationItems) { - return new Zotero.CSL.Citation(citationItems); -} - -Zotero.CSL.Compat.ItemSet = function(items, csl) { - this.items = []; - this.csl = csl; - if(items) this.add(items); - this.resort(); -} - -Zotero.CSL.Compat.ItemSet.prototype.getItemsByIds = function(ids) { - var returnList = []; - for each(var id in ids) { - var item = Zotero.Items.get(id); - if(this.items.indexOf(item) !== -1) { - returnList.push(item); - } else { - returnList.push(false); - } - } - return returnList; -} - -Zotero.CSL.Compat.ItemSet.prototype.add = function(items) { - var returnList = []; - for each(var item in items) { - if(!(item instanceof Zotero.Item)) { - item = Zotero.Items.get(item); - } - if(!item) { - throw "Zotero.CSL.Compat.ItemSet.add called on a non-item"; - } - this.items.push(item); - returnList.push(item); - - item.zoteroItem = item; - - item.setProperty = function(property, value) { - item._csl[property] = value; - } - - item.getProperty = function(property) { - return (item._csl[property] ? item._csl[property] : ""); - } - } - return returnList; -} - -Zotero.CSL.Compat.ItemSet.prototype.remove = function(items) { - for(var i in items) { - if(items[i] instanceof Zotero.Item) { - var item = items[i]; - } else { - var item = Zotero.Items.get(items[i]); - } - if(!item) continue; - this.items.splice(this.items.indexOf(item), 1); - } -} - -Zotero.CSL.Compat.ItemSet.prototype.resort = function() { - var oldDisambiguation = {}; - if(!this.items) return; - - // get data necessary to generate citations before sorting - for(var i in this.items) { - var item = this.items[i]; - var dateModified = this.csl._getField(item, "dateModified"); - - if(!item._csl || item._csl.dateModified != dateModified) { - // namespace everything in item._csl so there's no chance of overlap - item._csl = new Object(); - item._csl.dateModified = dateModified; - - // separate item into authors, editors, translators, recipients, interviewers - var creators = this.csl._separateItemCreators(item); - item._csl.authors = creators[0]; - item._csl.editors = creators[1]; - item._csl.translators = creators[2]; - item._csl.recipients = creators[3]; - item._csl.interviewers = creators[4]; - - // parse date - item._csl.date = Zotero.CSL.Compat.prototype._processDate(this.csl._getField(item, "date")); - } - - // clear disambiguation and subsequent author substitute - if(item._csl.date && item._csl.date.disambiguation) { - oldDisambiguation[item.getID()] = item._csl.date.disambiguation; - item._csl.date.disambiguation = undefined; - } - if(item._csl.subsequentAuthorSubstitute) item._csl.subsequentAuthorSubstitute = undefined; - } - - // sort by sort order - if(this.csl._bib.sortOrder) { - Zotero.debug("CSL: sorting this.items"); - var me = this.csl; - this.items.sort(function(a, b) { - return me._compareItem(a, b); - }); - } - - // disambiguate this.items after preprocessing and sorting - var usedCitations = new Array(); - var lastAuthors; - - for(var i in this.items) { - var item = this.items[i]; - - // handle subsequent author substitutes - if(item._csl.authors.length && lastAuthors) { - var authorsAreSame = true; - for(var i=item._csl.authors.length-1; i>=0; i--) { - if(!lastAuthors[i] || - lastAuthors[i].firstName != item._csl.authors[i].firstName || - lastAuthors[i].lastName != item._csl.authors[i].lastName || - lastAuthors[i].creatorType != item._csl.authors[i].creatorType) { - authorsAreSame = false; - break; - } - } - if(authorsAreSame) item._csl.subsequentAuthorSubstitute = true; - } - lastAuthors = item._csl.authors; - - // handle (2006a) disambiguation for author-date styles - if(this.csl.class == "author-date") { - var year = item._csl.date.year; - - if(authorsAreSame) { - if(usedCitations[year]) { - if(!usedCitations[year]._csl.date.disambiguation) { - usedCitations[year]._csl.date.disambiguation = "a"; - item._csl.date.disambiguation = "b"; - } else { - // get all but last character - var oldLetter = usedCitations[year]._csl.date.disambiguation; - if(oldLetter.length > 1) { - item._csl.date.disambiguation = oldLetter.substr(0, oldLetter.length-1); - } else { - item._csl.date.disambiguation = ""; - } - - var charCode = oldLetter.charCodeAt(oldLetter.length-1); - if(charCode == 122) { - // item is z; add another letter - item._csl.date.disambiguation += "za"; - } else { - // next lowercase letter - item._csl.date.disambiguation += String.fromCharCode(charCode+1); - } - } - } - } else { - usedCitations = new Array(); - } - - usedCitations[year] = item; - } - - // add numbers to each - item._csl.number = i; - } - - // see which items have changed - var returnItems = []; - for each(var item in this.items) { - if(item._csl.date && item._csl.date.disambiguation) { - var oldDisambig = oldDisambiguation[item.getID()]; - if(!oldDisambig || oldDisambig != item._csl.date.disambiguation) { - returnItems.push(item); - } - } - } - return returnItems; -} - -Zotero.CSL.Compat.prototype.formatCitation = function(citation, format) { - var string = new Zotero.CSL.Compat.FormattedString(this, format); - if(this.ibid == true && citation.citationItems.length == 1 && - citation.citationItems[0].position == Zotero.CSL.POSITION_IBID - || citation.citationItems[0].position == Zotero.CSL.POSITION_IBID_WITH_LOCATOR) { // indicates ibid - var term = this._getTerm("ibid"); - string.append(term[0].toUpperCase()+term.substr(1)); - - if(citation.citationItems[0].position == Zotero.CSL.POSITION_IBID_WITH_LOCATOR) { - // locator data - var locator = citation.citationItems[0].locator; - - if(locator) { - // search for elements with the same serialization - var element = this._getFieldDefaults("locator"); - if(!element) { - element = { - name:"locator", - children:{name:"number"} - }; - } - - if(element) { - string.append("., "); - string.appendLocator(citation.citationItems[0].locatorType, locator, element); - } - } - } - } else { // indicates primary or subsequent - var lasti = citation.citationItems.length-1; - for(var i in citation.citationItems) { - var citationItem = citation.citationItems[i]; - if(!citationItem.locatorType) citationItem.locatorType = 0; - - var position = (citationItem.position >= Zotero.CSL.POSITION_SUBSEQUENT ? "subsequent" : "first"); - var ignore = (citationItem.suppressAuthor ? {"author":true} : undefined); - - if(citationItem.prefix) string.append(citationItem.prefix+" "); - var citationString = this._getCitation(citationItem.item, - position, citationItem.locatorType, - citationItem.locator, format, this._cit, ignore); - string.concat(citationString); - if(citationItem.suffix) string.append(citationItem.suffix+" "); - - if(this._cit.format && this._cit.format.delimiter && i != lasti) { - // add delimiter if one exists, and this isn't the last element - string.append(this._cit.format.delimiter); - } - } - } - - // add format - if(this._cit.format) { - // add citation prefix or suffix - if(this._cit.format.prefix) { - string.string = this._cit.format.prefix + string.string; - } - if(this._cit.format.suffix) { - string.append(this._cit.format.suffix); - } - } - - return string.get(); -} - -/* - * create a bibliography - * (items is expected to be an array of items) - */ -Zotero.CSL.Compat.prototype.formatBibliography = function(itemSet, format) { - var items = itemSet.items; - var output = ""; - - var index = 0; - if(format == "HTML") { - if(this.class == "note" && this._bib == this._cit) { - output += '<ol>\r\n'; - } else if(this._bib.hangingIndent) { - output += '<div style="margin-left:0.5in;text-indent:-0.5in;">\r\n'; - } - } else if(format == "RTF") { - output += "{\\rtf\\ansi{\\fonttbl\\f0\\froman Times New Roman;}{\\colortbl;\\red255\\green255\\blue255;}\\pard\\f0"; - if(this._bib.hangingIndent) { - output += "\\li720\\fi-720"; - } - output += "\r\n"; - } - - for(var i in items) { - var item = items[i]; - - var string = item.getProperty("bibliography-"+format); - if(!string) { - string = this._getCitation(item, "first", false, false, format, this._bib).get(); - } - if(!string) { - continue; - } - - // add format - if(this._bib.format) { - // add citation prefix or suffix - if(this._bib.format.prefix) { - string = this._bib.format.prefix + string ; - } - if(this._bib.format.suffix) { - string += this._bib.format.suffix; - } - } - - // add line feeds - if(format == "HTML") { - var coins = Zotero.OpenURL.createContextObject(item, "1.0"); - if(coins) { - string += '<span class="Z3988" title="'+coins.replace("&", "&amp;")+'"></span>'; - } - - if(this.class == "note" && this._bib == this._cit) { - output += "<li>"+string+"</li>\r\n"; - } else { - output += "<p>"+string+"</p>\r\n"; - } - } else if(format == "RTF") { - if(this.class == "note" && this._bib == this._cit) { - index++; - output += index+". "; - } - output += string+"\\\r\n\\\r\n"; - } else { - if(format == "Text" && this.class == "note" && this._bib == this._cit) { - index++; - output += index+". "; - } - // attach \n on mac (since both \r and \n count as newlines for - // clipboard purposes) - output += string+(Zotero.isMac ? "\n\n" : "\r\n\r\n"); - } - } - - if(format == "HTML") { - if(this.class == "note" && this._bib == this._cit) { - output += '</ol>'; - } else if(this._bib.hangingIndent) { - output += '</div>'; - } - } else if(format == "RTF") { - // drop last 6 characters of output (last two returns) - output = output.substr(0, output.length-6)+"}"; - } else { - // drop last 4 characters (last two returns) - output = output.substr(0, (Zotero.isMac ? output.length-2 : output.length-4)); - } - - return output; -} - -/* - * parses attributes and children for a CSL field - */ -Zotero.CSL.Compat.prototype._parseFieldAttrChildren = function(element, desc, ignoreChildren) { - if(!desc) { - var desc = new Object(); - } - - // copy attributes - var attributes = element.attributes(); - for each(var attribute in attributes) { - desc[attribute.name()] = attribute.toString(); - } - - var children = element.children(); - if(!ignoreChildren) { - if(children.length()) { - // parse children - - if(children.length() > element.substitute.length()) { - // if there are non-substitute children, clear the current children - // array - desc.children = new Array(); - } - - // add children to children array - for each(var child in children) { - if(child.namespace() == Zotero.CSL.Compat.Global.ns) { // ignore elements in other - // namespaces - // parse recursively - var name = child.localName(); - if(name == "substitute") { - // place substitutes in their own key, so that they're - // overridden separately - if(child.choose.length) { // choose - desc.substitute = new Array(); - - var chooseChildren = child.choose.children(); - for each(var choose in chooseChildren) { - if(choose.namespace() == Zotero.CSL.Compat.Global.ns) { - var option = new Object(); - option.name = choose.localName(); - this._parseFieldAttrChildren(choose, option); - desc.substitute.push(option); - } - } - } else { // don't choose - desc.substitute = child.text().toString(); - } - } else { - var childDesc = this._parseFieldAttrChildren(child); - childDesc.name = name; - desc.children.push(childDesc); - } - } - } - } - } - - return desc; -} - -/* - * parses a list of fields into a defaults associative array - */ -Zotero.CSL.Compat.prototype._parseFieldDefaults = function(ref) { - for each(var element in ref.children()) { - if(element.namespace() == Zotero.CSL.Compat.Global.ns) { // ignore elements in other namespaces - var name = element.localName(); - Zotero.debug("CSL: parsing field defaults for "+name); - var fieldDesc = this._parseFieldAttrChildren(element); - - if(this._defaults[name]) { // inherit from existing defaults - this._defaults[name] = this._merge(this._defaults[name], - fieldDesc); - } else { - this._defaults[name] = fieldDesc; - } - } - } -} - -/* - * parses a list of fields into an array of objects - */ -Zotero.CSL.Compat.prototype._parseFields = function(ref, position, type, bibCitElement, inheritFormat) { - var typeDesc = new Array(); - for each(var element in ref) { - if(element.namespace() == Zotero.CSL.Compat.Global.ns) { // ignore elements in other namespaces - var itemDesc = new Object(); - itemDesc.name = element.localName(); - - // add defaults, but only if we're parsing as a reference type - if(type != undefined) { - var fieldDefaults = this._getFieldDefaults(itemDesc.name); - itemDesc = this._merge(fieldDefaults, itemDesc); - if(bibCitElement && inheritFormat) { - itemDesc = this._merge(bibCitElement.inheritFormat, itemDesc); - } - } - - // parse group children - if(itemDesc.name == "group" || itemDesc.name == "conditional" || - itemDesc.name == "if" || itemDesc.name == "else-if" || - itemDesc.name == "else") { - // parse attributes on this field, but ignore children - this._parseFieldAttrChildren(element, itemDesc, true); - - var children = element.children(); - if(children.length()) { - itemDesc.children = this._parseFields(children, position, type, bibCitElement); - } - } else { - // parse attributes on this field - this._parseFieldAttrChildren(element, itemDesc); - } - - if(type != undefined) { - // create serialized representation - itemDesc._serialized = this._serializeElement(itemDesc.name, itemDesc); - // add to serialization for type - if(bibCitElement && bibCitElement._serializations) { - bibCitElement._serializations[position][type][itemDesc._serialized] = itemDesc; - } - } - - typeDesc.push(itemDesc); - } - } - return typeDesc; -} - -/* - * parses an et al field - */ -Zotero.CSL.Compat.prototype._parseEtAl = function(etAl, bibCitElement) { - if(etAl.length()) { - bibCitElement.etAl = new Object(); - - if(etAl.length() > 1) { - // separate first and subsequent et als - for each(var etAlElement in etAl) { - if(etAlElement.@position == "subsequent") { - bibCitElement.subsequentEtAl = new Object(); - bibCitElement.subsequentEtAl.minCreators = parseInt(etAlElement['@min-authors'], 10); - bibCitElement.subsequentEtAl.useFirst = parseInt(etAlElement['@use-first'], 10); - } else { - var parseElement = etAlElement; - } - } - } else { - var parseElement = etAl; - } - - bibCitElement.etAl.minCreators = parseInt(parseElement['@min-authors'], 10); - bibCitElement.etAl.useFirst = parseInt(parseElement['@use-first'], 10); - } else if(this._defaults["et-al"]) { - bibCitElement.etAl = new Object(); - - bibCitElement.etAl.minCreators = parseInt(this._defaults["et-al"]['min-authors'], 10); - bibCitElement.etAl.useFirst = parseInt(this._defaults["et-al"]['use-first'], 10); - } -} - -/* - * parses cs-format attributes into just a prefix and a suffix; accepts an - * optional array of cs-format - */ -Zotero.CSL.Compat.prototype._parseBibliographyOptions = function() { - if(!this._csl.bibliography.length()) { - return; - } - - var bibliography = this._csl.bibliography; - this._bib = new Object(); - - // global prefix and suffix format information - this._bib.inheritFormat = new Array(); - for each(var attribute in bibliography.layout.item.attributes()) { - this._bib.inheritFormat[attribute.name()] = attribute.toString(); - } - - // sections (TODO) - this._bib.sections = [{groupBy:"default", - heading:bibliography.layout.heading.text["@term-name"].toString()}]; - for each(var section in bibliography.layout.section) { - this._bib.sections.push([{groupBy:section["@group-by"].toString(), - heading:section.heading.text["@term-name"].toString()}]); - } - - // subsequent author substitute - // replaces subsequent occurances of an author with a given string - if(bibliography['@subsequent-author-substitute']) { - this._bib.subsequentAuthorSubstitute = bibliography['@subsequent-author-substitute'].toString(); - } - - // hanging indent - if(bibliography['@hanging-indent']) { - this._bib.hangingIndent = true; - } - - // sort order - var algorithm = bibliography.sort.@algorithm.toString(); - if(algorithm) { - // for classes, use the sort order that - if(algorithm == "author-date") { - this._bib.sortOrder = [this._getFieldDefaults("author"), - this._getFieldDefaults("date"), - this._getFieldDefaults("titles")]; - this._bib.sortOrder[0].name = "author"; - this._bib.sortOrder[0]["name-as-sort-order"] = "all"; - this._bib.sortOrder[1].name = "date"; - this._bib.sortOrder[2].name = "titles"; - } else if(algorithm == "label") { - this._bib.sortOrder = [this._getFieldDefaults("label")]; - this._bib.sortOrder[0].name = "label"; - } else if(algorithm == "cited") { - this._bib.sortOrder = [this._getFieldDefaults("cited")]; - this._bib.sortOrder[0].name = "cited"; - } - } else { - this._bib.sortOrder = this._parseFields(bibliography.sort.children(), "first", false, this._bib); - } - - // parse et al - this._parseEtAl(bibliography["et-al"], this._bib); - - // parse types - this._parseTypes(this._csl.bibliography.layout.item, this._bib); -} - -/* - * parses cs-format attributes into just a prefix and a suffix; accepts an - * optional array of cs-format - */ -Zotero.CSL.Compat.prototype._parseCitationOptions = function() { - var citation = this._csl.citation; - this._cit = new Object(); - - // parse et al - this._parseEtAl(citation["et-al"], this._cit); - - // global format information - this._cit.format = new Array(); - for each(var attribute in citation.attributes()) { - this._cit.format[attribute.name()] = attribute.toString(); - } - - // parse types - this._parseTypes(this._csl.citation.layout.item, this._cit); -} - -/* - * determine available reference types and add their XML objects to the tree - * (they will be parsed on the fly when necessary; see _parseReferenceType) - */ -Zotero.CSL.Compat.prototype._parseTypes = function(itemElements, bibCitElement) { - Zotero.debug("CSL: parsing item elements"); - - bibCitElement._types = new Object(); - bibCitElement._serializations = new Object(); - - // find the type item without position="subsequent" - for each(var itemElement in itemElements) { - var position = itemElement.@position.toString(); - if(position) { - // handle ibids - if(position == "subsequent" && - itemElement.@ibid.toString() == "true") { - this.ibid = true; - } - } else { - position = "first"; - } - - if(!bibCitElement._types[position]) { - bibCitElement._types[position] = new Object(); - bibCitElement._serializations[position] = new Object(); - } - - // create an associative array of available types - if(itemElement.choose.length()) { - for each(var type in itemElement.choose.type) { - bibCitElement._types[position][type.@name] = type; - bibCitElement._serializations[position][type.@name] = new Object(); - } - } else { - // if there's only one type, bind it to index 0 - bibCitElement._types[position][0] = itemElement; - bibCitElement._serializations[position][0] = new Object(); - } - } -} - -/* - * convert reference types to native structures for speed - */ -Zotero.CSL.Compat.prototype._getTypeObject = function(position, reftype, bibCitElement) { - if(!bibCitElement._types[position][reftype]) { - // no type available - return false; - } - - // parse type if necessary - if(typeof(bibCitElement._types[position][reftype]) == "xml") { - Zotero.debug("CSL: parsing XML for "+reftype); - bibCitElement._types[position][reftype] = this._parseFields( - bibCitElement._types[position][reftype].children(), - position, reftype, bibCitElement, true); - } - - Zotero.debug("CSL: got object for "+reftype); - return bibCitElement._types[position][reftype]; -} - -/* - * merges two elements, letting the second override the first - */ -Zotero.CSL.Compat.prototype._merge = function(element1, element2) { - var mergedElement = new Object(); - for(var i in element1) { - mergedElement[i] = element1[i]; - } - for(var i in element2) { - mergedElement[i] = element2[i]; - } - return mergedElement; -} - -/* - * gets defaults for a specific element; handles various inheritance rules - * (contributor, locator) - */ -Zotero.CSL.Compat.prototype._getFieldDefaults = function(elementName) { - // first, see if there are specific defaults - if(this._defaults[elementName]) { - if(Zotero.CSL.Compat.Global.inherit[elementName]) { - var inheritedDefaults = this._getFieldDefaults(Zotero.CSL.Compat.Global.inherit[elementName]); - for(var i in inheritedDefaults) { // will only be called if there - // is merging necessary - return this._merge(inheritedDefaults, this._defaults[elementName]); - } - } - return this._defaults[elementName]; - } - // next, try to get defaults from the item from which this item inherits - if(Zotero.CSL.Compat.Global.inherit[elementName]) { - return this._getFieldDefaults(Zotero.CSL.Compat.Global.inherit[elementName]); - } - // finally, return an empty object - return {}; -} - -/* - * gets a term, in singular or plural form - */ -Zotero.CSL.Compat.prototype._getTerm = function(term, plural, form) { - if(!form) { - form = "long"; - } - if(!this._terms[form][term]) { - return ""; - } - - if(typeof(this._terms[form][term]) == "object") { // singular and plural forms - // are available - if(plural) { - return this._terms[form][term][1]; - } else { - return this._terms[form][term][0]; - } - } - - return this._terms[form][term]; -} - - -/* - * serializes an element into a string suitable to prevent substitutes from - * recurring in the same style - */ -Zotero.CSL.Compat.prototype._serializeElement = function(name, element) { - var string = name; - if(element.relation) { - string += " relation:"+element.relation; - } - if(element.role) { - string += " role:"+element.role; - } - return string; -} - -/* - * handles sorting of items - */ -Zotero.CSL.Compat.prototype._compareItem = function(a, b, opt) { - 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.getApplicationLocale()); - - for(var i in this._bib.sortOrder) { - var sortElement = this._bib.sortOrder[i]; - - if(sortElement.name == "date") { - var aValue = a.getField("date", true); - var bValue = b.getField("date", true); - - if(bValue == "" && aValue != "") { - return -1; - } else if(aValue == "" && bValue != "") { - return 1; - } else if(bValue > aValue) { - return -1; - } else if(bValue < aValue) { - return 1; - } - } else { - var formattedStringA = new Zotero.CSL.Compat.FormattedString(this, "compare"); - var formattedStringB = new Zotero.CSL.Compat.FormattedString(this, "compare"); - - //Zotero.debug('comparing '+sortElement.name+' on "'+a.getField("title")+'" and "'+b.getField("title")+'"'); - - this._getFieldValue(sortElement.name, sortElement, a, - formattedStringA, this._bib); - this._getFieldValue(sortElement.name, sortElement, b, - formattedStringB, this._bib); - - var aValue = formattedStringA.get().toLowerCase(); - var bValue = formattedStringB.get().toLowerCase(); - //Zotero.debug(aValue+" vs "+bValue); - - var cmp = collation.compareString(0, aValue, bValue); - if(cmp != 0) { - return cmp; - } - } - } - - // finally, give up; they're the same - return 0; -} - -/* - * process creator objects; if someone had a creator model that handled - * non-Western names better than ours, this would be the function to change - */ -Zotero.CSL.Compat.prototype._processCreators = function(type, element, creators, format, bibCitElement, position) { - var maxCreators = creators.length; - if(!maxCreators) return false; - - var data = new Zotero.CSL.Compat.FormattedString(this, format); - if(format == "disambiguate") { - // for disambiguation, return only the last name of the first creator - // TODO: is this right? - data.append(creators[0].lastName); - return data; - } - - if(!element.children) { - return false; - } - - var etAl = bibCitElement.etAl; - if(position == "subsequent" && bibCitElement.subsequentEtAl) { - etAl = bibCitElement.subsequentEtAl; - } - - for(var i in element.children) { - var child = element.children[i]; - var string = ""; - - if(child.name == "name") { - var useEtAl = false; - - // figure out if we need to use "et al" - if(etAl && maxCreators >= etAl.minCreators) { - maxCreators = etAl.useFirst; - useEtAl = true; - } - - // parse authors into strings - var authorStrings = []; - var firstName, lastName; - for(var i=0; i<maxCreators; i++) { - var firstName = ""; - if(!element["form"] || element["form"] != "short") { - if(child["initialize-with"] != undefined) { - // even if initialize-with is simply an empty string, use - // initials - - // use first initials - var firstNames = creators[i].firstName.split(" "); - for(var j in firstNames) { - if(firstNames[j]) { - // get first initial, put in upper case, add initializeWith string - firstName += firstNames[j][0].toUpperCase()+child["initialize-with"]; - } - } - } else { - firstName = creators[i].firstName; - } - } - lastName = creators[i].lastName; - - if(element["name-as-sort-order"] - && ((i == 0 && element["name-as-sort-order"] == "first") - || element["name-as-sort-order"] == "all") - && child["sort-separator"]) { - // if this is the first author and name-as-sort="first" - // or if this is a subsequent author and name-as-sort="all" - // then the name gets inverted - authorStrings.push(lastName+(firstName ? child["sort-separator"]+firstName : "")); - } else { - authorStrings.push((firstName ? firstName+" " : "")+lastName); - } - } - - // figure out if we need an "and" or an "et al" - var joinString = (child["delimiter"] ? child["delimiter"] : ", "); - if(creators.length > 1) { - if(useEtAl) { // multiple creators and need et al - authorStrings.push(this._getTerm("et-al")); - } else { // multiple creators but no et al - // add and to last creator - if(child["and"]) { - if(child["and"] == "symbol") { - var and = "&" - } else if(child["and"] == "text") { - var and = this._getTerm("and"); - } - - authorStrings[maxCreators-1] = and+" "+authorStrings[maxCreators-1]; - } - } - - // check whether to use a serial comma - Zotero.debug(child["delimiter-precedes-last"]); - if((authorStrings.length == 2 && (useEtAl || child["delimiter-precedes-last"] != "always")) || - (authorStrings.length > 2 && child["delimiter-precedes-last"] == "never")) { - var lastString = authorStrings.pop(); - authorStrings[authorStrings.length-1] = authorStrings[authorStrings.length-1]+" "+lastString; - } - } - string = authorStrings.join(joinString); - } else if(child.name == "label") { - string = this._getTerm(type, (maxCreators != 1), child["form"]); - } - - - // add string to data - if(string) { - data.append(string, child); - } - } - - // add to the data - return data; -} - -/* - * get a citation, given an item and bibCitElement - */ -Zotero.CSL.Compat.prototype._getCitation = function(item, position, locatorType, locator, format, bibCitElement, ignore) { - Zotero.debug("CSL: generating citation for item "+item.getID()); - - // use true position if possible, otherwise "first" - var typePosition = (bibCitElement._types[position] ? position : "first"); - - // determine mapping - if(bibCitElement._types[typePosition][0]) { - // only one element - var typeName = 0; - var type = this._getTypeObject(typePosition, typeName, bibCitElement); - } else { - var typeNames = this._getTypeFromItem(item); - for each(var typeName in typeNames) { - var type = this._getTypeObject(typePosition, typeName, bibCitElement); - if(type) { - break; - } - } - } - - Zotero.debug("CSL: using CSL type "+typeName); - - // remove previous ignore entries from list - this._ignore = (ignore ? ignore : new Object()); - - var formattedString = new Zotero.CSL.Compat.FormattedString(this, format); - for(var j in type) { - this._getFieldValue(type[j].name, type[j], item, formattedString, - bibCitElement, position, locatorType, locator, - typeName); - } - - return formattedString; -} - -/* - * processes an element from a (pre-processed) item into text - */ -Zotero.CSL.Compat.prototype._getFieldValue = function(name, element, item, formattedString, - bibCitElement, position, - locatorType, locator, typeName) { - var dataAppended = false; - var itemID = item.getID(); - - if(element._serialized && this._ignore && this._ignore[element._serialized]) { - return false; - } - - if(name == "author") { - if(item._csl.subsequentAuthorSubstitute && bibCitElement.subsequentAuthorSubstitute) { - // handle subsequent author substitute behavior - dataAppended = formattedString.append(bibCitElement.subsequentAuthorSubstitute, element); - } else { - var newString = this._processCreators(name, element, item._csl.authors, formattedString.format, bibCitElement, position); - if(newString) dataAppended = formattedString.concat(newString, element); - } - } else if(name == "editor") { - dataAppended = formattedString.concat(this._processCreators(name, element, item._csl.editors, formattedString.format, bibCitElement, position), element); - } else if(name == "translator") { - dataAppended = formattedString.concat(this._processCreators(name, element, item._csl.translators, formattedString.format, bibCitElement, position), element); - } else if(name == "recipient") { - dataAppended = formattedString.concat(this._processCreators(name, element, item._csl.recipients, formattedString.format, bibCitElement, position), element); - } else if(name == "interviewer") { - dataAppended = formattedString.concat(this._processCreators(name, element, item._csl.interviewers, formattedString.format, bibCitElement, position), element); - } else if(name == "titles") { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format); - - for(var i in element.children) { - var child = element.children[i]; - var string = null; - - if(child.name == "title") { // for now, we only care about the - // "title" sub-element - if(!element.relation) { - // preferentially use shortTitle if flagged - if(element.form && element.form == "short") { - string = this._getField(item, "shortTitle"); - } - if(!string) { - string = this._getField(item, "title"); - } - } else if(element.relation == "container") { - string = this._getField(item, "publicationTitle"); - } else if(element.relation == "collection") { - string = this._getField(item, "seriesTitle"); - if(!string) string = this._getField(item, "series"); - } else if(element.relation == "event") { - string = this._getField(item, "conferenceName"); - } - - // if comparing, drop "a" or "the" from title - if(formattedString.format == "compare" && string.length > 1) { - if(string.substr(0, 2).toLowerCase() == "a ") { - string = string.substr(2); - } else if(string.length > 3 && string.substr(0, 4).toLowerCase() == "the ") { - string = string.substr(4); - } - } - } - - if(string) { - data.append(string, child); - } - } - - dataAppended = formattedString.concat(data, element); - } else if(name == "date") { - dataAppended = formattedString.appendDate(item._csl.date, element); - } else if(name == "publisher") { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format); - - for(var i in element.children) { - var child = element.children[i]; - var string = ""; - - if(child.name == "place") { - string = this._getField(item, "place"); - } else if(child.name == "name") { - string = this._getField(item, "publisher"); - } - - if(string) { - data.append(string, child); - } - } - - dataAppended = formattedString.concat(data, element); - } else if(name == "access") { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format); - var text = null; - var save = false; - - for(var i in element.children) { - text = null; - var child = element.children[i]; - - if(child.name == "url") { - text = this._getField(item, "url"); - } else if(child.name == "date") { - var field = this._getField(item, "accessDate"); - if(field) { - data.appendDate(this._processDate(field), child); - save = true; - } - } else if(child.name == "physicalLocation") { - text = this._getField(item, "archiveLocation"); - } else if(child.name == "text") { - text = this._getTerm(child["term-name"], false, child["form"]); - } - - if(text) { - data.append(text, child); - if(child.name != "text") { - // only save if there's non-text data - save = true; - } - } - } - - if(save) { - dataAppended = formattedString.concat(data, element); - } - } else if(name == "volume" || name == "issue") { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format); - - var field = this._getField(item, name); - if(field) { - dataAppended = formattedString.appendLocator(name, field, element); - } - } else if(name == "pages") { - if(locatorType == "page") { - var field = locator; - } else if(typeName != "book") { - var field = this._getField(item, "pages"); - } - - if(field) { - dataAppended = formattedString.appendLocator("page", field, element); - } - } else if(name == "locator") { - if(locator) { - Zotero.debug("locatorType "+locatorType); - dataAppended = formattedString.appendLocator(locatorType, locator, element); - } - } else if(name == "edition") { - dataAppended = formattedString.append(this._getField(item, "edition"), element); - } else if(name == "genre") { - var data = this._getField(item, "type"); - if(!data) { - data = this._getField(item, "thesisType"); - } - dataAppended = formattedString.append(data, element); - } else if(name == "group") { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format, element["delimiter"]); - - for(var i in element.children) { - // get data for each child element - var child = element.children[i]; - - this._getFieldValue(child.name, child, item, data, - bibCitElement, position, locatorType, locator, - typeName); - } - - dataAppended = formattedString.concat(data, element); - } else if(name == "conditional") { - var status = false; - for(var i in element.children) { - var condition = element.children[i]; - - if(condition.name == "if" || condition.name == "else-if") { - // evaluate condition for if/else if - if(condition.type) { - var typeNames = this._getTypeFromItem(item); - for each(var typeName in typeNames) { - if(typeName == condition.type) { - status = true; - break; - } - } - } else if(condition.field) { - var testString = new Zotero.CSL.Compat.FormattedString(this, "Text"); - status = this._getFieldValue(condition.field, this._getFieldDefaults(condition.field), item, testString, - bibCitElement, position, locatorType, locator, - typeName); - } - } else if(condition.name == "else") { - status = true; - } - - if(status) { - var data = new Zotero.CSL.Compat.FormattedString(this, formattedString.format, element["delimiter"]); - for(var j in condition.children) { - // get data for each child element - var child = condition.children[j]; - - this._getFieldValue(child.name, child, item, data, - bibCitElement, position, locatorType, locator, - typeName); - } - dataAppended = formattedString.concat(data, condition); - break; - } - } - } else if(name == "text") { - dataAppended = formattedString.append(this._getTerm(element["term-name"], false, element["form"]), element); - } else if(name == "isbn" || name == "doi") { - var field = this._getField(item, name.toUpperCase()); - if(field) { - dataAppended = formattedString.appendLocator(null, field, element); - } - } else if(name == "number") { - dataAppended = formattedString.append(this._csl.number, element); - } - - // if no change and there's a substitute, try it - if(dataAppended) { - return true; - } else if (element.substitute) { - // try each substitute element until one returns something - for(var i in element.substitute) { - var substituteElement = element.substitute[i]; - var serialization = this._serializeElement(substituteElement.name, - substituteElement); - - var inheritElement; - if(Zotero.CSL.Compat.Global.inherit[substituteElement.name] && Zotero.CSL.Compat.Global.inherit[name] - && Zotero.CSL.Compat.Global.inherit[substituteElement.name] == Zotero.CSL.Compat.Global.inherit[name]) { - // if both substituteElement and the parent element inherit from - // the same base element, apply styles here - inheritElement = element; - } else { - // search for elements with the same serialization - if(typeName != undefined && bibCitElement._serializations[position] - && bibCitElement._serializations[position][typeName] - && bibCitElement._serializations[position][typeName][serialization]) { - inheritElement = bibCitElement._serializations[position][typeName][serialization]; - } else { - // otherwise, use defaults - inheritElement = this._getFieldDefaults(substituteElement.name); - } - } - - // merge inheritElement and element - substituteElement = this._merge(inheritElement, substituteElement); - // regardless of inheritance pathway, make sure substitute inherits - // general prefix and suffix from the element it's substituting for - substituteElement.prefix = element.prefix; - substituteElement.suffix = element.suffix; - substituteElement.form = element.form; - // clear substitute element off of the element we're substituting - substituteElement.substitute = undefined; - - // get field value - dataAppended = this._getFieldValue(substituteElement.name, - substituteElement, item, formattedString, - bibCitElement, position, locatorType, locator, - typeName); - - // ignore elements with the same serialization - if(this._ignore) { // array might not exist if doing disambiguation - this._ignore[serialization] = true; - } - - // return field value, if there is one; otherwise, keep processing - // the data - if(dataAppended) { - return true; - } - } - } - - return false; -} - - -Zotero.CSL.Compat.FormattedString = function(CSL, format, delimiter) { - this.CSL = CSL; - this.format = format; - this.delimiter = delimiter; - this.string = ""; - this.closePunctuation = false; - this.useBritishStyleQuotes = false; - - if(format == "RTF") { - this._openQuote = "\\uc0\\u8220 "; - this._closeQuote = "\\uc0\\u8221 "; - } else { - this._openQuote = "\u201c"; - this._closeQuote = "\u201d"; - } -} - -Zotero.CSL.Compat.FormattedString._punctuation = ["!", ".", ",", "?"]; - -/* - * attaches another formatted string to the end of the current one - */ -Zotero.CSL.Compat.FormattedString.prototype.concat = function(formattedString, element) { - if(!formattedString || !formattedString.string) { - return false; - } - - if(formattedString.format != this.format) { - throw "CSL: cannot concatenate formatted strings: formats do not match"; - } - - if(formattedString.string) { - // first, append the actual string - var haveAppended = this.append(formattedString.string, element, false, true); - - // if there's close punctuation to append, that also counts - if(formattedString.closePunctuation) { - haveAppended = true; - if(this.closePunctuation) { - // if there's existing close punctuation and punctuation to - // append, we need to append that - this.string += this.closePunctuation; - } - // add the new close punctuation - this.closePunctuation = formattedString.closePunctuation; - } - - return haveAppended; - } - return false; -} - -/* - * appends a string (with format parameters) to the current one - */ -Zotero.CSL.Compat.FormattedString.prototype.append = function(string, element, dontDelimit, dontEscape) { - if(!string) return false; - if(typeof(string) != "string") { - string = string.toString(); - } - - // append delimiter if necessary - if(this.delimiter && this.string && !dontDelimit) { - this.append(this.delimiter, null, true); - } - - // append prefix before closing punctuation - if(element && element.prefix && this.format != "compare") { - this.append(element.prefix, null, true); - } - - // close quotes, etc. using punctuation - if(this.closePunctuation) { - if(Zotero.CSL.Compat.FormattedString._punctuation.indexOf(string[0]) != -1) { - this.string += string[0]; - string = string.substr(1); - } - this.string += this.closePunctuation; - this.closePunctuation = false; - } - - // handle text transformation - if(element) { - if(element["text-transform"]) { - if(element["text-transform"] == "lowercase") { - // all lowercase - string = string.toLowerCase(); - } else if(element["text-transform"] == "uppercase") { - // all uppercase - string = string.toUpperCase(); - } else if(element["text-transform"] == "capitalize") { - // capitalize first - string = string[0].toUpperCase()+string.substr(1); - } - } - } - - if(!dontEscape) { - if(this.format == "HTML") { - var newString = ""; - - for(var i=0; i<string.length; i++) { - var charCode = string.charCodeAt(i); - // Replace certain characters with HTML entities - switch (charCode) { - case 38: // & - newString += '&amp;'; - break; - case 60: // < - newString += '&lt;'; - break; - case 62: // > - newString += '&gt;'; - break; - case 8211: // en-dash - newString += '&#8211;' - break; - case 8212: // em-dash - newString += '&#8212;' - break; - default: - newString += string[i]; - } - } - - string = newString; - - } else if(this.format == "RTF") { - var newString = ""; - - // go through and fix up unicode entities - for(var i=0; i<string.length; i++) { - var charCode = string.charCodeAt(i); - if(charCode > 127) { // encode unicode - newString += "{\\uc0\\u"+charCode.toString()+"}"; - } else if(charCode == 92) { // double backslashes - newString += "\\\\"; - } else { - newString += string[i]; - } - } - - string = newString; - } else if(this.format == "Integration") { - string = string.replace(/\\/g, "\\\\"); - } - } - - if(element) { - if(this.format == "HTML") { - var style = ""; - - var cssAttributes = ["font-family", "font-style", "font-variant", - "font-weight"]; - for(var j in cssAttributes) { - if(element[cssAttributes[j]] && element[cssAttributes[j]].indexOf('"') == -1) { - style += cssAttributes[j]+":"+element[cssAttributes[j]]; - } - } - - if(style) { - string = '<span style="'+style+'">'+string+'</span>'; - } - } else if(this.format == "RTF" || this.format == "Integration") { - if(element["font-style"] && (element["font-style"] == "oblique" || element["font-style"] == "italic")) { - string = "\\i "+string+"\\i0 "; - } - if(element["font-variant"] && element["font-variant"] == "small-caps") { - string = "\\scaps "+string+"\\scaps0 "; - } - if(element["font-weight"] && element["font-weight"] == "bold") { - string = "\\b "+string+"\\b0 "; - } - } - - // add quotes if necessary - if(element.quotes) { - this.string += this._openQuote; - - if(this.useBritishStyleQuotes) { - string += this._closeQuote; - } else { - this.closePunctuation = this._closeQuote; - } - } - } - - this.string += string; - - // special rule: if a field ends in a punctuation mark, and the suffix - // begins with a period, chop the period off the suffix - var suffix; - if(element && element.suffix && this.format != "compare") { - suffix = element.suffix; // copy so as to leave original intact - - if(suffix[0] == "." && - Zotero.CSL.Compat.FormattedString._punctuation.indexOf(string[string.length-1]) != -1) { - // if string already ends in punctuation, preserve the existing stuff - // and don't add a period - suffix = suffix.substr(1); - } - - this.append(suffix, null, true); - } - - return true; -} - -/* - * gets the formatted string - */ -Zotero.CSL.Compat.FormattedString.prototype.get = function() { - return this.string+(this.closePunctuation ? this.closePunctuation : ""); -} - -/* - * creates a new formatted string with the same formatting parameters as this one - */ -Zotero.CSL.Compat.FormattedString.prototype.clone = function() { - return new Zotero.CSL.Compat.FormattedString(this.CSL, this.format); -} - -/* - * formats a locator (pages, volume, issue) or an identifier (isbn, doi) - * note that label should be null for an identifier - */ -Zotero.CSL.Compat.FormattedString.prototype.appendLocator = function(identifier, number, element) { - if(number) { - var data = this.clone(); - - for(var i in element.children) { - var child = element.children[i]; - var string = ""; - - if(child.name == "number") { - string = number; - } else if(child.name == "text") { - var plural = (identifier && (number.indexOf(",") != -1 - || number.indexOf("-") != -1)); - string = this.CSL._getTerm(child["term-name"], plural, child["form"]); - } else if(identifier && child.name == "label") { - var plural = (number.indexOf(",") != -1 || number.indexOf("-") != -1); - string = this.CSL._getTerm(identifier, plural, child["form"]); - } - - if(string) { - data.append(string, child); - } - } - - this.concat(data, element); - return true; - } else { - return false; - } -} - -/* - * format the date in format supplied by element from the date object - * returned by this._processDate - */ -Zotero.CSL.Compat.FormattedString.prototype.appendDate = function(date, element) { - var data = this.clone(); - if(this.format == "disambiguate") { - // for disambiguation, return only the year - this.append(null, date.year); - return (date.year ? true : false); - } - - var data = this.clone(); - var isData = false; - for(var i in element.children) { - var child = element.children[i]; - var string = ""; - - if(child.name == "year" && date.year) { - if(this.format == "compare") { - string = Zotero.CSL.Compat.Global.lpad(date.year, "0", 4); - } else { - string = date.year.toString(); - if(date.disambiguation) { - string += date.disambiguation; - } - } - } else if(child.name == "month") { - if(date.month != undefined) { - if(this.format == "compare") { - string = Zotero.CSL.Compat.Global.lpad(date.month+1, "0", 2); - } else { - if(element.form == "short") { - string = this.CSL._terms["short"]["_months"][date.month]; - } else { - string = this.CSL._terms["long"]["_months"][date.month]; - } - } - } else if(date.part && this.format != "compare") { - string = date.part; - } - } else if(child.name == "day" && date.day) { - if(this.format == "compare") { - string = Zotero.CSL.Compat.Global.lpad(date.day, "0", 2); - } else { - string = date.day.toString(); - } - } else if(child.name == "text") { - string = this.CSL._getTerm(child["term-name"], false, child["form"]); - } - - if(string) { - data.append(string, child); - isData = true; - } - } - - this.concat(data, element); - - return isData; -} - - -/* - * THE FOLLOWING CODE IS SCHOLAR-SPECIFIC - * gets a list of possible CSL types, in order of preference, for an item - */ - Zotero.CSL.Compat.Global.optionalTypeMappings = { - journalArticle:"article-journal", - magazineArticle:"article-magazine", - newspaperArticle:"article-newspaper", - thesis:"thesis", - letter:"personal_communication", - manuscript:"manuscript", - interview:"interview", - film:"motion picture", - artwork:"graphic", - webpage:"webpage", - report:"report", // ?? - bill:"bill", - case:"legal case", - hearing:"bill", // ?? - patent:"patent", - statute:"bill", // ?? - email:"personal_communication", - map:"map", - blogPost:"webpage", - instantMessage:"personal_communication", - forumPost:"webpage", - audioRecording:"song", // ?? - presentation:"paper-conference", - videoRecording:"motion picture", - tvBroadcast:"motion picture", - radioBroadcast:"motion picture", - podcast:"speech", // ?? - computerProgram:"book" // ?? -}; -// TODO: check with Elena/APA/MLA on this -Zotero.CSL.Compat.Global.fallbackTypeMappings = { - book:"book", - bookSection:"chapter", - journalArticle:"article", - magazineArticle:"article", - newspaperArticle:"article", - thesis:"book", - letter:"article", - manuscript:"article", - interview:"article", - film:"book", - artwork:"book", - webpage:"article", - report:"book", - bill:"book", - case:"book", - hearing:"book", - patent:"book", - statute:"book", - email:"article", - map:"article", - blogPost:"article", - instantMessage:"article", - forumPost:"article", - audioRecording:"book", - presentation:"article", - videoRecording:"book", - tvBroadcast:"article", - radioBroadcast:"article", - podcast:"article", - computerProgram:"book" -}; - -Zotero.CSL.Compat.prototype._getTypeFromItem = function(item) { - var scholarType = Zotero.ItemTypes.getName(item.getType()); - - // get type - Zotero.debug("CSL: parsing item of Scholar type "+scholarType); - if(Zotero.CSL.Compat.Global.optionalTypeMappings[scholarType]) { // if there is an optional type mapping - var array = [Zotero.CSL.Compat.Global.optionalTypeMappings[scholarType]]; - - // check if there is a fallback type mapping; otherwise, use article - if(Zotero.CSL.Compat.Global.fallbackTypeMappings[scholarType]) { - array.push(Zotero.CSL.Compat.Global.fallbackTypeMappings[scholarType]); - } else { - array.push("article"); - } - - return array; - } else if(Zotero.CSL.Compat.Global.fallbackTypeMappings[scholarType]) { // if there is a fallback type mapping - return [Zotero.CSL.Compat.Global.fallbackTypeMappings[scholarType]]; - } else { // use article as backup type mapping - return ["article"]; - } -} - -/* - * separate creators object into authors, editors, translators, recipients, and interviewers - */ -Zotero.CSL.Compat.prototype._separateItemCreators = function(item) { - var authors = new Array(); - var editors = new Array(); - var translators = new Array(); - var recipients = new Array(); - var interviewers = new Array(); - - var authorID = Zotero.CreatorTypes.getPrimaryIDForType(item.getType()); - var editorID = Zotero.CreatorTypes.getID("editor"); - var translatorID = Zotero.CreatorTypes.getID("translator"); - var recipientID = Zotero.CreatorTypes.getID("recipient"); - var interviewerID = Zotero.CreatorTypes.getID("interviewer"); - - var creators = item.getCreators(); - for each(var creator in creators) { - if(creator.creatorTypeID == editorID) { - editors.push(creator); - } else if(creator.creatorTypeID == translatorID) { - translators.push(creator); - } else if(creator.creatorTypeID == recipientID) { - recipients.push(creator); - } else if(creator.creatorTypeID == interviewerID) { - interviewers.push(creator); - } else if(creator.creatorTypeID == authorID) { - // TODO: do we just ignore contributors? - authors.push(creator); - } - } - - return [authors, editors, translators, recipients, interviewers]; -} - -/* - * return an object containing year, month, and day - */ -Zotero.CSL.Compat.prototype._processDate = function(string) { - return Zotero.Date.strToDate(string); -} - -/* - * get a field on an item - */ -Zotero.CSL.Compat.prototype._getField = function(item, field) { - return item.getField(field, false, true); -} - -/* - * END SCHOLAR-SPECIFIC CODE - */ -\ No newline at end of file diff --git a/components/zotero-service.js b/components/zotero-service.js @@ -15,7 +15,7 @@ var ZoteroWrapped = this; *********************************************************************/ var xpcomFiles = ['zotero', - 'annotate', 'attachments', 'cite', 'cite_compat', 'collectionTreeView', + 'annotate', 'attachments', 'cite', 'collectionTreeView', 'dataServer', 'data_access', 'data/item', 'data/items', 'data/collection', 'data/collections', 'data/cachedTypes', 'data/creator', 'data/creators', 'data/itemFields', 'data/notes', 'data/tag', 'data/tags', 'db', 'enstyle',